HubSpot – Free Marketing Plugin for WordPress - Version 3.1.4

Version Description

(2015.03.17) =

Download this release

Release Info

Developer AndyGCook
Plugin Icon 128x128 HubSpot – Free Marketing Plugin for WordPress
Version 3.1.4
Comparing to
See all releases

Code changes from version 2.2.11 to 3.1.4

Files changed (84) hide show
  1. admin/inc/class-leadin-contact.php +335 -4
  2. admin/inc/class-leadin-list-table.php +15 -3
  3. admin/inc/class-leadin-tag-editor.php +1 -2
  4. admin/inc/class-stats-dashboard.php +1 -1
  5. admin/leadin-admin.php +405 -176
  6. assets/css/build/leadin-admin.css +1 -1
  7. assets/css/build/leadin-lead-notifcation.css +1 -1
  8. assets/css/build/leadin-subscribe-premium.css +0 -3
  9. assets/js/build/leadin-admin.js +177 -0
  10. assets/js/build/leadin-admin.min.js +8 -8
  11. assets/js/build/leadin-subscribe.js +7 -8
  12. assets/js/build/leadin-subscribe.min.js +1 -1
  13. images/power-up-icon-aweber-connect.png +0 -0
  14. images/power-up-icon-aweber-connect@2x.png +0 -0
  15. images/power-up-icon-aweber-connect_small.png +0 -0
  16. images/power-up-icon-aweber-connect_small@2x.png +0 -0
  17. images/power-up-icon-campaign-monitor-connect.png +0 -0
  18. images/power-up-icon-campaign-monitor-connect@2x.png +0 -0
  19. images/power-up-icon-campaign-monitor-connect_small.png +0 -0
  20. images/power-up-icon-campaign-monitor-connect_small@2x.png +0 -0
  21. images/power-up-icon-getresponse-connect.png +0 -0
  22. images/power-up-icon-getresponse-connect@2x.png +0 -0
  23. images/power-up-icon-getresponse-connect_small.png +0 -0
  24. images/power-up-icon-getresponse-connect_small@2x.png +0 -0
  25. images/power-up-icon-getresponse-list-sync_small.png +0 -0
  26. images/power-up-icon-getresponse-list-sync_small@2x.png +0 -0
  27. images/powerup-icon-lookups.png +0 -0
  28. images/powerup-icon-lookups@2x.png +0 -0
  29. inc/class-emailer.php +269 -22
  30. inc/class-leadin-updater.php +1 -3
  31. inc/class-leadin.php +19 -65
  32. inc/leadin-ajax-functions.php +69 -8
  33. inc/leadin-constants.php +15 -0
  34. inc/leadin-functions.php +248 -15
  35. leadin.php +65 -8
  36. lib/mixpanel/Base/LI_MixpanelBase.php +68 -0
  37. lib/mixpanel/ConsumerStrategies/LI_AbstractConsumer.php +58 -0
  38. lib/mixpanel/ConsumerStrategies/LI_CurlConsumer.php +222 -0
  39. lib/mixpanel/ConsumerStrategies/LI_FileConsumer.php +39 -0
  40. lib/mixpanel/ConsumerStrategies/LI_SocketConsumer.php +309 -0
  41. lib/mixpanel/LI_Mixpanel.php +305 -0
  42. lib/mixpanel/Producers/LI_MixpanelBaseProducer.php +230 -0
  43. lib/mixpanel/Producers/LI_MixpanelEvents.php +165 -0
  44. lib/mixpanel/Producers/LI_MixpanelPeople.php +139 -0
  45. lib/segment/lib/Segment.php +145 -0
  46. lib/segment/lib/Segment/Client.php +201 -0
  47. lib/segment/lib/Segment/Consumer.php +104 -0
  48. lib/segment/lib/Segment/Consumer/File.php +111 -0
  49. lib/segment/lib/Segment/Consumer/ForkCurl.php +59 -0
  50. lib/segment/lib/Segment/Consumer/Socket.php +174 -0
  51. lib/segment/lib/Segment/QueueConsumer.php +138 -0
  52. lib/segment/send.php +106 -0
  53. power-ups/aweber-connect.php +168 -0
  54. power-ups/aweber-connect/admin/aweber-connect-admin.php +323 -0
  55. power-ups/aweber-connect/inc/aweber_api/li_aweber.php +292 -0
  56. power-ups/aweber-connect/inc/aweber_api/li_aweber_api.php +8 -0
  57. power-ups/aweber-connect/inc/aweber_api/li_aweber_collection.php +268 -0
  58. power-ups/aweber-connect/inc/aweber_api/li_aweber_entry.php +343 -0
  59. power-ups/aweber-connect/inc/aweber_api/li_aweber_entry_data_array.php +68 -0
  60. power-ups/aweber-connect/inc/aweber_api/li_aweber_response.php +73 -0
  61. power-ups/aweber-connect/inc/aweber_api/li_curl_object.php +103 -0
  62. power-ups/aweber-connect/inc/aweber_api/li_curl_response.php +51 -0
  63. power-ups/aweber-connect/inc/aweber_api/li_exceptions.php +130 -0
  64. power-ups/aweber-connect/inc/aweber_api/li_oauth_adapter.php +11 -0
  65. power-ups/aweber-connect/inc/aweber_api/li_oauth_application.php +681 -0
  66. power-ups/campaign-monitor-connect.php +141 -0
  67. power-ups/campaign-monitor-connect/admin/campaign-monitor-connect-admin.php +225 -0
  68. power-ups/campaign-monitor-connect/inc/li_campaign_monitor.php +123 -0
  69. power-ups/campaign-monitor-connect/inc/test.php +35 -0
  70. power-ups/constant-contact-connect.php +9 -2
  71. power-ups/constant-contact-connect/admin/constant-contact-connect-admin.php +11 -50
  72. power-ups/contacts.php +1 -1
  73. power-ups/contacts/admin/contacts-admin.php +220 -9
  74. power-ups/getresponse-connect.php +133 -0
  75. power-ups/getresponse-connect/admin/getresponse-connect-admin.php +206 -0
  76. power-ups/getresponse-connect/inc/LI_GetResponseAPI.php +558 -0
  77. power-ups/lookups.php +78 -0
  78. power-ups/lookups/admin/inc/blacklist_domains.php +3025 -0
  79. power-ups/lookups/admin/lookups-admin.php +44 -0
  80. power-ups/mailchimp-connect.php +7 -28
  81. power-ups/mailchimp-connect/admin/mailchimp-connect-admin.php +15 -48
  82. power-ups/subscribe-widget.php +0 -11
  83. power-ups/subscribe-widget/admin/subscribe-widget-admin.php +5 -5
  84. readme.txt +102 -76
admin/inc/class-leadin-contact.php CHANGED
@@ -1,4 +1,11 @@
1
  <?php
 
 
 
 
 
 
 
2
  //=============================================
3
  // LI_Contact Class
4
  //=============================================
@@ -49,6 +56,12 @@ class LI_Contact {
49
  $submissions = $this->get_contact_submissions($this->hashkey, 'ARRAY_A');
50
  $tags = $this->get_contact_tags($this->hashkey);
51
 
 
 
 
 
 
 
52
  // Merge the page views array and submissions array and reorder by date
53
  $events_array = array_merge($pageviews, $submissions);
54
  usort($events_array, array('LI_Contact','sort_by_event_date'));
@@ -119,8 +132,7 @@ class LI_Contact {
119
  }
120
  else
121
  {
122
-
123
- // Always overwrite the first_submission date which will end as last submission date
124
  $lead->first_submission = $event['event_date'];
125
 
126
  $event['form_name'] = 'form';
@@ -264,7 +276,10 @@ class LI_Contact {
264
  lead_ip,
265
  lead_email,
266
  lead_first_name,
267
- lead_last_name
 
 
 
268
  FROM
269
  $wpdb->li_leads
270
  WHERE hashkey LIKE %s", $wpdb->db_hour_offset, '%b %D %l:%i%p', $hashkey);
@@ -274,6 +289,173 @@ class LI_Contact {
274
  return $contact_details;
275
  }
276
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  /**
278
  * Gets all the tags for a contact
279
  *
@@ -365,6 +547,8 @@ class LI_Contact {
365
  );
366
 
367
  $safe_tags .= $wpdb->insert_id . ',';
 
 
368
  }
369
  else
370
  {
@@ -393,7 +577,7 @@ class LI_Contact {
393
  if ( ! ${$power_up_global}->activated )
394
  continue;
395
 
396
- ${$power_up_global}->push_contact_to_list($list['list_id'], $this->history->lead->lead_email);
397
  }
398
 
399
  array_push($synced_lists, $list['list_id']);
@@ -405,10 +589,17 @@ class LI_Contact {
405
  {
406
  $q = $wpdb->prepare("UPDATE $wpdb->li_tag_relationships SET tag_relationship_deleted = 0 WHERE contact_hashkey = %s AND tag_relationship_id IN ( " . rtrim($tags_to_update, ',') . " ) ", $this->hashkey);
407
  $tag_updated = $wpdb->query($q);
 
 
408
  }
409
 
410
  $q = $wpdb->prepare("UPDATE $wpdb->li_tag_relationships SET tag_relationship_deleted = 1 WHERE contact_hashkey = %s " . ( $safe_tags ? "AND tag_relationship_id NOT IN ( " . rtrim($safe_tags, ',') . " ) " : '' ) . " AND tag_relationship_deleted = 0 ", $this->hashkey);
411
  $deleted_tags = $wpdb->query($q);
 
 
 
 
 
412
  }
413
 
414
  /**
@@ -424,5 +615,145 @@ class LI_Contact {
424
 
425
  return $val_a < $val_b;
426
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
427
  }
428
  ?>
1
  <?php
2
+
3
+ //=============================================
4
+ // Include Needed Files
5
+ //=============================================
6
+
7
+ require_once(LEADIN_PLUGIN_DIR . '/power-ups/lookups/admin/inc/blacklist_domains.php');
8
+
9
  //=============================================
10
  // LI_Contact Class
11
  //=============================================
56
  $submissions = $this->get_contact_submissions($this->hashkey, 'ARRAY_A');
57
  $tags = $this->get_contact_tags($this->hashkey);
58
 
59
+ if ( WPLeadIn::is_power_up_active('lookups') )
60
+ {
61
+ $lead->social_data = $this->get_social_details($lead);
62
+ $lead->company_data = $this->get_company_details($lead);
63
+ }
64
+
65
  // Merge the page views array and submissions array and reorder by date
66
  $events_array = array_merge($pageviews, $submissions);
67
  usort($events_array, array('LI_Contact','sort_by_event_date'));
132
  }
133
  else
134
  {
135
+ // Always overwrite the last_submission date which will end as last submission date
 
136
  $lead->first_submission = $event['event_date'];
137
 
138
  $event['form_name'] = 'form';
276
  lead_ip,
277
  lead_email,
278
  lead_first_name,
279
+ lead_last_name,
280
+ social_data,
281
+ company_data,
282
+ lead_deleted
283
  FROM
284
  $wpdb->li_leads
285
  WHERE hashkey LIKE %s", $wpdb->db_hour_offset, '%b %D %l:%i%p', $hashkey);
289
  return $contact_details;
290
  }
291
 
292
+ /**
293
+ * Sets the social_data on a contact
294
+ *
295
+ * @param object
296
+ * @return object
297
+ */
298
+ function get_social_details ( $lead )
299
+ {
300
+ $site_url = site_url();
301
+ $social_data = '';
302
+
303
+ if ( ! $lead->social_data )
304
+ {
305
+ // Grab the social intel lookup
306
+ $social_data = json_decode($this->query_social_lookup_endpoint(strtolower($lead->lead_email), $site_url));
307
+
308
+ if ( ! isset($social_data->status) )
309
+ {
310
+ $this->update_social_lookup_data($this->hashkey, serialize($social_data));
311
+
312
+ // Update the first and last names if one of them isn't set, and the respected name part is present or the full name is present the full name is present or the correspond
313
+ $first_name = '';
314
+ $last_name = '';
315
+ $update_name = FALSE;
316
+
317
+ if ( ! $lead->lead_first_name )
318
+ {
319
+ if ( isset($social_data->fullcontactDetails->contactinfo->givenname) )
320
+ {
321
+ $first_name = $social_data->fullcontactDetails->contactinfo->givenname;
322
+ $update_name = TRUE;
323
+ }
324
+ else if ( isset($social_data->fullcontactDetails->contactinfo->fullname) )
325
+ {
326
+ $first_name = reset(explode(' ', $social_data->fullcontactDetails->contactinfo->fullname));
327
+ $update_name = TRUE;
328
+ }
329
+ }
330
+ else
331
+ $first_name = $lead->lead_first_name;
332
+
333
+ if ( ! $lead->lead_last_name )
334
+ {
335
+ if ( isset($social_data->fullcontactDetails->contactinfo->familyname) )
336
+ {
337
+ $last_name = $social_data->fullcontactDetails->contactinfo->familyname;
338
+ $update_name = TRUE;
339
+ }
340
+ else if ( isset($social_data->fullcontactDetails->contactinfo->fullname) )
341
+ {
342
+ $last_name = end(explode(' ', $social_data->fullcontactDetails->contactinfo->fullname));
343
+ $update_name = TRUE;
344
+ }
345
+ }
346
+ else
347
+ $last_name = $lead->lead_first_name;
348
+
349
+ if ( $update_name )
350
+ $this->update_contact_full_name($this->hashkey, $first_name, $last_name);
351
+
352
+ }
353
+ else if ( isset($social_data->status) && $social_data->status == 'error' )
354
+ {
355
+ $social_data = '';
356
+ }
357
+ }
358
+ else
359
+ $social_data = unserialize($lead->social_data);
360
+
361
+ if ( isset($social_data->fullcontactDetails) )
362
+ {
363
+ $fullcontactDetails = $social_data->fullcontactDetails;
364
+
365
+ if ( count($fullcontactDetails->organizations) )
366
+ {
367
+ foreach ( $fullcontactDetails->organizations as $org )
368
+ {
369
+ if ( isset($org->isprimary) )
370
+ {
371
+ $social_data->properties->primary->company_name = ( isset($org->name) ? $org->name : '' );
372
+ $social_data->properties->primary->title = ( isset($org->title) ? $org->title : '' );
373
+ break;
374
+ }
375
+ }
376
+ }
377
+
378
+ if ( isset($social_data->twitterDetails->description) )
379
+ {
380
+ if ( $social_data->twitterDetails->description )
381
+ $social_data->properties->description = $social_data->twitterDetails->description;
382
+ }
383
+
384
+ if ( count($fullcontactDetails->socialprofiles) )
385
+ {
386
+ $social_profiles = array();
387
+
388
+ foreach ( $fullcontactDetails->socialprofiles as $key => $profile )
389
+ {
390
+ $whitelisted_profiles = array('twitter', 'facebook', 'linkedin', 'googleplus');
391
+ if ( in_array($profile->typeid, $whitelisted_profiles) && ! empty($profile->username) )
392
+ {
393
+ $social_profile = (object)NULL;
394
+ $social_profile->typename = $profile->typename;
395
+ $social_profile->url = leadin_safe_social_profile_url($profile->url);
396
+ $social_profile->typeid = $profile->typeid;
397
+ $social_profile->username = $profile->username;
398
+
399
+ $social_profiles[] = $social_profile;
400
+ }
401
+ }
402
+
403
+ if ( count($social_profiles) )
404
+ {
405
+ if ( isset($social_data->properties->social_profiles) )
406
+ $social_data->properties->social_profiles = $social_profiles;
407
+ }
408
+ }
409
+ }
410
+
411
+ return $social_data;
412
+ }
413
+
414
+ /**
415
+ * Sets the company_data on a contact
416
+ *
417
+ * @param object
418
+ * @return object
419
+ */
420
+ function get_company_details ( $lead )
421
+ {
422
+ global $blacklist_freemail_domains;
423
+ global $blacklist_nonmail_domains;
424
+
425
+ $site_url = site_url();
426
+ $email_domain = end(explode('@', $lead->lead_email));
427
+ $leadin_user = leadin_get_current_user();
428
+ $company_data = '';
429
+
430
+ if ( strstr($leadin_user['email'], ',') )
431
+ $leadin_user_email = reset(explode(',', $leadin_user['email']));
432
+ else
433
+ $leadin_user_email = $leadin_user['email'];
434
+
435
+ if ( ! in_array($email_domain, $blacklist_nonmail_domains) && ! in_array($email_domain, $blacklist_freemail_domains) )
436
+ {
437
+ if ( ! $lead->company_data )
438
+ {
439
+ // Grab the company intel lookup
440
+ $company_data = json_decode($this->query_company_lookup_endpoint($email_domain, $leadin_user_email, $site_url));
441
+
442
+ if ( isset($company_data->status) && $company_data->status != 'error' )
443
+ {
444
+ $this->update_company_lookup_data($this->hashkey, serialize($company_data));
445
+ }
446
+ else
447
+ {
448
+ }
449
+ }
450
+ else
451
+ {
452
+ $company_data = unserialize($lead->company_data);
453
+ }
454
+ }
455
+
456
+ return $company_data;
457
+ }
458
+
459
  /**
460
  * Gets all the tags for a contact
461
  *
547
  );
548
 
549
  $safe_tags .= $wpdb->insert_id . ',';
550
+
551
+ leadin_track_plugin_activity('Tag Added - Contact Timeline');
552
  }
553
  else
554
  {
577
  if ( ! ${$power_up_global}->activated )
578
  continue;
579
 
580
+ ${$power_up_global}->push_contact_to_list($list['list_id'], $this->history->lead->lead_email, $this->history->lead->lead_first_name, $this->history->lead->lead_last_name);
581
  }
582
 
583
  array_push($synced_lists, $list['list_id']);
589
  {
590
  $q = $wpdb->prepare("UPDATE $wpdb->li_tag_relationships SET tag_relationship_deleted = 0 WHERE contact_hashkey = %s AND tag_relationship_id IN ( " . rtrim($tags_to_update, ',') . " ) ", $this->hashkey);
591
  $tag_updated = $wpdb->query($q);
592
+
593
+ leadin_track_plugin_activity('Tag Restored - Contact Timeline');
594
  }
595
 
596
  $q = $wpdb->prepare("UPDATE $wpdb->li_tag_relationships SET tag_relationship_deleted = 1 WHERE contact_hashkey = %s " . ( $safe_tags ? "AND tag_relationship_id NOT IN ( " . rtrim($safe_tags, ',') . " ) " : '' ) . " AND tag_relationship_deleted = 0 ", $this->hashkey);
597
  $deleted_tags = $wpdb->query($q);
598
+
599
+ if ( $deleted_tags )
600
+ {
601
+ leadin_track_plugin_activity('Tag Removed - Contact Timeline');
602
+ }
603
  }
604
 
605
  /**
615
 
616
  return $val_a < $val_b;
617
  }
618
+
619
+ /**
620
+ * Query the social lookup endpoint on Leadin.com
621
+ *
622
+ * @param string
623
+ * @param string
624
+ * @return array
625
+ */
626
+ function query_social_lookup_endpoint ( $lookup_email, $caller_domain )
627
+ {
628
+ $api_endpoint = 'http://leadin.com/enrichment/v1/profile/email/email_lookup.php';
629
+ $params = '?lookup_email=' . $lookup_email . '&caller_domain=' . $caller_domain;
630
+
631
+ $curl_handle = curl_init();
632
+ curl_setopt($curl_handle,CURLOPT_URL, $api_endpoint . $params);
633
+ curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
634
+ curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
635
+ $data = curl_exec($curl_handle);
636
+ curl_close($curl_handle);
637
+
638
+
639
+ return htmlspecialchars_decode($data);
640
+
641
+ }
642
+
643
+ /**
644
+ * Query the company lookup endpoint on Leadin.com
645
+ *
646
+ * @param string
647
+ * @param string
648
+ * @param string
649
+ * @return array
650
+ */
651
+ function query_company_lookup_endpoint ( $lookup_company_url, $caller_email, $caller_domain )
652
+ {
653
+ $caller_domain = str_replace(array('http://', 'https://'), '', $caller_domain);
654
+ $caller_domain = 'leadin.com';
655
+
656
+ $api_endpoint = 'http://leadin.com/enrichment/v1/company/company_lookup.php';
657
+ $params = '?lookup_company_url=' . $lookup_company_url . '&caller_email=' . $caller_email . '&caller_domain=' . $caller_domain;
658
+
659
+ $curl_handle = curl_init();
660
+ curl_setopt($curl_handle,CURLOPT_URL, $api_endpoint . $params);
661
+ curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,2);
662
+ curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,1);
663
+ $data = curl_exec($curl_handle);
664
+ curl_close($curl_handle);
665
+
666
+
667
+ return htmlspecialchars_decode($data);
668
+ }
669
+
670
+ /**
671
+ * Queries for the company_data and social_data fields on the contact in li_leads
672
+ *
673
+ * @param string
674
+ * @return object
675
+ */
676
+ function get_cached_lookup_data ( $hashkey )
677
+ {
678
+ global $wpdb;
679
+
680
+ $q = $wpdb->prepare("SELECT social_data, company_data FROM $wpdb->li_leads WHERE hashkey = %s", $hashkey);
681
+ $result = $wpdb->get_row($q);
682
+
683
+ return $result;
684
+ }
685
+
686
+ /**
687
+ * Cache the social lookup data in the database
688
+ *
689
+ * @param string
690
+ * @param string serialized array
691
+ * @param string
692
+ * @return bool
693
+ */
694
+ function update_social_lookup_data ( $hashkey, $social_data )
695
+ {
696
+ global $wpdb;
697
+
698
+ $q = $wpdb->prepare("UPDATE $wpdb->li_leads SET social_data = %s WHERE hashkey = %s", $social_data, $hashkey);
699
+ $result = $wpdb->query($q);
700
+
701
+ return $result;
702
+ }
703
+
704
+ /**
705
+ * Cache the company lookup data in the database
706
+ *
707
+ * @param string
708
+ * @param string serialized array
709
+ * @param string
710
+ * @return bool
711
+ */
712
+ function update_company_lookup_data ( $hashkey, $company_data )
713
+ {
714
+ global $wpdb;
715
+
716
+ $q = $wpdb->prepare("UPDATE $wpdb->li_leads SET company_data = %s WHERE hashkey = %s", $company_data, $hashkey);
717
+ $result = $wpdb->query($q);
718
+
719
+ return $result;
720
+ }
721
+
722
+ /**
723
+ * Update the first + last name on a contact row in li_leads
724
+ *
725
+ * @param string
726
+ * @param string
727
+ * @param string
728
+ * @return bool
729
+ */
730
+ function update_contact_full_name ( $hashkey, $first_name, $last_name )
731
+ {
732
+ global $wpdb;
733
+
734
+ $q = $wpdb->prepare("UPDATE $wpdb->li_leads SET lead_first_name = %s, lead_last_name = %s WHERE hashkey = %s", $first_name, $last_name, $hashkey);
735
+ $result = $wpdb->query($q);
736
+
737
+ return $result;
738
+ }
739
+
740
+ /**
741
+ * Redirects the user to a merged contact when the current contact has been deleted
742
+ *
743
+ * @param string
744
+ *
745
+ */
746
+ function display_error_message_for_merged_contact ( $lead_email )
747
+ {
748
+ global $wpdb;
749
+
750
+ $q = $wpdb->prepare("SELECT lead_id FROM $wpdb->li_leads WHERE lead_email = %s AND lead_deleted = 0 ORDER BY lead_date DESC LIMIT 1", $lead_email);
751
+ $lead_id = $wpdb->get_var($q);
752
+
753
+ if ( $lead_id )
754
+ {
755
+ echo '<div style="background: #fff; border-left: 4px solid #dd3d36; padding: 1px 12px; margin-bottom: 20px;" ><p>This contact record was merged with a more recent entry and is out of date... <br/><br/> <a class="button" href="' . get_admin_url() . 'admin.php?page=leadin_contacts&action=view&lead=' . $lead_id . '">View the latest timeline</a></p></div>';
756
+ }
757
+ }
758
  }
759
  ?>
admin/inc/class-leadin-list-table.php CHANGED
@@ -189,7 +189,6 @@ class LI_List_Table extends WP_List_Table {
189
  $ids_for_action = '';
190
  $hashes_for_action = '';
191
 
192
- // @TODO Fix the delete logic
193
  if ( strstr($this->current_action(), 'delete') )
194
  {
195
  if ( 'delete_selected' === $this->current_action() )
@@ -201,6 +200,8 @@ class LI_List_Table extends WP_List_Table {
201
  if ( $i != (count($_GET['contact'])-1) )
202
  $ids_for_action .= ',';
203
  }
 
 
204
  }
205
  else if ( 'delete_all' === $this->current_action() )
206
  {
@@ -209,11 +210,12 @@ class LI_List_Table extends WP_List_Table {
209
  $ids_for_action .= $contact['ID'] . ',';
210
 
211
  $ids_for_action = rtrim($ids_for_action, ',');
 
 
212
  }
213
  else // default case for when it's not actually processing a bulk action
214
  return FALSE;
215
 
216
-
217
  $q = $wpdb->prepare("SELECT hashkey FROM $wpdb->li_leads WHERE lead_id IN ( " . $ids_for_action . " ) ", "");
218
  $hashes = $wpdb->get_results($q);
219
 
@@ -294,6 +296,8 @@ class LI_List_Table extends WP_List_Table {
294
  $wpdb->query($q);
295
  }
296
 
 
 
297
  // Bulk push all the email addresses for the tag to the MailChimp API
298
  $tagger = new LI_Tag_Editor($tag_id);
299
  $tagger->push_contacts_to_tagged_list($tag_id);
@@ -305,6 +309,8 @@ class LI_List_Table extends WP_List_Table {
305
  // "Delete" the existing tags only
306
  $q = $wpdb->prepare("UPDATE $wpdb->li_tag_relationships SET tag_relationship_deleted = 1 WHERE tag_id = %d AND contact_hashkey IN ( " . rtrim($contacts_to_update, ',') . ") ", $tag_id);
307
  $wpdb->query($q);
 
 
308
  }
309
  }
310
  }
@@ -345,6 +351,8 @@ class LI_List_Table extends WP_List_Table {
345
 
346
  $search_query = $_GET['s'];
347
  $mysql_search_filter = $wpdb->prepare(" AND ( l.lead_email LIKE '%%%s%%' OR l.lead_source LIKE '%%%s%%' ) ", $escaped_query, $escaped_query);
 
 
348
  }
349
 
350
  $filtered_contacts = array();
@@ -374,6 +382,8 @@ class LI_List_Table extends WP_List_Table {
374
  $q = $wpdb->prepare("SELECT lead_hashkey FROM $wpdb->li_pageviews WHERE pageview_title LIKE '%%%s%%' GROUP BY lead_hashkey", htmlspecialchars(urldecode($_GET['filter_content'])));
375
  $filtered_contacts = leadin_merge_filtered_contacts($wpdb->get_results($q, 'ARRAY_A'), $filtered_contacts);
376
  $filter_action_set = TRUE;
 
 
377
  }
378
  }
379
 
@@ -385,6 +395,8 @@ class LI_List_Table extends WP_List_Table {
385
  {
386
  $filter_form = str_replace(array('#', '.'), '', htmlspecialchars(urldecode($_GET['filter_form'])));
387
  $filter_form_query = $wpdb->prepare(" AND ( form_selector_id LIKE '%%%s%%' OR form_selector_classes LIKE '%%%s%%' )", $filter_form, $filter_form);
 
 
388
  }
389
 
390
  $q = $wpdb->prepare("SELECT lead_hashkey FROM $wpdb->li_submissions WHERE form_page_title LIKE '%%%s%%' ", ( $_GET['filter_content'] != 'any page' ? htmlspecialchars(urldecode($_GET['filter_content'])): '' ));
@@ -549,7 +561,7 @@ class LI_List_Table extends WP_List_Table {
549
  function views ()
550
  {
551
  $this->tags = stripslashes_deep($this->get_tags());
552
-
553
  $current = ( !empty($_GET['contact_type']) ? html_entity_decode($_GET['contact_type']) : 'all' );
554
  $all_params = array( 'contact_type', 's', 'paged', '_wpnonce', '_wpreferrer', '_wp_http_referer', 'action', 'action2', 'filter_form', 'filter_action', 'filter_content', 'contact');
555
 
189
  $ids_for_action = '';
190
  $hashes_for_action = '';
191
 
 
192
  if ( strstr($this->current_action(), 'delete') )
193
  {
194
  if ( 'delete_selected' === $this->current_action() )
200
  if ( $i != (count($_GET['contact'])-1) )
201
  $ids_for_action .= ',';
202
  }
203
+
204
+ leadin_track_plugin_activity('Bulk Contacts Deleted', array( "contact_type" => 'selected'));
205
  }
206
  else if ( 'delete_all' === $this->current_action() )
207
  {
210
  $ids_for_action .= $contact['ID'] . ',';
211
 
212
  $ids_for_action = rtrim($ids_for_action, ',');
213
+
214
+ leadin_track_plugin_activity('Bulk Contacts Deleted', array( "contact_type" => 'all'));
215
  }
216
  else // default case for when it's not actually processing a bulk action
217
  return FALSE;
218
 
 
219
  $q = $wpdb->prepare("SELECT hashkey FROM $wpdb->li_leads WHERE lead_id IN ( " . $ids_for_action . " ) ", "");
220
  $hashes = $wpdb->get_results($q);
221
 
296
  $wpdb->query($q);
297
  }
298
 
299
+ leadin_track_plugin_activity('Bulk Tag Added', array( "contact_type" => ( empty($_POST['leadin_selected_contacts']) ? 'all' : 'selected' )));
300
+
301
  // Bulk push all the email addresses for the tag to the MailChimp API
302
  $tagger = new LI_Tag_Editor($tag_id);
303
  $tagger->push_contacts_to_tagged_list($tag_id);
309
  // "Delete" the existing tags only
310
  $q = $wpdb->prepare("UPDATE $wpdb->li_tag_relationships SET tag_relationship_deleted = 1 WHERE tag_id = %d AND contact_hashkey IN ( " . rtrim($contacts_to_update, ',') . ") ", $tag_id);
311
  $wpdb->query($q);
312
+
313
+ leadin_track_plugin_activity('Bulk Tag Removed', array( "contact_type" => ( empty($_POST['leadin_selected_contacts']) ? 'all' : 'selected' )));
314
  }
315
  }
316
  }
351
 
352
  $search_query = $_GET['s'];
353
  $mysql_search_filter = $wpdb->prepare(" AND ( l.lead_email LIKE '%%%s%%' OR l.lead_source LIKE '%%%s%%' ) ", $escaped_query, $escaped_query);
354
+
355
+ leadin_track_plugin_activity('Filtered List', array ( "filter_type" => "search" ));
356
  }
357
 
358
  $filtered_contacts = array();
382
  $q = $wpdb->prepare("SELECT lead_hashkey FROM $wpdb->li_pageviews WHERE pageview_title LIKE '%%%s%%' GROUP BY lead_hashkey", htmlspecialchars(urldecode($_GET['filter_content'])));
383
  $filtered_contacts = leadin_merge_filtered_contacts($wpdb->get_results($q, 'ARRAY_A'), $filtered_contacts);
384
  $filter_action_set = TRUE;
385
+
386
+ leadin_track_plugin_activity('Filtered List', array ( "filter_type" => "page" ));
387
  }
388
  }
389
 
395
  {
396
  $filter_form = str_replace(array('#', '.'), '', htmlspecialchars(urldecode($_GET['filter_form'])));
397
  $filter_form_query = $wpdb->prepare(" AND ( form_selector_id LIKE '%%%s%%' OR form_selector_classes LIKE '%%%s%%' )", $filter_form, $filter_form);
398
+
399
+ leadin_track_plugin_activity('Filtered List', array ( "filter_type" => "form" ));
400
  }
401
 
402
  $q = $wpdb->prepare("SELECT lead_hashkey FROM $wpdb->li_submissions WHERE form_page_title LIKE '%%%s%%' ", ( $_GET['filter_content'] != 'any page' ? htmlspecialchars(urldecode($_GET['filter_content'])): '' ));
561
  function views ()
562
  {
563
  $this->tags = stripslashes_deep($this->get_tags());
564
+
565
  $current = ( !empty($_GET['contact_type']) ? html_entity_decode($_GET['contact_type']) : 'all' );
566
  $all_params = array( 'contact_type', 's', 'paged', '_wpnonce', '_wpreferrer', '_wp_http_referer', 'action', 'action2', 'filter_form', 'filter_action', 'filter_content', 'contact');
567
 
admin/inc/class-leadin-tag-editor.php CHANGED
@@ -88,7 +88,7 @@ class LI_Tag_Editor {
88
  {
89
  global $wpdb;
90
 
91
- $q = $wpdb->prepare("SELECT MAX(tag_order) FROM $wpdb->li_tags", "");
92
  $tag_order = $wpdb->get_var($q);
93
  $tag_order = ( $tag_order ? $tag_order + 1 : 1 );
94
  $tag_slug = $this->generate_slug($tag_text);
@@ -113,7 +113,6 @@ class LI_Tag_Editor {
113
  function save_tag ( $tag_id, $tag_text, $tag_form_selectors, $tag_synced_lists )
114
  {
115
  global $wpdb;
116
- global $leadin_mailchimp_connect_wp;
117
 
118
  $tag_slug = $this->generate_slug($tag_text, $tag_id);
119
 
88
  {
89
  global $wpdb;
90
 
91
+ $q = "SELECT MAX(tag_order) FROM $wpdb->li_tags";
92
  $tag_order = $wpdb->get_var($q);
93
  $tag_order = ( $tag_order ? $tag_order + 1 : 1 );
94
  $tag_slug = $this->generate_slug($tag_text);
113
  function save_tag ( $tag_id, $tag_text, $tag_form_selectors, $tag_synced_lists )
114
  {
115
  global $wpdb;
 
116
 
117
  $tag_slug = $this->generate_slug($tag_text, $tag_id);
118
 
admin/inc/class-stats-dashboard.php CHANGED
@@ -157,7 +157,7 @@ class LI_StatsDashboard {
157
  ( SELECT MIN(pageview_source) AS pageview_source FROM $wpdb->li_pageviews WHERE lead_hashkey = lh AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS lead_source,
158
  ( SELECT MIN(pageview_url) AS pageview_url FROM $wpdb->li_pageviews WHERE lead_hashkey = lh AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS lead_origin_url
159
  FROM
160
- $wpdb->li_leads ll, li_pageviews lpv
161
  WHERE
162
  lead_date >= CURRENT_DATE() AND
163
  ll.hashkey = lpv.lead_hashkey AND
157
  ( SELECT MIN(pageview_source) AS pageview_source FROM $wpdb->li_pageviews WHERE lead_hashkey = lh AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS lead_source,
158
  ( SELECT MIN(pageview_url) AS pageview_url FROM $wpdb->li_pageviews WHERE lead_hashkey = lh AND pageview_session_start = 1 AND pageview_deleted = 0 ) AS lead_origin_url
159
  FROM
160
+ $wpdb->li_leads ll, $wpdb->li_pageviews lpv
161
  WHERE
162
  lead_date >= CURRENT_DATE() AND
163
  ll.hashkey = lpv.lead_hashkey AND
admin/leadin-admin.php CHANGED
@@ -56,16 +56,12 @@ class WPLeadInAdmin {
56
  */
57
  function __construct ( $power_ups )
58
  {
59
- //echo get_bloginfo('wpurl');
60
  //=============================================
61
  // Hooks & Filters
62
  //=============================================
63
 
64
  $options = get_option('leadin_options');
65
 
66
- if ( is_multisite() )
67
- $options = leadin_check_multisite_missing_options($options);
68
-
69
  $this->action = $this->leadin_current_action();
70
 
71
  // If the plugin version matches the latest version escape the update function
@@ -83,19 +79,28 @@ class WPLeadInAdmin {
83
  {
84
  add_action('admin_footer', array($this, 'build_contacts_chart'));
85
  }
 
 
 
 
 
 
 
 
86
  }
87
 
88
- function leadin_update_check ( )
89
  {
90
  $options = get_option('leadin_options');
91
 
92
  // 0.5.1 upgrade - Create active power-ups option if it doesn't exist
93
  $leadin_active_power_ups = get_option('leadin_active_power_ups');
94
 
95
- if ( !$leadin_active_power_ups )
96
  {
97
  $auto_activate = array(
98
- 'contacts'
 
99
  );
100
 
101
  update_option('leadin_active_power_ups', serialize($auto_activate));
@@ -104,11 +109,13 @@ class WPLeadInAdmin {
104
  {
105
  // 0.9.2 upgrade - set beta program power-up to auto-activate
106
  $activated_power_ups = unserialize($leadin_active_power_ups);
 
107
 
108
  // 0.9.3 bug fix for duplicate beta_program values being stored in the active power-ups array
109
  if ( !in_array('beta_program', $activated_power_ups) )
110
  {
111
  $activated_power_ups[] = 'beta_program';
 
112
  }
113
  else
114
  {
@@ -116,7 +123,10 @@ class WPLeadInAdmin {
116
  $count = $tmp['beta_program'];
117
 
118
  if ( $count > 1 )
 
119
  $activated_power_ups = array_unique($activated_power_ups);
 
 
120
  }
121
 
122
  // 2.0.1 upgrade - [plugin_slug]_list_sync changed to [plugin_slug]_connect
@@ -125,6 +135,7 @@ class WPLeadInAdmin {
125
  {
126
  unset($activated_power_ups[$mailchimp_list_sync_key]);
127
  $activated_power_ups[] = 'mailchimp_connect';
 
128
  }
129
 
130
  $constant_contact_list_sync_key = array_search('constant_contact_list_sync', $activated_power_ups);
@@ -132,13 +143,11 @@ class WPLeadInAdmin {
132
  {
133
  unset($activated_power_ups[$constant_contact_list_sync_key]);
134
  $activated_power_ups[] = 'constant_contact_connect';
 
135
  }
136
 
137
- // 2.2.7 bug fix for non active contacts power-ups
138
- if ( !in_array('contacts', $activated_power_ups) )
139
- $activated_power_ups[] = 'contacts';
140
-
141
- update_option('leadin_active_power_ups', serialize($activated_power_ups));
142
  }
143
 
144
  // 0.7.2 bug fix - data recovery algorithm for deleted contacts
@@ -147,6 +156,28 @@ class WPLeadInAdmin {
147
  leadin_recover_contact_data();
148
  }
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  // Set the database version if it doesn't exist
151
  if ( isset($options['li_db_version']) )
152
  {
@@ -180,6 +211,19 @@ class WPLeadInAdmin {
180
 
181
  // Set the plugin version
182
  leadin_update_option('leadin_options', 'leadin_version', LEADIN_PLUGIN_VERSION);
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  }
184
 
185
  //=============================================
@@ -217,10 +261,11 @@ class WPLeadInAdmin {
217
 
218
  }
219
  }
220
-
221
  self::check_admin_action();
222
 
223
- add_menu_page('Leadin', 'Leadin', $capability, 'leadin_stats', array($this, 'leadin_build_stats_page'), LEADIN_PATH . '/images/' . ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'leadin-icon-32x32.png' : 'leadin-svg-icon.svg'), '25.100713');
 
224
 
225
  foreach ( $this->admin_power_ups as $power_up )
226
  {
@@ -237,6 +282,10 @@ class WPLeadInAdmin {
237
  add_submenu_page('leadin_stats', 'Tags', 'Tags', $capability, 'leadin_tags', array(&$this, 'leadin_build_tag_page'));
238
  add_submenu_page('leadin_stats', 'Settings', 'Settings', 'activate_plugins', 'leadin_settings', array(&$this, 'leadin_plugin_options'));
239
  add_submenu_page('leadin_stats', 'Power-ups', 'Power-ups', 'activate_plugins', 'leadin_power_ups', array(&$this, 'leadin_power_ups_page'));
 
 
 
 
240
  $submenu['leadin_stats'][0][0] = 'Stats';
241
 
242
  if ( !isset($_GET['page']) || $_GET['page'] != 'leadin_settings' )
@@ -249,6 +298,64 @@ class WPLeadInAdmin {
249
 
250
  }
251
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  //=============================================
253
  // Settings Page
254
  //=============================================
@@ -277,7 +384,7 @@ class WPLeadInAdmin {
277
 
278
  echo '<div id="leadin" class="li-stats wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
279
 
280
- $this->leadin_header('Leadin Stats: ' . date('F j Y, g:ia', current_time('timestamp')), 'leadin-stats__header');
281
 
282
  echo '<div class="leadin-stats__top-container">';
283
  echo $this->leadin_postbox('leadin-stats__chart', leadin_single_plural_label(number_format($this->stats_dashboard->total_contacts_last_30_days), 'new contact', 'new contacts') . ' last 30 days', $this->leadin_build_contacts_chart_stats());
@@ -293,6 +400,8 @@ class WPLeadInAdmin {
293
  echo '<div class="leadin-stats__postbox_containter">';
294
  echo $this->leadin_postbox('leadin-stats__sources', 'New contact sources last 30 days', $this->leadin_build_sources_postbox());
295
  echo '</div>';
 
 
296
  }
297
 
298
 
@@ -331,11 +440,17 @@ class WPLeadInAdmin {
331
  } // Create a comma deliniated list of synced lists for tag_synced_lists
332
  else if ( strstr($name, 'email_connect_') )
333
  {
334
- $synced_list = '';
335
  if ( strstr($name, '_mailchimp') )
336
  $synced_list = array('esp' => 'mailchimp', 'list_id' => str_replace('email_connect_mailchimp_', '', $name), 'list_name' => $value);
337
  else if ( strstr($name, '_constant_contact') )
338
  $synced_list = array('esp' => 'constant_contact', 'list_id' => str_replace('email_connect_constant_contact_', '', $name), 'list_name' => $value);
 
 
 
 
 
 
339
 
340
  array_push($tag_synced_lists, $synced_list);
341
  }
@@ -415,7 +530,12 @@ class WPLeadInAdmin {
415
  $tagger->get_tag_details($tagger->tag_id);
416
 
417
  echo '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">&larr; Manage tags</a>';
418
- $this->leadin_header(( $this->action == 'edit_tag' ? 'Edit a tag' : 'Add a tag' ), 'leadin-contacts__header');
 
 
 
 
 
419
  ?>
420
 
421
  <div class="">
@@ -495,6 +615,8 @@ class WPLeadInAdmin {
495
  case 'mailchimp' :
496
  $esp_list_url = 'http://admin.mailchimp.com/lists/new-list/';
497
  $settings_page_anchor_id = '#li_mls_api_key';
 
 
498
  break;
499
 
500
  case 'constant_contact' :
@@ -502,6 +624,27 @@ class WPLeadInAdmin {
502
  $settings_page_anchor_id = '#li_cc_email';
503
  break;
504
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  default:
506
  $esp_list_url = '';
507
  $settings_page_anchor_id = '';
@@ -511,12 +654,12 @@ class WPLeadInAdmin {
511
  if ( ! ${'leadin_' . $power_up_slug . '_wp'}->admin->authed )
512
  {
513
  echo 'It looks like you haven\'t set up your ' . $esp_name_readable . ' integration yet...<br/><br/>';
514
- echo '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_settings' . $settings_page_anchor_id . '">Setup your ' . $esp_name_readable . ' integration</a>';
515
  }
516
  else if ( ${'leadin_' . $power_up_slug . '_wp'}->admin->invalid_key )
517
  {
518
- echo 'It looks like your ' . $esp_name_readable . ' API key is invalid...<br/><br/>';
519
- echo '<p><a href="http://admin.mailchimp.com/account/api/" target="_blank">Get your API key from MailChimp.com</a> then try copying and pasting it again in <a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_settings' . $settings_page_anchor_id . '">Leadin → Settings</a></p>';
520
  }
521
  else if ( count($lists) )
522
  {
@@ -533,15 +676,18 @@ class WPLeadInAdmin {
533
 
534
  if ( $synced_lists )
535
  {
 
 
536
  $key = leadin_array_search_deep($list_id, $synced_lists, 'list_id');
537
 
538
  if ( isset($key) )
539
  {
 
540
  if ( $synced_lists[$key]['esp'] == $esp_name )
541
  $synced = TRUE;
542
  }
543
  }
544
-
545
  echo '<label for="' . $html_id . '">';
546
  echo '<input name="' . $html_id . '" type="checkbox" id="' . $html_id . '" value="' . $list->name . '" ' . ( $synced ? 'checked' : '' ) . '>';
547
  echo $list->name;
@@ -551,7 +697,7 @@ class WPLeadInAdmin {
551
  else
552
  {
553
  echo 'It looks like you don\'t have any ' . $esp_name_readable . ' lists yet...<br/><br/>';
554
- echo '<a href="' . $esp_list_url . '" target="_blank">Create a list on ' . $esp_url . '.com</a>';
555
  }
556
  echo '</fieldset>';
557
  echo '</td>';
@@ -602,7 +748,7 @@ class WPLeadInAdmin {
602
  <div class="leadin-contacts">
603
 
604
  <?php
605
- $this->leadin_header('Manage Leadin Tags <a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags&action=add_tag" class="add-new-h2">Add New</a>', '');
606
  ?>
607
 
608
  <div class="">
@@ -871,7 +1017,7 @@ class WPLeadInAdmin {
871
  function leadin_options_section_heading ( )
872
  {
873
  $this->print_hidden_settings_fields();
874
-
875
  if ( $this->has_leads() )
876
  {
877
  echo '<div class="leadin-section">';
@@ -885,7 +1031,7 @@ class WPLeadInAdmin {
885
  echo '<p style="color: #f67d42; font-weight: bold;">Leadin is set up and waiting for a form submission...</p>';
886
  echo '<p>Can\'t wait to see Leadin in action? Go fill out a form on your site to see your first contact.</p>';
887
  echo '</div>';
888
- }
889
  }
890
 
891
  function print_hidden_settings_fields ()
@@ -903,6 +1049,8 @@ class WPLeadInAdmin {
903
  $converted_to_tags = ( isset($options['converted_to_tags']) ? $options['converted_to_tags'] : 0 );
904
  $names_added_to_contacts = ( isset($options['names_added_to_contacts']) ? $options['names_added_to_contacts'] : 0 );
905
  $leadin_version = ( isset($options['leadin_version']) ? $options['leadin_version'] : LEADIN_PLUGIN_VERSION );
 
 
906
 
907
  printf(
908
  '<input id="li_installed" type="hidden" name="leadin_options[li_installed]" value="%d"/>',
@@ -953,6 +1101,16 @@ class WPLeadInAdmin {
953
  '<input id="leadin_version" type="hidden" name="leadin_options[leadin_version]" value="%s"/>',
954
  $leadin_version
955
  );
 
 
 
 
 
 
 
 
 
 
956
  }
957
 
958
  function has_leads ( )
@@ -963,21 +1121,13 @@ class WPLeadInAdmin {
963
  $num_contacts = $wpdb->get_var($q);
964
 
965
  if ( $num_contacts > 0 )
966
- {
967
- return true;
968
- }
969
  else
970
- {
971
- return false;
972
- }
973
  }
974
 
975
  function update_option_leadin_options_callback ( $old_value, $new_value )
976
  {
977
- $user_email = $new_value["li_email"];
978
-
979
- if ( isset( $_POST['li_updates_subscription'] ) && $_POST['li_updates_subscription'] )
980
- leadin_subscribe_user_updates();
981
  }
982
 
983
  /**
@@ -1004,73 +1154,90 @@ class WPLeadInAdmin {
1004
  global $wp_version;
1005
 
1006
  $li_options = get_option('leadin_options');
1007
-
1008
  echo '<div id="leadin" class="li-onboarding wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1009
 
1010
- $this->leadin_header('Leadin Setup');
1011
 
1012
  ?>
1013
 
1014
- <div class="oboarding-steps">
1015
-
1016
  <?php if ( ! isset($_GET['activate_popup']) ) : ?>
1017
 
1018
  <?php if ( $li_options['onboarding_step'] == 1 ) : ?>
1019
 
1020
- <ol class="oboarding-steps-names">
1021
- <li class="oboarding-step-name completed">Activate Leadin</li>
1022
- <li class="oboarding-step-name active">Get Contact Reports</li>
1023
- <li class="oboarding-step-name">Grow Your Contacts List</li>
1024
- </ol>
1025
- <div class="oboarding-step">
1026
- <h2 class="oboarding-step-title">Where should we send your contact reports?</h2>
1027
- <div class="oboarding-step-content">
1028
- <p class="oboarding-step-description">Leadin will help you get to know your website visitors by sending you a report including traffic source and pageview history each time a visitor fills out a form.</p>
1029
- <form id="li-onboarding-form" method="post" action="options.php">
1030
- <div>
1031
- <?php settings_fields('leadin_settings_options'); ?>
1032
- <?php $this->li_email_callback(); ?>
1033
- <?php if ( function_exists('curl_init') && function_exists('curl_setopt') ) : ?>
1034
- <br>
1035
- <label for="li_updates_subscription"><input type="checkbox" id="li_updates_subscription" name="li_updates_subscription" checked/>Keep me up to date with security and feature updates</label>
1036
- <?php endif; ?>
1037
- </div>
1038
- <?php $this->print_hidden_settings_fields(); ?>
1039
- <input type="hidden" id="next_onboarding_step" name="next_onboarding_step" value="2">
1040
- <input type="submit" name="submit" id="submit" class="button button-primary button-big" value="<?php esc_attr_e('Save Email'); ?>">
1041
- </form>
1042
  </div>
1043
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1044
 
1045
  <?php elseif ( $li_options['onboarding_step'] == 2 ) : ?>
1046
 
1047
- <ol class="oboarding-steps-names">
1048
- <li class="oboarding-step-name completed">Activate Leadin</li>
1049
- <li class="oboarding-step-name completed">Get Contact Reports</li>
1050
- <li class="oboarding-step-name active">Grow Your Contacts List</li>
1051
- </ol>
1052
- <div class="oboarding-step">
1053
- <h2 class="oboarding-step-title">Grow your contacts list with our popup form<br><small>and start converting visitors on <?php echo get_bloginfo('wpurl') ?></small></h2>
1054
- <form id="li-onboarding-form" method="post" action="options.php">
1055
- <?php $this->print_hidden_settings_fields(); ?>
1056
- <div class="popup-options">
1057
- <label class="popup-option">
1058
- <input type="radio" name="popup-position" value="slide_in" checked="checked" >Slide in
1059
- <img src="<?php echo LEADIN_PATH ?>/images/popup-bottom.png">
1060
- </label>
1061
- <label class="popup-option">
1062
- <input type="radio" name="popup-position" value="popup">Popup
1063
- <img src="<?php echo LEADIN_PATH ?>/images/popup-over.png">
1064
- </label>
1065
- <label class="popup-option">
1066
- <input type="radio" name="popup-position" value="top">Top
1067
- <img src="<?php echo LEADIN_PATH ?>/images/popup-top.png">
1068
- </label>
1069
- </div>
1070
- <input type="hidden" id="next_onboarding_step" name="next_onboarding_step" value="3">
1071
- <a id="btn-activate-subscribe" href="<?php echo get_admin_url() .'admin.php?page=leadin_settings&leadin_action=activate&power_up=subscribe_widget&redirect_to=' . get_admin_url() . urlencode('admin.php?page=leadin_settings&activate_popup=true&popup_position=slide_in'); ?>" class="button button-primary button-big"><?php esc_attr_e('Activate the popup form');?></a>
1072
- <p><a href="<?php echo get_admin_url() .'admin.php?page=leadin_settings&activate_popup=false'; ?>">Don't activate the popup form right now</a></p>
1073
- </form>
 
 
 
 
1074
  </div>
1075
 
1076
  <?php endif; ?>
@@ -1099,7 +1266,10 @@ class WPLeadInAdmin {
1099
  }
1100
 
1101
  leadin_update_option('leadin_subscribe_options', 'li_subscribe_vex_class', $vex_class_option);
 
1102
  }
 
 
1103
 
1104
  // Update the onboarding settings
1105
  if ( ! isset($options['onboarding_complete']) || ! $options['onboarding_complete'] )
@@ -1107,39 +1277,28 @@ class WPLeadInAdmin {
1107
  leadin_update_option('leadin_options', 'onboarding_complete', 1);
1108
  }
1109
  ?>
 
 
1110
 
1111
- <ol class="oboarding-steps-names">
1112
- <li class="oboarding-step-name completed">Activate Leadin</li>
1113
- <li class="oboarding-step-name completed">Get Contact Reports</li>
1114
- <li class="oboarding-step-name completed">Grow Your Contacts List</li>
1115
- </ol>
1116
- <div class="oboarding-step">
1117
- <h2 class="oboarding-step-title">Setup Complete!<br>Leadin is waiting for your first form submission.</h2>
1118
- <div class="oboarding-step-content">
1119
- <p class="oboarding-step-description">Leadin is set up and waiting for a form submission. Once Leadin detects a form submission, a new contact will be added to your contacts list. We recommend filling out a form on your site to test that Leadin is working correctly.</p>
1120
- <form id="li-onboarding-form" method="post" action="options.php">
1121
- <?php $this->print_hidden_settings_fields(); ?>
1122
- <a href="<?php echo get_admin_url() . 'admin.php?page=leadin_settings'; ?>" class="button button-primary button-big"><?php esc_attr_e('Complete Setup'); ?></a>
1123
- </form>
 
 
1124
  </div>
1125
  </div>
1126
 
1127
  <?php endif; ?>
1128
-
1129
- </div>
1130
-
1131
-
1132
- <div class="oboarding-steps-help">
1133
- <h4>Any questions?</h4>
1134
- <?php if ( isset($li_options['premium']) && $li_options['premium'] ) : ?>
1135
- <p>Send us a message and we’re happy to help you get set up.</p>
1136
- <a class="button" href="#" onclick="return SnapEngage.startLink();">Chat with us</a>
1137
- <?php else : ?>
1138
- <p>Leave us a message in the WordPress support forums. We're always happy to help you get set up and can answer any questions there.</p>
1139
- <a class="button" href="http://wordpress.org/support/plugin/leadin" target="_blank">Go to Forums</a>
1140
- <?php endif; ?>
1141
- </div>
1142
-
1143
 
1144
  <?php
1145
 
@@ -1158,7 +1317,7 @@ class WPLeadInAdmin {
1158
 
1159
  echo '<div id="leadin" class="li-settings wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1160
 
1161
- $this->leadin_header('Leadin Settings');
1162
 
1163
  ?>
1164
  <div class="leadin-settings__content">
@@ -1170,9 +1329,11 @@ class WPLeadInAdmin {
1170
  ?>
1171
  </form>
1172
  </div>
1173
- <div class="leadin-settings__sidebar">
1174
- <a href="http://leadin.com/pro-upgrade/?utm_source=Leadin%20Repo%20Plugin&utm_medium=Settings%20Banner&utm_campaign=Repo"><img class="pro-upgrade-cta" src="<?php echo LEADIN_PATH; ?>/images/pro-upgrade-cta.png"></a>
1175
- </div>
 
 
1176
  <?php
1177
 
1178
  $this->leadin_footer();
@@ -1190,42 +1351,45 @@ class WPLeadInAdmin {
1190
  {
1191
  $new_input = array();
1192
 
1193
- if( isset( $input['li_email'] ) )
1194
  $new_input['li_email'] = sanitize_text_field( $input['li_email'] );
1195
 
1196
- if( isset( $input['li_installed'] ) )
1197
  $new_input['li_installed'] = $input['li_installed'];
1198
 
1199
- if( isset( $input['li_db_version'] ) )
1200
  $new_input['li_db_version'] = $input['li_db_version'];
1201
 
1202
- if( isset( $input['onboarding_step'] ) )
1203
  $new_input['onboarding_step'] = ( $input['onboarding_step'] + 1 );
1204
 
1205
- if( isset( $input['onboarding_complete'] ) )
1206
  $new_input['onboarding_complete'] = $input['onboarding_complete'];
1207
 
1208
- if( isset( $input['ignore_settings_popup'] ) )
1209
  $new_input['ignore_settings_popup'] = $input['ignore_settings_popup'];
1210
 
1211
- if( isset( $input['data_recovered'] ) )
1212
  $new_input['data_recovered'] = $input['data_recovered'];
1213
 
1214
- if( isset( $input['converted_to_tags'] ) )
1215
  $new_input['converted_to_tags'] = $input['converted_to_tags'];
1216
 
1217
- if( isset( $input['names_added_to_contacts'] ) )
1218
  $new_input['names_added_to_contacts'] = $input['names_added_to_contacts'];
1219
 
1220
- if( isset( $input['delete_flags_fixed'] ) )
1221
  $new_input['delete_flags_fixed'] = $input['delete_flags_fixed'];
1222
 
1223
- if( isset( $input['leadin_version'] ) )
1224
  $new_input['leadin_version'] = $input['leadin_version'];
1225
 
1226
- if( isset( $input['li_updates_subscription'] ) )
1227
  $new_input['li_updates_subscription'] = $input['li_updates_subscription'];
1228
 
 
 
 
1229
  $user_roles = get_editable_roles();
1230
  if ( count($user_roles) )
1231
  {
@@ -1327,7 +1491,7 @@ class WPLeadInAdmin {
1327
 
1328
  echo '<div id="leadin" class="li-settings wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1329
 
1330
- $this->leadin_header('Leadin Power-ups');
1331
 
1332
  ?>
1333
 
@@ -1343,7 +1507,7 @@ class WPLeadInAdmin {
1343
  continue;
1344
  ?>
1345
 
1346
- <?php if ( $power_up_count == 1 ) : ?>
1347
  <!-- static content stats power-up - not a real powerup and this is a hack to put it second in the order -->
1348
  <li class="powerup activated">
1349
  <div class="img-containter">
@@ -1366,23 +1530,37 @@ class WPLeadInAdmin {
1366
  </div>
1367
  <h2><?php echo $power_up->power_up_name; ?></h2>
1368
  <p><?php echo $power_up->description; ?></p>
 
1369
  <?php if ( $power_up->activated ) : ?>
1370
  <?php if ( ! $power_up->permanent ) : ?>
 
1371
  <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups&leadin_action=deactivate&power_up=' . $power_up->slug; ?>" class="button button-secondary button-large">Deactivate</a>
1372
  <?php endif; ?>
1373
  <?php else : ?>
1374
- <?php if ( ( $power_up->curl_required && function_exists('curl_init') && function_exists('curl_setopt') ) || ! $power_up->curl_required ) : ?>
1375
- <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups&leadin_action=activate&power_up=' . $power_up->slug; ?>" class="button button-primary button-large">Activate</a>
 
 
 
1376
  <?php else : ?>
1377
- <p><a href="http://stackoverflow.com/questions/2939820/how-to-enable-curl-installed-ubuntu-lamp-stack" target="_blank">Install cURL</a> to use this power-up.</p>
1378
- <?php endif; ?>
 
 
 
 
 
 
1379
  <?php endif; ?>
 
 
1380
 
1381
- <?php if ( $power_up->activated || $power_up->permanent ) : ?>
1382
- <?php if ( $power_up->menu_link == 'contacts' ) : ?>
1383
- <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_' . $power_up->menu_link; ?>" class="button button-secondary button-large">View Contacts</a>
1384
  <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_settings'; ?>" class="button button-secondary button-large">Configure</a>
1385
  <?php else : ?>
 
1386
  <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_' . $power_up->menu_link; ?>" class="button button-secondary button-large">Configure</a>
1387
  <?php endif; ?>
1388
  <?php endif; ?>
@@ -1404,9 +1582,8 @@ class WPLeadInAdmin {
1404
  <img src="<?php echo LEADIN_PATH; ?>/images/powerup-icon-vip@2x.png" height="80px" width="80px">
1405
  </div>
1406
  <h2>Leadin VIP Program</h2>
1407
-
1408
  <p>Exclusive features and offers for consultants and agencies.</p>
1409
-
1410
  <a href="http://leadin.com/vip" target="_blank" class="button button-primary button-large">Become a VIP</a>
1411
  </li>
1412
 
@@ -1434,6 +1611,7 @@ class WPLeadInAdmin {
1434
 
1435
  WPLeadIn::activate_power_up( $power_up, FALSE );
1436
  //ob_end_clean();
 
1437
 
1438
  if ( isset($_GET['redirect_to']) )
1439
  wp_redirect($_GET['redirect_to']);
@@ -1448,6 +1626,7 @@ class WPLeadInAdmin {
1448
  $power_up = stripslashes( $_GET['power_up'] );
1449
 
1450
  WPLeadIn::deactivate_power_up( $power_up, FALSE );
 
1451
  wp_redirect(get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups');
1452
  exit;
1453
 
@@ -1502,27 +1681,97 @@ class WPLeadInAdmin {
1502
  *
1503
  * @param string
1504
  */
1505
- function leadin_header ( $page_title = '', $css_class = '' )
1506
  {
 
 
1507
  ?>
1508
-
1509
- <?php if ( ! $this->has_leads()) : ?>
1510
- <div id="message" class="updated">
1511
- <p>Leadin is set up and waiting for a form submission... Need help? <a href="http://wordpress.org/support/plugin/leadin">Contact Us</a>.</p>
1512
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1513
  <?php endif; ?>
1514
 
1515
  <?php screen_icon('leadin'); ?>
1516
-
1517
  <h2 class="<?php echo $css_class ?>"><?php echo $page_title; ?></h2>
1518
 
 
 
 
 
 
 
 
 
1519
  <?php $options = get_option('leadin_options'); ?>
1520
 
1521
  <?php if ( isset($_GET['settings-updated']) && $options['onboarding_complete'] ) : ?>
1522
  <div id="message" class="updated">
1523
  <p><strong><?php _e('Settings saved.') ?></strong></p>
1524
  </div>
1525
- <?php endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1526
  }
1527
 
1528
  function leadin_footer ()
@@ -1531,37 +1780,17 @@ class WPLeadInAdmin {
1531
 
1532
  ?>
1533
  <div id="leadin-footer">
1534
- <p class="support">
1535
- <a href="http://leadin.com">Leadin</a> <?php echo LEADIN_PLUGIN_VERSION?>
1536
- <?php if ( isset($li_options['premium']) && $li_options['premium'] ) : ?>
1537
- <span style="padding: 0px 5px;">|</span>Need help? <a href="#" onclick="return SnapEngage.startLink();">Contact us</a>
1538
- <?php else : ?>
1539
- <span style="padding: 0px 5px;">|</span><a href="https://wordpress.org/support/plugin/leadin" target="_blank">Support forums</a>
1540
- <?php endif; ?>
1541
  <span style="padding: 0px 5px;">|</span><a href="http://leadin.com/dev-updates/">Get product &amp; security updates</a>
1542
  <span style="padding: 0px 5px;">|</span><a href="http://wordpress.org/support/view/plugin-reviews/leadin?rate=5#postform">Leave us a review</a>
1543
  </p>
1544
- <p class="sharing"><a href="https://twitter.com/leadinapp" class="twitter-follow-button" data-show-count="false">Follow @leadinapp</a>
1545
 
 
1546
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script></p>
1547
  </div>
1548
- <!-- begin SnapEngage code -->
1549
- <script type="text/javascript">
1550
- (function() {
1551
- var se = document.createElement('script'); se.type = 'text/javascript'; se.async = true;
1552
- se.src = '//commondatastorage.googleapis.com/code.snapengage.com/js/b7667cce-a26d-4440-a716-7c4b9f086705.js';
1553
- var done = false;
1554
- se.onload = se.onreadystatechange = function() {
1555
- if (!done&&(!this.readyState||this.readyState==='loaded'||this.readyState==='complete')) {
1556
- done = true;
1557
- // Place your SnapEngage JS API code below
1558
- // SnapEngage.allowChatSound(true); // Example JS API: Enable sounds for Visitors.
1559
- }
1560
- };
1561
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(se, s);
1562
- })();
1563
- </script>
1564
- <!-- end SnapEngage code -->
1565
  <?php
1566
  }
1567
 
56
  */
57
  function __construct ( $power_ups )
58
  {
 
59
  //=============================================
60
  // Hooks & Filters
61
  //=============================================
62
 
63
  $options = get_option('leadin_options');
64
 
 
 
 
65
  $this->action = $this->leadin_current_action();
66
 
67
  // If the plugin version matches the latest version escape the update function
79
  {
80
  add_action('admin_footer', array($this, 'build_contacts_chart'));
81
  }
82
+
83
+ $updater_type = '';
84
+
85
+ if ( isset($options['pro']) && $options['pro'] )
86
+ $updater_type = 'pro';
87
+
88
+ if ( $updater_type )
89
+ $li_wp_updater = new WPLeadInUpdater($updater_type);
90
  }
91
 
92
+ function leadin_update_check ()
93
  {
94
  $options = get_option('leadin_options');
95
 
96
  // 0.5.1 upgrade - Create active power-ups option if it doesn't exist
97
  $leadin_active_power_ups = get_option('leadin_active_power_ups');
98
 
99
+ if ( ! $leadin_active_power_ups )
100
  {
101
  $auto_activate = array(
102
+ 'contacts',
103
+ 'lookups'
104
  );
105
 
106
  update_option('leadin_active_power_ups', serialize($auto_activate));
109
  {
110
  // 0.9.2 upgrade - set beta program power-up to auto-activate
111
  $activated_power_ups = unserialize($leadin_active_power_ups);
112
+ $update_active_power_ups = FALSE;
113
 
114
  // 0.9.3 bug fix for duplicate beta_program values being stored in the active power-ups array
115
  if ( !in_array('beta_program', $activated_power_ups) )
116
  {
117
  $activated_power_ups[] = 'beta_program';
118
+ $update_active_power_ups = TRUE;
119
  }
120
  else
121
  {
123
  $count = $tmp['beta_program'];
124
 
125
  if ( $count > 1 )
126
+ {
127
  $activated_power_ups = array_unique($activated_power_ups);
128
+ $update_active_power_ups = TRUE;
129
+ }
130
  }
131
 
132
  // 2.0.1 upgrade - [plugin_slug]_list_sync changed to [plugin_slug]_connect
135
  {
136
  unset($activated_power_ups[$mailchimp_list_sync_key]);
137
  $activated_power_ups[] = 'mailchimp_connect';
138
+ $update_active_power_ups = TRUE;
139
  }
140
 
141
  $constant_contact_list_sync_key = array_search('constant_contact_list_sync', $activated_power_ups);
143
  {
144
  unset($activated_power_ups[$constant_contact_list_sync_key]);
145
  $activated_power_ups[] = 'constant_contact_connect';
146
+ $update_active_power_ups = TRUE;
147
  }
148
 
149
+ if ( $update_active_power_ups )
150
+ update_option('leadin_active_power_ups', serialize($activated_power_ups));
 
 
 
151
  }
152
 
153
  // 0.7.2 bug fix - data recovery algorithm for deleted contacts
156
  leadin_recover_contact_data();
157
  }
158
 
159
+ // Check if the pro flag is not set and version > 3.0 and if yes, set the pro flag. This resets the Pro flag and takes care of the settings bug from Pro 3.1.3
160
+ if ( ! isset($options['pro']) )
161
+ {
162
+ if ( isset($options['leadin_version']) && version_compare($options['leadin_version'], '3.0.0', '>=') && version_compare($options['leadin_version'], '3.1.4', '<') )
163
+ {
164
+ leadin_update_option('leadin_options', 'pro', 1);
165
+
166
+ // Check to make sure the lookups power-up is activate for Pro users
167
+ if ( ! in_array('lookups', $activated_power_ups) )
168
+ WPLeadIn::activate_power_up('lookups', FALSE);
169
+ }
170
+ }
171
+ else
172
+ {
173
+ if ( $options['pro'] )
174
+ {
175
+ // Check to make sure the lookups power-up is activate for Pro users
176
+ if ( ! in_array('lookups', $activated_power_ups) )
177
+ WPLeadIn::activate_power_up('lookups', FALSE);
178
+ }
179
+ }
180
+
181
  // Set the database version if it doesn't exist
182
  if ( isset($options['li_db_version']) )
183
  {
211
 
212
  // Set the plugin version
213
  leadin_update_option('leadin_options', 'leadin_version', LEADIN_PLUGIN_VERSION);
214
+
215
+ if ( leadin_check_pro_user() )
216
+ {
217
+ $leadin_user = leadin_get_current_user();
218
+ leadin_set_user_properties(array(
219
+ '$wp-url' => get_bloginfo('wpurl'),
220
+ '$wp-version' => $leadin_user['wp_version'],
221
+ '$li-version' => $leadin_user['li_version']
222
+ ));
223
+ }
224
+
225
+ // Catch all for installs that get their options nixed for whatever reason
226
+ leadin_check_missing_options($options);
227
  }
228
 
229
  //=============================================
261
 
262
  }
263
  }
264
+
265
  self::check_admin_action();
266
 
267
+ $leadin_icon = ($wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? LEADIN_PATH . '/images/leadin-icon-32x32.png' : 'data:image/svg+xml;base64,' . base64_encode(file_get_contents(LEADIN_PATH . '/images/leadin-svg-icon.svg')));
268
+ add_menu_page('Leadin', 'Leadin', $capability, 'leadin_stats', array($this, 'leadin_build_stats_page'), $leadin_icon , '25.100713');
269
 
270
  foreach ( $this->admin_power_ups as $power_up )
271
  {
282
  add_submenu_page('leadin_stats', 'Tags', 'Tags', $capability, 'leadin_tags', array(&$this, 'leadin_build_tag_page'));
283
  add_submenu_page('leadin_stats', 'Settings', 'Settings', 'activate_plugins', 'leadin_settings', array(&$this, 'leadin_plugin_options'));
284
  add_submenu_page('leadin_stats', 'Power-ups', 'Power-ups', 'activate_plugins', 'leadin_power_ups', array(&$this, 'leadin_power_ups_page'));
285
+
286
+ if ( ! leadin_check_pro_user() )
287
+ add_submenu_page('leadin_stats', 'Pro Upgrade', 'Pro Upgrade', 'activate_plugins', 'leadin_pro_upgrade', array(&$this, 'leadin_pro_upgrade_page'));
288
+
289
  $submenu['leadin_stats'][0][0] = 'Stats';
290
 
291
  if ( !isset($_GET['page']) || $_GET['page'] != 'leadin_settings' )
298
 
299
  }
300
 
301
+ function leadin_pro_upgrade_page ()
302
+ {
303
+ global $wp_version;
304
+
305
+ echo '<div id="leadin" class=" wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
306
+
307
+ $this->leadin_header('Upgrade to Leadin Pro for free');
308
+
309
+ ?>
310
+ <p>Leadin Pro is the best version of Leadin to date. </p>
311
+ <div class="compare">
312
+ <div class="title">
313
+ <h2>Leadin (current version)</h2>
314
+ </div>
315
+ <div class="content">
316
+ <ul class="features">
317
+ <li>Contacts Tracking</li>
318
+ <p>Learn more about your visitors.</p>
319
+ <li>Contacts Analytics</li>
320
+ <p>Find out what content and traffic sources convert the best.</p>
321
+ <li>Popup Form</li>
322
+ <p>Convert more visitors to contacts, faster.</p>
323
+ <li>Email Connectors</li>
324
+ <p>Push contacts to MailChimp, Constant Contact, Campaign Monitor, GetResponse and AWeber without replacing any of your forms.</p>
325
+ </ul>
326
+ </div>
327
+ </div>
328
+ <div class="compare">
329
+ <div class="title teal">
330
+ <h2>Leadin Pro</h2>
331
+ </div>
332
+ <div class="content">
333
+ <p>All the features you're enjoying now, plus:</p>
334
+ <ul class="features plus">
335
+ <li>Contact Enrichment</li>
336
+ <p>In addition to seeing the pages your contacts have visited, you'll now be able to see publicly available information about your contacts and their businesses. Info like social accounts, job role, and company location all in your contact reports. </p>
337
+ </ul>
338
+ <?php
339
+ echo '<p id="agree-pp-error" style="display: none; border-left: 4px solid #dd3d36; padding-left: 12px; margin-bottom: 25px;">Before you can unlock the awesomeness of Leadin Pro, we need you to agree to our Privacy Policy, because lawyers.</p>';
340
+ echo '<label for="agree-pp">';
341
+ echo '<input type="checkbox" id="agree-pp" name="agree-pp"/>';
342
+ echo 'I agree to Leadin\'s <a href="http://leadin.com/legal/privacy-policy" target="_blank">Privacy Policy</a></label>';
343
+
344
+ echo '<a id="pro-upgrade-button" class="big-button--orange">Upgrade to Leadin Pro</a>';
345
+ ?>
346
+ </div>
347
+ </div>
348
+
349
+
350
+ <?php
351
+
352
+ $this->leadin_footer();
353
+
354
+ //end wrap
355
+ echo '</div>';
356
+
357
+ }
358
+
359
  //=============================================
360
  // Settings Page
361
  //=============================================
384
 
385
  echo '<div id="leadin" class="li-stats wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
386
 
387
+ $this->leadin_header('Leadin Stats: ' . date('F j Y, g:ia', current_time('timestamp')), 'leadin-stats__header', 'Loaded Stats Page');
388
 
389
  echo '<div class="leadin-stats__top-container">';
390
  echo $this->leadin_postbox('leadin-stats__chart', leadin_single_plural_label(number_format($this->stats_dashboard->total_contacts_last_30_days), 'new contact', 'new contacts') . ' last 30 days', $this->leadin_build_contacts_chart_stats());
400
  echo '<div class="leadin-stats__postbox_containter">';
401
  echo $this->leadin_postbox('leadin-stats__sources', 'New contact sources last 30 days', $this->leadin_build_sources_postbox());
402
  echo '</div>';
403
+
404
+ $this->leadin_footer();
405
  }
406
 
407
 
440
  } // Create a comma deliniated list of synced lists for tag_synced_lists
441
  else if ( strstr($name, 'email_connect_') )
442
  {
443
+ // Name comes through as email_connect_espslug_listid, so replace the beginning of each one with corresponding esp slug, which leaves just the list id
444
  if ( strstr($name, '_mailchimp') )
445
  $synced_list = array('esp' => 'mailchimp', 'list_id' => str_replace('email_connect_mailchimp_', '', $name), 'list_name' => $value);
446
  else if ( strstr($name, '_constant_contact') )
447
  $synced_list = array('esp' => 'constant_contact', 'list_id' => str_replace('email_connect_constant_contact_', '', $name), 'list_name' => $value);
448
+ else if ( strstr($name, '_aweber') )
449
+ $synced_list = array('esp' => 'aweber', 'list_id' => str_replace('email_connect_aweber_', '', $name), 'list_name' => $value);
450
+ else if ( strstr($name, '_campaign_monitor') )
451
+ $synced_list = array('esp' => 'campaign_monitor', 'list_id' => str_replace('email_connect_campaign_monitor_', '', $name), 'list_name' => $value);
452
+ else if ( strstr($name, '_getresponse') )
453
+ $synced_list = array('esp' => 'getresponse', 'list_id' => str_replace('email_connect_getresponse_', '', $name), 'list_name' => $value);
454
 
455
  array_push($tag_synced_lists, $synced_list);
456
  }
530
  $tagger->get_tag_details($tagger->tag_id);
531
 
532
  echo '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">&larr; Manage tags</a>';
533
+
534
+ if ( $this->action == 'edit_tag' ) {
535
+ $this->leadin_header('Edit a tag', 'leadin-contacts__header', 'Loaded Tag Editor');
536
+ } else {
537
+ $this->leadin_header('Add a tag', 'leadin-contacts__header', 'Loaded Add Tag');
538
+ }
539
  ?>
540
 
541
  <div class="">
615
  case 'mailchimp' :
616
  $esp_list_url = 'http://admin.mailchimp.com/lists/new-list/';
617
  $settings_page_anchor_id = '#li_mls_api_key';
618
+ $invalid_key_message = 'It looks like your ' . $esp_name_readable . ' API key is invalid...<br/><br/>';
619
+ $invalid_key_link = '<a target="_blank" href="http://kb.mailchimp.com/accounts/management/about-api-keys#Find-or-Generate-Your-API-Key">Get your API key</a> from <a href="http://admin.mailchimp.com/account/api/" target="_blank">MailChimp.com</a>';
620
  break;
621
 
622
  case 'constant_contact' :
624
  $settings_page_anchor_id = '#li_cc_email';
625
  break;
626
 
627
+ case 'aweber' :
628
+ $esp_list_url = 'https://www.aweber.com/users/newlist#about';
629
+ $settings_page_anchor_id = '#li_ac_auth_code';
630
+ $invalid_key_message = 'It looks like your ' . $esp_name_readable . ' Authorization Code is invalid...<br/><br/>';
631
+ $invalid_key_link = '<a target="_blank" href="https://help.aweber.com/hc/en-us/articles/204031226-How-Do-I-Authorize-an-App-">Get your Authorization Code</a> from <a href="https://auth.aweber.com/1.0/oauth/authorize_app/156b03fb" target="_blank">AWeber.com</a>';
632
+ break;
633
+
634
+ case 'campaign_monitor' :
635
+ $esp_list_url = 'https://login.createsend.com/l';
636
+ $settings_page_anchor_id = '#li_cm_api_key';
637
+ $invalid_key_message = 'It looks like your ' . $esp_name_readable . ' API key is invalid...<br/><br/>';
638
+ $invalid_key_link = '<a target="_blank" href="http://help.campaignmonitor.com/topic.aspx?t=206">Get your API key</a> from <a href="https://login.createsend.com/l" target="_blank">CampaignMonitor.com</a>';
639
+ break;
640
+
641
+ case 'getresponse' :
642
+ $esp_list_url = 'https://app.getresponse.com/create_campaign.html';
643
+ $settings_page_anchor_id = '#li_gr_api_key';
644
+ $invalid_key_message = 'It looks like your ' . $esp_name_readable . ' API key is invalid...<br/><br/>';
645
+ $invalid_key_link = '<a target="_blank" href="http://support.getresponse.com/faq/where-i-find-api-key">Get your API key</a> from <a href="https://app.getresponse.com/account.html#api" target="_blank">GetResponse.com</a>';
646
+ break;
647
+
648
  default:
649
  $esp_list_url = '';
650
  $settings_page_anchor_id = '';
654
  if ( ! ${'leadin_' . $power_up_slug . '_wp'}->admin->authed )
655
  {
656
  echo 'It looks like you haven\'t set up your ' . $esp_name_readable . ' integration yet...<br/><br/>';
657
+ echo '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_settings' . $settings_page_anchor_id . '">Set up your ' . $esp_name_readable . ' integration</a>';
658
  }
659
  else if ( ${'leadin_' . $power_up_slug . '_wp'}->admin->invalid_key )
660
  {
661
+ echo $invalid_key_message;
662
+ echo '<p>' . $invalid_key_link . ' then try copying and pasting it again in <a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_settings' . $settings_page_anchor_id . '">Leadin → Settings</a></p>';
663
  }
664
  else if ( count($lists) )
665
  {
676
 
677
  if ( $synced_lists )
678
  {
679
+
680
+ // Search the synched lists for this tag for the list_id
681
  $key = leadin_array_search_deep($list_id, $synced_lists, 'list_id');
682
 
683
  if ( isset($key) )
684
  {
685
+ // Double check that the list is synced with the actual ESP
686
  if ( $synced_lists[$key]['esp'] == $esp_name )
687
  $synced = TRUE;
688
  }
689
  }
690
+
691
  echo '<label for="' . $html_id . '">';
692
  echo '<input name="' . $html_id . '" type="checkbox" id="' . $html_id . '" value="' . $list->name . '" ' . ( $synced ? 'checked' : '' ) . '>';
693
  echo $list->name;
697
  else
698
  {
699
  echo 'It looks like you don\'t have any ' . $esp_name_readable . ' lists yet...<br/><br/>';
700
+ echo '<a href="' . $esp_list_url . '" target="_blank">Create a list on ' . $esp_url . '</a>';
701
  }
702
  echo '</fieldset>';
703
  echo '</td>';
748
  <div class="leadin-contacts">
749
 
750
  <?php
751
+ $this->leadin_header('Manage Leadin Tags <a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags&action=add_tag" class="add-new-h2">Add New</a>', 'leadin-contacts__header', 'Loaded Tag List');
752
  ?>
753
 
754
  <div class="">
1017
  function leadin_options_section_heading ( )
1018
  {
1019
  $this->print_hidden_settings_fields();
1020
+
1021
  if ( $this->has_leads() )
1022
  {
1023
  echo '<div class="leadin-section">';
1031
  echo '<p style="color: #f67d42; font-weight: bold;">Leadin is set up and waiting for a form submission...</p>';
1032
  echo '<p>Can\'t wait to see Leadin in action? Go fill out a form on your site to see your first contact.</p>';
1033
  echo '</div>';
1034
+ }
1035
  }
1036
 
1037
  function print_hidden_settings_fields ()
1049
  $converted_to_tags = ( isset($options['converted_to_tags']) ? $options['converted_to_tags'] : 0 );
1050
  $names_added_to_contacts = ( isset($options['names_added_to_contacts']) ? $options['names_added_to_contacts'] : 0 );
1051
  $leadin_version = ( isset($options['leadin_version']) ? $options['leadin_version'] : LEADIN_PLUGIN_VERSION );
1052
+ $pro = ( isset($options['pro']) ? $options['pro'] : 0 );
1053
+ $li_updates_subscription = ( isset($options['li_updates_subscription']) ? $options['li_updates_subscription'] : 0 );
1054
 
1055
  printf(
1056
  '<input id="li_installed" type="hidden" name="leadin_options[li_installed]" value="%d"/>',
1101
  '<input id="leadin_version" type="hidden" name="leadin_options[leadin_version]" value="%s"/>',
1102
  $leadin_version
1103
  );
1104
+
1105
+ printf(
1106
+ '<input id="pro" type="hidden" name="leadin_options[pro]" value="%d"/>',
1107
+ $pro
1108
+ );
1109
+
1110
+ printf(
1111
+ '<input id="li_updates_subscription" type="hidden" name="leadin_options[li_updates_subscription]" value="%d"/>',
1112
+ $li_updates_subscription
1113
+ );
1114
  }
1115
 
1116
  function has_leads ( )
1121
  $num_contacts = $wpdb->get_var($q);
1122
 
1123
  if ( $num_contacts > 0 )
1124
+ return TRUE;
 
 
1125
  else
1126
+ return FALSE;
 
 
1127
  }
1128
 
1129
  function update_option_leadin_options_callback ( $old_value, $new_value )
1130
  {
 
 
 
 
1131
  }
1132
 
1133
  /**
1154
  global $wp_version;
1155
 
1156
  $li_options = get_option('leadin_options');
1157
+
1158
  echo '<div id="leadin" class="li-onboarding wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1159
 
 
1160
 
1161
  ?>
1162
 
 
 
1163
  <?php if ( ! isset($_GET['activate_popup']) ) : ?>
1164
 
1165
  <?php if ( $li_options['onboarding_step'] == 1 ) : ?>
1166
 
1167
+ <?php $this->leadin_header('Leadin Setup', 'li_setup', 'Onboarding Step 2 - Get Contact Reports'); ?>
1168
+
1169
+ <div class="oboarding-steps">
1170
+ <ol class="oboarding-steps-names">
1171
+ <li class="oboarding-step-name completed">Activate Leadin</li>
1172
+ <li class="oboarding-step-name active">Get Contact Reports</li>
1173
+ <li class="oboarding-step-name">Grow Your Contacts List</li>
1174
+ </ol>
1175
+ <div class="oboarding-step">
1176
+ <h2 class="oboarding-step-title">Where should we send your contact reports?</h2>
1177
+ <div class="oboarding-step-content">
1178
+ <p class="oboarding-step-description">Leadin will help you get to know your website visitors by sending you a report including traffic source and pageview history each time a visitor fills out a form.</p>
1179
+ <form id="li-onboarding-form" method="post" action="options.php">
1180
+ <div>
1181
+ <?php settings_fields('leadin_settings_options'); ?>
1182
+ <?php $this->li_email_callback(); ?>
1183
+ </div>
1184
+ <?php $this->print_hidden_settings_fields(); ?>
1185
+ <input type="hidden" id="next_onboarding_step" name="next_onboarding_step" value="2">
1186
+ <input type="submit" name="submit" id="submit" class="button button-primary button-big" value="<?php esc_attr_e('Save Email'); ?>">
1187
+ </form>
1188
+ </div>
1189
  </div>
1190
  </div>
1191
+ <!-- Facebook Conversion Code for Installed plugin -->
1192
+ <script>(function() {
1193
+ var _fbq = window._fbq || (window._fbq = []);
1194
+ if (!_fbq.loaded) {
1195
+ var fbds = document.createElement('script');
1196
+ fbds.async = true;
1197
+ fbds.src = '//connect.facebook.net/en_US/fbds.js';
1198
+ var s = document.getElementsByTagName('script')[0];
1199
+ s.parentNode.insertBefore(fbds, s);
1200
+ _fbq.loaded = true;
1201
+ }
1202
+ })();
1203
+ window._fbq = window._fbq || [];
1204
+ window._fbq.push(['track', '6024677413664', {'value':'0.00','currency':'USD'}]);
1205
+ </script>
1206
+ <noscript><img height="1" width="1" alt="" style="display:none" src="https://www.facebook.com/tr?ev=6024677413664&amp;cd[value]=0.00&amp;cd[currency]=USD&amp;noscript=1" /></noscript>
1207
 
1208
  <?php elseif ( $li_options['onboarding_step'] == 2 ) : ?>
1209
 
1210
+ <?php $this->leadin_header('Leadin Setup', 'li_setup', 'Onboarding Step 3 - Grow Your Contact List'); ?>
1211
+
1212
+ <div class="oboarding-steps">
1213
+ <ol class="oboarding-steps-names">
1214
+ <li class="oboarding-step-name completed">Activate Leadin</li>
1215
+ <li class="oboarding-step-name completed">Get Contact Reports</li>
1216
+ <li class="oboarding-step-name active">Grow Your Contacts List</li>
1217
+ </ol>
1218
+ <div class="oboarding-step">
1219
+ <h2 class="oboarding-step-title">Grow your contacts list with our popup form<br><small>and start converting visitors on <?php echo get_bloginfo('wpurl') ?></small></h2>
1220
+ <form id="li-onboarding-form" method="post" action="options.php">
1221
+ <?php $this->print_hidden_settings_fields(); ?>
1222
+ <div class="popup-options">
1223
+ <label class="popup-option">
1224
+ <input type="radio" name="popup-position" value="slide_in" checked="checked" >Slide in
1225
+ <img src="<?php echo LEADIN_PATH ?>/images/popup-bottom.png">
1226
+ </label>
1227
+ <label class="popup-option">
1228
+ <input type="radio" name="popup-position" value="popup">Popup
1229
+ <img src="<?php echo LEADIN_PATH ?>/images/popup-over.png">
1230
+ </label>
1231
+ <label class="popup-option">
1232
+ <input type="radio" name="popup-position" value="top">Top
1233
+ <img src="<?php echo LEADIN_PATH ?>/images/popup-top.png">
1234
+ </label>
1235
+ </div>
1236
+ <input type="hidden" id="next_onboarding_step" name="next_onboarding_step" value="3">
1237
+ <a id="btn-activate-subscribe" href="<?php echo get_admin_url() .'admin.php?page=leadin_settings&leadin_action=activate&power_up=subscribe_widget&redirect_to=' . get_admin_url() . urlencode('admin.php?page=leadin_settings&activate_popup=true&popup_position=slide_in'); ?>" class="button button-primary button-big"><?php esc_attr_e('Activate the popup form');?></a>
1238
+ <p><a href="<?php echo get_admin_url() .'admin.php?page=leadin_settings&activate_popup=false'; ?>">Don't activate the popup form right now</a></p>
1239
+ </form>
1240
+ </div>
1241
  </div>
1242
 
1243
  <?php endif; ?>
1266
  }
1267
 
1268
  leadin_update_option('leadin_subscribe_options', 'li_subscribe_vex_class', $vex_class_option);
1269
+ leadin_track_plugin_activity('Onboarding Popup Activated');
1270
  }
1271
+ else
1272
+ leadin_track_plugin_activity('Onboarding Popup Not Activated');
1273
 
1274
  // Update the onboarding settings
1275
  if ( ! isset($options['onboarding_complete']) || ! $options['onboarding_complete'] )
1277
  leadin_update_option('leadin_options', 'onboarding_complete', 1);
1278
  }
1279
  ?>
1280
+
1281
+ <?php $this->leadin_header('Leadin Setup', 'li_setup', 'Onboarding Complete'); ?>
1282
 
1283
+ <div class="oboarding-steps">
1284
+ <ol class="oboarding-steps-names">
1285
+ <li class="oboarding-step-name completed">Activate Leadin</li>
1286
+ <li class="oboarding-step-name completed">Get Contact Reports</li>
1287
+ <li class="oboarding-step-name completed">Grow Your Contacts List</li>
1288
+ </ol>
1289
+ <div class="oboarding-step">
1290
+ <h2 class="oboarding-step-title">Setup Complete!<br>Leadin is waiting for your first form submission.</h2>
1291
+ <div class="oboarding-step-content">
1292
+ <p class="oboarding-step-description">Leadin is set up and waiting for a form submission. Once Leadin detects a form submission, a new contact will be added to your contacts list. We recommend filling out a form on your site to test that Leadin is working correctly.</p>
1293
+ <form id="li-onboarding-form" method="post" action="options.php">
1294
+ <?php $this->print_hidden_settings_fields(); ?>
1295
+ <a href="<?php echo get_admin_url() . 'admin.php?page=leadin_settings'; ?>" class="button button-primary button-big"><?php esc_attr_e('Complete Setup'); ?></a>
1296
+ </form>
1297
+ </div>
1298
  </div>
1299
  </div>
1300
 
1301
  <?php endif; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1302
 
1303
  <?php
1304
 
1317
 
1318
  echo '<div id="leadin" class="li-settings wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1319
 
1320
+ $this->leadin_header('Leadin Settings', 'li_settings', 'Loaded Settings Page');
1321
 
1322
  ?>
1323
  <div class="leadin-settings__content">
1329
  ?>
1330
  </form>
1331
  </div>
1332
+ <?php if ( ! leadin_check_pro_user() ) : ?>
1333
+ <div class="leadin-settings__sidebar">
1334
+ <a href="<?php echo admin_url(); ?>admin.php?page=leadin_pro_upgrade"><img class="pro-upgrade-cta" src="<?php echo LEADIN_PATH; ?>/images/pro-upgrade-cta.png"></a>
1335
+ </div>
1336
+ <?php endif; ?>
1337
  <?php
1338
 
1339
  $this->leadin_footer();
1351
  {
1352
  $new_input = array();
1353
 
1354
+ if ( isset($input['li_email']) )
1355
  $new_input['li_email'] = sanitize_text_field( $input['li_email'] );
1356
 
1357
+ if ( isset($input['li_installed']) )
1358
  $new_input['li_installed'] = $input['li_installed'];
1359
 
1360
+ if ( isset($input['li_db_version']) )
1361
  $new_input['li_db_version'] = $input['li_db_version'];
1362
 
1363
+ if ( isset($input['onboarding_step']) )
1364
  $new_input['onboarding_step'] = ( $input['onboarding_step'] + 1 );
1365
 
1366
+ if ( isset($input['onboarding_complete']) )
1367
  $new_input['onboarding_complete'] = $input['onboarding_complete'];
1368
 
1369
+ if ( isset($input['ignore_settings_popup']) )
1370
  $new_input['ignore_settings_popup'] = $input['ignore_settings_popup'];
1371
 
1372
+ if ( isset($input['data_recovered']) )
1373
  $new_input['data_recovered'] = $input['data_recovered'];
1374
 
1375
+ if ( isset($input['converted_to_tags']) )
1376
  $new_input['converted_to_tags'] = $input['converted_to_tags'];
1377
 
1378
+ if ( isset($input['names_added_to_contacts']) )
1379
  $new_input['names_added_to_contacts'] = $input['names_added_to_contacts'];
1380
 
1381
+ if ( isset($input['delete_flags_fixed']) )
1382
  $new_input['delete_flags_fixed'] = $input['delete_flags_fixed'];
1383
 
1384
+ if ( isset($input['leadin_version']) )
1385
  $new_input['leadin_version'] = $input['leadin_version'];
1386
 
1387
+ if ( isset($input['li_updates_subscription']) )
1388
  $new_input['li_updates_subscription'] = $input['li_updates_subscription'];
1389
 
1390
+ if ( isset($input['pro']) )
1391
+ $new_input['pro'] = $input['pro'];
1392
+
1393
  $user_roles = get_editable_roles();
1394
  if ( count($user_roles) )
1395
  {
1491
 
1492
  echo '<div id="leadin" class="li-settings wrap '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? 'pre-mp6' : ''). '">';
1493
 
1494
+ $this->leadin_header('Leadin Power-ups', 'li_powerups', 'Loaded Power-ups Page');
1495
 
1496
  ?>
1497
 
1507
  continue;
1508
  ?>
1509
 
1510
+ <?php if ( $power_up_count == 2 ) : ?>
1511
  <!-- static content stats power-up - not a real powerup and this is a hack to put it second in the order -->
1512
  <li class="powerup activated">
1513
  <div class="img-containter">
1530
  </div>
1531
  <h2><?php echo $power_up->power_up_name; ?></h2>
1532
  <p><?php echo $power_up->description; ?></p>
1533
+
1534
  <?php if ( $power_up->activated ) : ?>
1535
  <?php if ( ! $power_up->permanent ) : ?>
1536
+ <?php // SHOW DEACTIVATE POWER-UP BUTTON ?>
1537
  <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups&leadin_action=deactivate&power_up=' . $power_up->slug; ?>" class="button button-secondary button-large">Deactivate</a>
1538
  <?php endif; ?>
1539
  <?php else : ?>
1540
+ <?php // SHOW DEACTIVATE POWER-UP BUTTON ?>
1541
+ <?php if ( $power_up->pro_only ) : ?>
1542
+ <?php if ( ! leadin_check_pro_user() ) : ?>
1543
+ <a href="<?php echo admin_url(); ?>admin.php?page=leadin_pro_upgrade">Upgrade to Pro</a> for free to unlock
1544
+ <?php endif; ?>
1545
  <?php else : ?>
1546
+ <?php if ( ( $power_up->curl_required && function_exists('curl_init') && function_exists('curl_setopt') ) || ! $power_up->curl_required ) : ?>
1547
+ <?php // SHOW ACTIVATE POWER-UP BUTTON ?>
1548
+ <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups&leadin_action=activate&power_up=' . $power_up->slug; ?>" class="button button-primary button-large">Activate</a>
1549
+ <?php else : ?>
1550
+ <?php // SHOW CURL REQUIRED MESSAGE ?>
1551
+ <p><a href="http://stackoverflow.com/questions/2939820/how-to-enable-curl-installed-ubuntu-lamp-stack" target="_blank">Install cURL</a> to use this power-up.</p>
1552
+ <?php endif; ?>
1553
+ <?php endif; ?>
1554
  <?php endif; ?>
1555
+
1556
+ <?php if ( $power_up->activated || ( $power_up->permanent && $power_up->activated ) ) : ?>
1557
 
1558
+ <?php if ( $power_up->slug == 'contacts' || $power_up->slug == 'lookups' ) : ?>
1559
+ <?php // SHOW VIEW CONTACTS / CONFIGURE BUTTON ?>
1560
+ <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_contacts'; ?>" class="button button-secondary button-large">View Contacts</a>
1561
  <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_settings'; ?>" class="button button-secondary button-large">Configure</a>
1562
  <?php else : ?>
1563
+ <?php // SHOW CONFIGURE BUTTON ?>
1564
  <a href="<?php echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_' . $power_up->menu_link; ?>" class="button button-secondary button-large">Configure</a>
1565
  <?php endif; ?>
1566
  <?php endif; ?>
1582
  <img src="<?php echo LEADIN_PATH; ?>/images/powerup-icon-vip@2x.png" height="80px" width="80px">
1583
  </div>
1584
  <h2>Leadin VIP Program</h2>
 
1585
  <p>Exclusive features and offers for consultants and agencies.</p>
1586
+
1587
  <a href="http://leadin.com/vip" target="_blank" class="button button-primary button-large">Become a VIP</a>
1588
  </li>
1589
 
1611
 
1612
  WPLeadIn::activate_power_up( $power_up, FALSE );
1613
  //ob_end_clean();
1614
+ leadin_track_plugin_activity($power_up . " power-up activated");
1615
 
1616
  if ( isset($_GET['redirect_to']) )
1617
  wp_redirect($_GET['redirect_to']);
1626
  $power_up = stripslashes( $_GET['power_up'] );
1627
 
1628
  WPLeadIn::deactivate_power_up( $power_up, FALSE );
1629
+ leadin_track_plugin_activity($power_up . " power-up deactivated");
1630
  wp_redirect(get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_power_ups');
1631
  exit;
1632
 
1681
  *
1682
  * @param string
1683
  */
1684
+ function leadin_header ( $page_title = '', $css_class = '', $event_name = '' )
1685
  {
1686
+ $options = get_option('li_options');
1687
+ $leadin_user = leadin_get_current_user();
1688
  ?>
1689
+
1690
+ <?php if ( leadin_check_pro_user() ) : ?>
1691
+ <?php // @TODO - we should really move this logic to the leadin-admin.js file... ?>
1692
+ <script type="text/javascript">
1693
+ !function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="3.0.1";
1694
+ analytics.load("<?php echo SEGMENT_WRITE_KEY ?>");
1695
+ analytics.identify("<?php echo $leadin_user['user_id']; ?>", {
1696
+ "name" : "<?php echo $leadin_user['alias']; ?>",
1697
+ "email" : "<?php echo $leadin_user['email']; ?>",
1698
+ "wp-url" : "<?php echo $leadin_user['wp_url']; ?>",
1699
+ "wp-version" : "<?php echo $leadin_user['wp_version']; ?>",
1700
+ "li-version" : "<?php echo $leadin_user['li_version']; ?>",
1701
+ "li-source" : "<?php echo LEADIN_SOURCE; ?>",
1702
+ "createdAt" : "<?php echo date('Y-m-d H:i:s'); ?>",
1703
+ "website" : "<?php echo $leadin_user['wp_url']; ?>",
1704
+ "company" : "<?php echo $leadin_user['wp_url']; ?>",
1705
+ "contacts" : "<?php echo $leadin_user['total_contacts']; ?>",
1706
+ "utm_source" : "<?php echo $leadin_user['utm_source']; ?>",
1707
+ "utm_medium" : "<?php echo $leadin_user['utm_medium']; ?>",
1708
+ "utm_term" : "<?php echo $leadin_user['utm_term']; ?>",
1709
+ "utm_content" : "<?php echo $leadin_user['utm_content']; ?>",
1710
+ "utm_campaign" : "<?php echo $leadin_user['utm_campaign']; ?>",
1711
+ "referral_source" : "<?php echo $leadin_user['referral_source']; ?>"
1712
+ });
1713
+
1714
+ jQuery(document).ready( function ( $ ) {
1715
+ <?php if ( $event_name == 'Loaded Contact List Page' ) : ?>
1716
+ var num_tags = jQuery('.icon-tag').length;
1717
+ analytics.track(<?php echo "'$event_name', { num_tags: num_tags }"; ?>);
1718
+ <?php else : ?>
1719
+ analytics.track(<?php echo "'$event_name'"; ?>);
1720
+ <?php endif; ?>
1721
+ });
1722
+ }}();
1723
+ </script>
1724
  <?php endif; ?>
1725
 
1726
  <?php screen_icon('leadin'); ?>
1727
+
1728
  <h2 class="<?php echo $css_class ?>"><?php echo $page_title; ?></h2>
1729
 
1730
+ <?php if ( $options['onboarding_complete'] ) : ?>
1731
+ <?php if ( $this->has_leads() == FALSE ) : ?>
1732
+ <div id="message" class="updated">
1733
+ <p>Leadin is set up and waiting for a form submission... Need help? <a href="http://wordpress.org/support/plugin/leadin">Contact Us</a>.</p>
1734
+ </div>
1735
+ <?php endif; ?>
1736
+ <?php endif; ?>
1737
+
1738
  <?php $options = get_option('leadin_options'); ?>
1739
 
1740
  <?php if ( isset($_GET['settings-updated']) && $options['onboarding_complete'] ) : ?>
1741
  <div id="message" class="updated">
1742
  <p><strong><?php _e('Settings saved.') ?></strong></p>
1743
  </div>
1744
+ <?php endif; ?>
1745
+ <?php if ( isset($options['onboarding_complete']) && $options['onboarding_complete'] && ! isset($_COOKIE['ignore_social_share']) ) : ?>
1746
+ <?php if ( leadin_check_first_pageview_data() ) : ?>
1747
+ <div class="dialog-bottom-right">
1748
+ <h1>Hey, do you like Leadin?</h1>
1749
+ <a href="javscript:void(0);" id="close-share" class="close"></a>
1750
+ <p>Looks like you've been using Leadin for at least 30 days. Want to help support us by spreading the word?</p>
1751
+ <p>We'd love it if you could tell your friends about us or leave us a review on WordPress.org.</p>
1752
+ <a class="big-button--share fb" href="https://www.facebook.com/sharer/sharer.php?u=http://leadin.com/facebook-share" target="_blank"></a>
1753
+ <a class="big-button--share tw" href="https://twitter.com/home?status=I've%20been%20using%20%40LeadinApp%20to%20track%20visitors%20on%20my%20Wordpress%20site.%20Try%20it%20for%20free!%20http://leadin.com/twitter-share" target="_blank"></a>
1754
+ <a class="big-button--share wp" href="https://wordpress.org/support/view/plugin-reviews/leadin?rate=5#postform" target="_blank"></a>
1755
+ </div>
1756
+ <script type="text/javascript">
1757
+ jQuery(document).ready(function($){
1758
+ var BR = $(".dialog-bottom-right");
1759
+ var close = $(".close");
1760
+ BR.animate({
1761
+ "bottom" : 0
1762
+ },
1763
+ 1000);
1764
+ close.click(function(){
1765
+ BR.animate({
1766
+ "bottom" : -400
1767
+ },
1768
+ 1000);
1769
+ });
1770
+ });
1771
+ </script>
1772
+ <?php endif; ?>
1773
+ <?php endif; ?>
1774
+ <?php
1775
  }
1776
 
1777
  function leadin_footer ()
1780
 
1781
  ?>
1782
  <div id="leadin-footer">
1783
+ <p class="support">
1784
+ <a href="http://leadin.com">Leadin</a> <?php echo LEADIN_PLUGIN_VERSION; ?>
1785
+ <span style="padding: 0px 5px;">|</span><a href="http://support.leadin.com" target="_blank">Support Docs</a>
 
 
 
 
1786
  <span style="padding: 0px 5px;">|</span><a href="http://leadin.com/dev-updates/">Get product &amp; security updates</a>
1787
  <span style="padding: 0px 5px;">|</span><a href="http://wordpress.org/support/view/plugin-reviews/leadin?rate=5#postform">Leave us a review</a>
1788
  </p>
 
1789
 
1790
+ <p class="sharing"><a href="https://twitter.com/leadinapp" class="twitter-follow-button" data-show-count="false">Follow @leadinapp</a><p>
1791
  <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script></p>
1792
  </div>
1793
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1794
  <?php
1795
  }
1796
 
assets/css/build/leadin-admin.css CHANGED
@@ -1 +1 @@
1
- #leadin label{cursor:default}#leadin .col-wrap{padding:0}#leadin .col-left .col-wrap{padding-right:10px}#leadin .metabox-holder{*zoom:1}#leadin .metabox-holder:after{content:"";display:table;clear:both}#wp-admin-bar-leadin-admin-menu img{height:16px;width:16px;opacity:0.6}@media (min-width: 1200px){#leadin{*zoom:1;max-width:1420px;max-width:88.75rem;padding-left:20px;padding-left:1.25rem;padding-right:20px;padding-right:1.25rem;margin-left:auto;margin-right:auto;margin:10px 20px 0 0;padding:0}#leadin:after{content:"";display:table;clear:both}#leadin *{box-sizing:border-box}}#li_analytics-meta .li-analytics-link{float:left}#li_analytics-meta .li-analytics-link .li-analytics__face{height:35px;width:35px;margin-right:5px;margin-bottom:5px}#li_analytics-meta .hidden_face{display:none}#li_analytics-meta .show-all-faces-container{clear:both}.leadin-postbox,.powerup-list .powerup{background-color:#fff;border:1px solid #e5e5e5;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.leadin-postbox__header{margin:0;padding:8px 12px;font-size:14px;border-bottom:1px solid #eee}.leadin-postbox__content{margin:11px 0;padding:0 12px;*zoom:1}.leadin-postbox__content:after{content:"";display:table;clear:both}.leadin-postbox__table{margin:0;width:100%}.leadin-postbox__table th{padding:6px 0;text-align:left;text-transform:uppercase;letter-spacing:0.05em}.leadin-postbox__table td{padding:6px 0}.leadin-postbox__table tr,.leadin-postbox__table td,.leadin-postbox__table th{vertical-align:middle !important}.leadin-dynamic-avatar_0{background-color:#F88E4B}.leadin-dynamic-avatar_1{background-color:#64AADA}.leadin-dynamic-avatar_2{background-color:#64C2B6}.leadin-dynamic-avatar_3{background-color:#CF7BAA}.leadin-dynamic-avatar_4{background-color:#E7C24B}.leadin-dynamic-avatar_5{background-color:#9387DA}.leadin-dynamic-avatar_6{background-color:#D6DD99}.leadin-dynamic-avatar_7{background-color:#FF4C4C}.leadin-dynamic-avatar_8{background-color:#99583D}.leadin-dynamic-avatar_9{background-color:#54CC14}@font-face{font-family:"icomoon";src:url("../../fonts/icomoon.eot?-lejfm6");src:url("../../fonts/icomoon.eot?#iefix-lejfm6") format("embedded-opentype"),url("../../fonts/icomoon.woff?-lejfm6") format("woff"),url("../../fonts/icomoon.ttf?-lejfm6") format("truetype"),url("../../fonts/icomoon.svg?-lejfm6#icomoon") format("svg");font-weight:normal;font-style:normal}.icon,.icon-profile,.icon-tag,.icon-tags,.icon-envelope,.icon-user,.icon-cog,.icon-bars,.icon-lab,.icon-bulb,.icon-mover{font-family:"icomoon";speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-profile:before{content:""}.icon-tag:before{content:""}.icon-tags:before{content:""}.icon-envelope:before{content:""}.icon-user:before{content:""}.icon-cog:before{content:""}.icon-bars:before{content:""}.icon-lab:before{content:""}.icon-bulb:before{content:""}.icon-mover:before{content:""}#leadin-footer{*zoom:1;clear:both;margin-top:48px;color:#999;border-top:1px solid #dedede}#leadin-footer:after{content:"";display:table;clear:both}#leadin-footer .support .sharing{height:18px;text-align:left}@media screen and (min-width: 500px){#leadin-footer .support,#leadin-footer .version,#leadin-footer .sharing{width:50%;float:left}#leadin-footer .sharing{text-align:right}}.button-big{padding:6px 36px !important;font-size:14px !important;height:auto !important}.oboarding-steps-names{*zoom:1;margin:0}.oboarding-steps-names:after{content:"";display:table;clear:both}.oboarding-step-name{float:left;margin:0;padding-bottom:24px;list-style:decimal inside none;font-size:18px;color:#bbb}.oboarding-step-name.active{color:#1F7D71;background-image:url(../../../images/triangle.png);background-position:bottom center;background-repeat:no-repeat}.oboarding-step-name.completed{list-style-image:url(../../../images/checkmark.png)}.oboarding-step-name+.oboarding-step-name{margin-left:72px}.oboarding-steps{margin:18px 0}@media (min-width: 1200px){.oboarding-steps{width:66.19718%;float:left;margin-right:1.40845%}}.oboarding-step-content{margin:0 auto;max-width:500px}.oboarding-step-content .description{margin:12px 0;display:block;display:none}.oboarding-step{text-align:center;display:block;padding:36px;background-color:#D3EEEB;border:2px solid #2a9;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;color:#1F7D71}.oboarding-step .form-table th{display:none}.oboarding-step .form-table td{width:auto;display:block}.oboarding-step .form-table input{width:100%;font-size:16px;line-height:1.5;padding:7px 10px;display:block}.oboarding-step .oboarding-step-title,.oboarding-step .oboarding-step-description{color:#1F7D71;padding:0;margin-bottom:36px}.oboarding-step .button-primary{margin-top:36px}.oboarding-step .oboarding-step-description{font-size:16px;text-align:left}.oboarding-step .popup-option{width:31%;float:left;text-align:left;cursor:pointer !important}.oboarding-step .popup-option img{max-width:100%;margin-top:6px;-moz-box-shadow:0 1px 2px rgba(0,0,0,0.15);-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.15);box-shadow:0 1px 2px rgba(0,0,0,0.15);-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px}.oboarding-step .popup-option:hover img{-moz-box-shadow:0 2px 4px rgba(0,0,0,0.25);-webkit-box-shadow:0 2px 4px rgba(0,0,0,0.25);box-shadow:0 2px 4px rgba(0,0,0,0.25)}.oboarding-step .popup-option input{margin-right:8px !important}.oboarding-step .popup-option input:checked ~ img{border:2px solid #2ea2cc}.oboarding-step .popup-option+.popup-option{margin-left:3%}.oboarding-step .popup-options{*zoom:1}.oboarding-step .popup-options:after{content:"";display:table;clear:both}.oboarding-steps-help{margin-top:24px;color:#999}@media (min-width: 1200px){.oboarding-steps-help{width:15.49296%;float:left;margin-right:1.40845%;margin-top:60px}}@media (min-width: 1200px){.leadin-settings__content{width:74.64789%;float:left;margin-right:1.40845%}.leadin-settings__sidebar{width:23.94366%;float:right;margin-right:0}}.li-settings h3{border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-top:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;margin-bottom:0px;background:#fff;padding:8px 12px;font-size:15px}.li-settings .form-table{margin-top:0px;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;background-color:#fff;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.li-settings .form-table th{padding-left:12px}.li-settings .leadin-section{background-color:#fff;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;font-size:14px;padding:15px 12px 5px 12px}.li-settings .leadin-section p{margin:0;padding:0}.li-settings.pre-mp6 h3{font-family:Georgia}.li-settings.pre-mp6 select,.li-settings.pre-mp6 input{font-family:sans-serif;font-size:12px}.li-settings.pre-mp6 .form-table,.li-settings.pre-mp6 .leadin-section,.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important}.li-settings.pre-mp6 .form-table{-moz-border-radius-bottomleft:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-moz-border-radius-bottomright:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important;-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.li-settings.pre-mp6 .leadin-section{font-size:12px;padding-left:6px}.li-settings.pre-mp6 h3{padding-left:6px;font-weight:normal;color:#464646;text-shadow:#fff 0px 1px 0px}.li-settings.pre-mp6 label{font-size:12px}.li-settings.pre-mp6 input[type="checkbox"],.li-settings.pre-mp6 input[type="radio"]{margin-right:2px}#icon-leadin{background:url("../../images/leadin-icon-32x32.png") top center no-repeat}.help-notification{background:#d9edf7;border:1px solid #bce8f1;padding:10px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.toplevel_page_leadin_stats .wp-menu-image img{width:16px;height:16px}.leadin-contact-avatar{margin-right:10px;float:left}.power-up-settings-icon{padding-right:10px;float:left;max-height:20px;margin-top:-1px}.dashicons{margin-right:10px;float:left;margin-top:-1px}tr.synced-list-row td.synced-list-cell{padding:3px 0px 10px 0px}tr.synced-list-row td.synced-list-cell .icon-tag{font-size:12px}tr.synced-list-row span.synced-list-arrow{padding:0px 10px}tr.synced-list-row td.synced-list-edit{padding:3px 0px 10px 20px}.leadin-settings__sidebar .pro-upgrade-cta{max-width:100%}.leadin-contacts .button{transition:background-color 0.2s}@media (min-width: 1200px){.leadin-contacts__nav{width:15.49296%;float:left;margin-right:1.40845%;margin-top:30px}.leadin-contacts__content{width:83.09859%;float:right;margin-right:0;margin-bottom:18px;margin-top:30px}.leadin-contacts__export-form{width:83.09859%;float:left;margin-right:1.40845%;padding-left:16.90141%;margin-bottom:18px}}.leadin-contacts__search{float:right;padding:10px 0;padding-bottom:9px}.leadin-contacts__type-picker{margin:0 0 30px;*zoom:1}.leadin-contacts__type-picker:after{content:"";display:table;clear:both}.leadin-contacts__type-picker li{margin:0;padding:0 1em 0 0;float:left}@media (min-width: 1200px){.leadin-contacts__type-picker li{float:none;padding:0}.leadin-contacts__type-picker li+li{padding:18px 0 0}}.leadin-contacts__type-picker li a{display:block;line-height:24px;font-weight:400;font-size:16px;text-decoration:none}.leadin-contacts__type-picker li a.current{font-weight:bold}.leadin-contacts__type-picker li a.current,.leadin-contacts__type-picker li a:hover,.leadin-contacts__type-picker li a:active{color:#F67D42}.leadin-contacts__type-picker li a .icon-tag,.leadin-contacts__type-picker li a .icon-user{padding-right:1em;font-size:0.85em}.leadin-contacts__tags-header{margin:30px 0 18px;font-size:14px;text-transform:uppercase;letter-spacing:0.1em;color:#999}.leadin-contacts__filter-text{margin:0 0 18px}.leadin-contacts__filter-count{color:#F67D42}#clear-filter{font-size:0.8em;margin-left:10px}.leadin-contacts__table table th#source{width:20%}.leadin-contacts__table table th#visits,.leadin-contacts__table table th#submissions{width:8%}.leadin-contacts__table table th#status,.leadin-contacts__table table th#last_visit,.leadin-contacts__table table th#date,.leadin-contacts__table table th#pageviews{width:10%}.leadin-contacts__table table th,.leadin-contacts__table table td{display:none}.leadin-contacts__table table th:nth-child(-n+3),.leadin-contacts__table table td:nth-child(-n+3){display:table-cell}@media (min-width: 1200px){.leadin-contacts__table table th,.leadin-contacts__table table td{display:table-cell}}.leadin-contacts.pre-mp6 .table_search{float:right;padding:12px 0;padding-bottom:11px}.leadin-contacts.pre-mp6 table{background-color:#fff;border-color:#dedede}.leadin-contacts.pre-mp6 table tr.alternate{background-color:#fff}.leadin-contacts.pre-mp6 table th,.leadin-contacts.pre-mp6 table td{border-top:0;padding:12px 6px 11px}.leadin-contacts.pre-mp6 table th a,.leadin-contacts.pre-mp6 table td a{padding:0}.leadin-contacts.pre-mp6 table th[scope="col"]{background:#eee;font-family:sans-serif;font-size:12px;text-shadow:none}.leadin-contacts.pre-mp6 table td{border-color:#dedede;line-height:18px;font-size:14px}.leadin-contacts.pre-mp6 table td .row-actions{float:left}#leadin .contact-header-wrap{*zoom:1;padding:18px 0 24px}#leadin .contact-header-wrap:after{content:"";display:table;clear:both}#leadin .contact-header-wrap .contact-header-avatar,#leadin .contact-header-wrap .contact-header-info{float:left}#leadin .contact-header-info{padding-left:15px}#leadin .contact-name{line-height:30px;padding:0;margin:0}#leadin .contact-tags{margin-top:15px}#leadin .contact-tag{padding:4px 10px;color:#fff;background-color:#F67D42;text-decoration:none;font-weight:600;text-transform:uppercase;letter-spacing:0.1em;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#leadin .contact-tag:hover{opacity:0.9}#leadin .contact-tag+.contact-tag,#leadin .contact-tag+.contact-edit-tags{margin-left:10px}#leadin .contact-tag .icon-tag{padding-right:10px}#leadin .contact-info h3{margin:0}#leadin .contact-info label{font-weight:bold;line-height:1;cursor:default}#leadin .leadin-meta-section+.leadin-meta-section{margin-top:24px}#leadin .leadin-meta-table{width:100%;text-align:left}#leadin .leadin-meta-table th{color:#666;padding-bottom:6px}#leadin .leain-meta-header,#leadin .contact-history .session-date{margin:0 0 12px;text-transform:uppercase;letter-spacing:0.05em;color:#444}#leadin .leadin-premium-tag:after{content:"Pro";margin-left:10px;font-size:10px;color:#fff;background-color:#93C054;padding:2px 6px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#leadin .contact-history{margin-left:20px}@media (min-width: 1200px){#leadin .contact-history{padding-left:20px;border-left:2px solid #dedede}}#leadin .contact-history .sessions{margin:0}#leadin .contact-history .session+.session{margin-top:30px}#leadin .contact-history .session-date{position:relative}@media (min-width: 1200px){#leadin .contact-history .session-date:before{content:"•";font-size:32px;line-height:0;height:31px;width:31px;position:absolute;left:-27px;top:9px;color:#dedede}}#leadin .contact-history .session-time-range{color:#999;font-weight:400}#leadin .contact-history .events{background-color:#fff;border:1px solid #dedede;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}#leadin .contact-history .event{margin:0;padding:10px 20px;border-bottom:1px solid #dedede;border-left:4px solid;*zoom:1}#leadin .contact-history .event:after{content:"";display:table;clear:both}#leadin .contact-history .event:first-child{border-top:0}#leadin .contact-history .event.pageview{border-left-color:#28c;color:#28c}#leadin .contact-history .event.form-submission{border-left-color:#F67D42;color:#F67D42}#leadin .contact-history .event.source{border-left-color:#99AA1F;color:#99AA1F}#leadin .contact-history .event-title{margin:0;font-size:13px;font-weight:600}#leadin .contact-history .event-time{float:left;font-weight:400;width:75px}#leadin .contact-history .event-content{margin-left:75px}#leadin .contact-history .event-detail{margin-top:20px;color:#444}#leadin .contact-history .event-detail li+li{padding-top:6px;border-top:1px solid #eee}#leadin .contact-history .event-detail.pageview-url{color:#ccc}#leadin .contact-history .visit-source p{margin:0;color:#1F6696}#leadin .contact-history .field-label{text-transform:uppercase;letter-spacing:0.05em;color:#999;margin-bottom:6px;font-size:0.9em}#leadin .contact-history .field-value{margin:0}#leadin.pre-mp6 .events{background-color:#f9f9f9}.powerup-list{margin:0}.powerup-list .powerup{width:20%;min-width:250px;float:left;margin:20px;padding:15px}.powerup-list .powerup h2,.powerup-list .powerup p{margin:0;padding:0;color:#666;margin-bottom:15px}.powerup-list .powerup .img-containter{text-align:center;padding:30px 15px;margin-bottom:15px;background-color:#f1f1f1;color:red}.powerup-list .powerup .img-containter h2{font-size:20px}.powerup-list .powerup.activated h2,.powerup-list .powerup.activated p{color:#1F7D71}.powerup-list .powerup.activated .img-containter{background-color:#D3EEEB}@media (min-width: 1200px){.leadin-stats__top-container,.leadin-stats__chart-container,.leadin-stats__big-numbers-container{width:100%;float:right;margin-right:0}.leadin-stats__postbox_containter{width:49.29577%;float:left;margin-right:1.40845%}.leadin-stats__postbox_containter:nth-child(2n+2){width:49.29577%;float:right;margin-right:0}}h2.leadin-stats__header{margin-bottom:12px}.leadin-stats__postbox_containter .leadin-postbox,.leadin-stats__postbox_containter .powerup-list .powerup,.powerup-list .leadin-stats__postbox_containter .powerup{margin-bottom:12px}.leadin-stats__big-number{text-align:center;width:42%;float:left;padding:4%}@media (min-width: 1200px){.leadin-stats__big-number{width:25%;padding:10px}}.big-number--average .leadin-stats__big-number-top-label,.big-number--average .leadin-stats__big-number-content,.big-number--average .leadin-stats__big-number-bottom-label{color:#4CA6CF}.leadin-stats__top-container,.leadin-stats__big-number-top-label,.leadin-stats__big-number-content,.leadin-stats__big-number-bottom-label{color:#666;margin-bottom:12px}.leadin-stats__big-number-top-label{text-transform:uppercase;letter-spacing:0.05em}
1
+ #leadin label{cursor:default}#leadin .col-wrap{padding:0}#leadin .col-left .col-wrap{padding-right:10px}#leadin .metabox-holder{*zoom:1}#leadin .metabox-holder:after{content:"";display:table;clear:both}#wp-admin-bar-leadin-admin-menu img{height:16px;width:16px;opacity:0.6}@media (min-width: 1200px){#leadin{*zoom:1;max-width:1420px;max-width:88.75rem;padding-left:20px;padding-left:1.25rem;padding-right:20px;padding-right:1.25rem;margin-left:auto;margin-right:auto;margin:10px 20px 0 0;padding:0}#leadin:after{content:"";display:table;clear:both}#leadin *{box-sizing:border-box}}#li_analytics-meta .li-analytics-link{float:left}#li_analytics-meta .li-analytics-link .li-analytics__face{height:35px;width:35px;margin-right:5px;margin-bottom:5px}#li_analytics-meta .hidden_face{display:none}#li_analytics-meta .show-all-faces-container{clear:both}.leadin-postbox,.powerup-list .powerup{background-color:#fff;border:1px solid #e5e5e5;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.leadin-postbox__header{margin:0;padding:8px 12px;font-size:14px;border-bottom:1px solid #eee}.leadin-postbox__content{margin:11px 0;padding:0 12px;*zoom:1}.leadin-postbox__content:after{content:"";display:table;clear:both}.leadin-postbox__table{margin:0;width:100%}.leadin-postbox__table th{padding:6px 0;text-align:left;text-transform:uppercase;letter-spacing:0.05em}.leadin-postbox__table td{padding:6px 0}.leadin-postbox__table tr,.leadin-postbox__table td,.leadin-postbox__table th{vertical-align:middle !important}.leadin-dynamic-avatar_0{background-color:#F88E4B}.leadin-dynamic-avatar_1{background-color:#64AADA}.leadin-dynamic-avatar_2{background-color:#64C2B6}.leadin-dynamic-avatar_3{background-color:#CF7BAA}.leadin-dynamic-avatar_4{background-color:#E7C24B}.leadin-dynamic-avatar_5{background-color:#9387DA}.leadin-dynamic-avatar_6{background-color:#D6DD99}.leadin-dynamic-avatar_7{background-color:#FF4C4C}.leadin-dynamic-avatar_8{background-color:#99583D}.leadin-dynamic-avatar_9{background-color:#54CC14}@font-face{font-family:"icomoon";src:url("../../fonts/icomoon.eot?-lejfm6");src:url("../../fonts/icomoon.eot?#iefix-lejfm6") format("embedded-opentype"),url("../../fonts/icomoon.woff?-lejfm6") format("woff"),url("../../fonts/icomoon.ttf?-lejfm6") format("truetype"),url("../../fonts/icomoon.svg?-lejfm6#icomoon") format("svg");font-weight:normal;font-style:normal}.icon,.icon-profile,.icon-tag,.icon-tags,.icon-envelope,.icon-user,.icon-cog,.icon-bars,.icon-lab,.icon-bulb,.icon-mover{font-family:"icomoon";speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-profile:before{content:""}.icon-tag:before{content:""}.icon-tags:before{content:""}.icon-envelope:before{content:""}.icon-user:before{content:""}.icon-cog:before{content:""}.icon-bars:before{content:""}.icon-lab:before{content:""}.icon-bulb:before{content:""}.icon-mover:before{content:""}#leadin-footer{*zoom:1;clear:both;margin-top:48px;color:#999;border-top:1px solid #dedede}#leadin-footer:after{content:"";display:table;clear:both}#leadin-footer .support .sharing{height:18px;text-align:left}@media screen and (min-width: 500px){#leadin-footer .support,#leadin-footer .version,#leadin-footer .sharing{width:50%;float:left}#leadin-footer .sharing{text-align:right}}.button-big{padding:6px 36px !important;font-size:14px !important;height:auto !important}.oboarding-steps-names{*zoom:1;margin:0}.oboarding-steps-names:after{content:"";display:table;clear:both}.oboarding-step-name{float:left;margin:0;padding-bottom:24px;list-style:decimal inside none;font-size:18px;color:#bbb}.oboarding-step-name.active{color:#1F7D71;background-image:url(../../../images/triangle.png);background-position:bottom center;background-repeat:no-repeat}.oboarding-step-name.completed{list-style-image:url(../../../images/checkmark.png)}.oboarding-step-name+.oboarding-step-name{margin-left:72px}.oboarding-steps{margin:18px 0}@media (min-width: 1200px){.oboarding-steps{width:66.19718%;float:left;margin-right:1.40845%}}.oboarding-step-content{margin:0 auto;max-width:500px}.oboarding-step-content .description{margin:12px 0;display:block;display:none}.oboarding-step{text-align:center;display:block;padding:36px;background-color:#D3EEEB;border:2px solid #2a9;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px;color:#1F7D71}.oboarding-step .form-table th{display:none}.oboarding-step .form-table td{width:auto;display:block}.oboarding-step .form-table input{width:100%;font-size:16px;line-height:1.5;padding:7px 10px;display:block}.oboarding-step .oboarding-step-title,.oboarding-step .oboarding-step-description{color:#1F7D71;padding:0;margin-bottom:36px}.oboarding-step .button-primary{margin-top:36px}.oboarding-step .oboarding-step-description{font-size:16px;text-align:left}.oboarding-step .popup-option{width:31%;float:left;text-align:left;cursor:pointer !important}.oboarding-step .popup-option img{max-width:100%;margin-top:6px;-moz-box-shadow:0 1px 2px rgba(0,0,0,0.15);-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.15);box-shadow:0 1px 2px rgba(0,0,0,0.15);-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px}.oboarding-step .popup-option:hover img{-moz-box-shadow:0 2px 4px rgba(0,0,0,0.25);-webkit-box-shadow:0 2px 4px rgba(0,0,0,0.25);box-shadow:0 2px 4px rgba(0,0,0,0.25)}.oboarding-step .popup-option input{margin-right:8px !important}.oboarding-step .popup-option input:checked ~ img{border:2px solid #2ea2cc}.oboarding-step .popup-option+.popup-option{margin-left:3%}.oboarding-step .popup-options{*zoom:1}.oboarding-step .popup-options:after{content:"";display:table;clear:both}.oboarding-steps-help{margin-top:24px;color:#999}@media (min-width: 1200px){.oboarding-steps-help{width:15.49296%;float:left;margin-right:1.40845%;margin-top:60px}}@media (min-width: 1200px){.leadin-settings__content{width:74.64789%;float:left;margin-right:1.40845%}.leadin-settings__sidebar{width:23.94366%;float:right;margin-right:0}}.li-settings h3{border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-top:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;margin-bottom:0px;background:#fff;padding:8px 12px;font-size:15px}.li-settings .form-table{margin-top:0px;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;background-color:#fff;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.li-settings .form-table th{padding-left:12px}.li-settings .leadin-section{background-color:#fff;border-left:1px solid #e5e5e5;border-right:1px solid #e5e5e5;font-size:14px;padding:15px 12px 5px 12px}.li-settings .leadin-section p{margin:0;padding:0}.li-settings.pre-mp6 h3{font-family:Georgia}.li-settings.pre-mp6 select,.li-settings.pre-mp6 input{font-family:sans-serif;font-size:12px}.li-settings.pre-mp6 .form-table,.li-settings.pre-mp6 .leadin-section,.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important}.li-settings.pre-mp6 .form-table{-moz-border-radius-bottomleft:3px;-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-moz-border-radius-bottomright:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px}.li-settings.pre-mp6 h3{background-color:#f9f9f9 !important;-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.li-settings.pre-mp6 .leadin-section{font-size:12px;padding-left:6px}.li-settings.pre-mp6 h3{padding-left:6px;font-weight:normal;color:#464646;text-shadow:#fff 0px 1px 0px}.li-settings.pre-mp6 label{font-size:12px}.li-settings.pre-mp6 input[type="checkbox"],.li-settings.pre-mp6 input[type="radio"]{margin-right:2px}#icon-leadin{background:url("../../images/leadin-icon-32x32.png") top center no-repeat}.help-notification{background:#d9edf7;border:1px solid #bce8f1;padding:10px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.toplevel_page_leadin_stats .wp-menu-image img{width:16px;height:16px}.leadin-contact-avatar{margin-right:10px;float:left}.power-up-settings-icon{padding-right:10px;float:left;max-height:20px;margin-top:-1px}.dashicons{margin-right:10px;float:left;margin-top:-1px}tr.synced-list-row td.synced-list-cell{padding:3px 0px 10px 0px}tr.synced-list-row td.synced-list-cell .icon-tag{font-size:12px}tr.synced-list-row span.synced-list-arrow{padding:0px 10px}tr.synced-list-row td.synced-list-edit{padding:3px 0px 10px 20px}.leadin-settings__sidebar .pro-upgrade-cta{max-width:100%}.leadin-contacts .button{transition:background-color 0.2s}@media (min-width: 1200px){.leadin-contacts__nav{width:15.49296%;float:left;margin-right:1.40845%;margin-top:30px}.leadin-contacts__content{width:83.09859%;float:right;margin-right:0;margin-bottom:18px;margin-top:30px}.leadin-contacts__export-form{width:83.09859%;float:left;margin-right:1.40845%;padding-left:16.90141%;margin-bottom:18px}}.leadin-contacts__search{float:right;padding:10px 0;padding-bottom:9px}.leadin-contacts__type-picker{margin:0 0 30px;*zoom:1}.leadin-contacts__type-picker:after{content:"";display:table;clear:both}.leadin-contacts__type-picker li{margin:0;padding:0 1em 0 0;float:left}@media (min-width: 1200px){.leadin-contacts__type-picker li{float:none;padding:0}.leadin-contacts__type-picker li+li{padding:18px 0 0}}.leadin-contacts__type-picker li a{display:block;line-height:24px;font-weight:400;font-size:16px;text-decoration:none}.leadin-contacts__type-picker li a.current{font-weight:bold}.leadin-contacts__type-picker li a.current,.leadin-contacts__type-picker li a:hover,.leadin-contacts__type-picker li a:active{color:#F67D42}.leadin-contacts__type-picker li a .icon-tag,.leadin-contacts__type-picker li a .icon-user{padding-right:1em;font-size:0.85em}.leadin-contacts__tags-header{margin:30px 0 18px;font-size:14px;text-transform:uppercase;letter-spacing:0.1em;color:#999}.leadin-contacts__filter-text{margin:0 0 18px}.leadin-contacts__filter-count{color:#F67D42}#clear-filter{font-size:0.8em;margin-left:10px}.leadin-contacts__table table th#source{width:20%}.leadin-contacts__table table th#visits,.leadin-contacts__table table th#submissions{width:8%}.leadin-contacts__table table th#status,.leadin-contacts__table table th#last_visit,.leadin-contacts__table table th#date,.leadin-contacts__table table th#pageviews{width:10%}.leadin-contacts__table table th,.leadin-contacts__table table td{display:none}.leadin-contacts__table table th:nth-child(-n+3),.leadin-contacts__table table td:nth-child(-n+3){display:table-cell}@media (min-width: 1200px){.leadin-contacts__table table th,.leadin-contacts__table table td{display:table-cell}}.leadin-contacts.pre-mp6 .table_search{float:right;padding:12px 0;padding-bottom:11px}.leadin-contacts.pre-mp6 table{background-color:#fff;border-color:#dedede}.leadin-contacts.pre-mp6 table tr.alternate{background-color:#fff}.leadin-contacts.pre-mp6 table th,.leadin-contacts.pre-mp6 table td{border-top:0;padding:12px 6px 11px}.leadin-contacts.pre-mp6 table th a,.leadin-contacts.pre-mp6 table td a{padding:0}.leadin-contacts.pre-mp6 table th[scope="col"]{background:#eee;font-family:sans-serif;font-size:12px;text-shadow:none}.leadin-contacts.pre-mp6 table td{border-color:#dedede;line-height:18px;font-size:14px}.leadin-contacts.pre-mp6 table td .row-actions{float:left}#leadin .contact-header-wrap{*zoom:1;padding:18px 0 24px}#leadin .contact-header-wrap:after{content:"";display:table;clear:both}#leadin .contact-header-wrap .contact-header-avatar,#leadin .contact-header-wrap .contact-header-info{float:left}#leadin .contact-header-info{padding-left:15px}#leadin .contact-name{line-height:30px;padding:0;margin:0}#leadin .contact-tags{margin-top:15px}#leadin .contact-tag{padding:4px 10px;color:#fff;background-color:#F67D42;text-decoration:none;font-weight:600;text-transform:uppercase;letter-spacing:0.1em;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#leadin .contact-tag:hover{opacity:0.9}#leadin .contact-tag+.contact-tag,#leadin .contact-tag+.contact-edit-tags{margin-left:10px}#leadin .contact-tag .icon-tag{padding-right:10px}#leadin .contact-info h3{margin:0}#leadin .contact-info label{font-weight:bold;line-height:1;cursor:default}#leadin .leadin-meta-section+.leadin-meta-section{margin-top:24px}#leadin .leadin-meta-table{width:100%;text-align:left}#leadin .leadin-meta-table th{color:#666;padding-bottom:6px}#leadin .leain-meta-header,#leadin .contact-history .session-date{margin:0 0 12px;text-transform:uppercase;letter-spacing:0.05em;color:#444}#leadin .leadin-premium-tag:after{content:"Pro";margin-left:10px;font-size:10px;color:#fff;background-color:#93C054;padding:2px 6px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px}#leadin .contact-history{margin-left:20px}@media (min-width: 1200px){#leadin .contact-history{padding-left:20px;border-left:2px solid #dedede}}#leadin .contact-history .sessions{margin:0}#leadin .contact-history .session+.session{margin-top:30px}#leadin .contact-history .session-date{position:relative}@media (min-width: 1200px){#leadin .contact-history .session-date:before{content:"•";font-size:32px;line-height:0;height:31px;width:31px;position:absolute;left:-27px;top:9px;color:#dedede}}#leadin .contact-history .session-time-range{color:#999;font-weight:400}#leadin .contact-history .events{background-color:#fff;border:1px solid #dedede;-moz-box-shadow:0 1px 1px rgba(0,0,0,0.04);-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}#leadin .contact-history .event{margin:0;padding:10px 20px;border-bottom:1px solid #dedede;border-left:4px solid;*zoom:1}#leadin .contact-history .event:after{content:"";display:table;clear:both}#leadin .contact-history .event:first-child{border-top:0}#leadin .contact-history .event.pageview{border-left-color:#28c;color:#28c}#leadin .contact-history .event.form-submission{border-left-color:#F67D42;color:#F67D42}#leadin .contact-history .event.source{border-left-color:#99AA1F;color:#99AA1F}#leadin .contact-history .event-title{margin:0;font-size:13px;font-weight:600}#leadin .contact-history .event-time{float:left;font-weight:400;width:75px}#leadin .contact-history .event-content{margin-left:75px}#leadin .contact-history .event-detail{margin-top:20px;color:#444}#leadin .contact-history .event-detail li+li{padding-top:6px;border-top:1px solid #eee}#leadin .contact-history .event-detail.pageview-url{color:#ccc}#leadin .contact-history .visit-source p{margin:0;color:#1F6696}#leadin .contact-history .field-label{text-transform:uppercase;letter-spacing:0.05em;color:#999;margin-bottom:6px;font-size:0.9em}#leadin .contact-history .field-value{margin:0}#leadin.pre-mp6 .events{background-color:#f9f9f9}.powerup-list{margin:0}.powerup-list .powerup{width:20%;min-width:250px;float:left;margin:20px;padding:15px}.powerup-list .powerup h2,.powerup-list .powerup p{margin:0;padding:0;color:#666;margin-bottom:15px}.powerup-list .powerup .img-containter{text-align:center;padding:30px 15px;margin-bottom:15px;background-color:#f1f1f1;color:red}.powerup-list .powerup .img-containter h2{font-size:20px}.powerup-list .powerup.activated h2,.powerup-list .powerup.activated p{color:#1F7D71}.powerup-list .powerup.activated .img-containter{background-color:#D3EEEB}@media (min-width: 1200px){.leadin-stats__top-container,.leadin-stats__chart-container,.leadin-stats__big-numbers-container{width:100%;float:right;margin-right:0}.leadin-stats__postbox_containter{width:49.29577%;float:left;margin-right:1.40845%}.leadin-stats__postbox_containter:nth-child(2n+2){width:49.29577%;float:right;margin-right:0}}h2.leadin-stats__header{margin-bottom:12px}.leadin-stats__postbox_containter .leadin-postbox,.leadin-stats__postbox_containter .powerup-list .powerup,.powerup-list .leadin-stats__postbox_containter .powerup{margin-bottom:12px}.leadin-stats__big-number{text-align:center;width:42%;float:left;padding:4%}@media (min-width: 1200px){.leadin-stats__big-number{width:25%;padding:10px}}.big-number--average .leadin-stats__big-number-top-label,.big-number--average .leadin-stats__big-number-content,.big-number--average .leadin-stats__big-number-bottom-label{color:#4CA6CF}.leadin-stats__top-container,.leadin-stats__big-number-top-label,.leadin-stats__big-number-content,.leadin-stats__big-number-bottom-label{color:#666;margin-bottom:12px}.leadin-stats__big-number-top-label{text-transform:uppercase;letter-spacing:0.05em}.big-button,.big-button--orange,.big-button--share{display:block;text-align:center;color:#fff;text-decoration:none;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;padding:10px;font-size:16px;margin-top:15px}.big-button:hover,.big-button--orange:hover,.big-button--share:hover,.big-button:active,.big-button--orange:active,.big-button--share:active,.big-button:focus,.big-button--orange:focus,.big-button--share:focus,.big-button:visited,.big-button--orange:visited,.big-button--share:visited{color:#fff}.big-button--orange{background-color:#F67D42;border:1px solid #E75913;-webkit-box-shadow:inset 0 1px 0 rgba(255,195,166,0.5),0 1px 0 rgba(0,0,0,0.08);box-shadow:inset 0 1px 0 rgba(255,195,166,0.5),0 1px 0 rgba(0,0,0,0.08)}.big-button--orange:hover{color:#fff;background-color:#f56c2a}.big-button--orange:active{color:#f1f1f1;background-color:#f45c11;-moz-box-shadow:none;-webkit-box-shadow:none;box-shadow:none}.btn-submitting{background-color:#979797;cursor:not-allowed;border-color:grey;box-shadow:none}.btn-submitting:hover,.btn-submitting:active,.btn-submitting:focus,.btn-submitting:visited{background-color:#979797;color:#fff;box-shadow:none}.compare{width:100%;float:left;margin-right:1.40845%;display:inline;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#fff;position:relative;margin-bottom:20px}.compare:first-of-type{margin-bottom:60px}.compare:first-of-type:after{width:100%;float:left;margin-right:1.40845%;display:inline;content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 48px/1 "dashicons";position:absolute;bottom:-55px;text-align:center}@media (min-width: 1200px){.compare:first-of-type:after{width:7.04225%;float:left;margin-right:1.40845%;content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 48px/1 "dashicons";position:absolute;right:-40px;top:4em}}@media (min-width: 1200px){.compare{width:32.39437%;float:left;margin-right:1.40845%;margin-right:60px}}.compare .title{width:100%;height:72px;background-color:#979797;position:absolute;text-align:center;padding-top:15px;-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-topright:3px;-webkit-border-top-right-radius:3px;border-top-right-radius:3px}.compare .title h2{color:#fff;font-size:20px}.compare .title.teal{background-color:#6EC8C7}.compare .content{margin-top:50px;padding:30px}.compare .features{text-transform:uppercase;font-weight:bold;font-size:18px;padding-left:15px}.compare .features li{list-style-position:outside;text-indent:-10px}.compare .features li:before{content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 20px/1 "dashicons";vertical-align:top}.compare .features.plus li:before{content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 20px/1.1 "dashicons";vertical-align:top}.compare .features p{margin-left:2px;margin-top:-5px}.compare p{text-transform:none;font-weight:normal;line-height:27px}*{box-sizing:border-box}.big-button--share{display:inline-block;margin-right:2px;width:82px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.5),0 1px 0 rgba(0,0,0,0.08);box-shadow:inset 0 1px 0 rgba(255,255,255,0.5),0 1px 0 rgba(0,0,0,0.08)}@media (min-width: 1200px){.big-button--share{margin-right:7px;width:200px}}.big-button--share.fb{background-color:#3B579D;border:1px solid #344d8a}.big-button--share.fb:after{content:""}@media (min-width: 1200px){.big-button--share.fb:after{content:"Share on Facebook"}}.big-button--share.fb:hover{background-color:#4261b0}.big-button--share.fb:before{content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 20px/1.4 "dashicons";vertical-align:top;margin-right:5px}.big-button--share.tw{background-color:#1DB1EB;border:1px solid #13a3db}.big-button--share.tw:after{content:""}@media (min-width: 1200px){.big-button--share.tw:after{content:"Share on Twitter"}}.big-button--share.tw:hover{background-color:#34b9ed}.big-button--share.tw:before{content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 20px/1.4 "dashicons";vertical-align:top;margin-right:5px}.big-button--share.wp{background-color:#1585B6;border:1px solid #12749f}.big-button--share.wp:after{content:""}@media (min-width: 1200px){.big-button--share.wp:after{content:"Write a Review"}}.big-button--share.wp:hover{background-color:#1896cd}.big-button--share.wp:before{content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 20px/1.4 "dashicons";vertical-align:top;margin-right:5px}.dialog-bottom-right{line-height:28px;background-color:#6EC8C7;color:#fff;position:fixed;z-index:1111;right:0;bottom:-400px;-moz-border-radius-topleft:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;width:300px;padding:20px;-moz-box-shadow:grey -1px 0 7px;-webkit-box-shadow:grey -1px 0 7px;box-shadow:grey -1px 0 7px}@media (min-width: 1200px){.dialog-bottom-right{width:668px}}.dialog-bottom-right h1{color:#1B6F6C;font-size:20px;font-weight:600;margin:0px}.dialog-bottom-right p{color:#fff;font-size:14px}.close:before{content:"";display:inline-block;-webkit-font-smoothing:antialiased;font:normal 24px/1.4 "dashicons";vertical-align:top;float:right;margin-top:-30px;color:grey}
assets/css/build/leadin-lead-notifcation.css CHANGED
@@ -1 +1 @@
1
- body,.body{background-color:#f1f1f1}h1{font-size:26px;line-height:60px}h2{font-size:23px}h3{font-size:18px}h4{font-size:14px;font-weight:bold}.submission-detail h3{color:#666}.lead-timeline__pageview-url a{color:#999}.lead-timeline__submission-label{text-transform:uppercase;font-size:12px;color:#999;letter-spacing:0.05em}.lead-timeline__previous-activity h2{margin-top:15px}.lead-timeline__event{background-color:#fff;border-top:1px solid #dedede;border-right:1px solid #dedede}.lead-timeline__event.pageview{border-left:4px solid #28c}.lead-timeline__event.pageview .lead-timeline__event-title,.lead-timeline__event.pageview .lead-timeline__event-time{color:#1f6696}.lead-timeline__event.submission{border-left:4px solid #f6601d}.lead-timeline__event.submission .lead-timeline__event-title,.lead-timeline__event.submission .lead-timeline__event-time{color:#b34a12}.lead-timeline__event.traffic-source{border-left:4px solid #99aa1f;border-bottom:1px solid #dedede;margin-bottom:20px}.lead-timeline__event.traffic-source .lead-timeline__event-title,.lead-timeline__event.traffic-source .lead-timeline__event-time{color:#727e14}.footer{margin-bottom:20px}
1
+ body,.body{background-color:#f1f1f1}h1{font-size:26px;line-height:60px}h2{font-size:23px}h3{font-size:18px}h4{font-size:14px;font-weight:bold}.submission-detail h3{color:#666}.lead-timeline__pageview-url a{color:#999}.lead-timeline__submission-label{text-transform:uppercase;font-size:12px;color:#999;letter-spacing:0.05em}.lead-timeline__previous-activity h2{margin-top:15px}.lead-timeline__event{background-color:#fff;border-top:1px solid #dedede;border-right:1px solid #dedede}.lead-timeline__event.pageview{border-left:4px solid #28c}.lead-timeline__event.pageview .lead-timeline__event-title,.lead-timeline__event.pageview .lead-timeline__event-time{color:#1f6696}.lead-timeline__event.submission{border-left:4px solid #f6601d}.lead-timeline__event.submission .lead-timeline__event-title,.lead-timeline__event.submission .lead-timeline__event-time{color:#b34a12}.lead-timeline__event.traffic-source{border-left:4px solid #99aa1f;border-bottom:1px solid #dedede;margin-bottom:20px}.lead-timeline__event.traffic-source .lead-timeline__event-title,.lead-timeline__event.traffic-source .lead-timeline__event-time{color:#727e14}.data-lookup-header{font-size:20px;margin-bottom:15px}.data-lookup-limit .green,.data-lookup-limit .yellow,.data-lookup-limit .red{font-weight:bold}.data-lookup-limit .green{color:green}.data-lookup-limit .yellow{color:#ff0}.data-lookup-limit .red{color:red}.contact-name,.company-name{font-size:14px;font-weight:bold;color:#444}.contact-name-subhead,.company-name-subhead{font-size:14px;font-weight:400;margin-bottom:15px;color:#444}.contact-description,.company-description{color:#666}.footer{margin-bottom:20px}
assets/css/build/leadin-subscribe-premium.css DELETED
@@ -1,3 +0,0 @@
1
- #powered-by-leadin-thank-you, #leadin-subscribe-powered-by {
2
- display: none;
3
- }
 
 
 
assets/js/build/leadin-admin.js CHANGED
@@ -1,3 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /*
2
  Highcharts JS v4.0.1 (2014-04-24)
3
 
@@ -310,6 +423,17 @@ hasBidiBug:Nb,isTouchDevice:Jb,numberFormat:Ga,seriesTypes:F,setOptions:function
310
  }
311
  jQuery(document).ready( function ( $ ) {
312
 
 
 
 
 
 
 
 
 
 
 
 
313
  $("#filter_action").select2(
314
 
315
  );
@@ -434,7 +558,50 @@ jQuery(document).ready( function ( $ ) {
434
 
435
  $('#preview-popup-link').attr('href', preview_link);
436
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
437
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  jQuery(document).ready( function ( $ ) {
439
 
440
  var $bulk_opt_selected = $('.bulkactions select option[value="add_tag_to_selected"], .bulkactions select option[value="remove_tag_from_selected"], .bulkactions select option[value="delete_selected"]');
@@ -549,6 +716,16 @@ jQuery(document).ready( function ( $ ) {
549
  $('.bulkactions select').val('-1');
550
  }
551
  });
 
 
 
 
 
 
 
 
 
 
552
  });
553
  /*
554
  Copyright 2012 Igor Vaynberg
1
+ /*!
2
+ * jQuery Cookie Plugin v1.4.0
3
+ * https://github.com/carhartl/jquery-cookie
4
+ *
5
+ * Copyright 2013 Klaus Hartl
6
+ * Released under the MIT license
7
+ */
8
+ (function (factory) {
9
+ if (typeof define === 'function' && define.amd) {
10
+ // AMD. Register as anonymous module.
11
+ define(['jquery'], factory);
12
+ } else {
13
+ // Browser globals.
14
+ factory(jQuery);
15
+ }
16
+ }(function ($) {
17
+
18
+ var pluses = /\+/g;
19
+
20
+ function encode(s) {
21
+ return config.raw ? s : encodeURIComponent(s);
22
+ }
23
+
24
+ function decode(s) {
25
+ return config.raw ? s : decodeURIComponent(s);
26
+ }
27
+
28
+ function stringifyCookieValue(value) {
29
+ return encode(config.json ? JSON.stringify(value) : String(value));
30
+ }
31
+
32
+ function parseCookieValue(s) {
33
+ if (s.indexOf('"') === 0) {
34
+ // This is a quoted cookie as according to RFC2068, unescape...
35
+ s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
36
+ }
37
+
38
+ try {
39
+ // Replace server-side written pluses with spaces.
40
+ // If we can't decode the cookie, ignore it, it's unusable.
41
+ // If we can't parse the cookie, ignore it, it's unusable.
42
+ s = decodeURIComponent(s.replace(pluses, ' '));
43
+ return config.json ? JSON.parse(s) : s;
44
+ } catch(e) {}
45
+ }
46
+
47
+ function read(s, converter) {
48
+ var value = config.raw ? s : parseCookieValue(s);
49
+ return $.isFunction(converter) ? converter(value) : value;
50
+ }
51
+
52
+ var config = $.cookie = function (key, value, options) {
53
+
54
+ // Write
55
+ if (value !== undefined && !$.isFunction(value)) {
56
+ options = $.extend({}, config.defaults, options);
57
+
58
+ if (typeof options.expires === 'number') {
59
+ var days = options.expires, t = options.expires = new Date();
60
+ t.setDate(t.getDate() + days);
61
+ }
62
+
63
+ return (document.cookie = [
64
+ encode(key), '=', stringifyCookieValue(value),
65
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
66
+ options.path ? '; path=' + options.path : '',
67
+ options.domain ? '; domain=' + options.domain : '',
68
+ options.secure ? '; secure' : ''
69
+ ].join(''));
70
+ }
71
+
72
+ // Read
73
+
74
+ var result = key ? undefined : {};
75
+
76
+ // To prevent the for loop in the first place assign an empty array
77
+ // in case there are no cookies at all. Also prevents odd result when
78
+ // calling $.cookie().
79
+ var cookies = document.cookie ? document.cookie.split('; ') : [];
80
+
81
+ for (var i = 0, l = cookies.length; i < l; i++) {
82
+ var parts = cookies[i].split('=');
83
+ var name = decode(parts.shift());
84
+ var cookie = parts.join('=');
85
+
86
+ if (key && key === name) {
87
+ // If second argument (value) is a function it's a converter...
88
+ result = read(cookie, value);
89
+ break;
90
+ }
91
+
92
+ // Prevent storing a cookie that we couldn't decode.
93
+ if (!key && (cookie = read(cookie)) !== undefined) {
94
+ result[name] = cookie;
95
+ }
96
+ }
97
+
98
+ return result;
99
+ };
100
+
101
+ config.defaults = {};
102
+
103
+ $.removeCookie = function (key, options) {
104
+ if ($.cookie(key) === undefined) {
105
+ return false;
106
+ }
107
+
108
+ // Must not alter options, thus extending a fresh object...
109
+ $.cookie(key, '', $.extend({}, options, { expires: -1 }));
110
+ return !$.cookie(key);
111
+ };
112
+
113
+ }));
114
  /*
115
  Highcharts JS v4.0.1 (2014-04-24)
116
 
423
  }
424
  jQuery(document).ready( function ( $ ) {
425
 
426
+ $('#close-share').click( function( e ) {
427
+ $.cookie('ignore_social_share', 1, { expires: 30 });
428
+ });
429
+
430
+ $('.big-button--share').click( function( e ) {
431
+ $.cookie('ignore_social_share', 1);
432
+ });
433
+
434
+ if ( ! $.cookie('ignore_social_share') )
435
+ leadin_check_social_share_popup();
436
+
437
  $("#filter_action").select2(
438
 
439
  );
558
 
559
  $('#preview-popup-link').attr('href', preview_link);
560
  });
561
+
562
+ $('#pro-upgrade-button').click( function ( e ) {
563
+ e.preventDefault();
564
+
565
+ if ( ! $('#agree-pp').is(":checked") )
566
+ {
567
+ $('#agree-pp-error').show();
568
+ return false;
569
+ }
570
+ else
571
+ {
572
+ $('#agree-pp-error').hide();
573
+ $(this).addClass('btn-submitting').text('Upgrading...');
574
+ }
575
+
576
+ $.ajax({
577
+ type: 'POST',
578
+ url: li_admin_ajax.ajax_url,
579
+ data: {
580
+ "action": "leadin_upgrade_to_pro"
581
+ },
582
+ success: function( redirect_to ) {
583
+
584
+ if ( redirect_to )
585
+ window.location.href = redirect_to + "&pro_upgrade=1";
586
+ }
587
+ });
588
+ });
589
  });
590
+
591
+ function leadin_check_social_share_popup ()
592
+ {
593
+ jQuery.ajax({
594
+ type: 'POST',
595
+ url: li_admin_ajax.ajax_url,
596
+ data: {
597
+ "action": "leadin_check_installation_date"
598
+ },
599
+ success: function( data ) {
600
+ if ( ! data )
601
+ $.cookie('ignore_social_share', 1);
602
+ }
603
+ });
604
+ }
605
  jQuery(document).ready( function ( $ ) {
606
 
607
  var $bulk_opt_selected = $('.bulkactions select option[value="add_tag_to_selected"], .bulkactions select option[value="remove_tag_from_selected"], .bulkactions select option[value="delete_selected"]');
716
  $('.bulkactions select').val('-1');
717
  }
718
  });
719
+
720
+ $('#contact-detail-read-more').click( function ( e ) {
721
+ $('#company-detail-overview-short').hide();
722
+ $('#company-detail-overview-full').show();
723
+ });
724
+
725
+ $('#contact-detail-read-less').click( function ( e ) {
726
+ $('#company-detail-overview-full').hide();
727
+ $('#company-detail-overview-short').show();
728
+ });
729
  });
730
  /*
731
  Copyright 2012 Igor Vaynberg
assets/js/build/leadin-admin.min.js CHANGED
@@ -1,8 +1,8 @@
1
- window.Highcharts||!function(){function q(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function w(){var a,c,b=arguments,d={},e=function(a,b){var c,d;"object"!=typeof a&&(a={});for(d in b)b.hasOwnProperty(d)&&(c=b[d],a[d]=c&&"object"==typeof c&&"[object Array]"!==Object.prototype.toString.call(c)&&"renderTo"!==d&&"number"!=typeof c.nodeType?e(a[d]||{},c):b[d]);return a};for(b[0]===!0&&(d=b[1],b=Array.prototype.slice.call(b,2)),c=b.length,a=0;c>a;a++)d=e(d,b[a]);return d}function z(a,b){return parseInt(a,b||10)}function Fa(a){return"string"==typeof a}function ca(a){return"object"==typeof a}function La(a){return"[object Array]"===Object.prototype.toString.call(a)}function ha(a){return"number"==typeof a}function za(a){return U.log(a)/U.LN10}function ia(a){return U.pow(10,a)}function ja(a,b){for(var c=a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function r(a){return a!==t&&null!==a}function H(a,b,c){var d,e;if(Fa(b))r(c)?a.setAttribute(b,c):a&&a.getAttribute&&(e=a.getAttribute(b));else if(r(b)&&ca(b))for(d in b)a.setAttribute(d,b[d]);return e}function qa(a){return La(a)?a:[a]}function m(){var b,c,a=arguments,d=a.length;for(b=0;d>b;b++)if(c=a[b],"undefined"!=typeof c&&null!==c)return c}function G(a,b){Aa&&!aa&&b&&b.opacity!==t&&(b.filter="alpha(opacity="+100*b.opacity+")"),q(a.style,b)}function Y(a,b,c,d,e){return a=y.createElement(a),b&&q(a,b),e&&G(a,{padding:0,border:Q,margin:0}),c&&G(a,c),d&&d.appendChild(a),a}function ka(a,b){var c=function(){};return c.prototype=new a,q(c.prototype,b),c}function Ga(a,b,c,d){var e=E.lang,a=+a||0,f=-1===b?(a.toString().split(".")[1]||"").length:isNaN(b=M(b))?2:b,b=void 0===c?e.decimalPoint:c,d=void 0===d?e.thousandsSep:d,e=0>a?"-":"",c=String(z(a=M(a).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+M(a-c).toFixed(f).slice(2):"")}function Ha(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function Ma(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);return a.unshift(d),c.apply(this,a)}}function Ia(a,b){for(var e,f,g,h,i,c="{",d=!1,j=[];-1!==(c=a.indexOf(c));){if(e=a.slice(0,c),d){for(f=e.split(":"),g=f.shift().split("."),i=g.length,e=b,h=0;i>h;h++)e=e[g[h]];f.length&&(f=f.join(":"),g=/\.([0-9])/,h=E.lang,i=void 0,/f$/.test(f)?(i=(i=f.match(g))?i[1]:-1,null!==e&&(e=Ga(e,i,h.decimalPoint,f.indexOf(",")>-1?h.thousandsSep:""))):e=cb(f,e))}j.push(e),a=a.slice(c+1),c=(d=!d)?"}":"{"}return j.push(a),j.join("")}function mb(a){return U.pow(10,T(U.log(a)/U.LN10))}function nb(a,b,c,d){var e,c=m(c,1);for(e=a/c,b||(b=[1,2,2.5,5,10],d&&d.allowDecimals===!1&&(1===c?b=[1,2,5,10]:.1>=c&&(b=[1/c]))),d=0;d<b.length&&(a=b[d],!(e<=(b[d]+(b[d+1]||b[d]))/2));d++);return a*=c}function Bb(){this.symbol=this.color=0}function ob(a,b){var d,e,c=a.length;for(e=0;c>e;e++)a[e].ss_i=e;for(a.sort(function(a,c){return d=b(a,c),0===d?a.ss_i-c.ss_i:d}),e=0;c>e;e++)delete a[e].ss_i}function Na(a){for(var b=a.length,c=a[0];b--;)a[b]<c&&(c=a[b]);return c}function Ba(a){for(var b=a.length,c=a[0];b--;)a[b]>c&&(c=a[b]);return c}function Oa(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Pa(a){db||(db=Y(Ja)),a&&db.appendChild(a),db.innerHTML=""}function ra(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;I.console&&console.log(c)}function da(a){return parseFloat(a.toPrecision(14))}function Qa(a,b){va=m(a,b.animation)}function Cb(){var a=E.global.useUTC,b=a?"getUTC":"get",c=a?"setUTC":"set";Ra=6e4*(a&&E.global.timezoneOffset||0),eb=a?Date.UTC:function(a,b,c,g,h,i){return new Date(a,b,m(c,1),m(g,0),m(h,0),m(i,0)).getTime()},pb=b+"Minutes",qb=b+"Hours",rb=b+"Day",Xa=b+"Date",fb=b+"Month",gb=b+"FullYear",Db=c+"Minutes",Eb=c+"Hours",sb=c+"Date",Fb=c+"Month",Gb=c+"FullYear"}function P(){}function Sa(a,b,c,d){this.axis=a,this.pos=b,this.type=c||"",this.isNew=!0,!c&&!d&&this.addLabel()}function la(){this.init.apply(this,arguments)}function Ya(){this.init.apply(this,arguments)}function Hb(a,b,c,d,e){var f=a.chart.inverted;this.axis=a,this.isNegative=c,this.options=b,this.x=d,this.total=null,this.points={},this.stack=e,this.alignOptions={align:b.align||(f?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(f?"middle":c?"bottom":"top"),y:m(b.y,f?4:c?14:-6),x:m(b.x,f?c?-6:6:0)},this.textAlign=b.textAlign||(f?c?"right":"left":"center")}var t,Za,$a,db,E,cb,va,ub,A,eb,Ra,pb,qb,rb,Xa,fb,gb,Db,Eb,sb,Fb,Gb,y=document,I=window,U=Math,u=U.round,T=U.floor,Ka=U.ceil,v=U.max,C=U.min,M=U.abs,Z=U.cos,ea=U.sin,ma=U.PI,Ca=2*ma/360,wa=navigator.userAgent,Ib=I.opera,Aa=/msie/i.test(wa)&&!Ib,hb=8===y.documentMode,ib=/AppleWebKit/.test(wa),Ta=/Firefox/.test(wa),Jb=/(Mobile|Android|Windows Phone)/.test(wa),xa="http://www.w3.org/2000/svg",aa=!!y.createElementNS&&!!y.createElementNS(xa,"svg").createSVGRect,Nb=Ta&&parseInt(wa.split("Firefox/")[1],10)<4,fa=!aa&&!Aa&&!!y.createElement("canvas").getContext,Kb={},tb=0,sa=function(){},V=[],ab=0,Ja="div",Q="none",Ob=/^[0-9]+$/,Pb="stroke-width",F={},R=I.Highcharts=I.Highcharts?ra(16,!0):{};cb=function(a,b,c){if(!r(b)||isNaN(b))return"Invalid date";var e,a=m(a,"%Y-%m-%d %H:%M:%S"),d=new Date(b-Ra),f=d[qb](),g=d[rb](),h=d[Xa](),i=d[fb](),j=d[gb](),k=E.lang,l=k.weekdays,d=q({a:l[g].substr(0,3),A:l[g],d:Ha(h),e:h,b:k.shortMonths[i],B:k.months[i],m:Ha(i+1),y:j.toString().substr(2,2),Y:j,H:Ha(f),I:Ha(f%12||12),l:f%12||12,M:Ha(d[pb]()),p:12>f?"AM":"PM",P:12>f?"am":"pm",S:Ha(d.getSeconds()),L:Ha(u(b%1e3),3)},R.dateFormats);for(e in d)for(;-1!==a.indexOf("%"+e);)a=a.replace("%"+e,"function"==typeof d[e]?d[e](b):d[e]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a},Bb.prototype={wrapColor:function(a){this.color>=a&&(this.color=0)},wrapSymbol:function(a){this.symbol>=a&&(this.symbol=0)}},A=function(){for(var a=0,b=arguments,c=b.length,d={};c>a;a++)d[b[a++]]=b[a];return d}("millisecond",1,"second",1e3,"minute",6e4,"hour",36e5,"day",864e5,"week",6048e5,"month",26784e5,"year",31556952e3),ub={init:function(a,b,c){var g,h,i,b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,b=b.split(" "),c=[].concat(c),j=function(a){for(g=a.length;g--;)"M"===a[g]&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};if(e&&(j(b),j(c)),a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6)),d<=c.length/f&&b.length===c.length)for(;d--;)c=[].concat(c).splice(0,f).concat(c);if(a.shift=0,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);return h&&(b=b.concat(h),c=c.concat(i)),[b,c]},step:function(a,b,c,d){var e=[],f=a.length;if(1===c)e=d;else if(f===b.length&&1>c)for(;f--;)d=parseFloat(a[f]),e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d;else e=b;return e}},function(a){I.HighchartsAdapter=I.HighchartsAdapter||a&&{init:function(b){var e,c=a.fx,d=c.step,f=a.Tween,g=f&&f.propHooks;e=a.cssHooks.opacity,a.extend(a.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}}),a.each(["cur","_default","width","height","opacity"],function(a,b){var k,e=d;"cur"===b?e=c.prototype:"_default"===b&&f&&(e=g[b],b="set"),(k=e[b])&&(e[b]=function(c){var d,c=a?c:this;return"align"!==c.prop?(d=c.elem,d.attr?d.attr(c.prop,"cur"===b?t:c.now):k.apply(this,arguments)):void 0})}),Ma(e,"get",function(a,b,c){return b.attr?b.opacity||0:a.call(this,b,c)}),e=function(a){var d,c=a.elem;a.started||(d=b.init(c,c.d,c.toD),a.start=d[0],a.end=d[1],a.started=!0),c.attr("d",b.step(a.start,a.end,a.pos,c.toD))},f?g.d={set:e}:d.d=e,this.each=Array.prototype.forEach?function(a,b){return Array.prototype.forEach.call(a,b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(b.call(a[c],a[c],c,a)===!1)return c},a.fn.highcharts=function(){var c,d,a="Chart",b=arguments;return this[0]&&(Fa(b[0])&&(a=b[0],b=Array.prototype.slice.call(b,1)),c=b[0],c!==t&&(c.chart=c.chart||{},c.chart.renderTo=this[0],new R[a](c,b[1]),d=this),c===t&&(d=V[H(this[0],"data-highcharts-chart")])),d}},getScript:a.getScript,inArray:a.inArray,adapterRun:function(b,c){return a(b)[c]()},grep:a.grep,map:function(a,c){for(var d=[],e=0,f=a.length;f>e;e++)d[e]=c.call(a[e],a[e],e,a);return d},offset:function(b){return a(b).offset()},addEvent:function(b,c,d){a(b).bind(c,d)},removeEvent:function(b,c,d){var e=y.removeEventListener?"removeEventListener":"detachEvent";y[e]&&b&&!b[e]&&(b[e]=function(){}),a(b).unbind(c,d)},fireEvent:function(b,c,d,e){var h,f=a.Event(c),g="detached"+c;!Aa&&d&&(delete d.layerX,delete d.layerY,delete d.returnValue),q(f,d),b[c]&&(b[g]=b[c],b[c]=null),a.each(["preventDefault","stopPropagation"],function(a,b){var c=f[b];f[b]=function(){try{c.call(f)}catch(a){"preventDefault"===b&&(h=!0)}}}),a(b).trigger(f),b[g]&&(b[c]=b[g],b[g]=null),e&&!f.isDefaultPrevented()&&!h&&e(f)},washMouseEvent:function(a){var c=a.originalEvent||a;return c.pageX===t&&(c.pageX=a.pageX,c.pageY=a.pageY),c},animate:function(b,c,d){var e=a(b);b.style||(b.style={}),c.d&&(b.toD=c.d,c.d=1),e.stop(),c.opacity!==t&&b.attr&&(c.opacity+="px"),e.animate(c,d)},stop:function(b){a(b).stop()}}}(I.jQuery);var S=I.HighchartsAdapter,N=S||{};S&&S.init.call(S,ub);var jb=N.adapterRun,Qb=N.getScript,Da=N.inArray,p=N.each,vb=N.grep,Rb=N.offset,Ua=N.map,K=N.addEvent,W=N.removeEvent,D=N.fireEvent,Sb=N.washMouseEvent,kb=N.animate,bb=N.stop,N={enabled:!0,x:0,y:15,style:{color:"#606060",cursor:"default",fontSize:"11px"}};E={colors:"#7cb5ec,#434348,#90ed7d,#f7a35c,#8085e9,#f15c80,#e4d354,#8085e8,#8d4653,#91e8e1".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(","),decimalPoint:".",numericSymbols:"k,M,G,T,P,E".split(","),resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:!0,canvasToolsURL:"http://code.highcharts.com/4.0.1/modules/canvas-tools.js",VMLRadialGradientURL:"http://code.highcharts.com/4.0.1/gfx/vml-radial-gradient.png"},chart:{borderColor:"#4572A7",borderRadius:0,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacing:[10,10,15,10],backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0",resetZoomButton:{theme:{zIndex:20},position:{align:"right",x:-10,y:10}}},title:{text:"Chart title",align:"center",margin:15,style:{color:"#333333",fontSize:"18px"}},subtitle:{text:"",align:"center",style:{color:"#555555"}},plotOptions:{line:{allowPointSelect:!1,showCheckbox:!1,animation:{duration:1e3},events:{},lineWidth:2,marker:{lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{enabled:!0},select:{fillColor:"#FFFFFF",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:w(N,{align:"center",enabled:!1,formatter:function(){return null===this.y?"":Ga(this.y,-1)},verticalAlign:"bottom",y:0}),cropThreshold:300,pointRange:0,states:{hover:{marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1e3}},labels:{style:{position:"absolute",color:"#3E576F"}},legend:{enabled:!0,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderColor:"#909090",borderRadius:0,navigation:{activeColor:"#274b6d",inactiveColor:"#CCC"},shadow:!1,itemStyle:{color:"#333333",fontSize:"12px",fontWeight:"bold"},itemHoverStyle:{color:"#000"},itemHiddenStyle:{color:"#CCC"},itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},symbolPadding:5,verticalAlign:"bottom",x:0,y:0,title:{style:{fontWeight:"bold"}}},loading:{labelStyle:{fontWeight:"bold",position:"relative",top:"1em"},style:{position:"absolute",backgroundColor:"white",opacity:.5,textAlign:"center"}},tooltip:{enabled:!0,animation:aa,backgroundColor:"rgba(249, 249, 249, .85)",borderWidth:1,borderRadius:3,dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L",second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},headerFormat:'<span style="font-size: 10px">{point.key}</span><br/>',pointFormat:'<span style="color:{series.color}">●</span> {series.name}: <b>{point.y}</b><br/>',shadow:!0,snap:Jb?25:10,style:{color:"#333333",cursor:"default",fontSize:"12px",padding:"8px",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:"9px"}}};var ba=E.plotOptions,S=ba.line;Cb();var Tb=/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*\)/,Ub=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,Vb=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,ya=function(a){var c,d,b=[];return function(a){a&&a.stops?d=Ua(a.stops,function(a){return ya(a[1])}):(c=Tb.exec(a))?b=[z(c[1]),z(c[2]),z(c[3]),parseFloat(c[4],10)]:(c=Ub.exec(a))?b=[z(c[1],16),z(c[2],16),z(c[3],16),1]:(c=Vb.exec(a))&&(b=[z(c[1]),z(c[2]),z(c[3]),1])}(a),{get:function(c){var f;return d?(f=w(a),f.stops=[].concat(f.stops),p(d,function(a,b){f.stops[b]=[f.stops[b][0],a.get(c)]})):f=b&&!isNaN(b[0])?"rgb"===c?"rgb("+b[0]+","+b[1]+","+b[2]+")":"a"===c?b[3]:"rgba("+b.join(",")+")":a,f},brighten:function(a){if(d)p(d,function(b){b.brighten(a)});else if(ha(a)&&0!==a){var c;for(c=0;3>c;c++)b[c]+=z(255*a),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},rgba:b,setOpacity:function(a){return b[3]=a,this}}};P.prototype={init:function(a,b){this.element="span"===b?Y(b):y.createElementNS(xa,b),this.renderer=a},opacity:1,animate:function(a,b,c){b=m(b,va,!0),bb(this),b?(b=w(b,{}),c&&(b.complete=c),kb(this,a,b)):(this.attr(a),c&&c())},colorGradient:function(a,b,c){var e,f,g,h,i,j,k,l,o,n,d=this.renderer,s=[];if(a.linearGradient?f="linearGradient":a.radialGradient&&(f="radialGradient"),f){g=a[f],h=d.gradients,j=a.stops,o=c.radialReference,La(g)&&(a[f]=g={x1:g[0],y1:g[1],x2:g[2],y2:g[3],gradientUnits:"userSpaceOnUse"}),"radialGradient"===f&&o&&!r(g.gradientUnits)&&(g=w(g,{cx:o[0]-o[2]/2+g.cx*o[2],cy:o[1]-o[2]/2+g.cy*o[2],r:g.r*o[2],gradientUnits:"userSpaceOnUse"}));for(n in g)"id"!==n&&s.push(n,g[n]);for(n in j)s.push(j[n]);s=s.join(","),h[s]?a=h[s].attr("id"):(g.id=a="highcharts-"+tb++,h[s]=i=d.createElement(f).attr(g).add(d.defs),i.stops=[],p(j,function(a){0===a[1].indexOf("rgba")?(e=ya(a[1]),k=e.get("rgb"),l=e.get("a")):(k=a[1],l=1),a=d.createElement("stop").attr({offset:a[0],"stop-color":k,"stop-opacity":l}).add(i),i.stops.push(a)})),c.setAttribute(b,"url("+d.url+"#"+a+")")}},attr:function(a,b){var c,d,f,h,e=this.element,g=this;if("string"==typeof a&&b!==t&&(c=a,a={},a[c]=b),"string"==typeof a)g=(this[a+"Getter"]||this._defaultGetter).call(this,a,e);else{for(c in a)d=a[c],h=!1,this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c)&&(f||(this.symbolAttr(a),f=!0),h=!0),!this.rotation||"x"!==c&&"y"!==c||(this.doTransform=!0),h||(this[c+"Setter"]||this._defaultSetter).call(this,d,c,e),this.shadows&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(c)&&this.updateShadows(c,d);this.doTransform&&(this.updateTransform(),this.doTransform=!1)}return g},updateShadows:function(a,b){for(var c=this.shadows,d=c.length;d--;)c[d].setAttribute(a,"height"===a?v(b-(c[d].cutHeight||0),0):"d"===a?this.d:b)},addClass:function(a){var b=this.element,c=H(b,"class")||"";return-1===c.indexOf(a)&&H(b,"class",c+" "+a),this},symbolAttr:function(a){var b=this;p("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=m(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",a?"url("+this.renderer.url+"#"+a.id+")":Q)},crisp:function(a){var b,d,c={},e=a.strokeWidth||this.strokeWidth||this.attr&&this.attr("stroke-width")||0;d=u(e)%2/2,a.x=T(a.x||this.x||0)+d,a.y=T(a.y||this.y||0)+d,a.width=T((a.width||this.width||0)-2*d),a.height=T((a.height||this.height||0)-2*d),a.strokeWidth=e;for(b in a)this[b]!==a[b]&&(this[b]=c[b]=a[b]);return c},css:function(a){var e,f,b=this.styles,c={},d=this.element,g="";if(e=!b,a&&a.color&&(a.fill=a.color),b)for(f in a)a[f]!==b[f]&&(c[f]=a[f],e=!0);if(e){if(e=this.textWidth=a&&a.width&&"text"===d.nodeName.toLowerCase()&&z(a.width),b&&(a=q(b,c)),this.styles=a,e&&(fa||!aa&&this.renderer.forExport)&&delete a.width,Aa&&!aa)G(this.element,a);else{b=function(a,b){return"-"+b.toLowerCase()};for(f in a)g+=f.replace(/([A-Z])/g,b)+":"+a[f]+";";H(d,"style",g)}e&&this.added&&this.renderer.buildText(this)}return this},on:function(a,b){var c=this,d=c.element;return $a&&"click"===a?(d.ontouchstart=function(a){c.touchEventFired=Date.now(),a.preventDefault(),b.call(d,a)},d.onclick=function(a){(-1===wa.indexOf("Android")||Date.now()-(c.touchEventFired||0)>1100)&&b.call(d,a)}):d["on"+a]=b,this},setRadialReference:function(a){return this.element.radialReference=a,this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){return this.inverted=!0,this.updateTransform(),this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation,g=this.element;e&&(a+=this.attr("width"),b+=this.attr("height")),a=["translate("+a+","+b+")"],e?a.push("rotate(90) scale(-1,1)"):f&&a.push("rotate("+f+" "+(g.getAttribute("x")||0)+" "+(g.getAttribute("y")||0)+")"),(r(c)||r(d))&&a.push("scale("+m(c,1)+" "+m(d,1)+")"),a.length&&g.setAttribute("transform",a.join(" "))},toFront:function(){var a=this.element;return a.parentNode.appendChild(a),this},align:function(a,b,c){var d,e,f,g,h={};return e=this.renderer,f=e.alignedObjects,a?(this.alignOptions=a,this.alignByTranslate=b,(!c||Fa(c))&&(this.alignTo=d=c||"renderer",ja(f,this),f.push(this),c=null)):(a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo),c=m(c,e[d],e),d=a.align,e=a.verticalAlign,f=(c.x||0)+(a.x||0),g=(c.y||0)+(a.y||0),("right"===d||"center"===d)&&(f+=(c.width-(a.width||0))/{right:1,center:2}[d]),h[b?"translateX":"x"]=u(f),("bottom"===e||"middle"===e)&&(g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1)),h[b?"translateY":"y"]=u(g),this[this.placed?"animate":"attr"](h),this.placed=!0,this.alignAttr=h,this},getBBox:function(){var c,d,a=this.bBox,b=this.renderer,e=this.rotation;c=this.element;var f=this.styles,g=e*Ca;d=this.textStr;var h;if((""===d||Ob.test(d))&&(h="num."+d.toString().length+(f?"|"+f.fontSize+"|"+f.fontFamily:"")),h&&(a=b.cache[h]),!a){if(c.namespaceURI===xa||b.forExport){try{a=c.getBBox?q({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(i){}(!a||a.width<0)&&(a={width:0,height:0})}else a=this.htmlGetBBox();b.isSVG&&(c=a.width,d=a.height,Aa&&f&&"11px"===f.fontSize&&"16.9"===d.toPrecision(3)&&(a.height=d=14),e&&(a.width=M(d*ea(g))+M(c*Z(g)),a.height=M(d*Z(g))+M(c*ea(g)))),this.bBox=a,h&&(b.cache[h]=a)}return a},show:function(a){return a&&this.element.namespaceURI===xa?(this.element.removeAttribute("visibility"),this):this.attr({visibility:a?"inherit":"visible"})},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.hide()}})},add:function(a){var g,h,b=this.renderer,c=a||b,d=c.element||b.box,e=this.element,f=this.zIndex;if(a&&(this.parentGroup=a),this.parentInverted=a&&a.inverted,void 0!==this.textStr&&b.buildText(this),f&&(c.handleZ=!0,f=z(f)),c.handleZ)for(a=d.childNodes,g=0;g<a.length;g++)if(b=a[g],c=H(b,"zIndex"),b!==e&&(z(c)>f||!r(f)&&r(c))){d.insertBefore(e,b),h=!0;break}return h||d.appendChild(e),this.added=!0,this.onAdd&&this.onAdd(),this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var e,f,a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&"SPAN"===b.nodeName&&a.parentGroup;if(b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=null,bb(a),a.clipPath&&(a.clipPath=a.clipPath.destroy()),a.stops){for(f=0;f<a.stops.length;f++)a.stops[f]=a.stops[f].destroy();a.stops=null}for(a.safeRemoveChild(b),c&&p(c,function(b){a.safeRemoveChild(b)});d&&0===d.div.childNodes.length;)b=d.parentGroup,a.safeRemoveChild(d.div),delete d.div,d=b;a.alignTo&&ja(a.renderer.alignedObjects,a);for(e in a)delete a[e];return null},shadow:function(a,b,c){var e,f,h,i,j,k,d=[],g=this.element;if(a){for(i=m(a.width,3),j=(a.opacity||.15)/i,k=this.parentInverted?"(-1,-1)":"("+m(a.offsetX,1)+", "+m(a.offsetY,1)+")",e=1;i>=e;e++)f=g.cloneNode(0),h=2*i+1-2*e,H(f,{isShadow:"true",stroke:a.color||"black","stroke-opacity":j*e,"stroke-width":h,transform:"translate"+k,fill:Q}),c&&(H(f,"height",v(H(f,"height")-h,0)),f.cutHeight=h),b?b.element.appendChild(f):g.parentNode.insertBefore(f,g),d.push(f);this.shadows=d}return this},xGetter:function(a){return"circle"===this.element.nodeName&&(a={x:"cx",y:"cy"}[a]||a),this._defaultGetter(a)},_defaultGetter:function(a){return a=m(this[a],this.element?this.element.getAttribute(a):null,0),/^[0-9\.]+$/.test(a)&&(a=parseFloat(a)),a},dSetter:function(a,b,c){a&&a.join&&(a=a.join(" ")),/(NaN| {2}|^$)/.test(a)&&(a="M 0 0"),c.setAttribute(b,a),this[b]=a},dashstyleSetter:function(a){var b;if(a=a&&a.toLowerCase()){for(a=a.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(","),b=a.length;b--;)a[b]=z(a[b])*this.element.getAttribute("stroke-width");a=a.join(","),this.element.setAttribute("stroke-dasharray",a)}},alignSetter:function(a){this.element.setAttribute("text-anchor",{left:"start",center:"middle",right:"end"}[a])},opacitySetter:function(a,b,c){this[b]=a,c.setAttribute(b,a)},"stroke-widthSetter":function(a,b,c){0===a&&(a=1e-5),this.strokeWidth=a,c.setAttribute(b,a)},titleSetter:function(a){var b=this.element.getElementsByTagName("title")[0];b||(b=y.createElementNS(xa,"title"),this.element.appendChild(b)),b.textContent=a},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,b,c){"string"==typeof a?c.setAttribute(b,a):a&&this.colorGradient(a,b,c)},zIndexSetter:function(a,b,c){c.setAttribute(b,a),this[b]=a},_defaultSetter:function(a,b,c){c.setAttribute(b,a)}},P.prototype.yGetter=P.prototype.xGetter,P.prototype.translateXSetter=P.prototype.translateYSetter=P.prototype.rotationSetter=P.prototype.verticalAlignSetter=P.prototype.scaleXSetter=P.prototype.scaleYSetter=function(a,b){this[b]=a,this.doTransform=!0},P.prototype.strokeSetter=P.prototype.fillSetter;var ta=function(){this.init.apply(this,arguments)};ta.prototype={Element:P,init:function(a,b,c,d,e){var g,f=location,d=this.createElement("svg").attr({version:"1.1"}).css(this.getStyle(d));g=d.element,a.appendChild(g),-1===a.innerHTML.indexOf("xmlns")&&H(g,"xmlns",xa),this.isSVG=!0,this.box=g,this.boxWrapper=d,this.alignedObjects=[],this.url=(Ta||ib)&&y.getElementsByTagName("base").length?f.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"",this.createElement("desc").add().element.appendChild(y.createTextNode("Created with Highcharts 4.0.1")),this.defs=this.createElement("defs").add(),this.forExport=e,this.gradients={},this.cache={},this.setSize(b,c,!1);var h;Ta&&a.getBoundingClientRect&&(this.subPixelFix=b=function(){G(a,{left:0,top:0}),h=a.getBoundingClientRect(),G(a,{left:Ka(h.left)-h.left+"px",top:Ka(h.top)-h.top+"px"})},b(),K(I,"resize",b))},getStyle:function(a){return this.style=q({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;return this.box=null,this.boxWrapper=this.boxWrapper.destroy(),Oa(this.gradients||{}),this.gradients=null,a&&(this.defs=a.destroy()),this.subPixelFix&&W(I,"resize",this.subPixelFix),this.alignedObjects=null},createElement:function(a){var b=new this.Element;return b.init(this,a),b},draw:function(){},buildText:function(a){for(var h,i,b=a.element,c=this,d=c.forExport,e=m(a.textStr,"").toString(),f=-1!==e.indexOf("<"),g=b.childNodes,j=H(b,"x"),k=a.styles,l=a.textWidth,o=k&&k.lineHeight,n=g.length,s=function(a){return o?z(o):c.fontMetrics(/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:k&&k.fontSize||c.style.fontSize||12).h};n--;)b.removeChild(g[n]);f||-1!==e.indexOf(" ")?(h=/<.*style="([^"]+)".*>/,i=/<.*href="(http[^"]+)".*>/,l&&!a.added&&this.box.appendChild(b),e=f?e.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):[e],""===e[e.length-1]&&e.pop(),p(e,function(e,f){var g,n=0,e=e.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");g=e.split("|||"),p(g,function(e){if(""!==e||1===g.length){var p,o={},m=y.createElementNS(xa,"tspan");if(h.test(e)&&(p=e.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),H(m,"style",p)),i.test(e)&&!d&&(H(m,"onclick",'location.href="'+e.match(i)[1]+'"'),G(m,{cursor:"pointer"})),e=(e.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"<").replace(/&gt;/g,">")," "!==e&&(m.appendChild(y.createTextNode(e)),n?o.dx=0:f&&null!==j&&(o.x=j),H(m,o),!n&&f&&(!aa&&d&&G(m,{display:"block"}),H(m,"dy",s(m),ib&&m.offsetHeight)),b.appendChild(m),n++,l))for(var $,r,e=e.replace(/([^\^])-/g,"$1- ").split(" "),o=e.length>1&&"nowrap"!==k.whiteSpace,B=a._clipHeight,q=[],v=s(),t=1;o&&(e.length||q.length);)delete a.bBox,$=a.getBBox(),r=$.width,!aa&&c.forExport&&(r=c.measureSpanWidth(m.firstChild.data,a.styles)),$=r>l,$&&1!==e.length?(m.removeChild(m.firstChild),q.unshift(e.pop())):(e=q,q=[],e.length&&(t++,B&&t*v>B?(e=["..."],a.attr("title",a.textStr)):(m=y.createElementNS(xa,"tspan"),H(m,{dy:v,x:j}),p&&H(m,"style",p),b.appendChild(m),r>l&&(l=r)))),e.length&&m.appendChild(y.createTextNode(e.join(" ").replace(/- /g,"-")))}})})):b.appendChild(y.createTextNode(e))},button:function(a,b,c,d,e,f,g,h,i){var l,o,n,s,m,p,j=this.label(a,b,c,i,null,null,null,null,"button"),k=0,a={x1:0,y1:0,x2:0,y2:1},e=w({"stroke-width":1,stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);return n=e.style,delete e.style,f=w(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f),s=f.style,delete f.style,g=w(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g),m=g.style,delete g.style,h=w(e,{style:{color:"#CCC"}},h),p=h.style,delete h.style,K(j.element,Aa?"mouseover":"mouseenter",function(){3!==k&&j.attr(f).css(s)}),K(j.element,Aa?"mouseout":"mouseleave",function(){3!==k&&(l=[e,f,g][k],o=[n,s,m][k],j.attr(l).css(o))}),j.setState=function(a){(j.state=k=a)?2===a?j.attr(g).css(m):3===a&&j.attr(h).css(p):j.attr(e).css(n)},j.on("click",function(){3!==k&&d.call(j)}).attr(e).css(q({cursor:"default"},n))},crispLine:function(a,b){return a[1]===a[4]&&(a[1]=a[4]=u(a[1])-b%2/2),a[2]===a[5]&&(a[2]=a[5]=u(a[2])+b%2/2),a},path:function(a){var b={fill:Q};return La(a)?b.d=a:ca(a)&&q(b,a),this.createElement("path").attr(b)},circle:function(a,b,c){return a=ca(a)?a:{x:a,y:b,r:c},b=this.createElement("circle"),b.xSetter=function(a){this.element.setAttribute("cx",a)},b.ySetter=function(a){this.element.setAttribute("cy",a)},b.attr(a)},arc:function(a,b,c,d,e,f){return ca(a)&&(b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x),a=this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0}),a.r=c,a},rect:function(a,b,c,d,e,f){var e=ca(a)?a.r:e,g=this.createElement("rect"),a=ca(a)?a:a===t?{}:{x:a,y:b,width:v(c,0),height:v(d,0)};return f!==t&&(a.strokeWidth=f,a=g.crisp(a)),e&&(a.r=e),g.rSetter=function(a){H(this.element,{rx:a,ry:a})},g.attr(a)},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;for(this.width=a,this.height=b,this.boxWrapper[m(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return r(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:Q};return arguments.length>1&&q(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),f},symbol:function(a,b,c,d,e,f){var g,j,k,h=this.symbols[a],h=h&&h(u(b),u(c),d,e,f),i=/^url\((.*?)\)$/;return h?(g=this.path(h),q(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&q(g,f)):i.test(a)&&(k=function(a,b){a.element&&(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(u((d-b[0])/2),u((e-b[1])/2)))},j=a.match(i)[1],a=Kb[j],g=this.image(j).attr({x:b,y:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),Y("img",{onload:function(){k(g,Kb[j]=[this.width,this.height])},src:j}))),g},symbols:{circle:function(a,b,c,d){var e=.166*c;return["M",a+c/2,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["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",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-.001,d=e.innerR,h=e.open,i=Z(f),j=ea(f),k=Z(g),g=ea(g),e=e.end-f<ma?0:1;return["M",a+c*i,b+c*j,"A",c,c,0,e,1,a+c*k,b+c*g,h?"M":"L",a+d*k,b+d*g,"A",d,d,0,e,0,a+d*i,b+d*j,h?"":"Z"]},callout:function(a,b,c,d,e){var f=C(e&&e.r||0,c,d),g=f+6,h=e&&e.anchorX,i=e&&e.anchorY,e=u(e.strokeWidth||0)%2/2;return a+=e,b+=e,e=["M",a+f,b,"L",a+c-f,b,"C",a+c,b,a+c,b,a+c,b+f,"L",a+c,b+d-f,"C",a+c,b+d,a+c,b+d,a+c-f,b+d,"L",a+f,b+d,"C",a,b+d,a,b+d,a,b+d-f,"L",a,b+f,"C",a,b,a,b,a+f,b],h&&h>c&&i>b+g&&b+d-g>i?e.splice(13,3,"L",a+c,i-6,a+c+6,i,a+c,i+6,a+c,b+d-f):h&&0>h&&i>b+g&&b+d-g>i?e.splice(33,3,"L",a,i+6,a-6,i,a,i-6,a,b+f):i&&i>d&&h>a+g&&a+c-g>h?e.splice(23,3,"L",h+6,b+d,h,b+d+6,h-6,b+d,a+f,b+d):i&&0>i&&h>a+g&&a+c-g>h&&e.splice(3,3,"L",h-6,b,h,b-6,h+6,b,c-f,b),e}},clipRect:function(a,b,c,d){var e="highcharts-"+tb++,f=this.createElement("clipPath").attr({id:e}).add(this.defs),a=this.rect(a,b,c,d,0).add(f);return a.id=e,a.clipPath=f,a},text:function(a,b,c,d){var e=fa||!aa&&this.forExport,f={};return d&&!this.forExport?this.html(a,b,c):(f.x=Math.round(b||0),c&&(f.y=Math.round(c)),(a||0===a)&&(f.text=a),a=this.createElement("text").attr(f),e&&a.css({position:"absolute"}),d||(a.xSetter=function(a,b,c){var e,f,d=c.childNodes;for(f=1;f<d.length;f++)e=d[f],e.getAttribute("x")===c.getAttribute("x")&&e.setAttribute("x",a);c.setAttribute(b,a)}),a)},fontMetrics:function(a){var a=a||this.style.fontSize,a=/px/.test(a)?z(a):/em/.test(a)?12*parseFloat(a):12,a=24>a?a+4:u(1.2*a),b=u(.8*a);return{h:a,b:b}},label:function(a,b,c,d,e,f,g,h,i){function j(){var a,b;a=s.element.style,J=(void 0===Va||void 0===wb||n.styles.textAlign)&&s.textStr&&s.getBBox(),n.width=(Va||J.width||0)+2*x+v,n.height=(wb||J.height||0)+2*x,na=x+o.fontMetrics(a&&a.fontSize).b,z&&(m||(a=u(-L*x),b=h?-na:0,n.box=m=d?o.symbol(d,a,b,n.width,n.height,B):o.rect(a,b,n.width,n.height,0,B[Pb]),m.attr("fill",Q).add(n)),m.isImg||m.attr(q({width:u(n.width),height:u(n.height)},B)),B=null)}function k(){var c,a=n.styles,a=a&&a.textAlign,b=v+x*(1-L);c=h?0:na,r(Va)&&J&&("center"===a||"right"===a)&&(b+={center:.5,right:1}[a]*(Va-J.width)),(b!==s.x||c!==s.y)&&(s.attr("x",b),c!==t&&s.attr("y",c)),s.x=b,s.y=c}function l(a,b){m?m.attr(a,b):B[a]=b}var m,J,Va,wb,xb,yb,na,z,o=this,n=o.g(i),s=o.text("",0,0,g).attr({zIndex:1}),L=0,x=3,v=0,y=0,B={};n.onAdd=function(){s.add(n),n.attr({text:a||"",x:b,y:c}),m&&r(e)&&n.attr({anchorX:e,anchorY:f})},n.widthSetter=function(a){Va=a},n.heightSetter=function(a){wb=a},n.paddingSetter=function(a){r(a)&&a!==x&&(x=a,k())},n.paddingLeftSetter=function(a){r(a)&&a!==v&&(v=a,k())},n.alignSetter=function(a){L={left:0,center:.5,right:1}[a]},n.textSetter=function(a){a!==t&&s.textSetter(a),j(),k()},n["stroke-widthSetter"]=function(a,b){a&&(z=!0),y=a%2/2,l(b,a)},n.strokeSetter=n.fillSetter=n.rSetter=function(a,b){"fill"===b&&a&&(z=!0),l(b,a)
2
- },n.anchorXSetter=function(a,b){e=a,l(b,a+y-xb)},n.anchorYSetter=function(a,b){f=a,l(b,a-yb)},n.xSetter=function(a){n.x=a,L&&(a-=L*((Va||J.width)+x)),xb=u(a),n.attr("translateX",xb)},n.ySetter=function(a){yb=n.y=u(a),n.attr("translateY",yb)};var A=n.css;return q(n,{css:function(a){if(a){var b={},a=w(a);p("fontSize,fontWeight,fontFamily,color,lineHeight,width,textDecoration,textShadow".split(","),function(c){a[c]!==t&&(b[c]=a[c],delete a[c])}),s.css(b)}return A.call(n,a)},getBBox:function(){return{width:J.width+2*x,height:J.height+2*x,x:J.x-x,y:J.y-x}},shadow:function(a){return m&&m.shadow(a),n},destroy:function(){W(n.element,"mouseenter"),W(n.element,"mouseleave"),s&&(s=s.destroy()),m&&(m=m.destroy()),P.prototype.destroy.call(n),n=o=j=k=l=null}})}},Za=ta,q(P.prototype,{htmlCss:function(a){var b=this.element;return(b=a&&"SPAN"===b.tagName&&a.width)&&(delete a.width,this.textWidth=b,this.updateTransform()),this.styles=q(this.styles,a),G(this.element,a),this},htmlGetBBox:function(){var a=this.element,b=this.bBox;return b||("text"===a.nodeName&&(a.style.position="absolute"),b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}),b},htmlUpdateTransform:function(){if(this.added){var a=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:.5,right:1}[g],i=this.shadows;if(G(b,{marginLeft:c,marginTop:d}),i&&p(i,function(a){G(a,{marginLeft:c+1,marginTop:d+1})}),this.inverted&&p(b.childNodes,function(c){a.invertChild(c,b)}),"SPAN"===b.tagName){var k,j=this.rotation,l=z(this.textWidth),o=[j,g,b.innerHTML,this.textWidth].join(",");o!==this.cTT&&(k=a.fontMetrics(b.style.fontSize).b,r(j)&&this.setSpanRotation(j,h,k),i=m(this.elemWidth,b.offsetWidth),i>l&&/[ \-]/.test(b.textContent||b.innerText)&&(G(b,{width:l+"px",display:"block",whiteSpace:"normal"}),i=l),this.getSpanCorrection(i,k,h,j,g)),G(b,{left:e+(this.xCorr||0)+"px",top:f+(this.yCorr||0)+"px"}),ib&&(k=b.offsetHeight),this.cTT=o}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,c){var d={},e=Aa?"-ms-transform":ib?"-webkit-transform":Ta?"MozTransform":Ib?"-o-transform":"";d[e]=d.transform="rotate("+a+"deg)",d[e+(Ta?"Origin":"-origin")]=d.transformOrigin=100*b+"% "+c+"px",G(this.element,d)},getSpanCorrection:function(a,b,c){this.xCorr=-a*c,this.yCorr=-b}}),q(ta.prototype,{html:function(a,b,c){var d=this.createElement("span"),e=d.element,f=d.renderer;return d.textSetter=function(a){a!==e.innerHTML&&delete this.bBox,e.innerHTML=this.textStr=a},d.xSetter=d.ySetter=d.alignSetter=d.rotationSetter=function(a,b){"align"===b&&(b="textAlign"),d[b]=a,d.htmlUpdateTransform()},d.attr({text:a,x:u(b),y:u(c)}).css({position:"absolute",whiteSpace:"nowrap",fontFamily:this.style.fontFamily,fontSize:this.style.fontSize}),d.css=d.htmlCss,f.isSVG&&(d.add=function(a){var b,c=f.box.parentNode,j=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)j.push(a),a=a.parentGroup;p(j.reverse(),function(a){var d;b=a.div=a.div||Y(Ja,{className:H(a.element,"class")},{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px"},b||c),d=b.style,q(a,{translateXSetter:function(b,c){d.left=b+"px",a[c]=b,a.doTransform=!0},translateYSetter:function(b,c){d.top=b+"px",a[c]=b,a.doTransform=!0},visibilitySetter:function(a,b){d[b]=a}})})}}else b=c;return b.appendChild(e),d.added=!0,d.alignOnAdd&&d.htmlUpdateTransform(),d}),d}});var X;if(!aa&&!fa){R.VMLElement=X={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ","absolute",";"],e=b===Ja;("shape"===b||e)&&d.push("left:0;top:0;width:1px;height:1px;"),d.push("visibility: ",e?"hidden":"visible"),c.push(' style="',d.join(""),'"/>'),b&&(c=e||"span"===b||"img"===b?c.join(""):a.prepVML(c),this.element=Y(c)),this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;return a&&a.inverted&&b.invertChild(c,d),d.appendChild(c),this.added=!0,this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform(),this.onAdd&&this.onAdd(),this},updateTransform:P.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=Z(a*Ca),c=ea(a*Ca);G(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",b,", M12=",-c,", M21=",c,", M22=",b,", sizingMethod='auto expand')"].join(""):Q})},getSpanCorrection:function(a,b,c,d,e){var i,f=d?Z(d*Ca):1,g=d?ea(d*Ca):0,h=m(this.elemHeight,this.element.offsetHeight);this.xCorr=0>f&&-a,this.yCorr=0>g&&-h,i=0>f*g,this.xCorr+=g*b*(i?1-c:c),this.yCorr-=f*b*(d?i?c:1-c:1),e&&"left"!==e&&(this.xCorr-=a*c*(0>f?-1:1),d&&(this.yCorr-=h*c*(0>g?-1:1)),G(this.element,{textAlign:e}))},pathToVML:function(a){for(var b=a.length,c=[];b--;)ha(a[b])?c[b]=u(10*a[b])-5:"Z"===a[b]?c[b]="x":(c[b]=a[b],!a.isArc||"wa"!==a[b]&&"at"!==a[b]||(c[b+5]===c[b+7]&&(c[b+7]+=a[b+7]>a[b+5]?1:-1),c[b+6]===c[b+8]&&(c[b+8]+=a[b+8]>a[b+6]?1:-1)));return c.join(" ")||"x"},clip:function(a){var c,b=this;return a?(c=a.members,ja(c,b),c.push(b),b.destroyClip=function(){ja(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:hb?"inherit":"rect(auto)"}),b.css(a)},css:P.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Pa(a)},destroy:function(){return this.destroyClip&&this.destroyClip(),P.prototype.destroy.apply(this)},on:function(a,b){return this.element["on"+a]=function(){var a=I.event;a.target=a.srcElement,b(a)},this},cutOffPath:function(a,b){var c,a=a.split(/[ ,]/);return c=a.length,(9===c||11===c)&&(a[c-4]=a[c-2]=z(a[c-2])-10*b),a.join(" ")},shadow:function(a,b,c){var e,h,j,l,o,n,s,d=[],f=this.element,g=this.renderer,i=f.style,k=f.path;if(k&&"string"!=typeof k.value&&(k="x"),o=k,a){for(n=m(a.width,3),s=(a.opacity||.15)/n,e=1;3>=e;e++)l=2*n+1-2*e,c&&(o=this.cutOffPath(k.value,l+.5)),j=['<shape isShadow="true" strokeweight="',l,'" filled="false" path="',o,'" coordsize="10 10" style="',f.style.cssText,'" />'],h=Y(g.prepVML(j),null,{left:z(i.left)+m(a.offsetX,1),top:z(i.top)+m(a.offsetY,1)}),c&&(h.cutOff=l+1),j=['<stroke color="',a.color||"black",'" opacity="',s*e,'"/>'],Y(g.prepVML(j),null,null,h),b?b.element.appendChild(h):f.parentNode.insertBefore(h,f),d.push(h);this.shadows=d}return this},updateShadows:sa,setAttr:function(a,b){hb?this.element[a]=b:this.element.setAttribute(a,b)},classSetter:function(a){this.element.className=a},dashstyleSetter:function(a,b,c){(c.getElementsByTagName("stroke")[0]||Y(this.renderer.prepVML(["<stroke/>"]),null,null,c))[b]=a||"solid",this[b]=a},dSetter:function(a,b,c){var d=this.shadows,a=a||[];if(this.d=a.join(" "),c.path=a=this.pathToVML(a),d)for(c=d.length;c--;)d[c].path=d[c].cutOff?this.cutOffPath(a,d[c].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,c){var d=c.nodeName;"SPAN"===d?c.style.color=a:"IMG"!==d&&(c.filled=a!==Q,this.setAttr("fillcolor",this.renderer.color(a,c,b,this)))},opacitySetter:sa,rotationSetter:function(a,b,c){c=c.style,this[b]=c[b]=a,c.left=-u(ea(a*Ca)+1)+"px",c.top=u(Z(a*Ca))+"px"},strokeSetter:function(a,b,c){this.setAttr("strokecolor",this.renderer.color(a,c,b))},"stroke-widthSetter":function(a,b,c){c.stroked=!!a,this[b]=a,ha(a)&&(a+="px"),this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,c){"inherit"===a&&(a="visible"),this.shadows&&p(this.shadows,function(c){c.style[b]=a}),"DIV"===c.nodeName&&(a="hidden"===a?"-999em":0,hb||(c.style[b]=a?"visible":"hidden"),b="top"),c.style[b]=a},xSetter:function(a,b,c){this[b]=a,"x"===b?b="left":"y"===b&&(b="top"),this.updateClipping?(this[b]=a,this.updateClipping()):c.style[b]=a},zIndexSetter:function(a,b,c){c.style[b]=a}},X=ka(P,X),X.prototype.ySetter=X.prototype.widthSetter=X.prototype.heightSetter=X.prototype.xSetter;var ga={Element:X,isIE8:wa.indexOf("MSIE 8.0")>-1,init:function(a,b,c,d){var e;if(this.alignedObjects=[],d=this.createElement(Ja).css(q(this.getStyle(d),{position:"relative"})),e=d.element,a.appendChild(d.element),this.isVML=!0,this.box=e,this.boxWrapper=d,this.cache={},this.setSize(b,c,!1),!y.namespaces.hcv){y.namespaces.add("hcv","urn:schemas-microsoft-com:vml");try{y.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}catch(f){y.styleSheets[0].cssText+="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}}},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=ca(a);return q(e,{members:[],left:(f?a.x:a)+1,top:(f?a.y:b)+1,width:(f?a.width:c)-1,height:(f?a.height:d)-1,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-("shape"===c?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+u(a?e:d)+"px,"+u(a?f:b)+"px,"+u(a?b:f)+"px,"+u(a?d:e)+"px)"};return!a&&hb&&"DIV"===c&&q(d,{width:b+"px",height:f+"px"}),d},updateClipping:function(){p(e.members,function(a){a.element&&a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var f,h,i,e=this,g=/^rgba/,j=Q;if(a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern"),i){var k,l,n,s,m,J,L,r,o=a.linearGradient||a.radialGradient,x="",a=a.stops,v=[],q=function(){h=['<fill colors="'+v.join(",")+'" opacity="',m,'" o:opacity2="',s,'" type="',i,'" ',x,'focus="100%" method="any" />'],Y(e.prepVML(h),null,null,b)};if(n=a[0],r=a[a.length-1],n[0]>0&&a.unshift([0,n[1]]),r[0]<1&&a.push([1,r[1]]),p(a,function(a,b){g.test(a[1])?(f=ya(a[1]),k=f.get("rgb"),l=f.get("a")):(k=a[1],l=1),v.push(100*a[0]+"% "+k),b?(m=l,J=k):(s=l,L=k)}),"fill"===c)if("gradient"===i)c=o.x1||o[0]||0,a=o.y1||o[1]||0,n=o.x2||o[2]||0,o=o.y2||o[3]||0,x='angle="'+(90-180*U.atan((o-a)/(n-c))/ma)+'"',q();else{var w,j=o.r,t=2*j,u=2*j,y=o.cx,B=o.cy,na=b.radialReference,j=function(){na&&(w=d.getBBox(),y+=(na[0]-w.x)/w.width-.5,B+=(na[1]-w.y)/w.height-.5,t*=na[2]/w.width,u*=na[2]/w.height),x='src="'+E.global.VMLRadialGradientURL+'" size="'+t+","+u+'" origin="0.5,0.5" position="'+y+","+B+'" color2="'+L+'" ',q()};d.added?j():d.onAdd=j,j=J}else j=k}else g.test(a)&&"IMG"!==b.tagName?(f=ya(a),h=["<",c,' opacity="',f.get("a"),'"/>'],Y(this.prepVML(h),null,null,b),j=f.get("rgb")):(j=b.getElementsByTagName(c),j.length&&(j[0].opacity=1,j[0].type="solid"),j=a);return j},prepVML:function(a){var b=this.isIE8,a=a.join("");return b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=-1===a.indexOf('style="')?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:"),a},text:ta.prototype.html,path:function(a){var b={coordsize:"10 10"};return La(a)?b.d=a:ca(a)&&q(b,a),this.createElement("shape").attr(b)},circle:function(a,b,c){var d=this.symbol("circle");return ca(a)&&(c=a.r,b=a.y,a=a.x),d.isCircle=!0,d.r=c,d.attr({x:a,y:b})},g:function(a){var b;return a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a}),this.createElement(Ja).attr(b)},image:function(a,b,c,d,e){var f=this.createElement("img").attr({src:a});return arguments.length>1&&f.attr({x:b,y:c,width:d,height:e}),f},createElement:function(a){return"rect"===a?this.symbol(a):ta.prototype.createElement.call(this,a)},invertChild:function(a,b){var c=this,d=b.style,e="IMG"===a.tagName&&a.style;G(a,{flip:"x",left:z(d.width)-(e?z(e.top):1),top:z(d.height)-(e?z(e.left):1),rotation:-90}),p(a.childNodes,function(b){c.invertChild(b,a)})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||d,c=e.innerR,d=Z(f),i=ea(f),j=Z(g),k=ea(g);return g-f===0?["x"]:(f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k],e.open&&!c&&f.push("e","M",a,b),f.push("at",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,"x","e"),f.isArc=!0,f)},circle:function(a,b,c,d,e){return e&&(c=d=2*e.r),e&&e.isCircle&&(a-=c/2,b-=d/2),["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){return ta.prototype.symbols[r(e)&&e.r?"callout":"square"].call(0,a,b,c,d,e)}}};R.VMLRenderer=X=function(){this.init.apply(this,arguments)},X.prototype=w(ta.prototype,ga),Za=X}ta.prototype.measureSpanWidth=function(a,b){var d,c=y.createElement("span");return d=y.createTextNode(a),c.appendChild(d),G(c,b),this.box.appendChild(c),d=c.offsetWidth,Pa(c),d};var Lb;fa&&(R.CanVGRenderer=X=function(){xa="http://www.w3.org/1999/xhtml"},X.prototype.symbols={},Lb=function(){function a(){var d,a=b.length;for(d=0;a>d;d++)b[d]();b=[]}var b=[];return{push:function(c,d){0===b.length&&Qb(d,a),b.push(c)}}}(),Za=X),Sa.prototype={addLabel:function(){var l,a=this.axis,b=a.options,c=a.chart,d=a.horiz,e=a.categories,f=a.names,g=this.pos,h=b.labels,i=a.tickPositions,d=d&&e&&!h.step&&!h.staggerLines&&!h.rotation&&c.plotWidth/i.length||!d&&(c.margin[3]||.33*c.chartWidth),j=g===i[0],k=g===i[i.length-1],f=e?m(e[g],f[g],g):g,e=this.label,o=i.info;a.isDatetimeAxis&&o&&(l=b.dateTimeLabelFormats[o.higherRanks[g]||o.unitName]),this.isFirst=j,this.isLast=k,b=a.labelFormatter.call({axis:a,chart:c,isFirst:j,isLast:k,dateTimeLabelFormat:l,value:a.isLog?da(ia(f)):f}),g=d&&{width:v(1,u(d-2*(h.padding||10)))+"px"},g=q(g,h.style),r(e)?e&&e.attr({text:b}).css(g):(l={align:a.labelAlign},ha(h.rotation)&&(l.rotation=h.rotation),d&&h.ellipsis&&(l._clipHeight=a.len/i.length),this.label=r(b)&&h.enabled?c.renderer.text(b,0,0,h.useHTML).attr(l).css(g).add(a.labelGroup):null)},getLabelSize:function(){var a=this.label,b=this.axis;return a?a.getBBox()[b.horiz?"height":"width"]:0},getLabelSides:function(){var a=this.label.getBBox(),b=this.axis,c=b.horiz,d=b.options.labels,a=c?a.width:a.height,b=c?d.x-a*{left:0,center:.5,right:1}[b.labelAlign]:0;return[b,c?a+b:a]},handleOverflow:function(a,b){var l,o,n,c=!0,d=this.axis,e=this.isFirst,f=this.isLast,g=d.horiz?b.x:b.y,h=d.reversed,i=d.tickPositions,j=this.getLabelSides(),k=j[0],j=j[1],s=this.label.line||0;if(l=d.labelEdge,o=d.justifyLabels&&(e||f),l[s]===t||g+k>l[s]?l[s]=g+j:o||(c=!1),o){l=(o=d.justifyToPlot)?d.pos:0,o=o?l+d.len:d.chart.chartWidth;do a+=e?1:-1,n=d.ticks[i[a]];while(i[a]&&(!n||n.label.line!==s));d=n&&n.label.xy&&n.label.xy.x+n.getLabelSides()[e?0:1],e&&!h||f&&h?l>g+k&&(g=l-k,n&&g+j>d&&(c=!1)):g+j>o&&(g=o-j,n&&d>g+k&&(c=!1)),b.x=g}return c},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,b,c,d,e,f,g,h){var i=this.axis,j=i.transA,k=i.reversed,l=i.staggerLines,o=i.chart.renderer.fontMetrics(e.style.fontSize).b,n=e.rotation,a=a+e.x-(f&&d?f*j*(k?-1:1):0),b=b+e.y-(f&&!d?f*j*(k?1:-1):0);return n&&2===i.side&&(b-=o-o*Z(n*Ca)),!r(e.y)&&!n&&(b+=o-c.getBBox().height/2),l&&(c.line=g/(h||1)%l,b+=c.line*(i.labelOffset/l)),{x:a,y:b}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine(["M",a,b,"L",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,b,c){var d=this.axis,e=d.options,f=d.chart.renderer,g=d.horiz,h=this.type,i=this.label,j=this.pos,k=e.labels,l=this.gridLine,o=h?h+"Grid":"grid",n=h?h+"Tick":"tick",s=e[o+"LineWidth"],p=e[o+"LineColor"],J=e[o+"LineDashStyle"],L=e[n+"Length"],o=e[n+"Width"]||0,x=e[n+"Color"],r=e[n+"Position"],n=this.mark,v=k.step,q=!0,u=d.tickmarkOffset,w=this.getPosition(g,j,u,b),y=w.x,w=w.y,B=g&&y===d.pos+d.len||!g&&w===d.pos?-1:1;this.isActive=!0,s&&(j=d.getPlotLinePath(j+u,s*B,b,!0),l===t&&(l={stroke:p,"stroke-width":s},J&&(l.dashstyle=J),h||(l.zIndex=1),b&&(l.opacity=0),this.gridLine=l=s?f.path(j).attr(l).add(d.gridGroup):null),!b&&l&&j&&l[this.isNew?"attr":"animate"]({d:j,opacity:c})),o&&L&&("inside"===r&&(L=-L),d.opposite&&(L=-L),h=this.getMarkPath(y,w,L,o*B,g,f),n?n.animate({d:h,opacity:c}):this.mark=f.path(h).attr({stroke:x,"stroke-width":o,opacity:c}).add(d.axisGroup)),i&&!isNaN(y)&&(i.xy=w=this.getLabelPosition(y,w,i,g,k,u,a,v),this.isFirst&&!this.isLast&&!m(e.showFirstLabel,1)||this.isLast&&!this.isFirst&&!m(e.showLastLabel,1)?q=!1:!d.isRadial&&!k.step&&!k.rotation&&!b&&0!==c&&(q=this.handleOverflow(a,w)),v&&a%v&&(q=!1),q&&!isNaN(w.y)?(w.opacity=c,i[this.isNew?"attr":"animate"](w),this.isNew=!1):i.attr("y",-9999))},destroy:function(){Oa(this,this.axis)}},R.PlotLineOrBand=function(a,b){this.axis=a,b&&(this.options=b,this.id=b.id)},R.PlotLineOrBand.prototype={render:function(){var p,a=this,b=a.axis,c=b.horiz,d=(b.pointRange||0)/2,e=a.options,f=e.label,g=a.label,h=e.width,i=e.to,j=e.from,k=r(j)&&r(i),l=e.value,o=e.dashStyle,n=a.svgElem,s=[],J=e.color,L=e.zIndex,x=e.events,q={},t=b.chart.renderer;if(b.isLog&&(j=za(j),i=za(i),l=za(l)),h)s=b.getPlotLinePath(l,h),q={stroke:J,"stroke-width":h},o&&(q.dashstyle=o);else{if(!k)return;j=v(j,b.min-d),i=C(i,b.max+d),s=b.getPlotBandPath(j,i,e),J&&(q.fill=J),e.borderWidth&&(q.stroke=e.borderColor,q["stroke-width"]=e.borderWidth)}if(r(L)&&(q.zIndex=L),n)s?n.animate({d:s},null,n.onGetPath):(n.hide(),n.onGetPath=function(){n.show()},g&&(a.label=g=g.destroy()));else if(s&&s.length&&(a.svgElem=n=t.path(s).attr(q).add(),x))for(p in d=function(b){n.on(b,function(c){x[b].apply(a,[c])})},x)d(p);return f&&r(f.text)&&s&&s.length&&b.width>0&&b.height>0?(f=w({align:c&&k&&"center",x:c?!k&&4:10,verticalAlign:!c&&k&&"middle",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},f),g||(q={align:f.textAlign||f.align,rotation:f.rotation},r(L)&&(q.zIndex=L),a.label=g=t.text(f.text,0,0,f.useHTML).attr(q).css(f.style).add()),b=[s[1],s[4],m(s[6],s[1])],s=[s[2],s[5],m(s[7],s[2])],c=Na(b),k=Na(s),g.align(f,!1,{x:c,y:k,width:Ba(b)-c,height:Ba(s)-k}),g.show()):g&&g.hide(),a},destroy:function(){ja(this.axis.plotLinesAndBands,this),delete this.axis,Oa(this)}},la.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#C0C0C0",labels:N,lineColor:"#C0D0E0",lineWidth:1,minPadding:.01,maxPadding:.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#707070"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8,y:3},lineWidth:0,maxPadding:.05,minPadding:.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return Ga(this.total,-1)},style:N.style}},defaultLeftAxisOptions:{labels:{x:-15,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{x:0,y:20},title:{rotation:0}},defaultTopAxisOptions:{labels:{x:0,y:-15},title:{rotation:0}},init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c,this.coll=(this.isXAxis=c)?"xAxis":"yAxis",this.opposite=b.opposite,this.side=b.side||(this.horiz?this.opposite?0:2:this.opposite?1:3),this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter,this.userOptions=b,this.minPixelPadding=0,this.chart=a,this.reversed=d.reversed,this.zoomEnabled=d.zoomEnabled!==!1,this.categories=d.categories||"category"===e,this.names=[],this.isLog="logarithmic"===e,this.isDatetimeAxis="datetime"===e,this.isLinked=r(d.linkedTo),this.tickmarkOffset=this.categories&&"between"===d.tickmarkPlacement?.5:0,this.ticks={},this.labelEdge=[],this.minorTicks={},this.plotLinesAndBands=[],this.alternateBands={},this.len=0,this.minRange=this.userMinRange=d.minRange||d.maxZoom,this.range=d.range,this.offset=d.offset||0,this.stacks={},this.oldStacks={},this.min=this.max=null,this.crosshair=m(d.crosshair,qa(a.options.tooltip.crosshairs)[c?0:1],!1);var f,d=this.options.events;-1===Da(this,a.axes)&&(c&&!this.isColorAxis?a.axes.splice(a.xAxis.length,0,this):a.axes.push(this),a[this.coll].push(this)),this.series=this.series||[],a.inverted&&c&&this.reversed===t&&(this.reversed=!0),this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)K(this,f,d[f]);this.isLog&&(this.val2lin=za,this.lin2val=ia)},setOptions:function(a){this.options=w(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],w(E[this.coll],a))},defaultLabelFormatter:function(){var g,a=this.axis,b=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=E.lang.numericSymbols,f=e&&e.length,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ia(h,this);else if(c)g=b;else if(d)g=cb(d,b);else if(f&&a>=1e3)for(;f--&&g===t;)c=Math.pow(1e3,f+1),a>=c&&null!==e[f]&&(g=Ga(b/c,-1)+e[f]);return g===t&&(g=M(b)>=1e4?Ga(b,0):Ga(b,-1,t,"")),g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1,a.dataMin=a.dataMax=null,a.buildStacks&&a.buildStacks(),p(a.series,function(c){if(c.visible||!b.options.chart.ignoreHiddenSeries){var d;d=c.options.threshold;var e;a.hasVisibleSeries=!0,a.isLog&&0>=d&&(d=null),a.isXAxis?(d=c.xData,d.length&&(a.dataMin=C(m(a.dataMin,d[0]),Na(d)),a.dataMax=v(m(a.dataMax,d[0]),Ba(d)))):(c.getExtremes(),e=c.dataMax,c=c.dataMin,r(c)&&r(e)&&(a.dataMin=C(m(a.dataMin,c),c),a.dataMax=v(m(a.dataMax,e),e)),r(d)&&(a.dataMin>=d?(a.dataMin=d,a.ignoreMinPadding=!0):a.dataMax<d&&(a.dataMax=d,a.ignoreMaxPadding=!0)))}})},translate:function(a,b,c,d,e,f){var g=1,h=0,i=d?this.oldTransA:this.transA,d=d?this.oldMin:this.min,j=this.minPixelPadding,e=(this.options.ordinal||this.isLog&&e)&&this.lin2val;return i||(i=this.transA),c&&(g*=-1,h=this.len),this.reversed&&(g*=-1,h-=g*(this.sector||this.len)),b?(a=a*g+h,a-=j,a=a/i+d,e&&(a=this.lin2val(a))):(e&&(a=this.val2lin(a)),"between"===f&&(f=.5),a=g*(a-d)*i+h+g*j+(ha(f)?i*f*this.pointRange:0)),a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,e){var i,j,o,f=this.chart,g=this.left,h=this.top,k=c&&f.oldChartHeight||f.chartHeight,l=c&&f.oldChartWidth||f.chartWidth;return i=this.transB,e=m(e,this.translate(a,null,null,c)),a=c=u(e+i),i=j=u(k-e-i),isNaN(e)?o=!0:this.horiz?(i=h,j=k-this.bottom,(g>a||a>g+this.width)&&(o=!0)):(a=g,c=l-this.right,(h>i||i>h+this.height)&&(o=!0)),o&&!d?null:f.renderer.crispLine(["M",a,i,"L",c,j],b||1)},getLinearTickPositions:function(a,b,c){var d,e=da(T(b/a)*a),f=da(Ka(c/a)*a),g=[];if(b===c&&ha(b))return[b];for(b=e;f>=b&&(g.push(b),b=da(b+a),b!==d);)d=b;return g},getMinorTickPositions:function(){var e,a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[];if(this.isLog)for(e=b.length,a=1;e>a;a++)d=d.concat(this.getLogTickPositions(c,b[a-1],b[a],!0));else if(this.isDatetimeAxis&&"auto"===a.minorTickInterval)d=d.concat(this.getTimeTicks(this.normalizeTimeTickInterval(c),this.min,this.max,a.startOfWeek)),d[0]<this.min&&d.shift();else for(b=this.min+(b[0]-this.min)%c;b<=this.max;b+=c)d.push(b);return d},adjustForMinRange:function(){var d,f,g,h,i,j,a=this.options,b=this.min,c=this.max,e=this.dataMax-this.dataMin>=this.minRange;if(this.isXAxis&&this.minRange===t&&!this.isLog&&(r(a.min)||r(a.max)?this.minRange=null:(p(this.series,function(a){for(i=a.xData,g=j=a.xIncrement?1:i.length-1;g>0;g--)h=i[g]-i[g-1],(f===t||f>h)&&(f=h)}),this.minRange=C(5*f,this.dataMax-this.dataMin))),c-b<this.minRange){var k=this.minRange;d=(k-c+b)/2,d=[b-d,m(a.min,b-d)],e&&(d[2]=this.dataMin),b=Ba(d),c=[b+k,m(a.max,b+k)],e&&(c[2]=this.dataMax),c=Na(c),k>c-b&&(d[0]=c-k,d[1]=m(a.min,c-k),b=Ba(d))}this.min=b,this.max=c},setAxisTranslation:function(a){var e,b=this,c=b.max-b.min,d=b.axisPointRange||0,f=0,g=0,h=b.linkedParent,i=!!b.categories,j=b.transA;(b.isXAxis||i||d)&&(h?(f=h.minPointOffset,g=h.pointRangePadding):p(b.series,function(a){var h=i?1:b.isXAxis?a.pointRange:b.axisPointRange||0,j=a.options.pointPlacement,n=a.closestPointRange;h>c&&(h=0),d=v(d,h),f=v(f,Fa(j)?0:h/2),g=v(g,"on"===j?0:h),!a.noSharedTooltip&&r(n)&&(e=r(e)?C(e,n):n)}),h=b.ordinalSlope&&e?b.ordinalSlope/e:1,b.minPointOffset=f*=h,b.pointRangePadding=g*=h,b.pointRange=C(d,c),b.closestPointRange=e),a&&(b.oldTransA=j),b.translationSlope=b.transA=j=b.len/(c+g||1),b.transB=b.horiz?b.left:b.bottom,b.minPixelPadding=j*f},setTickPositions:function(a){var s,b=this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=b.options.tickPositioner,j=d.maxPadding,k=d.minPadding,l=d.tickInterval,o=d.minTickInterval,n=d.tickPixelInterval,$=b.categories;h?(b.linkedParent=c[b.coll][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=m(c.min,c.dataMin),b.max=m(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&ra(11,1)):(b.min=m(b.userMin,d.min,b.dataMin),b.max=m(b.userMax,d.max,b.dataMax)),e&&(!a&&C(b.min,m(b.dataMin,b.min))<=0&&ra(10,1),b.min=da(za(b.min)),b.max=da(za(b.max))),b.range&&r(b.max)&&(b.userMin=b.min=v(b.min,b.max-b.range),b.userMax=b.max,b.range=null),b.beforePadding&&b.beforePadding(),b.adjustForMinRange(),$||b.axisPointRange||b.usePercentage||h||!r(b.min)||!r(b.max)||!(c=b.max-b.min)||(r(d.min)||r(b.userMin)||!k||!(b.dataMin<0)&&b.ignoreMinPadding||(b.min-=c*k),r(d.max)||r(b.userMax)||!j||!(b.dataMax>0)&&b.ignoreMaxPadding||(b.max+=c*j)),ha(d.floor)&&(b.min=v(b.min,d.floor)),ha(d.ceiling)&&(b.max=C(b.max,d.ceiling)),b.min===b.max||void 0===b.min||void 0===b.max?b.tickInterval=1:h&&!l&&n===b.linkedParent.options.tickPixelInterval?b.tickInterval=b.linkedParent.tickInterval:(b.tickInterval=m(l,$?1:(b.max-b.min)*n/v(b.len,n)),!r(l)&&b.len<n&&!this.isRadial&&!this.isLog&&!$&&d.startOnTick&&d.endOnTick&&(s=!0,b.tickInterval/=4)),g&&!a&&p(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)}),b.setAxisTranslation(!0),b.beforeSetTickPositions&&b.beforeSetTickPositions(),b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval)),b.pointRange&&(b.tickInterval=v(b.pointRange,b.tickInterval)),!l&&b.tickInterval<o&&(b.tickInterval=o),f||e||l||(b.tickInterval=nb(b.tickInterval,null,mb(b.tickInterval),d)),b.minorTickInterval="auto"===d.minorTickInterval&&b.tickInterval?b.tickInterval/5:d.minorTickInterval,b.tickPositions=a=d.tickPositions?[].concat(d.tickPositions):i&&i.apply(b,[b.min,b.max]),a||(!b.ordinalPositions&&(b.max-b.min)/b.tickInterval>v(2*b.len,200)&&ra(19,!0),a=f?b.getTimeTicks(b.normalizeTimeTickInterval(b.tickInterval,d.units),b.min,b.max,d.startOfWeek,b.ordinalPositions,b.closestPointRange,!0):e?b.getLogTickPositions(b.tickInterval,b.min,b.max):b.getLinearTickPositions(b.tickInterval,b.min,b.max),s&&a.splice(1,a.length-2),b.tickPositions=a),h||(e=a[0],f=a[a.length-1],h=b.minPointOffset||0,d.startOnTick?b.min=e:b.min-h>e&&a.shift(),d.endOnTick?b.max=f:b.max+h<f&&a.pop(),1===a.length&&(d=M(b.max)>1e13?1:.001,b.min-=d,b.max+=d))},setMaxTicks:function(){var a=this.chart,b=a.maxTicks||{},c=this.tickPositions,d=this._maxTicksKey=[this.coll,this.pos,this.len].join("-");!this.isLinked&&!this.isDatetimeAxis&&c&&c.length>(b[d]||0)&&this.options.alignTicks!==!1&&(b[d]=c.length),a.maxTicks=b},adjustTickAmount:function(){var a=this._maxTicksKey,b=this.tickPositions,c=this.chart.maxTicks;if(c&&c[a]&&!this.isDatetimeAxis&&!this.categories&&!this.isLinked&&this.options.alignTicks!==!1&&this.min!==t){var d=this.tickAmount,e=b.length;if(this.tickAmount=a=c[a],a>e){for(;b.length<a;)b.push(da(b[b.length-1]+this.tickInterval));this.transA*=(e-1)/(a-1),this.max=b[b.length-1]}r(d)&&a!==d&&(this.isDirty=!0)}},setScale:function(){var b,c,d,e,a=this.stacks;if(this.oldMin=this.min,this.oldMax=this.max,this.oldAxisLength=this.len,this.setAxisSize(),e=this.len!==this.oldAxisLength,p(this.series,function(a){(a.isDirtyData||a.isDirty||a.xAxis.isDirty)&&(d=!0)}),e||d||this.isLinked||this.forceRedraw||this.userMin!==this.oldUserMin||this.userMax!==this.oldUserMax){if(!this.isXAxis)for(b in a)for(c in a[b])a[b][c].total=null,a[b][c].cum=0;this.forceRedraw=!1,this.getSeriesExtremes(),this.setTickPositions(),this.oldUserMin=this.userMin,this.oldUserMax=this.userMax,this.isDirty||(this.isDirty=e||this.min!==this.oldMin||this.max!==this.oldMax)}else if(!this.isXAxis){this.oldStacks&&(a=this.stacks=this.oldStacks);for(b in a)for(c in a[b])a[b][c].cum=a[b][c].total}this.setMaxTicks()},setExtremes:function(a,b,c,d,e){var f=this,g=f.chart,c=m(c,!0),e=q(e,{min:a,max:b});D(f,"setExtremes",e,function(){f.userMin=a,f.userMax=b,f.eventArgs=e,f.isDirtyExtremes=!0,c&&g.redraw(d)})},zoom:function(a,b){var c=this.dataMin,d=this.dataMax,e=this.options;return this.allowZoomOutside||(r(c)&&a<=C(c,m(e.min,c))&&(a=t),r(d)&&b>=v(d,m(e.max,d))&&(b=t)),this.displayBtn=a!==t||b!==t,this.setExtremes(a,b,!1,t,{trigger:"zoom"}),!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=this.horiz,e=m(b.width,a.plotWidth-c+(b.offsetRight||0)),f=m(b.height,a.plotHeight),g=m(b.top,a.plotTop),b=m(b.left,a.plotLeft+c),c=/%$/;c.test(f)&&(f=parseInt(f,10)/100*a.plotHeight),c.test(g)&&(g=parseInt(g,10)/100*a.plotHeight+a.plotTop),this.left=b,this.top=g,this.width=e,this.height=f,this.bottom=a.chartHeight-f-g,this.right=a.chartWidth-e-b,this.len=v(d?e:f,0),this.pos=d?b:g},getExtremes:function(){var a=this.isLog;return{min:a?da(ia(this.min)):this.min,max:a?da(ia(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?ia(this.min):this.min,b=b?ia(this.max):this.max;return c>a||null===a?a=c:a>b&&(a=b),this.translate(a,0,1,0,1)},autoLabelAlign:function(a){return a=(m(a,0)-90*this.side+720)%360,a>15&&165>a?"right":a>195&&345>a?"left":"center"},getOffset:function(){var j,l,q,y,z,A,B,a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,k=0,o=0,n=d.title,s=d.labels,$=0,J=b.axisOffset,L=b.clipOffset,x=[-1,1,1,-1][h],u=1,w=m(s.maxStaggerLines,5),na=2===h?c.fontMetrics(s.style.fontSize).b:0;if(a.hasData=j=a.hasVisibleSeries||r(a.min)&&r(a.max)&&!!e,a.showAxis=b=j||m(d.showEmpty,!0),a.staggerLines=a.horiz&&s.staggerLines,a.axisGroup||(a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g("axis-labels").attr({zIndex:s.zIndex||7}).addClass("highcharts-"+a.coll.toLowerCase()+"-labels").add()),j||a.isLinked){if(a.labelAlign=m(s.align||a.autoLabelAlign(s.rotation)),p(e,function(b){f[b]?f[b].addLabel():f[b]=new Sa(a,b)}),a.horiz&&!a.staggerLines&&w&&!s.rotation){for(q=a.reversed?[].concat(e).reverse():e;w>u;){for(j=[],y=!1,s=0;s<q.length;s++)z=q[s],A=(A=f[z].label&&f[z].label.getBBox())?A.width:0,B=s%u,A&&(z=a.translate(z),j[B]!==t&&z<j[B]&&(y=!0),j[B]=z+A);if(!y)break;u++}u>1&&(a.staggerLines=u)}p(e,function(b){(0===h||2===h||{1:"left",3:"right"}[h]===a.labelAlign)&&($=v(f[b].getLabelSize(),$))}),a.staggerLines&&($*=a.staggerLines,a.labelOffset=$)}else for(q in f)f[q].destroy(),delete f[q];n&&n.text&&n.enabled!==!1&&(a.axisTitle||(a.axisTitle=c.text(n.text,0,0,n.useHTML).attr({zIndex:7,rotation:n.rotation||0,align:n.textAlign||{low:"left",middle:"center",high:"right"}[n.align]}).addClass("highcharts-"+this.coll.toLowerCase()+"-title").css(n.style).add(a.axisGroup),a.axisTitle.isNew=!0),b&&(k=a.axisTitle.getBBox()[g?"height":"width"],o=m(n.margin,g?5:10),l=n.offset),a.axisTitle[b?"show":"hide"]()),a.offset=x*m(d.offset,J[h]),a.axisTitleMargin=m(l,$+o+($&&x*d.labels[g?"y":"x"]-na)),J[h]=v(J[h],a.axisTitleMargin+k+x*a.offset),L[i]=v(L[i],2*T(d.lineWidth/2))},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d,d=b.chartHeight-this.bottom-(c?this.height:0)+d;return c&&(a*=-1),b.renderer.crispLine(["M",e?this.left:f,e?d:this.top,"L",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=z(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(2===this.side?i:0);
3
- return{x:a?d:b+(g?this.width:0)+h+(e.x||0),y:a?b-(g?this.height:0)+h:d+(e.y||0)}},render:function(){var j,u,z,a=this,b=a.horiz,c=a.reversed,d=a.chart,e=d.renderer,f=a.options,g=a.isLog,h=a.isLinked,i=a.tickPositions,k=a.axisTitle,l=a.ticks,o=a.minorTicks,n=a.alternateBands,s=f.stackLabels,m=f.alternateGridColor,J=a.tickmarkOffset,L=f.lineWidth,x=d.hasRendered&&r(a.oldMin)&&!isNaN(a.oldMin),q=a.hasData,v=a.showAxis,w=f.labels.overflow,y=a.justifyLabels=b&&w!==!1;a.labelEdge.length=0,a.justifyToPlot="justify"===w,p([l,o,n],function(a){for(var b in a)a[b].isActive=!1}),(q||h)&&(a.minorTickInterval&&!a.categories&&p(a.getMinorTickPositions(),function(b){o[b]||(o[b]=new Sa(a,b,"minor")),x&&o[b].isNew&&o[b].render(null,!0),o[b].render(null,!1,1)}),i.length&&(j=i.slice(),(b&&c||!b&&!c)&&j.reverse(),y&&(j=j.slice(1).concat([j[0]])),p(j,function(b,c){y&&(c=c===j.length-1?0:c+1),(!h||b>=a.min&&b<=a.max)&&(l[b]||(l[b]=new Sa(a,b)),x&&l[b].isNew&&l[b].render(c,!0,.1),l[b].render(c,!1,1))}),J&&0===a.min&&(l[-1]||(l[-1]=new Sa(a,-1,null,!0)),l[-1].render(-1))),m&&p(i,function(b,c){c%2===0&&b<a.max&&(n[b]||(n[b]=new R.PlotLineOrBand(a)),u=b+J,z=i[c+1]!==t?i[c+1]+J:a.max,n[b].options={from:g?ia(u):u,to:g?ia(z):z,color:m},n[b].render(),n[b].isActive=!0)}),a._addedPlotLB||(p((f.plotLines||[]).concat(f.plotBands||[]),function(b){a.addPlotBandOrLine(b)}),a._addedPlotLB=!0)),p([l,o,n],function(a){var b,c,e=[],f=va?va.duration||500:0,g=function(){for(c=e.length;c--;)a[e[c]]&&!a[e[c]].isActive&&(a[e[c]].destroy(),delete a[e[c]])};for(b in a)a[b].isActive||(a[b].render(b,!1,0),a[b].isActive=!1,e.push(b));a!==n&&d.hasRendered&&f?f&&setTimeout(g,f):g()}),L&&(b=a.getLinePath(L),a.axisLine?a.axisLine.animate({d:b}):a.axisLine=e.path(b).attr({stroke:f.lineColor,"stroke-width":L,zIndex:7}).add(a.axisGroup),a.axisLine[v?"show":"hide"]()),k&&v&&(k[k.isNew?"attr":"animate"](a.getTitlePosition()),k.isNew=!1),s&&s.enabled&&a.renderStackTotals(),a.isDirty=!1},redraw:function(){var a=this.chart.pointer;a&&a.reset(!0),this.render(),p(this.plotLinesAndBands,function(a){a.render()}),p(this.series,function(a){a.isDirty=!0})},destroy:function(a){var d,b=this,c=b.stacks,e=b.plotLinesAndBands;a||W(b);for(d in c)Oa(c[d]),c[d]=null;for(p([b.ticks,b.minorTicks,b.alternateBands],function(a){Oa(a)}),a=e.length;a--;)e[a].destroy();p("stackTotalGroup,axisLine,axisTitle,axisGroup,cross,gridGroup,labelGroup".split(","),function(a){b[a]&&(b[a]=b[a].destroy())}),this.cross&&this.cross.destroy()},drawCrosshair:function(a,b){if(this.crosshair)if((r(b)||!m(this.crosshair.snap,!0))===!1)this.hideCrosshair();else{var c,d=this.crosshair,e=d.animation;m(d.snap,!0)?r(b)&&(c=this.chart.inverted!=this.horiz?b.plotX:this.len-b.plotY):c=this.horiz?a.chartX-this.pos:this.len-a.chartY+this.pos,c=this.isRadial?this.getPlotLinePath(this.isXAxis?b.x:m(b.stackY,b.y)):this.getPlotLinePath(null,null,null,null,c),null===c?this.hideCrosshair():this.cross?this.cross.attr({visibility:"visible"})[e?"animate":"attr"]({d:c},e):(e={"stroke-width":d.width||1,stroke:d.color||"#C0C0C0",zIndex:d.zIndex||2},d.dashStyle&&(e.dashstyle=d.dashStyle),this.cross=this.chart.renderer.path(c).attr(e).add())}},hideCrosshair:function(){this.cross&&this.cross.hide()}},q(la.prototype,{getPlotBandPath:function(a,b){var c=this.getPlotLinePath(b),d=this.getPlotLinePath(a);return d&&c?d.push(c[4],c[5],c[1],c[2]):d=null,d},addPlotBand:function(a){this.addPlotBandOrLine(a,"plotBands")},addPlotLine:function(a){this.addPlotBandOrLine(a,"plotLines")},addPlotBandOrLine:function(a,b){var c=new R.PlotLineOrBand(this,a).render(),d=this.userOptions;return c&&(b&&(d[b]=d[b]||[],d[b].push(a)),this.plotLinesAndBands.push(c)),c},removePlotBandOrLine:function(a){for(var b=this.plotLinesAndBands,c=this.options,d=this.userOptions,e=b.length;e--;)b[e].id===a&&b[e].destroy();p([c.plotLines||[],d.plotLines||[],c.plotBands||[],d.plotBands||[]],function(b){for(e=b.length;e--;)b[e].id===a&&ja(b,b[e])})}}),la.prototype.getTimeTicks=function(a,b,c,d){var h,e=[],f={},g=E.global.useUTC,i=new Date(b-Ra),j=a.unitRange,k=a.count;if(r(b)){j>=A.second&&(i.setMilliseconds(0),i.setSeconds(j>=A.minute?0:k*T(i.getSeconds()/k))),j>=A.minute&&i[Db](j>=A.hour?0:k*T(i[pb]()/k)),j>=A.hour&&i[Eb](j>=A.day?0:k*T(i[qb]()/k)),j>=A.day&&i[sb](j>=A.month?1:k*T(i[Xa]()/k)),j>=A.month&&(i[Fb](j>=A.year?0:k*T(i[fb]()/k)),h=i[gb]()),j>=A.year&&(h-=h%k,i[Gb](h)),j===A.week&&i[sb](i[Xa]()-i[rb]()+m(d,1)),b=1,Ra&&(i=new Date(i.getTime()+Ra)),h=i[gb]();for(var d=i.getTime(),l=i[fb](),o=i[Xa](),n=g?Ra:(864e5+6e4*i.getTimezoneOffset())%864e5;c>d;)e.push(d),j===A.year?d=eb(h+b*k,0):j===A.month?d=eb(h,l+b*k):g||j!==A.day&&j!==A.week?d+=j*k:d=eb(h,l,o+b*k*(j===A.day?1:7)),b++;e.push(d),p(vb(e,function(a){return j<=A.hour&&a%A.day===n}),function(a){f[a]="day"})}return e.info=q(a,{higherRanks:f,totalRange:j*k}),e},la.prototype.normalizeTimeTickInterval=function(a,b){var g,c=b||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]],d=c[c.length-1],e=A[d[0]],f=d[1];for(g=0;g<c.length&&(d=c[g],e=A[d[0]],f=d[1],!(c[g+1]&&a<=(e*f[f.length-1]+A[c[g+1][0]])/2));g++);return e===A.year&&5*e>a&&(f=[1,2,5]),c=nb(a/e,f,"year"===d[0]?v(mb(a/e),1):1),{unitRange:e,count:c,unitName:d[0]}},la.prototype.getLogTickPositions=function(a,b,c,d){var e=this.options,f=this.len,g=[];if(d||(this._minorAutoInterval=null),a>=.5)a=u(a),g=this.getLinearTickPositions(a,b,c);else if(a>=.08)for(var h,i,j,k,l,f=T(b),e=a>.3?[1,2,4]:a>.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];c+1>f&&!l;f++)for(i=e.length,h=0;i>h&&!l;h++)j=za(ia(f)*e[h]),j>b&&(!d||c>=k)&&g.push(k),k>c&&(l=!0),k=j;else b=ia(b),c=ia(c),a=e[d?"minorTickInterval":"tickInterval"],a=m("auto"===a?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=nb(a,null,mb(a)),g=Ua(this.getLinearTickPositions(a,b,c),za),d||(this._minorAutoInterval=a/5);return d||(this.tickInterval=a),g};var Mb=R.Tooltip=function(){this.init.apply(this,arguments)};Mb.prototype={init:function(a,b){var c=b.borderWidth,d=b.style,e=z(d.padding);this.chart=a,this.options=b,this.crosshairs=[],this.now={x:0,y:0},this.isHidden=!0,this.label=a.renderer.label("",0,0,b.shape||"callout",null,null,b.useHTML,null,"tooltip").attr({padding:e,fill:b.backgroundColor,"stroke-width":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).add().attr({y:-9999}),fa||this.label.shadow(b.shadow),this.shared=b.shared},destroy:function(){this.label&&(this.label=this.label.destroy()),clearTimeout(this.hideTimer),clearTimeout(this.tooltipTimeout)},move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==!1&&!e.isHidden,h=e.followPointer||e.len>1;q(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:h?t:g?(2*f.anchorX+c)/3:c,anchorY:h?t:g?(f.anchorY+d)/2:d}),e.label.attr(f),g&&(M(a-f.x)>1||M(b-f.y)>1)&&(clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32))},hide:function(){var b,a=this;clearTimeout(this.hideTimer),this.isHidden||(b=this.chart.hoverPoints,this.hideTimer=setTimeout(function(){a.label.fadeOut(),a.isHidden=!0},m(this.options.hideDelay,500)),b&&p(b,function(a){a.setState()}),this.chart.hoverPoints=null)},getAnchor:function(a,b){var c,i,d=this.chart,e=d.inverted,f=d.plotTop,g=0,h=0,a=qa(a);return c=a[0].tooltipPos,this.followPointer&&b&&(b.chartX===t&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]),c||(p(a,function(a){i=a.series.yAxis,g+=a.plotX,h+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&i?i.top-f:0)}),g/=a.length,h/=a.length,c=[e?d.plotWidth-h:g,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-g:h]),Ua(c,u)},getPosition:function(a,b,c){var g,d=this.chart,e=this.distance,f={},h=["y",d.chartHeight,b,c.plotY+d.plotTop],i=["x",d.chartWidth,a,c.plotX+d.plotLeft],j=c.ttBelow||d.inverted&&!c.negative||!d.inverted&&c.negative,k=function(a,b,c,d){var g=d-e>c,b=b>d+e+c,c=d-e-c;if(d+=e,j&&b)f[a]=d;else if(!j&&g)f[a]=c;else if(g)f[a]=c;else{if(!b)return!1;f[a]=d}},l=function(a,b,c,d){return e>d||d>b-e?!1:void(f[a]=c/2>d?1:d>b-c/2?b-c-2:d-c/2)},o=function(a){var b=h;h=i,i=b,g=a},n=function(){k.apply(0,h)!==!1?l.apply(0,i)===!1&&!g&&(o(!0),n()):g?f.x=f.y=0:(o(!0),n())};return(d.inverted||this.len>1)&&o(),n(),f},defaultFormatter:function(a){var d,b=this.points||qa(this),c=b[0].series;return d=[a.tooltipHeaderFormatter(b[0])],p(b,function(a){c=a.series,d.push(c.tooltipFormatter&&c.tooltipFormatter(a)||a.point.tooltipFormatter(c.tooltipOptions.pointFormat))}),d.push(a.options.footerFormat||""),d.join("")},refresh:function(a,b){var f,g,i,c=this.chart,d=this.label,e=this.options,h={},j=[];i=e.formatter||this.defaultFormatter;var k,h=c.hoverPoints,l=this.shared;clearTimeout(this.hideTimer),this.followPointer=qa(a)[0].series.tooltipOptions.followPointer,g=this.getAnchor(a,b),f=g[0],g=g[1],!l||a.series&&a.series.noSharedTooltip?h=a.getLabelConfig():(c.hoverPoints=a,h&&p(h,function(a){a.setState()}),p(a,function(a){a.setState("hover"),j.push(a.getLabelConfig())}),h={x:a[0].category,y:a[0].y},h.points=j,this.len=j.length,a=a[0]),i=i.call(h,this),h=a.series,this.distance=m(h.tooltipOptions.distance,16),i===!1?this.hide():(this.isHidden&&(bb(d),d.attr("opacity",1).show()),d.attr({text:i}),k=e.borderColor||a.color||h.color||"#606060",d.attr({stroke:k}),this.updatePosition({plotX:f,plotY:g,negative:a.negative,ttBelow:a.ttBelow}),this.isHidden=!1),D(c,"tooltipRefresh",{text:i,x:f+c.plotLeft,y:g+c.plotTop,borderColor:k})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(u(c.x),u(c.y),a.plotX+b.plotLeft,a.plotY+b.plotTop)},tooltipHeaderFormatter:function(a){var h,b=a.series,c=b.tooltipOptions,d=c.dateTimeLabelFormats,e=c.xDateFormat,f=b.xAxis,g=f&&"datetime"===f.options.type&&ha(a.key),c=c.headerFormat,f=f&&f.closestPointRange;if(g&&!e){if(f){for(h in A)if(A[h]>=f||A[h]<=A.day&&a.key%A[h]>0){e=d[h];break}}else e=d.day;e=e||d.year}return g&&e&&(c=c.replace("{point.key}","{point.key:"+e+"}")),Ia(c,{point:a,series:b})}};var oa;$a=y.documentElement.ontouchstart!==t;var Wa=R.Pointer=function(a,b){this.init(a,b)};if(Wa.prototype={init:function(a,b){var f,c=b.chart,d=c.events,e=fa?"":c.zoomType,c=a.inverted;this.options=b,this.chart=a,this.zoomX=f=/x/.test(e),this.zoomY=e=/y/.test(e),this.zoomHor=f&&!c||e&&c,this.zoomVert=e&&!c||f&&c,this.hasZoom=f||e,this.runChartClick=d&&!!d.click,this.pinchDown=[],this.lastValidTouch={},R.Tooltip&&b.tooltip.enabled&&(a.tooltip=new Mb(a,b.tooltip),this.followTouchMove=b.tooltip.followTouchMove),this.setDOMEvents()},normalize:function(a,b){var c,d,a=a||window.event,a=Sb(a);return a.target||(a.target=a.srcElement),d=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a,b||(this.chartPosition=b=Rb(this.chart.container)),d.pageX===t?(c=v(a.x,a.clientX-b.left),d=a.y):(c=d.pageX-b.left,d=d.pageY-b.top),q(a,{chartX:u(c),chartY:u(d)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};return p(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})}),b},getIndex:function(a){var b=this.chart;return b.inverted?b.plotHeight+b.plotTop-a.chartY:a.chartX-b.plotLeft},runPointActions:function(a){var e,f,i,j,b=this.chart,c=b.series,d=b.tooltip,g=b.hoverPoint,h=b.hoverSeries,k=b.chartWidth,l=this.getIndex(a);if(d&&this.options.tooltip.shared&&(!h||!h.noSharedTooltip)){for(f=[],i=c.length,j=0;i>j;j++)c[j].visible&&c[j].options.enableMouseTracking!==!1&&!c[j].noSharedTooltip&&c[j].singularTooltips!==!0&&c[j].tooltipPoints.length&&(e=c[j].tooltipPoints[l])&&e.series&&(e._dist=M(l-e.clientX),k=C(k,e._dist),f.push(e));for(i=f.length;i--;)f[i]._dist>k&&f.splice(i,1);f.length&&f[0].clientX!==this.hoverX&&(d.refresh(f,a),this.hoverX=f[0].clientX)}c=h&&h.tooltipOptions.followPointer,h&&h.tracker&&!c?(e=h.tooltipPoints[l])&&e!==g&&e.onMouseOver(a):d&&c&&!d.isHidden&&(h=d.getAnchor([{}],a),d.updatePosition({plotX:h[0],plotY:h[1]})),d&&!this._onDocumentMouseMove&&(this._onDocumentMouseMove=function(a){V[oa]&&V[oa].pointer.onDocumentMouseMove(a)},K(y,"mousemove",this._onDocumentMouseMove)),p(b.axes,function(b){b.drawCrosshair(a,m(e,g))})},reset:function(a){var b=this.chart,c=b.hoverSeries,d=b.hoverPoint,e=b.tooltip,f=e&&e.shared?b.hoverPoints:d;(a=a&&e&&f)&&qa(f)[0].plotX===t&&(a=!1),a?(e.refresh(f),d&&d.setState(d.state,!0)):(d&&d.onMouseOut(),c&&c.onMouseOut(),e&&e.hide(),this._onDocumentMouseMove&&(W(y,"mousemove",this._onDocumentMouseMove),this._onDocumentMouseMove=null),p(b.axes,function(a){a.hideCrosshair()}),this.hoverX=null)},scaleGroups:function(a,b){var d,c=this.chart;p(c.series,function(e){d=a||e.getPlotBox(),e.xAxis&&e.xAxis.zoomEnabled&&(e.group.attr(d),e.markerGroup&&(e.markerGroup.attr(d),e.markerGroup.clip(b?c.clipRect:null)),e.dataLabelsGroup&&e.dataLabelsGroup.attr(d))}),c.clipRect.attr(b||c.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type,b.cancelClick=!1,b.mouseDownX=this.mouseDownX=a.chartX,b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var l,b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,f=this.zoomHor,g=this.zoomVert,h=b.plotLeft,i=b.plotTop,j=b.plotWidth,k=b.plotHeight,o=this.mouseDownX,n=this.mouseDownY;h>d?d=h:d>h+j&&(d=h+j),i>e?e=i:e>i+k&&(e=i+k),this.hasDragged=Math.sqrt(Math.pow(o-d,2)+Math.pow(n-e,2)),this.hasDragged>10&&(l=b.isInsidePlot(o-h,n-i),b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&l&&!this.selectionMarker&&(this.selectionMarker=b.renderer.rect(h,i,f?1:j,g?1:k,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add()),this.selectionMarker&&f&&(d-=o,this.selectionMarker.attr({width:M(d),x:(d>0?0:d)+o})),this.selectionMarker&&g&&(d=e-n,this.selectionMarker.attr({height:M(d),y:(d>0?0:d)+n})),l&&!this.selectionMarker&&c.panning&&b.pan(a,c.panning))},drop:function(a){var b=this.chart,c=this.hasPinched;if(this.selectionMarker){var i,d={xAxis:[],yAxis:[],originalEvent:a.originalEvent||a},a=this.selectionMarker,e=a.attr?a.attr("x"):a.x,f=a.attr?a.attr("y"):a.y,g=a.attr?a.attr("width"):a.width,h=a.attr?a.attr("height"):a.height;(this.hasDragged||c)&&(p(b.axes,function(a){if(a.zoomEnabled){var b=a.horiz,c=a.toValue(b?e:f),b=a.toValue(b?e+g:f+h);!isNaN(c)&&!isNaN(b)&&(d[a.coll].push({axis:a,min:C(c,b),max:v(c,b)}),i=!0)}}),i&&D(b,"selection",d,function(a){b.zoom(q(a,c?{animation:!1}:null))})),this.selectionMarker=this.selectionMarker.destroy(),c&&this.scaleGroups()}b&&(G(b.container,{cursor:b._cursor}),b.cancelClick=this.hasDragged>10,b.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[])},onContainerMouseDown:function(a){a=this.normalize(a),a.preventDefault&&a.preventDefault(),this.dragStart(a)},onDocumentMouseUp:function(a){V[oa]&&V[oa].pointer.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,d=b.hoverSeries,a=this.normalize(a,c);c&&d&&!this.inClass(a.target,"highcharts-tracker")&&!b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){var a=V[oa];a&&(a.pointer.reset(),a.pointer.chartPosition=null)},onContainerMouseMove:function(a){var b=this.chart;oa=b.index,a=this.normalize(a),"mousedown"===b.mouseIsDown&&this.drag(a),(this.inClass(a.target,"highcharts-tracker")||b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=H(a,"class")){if(-1!==c.indexOf(b))return!0;if(-1!==c.indexOf("highcharts-container"))return!1}a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries,c=(a=a.relatedTarget||a.toElement)&&a.point&&a.point.series;!b||b.options.stickyTracking||this.inClass(a,"highcharts-tooltip")||c===b||b.onMouseOut()},onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,a=this.normalize(a);a.cancelBubble=!0,b.cancelClick||(c&&this.inClass(a.target,"highcharts-tracker")?(D(c.series,"click",q(a,{point:c})),b.hoverPoint&&c.firePointEvent("click",a)):(q(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&D(b,"click",a)))},setDOMEvents:function(){var a=this,b=a.chart.container;b.onmousedown=function(b){a.onContainerMouseDown(b)},b.onmousemove=function(b){a.onContainerMouseMove(b)},b.onclick=function(b){a.onContainerClick(b)},K(b,"mouseleave",a.onContainerMouseLeave),1===ab&&K(y,"mouseup",a.onDocumentMouseUp),$a&&(b.ontouchstart=function(b){a.onContainerTouchStart(b)},b.ontouchmove=function(b){a.onContainerTouchMove(b)},1===ab&&K(y,"touchend",a.onDocumentTouchEnd))},destroy:function(){var a;W(this.chart.container,"mouseleave",this.onContainerMouseLeave),ab||(W(y,"mouseup",this.onDocumentMouseUp),W(y,"touchend",this.onDocumentTouchEnd)),clearInterval(this.tooltipTimeout);for(a in this)this[a]=null}},q(R.Pointer.prototype,{pinchTranslate:function(a,b,c,d,e,f){(this.zoomHor||this.pinchHor)&&this.pinchTranslateDirection(!0,a,b,c,d,e,f),(this.zoomVert||this.pinchVert)&&this.pinchTranslateDirection(!1,a,b,c,d,e,f)},pinchTranslateDirection:function(a,b,c,d,e,f,g,h){var s,m,y,i=this.chart,j=a?"x":"y",k=a?"X":"Y",l="chart"+k,o=a?"width":"height",n=i["plot"+(a?"Left":"Top")],p=h||1,q=i.inverted,x=i.bounds[a?"h":"v"],r=1===b.length,v=b[0][l],u=c[0][l],t=!r&&b[1][l],w=!r&&c[1][l],c=function(){!r&&M(v-t)>20&&(p=h||M(u-w)/M(v-t)),m=(n-u)/p+v,s=i["plot"+(a?"Width":"Height")]/p};c(),b=m,b<x.min?(b=x.min,y=!0):b+s>x.max&&(b=x.max-s,y=!0),y?(u-=.8*(u-g[j][0]),r||(w-=.8*(w-g[j][1])),c()):g[j]=[u,w],q||(f[j]=m-n,f[o]=s),f=q?1/p:p,e[o]=s,e[j]=b,d[q?a?"scaleY":"scaleX":"scale"+k]=p,d["translate"+k]=f*n+(u-f*v)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,e=b.followTouchMove,f=a.touches,g=f.length,h=b.lastValidTouch,i=b.hasZoom,j=b.selectionMarker,k={},l=1===g&&(b.inClass(a.target,"highcharts-tracker")&&c.runTrackerClick||c.runChartClick),o={};(i||e)&&!l&&a.preventDefault(),Ua(f,function(a){return b.normalize(a)}),"touchstart"===a.type?(p(f,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),h.x=[d[0].chartX,d[1]&&d[1].chartX],h.y=[d[0].chartY,d[1]&&d[1].chartY],p(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"],d=a.minPixelPadding,e=a.toPixels(a.dataMin),f=a.toPixels(a.dataMax),g=C(e,f),e=v(e,f);b.min=C(a.pos,g-d),b.max=v(a.pos+a.len,e+d)}})):d.length&&(j||(b.selectionMarker=j=q({destroy:sa},c.plotBox)),b.pinchTranslate(d,f,k,j,o,h),b.hasPinched=i,b.scaleGroups(k,o),!i&&e&&1===g&&this.runPointActions(b.normalize(a)))},onContainerTouchStart:function(a){var b=this.chart;oa=b.index,1===a.touches.length?(a=this.normalize(a),b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)?(this.runPointActions(a),this.pinch(a)):this.reset()):2===a.touches.length&&this.pinch(a)},onContainerTouchMove:function(a){(1===a.touches.length||2===a.touches.length)&&this.pinch(a)},onDocumentTouchEnd:function(a){V[oa]&&V[oa].pointer.drop(a)}}),I.PointerEvent||I.MSPointerEvent){var ua={},zb=!!I.PointerEvent,Wb=function(){var a,b=[];b.item=function(a){return this[a]};for(a in ua)ua.hasOwnProperty(a)&&b.push({pageX:ua[a].pageX,pageY:ua[a].pageY,target:ua[a].target});return b},Ab=function(a,b,c,d){a=a.originalEvent||a,"touch"!==a.pointerType&&a.pointerType!==a.MSPOINTER_TYPE_TOUCH||!V[oa]||(d(a),d=V[oa].pointer,d[b]({type:c,target:a.currentTarget,preventDefault:sa,touches:Wb()}))};q(Wa.prototype,{onContainerPointerDown:function(a){Ab(a,"onContainerTouchStart","touchstart",function(a){ua[a.pointerId]={pageX:a.pageX,pageY:a.pageY,target:a.currentTarget}})},onContainerPointerMove:function(a){Ab(a,"onContainerTouchMove","touchmove",function(a){ua[a.pointerId]={pageX:a.pageX,pageY:a.pageY},ua[a.pointerId].target||(ua[a.pointerId].target=a.currentTarget)})},onDocumentPointerUp:function(a){Ab(a,"onContainerTouchEnd","touchend",function(a){delete ua[a.pointerId]})},batchMSEvents:function(a){a(this.chart.container,zb?"pointerdown":"MSPointerDown",this.onContainerPointerDown),a(this.chart.container,zb?"pointermove":"MSPointerMove",this.onContainerPointerMove),a(y,zb?"pointerup":"MSPointerUp",this.onDocumentPointerUp)}}),Ma(Wa.prototype,"init",function(a,b,c){a.call(this,b,c),(this.hasZoom||this.followTouchMove)&&G(b.container,{"-ms-touch-action":Q,"touch-action":Q})}),Ma(Wa.prototype,"setDOMEvents",function(a){a.apply(this),(this.hasZoom||this.followTouchMove)&&this.batchMSEvents(K)}),Ma(Wa.prototype,"destroy",function(a){this.batchMSEvents(W),a.call(this)})}var lb=R.Legend=function(a,b){this.init(a,b)};lb.prototype={init:function(a,b){var c=this,d=b.itemStyle,e=m(b.padding,8),f=b.itemMarginTop||0;this.options=b,b.enabled&&(c.baseline=z(d.fontSize)+3+f,c.itemStyle=d,c.itemHiddenStyle=w(d,b.itemHiddenStyle),c.itemMarginTop=f,c.padding=e,c.initialItemX=e,c.initialItemY=e-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.lastLineHeight=0,c.symbolWidth=m(b.symbolWidth,16),c.pages=[],c.render(),K(c.chart,"endResize",function(){c.positionCheckboxes()}))},colorizeItem:function(a,b){var j,c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:g,h=b?a.legendColor||a.color||"#CCC":g,g=a.options&&a.options.marker,i={fill:h};if(d&&d.css({fill:c,color:c}),e&&e.attr({stroke:h}),f){if(g&&f.isMarker)for(j in i.stroke=h,g=a.convertAttribs(g))d=g[j],d!==t&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth-e-2*c-4,d),f&&(f.x=e,f.y=d)},destroyItem:function(a){var b=a.checkbox;p(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())}),b&&Pa(a.checkbox)},destroy:function(){var a=this.group,b=this.box;b&&(this.box=b.destroy()),a&&(this.group=a.destroy())},positionCheckboxes:function(a){var c,b=this.group.alignAttr,d=this.clipHeight||this.legendHeight;b&&(c=b.translateY,p(this.allItems,function(e){var g,f=e.checkbox;f&&(g=c+f.y+(a||0)+3,G(f,{left:b.translateX+e.checkboxOffset+f.x-20+"px",top:g+"px",display:g>c-6&&c+d-6>g?"":Q}))}))},renderTitle:function(){var a=this.padding,b=this.options.title,c=0;b.text&&(this.title||(this.title=this.chart.renderer.label(b.text,a-3,a-4,null,null,null,null,null,"legend-title").attr({zIndex:1}).css(b.style).add(this.group)),a=this.title.getBBox(),c=a.height,this.offsetWidth=a.width,this.contentGroup.attr({translateY:c})),this.titleHeight=c},renderItem:function(a){var b=this.chart,c=b.renderer,d=this.options,e="horizontal"===d.layout,f=this.symbolWidth,g=d.symbolPadding,h=this.itemStyle,i=this.itemHiddenStyle,j=this.padding,k=e?m(d.itemDistance,20):0,l=!d.rtl,o=d.width,n=d.itemMarginBottom||0,s=this.itemMarginTop,p=this.initialItemX,q=a.legendItem,r=a.series&&a.series.drawLegendSymbol?a.series:a,x=r.options,x=this.createCheckboxForItem&&x&&x.showCheckbox,t=d.useHTML;q||(a.legendGroup=c.g("legend-item").attr({zIndex:1}).add(this.scrollGroup),r.drawLegendSymbol(this,a),a.legendItem=q=c.text(d.labelFormat?Ia(d.labelFormat,a):d.labelFormatter.call(a),l?f+g:-g,this.baseline,t).css(w(a.visible?h:i)).attr({align:l?"left":"right",zIndex:2}).add(a.legendGroup),this.setItemEvents&&this.setItemEvents(a,q,t,h,i),this.colorizeItem(a,a.visible),x&&this.createCheckboxForItem(a)),c=q.getBBox(),f=a.checkboxOffset=d.itemWidth||a.legendItemWidth||f+g+c.width+k+(x?20:0),this.itemHeight=g=u(a.legendItemHeight||c.height),e&&this.itemX-p+f>(o||b.chartWidth-2*j-p-d.x)&&(this.itemX=p,this.itemY+=s+this.lastLineHeight+n,this.lastLineHeight=0),this.maxItemWidth=v(this.maxItemWidth,f),this.lastItemY=s+this.itemY+n,this.lastLineHeight=v(g,this.lastLineHeight),a._legendItemPos=[this.itemX,this.itemY],e?this.itemX+=f:(this.itemY+=s+g+n,this.lastLineHeight=g),this.offsetWidth=o||v((e?this.itemX-p-k:f)+j,this.offsetWidth)},getAllItems:function(){var a=[];return p(this.chart.series,function(b){var c=b.options;m(c.showInLegend,r(c.linkedTo)?!1:t,!0)&&(a=a.concat(b.legendItems||("point"===c.legendType?b.data:b)))}),a},render:function(){var e,f,g,h,a=this,b=a.chart,c=b.renderer,d=a.group,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,o=j.backgroundColor;a.itemX=a.initialItemX,a.itemY=a.initialItemY,a.offsetWidth=0,a.lastItemY=0,d||(a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup)),a.renderTitle(),e=a.getAllItems(),ob(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)}),j.reversed&&e.reverse(),a.allItems=e,a.display=f=!!e.length,p(e,function(b){a.renderItem(b)}),g=j.width||a.offsetWidth,h=a.lastItemY+a.lastLineHeight+a.titleHeight,h=a.handleOverflow(h),(l||o)&&(g+=k,h+=k,i?g>0&&h>0&&(i[i.isNew?"attr":"animate"](i.crisp({width:g,height:h})),i.isNew=!1):(a.box=i=c.rect(0,0,g,h,j.borderRadius,l||0).attr({stroke:j.borderColor,"stroke-width":l||0,fill:o||Q}).add(d).shadow(j.shadow),i.isNew=!0),i[f?"show":"hide"]()),a.legendWidth=g,a.legendHeight=h,p(e,function(b){a.positionItem(b)}),f&&d.align(q({width:g,height:h},j),!0,"spacingBox"),b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var h,s,b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+("top"===e.verticalAlign?-f:f)-this.padding,g=e.maxHeight,i=this.clipRect,j=e.navigation,k=m(j.animation,!0),l=j.arrowSize||12,o=this.nav,n=this.pages,q=this.allItems;return"horizontal"===e.layout&&(f/=2),g&&(f=C(f,g)),n.length=0,a>f&&!e.useHTML?(this.clipHeight=h=f-20-this.titleHeight-this.padding,this.currentPage=m(this.currentPage,1),this.fullHeight=a,p(q,function(a,b){var c=a._legendItemPos[1],d=u(a.legendItem.getBBox().height),e=n.length;(!e||c-n[e-1]>h&&(s||c)!==n[e-1])&&(n.push(s||c),e++),b===q.length-1&&c+d-n[e-1]>h&&n.push(c),c!==s&&(s=c)}),i||(i=b.clipRect=d.clipRect(0,this.padding,9999,0),b.contentGroup.clip(i)),i.attr({height:h}),o||(this.nav=o=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,l,l).on("click",function(){b.scroll(-1,k)}).add(o),this.pager=d.text("",15,10).css(j.style).add(o),this.down=d.symbol("triangle-down",0,0,l,l).on("click",function(){b.scroll(1,k)}).add(o)),b.scroll(0),a=f):o&&(i.attr({height:c.chartHeight}),o.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0),a},scroll:function(a,b){var c=this.pages,d=c.length,e=this.currentPage+a,f=this.clipHeight,g=this.options.navigation,h=g.activeColor,g=g.inactiveColor,i=this.pager,j=this.padding;e>d&&(e=d),e>0&&(b!==t&&Qa(b,this.chart),this.nav.attr({translateX:j,translateY:f+this.padding+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:1===e?g:h}).css({cursor:1===e?"default":"pointer"}),i.attr({text:e+"/"+d}),this.down.attr({x:18+this.pager.getBBox().width,fill:e===d?g:h}).css({cursor:e===d?"default":"pointer"}),c=-c[e-1]+this.initialItemY,this.scrollGroup.animate({translateY:c}),this.currentPage=e,this.positionCheckboxes(c))}},N=R.LegendSymbolMixin={drawRectangle:function(a,b){var c=a.options.symbolHeight||12;b.legendSymbol=this.chart.renderer.rect(0,a.baseline-5-c/2,a.symbolWidth,c,a.options.symbolRadius||0).attr({zIndex:3}).add(b.legendGroup)},drawLineMarker:function(a){var d,b=this.options,c=b.marker;d=a.symbolWidth;var g,e=this.chart.renderer,f=this.legendGroup,a=a.baseline-u(.3*e.fontMetrics(a.options.itemStyle.fontSize).b);b.lineWidth&&(g={"stroke-width":b.lineWidth},b.dashStyle&&(g.dashstyle=b.dashStyle),this.legendLine=e.path(["M",0,a,"L",d,a]).attr(g).add(f)),c&&c.enabled!==!1&&(b=c.radius,this.legendSymbol=d=e.symbol(this.symbol,d/2-b,a-b,2*b,2*b).add(f),d.isMarker=!0)}},(/Trident\/7\.0/.test(wa)||Ta)&&Ma(lb.prototype,"positionItem",function(a,b){var c=this,d=function(){b._legendItemPos&&a.call(c,b)};d(),setTimeout(d)}),Ya.prototype={init:function(a,b){var c,d=a.series;a.series=null,c=w(E,a),c.series=a.series=d,this.userOptions=a,d=c.chart,this.margin=this.splashArray("margin",d),this.spacing=this.splashArray("spacing",d);var e=d.events;this.bounds={h:{},v:{}},this.callback=b,this.isResizing=0,this.options=c,this.axes=[],this.series=[],this.hasCartesianSeries=d.showAxes;var g,f=this;if(f.index=V.length,V.push(f),ab++,d.reflow!==!1&&K(f,"load",function(){f.initReflow()}),e)for(g in e)K(f,g,e[g]);f.xAxis=[],f.yAxis=[],f.animation=fa?!1:m(d.animation,!0),f.pointCount=0,f.counters=new Bb,f.firstRender()},initSeries:function(a){var b=this.options.chart;return(b=F[a.type||b.type||b.defaultSeriesType])||ra(17,!0),b=new b,b.init(this,a),b},isInsidePlot:function(a,b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},adjustTickAmounts:function(){this.options.chart.alignTicks!==!1&&p(this.axes,function(a){a.adjustTickAmount()}),this.maxTicks=null},redraw:function(a){var g,h,b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,i=this.isDirtyBox,j=c.length,k=j,l=this.renderer,o=l.isHidden(),n=[];for(Qa(a,this),o&&this.cloneRenderTo(),this.layOutTitles();k--;)if(a=c[k],a.options.stacking&&(g=!0,a.isDirty)){h=!0;break}if(h)for(k=j;k--;)a=c[k],a.options.stacking&&(a.isDirty=!0);p(c,function(a){a.isDirty&&"point"===a.options.legendType&&(f=!0)}),f&&e.options.enabled&&(e.render(),this.isDirtyLegend=!1),g&&this.getStacks(),this.hasCartesianSeries&&(this.isResizing||(this.maxTicks=null,p(b,function(a){a.setScale()})),this.adjustTickAmounts(),this.getMargins(),p(b,function(a){a.isDirty&&(i=!0)}),p(b,function(a){a.isDirtyExtremes&&(a.isDirtyExtremes=!1,n.push(function(){D(a,"afterSetExtremes",q(a.eventArgs,a.getExtremes())),delete a.eventArgs})),(i||g)&&a.redraw()})),i&&this.drawChartBox(),p(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()}),d&&d.reset(!0),l.draw(),D(this,"redraw"),o&&this.cloneRenderTo(!0),p(n,function(a){a.call()})},get:function(a){var d,e,b=this.axes,c=this.series;for(d=0;d<b.length;d++)if(b[d].options.id===a)return b[d];for(d=0;d<c.length;d++)if(c[d].options.id===a)return c[d];for(d=0;d<c.length;d++)for(e=c[d].points||[],b=0;b<e.length;b++)if(e[b].id===a)return e[b];return null},getAxes:function(){var a=this,b=this.options,c=b.xAxis=qa(b.xAxis||{}),b=b.yAxis=qa(b.yAxis||{});p(c,function(a,b){a.index=b,a.isX=!0}),p(b,function(a,b){a.index=b}),c=c.concat(b),p(c,function(b){new la(a,b)}),a.adjustTickAmounts()},getSelectedPoints:function(){var a=[];return p(this.series,function(b){a=a.concat(vb(b.points||[],function(a){return a.selected}))}),a},getSelectedSeries:function(){return vb(this.series,function(a){return a.selected})},getStacks:function(){var a=this;p(a.yAxis,function(a){a.stacks&&a.hasVisibleSeries&&(a.oldStacks=a.stacks)}),p(a.series,function(b){!b.options.stacking||b.visible!==!0&&a.options.chart.ignoreHiddenSeries!==!1||(b.stackKey=b.type+m(b.options.stack,""))})},setTitle:function(a,b,c){var g,f,d=this,e=d.options;f=e.title=w(e.title,a),g=e.subtitle=w(e.subtitle,b),e=g,p([["title",a,f],["subtitle",b,e]],function(a){var b=a[0],c=d[b],e=a[1],a=a[2];c&&e&&(d[b]=c=c.destroy()),a&&a.text&&!c&&(d[b]=d.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":"highcharts-"+b,zIndex:a.zIndex||4}).css(a.style).add())}),d.layOutTitles(c)},layOutTitles:function(a){var b=0,c=this.title,d=this.subtitle,e=this.options,f=e.title,e=e.subtitle,g=this.spacingBox.width-44;!c||(c.css({width:(f.width||g)+"px"}).align(q({y:15},f),!1,"spacingBox"),f.floating||f.verticalAlign)||(b=c.getBBox().height),d&&(d.css({width:(e.width||g)+"px"}).align(q({y:b+f.margin},e),!1,"spacingBox"),!e.floating&&!e.verticalAlign&&(b=Ka(b+d.getBBox().height))),c=this.titleOffset!==b,this.titleOffset=b,!this.isDirtyBox&&c&&(this.isDirtyBox=c,this.hasRendered&&m(a,!0)&&this.isDirtyBox&&this.redraw())},getChartSize:function(){var a=this.options.chart,b=a.width,a=a.height,c=this.renderToClone||this.renderTo;r(b)||(this.containerWidth=jb(c,"width")),r(a)||(this.containerHeight=jb(c,"height")),this.chartWidth=v(0,b||this.containerWidth||600),this.chartHeight=v(0,m(a,this.containerHeight>19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Pa(b),delete this.renderToClone):(c&&c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),G(b,{position:"absolute",top:"-9999px",display:"block"}),b.style.setProperty&&b.style.setProperty("display","block","important"),y.body.appendChild(b),c&&b.appendChild(c))
4
- },getContainer:function(){var a,c,d,e,b=this.options.chart;this.renderTo=a=b.renderTo,e="highcharts-"+tb++,Fa(a)&&(this.renderTo=a=y.getElementById(a)),a||ra(13,!0),c=z(H(a,"data-highcharts-chart")),!isNaN(c)&&V[c]&&V[c].hasRendered&&V[c].destroy(),H(a,"data-highcharts-chart",this.index),a.innerHTML="",!b.skipClone&&!a.offsetWidth&&this.cloneRenderTo(),this.getChartSize(),c=this.chartWidth,d=this.chartHeight,this.container=a=Y(Ja,{className:"highcharts-container"+(b.className?" "+b.className:""),id:e},q({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},b.style),this.renderToClone||a),this._cursor=a.style.cursor,this.renderer=b.forExport?new ta(a,c,d,b.style,!0):new Za(a,c,d,b.style),fa&&this.renderer.create(this,a,c,d)},getMargins:function(){var b,a=this.spacing,c=this.legend,d=this.margin,e=this.options.legend,f=m(e.margin,20),g=e.x,h=e.y,i=e.align,j=e.verticalAlign,k=this.titleOffset;this.resetMargins(),b=this.axisOffset,k&&!r(d[0])&&(this.plotTop=v(this.plotTop,k+this.options.title.margin+a[0])),c.display&&!e.floating&&("right"===i?r(d[1])||(this.marginRight=v(this.marginRight,c.legendWidth-g+f+a[1])):"left"===i?r(d[3])||(this.plotLeft=v(this.plotLeft,c.legendWidth+g+f+a[3])):"top"===j?r(d[0])||(this.plotTop=v(this.plotTop,c.legendHeight+h+f+a[0])):"bottom"!==j||r(d[2])||(this.marginBottom=v(this.marginBottom,c.legendHeight-h+f+a[2]))),this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin),this.extraTopMargin&&(this.plotTop+=this.extraTopMargin),this.hasCartesianSeries&&p(this.axes,function(a){a.getOffset()}),r(d[3])||(this.plotLeft+=b[3]),r(d[0])||(this.plotTop+=b[0]),r(d[2])||(this.marginBottom+=b[2]),r(d[1])||(this.marginRight+=b[1]),this.setChartSize()},reflow:function(a){var b=this,c=b.options.chart,d=b.renderTo,e=c.width||jb(d,"width"),f=c.height||jb(d,"height"),c=a?a.target:I,d=function(){b.container&&(b.setSize(e,f,!1),b.hasUserSize=null)};b.hasUserSize||!e||!f||c!==I&&c!==y||((e!==b.containerWidth||f!==b.containerHeight)&&(clearTimeout(b.reflowTimeout),a?b.reflowTimeout=setTimeout(d,100):d()),b.containerWidth=e,b.containerHeight=f)},initReflow:function(){var a=this,b=function(b){a.reflow(b)};K(I,"resize",b),K(a,"destroy",function(){W(I,"resize",b)})},setSize:function(a,b,c){var e,f,g,d=this;d.isResizing+=1,g=function(){d&&D(d,"endResize",null,function(){d.isResizing-=1})},Qa(c,d),d.oldChartHeight=d.chartHeight,d.oldChartWidth=d.chartWidth,r(a)&&(d.chartWidth=e=v(0,u(a)),d.hasUserSize=!!e),r(b)&&(d.chartHeight=f=v(0,u(b))),(va?kb:G)(d.container,{width:e+"px",height:f+"px"},va),d.setChartSize(!0),d.renderer.setSize(e,f,c),d.maxTicks=null,p(d.axes,function(a){a.isDirty=!0,a.setScale()}),p(d.series,function(a){a.isDirty=!0}),d.isDirtyLegend=!0,d.isDirtyBox=!0,d.layOutTitles(),d.getMargins(),d.redraw(c),d.oldChartHeight=null,D(d,"resize"),va===!1?g():setTimeout(g,va&&va.duration||500)},setChartSize:function(a){var i,j,k,l,b=this.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=this.spacing,h=this.clipOffset;this.plotLeft=i=u(this.plotLeft),this.plotTop=j=u(this.plotTop),this.plotWidth=k=v(0,u(d-i-this.marginRight)),this.plotHeight=l=v(0,u(e-j-this.marginBottom)),this.plotSizeX=b?l:k,this.plotSizeY=b?k:l,this.plotBorderWidth=f.plotBorderWidth||0,this.spacingBox=c.spacingBox={x:g[3],y:g[0],width:d-g[3]-g[1],height:e-g[0]-g[2]},this.plotBox=c.plotBox={x:i,y:j,width:k,height:l},d=2*T(this.plotBorderWidth/2),b=Ka(v(d,h[3])/2),c=Ka(v(d,h[0])/2),this.clipBox={x:b,y:c,width:T(this.plotSizeX-v(d,h[1])/2-b),height:T(this.plotSizeY-v(d,h[2])/2-c)},a||p(this.axes,function(a){a.setAxisSize(),a.setAxisTranslation()})},resetMargins:function(){var a=this.spacing,b=this.margin;this.plotTop=m(b[0],a[0]),this.marginRight=m(b[1],a[1]),this.marginBottom=m(b[2],a[2]),this.plotLeft=m(b[3],a[3]),this.axisOffset=[0,0,0,0],this.clipOffset=[0,0,0,0]},drawChartBox:function(){var n,a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,o=a.plotBorderWidth||0,s=this.plotLeft,m=this.plotTop,p=this.plotWidth,q=this.plotHeight,r=this.plotBox,v=this.clipRect,u=this.clipBox;n=i+(a.shadow?8:0),(i||j)&&(e?e.animate(e.crisp({width:c-n,height:d-n})):(e={fill:j||Q},i&&(e.stroke=a.borderColor,e["stroke-width"]=i),this.chartBackground=b.rect(n/2,n/2,c-n,d-n,a.borderRadius,i).attr(e).addClass("highcharts-background").add().shadow(a.shadow))),k&&(f?f.animate(r):this.plotBackground=b.rect(s,m,p,q,0).attr({fill:k}).add().shadow(a.plotShadow)),l&&(h?h.animate(r):this.plotBGImage=b.image(l,s,m,p,q).add()),v?v.animate({width:u.width,height:u.height}):this.clipRect=b.clipRect(u),o&&(g?g.animate(g.crisp({x:s,y:m,width:p,height:q})):this.plotBorder=b.rect(s,m,p,q,0,-o).attr({stroke:a.plotBorderColor,"stroke-width":o,fill:Q,zIndex:1}).add()),this.isDirtyBox=!1},propFromSeries:function(){var c,e,f,a=this,b=a.options.chart,d=a.options.series;p(["inverted","angular","polar"],function(g){for(c=F[b.type||b.defaultSeriesType],f=a[g]||b[g]||c&&c.prototype[g],e=d&&d.length;!f&&e--;)(c=F[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},linkSeries:function(){var a=this,b=a.series;p(b,function(a){a.linkedSeries.length=0}),p(b,function(b){var d=b.options.linkedTo;Fa(d)&&(d=":previous"===d?a.series[b.index-1]:a.get(d))&&(d.linkedSeries.push(b),b.linkedParent=d)})},renderSeries:function(){p(this.series,function(a){a.translate(),a.setTooltipPoints&&a.setTooltipPoints(),a.render()})},render:function(){var g,a=this,b=a.axes,c=a.renderer,d=a.options,e=d.labels,f=d.credits;a.setTitle(),a.legend=new lb(a,d.legend),a.getStacks(),p(b,function(a){a.setScale()}),a.getMargins(),a.maxTicks=null,p(b,function(a){a.setTickPositions(!0),a.setMaxTicks()}),a.adjustTickAmounts(),a.getMargins(),a.drawChartBox(),a.hasCartesianSeries&&p(b,function(a){a.render()}),a.seriesGroup||(a.seriesGroup=c.g("series-group").attr({zIndex:3}).add()),a.renderSeries(),e.items&&p(e.items,function(b){var d=q(e.style,b.style),f=z(d.left)+a.plotLeft,g=z(d.top)+a.plotTop+12;delete d.left,delete d.top,c.text(b.html,f,g).attr({zIndex:2}).css(d).add()}),f.enabled&&!a.credits&&(g=f.href,a.credits=c.text(f.text,0,0).on("click",function(){g&&(location.href=g)}).attr({align:f.position.align,zIndex:8}).css(f.style).add().align(f.position)),a.hasRendered=!0},destroy:function(){var e,a=this,b=a.axes,c=a.series,d=a.container,f=d&&d.parentNode;for(D(a,"destroy"),V[a.index]=t,ab--,a.renderTo.removeAttribute("data-highcharts-chart"),W(a),e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();p("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())}),d&&(d.innerHTML="",W(d),f&&Pa(d));for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!aa&&I==I.top&&"complete"!==y.readyState||fa&&!I.canvg?(fa?Lb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):y.attachEvent("onreadystatechange",function(){y.detachEvent("onreadystatechange",a.firstRender),"complete"===y.readyState&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;a.isReadyToRender()&&(a.getContainer(),D(a,"init"),a.resetMargins(),a.setChartSize(),a.propFromSeries(),a.getAxes(),p(b.series||[],function(b){a.initSeries(b)}),a.linkSeries(),D(a,"beforeRender"),R.Pointer&&(a.pointer=new Wa(a,b)),a.render(),a.renderer.draw(),c&&c.apply(a,[a]),p(a.callbacks,function(b){b.apply(a,[a])}),a.cloneRenderTo(!0),D(a,"load"))},splashArray:function(a,b){var c=b[a],c=ca(c)?c:[c,c,c,c];return[m(b[a+"Top"],c[0]),m(b[a+"Right"],c[1]),m(b[a+"Bottom"],c[2]),m(b[a+"Left"],c[3])]}},Ya.prototype.callbacks=[],X=R.CenteredSeriesMixin={getCenter:function(){var d,h,a=this.options,b=this.chart,c=2*(a.slicedOffset||0),e=b.plotWidth-2*c,f=b.plotHeight-2*c,b=a.center,a=[m(b[0],"50%"),m(b[1],"50%"),a.size||"100%",a.innerSize||0],g=C(e,f);return Ua(a,function(a,b){return h=/%$/.test(a),d=2>b||2===b&&h,(h?[e,f,g,g][b]*z(a)/100:a)+(d?c:0)})}};var Ea=function(){};Ea.prototype={init:function(a,b,c){return this.series=a,this.applyOptions(b,c),this.pointAttr={},a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++],a.colorCounter===b.length)&&(a.colorCounter=0),a.chart.pointCount++,this},applyOptions:function(a,b){var c=this.series,d=c.pointValKey,a=Ea.prototype.optionsToObject.call(this,a);return q(this,a),this.options=this.options?q(this.options,a):a,d&&(this.y=this[d]),this.x===t&&c&&(this.x=b===t?c.autoIncrement():b),this},optionsToObject:function(a){var b={},c=this.series,d=c.pointArrayMap||["y"],e=d.length,f=0,g=0;if("number"==typeof a||null===a)b[d[0]]=a;else if(La(a))for(a.length>e&&(c=typeof a[0],"string"===c?b.name=a[0]:"number"===c&&(b.x=a[0]),f++);e>g;)b[d[g++]]=a[f++];else"object"==typeof a&&(b=a,a.dataLabels&&(c._hasPointLabels=!0),a.marker&&(c._hasPointMarkers=!0));return b},destroy:function(){var c,a=this.series.chart,b=a.hoverPoints;a.pointCount--,b&&(this.setState(),ja(b,this),!b.length)&&(a.hoverPoints=null),this===a.hoverPoint&&this.onMouseOut(),(this.graphic||this.dataLabel)&&(W(this),this.destroyElements()),this.legendItem&&a.legend.destroyItem(this);for(c in this)this[c]=null},destroyElements:function(){for(var b,a="graphic,dataLabel,dataLabelUpper,group,connector,shadowGroup".split(","),c=6;c--;)b=a[c],this[b]&&(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}},tooltipFormatter:function(a){var b=this.series,c=b.tooltipOptions,d=m(c.valueDecimals,""),e=c.valuePrefix||"",f=c.valueSuffix||"";return p(b.pointArrayMap||["y"],function(b){b="{point."+b,(e||f)&&(a=a.replace(b+"}",e+b+"}"+f)),a=a.replace(b+"}",b+":,."+d+"f}")}),Ia(a,{point:this,series:this.series})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents(),"click"===a&&e.allowPointSelect&&(c=function(a){d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)}),D(this,a,b,c)}};var O=function(){};O.prototype={isCartesian:!0,type:"line",pointClass:Ea,sorted:!0,requireSorting:!0,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],init:function(a,b){var d,e,c=this,f=a.series,g=function(a,b){return m(a.options.index,a._i)-m(b.options.index,b._i)};c.chart=a,c.options=b=c.setOptions(b),c.linkedSeries=[],c.bindAxes(),q(c,{name:b.name,state:"",pointAttr:{},visible:b.visible!==!1,selected:b.selected===!0}),fa&&(b.animation=!1),e=b.events;for(d in e)K(c,d,e[d]);(e&&e.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)&&(a.runTrackerClick=!0),c.getColor(),c.getSymbol(),p(c.parallelArrays,function(a){c[a+"Data"]=[]}),c.setData(b.data,!1),c.isCartesian&&(a.hasCartesianSeries=!0),f.push(c),c._i=f.length-1,ob(f,g),this.yAxis&&ob(this.yAxis.series,g),p(f,function(a,b){a.index=b,a.name=a.name||"Series "+(b+1)})},bindAxes:function(){var d,a=this,b=a.options,c=a.chart;p(a.axisTypes||[],function(e){p(c[e],function(c){d=c.options,(b[e]===d.index||b[e]!==t&&b[e]===d.id||b[e]===t&&0===d.index)&&(c.series.push(a),a[e]=c,c.isDirty=!0)}),!a[e]&&a.optionalAxis!==e&&ra(18,!0)})},updateParallelArrays:function(a,b){var c=a.series,d=arguments;p(c.parallelArrays,"number"==typeof b?function(d){var f="y"===d&&c.toYData?c.toYData(a):a[d];c[d+"Data"][b]=f}:function(a){Array.prototype[b].apply(c[a+"Data"],Array.prototype.slice.call(d,2))})},autoIncrement:function(){var a=this.options,b=this.xIncrement,b=m(b,a.pointStart,0);return this.pointInterval=m(this.pointInterval,a.pointInterval,1),this.xIncrement=b+this.pointInterval,b},getSegments:function(){var c,a=-1,b=[],d=this.points,e=d.length;if(e)if(this.options.connectNulls){for(c=e;c--;)null===d[c].y&&d.splice(c,1);d.length&&(b=[d])}else p(d,function(c,g){null===c.y?(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,c=b.options.plotOptions,b=b.userOptions||{},d=b.plotOptions||{},e=c[this.type];return this.userOptions=a,c=w(e,c.series,a),this.tooltipOptions=w(E.tooltip,E.plotOptions[this.type].tooltip,b.tooltip,d.series&&d.series.tooltip,d[this.type]&&d[this.type].tooltip,a.tooltip),null===e.marker&&delete c.marker,c},getColor:function(){var e,a=this.options,b=this.userOptions,c=this.chart.options.colors,d=this.chart.counters;e=a.color||ba[this.type].color,e||a.colorByPoint||(r(b._colorIndex)?a=b._colorIndex:(b._colorIndex=d.color,a=d.color++),e=c[a]),this.color=e,d.wrapColor(c.length)},getSymbol:function(){var a=this.userOptions,b=this.options.marker,c=this.chart,d=c.options.symbols,c=c.counters;this.symbol=b.symbol,this.symbol||(r(a._symbolIndex)?a=a._symbolIndex:(a._symbolIndex=c.symbol,a=c.symbol++),this.symbol=d[a]),/^url/.test(this.symbol)&&(b.radius=0),c.wrapSymbol(d.length)},drawLegendSymbol:N.drawLineMarker,setData:function(a,b,c,d){var h,e=this,f=e.points,g=f&&f.length||0,i=e.options,j=e.chart,k=null,l=e.xAxis,o=l&&!!l.categories,n=e.tooltipPoints,s=i.turboThreshold,q=this.xData,r=this.yData,v=(h=e.pointArrayMap)&&h.length,a=a||[];if(h=a.length,b=m(b,!0),d===!1||!h||g!==h||e.cropped||e.hasGroupedData){if(e.xIncrement=null,e.pointRange=o?1:i.pointRange,e.colorCounter=0,p(this.parallelArrays,function(a){e[a+"Data"].length=0}),s&&h>s){for(c=0;null===k&&h>c;)k=a[c],c++;if(ha(k)){for(o=m(i.pointStart,0),i=m(i.pointInterval,1),c=0;h>c;c++)q[c]=o,r[c]=a[c],o+=i;e.xIncrement=o}else if(La(k))if(v)for(c=0;h>c;c++)i=a[c],q[c]=i[0],r[c]=i.slice(1,v+1);else for(c=0;h>c;c++)i=a[c],q[c]=i[0],r[c]=i[1];else ra(12)}else for(c=0;h>c;c++)a[c]!==t&&(i={series:e},e.pointClass.prototype.applyOptions.apply(i,[a[c]]),e.updateParallelArrays(i,c),o&&i.name)&&(l.names[i.x]=i.name);for(Fa(r[0])&&ra(14,!0),e.data=[],e.options.data=a,c=g;c--;)f[c]&&f[c].destroy&&f[c].destroy();n&&(n.length=0),l&&(l.minRange=l.userMinRange),e.isDirty=e.isDirtyData=j.isDirtyBox=!0,c=!1}else p(a,function(a,b){f[b].update(a,!1)});b&&j.redraw(c)},processData:function(a){var e,b=this.xData,c=this.yData,d=b.length;e=0;var f,g,o,n,h=this.xAxis,i=this.options,j=i.cropThreshold,k=0,l=this.isCartesian;if(l&&!this.isDirty&&!h.isDirty&&!this.yAxis.isDirty&&!a)return!1;for(l&&this.sorted&&(!j||d>j||this.forceCrop)&&(o=h.min,n=h.max,b[d-1]<o||b[0]>n?(b=[],c=[]):(b[0]<o||b[d-1]>n)&&(e=this.cropData(this.xData,this.yData,o,n),b=e.xData,c=e.yData,e=e.start,f=!0,k=b.length)),d=b.length-1;d>=0;d--)a=b[d]-b[d-1],!f&&b[d]>o&&b[d]<n&&k++,a>0&&(g===t||g>a)?g=a:0>a&&this.requireSorting&&ra(15);this.cropped=f,this.cropStart=e,this.processedXData=b,this.processedYData=c,this.activePointCount=k,null===i.pointRange&&(this.pointRange=g||1),this.closestPointRange=g},cropData:function(a,b,c,d){var i,e=a.length,f=0,g=e,h=m(this.cropShoulder,1);for(i=0;e>i;i++)if(a[i]>=c){f=v(0,i-h);break}for(;e>i;i++)if(a[i]>d){g=i+h;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var c,i,k,o,a=this.options.data,b=this.data,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,j=this.hasGroupedData,l=[];for(b||j||(b=[],b.length=a.length,b=this.data=b),o=0;g>o;o++)i=h+o,j?l[o]=(new f).init(this,[d[o]].concat(qa(e[o]))):(b[i]?k=b[i]:a[i]!==t&&(b[i]=k=(new f).init(this,a[i],d[o])),l[o]=k);if(b&&(g!==(c=b.length)||j))for(o=0;c>o;o++)o===h&&!j&&(o+=g),b[o]&&(b[o].destroyElements(),b[o].plotX=t);this.data=b,this.points=l},getExtremes:function(a){var d,b=this.yAxis,c=this.processedXData,e=[],f=0;d=this.xAxis.getExtremes();var i,j,k,l,g=d.min,h=d.max,a=a||this.stackedYData||this.processedYData;for(d=a.length,l=0;d>l;l++)if(j=c[l],k=a[l],i=null!==k&&k!==t&&(!b.isLog||k.length||k>0),j=this.getExtremesFromAll||this.cropped||(c[l+1]||j)>=g&&(c[l-1]||j)<=h,i&&j)if(i=k.length)for(;i--;)null!==k[i]&&(e[f++]=k[i]);else e[f++]=k;this.dataMin=m(void 0,Na(e)),this.dataMax=m(void 0,Ba(e))},translate:function(){this.processedXData||this.processData(),this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,h=!!this.modifyValue,i=a.pointPlacement,j="between"===i||ha(i),k=a.threshold,a=0;g>a;a++){var l=f[a],o=l.x,n=l.y,s=l.low,p=b&&e.stacks[(this.negStacks&&k>n?"-":"")+this.stackKey];e.isLog&&0>=n&&(l.y=n=null),l.plotX=c.translate(o,0,0,0,1,i,"flags"===this.type),b&&this.visible&&p&&p[o]&&(p=p[o],n=p.points[this.index+","+a],s=n[0],n=n[1],0===s&&(s=m(k,e.min)),e.isLog&&0>=s&&(s=null),l.total=l.stackTotal=p.total,l.percentage=p.total&&l.y/p.total*100,l.stackY=n,p.setOffset(this.pointXOffset||0,this.barW||0)),l.yBottom=r(s)?e.translate(s,0,1,0,1):null,h&&(n=this.modifyValue(n,l)),l.plotY="number"==typeof n&&1/0!==n?e.translate(n,0,1,0,1):t,l.clientX=j?c.translate(o,0,0,0,1):l.plotX,l.negative=l.y<(k||0),l.category=d&&d[l.x]!==t?d[l.x]:l.x}this.getSegments()},animate:function(a){var d,b=this.chart,c=b.renderer;d=this.options.animation;var g,e=this.clipBox||b.clipBox,f=b.inverted;d&&!ca(d)&&(d=ba[this.type].animation),g=["_sharedClip",d.duration,d.easing,e.height].join(","),a?(a=b[g],d=b[g+"m"],a||(b[g]=a=c.clipRect(q(e,{width:0})),b[g+"m"]=d=c.clipRect(-99,f?-b.plotLeft:-b.plotTop,99,f?b.chartWidth:b.chartHeight)),this.group.clip(a),this.markerGroup.clip(d),this.sharedClipKey=g):((a=b[g])&&a.animate({width:b.plotSizeX},d),b[g+"m"]&&b[g+"m"].animate({width:b.plotSizeX+99},d),this.animate=null)},afterAnimate:function(){var a=this.chart,b=this.sharedClipKey,c=this.group,d=this.clipBox;c&&this.options.clip!==!1&&(b&&d||c.clip(d?a.renderer.clipRect(d):a.clipRect),this.markerGroup.clip()),D(this,"afterAnimate"),setTimeout(function(){b&&a[b]&&(d||(a[b]=a[b].destroy()),a[b+"m"]&&(a[b+"m"]=a[b+"m"].destroy()))},100)},drawPoints:function(){var a,d,e,f,g,h,i,j,k,b=this.points,c=this.chart;d=this.options.marker;var o,l=this.pointAttr[""],n=this.markerGroup,s=m(d.enabled,this.activePointCount<.5*this.xAxis.len/d.radius);if(d.enabled!==!1||this._hasPointMarkers)for(f=b.length;f--;)g=b[f],d=T(g.plotX),e=g.plotY,k=g.graphic,i=g.marker||{},a=s&&i.enabled===t||i.enabled,o=c.isInsidePlot(u(d),e,c.inverted),a&&e!==t&&!isNaN(e)&&null!==g.y?(a=g.pointAttr[g.selected?"select":""]||l,h=a.r,i=m(i.symbol,this.symbol),j=0===i.indexOf("url"),k?k[o?"show":"hide"](!0).animate(q({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{})):o&&(h>0||j)&&(g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(n))):k&&(g.graphic=k.destroy())},convertAttribs:function(a,b,c,d){var f,g,e=this.pointAttrToOptions,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=m(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var f,a=this,b=a.options,c=ba[a.type].marker?b.marker:b,d=c.states,e=d.hover,g=a.color;f={stroke:g,fill:g};var i,k,h=a.points||[],j=[],l=a.pointAttrToOptions;k=a.hasPointSpecificOptions;var o=b.negativeColor,n=c.lineColor,s=c.fillColor;i=b.turboThreshold;var m;if(b.marker?(e.radius=e.radius||c.radius+2,e.lineWidth=e.lineWidth||c.lineWidth+1):e.color=e.color||ya(e.color||g).brighten(e.brightness).get(),j[""]=a.convertAttribs(c,f),p(["hover","select"],function(b){j[b]=a.convertAttribs(d[b],j[""])}),a.pointAttr=j,g=h.length,!i||i>g||k)for(;g--;){if(i=h[g],(c=i.options&&i.options.marker||i.options)&&c.enabled===!1&&(c.radius=0),i.negative&&o&&(i.color=i.fillColor=o),k=b.colorByPoint||i.color,i.options)for(m in l)r(c[l[m]])&&(k=!0);k?(c=c||{},k=[],d=c.states||{},f=d.hover=d.hover||{},b.marker||(f.color=f.color||!i.options.color&&e.color||ya(i.color).brighten(f.brightness||e.brightness).get()),f={color:i.color},s||(f.fillColor=i.color),n||(f.lineColor=i.color),k[""]=a.convertAttribs(q(f,c),j[""]),k.hover=a.convertAttribs(d.hover,j.hover,k[""]),k.select=a.convertAttribs(d.select,j.select,k[""])):k=j,i.pointAttr=k}},destroy:function(){var d,e,g,h,i,a=this,b=a.chart,c=/AppleWebKit\/533/.test(wa),f=a.data||[];for(D(a,"destroy"),W(a),p(a.axisTypes||[],function(b){(i=a[b])&&(ja(i.series,a),i.isDirty=i.forceRedraw=!0)}),a.legendItem&&a.chart.legend.destroyItem(a),e=f.length;e--;)(g=f[e])&&g.destroy&&g.destroy();a.points=null,clearTimeout(a.animationTimeout),p("area,graph,dataLabelsGroup,group,markerGroup,tracker,graphNeg,areaNeg,posClip,negClip".split(","),function(b){a[b]&&(d=c&&"group"===b?"hide":"destroy",a[b][d]())}),b.hoverSeries===a&&(b.hoverSeries=null),ja(b.series,a);for(h in a)delete a[h]},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;return p(a,function(e,f){var i,g=e.plotX,h=e.plotY;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"),d&&f&&(i=a[f-1],"right"===d?c.push(i.plotX,h):"center"===d?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))}),c},getGraphPath:function(){var c,a=this,b=[],d=[];return p(a.segments,function(e){c=a.getSegmentPath(e),e.length>1?b=b.concat(c):d.push(e[0])}),a.singlePoints=d,a.graphPath=b},drawGraph:function(){var a=this,b=this.options,c=[["graph",b.lineColor||this.color]],d=b.lineWidth,e=b.dashStyle,f="square"!==b.linecap,g=this.getGraphPath(),h=b.negativeColor;h&&c.push(["graphNeg",h]),p(c,function(c,h){var k=c[0],l=a[k];l?(bb(l),l.animate({d:g})):d&&g.length&&(l={stroke:c[1],"stroke-width":d,fill:Q,zIndex:1},e?l.dashstyle=e:f&&(l["stroke-linecap"]=l["stroke-linejoin"]="round"),a[k]=a.chart.renderer.path(g).attr(l).add(a.group).shadow(!h&&b.shadow))})},clipNeg:function(){var e,a=this.options,b=this.chart,c=b.renderer,d=a.negativeColor||a.negativeFillColor,f=this.graph,g=this.area,h=this.posClip,i=this.negClip;e=b.chartWidth;var j=b.chartHeight,k=v(e,j),l=this.yAxis;d&&(f||g)&&(d=u(l.toPixels(a.threshold||0,!0)),0>d&&(k-=d),a={x:0,y:0,width:k,height:d},k={x:0,y:d,width:k,height:k},b.inverted&&(a.height=k.y=b.plotWidth-d,c.isVML&&(a={x:b.plotWidth-d-b.plotLeft,y:0,width:e,height:j},k={x:d+b.plotLeft-e,y:0,width:b.plotLeft+d,height:e})),l.reversed?(b=k,e=a):(b=a,e=k),h?(h.animate(b),i.animate(e)):(this.posClip=h=c.clipRect(b),this.negClip=i=c.clipRect(e),f&&this.graphNeg&&(f.clip(h),this.graphNeg.clip(i)),g&&(g.clip(h),this.areaNeg.clip(i))))},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};p(["group","markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;b.xAxis&&(K(c,"resize",a),K(b,"destroy",function(){W(c,"resize",a)}),a(),b.invertGroups=a)},plotGroup:function(a,b,c,d,e){var f=this[a],g=!f;return g&&(this[a]=f=this.chart.renderer.g(b).attr({visibility:c,zIndex:d||.1}).add(e)),f[g?"attr":"animate"](this.getPlotBox()),f},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;return a.inverted&&(b=c,c=this.xAxis),{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var c,a=this,b=a.chart,d=a.options,e=(c=d.animation)&&!!a.animate&&b.renderer.isSVG&&m(c.duration,500)||0,f=a.visible?"visible":"hidden",g=d.zIndex,h=a.hasRendered,i=b.seriesGroup;c=a.plotGroup("group","series",f,g,i),a.markerGroup=a.plotGroup("markerGroup","markers",f,g,i),e&&a.animate(!0),a.getAttribs(),c.inverted=a.isCartesian?b.inverted:!1,a.drawGraph&&(a.drawGraph(),a.clipNeg()),a.drawDataLabels&&a.drawDataLabels(),a.visible&&a.drawPoints(),a.drawTracker&&a.options.enableMouseTracking!==!1&&a.drawTracker(),b.inverted&&a.invertGroups(),d.clip!==!1&&!a.sharedClipKey&&!h&&c.clip(b.clipRect),e&&a.animate(),h||(e?a.animationTimeout=setTimeout(function(){a.afterAnimate()},e):a.afterAnimate()),a.isDirty=a.isDirtyData=!1,a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:m(d&&d.left,a.plotLeft),translateY:m(e&&e.top,a.plotTop)})),this.translate(),this.setTooltipPoints&&this.setTooltipPoints(!0),this.render(),b&&D(this,"updatedData")}},Hb.prototype={destroy:function(){Oa(this,this.axis)},render:function(a){var b=this.options,c=b.format,c=c?Ia(c,this):b.formatter.call(this);this.label?this.label.attr({text:c,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(c,null,null,b.useHTML).css(b.style).attr({align:this.textAlign,rotation:b.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=this.isNegative,g=c.translate(c.usePercentage?100:this.total,0,0,0,1),c=c.translate(0),c=M(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};(e=this.label)&&(e.align(this.alignOptions,null,f),f=e.alignAttr,e[this.options.crop===!1||d.isInsidePlot(f.x,f.y)?"show":"hide"](!0))}},la.prototype.buildStacks=function(){var a=this.series,b=m(this.options.reversedStacks,!0),c=a.length;if(!this.isXAxis){for(this.usePercentage=!1;c--;)a[b?c:a.length-c-1].setStackedPoints();if(this.usePercentage)for(c=0;c<a.length;c++)a[c].setPercentStacks()}},la.prototype.renderStackTotals=function(){var d,e,a=this.chart,b=a.renderer,c=this.stacks,f=this.stackTotalGroup;f||(this.stackTotalGroup=f=b.g("stack-labels").attr({visibility:"visible",zIndex:6}).add()),f.translate(a.plotLeft,a.plotTop);for(d in c)for(e in a=c[d])a[e].render(f)},O.prototype.setStackedPoints=function(){if(this.options.stacking&&(this.visible===!0||this.chart.options.chart.ignoreHiddenSeries===!1)){var n,m,p,q,r,u,a=this.processedXData,b=this.processedYData,c=[],d=b.length,e=this.options,f=e.threshold,g=e.stack,e=e.stacking,h=this.stackKey,i="-"+h,j=this.negStacks,k=this.yAxis,l=k.stacks,o=k.oldStacks;for(q=0;d>q;q++)r=a[q],u=b[q],p=this.index+","+q,m=(n=j&&f>u)?i:h,l[m]||(l[m]={}),l[m][r]||(o[m]&&o[m][r]?(l[m][r]=o[m][r],l[m][r].total=null):l[m][r]=new Hb(k,k.options.stackLabels,n,r,g)),m=l[m][r],m.points[p]=[m.cum||0],"percent"===e?(n=n?h:i,j&&l[n]&&l[n][r]?(n=l[n][r],m.total=n.total=v(n.total,m.total)+M(u)||0):m.total=da(m.total+(M(u)||0))):m.total=da(m.total+(u||0)),m.cum=(m.cum||0)+(u||0),m.points[p].push(m.cum),c[q]=m.cum;"percent"===e&&(k.usePercentage=!0),this.stackedYData=c,k.oldStacks={}}},O.prototype.setPercentStacks=function(){var a=this,b=a.stackKey,c=a.yAxis.stacks,d=a.processedXData;p([b,"-"+b],function(b){for(var e,g,h,f=d.length;f--;)g=d[f],e=(h=c[b]&&c[b][g])&&h.points[a.index+","+f],(g=e)&&(h=h.total?100/h.total:0,g[0]=da(g[0]*h),g[1]=da(g[1]*h),a.stackedYData[f]=g[1])})},q(Ya.prototype,{addSeries:function(a,b,c){var d,e=this;return a&&(b=m(b,!0),D(e,"addSeries",{options:a},function(){d=e.initSeries(a),e.isDirtyLegend=!0,e.linkSeries(),b&&e.redraw(c)})),d},addAxis:function(a,b,c,d){var e=b?"xAxis":"yAxis",f=this.options;new la(this,w(a,{index:this[e].length,isX:b})),f[e]=qa(f[e]||{}),f[e].push(a),m(c,!0)&&this.redraw(d)},showLoading:function(a){var b=this.options,c=this.loadingDiv,d=b.loading;c||(this.loadingDiv=c=Y(Ja,{className:"highcharts-loading"},q(d.style,{zIndex:10,display:Q}),this.container),this.loadingSpan=Y("span",null,d.labelStyle,c)),this.loadingSpan.innerHTML=a||b.lang.loading,this.loadingShown||(G(c,{opacity:0,display:"",left:this.plotLeft+"px",top:this.plotTop+"px",width:this.plotWidth+"px",height:this.plotHeight+"px"}),kb(c,{opacity:d.style.opacity},{duration:d.showDuration||0}),this.loadingShown=!0)},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&kb(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){G(b,{display:Q})}}),this.loadingShown=!1}}),q(Ea.prototype,{update:function(a,b,c){var g,d=this,e=d.series,f=d.graphic,h=e.data,i=e.chart,j=e.options,b=m(b,!0);d.firePointEvent("update",{options:a},function(){d.applyOptions(a),ca(a)&&(e.getAttribs(),f&&(a&&a.marker&&a.marker.symbol?d.graphic=f.destroy():f.attr(d.pointAttr[d.state||""])),a&&a.dataLabels&&d.dataLabel&&(d.dataLabel=d.dataLabel.destroy())),g=Da(d,h),e.updateParallelArrays(d,g),j.data[g]=d.options,e.isDirty=e.isDirtyData=!0,!e.fixedBox&&e.hasCartesianSeries&&(i.isDirtyBox=!0),"point"===j.legendType&&i.legend.destroyItem(d),b&&i.redraw(c)})},remove:function(a,b){var g,c=this,d=c.series,e=d.points,f=d.chart,h=d.data;Qa(b,f),a=m(a,!0),c.firePointEvent("remove",null,function(){g=Da(c,h),h.length===e.length&&e.splice(g,1),h.splice(g,1),d.options.data.splice(g,1),d.updateParallelArrays(c,"splice",g,1),c.destroy(),d.isDirty=!0,d.isDirtyData=!0,a&&f.redraw()})}}),q(O.prototype,{addPoint:function(a,b,c,d){var o,e=this.options,f=this.data,g=this.graph,h=this.area,i=this.chart,j=this.xAxis&&this.xAxis.names,k=g&&g.shift||0,l=e.data,n=this.xData;if(Qa(d,i),c&&p([g,h,this.graphNeg,this.areaNeg],function(a){a&&(a.shift=k+1)}),h&&(h.isArea=!0),b=m(b,!0),d={series:this},this.pointClass.prototype.applyOptions.apply(d,[a]),g=d.x,h=n.length,this.requireSorting&&g<n[h-1])for(o=!0;h&&n[h-1]>g;)h--;this.updateParallelArrays(d,"splice",h,0,0),this.updateParallelArrays(d,h),j&&(j[g]=d.name),l.splice(h,0,a),o&&(this.data.splice(h,0,null),this.processData()),"point"===e.legendType&&this.generatePoints(),c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),this.updateParallelArrays(d,"shift"),l.shift())),this.isDirtyData=this.isDirty=!0,b&&(this.getAttribs(),i.redraw())},remove:function(a,b){var c=this,d=c.chart,a=m(a,!0);c.isRemoving||(c.isRemoving=!0,D(c,"remove",null,function(){c.destroy(),d.isDirtyLegend=d.isDirtyBox=!0,d.linkSeries(),a&&d.redraw(b)})),c.isRemoving=!1},update:function(a,b){var f,c=this.chart,d=this.type,e=F[d].prototype,a=w(this.userOptions,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1);for(f in e)e.hasOwnProperty(f)&&(this[f]=t);q(this,F[a.type||d].prototype),this.init(c,a),m(b,!0)&&c.redraw(!1)}}),q(la.prototype,{update:function(a,b){var c=this.chart,a=c.options[this.coll][this.options.index]=w(this.userOptions,a);this.destroy(!0),this._addedPlotLB=t,this.init(c,q(a,{events:t})),c.isDirtyBox=!0,m(b,!0)&&c.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,d=this.series,e=d.length;e--;)d[e]&&d[e].remove(!1);ja(b.axes,this),ja(b[c],this),b.options[c].splice(this.options.index,1),p(b[c],function(a,b){a.options.index=b}),this.destroy(),b.isDirtyBox=!0,m(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}}),ga=ka(O),F.line=ga,ba.area=w(S,{threshold:0});var pa=ka(O,{type:"area",getSegments:function(){var h,i,l,o,n,a=[],b=[],c=[],d=this.xAxis,e=this.yAxis,f=e.stacks[this.stackKey],g={},j=this.points,k=this.options.connectNulls;if(this.options.stacking&&!this.cropped){for(o=0;o<j.length;o++)g[j[o].x]=j[o];for(n in f)null!==f[n].total&&c.push(+n);c.sort(function(a,b){return a-b}),p(c,function(a){(!k||g[a]&&null!==g[a].y)&&(g[a]?b.push(g[a]):(h=d.translate(a),l=f[a].percent?f[a].total?100*f[a].cum/f[a].total:0:f[a].cum,i=e.toPixels(l,!0),b.push({y:null,plotX:h,clientX:h,plotY:i,yBottom:i,onMouseOver:sa})))}),b.length&&a.push(b)}else O.prototype.getSegments.call(this),a=this.segments;this.segments=a},getSegmentPath:function(a){var d,b=O.prototype.getSegmentPath.call(this,a),c=[].concat(b),e=this.options;d=b.length;var g,f=this.yAxis.getThreshold(e.threshold);if(3===d&&c.push("L",b[1],b[2]),e.stacking&&!this.closedStacks)for(d=a.length-1;d>=0;d--)g=m(a[d].yBottom,f),d<a.length-1&&e.step&&c.push(a[d+1].plotX,g),c.push(a[d].plotX,g);else this.closeSegment(c,a,f);return this.areaPath=this.areaPath.concat(c),b},closeSegment:function(a,b,c){a.push("L",b[b.length-1].plotX,c,"L",b[0].plotX,c)},drawGraph:function(){this.areaPath=[],O.prototype.drawGraph.apply(this);var a=this,b=this.areaPath,c=this.options,d=c.negativeColor,e=c.negativeFillColor,f=[["area",this.color,c.fillColor]];(d||e)&&f.push(["areaNeg",d,e]),p(f,function(d){var e=d[0],f=a[e];f?f.animate({d:b}):a[e]=a.chart.renderer.path(b).attr({fill:m(d[2],ya(d[1]).setOpacity(m(c.fillOpacity,.75)).get()),zIndex:0}).add(a.group)
5
- })},drawLegendSymbol:N.drawRectangle});F.area=pa,ba.spline=w(S),ga=ka(O,{type:"spline",getPointSpline:function(a,b,c){var h,i,j,k,d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1];if(f&&g){a=f.plotY,j=g.plotX;var l,g=g.plotY;h=(1.5*d+f.plotX)/2.5,i=(1.5*e+a)/2.5,j=(1.5*d+j)/2.5,k=(1.5*e+g)/2.5,l=(k-i)*(j-d)/(j-h)+e-k,i+=l,k+=l,i>a&&i>e?(i=v(a,e),k=2*e-i):a>i&&e>i&&(i=C(a,e),k=2*e-i),k>g&&k>e?(k=v(g,e),i=2*e-k):g>k&&e>k&&(k=C(g,e),i=2*e-k),b.rightContX=j,b.rightContY=k}return c?(b=["C",f.rightContX||f.plotX,f.rightContY||f.plotY,h||d,i||e,d,e],f.rightContX=f.rightContY=null):b=["M",d,e],b}}),F.spline=ga,ba.areaspline=w(ba.area),pa=pa.prototype,ga=ka(ga,{type:"areaspline",closedStacks:!0,getSegmentPath:pa.getSegmentPath,closeSegment:pa.closeSegment,drawGraph:pa.drawGraph,drawLegendSymbol:N.drawRectangle}),F.areaspline=ga,ba.column=w(S,{borderColor:"#FFFFFF",borderRadius:0,groupPadding:.2,marker:null,pointPadding:.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{brightness:.1,shadow:!1,halo:!1},select:{color:"#C0C0C0",borderColor:"#000000",shadow:!1}},dataLabels:{align:null,verticalAlign:null,y:null},stickyTracking:!1,tooltip:{distance:6},threshold:0}),ga=ka(O,{type:"column",pointAttrToOptions:{stroke:"borderColor",fill:"color",r:"borderRadius"},cropShoulder:0,trackerGroups:["group","dataLabelsGroup"],negStacks:!0,init:function(){O.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&p(b.series,function(b){b.type===a.type&&(b.isDirty=!0)})},getColumnMetrics:function(){var f,h,a=this,b=a.options,c=a.xAxis,d=a.yAxis,e=c.reversed,g={},i=0;b.grouping===!1?i=1:p(a.chart.series,function(b){var c=b.options,e=b.yAxis;b.type===a.type&&b.visible&&d.len===e.len&&d.pos===e.pos&&(c.stacking?(f=b.stackKey,g[f]===t&&(g[f]=i++),h=g[f]):c.grouping!==!1&&(h=i++),b.columnIndex=h)});var c=C(M(c.transA)*(c.ordinalSlope||b.pointRange||c.closestPointRange||c.tickInterval||1),c.len),j=c*b.groupPadding,k=(c-2*j)/i,l=b.pointWidth,b=r(l)?(k-l)/2:k*b.pointPadding,l=m(l,k-2*b);return a.columnMetrics={width:l,offset:b+(j+((e?i-(a.columnIndex||0):a.columnIndex)||0)*k-c/2)*(e?-1:1)}},translate:function(){var a=this,b=a.chart,c=a.options,d=a.borderWidth=m(c.borderWidth,a.activePointCount>.5*a.xAxis.len?0:1),e=a.yAxis,f=a.translatedThreshold=e.getThreshold(c.threshold),g=m(c.minPointLength,5),c=a.getColumnMetrics(),h=c.width,i=a.barW=Ka(v(h,1+2*d)),j=a.pointXOffset=c.offset,k=-(d%2?.5:0),l=d%2?.5:1;b.renderer.isVML&&b.inverted&&(l+=1),O.prototype.translate.apply(a),p(a.points,function(c){var x,d=m(c.yBottom,f),p=C(v(-999-d,c.plotY),e.len+999+d),q=c.plotX+j,r=i,t=C(p,d);x=v(p,d)-t,M(x)<g&&g&&(x=g,t=u(M(t-f)>g?d-g:f-(e.translate(c.y,0,1,0,1)<=f?g:0))),c.barX=q,c.pointWidth=h,c.tooltipPos=b.inverted?[e.len-p,a.xAxis.len-q-r/2]:[q+r/2,p],d=M(q)<.5,r=u(q+r)+k,q=u(q)+k,r-=q,p=M(t)<.5,x=u(t+x)+l,t=u(t)+l,x-=t,d&&(q+=1,r-=1),p&&(t-=1,x+=1),c.shapeType="rect",c.shapeArgs={x:q,y:t,width:r,height:x}})},getSymbol:sa,drawLegendSymbol:N.drawRectangle,drawGraph:sa,drawPoints:function(){var f,g,h,a=this,b=this.chart,c=a.options,d=b.renderer,e=c.animationLimit||250;p(a.points,function(i){var j=i.plotY,k=i.graphic;j===t||isNaN(j)||null===i.y?k&&(i.graphic=k.destroy()):(f=i.shapeArgs,h=r(a.borderWidth)?{"stroke-width":a.borderWidth}:{},g=i.pointAttr[i.selected?"select":""]||a.pointAttr[""],k?(bb(k),k.attr(h)[b.pointCount<e?"animate":"attr"](w(f))):i.graphic=d[i.shapeType](f).attr(g).attr(h).add(a.group).shadow(c.shadow,null,c.stacking&&!c.borderRadius))})},animate:function(a){var b=this.yAxis,c=this.options,d=this.chart.inverted,e={};aa&&(a?(e.scaleY=.001,a=C(b.pos+b.len,v(b.pos,b.toPixels(c.threshold))),d?e.translateX=a-b.len:e.translateY=a,this.group.attr(e)):(e.scaleY=1,e[d?"translateX":"translateY"]=b.pos,this.group.animate(e,this.options.animation),this.animate=null))},remove:function(){var a=this,b=a.chart;b.hasRendered&&p(b.series,function(b){b.type===a.type&&(b.isDirty=!0)}),O.prototype.remove.apply(a,arguments)}}),F.column=ga,ba.bar=w(ba.column),pa=ka(ga,{type:"bar",inverted:!0}),F.bar=pa,ba.scatter=w(S,{lineWidth:0,tooltip:{headerFormat:'<span style="color:{series.color}">●</span> <span style="font-size: 10px;"> {series.name}</span><br/>',pointFormat:"x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>"},stickyTracking:!1}),pa=ka(O,{type:"scatter",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["markerGroup"],takeOrdinalPosition:!1,singularTooltips:!0,drawGraph:function(){this.options.lineWidth&&O.prototype.drawGraph.call(this)}}),F.scatter=pa,ba.pie=w(S,{borderColor:"#FFFFFF",borderWidth:1,center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name}},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,states:{hover:{brightness:.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}}),S={type:"pie",isCartesian:!1,pointClass:ka(Ea,{init:function(){Ea.prototype.init.apply(this,arguments);var b,a=this;return a.y<0&&(a.y=null),q(a,{visible:a.visible!==!1,name:m(a.name,"Slice")}),b=function(b){a.slice("select"===b.type)},K(a,"select",b),K(a,"unselect",b),a},setVisible:function(a){var b=this,c=b.series,d=c.chart;b.visible=b.options.visible=a=a===t?!b.visible:a,c.options.data[Da(b,c.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){b[c]&&b[c][a?"show":"hide"](!0)}),b.legendItem&&d.legend.colorizeItem(b,a),!c.isDirty&&c.options.ignoreHiddenPoint&&(c.isDirty=!0,d.redraw())},slice:function(a,b,c){var d=this.series;Qa(c,d.chart),m(b,!0),this.sliced=this.options.sliced=a=r(a)?a:!this.sliced,d.options.data[Da(this,d.data)]=this.options,a=a?this.slicedTranslation:{translateX:0,translateY:0},this.graphic.animate(a),this.shadowGroup&&this.shadowGroup.animate(a)},haloPath:function(a){var b=this.shapeArgs,c=this.series.chart;return this.series.chart.renderer.symbols.arc(c.plotLeft+b.x,c.plotTop+b.y,b.r+a,b.r+a,{innerR:this.shapeArgs.r,start:b.start,end:b.end})}}),requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},singularTooltips:!0,getColor:sa,animate:function(a){var b=this,c=b.points,d=b.startAngleRad;a||(p(c,function(a){var c=a.graphic,a=a.shapeArgs;c&&(c.attr({r:b.center[3]/2,start:d,end:d}),c.animate({r:a.r,start:a.start,end:a.end},b.options.animation))}),b.animate=null)},setData:function(a,b,c,d){O.prototype.setData.call(this,a,!1,c,d),this.processData(),this.generatePoints(),m(b,!0)&&this.chart.redraw(c)},generatePoints:function(){var a,c,d,e,b=0,f=this.options.ignoreHiddenPoint;for(O.prototype.generatePoints.call(this),c=this.points,d=c.length,a=0;d>a;a++)e=c[a],b+=f&&!e.visible?0:e.y;for(this.total=b,a=0;d>a;a++)e=c[a],e.percentage=b>0?e.y/b*100:0,e.total=b},translate:function(a){this.generatePoints();var f,g,h,o,p,b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,i=c.startAngle||0,j=this.startAngleRad=ma/180*(i-90),i=(this.endAngleRad=ma/180*(m(c.endAngle,i+360)-90))-j,k=this.points,l=c.dataLabels.distance,c=c.ignoreHiddenPoint,n=k.length;for(a||(this.center=a=this.getCenter()),this.getX=function(b,c){return h=U.asin(C((b-a[1])/(a[2]/2+l),1)),a[0]+(c?-1:1)*Z(h)*(a[2]/2+l)},o=0;n>o;o++)p=k[o],f=j+b*i,(!c||p.visible)&&(b+=p.percentage/100),g=j+b*i,p.shapeType="arc",p.shapeArgs={x:a[0],y:a[1],r:a[2]/2,innerR:a[3]/2,start:u(1e3*f)/1e3,end:u(1e3*g)/1e3},h=(g+f)/2,h>1.5*ma?h-=2*ma:-ma/2>h&&(h+=2*ma),p.slicedTranslation={translateX:u(Z(h)*d),translateY:u(ea(h)*d)},f=Z(h)*a[2]/2,g=ea(h)*a[2]/2,p.tooltipPos=[a[0]+.7*f,a[1]+.7*g],p.half=-ma/2>h||h>ma/2?1:0,p.angle=h,e=C(e,l/2),p.labelPos=[a[0]+f+Z(h)*l,a[1]+g+ea(h)*l,a[0]+f+Z(h)*e,a[1]+g+ea(h)*e,a[0]+f,a[1]+g,0>l?"center":p.half?"right":"left",h]},drawGraph:null,drawPoints:function(){var c,d,f,g,a=this,b=a.chart.renderer,e=a.options.shadow;e&&!a.shadowGroup&&(a.shadowGroup=b.g("shadow").add(a.group)),p(a.points,function(h){d=h.graphic,g=h.shapeArgs,f=h.shadowGroup,e&&!f&&(f=h.shadowGroup=b.g("shadow").add(a.shadowGroup)),c=h.sliced?h.slicedTranslation:{translateX:0,translateY:0},f&&f.attr(c),d?d.animate(q(g,c)):h.graphic=d=b[h.shapeType](g).setRadialReference(a.center).attr(h.pointAttr[h.selected?"select":""]).attr({"stroke-linejoin":"round"}).attr(c).add(a.group).shadow(e,f),void 0!==h.visible&&h.setVisible(h.visible)})},sortByAngle:function(a,b){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*b})},drawLegendSymbol:N.drawRectangle,getCenter:X.getCenter,getSymbol:sa},S=ka(O,S),F.pie=S,O.prototype.drawDataLabels=function(){var f,g,h,i,a=this,b=a.options,c=b.cursor,d=b.dataLabels,e=a.points;(d.enabled||a._hasPointLabels)&&(a.dlProcessOptions&&a.dlProcessOptions(d),i=a.plotGroup("dataLabelsGroup","data-labels","hidden",d.zIndex||6),!a.hasRendered&&m(d.defer,!0)&&(i.attr({opacity:0}),K(a,"afterAnimate",function(){a.dataLabelsGroup.show()[b.animation?"animate":"attr"]({opacity:1},{duration:200})})),g=d,p(e,function(b){var e,o,n,l=b.dataLabel,p=b.connector,u=!0;if(f=b.options&&b.options.dataLabels,e=m(f&&f.enabled,g.enabled),l&&!e)b.dataLabel=l.destroy();else if(e){if(d=w(g,f),e=d.rotation,o=b.getLabelConfig(),h=d.format?Ia(d.format,o):d.formatter.call(o,d),d.style.color=m(d.color,d.style.color,a.color,"black"),l)r(h)?(l.attr({text:h}),u=!1):(b.dataLabel=l=l.destroy(),p&&(b.connector=p.destroy()));else if(r(h)){l={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:e,padding:d.padding,zIndex:1};for(n in l)l[n]===t&&delete l[n];l=b.dataLabel=a.chart.renderer[e?"text":"label"](h,0,-999,null,null,null,d.useHTML).attr(l).css(q(d.style,c&&{cursor:c})).add(i).shadow(d.shadow)}l&&a.alignDataLabel(b,l,d,null,u)}}))},O.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=m(a.plotX,-999),i=m(a.plotY,-999),j=b.getBBox();(a=this.visible&&(a.series.forceDL||f.isInsidePlot(h,u(i),g)||d&&f.isInsidePlot(h,g?d.x+1:d.y+d.height-1,g)))&&(d=q({x:g?f.plotWidth-i:h,y:u(g?f.plotHeight-h:i),width:0,height:0},d),q(c,{width:j.width,height:j.height}),c.rotation?(g={align:c.align,x:d.x+c.x+d.width/2,y:d.y+c.y+d.height/2},b[e?"attr":"animate"](g)):(b.align(c,null,d),g=b.alignAttr,"justify"===m(c.overflow,"justify")?this.justifyDataLabel(b,c,g,j,d,e):m(c.crop,!0)&&(a=f.isInsidePlot(g.x,g.y)&&f.isInsidePlot(g.x+j.width,g.y+j.height)))),a||(b.attr({y:-999}),b.placed=!1)},O.prototype.justifyDataLabel=function(a,b,c,d,e,f){var j,k,g=this.chart,h=b.align,i=b.verticalAlign;j=c.x,0>j&&("right"===h?b.align="left":b.x=-j,k=!0),j=c.x+d.width,j>g.plotWidth&&("left"===h?b.align="right":b.x=g.plotWidth-j,k=!0),j=c.y,0>j&&("bottom"===i?b.verticalAlign="top":b.y=-j,k=!0),j=c.y+d.height,j>g.plotHeight&&("top"===i?b.verticalAlign="bottom":b.y=g.plotHeight-j,k=!0),k&&(a.placed=!f,a.align(b,null,e))},F.pie&&(F.pie.prototype.drawDataLabels=function(){var c,i,j,t,w,x,y,A,C,G,D,B,a=this,b=a.data,d=a.chart,e=a.options.dataLabels,f=m(e.connectorPadding,10),g=m(e.connectorWidth,1),h=d.plotWidth,d=d.plotHeight,k=m(e.softConnector,!0),l=e.distance,o=a.center,n=o[2]/2,q=o[1],r=l>0,z=[[],[]],F=[0,0,0,0],N=function(a,b){return b.y-a.y};if(a.visible&&(e.enabled||a._hasPointLabels)){for(O.prototype.drawDataLabels.apply(a),p(b,function(a){a.dataLabel&&a.visible&&z[a.half].push(a)}),D=0;!y&&b[D];)y=b[D]&&b[D].dataLabel&&(b[D].dataLabel.getBBox().height||21),D++;for(D=2;D--;){var E,b=[],K=[],H=z[D],I=H.length;if(a.sortByAngle(H,D-.5),l>0){for(B=q-n-l;q+n+l>=B;B+=y)b.push(B);if(w=b.length,I>w){for(c=[].concat(H),c.sort(N),B=I;B--;)c[B].rank=B;for(B=I;B--;)H[B].rank>=w&&H.splice(B,1);I=H.length}for(B=0;I>B;B++){c=H[B],x=c.labelPos,c=9999;var Q,P;for(P=0;w>P;P++)Q=M(b[P]-x[1]),c>Q&&(c=Q,E=P);if(B>E&&null!==b[B])E=B;else for(I-B+E>w&&null!==b[B]&&(E=w-I+B);null===b[E];)E++;K.push({i:E,y:b[E]}),b[E]=null}K.sort(N)}for(B=0;I>B;B++)c=H[B],x=c.labelPos,t=c.dataLabel,G=c.visible===!1?"hidden":"visible",c=x[1],l>0?(w=K.pop(),E=w.i,C=w.y,(c>C&&null!==b[E+1]||C>c&&null!==b[E-1])&&(C=c)):C=c,A=e.justify?o[0]+(D?-1:1)*(n+l):a.getX(0===E||E===b.length-1?c:C,D),t._attr={visibility:G,align:x[6]},t._pos={x:A+e.x+({left:f,right:-f}[x[6]]||0),y:C+e.y-10},t.connX=A,t.connY=C,null===this.options.size&&(w=t.width,f>A-w?F[3]=v(u(w-A+f),F[3]):A+w>h-f&&(F[1]=v(u(A+w-h+f),F[1])),0>C-y/2?F[0]=v(u(-C+y/2),F[0]):C+y/2>d&&(F[2]=v(u(C+y/2-d),F[2])))}(0===Ba(F)||this.verifyDataLabelOverflow(F))&&(this.placeDataLabels(),r&&g&&p(this.points,function(b){i=b.connector,x=b.labelPos,(t=b.dataLabel)&&t._pos?(G=t._attr.visibility,A=t.connX,C=t.connY,j=k?["M",A+("left"===x[6]?5:-5),C,"C",A,C,2*x[2]-x[4],2*x[3]-x[5],x[2],x[3],"L",x[4],x[5]]:["M",A+("left"===x[6]?5:-5),C,"L",x[2],x[3],"L",x[4],x[5]],i?(i.animate({d:j}),i.attr("visibility",G)):b.connector=i=a.chart.renderer.path(j).attr({"stroke-width":g,stroke:e.connectorColor||b.color||"#606060",visibility:G}).add(a.dataLabelsGroup)):i&&(b.connector=i.destroy())}))}},F.pie.prototype.placeDataLabels=function(){p(this.points,function(a){var b,a=a.dataLabel;a&&((b=a._pos)?(a.attr(a._attr),a[a.moved?"animate":"attr"](b),a.moved=!0):a&&a.attr({y:-999}))})},F.pie.prototype.alignDataLabel=sa,F.pie.prototype.verifyDataLabelOverflow=function(a){var f,b=this.center,c=this.options,d=c.center,e=c=c.minSize||80;return null!==d[0]?e=v(b[2]-v(a[1],a[3]),c):(e=v(b[2]-a[1]-a[3],c),b[0]+=(a[3]-a[1])/2),null!==d[1]?e=v(C(e,b[2]-v(a[0],a[2])),c):(e=v(C(e,b[2]-a[0]-a[2]),c),b[1]+=(a[0]-a[2])/2),e<b[2]?(b[2]=e,this.translate(b),p(this.points,function(a){a.dataLabel&&(a.dataLabel._pos=null)}),this.drawDataLabels&&this.drawDataLabels()):f=!0,f}),F.column&&(F.column.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=a.dlBox||a.shapeArgs,i=a.below||a.plotY>m(this.translatedThreshold,f.plotSizeY),j=m(c.inside,!!this.options.stacking);h&&(d=w(h),g&&(d={x:f.plotWidth-d.y-d.height,y:f.plotHeight-d.x-d.width,width:d.height,height:d.width}),!j)&&(g?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0)),c.align=m(c.align,!g||j?"center":i?"right":"left"),c.verticalAlign=m(c.verticalAlign,g||j?"middle":i?"top":"bottom"),O.prototype.alignDataLabel.call(this,a,b,c,d,e)}),S=R.TrackerMixin={drawTrackerPoint:function(){var a=this,b=a.chart,c=b.pointer,d=a.options.cursor,e=d&&{cursor:d},f=function(c){var e,d=c.target;for(b.hoverSeries!==a&&a.onMouseOver();d&&!e;)e=d.point,d=d.parentNode;e!==t&&e!==b.hoverPoint&&e.onMouseOver(c)};p(a.points,function(a){a.graphic&&(a.graphic.element.point=a),a.dataLabel&&(a.dataLabel.element.point=a)}),a._hasTracking||(p(a.trackerGroups,function(b){a[b]&&(a[b].addClass("highcharts-tracker").on("mouseover",f).on("mouseout",function(a){c.onTrackerMouseOut(a)}).css(e),$a)&&a[b].on("touchstart",f)}),a._hasTracking=!0)},drawTrackerGraph:function(){var m,a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.pointer,h=f.renderer,i=f.options.tooltip.snap,j=a.tracker,k=b.cursor,l=k&&{cursor:k},k=a.singlePoints,n=function(){f.hoverSeries!==a&&a.onMouseOver()},q="rgba(192,192,192,"+(aa?1e-4:.002)+")";if(e&&!c)for(m=e+1;m--;)"M"===d[m]&&d.splice(m+1,0,d[m+1]-i,d[m+2],"L"),(m&&"M"===d[m]||m===e)&&d.splice(m,0,"L",d[m-2]+i,d[m-1]);for(m=0;m<k.length;m++)e=k[m],d.push("M",e.plotX-i,e.plotY,"L",e.plotX+i,e.plotY);j?j.attr({d:d}):(a.tracker=h.path(d).attr({"stroke-linejoin":"round",visibility:a.visible?"visible":"hidden",stroke:q,fill:c?q:Q,"stroke-width":b.lineWidth+(c?0:2*i),zIndex:2}).add(a.group),p([a.tracker,a.markerGroup],function(a){a.addClass("highcharts-tracker").on("mouseover",n).on("mouseout",function(a){g.onTrackerMouseOut(a)}).css(l),$a&&a.on("touchstart",n)}))}},F.column&&(ga.prototype.drawTracker=S.drawTrackerPoint),F.pie&&(F.pie.prototype.drawTracker=S.drawTrackerPoint),F.scatter&&(pa.prototype.drawTracker=S.drawTrackerPoint),q(lb.prototype,{setItemEvents:function(a,b,c,d,e){var f=this;(c?b:a.legendGroup).on("mouseover",function(){a.setState("hover"),b.css(f.options.itemHoverStyle)}).on("mouseout",function(){b.css(a.visible?d:e),a.setState()}).on("click",function(b){var c=function(){a.setVisible()},b={browserEvent:b};a.firePointEvent?a.firePointEvent("legendItemClick",b,c):D(a,"legendItemClick",b,c)})},createCheckboxForItem:function(a){a.checkbox=Y("input",{type:"checkbox",checked:a.selected,defaultChecked:a.selected},this.options.itemCheckboxStyle,this.chart.container),K(a.checkbox,"click",function(b){D(a,"checkboxClick",{checked:b.target.checked},function(){a.select()})})}}),E.legend.itemStyle.cursor="pointer",q(Ya.prototype,{showResetZoom:function(){var a=this,b=E.lang,c=a.options.chart.resetZoomButton,d=c.theme,e=d.states,f="chart"===c.relativeTo?null:"plotBox";this.resetZoomButton=a.renderer.button(b.resetZoom,null,null,function(){a.zoomOut()},d,e&&e.hover).attr({align:c.position.align,title:b.resetZoomTitle}).add().align(c.position,!1,f)},zoomOut:function(){var a=this;D(a,"selection",{resetSelection:!0},function(){a.zoom()})},zoom:function(a){var b,e,c=this.pointer,d=!1;!a||a.resetSelection?p(this.axes,function(a){b=a.zoom()}):p(a.xAxis.concat(a.yAxis),function(a){var e=a.axis,h=e.isXAxis;(c[h?"zoomX":"zoomY"]||c[h?"pinchX":"pinchY"])&&(b=e.zoom(a.min,a.max),e.displayBtn&&(d=!0))}),e=this.resetZoomButton,d&&!e?this.showResetZoom():!d&&ca(e)&&(this.resetZoomButton=e.destroy()),b&&this.redraw(m(this.options.chart.animation,a&&a.animation,this.pointCount<100))},pan:function(a,b){var e,c=this,d=c.hoverPoints;d&&p(d,function(a){a.setState()}),p("xy"===b?[1,0]:[1],function(b){var d=a[b?"chartX":"chartY"],h=c[b?"xAxis":"yAxis"][0],i=c[b?"mouseDownX":"mouseDownY"],j=(h.pointRange||0)/2,k=h.getExtremes(),l=h.toValue(i-d,!0)+j,i=h.toValue(i+c[b?"plotWidth":"plotHeight"]-d,!0)-j;h.series.length&&l>C(k.dataMin,k.min)&&i<v(k.dataMax,k.max)&&(h.setExtremes(l,i,!1,!1,{trigger:"pan"}),e=!0),c[b?"mouseDownX":"mouseDownY"]=d}),e&&c.redraw(!1),G(c.container,{cursor:"move"})}}),q(Ea.prototype,{select:function(a,b){var c=this,d=c.series,e=d.chart,a=m(a,!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=c.options.selected=a,d.options.data[Da(c,d.data)]=c.options,c.setState(a&&"select"),b||p(e.getSelectedPoints(),function(a){a.selected&&a!==c&&(a.selected=a.options.selected=!1,d.options.data[Da(a,d.data)]=a.options,a.setState(""),a.firePointEvent("unselect"))})})},onMouseOver:function(a){var b=this.series,c=b.chart,d=c.tooltip,e=c.hoverPoint;e&&e!==this&&e.onMouseOut(),this.firePointEvent("mouseOver"),d&&(!d.shared||b.noSharedTooltip)&&d.refresh(this,a),this.setState("hover"),c.hoverPoint=this},onMouseOut:function(){var a=this.series.chart,b=a.hoverPoints;b&&-1!==Da(this,b)||(this.firePointEvent("mouseOut"),this.setState(),a.hoverPoint=null)},importEvents:function(){if(!this.hasImportedEvents){var b,a=w(this.series.options.point,this.options).events;this.events=a;for(b in a)K(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a,b){var p,c=this.plotX,d=this.plotY,e=this.series,f=e.options.states,g=ba[e.type].marker&&e.options.marker,h=g&&!g.enabled,i=g&&g.states[a],j=i&&i.enabled===!1,k=e.stateMarkerGraphic,l=this.marker||{},m=e.chart,n=e.halo,a=a||"";p=this.pointAttr[a]||e.pointAttr[a],a===this.state&&!b||this.selected&&"select"!==a||f[a]&&f[a].enabled===!1||a&&(j||h&&i.enabled===!1)||a&&l.states&&l.states[a]&&l.states[a].enabled===!1||(this.graphic?(g=g&&this.graphic.symbolName&&p.r,this.graphic.attr(w(p,g?{x:c-g,y:d-g,width:2*g,height:2*g}:{})),k&&k.hide()):(a&&i&&(g=i.radius,l=l.symbol||e.symbol,k&&k.currentSymbol!==l&&(k=k.destroy()),k?k[b?"animate":"attr"]({x:c-g,y:d-g}):l&&(e.stateMarkerGraphic=k=m.renderer.symbol(l,c-g,d-g,2*g,2*g).attr(p).add(e.markerGroup),k.currentSymbol=l)),k&&k[a&&m.isInsidePlot(c,d,m.inverted)?"show":"hide"]()),(c=f[a]&&f[a].halo)&&c.size?(n||(e.halo=n=m.renderer.path().add(e.seriesGroup)),n.attr(q({fill:ya(this.color||e.color).setOpacity(c.opacity).get()},c.attributes))[b?"animate":"attr"]({d:this.haloPath(c.size)})):n&&n.attr({d:[]}),this.state=a)},haloPath:function(a){var b=this.series,c=b.chart,d=b.getPlotBox(),e=c.inverted;return c.renderer.symbols.circle(d.translateX+(e?b.yAxis.len-this.plotY:this.plotX)-a,d.translateY+(e?b.xAxis.len-this.plotX:this.plotY)-a,2*a,2*a)}}),q(O.prototype,{onMouseOver:function(){var a=this.chart,b=a.hoverSeries;b&&b!==this&&b.onMouseOut(),this.options.events.mouseOver&&D(this,"mouseOver"),this.setState("hover"),a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;d&&d.onMouseOut(),this&&a.events.mouseOut&&D(this,"mouseOut"),c&&!a.stickyTracking&&(!c.shared||this.noSharedTooltip)&&c.hide(),this.setState(),b.hoverSeries=null},setState:function(a){var b=this.options,c=this.graph,d=this.graphNeg,e=b.states,b=b.lineWidth,a=a||"";this.state!==a&&(this.state=a,e[a]&&e[a].enabled===!1||(a&&(b=e[a].lineWidth||b+1),c&&!c.dashstyle&&(a={"stroke-width":b},c.attr(a),d&&d.attr(a))))},setVisible:function(a,b){var f,c=this,d=c.chart,e=c.legendItem,g=d.options.chart.ignoreHiddenSeries,h=c.visible;f=(c.visible=a=c.userOptions.visible=a===t?!h:a)?"show":"hide",p(["group","dataLabelsGroup","markerGroup","tracker"],function(a){c[a]&&c[a][f]()}),d.hoverSeries===c&&c.onMouseOut(),e&&d.legend.colorizeItem(c,a),c.isDirty=!0,c.options.stacking&&p(d.series,function(a){a.options.stacking&&a.visible&&(a.isDirty=!0)}),p(c.linkedSeries,function(b){b.setVisible(a,!1)}),g&&(d.isDirtyBox=!0),b!==!1&&d.redraw(),D(c,f)},setTooltipPoints:function(a){var c,d,h,i,b=[],e=this.xAxis,f=e&&e.getExtremes(),g=e?e.tooltipLen||e.len:this.chart.plotSizeX,j=[];if(this.options.enableMouseTracking!==!1&&!this.singularTooltips){for(a&&(this.tooltipPoints=null),p(this.segments||this.points,function(a){b=b.concat(a)}),e&&e.reversed&&(b=b.reverse()),this.orderTooltipPoints&&this.orderTooltipPoints(b),a=b.length,i=0;a>i;i++)if(e=b[i],c=e.x,c>=f.min&&c<=f.max)for(h=b[i+1],c=d===t?0:d+1,d=b[i+1]?C(v(0,T((e.clientX+(h?h.wrappedClientX||h.clientX:g))/2)),g):g;c>=0&&d>=c;)j[c++]=e;this.tooltipPoints=j}},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=a===t?!this.selected:a,this.checkbox&&(this.checkbox.checked=a),D(this,a?"select":"unselect")},drawTracker:S.drawTrackerGraph}),q(R,{Axis:la,Chart:Ya,Color:ya,Point:Ea,Tick:Sa,Renderer:Za,Series:O,SVGElement:P,SVGRenderer:ta,arrayMin:Na,arrayMax:Ba,charts:V,dateFormat:cb,format:Ia,pathAnim:ub,getOptions:function(){return E},hasBidiBug:Nb,isTouchDevice:Jb,numberFormat:Ga,seriesTypes:F,setOptions:function(a){return E=w(!0,E,a),Cb(),E},addEvent:K,removeEvent:W,createElement:Y,discardElement:Pa,css:G,each:p,extend:q,map:Ua,merge:w,pick:m,splat:qa,extendClass:ka,pInt:z,wrap:Ma,svg:aa,canvas:fa,vml:!aa&&!fa,product:"Highcharts",version:"4.0.1"})}(),jQuery(document).ready(function($){$("#filter_action").select2(),$("#filter_action").change(function(){var $this=$(this);"submitted"==$this.val()?$("#form-filter-input").show():($("#form-filter-input").hide(),$("#filter_form").select2("val","any form"))}),$("#view-all-do-not-track-selectors").click(function(){$(".form-do-not-track, #view-less-do-not-track-selectors").not(".do-not-track-always-show").show(),$("#view-all-do-not-track-selectors").hide()}),$("#view-less-do-not-track-selectors").click(function(){$(".form-do-not-track, #view-less-do-not-track-selectors").not(".do-not-track-always-show").hide(),$("#view-all-do-not-track-selectors").show()}),$("#filter_content").select2({query:function(query){var key=query.term;$.ajax({type:"POST",url:li_admin_ajax.ajax_url,data:{action:"leadin_get_posts_and_pages",search_term:key},success:function(data){var i,json_data=jQuery.parseJSON(data),data_test={results:[]};for(i=0;i<json_data.length;i++)data_test.results.push({id:json_data[i].post_title,text:json_data[i].post_title});query.callback(data_test)}})},initSelection:function(){$("#filter_content").val()?$("#filter_content").select2("data",{id:$("#filter_content").val(),text:$("#filter_content").val()}):$("#filter_content").select2("data",{id:"any page",text:"any page"})}}),$("#filter_form").select2({query:function(query){var key=query.term;$.ajax({type:"POST",url:li_admin_ajax.ajax_url,data:{action:"leadin_get_form_selectors",search_term:key},success:function(data){var i,json_data=jQuery.parseJSON(data),data_test={results:[]};for(i=0;i<json_data.length;i++)data_test.results.push({id:json_data[i],text:json_data[i]});query.callback(data_test)}})},initSelection:function(){$("#filter_form").val()?$("#filter_form").select2("data",{id:$("#filter_form").val(),text:$("#filter_form").val()}):$("#filter_form").select2("data",{id:"any form",text:"any form"})}}),$("#leadin-contact-status").change(function(){$("#leadin-contact-status-button").addClass("button-primary")}),$("input[name=popup-position]:radio").change(function(){$("#btn-activate-subscribe").attr("href",window.location.href+"&leadin_action=activate&power_up=subscribe_widget&redirect_to="+encodeURIComponent(window.location.href+"&activate_popup=true&popup_position="+$("input:radio[name='popup-position']:checked").val()))}),$("#li_subscribe_vex_class, #li_subscribe_heading, #li_subscribe_text, #li_subscribe_btn_label, #li_subscribe_name_fields:checkbox, #li_subscribe_phone_field:checkbox").change(function(){var preview_link=$("#wp-admin-bar-view-site a.ab-item").attr("href")+"?preview-subscribe=1";preview_link+="&lis_heading="+$("#li_subscribe_heading").val(),preview_link+="&lis_desc="+$("#li_subscribe_text").val(),preview_link+="&lis_show_names="+($("#li_subscribe_name_fields").is(":checked")?1:0),preview_link+="&lis_show_phone="+($("#li_subscribe_phone_field").is(":checked")?1:0),preview_link+="&lis_btn_label="+$("#li_subscribe_btn_label").val(),preview_link+="&lis_vex_class="+$("#li_subscribe_vex_class option:selected").val(),$("#preview-popup-link").attr("href",preview_link)})}),jQuery(document).ready(function($){var $bulk_opt_selected=$('.bulkactions select option[value="add_tag_to_selected"], .bulkactions select option[value="remove_tag_from_selected"], .bulkactions select option[value="delete_selected"]');$("#leadin-contacts input:checkbox").not("thead input:checkbox, tfoot input:checkbox").bind("change",function(){var cb_count=0,selected_vals="",$btn_selected=$("#leadin-export-selected-leads"),$input_selected_vals=$(".leadin-selected-contacts"),$cb_selected=$("#leadin-contacts input:checkbox:checked").not("thead input:checkbox, tfoot input:checkbox");$cb_selected.length>0?($btn_selected.attr("disabled",!1),$bulk_opt_selected.attr("disabled",!1)):($btn_selected.attr("disabled",!0),$bulk_opt_selected.attr("disabled",!0)),$cb_selected.each(function(){selected_vals+=$(this).val(),cb_count!=$cb_selected.length-1&&(selected_vals+=","),cb_count++}),$input_selected_vals.val(selected_vals),$(".selected-contacts-count").text(cb_count)}),$("#cb-select-all-1, #cb-select-all-2").bind("change",function(){var cb_count=0,selected_vals="",$this=$(this),$btn_selected=$("#leadin-export-selected-leads"),$cb_selected=$("#leadin-contacts input:checkbox").not("thead input:checkbox, tfoot input:checkbox"),$input_selected_vals=$(".leadin-selected-contacts");$cb_selected.each(function(){selected_vals+=$(this).val(),cb_count!=$cb_selected.length-1&&(selected_vals+=","),cb_count++}),$input_selected_vals.val(selected_vals),$this.is(":checked")?($btn_selected.attr("disabled",!1),$bulk_opt_selected.attr("disabled",!1)):($btn_selected.attr("disabled",!0),$bulk_opt_selected.attr("disabled",!0),$(".selected-contacts-count").text($("#contact-count").text())),$(".selected-contacts-count").text(cb_count)}),$(".postbox .handlediv").bind("click",function(){var $postbox=$(this).parent();$postbox.hasClass("closed")?$postbox.removeClass("closed"):$postbox.addClass("closed")}),$(".selected-contacts-count").text($("#contact-count").text()),$bulk_opt_selected.attr("disabled",!0),$(".bulkactions select").change(function(){{var $this=$(this);$("#contact-count").text()}"add_tag_to_all"==$this.val()||"add_tag_to_selected"==$this.val()?($("#bulk-edit-tags h2").html($("#bulk-edit-tags h2").html().replace("remove from","add to")),$("#bulk-edit-button").val("Add Tag"),$("#bulk-edit-tag-action").val("add_tag"),tb_show("","#TB_inline?width=400&height=175&inlineId=bulk-edit-tags"),$(".bulkactions select").val("-1")):("remove_tag_from_all"==$this.val()||"remove_tag_from_selected"==$this.val())&&($("#bulk-edit-tags h2").html($("#bulk-edit-tags h2").html().replace("add to","remove from")),$("#bulk-edit-button").val("Remove Tag"),$("#bulk-edit-tag-action").val("remove_tag"),tb_show("","#TB_inline?width=400&height=175&inlineId=bulk-edit-tags"),$(".bulkactions select").val("-1"))})}),function($){"undefined"==typeof $.fn.each2&&$.extend($.fn,{each2:function(c){for(var j=$([0]),i=-1,l=this.length;++i<l&&(j.context=j[0]=this[i])&&c.call(j[0],i,j)!==!1;);return this}})}(jQuery),function($,undefined){"use strict";function reinsertElement(element){var placeholder=$(document.createTextNode(""));element.before(placeholder),placeholder.before(element),placeholder.remove()}function stripDiacritics(str){function match(a){return DIACRITICS[a]||a}return str.replace(/[^\u0000-\u007E]/g,match)}function indexOf(value,array){for(var i=0,l=array.length;l>i;i+=1)if(equal(value,array[i]))return i;return-1}function measureScrollbar(){var $template=$(MEASURE_SCROLLBAR_TEMPLATE);$template.appendTo("body");var dim={width:$template.width()-$template[0].clientWidth,height:$template.height()-$template[0].clientHeight};return $template.remove(),dim}function equal(a,b){return a===b?!0:a===undefined||b===undefined?!1:null===a||null===b?!1:a.constructor===String?a+""==b+"":b.constructor===String?b+""==a+"":!1}function splitVal(string,separator){var val,i,l;if(null===string||string.length<1)return[];for(val=string.split(separator),i=0,l=val.length;l>i;i+=1)val[i]=$.trim(val[i]);return val}function getSideBorderPadding(element){return element.outerWidth(!1)-element.width()}function installKeyUpChangeEvent(element){var key="keyup-change-value";element.on("keydown",function(){$.data(element,key)===undefined&&$.data(element,key,element.val())}),element.on("keyup",function(){var val=$.data(element,key);val!==undefined&&element.val()!==val&&($.removeData(element,key),element.trigger("keyup-change"))})}function installFilteredMouseMove(element){element.on("mousemove",function(e){var lastpos=lastMousePosition;(lastpos===undefined||lastpos.x!==e.pageX||lastpos.y!==e.pageY)&&$(e.target).trigger("mousemove-filtered",e)})}function debounce(quietMillis,fn,ctx){ctx=ctx||undefined;var timeout;return function(){var args=arguments;window.clearTimeout(timeout),timeout=window.setTimeout(function(){fn.apply(ctx,args)},quietMillis)}}function installDebouncedScroll(threshold,element){var notify=debounce(threshold,function(e){element.trigger("scroll-debounced",e)});element.on("scroll",function(e){indexOf(e.target,element.get())>=0&&notify(e)})}function focus($el){$el[0]!==document.activeElement&&window.setTimeout(function(){var range,el=$el[0],pos=$el.val().length;$el.focus();var isVisible=el.offsetWidth>0||el.offsetHeight>0;isVisible&&el===document.activeElement&&(el.setSelectionRange?el.setSelectionRange(pos,pos):el.createTextRange&&(range=el.createTextRange(),range.collapse(!1),range.select()))},0)}function getCursorInfo(el){el=$(el)[0];var offset=0,length=0;if("selectionStart"in el)offset=el.selectionStart,length=el.selectionEnd-offset;else if("selection"in document){el.focus();var sel=document.selection.createRange();length=document.selection.createRange().text.length,sel.moveStart("character",-el.value.length),offset=sel.text.length-length}return{offset:offset,length:length}}function killEvent(event){event.preventDefault(),event.stopPropagation()}function killEventImmediately(event){event.preventDefault(),event.stopImmediatePropagation()}function measureTextWidth(e){if(!sizer){var style=e[0].currentStyle||window.getComputedStyle(e[0],null);sizer=$(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:style.fontSize,fontFamily:style.fontFamily,fontStyle:style.fontStyle,fontWeight:style.fontWeight,letterSpacing:style.letterSpacing,textTransform:style.textTransform,whiteSpace:"nowrap"}),sizer.attr("class","select2-sizer"),$("body").append(sizer)
6
- }return sizer.text(e.val()),sizer.width()}function syncCssClasses(dest,src,adapter){var classes,adapted,replacements=[];classes=dest.attr("class"),classes&&(classes=""+classes,$(classes.split(" ")).each2(function(){0===this.indexOf("select2-")&&replacements.push(this)})),classes=src.attr("class"),classes&&(classes=""+classes,$(classes.split(" ")).each2(function(){0!==this.indexOf("select2-")&&(adapted=adapter(this),adapted&&replacements.push(adapted))})),dest.attr("class",replacements.join(" "))}function markMatch(text,term,markup,escapeMarkup){var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())),tl=term.length;return 0>match?void markup.push(escapeMarkup(text)):(markup.push(escapeMarkup(text.substring(0,match))),markup.push("<span class='select2-match'>"),markup.push(escapeMarkup(text.substring(match,match+tl))),markup.push("</span>"),void markup.push(escapeMarkup(text.substring(match+tl,text.length))))}function defaultEscapeMarkup(markup){var replace_map={"\\":"&#92;","&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#47;"};return String(markup).replace(/[&<>"'\/\\]/g,function(match){return replace_map[match]})}function ajax(options){var timeout,handler=null,quietMillis=options.quietMillis||100,ajaxUrl=options.url,self=this;return function(query){window.clearTimeout(timeout),timeout=window.setTimeout(function(){var data=options.data,url=ajaxUrl,transport=options.transport||$.fn.select2.ajaxDefaults.transport,deprecated={type:options.type||"GET",cache:options.cache||!1,jsonpCallback:options.jsonpCallback||undefined,dataType:options.dataType||"json"},params=$.extend({},$.fn.select2.ajaxDefaults.params,deprecated);data=data?data.call(self,query.term,query.page,query.context):null,url="function"==typeof url?url.call(self,query.term,query.page,query.context):url,handler&&"function"==typeof handler.abort&&handler.abort(),options.params&&($.isFunction(options.params)?$.extend(params,options.params.call(self)):$.extend(params,options.params)),$.extend(params,{url:url,dataType:options.dataType,data:data,success:function(data){var results=options.results(data,query.page);query.callback(results)}}),handler=transport.call(self,params)},quietMillis)}}function local(options){var dataText,tmp,data=options,text=function(item){return""+item.text};$.isArray(data)&&(tmp=data,data={results:tmp}),$.isFunction(data)===!1&&(tmp=data,data=function(){return tmp});var dataItem=data();return dataItem.text&&(text=dataItem.text,$.isFunction(text)||(dataText=dataItem.text,text=function(item){return item[dataText]})),function(query){var process,t=query.term,filtered={results:[]};return""===t?void query.callback(data()):(process=function(datum,collection){var group,attr;if(datum=datum[0],datum.children){group={};for(attr in datum)datum.hasOwnProperty(attr)&&(group[attr]=datum[attr]);group.children=[],$(datum.children).each2(function(i,childDatum){process(childDatum,group.children)}),(group.children.length||query.matcher(t,text(group),datum))&&collection.push(group)}else query.matcher(t,text(datum),datum)&&collection.push(datum)},$(data().results).each2(function(i,datum){process(datum,filtered.results)}),void query.callback(filtered))}}function tags(data){var isFunc=$.isFunction(data);return function(query){var t=query.term,filtered={results:[]},result=isFunc?data(query):data;$.isArray(result)&&($(result).each(function(){var isObject=this.text!==undefined,text=isObject?this.text:this;(""===t||query.matcher(t,text))&&filtered.results.push(isObject?this:{id:this,text:this})}),query.callback(filtered))}}function checkFormatter(formatter,formatterName){if($.isFunction(formatter))return!0;if(!formatter)return!1;if("string"==typeof formatter)return!0;throw new Error(formatterName+" must be a string, function, or falsy value")}function evaluate(val){if($.isFunction(val)){var args=Array.prototype.slice.call(arguments,1);return val.apply(null,args)}return val}function countResults(results){var count=0;return $.each(results,function(i,item){item.children?count+=countResults(item.children):count++}),count}function defaultTokenizer(input,selection,selectCallback,opts){var token,index,i,l,separator,original=input,dupe=!1;if(!opts.createSearchChoice||!opts.tokenSeparators||opts.tokenSeparators.length<1)return undefined;for(;;){for(index=-1,i=0,l=opts.tokenSeparators.length;l>i&&(separator=opts.tokenSeparators[i],index=input.indexOf(separator),!(index>=0));i++);if(0>index)break;if(token=input.substring(0,index),input=input.substring(index+separator.length),token.length>0&&(token=opts.createSearchChoice.call(this,token,selection),token!==undefined&&null!==token&&opts.id(token)!==undefined&&null!==opts.id(token))){for(dupe=!1,i=0,l=selection.length;l>i;i++)if(equal(opts.id(token),opts.id(selection[i]))){dupe=!0;break}dupe||selectCallback(token)}}return original!==input?input:void 0}function cleanupJQueryElements(){var self=this;Array.prototype.forEach.call(arguments,function(element){self[element].remove(),self[element]=null})}function clazz(SuperClass,methods){var constructor=function(){};return constructor.prototype=new SuperClass,constructor.prototype.constructor=constructor,constructor.prototype.parent=SuperClass.prototype,constructor.prototype=$.extend(constructor.prototype,methods),constructor}if(window.Select2===undefined){var KEY,AbstractSelect2,SingleSelect2,MultiSelect2,nextUid,sizer,$document,scrollBarDimensions,lastMousePosition={x:0,y:0},KEY={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(k){switch(k=k.which?k.which:k){case KEY.LEFT:case KEY.RIGHT:case KEY.UP:case KEY.DOWN:return!0}return!1},isControl:function(e){var k=e.which;switch(k){case KEY.SHIFT:case KEY.CTRL:case KEY.ALT:return!0}return e.metaKey?!0:!1},isFunctionKey:function(k){return k=k.which?k.which:k,k>=112&&123>=k}},MEASURE_SCROLLBAR_TEMPLATE="<div class='select2-measure-scrollbar'></div>",DIACRITICS={"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z"};$document=$(document),nextUid=function(){var counter=1;return function(){return counter++}}(),$document.on("mousemove",function(e){lastMousePosition.x=e.pageX,lastMousePosition.y=e.pageY}),AbstractSelect2=clazz(Object,{bind:function(func){var self=this;return function(){func.apply(self,arguments)}},init:function(opts){var results,search,resultsSelector=".select2-results";this.opts=opts=this.prepareOpts(opts),this.id=opts.id,opts.element.data("select2")!==undefined&&null!==opts.element.data("select2")&&opts.element.data("select2").destroy(),this.container=this.createContainer(),this.liveRegion=$("<span>",{role:"status","aria-live":"polite"}).addClass("select2-hidden-accessible").appendTo(document.body),this.containerId="s2id_"+(opts.element.attr("id")||"autogen"+nextUid()),this.containerEventName=this.containerId.replace(/([.])/g,"_").replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.container.attr("id",this.containerId),this.container.attr("title",opts.element.attr("title")),this.body=$("body"),syncCssClasses(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",opts.element.attr("style")),this.container.css(evaluate(opts.containerCss)),this.container.addClass(evaluate(opts.containerCssClass)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",killEvent),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),syncCssClasses(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(evaluate(opts.dropdownCssClass)),this.dropdown.data("select2",this),this.dropdown.on("click",killEvent),this.results=results=this.container.find(resultsSelector),this.search=search=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",killEvent),installFilteredMouseMove(this.results),this.dropdown.on("mousemove-filtered",resultsSelector,this.bind(this.highlightUnderEvent)),this.dropdown.on("touchstart touchmove touchend",resultsSelector,this.bind(function(event){this._touchEvent=!0,this.highlightUnderEvent(event)})),this.dropdown.on("touchmove",resultsSelector,this.bind(this.touchMoved)),this.dropdown.on("touchstart touchend",resultsSelector,this.bind(this.clearTouchMoved)),this.dropdown.on("click",this.bind(function(){this._touchEvent&&(this._touchEvent=!1,this.selectHighlighted())})),installDebouncedScroll(80,this.results),this.dropdown.on("scroll-debounced",resultsSelector,this.bind(this.loadMoreIfNeeded)),$(this.container).on("change",".select2-input",function(e){e.stopPropagation()}),$(this.dropdown).on("change",".select2-input",function(e){e.stopPropagation()}),$.fn.mousewheel&&results.mousewheel(function(e,delta,deltaX,deltaY){var top=results.scrollTop();deltaY>0&&0>=top-deltaY?(results.scrollTop(0),killEvent(e)):0>deltaY&&results.get(0).scrollHeight-results.scrollTop()+deltaY<=results.height()&&(results.scrollTop(results.get(0).scrollHeight-results.height()),killEvent(e))}),installKeyUpChangeEvent(search),search.on("keyup-change input paste",this.bind(this.updateResults)),search.on("focus",function(){search.addClass("select2-focused")}),search.on("blur",function(){search.removeClass("select2-focused")}),this.dropdown.on("mouseup",resultsSelector,this.bind(function(e){$(e.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(e),this.selectHighlighted(e))})),this.dropdown.on("click mouseup mousedown touchstart touchend focusin",function(e){e.stopPropagation()}),this.nextSearchTerm=undefined,$.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==opts.maximumInputLength&&this.search.attr("maxlength",opts.maximumInputLength);var disabled=opts.element.prop("disabled");disabled===undefined&&(disabled=!1),this.enable(!disabled);var readonly=opts.element.prop("readonly");readonly===undefined&&(readonly=!1),this.readonly(readonly),scrollBarDimensions=scrollBarDimensions||measureScrollbar(),this.autofocus=opts.element.prop("autofocus"),opts.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.search.attr("placeholder",opts.searchInputPlaceholder)},destroy:function(){var element=this.opts.element,select2=element.data("select2");this.close(),this.propertyObserver&&(this.propertyObserver.disconnect(),this.propertyObserver=null),select2!==undefined&&(select2.container.remove(),select2.liveRegion.remove(),select2.dropdown.remove(),element.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||!1),this.elementTabIndex?element.attr({tabindex:this.elementTabIndex}):element.removeAttr("tabindex"),element.show()),cleanupJQueryElements.call(this,"container","liveRegion","dropdown","results","search")},optionToData:function(element){return element.is("option")?{id:element.prop("value"),text:element.text(),element:element.get(),css:element.attr("class"),disabled:element.prop("disabled"),locked:equal(element.attr("locked"),"locked")||equal(element.data("locked"),!0)}:element.is("optgroup")?{text:element.attr("label"),children:[],element:element.get(),css:element.attr("class")}:void 0},prepareOpts:function(opts){var element,select,idKey,ajaxUrl,self=this;if(element=opts.element,"select"===element.get(0).tagName.toLowerCase()&&(this.select=select=opts.element),select&&$.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in opts)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a <select> element.")}),opts=$.extend({},{populateResults:function(container,results,query){var populate,id=this.opts.id,liveRegion=this.liveRegion;(populate=function(results,container,depth){var i,l,result,selectable,disabled,compound,node,label,innerContainer,formatted;for(results=opts.sortResults(results,container,query),i=0,l=results.length;l>i;i+=1)result=results[i],disabled=result.disabled===!0,selectable=!disabled&&id(result)!==undefined,compound=result.children&&result.children.length>0,node=$("<li></li>"),node.addClass("select2-results-dept-"+depth),node.addClass("select2-result"),node.addClass(selectable?"select2-result-selectable":"select2-result-unselectable"),disabled&&node.addClass("select2-disabled"),compound&&node.addClass("select2-result-with-children"),node.addClass(self.opts.formatResultCssClass(result)),node.attr("role","presentation"),label=$(document.createElement("div")),label.addClass("select2-result-label"),label.attr("id","select2-result-label-"+nextUid()),label.attr("role","option"),formatted=opts.formatResult(result,label,query,self.opts.escapeMarkup),formatted!==undefined&&(label.html(formatted),node.append(label)),compound&&(innerContainer=$("<ul></ul>"),innerContainer.addClass("select2-result-sub"),populate(result.children,innerContainer,depth+1),node.append(innerContainer)),node.data("select2-data",result),container.append(node);liveRegion.text(opts.formatMatches(results.length))})(results,container,0)}},$.fn.select2.defaults,opts),"function"!=typeof opts.id&&(idKey=opts.id,opts.id=function(e){return e[idKey]}),$.isArray(opts.element.data("select2Tags"))){if("tags"in opts)throw"tags specified as both an attribute 'data-select2-tags' and in options of Select2 "+opts.element.attr("id");opts.tags=opts.element.data("select2Tags")}if(select?(opts.query=this.bind(function(query){var children,placeholderOption,process,data={results:[],more:!1},term=query.term;process=function(element,collection){var group;element.is("option")?query.matcher(term,element.text(),element)&&collection.push(self.optionToData(element)):element.is("optgroup")&&(group=self.optionToData(element),element.children().each2(function(i,elm){process(elm,group.children)}),group.children.length>0&&collection.push(group))},children=element.children(),this.getPlaceholder()!==undefined&&children.length>0&&(placeholderOption=this.getPlaceholderOption(),placeholderOption&&(children=children.not(placeholderOption))),children.each2(function(i,elm){process(elm,data.results)}),query.callback(data)}),opts.id=function(e){return e.id}):"query"in opts||("ajax"in opts?(ajaxUrl=opts.element.data("ajax-url"),ajaxUrl&&ajaxUrl.length>0&&(opts.ajax.url=ajaxUrl),opts.query=ajax.call(opts.element,opts.ajax)):"data"in opts?opts.query=local(opts.data):"tags"in opts&&(opts.query=tags(opts.tags),opts.createSearchChoice===undefined&&(opts.createSearchChoice=function(term){return{id:$.trim(term),text:$.trim(term)}}),opts.initSelection===undefined&&(opts.initSelection=function(element,callback){var data=[];$(splitVal(element.val(),opts.separator)).each(function(){var obj={id:this,text:this},tags=opts.tags;$.isFunction(tags)&&(tags=tags()),$(tags).each(function(){return equal(this.id,obj.id)?(obj=this,!1):void 0}),data.push(obj)}),callback(data)}))),"function"!=typeof opts.query)throw"query function not defined for Select2 "+opts.element.attr("id");if("top"===opts.createSearchChoicePosition)opts.createSearchChoicePosition=function(list,item){list.unshift(item)};else if("bottom"===opts.createSearchChoicePosition)opts.createSearchChoicePosition=function(list,item){list.push(item)};else if("function"!=typeof opts.createSearchChoicePosition)throw"invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function";return opts},monitorSource:function(){var sync,observer,el=this.opts.element;el.on("change.select2",this.bind(function(){this.opts.element.data("select2-change-triggered")!==!0&&this.initSelection()})),sync=this.bind(function(){var disabled=el.prop("disabled");disabled===undefined&&(disabled=!1),this.enable(!disabled);var readonly=el.prop("readonly");readonly===undefined&&(readonly=!1),this.readonly(readonly),syncCssClasses(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.addClass(evaluate(this.opts.containerCssClass)),syncCssClasses(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(evaluate(this.opts.dropdownCssClass))}),el.length&&el[0].attachEvent&&el.each(function(){this.attachEvent("onpropertychange",sync)}),observer=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,observer!==undefined&&(this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),this.propertyObserver=new observer(function(mutations){mutations.forEach(sync)}),this.propertyObserver.observe(el.get(0),{attributes:!0,subtree:!1}))},triggerSelect:function(data){var evt=$.Event("select2-selecting",{val:this.id(data),object:data});return this.opts.element.trigger(evt),!evt.isDefaultPrevented()},triggerChange:function(details){details=details||{},details=$.extend({},details,{type:"change",val:this.val()}),this.opts.element.data("select2-change-triggered",!0),this.opts.element.trigger(details),this.opts.element.data("select2-change-triggered",!1),this.opts.element.click(),this.opts.blurOnChange&&this.opts.element.blur()},isInterfaceEnabled:function(){return this.enabledInterface===!0},enableInterface:function(){var enabled=this._enabled&&!this._readonly,disabled=!enabled;return enabled===this.enabledInterface?!1:(this.container.toggleClass("select2-container-disabled",disabled),this.close(),this.enabledInterface=enabled,!0)},enable:function(enabled){enabled===undefined&&(enabled=!0),this._enabled!==enabled&&(this._enabled=enabled,this.opts.element.prop("disabled",!enabled),this.enableInterface())},disable:function(){this.enable(!1)},readonly:function(enabled){enabled===undefined&&(enabled=!1),this._readonly!==enabled&&(this._readonly=enabled,this.opts.element.prop("readonly",enabled),this.enableInterface())},opened:function(){return this.container.hasClass("select2-dropdown-open")},positionDropdown:function(){var bodyOffset,above,changeDirection,css,resultsListNode,$dropdown=this.dropdown,offset=this.container.offset(),height=this.container.outerHeight(!1),width=this.container.outerWidth(!1),dropHeight=$dropdown.outerHeight(!1),$window=$(window),windowWidth=$window.width(),windowHeight=$window.height(),viewPortRight=$window.scrollLeft()+windowWidth,viewportBottom=$window.scrollTop()+windowHeight,dropTop=offset.top+height,dropLeft=offset.left,enoughRoomBelow=viewportBottom>=dropTop+dropHeight,enoughRoomAbove=offset.top-dropHeight>=$window.scrollTop(),dropWidth=$dropdown.outerWidth(!1),enoughRoomOnRight=viewPortRight>=dropLeft+dropWidth,aboveNow=$dropdown.hasClass("select2-drop-above");aboveNow?(above=!0,!enoughRoomAbove&&enoughRoomBelow&&(changeDirection=!0,above=!1)):(above=!1,!enoughRoomBelow&&enoughRoomAbove&&(changeDirection=!0,above=!0)),changeDirection&&($dropdown.hide(),offset=this.container.offset(),height=this.container.outerHeight(!1),width=this.container.outerWidth(!1),dropHeight=$dropdown.outerHeight(!1),viewPortRight=$window.scrollLeft()+windowWidth,viewportBottom=$window.scrollTop()+windowHeight,dropTop=offset.top+height,dropLeft=offset.left,dropWidth=$dropdown.outerWidth(!1),enoughRoomOnRight=viewPortRight>=dropLeft+dropWidth,$dropdown.show(),this.focusSearch()),this.opts.dropdownAutoWidth?(resultsListNode=$(".select2-results",$dropdown)[0],$dropdown.addClass("select2-drop-auto-width"),$dropdown.css("width",""),dropWidth=$dropdown.outerWidth(!1)+(resultsListNode.scrollHeight===resultsListNode.clientHeight?0:scrollBarDimensions.width),dropWidth>width?width=dropWidth:dropWidth=width,dropHeight=$dropdown.outerHeight(!1),enoughRoomOnRight=viewPortRight>=dropLeft+dropWidth):this.container.removeClass("select2-drop-auto-width"),"static"!==this.body.css("position")&&(bodyOffset=this.body.offset(),dropTop-=bodyOffset.top,dropLeft-=bodyOffset.left),enoughRoomOnRight||(dropLeft=offset.left+this.container.outerWidth(!1)-dropWidth),css={left:dropLeft,width:width},above?(css.top=offset.top-dropHeight,css.bottom="auto",this.container.addClass("select2-drop-above"),$dropdown.addClass("select2-drop-above")):(css.top=dropTop,css.bottom="auto",this.container.removeClass("select2-drop-above"),$dropdown.removeClass("select2-drop-above")),css=$.extend(css,evaluate(this.opts.dropdownCss)),$dropdown.css(css)},shouldOpen:function(){var event;return this.opened()?!1:this._enabled===!1||this._readonly===!0?!1:(event=$.Event("select2-opening"),this.opts.element.trigger(event),!event.isDefaultPrevented())},clearDropdownAlignmentPreference:function(){this.container.removeClass("select2-drop-above"),this.dropdown.removeClass("select2-drop-above")},open:function(){return this.shouldOpen()?(this.opening(),!0):!1},opening:function(){var mask,cid=this.containerEventName,scroll="scroll."+cid,resize="resize."+cid,orient="orientationchange."+cid;this.container.addClass("select2-dropdown-open").addClass("select2-container-active"),this.clearDropdownAlignmentPreference(),this.dropdown[0]!==this.body.children().last()[0]&&this.dropdown.detach().appendTo(this.body),mask=$("#select2-drop-mask"),0==mask.length&&(mask=$(document.createElement("div")),mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask"),mask.hide(),mask.appendTo(this.body),mask.on("mousedown touchstart click",function(e){reinsertElement(mask);var self,dropdown=$("#select2-drop");dropdown.length>0&&(self=dropdown.data("select2"),self.opts.selectOnBlur&&self.selectHighlighted({noFocus:!0}),self.close(),e.preventDefault(),e.stopPropagation())})),this.dropdown.prev()[0]!==mask[0]&&this.dropdown.before(mask),$("#select2-drop").removeAttr("id"),this.dropdown.attr("id","select2-drop"),mask.show(),this.positionDropdown(),this.dropdown.show(),this.positionDropdown(),this.dropdown.addClass("select2-drop-active");var that=this;this.container.parents().add(window).each(function(){$(this).on(resize+" "+scroll+" "+orient,function(){that.opened()&&that.positionDropdown()})})},close:function(){if(this.opened()){var cid=this.containerEventName,scroll="scroll."+cid,resize="resize."+cid,orient="orientationchange."+cid;this.container.parents().add(window).each(function(){$(this).off(scroll).off(resize).off(orient)}),this.clearDropdownAlignmentPreference(),$("#select2-drop-mask").hide(),this.dropdown.removeAttr("id"),this.dropdown.hide(),this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active"),this.results.empty(),this.clearSearch(),this.search.removeClass("select2-active"),this.opts.element.trigger($.Event("select2-close"))}},externalSearch:function(term){this.open(),this.search.val(term),this.updateResults(!1)},clearSearch:function(){},getMaximumSelectionSize:function(){return evaluate(this.opts.maximumSelectionSize)},ensureHighlightVisible:function(){var children,index,child,hb,rb,y,more,results=this.results;if(index=this.highlight(),!(0>index)){if(0==index)return void results.scrollTop(0);children=this.findHighlightableChoices().find(".select2-result-label"),child=$(children[index]),hb=child.offset().top+child.outerHeight(!0),index===children.length-1&&(more=results.find("li.select2-more-results"),more.length>0&&(hb=more.offset().top+more.outerHeight(!0))),rb=results.offset().top+results.outerHeight(!0),hb>rb&&results.scrollTop(results.scrollTop()+(hb-rb)),y=child.offset().top-results.offset().top,0>y&&"none"!=child.css("display")&&results.scrollTop(results.scrollTop()+y)}},findHighlightableChoices:function(){return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)")},moveHighlight:function(delta){for(var choices=this.findHighlightableChoices(),index=this.highlight();index>-1&&index<choices.length;){index+=delta;var choice=$(choices[index]);if(choice.hasClass("select2-result-selectable")&&!choice.hasClass("select2-disabled")&&!choice.hasClass("select2-selected")){this.highlight(index);break}}},highlight:function(index){var choice,data,choices=this.findHighlightableChoices();return 0===arguments.length?indexOf(choices.filter(".select2-highlighted")[0],choices.get()):(index>=choices.length&&(index=choices.length-1),0>index&&(index=0),this.removeHighlight(),choice=$(choices[index]),choice.addClass("select2-highlighted"),this.search.attr("aria-activedescendant",choice.find(".select2-result-label").attr("id")),this.ensureHighlightVisible(),this.liveRegion.text(choice.text()),data=choice.data("select2-data"),void(data&&this.opts.element.trigger({type:"select2-highlight",val:this.id(data),choice:data})))},removeHighlight:function(){this.results.find(".select2-highlighted").removeClass("select2-highlighted")},touchMoved:function(){this._touchMoved=!0},clearTouchMoved:function(){this._touchMoved=!1},countSelectableResults:function(){return this.findHighlightableChoices().length},highlightUnderEvent:function(event){var el=$(event.target).closest(".select2-result-selectable");if(el.length>0&&!el.is(".select2-highlighted")){var choices=this.findHighlightableChoices();this.highlight(choices.index(el))}else 0==el.length&&this.removeHighlight()},loadMoreIfNeeded:function(){var below,results=this.results,more=results.find("li.select2-more-results"),page=this.resultsPage+1,self=this,term=this.search.val(),context=this.context;0!==more.length&&(below=more.offset().top-results.offset().top-results.height(),below<=this.opts.loadMorePadding&&(more.addClass("select2-active"),this.opts.query({element:this.opts.element,term:term,page:page,context:context,matcher:this.opts.matcher,callback:this.bind(function(data){self.opened()&&(self.opts.populateResults.call(this,results,data.results,{term:term,page:page,context:context}),self.postprocessResults(data,!1,!1),data.more===!0?(more.detach().appendTo(results).text(evaluate(self.opts.formatLoadMore,page+1)),window.setTimeout(function(){self.loadMoreIfNeeded()
7
- },10)):more.remove(),self.positionDropdown(),self.resultsPage=page,self.context=data.context,this.opts.element.trigger({type:"select2-loaded",items:data}))})})))},tokenize:function(){},updateResults:function(initial){function postRender(){search.removeClass("select2-active"),self.positionDropdown(),self.liveRegion.text(results.find(".select2-no-results,.select2-selection-limit,.select2-searching").length?results.text():self.opts.formatMatches(results.find(".select2-result-selectable").length))}function render(html){results.html(html),postRender()}var data,input,queryNumber,search=this.search,results=this.results,opts=this.opts,self=this,term=search.val(),lastTerm=$.data(this.container,"select2-last-term");if((initial===!0||!lastTerm||!equal(term,lastTerm))&&($.data(this.container,"select2-last-term",term),initial===!0||this.showSearchInput!==!1&&this.opened())){queryNumber=++this.queryCount;var maxSelSize=this.getMaximumSelectionSize();if(maxSelSize>=1&&(data=this.data(),$.isArray(data)&&data.length>=maxSelSize&&checkFormatter(opts.formatSelectionTooBig,"formatSelectionTooBig")))return void render("<li class='select2-selection-limit'>"+evaluate(opts.formatSelectionTooBig,maxSelSize)+"</li>");if(search.val().length<opts.minimumInputLength)return render(checkFormatter(opts.formatInputTooShort,"formatInputTooShort")?"<li class='select2-no-results'>"+evaluate(opts.formatInputTooShort,search.val(),opts.minimumInputLength)+"</li>":""),void(initial&&this.showSearch&&this.showSearch(!0));if(opts.maximumInputLength&&search.val().length>opts.maximumInputLength)return void render(checkFormatter(opts.formatInputTooLong,"formatInputTooLong")?"<li class='select2-no-results'>"+evaluate(opts.formatInputTooLong,search.val(),opts.maximumInputLength)+"</li>":"");opts.formatSearching&&0===this.findHighlightableChoices().length&&render("<li class='select2-searching'>"+evaluate(opts.formatSearching)+"</li>"),search.addClass("select2-active"),this.removeHighlight(),input=this.tokenize(),input!=undefined&&null!=input&&search.val(input),this.resultsPage=1,opts.query({element:opts.element,term:search.val(),page:this.resultsPage,context:null,matcher:opts.matcher,callback:this.bind(function(data){var def;if(queryNumber==this.queryCount){if(!this.opened())return void this.search.removeClass("select2-active");if(this.context=data.context===undefined?null:data.context,this.opts.createSearchChoice&&""!==search.val()&&(def=this.opts.createSearchChoice.call(self,search.val(),data.results),def!==undefined&&null!==def&&self.id(def)!==undefined&&null!==self.id(def)&&0===$(data.results).filter(function(){return equal(self.id(this),self.id(def))}).length&&this.opts.createSearchChoicePosition(data.results,def)),0===data.results.length&&checkFormatter(opts.formatNoMatches,"formatNoMatches"))return void render("<li class='select2-no-results'>"+evaluate(opts.formatNoMatches,search.val())+"</li>");results.empty(),self.opts.populateResults.call(this,results,data.results,{term:search.val(),page:this.resultsPage,context:null}),data.more===!0&&checkFormatter(opts.formatLoadMore,"formatLoadMore")&&(results.append("<li class='select2-more-results'>"+self.opts.escapeMarkup(evaluate(opts.formatLoadMore,this.resultsPage))+"</li>"),window.setTimeout(function(){self.loadMoreIfNeeded()},10)),this.postprocessResults(data,initial),postRender(),this.opts.element.trigger({type:"select2-loaded",items:data})}})})}},cancel:function(){this.close()},blur:function(){this.opts.selectOnBlur&&this.selectHighlighted({noFocus:!0}),this.close(),this.container.removeClass("select2-container-active"),this.search[0]===document.activeElement&&this.search.blur(),this.clearSearch(),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus")},focusSearch:function(){focus(this.search)},selectHighlighted:function(options){if(this._touchMoved)return void this.clearTouchMoved();var index=this.highlight(),highlighted=this.results.find(".select2-highlighted"),data=highlighted.closest(".select2-result").data("select2-data");data?(this.highlight(index),this.onSelect(data,options)):options&&options.noFocus&&this.close()},getPlaceholder:function(){var placeholderOption;return this.opts.element.attr("placeholder")||this.opts.element.attr("data-placeholder")||this.opts.element.data("placeholder")||this.opts.placeholder||((placeholderOption=this.getPlaceholderOption())!==undefined?placeholderOption.text():undefined)},getPlaceholderOption:function(){if(this.select){var firstOption=this.select.children("option").first();if(this.opts.placeholderOption!==undefined)return"first"===this.opts.placeholderOption&&firstOption||"function"==typeof this.opts.placeholderOption&&this.opts.placeholderOption(this.select);if(""===$.trim(firstOption.text())&&""===firstOption.val())return firstOption}},initContainerWidth:function(){function resolveContainerWidth(){var style,attrs,matches,i,l,attr;if("off"===this.opts.width)return null;if("element"===this.opts.width)return 0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px";if("copy"===this.opts.width||"resolve"===this.opts.width){if(style=this.opts.element.attr("style"),style!==undefined)for(attrs=style.split(";"),i=0,l=attrs.length;l>i;i+=1)if(attr=attrs[i].replace(/\s/g,""),matches=attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i),null!==matches&&matches.length>=1)return matches[1];return"resolve"===this.opts.width?(style=this.opts.element.css("width"),style.indexOf("%")>0?style:0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px"):null}return $.isFunction(this.opts.width)?this.opts.width():this.opts.width}var width=resolveContainerWidth.call(this);null!==width&&this.container.css("width",width)}}),SingleSelect2=clazz(AbstractSelect2,{createContainer:function(){var container=$(document.createElement("div")).attr({"class":"select2-container"}).html(["<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>"," <span class='select2-chosen'>&#160;</span><abbr class='select2-search-choice-close'></abbr>"," <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>","</a>","<label for='' class='select2-offscreen'></label>","<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />","<div class='select2-drop select2-display-none'>"," <div class='select2-search'>"," <label for='' class='select2-offscreen'></label>"," <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'"," aria-autocomplete='list' />"," </div>"," <ul class='select2-results' role='listbox'>"," </ul>","</div>"].join(""));return container},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var el,range,len;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.opts.shouldFocusInput(this)&&(this.search.focus(),el=this.search.get(0),el.createTextRange?(range=el.createTextRange(),range.collapse(!1),range.select()):el.setSelectionRange&&(len=this.search.val().length,el.setSelectionRange(len,len))),""===this.search.val()&&this.nextSearchTerm!=undefined&&(this.search.val(this.nextSearchTerm),this.search.select()),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger($.Event("select2-open"))},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus()},destroy:function(){$("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments),cleanupJQueryElements.call(this,"selection","focusser")},initContainer:function(){var selection,elementLabel,container=this.container,dropdown=this.dropdown,idSuffix=nextUid();this.showSearch(this.opts.minimumResultsForSearch<0?!1:!0),this.selection=selection=container.find(".select2-choice"),this.focusser=container.find(".select2-focusser"),selection.find(".select2-chosen").attr("id","select2-chosen-"+idSuffix),this.focusser.attr("aria-labelledby","select2-chosen-"+idSuffix),this.results.attr("id","select2-results-"+idSuffix),this.search.attr("aria-owns","select2-results-"+idSuffix),this.focusser.attr("id","s2id_autogen"+idSuffix),elementLabel=$("label[for='"+this.opts.element.attr("id")+"']"),this.focusser.prev().text(elementLabel.text()).attr("for",this.focusser.attr("id"));var originalTitle=this.opts.element.attr("title");this.opts.element.attr("title",originalTitle||elementLabel.text()),this.focusser.attr("tabindex",this.elementTabIndex),this.search.attr("id",this.focusser.attr("id")+"_search"),this.search.prev().text($("label[for='"+this.focusser.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("keydown",this.bind(function(e){if(this.isInterfaceEnabled()){if(e.which===KEY.PAGE_UP||e.which===KEY.PAGE_DOWN)return void killEvent(e);switch(e.which){case KEY.UP:case KEY.DOWN:return this.moveHighlight(e.which===KEY.UP?-1:1),void killEvent(e);case KEY.ENTER:return this.selectHighlighted(),void killEvent(e);case KEY.TAB:return void this.selectHighlighted({noFocus:!0});case KEY.ESC:return this.cancel(e),void killEvent(e)}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body.get(0)&&window.setTimeout(this.bind(function(){this.opened()&&this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(e){if(this.isInterfaceEnabled()&&e.which!==KEY.TAB&&!KEY.isControl(e)&&!KEY.isFunctionKey(e)&&e.which!==KEY.ESC){if(this.opts.openOnEnter===!1&&e.which===KEY.ENTER)return void killEvent(e);if(e.which==KEY.DOWN||e.which==KEY.UP||e.which==KEY.ENTER&&this.opts.openOnEnter){if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey)return;return this.open(),void killEvent(e)}return e.which==KEY.DELETE||e.which==KEY.BACKSPACE?(this.opts.allowClear&&this.clear(),void killEvent(e)):void 0}})),installKeyUpChangeEvent(this.focusser),this.focusser.on("keyup-change input",this.bind(function(e){if(this.opts.minimumResultsForSearch>=0){if(e.stopPropagation(),this.opened())return;this.open()}})),selection.on("mousedown touchstart","abbr",this.bind(function(e){this.isInterfaceEnabled()&&(this.clear(),killEventImmediately(e),this.close(),this.selection.focus())})),selection.on("mousedown touchstart",this.bind(function(e){reinsertElement(selection),this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),killEvent(e)})),dropdown.on("mousedown touchstart",this.bind(function(){this.opts.shouldFocusInput(this)&&this.search.focus()})),selection.on("focus",this.bind(function(e){killEvent(e)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger($.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.setPlaceholder()},clear:function(triggerChange){var data=this.selection.data("select2-data");if(data){var evt=$.Event("select2-clearing");if(this.opts.element.trigger(evt),evt.isDefaultPrevented())return;var placeholderOption=this.getPlaceholderOption();this.opts.element.val(placeholderOption?placeholderOption.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),triggerChange!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(data),choice:data}),this.triggerChange({removed:data}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var self=this;this.opts.initSelection.call(null,this.opts.element,function(selected){selected!==undefined&&null!==selected&&(self.updateSelection(selected),self.close(),self.setPlaceholder(),self.nextSearchTerm=self.opts.nextSearchTerm(selected,self.search.val()))})}},isPlaceholderOptionSelected:function(){var placeholderOption;return this.getPlaceholder()===undefined?!1:(placeholderOption=this.getPlaceholderOption())!==undefined&&placeholderOption.prop("selected")||""===this.opts.element.val()||this.opts.element.val()===undefined||null===this.opts.element.val()},prepareOpts:function(){var opts=this.parent.prepareOpts.apply(this,arguments),self=this;return"select"===opts.element.get(0).tagName.toLowerCase()?opts.initSelection=function(element,callback){var selected=element.find("option").filter(function(){return this.selected&&!this.disabled});callback(self.optionToData(selected))}:"data"in opts&&(opts.initSelection=opts.initSelection||function(element,callback){var id=element.val(),match=null;opts.query({matcher:function(term,text,el){var is_match=equal(id,opts.id(el));return is_match&&(match=el),is_match},callback:$.isFunction(callback)?function(){callback(match)}:$.noop})}),opts},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===undefined?undefined:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var placeholder=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&placeholder!==undefined){if(this.select&&this.getPlaceholderOption()===undefined)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(data,initial,noHighlightUpdate){var selected=0,self=this;if(this.findHighlightableChoices().each2(function(i,elm){return equal(self.id(elm.data("select2-data")),self.opts.element.val())?(selected=i,!1):void 0}),noHighlightUpdate!==!1&&this.highlight(initial===!0&&selected>=0?selected:0),initial===!0){var min=this.opts.minimumResultsForSearch;min>=0&&this.showSearch(countResults(data.results)>=min)}},showSearch:function(showSearchInput){this.showSearchInput!==showSearchInput&&(this.showSearchInput=showSearchInput,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!showSearchInput),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!showSearchInput),$(this.dropdown,this.container).toggleClass("select2-with-searchbox",showSearchInput))},onSelect:function(data,options){if(this.triggerSelect(data)){var old=this.opts.element.val(),oldData=this.data();this.opts.element.val(this.id(data)),this.updateSelection(data),this.opts.element.trigger({type:"select2-selected",val:this.id(data),choice:data}),this.nextSearchTerm=this.opts.nextSearchTerm(data,this.search.val()),this.close(),options&&options.noFocus||!this.opts.shouldFocusInput(this)||this.focusser.focus(),equal(old,this.id(data))||this.triggerChange({added:data,removed:oldData})}},updateSelection:function(data){var formatted,cssClass,container=this.selection.find(".select2-chosen");this.selection.data("select2-data",data),container.empty(),null!==data&&(formatted=this.opts.formatSelection(data,container,this.opts.escapeMarkup)),formatted!==undefined&&container.append(formatted),cssClass=this.opts.formatSelectionCssClass(data,container),cssClass!==undefined&&container.addClass(cssClass),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==undefined&&this.container.addClass("select2-allowclear")},val:function(){var val,triggerChange=!1,data=null,self=this,oldData=this.data();if(0===arguments.length)return this.opts.element.val();if(val=arguments[0],arguments.length>1&&(triggerChange=arguments[1]),this.select)this.select.val(val).find("option").filter(function(){return this.selected}).each2(function(i,elm){return data=self.optionToData(elm),!1}),this.updateSelection(data),this.setPlaceholder(),triggerChange&&this.triggerChange({added:data,removed:oldData});else{if(!val&&0!==val)return void this.clear(triggerChange);if(this.opts.initSelection===undefined)throw new Error("cannot call val() if initSelection() is not defined");this.opts.element.val(val),this.opts.initSelection(this.opts.element,function(data){self.opts.element.val(data?self.id(data):""),self.updateSelection(data),self.setPlaceholder(),triggerChange&&self.triggerChange({added:data,removed:oldData})})}},clearSearch:function(){this.search.val(""),this.focusser.val("")},data:function(value){var data,triggerChange=!1;return 0===arguments.length?(data=this.selection.data("select2-data"),data==undefined&&(data=null),data):(arguments.length>1&&(triggerChange=arguments[1]),void(value?(data=this.data(),this.opts.element.val(value?this.id(value):""),this.updateSelection(value),triggerChange&&this.triggerChange({added:value,removed:data})):this.clear(triggerChange)))}}),MultiSelect2=clazz(AbstractSelect2,{createContainer:function(){var container=$(document.createElement("div")).attr({"class":"select2-container select2-container-multi"}).html(["<ul class='select2-choices'>"," <li class='select2-search-field'>"," <label for='' class='select2-offscreen'></label>"," <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>"," </li>","</ul>","<div class='select2-drop select2-drop-multi select2-display-none'>"," <ul class='select2-results'>"," </ul>","</div>"].join(""));return container},prepareOpts:function(){var opts=this.parent.prepareOpts.apply(this,arguments),self=this;return"select"===opts.element.get(0).tagName.toLowerCase()?opts.initSelection=function(element,callback){var data=[];element.find("option").filter(function(){return this.selected&&!this.disabled}).each2(function(i,elm){data.push(self.optionToData(elm))}),callback(data)}:"data"in opts&&(opts.initSelection=opts.initSelection||function(element,callback){var ids=splitVal(element.val(),opts.separator),matches=[];opts.query({matcher:function(term,text,el){var is_match=$.grep(ids,function(id){return equal(id,opts.id(el))}).length;return is_match&&matches.push(el),is_match},callback:$.isFunction(callback)?function(){for(var ordered=[],i=0;i<ids.length;i++)for(var id=ids[i],j=0;j<matches.length;j++){var match=matches[j];if(equal(id,opts.id(match))){ordered.push(match),matches.splice(j,1);break}}callback(ordered)}:$.noop})}),opts},selectChoice:function(choice){var selected=this.container.find(".select2-search-choice-focus");selected.length&&choice&&choice[0]==selected[0]||(selected.length&&this.opts.element.trigger("choice-deselected",selected),selected.removeClass("select2-search-choice-focus"),choice&&choice.length&&(this.close(),choice.addClass("select2-search-choice-focus"),this.opts.element.trigger("choice-selected",choice)))},destroy:function(){$("label[for='"+this.search.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments),cleanupJQueryElements.call(this,"searchContainer","selection")},initContainer:function(){var selection,selector=".select2-choices";this.searchContainer=this.container.find(".select2-search-field"),this.selection=selection=this.container.find(selector);var _this=this;this.selection.on("click",".select2-search-choice:not(.select2-locked)",function(){_this.search[0].focus(),_this.selectChoice($(this))}),this.search.attr("id","s2id_autogen"+nextUid()),this.search.prev().text($("label[for='"+this.opts.element.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("input paste",this.bind(function(){this.isInterfaceEnabled()&&(this.opened()||this.open())})),this.search.attr("tabindex",this.elementTabIndex),this.keydowns=0,this.search.on("keydown",this.bind(function(e){if(this.isInterfaceEnabled()){++this.keydowns;var selected=selection.find(".select2-search-choice-focus"),prev=selected.prev(".select2-search-choice:not(.select2-locked)"),next=selected.next(".select2-search-choice:not(.select2-locked)"),pos=getCursorInfo(this.search);if(selected.length&&(e.which==KEY.LEFT||e.which==KEY.RIGHT||e.which==KEY.BACKSPACE||e.which==KEY.DELETE||e.which==KEY.ENTER)){var selectedChoice=selected;return e.which==KEY.LEFT&&prev.length?selectedChoice=prev:e.which==KEY.RIGHT?selectedChoice=next.length?next:null:e.which===KEY.BACKSPACE?this.unselect(selected.first())&&(this.search.width(10),selectedChoice=prev.length?prev:next):e.which==KEY.DELETE?this.unselect(selected.first())&&(this.search.width(10),selectedChoice=next.length?next:null):e.which==KEY.ENTER&&(selectedChoice=null),this.selectChoice(selectedChoice),killEvent(e),void(selectedChoice&&selectedChoice.length||this.open())}if((e.which===KEY.BACKSPACE&&1==this.keydowns||e.which==KEY.LEFT)&&0==pos.offset&&!pos.length)return this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last()),void killEvent(e);if(this.selectChoice(null),this.opened())switch(e.which){case KEY.UP:case KEY.DOWN:return this.moveHighlight(e.which===KEY.UP?-1:1),void killEvent(e);case KEY.ENTER:return this.selectHighlighted(),void killEvent(e);case KEY.TAB:return this.selectHighlighted({noFocus:!0}),void this.close();case KEY.ESC:return this.cancel(e),void killEvent(e)}if(e.which!==KEY.TAB&&!KEY.isControl(e)&&!KEY.isFunctionKey(e)&&e.which!==KEY.BACKSPACE&&e.which!==KEY.ESC){if(e.which===KEY.ENTER){if(this.opts.openOnEnter===!1)return;if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey)return}this.open(),(e.which===KEY.PAGE_UP||e.which===KEY.PAGE_DOWN)&&killEvent(e),e.which===KEY.ENTER&&killEvent(e)}}})),this.search.on("keyup",this.bind(function(){this.keydowns=0,this.resizeSearch()})),this.search.on("blur",this.bind(function(e){this.container.removeClass("select2-container-active"),this.search.removeClass("select2-focused"),this.selectChoice(null),this.opened()||this.clearSearch(),e.stopImmediatePropagation(),this.opts.element.trigger($.Event("select2-blur"))})),this.container.on("click",selector,this.bind(function(e){this.isInterfaceEnabled()&&($(e.target).closest(".select2-search-choice").length>0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.open(),this.focusSearch(),e.preventDefault()))})),this.container.on("focus",selector,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var self=this;this.opts.initSelection.call(null,this.opts.element,function(data){data!==undefined&&null!==data&&(self.updateSelection(data),self.close(),self.clearSearch())})}},clearSearch:function(){var placeholder=this.getPlaceholder(),maxWidth=this.getMaxSearchWidth();placeholder!==undefined&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(placeholder).addClass("select2-default"),this.search.width(maxWidth>0?maxWidth:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),""===this.search.val()&&this.nextSearchTerm!=undefined&&(this.search.val(this.nextSearchTerm),this.search.select()),this.updateResults(!0),this.opts.shouldFocusInput(this)&&this.search.focus(),this.opts.element.trigger($.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(data){var ids=[],filtered=[],self=this;$(data).each(function(){indexOf(self.id(this),ids)<0&&(ids.push(self.id(this)),filtered.push(this))}),data=filtered,this.selection.find(".select2-search-choice").remove(),$(data).each(function(){self.addSelectedChoice(this)}),self.postprocessResults()},tokenize:function(){var input=this.search.val();input=this.opts.tokenizer.call(this,input,this.data(),this.bind(this.onSelect),this.opts),null!=input&&input!=undefined&&(this.search.val(input),input.length>0&&this.open())},onSelect:function(data,options){this.triggerSelect(data)&&(this.addSelectedChoice(data),this.opts.element.trigger({type:"selected",val:this.id(data),choice:data}),this.nextSearchTerm=this.opts.nextSearchTerm(data,this.search.val()),this.clearSearch(),this.updateResults(),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(data,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()?this.updateResults(!0):this.nextSearchTerm!=undefined&&(this.search.val(this.nextSearchTerm),this.updateResults(),this.search.select()),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:data}),options&&options.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(data){var formatted,cssClass,enableChoice=!data.locked,enabledItem=$("<li class='select2-search-choice'> <div></div> <a href='#' class='select2-search-choice-close' tabindex='-1'></a></li>"),disabledItem=$("<li class='select2-search-choice select2-locked'><div></div></li>"),choice=enableChoice?enabledItem:disabledItem,id=this.id(data),val=this.getVal();formatted=this.opts.formatSelection(data,choice.find("div"),this.opts.escapeMarkup),formatted!=undefined&&choice.find("div").replaceWith("<div>"+formatted+"</div>"),cssClass=this.opts.formatSelectionCssClass(data,choice.find("div")),cssClass!=undefined&&choice.addClass(cssClass),enableChoice&&choice.find(".select2-search-choice-close").on("mousedown",killEvent).on("click dblclick",this.bind(function(e){this.isInterfaceEnabled()&&(this.unselect($(e.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),killEvent(e),this.close(),this.focusSearch())})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),choice.data("select2-data",data),choice.insertBefore(this.searchContainer),val.push(id),this.setVal(val)},unselect:function(selected){var data,index,val=this.getVal();if(selected=selected.closest(".select2-search-choice"),0===selected.length)throw"Invalid argument: "+selected+". Must be .select2-search-choice";if(data=selected.data("select2-data")){var evt=$.Event("select2-removing");if(evt.val=this.id(data),evt.choice=data,this.opts.element.trigger(evt),evt.isDefaultPrevented())return!1;for(;(index=indexOf(this.id(data),val))>=0;)val.splice(index,1),this.setVal(val),this.select&&this.postprocessResults();return selected.remove(),this.opts.element.trigger({type:"select2-removed",val:this.id(data),choice:data}),this.triggerChange({removed:data}),!0}},postprocessResults:function(data,initial,noHighlightUpdate){var val=this.getVal(),choices=this.results.find(".select2-result"),compound=this.results.find(".select2-result-with-children"),self=this;choices.each2(function(i,choice){var id=self.id(choice.data("select2-data"));indexOf(id,val)>=0&&(choice.addClass("select2-selected"),choice.find(".select2-result-selectable").addClass("select2-selected"))}),compound.each2(function(i,choice){choice.is(".select2-result-selectable")||0!==choice.find(".select2-result-selectable:not(.select2-selected)").length||choice.addClass("select2-selected")}),-1==this.highlight()&&noHighlightUpdate!==!1&&self.highlight(0),!this.opts.createSearchChoice&&!choices.filter(".select2-result:not(.select2-selected)").length>0&&(!data||data&&!data.more&&0===this.results.find(".select2-no-results").length)&&checkFormatter(self.opts.formatNoMatches,"formatNoMatches")&&this.results.append("<li class='select2-no-results'>"+evaluate(self.opts.formatNoMatches,self.search.val())+"</li>")},getMaxSearchWidth:function(){return this.selection.width()-getSideBorderPadding(this.search)},resizeSearch:function(){var minimumWidth,left,maxWidth,containerLeft,searchWidth,sideBorderPadding=getSideBorderPadding(this.search);minimumWidth=measureTextWidth(this.search)+10,left=this.search.offset().left,maxWidth=this.selection.width(),containerLeft=this.selection.offset().left,searchWidth=maxWidth-(left-containerLeft)-sideBorderPadding,minimumWidth>searchWidth&&(searchWidth=maxWidth-sideBorderPadding),40>searchWidth&&(searchWidth=maxWidth-sideBorderPadding),0>=searchWidth&&(searchWidth=minimumWidth),this.search.width(Math.floor(searchWidth))},getVal:function(){var val;return this.select?(val=this.select.val(),null===val?[]:val):(val=this.opts.element.val(),splitVal(val,this.opts.separator))},setVal:function(val){var unique;this.select?this.select.val(val):(unique=[],$(val).each(function(){indexOf(this,unique)<0&&unique.push(this)}),this.opts.element.val(0===unique.length?"":unique.join(this.opts.separator)))},buildChangeDetails:function(old,current){for(var current=current.slice(0),old=old.slice(0),i=0;i<current.length;i++)for(var j=0;j<old.length;j++)equal(this.opts.id(current[i]),this.opts.id(old[j]))&&(current.splice(i,1),i>0&&i--,old.splice(j,1),j--);return{added:current,removed:old}},val:function(val,triggerChange){var oldData,self=this;if(0===arguments.length)return this.getVal();if(oldData=this.data(),oldData.length||(oldData=[]),!val&&0!==val)return this.opts.element.val(""),this.updateSelection([]),this.clearSearch(),void(triggerChange&&this.triggerChange({added:this.data(),removed:oldData}));if(this.setVal(val),this.select)this.opts.initSelection(this.select,this.bind(this.updateSelection)),triggerChange&&this.triggerChange(this.buildChangeDetails(oldData,this.data()));else{if(this.opts.initSelection===undefined)throw new Error("val() cannot be called if initSelection() is not defined");this.opts.initSelection(this.opts.element,function(data){var ids=$.map(data,self.id);self.setVal(ids),self.updateSelection(data),self.clearSearch(),triggerChange&&self.triggerChange(self.buildChangeDetails(oldData,self.data()))})}this.clearSearch()},onSortStart:function(){if(this.select)throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var val=[],self=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){val.push(self.opts.id($(this).data("select2-data")))
8
- }),this.setVal(val),this.triggerChange()},data:function(values,triggerChange){var ids,old,self=this;return 0===arguments.length?this.selection.children(".select2-search-choice").map(function(){return $(this).data("select2-data")}).get():(old=this.data(),values||(values=[]),ids=$.map(values,function(e){return self.opts.id(e)}),this.setVal(ids),this.updateSelection(values),this.clearSearch(),triggerChange&&this.triggerChange(this.buildChangeDetails(old,this.data())),void 0)}}),$.fn.select2=function(){var opts,select2,method,value,multiple,args=Array.prototype.slice.call(arguments,0),allowedMethods=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],valueMethods=["opened","isFocused","container","dropdown"],propertyMethods=["val","data"],methodsMap={search:"externalSearch"};return this.each(function(){if(0===args.length||"object"==typeof args[0])opts=0===args.length?{}:$.extend({},args[0]),opts.element=$(this),"select"===opts.element.get(0).tagName.toLowerCase()?multiple=opts.element.prop("multiple"):(multiple=opts.multiple||!1,"tags"in opts&&(opts.multiple=multiple=!0)),select2=multiple?new window.Select2["class"].multi:new window.Select2["class"].single,select2.init(opts);else{if("string"!=typeof args[0])throw"Invalid arguments to select2 plugin: "+args;if(indexOf(args[0],allowedMethods)<0)throw"Unknown method: "+args[0];if(value=undefined,select2=$(this).data("select2"),select2===undefined)return;if(method=args[0],"container"===method?value=select2.container:"dropdown"===method?value=select2.dropdown:(methodsMap[method]&&(method=methodsMap[method]),value=select2[method].apply(select2,args.slice(1))),indexOf(args[0],valueMethods)>=0||indexOf(args[0],propertyMethods)>=0&&1==args.length)return!1}}),value===undefined?this:value},$.fn.select2.defaults={width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(result,container,query,escapeMarkup){var markup=[];return markMatch(result.text,query.term,markup,escapeMarkup),markup.join("")},formatSelection:function(data,container,escapeMarkup){return data?escapeMarkup(data.text):undefined},sortResults:function(results){return results},formatResultCssClass:function(data){return data.css},formatSelectionCssClass:function(){return undefined},formatMatches:function(matches){return matches+" results are available, use up and down arrow keys to navigate."},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(input,min){var n=min-input.length;return"Please enter "+n+" or more character"+(1==n?"":"s")},formatInputTooLong:function(input,max){var n=input.length-max;return"Please delete "+n+" character"+(1==n?"":"s")},formatSelectionTooBig:function(limit){return"You can only select "+limit+" item"+(1==limit?"":"s")},formatLoadMore:function(){return"Loading more results…"},formatSearching:function(){return"Searching…"},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(e){return e==undefined?null:e.id},matcher:function(term,text){return stripDiacritics(""+text).toUpperCase().indexOf(stripDiacritics(""+term).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:defaultTokenizer,escapeMarkup:defaultEscapeMarkup,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(c){return c},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return undefined},searchInputPlaceholder:"",createSearchChoicePosition:"top",shouldFocusInput:function(instance){var supportsTouchEvents="ontouchstart"in window||navigator.msMaxTouchPoints>0;return supportsTouchEvents&&instance.opts.minimumResultsForSearch<0?!1:!0}},$.fn.select2.ajaxDefaults={transport:$.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:ajax,local:local,tags:tags},util:{debounce:debounce,markMatch:markMatch,escapeMarkup:defaultEscapeMarkup,stripDiacritics:stripDiacritics},"class":{"abstract":AbstractSelect2,single:SingleSelect2,multi:MultiSelect2}}}}(jQuery),jQuery(document).ready(function($){$("#filter_action, #filter_content, #filter_form").change(function(){$("#leadin-contacts-filter-button").addClass("button-primary")})});
1
+ function leadin_check_social_share_popup(){jQuery.ajax({type:"POST",url:li_admin_ajax.ajax_url,data:{action:"leadin_check_installation_date"},success:function(data){data||$.cookie("ignore_social_share",1)}})}!function(factory){"function"==typeof define&&define.amd?define(["jquery"],factory):factory(jQuery)}(function($){function encode(s){return config.raw?s:encodeURIComponent(s)}function decode(s){return config.raw?s:decodeURIComponent(s)}function stringifyCookieValue(value){return encode(config.json?JSON.stringify(value):String(value))}function parseCookieValue(s){0===s.indexOf('"')&&(s=s.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return s=decodeURIComponent(s.replace(pluses," ")),config.json?JSON.parse(s):s}catch(e){}}function read(s,converter){var value=config.raw?s:parseCookieValue(s);return $.isFunction(converter)?converter(value):value}var pluses=/\+/g,config=$.cookie=function(key,value,options){if(void 0!==value&&!$.isFunction(value)){if(options=$.extend({},config.defaults,options),"number"==typeof options.expires){var days=options.expires,t=options.expires=new Date;t.setDate(t.getDate()+days)}return document.cookie=[encode(key),"=",stringifyCookieValue(value),options.expires?"; expires="+options.expires.toUTCString():"",options.path?"; path="+options.path:"",options.domain?"; domain="+options.domain:"",options.secure?"; secure":""].join("")}for(var result=key?void 0:{},cookies=document.cookie?document.cookie.split("; "):[],i=0,l=cookies.length;l>i;i++){var parts=cookies[i].split("="),name=decode(parts.shift()),cookie=parts.join("=");if(key&&key===name){result=read(cookie,value);break}key||void 0===(cookie=read(cookie))||(result[name]=cookie)}return result};config.defaults={},$.removeCookie=function(key,options){return void 0===$.cookie(key)?!1:($.cookie(key,"",$.extend({},options,{expires:-1})),!$.cookie(key))}}),window.Highcharts||!function(){function q(a,b){var c;a||(a={});for(c in b)a[c]=b[c];return a}function w(){var a,c,b=arguments,d={},e=function(a,b){var c,d;"object"!=typeof a&&(a={});for(d in b)b.hasOwnProperty(d)&&(c=b[d],a[d]=c&&"object"==typeof c&&"[object Array]"!==Object.prototype.toString.call(c)&&"renderTo"!==d&&"number"!=typeof c.nodeType?e(a[d]||{},c):b[d]);return a};for(b[0]===!0&&(d=b[1],b=Array.prototype.slice.call(b,2)),c=b.length,a=0;c>a;a++)d=e(d,b[a]);return d}function z(a,b){return parseInt(a,b||10)}function Fa(a){return"string"==typeof a}function ca(a){return"object"==typeof a}function La(a){return"[object Array]"===Object.prototype.toString.call(a)}function ha(a){return"number"==typeof a}function za(a){return U.log(a)/U.LN10}function ia(a){return U.pow(10,a)}function ja(a,b){for(var c=a.length;c--;)if(a[c]===b){a.splice(c,1);break}}function r(a){return a!==t&&null!==a}function H(a,b,c){var d,e;if(Fa(b))r(c)?a.setAttribute(b,c):a&&a.getAttribute&&(e=a.getAttribute(b));else if(r(b)&&ca(b))for(d in b)a.setAttribute(d,b[d]);return e}function qa(a){return La(a)?a:[a]}function m(){var b,c,a=arguments,d=a.length;for(b=0;d>b;b++)if(c=a[b],"undefined"!=typeof c&&null!==c)return c}function G(a,b){Aa&&!aa&&b&&b.opacity!==t&&(b.filter="alpha(opacity="+100*b.opacity+")"),q(a.style,b)}function Y(a,b,c,d,e){return a=y.createElement(a),b&&q(a,b),e&&G(a,{padding:0,border:Q,margin:0}),c&&G(a,c),d&&d.appendChild(a),a}function ka(a,b){var c=function(){};return c.prototype=new a,q(c.prototype,b),c}function Ga(a,b,c,d){var e=E.lang,a=+a||0,f=-1===b?(a.toString().split(".")[1]||"").length:isNaN(b=M(b))?2:b,b=void 0===c?e.decimalPoint:c,d=void 0===d?e.thousandsSep:d,e=0>a?"-":"",c=String(z(a=M(a).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+M(a-c).toFixed(f).slice(2):"")}function Ha(a,b){return Array((b||2)+1-String(a).length).join(0)+a}function Ma(a,b,c){var d=a[b];a[b]=function(){var a=Array.prototype.slice.call(arguments);return a.unshift(d),c.apply(this,a)}}function Ia(a,b){for(var e,f,g,h,i,c="{",d=!1,j=[];-1!==(c=a.indexOf(c));){if(e=a.slice(0,c),d){for(f=e.split(":"),g=f.shift().split("."),i=g.length,e=b,h=0;i>h;h++)e=e[g[h]];f.length&&(f=f.join(":"),g=/\.([0-9])/,h=E.lang,i=void 0,/f$/.test(f)?(i=(i=f.match(g))?i[1]:-1,null!==e&&(e=Ga(e,i,h.decimalPoint,f.indexOf(",")>-1?h.thousandsSep:""))):e=cb(f,e))}j.push(e),a=a.slice(c+1),c=(d=!d)?"}":"{"}return j.push(a),j.join("")}function mb(a){return U.pow(10,T(U.log(a)/U.LN10))}function nb(a,b,c,d){var e,c=m(c,1);for(e=a/c,b||(b=[1,2,2.5,5,10],d&&d.allowDecimals===!1&&(1===c?b=[1,2,5,10]:.1>=c&&(b=[1/c]))),d=0;d<b.length&&(a=b[d],!(e<=(b[d]+(b[d+1]||b[d]))/2));d++);return a*=c}function Bb(){this.symbol=this.color=0}function ob(a,b){var d,e,c=a.length;for(e=0;c>e;e++)a[e].ss_i=e;for(a.sort(function(a,c){return d=b(a,c),0===d?a.ss_i-c.ss_i:d}),e=0;c>e;e++)delete a[e].ss_i}function Na(a){for(var b=a.length,c=a[0];b--;)a[b]<c&&(c=a[b]);return c}function Ba(a){for(var b=a.length,c=a[0];b--;)a[b]>c&&(c=a[b]);return c}function Oa(a,b){for(var c in a)a[c]&&a[c]!==b&&a[c].destroy&&a[c].destroy(),delete a[c]}function Pa(a){db||(db=Y(Ja)),a&&db.appendChild(a),db.innerHTML=""}function ra(a,b){var c="Highcharts error #"+a+": www.highcharts.com/errors/"+a;if(b)throw c;I.console&&console.log(c)}function da(a){return parseFloat(a.toPrecision(14))}function Qa(a,b){va=m(a,b.animation)}function Cb(){var a=E.global.useUTC,b=a?"getUTC":"get",c=a?"setUTC":"set";Ra=6e4*(a&&E.global.timezoneOffset||0),eb=a?Date.UTC:function(a,b,c,g,h,i){return new Date(a,b,m(c,1),m(g,0),m(h,0),m(i,0)).getTime()},pb=b+"Minutes",qb=b+"Hours",rb=b+"Day",Xa=b+"Date",fb=b+"Month",gb=b+"FullYear",Db=c+"Minutes",Eb=c+"Hours",sb=c+"Date",Fb=c+"Month",Gb=c+"FullYear"}function P(){}function Sa(a,b,c,d){this.axis=a,this.pos=b,this.type=c||"",this.isNew=!0,!c&&!d&&this.addLabel()}function la(){this.init.apply(this,arguments)}function Ya(){this.init.apply(this,arguments)}function Hb(a,b,c,d,e){var f=a.chart.inverted;this.axis=a,this.isNegative=c,this.options=b,this.x=d,this.total=null,this.points={},this.stack=e,this.alignOptions={align:b.align||(f?c?"left":"right":"center"),verticalAlign:b.verticalAlign||(f?"middle":c?"bottom":"top"),y:m(b.y,f?4:c?14:-6),x:m(b.x,f?c?-6:6:0)},this.textAlign=b.textAlign||(f?c?"right":"left":"center")}var t,Za,$a,db,E,cb,va,ub,A,eb,Ra,pb,qb,rb,Xa,fb,gb,Db,Eb,sb,Fb,Gb,y=document,I=window,U=Math,u=U.round,T=U.floor,Ka=U.ceil,v=U.max,C=U.min,M=U.abs,Z=U.cos,ea=U.sin,ma=U.PI,Ca=2*ma/360,wa=navigator.userAgent,Ib=I.opera,Aa=/msie/i.test(wa)&&!Ib,hb=8===y.documentMode,ib=/AppleWebKit/.test(wa),Ta=/Firefox/.test(wa),Jb=/(Mobile|Android|Windows Phone)/.test(wa),xa="http://www.w3.org/2000/svg",aa=!!y.createElementNS&&!!y.createElementNS(xa,"svg").createSVGRect,Nb=Ta&&parseInt(wa.split("Firefox/")[1],10)<4,fa=!aa&&!Aa&&!!y.createElement("canvas").getContext,Kb={},tb=0,sa=function(){},V=[],ab=0,Ja="div",Q="none",Ob=/^[0-9]+$/,Pb="stroke-width",F={},R=I.Highcharts=I.Highcharts?ra(16,!0):{};cb=function(a,b,c){if(!r(b)||isNaN(b))return"Invalid date";var e,a=m(a,"%Y-%m-%d %H:%M:%S"),d=new Date(b-Ra),f=d[qb](),g=d[rb](),h=d[Xa](),i=d[fb](),j=d[gb](),k=E.lang,l=k.weekdays,d=q({a:l[g].substr(0,3),A:l[g],d:Ha(h),e:h,b:k.shortMonths[i],B:k.months[i],m:Ha(i+1),y:j.toString().substr(2,2),Y:j,H:Ha(f),I:Ha(f%12||12),l:f%12||12,M:Ha(d[pb]()),p:12>f?"AM":"PM",P:12>f?"am":"pm",S:Ha(d.getSeconds()),L:Ha(u(b%1e3),3)},R.dateFormats);for(e in d)for(;-1!==a.indexOf("%"+e);)a=a.replace("%"+e,"function"==typeof d[e]?d[e](b):d[e]);return c?a.substr(0,1).toUpperCase()+a.substr(1):a},Bb.prototype={wrapColor:function(a){this.color>=a&&(this.color=0)},wrapSymbol:function(a){this.symbol>=a&&(this.symbol=0)}},A=function(){for(var a=0,b=arguments,c=b.length,d={};c>a;a++)d[b[a++]]=b[a];return d}("millisecond",1,"second",1e3,"minute",6e4,"hour",36e5,"day",864e5,"week",6048e5,"month",26784e5,"year",31556952e3),ub={init:function(a,b,c){var g,h,i,b=b||"",d=a.shift,e=b.indexOf("C")>-1,f=e?7:3,b=b.split(" "),c=[].concat(c),j=function(a){for(g=a.length;g--;)"M"===a[g]&&a.splice(g+1,0,a[g+1],a[g+2],a[g+1],a[g+2])};if(e&&(j(b),j(c)),a.isArea&&(h=b.splice(b.length-6,6),i=c.splice(c.length-6,6)),d<=c.length/f&&b.length===c.length)for(;d--;)c=[].concat(c).splice(0,f).concat(c);if(a.shift=0,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);return h&&(b=b.concat(h),c=c.concat(i)),[b,c]},step:function(a,b,c,d){var e=[],f=a.length;if(1===c)e=d;else if(f===b.length&&1>c)for(;f--;)d=parseFloat(a[f]),e[f]=isNaN(d)?a[f]:c*parseFloat(b[f]-d)+d;else e=b;return e}},function(a){I.HighchartsAdapter=I.HighchartsAdapter||a&&{init:function(b){var e,c=a.fx,d=c.step,f=a.Tween,g=f&&f.propHooks;e=a.cssHooks.opacity,a.extend(a.easing,{easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c}}),a.each(["cur","_default","width","height","opacity"],function(a,b){var k,e=d;"cur"===b?e=c.prototype:"_default"===b&&f&&(e=g[b],b="set"),(k=e[b])&&(e[b]=function(c){var d,c=a?c:this;return"align"!==c.prop?(d=c.elem,d.attr?d.attr(c.prop,"cur"===b?t:c.now):k.apply(this,arguments)):void 0})}),Ma(e,"get",function(a,b,c){return b.attr?b.opacity||0:a.call(this,b,c)}),e=function(a){var d,c=a.elem;a.started||(d=b.init(c,c.d,c.toD),a.start=d[0],a.end=d[1],a.started=!0),c.attr("d",b.step(a.start,a.end,a.pos,c.toD))},f?g.d={set:e}:d.d=e,this.each=Array.prototype.forEach?function(a,b){return Array.prototype.forEach.call(a,b)}:function(a,b){for(var c=0,d=a.length;d>c;c++)if(b.call(a[c],a[c],c,a)===!1)return c},a.fn.highcharts=function(){var c,d,a="Chart",b=arguments;return this[0]&&(Fa(b[0])&&(a=b[0],b=Array.prototype.slice.call(b,1)),c=b[0],c!==t&&(c.chart=c.chart||{},c.chart.renderTo=this[0],new R[a](c,b[1]),d=this),c===t&&(d=V[H(this[0],"data-highcharts-chart")])),d}},getScript:a.getScript,inArray:a.inArray,adapterRun:function(b,c){return a(b)[c]()},grep:a.grep,map:function(a,c){for(var d=[],e=0,f=a.length;f>e;e++)d[e]=c.call(a[e],a[e],e,a);return d},offset:function(b){return a(b).offset()},addEvent:function(b,c,d){a(b).bind(c,d)},removeEvent:function(b,c,d){var e=y.removeEventListener?"removeEventListener":"detachEvent";y[e]&&b&&!b[e]&&(b[e]=function(){}),a(b).unbind(c,d)},fireEvent:function(b,c,d,e){var h,f=a.Event(c),g="detached"+c;!Aa&&d&&(delete d.layerX,delete d.layerY,delete d.returnValue),q(f,d),b[c]&&(b[g]=b[c],b[c]=null),a.each(["preventDefault","stopPropagation"],function(a,b){var c=f[b];f[b]=function(){try{c.call(f)}catch(a){"preventDefault"===b&&(h=!0)}}}),a(b).trigger(f),b[g]&&(b[c]=b[g],b[g]=null),e&&!f.isDefaultPrevented()&&!h&&e(f)},washMouseEvent:function(a){var c=a.originalEvent||a;return c.pageX===t&&(c.pageX=a.pageX,c.pageY=a.pageY),c},animate:function(b,c,d){var e=a(b);b.style||(b.style={}),c.d&&(b.toD=c.d,c.d=1),e.stop(),c.opacity!==t&&b.attr&&(c.opacity+="px"),e.animate(c,d)},stop:function(b){a(b).stop()}}}(I.jQuery);var S=I.HighchartsAdapter,N=S||{};S&&S.init.call(S,ub);var jb=N.adapterRun,Qb=N.getScript,Da=N.inArray,p=N.each,vb=N.grep,Rb=N.offset,Ua=N.map,K=N.addEvent,W=N.removeEvent,D=N.fireEvent,Sb=N.washMouseEvent,kb=N.animate,bb=N.stop,N={enabled:!0,x:0,y:15,style:{color:"#606060",cursor:"default",fontSize:"11px"}};E={colors:"#7cb5ec,#434348,#90ed7d,#f7a35c,#8085e9,#f15c80,#e4d354,#8085e8,#8d4653,#91e8e1".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(","),decimalPoint:".",numericSymbols:"k,M,G,T,P,E".split(","),resetZoom:"Reset zoom",resetZoomTitle:"Reset zoom level 1:1",thousandsSep:","},global:{useUTC:!0,canvasToolsURL:"http://code.highcharts.com/4.0.1/modules/canvas-tools.js",VMLRadialGradientURL:"http://code.highcharts.com/4.0.1/gfx/vml-radial-gradient.png"},chart:{borderColor:"#4572A7",borderRadius:0,defaultSeriesType:"line",ignoreHiddenSeries:!0,spacing:[10,10,15,10],backgroundColor:"#FFFFFF",plotBorderColor:"#C0C0C0",resetZoomButton:{theme:{zIndex:20},position:{align:"right",x:-10,y:10}}},title:{text:"Chart title",align:"center",margin:15,style:{color:"#333333",fontSize:"18px"}},subtitle:{text:"",align:"center",style:{color:"#555555"}},plotOptions:{line:{allowPointSelect:!1,showCheckbox:!1,animation:{duration:1e3},events:{},lineWidth:2,marker:{lineWidth:0,radius:4,lineColor:"#FFFFFF",states:{hover:{enabled:!0},select:{fillColor:"#FFFFFF",lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:w(N,{align:"center",enabled:!1,formatter:function(){return null===this.y?"":Ga(this.y,-1)},verticalAlign:"bottom",y:0}),cropThreshold:300,pointRange:0,states:{hover:{marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1e3}},labels:{style:{position:"absolute",color:"#3E576F"}},legend:{enabled:!0,align:"center",layout:"horizontal",labelFormatter:function(){return this.name},borderColor:"#909090",borderRadius:0,navigation:{activeColor:"#274b6d",inactiveColor:"#CCC"},shadow:!1,itemStyle:{color:"#333333",fontSize:"12px",fontWeight:"bold"},itemHoverStyle:{color:"#000"},itemHiddenStyle:{color:"#CCC"},itemCheckboxStyle:{position:"absolute",width:"13px",height:"13px"},symbolPadding:5,verticalAlign:"bottom",x:0,y:0,title:{style:{fontWeight:"bold"}}},loading:{labelStyle:{fontWeight:"bold",position:"relative",top:"1em"},style:{position:"absolute",backgroundColor:"white",opacity:.5,textAlign:"center"}},tooltip:{enabled:!0,animation:aa,backgroundColor:"rgba(249, 249, 249, .85)",borderWidth:1,borderRadius:3,dateTimeLabelFormats:{millisecond:"%A, %b %e, %H:%M:%S.%L",second:"%A, %b %e, %H:%M:%S",minute:"%A, %b %e, %H:%M",hour:"%A, %b %e, %H:%M",day:"%A, %b %e, %Y",week:"Week from %A, %b %e, %Y",month:"%B %Y",year:"%Y"},headerFormat:'<span style="font-size: 10px">{point.key}</span><br/>',pointFormat:'<span style="color:{series.color}">●</span> {series.name}: <b>{point.y}</b><br/>',shadow:!0,snap:Jb?25:10,style:{color:"#333333",cursor:"default",fontSize:"12px",padding:"8px",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:"9px"}}};var ba=E.plotOptions,S=ba.line;Cb();var Tb=/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*\)/,Ub=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,Vb=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/,ya=function(a){var c,d,b=[];return function(a){a&&a.stops?d=Ua(a.stops,function(a){return ya(a[1])}):(c=Tb.exec(a))?b=[z(c[1]),z(c[2]),z(c[3]),parseFloat(c[4],10)]:(c=Ub.exec(a))?b=[z(c[1],16),z(c[2],16),z(c[3],16),1]:(c=Vb.exec(a))&&(b=[z(c[1]),z(c[2]),z(c[3]),1])}(a),{get:function(c){var f;return d?(f=w(a),f.stops=[].concat(f.stops),p(d,function(a,b){f.stops[b]=[f.stops[b][0],a.get(c)]})):f=b&&!isNaN(b[0])?"rgb"===c?"rgb("+b[0]+","+b[1]+","+b[2]+")":"a"===c?b[3]:"rgba("+b.join(",")+")":a,f},brighten:function(a){if(d)p(d,function(b){b.brighten(a)});else if(ha(a)&&0!==a){var c;for(c=0;3>c;c++)b[c]+=z(255*a),b[c]<0&&(b[c]=0),b[c]>255&&(b[c]=255)}return this},rgba:b,setOpacity:function(a){return b[3]=a,this}}};P.prototype={init:function(a,b){this.element="span"===b?Y(b):y.createElementNS(xa,b),this.renderer=a},opacity:1,animate:function(a,b,c){b=m(b,va,!0),bb(this),b?(b=w(b,{}),c&&(b.complete=c),kb(this,a,b)):(this.attr(a),c&&c())},colorGradient:function(a,b,c){var e,f,g,h,i,j,k,l,o,n,d=this.renderer,s=[];if(a.linearGradient?f="linearGradient":a.radialGradient&&(f="radialGradient"),f){g=a[f],h=d.gradients,j=a.stops,o=c.radialReference,La(g)&&(a[f]=g={x1:g[0],y1:g[1],x2:g[2],y2:g[3],gradientUnits:"userSpaceOnUse"}),"radialGradient"===f&&o&&!r(g.gradientUnits)&&(g=w(g,{cx:o[0]-o[2]/2+g.cx*o[2],cy:o[1]-o[2]/2+g.cy*o[2],r:g.r*o[2],gradientUnits:"userSpaceOnUse"}));for(n in g)"id"!==n&&s.push(n,g[n]);for(n in j)s.push(j[n]);s=s.join(","),h[s]?a=h[s].attr("id"):(g.id=a="highcharts-"+tb++,h[s]=i=d.createElement(f).attr(g).add(d.defs),i.stops=[],p(j,function(a){0===a[1].indexOf("rgba")?(e=ya(a[1]),k=e.get("rgb"),l=e.get("a")):(k=a[1],l=1),a=d.createElement("stop").attr({offset:a[0],"stop-color":k,"stop-opacity":l}).add(i),i.stops.push(a)})),c.setAttribute(b,"url("+d.url+"#"+a+")")}},attr:function(a,b){var c,d,f,h,e=this.element,g=this;if("string"==typeof a&&b!==t&&(c=a,a={},a[c]=b),"string"==typeof a)g=(this[a+"Getter"]||this._defaultGetter).call(this,a,e);else{for(c in a)d=a[c],h=!1,this.symbolName&&/^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)/.test(c)&&(f||(this.symbolAttr(a),f=!0),h=!0),!this.rotation||"x"!==c&&"y"!==c||(this.doTransform=!0),h||(this[c+"Setter"]||this._defaultSetter).call(this,d,c,e),this.shadows&&/^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test(c)&&this.updateShadows(c,d);this.doTransform&&(this.updateTransform(),this.doTransform=!1)}return g},updateShadows:function(a,b){for(var c=this.shadows,d=c.length;d--;)c[d].setAttribute(a,"height"===a?v(b-(c[d].cutHeight||0),0):"d"===a?this.d:b)},addClass:function(a){var b=this.element,c=H(b,"class")||"";return-1===c.indexOf(a)&&H(b,"class",c+" "+a),this},symbolAttr:function(a){var b=this;p("x,y,r,start,end,width,height,innerR,anchorX,anchorY".split(","),function(c){b[c]=m(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",a?"url("+this.renderer.url+"#"+a.id+")":Q)},crisp:function(a){var b,d,c={},e=a.strokeWidth||this.strokeWidth||this.attr&&this.attr("stroke-width")||0;d=u(e)%2/2,a.x=T(a.x||this.x||0)+d,a.y=T(a.y||this.y||0)+d,a.width=T((a.width||this.width||0)-2*d),a.height=T((a.height||this.height||0)-2*d),a.strokeWidth=e;for(b in a)this[b]!==a[b]&&(this[b]=c[b]=a[b]);return c},css:function(a){var e,f,b=this.styles,c={},d=this.element,g="";if(e=!b,a&&a.color&&(a.fill=a.color),b)for(f in a)a[f]!==b[f]&&(c[f]=a[f],e=!0);if(e){if(e=this.textWidth=a&&a.width&&"text"===d.nodeName.toLowerCase()&&z(a.width),b&&(a=q(b,c)),this.styles=a,e&&(fa||!aa&&this.renderer.forExport)&&delete a.width,Aa&&!aa)G(this.element,a);else{b=function(a,b){return"-"+b.toLowerCase()};for(f in a)g+=f.replace(/([A-Z])/g,b)+":"+a[f]+";";H(d,"style",g)}e&&this.added&&this.renderer.buildText(this)}return this},on:function(a,b){var c=this,d=c.element;return $a&&"click"===a?(d.ontouchstart=function(a){c.touchEventFired=Date.now(),a.preventDefault(),b.call(d,a)},d.onclick=function(a){(-1===wa.indexOf("Android")||Date.now()-(c.touchEventFired||0)>1100)&&b.call(d,a)}):d["on"+a]=b,this},setRadialReference:function(a){return this.element.radialReference=a,this},translate:function(a,b){return this.attr({translateX:a,translateY:b})},invert:function(){return this.inverted=!0,this.updateTransform(),this},updateTransform:function(){var a=this.translateX||0,b=this.translateY||0,c=this.scaleX,d=this.scaleY,e=this.inverted,f=this.rotation,g=this.element;e&&(a+=this.attr("width"),b+=this.attr("height")),a=["translate("+a+","+b+")"],e?a.push("rotate(90) scale(-1,1)"):f&&a.push("rotate("+f+" "+(g.getAttribute("x")||0)+" "+(g.getAttribute("y")||0)+")"),(r(c)||r(d))&&a.push("scale("+m(c,1)+" "+m(d,1)+")"),a.length&&g.setAttribute("transform",a.join(" "))},toFront:function(){var a=this.element;return a.parentNode.appendChild(a),this},align:function(a,b,c){var d,e,f,g,h={};return e=this.renderer,f=e.alignedObjects,a?(this.alignOptions=a,this.alignByTranslate=b,(!c||Fa(c))&&(this.alignTo=d=c||"renderer",ja(f,this),f.push(this),c=null)):(a=this.alignOptions,b=this.alignByTranslate,d=this.alignTo),c=m(c,e[d],e),d=a.align,e=a.verticalAlign,f=(c.x||0)+(a.x||0),g=(c.y||0)+(a.y||0),("right"===d||"center"===d)&&(f+=(c.width-(a.width||0))/{right:1,center:2}[d]),h[b?"translateX":"x"]=u(f),("bottom"===e||"middle"===e)&&(g+=(c.height-(a.height||0))/({bottom:1,middle:2}[e]||1)),h[b?"translateY":"y"]=u(g),this[this.placed?"animate":"attr"](h),this.placed=!0,this.alignAttr=h,this},getBBox:function(){var c,d,a=this.bBox,b=this.renderer,e=this.rotation;c=this.element;var f=this.styles,g=e*Ca;d=this.textStr;var h;if((""===d||Ob.test(d))&&(h="num."+d.toString().length+(f?"|"+f.fontSize+"|"+f.fontFamily:"")),h&&(a=b.cache[h]),!a){if(c.namespaceURI===xa||b.forExport){try{a=c.getBBox?q({},c.getBBox()):{width:c.offsetWidth,height:c.offsetHeight}}catch(i){}(!a||a.width<0)&&(a={width:0,height:0})}else a=this.htmlGetBBox();b.isSVG&&(c=a.width,d=a.height,Aa&&f&&"11px"===f.fontSize&&"16.9"===d.toPrecision(3)&&(a.height=d=14),e&&(a.width=M(d*ea(g))+M(c*Z(g)),a.height=M(d*Z(g))+M(c*ea(g)))),this.bBox=a,h&&(b.cache[h]=a)}return a},show:function(a){return a&&this.element.namespaceURI===xa?(this.element.removeAttribute("visibility"),this):this.attr({visibility:a?"inherit":"visible"})},hide:function(){return this.attr({visibility:"hidden"})},fadeOut:function(a){var b=this;b.animate({opacity:0},{duration:a||150,complete:function(){b.hide()}})},add:function(a){var g,h,b=this.renderer,c=a||b,d=c.element||b.box,e=this.element,f=this.zIndex;if(a&&(this.parentGroup=a),this.parentInverted=a&&a.inverted,void 0!==this.textStr&&b.buildText(this),f&&(c.handleZ=!0,f=z(f)),c.handleZ)for(a=d.childNodes,g=0;g<a.length;g++)if(b=a[g],c=H(b,"zIndex"),b!==e&&(z(c)>f||!r(f)&&r(c))){d.insertBefore(e,b),h=!0;break}return h||d.appendChild(e),this.added=!0,this.onAdd&&this.onAdd(),this},safeRemoveChild:function(a){var b=a.parentNode;b&&b.removeChild(a)},destroy:function(){var e,f,a=this,b=a.element||{},c=a.shadows,d=a.renderer.isSVG&&"SPAN"===b.nodeName&&a.parentGroup;if(b.onclick=b.onmouseout=b.onmouseover=b.onmousemove=b.point=null,bb(a),a.clipPath&&(a.clipPath=a.clipPath.destroy()),a.stops){for(f=0;f<a.stops.length;f++)a.stops[f]=a.stops[f].destroy();a.stops=null}for(a.safeRemoveChild(b),c&&p(c,function(b){a.safeRemoveChild(b)});d&&0===d.div.childNodes.length;)b=d.parentGroup,a.safeRemoveChild(d.div),delete d.div,d=b;a.alignTo&&ja(a.renderer.alignedObjects,a);for(e in a)delete a[e];return null},shadow:function(a,b,c){var e,f,h,i,j,k,d=[],g=this.element;if(a){for(i=m(a.width,3),j=(a.opacity||.15)/i,k=this.parentInverted?"(-1,-1)":"("+m(a.offsetX,1)+", "+m(a.offsetY,1)+")",e=1;i>=e;e++)f=g.cloneNode(0),h=2*i+1-2*e,H(f,{isShadow:"true",stroke:a.color||"black","stroke-opacity":j*e,"stroke-width":h,transform:"translate"+k,fill:Q}),c&&(H(f,"height",v(H(f,"height")-h,0)),f.cutHeight=h),b?b.element.appendChild(f):g.parentNode.insertBefore(f,g),d.push(f);this.shadows=d}return this},xGetter:function(a){return"circle"===this.element.nodeName&&(a={x:"cx",y:"cy"}[a]||a),this._defaultGetter(a)},_defaultGetter:function(a){return a=m(this[a],this.element?this.element.getAttribute(a):null,0),/^[0-9\.]+$/.test(a)&&(a=parseFloat(a)),a},dSetter:function(a,b,c){a&&a.join&&(a=a.join(" ")),/(NaN| {2}|^$)/.test(a)&&(a="M 0 0"),c.setAttribute(b,a),this[b]=a},dashstyleSetter:function(a){var b;if(a=a&&a.toLowerCase()){for(a=a.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(","),b=a.length;b--;)a[b]=z(a[b])*this.element.getAttribute("stroke-width");a=a.join(","),this.element.setAttribute("stroke-dasharray",a)}},alignSetter:function(a){this.element.setAttribute("text-anchor",{left:"start",center:"middle",right:"end"}[a])},opacitySetter:function(a,b,c){this[b]=a,c.setAttribute(b,a)},"stroke-widthSetter":function(a,b,c){0===a&&(a=1e-5),this.strokeWidth=a,c.setAttribute(b,a)},titleSetter:function(a){var b=this.element.getElementsByTagName("title")[0];b||(b=y.createElementNS(xa,"title"),this.element.appendChild(b)),b.textContent=a},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,b,c){"string"==typeof a?c.setAttribute(b,a):a&&this.colorGradient(a,b,c)},zIndexSetter:function(a,b,c){c.setAttribute(b,a),this[b]=a},_defaultSetter:function(a,b,c){c.setAttribute(b,a)}},P.prototype.yGetter=P.prototype.xGetter,P.prototype.translateXSetter=P.prototype.translateYSetter=P.prototype.rotationSetter=P.prototype.verticalAlignSetter=P.prototype.scaleXSetter=P.prototype.scaleYSetter=function(a,b){this[b]=a,this.doTransform=!0},P.prototype.strokeSetter=P.prototype.fillSetter;var ta=function(){this.init.apply(this,arguments)};ta.prototype={Element:P,init:function(a,b,c,d,e){var g,f=location,d=this.createElement("svg").attr({version:"1.1"}).css(this.getStyle(d));g=d.element,a.appendChild(g),-1===a.innerHTML.indexOf("xmlns")&&H(g,"xmlns",xa),this.isSVG=!0,this.box=g,this.boxWrapper=d,this.alignedObjects=[],this.url=(Ta||ib)&&y.getElementsByTagName("base").length?f.href.replace(/#.*?$/,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"",this.createElement("desc").add().element.appendChild(y.createTextNode("Created with Highcharts 4.0.1")),this.defs=this.createElement("defs").add(),this.forExport=e,this.gradients={},this.cache={},this.setSize(b,c,!1);var h;Ta&&a.getBoundingClientRect&&(this.subPixelFix=b=function(){G(a,{left:0,top:0}),h=a.getBoundingClientRect(),G(a,{left:Ka(h.left)-h.left+"px",top:Ka(h.top)-h.top+"px"})},b(),K(I,"resize",b))},getStyle:function(a){return this.style=q({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;return this.box=null,this.boxWrapper=this.boxWrapper.destroy(),Oa(this.gradients||{}),this.gradients=null,a&&(this.defs=a.destroy()),this.subPixelFix&&W(I,"resize",this.subPixelFix),this.alignedObjects=null},createElement:function(a){var b=new this.Element;return b.init(this,a),b},draw:function(){},buildText:function(a){for(var h,i,b=a.element,c=this,d=c.forExport,e=m(a.textStr,"").toString(),f=-1!==e.indexOf("<"),g=b.childNodes,j=H(b,"x"),k=a.styles,l=a.textWidth,o=k&&k.lineHeight,n=g.length,s=function(a){return o?z(o):c.fontMetrics(/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:k&&k.fontSize||c.style.fontSize||12).h};n--;)b.removeChild(g[n]);f||-1!==e.indexOf(" ")?(h=/<.*style="([^"]+)".*>/,i=/<.*href="(http[^"]+)".*>/,l&&!a.added&&this.box.appendChild(b),e=f?e.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):[e],""===e[e.length-1]&&e.pop(),p(e,function(e,f){var g,n=0,e=e.replace(/<span/g,"|||<span").replace(/<\/span>/g,"</span>|||");g=e.split("|||"),p(g,function(e){if(""!==e||1===g.length){var p,o={},m=y.createElementNS(xa,"tspan");if(h.test(e)&&(p=e.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),H(m,"style",p)),i.test(e)&&!d&&(H(m,"onclick",'location.href="'+e.match(i)[1]+'"'),G(m,{cursor:"pointer"})),e=(e.replace(/<(.|\n)*?>/g,"")||" ").replace(/&lt;/g,"<").replace(/&gt;/g,">")," "!==e&&(m.appendChild(y.createTextNode(e)),n?o.dx=0:f&&null!==j&&(o.x=j),H(m,o),!n&&f&&(!aa&&d&&G(m,{display:"block"}),H(m,"dy",s(m),ib&&m.offsetHeight)),b.appendChild(m),n++,l))for(var $,r,e=e.replace(/([^\^])-/g,"$1- ").split(" "),o=e.length>1&&"nowrap"!==k.whiteSpace,B=a._clipHeight,q=[],v=s(),t=1;o&&(e.length||q.length);)delete a.bBox,$=a.getBBox(),r=$.width,!aa&&c.forExport&&(r=c.measureSpanWidth(m.firstChild.data,a.styles)),$=r>l,$&&1!==e.length?(m.removeChild(m.firstChild),q.unshift(e.pop())):(e=q,q=[],e.length&&(t++,B&&t*v>B?(e=["..."],a.attr("title",a.textStr)):(m=y.createElementNS(xa,"tspan"),H(m,{dy:v,x:j}),p&&H(m,"style",p),b.appendChild(m),r>l&&(l=r)))),e.length&&m.appendChild(y.createTextNode(e.join(" ").replace(/- /g,"-")))}})})):b.appendChild(y.createTextNode(e))},button:function(a,b,c,d,e,f,g,h,i){var l,o,n,s,m,p,j=this.label(a,b,c,i,null,null,null,null,"button"),k=0,a={x1:0,y1:0,x2:0,y2:1},e=w({"stroke-width":1,stroke:"#CCCCCC",fill:{linearGradient:a,stops:[[0,"#FEFEFE"],[1,"#F6F6F6"]]},r:2,padding:5,style:{color:"black"}},e);return n=e.style,delete e.style,f=w(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#FFF"],[1,"#ACF"]]}},f),s=f.style,delete f.style,g=w(e,{stroke:"#68A",fill:{linearGradient:a,stops:[[0,"#9BD"],[1,"#CDF"]]}},g),m=g.style,delete g.style,h=w(e,{style:{color:"#CCC"}},h),p=h.style,delete h.style,K(j.element,Aa?"mouseover":"mouseenter",function(){3!==k&&j.attr(f).css(s)}),K(j.element,Aa?"mouseout":"mouseleave",function(){3!==k&&(l=[e,f,g][k],o=[n,s,m][k],j.attr(l).css(o))}),j.setState=function(a){(j.state=k=a)?2===a?j.attr(g).css(m):3===a&&j.attr(h).css(p):j.attr(e).css(n)},j.on("click",function(){3!==k&&d.call(j)}).attr(e).css(q({cursor:"default"},n))},crispLine:function(a,b){return a[1]===a[4]&&(a[1]=a[4]=u(a[1])-b%2/2),a[2]===a[5]&&(a[2]=a[5]=u(a[2])+b%2/2),a},path:function(a){var b={fill:Q};return La(a)?b.d=a:ca(a)&&q(b,a),this.createElement("path").attr(b)},circle:function(a,b,c){return a=ca(a)?a:{x:a,y:b,r:c},b=this.createElement("circle"),b.xSetter=function(a){this.element.setAttribute("cx",a)},b.ySetter=function(a){this.element.setAttribute("cy",a)},b.attr(a)},arc:function(a,b,c,d,e,f){return ca(a)&&(b=a.y,c=a.r,d=a.innerR,e=a.start,f=a.end,a=a.x),a=this.symbol("arc",a||0,b||0,c||0,c||0,{innerR:d||0,start:e||0,end:f||0}),a.r=c,a},rect:function(a,b,c,d,e,f){var e=ca(a)?a.r:e,g=this.createElement("rect"),a=ca(a)?a:a===t?{}:{x:a,y:b,width:v(c,0),height:v(d,0)};return f!==t&&(a.strokeWidth=f,a=g.crisp(a)),e&&(a.r=e),g.rSetter=function(a){H(this.element,{rx:a,ry:a})},g.attr(a)},setSize:function(a,b,c){var d=this.alignedObjects,e=d.length;for(this.width=a,this.height=b,this.boxWrapper[m(c,!0)?"animate":"attr"]({width:a,height:b});e--;)d[e].align()},g:function(a){var b=this.createElement("g");return r(a)?b.attr({"class":"highcharts-"+a}):b},image:function(a,b,c,d,e){var f={preserveAspectRatio:Q};return arguments.length>1&&q(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),f},symbol:function(a,b,c,d,e,f){var g,j,k,h=this.symbols[a],h=h&&h(u(b),u(c),d,e,f),i=/^url\((.*?)\)$/;return h?(g=this.path(h),q(g,{symbolName:a,x:b,y:c,width:d,height:e}),f&&q(g,f)):i.test(a)&&(k=function(a,b){a.element&&(a.attr({width:b[0],height:b[1]}),a.alignByTranslate||a.translate(u((d-b[0])/2),u((e-b[1])/2)))},j=a.match(i)[1],a=Kb[j],g=this.image(j).attr({x:b,y:c}),g.isImg=!0,a?k(g,a):(g.attr({width:0,height:0}),Y("img",{onload:function(){k(g,Kb[j]=[this.width,this.height])},src:j}))),g},symbols:{circle:function(a,b,c,d){var e=.166*c;return["M",a+c/2,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["M",a,b,"L",a+c,b,a+c,b+d,a,b+d,"Z"]},triangle:function(a,b,c,d){return["M",a+c/2,b,"L",a+c,b+d,a,b+d,"Z"]},"triangle-down":function(a,b,c,d){return["M",a,b,"L",a+c,b,a+c/2,b+d,"Z"]},diamond:function(a,b,c,d){return["M",a+c/2,b,"L",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-.001,d=e.innerR,h=e.open,i=Z(f),j=ea(f),k=Z(g),g=ea(g),e=e.end-f<ma?0:1;return["M",a+c*i,b+c*j,"A",c,c,0,e,1,a+c*k,b+c*g,h?"M":"L",a+d*k,b+d*g,"A",d,d,0,e,0,a+d*i,b+d*j,h?"":"Z"]},callout:function(a,b,c,d,e){var f=C(e&&e.r||0,c,d),g=f+6,h=e&&e.anchorX,i=e&&e.anchorY,e=u(e.strokeWidth||0)%2/2;return a+=e,b+=e,e=["M",a+f,b,"L",a+c-f,b,"C",a+c,b,a+c,b,a+c,b+f,"L",a+c,b+d-f,"C",a+c,b+d,a+c,b+d,a+c-f,b+d,"L",a+f,b+d,"C",a,b+d,a,b+d,a,b+d-f,"L",a,b+f,"C",a,b,a,b,a+f,b],h&&h>c&&i>b+g&&b+d-g>i?e.splice(13,3,"L",a+c,i-6,a+c+6,i,a+c,i+6,a+c,b+d-f):h&&0>h&&i>b+g&&b+d-g>i?e.splice(33,3,"L",a,i+6,a-6,i,a,i-6,a,b+f):i&&i>d&&h>a+g&&a+c-g>h?e.splice(23,3,"L",h+6,b+d,h,b+d+6,h-6,b+d,a+f,b+d):i&&0>i&&h>a+g&&a+c-g>h&&e.splice(3,3,"L",h-6,b,h,b-6,h+6,b,c-f,b),e}},clipRect:function(a,b,c,d){var e="highcharts-"+tb++,f=this.createElement("clipPath").attr({id:e}).add(this.defs),a=this.rect(a,b,c,d,0).add(f);return a.id=e,a.clipPath=f,a
2
+ },text:function(a,b,c,d){var e=fa||!aa&&this.forExport,f={};return d&&!this.forExport?this.html(a,b,c):(f.x=Math.round(b||0),c&&(f.y=Math.round(c)),(a||0===a)&&(f.text=a),a=this.createElement("text").attr(f),e&&a.css({position:"absolute"}),d||(a.xSetter=function(a,b,c){var e,f,d=c.childNodes;for(f=1;f<d.length;f++)e=d[f],e.getAttribute("x")===c.getAttribute("x")&&e.setAttribute("x",a);c.setAttribute(b,a)}),a)},fontMetrics:function(a){var a=a||this.style.fontSize,a=/px/.test(a)?z(a):/em/.test(a)?12*parseFloat(a):12,a=24>a?a+4:u(1.2*a),b=u(.8*a);return{h:a,b:b}},label:function(a,b,c,d,e,f,g,h,i){function j(){var a,b;a=s.element.style,J=(void 0===Va||void 0===wb||n.styles.textAlign)&&s.textStr&&s.getBBox(),n.width=(Va||J.width||0)+2*x+v,n.height=(wb||J.height||0)+2*x,na=x+o.fontMetrics(a&&a.fontSize).b,z&&(m||(a=u(-L*x),b=h?-na:0,n.box=m=d?o.symbol(d,a,b,n.width,n.height,B):o.rect(a,b,n.width,n.height,0,B[Pb]),m.attr("fill",Q).add(n)),m.isImg||m.attr(q({width:u(n.width),height:u(n.height)},B)),B=null)}function k(){var c,a=n.styles,a=a&&a.textAlign,b=v+x*(1-L);c=h?0:na,r(Va)&&J&&("center"===a||"right"===a)&&(b+={center:.5,right:1}[a]*(Va-J.width)),(b!==s.x||c!==s.y)&&(s.attr("x",b),c!==t&&s.attr("y",c)),s.x=b,s.y=c}function l(a,b){m?m.attr(a,b):B[a]=b}var m,J,Va,wb,xb,yb,na,z,o=this,n=o.g(i),s=o.text("",0,0,g).attr({zIndex:1}),L=0,x=3,v=0,y=0,B={};n.onAdd=function(){s.add(n),n.attr({text:a||"",x:b,y:c}),m&&r(e)&&n.attr({anchorX:e,anchorY:f})},n.widthSetter=function(a){Va=a},n.heightSetter=function(a){wb=a},n.paddingSetter=function(a){r(a)&&a!==x&&(x=a,k())},n.paddingLeftSetter=function(a){r(a)&&a!==v&&(v=a,k())},n.alignSetter=function(a){L={left:0,center:.5,right:1}[a]},n.textSetter=function(a){a!==t&&s.textSetter(a),j(),k()},n["stroke-widthSetter"]=function(a,b){a&&(z=!0),y=a%2/2,l(b,a)},n.strokeSetter=n.fillSetter=n.rSetter=function(a,b){"fill"===b&&a&&(z=!0),l(b,a)},n.anchorXSetter=function(a,b){e=a,l(b,a+y-xb)},n.anchorYSetter=function(a,b){f=a,l(b,a-yb)},n.xSetter=function(a){n.x=a,L&&(a-=L*((Va||J.width)+x)),xb=u(a),n.attr("translateX",xb)},n.ySetter=function(a){yb=n.y=u(a),n.attr("translateY",yb)};var A=n.css;return q(n,{css:function(a){if(a){var b={},a=w(a);p("fontSize,fontWeight,fontFamily,color,lineHeight,width,textDecoration,textShadow".split(","),function(c){a[c]!==t&&(b[c]=a[c],delete a[c])}),s.css(b)}return A.call(n,a)},getBBox:function(){return{width:J.width+2*x,height:J.height+2*x,x:J.x-x,y:J.y-x}},shadow:function(a){return m&&m.shadow(a),n},destroy:function(){W(n.element,"mouseenter"),W(n.element,"mouseleave"),s&&(s=s.destroy()),m&&(m=m.destroy()),P.prototype.destroy.call(n),n=o=j=k=l=null}})}},Za=ta,q(P.prototype,{htmlCss:function(a){var b=this.element;return(b=a&&"SPAN"===b.tagName&&a.width)&&(delete a.width,this.textWidth=b,this.updateTransform()),this.styles=q(this.styles,a),G(this.element,a),this},htmlGetBBox:function(){var a=this.element,b=this.bBox;return b||("text"===a.nodeName&&(a.style.position="absolute"),b=this.bBox={x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}),b},htmlUpdateTransform:function(){if(this.added){var a=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:.5,right:1}[g],i=this.shadows;if(G(b,{marginLeft:c,marginTop:d}),i&&p(i,function(a){G(a,{marginLeft:c+1,marginTop:d+1})}),this.inverted&&p(b.childNodes,function(c){a.invertChild(c,b)}),"SPAN"===b.tagName){var k,j=this.rotation,l=z(this.textWidth),o=[j,g,b.innerHTML,this.textWidth].join(",");o!==this.cTT&&(k=a.fontMetrics(b.style.fontSize).b,r(j)&&this.setSpanRotation(j,h,k),i=m(this.elemWidth,b.offsetWidth),i>l&&/[ \-]/.test(b.textContent||b.innerText)&&(G(b,{width:l+"px",display:"block",whiteSpace:"normal"}),i=l),this.getSpanCorrection(i,k,h,j,g)),G(b,{left:e+(this.xCorr||0)+"px",top:f+(this.yCorr||0)+"px"}),ib&&(k=b.offsetHeight),this.cTT=o}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,c){var d={},e=Aa?"-ms-transform":ib?"-webkit-transform":Ta?"MozTransform":Ib?"-o-transform":"";d[e]=d.transform="rotate("+a+"deg)",d[e+(Ta?"Origin":"-origin")]=d.transformOrigin=100*b+"% "+c+"px",G(this.element,d)},getSpanCorrection:function(a,b,c){this.xCorr=-a*c,this.yCorr=-b}}),q(ta.prototype,{html:function(a,b,c){var d=this.createElement("span"),e=d.element,f=d.renderer;return d.textSetter=function(a){a!==e.innerHTML&&delete this.bBox,e.innerHTML=this.textStr=a},d.xSetter=d.ySetter=d.alignSetter=d.rotationSetter=function(a,b){"align"===b&&(b="textAlign"),d[b]=a,d.htmlUpdateTransform()},d.attr({text:a,x:u(b),y:u(c)}).css({position:"absolute",whiteSpace:"nowrap",fontFamily:this.style.fontFamily,fontSize:this.style.fontSize}),d.css=d.htmlCss,f.isSVG&&(d.add=function(a){var b,c=f.box.parentNode,j=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)j.push(a),a=a.parentGroup;p(j.reverse(),function(a){var d;b=a.div=a.div||Y(Ja,{className:H(a.element,"class")},{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px"},b||c),d=b.style,q(a,{translateXSetter:function(b,c){d.left=b+"px",a[c]=b,a.doTransform=!0},translateYSetter:function(b,c){d.top=b+"px",a[c]=b,a.doTransform=!0},visibilitySetter:function(a,b){d[b]=a}})})}}else b=c;return b.appendChild(e),d.added=!0,d.alignOnAdd&&d.htmlUpdateTransform(),d}),d}});var X;if(!aa&&!fa){R.VMLElement=X={init:function(a,b){var c=["<",b,' filled="f" stroked="f"'],d=["position: ","absolute",";"],e=b===Ja;("shape"===b||e)&&d.push("left:0;top:0;width:1px;height:1px;"),d.push("visibility: ",e?"hidden":"visible"),c.push(' style="',d.join(""),'"/>'),b&&(c=e||"span"===b||"img"===b?c.join(""):a.prepVML(c),this.element=Y(c)),this.renderer=a},add:function(a){var b=this.renderer,c=this.element,d=b.box,d=a?a.element||a:d;return a&&a.inverted&&b.invertChild(c,d),d.appendChild(c),this.added=!0,this.alignOnAdd&&!this.deferUpdateTransform&&this.updateTransform(),this.onAdd&&this.onAdd(),this},updateTransform:P.prototype.htmlUpdateTransform,setSpanRotation:function(){var a=this.rotation,b=Z(a*Ca),c=ea(a*Ca);G(this.element,{filter:a?["progid:DXImageTransform.Microsoft.Matrix(M11=",b,", M12=",-c,", M21=",c,", M22=",b,", sizingMethod='auto expand')"].join(""):Q})},getSpanCorrection:function(a,b,c,d,e){var i,f=d?Z(d*Ca):1,g=d?ea(d*Ca):0,h=m(this.elemHeight,this.element.offsetHeight);this.xCorr=0>f&&-a,this.yCorr=0>g&&-h,i=0>f*g,this.xCorr+=g*b*(i?1-c:c),this.yCorr-=f*b*(d?i?c:1-c:1),e&&"left"!==e&&(this.xCorr-=a*c*(0>f?-1:1),d&&(this.yCorr-=h*c*(0>g?-1:1)),G(this.element,{textAlign:e}))},pathToVML:function(a){for(var b=a.length,c=[];b--;)ha(a[b])?c[b]=u(10*a[b])-5:"Z"===a[b]?c[b]="x":(c[b]=a[b],!a.isArc||"wa"!==a[b]&&"at"!==a[b]||(c[b+5]===c[b+7]&&(c[b+7]+=a[b+7]>a[b+5]?1:-1),c[b+6]===c[b+8]&&(c[b+8]+=a[b+8]>a[b+6]?1:-1)));return c.join(" ")||"x"},clip:function(a){var c,b=this;return a?(c=a.members,ja(c,b),c.push(b),b.destroyClip=function(){ja(c,b)},a=a.getCSS(b)):(b.destroyClip&&b.destroyClip(),a={clip:hb?"inherit":"rect(auto)"}),b.css(a)},css:P.prototype.htmlCss,safeRemoveChild:function(a){a.parentNode&&Pa(a)},destroy:function(){return this.destroyClip&&this.destroyClip(),P.prototype.destroy.apply(this)},on:function(a,b){return this.element["on"+a]=function(){var a=I.event;a.target=a.srcElement,b(a)},this},cutOffPath:function(a,b){var c,a=a.split(/[ ,]/);return c=a.length,(9===c||11===c)&&(a[c-4]=a[c-2]=z(a[c-2])-10*b),a.join(" ")},shadow:function(a,b,c){var e,h,j,l,o,n,s,d=[],f=this.element,g=this.renderer,i=f.style,k=f.path;if(k&&"string"!=typeof k.value&&(k="x"),o=k,a){for(n=m(a.width,3),s=(a.opacity||.15)/n,e=1;3>=e;e++)l=2*n+1-2*e,c&&(o=this.cutOffPath(k.value,l+.5)),j=['<shape isShadow="true" strokeweight="',l,'" filled="false" path="',o,'" coordsize="10 10" style="',f.style.cssText,'" />'],h=Y(g.prepVML(j),null,{left:z(i.left)+m(a.offsetX,1),top:z(i.top)+m(a.offsetY,1)}),c&&(h.cutOff=l+1),j=['<stroke color="',a.color||"black",'" opacity="',s*e,'"/>'],Y(g.prepVML(j),null,null,h),b?b.element.appendChild(h):f.parentNode.insertBefore(h,f),d.push(h);this.shadows=d}return this},updateShadows:sa,setAttr:function(a,b){hb?this.element[a]=b:this.element.setAttribute(a,b)},classSetter:function(a){this.element.className=a},dashstyleSetter:function(a,b,c){(c.getElementsByTagName("stroke")[0]||Y(this.renderer.prepVML(["<stroke/>"]),null,null,c))[b]=a||"solid",this[b]=a},dSetter:function(a,b,c){var d=this.shadows,a=a||[];if(this.d=a.join(" "),c.path=a=this.pathToVML(a),d)for(c=d.length;c--;)d[c].path=d[c].cutOff?this.cutOffPath(a,d[c].cutOff):a;this.setAttr(b,a)},fillSetter:function(a,b,c){var d=c.nodeName;"SPAN"===d?c.style.color=a:"IMG"!==d&&(c.filled=a!==Q,this.setAttr("fillcolor",this.renderer.color(a,c,b,this)))},opacitySetter:sa,rotationSetter:function(a,b,c){c=c.style,this[b]=c[b]=a,c.left=-u(ea(a*Ca)+1)+"px",c.top=u(Z(a*Ca))+"px"},strokeSetter:function(a,b,c){this.setAttr("strokecolor",this.renderer.color(a,c,b))},"stroke-widthSetter":function(a,b,c){c.stroked=!!a,this[b]=a,ha(a)&&(a+="px"),this.setAttr("strokeweight",a)},titleSetter:function(a,b){this.setAttr(b,a)},visibilitySetter:function(a,b,c){"inherit"===a&&(a="visible"),this.shadows&&p(this.shadows,function(c){c.style[b]=a}),"DIV"===c.nodeName&&(a="hidden"===a?"-999em":0,hb||(c.style[b]=a?"visible":"hidden"),b="top"),c.style[b]=a},xSetter:function(a,b,c){this[b]=a,"x"===b?b="left":"y"===b&&(b="top"),this.updateClipping?(this[b]=a,this.updateClipping()):c.style[b]=a},zIndexSetter:function(a,b,c){c.style[b]=a}},X=ka(P,X),X.prototype.ySetter=X.prototype.widthSetter=X.prototype.heightSetter=X.prototype.xSetter;var ga={Element:X,isIE8:wa.indexOf("MSIE 8.0")>-1,init:function(a,b,c,d){var e;if(this.alignedObjects=[],d=this.createElement(Ja).css(q(this.getStyle(d),{position:"relative"})),e=d.element,a.appendChild(d.element),this.isVML=!0,this.box=e,this.boxWrapper=d,this.cache={},this.setSize(b,c,!1),!y.namespaces.hcv){y.namespaces.add("hcv","urn:schemas-microsoft-com:vml");try{y.createStyleSheet().cssText="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}catch(f){y.styleSheets[0].cssText+="hcv\\:fill, hcv\\:path, hcv\\:shape, hcv\\:stroke{ behavior:url(#default#VML); display: inline-block; } "}}},isHidden:function(){return!this.box.offsetWidth},clipRect:function(a,b,c,d){var e=this.createElement(),f=ca(a);return q(e,{members:[],left:(f?a.x:a)+1,top:(f?a.y:b)+1,width:(f?a.width:c)-1,height:(f?a.height:d)-1,getCSS:function(a){var b=a.element,c=b.nodeName,a=a.inverted,d=this.top-("shape"===c?b.offsetTop:0),e=this.left,b=e+this.width,f=d+this.height,d={clip:"rect("+u(a?e:d)+"px,"+u(a?f:b)+"px,"+u(a?b:f)+"px,"+u(a?d:e)+"px)"};return!a&&hb&&"DIV"===c&&q(d,{width:b+"px",height:f+"px"}),d},updateClipping:function(){p(e.members,function(a){a.element&&a.css(e.getCSS(a))})}})},color:function(a,b,c,d){var f,h,i,e=this,g=/^rgba/,j=Q;if(a&&a.linearGradient?i="gradient":a&&a.radialGradient&&(i="pattern"),i){var k,l,n,s,m,J,L,r,o=a.linearGradient||a.radialGradient,x="",a=a.stops,v=[],q=function(){h=['<fill colors="'+v.join(",")+'" opacity="',m,'" o:opacity2="',s,'" type="',i,'" ',x,'focus="100%" method="any" />'],Y(e.prepVML(h),null,null,b)};if(n=a[0],r=a[a.length-1],n[0]>0&&a.unshift([0,n[1]]),r[0]<1&&a.push([1,r[1]]),p(a,function(a,b){g.test(a[1])?(f=ya(a[1]),k=f.get("rgb"),l=f.get("a")):(k=a[1],l=1),v.push(100*a[0]+"% "+k),b?(m=l,J=k):(s=l,L=k)}),"fill"===c)if("gradient"===i)c=o.x1||o[0]||0,a=o.y1||o[1]||0,n=o.x2||o[2]||0,o=o.y2||o[3]||0,x='angle="'+(90-180*U.atan((o-a)/(n-c))/ma)+'"',q();else{var w,j=o.r,t=2*j,u=2*j,y=o.cx,B=o.cy,na=b.radialReference,j=function(){na&&(w=d.getBBox(),y+=(na[0]-w.x)/w.width-.5,B+=(na[1]-w.y)/w.height-.5,t*=na[2]/w.width,u*=na[2]/w.height),x='src="'+E.global.VMLRadialGradientURL+'" size="'+t+","+u+'" origin="0.5,0.5" position="'+y+","+B+'" color2="'+L+'" ',q()};d.added?j():d.onAdd=j,j=J}else j=k}else g.test(a)&&"IMG"!==b.tagName?(f=ya(a),h=["<",c,' opacity="',f.get("a"),'"/>'],Y(this.prepVML(h),null,null,b),j=f.get("rgb")):(j=b.getElementsByTagName(c),j.length&&(j[0].opacity=1,j[0].type="solid"),j=a);return j},prepVML:function(a){var b=this.isIE8,a=a.join("");return b?(a=a.replace("/>",' xmlns="urn:schemas-microsoft-com:vml" />'),a=-1===a.indexOf('style="')?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:"),a},text:ta.prototype.html,path:function(a){var b={coordsize:"10 10"};return La(a)?b.d=a:ca(a)&&q(b,a),this.createElement("shape").attr(b)},circle:function(a,b,c){var d=this.symbol("circle");return ca(a)&&(c=a.r,b=a.y,a=a.x),d.isCircle=!0,d.r=c,d.attr({x:a,y:b})},g:function(a){var b;return a&&(b={className:"highcharts-"+a,"class":"highcharts-"+a}),this.createElement(Ja).attr(b)},image:function(a,b,c,d,e){var f=this.createElement("img").attr({src:a});return arguments.length>1&&f.attr({x:b,y:c,width:d,height:e}),f},createElement:function(a){return"rect"===a?this.symbol(a):ta.prototype.createElement.call(this,a)},invertChild:function(a,b){var c=this,d=b.style,e="IMG"===a.tagName&&a.style;G(a,{flip:"x",left:z(d.width)-(e?z(e.top):1),top:z(d.height)-(e?z(e.left):1),rotation:-90}),p(a.childNodes,function(b){c.invertChild(b,a)})},symbols:{arc:function(a,b,c,d,e){var f=e.start,g=e.end,h=e.r||c||d,c=e.innerR,d=Z(f),i=ea(f),j=Z(g),k=ea(g);return g-f===0?["x"]:(f=["wa",a-h,b-h,a+h,b+h,a+h*d,b+h*i,a+h*j,b+h*k],e.open&&!c&&f.push("e","M",a,b),f.push("at",a-c,b-c,a+c,b+c,a+c*j,b+c*k,a+c*d,b+c*i,"x","e"),f.isArc=!0,f)},circle:function(a,b,c,d,e){return e&&(c=d=2*e.r),e&&e.isCircle&&(a-=c/2,b-=d/2),["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){return ta.prototype.symbols[r(e)&&e.r?"callout":"square"].call(0,a,b,c,d,e)}}};R.VMLRenderer=X=function(){this.init.apply(this,arguments)},X.prototype=w(ta.prototype,ga),Za=X}ta.prototype.measureSpanWidth=function(a,b){var d,c=y.createElement("span");return d=y.createTextNode(a),c.appendChild(d),G(c,b),this.box.appendChild(c),d=c.offsetWidth,Pa(c),d};var Lb;fa&&(R.CanVGRenderer=X=function(){xa="http://www.w3.org/1999/xhtml"},X.prototype.symbols={},Lb=function(){function a(){var d,a=b.length;for(d=0;a>d;d++)b[d]();b=[]}var b=[];return{push:function(c,d){0===b.length&&Qb(d,a),b.push(c)}}}(),Za=X),Sa.prototype={addLabel:function(){var l,a=this.axis,b=a.options,c=a.chart,d=a.horiz,e=a.categories,f=a.names,g=this.pos,h=b.labels,i=a.tickPositions,d=d&&e&&!h.step&&!h.staggerLines&&!h.rotation&&c.plotWidth/i.length||!d&&(c.margin[3]||.33*c.chartWidth),j=g===i[0],k=g===i[i.length-1],f=e?m(e[g],f[g],g):g,e=this.label,o=i.info;a.isDatetimeAxis&&o&&(l=b.dateTimeLabelFormats[o.higherRanks[g]||o.unitName]),this.isFirst=j,this.isLast=k,b=a.labelFormatter.call({axis:a,chart:c,isFirst:j,isLast:k,dateTimeLabelFormat:l,value:a.isLog?da(ia(f)):f}),g=d&&{width:v(1,u(d-2*(h.padding||10)))+"px"},g=q(g,h.style),r(e)?e&&e.attr({text:b}).css(g):(l={align:a.labelAlign},ha(h.rotation)&&(l.rotation=h.rotation),d&&h.ellipsis&&(l._clipHeight=a.len/i.length),this.label=r(b)&&h.enabled?c.renderer.text(b,0,0,h.useHTML).attr(l).css(g).add(a.labelGroup):null)},getLabelSize:function(){var a=this.label,b=this.axis;return a?a.getBBox()[b.horiz?"height":"width"]:0},getLabelSides:function(){var a=this.label.getBBox(),b=this.axis,c=b.horiz,d=b.options.labels,a=c?a.width:a.height,b=c?d.x-a*{left:0,center:.5,right:1}[b.labelAlign]:0;return[b,c?a+b:a]},handleOverflow:function(a,b){var l,o,n,c=!0,d=this.axis,e=this.isFirst,f=this.isLast,g=d.horiz?b.x:b.y,h=d.reversed,i=d.tickPositions,j=this.getLabelSides(),k=j[0],j=j[1],s=this.label.line||0;if(l=d.labelEdge,o=d.justifyLabels&&(e||f),l[s]===t||g+k>l[s]?l[s]=g+j:o||(c=!1),o){l=(o=d.justifyToPlot)?d.pos:0,o=o?l+d.len:d.chart.chartWidth;do a+=e?1:-1,n=d.ticks[i[a]];while(i[a]&&(!n||n.label.line!==s));d=n&&n.label.xy&&n.label.xy.x+n.getLabelSides()[e?0:1],e&&!h||f&&h?l>g+k&&(g=l-k,n&&g+j>d&&(c=!1)):g+j>o&&(g=o-j,n&&d>g+k&&(c=!1)),b.x=g}return c},getPosition:function(a,b,c,d){var e=this.axis,f=e.chart,g=d&&f.oldChartHeight||f.chartHeight;return{x:a?e.translate(b+c,null,null,d)+e.transB:e.left+e.offset+(e.opposite?(d&&f.oldChartWidth||f.chartWidth)-e.right-e.left:0),y:a?g-e.bottom+e.offset-(e.opposite?e.height:0):g-e.translate(b+c,null,null,d)-e.transB}},getLabelPosition:function(a,b,c,d,e,f,g,h){var i=this.axis,j=i.transA,k=i.reversed,l=i.staggerLines,o=i.chart.renderer.fontMetrics(e.style.fontSize).b,n=e.rotation,a=a+e.x-(f&&d?f*j*(k?-1:1):0),b=b+e.y-(f&&!d?f*j*(k?1:-1):0);return n&&2===i.side&&(b-=o-o*Z(n*Ca)),!r(e.y)&&!n&&(b+=o-c.getBBox().height/2),l&&(c.line=g/(h||1)%l,b+=c.line*(i.labelOffset/l)),{x:a,y:b}},getMarkPath:function(a,b,c,d,e,f){return f.crispLine(["M",a,b,"L",a+(e?0:-c),b+(e?c:0)],d)},render:function(a,b,c){var d=this.axis,e=d.options,f=d.chart.renderer,g=d.horiz,h=this.type,i=this.label,j=this.pos,k=e.labels,l=this.gridLine,o=h?h+"Grid":"grid",n=h?h+"Tick":"tick",s=e[o+"LineWidth"],p=e[o+"LineColor"],J=e[o+"LineDashStyle"],L=e[n+"Length"],o=e[n+"Width"]||0,x=e[n+"Color"],r=e[n+"Position"],n=this.mark,v=k.step,q=!0,u=d.tickmarkOffset,w=this.getPosition(g,j,u,b),y=w.x,w=w.y,B=g&&y===d.pos+d.len||!g&&w===d.pos?-1:1;this.isActive=!0,s&&(j=d.getPlotLinePath(j+u,s*B,b,!0),l===t&&(l={stroke:p,"stroke-width":s},J&&(l.dashstyle=J),h||(l.zIndex=1),b&&(l.opacity=0),this.gridLine=l=s?f.path(j).attr(l).add(d.gridGroup):null),!b&&l&&j&&l[this.isNew?"attr":"animate"]({d:j,opacity:c})),o&&L&&("inside"===r&&(L=-L),d.opposite&&(L=-L),h=this.getMarkPath(y,w,L,o*B,g,f),n?n.animate({d:h,opacity:c}):this.mark=f.path(h).attr({stroke:x,"stroke-width":o,opacity:c}).add(d.axisGroup)),i&&!isNaN(y)&&(i.xy=w=this.getLabelPosition(y,w,i,g,k,u,a,v),this.isFirst&&!this.isLast&&!m(e.showFirstLabel,1)||this.isLast&&!this.isFirst&&!m(e.showLastLabel,1)?q=!1:!d.isRadial&&!k.step&&!k.rotation&&!b&&0!==c&&(q=this.handleOverflow(a,w)),v&&a%v&&(q=!1),q&&!isNaN(w.y)?(w.opacity=c,i[this.isNew?"attr":"animate"](w),this.isNew=!1):i.attr("y",-9999))},destroy:function(){Oa(this,this.axis)}},R.PlotLineOrBand=function(a,b){this.axis=a,b&&(this.options=b,this.id=b.id)},R.PlotLineOrBand.prototype={render:function(){var p,a=this,b=a.axis,c=b.horiz,d=(b.pointRange||0)/2,e=a.options,f=e.label,g=a.label,h=e.width,i=e.to,j=e.from,k=r(j)&&r(i),l=e.value,o=e.dashStyle,n=a.svgElem,s=[],J=e.color,L=e.zIndex,x=e.events,q={},t=b.chart.renderer;if(b.isLog&&(j=za(j),i=za(i),l=za(l)),h)s=b.getPlotLinePath(l,h),q={stroke:J,"stroke-width":h},o&&(q.dashstyle=o);else{if(!k)return;j=v(j,b.min-d),i=C(i,b.max+d),s=b.getPlotBandPath(j,i,e),J&&(q.fill=J),e.borderWidth&&(q.stroke=e.borderColor,q["stroke-width"]=e.borderWidth)}if(r(L)&&(q.zIndex=L),n)s?n.animate({d:s},null,n.onGetPath):(n.hide(),n.onGetPath=function(){n.show()},g&&(a.label=g=g.destroy()));else if(s&&s.length&&(a.svgElem=n=t.path(s).attr(q).add(),x))for(p in d=function(b){n.on(b,function(c){x[b].apply(a,[c])})},x)d(p);return f&&r(f.text)&&s&&s.length&&b.width>0&&b.height>0?(f=w({align:c&&k&&"center",x:c?!k&&4:10,verticalAlign:!c&&k&&"middle",y:c?k?16:10:k?6:-4,rotation:c&&!k&&90},f),g||(q={align:f.textAlign||f.align,rotation:f.rotation},r(L)&&(q.zIndex=L),a.label=g=t.text(f.text,0,0,f.useHTML).attr(q).css(f.style).add()),b=[s[1],s[4],m(s[6],s[1])],s=[s[2],s[5],m(s[7],s[2])],c=Na(b),k=Na(s),g.align(f,!1,{x:c,y:k,width:Ba(b)-c,height:Ba(s)-k}),g.show()):g&&g.hide(),a},destroy:function(){ja(this.axis.plotLinesAndBands,this),delete this.axis,Oa(this)}},la.prototype={defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,gridLineColor:"#C0C0C0",labels:N,lineColor:"#C0D0E0",lineWidth:1,minPadding:.01,maxPadding:.01,minorGridLineColor:"#E0E0E0",minorGridLineWidth:1,minorTickColor:"#A0A0A0",minorTickLength:2,minorTickPosition:"outside",startOfWeek:1,startOnTick:!1,tickColor:"#C0D0E0",tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",tickWidth:1,title:{align:"middle",style:{color:"#707070"}},type:"linear"},defaultYAxisOptions:{endOnTick:!0,gridLineWidth:1,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8,y:3},lineWidth:0,maxPadding:.05,minPadding:.05,startOnTick:!0,tickWidth:0,title:{rotation:270,text:"Values"},stackLabels:{enabled:!1,formatter:function(){return Ga(this.total,-1)},style:N.style}},defaultLeftAxisOptions:{labels:{x:-15,y:null},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15,y:null},title:{rotation:90}},defaultBottomAxisOptions:{labels:{x:0,y:20},title:{rotation:0}},defaultTopAxisOptions:{labels:{x:0,y:-15},title:{rotation:0}},init:function(a,b){var c=b.isX;this.horiz=a.inverted?!c:c,this.coll=(this.isXAxis=c)?"xAxis":"yAxis",this.opposite=b.opposite,this.side=b.side||(this.horiz?this.opposite?0:2:this.opposite?1:3),this.setOptions(b);var d=this.options,e=d.type;this.labelFormatter=d.labels.formatter||this.defaultLabelFormatter,this.userOptions=b,this.minPixelPadding=0,this.chart=a,this.reversed=d.reversed,this.zoomEnabled=d.zoomEnabled!==!1,this.categories=d.categories||"category"===e,this.names=[],this.isLog="logarithmic"===e,this.isDatetimeAxis="datetime"===e,this.isLinked=r(d.linkedTo),this.tickmarkOffset=this.categories&&"between"===d.tickmarkPlacement?.5:0,this.ticks={},this.labelEdge=[],this.minorTicks={},this.plotLinesAndBands=[],this.alternateBands={},this.len=0,this.minRange=this.userMinRange=d.minRange||d.maxZoom,this.range=d.range,this.offset=d.offset||0,this.stacks={},this.oldStacks={},this.min=this.max=null,this.crosshair=m(d.crosshair,qa(a.options.tooltip.crosshairs)[c?0:1],!1);var f,d=this.options.events;-1===Da(this,a.axes)&&(c&&!this.isColorAxis?a.axes.splice(a.xAxis.length,0,this):a.axes.push(this),a[this.coll].push(this)),this.series=this.series||[],a.inverted&&c&&this.reversed===t&&(this.reversed=!0),this.removePlotLine=this.removePlotBand=this.removePlotBandOrLine;for(f in d)K(this,f,d[f]);this.isLog&&(this.val2lin=za,this.lin2val=ia)},setOptions:function(a){this.options=w(this.defaultOptions,this.isXAxis?{}:this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions,this.defaultLeftAxisOptions][this.side],w(E[this.coll],a))},defaultLabelFormatter:function(){var g,a=this.axis,b=this.value,c=a.categories,d=this.dateTimeLabelFormat,e=E.lang.numericSymbols,f=e&&e.length,h=a.options.labels.format,a=a.isLog?b:a.tickInterval;if(h)g=Ia(h,this);else if(c)g=b;else if(d)g=cb(d,b);else if(f&&a>=1e3)for(;f--&&g===t;)c=Math.pow(1e3,f+1),a>=c&&null!==e[f]&&(g=Ga(b/c,-1)+e[f]);return g===t&&(g=M(b)>=1e4?Ga(b,0):Ga(b,-1,t,"")),g},getSeriesExtremes:function(){var a=this,b=a.chart;a.hasVisibleSeries=!1,a.dataMin=a.dataMax=null,a.buildStacks&&a.buildStacks(),p(a.series,function(c){if(c.visible||!b.options.chart.ignoreHiddenSeries){var d;d=c.options.threshold;var e;a.hasVisibleSeries=!0,a.isLog&&0>=d&&(d=null),a.isXAxis?(d=c.xData,d.length&&(a.dataMin=C(m(a.dataMin,d[0]),Na(d)),a.dataMax=v(m(a.dataMax,d[0]),Ba(d)))):(c.getExtremes(),e=c.dataMax,c=c.dataMin,r(c)&&r(e)&&(a.dataMin=C(m(a.dataMin,c),c),a.dataMax=v(m(a.dataMax,e),e)),r(d)&&(a.dataMin>=d?(a.dataMin=d,a.ignoreMinPadding=!0):a.dataMax<d&&(a.dataMax=d,a.ignoreMaxPadding=!0)))}})},translate:function(a,b,c,d,e,f){var g=1,h=0,i=d?this.oldTransA:this.transA,d=d?this.oldMin:this.min,j=this.minPixelPadding,e=(this.options.ordinal||this.isLog&&e)&&this.lin2val;return i||(i=this.transA),c&&(g*=-1,h=this.len),this.reversed&&(g*=-1,h-=g*(this.sector||this.len)),b?(a=a*g+h,a-=j,a=a/i+d,e&&(a=this.lin2val(a))):(e&&(a=this.val2lin(a)),"between"===f&&(f=.5),a=g*(a-d)*i+h+g*j+(ha(f)?i*f*this.pointRange:0)),a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,e){var i,j,o,f=this.chart,g=this.left,h=this.top,k=c&&f.oldChartHeight||f.chartHeight,l=c&&f.oldChartWidth||f.chartWidth;return i=this.transB,e=m(e,this.translate(a,null,null,c)),a=c=u(e+i),i=j=u(k-e-i),isNaN(e)?o=!0:this.horiz?(i=h,j=k-this.bottom,(g>a||a>g+this.width)&&(o=!0)):(a=g,c=l-this.right,(h>i||i>h+this.height)&&(o=!0)),o&&!d?null:f.renderer.crispLine(["M",a,i,"L",c,j],b||1)},getLinearTickPositions:function(a,b,c){var d,e=da(T(b/a)*a),f=da(Ka(c/a)*a),g=[];if(b===c&&ha(b))return[b];for(b=e;f>=b&&(g.push(b),b=da(b+a),b!==d);)d=b;return g},getMinorTickPositions:function(){var e,a=this.options,b=this.tickPositions,c=this.minorTickInterval,d=[];if(this.isLog)for(e=b.length,a=1;e>a;a++)d=d.concat(this.getLogTickPositions(c,b[a-1],b[a],!0));else if(this.isDatetimeAxis&&"auto"===a.minorTickInterval)d=d.concat(this.getTimeTicks(this.normalizeTimeTickInterval(c),this.min,this.max,a.startOfWeek)),d[0]<this.min&&d.shift();else for(b=this.min+(b[0]-this.min)%c;b<=this.max;b+=c)d.push(b);return d},adjustForMinRange:function(){var d,f,g,h,i,j,a=this.options,b=this.min,c=this.max,e=this.dataMax-this.dataMin>=this.minRange;if(this.isXAxis&&this.minRange===t&&!this.isLog&&(r(a.min)||r(a.max)?this.minRange=null:(p(this.series,function(a){for(i=a.xData,g=j=a.xIncrement?1:i.length-1;g>0;g--)h=i[g]-i[g-1],(f===t||f>h)&&(f=h)}),this.minRange=C(5*f,this.dataMax-this.dataMin))),c-b<this.minRange){var k=this.minRange;d=(k-c+b)/2,d=[b-d,m(a.min,b-d)],e&&(d[2]=this.dataMin),b=Ba(d),c=[b+k,m(a.max,b+k)],e&&(c[2]=this.dataMax),c=Na(c),k>c-b&&(d[0]=c-k,d[1]=m(a.min,c-k),b=Ba(d))}this.min=b,this.max=c},setAxisTranslation:function(a){var e,b=this,c=b.max-b.min,d=b.axisPointRange||0,f=0,g=0,h=b.linkedParent,i=!!b.categories,j=b.transA;(b.isXAxis||i||d)&&(h?(f=h.minPointOffset,g=h.pointRangePadding):p(b.series,function(a){var h=i?1:b.isXAxis?a.pointRange:b.axisPointRange||0,j=a.options.pointPlacement,n=a.closestPointRange;h>c&&(h=0),d=v(d,h),f=v(f,Fa(j)?0:h/2),g=v(g,"on"===j?0:h),!a.noSharedTooltip&&r(n)&&(e=r(e)?C(e,n):n)}),h=b.ordinalSlope&&e?b.ordinalSlope/e:1,b.minPointOffset=f*=h,b.pointRangePadding=g*=h,b.pointRange=C(d,c),b.closestPointRange=e),a&&(b.oldTransA=j),b.translationSlope=b.transA=j=b.len/(c+g||1),b.transB=b.horiz?b.left:b.bottom,b.minPixelPadding=j*f},setTickPositions:function(a){var s,b=this,c=b.chart,d=b.options,e=b.isLog,f=b.isDatetimeAxis,g=b.isXAxis,h=b.isLinked,i=b.options.tickPositioner,j=d.maxPadding,k=d.minPadding,l=d.tickInterval,o=d.minTickInterval,n=d.tickPixelInterval,$=b.categories;h?(b.linkedParent=c[b.coll][d.linkedTo],c=b.linkedParent.getExtremes(),b.min=m(c.min,c.dataMin),b.max=m(c.max,c.dataMax),d.type!==b.linkedParent.options.type&&ra(11,1)):(b.min=m(b.userMin,d.min,b.dataMin),b.max=m(b.userMax,d.max,b.dataMax)),e&&(!a&&C(b.min,m(b.dataMin,b.min))<=0&&ra(10,1),b.min=da(za(b.min)),b.max=da(za(b.max))),b.range&&r(b.max)&&(b.userMin=b.min=v(b.min,b.max-b.range),b.userMax=b.max,b.range=null),b.beforePadding&&b.beforePadding(),b.adjustForMinRange(),$||b.axisPointRange||b.usePercentage||h||!r(b.min)||!r(b.max)||!(c=b.max-b.min)||(r(d.min)||r(b.userMin)||!k||!(b.dataMin<0)&&b.ignoreMinPadding||(b.min-=c*k),r(d.max)||r(b.userMax)||!j||!(b.dataMax>0)&&b.ignoreMaxPadding||(b.max+=c*j)),ha(d.floor)&&(b.min=v(b.min,d.floor)),ha(d.ceiling)&&(b.max=C(b.max,d.ceiling)),b.min===b.max||void 0===b.min||void 0===b.max?b.tickInterval=1:h&&!l&&n===b.linkedParent.options.tickPixelInterval?b.tickInterval=b.linkedParent.tickInterval:(b.tickInterval=m(l,$?1:(b.max-b.min)*n/v(b.len,n)),!r(l)&&b.len<n&&!this.isRadial&&!this.isLog&&!$&&d.startOnTick&&d.endOnTick&&(s=!0,b.tickInterval/=4)),g&&!a&&p(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)}),b.setAxisTranslation(!0),b.beforeSetTickPositions&&b.beforeSetTickPositions(),b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval)),b.pointRange&&(b.tickInterval=v(b.pointRange,b.tickInterval)),!l&&b.tickInterval<o&&(b.tickInterval=o),f||e||l||(b.tickInterval=nb(b.tickInterval,null,mb(b.tickInterval),d)),b.minorTickInterval="auto"===d.minorTickInterval&&b.tickInterval?b.tickInterval/5:d.minorTickInterval,b.tickPositions=a=d.tickPositions?[].concat(d.tickPositions):i&&i.apply(b,[b.min,b.max]),a||(!b.ordinalPositions&&(b.max-b.min)/b.tickInterval>v(2*b.len,200)&&ra(19,!0),a=f?b.getTimeTicks(b.normalizeTimeTickInterval(b.tickInterval,d.units),b.min,b.max,d.startOfWeek,b.ordinalPositions,b.closestPointRange,!0):e?b.getLogTickPositions(b.tickInterval,b.min,b.max):b.getLinearTickPositions(b.tickInterval,b.min,b.max),s&&a.splice(1,a.length-2),b.tickPositions=a),h||(e=a[0],f=a[a.length-1],h=b.minPointOffset||0,d.startOnTick?b.min=e:b.min-h>e&&a.shift(),d.endOnTick?b.max=f:b.max+h<f&&a.pop(),1===a.length&&(d=M(b.max)>1e13?1:.001,b.min-=d,b.max+=d))},setMaxTicks:function(){var a=this.chart,b=a.maxTicks||{},c=this.tickPositions,d=this._maxTicksKey=[this.coll,this.pos,this.len].join("-");!this.isLinked&&!this.isDatetimeAxis&&c&&c.length>(b[d]||0)&&this.options.alignTicks!==!1&&(b[d]=c.length),a.maxTicks=b},adjustTickAmount:function(){var a=this._maxTicksKey,b=this.tickPositions,c=this.chart.maxTicks;if(c&&c[a]&&!this.isDatetimeAxis&&!this.categories&&!this.isLinked&&this.options.alignTicks!==!1&&this.min!==t){var d=this.tickAmount,e=b.length;if(this.tickAmount=a=c[a],a>e){for(;b.length<a;)b.push(da(b[b.length-1]+this.tickInterval));this.transA*=(e-1)/(a-1),this.max=b[b.length-1]}r(d)&&a!==d&&(this.isDirty=!0)}},setScale:function(){var b,c,d,e,a=this.stacks;if(this.oldMin=this.min,this.oldMax=this.max,this.oldAxisLength=this.len,this.setAxisSize(),e=this.len!==this.oldAxisLength,p(this.series,function(a){(a.isDirtyData||a.isDirty||a.xAxis.isDirty)&&(d=!0)}),e||d||this.isLinked||this.forceRedraw||this.userMin!==this.oldUserMin||this.userMax!==this.oldUserMax){if(!this.isXAxis)for(b in a)for(c in a[b])a[b][c].total=null,a[b][c].cum=0;this.forceRedraw=!1,this.getSeriesExtremes(),this.setTickPositions(),this.oldUserMin=this.userMin,this.oldUserMax=this.userMax,this.isDirty||(this.isDirty=e||this.min!==this.oldMin||this.max!==this.oldMax)}else if(!this.isXAxis){this.oldStacks&&(a=this.stacks=this.oldStacks);for(b in a)for(c in a[b])a[b][c].cum=a[b][c].total}this.setMaxTicks()},setExtremes:function(a,b,c,d,e){var f=this,g=f.chart,c=m(c,!0),e=q(e,{min:a,max:b});D(f,"setExtremes",e,function(){f.userMin=a,f.userMax=b,f.eventArgs=e,f.isDirtyExtremes=!0,c&&g.redraw(d)})},zoom:function(a,b){var c=this.dataMin,d=this.dataMax,e=this.options;return this.allowZoomOutside||(r(c)&&a<=C(c,m(e.min,c))&&(a=t),r(d)&&b>=v(d,m(e.max,d))&&(b=t)),this.displayBtn=a!==t||b!==t,this.setExtremes(a,b,!1,t,{trigger:"zoom"}),!0},setAxisSize:function(){var a=this.chart,b=this.options,c=b.offsetLeft||0,d=this.horiz,e=m(b.width,a.plotWidth-c+(b.offsetRight||0)),f=m(b.height,a.plotHeight),g=m(b.top,a.plotTop),b=m(b.left,a.plotLeft+c),c=/%$/;c.test(f)&&(f=parseInt(f,10)/100*a.plotHeight),c.test(g)&&(g=parseInt(g,10)/100*a.plotHeight+a.plotTop),this.left=b,this.top=g,this.width=e,this.height=f,this.bottom=a.chartHeight-f-g,this.right=a.chartWidth-e-b,this.len=v(d?e:f,0),this.pos=d?b:g},getExtremes:function(){var a=this.isLog;return{min:a?da(ia(this.min)):this.min,max:a?da(ia(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin,userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,c=b?ia(this.min):this.min,b=b?ia(this.max):this.max;return c>a||null===a?a=c:a>b&&(a=b),this.translate(a,0,1,0,1)},autoLabelAlign:function(a){return a=(m(a,0)-90*this.side+720)%360,a>15&&165>a?"right":a>195&&345>a?"left":"center"},getOffset:function(){var j,l,q,y,z,A,B,a=this,b=a.chart,c=b.renderer,d=a.options,e=a.tickPositions,f=a.ticks,g=a.horiz,h=a.side,i=b.inverted?[1,0,3,2][h]:h,k=0,o=0,n=d.title,s=d.labels,$=0,J=b.axisOffset,L=b.clipOffset,x=[-1,1,1,-1][h],u=1,w=m(s.maxStaggerLines,5),na=2===h?c.fontMetrics(s.style.fontSize).b:0;if(a.hasData=j=a.hasVisibleSeries||r(a.min)&&r(a.max)&&!!e,a.showAxis=b=j||m(d.showEmpty,!0),a.staggerLines=a.horiz&&s.staggerLines,a.axisGroup||(a.gridGroup=c.g("grid").attr({zIndex:d.gridZIndex||1}).add(),a.axisGroup=c.g("axis").attr({zIndex:d.zIndex||2}).add(),a.labelGroup=c.g("axis-labels").attr({zIndex:s.zIndex||7}).addClass("highcharts-"+a.coll.toLowerCase()+"-labels").add()),j||a.isLinked){if(a.labelAlign=m(s.align||a.autoLabelAlign(s.rotation)),p(e,function(b){f[b]?f[b].addLabel():f[b]=new Sa(a,b)
3
+ }),a.horiz&&!a.staggerLines&&w&&!s.rotation){for(q=a.reversed?[].concat(e).reverse():e;w>u;){for(j=[],y=!1,s=0;s<q.length;s++)z=q[s],A=(A=f[z].label&&f[z].label.getBBox())?A.width:0,B=s%u,A&&(z=a.translate(z),j[B]!==t&&z<j[B]&&(y=!0),j[B]=z+A);if(!y)break;u++}u>1&&(a.staggerLines=u)}p(e,function(b){(0===h||2===h||{1:"left",3:"right"}[h]===a.labelAlign)&&($=v(f[b].getLabelSize(),$))}),a.staggerLines&&($*=a.staggerLines,a.labelOffset=$)}else for(q in f)f[q].destroy(),delete f[q];n&&n.text&&n.enabled!==!1&&(a.axisTitle||(a.axisTitle=c.text(n.text,0,0,n.useHTML).attr({zIndex:7,rotation:n.rotation||0,align:n.textAlign||{low:"left",middle:"center",high:"right"}[n.align]}).addClass("highcharts-"+this.coll.toLowerCase()+"-title").css(n.style).add(a.axisGroup),a.axisTitle.isNew=!0),b&&(k=a.axisTitle.getBBox()[g?"height":"width"],o=m(n.margin,g?5:10),l=n.offset),a.axisTitle[b?"show":"hide"]()),a.offset=x*m(d.offset,J[h]),a.axisTitleMargin=m(l,$+o+($&&x*d.labels[g?"y":"x"]-na)),J[h]=v(J[h],a.axisTitleMargin+k+x*a.offset),L[i]=v(L[i],2*T(d.lineWidth/2))},getLinePath:function(a){var b=this.chart,c=this.opposite,d=this.offset,e=this.horiz,f=this.left+(c?this.width:0)+d,d=b.chartHeight-this.bottom-(c?this.height:0)+d;return c&&(a*=-1),b.renderer.crispLine(["M",e?this.left:f,e?d:this.top,"L",e?b.chartWidth-this.right:f,e?d:b.chartHeight-this.bottom],a)},getTitlePosition:function(){var a=this.horiz,b=this.left,c=this.top,d=this.len,e=this.options.title,f=a?b:c,g=this.opposite,h=this.offset,i=z(e.style.fontSize||12),d={low:f+(a?0:d),middle:f+d/2,high:f+(a?d:0)}[e.align],b=(a?c+this.height:b)+(a?1:-1)*(g?-1:1)*this.axisTitleMargin+(2===this.side?i:0);return{x:a?d:b+(g?this.width:0)+h+(e.x||0),y:a?b-(g?this.height:0)+h:d+(e.y||0)}},render:function(){var j,u,z,a=this,b=a.horiz,c=a.reversed,d=a.chart,e=d.renderer,f=a.options,g=a.isLog,h=a.isLinked,i=a.tickPositions,k=a.axisTitle,l=a.ticks,o=a.minorTicks,n=a.alternateBands,s=f.stackLabels,m=f.alternateGridColor,J=a.tickmarkOffset,L=f.lineWidth,x=d.hasRendered&&r(a.oldMin)&&!isNaN(a.oldMin),q=a.hasData,v=a.showAxis,w=f.labels.overflow,y=a.justifyLabels=b&&w!==!1;a.labelEdge.length=0,a.justifyToPlot="justify"===w,p([l,o,n],function(a){for(var b in a)a[b].isActive=!1}),(q||h)&&(a.minorTickInterval&&!a.categories&&p(a.getMinorTickPositions(),function(b){o[b]||(o[b]=new Sa(a,b,"minor")),x&&o[b].isNew&&o[b].render(null,!0),o[b].render(null,!1,1)}),i.length&&(j=i.slice(),(b&&c||!b&&!c)&&j.reverse(),y&&(j=j.slice(1).concat([j[0]])),p(j,function(b,c){y&&(c=c===j.length-1?0:c+1),(!h||b>=a.min&&b<=a.max)&&(l[b]||(l[b]=new Sa(a,b)),x&&l[b].isNew&&l[b].render(c,!0,.1),l[b].render(c,!1,1))}),J&&0===a.min&&(l[-1]||(l[-1]=new Sa(a,-1,null,!0)),l[-1].render(-1))),m&&p(i,function(b,c){c%2===0&&b<a.max&&(n[b]||(n[b]=new R.PlotLineOrBand(a)),u=b+J,z=i[c+1]!==t?i[c+1]+J:a.max,n[b].options={from:g?ia(u):u,to:g?ia(z):z,color:m},n[b].render(),n[b].isActive=!0)}),a._addedPlotLB||(p((f.plotLines||[]).concat(f.plotBands||[]),function(b){a.addPlotBandOrLine(b)}),a._addedPlotLB=!0)),p([l,o,n],function(a){var b,c,e=[],f=va?va.duration||500:0,g=function(){for(c=e.length;c--;)a[e[c]]&&!a[e[c]].isActive&&(a[e[c]].destroy(),delete a[e[c]])};for(b in a)a[b].isActive||(a[b].render(b,!1,0),a[b].isActive=!1,e.push(b));a!==n&&d.hasRendered&&f?f&&setTimeout(g,f):g()}),L&&(b=a.getLinePath(L),a.axisLine?a.axisLine.animate({d:b}):a.axisLine=e.path(b).attr({stroke:f.lineColor,"stroke-width":L,zIndex:7}).add(a.axisGroup),a.axisLine[v?"show":"hide"]()),k&&v&&(k[k.isNew?"attr":"animate"](a.getTitlePosition()),k.isNew=!1),s&&s.enabled&&a.renderStackTotals(),a.isDirty=!1},redraw:function(){var a=this.chart.pointer;a&&a.reset(!0),this.render(),p(this.plotLinesAndBands,function(a){a.render()}),p(this.series,function(a){a.isDirty=!0})},destroy:function(a){var d,b=this,c=b.stacks,e=b.plotLinesAndBands;a||W(b);for(d in c)Oa(c[d]),c[d]=null;for(p([b.ticks,b.minorTicks,b.alternateBands],function(a){Oa(a)}),a=e.length;a--;)e[a].destroy();p("stackTotalGroup,axisLine,axisTitle,axisGroup,cross,gridGroup,labelGroup".split(","),function(a){b[a]&&(b[a]=b[a].destroy())}),this.cross&&this.cross.destroy()},drawCrosshair:function(a,b){if(this.crosshair)if((r(b)||!m(this.crosshair.snap,!0))===!1)this.hideCrosshair();else{var c,d=this.crosshair,e=d.animation;m(d.snap,!0)?r(b)&&(c=this.chart.inverted!=this.horiz?b.plotX:this.len-b.plotY):c=this.horiz?a.chartX-this.pos:this.len-a.chartY+this.pos,c=this.isRadial?this.getPlotLinePath(this.isXAxis?b.x:m(b.stackY,b.y)):this.getPlotLinePath(null,null,null,null,c),null===c?this.hideCrosshair():this.cross?this.cross.attr({visibility:"visible"})[e?"animate":"attr"]({d:c},e):(e={"stroke-width":d.width||1,stroke:d.color||"#C0C0C0",zIndex:d.zIndex||2},d.dashStyle&&(e.dashstyle=d.dashStyle),this.cross=this.chart.renderer.path(c).attr(e).add())}},hideCrosshair:function(){this.cross&&this.cross.hide()}},q(la.prototype,{getPlotBandPath:function(a,b){var c=this.getPlotLinePath(b),d=this.getPlotLinePath(a);return d&&c?d.push(c[4],c[5],c[1],c[2]):d=null,d},addPlotBand:function(a){this.addPlotBandOrLine(a,"plotBands")},addPlotLine:function(a){this.addPlotBandOrLine(a,"plotLines")},addPlotBandOrLine:function(a,b){var c=new R.PlotLineOrBand(this,a).render(),d=this.userOptions;return c&&(b&&(d[b]=d[b]||[],d[b].push(a)),this.plotLinesAndBands.push(c)),c},removePlotBandOrLine:function(a){for(var b=this.plotLinesAndBands,c=this.options,d=this.userOptions,e=b.length;e--;)b[e].id===a&&b[e].destroy();p([c.plotLines||[],d.plotLines||[],c.plotBands||[],d.plotBands||[]],function(b){for(e=b.length;e--;)b[e].id===a&&ja(b,b[e])})}}),la.prototype.getTimeTicks=function(a,b,c,d){var h,e=[],f={},g=E.global.useUTC,i=new Date(b-Ra),j=a.unitRange,k=a.count;if(r(b)){j>=A.second&&(i.setMilliseconds(0),i.setSeconds(j>=A.minute?0:k*T(i.getSeconds()/k))),j>=A.minute&&i[Db](j>=A.hour?0:k*T(i[pb]()/k)),j>=A.hour&&i[Eb](j>=A.day?0:k*T(i[qb]()/k)),j>=A.day&&i[sb](j>=A.month?1:k*T(i[Xa]()/k)),j>=A.month&&(i[Fb](j>=A.year?0:k*T(i[fb]()/k)),h=i[gb]()),j>=A.year&&(h-=h%k,i[Gb](h)),j===A.week&&i[sb](i[Xa]()-i[rb]()+m(d,1)),b=1,Ra&&(i=new Date(i.getTime()+Ra)),h=i[gb]();for(var d=i.getTime(),l=i[fb](),o=i[Xa](),n=g?Ra:(864e5+6e4*i.getTimezoneOffset())%864e5;c>d;)e.push(d),j===A.year?d=eb(h+b*k,0):j===A.month?d=eb(h,l+b*k):g||j!==A.day&&j!==A.week?d+=j*k:d=eb(h,l,o+b*k*(j===A.day?1:7)),b++;e.push(d),p(vb(e,function(a){return j<=A.hour&&a%A.day===n}),function(a){f[a]="day"})}return e.info=q(a,{higherRanks:f,totalRange:j*k}),e},la.prototype.normalizeTimeTickInterval=function(a,b){var g,c=b||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]],d=c[c.length-1],e=A[d[0]],f=d[1];for(g=0;g<c.length&&(d=c[g],e=A[d[0]],f=d[1],!(c[g+1]&&a<=(e*f[f.length-1]+A[c[g+1][0]])/2));g++);return e===A.year&&5*e>a&&(f=[1,2,5]),c=nb(a/e,f,"year"===d[0]?v(mb(a/e),1):1),{unitRange:e,count:c,unitName:d[0]}},la.prototype.getLogTickPositions=function(a,b,c,d){var e=this.options,f=this.len,g=[];if(d||(this._minorAutoInterval=null),a>=.5)a=u(a),g=this.getLinearTickPositions(a,b,c);else if(a>=.08)for(var h,i,j,k,l,f=T(b),e=a>.3?[1,2,4]:a>.15?[1,2,4,6,8]:[1,2,3,4,5,6,7,8,9];c+1>f&&!l;f++)for(i=e.length,h=0;i>h&&!l;h++)j=za(ia(f)*e[h]),j>b&&(!d||c>=k)&&g.push(k),k>c&&(l=!0),k=j;else b=ia(b),c=ia(c),a=e[d?"minorTickInterval":"tickInterval"],a=m("auto"===a?null:a,this._minorAutoInterval,(c-b)*(e.tickPixelInterval/(d?5:1))/((d?f/this.tickPositions.length:f)||1)),a=nb(a,null,mb(a)),g=Ua(this.getLinearTickPositions(a,b,c),za),d||(this._minorAutoInterval=a/5);return d||(this.tickInterval=a),g};var Mb=R.Tooltip=function(){this.init.apply(this,arguments)};Mb.prototype={init:function(a,b){var c=b.borderWidth,d=b.style,e=z(d.padding);this.chart=a,this.options=b,this.crosshairs=[],this.now={x:0,y:0},this.isHidden=!0,this.label=a.renderer.label("",0,0,b.shape||"callout",null,null,b.useHTML,null,"tooltip").attr({padding:e,fill:b.backgroundColor,"stroke-width":c,r:b.borderRadius,zIndex:8}).css(d).css({padding:0}).add().attr({y:-9999}),fa||this.label.shadow(b.shadow),this.shared=b.shared},destroy:function(){this.label&&(this.label=this.label.destroy()),clearTimeout(this.hideTimer),clearTimeout(this.tooltipTimeout)},move:function(a,b,c,d){var e=this,f=e.now,g=e.options.animation!==!1&&!e.isHidden,h=e.followPointer||e.len>1;q(f,{x:g?(2*f.x+a)/3:a,y:g?(f.y+b)/2:b,anchorX:h?t:g?(2*f.anchorX+c)/3:c,anchorY:h?t:g?(f.anchorY+d)/2:d}),e.label.attr(f),g&&(M(a-f.x)>1||M(b-f.y)>1)&&(clearTimeout(this.tooltipTimeout),this.tooltipTimeout=setTimeout(function(){e&&e.move(a,b,c,d)},32))},hide:function(){var b,a=this;clearTimeout(this.hideTimer),this.isHidden||(b=this.chart.hoverPoints,this.hideTimer=setTimeout(function(){a.label.fadeOut(),a.isHidden=!0},m(this.options.hideDelay,500)),b&&p(b,function(a){a.setState()}),this.chart.hoverPoints=null)},getAnchor:function(a,b){var c,i,d=this.chart,e=d.inverted,f=d.plotTop,g=0,h=0,a=qa(a);return c=a[0].tooltipPos,this.followPointer&&b&&(b.chartX===t&&(b=d.pointer.normalize(b)),c=[b.chartX-d.plotLeft,b.chartY-f]),c||(p(a,function(a){i=a.series.yAxis,g+=a.plotX,h+=(a.plotLow?(a.plotLow+a.plotHigh)/2:a.plotY)+(!e&&i?i.top-f:0)}),g/=a.length,h/=a.length,c=[e?d.plotWidth-h:g,this.shared&&!e&&a.length>1&&b?b.chartY-f:e?d.plotHeight-g:h]),Ua(c,u)},getPosition:function(a,b,c){var g,d=this.chart,e=this.distance,f={},h=["y",d.chartHeight,b,c.plotY+d.plotTop],i=["x",d.chartWidth,a,c.plotX+d.plotLeft],j=c.ttBelow||d.inverted&&!c.negative||!d.inverted&&c.negative,k=function(a,b,c,d){var g=d-e>c,b=b>d+e+c,c=d-e-c;if(d+=e,j&&b)f[a]=d;else if(!j&&g)f[a]=c;else if(g)f[a]=c;else{if(!b)return!1;f[a]=d}},l=function(a,b,c,d){return e>d||d>b-e?!1:void(f[a]=c/2>d?1:d>b-c/2?b-c-2:d-c/2)},o=function(a){var b=h;h=i,i=b,g=a},n=function(){k.apply(0,h)!==!1?l.apply(0,i)===!1&&!g&&(o(!0),n()):g?f.x=f.y=0:(o(!0),n())};return(d.inverted||this.len>1)&&o(),n(),f},defaultFormatter:function(a){var d,b=this.points||qa(this),c=b[0].series;return d=[a.tooltipHeaderFormatter(b[0])],p(b,function(a){c=a.series,d.push(c.tooltipFormatter&&c.tooltipFormatter(a)||a.point.tooltipFormatter(c.tooltipOptions.pointFormat))}),d.push(a.options.footerFormat||""),d.join("")},refresh:function(a,b){var f,g,i,c=this.chart,d=this.label,e=this.options,h={},j=[];i=e.formatter||this.defaultFormatter;var k,h=c.hoverPoints,l=this.shared;clearTimeout(this.hideTimer),this.followPointer=qa(a)[0].series.tooltipOptions.followPointer,g=this.getAnchor(a,b),f=g[0],g=g[1],!l||a.series&&a.series.noSharedTooltip?h=a.getLabelConfig():(c.hoverPoints=a,h&&p(h,function(a){a.setState()}),p(a,function(a){a.setState("hover"),j.push(a.getLabelConfig())}),h={x:a[0].category,y:a[0].y},h.points=j,this.len=j.length,a=a[0]),i=i.call(h,this),h=a.series,this.distance=m(h.tooltipOptions.distance,16),i===!1?this.hide():(this.isHidden&&(bb(d),d.attr("opacity",1).show()),d.attr({text:i}),k=e.borderColor||a.color||h.color||"#606060",d.attr({stroke:k}),this.updatePosition({plotX:f,plotY:g,negative:a.negative,ttBelow:a.ttBelow}),this.isHidden=!1),D(c,"tooltipRefresh",{text:i,x:f+c.plotLeft,y:g+c.plotTop,borderColor:k})},updatePosition:function(a){var b=this.chart,c=this.label,c=(this.options.positioner||this.getPosition).call(this,c.width,c.height,a);this.move(u(c.x),u(c.y),a.plotX+b.plotLeft,a.plotY+b.plotTop)},tooltipHeaderFormatter:function(a){var h,b=a.series,c=b.tooltipOptions,d=c.dateTimeLabelFormats,e=c.xDateFormat,f=b.xAxis,g=f&&"datetime"===f.options.type&&ha(a.key),c=c.headerFormat,f=f&&f.closestPointRange;if(g&&!e){if(f){for(h in A)if(A[h]>=f||A[h]<=A.day&&a.key%A[h]>0){e=d[h];break}}else e=d.day;e=e||d.year}return g&&e&&(c=c.replace("{point.key}","{point.key:"+e+"}")),Ia(c,{point:a,series:b})}};var oa;$a=y.documentElement.ontouchstart!==t;var Wa=R.Pointer=function(a,b){this.init(a,b)};if(Wa.prototype={init:function(a,b){var f,c=b.chart,d=c.events,e=fa?"":c.zoomType,c=a.inverted;this.options=b,this.chart=a,this.zoomX=f=/x/.test(e),this.zoomY=e=/y/.test(e),this.zoomHor=f&&!c||e&&c,this.zoomVert=e&&!c||f&&c,this.hasZoom=f||e,this.runChartClick=d&&!!d.click,this.pinchDown=[],this.lastValidTouch={},R.Tooltip&&b.tooltip.enabled&&(a.tooltip=new Mb(a,b.tooltip),this.followTouchMove=b.tooltip.followTouchMove),this.setDOMEvents()},normalize:function(a,b){var c,d,a=a||window.event,a=Sb(a);return a.target||(a.target=a.srcElement),d=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a,b||(this.chartPosition=b=Rb(this.chart.container)),d.pageX===t?(c=v(a.x,a.clientX-b.left),d=a.y):(c=d.pageX-b.left,d=d.pageY-b.top),q(a,{chartX:u(c),chartY:u(d)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};return p(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})}),b},getIndex:function(a){var b=this.chart;return b.inverted?b.plotHeight+b.plotTop-a.chartY:a.chartX-b.plotLeft},runPointActions:function(a){var e,f,i,j,b=this.chart,c=b.series,d=b.tooltip,g=b.hoverPoint,h=b.hoverSeries,k=b.chartWidth,l=this.getIndex(a);if(d&&this.options.tooltip.shared&&(!h||!h.noSharedTooltip)){for(f=[],i=c.length,j=0;i>j;j++)c[j].visible&&c[j].options.enableMouseTracking!==!1&&!c[j].noSharedTooltip&&c[j].singularTooltips!==!0&&c[j].tooltipPoints.length&&(e=c[j].tooltipPoints[l])&&e.series&&(e._dist=M(l-e.clientX),k=C(k,e._dist),f.push(e));for(i=f.length;i--;)f[i]._dist>k&&f.splice(i,1);f.length&&f[0].clientX!==this.hoverX&&(d.refresh(f,a),this.hoverX=f[0].clientX)}c=h&&h.tooltipOptions.followPointer,h&&h.tracker&&!c?(e=h.tooltipPoints[l])&&e!==g&&e.onMouseOver(a):d&&c&&!d.isHidden&&(h=d.getAnchor([{}],a),d.updatePosition({plotX:h[0],plotY:h[1]})),d&&!this._onDocumentMouseMove&&(this._onDocumentMouseMove=function(a){V[oa]&&V[oa].pointer.onDocumentMouseMove(a)},K(y,"mousemove",this._onDocumentMouseMove)),p(b.axes,function(b){b.drawCrosshair(a,m(e,g))})},reset:function(a){var b=this.chart,c=b.hoverSeries,d=b.hoverPoint,e=b.tooltip,f=e&&e.shared?b.hoverPoints:d;(a=a&&e&&f)&&qa(f)[0].plotX===t&&(a=!1),a?(e.refresh(f),d&&d.setState(d.state,!0)):(d&&d.onMouseOut(),c&&c.onMouseOut(),e&&e.hide(),this._onDocumentMouseMove&&(W(y,"mousemove",this._onDocumentMouseMove),this._onDocumentMouseMove=null),p(b.axes,function(a){a.hideCrosshair()}),this.hoverX=null)},scaleGroups:function(a,b){var d,c=this.chart;p(c.series,function(e){d=a||e.getPlotBox(),e.xAxis&&e.xAxis.zoomEnabled&&(e.group.attr(d),e.markerGroup&&(e.markerGroup.attr(d),e.markerGroup.clip(b?c.clipRect:null)),e.dataLabelsGroup&&e.dataLabelsGroup.attr(d))}),c.clipRect.attr(b||c.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type,b.cancelClick=!1,b.mouseDownX=this.mouseDownX=a.chartX,b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var l,b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,f=this.zoomHor,g=this.zoomVert,h=b.plotLeft,i=b.plotTop,j=b.plotWidth,k=b.plotHeight,o=this.mouseDownX,n=this.mouseDownY;h>d?d=h:d>h+j&&(d=h+j),i>e?e=i:e>i+k&&(e=i+k),this.hasDragged=Math.sqrt(Math.pow(o-d,2)+Math.pow(n-e,2)),this.hasDragged>10&&(l=b.isInsidePlot(o-h,n-i),b.hasCartesianSeries&&(this.zoomX||this.zoomY)&&l&&!this.selectionMarker&&(this.selectionMarker=b.renderer.rect(h,i,f?1:j,g?1:k,0).attr({fill:c.selectionMarkerFill||"rgba(69,114,167,0.25)",zIndex:7}).add()),this.selectionMarker&&f&&(d-=o,this.selectionMarker.attr({width:M(d),x:(d>0?0:d)+o})),this.selectionMarker&&g&&(d=e-n,this.selectionMarker.attr({height:M(d),y:(d>0?0:d)+n})),l&&!this.selectionMarker&&c.panning&&b.pan(a,c.panning))},drop:function(a){var b=this.chart,c=this.hasPinched;if(this.selectionMarker){var i,d={xAxis:[],yAxis:[],originalEvent:a.originalEvent||a},a=this.selectionMarker,e=a.attr?a.attr("x"):a.x,f=a.attr?a.attr("y"):a.y,g=a.attr?a.attr("width"):a.width,h=a.attr?a.attr("height"):a.height;(this.hasDragged||c)&&(p(b.axes,function(a){if(a.zoomEnabled){var b=a.horiz,c=a.toValue(b?e:f),b=a.toValue(b?e+g:f+h);!isNaN(c)&&!isNaN(b)&&(d[a.coll].push({axis:a,min:C(c,b),max:v(c,b)}),i=!0)}}),i&&D(b,"selection",d,function(a){b.zoom(q(a,c?{animation:!1}:null))})),this.selectionMarker=this.selectionMarker.destroy(),c&&this.scaleGroups()}b&&(G(b.container,{cursor:b._cursor}),b.cancelClick=this.hasDragged>10,b.mouseIsDown=this.hasDragged=this.hasPinched=!1,this.pinchDown=[])},onContainerMouseDown:function(a){a=this.normalize(a),a.preventDefault&&a.preventDefault(),this.dragStart(a)},onDocumentMouseUp:function(a){V[oa]&&V[oa].pointer.drop(a)},onDocumentMouseMove:function(a){var b=this.chart,c=this.chartPosition,d=b.hoverSeries,a=this.normalize(a,c);c&&d&&!this.inClass(a.target,"highcharts-tracker")&&!b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)&&this.reset()},onContainerMouseLeave:function(){var a=V[oa];a&&(a.pointer.reset(),a.pointer.chartPosition=null)},onContainerMouseMove:function(a){var b=this.chart;oa=b.index,a=this.normalize(a),"mousedown"===b.mouseIsDown&&this.drag(a),(this.inClass(a.target,"highcharts-tracker")||b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop))&&!b.openMenu&&this.runPointActions(a)},inClass:function(a,b){for(var c;a;){if(c=H(a,"class")){if(-1!==c.indexOf(b))return!0;if(-1!==c.indexOf("highcharts-container"))return!1}a=a.parentNode}},onTrackerMouseOut:function(a){var b=this.chart.hoverSeries,c=(a=a.relatedTarget||a.toElement)&&a.point&&a.point.series;!b||b.options.stickyTracking||this.inClass(a,"highcharts-tooltip")||c===b||b.onMouseOut()},onContainerClick:function(a){var b=this.chart,c=b.hoverPoint,d=b.plotLeft,e=b.plotTop,a=this.normalize(a);a.cancelBubble=!0,b.cancelClick||(c&&this.inClass(a.target,"highcharts-tracker")?(D(c.series,"click",q(a,{point:c})),b.hoverPoint&&c.firePointEvent("click",a)):(q(a,this.getCoordinates(a)),b.isInsidePlot(a.chartX-d,a.chartY-e)&&D(b,"click",a)))},setDOMEvents:function(){var a=this,b=a.chart.container;b.onmousedown=function(b){a.onContainerMouseDown(b)},b.onmousemove=function(b){a.onContainerMouseMove(b)},b.onclick=function(b){a.onContainerClick(b)},K(b,"mouseleave",a.onContainerMouseLeave),1===ab&&K(y,"mouseup",a.onDocumentMouseUp),$a&&(b.ontouchstart=function(b){a.onContainerTouchStart(b)},b.ontouchmove=function(b){a.onContainerTouchMove(b)},1===ab&&K(y,"touchend",a.onDocumentTouchEnd))},destroy:function(){var a;W(this.chart.container,"mouseleave",this.onContainerMouseLeave),ab||(W(y,"mouseup",this.onDocumentMouseUp),W(y,"touchend",this.onDocumentTouchEnd)),clearInterval(this.tooltipTimeout);for(a in this)this[a]=null}},q(R.Pointer.prototype,{pinchTranslate:function(a,b,c,d,e,f){(this.zoomHor||this.pinchHor)&&this.pinchTranslateDirection(!0,a,b,c,d,e,f),(this.zoomVert||this.pinchVert)&&this.pinchTranslateDirection(!1,a,b,c,d,e,f)},pinchTranslateDirection:function(a,b,c,d,e,f,g,h){var s,m,y,i=this.chart,j=a?"x":"y",k=a?"X":"Y",l="chart"+k,o=a?"width":"height",n=i["plot"+(a?"Left":"Top")],p=h||1,q=i.inverted,x=i.bounds[a?"h":"v"],r=1===b.length,v=b[0][l],u=c[0][l],t=!r&&b[1][l],w=!r&&c[1][l],c=function(){!r&&M(v-t)>20&&(p=h||M(u-w)/M(v-t)),m=(n-u)/p+v,s=i["plot"+(a?"Width":"Height")]/p};c(),b=m,b<x.min?(b=x.min,y=!0):b+s>x.max&&(b=x.max-s,y=!0),y?(u-=.8*(u-g[j][0]),r||(w-=.8*(w-g[j][1])),c()):g[j]=[u,w],q||(f[j]=m-n,f[o]=s),f=q?1/p:p,e[o]=s,e[j]=b,d[q?a?"scaleY":"scaleX":"scale"+k]=p,d["translate"+k]=f*n+(u-f*v)},pinch:function(a){var b=this,c=b.chart,d=b.pinchDown,e=b.followTouchMove,f=a.touches,g=f.length,h=b.lastValidTouch,i=b.hasZoom,j=b.selectionMarker,k={},l=1===g&&(b.inClass(a.target,"highcharts-tracker")&&c.runTrackerClick||c.runChartClick),o={};(i||e)&&!l&&a.preventDefault(),Ua(f,function(a){return b.normalize(a)}),"touchstart"===a.type?(p(f,function(a,b){d[b]={chartX:a.chartX,chartY:a.chartY}}),h.x=[d[0].chartX,d[1]&&d[1].chartX],h.y=[d[0].chartY,d[1]&&d[1].chartY],p(c.axes,function(a){if(a.zoomEnabled){var b=c.bounds[a.horiz?"h":"v"],d=a.minPixelPadding,e=a.toPixels(a.dataMin),f=a.toPixels(a.dataMax),g=C(e,f),e=v(e,f);b.min=C(a.pos,g-d),b.max=v(a.pos+a.len,e+d)}})):d.length&&(j||(b.selectionMarker=j=q({destroy:sa},c.plotBox)),b.pinchTranslate(d,f,k,j,o,h),b.hasPinched=i,b.scaleGroups(k,o),!i&&e&&1===g&&this.runPointActions(b.normalize(a)))},onContainerTouchStart:function(a){var b=this.chart;oa=b.index,1===a.touches.length?(a=this.normalize(a),b.isInsidePlot(a.chartX-b.plotLeft,a.chartY-b.plotTop)?(this.runPointActions(a),this.pinch(a)):this.reset()):2===a.touches.length&&this.pinch(a)},onContainerTouchMove:function(a){(1===a.touches.length||2===a.touches.length)&&this.pinch(a)},onDocumentTouchEnd:function(a){V[oa]&&V[oa].pointer.drop(a)}}),I.PointerEvent||I.MSPointerEvent){var ua={},zb=!!I.PointerEvent,Wb=function(){var a,b=[];b.item=function(a){return this[a]};for(a in ua)ua.hasOwnProperty(a)&&b.push({pageX:ua[a].pageX,pageY:ua[a].pageY,target:ua[a].target});return b},Ab=function(a,b,c,d){a=a.originalEvent||a,"touch"!==a.pointerType&&a.pointerType!==a.MSPOINTER_TYPE_TOUCH||!V[oa]||(d(a),d=V[oa].pointer,d[b]({type:c,target:a.currentTarget,preventDefault:sa,touches:Wb()}))};q(Wa.prototype,{onContainerPointerDown:function(a){Ab(a,"onContainerTouchStart","touchstart",function(a){ua[a.pointerId]={pageX:a.pageX,pageY:a.pageY,target:a.currentTarget}})},onContainerPointerMove:function(a){Ab(a,"onContainerTouchMove","touchmove",function(a){ua[a.pointerId]={pageX:a.pageX,pageY:a.pageY},ua[a.pointerId].target||(ua[a.pointerId].target=a.currentTarget)})},onDocumentPointerUp:function(a){Ab(a,"onContainerTouchEnd","touchend",function(a){delete ua[a.pointerId]})},batchMSEvents:function(a){a(this.chart.container,zb?"pointerdown":"MSPointerDown",this.onContainerPointerDown),a(this.chart.container,zb?"pointermove":"MSPointerMove",this.onContainerPointerMove),a(y,zb?"pointerup":"MSPointerUp",this.onDocumentPointerUp)}}),Ma(Wa.prototype,"init",function(a,b,c){a.call(this,b,c),(this.hasZoom||this.followTouchMove)&&G(b.container,{"-ms-touch-action":Q,"touch-action":Q})}),Ma(Wa.prototype,"setDOMEvents",function(a){a.apply(this),(this.hasZoom||this.followTouchMove)&&this.batchMSEvents(K)}),Ma(Wa.prototype,"destroy",function(a){this.batchMSEvents(W),a.call(this)})}var lb=R.Legend=function(a,b){this.init(a,b)};lb.prototype={init:function(a,b){var c=this,d=b.itemStyle,e=m(b.padding,8),f=b.itemMarginTop||0;this.options=b,b.enabled&&(c.baseline=z(d.fontSize)+3+f,c.itemStyle=d,c.itemHiddenStyle=w(d,b.itemHiddenStyle),c.itemMarginTop=f,c.padding=e,c.initialItemX=e,c.initialItemY=e-5,c.maxItemWidth=0,c.chart=a,c.itemHeight=0,c.lastLineHeight=0,c.symbolWidth=m(b.symbolWidth,16),c.pages=[],c.render(),K(c.chart,"endResize",function(){c.positionCheckboxes()}))},colorizeItem:function(a,b){var j,c=this.options,d=a.legendItem,e=a.legendLine,f=a.legendSymbol,g=this.itemHiddenStyle.color,c=b?c.itemStyle.color:g,h=b?a.legendColor||a.color||"#CCC":g,g=a.options&&a.options.marker,i={fill:h};if(d&&d.css({fill:c,color:c}),e&&e.attr({stroke:h}),f){if(g&&f.isMarker)for(j in i.stroke=h,g=a.convertAttribs(g))d=g[j],d!==t&&(i[j]=d);f.attr(i)}},positionItem:function(a){var b=this.options,c=b.symbolPadding,b=!b.rtl,d=a._legendItemPos,e=d[0],d=d[1],f=a.checkbox;a.legendGroup&&a.legendGroup.translate(b?e:this.legendWidth-e-2*c-4,d),f&&(f.x=e,f.y=d)},destroyItem:function(a){var b=a.checkbox;p(["legendItem","legendLine","legendSymbol","legendGroup"],function(b){a[b]&&(a[b]=a[b].destroy())}),b&&Pa(a.checkbox)},destroy:function(){var a=this.group,b=this.box;b&&(this.box=b.destroy()),a&&(this.group=a.destroy())},positionCheckboxes:function(a){var c,b=this.group.alignAttr,d=this.clipHeight||this.legendHeight;b&&(c=b.translateY,p(this.allItems,function(e){var g,f=e.checkbox;f&&(g=c+f.y+(a||0)+3,G(f,{left:b.translateX+e.checkboxOffset+f.x-20+"px",top:g+"px",display:g>c-6&&c+d-6>g?"":Q}))}))},renderTitle:function(){var a=this.padding,b=this.options.title,c=0;b.text&&(this.title||(this.title=this.chart.renderer.label(b.text,a-3,a-4,null,null,null,null,null,"legend-title").attr({zIndex:1}).css(b.style).add(this.group)),a=this.title.getBBox(),c=a.height,this.offsetWidth=a.width,this.contentGroup.attr({translateY:c})),this.titleHeight=c},renderItem:function(a){var b=this.chart,c=b.renderer,d=this.options,e="horizontal"===d.layout,f=this.symbolWidth,g=d.symbolPadding,h=this.itemStyle,i=this.itemHiddenStyle,j=this.padding,k=e?m(d.itemDistance,20):0,l=!d.rtl,o=d.width,n=d.itemMarginBottom||0,s=this.itemMarginTop,p=this.initialItemX,q=a.legendItem,r=a.series&&a.series.drawLegendSymbol?a.series:a,x=r.options,x=this.createCheckboxForItem&&x&&x.showCheckbox,t=d.useHTML;q||(a.legendGroup=c.g("legend-item").attr({zIndex:1}).add(this.scrollGroup),r.drawLegendSymbol(this,a),a.legendItem=q=c.text(d.labelFormat?Ia(d.labelFormat,a):d.labelFormatter.call(a),l?f+g:-g,this.baseline,t).css(w(a.visible?h:i)).attr({align:l?"left":"right",zIndex:2}).add(a.legendGroup),this.setItemEvents&&this.setItemEvents(a,q,t,h,i),this.colorizeItem(a,a.visible),x&&this.createCheckboxForItem(a)),c=q.getBBox(),f=a.checkboxOffset=d.itemWidth||a.legendItemWidth||f+g+c.width+k+(x?20:0),this.itemHeight=g=u(a.legendItemHeight||c.height),e&&this.itemX-p+f>(o||b.chartWidth-2*j-p-d.x)&&(this.itemX=p,this.itemY+=s+this.lastLineHeight+n,this.lastLineHeight=0),this.maxItemWidth=v(this.maxItemWidth,f),this.lastItemY=s+this.itemY+n,this.lastLineHeight=v(g,this.lastLineHeight),a._legendItemPos=[this.itemX,this.itemY],e?this.itemX+=f:(this.itemY+=s+g+n,this.lastLineHeight=g),this.offsetWidth=o||v((e?this.itemX-p-k:f)+j,this.offsetWidth)},getAllItems:function(){var a=[];return p(this.chart.series,function(b){var c=b.options;m(c.showInLegend,r(c.linkedTo)?!1:t,!0)&&(a=a.concat(b.legendItems||("point"===c.legendType?b.data:b)))}),a},render:function(){var e,f,g,h,a=this,b=a.chart,c=b.renderer,d=a.group,i=a.box,j=a.options,k=a.padding,l=j.borderWidth,o=j.backgroundColor;a.itemX=a.initialItemX,a.itemY=a.initialItemY,a.offsetWidth=0,a.lastItemY=0,d||(a.group=d=c.g("legend").attr({zIndex:7}).add(),a.contentGroup=c.g().attr({zIndex:1}).add(d),a.scrollGroup=c.g().add(a.contentGroup)),a.renderTitle(),e=a.getAllItems(),ob(e,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)}),j.reversed&&e.reverse(),a.allItems=e,a.display=f=!!e.length,p(e,function(b){a.renderItem(b)}),g=j.width||a.offsetWidth,h=a.lastItemY+a.lastLineHeight+a.titleHeight,h=a.handleOverflow(h),(l||o)&&(g+=k,h+=k,i?g>0&&h>0&&(i[i.isNew?"attr":"animate"](i.crisp({width:g,height:h})),i.isNew=!1):(a.box=i=c.rect(0,0,g,h,j.borderRadius,l||0).attr({stroke:j.borderColor,"stroke-width":l||0,fill:o||Q}).add(d).shadow(j.shadow),i.isNew=!0),i[f?"show":"hide"]()),a.legendWidth=g,a.legendHeight=h,p(e,function(b){a.positionItem(b)}),f&&d.align(q({width:g,height:h},j),!0,"spacingBox"),b.isResizing||this.positionCheckboxes()},handleOverflow:function(a){var h,s,b=this,c=this.chart,d=c.renderer,e=this.options,f=e.y,f=c.spacingBox.height+("top"===e.verticalAlign?-f:f)-this.padding,g=e.maxHeight,i=this.clipRect,j=e.navigation,k=m(j.animation,!0),l=j.arrowSize||12,o=this.nav,n=this.pages,q=this.allItems;return"horizontal"===e.layout&&(f/=2),g&&(f=C(f,g)),n.length=0,a>f&&!e.useHTML?(this.clipHeight=h=f-20-this.titleHeight-this.padding,this.currentPage=m(this.currentPage,1),this.fullHeight=a,p(q,function(a,b){var c=a._legendItemPos[1],d=u(a.legendItem.getBBox().height),e=n.length;(!e||c-n[e-1]>h&&(s||c)!==n[e-1])&&(n.push(s||c),e++),b===q.length-1&&c+d-n[e-1]>h&&n.push(c),c!==s&&(s=c)}),i||(i=b.clipRect=d.clipRect(0,this.padding,9999,0),b.contentGroup.clip(i)),i.attr({height:h}),o||(this.nav=o=d.g().attr({zIndex:1}).add(this.group),this.up=d.symbol("triangle",0,0,l,l).on("click",function(){b.scroll(-1,k)}).add(o),this.pager=d.text("",15,10).css(j.style).add(o),this.down=d.symbol("triangle-down",0,0,l,l).on("click",function(){b.scroll(1,k)}).add(o)),b.scroll(0),a=f):o&&(i.attr({height:c.chartHeight}),o.hide(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0),a},scroll:function(a,b){var c=this.pages,d=c.length,e=this.currentPage+a,f=this.clipHeight,g=this.options.navigation,h=g.activeColor,g=g.inactiveColor,i=this.pager,j=this.padding;e>d&&(e=d),e>0&&(b!==t&&Qa(b,this.chart),this.nav.attr({translateX:j,translateY:f+this.padding+7+this.titleHeight,visibility:"visible"}),this.up.attr({fill:1===e?g:h}).css({cursor:1===e?"default":"pointer"}),i.attr({text:e+"/"+d}),this.down.attr({x:18+this.pager.getBBox().width,fill:e===d?g:h}).css({cursor:e===d?"default":"pointer"}),c=-c[e-1]+this.initialItemY,this.scrollGroup.animate({translateY:c}),this.currentPage=e,this.positionCheckboxes(c))}},N=R.LegendSymbolMixin={drawRectangle:function(a,b){var c=a.options.symbolHeight||12;b.legendSymbol=this.chart.renderer.rect(0,a.baseline-5-c/2,a.symbolWidth,c,a.options.symbolRadius||0).attr({zIndex:3}).add(b.legendGroup)},drawLineMarker:function(a){var d,b=this.options,c=b.marker;d=a.symbolWidth;var g,e=this.chart.renderer,f=this.legendGroup,a=a.baseline-u(.3*e.fontMetrics(a.options.itemStyle.fontSize).b);b.lineWidth&&(g={"stroke-width":b.lineWidth},b.dashStyle&&(g.dashstyle=b.dashStyle),this.legendLine=e.path(["M",0,a,"L",d,a]).attr(g).add(f)),c&&c.enabled!==!1&&(b=c.radius,this.legendSymbol=d=e.symbol(this.symbol,d/2-b,a-b,2*b,2*b).add(f),d.isMarker=!0)}},(/Trident\/7\.0/.test(wa)||Ta)&&Ma(lb.prototype,"positionItem",function(a,b){var c=this,d=function(){b._legendItemPos&&a.call(c,b)};d(),setTimeout(d)}),Ya.prototype={init:function(a,b){var c,d=a.series;a.series=null,c=w(E,a),c.series=a.series=d,this.userOptions=a,d=c.chart,this.margin=this.splashArray("margin",d),this.spacing=this.splashArray("spacing",d);var e=d.events;this.bounds={h:{},v:{}},this.callback=b,this.isResizing=0,this.options=c,this.axes=[],this.series=[],this.hasCartesianSeries=d.showAxes;var g,f=this;if(f.index=V.length,V.push(f),ab++,d.reflow!==!1&&K(f,"load",function(){f.initReflow()}),e)for(g in e)K(f,g,e[g]);f.xAxis=[],f.yAxis=[],f.animation=fa?!1:m(d.animation,!0),f.pointCount=0,f.counters=new Bb,f.firstRender()},initSeries:function(a){var b=this.options.chart;return(b=F[a.type||b.type||b.defaultSeriesType])||ra(17,!0),b=new b,b.init(this,a),b},isInsidePlot:function(a,b,c){var d=c?b:a,a=c?a:b;return d>=0&&d<=this.plotWidth&&a>=0&&a<=this.plotHeight},adjustTickAmounts:function(){this.options.chart.alignTicks!==!1&&p(this.axes,function(a){a.adjustTickAmount()}),this.maxTicks=null},redraw:function(a){var g,h,b=this.axes,c=this.series,d=this.pointer,e=this.legend,f=this.isDirtyLegend,i=this.isDirtyBox,j=c.length,k=j,l=this.renderer,o=l.isHidden(),n=[];for(Qa(a,this),o&&this.cloneRenderTo(),this.layOutTitles();k--;)if(a=c[k],a.options.stacking&&(g=!0,a.isDirty)){h=!0;break}if(h)for(k=j;k--;)a=c[k],a.options.stacking&&(a.isDirty=!0);p(c,function(a){a.isDirty&&"point"===a.options.legendType&&(f=!0)}),f&&e.options.enabled&&(e.render(),this.isDirtyLegend=!1),g&&this.getStacks(),this.hasCartesianSeries&&(this.isResizing||(this.maxTicks=null,p(b,function(a){a.setScale()})),this.adjustTickAmounts(),this.getMargins(),p(b,function(a){a.isDirty&&(i=!0)}),p(b,function(a){a.isDirtyExtremes&&(a.isDirtyExtremes=!1,n.push(function(){D(a,"afterSetExtremes",q(a.eventArgs,a.getExtremes())),delete a.eventArgs})),(i||g)&&a.redraw()})),i&&this.drawChartBox(),p(c,function(a){a.isDirty&&a.visible&&(!a.isCartesian||a.xAxis)&&a.redraw()}),d&&d.reset(!0),l.draw(),D(this,"redraw"),o&&this.cloneRenderTo(!0),p(n,function(a){a.call()})},get:function(a){var d,e,b=this.axes,c=this.series;for(d=0;d<b.length;d++)if(b[d].options.id===a)return b[d];for(d=0;d<c.length;d++)if(c[d].options.id===a)return c[d];for(d=0;d<c.length;d++)for(e=c[d].points||[],b=0;b<e.length;b++)if(e[b].id===a)return e[b];return null},getAxes:function(){var a=this,b=this.options,c=b.xAxis=qa(b.xAxis||{}),b=b.yAxis=qa(b.yAxis||{});p(c,function(a,b){a.index=b,a.isX=!0}),p(b,function(a,b){a.index=b}),c=c.concat(b),p(c,function(b){new la(a,b)}),a.adjustTickAmounts()},getSelectedPoints:function(){var a=[];return p(this.series,function(b){a=a.concat(vb(b.points||[],function(a){return a.selected}))
4
+ }),a},getSelectedSeries:function(){return vb(this.series,function(a){return a.selected})},getStacks:function(){var a=this;p(a.yAxis,function(a){a.stacks&&a.hasVisibleSeries&&(a.oldStacks=a.stacks)}),p(a.series,function(b){!b.options.stacking||b.visible!==!0&&a.options.chart.ignoreHiddenSeries!==!1||(b.stackKey=b.type+m(b.options.stack,""))})},setTitle:function(a,b,c){var g,f,d=this,e=d.options;f=e.title=w(e.title,a),g=e.subtitle=w(e.subtitle,b),e=g,p([["title",a,f],["subtitle",b,e]],function(a){var b=a[0],c=d[b],e=a[1],a=a[2];c&&e&&(d[b]=c=c.destroy()),a&&a.text&&!c&&(d[b]=d.renderer.text(a.text,0,0,a.useHTML).attr({align:a.align,"class":"highcharts-"+b,zIndex:a.zIndex||4}).css(a.style).add())}),d.layOutTitles(c)},layOutTitles:function(a){var b=0,c=this.title,d=this.subtitle,e=this.options,f=e.title,e=e.subtitle,g=this.spacingBox.width-44;!c||(c.css({width:(f.width||g)+"px"}).align(q({y:15},f),!1,"spacingBox"),f.floating||f.verticalAlign)||(b=c.getBBox().height),d&&(d.css({width:(e.width||g)+"px"}).align(q({y:b+f.margin},e),!1,"spacingBox"),!e.floating&&!e.verticalAlign&&(b=Ka(b+d.getBBox().height))),c=this.titleOffset!==b,this.titleOffset=b,!this.isDirtyBox&&c&&(this.isDirtyBox=c,this.hasRendered&&m(a,!0)&&this.isDirtyBox&&this.redraw())},getChartSize:function(){var a=this.options.chart,b=a.width,a=a.height,c=this.renderToClone||this.renderTo;r(b)||(this.containerWidth=jb(c,"width")),r(a)||(this.containerHeight=jb(c,"height")),this.chartWidth=v(0,b||this.containerWidth||600),this.chartHeight=v(0,m(a,this.containerHeight>19?this.containerHeight:400))},cloneRenderTo:function(a){var b=this.renderToClone,c=this.container;a?b&&(this.renderTo.appendChild(c),Pa(b),delete this.renderToClone):(c&&c.parentNode===this.renderTo&&this.renderTo.removeChild(c),this.renderToClone=b=this.renderTo.cloneNode(0),G(b,{position:"absolute",top:"-9999px",display:"block"}),b.style.setProperty&&b.style.setProperty("display","block","important"),y.body.appendChild(b),c&&b.appendChild(c))},getContainer:function(){var a,c,d,e,b=this.options.chart;this.renderTo=a=b.renderTo,e="highcharts-"+tb++,Fa(a)&&(this.renderTo=a=y.getElementById(a)),a||ra(13,!0),c=z(H(a,"data-highcharts-chart")),!isNaN(c)&&V[c]&&V[c].hasRendered&&V[c].destroy(),H(a,"data-highcharts-chart",this.index),a.innerHTML="",!b.skipClone&&!a.offsetWidth&&this.cloneRenderTo(),this.getChartSize(),c=this.chartWidth,d=this.chartHeight,this.container=a=Y(Ja,{className:"highcharts-container"+(b.className?" "+b.className:""),id:e},q({position:"relative",overflow:"hidden",width:c+"px",height:d+"px",textAlign:"left",lineHeight:"normal",zIndex:0,"-webkit-tap-highlight-color":"rgba(0,0,0,0)"},b.style),this.renderToClone||a),this._cursor=a.style.cursor,this.renderer=b.forExport?new ta(a,c,d,b.style,!0):new Za(a,c,d,b.style),fa&&this.renderer.create(this,a,c,d)},getMargins:function(){var b,a=this.spacing,c=this.legend,d=this.margin,e=this.options.legend,f=m(e.margin,20),g=e.x,h=e.y,i=e.align,j=e.verticalAlign,k=this.titleOffset;this.resetMargins(),b=this.axisOffset,k&&!r(d[0])&&(this.plotTop=v(this.plotTop,k+this.options.title.margin+a[0])),c.display&&!e.floating&&("right"===i?r(d[1])||(this.marginRight=v(this.marginRight,c.legendWidth-g+f+a[1])):"left"===i?r(d[3])||(this.plotLeft=v(this.plotLeft,c.legendWidth+g+f+a[3])):"top"===j?r(d[0])||(this.plotTop=v(this.plotTop,c.legendHeight+h+f+a[0])):"bottom"!==j||r(d[2])||(this.marginBottom=v(this.marginBottom,c.legendHeight-h+f+a[2]))),this.extraBottomMargin&&(this.marginBottom+=this.extraBottomMargin),this.extraTopMargin&&(this.plotTop+=this.extraTopMargin),this.hasCartesianSeries&&p(this.axes,function(a){a.getOffset()}),r(d[3])||(this.plotLeft+=b[3]),r(d[0])||(this.plotTop+=b[0]),r(d[2])||(this.marginBottom+=b[2]),r(d[1])||(this.marginRight+=b[1]),this.setChartSize()},reflow:function(a){var b=this,c=b.options.chart,d=b.renderTo,e=c.width||jb(d,"width"),f=c.height||jb(d,"height"),c=a?a.target:I,d=function(){b.container&&(b.setSize(e,f,!1),b.hasUserSize=null)};b.hasUserSize||!e||!f||c!==I&&c!==y||((e!==b.containerWidth||f!==b.containerHeight)&&(clearTimeout(b.reflowTimeout),a?b.reflowTimeout=setTimeout(d,100):d()),b.containerWidth=e,b.containerHeight=f)},initReflow:function(){var a=this,b=function(b){a.reflow(b)};K(I,"resize",b),K(a,"destroy",function(){W(I,"resize",b)})},setSize:function(a,b,c){var e,f,g,d=this;d.isResizing+=1,g=function(){d&&D(d,"endResize",null,function(){d.isResizing-=1})},Qa(c,d),d.oldChartHeight=d.chartHeight,d.oldChartWidth=d.chartWidth,r(a)&&(d.chartWidth=e=v(0,u(a)),d.hasUserSize=!!e),r(b)&&(d.chartHeight=f=v(0,u(b))),(va?kb:G)(d.container,{width:e+"px",height:f+"px"},va),d.setChartSize(!0),d.renderer.setSize(e,f,c),d.maxTicks=null,p(d.axes,function(a){a.isDirty=!0,a.setScale()}),p(d.series,function(a){a.isDirty=!0}),d.isDirtyLegend=!0,d.isDirtyBox=!0,d.layOutTitles(),d.getMargins(),d.redraw(c),d.oldChartHeight=null,D(d,"resize"),va===!1?g():setTimeout(g,va&&va.duration||500)},setChartSize:function(a){var i,j,k,l,b=this.inverted,c=this.renderer,d=this.chartWidth,e=this.chartHeight,f=this.options.chart,g=this.spacing,h=this.clipOffset;this.plotLeft=i=u(this.plotLeft),this.plotTop=j=u(this.plotTop),this.plotWidth=k=v(0,u(d-i-this.marginRight)),this.plotHeight=l=v(0,u(e-j-this.marginBottom)),this.plotSizeX=b?l:k,this.plotSizeY=b?k:l,this.plotBorderWidth=f.plotBorderWidth||0,this.spacingBox=c.spacingBox={x:g[3],y:g[0],width:d-g[3]-g[1],height:e-g[0]-g[2]},this.plotBox=c.plotBox={x:i,y:j,width:k,height:l},d=2*T(this.plotBorderWidth/2),b=Ka(v(d,h[3])/2),c=Ka(v(d,h[0])/2),this.clipBox={x:b,y:c,width:T(this.plotSizeX-v(d,h[1])/2-b),height:T(this.plotSizeY-v(d,h[2])/2-c)},a||p(this.axes,function(a){a.setAxisSize(),a.setAxisTranslation()})},resetMargins:function(){var a=this.spacing,b=this.margin;this.plotTop=m(b[0],a[0]),this.marginRight=m(b[1],a[1]),this.marginBottom=m(b[2],a[2]),this.plotLeft=m(b[3],a[3]),this.axisOffset=[0,0,0,0],this.clipOffset=[0,0,0,0]},drawChartBox:function(){var n,a=this.options.chart,b=this.renderer,c=this.chartWidth,d=this.chartHeight,e=this.chartBackground,f=this.plotBackground,g=this.plotBorder,h=this.plotBGImage,i=a.borderWidth||0,j=a.backgroundColor,k=a.plotBackgroundColor,l=a.plotBackgroundImage,o=a.plotBorderWidth||0,s=this.plotLeft,m=this.plotTop,p=this.plotWidth,q=this.plotHeight,r=this.plotBox,v=this.clipRect,u=this.clipBox;n=i+(a.shadow?8:0),(i||j)&&(e?e.animate(e.crisp({width:c-n,height:d-n})):(e={fill:j||Q},i&&(e.stroke=a.borderColor,e["stroke-width"]=i),this.chartBackground=b.rect(n/2,n/2,c-n,d-n,a.borderRadius,i).attr(e).addClass("highcharts-background").add().shadow(a.shadow))),k&&(f?f.animate(r):this.plotBackground=b.rect(s,m,p,q,0).attr({fill:k}).add().shadow(a.plotShadow)),l&&(h?h.animate(r):this.plotBGImage=b.image(l,s,m,p,q).add()),v?v.animate({width:u.width,height:u.height}):this.clipRect=b.clipRect(u),o&&(g?g.animate(g.crisp({x:s,y:m,width:p,height:q})):this.plotBorder=b.rect(s,m,p,q,0,-o).attr({stroke:a.plotBorderColor,"stroke-width":o,fill:Q,zIndex:1}).add()),this.isDirtyBox=!1},propFromSeries:function(){var c,e,f,a=this,b=a.options.chart,d=a.options.series;p(["inverted","angular","polar"],function(g){for(c=F[b.type||b.defaultSeriesType],f=a[g]||b[g]||c&&c.prototype[g],e=d&&d.length;!f&&e--;)(c=F[d[e].type])&&c.prototype[g]&&(f=!0);a[g]=f})},linkSeries:function(){var a=this,b=a.series;p(b,function(a){a.linkedSeries.length=0}),p(b,function(b){var d=b.options.linkedTo;Fa(d)&&(d=":previous"===d?a.series[b.index-1]:a.get(d))&&(d.linkedSeries.push(b),b.linkedParent=d)})},renderSeries:function(){p(this.series,function(a){a.translate(),a.setTooltipPoints&&a.setTooltipPoints(),a.render()})},render:function(){var g,a=this,b=a.axes,c=a.renderer,d=a.options,e=d.labels,f=d.credits;a.setTitle(),a.legend=new lb(a,d.legend),a.getStacks(),p(b,function(a){a.setScale()}),a.getMargins(),a.maxTicks=null,p(b,function(a){a.setTickPositions(!0),a.setMaxTicks()}),a.adjustTickAmounts(),a.getMargins(),a.drawChartBox(),a.hasCartesianSeries&&p(b,function(a){a.render()}),a.seriesGroup||(a.seriesGroup=c.g("series-group").attr({zIndex:3}).add()),a.renderSeries(),e.items&&p(e.items,function(b){var d=q(e.style,b.style),f=z(d.left)+a.plotLeft,g=z(d.top)+a.plotTop+12;delete d.left,delete d.top,c.text(b.html,f,g).attr({zIndex:2}).css(d).add()}),f.enabled&&!a.credits&&(g=f.href,a.credits=c.text(f.text,0,0).on("click",function(){g&&(location.href=g)}).attr({align:f.position.align,zIndex:8}).css(f.style).add().align(f.position)),a.hasRendered=!0},destroy:function(){var e,a=this,b=a.axes,c=a.series,d=a.container,f=d&&d.parentNode;for(D(a,"destroy"),V[a.index]=t,ab--,a.renderTo.removeAttribute("data-highcharts-chart"),W(a),e=b.length;e--;)b[e]=b[e].destroy();for(e=c.length;e--;)c[e]=c[e].destroy();p("title,subtitle,chartBackground,plotBackground,plotBGImage,plotBorder,seriesGroup,clipRect,credits,pointer,scroller,rangeSelector,legend,resetZoomButton,tooltip,renderer".split(","),function(b){var c=a[b];c&&c.destroy&&(a[b]=c.destroy())}),d&&(d.innerHTML="",W(d),f&&Pa(d));for(e in a)delete a[e]},isReadyToRender:function(){var a=this;return!aa&&I==I.top&&"complete"!==y.readyState||fa&&!I.canvg?(fa?Lb.push(function(){a.firstRender()},a.options.global.canvasToolsURL):y.attachEvent("onreadystatechange",function(){y.detachEvent("onreadystatechange",a.firstRender),"complete"===y.readyState&&a.firstRender()}),!1):!0},firstRender:function(){var a=this,b=a.options,c=a.callback;a.isReadyToRender()&&(a.getContainer(),D(a,"init"),a.resetMargins(),a.setChartSize(),a.propFromSeries(),a.getAxes(),p(b.series||[],function(b){a.initSeries(b)}),a.linkSeries(),D(a,"beforeRender"),R.Pointer&&(a.pointer=new Wa(a,b)),a.render(),a.renderer.draw(),c&&c.apply(a,[a]),p(a.callbacks,function(b){b.apply(a,[a])}),a.cloneRenderTo(!0),D(a,"load"))},splashArray:function(a,b){var c=b[a],c=ca(c)?c:[c,c,c,c];return[m(b[a+"Top"],c[0]),m(b[a+"Right"],c[1]),m(b[a+"Bottom"],c[2]),m(b[a+"Left"],c[3])]}},Ya.prototype.callbacks=[],X=R.CenteredSeriesMixin={getCenter:function(){var d,h,a=this.options,b=this.chart,c=2*(a.slicedOffset||0),e=b.plotWidth-2*c,f=b.plotHeight-2*c,b=a.center,a=[m(b[0],"50%"),m(b[1],"50%"),a.size||"100%",a.innerSize||0],g=C(e,f);return Ua(a,function(a,b){return h=/%$/.test(a),d=2>b||2===b&&h,(h?[e,f,g,g][b]*z(a)/100:a)+(d?c:0)})}};var Ea=function(){};Ea.prototype={init:function(a,b,c){return this.series=a,this.applyOptions(b,c),this.pointAttr={},a.options.colorByPoint&&(b=a.options.colors||a.chart.options.colors,this.color=this.color||b[a.colorCounter++],a.colorCounter===b.length)&&(a.colorCounter=0),a.chart.pointCount++,this},applyOptions:function(a,b){var c=this.series,d=c.pointValKey,a=Ea.prototype.optionsToObject.call(this,a);return q(this,a),this.options=this.options?q(this.options,a):a,d&&(this.y=this[d]),this.x===t&&c&&(this.x=b===t?c.autoIncrement():b),this},optionsToObject:function(a){var b={},c=this.series,d=c.pointArrayMap||["y"],e=d.length,f=0,g=0;if("number"==typeof a||null===a)b[d[0]]=a;else if(La(a))for(a.length>e&&(c=typeof a[0],"string"===c?b.name=a[0]:"number"===c&&(b.x=a[0]),f++);e>g;)b[d[g++]]=a[f++];else"object"==typeof a&&(b=a,a.dataLabels&&(c._hasPointLabels=!0),a.marker&&(c._hasPointMarkers=!0));return b},destroy:function(){var c,a=this.series.chart,b=a.hoverPoints;a.pointCount--,b&&(this.setState(),ja(b,this),!b.length)&&(a.hoverPoints=null),this===a.hoverPoint&&this.onMouseOut(),(this.graphic||this.dataLabel)&&(W(this),this.destroyElements()),this.legendItem&&a.legend.destroyItem(this);for(c in this)this[c]=null},destroyElements:function(){for(var b,a="graphic,dataLabel,dataLabelUpper,group,connector,shadowGroup".split(","),c=6;c--;)b=a[c],this[b]&&(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}},tooltipFormatter:function(a){var b=this.series,c=b.tooltipOptions,d=m(c.valueDecimals,""),e=c.valuePrefix||"",f=c.valueSuffix||"";return p(b.pointArrayMap||["y"],function(b){b="{point."+b,(e||f)&&(a=a.replace(b+"}",e+b+"}"+f)),a=a.replace(b+"}",b+":,."+d+"f}")}),Ia(a,{point:this,series:this.series})},firePointEvent:function(a,b,c){var d=this,e=this.series.options;(e.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents(),"click"===a&&e.allowPointSelect&&(c=function(a){d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)}),D(this,a,b,c)}};var O=function(){};O.prototype={isCartesian:!0,type:"line",pointClass:Ea,sorted:!0,requireSorting:!0,pointAttrToOptions:{stroke:"lineColor","stroke-width":"lineWidth",fill:"fillColor",r:"radius"},axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],init:function(a,b){var d,e,c=this,f=a.series,g=function(a,b){return m(a.options.index,a._i)-m(b.options.index,b._i)};c.chart=a,c.options=b=c.setOptions(b),c.linkedSeries=[],c.bindAxes(),q(c,{name:b.name,state:"",pointAttr:{},visible:b.visible!==!1,selected:b.selected===!0}),fa&&(b.animation=!1),e=b.events;for(d in e)K(c,d,e[d]);(e&&e.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)&&(a.runTrackerClick=!0),c.getColor(),c.getSymbol(),p(c.parallelArrays,function(a){c[a+"Data"]=[]}),c.setData(b.data,!1),c.isCartesian&&(a.hasCartesianSeries=!0),f.push(c),c._i=f.length-1,ob(f,g),this.yAxis&&ob(this.yAxis.series,g),p(f,function(a,b){a.index=b,a.name=a.name||"Series "+(b+1)})},bindAxes:function(){var d,a=this,b=a.options,c=a.chart;p(a.axisTypes||[],function(e){p(c[e],function(c){d=c.options,(b[e]===d.index||b[e]!==t&&b[e]===d.id||b[e]===t&&0===d.index)&&(c.series.push(a),a[e]=c,c.isDirty=!0)}),!a[e]&&a.optionalAxis!==e&&ra(18,!0)})},updateParallelArrays:function(a,b){var c=a.series,d=arguments;p(c.parallelArrays,"number"==typeof b?function(d){var f="y"===d&&c.toYData?c.toYData(a):a[d];c[d+"Data"][b]=f}:function(a){Array.prototype[b].apply(c[a+"Data"],Array.prototype.slice.call(d,2))})},autoIncrement:function(){var a=this.options,b=this.xIncrement,b=m(b,a.pointStart,0);return this.pointInterval=m(this.pointInterval,a.pointInterval,1),this.xIncrement=b+this.pointInterval,b},getSegments:function(){var c,a=-1,b=[],d=this.points,e=d.length;if(e)if(this.options.connectNulls){for(c=e;c--;)null===d[c].y&&d.splice(c,1);d.length&&(b=[d])}else p(d,function(c,g){null===c.y?(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,c=b.options.plotOptions,b=b.userOptions||{},d=b.plotOptions||{},e=c[this.type];return this.userOptions=a,c=w(e,c.series,a),this.tooltipOptions=w(E.tooltip,E.plotOptions[this.type].tooltip,b.tooltip,d.series&&d.series.tooltip,d[this.type]&&d[this.type].tooltip,a.tooltip),null===e.marker&&delete c.marker,c},getColor:function(){var e,a=this.options,b=this.userOptions,c=this.chart.options.colors,d=this.chart.counters;e=a.color||ba[this.type].color,e||a.colorByPoint||(r(b._colorIndex)?a=b._colorIndex:(b._colorIndex=d.color,a=d.color++),e=c[a]),this.color=e,d.wrapColor(c.length)},getSymbol:function(){var a=this.userOptions,b=this.options.marker,c=this.chart,d=c.options.symbols,c=c.counters;this.symbol=b.symbol,this.symbol||(r(a._symbolIndex)?a=a._symbolIndex:(a._symbolIndex=c.symbol,a=c.symbol++),this.symbol=d[a]),/^url/.test(this.symbol)&&(b.radius=0),c.wrapSymbol(d.length)},drawLegendSymbol:N.drawLineMarker,setData:function(a,b,c,d){var h,e=this,f=e.points,g=f&&f.length||0,i=e.options,j=e.chart,k=null,l=e.xAxis,o=l&&!!l.categories,n=e.tooltipPoints,s=i.turboThreshold,q=this.xData,r=this.yData,v=(h=e.pointArrayMap)&&h.length,a=a||[];if(h=a.length,b=m(b,!0),d===!1||!h||g!==h||e.cropped||e.hasGroupedData){if(e.xIncrement=null,e.pointRange=o?1:i.pointRange,e.colorCounter=0,p(this.parallelArrays,function(a){e[a+"Data"].length=0}),s&&h>s){for(c=0;null===k&&h>c;)k=a[c],c++;if(ha(k)){for(o=m(i.pointStart,0),i=m(i.pointInterval,1),c=0;h>c;c++)q[c]=o,r[c]=a[c],o+=i;e.xIncrement=o}else if(La(k))if(v)for(c=0;h>c;c++)i=a[c],q[c]=i[0],r[c]=i.slice(1,v+1);else for(c=0;h>c;c++)i=a[c],q[c]=i[0],r[c]=i[1];else ra(12)}else for(c=0;h>c;c++)a[c]!==t&&(i={series:e},e.pointClass.prototype.applyOptions.apply(i,[a[c]]),e.updateParallelArrays(i,c),o&&i.name)&&(l.names[i.x]=i.name);for(Fa(r[0])&&ra(14,!0),e.data=[],e.options.data=a,c=g;c--;)f[c]&&f[c].destroy&&f[c].destroy();n&&(n.length=0),l&&(l.minRange=l.userMinRange),e.isDirty=e.isDirtyData=j.isDirtyBox=!0,c=!1}else p(a,function(a,b){f[b].update(a,!1)});b&&j.redraw(c)},processData:function(a){var e,b=this.xData,c=this.yData,d=b.length;e=0;var f,g,o,n,h=this.xAxis,i=this.options,j=i.cropThreshold,k=0,l=this.isCartesian;if(l&&!this.isDirty&&!h.isDirty&&!this.yAxis.isDirty&&!a)return!1;for(l&&this.sorted&&(!j||d>j||this.forceCrop)&&(o=h.min,n=h.max,b[d-1]<o||b[0]>n?(b=[],c=[]):(b[0]<o||b[d-1]>n)&&(e=this.cropData(this.xData,this.yData,o,n),b=e.xData,c=e.yData,e=e.start,f=!0,k=b.length)),d=b.length-1;d>=0;d--)a=b[d]-b[d-1],!f&&b[d]>o&&b[d]<n&&k++,a>0&&(g===t||g>a)?g=a:0>a&&this.requireSorting&&ra(15);this.cropped=f,this.cropStart=e,this.processedXData=b,this.processedYData=c,this.activePointCount=k,null===i.pointRange&&(this.pointRange=g||1),this.closestPointRange=g},cropData:function(a,b,c,d){var i,e=a.length,f=0,g=e,h=m(this.cropShoulder,1);for(i=0;e>i;i++)if(a[i]>=c){f=v(0,i-h);break}for(;e>i;i++)if(a[i]>d){g=i+h;break}return{xData:a.slice(f,g),yData:b.slice(f,g),start:f,end:g}},generatePoints:function(){var c,i,k,o,a=this.options.data,b=this.data,d=this.processedXData,e=this.processedYData,f=this.pointClass,g=d.length,h=this.cropStart||0,j=this.hasGroupedData,l=[];for(b||j||(b=[],b.length=a.length,b=this.data=b),o=0;g>o;o++)i=h+o,j?l[o]=(new f).init(this,[d[o]].concat(qa(e[o]))):(b[i]?k=b[i]:a[i]!==t&&(b[i]=k=(new f).init(this,a[i],d[o])),l[o]=k);if(b&&(g!==(c=b.length)||j))for(o=0;c>o;o++)o===h&&!j&&(o+=g),b[o]&&(b[o].destroyElements(),b[o].plotX=t);this.data=b,this.points=l},getExtremes:function(a){var d,b=this.yAxis,c=this.processedXData,e=[],f=0;d=this.xAxis.getExtremes();var i,j,k,l,g=d.min,h=d.max,a=a||this.stackedYData||this.processedYData;for(d=a.length,l=0;d>l;l++)if(j=c[l],k=a[l],i=null!==k&&k!==t&&(!b.isLog||k.length||k>0),j=this.getExtremesFromAll||this.cropped||(c[l+1]||j)>=g&&(c[l-1]||j)<=h,i&&j)if(i=k.length)for(;i--;)null!==k[i]&&(e[f++]=k[i]);else e[f++]=k;this.dataMin=m(void 0,Na(e)),this.dataMax=m(void 0,Ba(e))},translate:function(){this.processedXData||this.processData(),this.generatePoints();for(var a=this.options,b=a.stacking,c=this.xAxis,d=c.categories,e=this.yAxis,f=this.points,g=f.length,h=!!this.modifyValue,i=a.pointPlacement,j="between"===i||ha(i),k=a.threshold,a=0;g>a;a++){var l=f[a],o=l.x,n=l.y,s=l.low,p=b&&e.stacks[(this.negStacks&&k>n?"-":"")+this.stackKey];e.isLog&&0>=n&&(l.y=n=null),l.plotX=c.translate(o,0,0,0,1,i,"flags"===this.type),b&&this.visible&&p&&p[o]&&(p=p[o],n=p.points[this.index+","+a],s=n[0],n=n[1],0===s&&(s=m(k,e.min)),e.isLog&&0>=s&&(s=null),l.total=l.stackTotal=p.total,l.percentage=p.total&&l.y/p.total*100,l.stackY=n,p.setOffset(this.pointXOffset||0,this.barW||0)),l.yBottom=r(s)?e.translate(s,0,1,0,1):null,h&&(n=this.modifyValue(n,l)),l.plotY="number"==typeof n&&1/0!==n?e.translate(n,0,1,0,1):t,l.clientX=j?c.translate(o,0,0,0,1):l.plotX,l.negative=l.y<(k||0),l.category=d&&d[l.x]!==t?d[l.x]:l.x}this.getSegments()},animate:function(a){var d,b=this.chart,c=b.renderer;d=this.options.animation;var g,e=this.clipBox||b.clipBox,f=b.inverted;d&&!ca(d)&&(d=ba[this.type].animation),g=["_sharedClip",d.duration,d.easing,e.height].join(","),a?(a=b[g],d=b[g+"m"],a||(b[g]=a=c.clipRect(q(e,{width:0})),b[g+"m"]=d=c.clipRect(-99,f?-b.plotLeft:-b.plotTop,99,f?b.chartWidth:b.chartHeight)),this.group.clip(a),this.markerGroup.clip(d),this.sharedClipKey=g):((a=b[g])&&a.animate({width:b.plotSizeX},d),b[g+"m"]&&b[g+"m"].animate({width:b.plotSizeX+99},d),this.animate=null)},afterAnimate:function(){var a=this.chart,b=this.sharedClipKey,c=this.group,d=this.clipBox;c&&this.options.clip!==!1&&(b&&d||c.clip(d?a.renderer.clipRect(d):a.clipRect),this.markerGroup.clip()),D(this,"afterAnimate"),setTimeout(function(){b&&a[b]&&(d||(a[b]=a[b].destroy()),a[b+"m"]&&(a[b+"m"]=a[b+"m"].destroy()))},100)},drawPoints:function(){var a,d,e,f,g,h,i,j,k,b=this.points,c=this.chart;d=this.options.marker;var o,l=this.pointAttr[""],n=this.markerGroup,s=m(d.enabled,this.activePointCount<.5*this.xAxis.len/d.radius);if(d.enabled!==!1||this._hasPointMarkers)for(f=b.length;f--;)g=b[f],d=T(g.plotX),e=g.plotY,k=g.graphic,i=g.marker||{},a=s&&i.enabled===t||i.enabled,o=c.isInsidePlot(u(d),e,c.inverted),a&&e!==t&&!isNaN(e)&&null!==g.y?(a=g.pointAttr[g.selected?"select":""]||l,h=a.r,i=m(i.symbol,this.symbol),j=0===i.indexOf("url"),k?k[o?"show":"hide"](!0).animate(q({x:d-h,y:e-h},k.symbolName?{width:2*h,height:2*h}:{})):o&&(h>0||j)&&(g.graphic=c.renderer.symbol(i,d-h,e-h,2*h,2*h).attr(a).add(n))):k&&(g.graphic=k.destroy())},convertAttribs:function(a,b,c,d){var f,g,e=this.pointAttrToOptions,h={},a=a||{},b=b||{},c=c||{},d=d||{};for(f in e)g=e[f],h[f]=m(a[g],b[f],c[f],d[f]);return h},getAttribs:function(){var f,a=this,b=a.options,c=ba[a.type].marker?b.marker:b,d=c.states,e=d.hover,g=a.color;f={stroke:g,fill:g};var i,k,h=a.points||[],j=[],l=a.pointAttrToOptions;k=a.hasPointSpecificOptions;var o=b.negativeColor,n=c.lineColor,s=c.fillColor;i=b.turboThreshold;var m;if(b.marker?(e.radius=e.radius||c.radius+2,e.lineWidth=e.lineWidth||c.lineWidth+1):e.color=e.color||ya(e.color||g).brighten(e.brightness).get(),j[""]=a.convertAttribs(c,f),p(["hover","select"],function(b){j[b]=a.convertAttribs(d[b],j[""])}),a.pointAttr=j,g=h.length,!i||i>g||k)for(;g--;){if(i=h[g],(c=i.options&&i.options.marker||i.options)&&c.enabled===!1&&(c.radius=0),i.negative&&o&&(i.color=i.fillColor=o),k=b.colorByPoint||i.color,i.options)for(m in l)r(c[l[m]])&&(k=!0);k?(c=c||{},k=[],d=c.states||{},f=d.hover=d.hover||{},b.marker||(f.color=f.color||!i.options.color&&e.color||ya(i.color).brighten(f.brightness||e.brightness).get()),f={color:i.color},s||(f.fillColor=i.color),n||(f.lineColor=i.color),k[""]=a.convertAttribs(q(f,c),j[""]),k.hover=a.convertAttribs(d.hover,j.hover,k[""]),k.select=a.convertAttribs(d.select,j.select,k[""])):k=j,i.pointAttr=k}},destroy:function(){var d,e,g,h,i,a=this,b=a.chart,c=/AppleWebKit\/533/.test(wa),f=a.data||[];for(D(a,"destroy"),W(a),p(a.axisTypes||[],function(b){(i=a[b])&&(ja(i.series,a),i.isDirty=i.forceRedraw=!0)}),a.legendItem&&a.chart.legend.destroyItem(a),e=f.length;e--;)(g=f[e])&&g.destroy&&g.destroy();a.points=null,clearTimeout(a.animationTimeout),p("area,graph,dataLabelsGroup,group,markerGroup,tracker,graphNeg,areaNeg,posClip,negClip".split(","),function(b){a[b]&&(d=c&&"group"===b?"hide":"destroy",a[b][d]())}),b.hoverSeries===a&&(b.hoverSeries=null),ja(b.series,a);for(h in a)delete a[h]},getSegmentPath:function(a){var b=this,c=[],d=b.options.step;return p(a,function(e,f){var i,g=e.plotX,h=e.plotY;b.getPointSpline?c.push.apply(c,b.getPointSpline(a,e,f)):(c.push(f?"L":"M"),d&&f&&(i=a[f-1],"right"===d?c.push(i.plotX,h):"center"===d?c.push((i.plotX+g)/2,i.plotY,(i.plotX+g)/2,h):c.push(g,i.plotY)),c.push(e.plotX,e.plotY))}),c},getGraphPath:function(){var c,a=this,b=[],d=[];return p(a.segments,function(e){c=a.getSegmentPath(e),e.length>1?b=b.concat(c):d.push(e[0])}),a.singlePoints=d,a.graphPath=b},drawGraph:function(){var a=this,b=this.options,c=[["graph",b.lineColor||this.color]],d=b.lineWidth,e=b.dashStyle,f="square"!==b.linecap,g=this.getGraphPath(),h=b.negativeColor;h&&c.push(["graphNeg",h]),p(c,function(c,h){var k=c[0],l=a[k];l?(bb(l),l.animate({d:g})):d&&g.length&&(l={stroke:c[1],"stroke-width":d,fill:Q,zIndex:1},e?l.dashstyle=e:f&&(l["stroke-linecap"]=l["stroke-linejoin"]="round"),a[k]=a.chart.renderer.path(g).attr(l).add(a.group).shadow(!h&&b.shadow))})},clipNeg:function(){var e,a=this.options,b=this.chart,c=b.renderer,d=a.negativeColor||a.negativeFillColor,f=this.graph,g=this.area,h=this.posClip,i=this.negClip;e=b.chartWidth;var j=b.chartHeight,k=v(e,j),l=this.yAxis;d&&(f||g)&&(d=u(l.toPixels(a.threshold||0,!0)),0>d&&(k-=d),a={x:0,y:0,width:k,height:d},k={x:0,y:d,width:k,height:k},b.inverted&&(a.height=k.y=b.plotWidth-d,c.isVML&&(a={x:b.plotWidth-d-b.plotLeft,y:0,width:e,height:j},k={x:d+b.plotLeft-e,y:0,width:b.plotLeft+d,height:e})),l.reversed?(b=k,e=a):(b=a,e=k),h?(h.animate(b),i.animate(e)):(this.posClip=h=c.clipRect(b),this.negClip=i=c.clipRect(e),f&&this.graphNeg&&(f.clip(h),this.graphNeg.clip(i)),g&&(g.clip(h),this.areaNeg.clip(i))))},invertGroups:function(){function a(){var a={width:b.yAxis.len,height:b.xAxis.len};p(["group","markerGroup"],function(c){b[c]&&b[c].attr(a).invert()})}var b=this,c=b.chart;b.xAxis&&(K(c,"resize",a),K(b,"destroy",function(){W(c,"resize",a)}),a(),b.invertGroups=a)},plotGroup:function(a,b,c,d,e){var f=this[a],g=!f;return g&&(this[a]=f=this.chart.renderer.g(b).attr({visibility:c,zIndex:d||.1}).add(e)),f[g?"attr":"animate"](this.getPlotBox()),f},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;return a.inverted&&(b=c,c=this.xAxis),{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var c,a=this,b=a.chart,d=a.options,e=(c=d.animation)&&!!a.animate&&b.renderer.isSVG&&m(c.duration,500)||0,f=a.visible?"visible":"hidden",g=d.zIndex,h=a.hasRendered,i=b.seriesGroup;c=a.plotGroup("group","series",f,g,i),a.markerGroup=a.plotGroup("markerGroup","markers",f,g,i),e&&a.animate(!0),a.getAttribs(),c.inverted=a.isCartesian?b.inverted:!1,a.drawGraph&&(a.drawGraph(),a.clipNeg()),a.drawDataLabels&&a.drawDataLabels(),a.visible&&a.drawPoints(),a.drawTracker&&a.options.enableMouseTracking!==!1&&a.drawTracker(),b.inverted&&a.invertGroups(),d.clip!==!1&&!a.sharedClipKey&&!h&&c.clip(b.clipRect),e&&a.animate(),h||(e?a.animationTimeout=setTimeout(function(){a.afterAnimate()},e):a.afterAnimate()),a.isDirty=a.isDirtyData=!1,a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:m(d&&d.left,a.plotLeft),translateY:m(e&&e.top,a.plotTop)})),this.translate(),this.setTooltipPoints&&this.setTooltipPoints(!0),this.render(),b&&D(this,"updatedData")}},Hb.prototype={destroy:function(){Oa(this,this.axis)},render:function(a){var b=this.options,c=b.format,c=c?Ia(c,this):b.formatter.call(this);this.label?this.label.attr({text:c,visibility:"hidden"}):this.label=this.axis.chart.renderer.text(c,null,null,b.useHTML).css(b.style).attr({align:this.textAlign,rotation:b.rotation,visibility:"hidden"}).add(a)},setOffset:function(a,b){var c=this.axis,d=c.chart,e=d.inverted,f=this.isNegative,g=c.translate(c.usePercentage?100:this.total,0,0,0,1),c=c.translate(0),c=M(g-c),h=d.xAxis[0].translate(this.x)+a,i=d.plotHeight,f={x:e?f?g:g-c:h,y:e?i-h-b:f?i-g-c:i-g,width:e?c:b,height:e?b:c};(e=this.label)&&(e.align(this.alignOptions,null,f),f=e.alignAttr,e[this.options.crop===!1||d.isInsidePlot(f.x,f.y)?"show":"hide"](!0))}},la.prototype.buildStacks=function(){var a=this.series,b=m(this.options.reversedStacks,!0),c=a.length;if(!this.isXAxis){for(this.usePercentage=!1;c--;)a[b?c:a.length-c-1].setStackedPoints();if(this.usePercentage)for(c=0;c<a.length;c++)a[c].setPercentStacks()}},la.prototype.renderStackTotals=function(){var d,e,a=this.chart,b=a.renderer,c=this.stacks,f=this.stackTotalGroup;f||(this.stackTotalGroup=f=b.g("stack-labels").attr({visibility:"visible",zIndex:6}).add()),f.translate(a.plotLeft,a.plotTop);for(d in c)for(e in a=c[d])a[e].render(f)},O.prototype.setStackedPoints=function(){if(this.options.stacking&&(this.visible===!0||this.chart.options.chart.ignoreHiddenSeries===!1)){var n,m,p,q,r,u,a=this.processedXData,b=this.processedYData,c=[],d=b.length,e=this.options,f=e.threshold,g=e.stack,e=e.stacking,h=this.stackKey,i="-"+h,j=this.negStacks,k=this.yAxis,l=k.stacks,o=k.oldStacks;for(q=0;d>q;q++)r=a[q],u=b[q],p=this.index+","+q,m=(n=j&&f>u)?i:h,l[m]||(l[m]={}),l[m][r]||(o[m]&&o[m][r]?(l[m][r]=o[m][r],l[m][r].total=null):l[m][r]=new Hb(k,k.options.stackLabels,n,r,g)),m=l[m][r],m.points[p]=[m.cum||0],"percent"===e?(n=n?h:i,j&&l[n]&&l[n][r]?(n=l[n][r],m.total=n.total=v(n.total,m.total)+M(u)||0):m.total=da(m.total+(M(u)||0))):m.total=da(m.total+(u||0)),m.cum=(m.cum||0)+(u||0),m.points[p].push(m.cum),c[q]=m.cum;"percent"===e&&(k.usePercentage=!0),this.stackedYData=c,k.oldStacks={}}},O.prototype.setPercentStacks=function(){var a=this,b=a.stackKey,c=a.yAxis.stacks,d=a.processedXData;p([b,"-"+b],function(b){for(var e,g,h,f=d.length;f--;)g=d[f],e=(h=c[b]&&c[b][g])&&h.points[a.index+","+f],(g=e)&&(h=h.total?100/h.total:0,g[0]=da(g[0]*h),g[1]=da(g[1]*h),a.stackedYData[f]=g[1])})},q(Ya.prototype,{addSeries:function(a,b,c){var d,e=this;return a&&(b=m(b,!0),D(e,"addSeries",{options:a},function(){d=e.initSeries(a),e.isDirtyLegend=!0,e.linkSeries(),b&&e.redraw(c)})),d},addAxis:function(a,b,c,d){var e=b?"xAxis":"yAxis",f=this.options;new la(this,w(a,{index:this[e].length,isX:b})),f[e]=qa(f[e]||{}),f[e].push(a),m(c,!0)&&this.redraw(d)},showLoading:function(a){var b=this.options,c=this.loadingDiv,d=b.loading;c||(this.loadingDiv=c=Y(Ja,{className:"highcharts-loading"},q(d.style,{zIndex:10,display:Q}),this.container),this.loadingSpan=Y("span",null,d.labelStyle,c)),this.loadingSpan.innerHTML=a||b.lang.loading,this.loadingShown||(G(c,{opacity:0,display:"",left:this.plotLeft+"px",top:this.plotTop+"px",width:this.plotWidth+"px",height:this.plotHeight+"px"}),kb(c,{opacity:d.style.opacity},{duration:d.showDuration||0}),this.loadingShown=!0)},hideLoading:function(){var a=this.options,b=this.loadingDiv;b&&kb(b,{opacity:0},{duration:a.loading.hideDuration||100,complete:function(){G(b,{display:Q})}}),this.loadingShown=!1}}),q(Ea.prototype,{update:function(a,b,c){var g,d=this,e=d.series,f=d.graphic,h=e.data,i=e.chart,j=e.options,b=m(b,!0);d.firePointEvent("update",{options:a},function(){d.applyOptions(a),ca(a)&&(e.getAttribs(),f&&(a&&a.marker&&a.marker.symbol?d.graphic=f.destroy():f.attr(d.pointAttr[d.state||""])),a&&a.dataLabels&&d.dataLabel&&(d.dataLabel=d.dataLabel.destroy())),g=Da(d,h),e.updateParallelArrays(d,g),j.data[g]=d.options,e.isDirty=e.isDirtyData=!0,!e.fixedBox&&e.hasCartesianSeries&&(i.isDirtyBox=!0),"point"===j.legendType&&i.legend.destroyItem(d),b&&i.redraw(c)})},remove:function(a,b){var g,c=this,d=c.series,e=d.points,f=d.chart,h=d.data;Qa(b,f),a=m(a,!0),c.firePointEvent("remove",null,function(){g=Da(c,h),h.length===e.length&&e.splice(g,1),h.splice(g,1),d.options.data.splice(g,1),d.updateParallelArrays(c,"splice",g,1),c.destroy(),d.isDirty=!0,d.isDirtyData=!0,a&&f.redraw()})}}),q(O.prototype,{addPoint:function(a,b,c,d){var o,e=this.options,f=this.data,g=this.graph,h=this.area,i=this.chart,j=this.xAxis&&this.xAxis.names,k=g&&g.shift||0,l=e.data,n=this.xData;if(Qa(d,i),c&&p([g,h,this.graphNeg,this.areaNeg],function(a){a&&(a.shift=k+1)}),h&&(h.isArea=!0),b=m(b,!0),d={series:this},this.pointClass.prototype.applyOptions.apply(d,[a]),g=d.x,h=n.length,this.requireSorting&&g<n[h-1])for(o=!0;h&&n[h-1]>g;)h--;this.updateParallelArrays(d,"splice",h,0,0),this.updateParallelArrays(d,h),j&&(j[g]=d.name),l.splice(h,0,a),o&&(this.data.splice(h,0,null),this.processData()),"point"===e.legendType&&this.generatePoints(),c&&(f[0]&&f[0].remove?f[0].remove(!1):(f.shift(),this.updateParallelArrays(d,"shift"),l.shift())),this.isDirtyData=this.isDirty=!0,b&&(this.getAttribs(),i.redraw())},remove:function(a,b){var c=this,d=c.chart,a=m(a,!0);c.isRemoving||(c.isRemoving=!0,D(c,"remove",null,function(){c.destroy(),d.isDirtyLegend=d.isDirtyBox=!0,d.linkSeries(),a&&d.redraw(b)})),c.isRemoving=!1},update:function(a,b){var f,c=this.chart,d=this.type,e=F[d].prototype,a=w(this.userOptions,{animation:!1,index:this.index,pointStart:this.xData[0]},{data:this.options.data},a);this.remove(!1);for(f in e)e.hasOwnProperty(f)&&(this[f]=t);q(this,F[a.type||d].prototype),this.init(c,a),m(b,!0)&&c.redraw(!1)}}),q(la.prototype,{update:function(a,b){var c=this.chart,a=c.options[this.coll][this.options.index]=w(this.userOptions,a);
5
+ this.destroy(!0),this._addedPlotLB=t,this.init(c,q(a,{events:t})),c.isDirtyBox=!0,m(b,!0)&&c.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,d=this.series,e=d.length;e--;)d[e]&&d[e].remove(!1);ja(b.axes,this),ja(b[c],this),b.options[c].splice(this.options.index,1),p(b[c],function(a,b){a.options.index=b}),this.destroy(),b.isDirtyBox=!0,m(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}}),ga=ka(O),F.line=ga,ba.area=w(S,{threshold:0});var pa=ka(O,{type:"area",getSegments:function(){var h,i,l,o,n,a=[],b=[],c=[],d=this.xAxis,e=this.yAxis,f=e.stacks[this.stackKey],g={},j=this.points,k=this.options.connectNulls;if(this.options.stacking&&!this.cropped){for(o=0;o<j.length;o++)g[j[o].x]=j[o];for(n in f)null!==f[n].total&&c.push(+n);c.sort(function(a,b){return a-b}),p(c,function(a){(!k||g[a]&&null!==g[a].y)&&(g[a]?b.push(g[a]):(h=d.translate(a),l=f[a].percent?f[a].total?100*f[a].cum/f[a].total:0:f[a].cum,i=e.toPixels(l,!0),b.push({y:null,plotX:h,clientX:h,plotY:i,yBottom:i,onMouseOver:sa})))}),b.length&&a.push(b)}else O.prototype.getSegments.call(this),a=this.segments;this.segments=a},getSegmentPath:function(a){var d,b=O.prototype.getSegmentPath.call(this,a),c=[].concat(b),e=this.options;d=b.length;var g,f=this.yAxis.getThreshold(e.threshold);if(3===d&&c.push("L",b[1],b[2]),e.stacking&&!this.closedStacks)for(d=a.length-1;d>=0;d--)g=m(a[d].yBottom,f),d<a.length-1&&e.step&&c.push(a[d+1].plotX,g),c.push(a[d].plotX,g);else this.closeSegment(c,a,f);return this.areaPath=this.areaPath.concat(c),b},closeSegment:function(a,b,c){a.push("L",b[b.length-1].plotX,c,"L",b[0].plotX,c)},drawGraph:function(){this.areaPath=[],O.prototype.drawGraph.apply(this);var a=this,b=this.areaPath,c=this.options,d=c.negativeColor,e=c.negativeFillColor,f=[["area",this.color,c.fillColor]];(d||e)&&f.push(["areaNeg",d,e]),p(f,function(d){var e=d[0],f=a[e];f?f.animate({d:b}):a[e]=a.chart.renderer.path(b).attr({fill:m(d[2],ya(d[1]).setOpacity(m(c.fillOpacity,.75)).get()),zIndex:0}).add(a.group)})},drawLegendSymbol:N.drawRectangle});F.area=pa,ba.spline=w(S),ga=ka(O,{type:"spline",getPointSpline:function(a,b,c){var h,i,j,k,d=b.plotX,e=b.plotY,f=a[c-1],g=a[c+1];if(f&&g){a=f.plotY,j=g.plotX;var l,g=g.plotY;h=(1.5*d+f.plotX)/2.5,i=(1.5*e+a)/2.5,j=(1.5*d+j)/2.5,k=(1.5*e+g)/2.5,l=(k-i)*(j-d)/(j-h)+e-k,i+=l,k+=l,i>a&&i>e?(i=v(a,e),k=2*e-i):a>i&&e>i&&(i=C(a,e),k=2*e-i),k>g&&k>e?(k=v(g,e),i=2*e-k):g>k&&e>k&&(k=C(g,e),i=2*e-k),b.rightContX=j,b.rightContY=k}return c?(b=["C",f.rightContX||f.plotX,f.rightContY||f.plotY,h||d,i||e,d,e],f.rightContX=f.rightContY=null):b=["M",d,e],b}}),F.spline=ga,ba.areaspline=w(ba.area),pa=pa.prototype,ga=ka(ga,{type:"areaspline",closedStacks:!0,getSegmentPath:pa.getSegmentPath,closeSegment:pa.closeSegment,drawGraph:pa.drawGraph,drawLegendSymbol:N.drawRectangle}),F.areaspline=ga,ba.column=w(S,{borderColor:"#FFFFFF",borderRadius:0,groupPadding:.2,marker:null,pointPadding:.1,minPointLength:0,cropThreshold:50,pointRange:null,states:{hover:{brightness:.1,shadow:!1,halo:!1},select:{color:"#C0C0C0",borderColor:"#000000",shadow:!1}},dataLabels:{align:null,verticalAlign:null,y:null},stickyTracking:!1,tooltip:{distance:6},threshold:0}),ga=ka(O,{type:"column",pointAttrToOptions:{stroke:"borderColor",fill:"color",r:"borderRadius"},cropShoulder:0,trackerGroups:["group","dataLabelsGroup"],negStacks:!0,init:function(){O.prototype.init.apply(this,arguments);var a=this,b=a.chart;b.hasRendered&&p(b.series,function(b){b.type===a.type&&(b.isDirty=!0)})},getColumnMetrics:function(){var f,h,a=this,b=a.options,c=a.xAxis,d=a.yAxis,e=c.reversed,g={},i=0;b.grouping===!1?i=1:p(a.chart.series,function(b){var c=b.options,e=b.yAxis;b.type===a.type&&b.visible&&d.len===e.len&&d.pos===e.pos&&(c.stacking?(f=b.stackKey,g[f]===t&&(g[f]=i++),h=g[f]):c.grouping!==!1&&(h=i++),b.columnIndex=h)});var c=C(M(c.transA)*(c.ordinalSlope||b.pointRange||c.closestPointRange||c.tickInterval||1),c.len),j=c*b.groupPadding,k=(c-2*j)/i,l=b.pointWidth,b=r(l)?(k-l)/2:k*b.pointPadding,l=m(l,k-2*b);return a.columnMetrics={width:l,offset:b+(j+((e?i-(a.columnIndex||0):a.columnIndex)||0)*k-c/2)*(e?-1:1)}},translate:function(){var a=this,b=a.chart,c=a.options,d=a.borderWidth=m(c.borderWidth,a.activePointCount>.5*a.xAxis.len?0:1),e=a.yAxis,f=a.translatedThreshold=e.getThreshold(c.threshold),g=m(c.minPointLength,5),c=a.getColumnMetrics(),h=c.width,i=a.barW=Ka(v(h,1+2*d)),j=a.pointXOffset=c.offset,k=-(d%2?.5:0),l=d%2?.5:1;b.renderer.isVML&&b.inverted&&(l+=1),O.prototype.translate.apply(a),p(a.points,function(c){var x,d=m(c.yBottom,f),p=C(v(-999-d,c.plotY),e.len+999+d),q=c.plotX+j,r=i,t=C(p,d);x=v(p,d)-t,M(x)<g&&g&&(x=g,t=u(M(t-f)>g?d-g:f-(e.translate(c.y,0,1,0,1)<=f?g:0))),c.barX=q,c.pointWidth=h,c.tooltipPos=b.inverted?[e.len-p,a.xAxis.len-q-r/2]:[q+r/2,p],d=M(q)<.5,r=u(q+r)+k,q=u(q)+k,r-=q,p=M(t)<.5,x=u(t+x)+l,t=u(t)+l,x-=t,d&&(q+=1,r-=1),p&&(t-=1,x+=1),c.shapeType="rect",c.shapeArgs={x:q,y:t,width:r,height:x}})},getSymbol:sa,drawLegendSymbol:N.drawRectangle,drawGraph:sa,drawPoints:function(){var f,g,h,a=this,b=this.chart,c=a.options,d=b.renderer,e=c.animationLimit||250;p(a.points,function(i){var j=i.plotY,k=i.graphic;j===t||isNaN(j)||null===i.y?k&&(i.graphic=k.destroy()):(f=i.shapeArgs,h=r(a.borderWidth)?{"stroke-width":a.borderWidth}:{},g=i.pointAttr[i.selected?"select":""]||a.pointAttr[""],k?(bb(k),k.attr(h)[b.pointCount<e?"animate":"attr"](w(f))):i.graphic=d[i.shapeType](f).attr(g).attr(h).add(a.group).shadow(c.shadow,null,c.stacking&&!c.borderRadius))})},animate:function(a){var b=this.yAxis,c=this.options,d=this.chart.inverted,e={};aa&&(a?(e.scaleY=.001,a=C(b.pos+b.len,v(b.pos,b.toPixels(c.threshold))),d?e.translateX=a-b.len:e.translateY=a,this.group.attr(e)):(e.scaleY=1,e[d?"translateX":"translateY"]=b.pos,this.group.animate(e,this.options.animation),this.animate=null))},remove:function(){var a=this,b=a.chart;b.hasRendered&&p(b.series,function(b){b.type===a.type&&(b.isDirty=!0)}),O.prototype.remove.apply(a,arguments)}}),F.column=ga,ba.bar=w(ba.column),pa=ka(ga,{type:"bar",inverted:!0}),F.bar=pa,ba.scatter=w(S,{lineWidth:0,tooltip:{headerFormat:'<span style="color:{series.color}">●</span> <span style="font-size: 10px;"> {series.name}</span><br/>',pointFormat:"x: <b>{point.x}</b><br/>y: <b>{point.y}</b><br/>"},stickyTracking:!1}),pa=ka(O,{type:"scatter",sorted:!1,requireSorting:!1,noSharedTooltip:!0,trackerGroups:["markerGroup"],takeOrdinalPosition:!1,singularTooltips:!0,drawGraph:function(){this.options.lineWidth&&O.prototype.drawGraph.call(this)}}),F.scatter=pa,ba.pie=w(S,{borderColor:"#FFFFFF",borderWidth:1,center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30,enabled:!0,formatter:function(){return this.point.name}},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,states:{hover:{brightness:.1,shadow:!1}},stickyTracking:!1,tooltip:{followPointer:!0}}),S={type:"pie",isCartesian:!1,pointClass:ka(Ea,{init:function(){Ea.prototype.init.apply(this,arguments);var b,a=this;return a.y<0&&(a.y=null),q(a,{visible:a.visible!==!1,name:m(a.name,"Slice")}),b=function(b){a.slice("select"===b.type)},K(a,"select",b),K(a,"unselect",b),a},setVisible:function(a){var b=this,c=b.series,d=c.chart;b.visible=b.options.visible=a=a===t?!b.visible:a,c.options.data[Da(b,c.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){b[c]&&b[c][a?"show":"hide"](!0)}),b.legendItem&&d.legend.colorizeItem(b,a),!c.isDirty&&c.options.ignoreHiddenPoint&&(c.isDirty=!0,d.redraw())},slice:function(a,b,c){var d=this.series;Qa(c,d.chart),m(b,!0),this.sliced=this.options.sliced=a=r(a)?a:!this.sliced,d.options.data[Da(this,d.data)]=this.options,a=a?this.slicedTranslation:{translateX:0,translateY:0},this.graphic.animate(a),this.shadowGroup&&this.shadowGroup.animate(a)},haloPath:function(a){var b=this.shapeArgs,c=this.series.chart;return this.series.chart.renderer.symbols.arc(c.plotLeft+b.x,c.plotTop+b.y,b.r+a,b.r+a,{innerR:this.shapeArgs.r,start:b.start,end:b.end})}}),requireSorting:!1,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color"},singularTooltips:!0,getColor:sa,animate:function(a){var b=this,c=b.points,d=b.startAngleRad;a||(p(c,function(a){var c=a.graphic,a=a.shapeArgs;c&&(c.attr({r:b.center[3]/2,start:d,end:d}),c.animate({r:a.r,start:a.start,end:a.end},b.options.animation))}),b.animate=null)},setData:function(a,b,c,d){O.prototype.setData.call(this,a,!1,c,d),this.processData(),this.generatePoints(),m(b,!0)&&this.chart.redraw(c)},generatePoints:function(){var a,c,d,e,b=0,f=this.options.ignoreHiddenPoint;for(O.prototype.generatePoints.call(this),c=this.points,d=c.length,a=0;d>a;a++)e=c[a],b+=f&&!e.visible?0:e.y;for(this.total=b,a=0;d>a;a++)e=c[a],e.percentage=b>0?e.y/b*100:0,e.total=b},translate:function(a){this.generatePoints();var f,g,h,o,p,b=0,c=this.options,d=c.slicedOffset,e=d+c.borderWidth,i=c.startAngle||0,j=this.startAngleRad=ma/180*(i-90),i=(this.endAngleRad=ma/180*(m(c.endAngle,i+360)-90))-j,k=this.points,l=c.dataLabels.distance,c=c.ignoreHiddenPoint,n=k.length;for(a||(this.center=a=this.getCenter()),this.getX=function(b,c){return h=U.asin(C((b-a[1])/(a[2]/2+l),1)),a[0]+(c?-1:1)*Z(h)*(a[2]/2+l)},o=0;n>o;o++)p=k[o],f=j+b*i,(!c||p.visible)&&(b+=p.percentage/100),g=j+b*i,p.shapeType="arc",p.shapeArgs={x:a[0],y:a[1],r:a[2]/2,innerR:a[3]/2,start:u(1e3*f)/1e3,end:u(1e3*g)/1e3},h=(g+f)/2,h>1.5*ma?h-=2*ma:-ma/2>h&&(h+=2*ma),p.slicedTranslation={translateX:u(Z(h)*d),translateY:u(ea(h)*d)},f=Z(h)*a[2]/2,g=ea(h)*a[2]/2,p.tooltipPos=[a[0]+.7*f,a[1]+.7*g],p.half=-ma/2>h||h>ma/2?1:0,p.angle=h,e=C(e,l/2),p.labelPos=[a[0]+f+Z(h)*l,a[1]+g+ea(h)*l,a[0]+f+Z(h)*e,a[1]+g+ea(h)*e,a[0]+f,a[1]+g,0>l?"center":p.half?"right":"left",h]},drawGraph:null,drawPoints:function(){var c,d,f,g,a=this,b=a.chart.renderer,e=a.options.shadow;e&&!a.shadowGroup&&(a.shadowGroup=b.g("shadow").add(a.group)),p(a.points,function(h){d=h.graphic,g=h.shapeArgs,f=h.shadowGroup,e&&!f&&(f=h.shadowGroup=b.g("shadow").add(a.shadowGroup)),c=h.sliced?h.slicedTranslation:{translateX:0,translateY:0},f&&f.attr(c),d?d.animate(q(g,c)):h.graphic=d=b[h.shapeType](g).setRadialReference(a.center).attr(h.pointAttr[h.selected?"select":""]).attr({"stroke-linejoin":"round"}).attr(c).add(a.group).shadow(e,f),void 0!==h.visible&&h.setVisible(h.visible)})},sortByAngle:function(a,b){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*b})},drawLegendSymbol:N.drawRectangle,getCenter:X.getCenter,getSymbol:sa},S=ka(O,S),F.pie=S,O.prototype.drawDataLabels=function(){var f,g,h,i,a=this,b=a.options,c=b.cursor,d=b.dataLabels,e=a.points;(d.enabled||a._hasPointLabels)&&(a.dlProcessOptions&&a.dlProcessOptions(d),i=a.plotGroup("dataLabelsGroup","data-labels","hidden",d.zIndex||6),!a.hasRendered&&m(d.defer,!0)&&(i.attr({opacity:0}),K(a,"afterAnimate",function(){a.dataLabelsGroup.show()[b.animation?"animate":"attr"]({opacity:1},{duration:200})})),g=d,p(e,function(b){var e,o,n,l=b.dataLabel,p=b.connector,u=!0;if(f=b.options&&b.options.dataLabels,e=m(f&&f.enabled,g.enabled),l&&!e)b.dataLabel=l.destroy();else if(e){if(d=w(g,f),e=d.rotation,o=b.getLabelConfig(),h=d.format?Ia(d.format,o):d.formatter.call(o,d),d.style.color=m(d.color,d.style.color,a.color,"black"),l)r(h)?(l.attr({text:h}),u=!1):(b.dataLabel=l=l.destroy(),p&&(b.connector=p.destroy()));else if(r(h)){l={fill:d.backgroundColor,stroke:d.borderColor,"stroke-width":d.borderWidth,r:d.borderRadius||0,rotation:e,padding:d.padding,zIndex:1};for(n in l)l[n]===t&&delete l[n];l=b.dataLabel=a.chart.renderer[e?"text":"label"](h,0,-999,null,null,null,d.useHTML).attr(l).css(q(d.style,c&&{cursor:c})).add(i).shadow(d.shadow)}l&&a.alignDataLabel(b,l,d,null,u)}}))},O.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=m(a.plotX,-999),i=m(a.plotY,-999),j=b.getBBox();(a=this.visible&&(a.series.forceDL||f.isInsidePlot(h,u(i),g)||d&&f.isInsidePlot(h,g?d.x+1:d.y+d.height-1,g)))&&(d=q({x:g?f.plotWidth-i:h,y:u(g?f.plotHeight-h:i),width:0,height:0},d),q(c,{width:j.width,height:j.height}),c.rotation?(g={align:c.align,x:d.x+c.x+d.width/2,y:d.y+c.y+d.height/2},b[e?"attr":"animate"](g)):(b.align(c,null,d),g=b.alignAttr,"justify"===m(c.overflow,"justify")?this.justifyDataLabel(b,c,g,j,d,e):m(c.crop,!0)&&(a=f.isInsidePlot(g.x,g.y)&&f.isInsidePlot(g.x+j.width,g.y+j.height)))),a||(b.attr({y:-999}),b.placed=!1)},O.prototype.justifyDataLabel=function(a,b,c,d,e,f){var j,k,g=this.chart,h=b.align,i=b.verticalAlign;j=c.x,0>j&&("right"===h?b.align="left":b.x=-j,k=!0),j=c.x+d.width,j>g.plotWidth&&("left"===h?b.align="right":b.x=g.plotWidth-j,k=!0),j=c.y,0>j&&("bottom"===i?b.verticalAlign="top":b.y=-j,k=!0),j=c.y+d.height,j>g.plotHeight&&("top"===i?b.verticalAlign="bottom":b.y=g.plotHeight-j,k=!0),k&&(a.placed=!f,a.align(b,null,e))},F.pie&&(F.pie.prototype.drawDataLabels=function(){var c,i,j,t,w,x,y,A,C,G,D,B,a=this,b=a.data,d=a.chart,e=a.options.dataLabels,f=m(e.connectorPadding,10),g=m(e.connectorWidth,1),h=d.plotWidth,d=d.plotHeight,k=m(e.softConnector,!0),l=e.distance,o=a.center,n=o[2]/2,q=o[1],r=l>0,z=[[],[]],F=[0,0,0,0],N=function(a,b){return b.y-a.y};if(a.visible&&(e.enabled||a._hasPointLabels)){for(O.prototype.drawDataLabels.apply(a),p(b,function(a){a.dataLabel&&a.visible&&z[a.half].push(a)}),D=0;!y&&b[D];)y=b[D]&&b[D].dataLabel&&(b[D].dataLabel.getBBox().height||21),D++;for(D=2;D--;){var E,b=[],K=[],H=z[D],I=H.length;if(a.sortByAngle(H,D-.5),l>0){for(B=q-n-l;q+n+l>=B;B+=y)b.push(B);if(w=b.length,I>w){for(c=[].concat(H),c.sort(N),B=I;B--;)c[B].rank=B;for(B=I;B--;)H[B].rank>=w&&H.splice(B,1);I=H.length}for(B=0;I>B;B++){c=H[B],x=c.labelPos,c=9999;var Q,P;for(P=0;w>P;P++)Q=M(b[P]-x[1]),c>Q&&(c=Q,E=P);if(B>E&&null!==b[B])E=B;else for(I-B+E>w&&null!==b[B]&&(E=w-I+B);null===b[E];)E++;K.push({i:E,y:b[E]}),b[E]=null}K.sort(N)}for(B=0;I>B;B++)c=H[B],x=c.labelPos,t=c.dataLabel,G=c.visible===!1?"hidden":"visible",c=x[1],l>0?(w=K.pop(),E=w.i,C=w.y,(c>C&&null!==b[E+1]||C>c&&null!==b[E-1])&&(C=c)):C=c,A=e.justify?o[0]+(D?-1:1)*(n+l):a.getX(0===E||E===b.length-1?c:C,D),t._attr={visibility:G,align:x[6]},t._pos={x:A+e.x+({left:f,right:-f}[x[6]]||0),y:C+e.y-10},t.connX=A,t.connY=C,null===this.options.size&&(w=t.width,f>A-w?F[3]=v(u(w-A+f),F[3]):A+w>h-f&&(F[1]=v(u(A+w-h+f),F[1])),0>C-y/2?F[0]=v(u(-C+y/2),F[0]):C+y/2>d&&(F[2]=v(u(C+y/2-d),F[2])))}(0===Ba(F)||this.verifyDataLabelOverflow(F))&&(this.placeDataLabels(),r&&g&&p(this.points,function(b){i=b.connector,x=b.labelPos,(t=b.dataLabel)&&t._pos?(G=t._attr.visibility,A=t.connX,C=t.connY,j=k?["M",A+("left"===x[6]?5:-5),C,"C",A,C,2*x[2]-x[4],2*x[3]-x[5],x[2],x[3],"L",x[4],x[5]]:["M",A+("left"===x[6]?5:-5),C,"L",x[2],x[3],"L",x[4],x[5]],i?(i.animate({d:j}),i.attr("visibility",G)):b.connector=i=a.chart.renderer.path(j).attr({"stroke-width":g,stroke:e.connectorColor||b.color||"#606060",visibility:G}).add(a.dataLabelsGroup)):i&&(b.connector=i.destroy())}))}},F.pie.prototype.placeDataLabels=function(){p(this.points,function(a){var b,a=a.dataLabel;a&&((b=a._pos)?(a.attr(a._attr),a[a.moved?"animate":"attr"](b),a.moved=!0):a&&a.attr({y:-999}))})},F.pie.prototype.alignDataLabel=sa,F.pie.prototype.verifyDataLabelOverflow=function(a){var f,b=this.center,c=this.options,d=c.center,e=c=c.minSize||80;return null!==d[0]?e=v(b[2]-v(a[1],a[3]),c):(e=v(b[2]-a[1]-a[3],c),b[0]+=(a[3]-a[1])/2),null!==d[1]?e=v(C(e,b[2]-v(a[0],a[2])),c):(e=v(C(e,b[2]-a[0]-a[2]),c),b[1]+=(a[0]-a[2])/2),e<b[2]?(b[2]=e,this.translate(b),p(this.points,function(a){a.dataLabel&&(a.dataLabel._pos=null)}),this.drawDataLabels&&this.drawDataLabels()):f=!0,f}),F.column&&(F.column.prototype.alignDataLabel=function(a,b,c,d,e){var f=this.chart,g=f.inverted,h=a.dlBox||a.shapeArgs,i=a.below||a.plotY>m(this.translatedThreshold,f.plotSizeY),j=m(c.inside,!!this.options.stacking);h&&(d=w(h),g&&(d={x:f.plotWidth-d.y-d.height,y:f.plotHeight-d.x-d.width,width:d.height,height:d.width}),!j)&&(g?(d.x+=i?0:d.width,d.width=0):(d.y+=i?d.height:0,d.height=0)),c.align=m(c.align,!g||j?"center":i?"right":"left"),c.verticalAlign=m(c.verticalAlign,g||j?"middle":i?"top":"bottom"),O.prototype.alignDataLabel.call(this,a,b,c,d,e)}),S=R.TrackerMixin={drawTrackerPoint:function(){var a=this,b=a.chart,c=b.pointer,d=a.options.cursor,e=d&&{cursor:d},f=function(c){var e,d=c.target;for(b.hoverSeries!==a&&a.onMouseOver();d&&!e;)e=d.point,d=d.parentNode;e!==t&&e!==b.hoverPoint&&e.onMouseOver(c)};p(a.points,function(a){a.graphic&&(a.graphic.element.point=a),a.dataLabel&&(a.dataLabel.element.point=a)}),a._hasTracking||(p(a.trackerGroups,function(b){a[b]&&(a[b].addClass("highcharts-tracker").on("mouseover",f).on("mouseout",function(a){c.onTrackerMouseOut(a)}).css(e),$a)&&a[b].on("touchstart",f)}),a._hasTracking=!0)},drawTrackerGraph:function(){var m,a=this,b=a.options,c=b.trackByArea,d=[].concat(c?a.areaPath:a.graphPath),e=d.length,f=a.chart,g=f.pointer,h=f.renderer,i=f.options.tooltip.snap,j=a.tracker,k=b.cursor,l=k&&{cursor:k},k=a.singlePoints,n=function(){f.hoverSeries!==a&&a.onMouseOver()},q="rgba(192,192,192,"+(aa?1e-4:.002)+")";if(e&&!c)for(m=e+1;m--;)"M"===d[m]&&d.splice(m+1,0,d[m+1]-i,d[m+2],"L"),(m&&"M"===d[m]||m===e)&&d.splice(m,0,"L",d[m-2]+i,d[m-1]);for(m=0;m<k.length;m++)e=k[m],d.push("M",e.plotX-i,e.plotY,"L",e.plotX+i,e.plotY);j?j.attr({d:d}):(a.tracker=h.path(d).attr({"stroke-linejoin":"round",visibility:a.visible?"visible":"hidden",stroke:q,fill:c?q:Q,"stroke-width":b.lineWidth+(c?0:2*i),zIndex:2}).add(a.group),p([a.tracker,a.markerGroup],function(a){a.addClass("highcharts-tracker").on("mouseover",n).on("mouseout",function(a){g.onTrackerMouseOut(a)}).css(l),$a&&a.on("touchstart",n)}))}},F.column&&(ga.prototype.drawTracker=S.drawTrackerPoint),F.pie&&(F.pie.prototype.drawTracker=S.drawTrackerPoint),F.scatter&&(pa.prototype.drawTracker=S.drawTrackerPoint),q(lb.prototype,{setItemEvents:function(a,b,c,d,e){var f=this;(c?b:a.legendGroup).on("mouseover",function(){a.setState("hover"),b.css(f.options.itemHoverStyle)}).on("mouseout",function(){b.css(a.visible?d:e),a.setState()}).on("click",function(b){var c=function(){a.setVisible()},b={browserEvent:b};a.firePointEvent?a.firePointEvent("legendItemClick",b,c):D(a,"legendItemClick",b,c)})},createCheckboxForItem:function(a){a.checkbox=Y("input",{type:"checkbox",checked:a.selected,defaultChecked:a.selected},this.options.itemCheckboxStyle,this.chart.container),K(a.checkbox,"click",function(b){D(a,"checkboxClick",{checked:b.target.checked},function(){a.select()})})}}),E.legend.itemStyle.cursor="pointer",q(Ya.prototype,{showResetZoom:function(){var a=this,b=E.lang,c=a.options.chart.resetZoomButton,d=c.theme,e=d.states,f="chart"===c.relativeTo?null:"plotBox";this.resetZoomButton=a.renderer.button(b.resetZoom,null,null,function(){a.zoomOut()},d,e&&e.hover).attr({align:c.position.align,title:b.resetZoomTitle}).add().align(c.position,!1,f)},zoomOut:function(){var a=this;D(a,"selection",{resetSelection:!0},function(){a.zoom()})},zoom:function(a){var b,e,c=this.pointer,d=!1;!a||a.resetSelection?p(this.axes,function(a){b=a.zoom()}):p(a.xAxis.concat(a.yAxis),function(a){var e=a.axis,h=e.isXAxis;(c[h?"zoomX":"zoomY"]||c[h?"pinchX":"pinchY"])&&(b=e.zoom(a.min,a.max),e.displayBtn&&(d=!0))}),e=this.resetZoomButton,d&&!e?this.showResetZoom():!d&&ca(e)&&(this.resetZoomButton=e.destroy()),b&&this.redraw(m(this.options.chart.animation,a&&a.animation,this.pointCount<100))},pan:function(a,b){var e,c=this,d=c.hoverPoints;d&&p(d,function(a){a.setState()}),p("xy"===b?[1,0]:[1],function(b){var d=a[b?"chartX":"chartY"],h=c[b?"xAxis":"yAxis"][0],i=c[b?"mouseDownX":"mouseDownY"],j=(h.pointRange||0)/2,k=h.getExtremes(),l=h.toValue(i-d,!0)+j,i=h.toValue(i+c[b?"plotWidth":"plotHeight"]-d,!0)-j;h.series.length&&l>C(k.dataMin,k.min)&&i<v(k.dataMax,k.max)&&(h.setExtremes(l,i,!1,!1,{trigger:"pan"}),e=!0),c[b?"mouseDownX":"mouseDownY"]=d}),e&&c.redraw(!1),G(c.container,{cursor:"move"})}}),q(Ea.prototype,{select:function(a,b){var c=this,d=c.series,e=d.chart,a=m(a,!c.selected);c.firePointEvent(a?"select":"unselect",{accumulate:b},function(){c.selected=c.options.selected=a,d.options.data[Da(c,d.data)]=c.options,c.setState(a&&"select"),b||p(e.getSelectedPoints(),function(a){a.selected&&a!==c&&(a.selected=a.options.selected=!1,d.options.data[Da(a,d.data)]=a.options,a.setState(""),a.firePointEvent("unselect"))})})},onMouseOver:function(a){var b=this.series,c=b.chart,d=c.tooltip,e=c.hoverPoint;e&&e!==this&&e.onMouseOut(),this.firePointEvent("mouseOver"),d&&(!d.shared||b.noSharedTooltip)&&d.refresh(this,a),this.setState("hover"),c.hoverPoint=this},onMouseOut:function(){var a=this.series.chart,b=a.hoverPoints;b&&-1!==Da(this,b)||(this.firePointEvent("mouseOut"),this.setState(),a.hoverPoint=null)},importEvents:function(){if(!this.hasImportedEvents){var b,a=w(this.series.options.point,this.options).events;this.events=a;for(b in a)K(this,b,a[b]);this.hasImportedEvents=!0}},setState:function(a,b){var p,c=this.plotX,d=this.plotY,e=this.series,f=e.options.states,g=ba[e.type].marker&&e.options.marker,h=g&&!g.enabled,i=g&&g.states[a],j=i&&i.enabled===!1,k=e.stateMarkerGraphic,l=this.marker||{},m=e.chart,n=e.halo,a=a||"";p=this.pointAttr[a]||e.pointAttr[a],a===this.state&&!b||this.selected&&"select"!==a||f[a]&&f[a].enabled===!1||a&&(j||h&&i.enabled===!1)||a&&l.states&&l.states[a]&&l.states[a].enabled===!1||(this.graphic?(g=g&&this.graphic.symbolName&&p.r,this.graphic.attr(w(p,g?{x:c-g,y:d-g,width:2*g,height:2*g}:{})),k&&k.hide()):(a&&i&&(g=i.radius,l=l.symbol||e.symbol,k&&k.currentSymbol!==l&&(k=k.destroy()),k?k[b?"animate":"attr"]({x:c-g,y:d-g}):l&&(e.stateMarkerGraphic=k=m.renderer.symbol(l,c-g,d-g,2*g,2*g).attr(p).add(e.markerGroup),k.currentSymbol=l)),k&&k[a&&m.isInsidePlot(c,d,m.inverted)?"show":"hide"]()),(c=f[a]&&f[a].halo)&&c.size?(n||(e.halo=n=m.renderer.path().add(e.seriesGroup)),n.attr(q({fill:ya(this.color||e.color).setOpacity(c.opacity).get()},c.attributes))[b?"animate":"attr"]({d:this.haloPath(c.size)})):n&&n.attr({d:[]}),this.state=a)},haloPath:function(a){var b=this.series,c=b.chart,d=b.getPlotBox(),e=c.inverted;return c.renderer.symbols.circle(d.translateX+(e?b.yAxis.len-this.plotY:this.plotX)-a,d.translateY+(e?b.xAxis.len-this.plotX:this.plotY)-a,2*a,2*a)}}),q(O.prototype,{onMouseOver:function(){var a=this.chart,b=a.hoverSeries;b&&b!==this&&b.onMouseOut(),this.options.events.mouseOver&&D(this,"mouseOver"),this.setState("hover"),a.hoverSeries=this},onMouseOut:function(){var a=this.options,b=this.chart,c=b.tooltip,d=b.hoverPoint;d&&d.onMouseOut(),this&&a.events.mouseOut&&D(this,"mouseOut"),c&&!a.stickyTracking&&(!c.shared||this.noSharedTooltip)&&c.hide(),this.setState(),b.hoverSeries=null},setState:function(a){var b=this.options,c=this.graph,d=this.graphNeg,e=b.states,b=b.lineWidth,a=a||"";this.state!==a&&(this.state=a,e[a]&&e[a].enabled===!1||(a&&(b=e[a].lineWidth||b+1),c&&!c.dashstyle&&(a={"stroke-width":b},c.attr(a),d&&d.attr(a))))},setVisible:function(a,b){var f,c=this,d=c.chart,e=c.legendItem,g=d.options.chart.ignoreHiddenSeries,h=c.visible;f=(c.visible=a=c.userOptions.visible=a===t?!h:a)?"show":"hide",p(["group","dataLabelsGroup","markerGroup","tracker"],function(a){c[a]&&c[a][f]()}),d.hoverSeries===c&&c.onMouseOut(),e&&d.legend.colorizeItem(c,a),c.isDirty=!0,c.options.stacking&&p(d.series,function(a){a.options.stacking&&a.visible&&(a.isDirty=!0)}),p(c.linkedSeries,function(b){b.setVisible(a,!1)}),g&&(d.isDirtyBox=!0),b!==!1&&d.redraw(),D(c,f)},setTooltipPoints:function(a){var c,d,h,i,b=[],e=this.xAxis,f=e&&e.getExtremes(),g=e?e.tooltipLen||e.len:this.chart.plotSizeX,j=[];if(this.options.enableMouseTracking!==!1&&!this.singularTooltips){for(a&&(this.tooltipPoints=null),p(this.segments||this.points,function(a){b=b.concat(a)}),e&&e.reversed&&(b=b.reverse()),this.orderTooltipPoints&&this.orderTooltipPoints(b),a=b.length,i=0;a>i;i++)if(e=b[i],c=e.x,c>=f.min&&c<=f.max)for(h=b[i+1],c=d===t?0:d+1,d=b[i+1]?C(v(0,T((e.clientX+(h?h.wrappedClientX||h.clientX:g))/2)),g):g;c>=0&&d>=c;)j[c++]=e;this.tooltipPoints=j}},show:function(){this.setVisible(!0)},hide:function(){this.setVisible(!1)},select:function(a){this.selected=a=a===t?!this.selected:a,this.checkbox&&(this.checkbox.checked=a),D(this,a?"select":"unselect")},drawTracker:S.drawTrackerGraph}),q(R,{Axis:la,Chart:Ya,Color:ya,Point:Ea,Tick:Sa,Renderer:Za,Series:O,SVGElement:P,SVGRenderer:ta,arrayMin:Na,arrayMax:Ba,charts:V,dateFormat:cb,format:Ia,pathAnim:ub,getOptions:function(){return E},hasBidiBug:Nb,isTouchDevice:Jb,numberFormat:Ga,seriesTypes:F,setOptions:function(a){return E=w(!0,E,a),Cb(),E},addEvent:K,removeEvent:W,createElement:Y,discardElement:Pa,css:G,each:p,extend:q,map:Ua,merge:w,pick:m,splat:qa,extendClass:ka,pInt:z,wrap:Ma,svg:aa,canvas:fa,vml:!aa&&!fa,product:"Highcharts",version:"4.0.1"})}(),jQuery(document).ready(function($){$("#close-share").click(function(){$.cookie("ignore_social_share",1,{expires:30})}),$(".big-button--share").click(function(){$.cookie("ignore_social_share",1)}),$.cookie("ignore_social_share")||leadin_check_social_share_popup(),$("#filter_action").select2(),$("#filter_action").change(function(){var $this=$(this);"submitted"==$this.val()?$("#form-filter-input").show():($("#form-filter-input").hide(),$("#filter_form").select2("val","any form"))}),$("#view-all-do-not-track-selectors").click(function(){$(".form-do-not-track, #view-less-do-not-track-selectors").not(".do-not-track-always-show").show(),$("#view-all-do-not-track-selectors").hide()}),$("#view-less-do-not-track-selectors").click(function(){$(".form-do-not-track, #view-less-do-not-track-selectors").not(".do-not-track-always-show").hide(),$("#view-all-do-not-track-selectors").show()}),$("#filter_content").select2({query:function(query){var key=query.term;$.ajax({type:"POST",url:li_admin_ajax.ajax_url,data:{action:"leadin_get_posts_and_pages",search_term:key},success:function(data){var i,json_data=jQuery.parseJSON(data),data_test={results:[]};for(i=0;i<json_data.length;i++)data_test.results.push({id:json_data[i].post_title,text:json_data[i].post_title});query.callback(data_test)}})},initSelection:function(){$("#filter_content").val()?$("#filter_content").select2("data",{id:$("#filter_content").val(),text:$("#filter_content").val()}):$("#filter_content").select2("data",{id:"any page",text:"any page"})}}),$("#filter_form").select2({query:function(query){var key=query.term;$.ajax({type:"POST",url:li_admin_ajax.ajax_url,data:{action:"leadin_get_form_selectors",search_term:key},success:function(data){var i,json_data=jQuery.parseJSON(data),data_test={results:[]};for(i=0;i<json_data.length;i++)data_test.results.push({id:json_data[i],text:json_data[i]});query.callback(data_test)}})},initSelection:function(){$("#filter_form").val()?$("#filter_form").select2("data",{id:$("#filter_form").val(),text:$("#filter_form").val()}):$("#filter_form").select2("data",{id:"any form",text:"any form"})}}),$("#leadin-contact-status").change(function(){$("#leadin-contact-status-button").addClass("button-primary")}),$("input[name=popup-position]:radio").change(function(){$("#btn-activate-subscribe").attr("href",window.location.href+"&leadin_action=activate&power_up=subscribe_widget&redirect_to="+encodeURIComponent(window.location.href+"&activate_popup=true&popup_position="+$("input:radio[name='popup-position']:checked").val()))}),$("#li_subscribe_vex_class, #li_subscribe_heading, #li_subscribe_text, #li_subscribe_btn_label, #li_subscribe_name_fields:checkbox, #li_subscribe_phone_field:checkbox").change(function(){var preview_link=$("#wp-admin-bar-view-site a.ab-item").attr("href")+"?preview-subscribe=1";preview_link+="&lis_heading="+$("#li_subscribe_heading").val(),preview_link+="&lis_desc="+$("#li_subscribe_text").val(),preview_link+="&lis_show_names="+($("#li_subscribe_name_fields").is(":checked")?1:0),preview_link+="&lis_show_phone="+($("#li_subscribe_phone_field").is(":checked")?1:0),preview_link+="&lis_btn_label="+$("#li_subscribe_btn_label").val(),preview_link+="&lis_vex_class="+$("#li_subscribe_vex_class option:selected").val(),$("#preview-popup-link").attr("href",preview_link)}),$("#pro-upgrade-button").click(function(e){return e.preventDefault(),$("#agree-pp").is(":checked")?($("#agree-pp-error").hide(),$(this).addClass("btn-submitting").text("Upgrading..."),void $.ajax({type:"POST",url:li_admin_ajax.ajax_url,data:{action:"leadin_upgrade_to_pro"},success:function(redirect_to){redirect_to&&(window.location.href=redirect_to+"&pro_upgrade=1")}})):($("#agree-pp-error").show(),!1)})}),jQuery(document).ready(function($){var $bulk_opt_selected=$('.bulkactions select option[value="add_tag_to_selected"], .bulkactions select option[value="remove_tag_from_selected"], .bulkactions select option[value="delete_selected"]');$("#leadin-contacts input:checkbox").not("thead input:checkbox, tfoot input:checkbox").bind("change",function(){var cb_count=0,selected_vals="",$btn_selected=$("#leadin-export-selected-leads"),$input_selected_vals=$(".leadin-selected-contacts"),$cb_selected=$("#leadin-contacts input:checkbox:checked").not("thead input:checkbox, tfoot input:checkbox");$cb_selected.length>0?($btn_selected.attr("disabled",!1),$bulk_opt_selected.attr("disabled",!1)):($btn_selected.attr("disabled",!0),$bulk_opt_selected.attr("disabled",!0)),$cb_selected.each(function(){selected_vals+=$(this).val(),cb_count!=$cb_selected.length-1&&(selected_vals+=","),cb_count++}),$input_selected_vals.val(selected_vals),$(".selected-contacts-count").text(cb_count)}),$("#cb-select-all-1, #cb-select-all-2").bind("change",function(){var cb_count=0,selected_vals="",$this=$(this),$btn_selected=$("#leadin-export-selected-leads"),$cb_selected=$("#leadin-contacts input:checkbox").not("thead input:checkbox, tfoot input:checkbox"),$input_selected_vals=$(".leadin-selected-contacts");$cb_selected.each(function(){selected_vals+=$(this).val(),cb_count!=$cb_selected.length-1&&(selected_vals+=","),cb_count++}),$input_selected_vals.val(selected_vals),$this.is(":checked")?($btn_selected.attr("disabled",!1),$bulk_opt_selected.attr("disabled",!1)):($btn_selected.attr("disabled",!0),$bulk_opt_selected.attr("disabled",!0),$(".selected-contacts-count").text($("#contact-count").text())),$(".selected-contacts-count").text(cb_count)}),$(".postbox .handlediv").bind("click",function(){var $postbox=$(this).parent();$postbox.hasClass("closed")?$postbox.removeClass("closed"):$postbox.addClass("closed")}),$(".selected-contacts-count").text($("#contact-count").text()),$bulk_opt_selected.attr("disabled",!0),$(".bulkactions select").change(function(){{var $this=$(this);$("#contact-count").text()}"add_tag_to_all"==$this.val()||"add_tag_to_selected"==$this.val()?($("#bulk-edit-tags h2").html($("#bulk-edit-tags h2").html().replace("remove from","add to")),$("#bulk-edit-button").val("Add Tag"),$("#bulk-edit-tag-action").val("add_tag"),tb_show("","#TB_inline?width=400&height=175&inlineId=bulk-edit-tags"),$(".bulkactions select").val("-1")):("remove_tag_from_all"==$this.val()||"remove_tag_from_selected"==$this.val())&&($("#bulk-edit-tags h2").html($("#bulk-edit-tags h2").html().replace("add to","remove from")),$("#bulk-edit-button").val("Remove Tag"),$("#bulk-edit-tag-action").val("remove_tag"),tb_show("","#TB_inline?width=400&height=175&inlineId=bulk-edit-tags"),$(".bulkactions select").val("-1"))}),$("#contact-detail-read-more").click(function(){$("#company-detail-overview-short").hide(),$("#company-detail-overview-full").show()}),$("#contact-detail-read-less").click(function(){$("#company-detail-overview-full").hide(),$("#company-detail-overview-short").show()})}),function($){"undefined"==typeof $.fn.each2&&$.extend($.fn,{each2:function(c){for(var j=$([0]),i=-1,l=this.length;++i<l&&(j.context=j[0]=this[i])&&c.call(j[0],i,j)!==!1;);return this}})}(jQuery),function($,undefined){"use strict";function reinsertElement(element){var placeholder=$(document.createTextNode(""));element.before(placeholder),placeholder.before(element),placeholder.remove()}function stripDiacritics(str){function match(a){return DIACRITICS[a]||a
6
+ }return str.replace(/[^\u0000-\u007E]/g,match)}function indexOf(value,array){for(var i=0,l=array.length;l>i;i+=1)if(equal(value,array[i]))return i;return-1}function measureScrollbar(){var $template=$(MEASURE_SCROLLBAR_TEMPLATE);$template.appendTo("body");var dim={width:$template.width()-$template[0].clientWidth,height:$template.height()-$template[0].clientHeight};return $template.remove(),dim}function equal(a,b){return a===b?!0:a===undefined||b===undefined?!1:null===a||null===b?!1:a.constructor===String?a+""==b+"":b.constructor===String?b+""==a+"":!1}function splitVal(string,separator){var val,i,l;if(null===string||string.length<1)return[];for(val=string.split(separator),i=0,l=val.length;l>i;i+=1)val[i]=$.trim(val[i]);return val}function getSideBorderPadding(element){return element.outerWidth(!1)-element.width()}function installKeyUpChangeEvent(element){var key="keyup-change-value";element.on("keydown",function(){$.data(element,key)===undefined&&$.data(element,key,element.val())}),element.on("keyup",function(){var val=$.data(element,key);val!==undefined&&element.val()!==val&&($.removeData(element,key),element.trigger("keyup-change"))})}function installFilteredMouseMove(element){element.on("mousemove",function(e){var lastpos=lastMousePosition;(lastpos===undefined||lastpos.x!==e.pageX||lastpos.y!==e.pageY)&&$(e.target).trigger("mousemove-filtered",e)})}function debounce(quietMillis,fn,ctx){ctx=ctx||undefined;var timeout;return function(){var args=arguments;window.clearTimeout(timeout),timeout=window.setTimeout(function(){fn.apply(ctx,args)},quietMillis)}}function installDebouncedScroll(threshold,element){var notify=debounce(threshold,function(e){element.trigger("scroll-debounced",e)});element.on("scroll",function(e){indexOf(e.target,element.get())>=0&&notify(e)})}function focus($el){$el[0]!==document.activeElement&&window.setTimeout(function(){var range,el=$el[0],pos=$el.val().length;$el.focus();var isVisible=el.offsetWidth>0||el.offsetHeight>0;isVisible&&el===document.activeElement&&(el.setSelectionRange?el.setSelectionRange(pos,pos):el.createTextRange&&(range=el.createTextRange(),range.collapse(!1),range.select()))},0)}function getCursorInfo(el){el=$(el)[0];var offset=0,length=0;if("selectionStart"in el)offset=el.selectionStart,length=el.selectionEnd-offset;else if("selection"in document){el.focus();var sel=document.selection.createRange();length=document.selection.createRange().text.length,sel.moveStart("character",-el.value.length),offset=sel.text.length-length}return{offset:offset,length:length}}function killEvent(event){event.preventDefault(),event.stopPropagation()}function killEventImmediately(event){event.preventDefault(),event.stopImmediatePropagation()}function measureTextWidth(e){if(!sizer){var style=e[0].currentStyle||window.getComputedStyle(e[0],null);sizer=$(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:style.fontSize,fontFamily:style.fontFamily,fontStyle:style.fontStyle,fontWeight:style.fontWeight,letterSpacing:style.letterSpacing,textTransform:style.textTransform,whiteSpace:"nowrap"}),sizer.attr("class","select2-sizer"),$("body").append(sizer)}return sizer.text(e.val()),sizer.width()}function syncCssClasses(dest,src,adapter){var classes,adapted,replacements=[];classes=dest.attr("class"),classes&&(classes=""+classes,$(classes.split(" ")).each2(function(){0===this.indexOf("select2-")&&replacements.push(this)})),classes=src.attr("class"),classes&&(classes=""+classes,$(classes.split(" ")).each2(function(){0!==this.indexOf("select2-")&&(adapted=adapter(this),adapted&&replacements.push(adapted))})),dest.attr("class",replacements.join(" "))}function markMatch(text,term,markup,escapeMarkup){var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())),tl=term.length;return 0>match?void markup.push(escapeMarkup(text)):(markup.push(escapeMarkup(text.substring(0,match))),markup.push("<span class='select2-match'>"),markup.push(escapeMarkup(text.substring(match,match+tl))),markup.push("</span>"),void markup.push(escapeMarkup(text.substring(match+tl,text.length))))}function defaultEscapeMarkup(markup){var replace_map={"\\":"&#92;","&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#47;"};return String(markup).replace(/[&<>"'\/\\]/g,function(match){return replace_map[match]})}function ajax(options){var timeout,handler=null,quietMillis=options.quietMillis||100,ajaxUrl=options.url,self=this;return function(query){window.clearTimeout(timeout),timeout=window.setTimeout(function(){var data=options.data,url=ajaxUrl,transport=options.transport||$.fn.select2.ajaxDefaults.transport,deprecated={type:options.type||"GET",cache:options.cache||!1,jsonpCallback:options.jsonpCallback||undefined,dataType:options.dataType||"json"},params=$.extend({},$.fn.select2.ajaxDefaults.params,deprecated);data=data?data.call(self,query.term,query.page,query.context):null,url="function"==typeof url?url.call(self,query.term,query.page,query.context):url,handler&&"function"==typeof handler.abort&&handler.abort(),options.params&&($.isFunction(options.params)?$.extend(params,options.params.call(self)):$.extend(params,options.params)),$.extend(params,{url:url,dataType:options.dataType,data:data,success:function(data){var results=options.results(data,query.page);query.callback(results)}}),handler=transport.call(self,params)},quietMillis)}}function local(options){var dataText,tmp,data=options,text=function(item){return""+item.text};$.isArray(data)&&(tmp=data,data={results:tmp}),$.isFunction(data)===!1&&(tmp=data,data=function(){return tmp});var dataItem=data();return dataItem.text&&(text=dataItem.text,$.isFunction(text)||(dataText=dataItem.text,text=function(item){return item[dataText]})),function(query){var process,t=query.term,filtered={results:[]};return""===t?void query.callback(data()):(process=function(datum,collection){var group,attr;if(datum=datum[0],datum.children){group={};for(attr in datum)datum.hasOwnProperty(attr)&&(group[attr]=datum[attr]);group.children=[],$(datum.children).each2(function(i,childDatum){process(childDatum,group.children)}),(group.children.length||query.matcher(t,text(group),datum))&&collection.push(group)}else query.matcher(t,text(datum),datum)&&collection.push(datum)},$(data().results).each2(function(i,datum){process(datum,filtered.results)}),void query.callback(filtered))}}function tags(data){var isFunc=$.isFunction(data);return function(query){var t=query.term,filtered={results:[]},result=isFunc?data(query):data;$.isArray(result)&&($(result).each(function(){var isObject=this.text!==undefined,text=isObject?this.text:this;(""===t||query.matcher(t,text))&&filtered.results.push(isObject?this:{id:this,text:this})}),query.callback(filtered))}}function checkFormatter(formatter,formatterName){if($.isFunction(formatter))return!0;if(!formatter)return!1;if("string"==typeof formatter)return!0;throw new Error(formatterName+" must be a string, function, or falsy value")}function evaluate(val){if($.isFunction(val)){var args=Array.prototype.slice.call(arguments,1);return val.apply(null,args)}return val}function countResults(results){var count=0;return $.each(results,function(i,item){item.children?count+=countResults(item.children):count++}),count}function defaultTokenizer(input,selection,selectCallback,opts){var token,index,i,l,separator,original=input,dupe=!1;if(!opts.createSearchChoice||!opts.tokenSeparators||opts.tokenSeparators.length<1)return undefined;for(;;){for(index=-1,i=0,l=opts.tokenSeparators.length;l>i&&(separator=opts.tokenSeparators[i],index=input.indexOf(separator),!(index>=0));i++);if(0>index)break;if(token=input.substring(0,index),input=input.substring(index+separator.length),token.length>0&&(token=opts.createSearchChoice.call(this,token,selection),token!==undefined&&null!==token&&opts.id(token)!==undefined&&null!==opts.id(token))){for(dupe=!1,i=0,l=selection.length;l>i;i++)if(equal(opts.id(token),opts.id(selection[i]))){dupe=!0;break}dupe||selectCallback(token)}}return original!==input?input:void 0}function cleanupJQueryElements(){var self=this;Array.prototype.forEach.call(arguments,function(element){self[element].remove(),self[element]=null})}function clazz(SuperClass,methods){var constructor=function(){};return constructor.prototype=new SuperClass,constructor.prototype.constructor=constructor,constructor.prototype.parent=SuperClass.prototype,constructor.prototype=$.extend(constructor.prototype,methods),constructor}if(window.Select2===undefined){var KEY,AbstractSelect2,SingleSelect2,MultiSelect2,nextUid,sizer,$document,scrollBarDimensions,lastMousePosition={x:0,y:0},KEY={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(k){switch(k=k.which?k.which:k){case KEY.LEFT:case KEY.RIGHT:case KEY.UP:case KEY.DOWN:return!0}return!1},isControl:function(e){var k=e.which;switch(k){case KEY.SHIFT:case KEY.CTRL:case KEY.ALT:return!0}return e.metaKey?!0:!1},isFunctionKey:function(k){return k=k.which?k.which:k,k>=112&&123>=k}},MEASURE_SCROLLBAR_TEMPLATE="<div class='select2-measure-scrollbar'></div>",DIACRITICS={"Ⓐ":"A","A":"A","À":"A","Á":"A","Â":"A","Ầ":"A","Ấ":"A","Ẫ":"A","Ẩ":"A","Ã":"A","Ā":"A","Ă":"A","Ằ":"A","Ắ":"A","Ẵ":"A","Ẳ":"A","Ȧ":"A","Ǡ":"A","Ä":"A","Ǟ":"A","Ả":"A","Å":"A","Ǻ":"A","Ǎ":"A","Ȁ":"A","Ȃ":"A","Ạ":"A","Ậ":"A","Ặ":"A","Ḁ":"A","Ą":"A","Ⱥ":"A","Ɐ":"A","Ꜳ":"AA","Æ":"AE","Ǽ":"AE","Ǣ":"AE","Ꜵ":"AO","Ꜷ":"AU","Ꜹ":"AV","Ꜻ":"AV","Ꜽ":"AY","Ⓑ":"B","B":"B","Ḃ":"B","Ḅ":"B","Ḇ":"B","Ƀ":"B","Ƃ":"B","Ɓ":"B","Ⓒ":"C","C":"C","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","Ç":"C","Ḉ":"C","Ƈ":"C","Ȼ":"C","Ꜿ":"C","Ⓓ":"D","D":"D","Ḋ":"D","Ď":"D","Ḍ":"D","Ḑ":"D","Ḓ":"D","Ḏ":"D","Đ":"D","Ƌ":"D","Ɗ":"D","Ɖ":"D","Ꝺ":"D","DZ":"DZ","DŽ":"DZ","Dz":"Dz","Dž":"Dz","Ⓔ":"E","E":"E","È":"E","É":"E","Ê":"E","Ề":"E","Ế":"E","Ễ":"E","Ể":"E","Ẽ":"E","Ē":"E","Ḕ":"E","Ḗ":"E","Ĕ":"E","Ė":"E","Ë":"E","Ẻ":"E","Ě":"E","Ȅ":"E","Ȇ":"E","Ẹ":"E","Ệ":"E","Ȩ":"E","Ḝ":"E","Ę":"E","Ḙ":"E","Ḛ":"E","Ɛ":"E","Ǝ":"E","Ⓕ":"F","F":"F","Ḟ":"F","Ƒ":"F","Ꝼ":"F","Ⓖ":"G","G":"G","Ǵ":"G","Ĝ":"G","Ḡ":"G","Ğ":"G","Ġ":"G","Ǧ":"G","Ģ":"G","Ǥ":"G","Ɠ":"G","Ꞡ":"G","Ᵹ":"G","Ꝿ":"G","Ⓗ":"H","H":"H","Ĥ":"H","Ḣ":"H","Ḧ":"H","Ȟ":"H","Ḥ":"H","Ḩ":"H","Ḫ":"H","Ħ":"H","Ⱨ":"H","Ⱶ":"H","Ɥ":"H","Ⓘ":"I","I":"I","Ì":"I","Í":"I","Î":"I","Ĩ":"I","Ī":"I","Ĭ":"I","İ":"I","Ï":"I","Ḯ":"I","Ỉ":"I","Ǐ":"I","Ȉ":"I","Ȋ":"I","Ị":"I","Į":"I","Ḭ":"I","Ɨ":"I","Ⓙ":"J","J":"J","Ĵ":"J","Ɉ":"J","Ⓚ":"K","K":"K","Ḱ":"K","Ǩ":"K","Ḳ":"K","Ķ":"K","Ḵ":"K","Ƙ":"K","Ⱪ":"K","Ꝁ":"K","Ꝃ":"K","Ꝅ":"K","Ꞣ":"K","Ⓛ":"L","L":"L","Ŀ":"L","Ĺ":"L","Ľ":"L","Ḷ":"L","Ḹ":"L","Ļ":"L","Ḽ":"L","Ḻ":"L","Ł":"L","Ƚ":"L","Ɫ":"L","Ⱡ":"L","Ꝉ":"L","Ꝇ":"L","Ꞁ":"L","LJ":"LJ","Lj":"Lj","Ⓜ":"M","M":"M","Ḿ":"M","Ṁ":"M","Ṃ":"M","Ɱ":"M","Ɯ":"M","Ⓝ":"N","N":"N","Ǹ":"N","Ń":"N","Ñ":"N","Ṅ":"N","Ň":"N","Ṇ":"N","Ņ":"N","Ṋ":"N","Ṉ":"N","Ƞ":"N","Ɲ":"N","Ꞑ":"N","Ꞥ":"N","NJ":"NJ","Nj":"Nj","Ⓞ":"O","O":"O","Ò":"O","Ó":"O","Ô":"O","Ồ":"O","Ố":"O","Ỗ":"O","Ổ":"O","Õ":"O","Ṍ":"O","Ȭ":"O","Ṏ":"O","Ō":"O","Ṑ":"O","Ṓ":"O","Ŏ":"O","Ȯ":"O","Ȱ":"O","Ö":"O","Ȫ":"O","Ỏ":"O","Ő":"O","Ǒ":"O","Ȍ":"O","Ȏ":"O","Ơ":"O","Ờ":"O","Ớ":"O","Ỡ":"O","Ở":"O","Ợ":"O","Ọ":"O","Ộ":"O","Ǫ":"O","Ǭ":"O","Ø":"O","Ǿ":"O","Ɔ":"O","Ɵ":"O","Ꝋ":"O","Ꝍ":"O","Ƣ":"OI","Ꝏ":"OO","Ȣ":"OU","Ⓟ":"P","P":"P","Ṕ":"P","Ṗ":"P","Ƥ":"P","Ᵽ":"P","Ꝑ":"P","Ꝓ":"P","Ꝕ":"P","Ⓠ":"Q","Q":"Q","Ꝗ":"Q","Ꝙ":"Q","Ɋ":"Q","Ⓡ":"R","R":"R","Ŕ":"R","Ṙ":"R","Ř":"R","Ȑ":"R","Ȓ":"R","Ṛ":"R","Ṝ":"R","Ŗ":"R","Ṟ":"R","Ɍ":"R","Ɽ":"R","Ꝛ":"R","Ꞧ":"R","Ꞃ":"R","Ⓢ":"S","S":"S","ẞ":"S","Ś":"S","Ṥ":"S","Ŝ":"S","Ṡ":"S","Š":"S","Ṧ":"S","Ṣ":"S","Ṩ":"S","Ș":"S","Ş":"S","Ȿ":"S","Ꞩ":"S","Ꞅ":"S","Ⓣ":"T","T":"T","Ṫ":"T","Ť":"T","Ṭ":"T","Ț":"T","Ţ":"T","Ṱ":"T","Ṯ":"T","Ŧ":"T","Ƭ":"T","Ʈ":"T","Ⱦ":"T","Ꞇ":"T","Ꜩ":"TZ","Ⓤ":"U","U":"U","Ù":"U","Ú":"U","Û":"U","Ũ":"U","Ṹ":"U","Ū":"U","Ṻ":"U","Ŭ":"U","Ü":"U","Ǜ":"U","Ǘ":"U","Ǖ":"U","Ǚ":"U","Ủ":"U","Ů":"U","Ű":"U","Ǔ":"U","Ȕ":"U","Ȗ":"U","Ư":"U","Ừ":"U","Ứ":"U","Ữ":"U","Ử":"U","Ự":"U","Ụ":"U","Ṳ":"U","Ų":"U","Ṷ":"U","Ṵ":"U","Ʉ":"U","Ⓥ":"V","V":"V","Ṽ":"V","Ṿ":"V","Ʋ":"V","Ꝟ":"V","Ʌ":"V","Ꝡ":"VY","Ⓦ":"W","W":"W","Ẁ":"W","Ẃ":"W","Ŵ":"W","Ẇ":"W","Ẅ":"W","Ẉ":"W","Ⱳ":"W","Ⓧ":"X","X":"X","Ẋ":"X","Ẍ":"X","Ⓨ":"Y","Y":"Y","Ỳ":"Y","Ý":"Y","Ŷ":"Y","Ỹ":"Y","Ȳ":"Y","Ẏ":"Y","Ÿ":"Y","Ỷ":"Y","Ỵ":"Y","Ƴ":"Y","Ɏ":"Y","Ỿ":"Y","Ⓩ":"Z","Z":"Z","Ź":"Z","Ẑ":"Z","Ż":"Z","Ž":"Z","Ẓ":"Z","Ẕ":"Z","Ƶ":"Z","Ȥ":"Z","Ɀ":"Z","Ⱬ":"Z","Ꝣ":"Z","ⓐ":"a","a":"a","ẚ":"a","à":"a","á":"a","â":"a","ầ":"a","ấ":"a","ẫ":"a","ẩ":"a","ã":"a","ā":"a","ă":"a","ằ":"a","ắ":"a","ẵ":"a","ẳ":"a","ȧ":"a","ǡ":"a","ä":"a","ǟ":"a","ả":"a","å":"a","ǻ":"a","ǎ":"a","ȁ":"a","ȃ":"a","ạ":"a","ậ":"a","ặ":"a","ḁ":"a","ą":"a","ⱥ":"a","ɐ":"a","ꜳ":"aa","æ":"ae","ǽ":"ae","ǣ":"ae","ꜵ":"ao","ꜷ":"au","ꜹ":"av","ꜻ":"av","ꜽ":"ay","ⓑ":"b","b":"b","ḃ":"b","ḅ":"b","ḇ":"b","ƀ":"b","ƃ":"b","ɓ":"b","ⓒ":"c","c":"c","ć":"c","ĉ":"c","ċ":"c","č":"c","ç":"c","ḉ":"c","ƈ":"c","ȼ":"c","ꜿ":"c","ↄ":"c","ⓓ":"d","d":"d","ḋ":"d","ď":"d","ḍ":"d","ḑ":"d","ḓ":"d","ḏ":"d","đ":"d","ƌ":"d","ɖ":"d","ɗ":"d","ꝺ":"d","dz":"dz","dž":"dz","ⓔ":"e","e":"e","è":"e","é":"e","ê":"e","ề":"e","ế":"e","ễ":"e","ể":"e","ẽ":"e","ē":"e","ḕ":"e","ḗ":"e","ĕ":"e","ė":"e","ë":"e","ẻ":"e","ě":"e","ȅ":"e","ȇ":"e","ẹ":"e","ệ":"e","ȩ":"e","ḝ":"e","ę":"e","ḙ":"e","ḛ":"e","ɇ":"e","ɛ":"e","ǝ":"e","ⓕ":"f","f":"f","ḟ":"f","ƒ":"f","ꝼ":"f","ⓖ":"g","g":"g","ǵ":"g","ĝ":"g","ḡ":"g","ğ":"g","ġ":"g","ǧ":"g","ģ":"g","ǥ":"g","ɠ":"g","ꞡ":"g","ᵹ":"g","ꝿ":"g","ⓗ":"h","h":"h","ĥ":"h","ḣ":"h","ḧ":"h","ȟ":"h","ḥ":"h","ḩ":"h","ḫ":"h","ẖ":"h","ħ":"h","ⱨ":"h","ⱶ":"h","ɥ":"h","ƕ":"hv","ⓘ":"i","i":"i","ì":"i","í":"i","î":"i","ĩ":"i","ī":"i","ĭ":"i","ï":"i","ḯ":"i","ỉ":"i","ǐ":"i","ȉ":"i","ȋ":"i","ị":"i","į":"i","ḭ":"i","ɨ":"i","ı":"i","ⓙ":"j","j":"j","ĵ":"j","ǰ":"j","ɉ":"j","ⓚ":"k","k":"k","ḱ":"k","ǩ":"k","ḳ":"k","ķ":"k","ḵ":"k","ƙ":"k","ⱪ":"k","ꝁ":"k","ꝃ":"k","ꝅ":"k","ꞣ":"k","ⓛ":"l","l":"l","ŀ":"l","ĺ":"l","ľ":"l","ḷ":"l","ḹ":"l","ļ":"l","ḽ":"l","ḻ":"l","ſ":"l","ł":"l","ƚ":"l","ɫ":"l","ⱡ":"l","ꝉ":"l","ꞁ":"l","ꝇ":"l","lj":"lj","ⓜ":"m","m":"m","ḿ":"m","ṁ":"m","ṃ":"m","ɱ":"m","ɯ":"m","ⓝ":"n","n":"n","ǹ":"n","ń":"n","ñ":"n","ṅ":"n","ň":"n","ṇ":"n","ņ":"n","ṋ":"n","ṉ":"n","ƞ":"n","ɲ":"n","ʼn":"n","ꞑ":"n","ꞥ":"n","nj":"nj","ⓞ":"o","o":"o","ò":"o","ó":"o","ô":"o","ồ":"o","ố":"o","ỗ":"o","ổ":"o","õ":"o","ṍ":"o","ȭ":"o","ṏ":"o","ō":"o","ṑ":"o","ṓ":"o","ŏ":"o","ȯ":"o","ȱ":"o","ö":"o","ȫ":"o","ỏ":"o","ő":"o","ǒ":"o","ȍ":"o","ȏ":"o","ơ":"o","ờ":"o","ớ":"o","ỡ":"o","ở":"o","ợ":"o","ọ":"o","ộ":"o","ǫ":"o","ǭ":"o","ø":"o","ǿ":"o","ɔ":"o","ꝋ":"o","ꝍ":"o","ɵ":"o","ƣ":"oi","ȣ":"ou","ꝏ":"oo","ⓟ":"p","p":"p","ṕ":"p","ṗ":"p","ƥ":"p","ᵽ":"p","ꝑ":"p","ꝓ":"p","ꝕ":"p","ⓠ":"q","q":"q","ɋ":"q","ꝗ":"q","ꝙ":"q","ⓡ":"r","r":"r","ŕ":"r","ṙ":"r","ř":"r","ȑ":"r","ȓ":"r","ṛ":"r","ṝ":"r","ŗ":"r","ṟ":"r","ɍ":"r","ɽ":"r","ꝛ":"r","ꞧ":"r","ꞃ":"r","ⓢ":"s","s":"s","ß":"s","ś":"s","ṥ":"s","ŝ":"s","ṡ":"s","š":"s","ṧ":"s","ṣ":"s","ṩ":"s","ș":"s","ş":"s","ȿ":"s","ꞩ":"s","ꞅ":"s","ẛ":"s","ⓣ":"t","t":"t","ṫ":"t","ẗ":"t","ť":"t","ṭ":"t","ț":"t","ţ":"t","ṱ":"t","ṯ":"t","ŧ":"t","ƭ":"t","ʈ":"t","ⱦ":"t","ꞇ":"t","ꜩ":"tz","ⓤ":"u","u":"u","ù":"u","ú":"u","û":"u","ũ":"u","ṹ":"u","ū":"u","ṻ":"u","ŭ":"u","ü":"u","ǜ":"u","ǘ":"u","ǖ":"u","ǚ":"u","ủ":"u","ů":"u","ű":"u","ǔ":"u","ȕ":"u","ȗ":"u","ư":"u","ừ":"u","ứ":"u","ữ":"u","ử":"u","ự":"u","ụ":"u","ṳ":"u","ų":"u","ṷ":"u","ṵ":"u","ʉ":"u","ⓥ":"v","v":"v","ṽ":"v","ṿ":"v","ʋ":"v","ꝟ":"v","ʌ":"v","ꝡ":"vy","ⓦ":"w","w":"w","ẁ":"w","ẃ":"w","ŵ":"w","ẇ":"w","ẅ":"w","ẘ":"w","ẉ":"w","ⱳ":"w","ⓧ":"x","x":"x","ẋ":"x","ẍ":"x","ⓨ":"y","y":"y","ỳ":"y","ý":"y","ŷ":"y","ỹ":"y","ȳ":"y","ẏ":"y","ÿ":"y","ỷ":"y","ẙ":"y","ỵ":"y","ƴ":"y","ɏ":"y","ỿ":"y","ⓩ":"z","z":"z","ź":"z","ẑ":"z","ż":"z","ž":"z","ẓ":"z","ẕ":"z","ƶ":"z","ȥ":"z","ɀ":"z","ⱬ":"z","ꝣ":"z"};$document=$(document),nextUid=function(){var counter=1;return function(){return counter++}}(),$document.on("mousemove",function(e){lastMousePosition.x=e.pageX,lastMousePosition.y=e.pageY}),AbstractSelect2=clazz(Object,{bind:function(func){var self=this;return function(){func.apply(self,arguments)}},init:function(opts){var results,search,resultsSelector=".select2-results";this.opts=opts=this.prepareOpts(opts),this.id=opts.id,opts.element.data("select2")!==undefined&&null!==opts.element.data("select2")&&opts.element.data("select2").destroy(),this.container=this.createContainer(),this.liveRegion=$("<span>",{role:"status","aria-live":"polite"}).addClass("select2-hidden-accessible").appendTo(document.body),this.containerId="s2id_"+(opts.element.attr("id")||"autogen"+nextUid()),this.containerEventName=this.containerId.replace(/([.])/g,"_").replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.container.attr("id",this.containerId),this.container.attr("title",opts.element.attr("title")),this.body=$("body"),syncCssClasses(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",opts.element.attr("style")),this.container.css(evaluate(opts.containerCss)),this.container.addClass(evaluate(opts.containerCssClass)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",killEvent),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),syncCssClasses(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(evaluate(opts.dropdownCssClass)),this.dropdown.data("select2",this),this.dropdown.on("click",killEvent),this.results=results=this.container.find(resultsSelector),this.search=search=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",killEvent),installFilteredMouseMove(this.results),this.dropdown.on("mousemove-filtered",resultsSelector,this.bind(this.highlightUnderEvent)),this.dropdown.on("touchstart touchmove touchend",resultsSelector,this.bind(function(event){this._touchEvent=!0,this.highlightUnderEvent(event)})),this.dropdown.on("touchmove",resultsSelector,this.bind(this.touchMoved)),this.dropdown.on("touchstart touchend",resultsSelector,this.bind(this.clearTouchMoved)),this.dropdown.on("click",this.bind(function(){this._touchEvent&&(this._touchEvent=!1,this.selectHighlighted())})),installDebouncedScroll(80,this.results),this.dropdown.on("scroll-debounced",resultsSelector,this.bind(this.loadMoreIfNeeded)),$(this.container).on("change",".select2-input",function(e){e.stopPropagation()}),$(this.dropdown).on("change",".select2-input",function(e){e.stopPropagation()}),$.fn.mousewheel&&results.mousewheel(function(e,delta,deltaX,deltaY){var top=results.scrollTop();deltaY>0&&0>=top-deltaY?(results.scrollTop(0),killEvent(e)):0>deltaY&&results.get(0).scrollHeight-results.scrollTop()+deltaY<=results.height()&&(results.scrollTop(results.get(0).scrollHeight-results.height()),killEvent(e))}),installKeyUpChangeEvent(search),search.on("keyup-change input paste",this.bind(this.updateResults)),search.on("focus",function(){search.addClass("select2-focused")}),search.on("blur",function(){search.removeClass("select2-focused")}),this.dropdown.on("mouseup",resultsSelector,this.bind(function(e){$(e.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(e),this.selectHighlighted(e))})),this.dropdown.on("click mouseup mousedown touchstart touchend focusin",function(e){e.stopPropagation()}),this.nextSearchTerm=undefined,$.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==opts.maximumInputLength&&this.search.attr("maxlength",opts.maximumInputLength);var disabled=opts.element.prop("disabled");disabled===undefined&&(disabled=!1),this.enable(!disabled);var readonly=opts.element.prop("readonly");readonly===undefined&&(readonly=!1),this.readonly(readonly),scrollBarDimensions=scrollBarDimensions||measureScrollbar(),this.autofocus=opts.element.prop("autofocus"),opts.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.search.attr("placeholder",opts.searchInputPlaceholder)},destroy:function(){var element=this.opts.element,select2=element.data("select2");this.close(),this.propertyObserver&&(this.propertyObserver.disconnect(),this.propertyObserver=null),select2!==undefined&&(select2.container.remove(),select2.liveRegion.remove(),select2.dropdown.remove(),element.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||!1),this.elementTabIndex?element.attr({tabindex:this.elementTabIndex}):element.removeAttr("tabindex"),element.show()),cleanupJQueryElements.call(this,"container","liveRegion","dropdown","results","search")},optionToData:function(element){return element.is("option")?{id:element.prop("value"),text:element.text(),element:element.get(),css:element.attr("class"),disabled:element.prop("disabled"),locked:equal(element.attr("locked"),"locked")||equal(element.data("locked"),!0)}:element.is("optgroup")?{text:element.attr("label"),children:[],element:element.get(),css:element.attr("class")}:void 0},prepareOpts:function(opts){var element,select,idKey,ajaxUrl,self=this;if(element=opts.element,"select"===element.get(0).tagName.toLowerCase()&&(this.select=select=opts.element),select&&$.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in opts)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a <select> element.")}),opts=$.extend({},{populateResults:function(container,results,query){var populate,id=this.opts.id,liveRegion=this.liveRegion;(populate=function(results,container,depth){var i,l,result,selectable,disabled,compound,node,label,innerContainer,formatted;for(results=opts.sortResults(results,container,query),i=0,l=results.length;l>i;i+=1)result=results[i],disabled=result.disabled===!0,selectable=!disabled&&id(result)!==undefined,compound=result.children&&result.children.length>0,node=$("<li></li>"),node.addClass("select2-results-dept-"+depth),node.addClass("select2-result"),node.addClass(selectable?"select2-result-selectable":"select2-result-unselectable"),disabled&&node.addClass("select2-disabled"),compound&&node.addClass("select2-result-with-children"),node.addClass(self.opts.formatResultCssClass(result)),node.attr("role","presentation"),label=$(document.createElement("div")),label.addClass("select2-result-label"),label.attr("id","select2-result-label-"+nextUid()),label.attr("role","option"),formatted=opts.formatResult(result,label,query,self.opts.escapeMarkup),formatted!==undefined&&(label.html(formatted),node.append(label)),compound&&(innerContainer=$("<ul></ul>"),innerContainer.addClass("select2-result-sub"),populate(result.children,innerContainer,depth+1),node.append(innerContainer)),node.data("select2-data",result),container.append(node);liveRegion.text(opts.formatMatches(results.length))})(results,container,0)}},$.fn.select2.defaults,opts),"function"!=typeof opts.id&&(idKey=opts.id,opts.id=function(e){return e[idKey]}),$.isArray(opts.element.data("select2Tags"))){if("tags"in opts)throw"tags specified as both an attribute 'data-select2-tags' and in options of Select2 "+opts.element.attr("id");opts.tags=opts.element.data("select2Tags")}if(select?(opts.query=this.bind(function(query){var children,placeholderOption,process,data={results:[],more:!1},term=query.term;process=function(element,collection){var group;element.is("option")?query.matcher(term,element.text(),element)&&collection.push(self.optionToData(element)):element.is("optgroup")&&(group=self.optionToData(element),element.children().each2(function(i,elm){process(elm,group.children)}),group.children.length>0&&collection.push(group))},children=element.children(),this.getPlaceholder()!==undefined&&children.length>0&&(placeholderOption=this.getPlaceholderOption(),placeholderOption&&(children=children.not(placeholderOption))),children.each2(function(i,elm){process(elm,data.results)}),query.callback(data)}),opts.id=function(e){return e.id}):"query"in opts||("ajax"in opts?(ajaxUrl=opts.element.data("ajax-url"),ajaxUrl&&ajaxUrl.length>0&&(opts.ajax.url=ajaxUrl),opts.query=ajax.call(opts.element,opts.ajax)):"data"in opts?opts.query=local(opts.data):"tags"in opts&&(opts.query=tags(opts.tags),opts.createSearchChoice===undefined&&(opts.createSearchChoice=function(term){return{id:$.trim(term),text:$.trim(term)}}),opts.initSelection===undefined&&(opts.initSelection=function(element,callback){var data=[];$(splitVal(element.val(),opts.separator)).each(function(){var obj={id:this,text:this},tags=opts.tags;$.isFunction(tags)&&(tags=tags()),$(tags).each(function(){return equal(this.id,obj.id)?(obj=this,!1):void 0}),data.push(obj)}),callback(data)}))),"function"!=typeof opts.query)throw"query function not defined for Select2 "+opts.element.attr("id");if("top"===opts.createSearchChoicePosition)opts.createSearchChoicePosition=function(list,item){list.unshift(item)};else if("bottom"===opts.createSearchChoicePosition)opts.createSearchChoicePosition=function(list,item){list.push(item)};else if("function"!=typeof opts.createSearchChoicePosition)throw"invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function";return opts},monitorSource:function(){var sync,observer,el=this.opts.element;el.on("change.select2",this.bind(function(){this.opts.element.data("select2-change-triggered")!==!0&&this.initSelection()})),sync=this.bind(function(){var disabled=el.prop("disabled");disabled===undefined&&(disabled=!1),this.enable(!disabled);var readonly=el.prop("readonly");readonly===undefined&&(readonly=!1),this.readonly(readonly),syncCssClasses(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.addClass(evaluate(this.opts.containerCssClass)),syncCssClasses(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(evaluate(this.opts.dropdownCssClass))}),el.length&&el[0].attachEvent&&el.each(function(){this.attachEvent("onpropertychange",sync)}),observer=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,observer!==undefined&&(this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),this.propertyObserver=new observer(function(mutations){mutations.forEach(sync)}),this.propertyObserver.observe(el.get(0),{attributes:!0,subtree:!1}))},triggerSelect:function(data){var evt=$.Event("select2-selecting",{val:this.id(data),object:data});return this.opts.element.trigger(evt),!evt.isDefaultPrevented()},triggerChange:function(details){details=details||{},details=$.extend({},details,{type:"change",val:this.val()}),this.opts.element.data("select2-change-triggered",!0),this.opts.element.trigger(details),this.opts.element.data("select2-change-triggered",!1),this.opts.element.click(),this.opts.blurOnChange&&this.opts.element.blur()},isInterfaceEnabled:function(){return this.enabledInterface===!0},enableInterface:function(){var enabled=this._enabled&&!this._readonly,disabled=!enabled;return enabled===this.enabledInterface?!1:(this.container.toggleClass("select2-container-disabled",disabled),this.close(),this.enabledInterface=enabled,!0)},enable:function(enabled){enabled===undefined&&(enabled=!0),this._enabled!==enabled&&(this._enabled=enabled,this.opts.element.prop("disabled",!enabled),this.enableInterface())},disable:function(){this.enable(!1)},readonly:function(enabled){enabled===undefined&&(enabled=!1),this._readonly!==enabled&&(this._readonly=enabled,this.opts.element.prop("readonly",enabled),this.enableInterface())},opened:function(){return this.container.hasClass("select2-dropdown-open")},positionDropdown:function(){var bodyOffset,above,changeDirection,css,resultsListNode,$dropdown=this.dropdown,offset=this.container.offset(),height=this.container.outerHeight(!1),width=this.container.outerWidth(!1),dropHeight=$dropdown.outerHeight(!1),$window=$(window),windowWidth=$window.width(),windowHeight=$window.height(),viewPortRight=$window.scrollLeft()+windowWidth,viewportBottom=$window.scrollTop()+windowHeight,dropTop=offset.top+height,dropLeft=offset.left,enoughRoomBelow=viewportBottom>=dropTop+dropHeight,enoughRoomAbove=offset.top-dropHeight>=$window.scrollTop(),dropWidth=$dropdown.outerWidth(!1),enoughRoomOnRight=viewPortRight>=dropLeft+dropWidth,aboveNow=$dropdown.hasClass("select2-drop-above");aboveNow?(above=!0,!enoughRoomAbove&&enoughRoomBelow&&(changeDirection=!0,above=!1)):(above=!1,!enoughRoomBelow&&enoughRoomAbove&&(changeDirection=!0,above=!0)),changeDirection&&($dropdown.hide(),offset=this.container.offset(),height=this.container.outerHeight(!1),width=this.container.outerWidth(!1),dropHeight=$dropdown.outerHeight(!1),viewPortRight=$window.scrollLeft()+windowWidth,viewportBottom=$window.scrollTop()+windowHeight,dropTop=offset.top+height,dropLeft=offset.left,dropWidth=$dropdown.outerWidth(!1),enoughRoomOnRight=viewPortRight>=dropLeft+dropWidth,$dropdown.show(),this.focusSearch()),this.opts.dropdownAutoWidth?(resultsListNode=$(".select2-results",$dropdown)[0],$dropdown.addClass("select2-drop-auto-width"),$dropdown.css("width",""),dropWidth=$dropdown.outerWidth(!1)+(resultsListNode.scrollHeight===resultsListNode.clientHeight?0:scrollBarDimensions.width),dropWidth>width?width=dropWidth:dropWidth=width,dropHeight=$dropdown.outerHeight(!1),enoughRoomOnRight=viewPortRight>=dropLeft+dropWidth):this.container.removeClass("select2-drop-auto-width"),"static"!==this.body.css("position")&&(bodyOffset=this.body.offset(),dropTop-=bodyOffset.top,dropLeft-=bodyOffset.left),enoughRoomOnRight||(dropLeft=offset.left+this.container.outerWidth(!1)-dropWidth),css={left:dropLeft,width:width},above?(css.top=offset.top-dropHeight,css.bottom="auto",this.container.addClass("select2-drop-above"),$dropdown.addClass("select2-drop-above")):(css.top=dropTop,css.bottom="auto",this.container.removeClass("select2-drop-above"),$dropdown.removeClass("select2-drop-above")),css=$.extend(css,evaluate(this.opts.dropdownCss)),$dropdown.css(css)},shouldOpen:function(){var event;return this.opened()?!1:this._enabled===!1||this._readonly===!0?!1:(event=$.Event("select2-opening"),this.opts.element.trigger(event),!event.isDefaultPrevented())},clearDropdownAlignmentPreference:function(){this.container.removeClass("select2-drop-above"),this.dropdown.removeClass("select2-drop-above")},open:function(){return this.shouldOpen()?(this.opening(),!0):!1},opening:function(){var mask,cid=this.containerEventName,scroll="scroll."+cid,resize="resize."+cid,orient="orientationchange."+cid;this.container.addClass("select2-dropdown-open").addClass("select2-container-active"),this.clearDropdownAlignmentPreference(),this.dropdown[0]!==this.body.children().last()[0]&&this.dropdown.detach().appendTo(this.body),mask=$("#select2-drop-mask"),0==mask.length&&(mask=$(document.createElement("div")),mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask"),mask.hide(),mask.appendTo(this.body),mask.on("mousedown touchstart click",function(e){reinsertElement(mask);var self,dropdown=$("#select2-drop");dropdown.length>0&&(self=dropdown.data("select2"),self.opts.selectOnBlur&&self.selectHighlighted({noFocus:!0}),self.close(),e.preventDefault(),e.stopPropagation())})),this.dropdown.prev()[0]!==mask[0]&&this.dropdown.before(mask),$("#select2-drop").removeAttr("id"),this.dropdown.attr("id","select2-drop"),mask.show(),this.positionDropdown(),this.dropdown.show(),this.positionDropdown(),this.dropdown.addClass("select2-drop-active");var that=this;this.container.parents().add(window).each(function(){$(this).on(resize+" "+scroll+" "+orient,function(){that.opened()&&that.positionDropdown()})})},close:function(){if(this.opened()){var cid=this.containerEventName,scroll="scroll."+cid,resize="resize."+cid,orient="orientationchange."+cid;this.container.parents().add(window).each(function(){$(this).off(scroll).off(resize).off(orient)}),this.clearDropdownAlignmentPreference(),$("#select2-drop-mask").hide(),this.dropdown.removeAttr("id"),this.dropdown.hide(),this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active"),this.results.empty(),this.clearSearch(),this.search.removeClass("select2-active"),this.opts.element.trigger($.Event("select2-close"))
7
+ }},externalSearch:function(term){this.open(),this.search.val(term),this.updateResults(!1)},clearSearch:function(){},getMaximumSelectionSize:function(){return evaluate(this.opts.maximumSelectionSize)},ensureHighlightVisible:function(){var children,index,child,hb,rb,y,more,results=this.results;if(index=this.highlight(),!(0>index)){if(0==index)return void results.scrollTop(0);children=this.findHighlightableChoices().find(".select2-result-label"),child=$(children[index]),hb=child.offset().top+child.outerHeight(!0),index===children.length-1&&(more=results.find("li.select2-more-results"),more.length>0&&(hb=more.offset().top+more.outerHeight(!0))),rb=results.offset().top+results.outerHeight(!0),hb>rb&&results.scrollTop(results.scrollTop()+(hb-rb)),y=child.offset().top-results.offset().top,0>y&&"none"!=child.css("display")&&results.scrollTop(results.scrollTop()+y)}},findHighlightableChoices:function(){return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)")},moveHighlight:function(delta){for(var choices=this.findHighlightableChoices(),index=this.highlight();index>-1&&index<choices.length;){index+=delta;var choice=$(choices[index]);if(choice.hasClass("select2-result-selectable")&&!choice.hasClass("select2-disabled")&&!choice.hasClass("select2-selected")){this.highlight(index);break}}},highlight:function(index){var choice,data,choices=this.findHighlightableChoices();return 0===arguments.length?indexOf(choices.filter(".select2-highlighted")[0],choices.get()):(index>=choices.length&&(index=choices.length-1),0>index&&(index=0),this.removeHighlight(),choice=$(choices[index]),choice.addClass("select2-highlighted"),this.search.attr("aria-activedescendant",choice.find(".select2-result-label").attr("id")),this.ensureHighlightVisible(),this.liveRegion.text(choice.text()),data=choice.data("select2-data"),void(data&&this.opts.element.trigger({type:"select2-highlight",val:this.id(data),choice:data})))},removeHighlight:function(){this.results.find(".select2-highlighted").removeClass("select2-highlighted")},touchMoved:function(){this._touchMoved=!0},clearTouchMoved:function(){this._touchMoved=!1},countSelectableResults:function(){return this.findHighlightableChoices().length},highlightUnderEvent:function(event){var el=$(event.target).closest(".select2-result-selectable");if(el.length>0&&!el.is(".select2-highlighted")){var choices=this.findHighlightableChoices();this.highlight(choices.index(el))}else 0==el.length&&this.removeHighlight()},loadMoreIfNeeded:function(){var below,results=this.results,more=results.find("li.select2-more-results"),page=this.resultsPage+1,self=this,term=this.search.val(),context=this.context;0!==more.length&&(below=more.offset().top-results.offset().top-results.height(),below<=this.opts.loadMorePadding&&(more.addClass("select2-active"),this.opts.query({element:this.opts.element,term:term,page:page,context:context,matcher:this.opts.matcher,callback:this.bind(function(data){self.opened()&&(self.opts.populateResults.call(this,results,data.results,{term:term,page:page,context:context}),self.postprocessResults(data,!1,!1),data.more===!0?(more.detach().appendTo(results).text(evaluate(self.opts.formatLoadMore,page+1)),window.setTimeout(function(){self.loadMoreIfNeeded()},10)):more.remove(),self.positionDropdown(),self.resultsPage=page,self.context=data.context,this.opts.element.trigger({type:"select2-loaded",items:data}))})})))},tokenize:function(){},updateResults:function(initial){function postRender(){search.removeClass("select2-active"),self.positionDropdown(),self.liveRegion.text(results.find(".select2-no-results,.select2-selection-limit,.select2-searching").length?results.text():self.opts.formatMatches(results.find(".select2-result-selectable").length))}function render(html){results.html(html),postRender()}var data,input,queryNumber,search=this.search,results=this.results,opts=this.opts,self=this,term=search.val(),lastTerm=$.data(this.container,"select2-last-term");if((initial===!0||!lastTerm||!equal(term,lastTerm))&&($.data(this.container,"select2-last-term",term),initial===!0||this.showSearchInput!==!1&&this.opened())){queryNumber=++this.queryCount;var maxSelSize=this.getMaximumSelectionSize();if(maxSelSize>=1&&(data=this.data(),$.isArray(data)&&data.length>=maxSelSize&&checkFormatter(opts.formatSelectionTooBig,"formatSelectionTooBig")))return void render("<li class='select2-selection-limit'>"+evaluate(opts.formatSelectionTooBig,maxSelSize)+"</li>");if(search.val().length<opts.minimumInputLength)return render(checkFormatter(opts.formatInputTooShort,"formatInputTooShort")?"<li class='select2-no-results'>"+evaluate(opts.formatInputTooShort,search.val(),opts.minimumInputLength)+"</li>":""),void(initial&&this.showSearch&&this.showSearch(!0));if(opts.maximumInputLength&&search.val().length>opts.maximumInputLength)return void render(checkFormatter(opts.formatInputTooLong,"formatInputTooLong")?"<li class='select2-no-results'>"+evaluate(opts.formatInputTooLong,search.val(),opts.maximumInputLength)+"</li>":"");opts.formatSearching&&0===this.findHighlightableChoices().length&&render("<li class='select2-searching'>"+evaluate(opts.formatSearching)+"</li>"),search.addClass("select2-active"),this.removeHighlight(),input=this.tokenize(),input!=undefined&&null!=input&&search.val(input),this.resultsPage=1,opts.query({element:opts.element,term:search.val(),page:this.resultsPage,context:null,matcher:opts.matcher,callback:this.bind(function(data){var def;if(queryNumber==this.queryCount){if(!this.opened())return void this.search.removeClass("select2-active");if(this.context=data.context===undefined?null:data.context,this.opts.createSearchChoice&&""!==search.val()&&(def=this.opts.createSearchChoice.call(self,search.val(),data.results),def!==undefined&&null!==def&&self.id(def)!==undefined&&null!==self.id(def)&&0===$(data.results).filter(function(){return equal(self.id(this),self.id(def))}).length&&this.opts.createSearchChoicePosition(data.results,def)),0===data.results.length&&checkFormatter(opts.formatNoMatches,"formatNoMatches"))return void render("<li class='select2-no-results'>"+evaluate(opts.formatNoMatches,search.val())+"</li>");results.empty(),self.opts.populateResults.call(this,results,data.results,{term:search.val(),page:this.resultsPage,context:null}),data.more===!0&&checkFormatter(opts.formatLoadMore,"formatLoadMore")&&(results.append("<li class='select2-more-results'>"+self.opts.escapeMarkup(evaluate(opts.formatLoadMore,this.resultsPage))+"</li>"),window.setTimeout(function(){self.loadMoreIfNeeded()},10)),this.postprocessResults(data,initial),postRender(),this.opts.element.trigger({type:"select2-loaded",items:data})}})})}},cancel:function(){this.close()},blur:function(){this.opts.selectOnBlur&&this.selectHighlighted({noFocus:!0}),this.close(),this.container.removeClass("select2-container-active"),this.search[0]===document.activeElement&&this.search.blur(),this.clearSearch(),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus")},focusSearch:function(){focus(this.search)},selectHighlighted:function(options){if(this._touchMoved)return void this.clearTouchMoved();var index=this.highlight(),highlighted=this.results.find(".select2-highlighted"),data=highlighted.closest(".select2-result").data("select2-data");data?(this.highlight(index),this.onSelect(data,options)):options&&options.noFocus&&this.close()},getPlaceholder:function(){var placeholderOption;return this.opts.element.attr("placeholder")||this.opts.element.attr("data-placeholder")||this.opts.element.data("placeholder")||this.opts.placeholder||((placeholderOption=this.getPlaceholderOption())!==undefined?placeholderOption.text():undefined)},getPlaceholderOption:function(){if(this.select){var firstOption=this.select.children("option").first();if(this.opts.placeholderOption!==undefined)return"first"===this.opts.placeholderOption&&firstOption||"function"==typeof this.opts.placeholderOption&&this.opts.placeholderOption(this.select);if(""===$.trim(firstOption.text())&&""===firstOption.val())return firstOption}},initContainerWidth:function(){function resolveContainerWidth(){var style,attrs,matches,i,l,attr;if("off"===this.opts.width)return null;if("element"===this.opts.width)return 0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px";if("copy"===this.opts.width||"resolve"===this.opts.width){if(style=this.opts.element.attr("style"),style!==undefined)for(attrs=style.split(";"),i=0,l=attrs.length;l>i;i+=1)if(attr=attrs[i].replace(/\s/g,""),matches=attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i),null!==matches&&matches.length>=1)return matches[1];return"resolve"===this.opts.width?(style=this.opts.element.css("width"),style.indexOf("%")>0?style:0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px"):null}return $.isFunction(this.opts.width)?this.opts.width():this.opts.width}var width=resolveContainerWidth.call(this);null!==width&&this.container.css("width",width)}}),SingleSelect2=clazz(AbstractSelect2,{createContainer:function(){var container=$(document.createElement("div")).attr({"class":"select2-container"}).html(["<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>"," <span class='select2-chosen'>&#160;</span><abbr class='select2-search-choice-close'></abbr>"," <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>","</a>","<label for='' class='select2-offscreen'></label>","<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />","<div class='select2-drop select2-display-none'>"," <div class='select2-search'>"," <label for='' class='select2-offscreen'></label>"," <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'"," aria-autocomplete='list' />"," </div>"," <ul class='select2-results' role='listbox'>"," </ul>","</div>"].join(""));return container},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var el,range,len;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.opts.shouldFocusInput(this)&&(this.search.focus(),el=this.search.get(0),el.createTextRange?(range=el.createTextRange(),range.collapse(!1),range.select()):el.setSelectionRange&&(len=this.search.val().length,el.setSelectionRange(len,len))),""===this.search.val()&&this.nextSearchTerm!=undefined&&(this.search.val(this.nextSearchTerm),this.search.select()),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger($.Event("select2-open"))},close:function(){this.opened()&&(this.parent.close.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.prop("disabled",!1),this.opts.shouldFocusInput(this)&&this.focusser.focus()},destroy:function(){$("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments),cleanupJQueryElements.call(this,"selection","focusser")},initContainer:function(){var selection,elementLabel,container=this.container,dropdown=this.dropdown,idSuffix=nextUid();this.showSearch(this.opts.minimumResultsForSearch<0?!1:!0),this.selection=selection=container.find(".select2-choice"),this.focusser=container.find(".select2-focusser"),selection.find(".select2-chosen").attr("id","select2-chosen-"+idSuffix),this.focusser.attr("aria-labelledby","select2-chosen-"+idSuffix),this.results.attr("id","select2-results-"+idSuffix),this.search.attr("aria-owns","select2-results-"+idSuffix),this.focusser.attr("id","s2id_autogen"+idSuffix),elementLabel=$("label[for='"+this.opts.element.attr("id")+"']"),this.focusser.prev().text(elementLabel.text()).attr("for",this.focusser.attr("id"));var originalTitle=this.opts.element.attr("title");this.opts.element.attr("title",originalTitle||elementLabel.text()),this.focusser.attr("tabindex",this.elementTabIndex),this.search.attr("id",this.focusser.attr("id")+"_search"),this.search.prev().text($("label[for='"+this.focusser.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("keydown",this.bind(function(e){if(this.isInterfaceEnabled()){if(e.which===KEY.PAGE_UP||e.which===KEY.PAGE_DOWN)return void killEvent(e);switch(e.which){case KEY.UP:case KEY.DOWN:return this.moveHighlight(e.which===KEY.UP?-1:1),void killEvent(e);case KEY.ENTER:return this.selectHighlighted(),void killEvent(e);case KEY.TAB:return void this.selectHighlighted({noFocus:!0});case KEY.ESC:return this.cancel(e),void killEvent(e)}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body.get(0)&&window.setTimeout(this.bind(function(){this.opened()&&this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(e){if(this.isInterfaceEnabled()&&e.which!==KEY.TAB&&!KEY.isControl(e)&&!KEY.isFunctionKey(e)&&e.which!==KEY.ESC){if(this.opts.openOnEnter===!1&&e.which===KEY.ENTER)return void killEvent(e);if(e.which==KEY.DOWN||e.which==KEY.UP||e.which==KEY.ENTER&&this.opts.openOnEnter){if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey)return;return this.open(),void killEvent(e)}return e.which==KEY.DELETE||e.which==KEY.BACKSPACE?(this.opts.allowClear&&this.clear(),void killEvent(e)):void 0}})),installKeyUpChangeEvent(this.focusser),this.focusser.on("keyup-change input",this.bind(function(e){if(this.opts.minimumResultsForSearch>=0){if(e.stopPropagation(),this.opened())return;this.open()}})),selection.on("mousedown touchstart","abbr",this.bind(function(e){this.isInterfaceEnabled()&&(this.clear(),killEventImmediately(e),this.close(),this.selection.focus())})),selection.on("mousedown touchstart",this.bind(function(e){reinsertElement(selection),this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),killEvent(e)})),dropdown.on("mousedown touchstart",this.bind(function(){this.opts.shouldFocusInput(this)&&this.search.focus()})),selection.on("focus",this.bind(function(e){killEvent(e)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger($.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.setPlaceholder()},clear:function(triggerChange){var data=this.selection.data("select2-data");if(data){var evt=$.Event("select2-clearing");if(this.opts.element.trigger(evt),evt.isDefaultPrevented())return;var placeholderOption=this.getPlaceholderOption();this.opts.element.val(placeholderOption?placeholderOption.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),triggerChange!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(data),choice:data}),this.triggerChange({removed:data}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var self=this;this.opts.initSelection.call(null,this.opts.element,function(selected){selected!==undefined&&null!==selected&&(self.updateSelection(selected),self.close(),self.setPlaceholder(),self.nextSearchTerm=self.opts.nextSearchTerm(selected,self.search.val()))})}},isPlaceholderOptionSelected:function(){var placeholderOption;return this.getPlaceholder()===undefined?!1:(placeholderOption=this.getPlaceholderOption())!==undefined&&placeholderOption.prop("selected")||""===this.opts.element.val()||this.opts.element.val()===undefined||null===this.opts.element.val()},prepareOpts:function(){var opts=this.parent.prepareOpts.apply(this,arguments),self=this;return"select"===opts.element.get(0).tagName.toLowerCase()?opts.initSelection=function(element,callback){var selected=element.find("option").filter(function(){return this.selected&&!this.disabled});callback(self.optionToData(selected))}:"data"in opts&&(opts.initSelection=opts.initSelection||function(element,callback){var id=element.val(),match=null;opts.query({matcher:function(term,text,el){var is_match=equal(id,opts.id(el));return is_match&&(match=el),is_match},callback:$.isFunction(callback)?function(){callback(match)}:$.noop})}),opts},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===undefined?undefined:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var placeholder=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&placeholder!==undefined){if(this.select&&this.getPlaceholderOption()===undefined)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(data,initial,noHighlightUpdate){var selected=0,self=this;if(this.findHighlightableChoices().each2(function(i,elm){return equal(self.id(elm.data("select2-data")),self.opts.element.val())?(selected=i,!1):void 0}),noHighlightUpdate!==!1&&this.highlight(initial===!0&&selected>=0?selected:0),initial===!0){var min=this.opts.minimumResultsForSearch;min>=0&&this.showSearch(countResults(data.results)>=min)}},showSearch:function(showSearchInput){this.showSearchInput!==showSearchInput&&(this.showSearchInput=showSearchInput,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!showSearchInput),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!showSearchInput),$(this.dropdown,this.container).toggleClass("select2-with-searchbox",showSearchInput))},onSelect:function(data,options){if(this.triggerSelect(data)){var old=this.opts.element.val(),oldData=this.data();this.opts.element.val(this.id(data)),this.updateSelection(data),this.opts.element.trigger({type:"select2-selected",val:this.id(data),choice:data}),this.nextSearchTerm=this.opts.nextSearchTerm(data,this.search.val()),this.close(),options&&options.noFocus||!this.opts.shouldFocusInput(this)||this.focusser.focus(),equal(old,this.id(data))||this.triggerChange({added:data,removed:oldData})}},updateSelection:function(data){var formatted,cssClass,container=this.selection.find(".select2-chosen");this.selection.data("select2-data",data),container.empty(),null!==data&&(formatted=this.opts.formatSelection(data,container,this.opts.escapeMarkup)),formatted!==undefined&&container.append(formatted),cssClass=this.opts.formatSelectionCssClass(data,container),cssClass!==undefined&&container.addClass(cssClass),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==undefined&&this.container.addClass("select2-allowclear")},val:function(){var val,triggerChange=!1,data=null,self=this,oldData=this.data();if(0===arguments.length)return this.opts.element.val();if(val=arguments[0],arguments.length>1&&(triggerChange=arguments[1]),this.select)this.select.val(val).find("option").filter(function(){return this.selected}).each2(function(i,elm){return data=self.optionToData(elm),!1}),this.updateSelection(data),this.setPlaceholder(),triggerChange&&this.triggerChange({added:data,removed:oldData});else{if(!val&&0!==val)return void this.clear(triggerChange);if(this.opts.initSelection===undefined)throw new Error("cannot call val() if initSelection() is not defined");this.opts.element.val(val),this.opts.initSelection(this.opts.element,function(data){self.opts.element.val(data?self.id(data):""),self.updateSelection(data),self.setPlaceholder(),triggerChange&&self.triggerChange({added:data,removed:oldData})})}},clearSearch:function(){this.search.val(""),this.focusser.val("")},data:function(value){var data,triggerChange=!1;return 0===arguments.length?(data=this.selection.data("select2-data"),data==undefined&&(data=null),data):(arguments.length>1&&(triggerChange=arguments[1]),void(value?(data=this.data(),this.opts.element.val(value?this.id(value):""),this.updateSelection(value),triggerChange&&this.triggerChange({added:value,removed:data})):this.clear(triggerChange)))}}),MultiSelect2=clazz(AbstractSelect2,{createContainer:function(){var container=$(document.createElement("div")).attr({"class":"select2-container select2-container-multi"}).html(["<ul class='select2-choices'>"," <li class='select2-search-field'>"," <label for='' class='select2-offscreen'></label>"," <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>"," </li>","</ul>","<div class='select2-drop select2-drop-multi select2-display-none'>"," <ul class='select2-results'>"," </ul>","</div>"].join(""));return container},prepareOpts:function(){var opts=this.parent.prepareOpts.apply(this,arguments),self=this;return"select"===opts.element.get(0).tagName.toLowerCase()?opts.initSelection=function(element,callback){var data=[];element.find("option").filter(function(){return this.selected&&!this.disabled}).each2(function(i,elm){data.push(self.optionToData(elm))}),callback(data)}:"data"in opts&&(opts.initSelection=opts.initSelection||function(element,callback){var ids=splitVal(element.val(),opts.separator),matches=[];opts.query({matcher:function(term,text,el){var is_match=$.grep(ids,function(id){return equal(id,opts.id(el))}).length;return is_match&&matches.push(el),is_match},callback:$.isFunction(callback)?function(){for(var ordered=[],i=0;i<ids.length;i++)for(var id=ids[i],j=0;j<matches.length;j++){var match=matches[j];if(equal(id,opts.id(match))){ordered.push(match),matches.splice(j,1);break}}callback(ordered)}:$.noop})}),opts},selectChoice:function(choice){var selected=this.container.find(".select2-search-choice-focus");selected.length&&choice&&choice[0]==selected[0]||(selected.length&&this.opts.element.trigger("choice-deselected",selected),selected.removeClass("select2-search-choice-focus"),choice&&choice.length&&(this.close(),choice.addClass("select2-search-choice-focus"),this.opts.element.trigger("choice-selected",choice)))},destroy:function(){$("label[for='"+this.search.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments),cleanupJQueryElements.call(this,"searchContainer","selection")},initContainer:function(){var selection,selector=".select2-choices";this.searchContainer=this.container.find(".select2-search-field"),this.selection=selection=this.container.find(selector);var _this=this;this.selection.on("click",".select2-search-choice:not(.select2-locked)",function(){_this.search[0].focus(),_this.selectChoice($(this))}),this.search.attr("id","s2id_autogen"+nextUid()),this.search.prev().text($("label[for='"+this.opts.element.attr("id")+"']").text()).attr("for",this.search.attr("id")),this.search.on("input paste",this.bind(function(){this.isInterfaceEnabled()&&(this.opened()||this.open())})),this.search.attr("tabindex",this.elementTabIndex),this.keydowns=0,this.search.on("keydown",this.bind(function(e){if(this.isInterfaceEnabled()){++this.keydowns;var selected=selection.find(".select2-search-choice-focus"),prev=selected.prev(".select2-search-choice:not(.select2-locked)"),next=selected.next(".select2-search-choice:not(.select2-locked)"),pos=getCursorInfo(this.search);if(selected.length&&(e.which==KEY.LEFT||e.which==KEY.RIGHT||e.which==KEY.BACKSPACE||e.which==KEY.DELETE||e.which==KEY.ENTER)){var selectedChoice=selected;return e.which==KEY.LEFT&&prev.length?selectedChoice=prev:e.which==KEY.RIGHT?selectedChoice=next.length?next:null:e.which===KEY.BACKSPACE?this.unselect(selected.first())&&(this.search.width(10),selectedChoice=prev.length?prev:next):e.which==KEY.DELETE?this.unselect(selected.first())&&(this.search.width(10),selectedChoice=next.length?next:null):e.which==KEY.ENTER&&(selectedChoice=null),this.selectChoice(selectedChoice),killEvent(e),void(selectedChoice&&selectedChoice.length||this.open())}if((e.which===KEY.BACKSPACE&&1==this.keydowns||e.which==KEY.LEFT)&&0==pos.offset&&!pos.length)return this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last()),void killEvent(e);if(this.selectChoice(null),this.opened())switch(e.which){case KEY.UP:case KEY.DOWN:return this.moveHighlight(e.which===KEY.UP?-1:1),void killEvent(e);case KEY.ENTER:return this.selectHighlighted(),void killEvent(e);case KEY.TAB:return this.selectHighlighted({noFocus:!0}),void this.close();case KEY.ESC:return this.cancel(e),void killEvent(e)}if(e.which!==KEY.TAB&&!KEY.isControl(e)&&!KEY.isFunctionKey(e)&&e.which!==KEY.BACKSPACE&&e.which!==KEY.ESC){if(e.which===KEY.ENTER){if(this.opts.openOnEnter===!1)return;if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey)return}this.open(),(e.which===KEY.PAGE_UP||e.which===KEY.PAGE_DOWN)&&killEvent(e),e.which===KEY.ENTER&&killEvent(e)}}})),this.search.on("keyup",this.bind(function(){this.keydowns=0,this.resizeSearch()})),this.search.on("blur",this.bind(function(e){this.container.removeClass("select2-container-active"),this.search.removeClass("select2-focused"),this.selectChoice(null),this.opened()||this.clearSearch(),e.stopImmediatePropagation(),this.opts.element.trigger($.Event("select2-blur"))})),this.container.on("click",selector,this.bind(function(e){this.isInterfaceEnabled()&&($(e.target).closest(".select2-search-choice").length>0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.open(),this.focusSearch(),e.preventDefault()))})),this.container.on("focus",selector,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger($.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var self=this;this.opts.initSelection.call(null,this.opts.element,function(data){data!==undefined&&null!==data&&(self.updateSelection(data),self.close(),self.clearSearch())})}},clearSearch:function(){var placeholder=this.getPlaceholder(),maxWidth=this.getMaxSearchWidth();placeholder!==undefined&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(placeholder).addClass("select2-default"),this.search.width(maxWidth>0?maxWidth:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),""===this.search.val()&&this.nextSearchTerm!=undefined&&(this.search.val(this.nextSearchTerm),this.search.select()),this.updateResults(!0),this.opts.shouldFocusInput(this)&&this.search.focus(),this.opts.element.trigger($.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(data){var ids=[],filtered=[],self=this;$(data).each(function(){indexOf(self.id(this),ids)<0&&(ids.push(self.id(this)),filtered.push(this))}),data=filtered,this.selection.find(".select2-search-choice").remove(),$(data).each(function(){self.addSelectedChoice(this)}),self.postprocessResults()},tokenize:function(){var input=this.search.val();input=this.opts.tokenizer.call(this,input,this.data(),this.bind(this.onSelect),this.opts),null!=input&&input!=undefined&&(this.search.val(input),input.length>0&&this.open())},onSelect:function(data,options){this.triggerSelect(data)&&(this.addSelectedChoice(data),this.opts.element.trigger({type:"selected",val:this.id(data),choice:data}),this.nextSearchTerm=this.opts.nextSearchTerm(data,this.search.val()),this.clearSearch(),this.updateResults(),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(data,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()?this.updateResults(!0):this.nextSearchTerm!=undefined&&(this.search.val(this.nextSearchTerm),this.updateResults(),this.search.select()),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:data}),options&&options.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(data){var formatted,cssClass,enableChoice=!data.locked,enabledItem=$("<li class='select2-search-choice'> <div></div> <a href='#' class='select2-search-choice-close' tabindex='-1'></a></li>"),disabledItem=$("<li class='select2-search-choice select2-locked'><div></div></li>"),choice=enableChoice?enabledItem:disabledItem,id=this.id(data),val=this.getVal();formatted=this.opts.formatSelection(data,choice.find("div"),this.opts.escapeMarkup),formatted!=undefined&&choice.find("div").replaceWith("<div>"+formatted+"</div>"),cssClass=this.opts.formatSelectionCssClass(data,choice.find("div")),cssClass!=undefined&&choice.addClass(cssClass),enableChoice&&choice.find(".select2-search-choice-close").on("mousedown",killEvent).on("click dblclick",this.bind(function(e){this.isInterfaceEnabled()&&(this.unselect($(e.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),killEvent(e),this.close(),this.focusSearch())})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),choice.data("select2-data",data),choice.insertBefore(this.searchContainer),val.push(id),this.setVal(val)},unselect:function(selected){var data,index,val=this.getVal();if(selected=selected.closest(".select2-search-choice"),0===selected.length)throw"Invalid argument: "+selected+". Must be .select2-search-choice";if(data=selected.data("select2-data")){var evt=$.Event("select2-removing");if(evt.val=this.id(data),evt.choice=data,this.opts.element.trigger(evt),evt.isDefaultPrevented())return!1;for(;(index=indexOf(this.id(data),val))>=0;)val.splice(index,1),this.setVal(val),this.select&&this.postprocessResults();return selected.remove(),this.opts.element.trigger({type:"select2-removed",val:this.id(data),choice:data}),this.triggerChange({removed:data}),!0}},postprocessResults:function(data,initial,noHighlightUpdate){var val=this.getVal(),choices=this.results.find(".select2-result"),compound=this.results.find(".select2-result-with-children"),self=this;choices.each2(function(i,choice){var id=self.id(choice.data("select2-data"));indexOf(id,val)>=0&&(choice.addClass("select2-selected"),choice.find(".select2-result-selectable").addClass("select2-selected"))
8
+ }),compound.each2(function(i,choice){choice.is(".select2-result-selectable")||0!==choice.find(".select2-result-selectable:not(.select2-selected)").length||choice.addClass("select2-selected")}),-1==this.highlight()&&noHighlightUpdate!==!1&&self.highlight(0),!this.opts.createSearchChoice&&!choices.filter(".select2-result:not(.select2-selected)").length>0&&(!data||data&&!data.more&&0===this.results.find(".select2-no-results").length)&&checkFormatter(self.opts.formatNoMatches,"formatNoMatches")&&this.results.append("<li class='select2-no-results'>"+evaluate(self.opts.formatNoMatches,self.search.val())+"</li>")},getMaxSearchWidth:function(){return this.selection.width()-getSideBorderPadding(this.search)},resizeSearch:function(){var minimumWidth,left,maxWidth,containerLeft,searchWidth,sideBorderPadding=getSideBorderPadding(this.search);minimumWidth=measureTextWidth(this.search)+10,left=this.search.offset().left,maxWidth=this.selection.width(),containerLeft=this.selection.offset().left,searchWidth=maxWidth-(left-containerLeft)-sideBorderPadding,minimumWidth>searchWidth&&(searchWidth=maxWidth-sideBorderPadding),40>searchWidth&&(searchWidth=maxWidth-sideBorderPadding),0>=searchWidth&&(searchWidth=minimumWidth),this.search.width(Math.floor(searchWidth))},getVal:function(){var val;return this.select?(val=this.select.val(),null===val?[]:val):(val=this.opts.element.val(),splitVal(val,this.opts.separator))},setVal:function(val){var unique;this.select?this.select.val(val):(unique=[],$(val).each(function(){indexOf(this,unique)<0&&unique.push(this)}),this.opts.element.val(0===unique.length?"":unique.join(this.opts.separator)))},buildChangeDetails:function(old,current){for(var current=current.slice(0),old=old.slice(0),i=0;i<current.length;i++)for(var j=0;j<old.length;j++)equal(this.opts.id(current[i]),this.opts.id(old[j]))&&(current.splice(i,1),i>0&&i--,old.splice(j,1),j--);return{added:current,removed:old}},val:function(val,triggerChange){var oldData,self=this;if(0===arguments.length)return this.getVal();if(oldData=this.data(),oldData.length||(oldData=[]),!val&&0!==val)return this.opts.element.val(""),this.updateSelection([]),this.clearSearch(),void(triggerChange&&this.triggerChange({added:this.data(),removed:oldData}));if(this.setVal(val),this.select)this.opts.initSelection(this.select,this.bind(this.updateSelection)),triggerChange&&this.triggerChange(this.buildChangeDetails(oldData,this.data()));else{if(this.opts.initSelection===undefined)throw new Error("val() cannot be called if initSelection() is not defined");this.opts.initSelection(this.opts.element,function(data){var ids=$.map(data,self.id);self.setVal(ids),self.updateSelection(data),self.clearSearch(),triggerChange&&self.triggerChange(self.buildChangeDetails(oldData,self.data()))})}this.clearSearch()},onSortStart:function(){if(this.select)throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var val=[],self=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){val.push(self.opts.id($(this).data("select2-data")))}),this.setVal(val),this.triggerChange()},data:function(values,triggerChange){var ids,old,self=this;return 0===arguments.length?this.selection.children(".select2-search-choice").map(function(){return $(this).data("select2-data")}).get():(old=this.data(),values||(values=[]),ids=$.map(values,function(e){return self.opts.id(e)}),this.setVal(ids),this.updateSelection(values),this.clearSearch(),triggerChange&&this.triggerChange(this.buildChangeDetails(old,this.data())),void 0)}}),$.fn.select2=function(){var opts,select2,method,value,multiple,args=Array.prototype.slice.call(arguments,0),allowedMethods=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],valueMethods=["opened","isFocused","container","dropdown"],propertyMethods=["val","data"],methodsMap={search:"externalSearch"};return this.each(function(){if(0===args.length||"object"==typeof args[0])opts=0===args.length?{}:$.extend({},args[0]),opts.element=$(this),"select"===opts.element.get(0).tagName.toLowerCase()?multiple=opts.element.prop("multiple"):(multiple=opts.multiple||!1,"tags"in opts&&(opts.multiple=multiple=!0)),select2=multiple?new window.Select2["class"].multi:new window.Select2["class"].single,select2.init(opts);else{if("string"!=typeof args[0])throw"Invalid arguments to select2 plugin: "+args;if(indexOf(args[0],allowedMethods)<0)throw"Unknown method: "+args[0];if(value=undefined,select2=$(this).data("select2"),select2===undefined)return;if(method=args[0],"container"===method?value=select2.container:"dropdown"===method?value=select2.dropdown:(methodsMap[method]&&(method=methodsMap[method]),value=select2[method].apply(select2,args.slice(1))),indexOf(args[0],valueMethods)>=0||indexOf(args[0],propertyMethods)>=0&&1==args.length)return!1}}),value===undefined?this:value},$.fn.select2.defaults={width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(result,container,query,escapeMarkup){var markup=[];return markMatch(result.text,query.term,markup,escapeMarkup),markup.join("")},formatSelection:function(data,container,escapeMarkup){return data?escapeMarkup(data.text):undefined},sortResults:function(results){return results},formatResultCssClass:function(data){return data.css},formatSelectionCssClass:function(){return undefined},formatMatches:function(matches){return matches+" results are available, use up and down arrow keys to navigate."},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(input,min){var n=min-input.length;return"Please enter "+n+" or more character"+(1==n?"":"s")},formatInputTooLong:function(input,max){var n=input.length-max;return"Please delete "+n+" character"+(1==n?"":"s")},formatSelectionTooBig:function(limit){return"You can only select "+limit+" item"+(1==limit?"":"s")},formatLoadMore:function(){return"Loading more results…"},formatSearching:function(){return"Searching…"},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(e){return e==undefined?null:e.id},matcher:function(term,text){return stripDiacritics(""+text).toUpperCase().indexOf(stripDiacritics(""+term).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:defaultTokenizer,escapeMarkup:defaultEscapeMarkup,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(c){return c},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return undefined},searchInputPlaceholder:"",createSearchChoicePosition:"top",shouldFocusInput:function(instance){var supportsTouchEvents="ontouchstart"in window||navigator.msMaxTouchPoints>0;return supportsTouchEvents&&instance.opts.minimumResultsForSearch<0?!1:!0}},$.fn.select2.ajaxDefaults={transport:$.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:ajax,local:local,tags:tags},util:{debounce:debounce,markMatch:markMatch,escapeMarkup:defaultEscapeMarkup,stripDiacritics:stripDiacritics},"class":{"abstract":AbstractSelect2,single:SingleSelect2,multi:MultiSelect2}}}}(jQuery),jQuery(document).ready(function($){$("#filter_action, #filter_content, #filter_form").change(function(){$("#leadin-contacts-filter-button").addClass("button-primary")})});
assets/js/build/leadin-subscribe.js CHANGED
@@ -404,10 +404,11 @@ jQuery(document).ready( function ( $ ) {
404
 
405
  function bind_leadin_subscribe_widget ( lis_heading, lis_desc, lis_show_names, lis_show_phone, lis_btn_label, lis_vex_class, lis_confirmation )
406
  {
407
- lis_heading = ( lis_heading ? lis_heading : 'Sign up for email updates' );
408
- lis_desc = ( lis_desc ? lis_desc : '' );
409
- lis_btn_label = ( lis_btn_label ? lis_btn_label : 'SUBSCRIBE' );
410
- lis_vex_class = ( lis_vex_class ? lis_vex_class : 'vex-theme-bottom-right-corner' );
 
411
  lis_confirmation = ( lis_confirmation ? lis_confirmation : 1 );
412
 
413
  (function(){
@@ -469,7 +470,7 @@ function bind_leadin_subscribe_widget ( lis_heading, lis_desc, lis_show_names, l
469
  ( parseInt(lis_confirmation) ? '<h3>Thanks!<br>You should receive a confirmation email in your inbox shortly.</h3>' : '<h3>Thanks!<br>We received your submission.</h3>' ) +
470
  '<div id="powered-by-leadin-thank-you">' +
471
  '<span class="powered-by">Powered by Leadin</span>' +
472
- '<a href="http://leadin.com/wordpress-subscribe-widget-plugin/?utm_campaign=subscribe_widget&utm_medium=email&utm_source=' + window.location.host + '"><img alt="Leadin" height="20px" width="99px" src="' + document.location.protocol + '//leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/Leadin_logo@2x.png" alt="leadin.com"/></a>' +
473
  '</div>'
474
  ).css('text-align', 'center').fadeIn(250);
475
  });
@@ -487,9 +488,7 @@ function bind_leadin_subscribe_widget ( lis_heading, lis_desc, lis_show_names, l
487
  }
488
  });
489
 
490
- //leadin_subscribe_show();
491
-
492
- $('.leadin-subscribe form.vex-dialog-form').append('<a href="http://leadin.com/wordpress-subscribe-widget-plugin/?utm_campaign=subscribe_widget&utm_medium=widget&utm_source=' + document.URL + '" id="leadin-subscribe-powered-by" class="leadin-subscribe-powered-by">Powered by Leadin</a>');
493
  };
494
 
495
  subscribe._open = function() {
404
 
405
  function bind_leadin_subscribe_widget ( lis_heading, lis_desc, lis_show_names, lis_show_phone, lis_btn_label, lis_vex_class, lis_confirmation )
406
  {
407
+
408
+ lis_heading = ( lis_heading ? lis_heading : 'Sign up for email updates' );
409
+ lis_desc = ( lis_desc ? lis_desc : '' );
410
+ lis_btn_label = ( lis_btn_label ? lis_btn_label : 'SUBSCRIBE' );
411
+ lis_vex_class = ( lis_vex_class ? lis_vex_class : 'vex-theme-bottom-right-corner' );
412
  lis_confirmation = ( lis_confirmation ? lis_confirmation : 1 );
413
 
414
  (function(){
470
  ( parseInt(lis_confirmation) ? '<h3>Thanks!<br>You should receive a confirmation email in your inbox shortly.</h3>' : '<h3>Thanks!<br>We received your submission.</h3>' ) +
471
  '<div id="powered-by-leadin-thank-you">' +
472
  '<span class="powered-by">Powered by Leadin</span>' +
473
+ '<a href="http://leadin.com/wordpress-subscribe-widget-plugin?utm_source=virality&utm_medium=referral&utm_term=' + window.location.host + '&utm_content=e11&utm_campaign=subscribe%20widget"><img alt="Leadin" height="20px" width="99px" src="' + document.location.protocol + '//leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/Leadin_logo@2x.png" alt="leadin.com"/></a>' +
474
  '</div>'
475
  ).css('text-align', 'center').fadeIn(250);
476
  });
488
  }
489
  });
490
 
491
+ $('.leadin-subscribe form.vex-dialog-form').append('<a href="http://leadin.com/wordpress-subscribe-widget-plugin?utm_source=virality&utm_medium=referral&utm_term=' + window.location.host + '&utm_content=e11&utm_campaign=subscribe%20widget" id="leadin-subscribe-powered-by" class="leadin-subscribe-powered-by">Powered by Leadin</a>');
 
 
492
  };
493
 
494
  subscribe._open = function() {
assets/js/build/leadin-subscribe.min.js CHANGED
@@ -1 +1 @@
1
- function bind_leadin_subscribe_widget(lis_heading,lis_desc,lis_show_names,lis_show_phone,lis_btn_label,lis_vex_class,lis_confirmation){lis_heading=lis_heading?lis_heading:"Sign up for email updates",lis_desc=lis_desc?lis_desc:"",lis_btn_label=lis_btn_label?lis_btn_label:"SUBSCRIBE",lis_vex_class=lis_vex_class?lis_vex_class:"vex-theme-bottom-right-corner",lis_confirmation=lis_confirmation?lis_confirmation:1,function(){var $=jQuery,subscribe={};subscribe.vex=void 0,subscribe.init=function(){$(window).scrollTop()+$(window).height()>$(document).height()/2&&subscribe.open(),$(window).scroll(function(){$(window).scrollTop()+$(window).height()>$(document).height()/2&&subscribe.open()})},subscribe.open=function(){return subscribe.vex?subscribe._open():(subscribe.vex=vex.dialog.open({showCloseButton:!0,className:"leadin-subscribe "+lis_vex_class,message:"<h4>"+lis_heading+"</h4><p>"+lis_desc+"</p>",input:'<input id="leadin-subscribe-email" name="email" type="email" placeholder="Email address" />'+(parseInt(lis_show_names)?'<input id="leadin-subscribe-fname" name="fname" type="text" placeholder="First Name" /><input id="leadin-subscribe-lname" name="lname" type="text" placeholder="Last Name" />':"")+(parseInt(lis_show_phone)?'<input id="leadin-subscribe-phone" name="phone" type="tel" placeholder="Phone" />':""),buttons:[$.extend({},vex.dialog.buttons.YES,{text:lis_btn_label?lis_btn_label:"SUBSCRIBE"})],onSubmit:function(){$subscribe_form=$(this),$subscribe_form.find("input.error").removeClass("error");var form_validated=!0;return $subscribe_form.find("input").each(function(){var $input=$(this);$input.val()||($input.addClass("error"),form_validated=!1)}),form_validated?($(".vex-dialog-form").fadeOut(300,function(){$(".vex-dialog-form").html('<div class="vex-close"></div>'+(parseInt(lis_confirmation)?"<h3>Thanks!<br>You should receive a confirmation email in your inbox shortly.</h3>":"<h3>Thanks!<br>We received your submission.</h3>")+'<div id="powered-by-leadin-thank-you"><span class="powered-by">Powered by Leadin</span><a href="http://leadin.com/wordpress-subscribe-widget-plugin/?utm_campaign=subscribe_widget&utm_medium=email&utm_source='+window.location.host+'"><img alt="Leadin" height="20px" width="99px" src="'+document.location.protocol+'//leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/Leadin_logo@2x.png" alt="leadin.com"/></a></div>').css("text-align","center").fadeIn(250)}),leadin_submit_form($(".leadin-subscribe form"),$),$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date}),!1):!1},callback:function(data){data===!1&&$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date}),$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date})}}),void $(".leadin-subscribe form.vex-dialog-form").append('<a href="http://leadin.com/wordpress-subscribe-widget-plugin/?utm_campaign=subscribe_widget&utm_medium=widget&utm_source='+document.URL+'" id="leadin-subscribe-powered-by" class="leadin-subscribe-powered-by">Powered by Leadin</a>'))},subscribe._open=function(){subscribe.vex.parent().removeClass("vex-closing")},subscribe.close=function(){subscribe.vex&&subscribe.vex.parent().addClass("vex-closing")},subscribe.init(),window.subscribe=subscribe}()}function leadin_subscribe_check_mobile($){var is_mobile=!1;return"none"==$("#leadin-subscribe-mobile-check").css("display")&&(is_mobile=!0),is_mobile}function leadin_subscribe_show(){jQuery.ajax({type:"POST",url:li_ajax.ajax_url,data:{action:"leadin_subscribe_show"},success:function(){},error:function(){}})}function leadin_get_parameter_by_name(name){name=name.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var regex=new RegExp("[\\?&]"+name+"=([^&#]*)"),results=regex.exec(location.search);return null==results?"":decodeURIComponent(results[1].replace(/\+/g," "))}(function(){var vexFactory;vexFactory=function($){var animationEndSupport,vex;return animationEndSupport=!1,$(function(){var s;return s=(document.body||document.documentElement).style,animationEndSupport=void 0!==s.animation||void 0!==s.WebkitAnimation||void 0!==s.MozAnimation||void 0!==s.MsAnimation||void 0!==s.OAnimation,$(window).bind("keyup.vex",function(event){return 27===event.keyCode?vex.closeByEscape():void 0})}),vex={globalID:1,animationEndEvent:"animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend",baseClassNames:{vex:"vex",content:"vex-content",overlay:"vex-overlay",close:"vex-close",closing:"vex-closing",open:"vex-open"},defaultOptions:{content:"",showCloseButton:!0,escapeButtonCloses:!0,overlayClosesOnClick:!0,appendLocation:"body",className:"",css:{},overlayClassName:"",overlayCSS:{},contentClassName:"",contentCSS:{},closeClassName:"",closeCSS:{}},open:function(options){return options=$.extend({},vex.defaultOptions,options),options.id=vex.globalID,vex.globalID+=1,options.$vex=$("<div>").addClass(vex.baseClassNames.vex).addClass(options.className).css(options.css).data({vex:options}),options.$vexOverlay=$("<div>").addClass(vex.baseClassNames.overlay).addClass(options.overlayClassName).css(options.overlayCSS).data({vex:options}),options.overlayClosesOnClick&&options.$vexOverlay.bind("click.vex",function(e){return e.target===this?vex.close($(this).data().vex.id):void 0}),options.$vex.append(options.$vexOverlay),options.$vexContent=$("<div>").addClass(vex.baseClassNames.content).addClass(options.contentClassName).css(options.contentCSS).append(options.content).data({vex:options}),options.$vex.append(options.$vexContent),options.showCloseButton&&(options.$closeButton=$("<div>").addClass(vex.baseClassNames.close).addClass(options.closeClassName).css(options.closeCSS).data({vex:options}).bind("click.vex",function(){return vex.close($(this).data().vex.id)}),options.$vexContent.append(options.$closeButton)),$(options.appendLocation).append(options.$vex),vex.setupBodyClassName(options.$vex),options.afterOpen&&options.afterOpen(options.$vexContent,options),setTimeout(function(){return options.$vexContent.trigger("vexOpen",options)},0),options.$vexContent},getAllVexes:function(){return $("."+vex.baseClassNames.vex+':not(".'+vex.baseClassNames.closing+'") .'+vex.baseClassNames.content)},getVexByID:function(id){return vex.getAllVexes().filter(function(){return $(this).data().vex.id===id})},close:function(id){var $lastVex;if(!id){if($lastVex=vex.getAllVexes().last(),!$lastVex.length)return!1;id=$lastVex.data().vex.id}return vex.closeByID(id)},closeAll:function(){var ids;return ids=vex.getAllVexes().map(function(){return $(this).data().vex.id}).toArray(),(null!=ids?ids.length:void 0)?($.each(ids.reverse(),function(index,id){return vex.closeByID(id)}),!0):!1},closeByID:function(id){var $vex,$vexContent,beforeClose,close,options;return $vexContent=vex.getVexByID(id),$vexContent.length?($vex=$vexContent.data().vex.$vex,options=$.extend({},$vexContent.data().vex),beforeClose=function(){return options.beforeClose?options.beforeClose($vexContent,options):void 0},close=function(){return $vexContent.trigger("vexClose",options),$vex.remove(),options.afterClose?options.afterClose($vexContent,options):void 0},animationEndSupport?(beforeClose(),$vex.unbind(vex.animationEndEvent).bind(vex.animationEndEvent,function(){return close()}).addClass(vex.baseClassNames.closing)):(beforeClose(),close()),!0):void 0},closeByEscape:function(){var $lastVex,id,ids;return ids=vex.getAllVexes().map(function(){return $(this).data().vex.id}).toArray(),(null!=ids?ids.length:void 0)?(id=Math.max.apply(Math,ids),$lastVex=vex.getVexByID(id),$lastVex.data().vex.escapeButtonCloses!==!0?!1:vex.closeByID(id)):!1},setupBodyClassName:function($vex){return $vex.bind("vexOpen.vex",function(){return $("body").addClass(vex.baseClassNames.open)}).bind("vexClose.vex",function(){return vex.getAllVexes().length?void 0:$("body").removeClass(vex.baseClassNames.open)})},hideLoading:function(){return $(".vex-loading-spinner").remove()},showLoading:function(){return vex.hideLoading(),$("body").append('<div class="vex-loading-spinner '+vex.defaultOptions.className+'"></div>')}}},"function"==typeof define&&define.amd?define(["jquery"],vexFactory):"object"==typeof exports?module.exports=vexFactory(require("jquery")):window.vex=vexFactory(jQuery)}).call(this),function(){var vexDialogFactory;vexDialogFactory=function($,vex){var $formToObject,dialog;return null==vex?$.error("Vex is required to use vex.dialog"):($formToObject=function($form){var object;return object={},$.each($form.serializeArray(),function(){return object[this.name]?(object[this.name].push||(object[this.name]=[object[this.name]]),object[this.name].push(this.value||"")):object[this.name]=this.value||""}),object},dialog={},dialog.buttons={YES:{text:"OK",type:"submit",className:"vex-dialog-button-primary"},NO:{text:"Cancel",type:"button",className:"vex-dialog-button-secondary",click:function($vexContent){return $vexContent.data().vex.value=!1,vex.close($vexContent.data().vex.id)}}},dialog.defaultOptions={callback:function(){},afterOpen:function(){},message:"Message",input:'<input name="vex" type="hidden" value="_vex-empty-value" />',value:!1,buttons:[dialog.buttons.YES,dialog.buttons.NO],showCloseButton:!1,onSubmit:function(event){var $form,$vexContent;return $form=$(this),$vexContent=$form.parent(),event.preventDefault(),event.stopPropagation(),$vexContent.data().vex.value=dialog.getFormValueOnSubmit($formToObject($form)),vex.close($vexContent.data().vex.id)},focusFirstInput:!0},dialog.defaultAlertOptions={message:"Alert",buttons:[dialog.buttons.YES]},dialog.defaultConfirmOptions={message:"Confirm"},dialog.open=function(options){var $vexContent;return options=$.extend({},vex.defaultOptions,dialog.defaultOptions,options),options.content=dialog.buildDialogForm(options),options.beforeClose=function($vexContent){return options.callback($vexContent.data().vex.value)},$vexContent=vex.open(options),options.focusFirstInput&&$vexContent.find('input[type="submit"], textarea, input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="email"], input[type="month"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="time"], input[type="url"], input[type="week"]').first().focus(),$vexContent},dialog.alert=function(options){return"string"==typeof options&&(options={message:options}),options=$.extend({},dialog.defaultAlertOptions,options),dialog.open(options)},dialog.confirm=function(options){return"string"==typeof options?$.error("dialog.confirm(options) requires options.callback."):(options=$.extend({},dialog.defaultConfirmOptions,options),dialog.open(options))},dialog.prompt=function(options){var defaultPromptOptions;return"string"==typeof options?$.error("dialog.prompt(options) requires options.callback."):(defaultPromptOptions={message:'<label for="vex">'+(options.label||"Prompt:")+"</label>",input:'<input name="vex" type="text" class="vex-dialog-prompt-input" placeholder="'+(options.placeholder||"")+'" value="'+(options.value||"")+'" />'},options=$.extend({},defaultPromptOptions,options),dialog.open(options))},dialog.buildDialogForm=function(options){var $form,$input,$message;return $form=$('<form class="vex-dialog-form" />'),$message=$('<div class="vex-dialog-message" />'),$input=$('<div class="vex-dialog-input" />'),$form.append($message.append(options.message)).append($input.append(options.input)).append(dialog.buttonsToDOM(options.buttons)).bind("submit.vex",options.onSubmit),$form},dialog.getFormValueOnSubmit=function(formData){return formData.vex||""===formData.vex?"_vex-empty-value"===formData.vex?!0:formData.vex:formData},dialog.buttonsToDOM=function(buttons){var $buttons;return $buttons=$('<div class="vex-dialog-buttons" />'),$.each(buttons,function(index,button){return $buttons.append($('<input type="'+button.type+'" />').val(button.text).addClass(button.className+" vex-dialog-button "+(0===index?"vex-first ":"")+(index===buttons.length-1?"vex-last ":"")).bind("click.vex",function(e){return button.click?button.click($(this).parents("."+vex.baseClassNames.content),e):void 0}))}),$buttons},dialog)},"function"==typeof define&&define.amd?define(["jquery","vex"],vexDialogFactory):"object"==typeof exports?module.exports=vexDialogFactory(require("jquery"),require("vex")):window.vex.dialog=vexDialogFactory(window.jQuery,window.vex)}.call(this);var ignore_date=new Date;ignore_date.setTime(ignore_date.getTime()+12096e5),jQuery(document).ready(function($){var li_subscribe_flag=$.cookie("li_subscribe"),preview_subscribe=leadin_get_parameter_by_name("preview-subscribe");leadin_subscribe_check_mobile($)||preview_subscribe?preview_subscribe&&(bind_leadin_subscribe_widget(leadin_get_parameter_by_name("lis_heading"),leadin_get_parameter_by_name("lis_desc"),leadin_get_parameter_by_name("lis_show_names"),leadin_get_parameter_by_name("lis_show_phone"),leadin_get_parameter_by_name("lis_btn_label"),leadin_get_parameter_by_name("lis_vex_class"),leadin_get_parameter_by_name("lis_confirmation")),subscribe.open()):li_subscribe_flag?"show"==li_subscribe_flag&&bind_leadin_subscribe_widget($("#leadin-subscribe-heading").val(),$("#leadin-subscribe-text").val(),$("#leadin-subscribe-name-fields").val(),$("#leadin-subscribe-phone-field").val(),$("#leadin-subscribe-btn-label").val(),$("#leadin-subscribe-vex-class").val(),$("#leadin-subscribe-confirmation").val()):leadin_check_visitor_status($.cookie("li_hash"),function(data){"vex_set"!=data?($.cookie("li_subscribe","show",{path:"/",domain:""}),bind_leadin_subscribe_widget($("#leadin-subscribe-heading").val(),$("#leadin-subscribe-text").val(),$("#leadin-subscribe-name-fields").val(),$("#leadin-subscribe-phone-field").val(),$("#leadin-subscribe-btn-label").val(),$("#leadin-subscribe-vex-class").val(),$("#leadin-subscribe-confirmation").val())):$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date})})});
1
+ function bind_leadin_subscribe_widget(lis_heading,lis_desc,lis_show_names,lis_show_phone,lis_btn_label,lis_vex_class,lis_confirmation){lis_heading=lis_heading?lis_heading:"Sign up for email updates",lis_desc=lis_desc?lis_desc:"",lis_btn_label=lis_btn_label?lis_btn_label:"SUBSCRIBE",lis_vex_class=lis_vex_class?lis_vex_class:"vex-theme-bottom-right-corner",lis_confirmation=lis_confirmation?lis_confirmation:1,function(){var $=jQuery,subscribe={};subscribe.vex=void 0,subscribe.init=function(){$(window).scrollTop()+$(window).height()>$(document).height()/2&&subscribe.open(),$(window).scroll(function(){$(window).scrollTop()+$(window).height()>$(document).height()/2&&subscribe.open()})},subscribe.open=function(){return subscribe.vex?subscribe._open():(subscribe.vex=vex.dialog.open({showCloseButton:!0,className:"leadin-subscribe "+lis_vex_class,message:"<h4>"+lis_heading+"</h4><p>"+lis_desc+"</p>",input:'<input id="leadin-subscribe-email" name="email" type="email" placeholder="Email address" />'+(parseInt(lis_show_names)?'<input id="leadin-subscribe-fname" name="fname" type="text" placeholder="First Name" /><input id="leadin-subscribe-lname" name="lname" type="text" placeholder="Last Name" />':"")+(parseInt(lis_show_phone)?'<input id="leadin-subscribe-phone" name="phone" type="tel" placeholder="Phone" />':""),buttons:[$.extend({},vex.dialog.buttons.YES,{text:lis_btn_label?lis_btn_label:"SUBSCRIBE"})],onSubmit:function(){$subscribe_form=$(this),$subscribe_form.find("input.error").removeClass("error");var form_validated=!0;return $subscribe_form.find("input").each(function(){var $input=$(this);$input.val()||($input.addClass("error"),form_validated=!1)}),form_validated?($(".vex-dialog-form").fadeOut(300,function(){$(".vex-dialog-form").html('<div class="vex-close"></div>'+(parseInt(lis_confirmation)?"<h3>Thanks!<br>You should receive a confirmation email in your inbox shortly.</h3>":"<h3>Thanks!<br>We received your submission.</h3>")+'<div id="powered-by-leadin-thank-you"><span class="powered-by">Powered by Leadin</span><a href="http://leadin.com/wordpress-subscribe-widget-plugin?utm_source=virality&utm_medium=referral&utm_term='+window.location.host+'&utm_content=e11&utm_campaign=subscribe%20widget"><img alt="Leadin" height="20px" width="99px" src="'+document.location.protocol+'//leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/Leadin_logo@2x.png" alt="leadin.com"/></a></div>').css("text-align","center").fadeIn(250)}),leadin_submit_form($(".leadin-subscribe form"),$),$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date}),!1):!1},callback:function(data){data===!1&&$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date}),$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date})}}),void $(".leadin-subscribe form.vex-dialog-form").append('<a href="http://leadin.com/wordpress-subscribe-widget-plugin?utm_source=virality&utm_medium=referral&utm_term='+window.location.host+'&utm_content=e11&utm_campaign=subscribe%20widget" id="leadin-subscribe-powered-by" class="leadin-subscribe-powered-by">Powered by Leadin</a>'))},subscribe._open=function(){subscribe.vex.parent().removeClass("vex-closing")},subscribe.close=function(){subscribe.vex&&subscribe.vex.parent().addClass("vex-closing")},subscribe.init(),window.subscribe=subscribe}()}function leadin_subscribe_check_mobile($){var is_mobile=!1;return"none"==$("#leadin-subscribe-mobile-check").css("display")&&(is_mobile=!0),is_mobile}function leadin_subscribe_show(){jQuery.ajax({type:"POST",url:li_ajax.ajax_url,data:{action:"leadin_subscribe_show"},success:function(){},error:function(){}})}function leadin_get_parameter_by_name(name){name=name.replace(/[\[]/,"\\[").replace(/[\]]/,"\\]");var regex=new RegExp("[\\?&]"+name+"=([^&#]*)"),results=regex.exec(location.search);return null==results?"":decodeURIComponent(results[1].replace(/\+/g," "))}(function(){var vexFactory;vexFactory=function($){var animationEndSupport,vex;return animationEndSupport=!1,$(function(){var s;return s=(document.body||document.documentElement).style,animationEndSupport=void 0!==s.animation||void 0!==s.WebkitAnimation||void 0!==s.MozAnimation||void 0!==s.MsAnimation||void 0!==s.OAnimation,$(window).bind("keyup.vex",function(event){return 27===event.keyCode?vex.closeByEscape():void 0})}),vex={globalID:1,animationEndEvent:"animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend",baseClassNames:{vex:"vex",content:"vex-content",overlay:"vex-overlay",close:"vex-close",closing:"vex-closing",open:"vex-open"},defaultOptions:{content:"",showCloseButton:!0,escapeButtonCloses:!0,overlayClosesOnClick:!0,appendLocation:"body",className:"",css:{},overlayClassName:"",overlayCSS:{},contentClassName:"",contentCSS:{},closeClassName:"",closeCSS:{}},open:function(options){return options=$.extend({},vex.defaultOptions,options),options.id=vex.globalID,vex.globalID+=1,options.$vex=$("<div>").addClass(vex.baseClassNames.vex).addClass(options.className).css(options.css).data({vex:options}),options.$vexOverlay=$("<div>").addClass(vex.baseClassNames.overlay).addClass(options.overlayClassName).css(options.overlayCSS).data({vex:options}),options.overlayClosesOnClick&&options.$vexOverlay.bind("click.vex",function(e){return e.target===this?vex.close($(this).data().vex.id):void 0}),options.$vex.append(options.$vexOverlay),options.$vexContent=$("<div>").addClass(vex.baseClassNames.content).addClass(options.contentClassName).css(options.contentCSS).append(options.content).data({vex:options}),options.$vex.append(options.$vexContent),options.showCloseButton&&(options.$closeButton=$("<div>").addClass(vex.baseClassNames.close).addClass(options.closeClassName).css(options.closeCSS).data({vex:options}).bind("click.vex",function(){return vex.close($(this).data().vex.id)}),options.$vexContent.append(options.$closeButton)),$(options.appendLocation).append(options.$vex),vex.setupBodyClassName(options.$vex),options.afterOpen&&options.afterOpen(options.$vexContent,options),setTimeout(function(){return options.$vexContent.trigger("vexOpen",options)},0),options.$vexContent},getAllVexes:function(){return $("."+vex.baseClassNames.vex+':not(".'+vex.baseClassNames.closing+'") .'+vex.baseClassNames.content)},getVexByID:function(id){return vex.getAllVexes().filter(function(){return $(this).data().vex.id===id})},close:function(id){var $lastVex;if(!id){if($lastVex=vex.getAllVexes().last(),!$lastVex.length)return!1;id=$lastVex.data().vex.id}return vex.closeByID(id)},closeAll:function(){var ids;return ids=vex.getAllVexes().map(function(){return $(this).data().vex.id}).toArray(),(null!=ids?ids.length:void 0)?($.each(ids.reverse(),function(index,id){return vex.closeByID(id)}),!0):!1},closeByID:function(id){var $vex,$vexContent,beforeClose,close,options;return $vexContent=vex.getVexByID(id),$vexContent.length?($vex=$vexContent.data().vex.$vex,options=$.extend({},$vexContent.data().vex),beforeClose=function(){return options.beforeClose?options.beforeClose($vexContent,options):void 0},close=function(){return $vexContent.trigger("vexClose",options),$vex.remove(),options.afterClose?options.afterClose($vexContent,options):void 0},animationEndSupport?(beforeClose(),$vex.unbind(vex.animationEndEvent).bind(vex.animationEndEvent,function(){return close()}).addClass(vex.baseClassNames.closing)):(beforeClose(),close()),!0):void 0},closeByEscape:function(){var $lastVex,id,ids;return ids=vex.getAllVexes().map(function(){return $(this).data().vex.id}).toArray(),(null!=ids?ids.length:void 0)?(id=Math.max.apply(Math,ids),$lastVex=vex.getVexByID(id),$lastVex.data().vex.escapeButtonCloses!==!0?!1:vex.closeByID(id)):!1},setupBodyClassName:function($vex){return $vex.bind("vexOpen.vex",function(){return $("body").addClass(vex.baseClassNames.open)}).bind("vexClose.vex",function(){return vex.getAllVexes().length?void 0:$("body").removeClass(vex.baseClassNames.open)})},hideLoading:function(){return $(".vex-loading-spinner").remove()},showLoading:function(){return vex.hideLoading(),$("body").append('<div class="vex-loading-spinner '+vex.defaultOptions.className+'"></div>')}}},"function"==typeof define&&define.amd?define(["jquery"],vexFactory):"object"==typeof exports?module.exports=vexFactory(require("jquery")):window.vex=vexFactory(jQuery)}).call(this),function(){var vexDialogFactory;vexDialogFactory=function($,vex){var $formToObject,dialog;return null==vex?$.error("Vex is required to use vex.dialog"):($formToObject=function($form){var object;return object={},$.each($form.serializeArray(),function(){return object[this.name]?(object[this.name].push||(object[this.name]=[object[this.name]]),object[this.name].push(this.value||"")):object[this.name]=this.value||""}),object},dialog={},dialog.buttons={YES:{text:"OK",type:"submit",className:"vex-dialog-button-primary"},NO:{text:"Cancel",type:"button",className:"vex-dialog-button-secondary",click:function($vexContent){return $vexContent.data().vex.value=!1,vex.close($vexContent.data().vex.id)}}},dialog.defaultOptions={callback:function(){},afterOpen:function(){},message:"Message",input:'<input name="vex" type="hidden" value="_vex-empty-value" />',value:!1,buttons:[dialog.buttons.YES,dialog.buttons.NO],showCloseButton:!1,onSubmit:function(event){var $form,$vexContent;return $form=$(this),$vexContent=$form.parent(),event.preventDefault(),event.stopPropagation(),$vexContent.data().vex.value=dialog.getFormValueOnSubmit($formToObject($form)),vex.close($vexContent.data().vex.id)},focusFirstInput:!0},dialog.defaultAlertOptions={message:"Alert",buttons:[dialog.buttons.YES]},dialog.defaultConfirmOptions={message:"Confirm"},dialog.open=function(options){var $vexContent;return options=$.extend({},vex.defaultOptions,dialog.defaultOptions,options),options.content=dialog.buildDialogForm(options),options.beforeClose=function($vexContent){return options.callback($vexContent.data().vex.value)},$vexContent=vex.open(options),options.focusFirstInput&&$vexContent.find('input[type="submit"], textarea, input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="email"], input[type="month"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="time"], input[type="url"], input[type="week"]').first().focus(),$vexContent},dialog.alert=function(options){return"string"==typeof options&&(options={message:options}),options=$.extend({},dialog.defaultAlertOptions,options),dialog.open(options)},dialog.confirm=function(options){return"string"==typeof options?$.error("dialog.confirm(options) requires options.callback."):(options=$.extend({},dialog.defaultConfirmOptions,options),dialog.open(options))},dialog.prompt=function(options){var defaultPromptOptions;return"string"==typeof options?$.error("dialog.prompt(options) requires options.callback."):(defaultPromptOptions={message:'<label for="vex">'+(options.label||"Prompt:")+"</label>",input:'<input name="vex" type="text" class="vex-dialog-prompt-input" placeholder="'+(options.placeholder||"")+'" value="'+(options.value||"")+'" />'},options=$.extend({},defaultPromptOptions,options),dialog.open(options))},dialog.buildDialogForm=function(options){var $form,$input,$message;return $form=$('<form class="vex-dialog-form" />'),$message=$('<div class="vex-dialog-message" />'),$input=$('<div class="vex-dialog-input" />'),$form.append($message.append(options.message)).append($input.append(options.input)).append(dialog.buttonsToDOM(options.buttons)).bind("submit.vex",options.onSubmit),$form},dialog.getFormValueOnSubmit=function(formData){return formData.vex||""===formData.vex?"_vex-empty-value"===formData.vex?!0:formData.vex:formData},dialog.buttonsToDOM=function(buttons){var $buttons;return $buttons=$('<div class="vex-dialog-buttons" />'),$.each(buttons,function(index,button){return $buttons.append($('<input type="'+button.type+'" />').val(button.text).addClass(button.className+" vex-dialog-button "+(0===index?"vex-first ":"")+(index===buttons.length-1?"vex-last ":"")).bind("click.vex",function(e){return button.click?button.click($(this).parents("."+vex.baseClassNames.content),e):void 0}))}),$buttons},dialog)},"function"==typeof define&&define.amd?define(["jquery","vex"],vexDialogFactory):"object"==typeof exports?module.exports=vexDialogFactory(require("jquery"),require("vex")):window.vex.dialog=vexDialogFactory(window.jQuery,window.vex)}.call(this);var ignore_date=new Date;ignore_date.setTime(ignore_date.getTime()+12096e5),jQuery(document).ready(function($){var li_subscribe_flag=$.cookie("li_subscribe"),preview_subscribe=leadin_get_parameter_by_name("preview-subscribe");leadin_subscribe_check_mobile($)||preview_subscribe?preview_subscribe&&(bind_leadin_subscribe_widget(leadin_get_parameter_by_name("lis_heading"),leadin_get_parameter_by_name("lis_desc"),leadin_get_parameter_by_name("lis_show_names"),leadin_get_parameter_by_name("lis_show_phone"),leadin_get_parameter_by_name("lis_btn_label"),leadin_get_parameter_by_name("lis_vex_class"),leadin_get_parameter_by_name("lis_confirmation")),subscribe.open()):li_subscribe_flag?"show"==li_subscribe_flag&&bind_leadin_subscribe_widget($("#leadin-subscribe-heading").val(),$("#leadin-subscribe-text").val(),$("#leadin-subscribe-name-fields").val(),$("#leadin-subscribe-phone-field").val(),$("#leadin-subscribe-btn-label").val(),$("#leadin-subscribe-vex-class").val(),$("#leadin-subscribe-confirmation").val()):leadin_check_visitor_status($.cookie("li_hash"),function(data){"vex_set"!=data?($.cookie("li_subscribe","show",{path:"/",domain:""}),bind_leadin_subscribe_widget($("#leadin-subscribe-heading").val(),$("#leadin-subscribe-text").val(),$("#leadin-subscribe-name-fields").val(),$("#leadin-subscribe-phone-field").val(),$("#leadin-subscribe-btn-label").val(),$("#leadin-subscribe-vex-class").val(),$("#leadin-subscribe-confirmation").val())):$.cookie("li_subscribe","ignore",{path:"/",domain:"",expires:ignore_date})})});
images/power-up-icon-aweber-connect.png ADDED
Binary file
images/power-up-icon-aweber-connect@2x.png ADDED
Binary file
images/power-up-icon-aweber-connect_small.png ADDED
Binary file
images/power-up-icon-aweber-connect_small@2x.png ADDED
Binary file
images/power-up-icon-campaign-monitor-connect.png ADDED
Binary file
images/power-up-icon-campaign-monitor-connect@2x.png ADDED
Binary file
images/power-up-icon-campaign-monitor-connect_small.png ADDED
Binary file
images/power-up-icon-campaign-monitor-connect_small@2x.png ADDED
Binary file
images/power-up-icon-getresponse-connect.png ADDED
Binary file
images/power-up-icon-getresponse-connect@2x.png ADDED
Binary file
images/power-up-icon-getresponse-connect_small.png ADDED
Binary file
images/power-up-icon-getresponse-connect_small@2x.png ADDED
Binary file
images/power-up-icon-getresponse-list-sync_small.png ADDED
Binary file
images/power-up-icon-getresponse-list-sync_small@2x.png ADDED
Binary file
images/powerup-icon-lookups.png ADDED
Binary file
images/powerup-icon-lookups@2x.png ADDED
Binary file
inc/class-emailer.php CHANGED
@@ -32,13 +32,6 @@ class LI_Emailer {
32
  // Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
33
  $body = wordwrap($body, 900, "\r\n");
34
 
35
- $from = $history->lead->lead_email;
36
- $headers = "From: " . $from . " <" . $from . ">\r\n";
37
- $headers.= "Reply-To: " . $from . " <" . $from . ">\r\n";
38
- $headers.= "X-Mailer: PHP/" . phpversion() . "\r\n";
39
- $headers.= "MIME-Version: 1.0\r\n";
40
- $headers.= "Content-type: text/html; charset=utf-8\r\n";
41
-
42
  // Get email from plugin settings, if none set, use admin email
43
  $options = get_option('leadin_options');
44
  $to = ( $options['li_email'] ? $options['li_email'] : get_bloginfo('admin_email') ); // Get email from plugin settings, if none set, use admin email
@@ -55,8 +48,38 @@ class LI_Emailer {
55
  $return_status = 'by a returning contact ';
56
 
57
  $subject = "Form submission " . $tag_status . $return_status . "on " . get_bloginfo('name') . " - " . $history->lead->lead_email;
58
- $email_sent = wp_mail($to, $subject, $body, $headers);
59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  return $email_sent;
62
  }
@@ -70,7 +93,8 @@ class LI_Emailer {
70
  function build_body ( $li_contact )
71
  {
72
  $format = '<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/><meta name="viewport" content="width=device-width"/></head><body style="width: 100%%;min-width: 100%%;-webkit-text-size-adjust: 100%%;-ms-text-size-adjust: 100%%;margin: 0;padding: 0;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;text-align: left;line-height: 19px;font-size: 14px;background-color: #f1f1f1;"><table class="body" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;height: 100%%;width: 100%%;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;background-color: #f1f1f1;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="center" align="center" valign="top" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: center;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><center style="width: 100%%;min-width: 580px;"><table class="container" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: inherit;width: 580px;margin: 0 auto;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;">%s%s%s%s%s</td></tr></table></center></td></tr></table></body></html>';
73
- $built_body = sprintf($format, $this->build_submission_details(get_bloginfo('url')), $this->build_contact_identity($li_contact->history->lead->lead_email), $this->build_sessions($li_contact->history), $this->build_enrichment_data(), $this->build_footer($li_contact));
 
74
 
75
  return $built_body;
76
  }
@@ -84,6 +108,7 @@ class LI_Emailer {
84
  function build_submission_details ( $url ) {
85
  $format = '<table class="row submission-detail" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="wrapper last" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;padding-right: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="twelve columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 580px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h3 style="color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 18px;">New submission on <a href="%s" style="color: #2ba6cb;text-decoration: none;">%s</a></h3></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td></tr></table>' . "\r\n";
86
  $built_submission_details = sprintf($format, $url, get_bloginfo('name'));
 
87
 
88
  return $built_submission_details;
89
  }
@@ -223,19 +248,193 @@ class LI_Emailer {
223
  return $built_source_url_params;
224
  }
225
 
226
-
227
  /**
228
  * Creates the data lookup content for the contact notificaiton email
229
  *
230
  * @param stdClass history from LI_Contact
231
  * @return string footer content
232
  */
233
- function build_enrichment_data ( ) {
234
- $built_enrichment_data = '<table class="row contact-details" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="wrapper last" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;padding-right: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="twelve columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 580px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h2 class="data-lookup-header" style="color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 20px;margin-bottom: 15px;">Data Lookup</h2><p class="data-lookup-limit" style="margin: 0;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;"><a href="http://leadin.com/pro-upgrade/?utm_source=Leadin%20Repo%20Plugin&utm_medium=New%20Contact%20Email&utm_campaign=Repo">Upgrade to Leadin Pro for free</a> to get unlimited data lookups!</p></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td></tr></table>';
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
  return $built_enrichment_data;
237
  }
238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  /**
240
  * Creates the footer content for the contact notificaiton email
241
  *
@@ -323,14 +522,7 @@ class LI_Emailer {
323
  $body .="You may also contact us at:<br/><a href='mailto:" . $leadin_email . "'>" . $leadin_email . "</a>";
324
  $body .= "</td></tr></table></td><td class='expander' style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: left;visibility: hidden;width: 0px;padding: 0;border: 0;' align='left' valign='top'></td></tr></table></td></tr></table>";
325
 
326
- // Build Powered by Leadin row
327
- if ( isset($options['premium']) )
328
- {
329
- if ( ! $options['premium'] )
330
- $body .= $this->build_powered_by_link();
331
- }
332
- else
333
- $body .= $this->build_powered_by_link();
334
 
335
  // @EMAIL - end form section
336
 
@@ -341,7 +533,7 @@ class LI_Emailer {
341
  // Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
342
  $body = wordwrap($body, 900, "\r\n");
343
 
344
- $headers = "From: Leadin <team@leadin.com>\r\n";
345
  $headers.= "Reply-To: Leadin <" . $from . ">\r\n";
346
  $headers.= "X-Mailer: PHP/" . phpversion() . "\r\n";
347
  $headers.= "MIME-Version: 1.0\r\n";
@@ -363,9 +555,64 @@ class LI_Emailer {
363
  $powered_by = '';
364
 
365
  $powered_by .= "<table class='row section' style='border-spacing: 0;border-collapse: collapse;vertical-align: top;text-align: left;width: 100%;position: relative;display: block;margin-top: 20px;padding: 0px;'><tr style='vertical-align: top;text-align: left;padding: 0;' align='left'><td class='wrapper last' style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: left;position: relative;padding: 0 0px 0 0;' align='left' valign='top'><table class='twelve columns' style='border-spacing: 0;border-collapse: collapse;vertical-align: top;text-align: left;width: 580px;margin: 0 auto;padding: 0;'><tr style='vertical-align: top;text-align: left;padding: 0;' align='left'><td style='padding: 10px 20px;' align='left' valign='top'><table style='border-spacing: 0;border-collapse: collapse;vertical-align: top;text-align: left;width: 100%;overflow: hidden;padding: 0;'><tr style='vertical-align: top;text-align: left;padding: 0;' align='left'><td style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: center;display: block;width: auto !important;font-size: 16px;padding: 10px 20px;' align='center' valign='top'>";
366
- $powered_by .="<div style='font-size: 11px; color: #888; padding: 0 0 5px 0;'>Powered by</div><a href='http://leadin.com/wordpress-subscribe-widget-plugin/?utm_campaign=subscribe_widget&utm_medium=email&utm_source=" . get_bloginfo('wpurl') . "'><img alt='Leadin' height='20px' width='99px' src='http://leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/leadin_logo_small_grey.png' alt='leadin.com'/></a>";
367
  $powered_by .= "</td></tr></table></td><td class='expander' style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: left;visibility: hidden;width: 0px;padding: 0;border: 0;' align='left' valign='top'></td></tr></table></td></tr></table>";
368
 
369
  return $powered_by;
370
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  }
32
  // Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
33
  $body = wordwrap($body, 900, "\r\n");
34
 
 
 
 
 
 
 
 
35
  // Get email from plugin settings, if none set, use admin email
36
  $options = get_option('leadin_options');
37
  $to = ( $options['li_email'] ? $options['li_email'] : get_bloginfo('admin_email') ); // Get email from plugin settings, if none set, use admin email
48
  $return_status = 'by a returning contact ';
49
 
50
  $subject = "Form submission " . $tag_status . $return_status . "on " . get_bloginfo('name') . " - " . $history->lead->lead_email;
 
51
 
52
+ $headers = "From: Leadin <notifications@leadin.com>\r\n";
53
+ $headers .= "Reply-To: Leadin <notifications@leadin.com>\r\n";
54
+ $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
55
+ $headers .= "MIME-Version: 1.0\r\n";
56
+ $headers .= "Content-type: text/html; charset=utf-8\r\n";
57
+
58
+ if ( isset($options['pro']) && $options['pro'] )
59
+ {
60
+ $email_sent = $this->send_email_via_sendgrid($to, $subject, $body, get_bloginfo('wpurl'));
61
+
62
+ if ( $email_sent )
63
+ {
64
+ leadin_track_plugin_activity('Contact Notification Sent', array('service' => 'sendgrid'));
65
+ }
66
+ else
67
+ {
68
+ $email_sent = wp_mail($to, $subject, $body, $headers);
69
+ leadin_track_plugin_activity('Contact Notification Sent', array('service' => 'php_mail'));
70
+ }
71
+ }
72
+ else
73
+ {
74
+ $headers = "From: Leadin <notifications@leadin.com>\r\n";
75
+ $headers .= "Reply-To: Leadin <notifications@leadin.com>\r\n";
76
+ $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";
77
+ $headers .= "MIME-Version: 1.0\r\n";
78
+ $headers .= "Content-type: text/html; charset=utf-8\r\n";
79
+
80
+ $email_sent = wp_mail($to, $subject, $body, $headers);
81
+ leadin_track_plugin_activity('Contact Notification Sent', array('service' => 'php_mail'));
82
+ }
83
 
84
  return $email_sent;
85
  }
93
  function build_body ( $li_contact )
94
  {
95
  $format = '<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"/><meta name="viewport" content="width=device-width"/></head><body style="width: 100%%;min-width: 100%%;-webkit-text-size-adjust: 100%%;-ms-text-size-adjust: 100%%;margin: 0;padding: 0;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;text-align: left;line-height: 19px;font-size: 14px;background-color: #f1f1f1;"><table class="body" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;height: 100%%;width: 100%%;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;background-color: #f1f1f1;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="center" align="center" valign="top" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: center;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><center style="width: 100%%;min-width: 580px;"><table class="container" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: inherit;width: 580px;margin: 0 auto;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;">%s%s%s%s%s</td></tr></table></center></td></tr></table></body></html>';
96
+
97
+ $built_body = sprintf($format, $this->build_submission_details(get_bloginfo('url')), $this->build_contact_identity($li_contact->history->lead->lead_email), $this->build_sessions($li_contact->history), $this->build_enrichment_data($li_contact), $this->build_footer($li_contact));
98
 
99
  return $built_body;
100
  }
108
  function build_submission_details ( $url ) {
109
  $format = '<table class="row submission-detail" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="wrapper last" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;padding-right: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="twelve columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 580px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h3 style="color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 18px;">New submission on <a href="%s" style="color: #2ba6cb;text-decoration: none;">%s</a></h3></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td></tr></table>' . "\r\n";
110
  $built_submission_details = sprintf($format, $url, get_bloginfo('name'));
111
+ $built_submission_details .= '<img src="' . $this->create_tracking_pixel() . '"/>';
112
 
113
  return $built_submission_details;
114
  }
248
  return $built_source_url_params;
249
  }
250
 
 
251
  /**
252
  * Creates the data lookup content for the contact notificaiton email
253
  *
254
  * @param stdClass history from LI_Contact
255
  * @return string footer content
256
  */
257
+ function build_enrichment_data ( $li_contact )
258
+ {
259
+ $built_enrichment_data = "";
260
+
261
+ if ( leadin_check_pro_user() )
262
+ {
263
+ $format = '<table class="row contact-details" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="wrapper last" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;padding-right: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="twelve columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 580px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h2 class="data-lookup-header" style="color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 20px;margin-bottom: 15px;">Data Lookup</h2><p class="data-lookup-limit" style="margin: 0;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;">You have <span class="green" style="font-weight: bold;color: green;">unlimited free data lookups remaining</span> this month.</p></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td></tr></table><table class="row contact-details" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;">%s%s</tr></table>';
264
+ $built_enrichment_personal = $this->build_enrichment_personal($li_contact);
265
+ $built_enrichment_data .= sprintf($format, ( $built_enrichment_personal ? $built_enrichment_personal : 'No dice' ), $this->build_enrichment_company($li_contact));
266
+ }
267
+ else
268
+ {
269
+ $built_enrichment_data = '<table class="row contact-details" style="border-spacing: 0;border-collapse: collapse;padding: 0px;vertical-align: top;text-align: left;width: 100%%;position: relative;display: block;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="wrapper last" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;padding-right: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="twelve columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 580px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h2 class="data-lookup-header" style="color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 20px;margin-bottom: 15px;">Data Lookup</h2><p class="data-lookup-limit" style="margin: 0;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;"><a href="'. admin_url() . 'admin.php?page=leadin_pro_upgrade">Upgrade to Leadin Pro for free</a> to get unlimited data lookups!</p></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td></tr></table>';
270
+ }
271
 
272
  return $built_enrichment_data;
273
  }
274
 
275
+ /**
276
+ * Creates the personal info column in the data lookup content for the contact notificaiton email
277
+ *
278
+ * @param stdClass history from LI_Contact
279
+ * @return string footer content
280
+ */
281
+ function build_enrichment_personal ( $li_contact )
282
+ {
283
+ $properties = ( isset($li_contact->history->lead->social_data->properties) ? $li_contact->history->lead->social_data->properties : '' );
284
+ $built_personal_data = "";
285
+
286
+ if ( ! isset($properties->primary) && empty($properties->social_profiles) )
287
+ {
288
+ $format = '<td class="wrapper" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="six columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 280px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><p class="contact-description" style="margin: 0;color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;">%s</p></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td>';
289
+ $built_personal_data .= sprintf($format, 'We couldn\'t find any personal info for this contact.');
290
+
291
+ return $built_personal_data;
292
+ }
293
+
294
+ $format = '<td class="wrapper" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="six columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 280px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h3 class="contact-name" style="color: #444;font-family: Helvetica, Arial, sans-serif;font-weight: bold;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 14px;">%s</h3><h4 class="contact-name-subhead" style="color: #444;font-family: Helvetica, Arial, sans-serif;font-weight: 400;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 14px;margin-bottom: 15px;">%s</h4><p class="contact-description" style="margin: 0;color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;">%s</p>%s</td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td>';
295
+ $format = '<td class="wrapper" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="six columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 280px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h3 class="contact-name" style="color: #444;font-family: Helvetica, Arial, sans-serif;font-weight: bold;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 14px;">%s</h3><h4 class="contact-name-subhead" style="color: #444;font-family: Helvetica, Arial, sans-serif;font-weight: 400;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 14px;margin-bottom: 15px;">%s</h4><p class="contact-description" style="margin: 0;color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;">%s</p>%s</td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td>';
296
+
297
+ $contact_name = $li_contact->history->lead->lead_first_name . ' ' . $li_contact->history->lead->lead_last_name;
298
+
299
+ $contact_job_title = '';
300
+ if ( isset($properties->primary) )
301
+ $contact_job_title = $properties->primary->title . ( $properties->primary->company_name ? ' - ' . $properties->primary->company_name : '' );
302
+
303
+ $contact_bio = ( ! empty($properties->description) ? $properties->description : '');
304
+
305
+ $built_personal_data .= sprintf($format, $contact_name, $contact_job_title, $contact_bio, $this->build_enrichment_personal_fields($li_contact));
306
+
307
+ return $built_personal_data;
308
+ }
309
+
310
+ /**
311
+ * Creates the personal info column in the data lookup content for the contact notificaiton email
312
+ *
313
+ * @param stdClass history from LI_Contact
314
+ * @return string footer content
315
+ */
316
+ function build_enrichment_personal_fields ( $li_contact ) {
317
+ $built_personal_data_fields = "";
318
+
319
+ $format = '<p class="lead-timeline__submission-field" style="margin: 0;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;"><label class="lead-timeline__submission-label" style="text-transform: uppercase;font-size: 12px;color: #999;letter-spacing: 0.05em;">%s</label><br/>%s</p>';
320
+
321
+ if ( isset($li_contact->history->lead->social_data->properties->social_profiles) )
322
+ {
323
+ if ( count($li_contact->history->lead->social_data->properties->social_profiles) )
324
+ {
325
+ foreach ( $li_contact->history->lead->social_data->properties->social_profiles as $key => $profile )
326
+ {
327
+ $field_label = $profile->typename;
328
+ $field_data = '<a href="' . leadin_safe_social_profile_url($profile->url) . '" target="_blank">' . ( $profile->typeid == 'twitter' ? '@' : '' ) . ( $profile->typeid == 'linkedin' ? '/in/' : '' ) . $profile->username . '</a>';
329
+
330
+ $built_personal_data_fields .= sprintf($format, $field_label, $field_data);
331
+ }
332
+ }
333
+ }
334
+
335
+ return $built_personal_data_fields;
336
+ }
337
+
338
+ /**
339
+ * Creates the personal info column in the data lookup content for the contact notificaiton email
340
+ *
341
+ * @param stdClass history from LI_Contact
342
+ * @return string footer content
343
+ */
344
+ function build_enrichment_company ( $li_contact )
345
+ {
346
+ $built_company_data = "";
347
+
348
+ $company_data_exists = FALSE;
349
+ $properties = ( isset($li_contact->history->lead->company_data->properties) ? $li_contact->history->lead->company_data->properties : '' );
350
+
351
+ $company_name = '';
352
+ $company_location = '';
353
+ $company_bio = '';
354
+
355
+ if ( isset($properties->name) && $properties->name )
356
+ $company_name .= $properties->name;
357
+
358
+ if ( isset($properties->city) && $properties->city )
359
+ {
360
+ $company_location .= $properties->city;
361
+ $company_data_exists = TRUE;
362
+ }
363
+
364
+ if ( isset($properties->state) && $properties->state )
365
+ {
366
+ $company_location .= ', ' . $properties->state;
367
+ $company_data_exists = TRUE;
368
+ }
369
+
370
+ if ( isset($properties->country) && $properties->country )
371
+ {
372
+ $company_location .= ', ' . $properties->country;
373
+ $company_data_exists = TRUE;
374
+ }
375
+
376
+ if ( isset($properties->overview) )
377
+ {
378
+ if ( strlen($properties->overview) < 260 )
379
+ $company_bio = $properties->overview;
380
+ else
381
+ $company_bio = substr($properties->overview, 0, strpos($properties->overview, '.', 260)) . ' ...';
382
+
383
+ $company_data_exists = TRUE;
384
+ }
385
+
386
+ if ( $company_data_exists )
387
+ {
388
+ $format = '<td class="wrapper" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="six columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 280px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><h3 class="contact-name" style="color: #444;font-family: Helvetica, Arial, sans-serif;font-weight: bold;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 14px;">%s</h3><h4 class="contact-name-subhead" style="color: #444;font-family: Helvetica, Arial, sans-serif;font-weight: 400;padding: 0;margin: 0;text-align: left;line-height: 1.3;word-break: normal;font-size: 14px;margin-bottom: 15px;">%s</h4><p class="contact-description" style="margin: 0;color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;">%s</p>%s</td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td>';
389
+ $built_company_data .= sprintf($format, $company_name, $company_location, $company_bio, $this->build_enrichment_company_fields($li_contact));
390
+ }
391
+ else
392
+ {
393
+ $format = '<td class="wrapper" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 10px 20px 0px 0px;vertical-align: top;text-align: left;position: relative;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><table class="six columns" style="border-spacing: 0;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;margin: 0 auto;width: 280px;"><tr style="padding: 0;vertical-align: top;text-align: left;"><td class="text-pad" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0px 0px 10px;vertical-align: top;text-align: left;padding-left: 10px;padding-right: 10px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"><p class="contact-description" style="margin: 0;color: #666;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;">%s</p></td><td class="expander" style="word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse;padding: 0;vertical-align: top;text-align: left;visibility: hidden;width: 0px;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;margin: 0;line-height: 19px;font-size: 14px;"></td></tr></table></td>';
394
+ $built_company_data .= sprintf($format, 'We couldn\'t find any company info for this contact.');
395
+ }
396
+
397
+ return $built_company_data;
398
+ }
399
+
400
+ /**
401
+ * Creates the company info column in the data lookup content for the contact notificaiton email
402
+ *
403
+ * @param stdClass history from LI_Contact
404
+ * @return string footer content
405
+ */
406
+ function build_enrichment_company_fields ( $li_contact ) {
407
+ $properties = $li_contact->history->lead->company_data->properties;
408
+
409
+ $built_company_data_fields = "";
410
+
411
+ $format = '<p class="lead-timeline__submission-field" style="margin: 0;color: #222222;font-family: Helvetica, Arial, sans-serif;font-weight: normal;padding: 0;text-align: left;line-height: 19px;font-size: 14px;margin-bottom: 10px;"><label class="lead-timeline__submission-label" style="text-transform: uppercase;font-size: 12px;color: #999;letter-spacing: 0.05em;">%s</label><br/>%s</p>';
412
+
413
+ if ( !empty($properties->facebookpageurl) )
414
+ {
415
+ $field_label = "Facebook";
416
+ $field_data = '<a href="' . $properties->facebookpageurl . '" target="_blank">' . $properties->name . '</a>';
417
+ $built_company_data_fields .= sprintf($format, $field_label, $field_data);
418
+ }
419
+
420
+ if ( !empty($properties->twitterusername) )
421
+ {
422
+ $field_label = "Twitter";
423
+ $field_data = '<a href="' . $properties->twitterurl . '" target="_blank">' . '@' . $properties->twitterusername . '</a>';
424
+ $built_company_data_fields .= sprintf($format, $field_label, $field_data);
425
+ }
426
+
427
+ if ( !empty($properties->linkedinurl) )
428
+ {
429
+ $field_label = "LinkedIn";
430
+ $field_data = '<a href="' . $properties->linkedinurl . '" target="_blank">' . $properties->name . '</a>';
431
+ $built_company_data_fields .= sprintf($format, $field_label, $field_data);
432
+ }
433
+
434
+
435
+ return $built_company_data_fields;
436
+ }
437
+
438
  /**
439
  * Creates the footer content for the contact notificaiton email
440
  *
522
  $body .="You may also contact us at:<br/><a href='mailto:" . $leadin_email . "'>" . $leadin_email . "</a>";
523
  $body .= "</td></tr></table></td><td class='expander' style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: left;visibility: hidden;width: 0px;padding: 0;border: 0;' align='left' valign='top'></td></tr></table></td></tr></table>";
524
 
525
+ $body .= $this->build_powered_by_link();
 
 
 
 
 
 
 
526
 
527
  // @EMAIL - end form section
528
 
533
  // Each line in an email can only be 998 characters long, so lines need to be broken with a wordwrap
534
  $body = wordwrap($body, 900, "\r\n");
535
 
536
+ $headers = "From: Leadin <notifications@leadin.com>\r\n";
537
  $headers.= "Reply-To: Leadin <" . $from . ">\r\n";
538
  $headers.= "X-Mailer: PHP/" . phpversion() . "\r\n";
539
  $headers.= "MIME-Version: 1.0\r\n";
555
  $powered_by = '';
556
 
557
  $powered_by .= "<table class='row section' style='border-spacing: 0;border-collapse: collapse;vertical-align: top;text-align: left;width: 100%;position: relative;display: block;margin-top: 20px;padding: 0px;'><tr style='vertical-align: top;text-align: left;padding: 0;' align='left'><td class='wrapper last' style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: left;position: relative;padding: 0 0px 0 0;' align='left' valign='top'><table class='twelve columns' style='border-spacing: 0;border-collapse: collapse;vertical-align: top;text-align: left;width: 580px;margin: 0 auto;padding: 0;'><tr style='vertical-align: top;text-align: left;padding: 0;' align='left'><td style='padding: 10px 20px;' align='left' valign='top'><table style='border-spacing: 0;border-collapse: collapse;vertical-align: top;text-align: left;width: 100%;overflow: hidden;padding: 0;'><tr style='vertical-align: top;text-align: left;padding: 0;' align='left'><td style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: center;display: block;width: auto !important;font-size: 16px;padding: 10px 20px;' align='center' valign='top'>";
558
+ $powered_by .="<div style='font-size: 11px; color: #888; padding: 0 0 5px 0;'>Powered by</div><a href='http://leadin.com/wordpress-subscribe-widget-plugin?utm_source=virality&utm_medium=referral&utm_term=" . get_bloginfo('wpurl') . "&utm_content=e11&utm_campaign=subscribe%20confirmation%20email'><img alt='Leadin' height='20px' width='99px' src='http://leadin.com/wp-content/themes/LeadIn-WP-Theme/library/images/logos/leadin_logo_small_grey.png' alt='leadin.com'/></a>";
559
  $powered_by .= "</td></tr></table></td><td class='expander' style='word-break: break-word;-webkit-hyphens: auto;-moz-hyphens: auto;hyphens: auto;border-collapse: collapse !important;vertical-align: top;text-align: left;visibility: hidden;width: 0px;padding: 0;border: 0;' align='left' valign='top'></td></tr></table></td></tr></table>";
560
 
561
  return $powered_by;
562
  }
563
+
564
+ /**
565
+ * Creates Mixpanel tracking email pixel
566
+ *
567
+ * @return string specs @ https://mixpanel.com/docs/api-documentation/pixel-based-event-tracking
568
+ */
569
+ function create_tracking_pixel ( )
570
+ {
571
+ $url_properties = array(
572
+ 'token' => MIXPANEL_PROJECT_TOKEN
573
+ );
574
+
575
+ $leadin_user = leadin_get_current_user();
576
+ $leadin_user_properties = array(
577
+ 'distinct_id' => $leadin_user['user_id'],
578
+ '$wp-url' => $leadin_user['wp_url'],
579
+ '$wp-version' => $leadin_user['wp_version'],
580
+ '$li-version' => $leadin_user['li_version']
581
+ );
582
+
583
+ $properties = array_merge($url_properties, $leadin_user_properties);
584
+
585
+ $params = array ( 'event' => 'Contact Notification Opened', 'properties' => $properties );
586
+
587
+ return 'http://api.mixpanel.com/track/?data=' . base64_encode(json_encode($params)) . '&ip=1&img=1';
588
+ }
589
+
590
+ /**
591
+ * Creates Mixpanel tracking email pixel
592
+ *
593
+ * @param string email address to send notification to
594
+ * @param string subject line for contact notification email
595
+ * @param string html body of email
596
+ * @return string specs @ https://mixpanel.com/docs/api-documentation/pixel-based-event-tracking
597
+ */
598
+ function send_email_via_sendgrid ( $to = '', $subject = '', $body = '', $domain = '' )
599
+ {
600
+ $fields = array(
601
+ 'to_email' => urlencode($to),
602
+ 'subject' => urlencode($subject),
603
+ 'message' => urlencode($body),
604
+ 'domain' => urlencode($domain)
605
+ );
606
+
607
+ $fields_string = http_build_query($fields);
608
+
609
+ $ch = curl_init();
610
+ curl_setopt($ch,CURLOPT_URL, 'http://leadin.com/pro/notifications/sendgrid_email.php');
611
+ curl_setopt($ch,CURLOPT_POST, 1);
612
+ curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
613
+ $result = curl_exec($ch);
614
+ curl_close($ch);
615
+
616
+ return $result;
617
+ }
618
  }
inc/class-leadin-updater.php CHANGED
@@ -19,9 +19,7 @@ class WPLeadInUpdater {
19
  */
20
  function __construct ( $update_type = 'beta' )
21
  {
22
- if ( $update_type == 'beta' )
23
- $this->api_url = 'http://leadin.com/plugins/index.php';
24
- else if ( $update_type == 'pro' )
25
  $this->api_url = 'http://leadin.com/pro/index.php';
26
 
27
  $this->plugin_slug = LEADIN_PLUGIN_SLUG;
19
  */
20
  function __construct ( $update_type = 'beta' )
21
  {
22
+ if ( $update_type == 'pro' )
 
 
23
  $this->api_url = 'http://leadin.com/pro/index.php';
24
 
25
  $this->plugin_slug = LEADIN_PLUGIN_SLUG;
inc/class-leadin.php CHANGED
@@ -30,6 +30,7 @@ class WPLeadIn {
30
  }
31
  else
32
  {
 
33
  if ( in_array($GLOBALS['pagenow'], array('wp-login.php', 'wp-register.php')) )
34
  add_action('login_enqueue_scripts', array($this, 'add_leadin_frontend_scripts'));
35
  else
@@ -48,7 +49,7 @@ class WPLeadIn {
48
  {
49
  wp_register_script('leadin-tracking', LEADIN_PATH . '/assets/js/build/leadin-tracking.min.js', array ('jquery'), FALSE, TRUE);
50
  wp_enqueue_script('leadin-tracking');
51
-
52
  // replace https with http for admin-ajax calls for SSLed backends
53
  $admin_url = admin_url('admin-ajax.php');
54
  wp_localize_script(
@@ -61,7 +62,7 @@ class WPLeadIn {
61
  /**
62
  * Adds Leadin link to top-level admin bar
63
  */
64
- function add_leadin_link_to_admin_bar ( $wp_admin_bar )
65
  {
66
  global $wp_version;
67
 
@@ -73,7 +74,7 @@ class WPLeadIn {
73
 
74
  $args = array(
75
  'id' => 'leadin-admin-menu',
76
- 'title' => '<span class="ab-icon" '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? ' style="margin-top: 3px;"' : ''). '><img src="' . content_url() . '/plugins/leadin/images/leadin-svg-icon.svg" style="height:16px; width:16px;"></span><span class="ab-label">Leadin</span>', // alter the title of existing node
77
  'parent' => FALSE, // set parent to false to make it a top level (parent) node
78
  'href' => get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_stats',
79
  'meta' => array('title' => 'Leadin')
@@ -107,12 +108,13 @@ class WPLeadIn {
107
  $power_up->link_uri = $headers['uri'];
108
  $power_up->description = $headers['description'];
109
  $power_up->icon = $headers['icon'];
 
110
  $power_up->permanent = ( $headers['permanent'] == 'Yes' ? 1 : 0 );
111
  $power_up->auto_activate = ( $headers['auto_activate'] == 'Yes' ? 1 : 0 );
112
  $power_up->hidden = ( $headers['hidden'] == 'Yes' ? 1 : 0 );
113
  $power_up->curl_required = ( $headers['curl_required'] == 'Yes' ? 1 : 0 );
114
- $power_up->activated = $headers['activated'];
115
-
116
  // Set the small icons HTML for the settings page
117
  if ( strstr($headers['icon_small'], 'dashicons') )
118
  $power_up->icon_small = '<span class="dashicons ' . $headers['icon_small'] . '"></span>';
@@ -165,7 +167,8 @@ class WPLeadIn {
165
  'permanent' => 'Permanently Enabled',
166
  'power_up_tags' => 'Power-up Tags',
167
  'hidden' => 'Hidden',
168
- 'curl_required' => 'cURL Required'
 
169
  );
170
 
171
  $file = self::get_power_up_path( self::get_power_up_slug( $power_up ) );
@@ -211,10 +214,15 @@ class WPLeadIn {
211
  }
212
 
213
  $files = leadin_sort_power_ups($files, array(
214
- LEADIN_PLUGIN_DIR . '/power-ups/contacts.php',
 
215
  LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php',
216
  LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php',
217
- LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php'
 
 
 
 
218
  ));
219
 
220
  closedir( $dir );
@@ -247,7 +255,7 @@ class WPLeadIn {
247
  return array();
248
  }
249
 
250
- public static function activate_power_up ( $power_up_slug, $exit = TRUE )
251
  {
252
  if ( ! strlen( $power_up_slug ) )
253
  return FALSE;
@@ -278,12 +286,12 @@ class WPLeadIn {
278
  }
279
  }
280
 
281
- public static function deactivate_power_up ( $power_up_slug, $exit = TRUE )
282
  {
283
  if ( ! strlen( $power_up_slug ) )
284
  return FALSE;
285
 
286
- // If it's already deactivated, then don't do it again
287
  $active = self::is_power_up_active($power_up_slug);
288
  if ( ! $active )
289
  return TRUE;
@@ -297,61 +305,7 @@ class WPLeadIn {
297
  {
298
  exit;
299
  }
300
- }
301
 
302
- /**
303
- * Throws an error for when the premium version and the free version are activated in tandem
304
- */
305
- function deactivate_leadin_notice ()
306
- {
307
- ?>
308
- <div id="message" class="update-nag">
309
- <?php
310
- _e(
311
- '<p>' .
312
- '<a style="font-size: 14px; float: right; color: #ccc; text-decoration: none; margin-top: -15px;" href="#">&#10006;</a>' .
313
- '<b>Leadin Pro is now avaialble!</b>' .
314
- '</p>' .
315
- '<p>' .
316
- 'Leadin Pro includes all the features you\'ve come to love from our plugin along with some powerful new ones too. <a href="#">See all the features</a>' .
317
- '</p>' .
318
- '<p>' .
319
- 'The launch of Leadin Pro also means that we are no longer supporting the version of Leadin hosted by the WordPress Plugin Directory.' .
320
- 'Read more about why we are making this change on <a href="http://leadin.com/the-move-to-pro">the Leadin blog</a>. ' .
321
- '</p>' .
322
- '<p>' .
323
- 'If you run have any questions or concerns, please feel free to email us - <a href="mailto:support@leadin.com">support@leadin.com</a>' .
324
- '</p>' .
325
- '<p>' .
326
- '<a class="button button-primary" href="http://leadin.com">Download Leadin Pro for Free</a> ' .
327
- '</p>',
328
- 'my-text-domain'
329
- );
330
- ?>
331
- </div>
332
- <?php
333
- }
334
-
335
- /* Display a notice that can be dismissed */
336
-
337
- function example_admin_notice() {
338
- global $current_user ;
339
- $user_id = $current_user->ID;
340
- /* Check that the user hasn't already clicked to ignore the message */
341
- if ( ! get_user_meta($user_id, 'example_ignore_notice') ) {
342
- echo '<div class="updated"><p>';
343
- printf(__('This is an annoying nag message. Why do people make these? | <a href="%1$s">Hide Notice</a>'), '?example_nag_ignore=0');
344
- echo "</p></div>";
345
- }
346
- }
347
-
348
- function example_nag_ignore() {
349
- global $current_user;
350
- $user_id = $current_user->ID;
351
- /* If user clicks to ignore the notice, add that to their user meta */
352
- if ( isset($_GET['example_nag_ignore']) && '0' == $_GET['example_nag_ignore'] ) {
353
- add_user_meta($user_id, 'example_ignore_notice', 'true', true);
354
- }
355
  }
356
  }
357
 
30
  }
31
  else
32
  {
33
+ // Adds the leadin-tracking script to wp-login.php page which doesnt hook into the enqueue logic
34
  if ( in_array($GLOBALS['pagenow'], array('wp-login.php', 'wp-register.php')) )
35
  add_action('login_enqueue_scripts', array($this, 'add_leadin_frontend_scripts'));
36
  else
49
  {
50
  wp_register_script('leadin-tracking', LEADIN_PATH . '/assets/js/build/leadin-tracking.min.js', array ('jquery'), FALSE, TRUE);
51
  wp_enqueue_script('leadin-tracking');
52
+
53
  // replace https with http for admin-ajax calls for SSLed backends
54
  $admin_url = admin_url('admin-ajax.php');
55
  wp_localize_script(
62
  /**
63
  * Adds Leadin link to top-level admin bar
64
  */
65
+ function add_leadin_link_to_admin_bar ( $wp_admin_bar )
66
  {
67
  global $wp_version;
68
 
74
 
75
  $args = array(
76
  'id' => 'leadin-admin-menu',
77
+ 'title' => '<span class="ab-icon" '. ( $wp_version < 3.8 && !is_plugin_active('mp6/mp6.php') ? ' style="margin-top: 3px;"' : ''). '><img src="data:image/svg+xml;base64,' . base64_encode(file_get_contents(LEADIN_PATH . '/images/leadin-svg-icon.svg')). '"></span><span class="ab-label">Leadin</span>', // alter the title of existing node
78
  'parent' => FALSE, // set parent to false to make it a top level (parent) node
79
  'href' => get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_stats',
80
  'meta' => array('title' => 'Leadin')
108
  $power_up->link_uri = $headers['uri'];
109
  $power_up->description = $headers['description'];
110
  $power_up->icon = $headers['icon'];
111
+ $power_up->activated = $headers['activated'];
112
  $power_up->permanent = ( $headers['permanent'] == 'Yes' ? 1 : 0 );
113
  $power_up->auto_activate = ( $headers['auto_activate'] == 'Yes' ? 1 : 0 );
114
  $power_up->hidden = ( $headers['hidden'] == 'Yes' ? 1 : 0 );
115
  $power_up->curl_required = ( $headers['curl_required'] == 'Yes' ? 1 : 0 );
116
+ $power_up->pro_only = ( $headers['pro_only'] == 'Yes' ? 1 : 0 );
117
+
118
  // Set the small icons HTML for the settings page
119
  if ( strstr($headers['icon_small'], 'dashicons') )
120
  $power_up->icon_small = '<span class="dashicons ' . $headers['icon_small'] . '"></span>';
167
  'permanent' => 'Permanently Enabled',
168
  'power_up_tags' => 'Power-up Tags',
169
  'hidden' => 'Hidden',
170
+ 'curl_required' => 'cURL Required',
171
+ 'pro_only' => 'Pro Only'
172
  );
173
 
174
  $file = self::get_power_up_path( self::get_power_up_slug( $power_up ) );
214
  }
215
 
216
  $files = leadin_sort_power_ups($files, array(
217
+ LEADIN_PLUGIN_DIR . '/power-ups/contacts.php',
218
+ LEADIN_PLUGIN_DIR . '/power-ups/lookups.php',
219
  LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php',
220
  LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php',
221
+ LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php',
222
+ LEADIN_PLUGIN_DIR . '/power-ups/aweber-connect.php',
223
+ LEADIN_PLUGIN_DIR . '/power-ups/campaign-monitor-connect.php',
224
+ LEADIN_PLUGIN_DIR . '/power-ups/getresponse-connect.php',
225
+ LEADIN_PLUGIN_DIR . '/power-ups/beta-program.php'
226
  ));
227
 
228
  closedir( $dir );
255
  return array();
256
  }
257
 
258
+ public static function activate_power_up( $power_up_slug, $exit = TRUE )
259
  {
260
  if ( ! strlen( $power_up_slug ) )
261
  return FALSE;
286
  }
287
  }
288
 
289
+ public static function deactivate_power_up( $power_up_slug, $exit = TRUE )
290
  {
291
  if ( ! strlen( $power_up_slug ) )
292
  return FALSE;
293
 
294
+ // If it's already active, then don't do it again
295
  $active = self::is_power_up_active($power_up_slug);
296
  if ( ! $active )
297
  return TRUE;
305
  {
306
  exit;
307
  }
 
308
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  }
310
  }
311
 
inc/leadin-ajax-functions.php CHANGED
@@ -175,11 +175,11 @@ function leadin_insert_form_submission ()
175
  $contact = $wpdb->get_row($q);
176
 
177
  // Check if either of the names field are set and a value was filled out that's different than the existing name field
178
- $lead_first_name = $contact->lead_first_name;
179
  if ( strlen($first_name) && $lead_first_name != $first_name )
180
  $lead_first_name = $first_name;
181
 
182
- $lead_last_name = $contact->lead_last_name;
183
  if ( strlen($last_name) && $lead_last_name != $last_name )
184
  $lead_last_name = $last_name;
185
 
@@ -188,7 +188,7 @@ function leadin_insert_form_submission ()
188
  $existing_contacts = $wpdb->get_results($q);
189
 
190
  // Setup the string for the existing hashkeys
191
- $existing_contact_hashkeys = $contact->merged_hashkeys;
192
  if ( $contact->merged_hashkeys && count($existing_contacts) )
193
  $existing_contact_hashkeys .= ',';
194
 
@@ -277,11 +277,10 @@ function leadin_insert_form_submission ()
277
  // e.g. leadin_constant_contact_connect_wp
278
  $leadin_esp_wp = 'leadin_' . $synced_list['esp'] . '_connect_wp';
279
  global ${$leadin_esp_wp};
280
-
281
- if ( isset(${$leadin_esp_wp}) )
282
  {
283
- if ( ${$leadin_esp_wp}->activated )
284
- ${$leadin_esp_wp}->push_contact_to_list($synced_list['list_id'], $email, $first_name, $last_name, $phone);
285
  }
286
  }
287
  }
@@ -290,6 +289,7 @@ function leadin_insert_form_submission ()
290
  }
291
 
292
  // Apply the tag relationship to contacts for class rules
 
293
  if ( $form_selector_classes )
294
  $form_classes = explode(',', $form_selector_classes);
295
 
@@ -316,8 +316,10 @@ function leadin_insert_form_submission ()
316
  $leadin_esp_wp = 'leadin_' . $synced_list['esp'] . '_connect_wp';
317
  global ${$leadin_esp_wp};
318
 
319
- if ( ${$leadin_esp_wp}->activated )
 
320
  ${$leadin_esp_wp}->push_contact_to_list($synced_list['list_id'], $email, $first_name, $last_name, $phone);
 
321
  }
322
  }
323
  }
@@ -342,6 +344,8 @@ function leadin_insert_form_submission ()
342
  else if ( strstr($form_selector_id, 'commentform') )
343
  $contact_type = 'comment';
344
 
 
 
345
  return $rows_updated;
346
  }
347
 
@@ -385,6 +389,7 @@ add_action('wp_ajax_nopriv_leadin_check_visitor_status', 'leadin_check_visitor_s
385
  */
386
  function leadin_subscribe_show ()
387
  {
 
388
  die();
389
  }
390
 
@@ -400,6 +405,8 @@ function leadin_get_posts_and_pages ( )
400
  {
401
  global $wpdb;
402
 
 
 
403
  $search_term = $_POST['search_term'];
404
 
405
  $q = $wpdb->prepare("SELECT post_title, post_name FROM " . $wpdb->prefix . "posts WHERE post_status = 'publish' AND ( post_name LIKE '%%%s%%' OR post_title LIKE '%%%s%%' ) GROUP BY post_name ORDER BY post_date DESC LIMIT 25", $search_term, $search_term);
@@ -428,6 +435,8 @@ function leadin_get_form_selectors ( )
428
  {
429
  global $wpdb;
430
 
 
 
431
  $search_term = $_POST['search_term'];
432
  $tagger = new LI_Tag_Editor();
433
 
@@ -477,4 +486,56 @@ function leadin_get_form_selectors ( )
477
  add_action('wp_ajax_leadin_get_form_selectors', 'leadin_get_form_selectors'); // Call when user logged in
478
  add_action('wp_ajax_nopriv_leadin_get_form_selectors', 'leadin_get_form_selectors'); // Call when user is not logged in
479
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
480
  ?>
175
  $contact = $wpdb->get_row($q);
176
 
177
  // Check if either of the names field are set and a value was filled out that's different than the existing name field
178
+ $lead_first_name = ( isset($contact->lead_first_name) ? $contact->lead_first_name : '' );
179
  if ( strlen($first_name) && $lead_first_name != $first_name )
180
  $lead_first_name = $first_name;
181
 
182
+ $lead_last_name = ( isset($contact->lead_last_name) ? $contact->lead_last_name : '' );
183
  if ( strlen($last_name) && $lead_last_name != $last_name )
184
  $lead_last_name = $last_name;
185
 
188
  $existing_contacts = $wpdb->get_results($q);
189
 
190
  // Setup the string for the existing hashkeys
191
+ $existing_contact_hashkeys = ( isset($contact->merged_hashkeys) ? $contact->merged_hashkeys : '' );
192
  if ( $contact->merged_hashkeys && count($existing_contacts) )
193
  $existing_contact_hashkeys .= ',';
194
 
277
  // e.g. leadin_constant_contact_connect_wp
278
  $leadin_esp_wp = 'leadin_' . $synced_list['esp'] . '_connect_wp';
279
  global ${$leadin_esp_wp};
280
+
281
+ if ( isset(${$leadin_esp_wp}->activated) && ${$leadin_esp_wp}->activated )
282
  {
283
+ ${$leadin_esp_wp}->push_contact_to_list($synced_list['list_id'], $email, $first_name, $last_name, $phone);
 
284
  }
285
  }
286
  }
289
  }
290
 
291
  // Apply the tag relationship to contacts for class rules
292
+ $form_classes = '';
293
  if ( $form_selector_classes )
294
  $form_classes = explode(',', $form_selector_classes);
295
 
316
  $leadin_esp_wp = 'leadin_' . $synced_list['esp'] . '_connect_wp';
317
  global ${$leadin_esp_wp};
318
 
319
+ if ( isset(${$leadin_esp_wp}->activated) && ${$leadin_esp_wp}->activated )
320
+ {
321
  ${$leadin_esp_wp}->push_contact_to_list($synced_list['list_id'], $email, $first_name, $last_name, $phone);
322
+ }
323
  }
324
  }
325
  }
344
  else if ( strstr($form_selector_id, 'commentform') )
345
  $contact_type = 'comment';
346
 
347
+ leadin_track_plugin_activity("New lead", array("contact_type" => $contact_type));
348
+
349
  return $rows_updated;
350
  }
351
 
389
  */
390
  function leadin_subscribe_show ()
391
  {
392
+ leadin_track_plugin_activity('widget shown');
393
  die();
394
  }
395
 
405
  {
406
  global $wpdb;
407
 
408
+ leadin_track_plugin_activity('Filter action clicked', array( "filter_type" => "page" ));
409
+
410
  $search_term = $_POST['search_term'];
411
 
412
  $q = $wpdb->prepare("SELECT post_title, post_name FROM " . $wpdb->prefix . "posts WHERE post_status = 'publish' AND ( post_name LIKE '%%%s%%' OR post_title LIKE '%%%s%%' ) GROUP BY post_name ORDER BY post_date DESC LIMIT 25", $search_term, $search_term);
435
  {
436
  global $wpdb;
437
 
438
+ leadin_track_plugin_activity('Filter action clicked', array( "filter_type" => "form" ));
439
+
440
  $search_term = $_POST['search_term'];
441
  $tagger = new LI_Tag_Editor();
442
 
486
  add_action('wp_ajax_leadin_get_form_selectors', 'leadin_get_form_selectors'); // Call when user logged in
487
  add_action('wp_ajax_nopriv_leadin_get_form_selectors', 'leadin_get_form_selectors'); // Call when user is not logged in
488
 
489
+ /**
490
+ * Sets the Pro flag for the Leadin Pro upgrade
491
+ *
492
+ */
493
+ function leadin_upgrade_to_pro ( )
494
+ {
495
+ global $wpdb;
496
+
497
+ $options = get_option('leadin_options');
498
+ if ( isset($options['pro']) && $options['pro'] )
499
+ {
500
+ echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_contacts';
501
+ }
502
+ else
503
+ {
504
+ $updated = leadin_update_option('leadin_options', 'pro', 1);
505
+ echo get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_contacts';
506
+ }
507
+
508
+ WPLeadIn::activate_power_up('lookups', FALSE);
509
+
510
+ // Create the user in Segment
511
+ $traits = leadin_get_segment_traits();
512
+ $traits["last_activated"] = date("Y-m-d H:i:s");
513
+ $traits["li-status"] = "activated";
514
+ leadin_set_user_properties($traits);
515
+
516
+ leadin_track_plugin_activity("Upgraded to Pro");
517
+
518
+ die();
519
+ }
520
+
521
+ add_action('wp_ajax_leadin_upgrade_to_pro', 'leadin_upgrade_to_pro'); // Call when user logged in
522
+ add_action('wp_ajax_nopriv_leadin_upgrade_to_pro', 'leadin_upgrade_to_pro'); // Call when user is not logged in
523
+
524
+ /**
525
+ * Checks the first entry in the pageviews table and echos flag to Javascript
526
+ *
527
+ */
528
+ function leadin_check_installation_date ( )
529
+ {
530
+ if ( leadin_check_first_pageview_data() )
531
+ echo 1;
532
+ else
533
+ echo 0;
534
+
535
+ die();
536
+ }
537
+
538
+ add_action('wp_ajax_leadin_check_installation_date', 'leadin_check_installation_date'); // Call when user logged in
539
+ add_action('wp_ajax_nopriv_leadin_check_installation_date', 'leadin_check_installation_date'); // Call when user is not logged in
540
+
541
  ?>
inc/leadin-constants.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if ( ! defined('LEADIN_UTM_SOURCE') )
4
+ define('LEADIN_UTM_SOURCE', 'leadin%20repo%20plugin');
5
+
6
+ if ( ! defined('LEADIN_UTM_MEDIUM') )
7
+ define('LEADIN_UTM_MEDIUM', 'referral');
8
+
9
+ if ( ! defined('LEADIN_UTM_CONTENT') )
10
+ define('LEADIN_UTM_CONTENT', 'e10');
11
+
12
+ if ( ! defined('LEADIN_UTM_CAMPAIGN') )
13
+ define('LEADIN_UTM_CAMPAIGN', 'one%20click%20updater');
14
+
15
+ ?>
inc/leadin-functions.php CHANGED
@@ -101,26 +101,122 @@ function leadin_get_current_user ()
101
  'alias' => $current_user->display_name,
102
  'wp_url' => get_bloginfo('wpurl'),
103
  'li_version' => LEADIN_PLUGIN_VERSION,
104
- 'wp_version' => $wp_version
 
105
  );
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  return $leadin_user;
108
  }
109
 
110
  /**
111
- * Subscribe user to user updates in MailChimp
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  *
113
  * @return bool
114
  */
115
- function leadin_subscribe_user_updates ()
116
  {
117
- //@MP hack
118
- return FALSE;
 
 
 
119
 
120
  $leadin_user = leadin_get_current_user();
121
-
122
- // Sync to email to MailChimp
123
 
 
 
 
 
 
 
 
 
124
  $MailChimp = new LI_MailChimp(MC_KEY);
125
  $contact_synced = $MailChimp->call("lists/subscribe", array(
126
  "id" => 'c390aea726',
@@ -133,7 +229,91 @@ function leadin_subscribe_user_updates ()
133
  "merge_vars" => array('EMAIL' => $leadin_user['email'], 'WEBSITE' => get_site_url() )
134
  ));
135
 
136
- return $contact_synced;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  }
138
 
139
  /**
@@ -706,11 +886,11 @@ function leadin_in_array_deep ( $needle, $haystack )
706
  */
707
  function leadin_array_search_deep ( $needle, $array, $index )
708
  {
709
- foreach ( $array as $key => $val )
710
- {
711
- if ( $val[$index] === $needle )
712
- return $key;
713
- }
714
 
715
  return NULL;
716
  }
@@ -835,7 +1015,13 @@ function leadin_ignore_logged_in_user ()
835
  return FALSE;
836
  }
837
 
838
- function leadin_check_multisite_missing_options ( $options )
 
 
 
 
 
 
839
  {
840
  $default_options = array(
841
  'li_installed' => 1,
@@ -853,18 +1039,65 @@ function leadin_check_multisite_missing_options ( $options )
853
  'names_added_to_contacts' => 1
854
  );
855
 
 
 
 
 
 
856
  if ( count($options) && is_array($options) )
857
  {
858
  foreach ( $default_options as $key => $value )
859
  {
860
  if ( ! array_key_exists($key, $options) )
 
861
  $options[$key] = $value;
 
 
862
  }
863
  }
864
 
865
- update_option('leadin_options', $options);
 
866
 
867
  return $options;
868
  }
869
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
870
  ?>
101
  'alias' => $current_user->display_name,
102
  'wp_url' => get_bloginfo('wpurl'),
103
  'li_version' => LEADIN_PLUGIN_VERSION,
104
+ 'wp_version' => $wp_version,
105
+ 'total_contacts' => get_total_contacts()
106
  );
107
 
108
+ if ( defined('LEADIN_REFERRAL_SOURCE') )
109
+ $leadin_user['referral_source'] = LEADIN_REFERRAL_SOURCE;
110
+ else
111
+ $leadin_user['referral_source'] = '';
112
+
113
+ if ( defined('LEADIN_UTM_SOURCE') )
114
+ $leadin_user['utm_source'] = LEADIN_UTM_SOURCE;
115
+ else
116
+ $leadin_user['utm_source'] = '';
117
+
118
+ if ( defined('LEADIN_UTM_MEDIUM') )
119
+ $leadin_user['utm_medium'] = LEADIN_UTM_MEDIUM;
120
+ else
121
+ $leadin_user['utm_medium'] = '';
122
+
123
+ if ( defined('LEADIN_UTM_TERM') )
124
+ $leadin_user['utm_term'] = LEADIN_UTM_TERM;
125
+ else
126
+ $leadin_user['utm_term'] = '';
127
+
128
+ if ( defined('LEADIN_UTM_CONTENT') )
129
+ $leadin_user['utm_content'] = LEADIN_UTM_CONTENT;
130
+ else
131
+ $leadin_user['utm_content'] = '';
132
+
133
+ if ( defined('LEADIN_UTM_CAMPAIGN') )
134
+ $leadin_user['utm_campaign'] = LEADIN_UTM_CAMPAIGN;
135
+ else
136
+ $leadin_user['utm_campaign'] = '';
137
+
138
  return $leadin_user;
139
  }
140
 
141
  /**
142
+ * Get list of traits converted for Segment
143
+ *
144
+ * @return array
145
+ */
146
+ function leadin_get_segment_traits ()
147
+ {
148
+ $leadin_user = leadin_get_current_user();
149
+ $traits = array(
150
+ "name" => $leadin_user['alias'],
151
+ "email" => $leadin_user['email'],
152
+ "wp-url" => $leadin_user["wp_url"],
153
+ "wp-version" => $leadin_user["wp_version"],
154
+ "li-version" => $leadin_user["li_version"],
155
+ "li-source" => LEADIN_SOURCE,
156
+ "createdAt" => date("Y-m-d H:i:s"),
157
+ "website" => $leadin_user["wp_url"],
158
+ "company" => $leadin_user["wp_url"],
159
+ "contacts" => $leadin_user["total_contacts"],
160
+ "utm_source" => $leadin_user["utm_source"],
161
+ "utm_medium" => $leadin_user["utm_medium"],
162
+ "utm_term" => $leadin_user["utm_term"],
163
+ "utm_content" => $leadin_user["utm_content"],
164
+ "utm_campaign" => $leadin_user["utm_campaign"],
165
+ "referral_source" => $leadin_user["referral_source"]
166
+ );
167
+
168
+ return $traits;
169
+ }
170
+
171
+
172
+
173
+
174
+ /**
175
+ * Gets the total number of contacts, comments and subscribers for above the table
176
+ */
177
+ function get_total_contacts ()
178
+ {
179
+ global $wpdb;
180
+
181
+ if ( ! isset($wpdb->li_leads) )
182
+ return 0;
183
+
184
+ $q = "
185
+ SELECT
186
+ COUNT(DISTINCT hashkey) AS total_contacts
187
+ FROM
188
+ $wpdb->li_leads
189
+ WHERE
190
+ lead_email != '' AND lead_deleted = 0 AND hashkey != ''";
191
+
192
+ $total_contacts = $wpdb->get_var($q);
193
+ return $total_contacts;
194
+ }
195
+
196
+ /**
197
+ * Register Leadin user
198
  *
199
  * @return bool
200
  */
201
+ function leadin_register_user ()
202
  {
203
+ if ( ! leadin_check_pro_user() )
204
+ return FALSE;
205
+
206
+ if ( ! function_exists('curl_init') )
207
+ return FALSE;
208
 
209
  $leadin_user = leadin_get_current_user();
210
+ $traits = leadin_get_segment_traits();
 
211
 
212
+ Segment::init(SEGMENT_WRITE_KEY);
213
+
214
+ Segment::identify(array(
215
+ "userId" => $leadin_user['user_id'],
216
+ "traits" => $traits
217
+ ));
218
+
219
+ // Sync to email to MailChimp
220
  $MailChimp = new LI_MailChimp(MC_KEY);
221
  $contact_synced = $MailChimp->call("lists/subscribe", array(
222
  "id" => 'c390aea726',
229
  "merge_vars" => array('EMAIL' => $leadin_user['email'], 'WEBSITE' => get_site_url() )
230
  ));
231
 
232
+ return TRUE;
233
+ }
234
+
235
+ /**
236
+ * Set Premium propertey on Leadin user in Segment
237
+ *
238
+ * @return bool
239
+ */
240
+ function leadin_set_user_properties ( $properties = array() )
241
+ {
242
+ if ( ! leadin_check_pro_user() )
243
+ return FALSE;
244
+
245
+ if ( ! function_exists('curl_init') )
246
+ return FALSE;
247
+
248
+ $leadin_user = leadin_get_current_user();
249
+
250
+ Segment::init(SEGMENT_WRITE_KEY);
251
+
252
+ Segment::identify(array(
253
+ "userId" => $leadin_user['user_id'],
254
+ "traits" => $properties
255
+ ));
256
+ }
257
+
258
+ /**
259
+ * Send Mixpanel event when plugin is activated/deactivated
260
+ *
261
+ * @param bool
262
+ *
263
+ * @return bool
264
+ */
265
+ function leadin_track_plugin_registration_hook ( $activated )
266
+ {
267
+ $properties = array();
268
+
269
+ if ( $activated )
270
+ {
271
+ leadin_register_user();
272
+ leadin_track_plugin_activity("Activated Plugin");
273
+ $properties["last_activated"] = date("Y-m-d H:i:s");
274
+ $properties["li-status"] = "activated";
275
+ }
276
+ else
277
+ {
278
+ leadin_track_plugin_activity("Deactivated Plugin");
279
+ $properties["last_deactivated"] = date("Y-m-d H:i:s");
280
+ $properties["li-status"] = "deactivated";
281
+ }
282
+
283
+ leadin_set_user_properties( $properties );
284
+
285
+ return TRUE;
286
+ }
287
+
288
+ /**
289
+ * Track plugin activity
290
+ *
291
+ * @param string
292
+ *
293
+ * @return array
294
+ */
295
+ function leadin_track_plugin_activity ( $activity_desc, $custom_properties = array() )
296
+ {
297
+ if ( ! leadin_check_pro_user() )
298
+ return FALSE;
299
+
300
+ if ( ! function_exists('curl_init') )
301
+ return FALSE;
302
+
303
+ $leadin_user = leadin_get_current_user();
304
+
305
+ $default_properties = leadin_get_segment_traits();
306
+ $properties = array_merge((array)$default_properties, (array)$custom_properties);
307
+
308
+ Segment::init(SEGMENT_WRITE_KEY);
309
+
310
+ Segment::track(array(
311
+ 'userId' => $leadin_user['user_id'],
312
+ 'event' => $activity_desc,
313
+ 'properties' => $properties
314
+ ));
315
+
316
+ return TRUE;
317
  }
318
 
319
  /**
886
  */
887
  function leadin_array_search_deep ( $needle, $array, $index )
888
  {
889
+ foreach ( $array as $key => $val )
890
+ {
891
+ if ( $val[$index] == $needle )
892
+ return $key;
893
+ }
894
 
895
  return NULL;
896
  }
1015
  return FALSE;
1016
  }
1017
 
1018
+ function leadin_safe_social_profile_url ( $url )
1019
+ {
1020
+ $url = str_replace('∖', '/', $url);
1021
+ return $url;
1022
+ }
1023
+
1024
+ function leadin_check_missing_options ( $options )
1025
  {
1026
  $default_options = array(
1027
  'li_installed' => 1,
1039
  'names_added_to_contacts' => 1
1040
  );
1041
 
1042
+ // Add the Pro flag if this is a pro installation
1043
+ if ( ( defined('LEADIN_UTM_SOURCE') && LEADIN_UTM_SOURCE != 'leadin%20repo%20plugin') || ! defined('LEADIN_UTM_SOURCE') )
1044
+ $default_options['pro'] = 1;
1045
+
1046
+ $update_option = FALSE;
1047
  if ( count($options) && is_array($options) )
1048
  {
1049
  foreach ( $default_options as $key => $value )
1050
  {
1051
  if ( ! array_key_exists($key, $options) )
1052
+ {
1053
  $options[$key] = $value;
1054
+ $update_option = TRUE;
1055
+ }
1056
  }
1057
  }
1058
 
1059
+ if ( $update_option )
1060
+ update_option('leadin_options', $options);
1061
 
1062
  return $options;
1063
  }
1064
 
1065
+ /**
1066
+ * Checks to see if an installation is Leadin Pro enabled
1067
+ *
1068
+ * @return bool
1069
+ */
1070
+ function leadin_check_pro_user ( )
1071
+ {
1072
+ $options = get_option('leadin_options');
1073
+ if ( isset($options['pro']) && $options['pro'])
1074
+ return TRUE;
1075
+ else
1076
+ return FALSE;
1077
+ }
1078
+
1079
+ /**
1080
+ * Checks the first entry in the pageviews table
1081
+ *
1082
+ */
1083
+ function leadin_check_first_pageview_data ( )
1084
+ {
1085
+ global $wpdb;
1086
+
1087
+ $q = "SELECT pageview_date FROM $wpdb->li_pageviews ORDER BY pageview_date ASC LIMIT 1";
1088
+ $date = $wpdb->get_var($q);
1089
+
1090
+ if ( $date )
1091
+ {
1092
+ if ( strtotime($date) < strtotime('-30 days') )
1093
+ return TRUE;
1094
+ else
1095
+ return FALSE;
1096
+ }
1097
+ else
1098
+ {
1099
+ return FALSE;
1100
+ }
1101
+ }
1102
+
1103
  ?>
leadin.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Leadin
4
  Plugin URI: http://leadin.com
5
  Description: Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
6
- Version: 2.2.11
7
  Author: Andy Cook, Nelson Joyce
8
  Author URI: http://leadin.com
9
  License: GPL2
@@ -26,7 +26,13 @@ if ( !defined('LEADIN_DB_VERSION') )
26
  define('LEADIN_DB_VERSION', '2.2.4');
27
 
28
  if ( !defined('LEADIN_PLUGIN_VERSION') )
29
- define('LEADIN_PLUGIN_VERSION', '2.2.11');
 
 
 
 
 
 
30
 
31
  if ( !defined('MC_KEY') )
32
  define('MC_KEY', '934aaed05049dde737d308be26167eef-us3');
@@ -38,18 +44,30 @@ if ( !defined('LEADIN_SOURCE') )
38
  // Include Needed Files
39
  //=============================================
40
 
 
 
 
41
  require_once(LEADIN_PLUGIN_DIR . '/inc/leadin-ajax-functions.php');
42
  require_once(LEADIN_PLUGIN_DIR . '/inc/leadin-functions.php');
43
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-emailer.php');
44
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin-updater.php');
45
  require_once(LEADIN_PLUGIN_DIR . '/admin/leadin-admin.php');
46
 
 
 
47
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin.php');
48
 
49
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php');
50
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/contacts.php');
51
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php');
52
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php');
 
 
 
 
 
 
 
53
 
54
  //=============================================
55
  // Hooks & Filters
@@ -78,6 +96,7 @@ function activate_leadin ( $network_wide )
78
  switch_to_blog($blog_id);
79
  add_leadin_defaults();
80
  $activated[] = $blog_id;
 
81
  }
82
 
83
  // Switch back to the current blog
@@ -89,6 +108,7 @@ function activate_leadin ( $network_wide )
89
  else
90
  {
91
  add_leadin_defaults();
 
92
  }
93
  }
94
 
@@ -105,7 +125,7 @@ function add_leadin_defaults ( )
105
  {
106
  $opt = array(
107
  'li_installed' => 1,
108
- 'leadin_version' => LEADIN_PLUGIN_VERSION,
109
  'li_db_version' => LEADIN_DB_VERSION,
110
  'li_email' => get_bloginfo('admin_email'),
111
  'li_updates_subscription' => 1,
@@ -114,10 +134,15 @@ function add_leadin_defaults ( )
114
  'ignore_settings_popup' => 0,
115
  'data_recovered' => 1,
116
  'delete_flags_fixed' => 1,
 
117
  'converted_to_tags' => 1,
118
  'names_added_to_contacts' => 1
119
  );
120
-
 
 
 
 
121
  // this is a hack because multisite doesn't recognize local options using either update_option or update_site_option...
122
  if ( is_multisite() )
123
  {
@@ -134,26 +159,55 @@ function add_leadin_defaults ( )
134
  leadin_db_install();
135
 
136
  $multisite_prefix = ( is_multisite() ? $wpdb->prefix : '' );
137
- $q = $wpdb->prepare("
138
  INSERT INTO " . $multisite_prefix . "li_tags
139
  ( tag_text, tag_slug, tag_form_selectors, tag_synced_lists, tag_order )
140
  VALUES ('Commenters', 'commenters', '#commentform', '', 1),
141
  ('Leads', 'leads', '', '', 2),
142
  ('Contacted', 'contacted', '', '', 3),
143
- ('Customers', 'customers', '', '', 4)", "");
144
  $wpdb->query($q);
145
  }
146
 
147
  $leadin_active_power_ups = get_option('leadin_active_power_ups');
148
 
149
- if ( !$leadin_active_power_ups )
150
  {
151
  $auto_activate = array(
152
- 'contacts'
 
153
  );
154
 
155
  update_option('leadin_active_power_ups', serialize($auto_activate));
156
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  }
158
 
159
  /**
@@ -174,11 +228,14 @@ function deactivate_leadin ( $network_wide )
174
  foreach ( $blog_ids as $blog_id )
175
  {
176
  switch_to_blog($blog_id);
 
177
  }
178
 
179
  // Switch back to the current blog
180
  switch_to_blog($current_blog);
181
  }
 
 
182
  }
183
 
184
  function activate_leadin_on_new_blog ( $blog_id, $user_id, $domain, $path, $site_id, $meta )
3
  Plugin Name: Leadin
4
  Plugin URI: http://leadin.com
5
  Description: Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
6
+ Version: 3.1.4
7
  Author: Andy Cook, Nelson Joyce
8
  Author URI: http://leadin.com
9
  License: GPL2
26
  define('LEADIN_DB_VERSION', '2.2.4');
27
 
28
  if ( !defined('LEADIN_PLUGIN_VERSION') )
29
+ define('LEADIN_PLUGIN_VERSION', '3.1.4');
30
+
31
+ if ( !defined('MIXPANEL_PROJECT_TOKEN') )
32
+ define('MIXPANEL_PROJECT_TOKEN', '2791b6942b57bbef2ba12b2452468253');
33
+
34
+ if ( !defined('SEGMENT_WRITE_KEY') )
35
+ define('SEGMENT_WRITE_KEY', 'fklilck6m2');
36
 
37
  if ( !defined('MC_KEY') )
38
  define('MC_KEY', '934aaed05049dde737d308be26167eef-us3');
44
  // Include Needed Files
45
  //=============================================
46
 
47
+ if ( file_exists(LEADIN_PLUGIN_DIR . '/inc/leadin-constants.php') )
48
+ include_once(LEADIN_PLUGIN_DIR . '/inc/leadin-constants.php');
49
+
50
  require_once(LEADIN_PLUGIN_DIR . '/inc/leadin-ajax-functions.php');
51
  require_once(LEADIN_PLUGIN_DIR . '/inc/leadin-functions.php');
52
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-emailer.php');
53
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin-updater.php');
54
  require_once(LEADIN_PLUGIN_DIR . '/admin/leadin-admin.php');
55
 
56
+ require_once(LEADIN_PLUGIN_DIR . '/lib/mixpanel/LI_Mixpanel.php');
57
+ require_once(LEADIN_PLUGIN_DIR . '/lib/segment/lib/Segment.php');
58
  require_once(LEADIN_PLUGIN_DIR . '/inc/class-leadin.php');
59
 
60
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/subscribe-widget.php');
61
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/contacts.php');
62
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/mailchimp-connect.php');
63
  require_once(LEADIN_PLUGIN_DIR . '/power-ups/constant-contact-connect.php');
64
+ require_once(LEADIN_PLUGIN_DIR . '/power-ups/aweber-connect.php');
65
+ require_once(LEADIN_PLUGIN_DIR . '/power-ups/campaign-monitor-connect.php');
66
+ require_once(LEADIN_PLUGIN_DIR . '/power-ups/getresponse-connect.php');
67
+ require_once(LEADIN_PLUGIN_DIR . '/power-ups/beta-program.php');
68
+ require_once(LEADIN_PLUGIN_DIR . '/power-ups/lookups.php');
69
+
70
+
71
 
72
  //=============================================
73
  // Hooks & Filters
96
  switch_to_blog($blog_id);
97
  add_leadin_defaults();
98
  $activated[] = $blog_id;
99
+ leadin_track_plugin_registration_hook(TRUE);
100
  }
101
 
102
  // Switch back to the current blog
108
  else
109
  {
110
  add_leadin_defaults();
111
+ leadin_track_plugin_registration_hook(TRUE);
112
  }
113
  }
114
 
125
  {
126
  $opt = array(
127
  'li_installed' => 1,
128
+ 'leadin_version' => LEADIN_PLUGIN_VERSION,
129
  'li_db_version' => LEADIN_DB_VERSION,
130
  'li_email' => get_bloginfo('admin_email'),
131
  'li_updates_subscription' => 1,
134
  'ignore_settings_popup' => 0,
135
  'data_recovered' => 1,
136
  'delete_flags_fixed' => 1,
137
+ 'beta_tester' => 0,
138
  'converted_to_tags' => 1,
139
  'names_added_to_contacts' => 1
140
  );
141
+
142
+ // Add the Pro flag if this is a pro installation
143
+ if ( ( defined('LEADIN_UTM_SOURCE') && LEADIN_UTM_SOURCE != 'leadin%20repo%20plugin' ) || ! defined('LEADIN_UTM_SOURCE') )
144
+ $opt['pro'] = 1;
145
+
146
  // this is a hack because multisite doesn't recognize local options using either update_option or update_site_option...
147
  if ( is_multisite() )
148
  {
159
  leadin_db_install();
160
 
161
  $multisite_prefix = ( is_multisite() ? $wpdb->prefix : '' );
162
+ $q = "
163
  INSERT INTO " . $multisite_prefix . "li_tags
164
  ( tag_text, tag_slug, tag_form_selectors, tag_synced_lists, tag_order )
165
  VALUES ('Commenters', 'commenters', '#commentform', '', 1),
166
  ('Leads', 'leads', '', '', 2),
167
  ('Contacted', 'contacted', '', '', 3),
168
+ ('Customers', 'customers', '', '', 4)";
169
  $wpdb->query($q);
170
  }
171
 
172
  $leadin_active_power_ups = get_option('leadin_active_power_ups');
173
 
174
+ if ( ! $leadin_active_power_ups )
175
  {
176
  $auto_activate = array(
177
+ 'contacts',
178
+ 'lookups' // 3.1.4 change - auto activating this power-up and using the Pro flag to toggle on/off
179
  );
180
 
181
  update_option('leadin_active_power_ups', serialize($auto_activate));
182
  }
183
+
184
+ setcookie ( "ignore_social_share" , "1", 2592000, "/" );
185
+
186
+ // This is in here because Segment doesn't have register_once, so it's in a method that's only called once
187
+ if ( leadin_check_pro_user() )
188
+ {
189
+ $traits = array();
190
+
191
+ if ( defined('LEADIN_REFERRAL_SOURCE') )
192
+ $traits['referral_source'] = LEADIN_REFERRAL_SOURCE;
193
+
194
+ if ( defined('LEADIN_UTM_SOURCE') )
195
+ $traits['utm_source'] = LEADIN_UTM_SOURCE;
196
+
197
+ if ( defined('LEADIN_UTM_MEDIUM') )
198
+ $traits['utm_medium'] = LEADIN_UTM_MEDIUM;
199
+
200
+ if ( defined('LEADIN_UTM_TERM') )
201
+ $traits['utm_term'] = LEADIN_UTM_TERM;
202
+
203
+ if ( defined('LEADIN_UTM_CONTENT') )
204
+ $traits['utm_content'] = LEADIN_UTM_CONTENT;
205
+
206
+ if ( defined('LEADIN_UTM_CAMPAIGN') )
207
+ $traits['utm_campaign'] = LEADIN_UTM_CAMPAIGN;
208
+
209
+ leadin_set_user_properties($traits);
210
+ }
211
  }
212
 
213
  /**
228
  foreach ( $blog_ids as $blog_id )
229
  {
230
  switch_to_blog($blog_id);
231
+ leadin_track_plugin_registration_hook(FALSE);
232
  }
233
 
234
  // Switch back to the current blog
235
  switch_to_blog($current_blog);
236
  }
237
+ else
238
+ leadin_track_plugin_registration_hook(FALSE);
239
  }
240
 
241
  function activate_leadin_on_new_blog ( $blog_id, $user_id, $domain, $path, $site_id, $meta )
lib/mixpanel/Base/LI_MixpanelBase.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * This a Base class which all Mixpanel classes extend from to provide some very basic
5
+ * debugging and logging functionality. It also serves to persist $_options across the library.
6
+ *
7
+ */
8
+
9
+
10
+
11
+ class LI_Base_MixpanelBase {
12
+
13
+
14
+ /**
15
+ * Default options that can be overridden via the $options constructor arg
16
+ * @var array
17
+ */
18
+ private $_defaults = array(
19
+ "max_batch_size" => 50, // the max batch size Mixpanel will accept is 50,
20
+ "max_queue_size" => 1000, // the max num of items to hold in memory before flushing
21
+ "debug" => false, // enable/disable debug mode
22
+ "consumer" => "curl", // which consumer to use
23
+ "host" => "api.mixpanel.com", // the host name for api calls
24
+ "events_endpoint" => "/track", // host relative endpoint for events
25
+ "people_endpoint" => "/engage", // host relative endpoint for people updates
26
+ "use_ssl" => true, // use ssl when available
27
+ "error_callback" => null // callback to use on consumption failures
28
+ );
29
+
30
+
31
+ /**
32
+ * An array of options to be used by the Mixpanel library.
33
+ * @var array
34
+ */
35
+ protected $_options = array();
36
+
37
+
38
+ /**
39
+ * Construct a new MixpanelBase object and merge custom options with defaults
40
+ * @param array $options
41
+ */
42
+ public function __construct($options = array()) {
43
+ $options = array_merge($this->_defaults, $options);
44
+ $this->_options = $options;
45
+ }
46
+
47
+
48
+ /**
49
+ * Log a message to PHP's error log
50
+ * @param $msg
51
+ */
52
+ protected function _log($msg) {
53
+ $arr = debug_backtrace();
54
+ $class = $arr[0]['class'];
55
+ $line = $arr[0]['line'];
56
+ error_log ( "[ $class - line $line ] : " . $msg );
57
+ }
58
+
59
+
60
+ /**
61
+ * Returns true if in debug mode, false if in production mode
62
+ * @return bool
63
+ */
64
+ protected function _debug() {
65
+ return array_key_exists("debug", $this->_options) && $this->_options["debug"] == true;
66
+ }
67
+
68
+ }
lib/mixpanel/ConsumerStrategies/LI_AbstractConsumer.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(dirname(__FILE__) . "/../Base/LI_MixpanelBase.php");
4
+
5
+ /**
6
+ * Provides some base methods for use by a Consumer implementation
7
+ */
8
+ abstract class LI_ConsumerStrategies_AbstractConsumer extends LI_Base_MixpanelBase {
9
+
10
+ /**
11
+ * Creates a new AbstractConsumer
12
+ * @param array $options
13
+ */
14
+ function __construct($options = array()) {
15
+
16
+ parent::__construct($options);
17
+
18
+ if ($this->_debug()) {
19
+ $this->_log("Instantiated new Consumer");
20
+ }
21
+
22
+ }
23
+
24
+ /**
25
+ * Encode an array to be persisted
26
+ * @param array $params
27
+ * @return string
28
+ */
29
+ protected function _encode($params) {
30
+ return base64_encode(json_encode($params));
31
+ }
32
+
33
+ /**
34
+ * Handles errors that occur in a consumer
35
+ * @param $code
36
+ * @param $msg
37
+ */
38
+ protected function _handleError($code, $msg) {
39
+ if (isset($this->_options['error_callback'])) {
40
+ $handler = $this->_options['error_callback'];
41
+ call_user_func($handler, $code, $msg);
42
+ }
43
+
44
+ if ($this->_debug()) {
45
+ $arr = debug_backtrace();
46
+ $class = get_class($arr[0]['object']);
47
+ $line = $arr[0]['line'];
48
+ error_log ( "[ $class - line $line ] : " . print_r($msg, true) );
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Persist a batch of messages in whatever way the implementer sees fit
54
+ * @param array $batch an array of messages to consume
55
+ * @return boolean success or fail
56
+ */
57
+ abstract function persist($batch);
58
+ }
lib/mixpanel/ConsumerStrategies/LI_CurlConsumer.php ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
4
+
5
+ /**
6
+ * Consumes messages and sends them to a host/endpoint using cURL
7
+ */
8
+ class LI_ConsumerStrategies_CurlConsumer extends LI_ConsumerStrategies_AbstractConsumer {
9
+
10
+ /**
11
+ * @var string the host to connect to (e.g. api.mixpanel.com)
12
+ */
13
+ protected $_host;
14
+
15
+
16
+ /**
17
+ * @var string the host-relative endpoint to write to (e.g. /engage)
18
+ */
19
+ protected $_endpoint;
20
+
21
+
22
+ /**
23
+ * @var int connect_timeout The number of seconds to wait while trying to connect. Default is 5 seconds.
24
+ */
25
+ protected $_connect_timeout;
26
+
27
+
28
+ /**
29
+ * @var int timeout The maximum number of seconds to allow cURL call to execute. Default is 30 seconds.
30
+ */
31
+ protected $_timeout;
32
+
33
+
34
+ /**
35
+ * @var string the protocol to use for the cURL connection
36
+ */
37
+ protected $_protocol;
38
+
39
+
40
+ /**
41
+ * @var bool|null true to fork the cURL process (using exec) or false to use PHP's cURL extension. false by default
42
+ */
43
+ protected $_fork = null;
44
+
45
+
46
+ /**
47
+ * Creates a new LI_CurlConsumer and assigns properties from the $options array
48
+ * @param array $options
49
+ * @throws Exception
50
+ */
51
+ function __construct($options) {
52
+ parent::__construct($options);
53
+
54
+ $this->_host = $options['host'];
55
+ $this->_endpoint = $options['endpoint'];
56
+ $this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
57
+ $this->_timeout = array_key_exists('timeout', $options) ? $options['timeout'] : 30;
58
+ $this->_protocol = array_key_exists('use_ssl', $options) && $options['use_ssl'] == true ? "https" : "http";
59
+ $this->_fork = array_key_exists('fork', $options) ? ($options['fork'] == true) : false;
60
+
61
+ // ensure the environment is workable for the given settings
62
+ /*if ($this->_fork == true) {
63
+ $exists = function_exists('exec');
64
+ if (!$exists) {
65
+ throw new Exception('The "exec" function must exist to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
66
+ }
67
+ $disabled = explode(', ', ini_get('disable_functions'));
68
+ $enabled = !in_array('exec', $disabled);
69
+ if (!$enabled) {
70
+ throw new Exception('The "exec" function must be enabled to use the cURL consumer in "fork" mode. Try setting fork = false or use another consumer.');
71
+ }
72
+ } else {
73
+ if (!function_exists('curl_init')) {
74
+ throw new Exception('The cURL PHP extension is required to use the cURL consumer with fork = false. Try setting fork = true or use another consumer.');
75
+ }
76
+ }*/
77
+ }
78
+
79
+
80
+ /**
81
+ * Write to the given host/endpoint using either a forked cURL process or using PHP's cURL extension
82
+ * @param array $batch
83
+ * @return bool
84
+ */
85
+ public function persist($batch) {
86
+ if (count($batch) > 0) {
87
+ $data = "data=" . $this->_encode($batch);
88
+ $url = $this->_protocol . "://" . $this->_host . $this->_endpoint;
89
+ if ($this->_fork) {
90
+ return $this->_execute_forked($url, $data);
91
+ } else {
92
+ return $this->_execute($url, $data);
93
+ }
94
+ } else {
95
+ return true;
96
+ }
97
+ }
98
+
99
+
100
+ /**
101
+ * Write using the cURL php extension
102
+ * @param $url
103
+ * @param $data
104
+ * @return bool
105
+ */
106
+ protected function _execute($url, $data) {
107
+ if ($this->_debug()) {
108
+ $this->_log("Making blocking cURL call to $url");
109
+ }
110
+
111
+ $ch = curl_init();
112
+ curl_setopt($ch, CURLOPT_URL, $url);
113
+ curl_setopt($ch, CURLOPT_HEADER, 0);
114
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->_connect_timeout);
115
+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout);
116
+ curl_setopt($ch, CURLOPT_POST, 1);
117
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
118
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
119
+ $response = curl_exec($ch);
120
+ if (false === $response) {
121
+ $curl_error = curl_error($ch);
122
+ $curl_errno = curl_errno($ch);
123
+ curl_close($ch);
124
+ $this->_handleError($curl_errno, $curl_error);
125
+ return false;
126
+ } else {
127
+ curl_close($ch);
128
+ if (trim($response) == "1") {
129
+ return true;
130
+ } else {
131
+ $this->_handleError(0, $response);
132
+ return false;
133
+ }
134
+ }
135
+ }
136
+
137
+
138
+ /**
139
+ * Write using a forked cURL process
140
+ * @param $url
141
+ * @param $data
142
+ * @return bool
143
+ */
144
+ protected function _execute_forked($url, $data) {
145
+
146
+ if ($this->_debug()) {
147
+ $this->_log("Making forked cURL call to $url");
148
+ }
149
+
150
+ $exec = 'curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d ' . $data . ' "' . $url . '"';
151
+
152
+ if(!$this->_debug()) {
153
+ $exec .= " >/dev/null 2>&1 &";
154
+ }
155
+
156
+ exec($exec, $output, $return_var);
157
+
158
+ if ($return_var != 0) {
159
+ $this->_handleError($return_var, $output);
160
+ }
161
+
162
+ return $return_var == 0;
163
+ }
164
+
165
+ /**
166
+ * @return int
167
+ */
168
+ public function getConnectTimeout()
169
+ {
170
+ return $this->_connect_timeout;
171
+ }
172
+
173
+ /**
174
+ * @return string
175
+ */
176
+ public function getEndpoint()
177
+ {
178
+ return $this->_endpoint;
179
+ }
180
+
181
+ /**
182
+ * @return bool|null
183
+ */
184
+ public function getFork()
185
+ {
186
+ return $this->_fork;
187
+ }
188
+
189
+ /**
190
+ * @return string
191
+ */
192
+ public function getHost()
193
+ {
194
+ return $this->_host;
195
+ }
196
+
197
+ /**
198
+ * @return array
199
+ */
200
+ public function getOptions()
201
+ {
202
+ return $this->_options;
203
+ }
204
+
205
+ /**
206
+ * @return string
207
+ */
208
+ public function getProtocol()
209
+ {
210
+ return $this->_protocol;
211
+ }
212
+
213
+ /**
214
+ * @return int
215
+ */
216
+ public function getTimeout()
217
+ {
218
+ return $this->_timeout;
219
+ }
220
+
221
+
222
+ }
lib/mixpanel/ConsumerStrategies/LI_FileConsumer.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
4
+ /**
5
+ * Consumes messages and writes them to a file
6
+ */
7
+ class ConsumerStrategies_LI_FileConsumer extends LI_ConsumerStrategies_AbstractConsumer {
8
+
9
+ /**
10
+ * @var string path to a file that we want to write the messages to
11
+ */
12
+ private $_file;
13
+
14
+
15
+ /**
16
+ * Creates a new LI_FileConsumer and assigns properties from the $options array
17
+ * @param array $options
18
+ */
19
+ function __construct($options) {
20
+ parent::__construct($options);
21
+
22
+ // what file to write to?
23
+ $this->_file = array_key_exists("file", $options) ? $options['file'] : dirname(__FILE__)."/../../messages.txt";
24
+ }
25
+
26
+
27
+ /**
28
+ * Append $batch to a file
29
+ * @param array $batch
30
+ * @return bool
31
+ */
32
+ public function persist($batch) {
33
+ if (count($batch) > 0) {
34
+ return file_put_contents($this->_file, json_encode($batch)."\n", FILE_APPEND | LOCK_EX) !== false;
35
+ } else {
36
+ return true;
37
+ }
38
+ }
39
+ }
lib/mixpanel/ConsumerStrategies/LI_SocketConsumer.php ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Portions of this class were borrowed from
4
+ * https://github.com/segmentio/analytics-php/blob/master/lib/Analytics/Consumer/Socket.php.
5
+ * Thanks for the work!
6
+ *
7
+ * WWWWWW||WWWWWW
8
+ * W W W||W W W
9
+ * ||
10
+ * ( OO )__________
11
+ * / | \
12
+ * /o o| MIT \
13
+ * \___/||_||__||_|| *
14
+ * || || || ||
15
+ * _||_|| _||_||
16
+ * (__|__|(__|__|
17
+ * (The MIT License)
18
+ *
19
+ * Copyright (c) 2013 Segment.io Inc. friends@segment.io
20
+ *
21
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
22
+ * documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
23
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
24
+ * permit persons to whom the Software is furnished to do so, subject to the following conditions:
25
+ *
26
+ * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
27
+ * Software.
28
+ *
29
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
30
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
31
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
32
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33
+ */
34
+
35
+ require_once(dirname(__FILE__) . "/LI_AbstractConsumer.php");
36
+
37
+ /**
38
+ * Consumes messages and writes them to host/endpoint using a persistent socket
39
+ */
40
+ class LI_ConsumerStrategies_SocketConsumer extends LI_ConsumerStrategies_AbstractConsumer {
41
+
42
+ /**
43
+ * @var string the host to connect to (e.g. api.mixpanel.com)
44
+ */
45
+ private $_host;
46
+
47
+
48
+ /**
49
+ * @var string the host-relative endpoint to write to (e.g. /engage)
50
+ */
51
+ private $_endpoint;
52
+
53
+
54
+ /**
55
+ * @var int connect_timeout the socket connection timeout in seconds
56
+ */
57
+ private $_connect_timeout;
58
+
59
+
60
+ /**
61
+ * @var string the protocol to use for the socket connection
62
+ */
63
+ private $_protocol;
64
+
65
+
66
+ /**
67
+ * @var resource holds the socket resource
68
+ */
69
+ private $_socket;
70
+
71
+ /**
72
+ * @var bool whether or not to wait for a response
73
+ */
74
+ private $_async;
75
+
76
+
77
+ /**
78
+ * Creates a new SocketConsumer and assigns properties from the $options array
79
+ * @param array $options
80
+ */
81
+ public function __construct($options = array()) {
82
+ parent::__construct($options);
83
+
84
+
85
+ $this->_host = $options['host'];
86
+ $this->_endpoint = $options['endpoint'];
87
+ $this->_connect_timeout = array_key_exists('connect_timeout', $options) ? $options['connect_timeout'] : 5;
88
+ $this->_async = array_key_exists('async', $options) && $options['async'] === false ? false : true;
89
+
90
+ if (array_key_exists('use_ssl', $options) && $options['use_ssl'] == true) {
91
+ $this->_protocol = "ssl";
92
+ $this->_port = 443;
93
+ } else {
94
+ $this->_protocol = "tcp";
95
+ $this->_port = 80;
96
+ }
97
+ }
98
+
99
+
100
+ /**
101
+ * Write using a persistent socket connection.
102
+ * @param array $batch
103
+ * @return bool
104
+ */
105
+ public function persist($batch) {
106
+
107
+ $socket = $this->_getSocket();
108
+ if (!is_resource($socket)) {
109
+ return false;
110
+ }
111
+
112
+ $data = "data=".$this->_encode($batch);
113
+
114
+ $body = "";
115
+ $body.= "POST ".$this->_endpoint." HTTP/1.1\r\n";
116
+ $body.= "Host: " . $this->_host . "\r\n";
117
+ $body.= "Content-Type: application/x-www-form-urlencoded\r\n";
118
+ $body.= "Accept: application/json\r\n";
119
+ $body.= "Content-length: " . strlen($data) . "\r\n";
120
+ $body.= "\r\n";
121
+ $body.= $data;
122
+
123
+ return $this->_write($socket, $body);
124
+ }
125
+
126
+
127
+ /**
128
+ * Return cached socket if open or create a new persistent socket
129
+ * @return bool|resource
130
+ */
131
+ private function _getSocket() {
132
+ if(is_resource($this->_socket)) {
133
+
134
+ if ($this->_debug()) {
135
+ $this->_log("Using existing socket");
136
+ }
137
+
138
+ return $this->_socket;
139
+ } else {
140
+
141
+ if ($this->_debug()) {
142
+ $this->_log("Creating new socket at ".time());
143
+ }
144
+
145
+ return $this->_createSocket();
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Attempt to open a new socket connection, cache it, and return the resource
151
+ * @param bool $retry
152
+ * @return bool|resource
153
+ */
154
+ private function _createSocket($retry = true) {
155
+ try {
156
+ $socket = pfsockopen($this->_protocol . "://" . $this->_host, $this->_port, $err_no, $err_msg, $this->_connect_timeout);
157
+
158
+ if ($this->_debug()) {
159
+ $this->_log("Opening socket connection to " . $this->_protocol . "://" . $this->_host . ":" . $this->_port);
160
+ }
161
+
162
+ if ($err_no != 0) {
163
+ $this->_handleError($err_no, $err_msg);
164
+ return $retry == true ? $this->_createSocket(false) : false;
165
+ } else {
166
+ // cache the socket
167
+ $this->_socket = $socket;
168
+ return $socket;
169
+ }
170
+
171
+ } catch (Exception $e) {
172
+ $this->_handleError($e->getCode(), $e->getMessage());
173
+ return $retry == true ? $this->_createSocket(false) : false;
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Attempt to close and dereference a socket resource
179
+ */
180
+ private function _destroySocket() {
181
+ $socket = $this->_socket;
182
+ $this->_socket = null;
183
+ fclose($socket);
184
+ }
185
+
186
+
187
+ /**
188
+ * Write $data through the given $socket
189
+ * @param $socket
190
+ * @param $data
191
+ * @param bool $retry
192
+ * @return bool
193
+ */
194
+ private function _write($socket, $data, $retry = true) {
195
+
196
+ $bytes_sent = 0;
197
+ $bytes_total = strlen($data);
198
+ $socket_closed = false;
199
+ $success = true;
200
+ $max_bytes_per_write = 8192;
201
+
202
+ // if we have no data to write just return true
203
+ if ($bytes_total == 0) {
204
+ return true;
205
+ }
206
+
207
+ // try to write the data
208
+ while (!$socket_closed && $bytes_sent < $bytes_total) {
209
+
210
+ try {
211
+ $bytes = fwrite($socket, $data, $max_bytes_per_write);
212
+
213
+ if ($this->_debug()) {
214
+ $this->_log("Socket wrote ".$bytes." bytes");
215
+ }
216
+
217
+ // if we actually wrote data, then remove the written portion from $data left to write
218
+ if ($bytes > 0) {
219
+ $data = substr($data, $max_bytes_per_write);
220
+ }
221
+
222
+ } catch (Exception $e) {
223
+ $this->_handleError($e->getCode(), $e->getMessage());
224
+ $socket_closed = true;
225
+ }
226
+
227
+ if (isset($bytes) && $bytes) {
228
+ $bytes_sent += $bytes;
229
+ } else {
230
+ $socket_closed = true;
231
+ }
232
+ }
233
+
234
+ // create a new socket if the current one is closed and retry the message
235
+ if ($socket_closed) {
236
+
237
+ $this->_destroySocket();
238
+
239
+ if ($retry) {
240
+ if ($this->_debug()) {
241
+ $this->_log("Retrying socket write...");
242
+ }
243
+ $socket = $this->_getSocket();
244
+ if ($socket) return $this->_write($socket, $data, false);
245
+ }
246
+
247
+ return false;
248
+ }
249
+
250
+
251
+ // only wait for the response in debug mode or if we explicitly want to be synchronous
252
+ if ($this->_debug() || !$this->_async) {
253
+ $res = $this->handleResponse(fread($socket, 2048));
254
+ if ($res["status"] != "200") {
255
+ $this->_handleError($res["status"], $res["body"]);
256
+ $success = false;
257
+ }
258
+ }
259
+
260
+ return $success;
261
+ }
262
+
263
+
264
+ /**
265
+ * Parse the response from a socket write (only used for debugging)
266
+ * @param $response
267
+ * @return array
268
+ */
269
+ private function handleResponse($response) {
270
+
271
+ $lines = explode("\n", $response);
272
+
273
+ // extract headers
274
+ $headers = array();
275
+ foreach($lines as $line) {
276
+ $kvsplit = explode(":", $line);
277
+ if (count($kvsplit) == 2) {
278
+ $header = $kvsplit[0];
279
+ $value = $kvsplit[1];
280
+ $headers[$header] = trim($value);
281
+ }
282
+
283
+ }
284
+
285
+ // extract status
286
+ $line_one_exploded = explode(" ", $lines[0]);
287
+ $status = $line_one_exploded[1];
288
+
289
+ // extract body
290
+ $body = $lines[count($lines) - 1];
291
+
292
+ // if the connection has been closed lets kill the socket
293
+ if ($headers['Connection'] == "close") {
294
+ $this->_destroySocket();
295
+ if ($this->_debug()) {
296
+ $this->_log("Server told us connection closed so lets destroy the socket so it'll reconnect on next call");
297
+ }
298
+ }
299
+
300
+ $ret = array(
301
+ "status" => $status,
302
+ "body" => $body,
303
+ );
304
+
305
+ return $ret;
306
+ }
307
+
308
+
309
+ }
lib/mixpanel/LI_Mixpanel.php ADDED
@@ -0,0 +1,305 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(dirname(__FILE__) . "/Base/LI_MixpanelBase.php");
4
+ require_once(dirname(__FILE__) . "/Producers/LI_MixpanelPeople.php");
5
+ require_once(dirname(__FILE__) . "/Producers/LI_MixpanelEvents.php");
6
+
7
+ /**
8
+ * This is the main class for the Mixpanel PHP Library which provides all of the methods you need to track events and
9
+ * create/update profiles.
10
+ *
11
+ * Architecture
12
+ * -------------
13
+ *
14
+ * This library is built such that all messages are buffered in an in-memory "queue"
15
+ * The queue will be automatically flushed at the end of every request. Alternatively, you can call "flush()" manually
16
+ * at any time. Flushed messages will be passed to a Consumer's "persist" method. The library comes with a handful of
17
+ * Consumers. The "LI_CurlConsumer" is used by default which will send the messages to Mixpanel using forked cURL processes.
18
+ * You can implement your own custom Consumer to customize how a message is sent to Mixpanel. This can be useful when
19
+ * you want to put messages onto a distributed queue (such as ActiveMQ or Kestrel) instead of writing to Mixpanel in
20
+ * the user thread.
21
+ *
22
+ * Options
23
+ * -------------
24
+ *
25
+ * <table width="100%" cellpadding="5">
26
+ * <tr>
27
+ * <th>Option</th>
28
+ * <th>Description</th>
29
+ * <th>Default</th>
30
+ * </tr>
31
+ * <tr>
32
+ * <td>max_queue_size</td>
33
+ * <td>The maximum number of items to buffer in memory before flushing</td>
34
+ * <td>1000</td>
35
+ * </tr>
36
+ * <tr>
37
+ * <td>debug</td>
38
+ * <td>Enable/disable debug mode</td>
39
+ * <td>false</td>
40
+ * </tr>
41
+ * <tr>
42
+ * <td>consumer</td>
43
+ * <td>The consumer to use for writing messages</td>
44
+ * <td>curl</td>
45
+ * </tr>
46
+ * <tr>
47
+ * <td>consumers</td>
48
+ * <td>An array of custom consumers in the format array(consumer_key => class_name)</td>
49
+ * <td>null</td>
50
+ * </tr>
51
+ * <tr>
52
+ * <td>host</td>
53
+ * <td>The host name for api calls (used by some consumers)</td>
54
+ * <td>api.mixpanel.com</td>
55
+ * </tr>
56
+ * <tr>
57
+ * <td>events_endpoint</td>
58
+ * <td>The endpoint for tracking events (relative to the host)</td>
59
+ * <td>/events</td>
60
+ * </tr>
61
+ * <tr>
62
+ * <td>people_endpoint</td>
63
+ * <td>The endpoint for making people updates (relative to the host)</td>
64
+ * <td>/engage</td>
65
+ * </tr>
66
+ * <tr>
67
+ * <td>use_ssl</td>
68
+ * <td>Tell the consumer whether or not to use ssl (when available)</td>
69
+ * <td>true</td>
70
+ * </tr>
71
+ * <tr>
72
+ * <td>error_callback</td>
73
+ * <td>The name of a function to be called on consumption failures</td>
74
+ * <td>null</td>
75
+ * </tr>
76
+ * <tr>
77
+ * <td>connect_timeout</td>
78
+ * <td>In both the SocketConsumer and LI_CurlConsumer, this is used for the connection timeout (i.e. How long it has take to actually make a connection).
79
+ * <td>5</td>
80
+ * </tr>
81
+ * <tr>
82
+ * <td>timeout</td>
83
+ * <td>In the LI_CurlConsumer (non-forked), it is used to determine how long the cURL call has to execute.
84
+ * <td>30</td>
85
+ * </tr>
86
+ * </table>
87
+ *
88
+ * Example: Tracking an Event
89
+ * -------------
90
+ *
91
+ * $mp = Mixpanel::getInstance("MY_TOKEN");
92
+ *
93
+ * $mp->track("My Event");
94
+ *
95
+ * Example: Setting Profile Properties
96
+ * -------------
97
+ *
98
+ * $mp = Mixpanel::getInstance("MY_TOKEN", array("use_ssl" => false));
99
+ *
100
+ * $mp->people->set(12345, array(
101
+ * '$first_name' => "John",
102
+ * '$last_name' => "Doe",
103
+ * '$email' => "john.doe@example.com",
104
+ * '$phone' => "5555555555",
105
+ * 'Favorite Color' => "red"
106
+ * ));
107
+ *
108
+ */
109
+ class LI_Mixpanel extends LI_Base_MixpanelBase {
110
+
111
+
112
+ /**
113
+ * An instance of the MixpanelPeople class (used to create/update profiles)
114
+ * @var MixpanelPeople
115
+ */
116
+ public $people;
117
+
118
+
119
+ /**
120
+ * An instance of the MixpanelEvents class
121
+ * @var Producers_MixpanelEvents
122
+ */
123
+ private $_events;
124
+
125
+
126
+ /**
127
+ * An instance of the Mixpanel class (for singleton use)
128
+ * @var Mixpanel
129
+ */
130
+ public $instance;
131
+
132
+
133
+ /**
134
+ * Instantiates a new Mixpanel instance.
135
+ * @param $token
136
+ * @param array $options
137
+ */
138
+ public function __construct($token, $options = array()) {
139
+ parent::__construct($options);
140
+ $this->people = new LI_Producers_MixpanelPeople($token, $options);
141
+ $this->_events = new LI_Producers_MixpanelEvents($token, $options);
142
+ }
143
+
144
+
145
+ /**
146
+ * Returns a singleton instance of Mixpanel
147
+ * @param $token
148
+ * @param array $options
149
+ * @return Mixpanel
150
+ */
151
+ public static function getInstance($token, $options = array()) {
152
+
153
+
154
+
155
+
156
+ $this->instance = new LI_Mixpanel($token, $options);
157
+
158
+
159
+ }
160
+
161
+
162
+ /**
163
+ * Add an array representing a message to be sent to Mixpanel to the in-memory queue.
164
+ * @param array $message
165
+ */
166
+ public function enqueue($message = array()) {
167
+ $this->_events->enqueue($message);
168
+ }
169
+
170
+
171
+ /**
172
+ * Add an array representing a list of messages to be sent to Mixpanel to a queue.
173
+ * @param array $messages
174
+ */
175
+ public function enqueueAll($messages = array()) {
176
+ $this->_events->enqueueAll($messages);
177
+ }
178
+
179
+
180
+ /**
181
+ * Flush the events queue
182
+ * @param int $desired_batch_size
183
+ */
184
+ public function flush($desired_batch_size = 50) {
185
+ $this->_events->flush($desired_batch_size);
186
+ }
187
+
188
+
189
+ /**
190
+ * Empty the events queue
191
+ */
192
+ public function reset() {
193
+ $this->_events->reset();
194
+ }
195
+
196
+
197
+ /**
198
+ * Identify the user you want to associate to tracked events
199
+ * @param string|int $user_id
200
+ */
201
+ public function identify($user_id) {
202
+ $this->_events->identify($user_id);
203
+ }
204
+
205
+ /**
206
+ * Track an event defined by $event associated with metadata defined by $properties
207
+ * @param string $event
208
+ * @param array $properties
209
+ */
210
+ public function track($event, $properties = array()) {
211
+ $this->_events->track($event, $properties);
212
+ }
213
+
214
+
215
+ /**
216
+ * Register a property to be sent with every event.
217
+ *
218
+ * If the property has already been registered, it will be
219
+ * overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
220
+ * @param string $property
221
+ * @param mixed $value
222
+ */
223
+ public function register($property, $value) {
224
+ $this->_events->register($property, $value);
225
+ }
226
+
227
+
228
+ /**
229
+ * Register multiple properties to be sent with every event.
230
+ *
231
+ * If any of the properties have already been registered,
232
+ * they will be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
233
+ * instance.
234
+ * @param array $props_and_vals
235
+ */
236
+ public function registerAll($props_and_vals = array()) {
237
+ $this->_events->registerAll($props_and_vals);
238
+ }
239
+
240
+
241
+ /**
242
+ * Register a property to be sent with every event.
243
+ *
244
+ * If the property has already been registered, it will NOT be
245
+ * overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class instance.
246
+ * @param $property
247
+ * @param $value
248
+ */
249
+ public function registerOnce($property, $value) {
250
+ $this->_events->registerOnce($property, $value);
251
+ }
252
+
253
+
254
+ /**
255
+ * Register multiple properties to be sent with every event.
256
+ *
257
+ * If any of the properties have already been registered,
258
+ * they will NOT be overwritten. NOTE: Registered properties are only persisted for the life of the Mixpanel class
259
+ * instance.
260
+ * @param array $props_and_vals
261
+ */
262
+ public function registerAllOnce($props_and_vals = array()) {
263
+ $this->_events->registerAllOnce($props_and_vals);
264
+ }
265
+
266
+
267
+ /**
268
+ * Un-register an property to be sent with every event.
269
+ * @param string $property
270
+ */
271
+ public function unregister($property) {
272
+ $this->_events->unregister($property);
273
+ }
274
+
275
+
276
+ /**
277
+ * Un-register a list of properties to be sent with every event.
278
+ * @param array $properties
279
+ */
280
+ public function unregisterAll($properties) {
281
+ $this->_events->unregisterAll($properties);
282
+ }
283
+
284
+
285
+ /**
286
+ * Get a property that is set to be sent with every event
287
+ * @param string $property
288
+ * @return mixed
289
+ */
290
+ public function getProperty($property)
291
+ {
292
+ return $this->_events->getProperty($property);
293
+ }
294
+
295
+
296
+ /**
297
+ * Alias an existing id with a different unique id. This is helpful when you want to associate a generated id
298
+ * (such as a session id) to a user id or username.
299
+ * @param string|int $original_id
300
+ * @param string|int $new_id
301
+ */
302
+ public function createAlias($original_id, $new_id) {
303
+ $this->_events->createAlias($original_id, $new_id);
304
+ }
305
+ }
lib/mixpanel/Producers/LI_MixpanelBaseProducer.php ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(dirname(__FILE__) . "/../Base/LI_MixpanelBase.php");
4
+ require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_FileConsumer.php");
5
+ require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_CurlConsumer.php");
6
+ require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_SocketConsumer.php");
7
+
8
+ if (!function_exists('json_encode')) {
9
+ throw new Exception('The JSON PHP extension is required.');
10
+ }
11
+
12
+ /**
13
+ * Provides some base methods for use by a message Producer
14
+ */
15
+ abstract class LI_Producers_MixpanelBaseProducer extends LI_Base_MixpanelBase {
16
+
17
+
18
+ /**
19
+ * @var string a token associated to a Mixpanel project
20
+ */
21
+ protected $_token;
22
+
23
+
24
+ /**
25
+ * @var array a queue to hold messages in memory before flushing in batches
26
+ */
27
+ private $_queue = array();
28
+
29
+
30
+ /**
31
+ * @var LI_ConsumerStrategies_AbstractConsumer the consumer to use when flushing messages
32
+ */
33
+ private $_consumer = null;
34
+
35
+
36
+ /**
37
+ * @var array The list of available consumers
38
+ */
39
+ private $_consumers = array(
40
+ "file" => "LI_ConsumerStrategies_FileConsumer",
41
+ "curl" => "LI_ConsumerStrategies_CurlConsumer",
42
+ "socket" => "LI_ConsumerStrategies_SocketConsumer"
43
+ );
44
+
45
+
46
+ /**
47
+ * If the queue reaches this size we'll auto-flush to prevent out of memory errors
48
+ * @var int
49
+ */
50
+ protected $_max_queue_size = 1000;
51
+
52
+
53
+ /**
54
+ * Creates a new MixpanelBaseProducer, assings Mixpanel project token, registers custom Consumers, and instantiates
55
+ * the desired consumer
56
+ * @param $token
57
+ * @param array $options
58
+ */
59
+ public function __construct($token, $options = array()) {
60
+
61
+ parent::__construct($options);
62
+
63
+ // register any customer consumers
64
+ if (array_key_exists("consumers", $options)) {
65
+ $this->_consumers = array_merge($this->_consumers, $options['consumers']);
66
+ }
67
+
68
+ // set max queue size
69
+ if (array_key_exists("max_queue_size", $options)) {
70
+ $this->_max_queue_size = $options['max_queue_size'];
71
+ }
72
+
73
+ // associate token
74
+ $this->_token = $token;
75
+
76
+ if ($this->_debug()) {
77
+ $this->_log("Using token: ".$this->_token);
78
+ }
79
+
80
+ // instantiate the chosen consumer
81
+ $this->_consumer = $this->_getConsumer();
82
+
83
+ }
84
+
85
+
86
+ /**
87
+ * Flush the queue when we destruct the client with retries
88
+ */
89
+ public function __destruct() {
90
+ $attempts = 0;
91
+ $max_attempts = 10;
92
+ $success = false;
93
+ while (!$success && $attempts < $max_attempts) {
94
+ if ($this->_debug()) {
95
+ $this->_log("destruct flush attempt #".($attempts+1));
96
+ }
97
+ $success = $this->flush();
98
+ $attempts++;
99
+ }
100
+ }
101
+
102
+
103
+ /**
104
+ * Iterate the queue and write in batches using the instantiated Consumer Strategy
105
+ * @param int $desired_batch_size
106
+ * @return bool whether or not the flush was successful
107
+ */
108
+ public function flush($desired_batch_size = 50) {
109
+ $queue_size = count($this->_queue);
110
+ $succeeded = true;
111
+ if ($this->_debug()) {
112
+ $this->_log("Flush called - queue size: ".$queue_size);
113
+ }
114
+
115
+ while($queue_size > 0 && $succeeded) {
116
+ $batch_size = min(array($queue_size, $desired_batch_size, $this->_options['max_batch_size']));
117
+ $batch = array_splice($this->_queue, 0, $batch_size);
118
+ $succeeded = $this->_persist($batch);
119
+
120
+ if (!$succeeded) {
121
+ if ($this->_debug()) {
122
+ $this->_log("Batch consumption failed!");
123
+ }
124
+ $this->_queue = array_merge($batch, $this->_queue);
125
+
126
+ if ($this->_debug()) {
127
+ $this->_log("added batch back to queue, queue size is now $queue_size");
128
+ }
129
+ }
130
+
131
+ $queue_size = count($this->_queue);
132
+
133
+ if ($this->_debug()) {
134
+ $this->_log("Batch of $batch_size consumed, queue size is now $queue_size");
135
+ }
136
+ }
137
+ return $succeeded;
138
+ }
139
+
140
+
141
+ /**
142
+ * Empties the queue without persisting any of the messages
143
+ */
144
+ public function reset() {
145
+ $this->_queue = array();
146
+ }
147
+
148
+
149
+ /**
150
+ * Returns the in-memory queue
151
+ * @return array
152
+ */
153
+ public function getQueue() {
154
+ return $this->_queue;
155
+ }
156
+
157
+ /**
158
+ * Returns the current Mixpanel project token
159
+ * @return string
160
+ */
161
+ public function getToken() {
162
+ return $this->_token;
163
+ }
164
+
165
+
166
+ /**
167
+ * Given a strategy type, return a new PersistenceStrategy object
168
+ * @return LI_ConsumerStrategies_AbstractConsumer
169
+ */
170
+ protected function _getConsumer() {
171
+ $key = $this->_options['consumer'];
172
+ $Strategy = $this->_consumers[$key];
173
+ if ($this->_debug()) {
174
+ $this->_log("Using consumer: " . $key . " -> " . $Strategy);
175
+ }
176
+ $this->_options['endpoint'] = $this->_getEndpoint();
177
+
178
+ return new $Strategy($this->_options);
179
+ }
180
+
181
+
182
+ /**
183
+ * Add an array representing a message to be sent to Mixpanel to a queue.
184
+ * @param array $message
185
+ */
186
+ public function enqueue($message = array()) {
187
+ array_push($this->_queue, $message);
188
+
189
+ // force a flush if we've reached our threshold
190
+ if (count($this->_queue) > $this->_max_queue_size) {
191
+ $this->flush();
192
+ }
193
+
194
+ if ($this->_debug()) {
195
+ $this->_log("Queued message: ".json_encode($message));
196
+ }
197
+ }
198
+
199
+
200
+ /**
201
+ * Add an array representing a list of messages to be sent to Mixpanel to a queue.
202
+ * @param array $messages
203
+ */
204
+ public function enqueueAll($messages = array()) {
205
+ foreach($messages as $message) {
206
+ $this->enqueue($message);
207
+ }
208
+
209
+ }
210
+
211
+
212
+ /**
213
+ * Given an array of messages, persist it with the instantiated Persistence Strategy
214
+ * @param $message
215
+ * @return mixed
216
+ */
217
+ protected function _persist($message) {
218
+ return $this->_consumer->persist($message);
219
+ }
220
+
221
+
222
+
223
+
224
+ /**
225
+ * Return the endpoint that should be used by a consumer that consumes messages produced by this producer.
226
+ * @return string
227
+ */
228
+ abstract function _getEndpoint();
229
+
230
+ }
lib/mixpanel/Producers/LI_MixpanelEvents.php ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(dirname(__FILE__) . "/LI_MixpanelBaseProducer.php");
4
+ require_once(dirname(__FILE__) . "/LI_MixpanelPeople.php");
5
+ require_once(dirname(__FILE__) . "/../ConsumerStrategies/LI_CurlConsumer.php");
6
+
7
+ /**
8
+ * Provides an API to track events on Mixpanel
9
+ */
10
+ class LI_Producers_MixpanelEvents extends LI_Producers_MixpanelBaseProducer {
11
+
12
+ /**
13
+ * An array of properties to attach to every tracked event
14
+ * @var array
15
+ */
16
+ private $_super_properties = array("mp_lib" => "php");
17
+
18
+
19
+ /**
20
+ * Track an event defined by $event associated with metadata defined by $properties
21
+ * @param string $event
22
+ * @param array $properties
23
+ */
24
+ public function track($event, $properties = array()) {
25
+
26
+ // if no token is passed in, use current token
27
+ if (!array_key_exists("token", $properties)) $properties['token'] = $this->_token;
28
+
29
+ // if no time is passed in, use the current time
30
+ if (!array_key_exists('time', $properties)) $properties['time'] = time();
31
+
32
+ $params['event'] = $event;
33
+ $params['properties'] = array_merge($this->_super_properties, $properties);
34
+
35
+ $this->enqueue($params);
36
+ }
37
+
38
+
39
+ /**
40
+ * Register a property to be sent with every event. If the property has already been registered, it will be
41
+ * overwritten.
42
+ * @param string $property
43
+ * @param mixed $value
44
+ */
45
+ public function register($property, $value) {
46
+ $this->_super_properties[$property] = $value;
47
+ }
48
+
49
+
50
+ /**
51
+ * Register multiple properties to be sent with every event. If any of the properties have already been registered,
52
+ * they will be overwritten.
53
+ * @param array $props_and_vals
54
+ */
55
+ public function registerAll($props_and_vals = array()) {
56
+ foreach($props_and_vals as $property => $value) {
57
+ $this->register($property, $value);
58
+ }
59
+ }
60
+
61
+
62
+ /**
63
+ * Register a property to be sent with every event. If the property has already been registered, it will NOT be
64
+ * overwritten.
65
+ * @param $property
66
+ * @param $value
67
+ */
68
+ public function registerOnce($property, $value) {
69
+ if (!isset($this->_super_properties[$property])) {
70
+ $this->register($property, $value);
71
+ }
72
+ }
73
+
74
+
75
+ /**
76
+ * Register multiple properties to be sent with every event. If any of the properties have already been registered,
77
+ * they will NOT be overwritten.
78
+ * @param array $props_and_vals
79
+ */
80
+ public function registerAllOnce($props_and_vals = array()) {
81
+ foreach($props_and_vals as $property => $value) {
82
+ if (!isset($this->_super_properties[$property])) {
83
+ $this->register($property, $value);
84
+ }
85
+ }
86
+ }
87
+
88
+
89
+ /**
90
+ * Un-register an property to be sent with every event.
91
+ * @param string $property
92
+ */
93
+ public function unregister($property) {
94
+ unset($this->_super_properties[$property]);
95
+ }
96
+
97
+
98
+ /**
99
+ * Un-register a list of properties to be sent with every event.
100
+ * @param array $properties
101
+ */
102
+ public function unregisterAll($properties) {
103
+ foreach($properties as $property) {
104
+ $this->unregister($property);
105
+ }
106
+ }
107
+
108
+
109
+ /**
110
+ * Get a property that is set to be sent with every event
111
+ * @param string $property
112
+ * @return mixed
113
+ */
114
+ public function getProperty($property) {
115
+ return $this->_super_properties[$property];
116
+ }
117
+
118
+
119
+ /**
120
+ * Identify the user you want to associate to tracked events
121
+ * @param string|int $user_id
122
+ */
123
+ public function identify($user_id) {
124
+ $this->register("distinct_id", $user_id);
125
+ }
126
+
127
+
128
+ /**
129
+ * Alias an existing id with a different unique id. This is helpful when you want to associate a generated id to
130
+ * a username or e-mail address.
131
+ *
132
+ * Because aliasing can be extremely vulnerable to race conditions and ordering issues, we'll make a synchronous
133
+ * call directly to Mixpanel when this method is called. If it fails we'll throw an Exception as subsequent
134
+ * events are likely to be incorrectly tracked.
135
+ * @param string|int $original_id
136
+ * @param string|int $new_id
137
+ * @return array $msg
138
+ * @throws Exception
139
+ */
140
+ public function createAlias($original_id, $new_id) {
141
+ $msg = array(
142
+ "event" => '$create_alias',
143
+ "properties" => array("distinct_id" => $original_id, "alias" => $new_id, "token" => $this->_token)
144
+ );
145
+
146
+ $options = array_merge($this->_options, array("endpoint" => $this->_getEndpoint(), "fork" => false));
147
+ $LI_CurlConsumer = new LI_ConsumerStrategies_CurlConsumer($options);
148
+ $success = $LI_CurlConsumer->persist(array($msg));
149
+ if (!$success) {
150
+ //error_log("Creating Mixpanel Alias (original id: $original_id, new id: $new_id) failed");
151
+ //throw new Exception("Tried to create an alias but the call was not successful");
152
+ } else {
153
+ return $msg;
154
+ }
155
+ }
156
+
157
+
158
+ /**
159
+ * Returns the "events" endpoint
160
+ * @return string
161
+ */
162
+ function _getEndpoint() {
163
+ return $this->_options['events_endpoint'];
164
+ }
165
+ }
lib/mixpanel/Producers/LI_MixpanelPeople.php ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require_once(dirname(__FILE__) . "/LI_MixpanelBaseProducer.php");
4
+
5
+ /**
6
+ * Provides an API to create/update profiles on Mixpanel
7
+ */
8
+ class LI_Producers_MixpanelPeople extends LI_Producers_MixpanelBaseProducer {
9
+
10
+ /**
11
+ * Internal method to prepare a message given the message data
12
+ * @param $distinct_id
13
+ * @param $operation
14
+ * @param $value
15
+ * @param null $ip
16
+ * @return array
17
+ */
18
+ private function _constructPayload($distinct_id, $operation, $value, $ip = null) {
19
+ $payload = array(
20
+ '$token' => $this->_token,
21
+ '$distinct_id' => $distinct_id,
22
+ $operation => $value
23
+ );
24
+ if ($ip !== null) $payload['$ip'] = $ip;
25
+ return $payload;
26
+ }
27
+
28
+ /**
29
+ * Set properties on a user record. If the profile does not exist, it creates it with these properties.
30
+ * If it does exist, it sets the properties to these values, overwriting existing values.
31
+ * @param string|int $distinct_id the distinct_id or alias of a user
32
+ * @param array $props associative array of properties to set on the profile
33
+ * @param string|null $ip the ip address of the client (used for geo-location)
34
+ */
35
+ public function set($distinct_id, $props, $ip = null) {
36
+ $payload = $this->_constructPayload($distinct_id, '$set', $props, $ip);
37
+ $this->enqueue($payload);
38
+ }
39
+
40
+ /**
41
+ * Set properties on a user record. If the profile does not exist, it creates it with these properties.
42
+ * If it does exist, it sets the properties to these values but WILL NOT overwrite existing values.
43
+ * @param string|int $distinct_id the distinct_id or alias of a user
44
+ * @param array $props associative array of properties to set on the profile
45
+ * @param string|null $ip the ip address of the client (used for geo-location)
46
+ */
47
+ public function setOnce($distinct_id, $props, $ip = null) {
48
+ $payload = $this->_constructPayload($distinct_id, '$set_once', $props, $ip);
49
+ $this->enqueue($payload);
50
+ }
51
+
52
+ /**
53
+ * Unset properties on a user record. If the profile does not exist, it creates it with no properties.
54
+ * If it does exist, it unsets these properties. NOTE: In other libraries we use 'unset' which is
55
+ * a reserved word in PHP.
56
+ * @param string|int $distinct_id the distinct_id or alias of a user
57
+ * @param array $props associative array of properties to unset on the profile
58
+ * @param string|null $ip the ip address of the client (used for geo-location)
59
+ */
60
+ public function remove($distinct_id, $props, $ip = null) {
61
+ $payload = $this->_constructPayload($distinct_id, '$unset', $props, $ip);
62
+ $this->enqueue($payload);
63
+ }
64
+
65
+ /**
66
+ * Increments the value of a property on a user record. If the profile does not exist, it creates it and sets the
67
+ * property to the increment value.
68
+ * @param string|int $distinct_id the distinct_id or alias of a user
69
+ * @param $prop string the property to increment
70
+ * @param int $val the amount to increment the property by
71
+ * @param string|null $ip the ip address of the client (used for geo-location)
72
+ */
73
+ public function increment($distinct_id, $prop, $val, $ip = null) {
74
+ $payload = $this->_constructPayload($distinct_id, '$add', array("$prop" => $val), $ip);
75
+ $this->enqueue($payload);
76
+ }
77
+
78
+ /**
79
+ * Adds $val to a list located at $prop. If the property does not exist, it will be created. If $val is a string
80
+ * and the list is empty or does not exist, a new list with one value will be created.
81
+ * @param string|int $distinct_id the distinct_id or alias of a user
82
+ * @param string $prop the property that holds the list
83
+ * @param string|array $val items to add to the list
84
+ * @param string|null $ip the ip address of the client (used for geo-location)
85
+ */
86
+ public function append($distinct_id, $prop, $val, $ip = null) {
87
+ $operation = gettype($val) == "array" ? '$union' : '$append';
88
+ $payload = $this->_constructPayload($distinct_id, $operation, array("$prop" => $val), $ip);
89
+ $this->enqueue($payload);
90
+ }
91
+
92
+ /**
93
+ * Adds a transaction to the user's profile for revenue tracking
94
+ * @param string|int $distinct_id the distinct_id or alias of a user
95
+ * @param string $amount the transaction amount e.g. "20.50"
96
+ * @param null $timestamp the timestamp of when the transaction occurred (default to current timestamp)
97
+ * @param string|null $ip the ip address of the client (used for geo-location)
98
+ */
99
+ public function trackCharge($distinct_id, $amount, $timestamp = null, $ip = null) {
100
+ $timestamp = $timestamp == null ? time() : $timestamp;
101
+ $date_iso = date("c", $timestamp);
102
+ $transaction = array(
103
+ '$time' => $date_iso,
104
+ '$amount' => $amount
105
+ );
106
+ $val = array('$transactions' => $transaction);
107
+ $payload = $this->_constructPayload($distinct_id, '$append', $val, $ip);
108
+ $this->enqueue($payload);
109
+ }
110
+
111
+ /**
112
+ * Clear all transactions stored on a user's profile
113
+ * @param string|int $distinct_id the distinct_id or alias of a user
114
+ * @param string|null $ip the ip address of the client (used for geo-location)
115
+ */
116
+ public function clearCharges($distinct_id, $ip = null) {
117
+ $payload = $this->_constructPayload($distinct_id, '$set', array('$transactions' => array()), $ip);
118
+ $this->enqueue($payload);
119
+ }
120
+
121
+ /**
122
+ * Delete this profile from Mixpanel
123
+ * @param string|int $distinct_id the distinct_id or alias of a user
124
+ * @param string|null $ip the ip address of the client (used for geo-location)
125
+ */
126
+ public function deleteUser($distinct_id, $ip = null) {
127
+ $payload = $this->_constructPayload($distinct_id, '$delete', "", $ip);
128
+ $this->enqueue($payload);
129
+ }
130
+
131
+ /**
132
+ * Returns the "engage" endpoint
133
+ * @return string
134
+ */
135
+ function _getEndpoint() {
136
+ return $this->_options['people_endpoint'];
137
+ }
138
+
139
+ }
lib/segment/lib/Segment.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!function_exists('json_encode')) {
4
+ throw new Exception('Segment needs the JSON PHP extension.');
5
+ }
6
+
7
+ require(dirname(__FILE__) . '/Segment/Client.php');
8
+
9
+
10
+ class Segment {
11
+
12
+ private static $client;
13
+
14
+ /**
15
+ * Initializes the default client to use. Uses the socket consumer by default.
16
+ * @param string $secret your project's secret key
17
+ * @param array $options passed straight to the client
18
+ */
19
+ public static function init($secret, $options = array()) {
20
+ self::assert($secret, "Segment::init() requires secret");
21
+ self::$client = new Segment_Client($secret, $options);
22
+ }
23
+
24
+ /**
25
+ * Tracks a user action
26
+ *
27
+ * @param array $message
28
+ * @return boolean whether the track call succeeded
29
+ */
30
+ public static function track(array $message) {
31
+ self::checkClient();
32
+ $event = !empty($message["event"]);
33
+ self::assert($event, "Segment::track() expects an event");
34
+ self::validate($message, "track");
35
+ return self::$client->track($message);
36
+ }
37
+
38
+ /**
39
+ * Tags traits about the user.
40
+ *
41
+ * @param array $message
42
+ * @return boolean whether the identify call succeeded
43
+ */
44
+ public static function identify(array $message) {
45
+ self::checkClient();
46
+ $message["type"] = "identify";
47
+ self::validate($message, "identify");
48
+ return self::$client->identify($message);
49
+ }
50
+
51
+ /**
52
+ * Tags traits about the group.
53
+ *
54
+ * @param array $message
55
+ * @return boolean whether the group call succeeded
56
+ */
57
+ public static function group(array $message) {
58
+ self::checkClient();
59
+ $groupId = !empty($message["groupId"]);
60
+ $userId = !empty($message["userId"]);
61
+ self::assert($groupId && $userId, "Segment::group() expects userId and groupId");
62
+ return self::$client->group($message);
63
+ }
64
+
65
+ /**
66
+ * Tracks a page view
67
+ *
68
+ * @param array $message
69
+ * @return boolean whether the page call succeeded
70
+ */
71
+ public static function page(array $message) {
72
+ self::checkClient();
73
+ self::validate($message, "page");
74
+ return self::$client->page($message);
75
+ }
76
+
77
+ /**
78
+ * Tracks a screen view
79
+ *
80
+ * @param array $message
81
+ * @return boolean whether the screen call succeeded
82
+ */
83
+ public static function screen(array $message) {
84
+ self::checkClient();
85
+ self::validate($message, "screen");
86
+ return self::$client->screen($message);
87
+ }
88
+
89
+ /**
90
+ * Aliases the user id from a temporary id to a permanent one
91
+ *
92
+ * @param array $from user id to alias from
93
+ * @return boolean whether the alias call succeeded
94
+ */
95
+ public static function alias(array $message) {
96
+ self::checkClient();
97
+ $userId = !empty($message["userId"]);
98
+ $previousId = !empty($message["previousId"]);
99
+ self::assert($userId && $previousId, "Segment::alias() requires both userId and previousId");
100
+ return self::$client->alias($message);
101
+ }
102
+
103
+ /**
104
+ * Validate common properties.
105
+ *
106
+ * @param array $msg
107
+ * @param string $type
108
+ */
109
+ public static function validate($msg, $type){
110
+ $userId = !empty($msg["userId"]);
111
+ $anonId = !empty($msg["anonymousId"]);
112
+ self::assert($userId || $anonId, "Segment::$type() requires userId or anonymousId");
113
+ }
114
+
115
+ /**
116
+ * Flush the client
117
+ */
118
+
119
+ public static function flush(){
120
+ self::checkClient();
121
+ return self::$client->flush();
122
+ }
123
+
124
+ /**
125
+ * Check the client.
126
+ *
127
+ * @throws Exception
128
+ */
129
+ private static function checkClient(){
130
+ if (null != self::$client) return;
131
+ throw new Exception("Analytics::init() must be called before any other tracking method.");
132
+ }
133
+
134
+ /**
135
+ * Assert `value` or throw.
136
+ *
137
+ * @param array $value
138
+ * @param string $msg
139
+ * @throws Exception
140
+ */
141
+ private static function assert($value, $msg){
142
+ if (!$value) throw new Exception($msg);
143
+ }
144
+
145
+ }
lib/segment/lib/Segment/Client.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ require(__DIR__ . '/Consumer.php');
4
+ require(__DIR__ . '/QueueConsumer.php');
5
+ require(__DIR__ . '/Consumer/File.php');
6
+ require(__DIR__ . '/Consumer/ForkCurl.php');
7
+ require(__DIR__ . '/Consumer/Socket.php');
8
+
9
+ class Segment_Client {
10
+
11
+ /**
12
+ * VERSION
13
+ */
14
+
15
+ const VERSION = "1.1.0";
16
+
17
+ private $consumer;
18
+
19
+ /**
20
+ * Create a new analytics object with your app's secret
21
+ * key
22
+ *
23
+ * @param string $secret
24
+ * @param array $options array of consumer options [optional]
25
+ * @param string Consumer constructor to use, socket by default.
26
+ */
27
+ public function __construct($secret, $options = array()) {
28
+
29
+ $consumers = array(
30
+ "socket" => "Segment_Consumer_Socket",
31
+ "file" => "Segment_Consumer_File",
32
+ "fork_curl" => "Segment_Consumer_ForkCurl"
33
+ );
34
+
35
+ # Use our socket consumer by default
36
+ $consumer_type = isset($options["consumer"]) ? $options["consumer"] :
37
+ "socket";
38
+ $Consumer = $consumers[$consumer_type];
39
+
40
+ $this->consumer = new $Consumer($secret, $options);
41
+ }
42
+
43
+ public function __destruct() {
44
+ $this->consumer->__destruct();
45
+ }
46
+
47
+ /**
48
+ * Tracks a user action
49
+ *
50
+ * @param array $message
51
+ * @return [boolean] whether the track call succeeded
52
+ */
53
+ public function track(array $message) {
54
+ $message = $this->message($message, "properties");
55
+ $message["type"] = "track";
56
+ return $this->consumer->track($message);
57
+ }
58
+
59
+ /**
60
+ * Tags traits about the user.
61
+ *
62
+ * @param [array] $message
63
+ * @return [boolean] whether the track call succeeded
64
+ */
65
+ public function identify(array $message) {
66
+ $message = $this->message($message, "traits");
67
+ $message["type"] = "identify";
68
+ return $this->consumer->identify($message);
69
+ }
70
+
71
+ /**
72
+ * Tags traits about the group.
73
+ *
74
+ * @param [array] $message
75
+ * @return [boolean] whether the group call succeeded
76
+ */
77
+ public function group(array $message) {
78
+ $message = $this->message($message, "traits");
79
+ $message["type"] = "group";
80
+ return $this->consumer->group($message);
81
+ }
82
+
83
+ /**
84
+ * Tracks a page view.
85
+ *
86
+ * @param [array] $message
87
+ * @return [boolean] whether the page call succeeded
88
+ */
89
+ public function page(array $message) {
90
+ $message = $this->message($message, "properties");
91
+ $message["type"] = "page";
92
+ return $this->consumer->page($message);
93
+ }
94
+
95
+ /**
96
+ * Tracks a screen view.
97
+ *
98
+ * @param [array] $message
99
+ * @return [boolean] whether the screen call succeeded
100
+ */
101
+ public function screen(array $message) {
102
+ $message = $this->message($message, "properties");
103
+ $message["type"] = "screen";
104
+ return $this->consumer->screen($message);
105
+ }
106
+
107
+ /**
108
+ * Aliases from one user id to another
109
+ *
110
+ * @param array $message
111
+ * @return boolean whether the alias call succeeded
112
+ */
113
+ public function alias(array $message) {
114
+ $message = $this->message($message);
115
+ $message["type"] = "alias";
116
+ return $this->consumer->alias($message);
117
+ }
118
+
119
+ /**
120
+ * Flush any async consumers
121
+ */
122
+ public function flush() {
123
+ if (!method_exists($this->consumer, 'flush')) return;
124
+ $this->consumer->flush();
125
+ }
126
+
127
+ /**
128
+ * Formats a timestamp by making sure it is set
129
+ * and converting it to iso8601.
130
+ *
131
+ * The timestamp can be time in seconds `time()` or `microseconds(true)`.
132
+ * any other input is considered an error and the method will return a new date.
133
+ *
134
+ * Note: php's date() "u" format (for microseconds) has a bug in it
135
+ * it always shows `.000` for microseconds since `date()` only accepts
136
+ * ints, so we have to construct the date ourselves if microtime is passed.
137
+ *
138
+ * @param time $timestamp - time in seconds (time())
139
+ */
140
+ private function formatTime($ts) {
141
+ if ($ts == null) $ts = time();
142
+ if ("integer" == gettype($ts)) return date("c", $ts);
143
+ if (-1 == ($pos = strrpos($ts, "."))) return date("c");
144
+ $sec = substr($ts, 0, $pos);
145
+ $usec = substr($ts, $pos);
146
+ $fmt = sprintf("Y-m-d\TH:i:s%sP", $usec);
147
+ return date($fmt, (int)$sec);
148
+ }
149
+
150
+ /**
151
+ * Add common fields to the gvien `message`
152
+ *
153
+ * @param array $msg
154
+ * @param string $def
155
+ * @return array
156
+ */
157
+
158
+ private function message($msg, $def = ""){
159
+ if ($def && !isset($msg[$def])) $msg[$def] = array();
160
+ if ($def && empty($msg[$def])) $msg[$def] = (object)$msg[$def];
161
+ if (!isset($msg["context"])) $msg["context"] = array();
162
+ if (!isset($msg["timestamp"])) $msg["timestamp"] = null;
163
+ $msg["context"] = array_merge($msg["context"], $this->getContext());
164
+ $msg["timestamp"] = $this->formatTime($msg["timestamp"]);
165
+ $msg["messageId"] = self::messageId();
166
+ return $msg;
167
+ }
168
+
169
+ /**
170
+ * Generate a random messageId.
171
+ *
172
+ * https://gist.github.com/dahnielson/508447#file-uuid-php-L74
173
+ *
174
+ * @return string
175
+ */
176
+
177
+ private static function messageId(){
178
+ return sprintf("%04x%04x-%04x-%04x-%04x-%04x%04x%04x"
179
+ , mt_rand(0, 0xffff)
180
+ , mt_rand(0, 0xffff)
181
+ , mt_rand(0, 0xffff)
182
+ , mt_rand(0, 0x0fff) | 0x4000
183
+ , mt_rand(0, 0x3fff) | 0x8000
184
+ , mt_rand(0, 0xffff)
185
+ , mt_rand(0, 0xffff)
186
+ , mt_rand(0, 0xffff));
187
+ }
188
+
189
+ /**
190
+ * Add the segment.io context to the request
191
+ * @return array additional context
192
+ */
193
+ private function getContext () {
194
+ return array(
195
+ "library" => array(
196
+ "name" => "analytics-php",
197
+ "version" => self::VERSION
198
+ )
199
+ );
200
+ }
201
+ }
lib/segment/lib/Segment/Consumer.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ abstract class Segment_Consumer {
3
+
4
+ protected $type = "Consumer";
5
+
6
+ protected $options;
7
+ protected $secret;
8
+
9
+ /**
10
+ * Store our secret and options as part of this consumer
11
+ * @param string $secret
12
+ * @param array $options
13
+ */
14
+ public function __construct($secret, $options = array()) {
15
+ $this->secret = $secret;
16
+ $this->options = $options;
17
+ }
18
+
19
+
20
+ /**
21
+ * Tracks a user action
22
+ *
23
+ * @param array $message
24
+ * @return boolean whether the track call succeeded
25
+ */
26
+ abstract public function track(array $message);
27
+
28
+ /**
29
+ * Tags traits about the user.
30
+ *
31
+ * @param array $message
32
+ * @return boolean whether the identify call succeeded
33
+ */
34
+ abstract public function identify(array $message);
35
+
36
+ /**
37
+ * Tags traits about the group.
38
+ *
39
+ * @param array $message
40
+ * @return boolean whether the group call succeeded
41
+ */
42
+ abstract public function group(array $message);
43
+
44
+ /**
45
+ * Tracks a page view.
46
+ *
47
+ * @param array $message
48
+ * @return boolean whether the page call succeeded
49
+ */
50
+ abstract public function page(array $message);
51
+
52
+ /**
53
+ * Tracks a screen view.
54
+ *
55
+ * @param array $message
56
+ * @return boolean whether the group call succeeded
57
+ */
58
+ abstract public function screen(array $message);
59
+
60
+ /**
61
+ * Aliases from one user id to another
62
+ *
63
+ * @param array $message
64
+ * @return boolean whether the alias call succeeded
65
+ */
66
+ abstract public function alias(array $message);
67
+
68
+ /**
69
+ * Check whether debug mode is enabled
70
+ * @return boolean
71
+ */
72
+ protected function debug() {
73
+ return isset($this->options["debug"]) ? $this->options["debug"] : false;
74
+ }
75
+
76
+ /**
77
+ * Check whether we should connect to the API using SSL. This is enabled by
78
+ * default with connections which make batching requests. For connections
79
+ * which can save on round-trip times, we disable it.
80
+ * @return boolean
81
+ */
82
+ protected function ssl() {
83
+ return isset($this->options["ssl"]) ? $this->options["ssl"] : false;
84
+ }
85
+
86
+
87
+ /**
88
+ * On an error, try and call the error handler, if debugging output to
89
+ * error_log as well.
90
+ * @param string $code
91
+ * @param string $msg
92
+ */
93
+ protected function handleError($code, $msg) {
94
+
95
+ if (isset($this->options['error_handler'])) {
96
+ $handler = $this->options['error_handler'];
97
+ $handler($code, $msg);
98
+ }
99
+
100
+ if ($this->debug()) {
101
+ error_log("[Analytics][" . $this->type . "] " . $msg);
102
+ }
103
+ }
104
+ }
lib/segment/lib/Segment/Consumer/File.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Segment_Consumer_File extends Segment_Consumer {
4
+
5
+ private $file_handle;
6
+ protected $type = "File";
7
+
8
+ /**
9
+ * The file consumer writes track and identify calls to a file.
10
+ * @param string $secret
11
+ * @param array $options
12
+ * string "filename" - where to log the analytics calls
13
+ */
14
+ public function __construct($secret, $options = array()) {
15
+
16
+ if (!isset($options["filename"]))
17
+ $options["filename"] = sys_get_temp_dir() . DIRECTORY_SEPARATOR . "analytics.log";
18
+
19
+ parent::__construct($secret, $options);
20
+
21
+ try {
22
+ $this->file_handle = fopen($options["filename"], "a");
23
+ chmod($options["filename"], 0777);
24
+ } catch (Exception $e) {
25
+ $this->handleError($e->getCode(), $e->getMessage());
26
+ }
27
+ }
28
+
29
+ public function __destruct() {
30
+ if ($this->file_handle &&
31
+ get_resource_type($this->file_handle) != "Unknown") {
32
+ fclose($this->file_handle);
33
+ }
34
+ }
35
+
36
+ /**
37
+ * Tracks a user action
38
+ *
39
+ * @param array $message
40
+ * @return [boolean] whether the track call succeeded
41
+ */
42
+ public function track(array $message) {
43
+ return $this->write($message);
44
+ }
45
+
46
+ /**
47
+ * Tags traits about the user.
48
+ *
49
+ * @param array $message
50
+ * @return [boolean] whether the identify call succeeded
51
+ */
52
+ public function identify(array $message) {
53
+ return $this->write($message);
54
+ }
55
+
56
+ /**
57
+ * Tags traits about the group.
58
+ *
59
+ * @param array $message
60
+ * @return [boolean] whether the group call succeeded
61
+ */
62
+ public function group(array $message) {
63
+ return $this->write($message);
64
+ }
65
+
66
+ /**
67
+ * Tracks a page view.
68
+ *
69
+ * @param array $message
70
+ * @return [boolean] whether the page call succeeded
71
+ */
72
+ public function page(array $message) {
73
+ return $this->write($message);
74
+ }
75
+
76
+ /**
77
+ * Tracks a screen view.
78
+ *
79
+ * @param array $message
80
+ * @return [boolean] whether the screen call succeeded
81
+ */
82
+ public function screen(array $message) {
83
+ return $this->write($message);
84
+ }
85
+
86
+ /**
87
+ * Aliases from one user id to another
88
+ *
89
+ * @param array $message
90
+ * @return boolean whether the alias call succeeded
91
+ */
92
+ public function alias(array $message) {
93
+ return $this->write($message);
94
+ }
95
+
96
+ /**
97
+ * Writes the API call to a file as line-delimited json
98
+ * @param [array] $body post body content.
99
+ * @return [boolean] whether the request succeeded
100
+ */
101
+ private function write($body) {
102
+
103
+ if (!$this->file_handle)
104
+ return false;
105
+
106
+ $content = json_encode($body);
107
+ $content.= "\n";
108
+
109
+ return fwrite($this->file_handle, $content) == strlen($content);
110
+ }
111
+ }
lib/segment/lib/Segment/Consumer/ForkCurl.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Segment_Consumer_ForkCurl extends Segment_QueueConsumer {
4
+
5
+ protected $type = "ForkCurl";
6
+
7
+
8
+ /**
9
+ * Creates a new queued fork consumer which queues fork and identify
10
+ * calls before adding them to
11
+ * @param string $secret
12
+ * @param array $options
13
+ * boolean "debug" - whether to use debug output, wait for response.
14
+ * number "max_queue_size" - the max size of messages to enqueue
15
+ * number "batch_size" - how many messages to send in a single request
16
+ */
17
+ public function __construct($secret, $options = array()) {
18
+ parent::__construct($secret, $options);
19
+ }
20
+
21
+ /**
22
+ * Make an async request to our API. Fork a curl process, immediately send
23
+ * to the API. If debug is enabled, we wait for the response.
24
+ * @param array $messages array of all the messages to send
25
+ * @return boolean whether the request succeeded
26
+ */
27
+ public function flushBatch($messages) {
28
+
29
+ $body = array(
30
+ "batch" => $messages,
31
+ );
32
+
33
+ $payload = json_encode($body);
34
+
35
+ # Escape for shell usage.
36
+ $payload = escapeshellarg($payload);
37
+ $secret = $this->secret;
38
+
39
+ $protocol = $this->ssl() ? "https://" : "http://";
40
+ $host = "api.segment.io";
41
+ $path = "/v1/import";
42
+ $url = $protocol . $host . $path;
43
+
44
+ $cmd = "curl -u $secret: -X POST -H 'Content-Type: application/json'";
45
+ $cmd.= " -d " . $payload . " '" . $url . "'";
46
+
47
+ if (!$this->debug()) {
48
+ $cmd .= " > /dev/null 2>&1 &";
49
+ }
50
+
51
+ exec($cmd, $output, $exit);
52
+
53
+ if ($exit != 0) {
54
+ $this->handleError($exit, $output);
55
+ }
56
+
57
+ return $exit == 0;
58
+ }
59
+ }
lib/segment/lib/Segment/Consumer/Socket.php ADDED
@@ -0,0 +1,174 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Segment_Consumer_Socket extends Segment_QueueConsumer {
4
+
5
+ protected $type = "Socket";
6
+ private $socket_failed;
7
+
8
+ /**
9
+ * Creates a new socket consumer for dispatching async requests immediately
10
+ * @param string $secret
11
+ * @param array $options
12
+ * number "timeout" - the timeout for connecting
13
+ * function "error_handler" - function called back on errors.
14
+ * boolean "debug" - whether to use debug output, wait for response.
15
+ */
16
+ public function __construct($secret, $options = array()) {
17
+
18
+ if (!isset($options["timeout"]))
19
+ $options["timeout"] = 0.5;
20
+
21
+ if (!isset($options["host"]))
22
+ $options["host"] = "api.segment.io";
23
+
24
+ parent::__construct($secret, $options);
25
+ }
26
+
27
+
28
+ public function flushBatch($batch) {
29
+ $socket = $this->createSocket();
30
+
31
+ if (!$socket)
32
+ return;
33
+
34
+ $payload = array("batch" => $batch);
35
+
36
+ $payload = json_encode($payload);
37
+
38
+ $body = $this->createBody($this->options["host"], $payload);
39
+ return $this->makeRequest($socket, $body);
40
+ }
41
+
42
+
43
+ private function createSocket() {
44
+
45
+ if ($this->socket_failed)
46
+ return false;
47
+
48
+ $protocol = $this->ssl() ? "ssl" : "tcp";
49
+ $host = $this->options["host"];
50
+ $port = $this->ssl() ? 443 : 80;
51
+ $timeout = $this->options["timeout"];
52
+
53
+ try {
54
+ # Open our socket to the API Server.
55
+ # Since we're try catch'ing prevent PHP logs.
56
+ $socket = @pfsockopen($protocol . "://" . $host, $port, $errno,
57
+ $errstr, $timeout);
58
+
59
+ # If we couldn't open the socket, handle the error.
60
+ if ($errno != 0) {
61
+ $this->handleError($errno, $errstr);
62
+ $this->socket_failed = true;
63
+ return false;
64
+ }
65
+
66
+ return $socket;
67
+
68
+ } catch (Exception $e) {
69
+ $this->handleError($e->getCode(), $e->getMessage());
70
+ $this->socket_failed = true;
71
+ return false;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Attempt to write the request to the socket, wait for response if debug
77
+ * mode is enabled.
78
+ * @param stream $socket the handle for the socket
79
+ * @param string $req request body
80
+ * @return boolean $success
81
+ */
82
+ private function makeRequest($socket, $req, $retry = true) {
83
+
84
+ $bytes_written = 0;
85
+ $bytes_total = strlen($req);
86
+ $closed = false;
87
+
88
+ # Write the request
89
+ while (!$closed && $bytes_written < $bytes_total) {
90
+ try {
91
+ # Since we're try catch'ing prevent PHP logs.
92
+ $written = @fwrite($socket, substr($req, $bytes_written));
93
+ } catch (Exception $e) {
94
+ $this->handleError($e->getCode(), $e->getMessage());
95
+ $closed = true;
96
+ }
97
+ if (!isset($written) || !$written) {
98
+ $closed = true;
99
+ } else {
100
+ $bytes_written += $written;
101
+ }
102
+ }
103
+
104
+ # If the socket has been closed, attempt to retry a single time.
105
+ if ($closed) {
106
+ fclose($socket);
107
+
108
+ if ($retry) {
109
+ $socket = $this->createSocket();
110
+ if ($socket) return $this->makeRequest($socket, $req, false);
111
+ }
112
+ return false;
113
+ }
114
+
115
+
116
+ $success = true;
117
+
118
+ if ($this->debug()) {
119
+ $res = $this->parseResponse(fread($socket, 2048));
120
+
121
+ if ($res["status"] != "200") {
122
+ $this->handleError($res["status"], $res["message"]);
123
+ $success = false;
124
+ }
125
+ }
126
+
127
+ return $success;
128
+ }
129
+
130
+
131
+ /**
132
+ * Create the body to send as the post request.
133
+ * @param string $host
134
+ * @param string $content
135
+ * @return string body
136
+ */
137
+ private function createBody($host, $content) {
138
+
139
+ $req = "";
140
+ $req.= "POST /v1/import HTTP/1.1\r\n";
141
+ $req.= "Host: " . $host . "\r\n";
142
+ $req.= "Content-Type: application/json\r\n";
143
+ $req.= "Authorization: Basic " . base64_encode($this->secret . ":") . "\r\n";
144
+ $req.= "Accept: application/json\r\n";
145
+ $req.= "Content-length: " . strlen($content) . "\r\n";
146
+ $req.= "\r\n";
147
+ $req.= $content;
148
+
149
+ return $req;
150
+ }
151
+
152
+
153
+ /**
154
+ * Parse our response from the server, check header and body.
155
+ * @param string $res
156
+ * @return array
157
+ * string $status HTTP code, e.g. "200"
158
+ * string $message JSON response from the api
159
+ */
160
+ private function parseResponse($res) {
161
+
162
+ $contents = explode("\n", $res);
163
+
164
+ # Response comes back as HTTP/1.1 200 OK
165
+ # Final line contains HTTP response.
166
+ $status = explode(" ", $contents[0], 3);
167
+ $result = $contents[count($contents) - 1];
168
+
169
+ return array(
170
+ "status" => isset($status[1]) ? $status[1] : null,
171
+ "message" => $result
172
+ );
173
+ }
174
+ }
lib/segment/lib/Segment/QueueConsumer.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ abstract class Segment_QueueConsumer extends Segment_Consumer {
3
+
4
+ protected $type = "QueueConsumer";
5
+
6
+ protected $queue;
7
+ protected $max_queue_size = 1000;
8
+ protected $batch_size = 100;
9
+
10
+ /**
11
+ * Store our secret and options as part of this consumer
12
+ * @param string $secret
13
+ * @param array $options
14
+ */
15
+ public function __construct($secret, $options = array()) {
16
+ parent::__construct($secret, $options);
17
+
18
+ if (isset($options["max_queue_size"]))
19
+ $this->max_queue_size = $options["max_queue_size"];
20
+
21
+ if (isset($options["batch_size"]))
22
+ $this->batch_size = $options["batch_size"];
23
+
24
+ $this->queue = array();
25
+ }
26
+
27
+ public function __destruct() {
28
+ # Flush our queue on destruction
29
+ $this->flush();
30
+ }
31
+
32
+ /**
33
+ * Tracks a user action
34
+ *
35
+ * @param array $message
36
+ * @return boolean whether the track call succeeded
37
+ */
38
+ public function track(array $message) {
39
+ return $this->enqueue($message);
40
+ }
41
+
42
+ /**
43
+ * Tags traits about the user.
44
+ *
45
+ * @param array $message
46
+ * @return boolean whether the identify call succeeded
47
+ */
48
+ public function identify(array $message) {
49
+ return $this->enqueue($message);
50
+ }
51
+
52
+ /**
53
+ * Tags traits about the group.
54
+ *
55
+ * @param array $message
56
+ * @return boolean whether the group call succeeded
57
+ */
58
+ public function group(array $message) {
59
+ return $this->enqueue($message);
60
+ }
61
+
62
+ /**
63
+ * Tracks a page view.
64
+ *
65
+ * @param array $message
66
+ * @return boolean whether the page call succeeded
67
+ */
68
+ public function page(array $message) {
69
+ return $this->enqueue($message);
70
+ }
71
+
72
+ /**
73
+ * Tracks a screen view.
74
+ *
75
+ * @param array $message
76
+ * @return boolean whether the screen call succeeded
77
+ */
78
+ public function screen(array $message) {
79
+ return $this->enqueue($message);
80
+ }
81
+
82
+ /**
83
+ * Aliases from one user id to another
84
+ *
85
+ * @param array $message
86
+ * @return boolean whether the alias call succeeded
87
+ */
88
+ public function alias(array $message) {
89
+ return $this->enqueue($message);
90
+ }
91
+
92
+ /**
93
+ * Adds an item to our queue.
94
+ * @param mixed $item
95
+ * @return boolean whether the queue has room
96
+ */
97
+ protected function enqueue($item) {
98
+
99
+ $count = count($this->queue);
100
+
101
+ if ($count > $this->max_queue_size)
102
+ return false;
103
+
104
+ $count = array_push($this->queue, $item);
105
+
106
+ if ($count > $this->batch_size)
107
+ $this->flush();
108
+
109
+ return true;
110
+ }
111
+
112
+
113
+ /**
114
+ * Flushes our queue of messages by batching them to the server
115
+ */
116
+ public function flush() {
117
+
118
+ $count = count($this->queue);
119
+ $success = true;
120
+
121
+ while($count > 0 && $success) {
122
+
123
+ $batch = array_splice($this->queue, 0, min($this->batch_size, $count));
124
+ $success = $this->flushBatch($batch);
125
+
126
+ $count = count($this->queue);
127
+ }
128
+
129
+ return $success;
130
+ }
131
+
132
+ /**
133
+ * Flushes a batch of messages.
134
+ * @param [type] $batch [description]
135
+ * @return [type] [description]
136
+ */
137
+ abstract function flushBatch($batch);
138
+ }
lib/segment/send.php ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * require client
5
+ */
6
+
7
+ require(__DIR__ . "/lib/Segment.php");
8
+
9
+ /**
10
+ * Args
11
+ */
12
+
13
+ $args = parse($argv);
14
+
15
+ /**
16
+ * Make sure both are set
17
+ */
18
+
19
+ if (!isset($args["secret"])) die("--secret must be given");
20
+ if (!isset($args["file"])) die("--file must be given");
21
+
22
+ $file = $args["file"];
23
+ if ($file[0] != '/') $file = __DIR__ . "/" . $file;
24
+
25
+ /**
26
+ * Rename the file so we don't write the same calls
27
+ * multiple times
28
+ */
29
+
30
+ $dir = dirname($file);
31
+ $old = $file;
32
+ $file = $dir . '/analytics-' . rand() . '.log';
33
+
34
+ if(!file_exists($old)) {
35
+ print("file: $old does not exist");
36
+ exit(0);
37
+ }
38
+
39
+ if (!rename($old, $file)) {
40
+ print("error renaming from $old to $new\n");
41
+ exit(1);
42
+ }
43
+
44
+ /**
45
+ * File contents.
46
+ */
47
+
48
+ $contents = file_get_contents($file);
49
+ $lines = explode("\n", $contents);
50
+
51
+ /**
52
+ * Initialize the client.
53
+ */
54
+
55
+ Segment::init($args["secret"], array(
56
+ "debug" => true,
57
+ "on_error" => function($code, $msg){
58
+ print("$code: $msg\n");
59
+ exit(1);
60
+ }
61
+ ));
62
+
63
+ /**
64
+ * Payloads
65
+ */
66
+
67
+ $total = 0;
68
+ $successful = 0;
69
+ foreach ($lines as $line) {
70
+ if (!trim($line)) continue;
71
+ $payload = json_decode($line, true);
72
+ $dt = new DateTime($payload["timestamp"]);
73
+ $ts = floatval($dt->getTimestamp() . "." . $dt->format("u"));
74
+ $payload["timestamp"] = $ts;
75
+ $type = $payload["type"];
76
+ $ret = call_user_func_array(array("Segment", $type), array($payload));
77
+ if ($ret) $successful++;
78
+ $total++;
79
+ if ($total % 100 === 0) Segment::flush();
80
+ }
81
+
82
+ Segment::flush();
83
+ unlink($file);
84
+
85
+ /**
86
+ * Sent
87
+ */
88
+
89
+ print("sent $successful from $total requests successfully");
90
+ exit(0);
91
+
92
+ /**
93
+ * Parse arguments
94
+ */
95
+
96
+ function parse($argv){
97
+ $ret = array();
98
+
99
+ for ($i = 0; $i < count($argv); ++$i) {
100
+ $arg = $argv[$i];
101
+ if ('--' != substr($arg, 0, 2)) continue;
102
+ $ret[substr($arg, 2, strlen($arg))] = trim($argv[++$i]);
103
+ }
104
+
105
+ return $ret;
106
+ }
power-ups/aweber-connect.php ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Power-up Name: AWeber
4
+ * Power-up Class: LIAWeberConnect
5
+ * Power-up Menu Text:
6
+ * Power-up Slug: aweber_connect
7
+ * Power-up Menu Link: settings
8
+ * Power-up URI: http://leadin.com/wordpress-mailchimp-sync-plugin/
9
+ * Power-up Description: Push your contacts to AWeber email lists.
10
+ * Power-up Icon: power-up-icon-aweber-connect
11
+ * Power-up Icon Small: power-up-icon-aweber-connect_small
12
+ * First Introduced: 2.3.0
13
+ * Power-up Tags: Newsletter, Email
14
+ * Auto Activate: No
15
+ * Permanently Enabled: No
16
+ * Hidden: No
17
+ * cURL Required: Yes
18
+ */
19
+
20
+ //=============================================
21
+ // Define Constants
22
+ //=============================================
23
+
24
+ if ( !defined('LEADIN_AWEBER_CONNECT_PATH') )
25
+ define('LEADIN_AWEBER_CONNECT_PATH', LEADIN_PATH . '/power-ups/aweber-connect');
26
+
27
+ if ( !defined('LEADIN_AWEBER_CONNECT_PLUGIN_DIR') )
28
+ define('LEADIN_AWEBER_CONNECT_PLUGIN_DIR', LEADIN_PLUGIN_DIR . '/power-ups/aweber-connect');
29
+
30
+ if ( !defined('LEADIN_AWEBER_CONNECT_PLUGIN_SLUG') )
31
+ define('LEADIN_AWEBER_CONNECT_PLUGIN_SLUG', basename(dirname(__FILE__)));
32
+
33
+ //=============================================
34
+ // Include Needed Files
35
+ //=============================================
36
+ require_once(LEADIN_AWEBER_CONNECT_PLUGIN_DIR . '/admin/aweber-connect-admin.php');
37
+ require_once(LEADIN_AWEBER_CONNECT_PLUGIN_DIR . '/inc/aweber_api/li_aweber_api.php');
38
+
39
+ //=============================================
40
+ // WPLeadIn Class
41
+ //=============================================
42
+ class LIAWeberConnect extends WPLeadIn {
43
+
44
+ var $admin;
45
+ var $options;
46
+ var $power_option_name = 'leadin_aweber_connect_options';
47
+
48
+ /**
49
+ * Class constructor
50
+ */
51
+ function __construct ( $activated )
52
+ {
53
+ //=============================================
54
+ // Hooks & Filters
55
+ //=============================================
56
+
57
+ if ( ! $activated )
58
+ return false;
59
+
60
+ global $leadin_aweber_connect_wp;
61
+ $leadin_aweber_connect_wp = $this;
62
+ $this->options = get_option($this->power_option_name);
63
+ }
64
+
65
+ public function admin_init ( )
66
+ {
67
+ $admin_class = get_class($this) . 'Admin';
68
+ $this->admin = new $admin_class($this->icon_small);
69
+ }
70
+
71
+ function power_up_setup_callback ( )
72
+ {
73
+ $this->admin->power_up_setup_callback();
74
+ }
75
+
76
+ /**
77
+ * Activate the power-up and add the defaults
78
+ */
79
+ function add_defaults ()
80
+ {
81
+
82
+ }
83
+
84
+ /**
85
+ * Adds a subcsriber to a specific list
86
+ *
87
+ * @param string
88
+ * @param string
89
+ * @param string
90
+ * @param string
91
+ * @param string
92
+ * @return int/bool
93
+ */
94
+ function push_contact_to_list ( $list_id = '', $email = '', $first_name = '', $last_name = '', $phone = '' )
95
+ {
96
+ if ( isset($this->options['li_ac_ck']) && $this->options['li_ac_ck'] && $list_id )
97
+ {
98
+ try
99
+ {
100
+ $aweber = new LI_AWeberAPI($this->options['li_ac_ck'], $this->options['li_ac_cs']);
101
+ $account = $aweber->getAccount($this->options['li_ac_ak'], $this->options['li_ac_as']);
102
+
103
+ $list_url = "/accounts/" . $account->id . "/lists/" . $list_id;
104
+
105
+ //Check if custom Field Exists
106
+ $list_custom_fields_url = "/accounts/" . $account->id . "/lists/" . $list_id . "/custom_fields";
107
+ $list_custom_fields = $account->loadFromUrl($list_custom_fields_url);
108
+
109
+ $params = array(
110
+ 'email' => $email,
111
+ 'name' => $first_name . $last_name
112
+ );
113
+
114
+ if ( count($list_custom_fields->data['entries']) )
115
+ {
116
+ foreach ( $list_custom_fields->data['entries'] as $entry )
117
+ {
118
+ if ( $entry['name'] == 'phone' )
119
+ {
120
+ $params['custom_fields'] = array('phone' => $phone);
121
+ break;
122
+ }
123
+ }
124
+ }
125
+
126
+ $list = $account->loadFromUrl($list_url);
127
+
128
+ $subscribers = $list->subscribers;
129
+ $subscribers->create($params);
130
+
131
+ leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'aweber'));
132
+
133
+ return TRUE;
134
+ }
135
+ catch ( AWeberAPIException $exc )
136
+ {
137
+
138
+ }
139
+ }
140
+
141
+ return FALSE;
142
+ }
143
+
144
+ /**
145
+ * Adds a subcsriber to a specific list
146
+ *
147
+ * @param string
148
+ * @param array
149
+ * @return int/bool API status code OR false if api key not set
150
+ */
151
+ function bulk_push_contact_to_list ( $list_id = '', $contacts = '' )
152
+ {
153
+ /*
154
+ The majority of our user base doesn't use AWeber, so we decided not to retroactively sync contacts to the list.
155
+ If people complain, we will respond with a support ticket and ask them to export/import manually.
156
+ */
157
+
158
+ return FALSE;
159
+ }
160
+ }
161
+
162
+ //=============================================
163
+ // ESP Connect Init
164
+ //=============================================
165
+
166
+ global $leadin_aweber_connect_wp;
167
+
168
+ ?>
power-ups/aweber-connect/admin/aweber-connect-admin.php ADDED
@@ -0,0 +1,323 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //=============================================
3
+ // LIAweberConnectAdmin Class
4
+ //=============================================
5
+ class LIAweberConnectAdmin extends WPLeadInAdmin {
6
+
7
+ var $power_up_settings_section = 'leadin_aweber_connect_options_section';
8
+ var $power_option_name = 'leadin_aweber_connect_options';
9
+ var $power_up_icon;
10
+ var $options;
11
+ var $authed = FALSE;
12
+ var $invalid_key = FALSE;
13
+
14
+ /**
15
+ * Class constructor
16
+ */
17
+ function __construct ( $power_up_icon_small )
18
+ {
19
+ //=============================================
20
+ // Hooks & Filters
21
+ //=============================================
22
+
23
+ if ( is_admin() )
24
+ {
25
+ $this->power_up_icon = $power_up_icon_small;
26
+ add_action('admin_init', array($this, 'leadin_build_esp_settings_page'));
27
+ $this->options = get_option($this->power_option_name);
28
+ $this->authed = ( isset($this->options['li_ac_auth_code']) && $this->options['li_ac_auth_code'] ? TRUE : FALSE );
29
+
30
+ if ( $this->authed )
31
+ {
32
+ if ( ! isset($this->options['li_ac_ck']) )
33
+ {
34
+ $this->li_ac_connect_to_api($this->options['li_ac_auth_code']);
35
+ }
36
+ else
37
+ {
38
+ $this->invalid_key = $this->li_ac_check_invalid_auth_code($this->options['li_ac_ck'], $this->options['li_ac_cs'], $this->options['li_ac_ak'], $this->options['li_ac_as']);
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ //=============================================
45
+ // Settings Page
46
+ //=============================================
47
+
48
+ /**
49
+ * Creates settings options
50
+ */
51
+ function leadin_build_esp_settings_page ()
52
+ {
53
+ register_setting('leadin_settings_options', $this->power_option_name, array($this, 'sanitize'));
54
+ add_settings_section($this->power_up_settings_section, $this->power_up_icon . "AWeber", array($this, 'aweber_connect_section_callback'), LEADIN_ADMIN_PATH);
55
+ add_settings_field('li_ac_auth_code', 'Authorization Code', array($this, 'li_ac_auth_code_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
56
+
57
+ if ( isset($this->options['li_ac_auth_code']) )
58
+ {
59
+ if ( $this->options['li_ac_auth_code'] )
60
+ add_settings_field('li_print_synced_lists', 'Synced tags', array($this, 'li_print_synced_lists'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
61
+ }
62
+ }
63
+
64
+ function aweber_connect_section_callback ( )
65
+ {
66
+ $this->print_hidden_settings_fields();
67
+ }
68
+
69
+ function print_hidden_settings_fields ()
70
+ {
71
+ // Hacky solution to solve the Settings API overwriting the default values
72
+ $li_ac_ck = ( $this->options['li_ac_ck'] ? $this->options['li_ac_ck'] : '' );
73
+ $li_ac_cs = ( $this->options['li_ac_cs'] ? $this->options['li_ac_cs'] : '' );
74
+ $li_ac_ak = ( $this->options['li_ac_ak'] ? $this->options['li_ac_ak'] : '' );
75
+ $li_ac_as = ( $this->options['li_ac_as'] ? $this->options['li_ac_as'] : '' );
76
+
77
+ if ( $li_ac_ck )
78
+ {
79
+ printf(
80
+ '<input id="li_ac_ck" type="hidden" name="' . $this->power_option_name . '[li_ac_ck]" value="%s"/>',
81
+ $li_ac_ck
82
+ );
83
+ }
84
+
85
+ if ( $li_ac_cs )
86
+ {
87
+ printf(
88
+ '<input id="li_ac_cs" type="hidden" name="' . $this->power_option_name . '[li_ac_cs]" value="%s"/>',
89
+ $li_ac_cs
90
+ );
91
+ }
92
+
93
+ if ( $li_ac_ak )
94
+ {
95
+ printf(
96
+ '<input id="li_ac_ak" type="hidden" name="' . $this->power_option_name . '[li_ac_ak]" value="%s"/>',
97
+ $li_ac_ak
98
+ );
99
+ }
100
+
101
+ if ( $li_ac_as )
102
+ {
103
+ printf(
104
+ '<input id="li_ac_as" type="hidden" name="' . $this->power_option_name . '[li_ac_as]" value="%s"/>',
105
+ $li_ac_as
106
+ );
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Sanitize each setting field as needed
112
+ *
113
+ * @param array $input Contains all settings fields as array keys
114
+ */
115
+ public function sanitize ( $input )
116
+ {
117
+ $new_input = array();
118
+
119
+ if ( isset( $input['li_ac_auth_code'] ) )
120
+ $new_input['li_ac_auth_code'] = sanitize_text_field( $input['li_ac_auth_code'] );
121
+
122
+ if ( isset( $input['li_ac_ck'] ) )
123
+ $new_input['li_ac_ck'] = sanitize_text_field( $input['li_ac_ck'] );
124
+
125
+ if ( isset( $input['li_ac_cs'] ) )
126
+ $new_input['li_ac_cs'] = sanitize_text_field( $input['li_ac_cs'] );
127
+
128
+ if ( isset( $input['li_ac_ak'] ) )
129
+ $new_input['li_ac_ak'] = sanitize_text_field( $input['li_ac_ak'] );
130
+
131
+ if ( isset( $input['li_ac_as'] ) )
132
+ $new_input['li_ac_as'] = sanitize_text_field( $input['li_ac_as'] );
133
+
134
+ return $new_input;
135
+ }
136
+
137
+ /**
138
+ * Prints API key input for settings page
139
+ */
140
+ function li_ac_auth_code_callback ()
141
+ {
142
+ $li_ac_auth_code = ( $this->options['li_ac_auth_code'] ? $this->options['li_ac_auth_code'] : '' ); // Get header from options, or show default
143
+
144
+ printf(
145
+ '<input id="li_ac_auth_code" type="text" id="title" name="' . $this->power_option_name . '[li_ac_auth_code]" value="%s" style="width: 430px;"/>',
146
+ $li_ac_auth_code
147
+ );
148
+
149
+ if ( ! isset($li_ac_auth_code) || ! $li_ac_auth_code )
150
+ echo '<p><a target="_blank" href="https://help.aweber.com/hc/en-us/articles/204031226-How-Do-I-Authorize-an-App-">Get your Authorization Code</a> from <a href="https://auth.aweber.com/1.0/oauth/authorize_app/156b03fb" target="_blank">AWeber.com</a></p>';
151
+ }
152
+
153
+ /**
154
+ * Prints synced lists out for settings page in format Tag Name → ESP list
155
+ */
156
+ function li_print_synced_lists ()
157
+ {
158
+ $li_ac_auth_code = ( $this->options['li_ac_auth_code'] ? $this->options['li_ac_auth_code'] : '' ); // Get header from options, or show default
159
+
160
+ if ( isset($li_ac_auth_code ) )
161
+ {
162
+ $synced_lists = $this->li_get_synced_list_for_esp('aweber');
163
+ $list_value_pairs = array();
164
+ $synced_list_count = 0;
165
+
166
+ echo '<table>';
167
+ foreach ( $synced_lists as $synced_list )
168
+ {
169
+ foreach ( stripslashes_deep(unserialize($synced_list->tag_synced_lists)) as $tag_synced_list )
170
+ {
171
+ if ( $tag_synced_list['esp'] == 'aweber' )
172
+ {
173
+ echo '<tr class="synced-list-row">';
174
+ echo '<td class="synced-list-cell"><span class="icon-tag"></span> ' . $synced_list->tag_text . '</td>';
175
+ echo '<td class="synced-list-cell"><span class="synced-list-arrow">&#8594;</span></td>';
176
+ echo '<td class="synced-list-cell"><span class="icon-envelope"></span> ' . $tag_synced_list['list_name'] . '</td>';
177
+ echo '<td class="synced-list-edit"><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags&action=edit_tag&tag=' . $synced_list->tag_id . '">edit tag</a></td>';
178
+ echo '</tr>';
179
+
180
+ $synced_list_count++;
181
+ }
182
+ }
183
+ }
184
+ echo '</table>';
185
+
186
+ if ( ! $synced_list_count ) {
187
+ echo '<p>AWeber connected succesfully! <a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">Select a tag to send contacts to AWeber</a>.</p>';
188
+ } else {
189
+ echo '<p><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">Edit your tags</a> or <a href="https://www.aweber.com/users/newlist#about" target="_blank">Create a new list on AWeber.com</a></p>';
190
+ }
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Get synced list for the ESP from the WordPress database
196
+ *
197
+ * @return array/object
198
+ */
199
+ function li_get_synced_list_for_esp ( $esp_name, $output_type = 'OBJECT' )
200
+ {
201
+ global $wpdb;
202
+
203
+ $q = $wpdb->prepare("SELECT * FROM $wpdb->li_tags WHERE tag_synced_lists LIKE '%%%s%%' AND tag_deleted = 0", $esp_name);
204
+ $synced_lists = $wpdb->get_results($q, $output_type);
205
+
206
+ return $synced_lists;
207
+ }
208
+
209
+ /**
210
+ * Format API-returned lists into parseable format on front end for Leadin to consume
211
+ *
212
+ * @return array
213
+ */
214
+ function li_get_lists ( )
215
+ {
216
+ $lists = $this->li_get_api_lists($this->options['li_ac_ck'], $this->options['li_ac_cs'], $this->options['li_ac_ak'], $this->options['li_ac_as']);
217
+
218
+ $sanitized_lists = array();
219
+ if ( count($lists) )
220
+ {
221
+ foreach ( $lists as $list )
222
+ {
223
+ $list_obj = (Object)NULL;
224
+ $list_obj->id = $list->id;
225
+ $list_obj->name = $list->name;
226
+
227
+ array_push($sanitized_lists, $list_obj);;
228
+ }
229
+ }
230
+
231
+ return $sanitized_lists;
232
+ }
233
+
234
+ /**
235
+ * Get lists from AWeber account
236
+ *
237
+ * @param string
238
+ * @return array
239
+ */
240
+ function li_get_api_lists ( $consumer_key, $consumer_secret, $access_key, $access_secret )
241
+ {
242
+ try
243
+ {
244
+ $aweber = new LI_AWeberAPI($consumer_key, $consumer_secret);
245
+ $account = $aweber->getAccount($access_key, $access_secret);
246
+ $lists = $account->lists;
247
+ return $lists;
248
+ }
249
+ catch ( LI_AWeberAPIException $exc )
250
+ {
251
+ /*print "<h3>AWeberAPIException:</h3>";
252
+ print " <li> Type: $exc->type <br>";
253
+ print " <li> Msg : $exc->message <br>";
254
+ print " <li> Docs: $exc->documentation_url <br>";
255
+ print "<hr>";*/
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Use MailChimp API key to try to grab corresponding user profile to check validity of key
261
+ *
262
+ * @param string
263
+ * @return bool
264
+ */
265
+ function li_ac_check_invalid_auth_code ( $consumer_key, $consumer_secret, $access_key, $access_secret )
266
+ {
267
+ try
268
+ {
269
+ $aweber = new LI_AWeberAPI($consumer_key, $consumer_secret);
270
+ $account = $aweber->getAccount($access_key, $access_secret);
271
+
272
+ return FALSE;
273
+ }
274
+ catch ( LI_AWeberAPIException $exc )
275
+ {
276
+ if ( $exc->type == 'UnauthorizedError' )
277
+ {
278
+ unset($this->options['li_ac_auth_code']);
279
+ unset($this->options['li_ac_ck']);
280
+ unset($this->options['li_ac_cs']);
281
+ unset($this->options['li_ac_ak']);
282
+ unset($this->options['li_ac_as']);
283
+
284
+ update_option($this->power_option_name, $this->options);
285
+ return TRUE;
286
+ }
287
+ else
288
+ return FALSE;
289
+
290
+ /*print "<h3>AWeberAPIException:</h3>";
291
+ print " <li> Type: $exc->type <br>";
292
+ print " <li> Msg : $exc->message <br>";
293
+ print " <li> Docs: $exc->documentation_url <br>";
294
+ print "<hr>";*/
295
+ }
296
+ }
297
+
298
+ function li_ac_connect_to_api ( $auth_code )
299
+ {
300
+ try
301
+ {
302
+ $auth = LI_AWeberAPI::getDataFromAweberID($auth_code);
303
+ list($consumerKey, $consumerSecret, $accessKey, $accessSecret) = $auth;
304
+
305
+ $this->options['li_ac_ck'] = $consumerKey;
306
+ $this->options['li_ac_cs'] = $consumerSecret;
307
+ $this->options['li_ac_ak'] = $accessKey;
308
+ $this->options['li_ac_as'] = $accessSecret;
309
+
310
+ update_option($this->power_option_name, $this->options);
311
+ }
312
+ catch ( LI_AWeberAPIException $exc )
313
+ {
314
+ /*print "<h3>AWeberAPIException:</h3>";
315
+ print " <li> Type: $exc->type <br>";
316
+ print " <li> Msg : $exc->message <br>";
317
+ print " <li> Docs: $exc->documentation_url <br>";
318
+ print "<hr>";*/
319
+ }
320
+ }
321
+ }
322
+
323
+ ?>
power-ups/aweber-connect/inc/aweber_api/li_aweber.php ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once('li_exceptions.php');
3
+ require_once('li_oauth_adapter.php');
4
+ require_once('li_oauth_application.php');
5
+ require_once('li_aweber_response.php');
6
+ require_once('li_aweber_collection.php');
7
+ require_once('li_aweber_entry_data_array.php');
8
+ require_once('li_aweber_entry.php');
9
+
10
+ /**
11
+ * AWeberServiceProvider
12
+ *
13
+ * Provides specific AWeber information or implementing OAuth.
14
+ * @uses OAuthServiceProvider
15
+ * @package
16
+ * @version $id$
17
+ */
18
+ class LI_AWeberServiceProvider implements LI_OAuthServiceProvider {
19
+
20
+ /**
21
+ * @var String Location for API calls
22
+ */
23
+ public $baseUri = 'https://api.aweber.com/1.0';
24
+
25
+ /**
26
+ * @var String Location to request an access token
27
+ */
28
+ public $accessTokenUrl = 'https://auth.aweber.com/1.0/oauth/access_token';
29
+
30
+ /**
31
+ * @var String Location to authorize an Application
32
+ */
33
+ public $authorizeUrl = 'https://auth.aweber.com/1.0/oauth/authorize';
34
+
35
+ /**
36
+ * @var String Location to request a request token
37
+ */
38
+ public $requestTokenUrl = 'https://auth.aweber.com/1.0/oauth/request_token';
39
+
40
+
41
+ public function getBaseUri() {
42
+ return $this->baseUri;
43
+ }
44
+
45
+ public function removeBaseUri($url) {
46
+ return str_replace($this->getBaseUri(), '', $url);
47
+ }
48
+
49
+ public function getAccessTokenUrl() {
50
+ return $this->accessTokenUrl;
51
+ }
52
+
53
+ public function getAuthorizeUrl() {
54
+ return $this->authorizeUrl;
55
+ }
56
+
57
+ public function getRequestTokenUrl() {
58
+ return $this->requestTokenUrl;
59
+ }
60
+
61
+ public function getAuthTokenFromUrl() { return ''; }
62
+ public function getUserData() { return ''; }
63
+
64
+ }
65
+
66
+ /**
67
+ * AWeberAPIBase
68
+ *
69
+ * Base object that all AWeberAPI objects inherit from. Allows specific pieces
70
+ * of functionality to be shared across any object in the API, such as the
71
+ * ability to introspect the collections map.
72
+ *
73
+ * @package
74
+ * @version $id$
75
+ */
76
+ class LI_AWeberAPIBase {
77
+
78
+ /**
79
+ * Maintains data about what children collections a given object type
80
+ * contains.
81
+ */
82
+ static protected $_collectionMap = array(
83
+ 'account' => array('lists', 'integrations'),
84
+ 'broadcast_campaign' => array('links', 'messages', 'stats'),
85
+ 'followup_campaign' => array('links', 'messages', 'stats'),
86
+ 'link' => array('clicks'),
87
+ 'list' => array('campaigns', 'custom_fields', 'subscribers',
88
+ 'web_forms', 'web_form_split_tests'),
89
+ 'web_form' => array(),
90
+ 'web_form_split_test' => array('components'),
91
+ );
92
+
93
+ /**
94
+ * loadFromUrl
95
+ *
96
+ * Creates an object, either collection or entry, based on the given
97
+ * URL.
98
+ *
99
+ * @param mixed $url URL for this request
100
+ * @access public
101
+ * @return AWeberEntry or AWeberCollection
102
+ */
103
+ public function loadFromUrl($url) {
104
+ $data = $this->adapter->request('GET', $url);
105
+ return $this->readResponse($data, $url);
106
+ }
107
+
108
+ protected function _cleanUrl($url) {
109
+ return str_replace($this->adapter->app->getBaseUri(), '', $url);
110
+ }
111
+
112
+ /**
113
+ * readResponse
114
+ *
115
+ * Interprets a response, and creates the appropriate object from it.
116
+ * @param mixed $response Data returned from a request to the AWeberAPI
117
+ * @param mixed $url URL that this data was requested from
118
+ * @access protected
119
+ * @return mixed
120
+ */
121
+ protected function readResponse($response, $url) {
122
+ $this->adapter->parseAsError($response);
123
+ if (!empty($response['id'])) {
124
+ return new LI_AWeberEntry($response, $url, $this->adapter);
125
+ } else if (array_key_exists('entries', $response)) {
126
+ return new LI_AWeberCollection($response, $url, $this->adapter);
127
+ }
128
+ return false;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * AWeberAPI
134
+ *
135
+ * Creates a connection to the AWeberAPI for a given consumer application.
136
+ * This is generally the starting point for this library. Instances can be
137
+ * created directly with consumerKey and consumerSecret.
138
+ * @uses AWeberAPIBase
139
+ * @package
140
+ * @version $id$
141
+ */
142
+ class LI_AWeberAPI extends LI_AWeberAPIBase {
143
+
144
+ /**
145
+ * @var String Consumer Key
146
+ */
147
+ public $consumerKey = false;
148
+
149
+ /**
150
+ * @var String Consumer Secret
151
+ */
152
+ public $consumerSecret = false;
153
+
154
+ /**
155
+ * @var Object - Populated in setAdapter()
156
+ */
157
+ public $adapter = false;
158
+
159
+ /**
160
+ * Uses the app's authorization code to fetch an access token
161
+ *
162
+ * @param String Authorization code from authorize app page
163
+ */
164
+ public static function getDataFromAweberID($string) {
165
+ list($consumerKey, $consumerSecret, $requestToken, $tokenSecret, $verifier) = LI_AWeberAPI::_parseAweberID($string);
166
+
167
+ if (!$verifier) {
168
+ return null;
169
+ }
170
+ $aweber = new LI_AWeberAPI($consumerKey, $consumerSecret);
171
+ $aweber->adapter->user->requestToken = $requestToken;
172
+ $aweber->adapter->user->tokenSecret = $tokenSecret;
173
+ $aweber->adapter->user->verifier = $verifier;
174
+ list($accessToken, $accessSecret) = $aweber->getAccessToken();
175
+ return array($consumerKey, $consumerSecret, $accessToken, $accessSecret);
176
+ }
177
+
178
+ protected static function _parseAWeberID($string) {
179
+ $values = explode('|', $string);
180
+ if (count($values) < 5) {
181
+ return null;
182
+ }
183
+ return array_slice($values, 0, 5);
184
+ }
185
+
186
+ /**
187
+ * Sets the consumer key and secret for the API object. The
188
+ * key and secret are listed in the My Apps page in the labs.aweber.com
189
+ * Control Panel OR, in the case of distributed apps, will be returned
190
+ * from the getDataFromAweberID() function
191
+ *
192
+ * @param String Consumer Key
193
+ * @param String Consumer Secret
194
+ * @return null
195
+ */
196
+ public function __construct($key, $secret) {
197
+ // Load key / secret
198
+ $this->consumerKey = $key;
199
+ $this->consumerSecret = $secret;
200
+
201
+ $this->setAdapter();
202
+ }
203
+
204
+ /**
205
+ * Returns the authorize URL by appending the request
206
+ * token to the end of the Authorize URI, if it exists
207
+ *
208
+ * @return string The Authorization URL
209
+ */
210
+ public function getAuthorizeUrl() {
211
+ $requestToken = $this->user->requestToken;
212
+ return (empty($requestToken)) ?
213
+ $this->adapter->app->getAuthorizeUrl()
214
+ :
215
+ $this->adapter->app->getAuthorizeUrl() . "?oauth_token={$this->user->requestToken}";
216
+ }
217
+
218
+ /**
219
+ * Sets the adapter for use with the API
220
+ */
221
+ public function setAdapter($adapter=null) {
222
+ if (empty($adapter)) {
223
+ $serviceProvider = new LI_AWeberServiceProvider();
224
+ $adapter = new LI_OAuthApplication($serviceProvider);
225
+ $adapter->consumerKey = $this->consumerKey;
226
+ $adapter->consumerSecret = $this->consumerSecret;
227
+ }
228
+ $this->adapter = $adapter;
229
+ }
230
+
231
+ /**
232
+ * Fetches account data for the associated account
233
+ *
234
+ * @param String Access Token (Only optional/cached if you called getAccessToken() earlier
235
+ * on the same page)
236
+ * @param String Access Token Secret (Only optional/cached if you called getAccessToken() earlier
237
+ * on the same page)
238
+ * @return Object AWeberCollection Object with the requested
239
+ * account data
240
+ */
241
+ public function getAccount($token=false, $secret=false) {
242
+ if ($token && $secret) {
243
+ $user = new LI_OAuthUser();
244
+ $user->accessToken = $token;
245
+ $user->tokenSecret = $secret;
246
+ $this->adapter->user = $user;
247
+ }
248
+
249
+ $body = $this->adapter->request('GET', '/accounts');
250
+ $accounts = $this->readResponse($body, '/accounts');
251
+ return $accounts[0];
252
+ }
253
+
254
+ /**
255
+ * PHP Automagic
256
+ */
257
+ public function __get($item) {
258
+ if ($item == 'user') return $this->adapter->user;
259
+ trigger_error("Could not find \"{$item}\"");
260
+ }
261
+
262
+ /**
263
+ * Request a request token from AWeber and associate the
264
+ * provided $callbackUrl with the new token
265
+ * @param String The URL where users should be redirected
266
+ * once they authorize your app
267
+ * @return Array Contains the request token as the first item
268
+ * and the request token secret as the second item of the array
269
+ */
270
+ public function getRequestToken($callbackUrl) {
271
+ $requestToken = $this->adapter->getRequestToken($callbackUrl);
272
+ return array($requestToken, $this->user->tokenSecret);
273
+ }
274
+
275
+ /**
276
+ * Request an access token using the request tokens stored in the
277
+ * current user object. You would want to first set the request tokens
278
+ * on the user before calling this function via:
279
+ *
280
+ * $aweber->user->tokenSecret = $_COOKIE['requestTokenSecret'];
281
+ * $aweber->user->requestToken = $_GET['oauth_token'];
282
+ * $aweber->user->verifier = $_GET['oauth_verifier'];
283
+ *
284
+ * @return Array Contains the access token as the first item
285
+ * and the access token secret as the second item of the array
286
+ */
287
+ public function getAccessToken() {
288
+ return $this->adapter->getAccessToken();
289
+ }
290
+ }
291
+
292
+ ?>
power-ups/aweber-connect/inc/aweber_api/li_aweber_api.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (class_exists('LI_AWeberAPI')) {
4
+ trigger_error("Duplicate: Another LI_AWeberAPI client library is already in scope.", E_USER_WARNING);
5
+ }
6
+ else {
7
+ require_once('li_aweber.php');
8
+ }
power-ups/aweber-connect/inc/aweber_api/li_aweber_collection.php ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class LI_AWeberCollection extends LI_AWeberResponse implements ArrayAccess, Iterator, Countable {
3
+
4
+ protected $pageSize = 100;
5
+ protected $pageStart = 0;
6
+
7
+ protected function _updatePageSize() {
8
+
9
+ # grab the url, or prev and next url and pull ws.size from it
10
+ $url = $this->url;
11
+ if (array_key_exists('next_collection_link', $this->data)) {
12
+ $url = $this->data['next_collection_link'];
13
+
14
+ } elseif (array_key_exists('prev_collection_link', $this->data)) {
15
+ $url = $this->data['prev_collection_link'];
16
+ }
17
+
18
+ # scan querystring for ws_size
19
+ $url_parts = parse_url($url);
20
+
21
+ # we have a query string
22
+ if (array_key_exists('query', $url_parts)) {
23
+ parse_str($url_parts['query'], $params);
24
+
25
+ # we have a ws_size
26
+ if (array_key_exists('ws_size', $params)) {
27
+
28
+ # set pageSize
29
+ $this->pageSize = $params['ws_size'];
30
+ return;
31
+ }
32
+ }
33
+
34
+ # we dont have one, just count the # of entries
35
+ $this->pageSize = count($this->data['entries']);
36
+ }
37
+
38
+ public function __construct($response, $url, $adapter) {
39
+ parent::__construct($response, $url, $adapter);
40
+ $this->_updatePageSize();
41
+ }
42
+
43
+ /**
44
+ * @var array Holds list of keys that are not publicly accessible
45
+ */
46
+ protected $_privateData = array(
47
+ 'entries',
48
+ 'start',
49
+ 'next_collection_link',
50
+ );
51
+
52
+ /**
53
+ * getById
54
+ *
55
+ * Gets an entry object of this collection type with the given id
56
+ * @param mixed $id ID of the entry you are requesting
57
+ * @access public
58
+ * @return AWeberEntry
59
+ */
60
+ public function getById($id) {
61
+ $data = $this->adapter->request('GET', "{$this->url}/{$id}");
62
+ $url = "{$this->url}/{$id}";
63
+ return new LI_AWeberEntry($data, $url, $this->adapter);
64
+ }
65
+
66
+ /** getParentEntry
67
+ *
68
+ * Gets an entry's parent entry
69
+ * Returns NULL if no parent entry
70
+ */
71
+ public function getParentEntry(){
72
+ $url_parts = explode('/', $this->url);
73
+ $size = count($url_parts);
74
+
75
+ # Remove collection id and slash from end of url
76
+ $url = substr($this->url, 0, -strlen($url_parts[$size-1])-1);
77
+
78
+ try {
79
+ $data = $this->adapter->request('GET', $url);
80
+ return new LI_AWeberEntry($data, $url, $this->adapter);
81
+ } catch (Exception $e) {
82
+ return NULL;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * _type
88
+ *
89
+ * Interpret what type of resources are held in this collection by
90
+ * analyzing the URL
91
+ *
92
+ * @access protected
93
+ * @return void
94
+ */
95
+ protected function _type() {
96
+ $urlParts = explode('/', $this->url);
97
+ $type = array_pop($urlParts);
98
+ return $type;
99
+ }
100
+
101
+ /**
102
+ * create
103
+ *
104
+ * Invoke the API method to CREATE a new entry resource.
105
+ *
106
+ * Note: Not all entry resources are eligible to be created, please
107
+ * refer to the AWeber API Reference Documentation at
108
+ * https://labs.aweber.com/docs/reference/1.0 for more
109
+ * details on which entry resources may be created and what
110
+ * attributes are required for creating resources.
111
+ *
112
+ * @access public
113
+ * @param params mixed associtative array of key/value pairs.
114
+ * @return AWeberEntry(Resource) The new resource created
115
+ */
116
+ public function create($kv_pairs) {
117
+ # Create Resource
118
+ $params = array_merge(array('ws.op' => 'create'), $kv_pairs);
119
+ $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'));
120
+
121
+ # Return new Resource
122
+ $url = $data['Location'];
123
+ $resource_data = $this->adapter->request('GET', $url);
124
+ return new LI_AWeberEntry($resource_data, $url, $this->adapter);
125
+ }
126
+
127
+ /**
128
+ * find
129
+ *
130
+ * Invoke the API 'find' operation on a collection to return a subset
131
+ * of that collection. Not all collections support the 'find' operation.
132
+ * refer to https://labs.aweber.com/docs/reference/1.0 for more information.
133
+ *
134
+ * @param mixed $search_data Associative array of key/value pairs used as search filters
135
+ * * refer to https://labs.aweber.com/docs/reference/1.0 for a
136
+ * complete list of valid search filters.
137
+ * * filtering on attributes that require additional permissions to
138
+ * display requires an app authorized with those additional permissions.
139
+ * @access public
140
+ * @return AWeberCollection
141
+ */
142
+ public function find($search_data) {
143
+ # invoke find operation
144
+ $params = array_merge($search_data, array('ws.op' => 'find'));
145
+ $data = $this->adapter->request('GET', $this->url, $params);
146
+
147
+ # get total size
148
+ $ts_params = array_merge($params, array('ws.show' => 'total_size'));
149
+ $total_size = $this->adapter->request('GET', $this->url, $ts_params, array('return' => 'integer'));
150
+ $data['total_size'] = $total_size;
151
+
152
+ # return collection
153
+ return $this->readResponse($data, $this->url);
154
+ }
155
+
156
+ /*
157
+ * ArrayAccess Functions
158
+ *
159
+ * Allows this object to be accessed via bracket notation (ie $obj[$x])
160
+ * http://php.net/manual/en/class.arrayaccess.php
161
+ */
162
+
163
+ public function offsetSet($offset, $value) {}
164
+ public function offsetUnset($offset) {}
165
+ public function offsetExists($offset) {
166
+
167
+ if ($offset >=0 && $offset < $this->total_size) {
168
+ return true;
169
+ }
170
+ return false;
171
+ }
172
+ protected function _fetchCollectionData($offset) {
173
+
174
+ # we dont have a next page, we're done
175
+ if (!array_key_exists('next_collection_link', $this->data)) {
176
+ return null;
177
+ }
178
+
179
+ # snag query string args from collection
180
+ $parsed = parse_url($this->data['next_collection_link']);
181
+
182
+ # parse the query string to get params
183
+ $pairs = explode('&', $parsed['query']);
184
+ foreach ($pairs as $pair) {
185
+ list($key, $val) = explode('=', $pair);
186
+ $params[$key] = $val;
187
+ }
188
+
189
+ # calculate new args
190
+ $limit = $params['ws.size'];
191
+ $pagination_offset = intval($offset / $limit) * $limit;
192
+ $params['ws.start'] = $pagination_offset;
193
+
194
+ # fetch data, exclude query string
195
+ $url_parts = explode('?', $this->url);
196
+ $data = $this->adapter->request('GET', $url_parts[0], $params);
197
+ $this->pageStart = $params['ws.start'];
198
+ $this->pageSize = $params['ws.size'];
199
+
200
+ $collection_data = array('entries', 'next_collection_link', 'prev_collection_link', 'ws.start');
201
+
202
+ foreach ($collection_data as $item) {
203
+ if (!array_key_exists($item, $this->data)) {
204
+ continue;
205
+ }
206
+ if (!array_key_exists($item, $data)) {
207
+ continue;
208
+ }
209
+ $this->data[$item] = $data[$item];
210
+ }
211
+ }
212
+
213
+ public function offsetGet($offset) {
214
+
215
+ if (!$this->offsetExists($offset)) {
216
+ return null;
217
+ }
218
+
219
+ $limit = $this->pageSize;
220
+ $pagination_offset = intval($offset / $limit) * $limit;
221
+
222
+ # load collection page if needed
223
+ if ($pagination_offset !== $this->pageStart) {
224
+ $this->_fetchCollectionData($offset);
225
+ }
226
+
227
+ $entry = $this->data['entries'][$offset - $pagination_offset];
228
+
229
+ # we have an entry, cast it to an AWeberEntry and return it
230
+ $entry_url = $this->adapter->app->removeBaseUri($entry['self_link']);
231
+ return new LI_AWeberEntry($entry, $entry_url, $this->adapter);
232
+ }
233
+
234
+ /*
235
+ * Iterator
236
+ */
237
+ protected $_iterationKey = 0;
238
+
239
+ public function current() {
240
+ return $this->offsetGet($this->_iterationKey);
241
+ }
242
+
243
+ public function key() {
244
+ return $this->_iterationKey;
245
+ }
246
+
247
+ public function next() {
248
+ $this->_iterationKey++;
249
+ }
250
+
251
+ public function rewind() {
252
+ $this->_iterationKey = 0;
253
+ }
254
+
255
+ public function valid() {
256
+ return $this->offsetExists($this->key());
257
+ }
258
+
259
+ /*
260
+ * Countable interface methods
261
+ * Allows PHP's count() and sizeOf() functions to act on this object
262
+ * http://www.php.net/manual/en/class.countable.php
263
+ */
264
+
265
+ public function count() {
266
+ return $this->total_size;
267
+ }
268
+ }
power-ups/aweber-connect/inc/aweber_api/li_aweber_entry.php ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class LI_AWeberEntry extends LI_AWeberResponse {
4
+
5
+ /**
6
+ * @var array Holds list of data keys that are not publicly accessible
7
+ */
8
+ protected $_privateData = array(
9
+ 'resource_type_link',
10
+ 'http_etag',
11
+ );
12
+
13
+ /**
14
+ * @var array Stores local modifications that have not been saved
15
+ */
16
+ protected $_localDiff = array();
17
+
18
+ /**
19
+ * @var array Holds AWeberCollection objects already instantiated, keyed by
20
+ * their resource name (plural)
21
+ */
22
+ protected $_collections = array();
23
+
24
+ /**
25
+ * attrs
26
+ *
27
+ * Provides a simple array of all the available data (and collections) available
28
+ * in this entry.
29
+ *
30
+ * @access public
31
+ * @return array
32
+ */
33
+ public function attrs() {
34
+ $attrs = array();
35
+ foreach ($this->data as $key => $value) {
36
+ if (!in_array($key, $this->_privateData) && !strpos($key, 'collection_link')) {
37
+ $attrs[$key] = $value;
38
+ }
39
+ }
40
+ if (!empty(LI_AWeberAPI::$_collectionMap[$this->type])) {
41
+ foreach (LI_AWeberAPI::$_collectionMap[$this->type] as $child) {
42
+ $attrs[$child] = 'collection';
43
+ }
44
+ }
45
+ return $attrs;
46
+ }
47
+
48
+ /**
49
+ * _type
50
+ *
51
+ * Used to pull the name of this resource from its resource_type_link
52
+ * @access protected
53
+ * @return String
54
+ */
55
+ protected function _type() {
56
+ if (empty($this->type)) {
57
+ $typeLink = $this->data['resource_type_link'];
58
+ if (empty($typeLink)) return null;
59
+ list($url, $type) = explode('#', $typeLink);
60
+ $this->type = $type;
61
+ }
62
+ return $this->type;
63
+ }
64
+
65
+ /**
66
+ * delete
67
+ *
68
+ * Delete this object from the AWeber system. May not be supported
69
+ * by all entry types.
70
+ * @access public
71
+ * @return boolean Returns true if it is successfully deleted, false
72
+ * if the delete request failed.
73
+ */
74
+ public function delete() {
75
+ $this->adapter->request('DELETE', $this->url, array(), array('return' => 'status'));
76
+ return true;
77
+ }
78
+
79
+ /**
80
+ * move
81
+ *
82
+ * Invoke the API method to MOVE an entry resource to a different List.
83
+ *
84
+ * Note: Not all entry resources are eligible to be moved, please
85
+ * refer to the AWeber API Reference Documentation at
86
+ * https://labs.aweber.com/docs/reference/1.0 for more
87
+ * details on which entry resources may be moved and if there
88
+ * are any requirements for moving that resource.
89
+ *
90
+ * @access public
91
+ * @param AWeberEntry(List) List to move Resource (this) too.
92
+ * @return mixed AWeberEntry(Resource) Resource created on List ($list)
93
+ * or False if resource was not created.
94
+ */
95
+ public function move($list, $last_followup_message_number_sent=NULL) {
96
+ # Move Resource
97
+ $params = array(
98
+ 'ws.op' => 'move',
99
+ 'list_link' => $list->self_link
100
+ );
101
+ if (isset($last_followup_message_number_sent)) {
102
+ $params['last_followup_message_number_sent'] = $last_followup_message_number_sent;
103
+ }
104
+
105
+ $data = $this->adapter->request('POST', $this->url, $params, array('return' => 'headers'));
106
+
107
+ # Return new Resource
108
+ $url = $data['Location'];
109
+ $resource_data = $this->adapter->request('GET', $url);
110
+ return new LI_AWeberEntry($resource_data, $url, $this->adapter);
111
+ }
112
+
113
+ /**
114
+ * save
115
+ *
116
+ * Saves the current state of this object if it has been changed.
117
+ * @access public
118
+ * @return void
119
+ */
120
+ public function save() {
121
+ if (!empty($this->_localDiff)) {
122
+ $data = $this->adapter->request('PATCH', $this->url, $this->_localDiff, array('return' => 'status'));
123
+ }
124
+ $this->_localDiff = array();
125
+ return true;
126
+
127
+ }
128
+
129
+ /**
130
+ * __get
131
+ *
132
+ * Used to look up items in data, and special properties like type and
133
+ * child collections dynamically.
134
+ *
135
+ * @param String $value Attribute being accessed
136
+ * @access public
137
+ * @throws AWeberResourceNotImplemented
138
+ * @return mixed
139
+ */
140
+ public function __get($value) {
141
+ if (in_array($value, $this->_privateData)) {
142
+ return null;
143
+ }
144
+ if (!empty($this->data) && array_key_exists($value, $this->data)) {
145
+ if (is_array($this->data[$value])) {
146
+ $array = new LI_AWeberEntryDataArray($this->data[$value], $value, $this);
147
+ $this->data[$value] = $array;
148
+ }
149
+ return $this->data[$value];
150
+ }
151
+ if ($value == 'type') return $this->_type();
152
+ if ($this->_isChildCollection($value)) {
153
+ return $this->_getCollection($value);
154
+ }
155
+ throw new LI_AWeberResourceNotImplemented($this, $value);
156
+ }
157
+
158
+ /**
159
+ * __set
160
+ *
161
+ * If the key provided is part of the data array, then update it in the
162
+ * data array. Otherwise, use the default __set() behavior.
163
+ *
164
+ * @param mixed $key Key of the attr being set
165
+ * @param mixed $value Value being set to the $key attr
166
+ * @access public
167
+ */
168
+ public function __set($key, $value) {
169
+ if (array_key_exists($key, $this->data)) {
170
+ $this->_localDiff[$key] = $value;
171
+ return $this->data[$key] = $value;
172
+ } else {
173
+ return parent::__set($key, $value);
174
+ }
175
+ }
176
+
177
+ /**
178
+ * findSubscribers
179
+ *
180
+ * Looks through all lists for subscribers
181
+ * that match the given filter
182
+ * @access public
183
+ * @return AWeberCollection
184
+ */
185
+ public function findSubscribers($search_data) {
186
+ $this->_methodFor(array('account'));
187
+ $params = array_merge($search_data, array('ws.op' => 'findSubscribers'));
188
+ $data = $this->adapter->request('GET', $this->url, $params);
189
+
190
+ $ts_params = array_merge($params, array('ws.show' => 'total_size'));
191
+ $total_size = $this->adapter->request('GET', $this->url, $ts_params, array('return' => 'integer'));
192
+
193
+ # return collection
194
+ $data['total_size'] = $total_size;
195
+ $url = $this->url . '?'. http_build_query($params);
196
+ return new LI_AWeberCollection($data, $url, $this->adapter);
197
+ }
198
+
199
+ /**
200
+ * getActivity
201
+ *
202
+ * Returns analytics activity for a given subscriber
203
+ * @access public
204
+ * @return AWeberCollection
205
+ */
206
+ public function getActivity() {
207
+ $this->_methodFor(array('subscriber'));
208
+ $params = array('ws.op' => 'getActivity');
209
+ $data = $this->adapter->request('GET', $this->url, $params);
210
+
211
+ $ts_params = array_merge($params, array('ws.show' => 'total_size'));
212
+ $total_size = $this->adapter->request('GET', $this->url, $ts_params, array('return' => 'integer'));
213
+
214
+ # return collection
215
+ $data['total_size'] = $total_size;
216
+ $url = $this->url . '?'. http_build_query($params);
217
+ return new LI_AWeberCollection($data, $url, $this->adapter);
218
+ }
219
+
220
+ /** getParentEntry
221
+ *
222
+ * Gets an entry's parent entry
223
+ * Returns NULL if no parent entry
224
+ */
225
+ public function getParentEntry(){
226
+ $url_parts = explode('/', $this->url);
227
+ $size = count($url_parts);
228
+
229
+ #Remove entry id and slash from end of url
230
+ $url = substr($this->url, 0, -strlen($url_parts[$size-1])-1);
231
+
232
+ #Remove collection name and slash from end of url
233
+ $url = substr($url, 0, -strlen($url_parts[$size-2])-1);
234
+
235
+ try {
236
+ $data = $this->adapter->request('GET', $url);
237
+ return new LI_AWeberEntry($data, $url, $this->adapter);
238
+ } catch (Exception $e) {
239
+ return NULL;
240
+ }
241
+ }
242
+
243
+ /**
244
+ * getWebForms
245
+ *
246
+ * Gets all web_forms for this account
247
+ * @access public
248
+ * @return array
249
+ */
250
+ public function getWebForms() {
251
+ $this->_methodFor(array('account'));
252
+ $data = $this->adapter->request('GET', $this->url.'?ws.op=getWebForms', array(),
253
+ array('allow_empty' => true));
254
+ return $this->_parseNamedOperation($data);
255
+ }
256
+
257
+
258
+ /**
259
+ * getWebFormSplitTests
260
+ *
261
+ * Gets all web_form split tests for this account
262
+ * @access public
263
+ * @return array
264
+ */
265
+ public function getWebFormSplitTests() {
266
+ $this->_methodFor(array('account'));
267
+ $data = $this->adapter->request('GET', $this->url.'?ws.op=getWebFormSplitTests', array(),
268
+ array('allow_empty' => true));
269
+ return $this->_parseNamedOperation($data);
270
+ }
271
+
272
+ /**
273
+ * _parseNamedOperation
274
+ *
275
+ * Turns a dumb array of json into an array of Entries. This is NOT
276
+ * a collection, but simply an array of entries, as returned from a
277
+ * named operation.
278
+ *
279
+ * @param array $data
280
+ * @access protected
281
+ * @return array
282
+ */
283
+ protected function _parseNamedOperation($data) {
284
+ $results = array();
285
+ foreach($data as $entryData) {
286
+ $results[] = new LI_AWeberEntry($entryData, str_replace($this->adapter->app->getBaseUri(), '',
287
+ $entryData['self_link']), $this->adapter);
288
+ }
289
+ return $results;
290
+ }
291
+
292
+ /**
293
+ * _methodFor
294
+ *
295
+ * Raises exception if $this->type is not in array entryTypes.
296
+ * Used to restrict methods to specific entry type(s).
297
+ * @param mixed $entryTypes Array of entry types as strings, ie array('account')
298
+ * @access protected
299
+ * @return void
300
+ */
301
+ protected function _methodFor($entryTypes) {
302
+ if (in_array($this->type, $entryTypes)) return true;
303
+ throw new LI_AWeberMethodNotImplemented($this);
304
+ }
305
+
306
+ /**
307
+ * _getCollection
308
+ *
309
+ * Returns the AWeberCollection object representing the given
310
+ * collection name, relative to this entry.
311
+ *
312
+ * @param String $value The name of the sub-collection
313
+ * @access protected
314
+ * @return AWeberCollection
315
+ */
316
+ protected function _getCollection($value) {
317
+ if (empty($this->_collections[$value])) {
318
+ $url = "{$this->url}/{$value}";
319
+ $data = $this->adapter->request('GET', $url);
320
+ $this->_collections[$value] = new LI_AWeberCollection($data, $url, $this->adapter);
321
+ }
322
+ return $this->_collections[$value];
323
+ }
324
+
325
+
326
+ /**
327
+ * _isChildCollection
328
+ *
329
+ * Is the given name of a collection a child collection of this entry?
330
+ *
331
+ * @param String $value The name of the collection we are looking for
332
+ * @access protected
333
+ * @return boolean
334
+ * @throws AWeberResourceNotImplemented
335
+ */
336
+ protected function _isChildCollection($value) {
337
+ $this->_type();
338
+ if (!empty(LI_AWeberAPI::$_collectionMap[$this->type]) &&
339
+ in_array($value, LI_AWeberAPI::$_collectionMap[$this->type])) return true;
340
+ return false;
341
+ }
342
+
343
+ }
power-ups/aweber-connect/inc/aweber_api/li_aweber_entry_data_array.php ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class LI_AWeberEntryDataArray implements ArrayAccess, Countable, Iterator {
4
+ private $counter = 0;
5
+
6
+ protected $data;
7
+ protected $keys;
8
+ protected $name;
9
+ protected $parent;
10
+
11
+ public function __construct($data, $name, $parent) {
12
+ $this->data = $data;
13
+ $this->keys = array_keys($data);
14
+ $this->name = $name;
15
+ $this->parent = $parent;
16
+ }
17
+
18
+ public function count() {
19
+ return sizeOf($this->data);
20
+ }
21
+
22
+ public function offsetExists($offset) {
23
+ return (isset($this->data[$offset]));
24
+ }
25
+
26
+ public function offsetGet($offset) {
27
+ return $this->data[$offset];
28
+ }
29
+
30
+ public function offsetSet($offset, $value) {
31
+ $this->data[$offset] = $value;
32
+ $this->parent->{$this->name} = $this->data;
33
+ return $value;
34
+ }
35
+
36
+ public function offsetUnset($offset) {
37
+ unset($this->data[$offset]);
38
+ }
39
+
40
+ public function rewind() {
41
+ $this->counter = 0;
42
+ }
43
+
44
+ public function current() {
45
+ return $this->data[$this->key()];
46
+ }
47
+
48
+ public function key() {
49
+ return $this->keys[$this->counter];
50
+ }
51
+
52
+ public function next() {
53
+ $this->counter++;
54
+ }
55
+
56
+ public function valid() {
57
+ if ($this->counter >= sizeOf($this->data)) {
58
+ return false;
59
+ }
60
+ return true;
61
+ }
62
+
63
+
64
+ }
65
+
66
+
67
+
68
+ ?>
power-ups/aweber-connect/inc/aweber_api/li_aweber_response.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * AWeberResponse
5
+ *
6
+ * Base class for objects that represent a response from the AWeberAPI.
7
+ * Responses will exist as one of the two AWeberResponse subclasses:
8
+ * - AWeberEntry - a single instance of an AWeber resource
9
+ * - AWeberCollection - a collection of AWeber resources
10
+ * @uses AWeberAPIBase
11
+ * @package
12
+ * @version $id$
13
+ */
14
+ class LI_AWeberResponse extends LI_AWeberAPIBase {
15
+
16
+ public $adapter = false;
17
+ public $data = array();
18
+ public $_dynamicData = array();
19
+
20
+ /**
21
+ * __construct
22
+ *
23
+ * Creates a new AWeberRespones
24
+ *
25
+ * @param mixed $response Data returned by the API servers
26
+ * @param mixed $url URL we hit to get the data
27
+ * @param mixed $adapter OAuth adapter used for future interactions
28
+ * @access public
29
+ * @return void
30
+ */
31
+ public function __construct($response, $url, $adapter) {
32
+ $this->adapter = $adapter;
33
+ $this->url = $url;
34
+ $this->data = $response;
35
+ }
36
+
37
+ /**
38
+ * __set
39
+ *
40
+ * Manual re-implementation of __set, allows sub classes to access
41
+ * the default behavior by using the parent:: format.
42
+ *
43
+ * @param mixed $key Key of the attr being set
44
+ * @param mixed $value Value being set to the attr
45
+ * @access public
46
+ */
47
+ public function __set($key, $value) {
48
+ $this->{$key} = $value;
49
+ }
50
+
51
+ /**
52
+ * __get
53
+ *
54
+ * PHP "MagicMethod" to allow for dynamic objects. Defers first to the
55
+ * data in $this->data.
56
+ *
57
+ * @param String $value Name of the attribute requested
58
+ * @access public
59
+ * @return mixed
60
+ */
61
+ public function __get($value) {
62
+ if (in_array($value, $this->_privateData)) {
63
+ return null;
64
+ }
65
+ if (array_key_exists($value, $this->data)) {
66
+ return $this->data[$value];
67
+ }
68
+ if ($value == 'type') return $this->_type();
69
+ }
70
+
71
+ }
72
+
73
+
power-ups/aweber-connect/inc/aweber_api/li_curl_object.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * CurlInterface
5
+ *
6
+ * An object-oriented shim that wraps the standard PHP cURL library.
7
+ *
8
+ * This interface has been created so that cURL functionality can be stubbed
9
+ * out for unit testing, or swapped for an alternative library.
10
+ *
11
+ * @see curl
12
+ * @package
13
+ * @version $id$
14
+ */
15
+ interface LI_CurlInterface {
16
+
17
+ /**
18
+ * errNo
19
+ *
20
+ * Encapsulates curl_errno - Returns the last error number
21
+ * @param resource $ch - A cURL handle returned by init.
22
+ * @access public
23
+ * @return the error number or 0 if no error occured.
24
+ */
25
+ public function errno($ch);
26
+
27
+ /**
28
+ * error
29
+ *
30
+ * Encapsulates curl_error - Return last error string
31
+ * @param resource $ch - A cURL handle returned by init.
32
+ * @access public
33
+ * @return the error messge or '' if no error occured.
34
+ */
35
+ public function error($ch);
36
+
37
+ /**
38
+ * execute
39
+ *
40
+ * Encapsulates curl_exec - Perform a cURL session.
41
+ * @param resource $ch - A cURL handle returned by init.
42
+ * @access public
43
+ * @return TRUE on success, FALSE on failure.
44
+ */
45
+ public function execute($ch);
46
+
47
+ /**
48
+ * init
49
+ *
50
+ * Encapsulates curl_init - Initialize a cURL session.
51
+ * @param string $url - url to use.
52
+ * @access public
53
+ * @return cURL handle on success, FALSE on failure.
54
+ */
55
+ public function init($url);
56
+
57
+ /**
58
+ * setopt
59
+ *
60
+ * Encapsulates curl_setopt - Set an option for cURL transfer.
61
+ * @param resource $ch - A cURL handle returned by init.
62
+ * @param int $opt - The CURLOPT to set.
63
+ * @param mixed $value - The value to set.
64
+ * @access public
65
+ * @return True on success, FALSE on failure.
66
+ */
67
+ public function setopt ($ch , $option , $value);
68
+ }
69
+
70
+
71
+ /**
72
+ * CurlObject
73
+ *
74
+ * A concrete implementation of CurlInterface using the PHP cURL library.
75
+ *
76
+ * @package
77
+ * @version $id$
78
+ */
79
+ class LI_CurlObject implements LI_CurlInterface {
80
+
81
+ public function errno($ch) {
82
+ return curl_errno($ch);
83
+ }
84
+
85
+ public function error($ch) {
86
+ return curl_error($ch);
87
+ }
88
+
89
+ public function execute($ch) {
90
+ return curl_exec($ch);
91
+ }
92
+
93
+ public function init($url) {
94
+ return curl_init($url);
95
+ }
96
+
97
+ public function setopt ($ch , $option , $value) {
98
+ return curl_setopt($ch, $option, $value);
99
+ }
100
+
101
+ }
102
+
103
+ ?>
power-ups/aweber-connect/inc/aweber_api/li_curl_response.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ # CurlResponse
4
+ #
5
+ # Author Sean Huber - shuber@huberry.com
6
+ # Date May 2008
7
+ #
8
+ # A basic CURL wrapper for PHP
9
+ #
10
+ # See the README for documentation/examples or http://php.net/curl for more information
11
+ # about the libcurl extension for PHP -- http://github.com/shuber/curl/tree/master
12
+ #
13
+
14
+ class LI_CurlResponse
15
+ {
16
+ public $body = '';
17
+ public $headers = array();
18
+
19
+ public function __construct($response)
20
+ {
21
+ # Extract headers from response
22
+ $pattern = '#HTTP/\d\.\d.*?$.*?\r\n\r\n#ims';
23
+ preg_match_all($pattern, $response, $matches);
24
+ $headers = explode("\r\n", str_replace("\r\n\r\n", '', array_pop($matches[0])));
25
+
26
+ # Extract the version and status from the first header
27
+ $version_and_status = array_shift($headers);
28
+ preg_match('#HTTP/(\d\.\d)\s(\d\d\d)\s(.*)#', $version_and_status, $matches);
29
+ $this->headers['Http-Version'] = $matches[1];
30
+ $this->headers['Status-Code'] = $matches[2];
31
+ $this->headers['Status'] = $matches[2].' '.$matches[3];
32
+
33
+ # Convert headers into an associative array
34
+ foreach ($headers as $header) {
35
+ preg_match('#(.*?)\:\s(.*)#', $header, $matches);
36
+ $this->headers[$matches[1]] = $matches[2];
37
+ }
38
+
39
+ # Remove the headers from the response body
40
+ $this->body = preg_replace($pattern, '', $response);
41
+ }
42
+
43
+ public function __toString()
44
+ {
45
+ return $this->body;
46
+ }
47
+
48
+ public function headers(){
49
+ return $this->headers;
50
+ }
51
+ }
power-ups/aweber-connect/inc/aweber_api/li_exceptions.php ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class LI_AWeberException extends Exception { }
4
+
5
+ /**
6
+ * Thrown when the API returns an error. (HTTP status >= 400)
7
+ *
8
+ *
9
+ * @uses AWeberException
10
+ * @package
11
+ * @version $id$
12
+ */
13
+ class LI_AWeberAPIException extends LI_AWeberException {
14
+
15
+ public $type;
16
+ public $status;
17
+ public $message;
18
+ public $documentation_url;
19
+ public $url;
20
+
21
+ public function __construct($error, $url) {
22
+ // record specific details of the API exception for processing
23
+ $this->url = $url;
24
+ $this->type = $error['type'];
25
+ $this->status = array_key_exists('status', $error) ? $error['status'] : '';
26
+ $this->message = $error['message'];
27
+ $this->documentation_url = $error['documentation_url'];
28
+
29
+ parent::__construct($this->message);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Thrown when attempting to use a resource that is not implemented.
35
+ *
36
+ * @uses AWeberException
37
+ * @package
38
+ * @version $id$
39
+ */
40
+ class LI_AWeberResourceNotImplemented extends LI_AWeberException {
41
+
42
+ public function __construct($object, $value) {
43
+ $this->object = $object;
44
+ $this->value = $value;
45
+ parent::__construct("Resource \"{$value}\" is not implemented on this resource.");
46
+ }
47
+ }
48
+
49
+ /**
50
+ * AWeberMethodNotImplemented
51
+ *
52
+ * Thrown when attempting to call a method that is not implemented for a resource
53
+ * / collection. Differs from standard method not defined errors, as this will
54
+ * be thrown when the method is infact implemented on the base class, but the
55
+ * current resource type does not provide access to that method (ie calling
56
+ * getByMessageNumber on a web_forms collection).
57
+ *
58
+ * @uses AWeberException
59
+ * @package
60
+ * @version $id$
61
+ */
62
+ class LI_AWeberMethodNotImplemented extends LI_AWeberException {
63
+
64
+ public function __construct($object) {
65
+ $this->object = $object;
66
+ parent::__construct("This method is not implemented by the current resource.");
67
+
68
+ }
69
+ }
70
+
71
+ /**
72
+ * AWeberOAuthException
73
+ *
74
+ * OAuth exception, as generated by an API JSON error response
75
+ * @uses AWeberException
76
+ * @package
77
+ * @version $id$
78
+ */
79
+ class LI_AWeberOAuthException extends LI_AWeberException {
80
+
81
+ public function __construct($type, $message) {
82
+ $this->type = $type;
83
+ $this->message = $message;
84
+ parent::__construct("{$type}: {$message}");
85
+ }
86
+ }
87
+
88
+ /**
89
+ * AWeberOAuthDataMissing
90
+ *
91
+ * Used when a specific piece or pieces of data was not found in the
92
+ * response. This differs from the exception that might be thrown as
93
+ * an AWeberOAuthException when parameters are not provided because
94
+ * it is not the servers' expectations that were not met, but rather
95
+ * the expecations of the client were not met by the server.
96
+ *
97
+ * @uses AWeberException
98
+ * @package
99
+ * @version $id$
100
+ */
101
+ class LI_AWeberOAuthDataMissing extends LI_AWeberException {
102
+
103
+ public function __construct($missing) {
104
+ if (!is_array($missing)) $missing = array($missing);
105
+ $this->missing = $missing;
106
+ $required = join(', ', $this->missing);
107
+ parent::__construct("OAuthDataMissing: Response was expected to contain: {$required}");
108
+
109
+ }
110
+ }
111
+
112
+ /**
113
+ * AWeberResponseError
114
+ *
115
+ * This is raised when the server returns a non-JSON response. This
116
+ * should only occur when there is a server or some type of connectivity
117
+ * issue.
118
+ *
119
+ * @uses AWeberException
120
+ * @package
121
+ * @version $id$
122
+ */
123
+ class LI_AWeberResponseError extends LI_AWeberException {
124
+
125
+ public function __construct($uri) {
126
+ $this->uri = $uri;
127
+ parent::__construct("Request for {$uri} did not respond properly.");
128
+ }
129
+
130
+ }
power-ups/aweber-connect/inc/aweber_api/li_oauth_adapter.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ interface LI_AWeberOAuthAdapter {
4
+
5
+ public function request($method, $uri, $data = array());
6
+ public function getRequestToken($callbackUrl=false);
7
+
8
+ }
9
+
10
+
11
+ ?>
power-ups/aweber-connect/inc/aweber_api/li_oauth_application.php ADDED
@@ -0,0 +1,681 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if (!class_exists('LI_CurlObject')) require_once('li_curl_object.php');
3
+ if (!class_exists('LI_CurlResponse')) require_once('li_curl_response.php');
4
+
5
+ /**
6
+ * OAuthServiceProvider
7
+ *
8
+ * Represents the service provider in the OAuth authentication model.
9
+ * The class that implements the service provider will contain the
10
+ * specific knowledge about the API we are interfacing with, and
11
+ * provide useful methods for interfacing with its API.
12
+ *
13
+ * For example, an OAuthServiceProvider would know the URLs necessary
14
+ * to perform specific actions, the type of data that the API calls
15
+ * would return, and would be responsible for manipulating the results
16
+ * into a useful manner.
17
+ *
18
+ * It should be noted that the methods enforced by the OAuthServiceProvider
19
+ * interface are made so that it can interact with our OAuthApplication
20
+ * cleanly, rather than from a general use perspective, though some
21
+ * methods for those purposes do exists (such as getUserData).
22
+ *
23
+ * @package
24
+ * @version $id$
25
+ */
26
+ interface LI_OAuthServiceProvider {
27
+
28
+ public function getAccessTokenUrl();
29
+ public function getAuthorizeUrl();
30
+ public function getRequestTokenUrl();
31
+ public function getAuthTokenFromUrl();
32
+ public function getBaseUri();
33
+ public function getUserData();
34
+
35
+ }
36
+
37
+ /**
38
+ * OAuthApplication
39
+ *
40
+ * Base class to represent an OAuthConsumer application. This class is
41
+ * intended to be extended and modified for each ServiceProvider. Each
42
+ * OAuthServiceProvider should have a complementary OAuthApplication
43
+ *
44
+ * The OAuthApplication class should contain any details on preparing
45
+ * requires that is unique or specific to that specific service provider's
46
+ * implementation of the OAuth model.
47
+ *
48
+ * This base class is based on OAuth 1.0, designed with AWeber's implementation
49
+ * as a model. An OAuthApplication built to work with a different service
50
+ * provider (especially an OAuth2.0 Application) may alter or bypass portions
51
+ * of the logic in this class to meet the needs of the service provider it
52
+ * is designed to interface with.
53
+ *
54
+ * @package
55
+ * @version $id$
56
+ */
57
+ class LI_OAuthApplication implements LI_AWeberOAuthAdapter {
58
+ public $debug = false;
59
+
60
+ public $userAgent = 'AWeber OAuth Consumer Application 1.0 - https://labs.aweber.com/';
61
+
62
+ public $format = false;
63
+
64
+ public $requiresTokenSecret = true;
65
+
66
+ public $signatureMethod = 'HMAC-SHA1';
67
+ public $version = '1.0';
68
+
69
+ public $curl = false;
70
+
71
+ /**
72
+ * @var OAuthUser User currently interacting with the service provider
73
+ */
74
+ public $user = false;
75
+
76
+ // Data binding this OAuthApplication to the consumer application it is acting
77
+ // as a proxy for
78
+ public $consumerKey = false;
79
+ public $consumerSecret = false;
80
+
81
+ /**
82
+ * __construct
83
+ *
84
+ * Create a new OAuthApplication, based on an OAuthServiceProvider
85
+ * @access public
86
+ * @return void
87
+ */
88
+ public function __construct($parentApp = false) {
89
+ if ($parentApp) {
90
+ if (!is_a($parentApp, 'LI_OAuthServiceProvider')) {
91
+ throw new Exception('Parent App must be a valid LI_OAuthServiceProvider!');
92
+ }
93
+ $this->app = $parentApp;
94
+ }
95
+ $this->user = new LI_OAuthUser();
96
+ $this->curl = new LI_CurlObject();
97
+ }
98
+
99
+ /**
100
+ * request
101
+ *
102
+ * Implemented for a standard OAuth adapter interface
103
+ * @param mixed $method
104
+ * @param mixed $uri
105
+ * @param array $data
106
+ * @param array $options
107
+ * @access public
108
+ * @return void
109
+ */
110
+ public function request($method, $uri, $data = array(), $options = array()) {
111
+ $uri = $this->app->removeBaseUri($uri);
112
+ $url = $this->app->getBaseUri() . $uri;
113
+
114
+ # WARNING: non-primative items in data must be json serialized in GET and POST.
115
+ if ($method == 'POST' or $method == 'GET') {
116
+ foreach ($data as $key => $value) {
117
+ if (is_array($value)) {
118
+ $data[$key] = json_encode($value);
119
+ }
120
+ }
121
+ }
122
+
123
+ $response = $this->makeRequest($method, $url, $data);
124
+ if (!empty($options['return'])) {
125
+ if ($options['return'] == 'status') {
126
+ return $response->headers['Status-Code'];
127
+ }
128
+ if ($options['return'] == 'headers') {
129
+ return $response->headers;
130
+ }
131
+ if ($options['return'] == 'integer') {
132
+ return intval($response->body);
133
+ }
134
+ }
135
+
136
+ $data = json_decode($response->body, true);
137
+
138
+ if (empty($options['allow_empty']) && !isset($data)) {
139
+ throw new LI_AWeberResponseError($uri);
140
+ }
141
+ return $data;
142
+ }
143
+
144
+ /**
145
+ * getRequestToken
146
+ *
147
+ * Gets a new request token / secret for this user.
148
+ * @access public
149
+ * @return void
150
+ */
151
+ public function getRequestToken($callbackUrl=false) {
152
+ $data = ($callbackUrl)? array('oauth_callback' => $callbackUrl) : array();
153
+ $resp = $this->makeRequest('POST', $this->app->getRequestTokenUrl(), $data);
154
+ $data = $this->parseResponse($resp);
155
+ $this->requiredFromResponse($data, array('oauth_token', 'oauth_token_secret'));
156
+ $this->user->requestToken = $data['oauth_token'];
157
+ $this->user->tokenSecret = $data['oauth_token_secret'];
158
+ return $data['oauth_token'];
159
+ }
160
+
161
+ /**
162
+ * getAccessToken
163
+ *
164
+ * Makes a request for access tokens. Requires that the current user has an authorized
165
+ * token and token secret.
166
+ *
167
+ * @access public
168
+ * @return void
169
+ */
170
+ public function getAccessToken() {
171
+ $resp = $this->makeRequest('POST', $this->app->getAccessTokenUrl(),
172
+ array('oauth_verifier' => $this->user->verifier)
173
+ );
174
+ $data = $this->parseResponse($resp);
175
+ $this->requiredFromResponse($data, array('oauth_token', 'oauth_token_secret'));
176
+
177
+ if (empty($data['oauth_token'])) {
178
+ throw new LI_AWeberOAuthDataMissing('oauth_token');
179
+ }
180
+
181
+ $this->user->accessToken = $data['oauth_token'];
182
+ $this->user->tokenSecret = $data['oauth_token_secret'];
183
+ return array($data['oauth_token'], $data['oauth_token_secret']);
184
+ }
185
+
186
+ /**
187
+ * parseAsError
188
+ *
189
+ * Checks if response is an error. If it is, raise an appropriately
190
+ * configured exception.
191
+ *
192
+ * @param mixed $response Data returned from the server, in array form
193
+ * @access public
194
+ * @throws AWeberOAuthException
195
+ * @return void
196
+ */
197
+ public function parseAsError($response) {
198
+ if (!empty($response['error'])) {
199
+ throw new LI_AWeberOAuthException($response['error']['type'],
200
+ $response['error']['message']);
201
+ }
202
+ }
203
+
204
+ /**
205
+ * requiredFromResponse
206
+ *
207
+ * Enforce that all the fields in requiredFields are present and not
208
+ * empty in data. If a required field is empty, throw an exception.
209
+ *
210
+ * @param mixed $data Array of data
211
+ * @param mixed $requiredFields Array of required field names.
212
+ * @access protected
213
+ * @return void
214
+ */
215
+ protected function requiredFromResponse($data, $requiredFields) {
216
+ foreach ($requiredFields as $field) {
217
+ if (empty($data[$field])) {
218
+ throw new LI_AWeberOAuthDataMissing($field);
219
+ }
220
+ }
221
+ }
222
+
223
+ /**
224
+ * get
225
+ *
226
+ * Make a get request. Used to exchange user tokens with serice provider.
227
+ * @param mixed $url URL to make a get request from.
228
+ * @param array $data Data for the request.
229
+ * @access protected
230
+ * @return void
231
+ */
232
+ protected function get($url, $data) {
233
+ $url = $this->_addParametersToUrl($url, $data);
234
+ $handle = $this->curl->init($url);
235
+ $resp = $this->_sendRequest($handle);
236
+ return $resp;
237
+ }
238
+
239
+ /**
240
+ * _addParametersToUrl
241
+ *
242
+ * Adds the parameters in associative array $data to the
243
+ * given URL
244
+ * @param String $url URL
245
+ * @param array $data Parameters to be added as a query string to
246
+ * the URL provided
247
+ * @access protected
248
+ * @return void
249
+ */
250
+ protected function _addParametersToUrl($url, $data) {
251
+ if (!empty($data)) {
252
+ if (strpos($url, '?') === false) {
253
+ $url .= '?'.$this->buildData($data);
254
+ } else {
255
+ $url .= '&'.$this->buildData($data);
256
+ }
257
+ }
258
+ return $url;
259
+ }
260
+
261
+ /**
262
+ * generateNonce
263
+ *
264
+ * Generates a 'nonce', which is a unique request id based on the
265
+ * timestamp. If no timestamp is provided, generate one.
266
+ * @param mixed $timestamp Either a timestamp (epoch seconds) or false,
267
+ * in which case it will generate a timestamp.
268
+ * @access public
269
+ * @return string Returns a unique nonce
270
+ */
271
+ public function generateNonce($timestamp = false) {
272
+ if (!$timestamp) $timestamp = $this->generateTimestamp();
273
+ return md5($timestamp.'-'.rand(10000,99999).'-'.uniqid());
274
+ }
275
+
276
+ /**
277
+ * generateTimestamp
278
+ *
279
+ * Generates a timestamp, in seconds
280
+ * @access public
281
+ * @return int Timestamp, in epoch seconds
282
+ */
283
+ public function generateTimestamp() {
284
+ return time();
285
+ }
286
+
287
+ /**
288
+ * createSignature
289
+ *
290
+ * Creates a signature on the signature base and the signature key
291
+ * @param mixed $sigBase Base string of data to sign
292
+ * @param mixed $sigKey Key to sign the data with
293
+ * @access public
294
+ * @return string The signature
295
+ */
296
+ public function createSignature($sigBase, $sigKey) {
297
+ switch ($this->signatureMethod) {
298
+ case 'HMAC-SHA1':
299
+ default:
300
+ return base64_encode(hash_hmac('sha1', $sigBase, $sigKey, true));
301
+ }
302
+ }
303
+
304
+ /**
305
+ * encode
306
+ *
307
+ * Short-cut for utf8_encode / rawurlencode
308
+ * @param mixed $data Data to encode
309
+ * @access protected
310
+ * @return void Encoded data
311
+ */
312
+ protected function encode($data) {
313
+ return rawurlencode(utf8_encode($data));
314
+ }
315
+
316
+ /**
317
+ * createSignatureKey
318
+ *
319
+ * Creates a key that will be used to sign our signature. Signatures
320
+ * are signed with the consumerSecret for this consumer application and
321
+ * the token secret of the user that the application is acting on behalf
322
+ * of.
323
+ * @access public
324
+ * @return void
325
+ */
326
+ public function createSignatureKey() {
327
+ return $this->consumerSecret.'&'.$this->user->tokenSecret;
328
+ }
329
+
330
+ /**
331
+ * getOAuthRequestData
332
+ *
333
+ * Get all the pre-signature, OAuth specific parameters for a request.
334
+ * @access public
335
+ * @return void
336
+ */
337
+ public function getOAuthRequestData() {
338
+ $token = $this->user->getHighestPriorityToken();
339
+ $ts = $this->generateTimestamp();
340
+ $nonce = $this->generateNonce($ts);
341
+ return array(
342
+ 'oauth_token' => $token,
343
+ 'oauth_consumer_key' => $this->consumerKey,
344
+ 'oauth_version' => $this->version,
345
+ 'oauth_timestamp' => $ts,
346
+ 'oauth_signature_method' => $this->signatureMethod,
347
+ 'oauth_nonce' => $nonce);
348
+ }
349
+
350
+
351
+ /**
352
+ * mergeOAuthData
353
+ *
354
+ * @param mixed $requestData
355
+ * @access public
356
+ * @return void
357
+ */
358
+ public function mergeOAuthData($requestData) {
359
+ $oauthData = $this->getOAuthRequestData();
360
+ return array_merge($requestData, $oauthData);
361
+ }
362
+
363
+ /**
364
+ * createSignatureBase
365
+ *
366
+ * @param mixed $method String name of HTTP method, such as "GET"
367
+ * @param mixed $url URL where this request will go
368
+ * @param mixed $data Array of params for this request. This should
369
+ * include ALL oauth properties except for the signature.
370
+ * @access public
371
+ * @return void
372
+ */
373
+ public function createSignatureBase($method, $url, $data) {
374
+ $method = $this->encode(strtoupper($method));
375
+ $query = parse_url($url, PHP_URL_QUERY);
376
+ if ($query) {
377
+ $parts = explode('?', $url, 2);
378
+ $url = array_shift($parts);
379
+ $items = explode('&', $query);
380
+ foreach ($items as $item) {
381
+ list($key, $value) = explode('=', $item);
382
+ $data[rawurldecode($key)] = rawurldecode($value);
383
+ }
384
+ }
385
+ $url = $this->encode($url);
386
+ $data = $this->encode($this->collapseDataForSignature($data));
387
+ return $method.'&'.$url.'&'.$data;
388
+ }
389
+
390
+ /**
391
+ * collapseDataForSignature
392
+ *
393
+ * Turns an array of request data into a string, as used by the oauth
394
+ * signature
395
+ * @param mixed $data
396
+ * @access public
397
+ * @return void
398
+ */
399
+ public function collapseDataForSignature($data) {
400
+ ksort($data);
401
+ $collapse = '';
402
+ foreach ($data as $key => $val) {
403
+ if (!empty($collapse)) $collapse .= '&';
404
+ $collapse .= $key.'='.$this->encode($val);
405
+ }
406
+ return $collapse;
407
+ }
408
+
409
+ /**
410
+ * signRequest
411
+ *
412
+ * Signs the request.
413
+ *
414
+ * @param mixed $method HTTP method
415
+ * @param mixed $url URL for the request
416
+ * @param mixed $data The data to be signed
417
+ * @access public
418
+ * @return array The data, with the signature.
419
+ */
420
+ public function signRequest($method, $url, $data) {
421
+ $base = $this->createSignatureBase($method, $url, $data);
422
+ $key = $this->createSignatureKey();
423
+ $data['oauth_signature'] = $this->createSignature($base, $key);
424
+ ksort($data);
425
+ return $data;
426
+ }
427
+
428
+
429
+ /**
430
+ * makeRequest
431
+ *
432
+ * Public facing function to make a request
433
+ *
434
+ * @param mixed $method
435
+ * @param mixed $url - Reserved characters in query params MUST be escaped
436
+ * @param mixed $data - Reserved characters in values MUST NOT be escaped
437
+ * @access public
438
+ * @return void
439
+ */
440
+ public function makeRequest($method, $url, $data=array()) {
441
+
442
+ if ($this->debug) echo "\n** {$method}: $url\n";
443
+
444
+ switch (strtoupper($method)) {
445
+ case 'POST':
446
+ $oauth = $this->prepareRequest($method, $url, $data);
447
+ $resp = $this->post($url, $oauth);
448
+ break;
449
+
450
+ case 'GET':
451
+ $oauth = $this->prepareRequest($method, $url, $data);
452
+ $resp = $this->get($url, $oauth, $data);
453
+ break;
454
+
455
+ case 'DELETE':
456
+ $oauth = $this->prepareRequest($method, $url, $data);
457
+ $resp = $this->delete($url, $oauth);
458
+ break;
459
+
460
+ case 'PATCH':
461
+ $oauth = $this->prepareRequest($method, $url, array());
462
+ $resp = $this->patch($url, $oauth, $data);
463
+ break;
464
+ }
465
+
466
+ // enable debug output
467
+ if ($this->debug) {
468
+ echo "<pre>";
469
+ print_r($oauth);
470
+ echo " --> Status: {$resp->headers['Status-Code']}\n";
471
+ echo " --> Body: {$resp->body}";
472
+ echo "</pre>";
473
+ }
474
+
475
+ if (!$resp) {
476
+ $msg = 'Unable to connect to the AWeber API. (' . $this->error . ')';
477
+ $error = array('message' => $msg, 'type' => 'APIUnreachableError',
478
+ 'documentation_url' => 'https://labs.aweber.com/docs/troubleshooting');
479
+ throw new LI_AWeberAPIException($error, $url);
480
+ }
481
+
482
+ if($resp->headers['Status-Code'] >= 400) {
483
+ $data = json_decode($resp->body, true);
484
+ throw new LI_AWeberAPIException($data['error'], $url);
485
+ }
486
+
487
+ return $resp;
488
+ }
489
+
490
+ /**
491
+ * put
492
+ *
493
+ * Prepare an OAuth put method.
494
+ *
495
+ * @param mixed $url URL where we are making the request to
496
+ * @param mixed $data Data that is used to make the request
497
+ * @access protected
498
+ * @return void
499
+ */
500
+ protected function patch($url, $oauth, $data) {
501
+ $url = $this->_addParametersToUrl($url, $oauth);
502
+ $handle = $this->curl->init($url);
503
+ $this->curl->setopt($handle, CURLOPT_CUSTOMREQUEST, 'PATCH');
504
+ $this->curl->setopt($handle, CURLOPT_POSTFIELDS, json_encode($data));
505
+ $resp = $this->_sendRequest($handle, array('Expect:', 'Content-Type: application/json'));
506
+ return $resp;
507
+ }
508
+
509
+ /**
510
+ * post
511
+ *
512
+ * Prepare an OAuth post method.
513
+ *
514
+ * @param mixed $url URL where we are making the request to
515
+ * @param mixed $data Data that is used to make the request
516
+ * @access protected
517
+ * @return void
518
+ */
519
+ protected function post($url, $oauth) {
520
+ $handle = $this->curl->init($url);
521
+ $postData = $this->buildData($oauth);
522
+ $this->curl->setopt($handle, CURLOPT_POST, true);
523
+ $this->curl->setopt($handle, CURLOPT_POSTFIELDS, $postData);
524
+ $resp = $this->_sendRequest($handle);
525
+ return $resp;
526
+ }
527
+
528
+ /**
529
+ * delete
530
+ *
531
+ * Makes a DELETE request
532
+ * @param mixed $url URL where we are making the request to
533
+ * @param mixed $data Data that is used in the request
534
+ * @access protected
535
+ * @return void
536
+ */
537
+ protected function delete($url, $data) {
538
+ $url = $this->_addParametersToUrl($url, $data);
539
+ $handle = $this->curl->init($url);
540
+ $this->curl->setopt($handle, CURLOPT_CUSTOMREQUEST, 'DELETE');
541
+ $resp = $this->_sendRequest($handle);
542
+ return $resp;
543
+ }
544
+
545
+ /**
546
+ * buildData
547
+ *
548
+ * Creates a string of data for either post or get requests.
549
+ * @param mixed $data Array of key value pairs
550
+ * @access public
551
+ * @return void
552
+ */
553
+ public function buildData($data) {
554
+ ksort($data);
555
+ $params = array();
556
+ foreach ($data as $key => $value) {
557
+ $params[] = $key.'='.$this->encode($value);
558
+ }
559
+ return implode('&', $params);
560
+ }
561
+
562
+ /**
563
+ * _sendRequest
564
+ *
565
+ * Actually makes a request.
566
+ * @param mixed $handle Curl handle
567
+ * @param array $headers Additional headers needed for request
568
+ * @access private
569
+ * @return void
570
+ */
571
+ private function _sendRequest($handle, $headers = array('Expect:')) {
572
+ $this->curl->setopt($handle, CURLOPT_RETURNTRANSFER, true);
573
+ $this->curl->setopt($handle, CURLOPT_HEADER, true);
574
+ $this->curl->setopt($handle, CURLOPT_HTTPHEADER, $headers);
575
+ $this->curl->setopt($handle, CURLOPT_USERAGENT, $this->userAgent);
576
+ $this->curl->setopt($handle, CURLOPT_SSL_VERIFYPEER, FALSE);
577
+ $this->curl->setopt($handle, CURLOPT_VERBOSE, FALSE);
578
+ $this->curl->setopt($handle, CURLOPT_CONNECTTIMEOUT, 10);
579
+ $this->curl->setopt($handle, CURLOPT_TIMEOUT, 90);
580
+ $resp = $this->curl->execute($handle);
581
+ if ($resp) {
582
+ return new LI_CurlResponse($resp);
583
+ }
584
+ $this->error = $this->curl->errno($handle) . ' - ' .
585
+ $this->curl->error($handle);
586
+ return false;
587
+ }
588
+
589
+ /**
590
+ * prepareRequest
591
+ *
592
+ * @param mixed $method HTTP method
593
+ * @param mixed $url URL for the request
594
+ * @param mixed $data The data to generate oauth data and be signed
595
+ * @access public
596
+ * @return void The data, with all its OAuth variables and signature
597
+ */
598
+ public function prepareRequest($method, $url, $data) {
599
+ $data = $this->mergeOAuthData($data);
600
+ $data = $this->signRequest($method, $url, $data);
601
+ return $data;
602
+ }
603
+
604
+ /**
605
+ * parseResponse
606
+ *
607
+ * Parses the body of the response into an array
608
+ * @param mixed $string The body of a response
609
+ * @access public
610
+ * @return void
611
+ */
612
+ public function parseResponse($resp) {
613
+ $data = array();
614
+
615
+ if (!$resp) { return $data; }
616
+ if (empty($resp)) { return $data; }
617
+ if (empty($resp->body)) { return $data; }
618
+
619
+ switch ($this->format) {
620
+ case 'json':
621
+ $data = json_decode($resp->body);
622
+ break;
623
+ default:
624
+ parse_str($resp->body, $data);
625
+ }
626
+ $this->parseAsError($data);
627
+ return $data;
628
+ }
629
+
630
+ }
631
+
632
+ /**
633
+ * OAuthUser
634
+ *
635
+ * Simple data class representing the user in an OAuth application.
636
+ * @package
637
+ * @version $id$
638
+ */
639
+ class LI_OAuthUser {
640
+
641
+ public $authorizedToken = false;
642
+ public $requestToken = false;
643
+ public $verifier = false;
644
+ public $tokenSecret = false;
645
+ public $accessToken = false;
646
+
647
+ /**
648
+ * isAuthorized
649
+ *
650
+ * Checks if this user is authorized.
651
+ * @access public
652
+ * @return void
653
+ */
654
+ public function isAuthorized() {
655
+ if (empty($this->authorizedToken) && empty($this->accessToken)) {
656
+ return false;
657
+ }
658
+ return true;
659
+ }
660
+
661
+
662
+ /**
663
+ * getHighestPriorityToken
664
+ *
665
+ * Returns highest priority token - used to define authorization
666
+ * state for a given OAuthUser
667
+ * @access public
668
+ * @return void
669
+ */
670
+ public function getHighestPriorityToken() {
671
+ if (!empty($this->accessToken)) return $this->accessToken;
672
+ if (!empty($this->authorizedToken)) return $this->authorizedToken;
673
+ if (!empty($this->requestToken)) return $this->requestToken;
674
+
675
+ // Return no token, new user
676
+ return '';
677
+ }
678
+
679
+ }
680
+
681
+ ?>
power-ups/campaign-monitor-connect.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Power-up Name: Campaign Monitor
4
+ * Power-up Class: LICampaignMonitorConnect
5
+ * Power-up Menu Text:
6
+ * Power-up Slug: campaign_monitor_connect
7
+ * Power-up Menu Link: settings
8
+ * Power-up URI: http://leadin.com/mailchimp-connect
9
+ * Power-up Description: Push your contacts to Campaign Monitor email lists.
10
+ * Power-up Icon: power-up-icon-campaign-monitor-connect
11
+ * Power-up Icon Small: power-up-icon-campaign-monitor-connect_small
12
+ * First Introduced: 0.7.0
13
+ * Power-up Tags: Newsletter, Email
14
+ * Auto Activate: No
15
+ * Permanently Enabled: No
16
+ * Hidden: No
17
+ * cURL Required: Yes
18
+ */
19
+
20
+ //=============================================
21
+ // Define Constants
22
+ //=============================================
23
+
24
+ if ( !defined('LEADIN_CAMPAIGN_MONITOR_CONNECT_PATH') )
25
+ define('LEADIN_CAMPAIGN_MONITOR_CONNECT_PATH', LEADIN_PATH . '/power-ups/campaign-monitor-connect');
26
+
27
+ if ( !defined('LEADIN_CAMPAIGN_MONITOR_CONNECT_PLUGIN_DIR') )
28
+ define('LEADIN_CAMPAIGN_MONITOR_CONNECT_PLUGIN_DIR', LEADIN_PLUGIN_DIR . '/power-ups/campaign-monitor-connect');
29
+
30
+ if ( !defined('LEADIN_CAMPAIGN_MONITOR_CONNECT_PLUGIN_SLUG') )
31
+ define('LEADIN_CAMPAIGN_MONITOR_CONNECT_SLUG', basename(dirname(__FILE__)));
32
+
33
+ //=============================================
34
+ // Include Needed Files
35
+ //=============================================
36
+ require_once(LEADIN_CAMPAIGN_MONITOR_CONNECT_PLUGIN_DIR . '/admin/campaign-monitor-connect-admin.php');
37
+ require_once(LEADIN_CAMPAIGN_MONITOR_CONNECT_PLUGIN_DIR . '/inc/li_campaign_monitor.php');
38
+
39
+ //=============================================
40
+ // WPLeadIn Class
41
+ //=============================================
42
+ class LICampaignMonitorConnect extends WPLeadIn {
43
+
44
+ var $admin;
45
+ var $options;
46
+ var $power_option_name = 'leadin_campaign_monitor_connect_options';
47
+
48
+ /**
49
+ * Class constructor
50
+ */
51
+ function __construct ( $activated )
52
+ {
53
+ //=============================================
54
+ // Hooks & Filters
55
+ //=============================================
56
+
57
+ if ( ! $activated )
58
+ return false;
59
+
60
+ global $leadin_campaign_monitor_connect_wp;
61
+ $leadin_campaign_monitor_connect_wp = $this;
62
+ $this->options = get_option($this->power_option_name);
63
+ }
64
+
65
+ public function admin_init ( )
66
+ {
67
+ $admin_class = get_class($this) . 'Admin';
68
+ $this->admin = new $admin_class($this->icon_small);
69
+ }
70
+
71
+ function power_up_setup_callback ( )
72
+ {
73
+ $this->admin->power_up_setup_callback();
74
+ }
75
+
76
+ /**
77
+ * Activate the power-up and add the defaults
78
+ */
79
+ function add_defaults ()
80
+ {
81
+
82
+ }
83
+
84
+ /**
85
+ * Adds a subcsriber to a specific list
86
+ *
87
+ * @param string
88
+ * @param string
89
+ * @param string
90
+ * @param string
91
+ * @param string
92
+ * @return int/bool API status code OR false if api key not set
93
+ */
94
+ function push_contact_to_list ( $list_id = '', $email = '', $first_name = '', $last_name = '', $phone = '' )
95
+ {
96
+ if ( isset($this->options['li_cm_api_key']) && $this->options['li_cm_api_key'] && $list_id )
97
+ {
98
+ $cm = new LI_Campaign_Monitor($this->options['li_cm_api_key']);
99
+ $r = $cm->call('subscribers/' . $list_id, 'POST', array(
100
+ 'EmailAddress' => $email,
101
+ 'Name' => $first_name . ' ' . $last_name,
102
+ 'Resubscribe' => TRUE
103
+ ));
104
+
105
+ if ( $r['code'] <= 400 )
106
+ {
107
+ leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'campaign_monitor'));
108
+ return TRUE;
109
+ }
110
+ else
111
+ return FALSE;
112
+ }
113
+
114
+ return FALSE;
115
+ }
116
+
117
+ /**
118
+ * Adds a subcsriber to a specific list
119
+ *
120
+ * @param string
121
+ * @param array
122
+ * @return int/bool API status code OR false if api key not set
123
+ */
124
+ function bulk_push_contact_to_list ( $list_id = '', $contacts = '' )
125
+ {
126
+ /*
127
+ The majority of our user base doesn't use Campaign Monitor, so we decided not to retroactively sync contacts to the list.
128
+ If people complain, we will respond with a support ticket and ask them to export/import manually.
129
+ */
130
+
131
+ return FALSE;
132
+ }
133
+ }
134
+
135
+ //=============================================
136
+ // ESP Connect Init
137
+ //=============================================
138
+
139
+ global $leadin_campaign_monitor_connect_wp;
140
+
141
+ ?>
power-ups/campaign-monitor-connect/admin/campaign-monitor-connect-admin.php ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //=============================================
3
+ // LICampaignMonitorConnectAdmin Class
4
+ //=============================================
5
+ class LICampaignMonitorConnectAdmin extends WPLeadInAdmin {
6
+
7
+ var $power_up_settings_section = 'leadin_campaign_monitor_connect_options_section';
8
+ var $power_option_name = 'leadin_campaign_monitor_connect_options';
9
+ var $power_up_icon;
10
+ var $options;
11
+ var $authed = FALSE;
12
+ var $invalid_key = FALSE;
13
+
14
+ /**
15
+ * Class constructor
16
+ */
17
+ function __construct ( $power_up_icon_small )
18
+ {
19
+ //=============================================
20
+ // Hooks & Filters
21
+ //=============================================
22
+
23
+ if ( is_admin() )
24
+ {
25
+ $this->power_up_icon = $power_up_icon_small;
26
+ add_action('admin_init', array($this, 'leadin_build_esp_settings_page'));
27
+ $this->options = get_option($this->power_option_name);
28
+ $this->authed = ( isset($this->options['li_cm_api_key']) && $this->options['li_cm_api_key'] ? TRUE : FALSE );
29
+
30
+ if ( $this->authed )
31
+ $this->invalid_key = $this->li_check_invalid_api_key($this->options['li_cm_api_key']);
32
+ }
33
+ }
34
+
35
+ //=============================================
36
+ // Settings Page
37
+ //=============================================
38
+
39
+ /**
40
+ * Creates settings options
41
+ */
42
+ function leadin_build_esp_settings_page ()
43
+ {
44
+ register_setting('leadin_settings_options', $this->power_option_name, array($this, 'sanitize'));
45
+ add_settings_section($this->power_up_settings_section, $this->power_up_icon . "Campaign Monitor", '', LEADIN_ADMIN_PATH);
46
+ add_settings_field('li_cm_api_key', 'API key', array($this, 'li_cm_api_key_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
47
+
48
+ if ( isset($this->options['li_cm_api_key']) )
49
+ {
50
+ if ( $this->options['li_cm_api_key'] )
51
+ add_settings_field('li_print_synced_lists', 'Synced tags', array($this, 'li_print_synced_lists'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Sanitize each setting field as needed
57
+ *
58
+ * @param array $input Contains all settings fields as array keys
59
+ */
60
+ public function sanitize ( $input )
61
+ {
62
+ $new_input = array();
63
+
64
+ if ( isset( $input['li_cm_api_key'] ) )
65
+ $new_input['li_cm_api_key'] = sanitize_text_field( $input['li_cm_api_key'] );
66
+
67
+ return $new_input;
68
+ }
69
+
70
+ /**
71
+ * Prints API key input for settings page
72
+ */
73
+ function li_cm_api_key_callback ()
74
+ {
75
+ $li_cm_api_key = ( $this->options['li_cm_api_key'] ? $this->options['li_cm_api_key'] : '' ); // Get header from options, or show default
76
+
77
+ printf(
78
+ '<input id="li_cm_api_key" type="text" id="title" name="' . $this->power_option_name . '[li_cm_api_key]" value="%s" style="width: 430px;"/>',
79
+ $li_cm_api_key
80
+ );
81
+
82
+ if ( ! isset($li_cm_api_key) || ! $li_cm_api_key )
83
+ echo '<p><a target="_blank" href="http://help.campaignmonitor.com/topic.aspx?t=206">Get your API key</a> from <a href="https://login.createsend.com/l" target="_blank">CampaignMonitor.com</a></p>';
84
+ }
85
+
86
+ /**
87
+ * Prints synced lists out for settings page in format Tag Name → ESP list
88
+ */
89
+ function li_print_synced_lists ()
90
+ {
91
+ $li_cm_api_key = ( $this->options['li_cm_api_key'] ? $this->options['li_cm_api_key'] : '' ); // Get header from options, or show default
92
+
93
+ if ( isset($li_cm_api_key ) )
94
+ {
95
+ $synced_lists = $this->li_get_synced_list_for_esp('campaign_monitor');
96
+ $list_value_pairs = array();
97
+ $synced_list_count = 0;
98
+
99
+ echo '<table>';
100
+ foreach ( $synced_lists as $synced_list )
101
+ {
102
+ foreach ( stripslashes_deep(unserialize($synced_list->tag_synced_lists)) as $tag_synced_list )
103
+ {
104
+ if ( $tag_synced_list['esp'] == 'campaign_monitor' )
105
+ {
106
+ echo '<tr class="synced-list-row">';
107
+ echo '<td class="synced-list-cell"><span class="icon-tag"></span> ' . $synced_list->tag_text . '</td>';
108
+ echo '<td class="synced-list-cell"><span class="synced-list-arrow">&#8594;</span></td>';
109
+ echo '<td class="synced-list-cell"><span class="icon-envelope"></span> ' . $tag_synced_list['list_name'] . '</td>';
110
+ echo '<td class="synced-list-edit"><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags&action=edit_tag&tag=' . $synced_list->tag_id . '">edit tag</a></td>';
111
+ echo '</tr>';
112
+
113
+ $synced_list_count++;
114
+ }
115
+ }
116
+ }
117
+ echo '</table>';
118
+
119
+ if ( ! $synced_list_count ) {
120
+ echo '<p>Campaign Monitor connected succesfully! <a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">Select a tag to send contacts to Campaign Monitor</a>.</p>';
121
+ } else {
122
+ echo '<p><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">Edit your tags</a> or <a href="https://login.createsend.com/l" target="_blank">Create a new list on CampaignMonitor.com</a></p>';
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Get synced list for the ESP from the WordPress database
129
+ *
130
+ * @return array/object
131
+ */
132
+ function li_get_synced_list_for_esp ( $esp_name, $output_type = 'OBJECT' )
133
+ {
134
+ global $wpdb;
135
+
136
+ $q = $wpdb->prepare("SELECT * FROM $wpdb->li_tags WHERE tag_synced_lists LIKE '%%%s%%' AND tag_deleted = 0", $esp_name);
137
+ $synced_lists = $wpdb->get_results($q, $output_type);
138
+
139
+ return $synced_lists;
140
+ }
141
+
142
+ /**
143
+ * Format API-returned lists into parseable format on front end
144
+ *
145
+ * @return array
146
+ */
147
+ function li_get_lists ( )
148
+ {
149
+ $lists = $this->li_get_api_lists($this->options['li_cm_api_key']);
150
+
151
+ $sanitized_lists = array();
152
+ if ( count($lists) )
153
+ {
154
+ foreach ( $lists as $list )
155
+ {
156
+ $list_obj = (Object)NULL;
157
+ $list_obj->id = $list['ListID'];
158
+ $list_obj->name = $list['Name'] . ' (Client: ' . $list['ClientName'] . ')';
159
+
160
+ array_push($sanitized_lists, $list_obj);;
161
+ }
162
+ }
163
+
164
+ return $sanitized_lists;
165
+ }
166
+
167
+ /**
168
+ * Get lists from Campaign Monitor account
169
+ *
170
+ * @param string
171
+ * @return array
172
+ */
173
+ function li_get_api_lists ( $api_key )
174
+ {
175
+ $all_lists = array();
176
+
177
+ $cm = new LI_Campaign_Monitor($api_key);
178
+ $clients = $cm->call('clients', 'GET');
179
+
180
+ if ( count($clients['response']) )
181
+ {
182
+ foreach ( $clients['response'] as $client )
183
+ {
184
+ $lists = $cm->call('clients/' . $client['ClientID'] . '/lists', 'GET');
185
+
186
+ if ( count($lists['response']) )
187
+ {
188
+ foreach ( $lists['response'] as $list )
189
+ {
190
+ $list['ClientName'] = $client['Name'];
191
+ array_push($all_lists, $list);
192
+ }
193
+ }
194
+ }
195
+ }
196
+
197
+ return $all_lists;
198
+ }
199
+
200
+ /**
201
+ * Use MailChimp API key to try to grab corresponding user profile to check validity of key
202
+ *
203
+ * @param string
204
+ * @return bool
205
+ */
206
+ function li_check_invalid_api_key ( $api_key )
207
+ {
208
+ $cm = new LI_Campaign_Monitor($api_key);
209
+ $test = $cm->call('clients', 'GET');
210
+
211
+ if ( $test['code'] >= 400 )
212
+ {
213
+ unset($this->options['li_cm_api_key']);
214
+ update_option($this->power_option_name, $this->options);
215
+
216
+ $invalid_key = TRUE;
217
+ }
218
+ else
219
+ $invalid_key = FALSE;
220
+
221
+ return $invalid_key;
222
+ }
223
+ }
224
+
225
+ ?>
power-ups/campaign-monitor-connect/inc/li_campaign_monitor.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Simple Campaign Monitor API wrapper
4
+ *
5
+ * Uses cURL
6
+ * When called it returns HTTP response code and associative array of JSON response
7
+ * The HTTP response code can be used to determine if the request processed successfully
8
+ * If there is an error it is described in the associative array of JSON response
9
+ *
10
+ * @author Mehedi Hasan <mha_bd@yahoo.com>
11
+ *
12
+ * @usage
13
+ *
14
+ * $cm = new CMWrapper("{api_key}");
15
+ * $r = $cm->call("{method}", "{httpmethod}", {jsonargs}. {urlargs});
16
+ *
17
+ * @example
18
+ * the following updates a subscribers email address from name@test.com to newname@test.com
19
+ * $cm = new CMWrapper("abcd1234");
20
+ * $r = $cm->call("subscribers/xyz789", "PUT", array("EmailAddress" => "newname@test.com"), array("EmailAddress" => "name@test.com"));
21
+ */
22
+
23
+ class LI_Campaign_Monitor
24
+ {
25
+ private $api_key;
26
+ private $api_endpoint = 'https://api.createsend.com/api/v3.1';
27
+ private $verify_ssl = false;
28
+
29
+ /**
30
+ * Create a new instance
31
+ * @param string $api_key Your Campaign Monitor API key
32
+ */
33
+ function __construct($api_key)
34
+ {
35
+ $this->api_key = $api_key;
36
+ }
37
+
38
+ /**
39
+ * Call an API method. Every request needs the API key, so that is added automatically -- you don't need to pass it in.
40
+ * @param string $method The API method to call, e.g. 'subscribers/{listid}',
41
+ * @param string $httpmethod The HTTP method to be used, e.g. 'GET', 'POST', 'PUT', 'DELETE'
42
+ * @param array $jsonargs An array of arguments to pass to the method while using POST/PUT. Will be json encoded for you.
43
+ * @param array $urlargs An array of arguments to pass to the method. Will be appended to URL.
44
+ * @return array An array of response HTTP code and associative array of json decoded API response.
45
+ */
46
+ public function call($method, $httpmethod, $jsonargs = array(), $urlargs = array())
47
+ {
48
+ return $this->makeRequest($method, $httpmethod, $jsonargs, $urlargs);
49
+ }
50
+
51
+ /**
52
+ * Performs the underlying HTTP request.
53
+ * @param string $method The API method to call, e.g. 'subscribers/{listid}',
54
+ * @param string $httpmethod The HTTP method to be used, e.g. 'GET', 'POST', 'PUT', 'DELETE'
55
+ * @param array $jsonargs An array of arguments to pass to the method while using POST/PUT. Will be json encoded for you.
56
+ * @param array $urlargs An array of arguments to pass to the method. Will be appended to URL.
57
+ * @return array An array of response HTTP code and associative array of json decoded API response.
58
+ */
59
+ private function makeRequest($method, $httpmethod, $jsonargs = array(), $urlargs = array())
60
+ {
61
+ $args['apikey'] = $this->api_key;
62
+
63
+ $url = $this->api_endpoint.'/'.$method.'.json';
64
+
65
+ if( count($urlargs) > 0 ){
66
+ $url = $url . "?" . http_build_query($urlargs);
67
+ }
68
+
69
+ $ch = curl_init();
70
+ curl_setopt($ch, CURLOPT_URL, $url);
71
+ curl_setopt($ch, CURLOPT_HTTPHEADER,
72
+ array('Content-Type: application/json',
73
+ "Authorization: Basic " . base64_encode($this->api_key . ":x")
74
+ )
75
+ );
76
+ curl_setopt($ch, CURLOPT_USERAGENT, 'PHP-CMAPI');
77
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
78
+ curl_setopt($ch, CURLOPT_TIMEOUT, 10);
79
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl);
80
+ curl_setopt($ch, CURLOPT_HEADER, false);
81
+ curl_setopt($ch, CURLINFO_HEADER_OUT, true);
82
+
83
+ if( $httpmethod === "POST" ){
84
+ curl_setopt($ch, CURLOPT_POST, true);
85
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($jsonargs));
86
+ }
87
+
88
+ if( $httpmethod === "PUT" ){
89
+ curl_setopt($ch, CURLOPT_PUT, true);
90
+
91
+ $json = json_encode($jsonargs);
92
+
93
+ $fp = fopen('php://temp/maxmemory:256000', 'w');
94
+ fwrite($fp, $json);
95
+ fseek($fp, 0);
96
+
97
+ curl_setopt($ch, CURLOPT_INFILE, $fp);
98
+ curl_setopt($ch, CURLOPT_INFILESIZE, strlen($json));
99
+ }
100
+
101
+ if( $httpmethod === "DELETE" ){
102
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
103
+ }
104
+
105
+ $result = curl_exec($ch);
106
+
107
+ $ret = array(
108
+ "code" => curl_getinfo($ch, CURLINFO_HTTP_CODE),
109
+ "response" => json_decode($result, true),
110
+ );
111
+
112
+ curl_close($ch);
113
+
114
+ if( $httpmethod === "PUT" ){
115
+ fclose($fp);
116
+ }
117
+
118
+ //var_dump($httpmethod . " " . $url);
119
+ //var_dump($ret);
120
+
121
+ return $ret;
122
+ }
123
+ }
power-ups/campaign-monitor-connect/inc/test.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //api key 6efceb8935e61ab01f2a1f216b023d4b
3
+ //client id f70880b91dd8c7dd73d599cad4a5a639
4
+ //list id de1fa82595ce3b2eb99a6f4a69bbe452
5
+
6
+ require_once("li_campaign_monitor.php");
7
+
8
+ $cm = new LI_Campaign_Monitor("6efceb8935e61ab01f2a1f216b023d4b");
9
+
10
+ //test POST request
11
+ //adding a new subscriber with email name@test.com
12
+ $r = $cm->call("clients/f70880b91dd8c7dd73d599cad4a5a639/lists", "GET");
13
+ var_dump($r);
14
+ /*
15
+ //test GET request
16
+ //get details for subscriber with email name@test.com
17
+ $r = $cm->call("subscribers/de1fa82595ce3b2eb99a6f4a69bbe452", "GET", array(), array("email" => "name@test.com"));
18
+ var_dump($r);
19
+
20
+ //test PUT request
21
+ //change email of subscriber with email name@test.com to othername@test.com
22
+ $r = $cm->call("subscribers/de1fa82595ce3b2eb99a6f4a69bbe452", "PUT", array("EmailAddress" => "othername@test.com"), array("email" => "name@test.com"));
23
+ var_dump($r);
24
+
25
+ //test PUT request again
26
+ //change email of subscriber with email othername@test.com to name@test.com
27
+ $r = $cm->call("subscribers/de1fa82595ce3b2eb99a6f4a69bbe452", "PUT", array("EmailAddress" => "name@test.com"), array("email" => "othername@test.com"));
28
+ var_dump($r);
29
+
30
+ //test DELETE request
31
+ //delete subscriber with email name@test.com
32
+ $r = $cm->call("subscribers/de1fa82595ce3b2eb99a6f4a69bbe452", "DELETE", array(), array("email" => "name@test.com"));
33
+ var_dump($r);
34
+ */
35
+ ?>
power-ups/constant-contact-connect.php CHANGED
@@ -48,6 +48,7 @@ class WPConstantContactConnect extends WPLeadIn {
48
 
49
  var $admin;
50
  var $options;
 
51
  var $constant_contact;
52
  var $cc_id;
53
 
@@ -65,7 +66,7 @@ class WPConstantContactConnect extends WPLeadIn {
65
 
66
  global $leadin_constant_contact_connect_wp;
67
  $leadin_constant_contact_connect_wp = $this;
68
- $this->options = get_option('leadin_cc_options');
69
  }
70
 
71
  public function admin_init ( )
@@ -113,6 +114,8 @@ class WPConstantContactConnect extends WPLeadIn {
113
 
114
  if ( $this->cc_id )
115
  {
 
 
116
  return $this->constant_contact->add_subscription($this->cc_id, $list_id, 'ACTION_BY_CLIENT');
117
  }
118
  else
@@ -133,6 +136,8 @@ class WPConstantContactConnect extends WPLeadIn {
133
  if ( $phone )
134
  $contact['WorkPhone'] = $phone;
135
 
 
 
136
  return $this->constant_contact->add_contact($contact, array($list_id));
137
  }
138
  }
@@ -157,6 +162,8 @@ class WPConstantContactConnect extends WPLeadIn {
157
 
158
  if ( $cc_id )
159
  {
 
 
160
  return $this->constant_contact->remove_subscription($cc_id, $list_id);
161
  }
162
  else
@@ -183,7 +190,7 @@ class WPConstantContactConnect extends WPLeadIn {
183
  }
184
 
185
  //=============================================
186
- // Subscribe Widget Init
187
  //=============================================
188
 
189
  global $leadin_constant_contact_connect_wp;
48
 
49
  var $admin;
50
  var $options;
51
+ var $power_option_name = 'leadin_cc_options';
52
  var $constant_contact;
53
  var $cc_id;
54
 
66
 
67
  global $leadin_constant_contact_connect_wp;
68
  $leadin_constant_contact_connect_wp = $this;
69
+ $this->options = get_option($this->power_option_name);
70
  }
71
 
72
  public function admin_init ( )
114
 
115
  if ( $this->cc_id )
116
  {
117
+ leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'constant_contact'));
118
+
119
  return $this->constant_contact->add_subscription($this->cc_id, $list_id, 'ACTION_BY_CLIENT');
120
  }
121
  else
136
  if ( $phone )
137
  $contact['WorkPhone'] = $phone;
138
 
139
+ leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'constant_contact'));
140
+
141
  return $this->constant_contact->add_contact($contact, array($list_id));
142
  }
143
  }
162
 
163
  if ( $cc_id )
164
  {
165
+ leadin_track_plugin_activity('Contact Removed from List', array('esp_connector' => 'constant_contact'));
166
+
167
  return $this->constant_contact->remove_subscription($cc_id, $list_id);
168
  }
169
  else
190
  }
191
 
192
  //=============================================
193
+ // ESP Connect Init
194
  //=============================================
195
 
196
  global $leadin_constant_contact_connect_wp;
power-ups/constant-contact-connect/admin/constant-contact-connect-admin.php CHANGED
@@ -5,6 +5,7 @@
5
  class WPConstantContactConnectAdmin extends WPLeadInAdmin {
6
 
7
  var $power_up_settings_section = 'leadin_cc_options_section';
 
8
  var $power_up_icon;
9
  var $bad_api_call;
10
  var $constant_contact;
@@ -26,8 +27,8 @@ class WPConstantContactConnectAdmin extends WPLeadInAdmin {
26
  if ( is_admin() )
27
  {
28
  $this->power_up_icon = $power_up_icon_small;
29
- add_action('admin_init', array($this, 'leadin_cc_build_settings_page'));
30
- $this->options = get_option('leadin_cc_options');
31
  if ( isset($this->options['li_cc_email']) && isset($this->options['li_cc_password']) && $this->options['li_cc_email'] && $this->options['li_cc_password'] )
32
  $this->authed = TRUE;
33
  }
@@ -40,11 +41,11 @@ class WPConstantContactConnectAdmin extends WPLeadInAdmin {
40
  /**
41
  * Creates settings options
42
  */
43
- function leadin_cc_build_settings_page ()
44
  {
45
  global $leadin_constant_contact_connect_wp;
46
 
47
- register_setting('leadin_settings_options', 'leadin_cc_options', array($this, 'sanitize'));
48
 
49
  // If the creds are set, check if they are any good by hitting the API
50
  if ( $this->authed )
@@ -88,7 +89,7 @@ class WPConstantContactConnectAdmin extends WPLeadInAdmin {
88
  if ( $li_cc_email )
89
  {
90
  printf(
91
- '<input id="li_cc_email" type="hidden" name="leadin_cc_options[li_cc_email]" value="%s"/>',
92
  $li_cc_email
93
  );
94
  }
@@ -96,7 +97,7 @@ class WPConstantContactConnectAdmin extends WPLeadInAdmin {
96
  if ( $li_cc_password )
97
  {
98
  printf(
99
- '<input id="li_cc_password" type="hidden" name="leadin_cc_options[li_cc_password]" value="%s"/>',
100
  $li_cc_password
101
  );
102
  }
@@ -111,15 +112,12 @@ class WPConstantContactConnectAdmin extends WPLeadInAdmin {
111
  {
112
  $new_input = array();
113
 
114
- if( isset( $input['li_cc_email'] ) )
115
  $new_input['li_cc_email'] = sanitize_text_field( $input['li_cc_email'] );
116
 
117
- if( isset( $input['li_cc_password'] ) )
118
  $new_input['li_cc_password'] = sanitize_text_field( $input['li_cc_password'] );
119
 
120
- if( isset( $input['li_cc_subscribers_to_list'] ) )
121
- $new_input['li_cc_subscribers_to_list'] = sanitize_text_field( $input['li_cc_subscribers_to_list'] );
122
-
123
  return $new_input;
124
  }
125
 
@@ -131,7 +129,7 @@ class WPConstantContactConnectAdmin extends WPLeadInAdmin {
131
  $li_cc_email = ( $this->options['li_cc_email'] ? $this->options['li_cc_email'] : '' ); // Get header from options, or show default
132
 
133
  printf(
134
- '<input id="li_cc_email" type="text" id="title" name="leadin_cc_options[li_cc_email]" value="%s" size="50"/>',
135
  $li_cc_email
136
  );
137
  }
@@ -144,48 +142,11 @@ class WPConstantContactConnectAdmin extends WPLeadInAdmin {
144
  $li_cc_password = ( $this->options['li_cc_password'] ? $this->options['li_cc_password'] : '' ); // Get header from options, or show default
145
 
146
  printf(
147
- '<input id="li_cc_password" type="password" id="title" name="leadin_cc_options[li_cc_password]" value="%s" size="50"/>',
148
  $li_cc_password
149
  );
150
  }
151
 
152
- /**
153
- * Prints email input for settings page
154
- */
155
- function li_cc_subscribers_to_list_callback ()
156
- {
157
- $li_cc_subscribers_to_list = ( isset($this->options['li_cc_subscribers_to_list']) ? $this->options['li_cc_subscribers_to_list'] : '' ); // Get header from options, or show default
158
-
159
- echo '<select id="li_cc_subscribers_to_list" name="leadin_cc_options[li_cc_subscribers_to_list]" ' . ( ! count($this->lists) ? 'disabled' : '' ) . '>';
160
-
161
- if ( count($this->lists) )
162
- {
163
- $list_set = FALSE;
164
-
165
- foreach ( $this->lists as $list )
166
- {
167
- // Skip over default lists
168
- if ( $list['Name'] == 'Active' || $list['Name'] == 'Do Not Mail' || $list['Name'] == 'Removed' )
169
- continue;
170
-
171
- if ( urldecode($list['ListID']) == $li_cc_subscribers_to_list && !$list_set )
172
- $list_set = TRUE;
173
-
174
- echo '<option ' . ( urldecode($list['ListID']) == $li_cc_subscribers_to_list ? 'selected' : '' ) . ' value="' . urldecode($list['ListID']) . '">' . $list['Name'] . '</option>';
175
- }
176
-
177
- if ( !$list_set )
178
- echo '<option selected value="">No list set...</option>';
179
- }
180
- else
181
- {
182
- echo '<option value="No lists...">No lists...</option>';
183
- }
184
-
185
- echo '</select>';
186
- echo '<p><a href="https://login.constantcontact.com/login/login.sdo?goto=https://ui.constantcontact.com/rnavmap/distui/contacts" target="_blank">Create a new list on ConstantContact.com</a></p>';
187
- }
188
-
189
  function li_cc_get_email_lists ( $api_key, $username, $password )
190
  {
191
  $this->constant_contact = new LI_ConstantContact($username, $password, $api_key, FALSE);
5
  class WPConstantContactConnectAdmin extends WPLeadInAdmin {
6
 
7
  var $power_up_settings_section = 'leadin_cc_options_section';
8
+ var $power_option_name = 'leadin_cc_options';
9
  var $power_up_icon;
10
  var $bad_api_call;
11
  var $constant_contact;
27
  if ( is_admin() )
28
  {
29
  $this->power_up_icon = $power_up_icon_small;
30
+ add_action('admin_init', array($this, 'leadin_build_esp_settings_page'));
31
+ $this->options = get_option($this->power_option_name);
32
  if ( isset($this->options['li_cc_email']) && isset($this->options['li_cc_password']) && $this->options['li_cc_email'] && $this->options['li_cc_password'] )
33
  $this->authed = TRUE;
34
  }
41
  /**
42
  * Creates settings options
43
  */
44
+ function leadin_build_esp_settings_page ()
45
  {
46
  global $leadin_constant_contact_connect_wp;
47
 
48
+ register_setting('leadin_settings_options', $this->power_option_name, array($this, 'sanitize'));
49
 
50
  // If the creds are set, check if they are any good by hitting the API
51
  if ( $this->authed )
89
  if ( $li_cc_email )
90
  {
91
  printf(
92
+ '<input id="li_cc_email" type="hidden" name="' . $this->power_option_name . '[li_cc_email]" value="%s"/>',
93
  $li_cc_email
94
  );
95
  }
97
  if ( $li_cc_password )
98
  {
99
  printf(
100
+ '<input id="li_cc_password" type="hidden" name="' . $this->power_option_name . '[li_cc_password]" value="%s"/>',
101
  $li_cc_password
102
  );
103
  }
112
  {
113
  $new_input = array();
114
 
115
+ if ( isset( $input['li_cc_email'] ) )
116
  $new_input['li_cc_email'] = sanitize_text_field( $input['li_cc_email'] );
117
 
118
+ if ( isset( $input['li_cc_password'] ) )
119
  $new_input['li_cc_password'] = sanitize_text_field( $input['li_cc_password'] );
120
 
 
 
 
121
  return $new_input;
122
  }
123
 
129
  $li_cc_email = ( $this->options['li_cc_email'] ? $this->options['li_cc_email'] : '' ); // Get header from options, or show default
130
 
131
  printf(
132
+ '<input id="li_cc_email" type="text" id="title" name="' . $this->power_option_name . '[li_cc_email]" value="%s" style="width: 430px;"/>',
133
  $li_cc_email
134
  );
135
  }
142
  $li_cc_password = ( $this->options['li_cc_password'] ? $this->options['li_cc_password'] : '' ); // Get header from options, or show default
143
 
144
  printf(
145
+ '<input id="li_cc_password" type="password" id="title" name="' . $this->power_option_name . '[li_cc_password]" value="%s" style="width: 430px;"/>',
146
  $li_cc_password
147
  );
148
  }
149
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  function li_cc_get_email_lists ( $api_key, $username, $password )
151
  {
152
  $this->constant_contact = new LI_ConstantContact($username, $password, $api_key, FALSE);
power-ups/contacts.php CHANGED
@@ -37,7 +37,7 @@ if ( !defined('LEADIN_CONTACTS_PLUGIN_SLUG') )
37
  require_once(LEADIN_CONTACTS_PLUGIN_DIR . '/admin/contacts-admin.php');
38
 
39
  //=============================================
40
- // WPLeadIn Class
41
  //=============================================
42
  class WPLeadInContacts extends WPLeadIn {
43
 
37
  require_once(LEADIN_CONTACTS_PLUGIN_DIR . '/admin/contacts-admin.php');
38
 
39
  //=============================================
40
+ // WPLeadInContacts Class
41
  //=============================================
42
  class WPLeadInContacts extends WPLeadIn {
43
 
power-ups/contacts/admin/contacts-admin.php CHANGED
@@ -84,6 +84,20 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
84
  $li_contact->get_contact_history();
85
  $lead_email = $li_contact->history->lead->lead_email;
86
  $lead_source = leadin_strip_params_from_url($li_contact->history->lead->lead_source);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  if ( isset($_POST['edit_tags']) )
89
  {
@@ -126,9 +140,15 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
126
  }
127
 
128
  echo '<div class="contact-header-wrap">';
 
 
 
 
129
  echo '<img class="contact-header-avatar leadin-dynamic-avatar_' . substr($lead_id, -1) . '" height="76px" width="76px" src="https://api.hubapi.com/socialintel/v1/avatars?email=' . $lead_email . '"/>';
130
  echo '<div class="contact-header-info">';
131
  echo '<h1 class="contact-name">' . $lead_email . '</h1>';
 
 
132
  echo '<div class="contact-tags">';
133
  foreach( $li_contact->history->tags as $tag ) {
134
  if ($tag->tag_set)
@@ -160,7 +180,7 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
160
  </form>
161
  </div>
162
 
163
- <a class="thickbox contact-edit-tags" href="#TB_inline?width=400&height=400&inlineId=edit-contact-tags">edit tags</a>
164
 
165
  <?php
166
 
@@ -169,7 +189,7 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
169
  echo '</div>';
170
 
171
  echo '<div id="col-container">';
172
- echo '<div id="col-right">';
173
  echo '<div class="col-wrap contact-history">';
174
  echo '<ul class="sessions">';
175
  $sessions = $li_contact->history->sessions;
@@ -279,7 +299,7 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
279
  echo '</ul>';
280
  echo '</div>';
281
  echo '</div>';
282
- echo '<div id="col-left" class="metabox-holder">';
283
  echo '<div class="leadin-meta-section">';
284
  echo '<h4 class="leain-meta-header">Tracking Info</h4>';
285
  echo '<table class="leadin-meta-table"><tbody>';
@@ -314,10 +334,61 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
314
  echo '</tbody></table>';
315
  echo '</div>'; // leadin-meta-section
316
  echo '<div class="leadin-meta-section">';
317
- echo '<h4 class="leain-meta-header leadin-premium-tag">Social Info</h4>';
318
  echo '<table class="leadin-meta-table"><tbody>';
319
  echo '<tr>';
320
- echo '<td><a href="http://leadin.com/pro-upgrade/?utm_source=Leadin%20Repo%20Plugin&utm_medium=Contact%20Detail%20Screen&utm_campaign=Repo" target="_blank">Upgrade to Leadin Pro for free</a> to get social info</td>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  echo '</tr>';
322
  echo '</tbody></table>';
323
  echo '</div>'; // leadin-meta-section
@@ -325,12 +396,145 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
325
  echo '<h4 class="leain-meta-header leadin-premium-tag">Company Info</h4>';
326
  echo '<table class="leadin-meta-table"><tbody>';
327
  echo '<tr>';
328
- echo '<td><a href="http://leadin.com/pro-upgrade/?utm_source=Leadin%20Repo%20Plugin&utm_medium=Contact%20Detail%20Screen&utm_campaign=Repo" target="_blank">Upgrade to Leadin Pro for free</a> to get company info</td>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  echo '</tr>';
330
  echo '</tbody></table>';
331
  echo '</div>'; // leadin-meta-section
332
- echo '</div>';
333
-
334
  echo '</div>';
335
  }
336
 
@@ -365,9 +569,15 @@ class WPLeadInContactsAdmin extends WPLeadInAdmin {
365
 
366
  <?php
367
 
368
- $this->leadin_header('Leadin Contacts', 'leadin-contacts__header');
369
  ?>
370
 
 
 
 
 
 
 
371
  <div class="leadin-contacts__nav">
372
  <?php $leadinListTable->views(); ?>
373
  </div>
@@ -656,4 +866,5 @@ if ( isset($_POST['export-all']) || isset($_POST['export-selected']) )
656
  exit;
657
  }
658
 
 
659
  ?>
84
  $li_contact->get_contact_history();
85
  $lead_email = $li_contact->history->lead->lead_email;
86
  $lead_source = leadin_strip_params_from_url($li_contact->history->lead->lead_source);
87
+ $leadin_user = leadin_get_current_user();
88
+
89
+ ?>
90
+ <script type="text/javascript">
91
+ !function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="3.0.1";
92
+ analytics.load("<?php echo SEGMENT_WRITE_KEY ?>");
93
+ analytics.identify("<?php echo $leadin_user['user_id'] ?>", {
94
+ email : "<?php echo $leadin_user['email'] ?>",
95
+ contacts : "<?php echo $leadin_user['total_contacts'] ?>",
96
+ });
97
+ analytics.page("Loaded Contact Detail Page");
98
+ }}();
99
+ </script>
100
+ <?php
101
 
102
  if ( isset($_POST['edit_tags']) )
103
  {
140
  }
141
 
142
  echo '<div class="contact-header-wrap">';
143
+
144
+ if ( $li_contact->history->lead->lead_deleted )
145
+ $li_contact->display_error_message_for_merged_contact($li_contact->history->lead->lead_email);
146
+
147
  echo '<img class="contact-header-avatar leadin-dynamic-avatar_' . substr($lead_id, -1) . '" height="76px" width="76px" src="https://api.hubapi.com/socialintel/v1/avatars?email=' . $lead_email . '"/>';
148
  echo '<div class="contact-header-info">';
149
  echo '<h1 class="contact-name">' . $lead_email . '</h1>';
150
+
151
+
152
  echo '<div class="contact-tags">';
153
  foreach( $li_contact->history->tags as $tag ) {
154
  if ($tag->tag_set)
180
  </form>
181
  </div>
182
 
183
+ <a class="thickbox contact-edit-tags" <?php echo ( $li_contact->history->lead->lead_deleted ? 'style="display: none;"' : '' ); ?> href="#TB_inline?width=400&height=400&inlineId=edit-contact-tags">edit tags</a>
184
 
185
  <?php
186
 
189
  echo '</div>';
190
 
191
  echo '<div id="col-container">';
192
+ echo '<div id="col-right" ' . ( $li_contact->history->lead->lead_deleted ? 'style="display: none;"' : '' ) . '>';
193
  echo '<div class="col-wrap contact-history">';
194
  echo '<ul class="sessions">';
195
  $sessions = $li_contact->history->sessions;
299
  echo '</ul>';
300
  echo '</div>';
301
  echo '</div>';
302
+ echo '<div id="col-left" class="metabox-holder" ' . ( $li_contact->history->lead->lead_deleted ? 'style="display: none;"' : '' ) . '>';
303
  echo '<div class="leadin-meta-section">';
304
  echo '<h4 class="leain-meta-header">Tracking Info</h4>';
305
  echo '<table class="leadin-meta-table"><tbody>';
334
  echo '</tbody></table>';
335
  echo '</div>'; // leadin-meta-section
336
  echo '<div class="leadin-meta-section">';
337
+ echo '<h4 class="leain-meta-header leadin-premium-tag">Personal Info</h4>';
338
  echo '<table class="leadin-meta-table"><tbody>';
339
  echo '<tr>';
340
+ if ( leadin_check_pro_user() )
341
+ {
342
+ $social_data = FALSE;
343
+
344
+ if ( isset($li_contact->history->lead->social_data->properties->primary) )
345
+ {
346
+ $primary = $li_contact->history->lead->social_data->properties->primary;
347
+ echo '<b>' . $primary->title . ( $primary->company_name ? ' - ' . $primary->company_name : '' ) . '</b>';
348
+
349
+ $social_data = TRUE;
350
+ }
351
+
352
+ if ( isset($li_contact->history->lead->social_data->properties->description) )
353
+ {
354
+ echo '</br>' . $li_contact->history->lead->social_data->properties->description;
355
+
356
+ $social_data = TRUE;
357
+ }
358
+
359
+ if ( isset($li_contact->history->lead->social_data->properties->social_profiles) )
360
+ {
361
+ if ( count($li_contact->history->lead->social_data->properties->social_profiles) )
362
+ {
363
+ echo '<table class="leadin-meta-table"><tbody>';
364
+ foreach ( $li_contact->history->lead->social_data->properties->social_profiles as $key => $profile )
365
+ {
366
+ echo '<tr>';
367
+ echo '<th>';
368
+ echo $profile->typename;
369
+ echo '</th>';
370
+ echo '<td>';
371
+ echo '<a href="' . leadin_safe_social_profile_url($profile->url) . '" target="_blank">' . ( $profile->typeid == 'twitter' ? '@' : '' ) . ( $profile->typeid == 'linkedin' ? '/in/' : '' ) . $profile->username . '</a>';
372
+ echo '</td>';
373
+ echo '</tr>';
374
+ }
375
+ echo '</tbody></table>';
376
+
377
+ $social_data = TRUE;
378
+ }
379
+ }
380
+
381
+ if ( ! $social_data )
382
+ echo 'We couldn\'t find any personal info for this contact.';
383
+ }
384
+ else
385
+ {
386
+ echo '<table class="leadin-meta-table"><tbody>';
387
+ echo '<tr>';
388
+ echo '<td><a href="'. admin_url() . 'admin.php?page=leadin_pro_upgrade">Upgrade to Leadin Pro for free</a> to get personal info</td>';
389
+ echo '</tr>';
390
+ echo '</tbody></table>';
391
+ }
392
  echo '</tr>';
393
  echo '</tbody></table>';
394
  echo '</div>'; // leadin-meta-section
396
  echo '<h4 class="leain-meta-header leadin-premium-tag">Company Info</h4>';
397
  echo '<table class="leadin-meta-table"><tbody>';
398
  echo '<tr>';
399
+ if ( leadin_check_pro_user() )
400
+ {
401
+ $company_data = FALSE;
402
+
403
+ $properties = ( isset($li_contact->history->lead->company_data->properties) ? $li_contact->history->lead->company_data->properties : '' );
404
+
405
+ if ( isset($properties->name) )
406
+ {
407
+ echo '<p>';
408
+ echo '<b>About ' . $properties->name . '</b>';
409
+ if ( isset($properties->overview) )
410
+ {
411
+ $overview = $properties->overview;
412
+
413
+ if ( strlen($overview) < 260 )
414
+ {
415
+ echo '<br>' . $overview;
416
+ }
417
+ else
418
+ {
419
+ echo '<div id="company-detail-overview-short">' . substr($overview, 0, strpos($overview, '.', 260)) . ' ... <a id="contact-detail-read-more" href="javascript:void(0);">read more</a></div>';
420
+ echo '<div style="display: none;" id="company-detail-overview-full">' . $overview . ' <a id="contact-detail-read-less" href="javascript:void(0);">read less</a></div>';
421
+ }
422
+
423
+ $company_data = TRUE;
424
+ }
425
+ echo '</p>';
426
+ }
427
+
428
+ echo '<table class="leadin-meta-table"><tbody>';
429
+
430
+ if ( !empty($properties->employees) )
431
+ {
432
+ echo '<tr>';
433
+ echo '<th>Employees</th>';
434
+ echo '<td>' . $properties->employees . '</td>';
435
+ echo '</tr>';
436
+
437
+ $company_data = TRUE;
438
+ }
439
+
440
+ if ( !empty($properties->revenue) )
441
+ {
442
+ echo '<tr>';
443
+ echo '<th>Revenue</th>';
444
+ echo '<td>' . $properties->revenue . '</td>';
445
+ echo '</tr>';
446
+
447
+ $company_data = TRUE;
448
+ }
449
+
450
+ if ( !empty($properties->state) || !empty($properties->country) )
451
+ {
452
+ echo '<tr>';
453
+ echo '<th>Headquarters</th>';
454
+ echo '<td>' . ( !empty($properties->state) ? $properties->state : '' ) . ( !empty($properties->state) && !empty($properties->country) ? ', ' : '' ) . ( !empty($properties->country) ? $properties->country : '' ) . '</td>';
455
+ echo '</tr>';
456
+
457
+ $company_data = TRUE;
458
+ }
459
+
460
+ if ( !empty($properties->founded) )
461
+ {
462
+ echo '<tr>';
463
+ echo '<th>Founded</th>';
464
+ echo '<td>' . $properties->founded . '</td>';
465
+ echo '</tr>';
466
+
467
+ $company_data = TRUE;
468
+ }
469
+
470
+ if ( !empty($properties->facebookpageurl) )
471
+ {
472
+ echo '<tr>';
473
+ echo '<th>Facebook</th>';
474
+ echo '<td>' . '<a href="' . $properties->facebookpageurl . '" target="_blank">' . $properties->name . '</a></td>';
475
+ echo '</tr>';
476
+
477
+ $company_data = TRUE;
478
+ }
479
+
480
+ if ( !empty($properties->twitterusername) )
481
+ {
482
+ echo '<tr>';
483
+ echo '<th>Twitter</th>';
484
+ echo '<td>' . '<a href="' . $properties->twitterurl . '" target="_blank">' . '@' . $properties->twitterusername . '</a></td>';
485
+ echo '</tr>';
486
+
487
+ $company_data = TRUE;
488
+ }
489
+
490
+ if ( !empty($properties->linkedinurl) )
491
+ {
492
+ echo '<tr>';
493
+ echo '<th>LinkedIn</th>';
494
+ echo '<td>' . '<a href="' . $properties->linkedinurl . '" target="_blank">' . $properties->name . '</a></td>';
495
+ echo '</tr>';
496
+
497
+ $company_data = TRUE;
498
+ }
499
+
500
+ if ( !empty($properties->address) )
501
+ {
502
+ echo '<tr>';
503
+ echo '<th>Address</th>';
504
+ echo '<td><a href="http://maps.google.com/maps?q=' . urlencode($properties->address) . '"" target="_blank">' . $properties->address . '</a></td>';
505
+ echo '</tr>';
506
+
507
+ $company_data = TRUE;
508
+ }
509
+
510
+ if ( !empty($properties->country) )
511
+ {
512
+ echo '<tr>';
513
+ echo '<th>Country</th>';
514
+ echo '<td>' . $properties->country . '</td>';
515
+ echo '</tr>';
516
+
517
+ $company_data = TRUE;
518
+ }
519
+
520
+ if ( ! $company_data )
521
+ echo 'We couldn\'t find any company info for this contact.';
522
+
523
+
524
+ echo '</tbody></table>';
525
+ }
526
+ else
527
+ {
528
+ echo '<table class="leadin-meta-table"><tbody>';
529
+ echo '<tr>';
530
+ echo '<td><a href="'. admin_url() . 'admin.php?page=leadin_pro_upgrade">Upgrade to Leadin Pro for free</a> to get company info</td>';
531
+ echo '</tr>';
532
+ echo '</tbody></table>';
533
+ }
534
  echo '</tr>';
535
  echo '</tbody></table>';
536
  echo '</div>'; // leadin-meta-section
537
+ echo '</div>'; // col-left
 
538
  echo '</div>';
539
  }
540
 
569
 
570
  <?php
571
 
572
+ $this->leadin_header('Leadin Contacts', 'leadin-contacts__header', 'Loaded Contact List Page');
573
  ?>
574
 
575
+ <?php if ( isset($_GET['pro_upgrade']) ) : ?>
576
+ <div class="updated">
577
+ <p><?php _e( '<p><b>Welcome to Leadin Pro!</b></p> You can now use every feature Leadin has to offer. Visit our site to <a href="http://leadin.com/go-pro" target="_blank">learn more</a> about what Leadin Pro unlocks for you.', 'my-text-domain' ); ?></p>
578
+ </div>
579
+ <?php endif; ?>
580
+
581
  <div class="leadin-contacts__nav">
582
  <?php $leadinListTable->views(); ?>
583
  </div>
866
  exit;
867
  }
868
 
869
+
870
  ?>
power-ups/getresponse-connect.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Power-up Name: GetResponse
4
+ * Power-up Class: LIGetResponseConnect
5
+ * Power-up Menu Text:
6
+ * Power-up Slug: getresponse_connect
7
+ * Power-up Menu Link: settings
8
+ * Power-up URI: http://leadin.com/mailchimp-connect
9
+ * Power-up Description: Push your contacts to GetResponse email lists.
10
+ * Power-up Icon: power-up-icon-getresponse-connect
11
+ * Power-up Icon Small: power-up-icon-getresponse-connect_small
12
+ * First Introduced: 3.1.0
13
+ * Power-up Tags: Newsletter, Email
14
+ * Auto Activate: No
15
+ * Permanently Enabled: No
16
+ * Hidden: No
17
+ * cURL Required: Yes
18
+ */
19
+
20
+ //=============================================
21
+ // Define Constants
22
+ //=============================================
23
+
24
+ if ( !defined('LEADIN_GETRESPONSE_CONNECT_PATH') )
25
+ define('LEADIN_GETRESPONSE_CONNECT_PATH', LEADIN_PATH . '/power-ups/getresponse-connect');
26
+
27
+ if ( !defined('LEADIN_GETRESPONSE_CONNECT_PLUGIN_DIR') )
28
+ define('LEADIN_GETRESPONSE_CONNECT_PLUGIN_DIR', LEADIN_PLUGIN_DIR . '/power-ups/getresponse-connect');
29
+
30
+ if ( !defined('LEADIN_GETRESPONSE_CONNECT_PLUGIN_SLUG') )
31
+ define('LEADIN_GETRESPONSE_CONNECT_SLUG', basename(dirname(__FILE__)));
32
+
33
+ //=============================================
34
+ // Include Needed Files
35
+ //=============================================
36
+ require_once(LEADIN_GETRESPONSE_CONNECT_PLUGIN_DIR . '/admin/getresponse-connect-admin.php');
37
+ require_once(LEADIN_GETRESPONSE_CONNECT_PLUGIN_DIR . '/inc/LI_GetResponseAPI.php');
38
+
39
+ //=============================================
40
+ // WPLeadIn Class
41
+ //=============================================
42
+ class LIGetResponseConnect extends WPLeadIn {
43
+
44
+ var $admin;
45
+ var $options;
46
+ var $power_option_name = 'leadin_getresponse_connect_options';
47
+
48
+ /**
49
+ * Class constructor
50
+ */
51
+ function __construct ( $activated )
52
+ {
53
+ //=============================================
54
+ // Hooks & Filters
55
+ //=============================================
56
+
57
+ if ( ! $activated )
58
+ return false;
59
+
60
+ global $leadin_getresponse_connect_wp;
61
+ $leadin_getresponse_connect_wp = $this;
62
+ $this->options = get_option($this->power_option_name);
63
+ }
64
+
65
+ public function admin_init ( )
66
+ {
67
+ $admin_class = get_class($this) . 'Admin';
68
+ $this->admin = new $admin_class($this->icon_small);
69
+ }
70
+
71
+ function power_up_setup_callback ( )
72
+ {
73
+ $this->admin->power_up_setup_callback();
74
+ }
75
+
76
+ /**
77
+ * Activate the power-up and add the defaults
78
+ */
79
+ function add_defaults ()
80
+ {
81
+
82
+ }
83
+
84
+ /**
85
+ * Adds a subcsriber to a specific list
86
+ *
87
+ * @param string
88
+ * @param string
89
+ * @param string
90
+ * @param string
91
+ * @param string
92
+ * @return int/bool
93
+ */
94
+ function push_contact_to_list ( $list_id = '', $email = '', $first_name = '', $last_name = '', $phone = '' )
95
+ {
96
+ if ( isset($this->options['li_gr_api_key']) && $this->options['li_gr_api_key'] && $list_id )
97
+ {
98
+ $gr = new LI_GetResponse($this->options['li_gr_api_key']);
99
+ $contact_synced = $gr->addContact($list_id, $first_name . ' ' . $last_name, $email);
100
+
101
+ leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'getresponse'));
102
+
103
+ return TRUE;
104
+ }
105
+
106
+ return FALSE;
107
+ }
108
+
109
+ /**
110
+ * Adds a subcsriber to a specific list
111
+ *
112
+ * @param string
113
+ * @param array
114
+ * @return int/bool API status code OR false if api key not set
115
+ */
116
+ function bulk_push_contact_to_list ( $list_id = '', $contacts = '' )
117
+ {
118
+ /*
119
+ The majority of our user base doesn't use Get Response, so we decided not to retroactively sync contacts to the list.
120
+ If people complain, we will respond with a support ticket and ask them to export/import manually.
121
+ */
122
+
123
+ return FALSE;
124
+ }
125
+ }
126
+
127
+ //=============================================
128
+ // ESP Connect Init
129
+ //=============================================
130
+
131
+ global $leadin_getresponse_connect_wp;
132
+
133
+ ?>
power-ups/getresponse-connect/admin/getresponse-connect-admin.php ADDED
@@ -0,0 +1,206 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //=============================================
3
+ // LIGetResponseConnectAdmin Class
4
+ //=============================================
5
+ class LIGetResponseConnectAdmin extends WPLeadInAdmin {
6
+
7
+ var $power_up_settings_section = 'leadin_getresponse_connect_options_section';
8
+ var $power_option_name = 'leadin_getresponse_connect_options';
9
+ var $power_up_icon;
10
+ var $options;
11
+ var $authed = FALSE;
12
+ var $invalid_key = FALSE;
13
+
14
+ /**
15
+ * Class constructor
16
+ */
17
+ function __construct ( $power_up_icon_small )
18
+ {
19
+ //=============================================
20
+ // Hooks & Filters
21
+ //=============================================
22
+
23
+ if ( is_admin() )
24
+ {
25
+ $this->power_up_icon = $power_up_icon_small;
26
+ add_action('admin_init', array($this, 'leadin_build_esp_settings_page'));
27
+ $this->options = get_option($this->power_option_name);
28
+ $this->authed = ( isset($this->options['li_gr_api_key']) && $this->options['li_gr_api_key'] ? TRUE : FALSE );
29
+
30
+ if ( $this->authed )
31
+ $this->invalid_key = $this->li_check_invalid_api_key($this->options['li_gr_api_key']);
32
+ }
33
+ }
34
+
35
+ //=============================================
36
+ // Settings Page
37
+ //=============================================
38
+
39
+ /**
40
+ * Creates settings options
41
+ */
42
+ function leadin_build_esp_settings_page ()
43
+ {
44
+ register_setting('leadin_settings_options', $this->power_option_name, array($this, 'sanitize'));
45
+ add_settings_section($this->power_up_settings_section, $this->power_up_icon . "GetResponse", '', LEADIN_ADMIN_PATH);
46
+ add_settings_field('li_gr_api_key', 'API key', array($this, 'li_gr_api_key_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
47
+
48
+ if ( isset($this->options['li_gr_api_key']) )
49
+ {
50
+ if ( $this->options['li_gr_api_key'] )
51
+ add_settings_field('li_print_synced_lists', 'Synced tags', array($this, 'li_print_synced_lists'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Sanitize each setting field as needed
57
+ *
58
+ * @param array $input Contains all settings fields as array keys
59
+ */
60
+ public function sanitize ( $input )
61
+ {
62
+ $new_input = array();
63
+
64
+ if ( isset( $input['li_gr_api_key'] ) )
65
+ $new_input['li_gr_api_key'] = sanitize_text_field( $input['li_gr_api_key'] );
66
+
67
+ return $new_input;
68
+ }
69
+
70
+ /**
71
+ * Prints API key input for settings page
72
+ */
73
+ function li_gr_api_key_callback ()
74
+ {
75
+ $li_gr_api_key = ( $this->options['li_gr_api_key'] ? $this->options['li_gr_api_key'] : '' ); // Get header from options, or show default
76
+
77
+ printf(
78
+ '<input id="li_gr_api_key" type="text" id="title" name="' . $this->power_option_name . '[li_gr_api_key]" value="%s" size="50"/>',
79
+ $li_gr_api_key
80
+ );
81
+
82
+ if ( ! isset($li_gr_api_key) || ! $li_gr_api_key )
83
+ echo '<p><a target="_blank" href="http://support.getresponse.com/faq/where-i-find-api-key">Get your API key</a> from <a href="https://app.getresponse.com/account.html#api" target="_blank">GetResponse.com</a></p>';
84
+ }
85
+
86
+ /**
87
+ * Prints synced lists out for settings page in format Tag Name → ESP list
88
+ */
89
+ function li_print_synced_lists ()
90
+ {
91
+ $li_gr_api_key = ( $this->options['li_gr_api_key'] ? $this->options['li_gr_api_key'] : '' ); // Get header from options, or show default
92
+
93
+ if ( isset($li_gr_api_key ) )
94
+ {
95
+ $synced_lists = $this->li_get_synced_list_for_esp('getresponse');
96
+ $list_value_pairs = array();
97
+ $synced_list_count = 0;
98
+
99
+ echo '<table>';
100
+ foreach ( $synced_lists as $synced_list )
101
+ {
102
+ foreach ( stripslashes_deep(unserialize($synced_list->tag_synced_lists)) as $tag_synced_list )
103
+ {
104
+ if ( $tag_synced_list['esp'] == 'getresponse' )
105
+ {
106
+ echo '<tr class="synced-list-row">';
107
+ echo '<td class="synced-list-cell"><span class="icon-tag"></span> ' . $synced_list->tag_text . '</td>';
108
+ echo '<td class="synced-list-cell"><span class="synced-list-arrow">&#8594;</span></td>';
109
+ echo '<td class="synced-list-cell"><span class="icon-envelope"></span> ' . $tag_synced_list['list_name'] . '</td>';
110
+ echo '<td class="synced-list-edit"><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags&action=edit_tag&tag=' . $synced_list->tag_id . '">edit tag</a></td>';
111
+ echo '</tr>';
112
+
113
+ $synced_list_count++;
114
+ }
115
+ }
116
+ }
117
+ echo '</table>';
118
+
119
+ if ( ! $synced_list_count ) {
120
+ echo '<p>GetResponse connected succesfully! <a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">Select a tag to send contacts to GetResponse</a>.</p>';
121
+ } else {
122
+ echo '<p><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags">Edit your tags</a> or <a href="https://app.getresponse.com/create_campaign.html" target="_blank">Create a new list on GetResponse.com</a></p>';
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Get synced list for the ESP from the WordPress database
129
+ *
130
+ * @return array/object
131
+ */
132
+ function li_get_synced_list_for_esp ( $esp_name, $output_type = 'OBJECT' )
133
+ {
134
+ global $wpdb;
135
+
136
+ $q = $wpdb->prepare("SELECT * FROM $wpdb->li_tags WHERE tag_synced_lists LIKE '%%%s%%' AND tag_deleted = 0", $esp_name);
137
+ $synced_lists = $wpdb->get_results($q, $output_type);
138
+
139
+ return $synced_lists;
140
+ }
141
+
142
+ /**
143
+ * Format API-returned lists into parseable format on front end
144
+ *
145
+ * @return array
146
+ */
147
+ function li_get_lists ( )
148
+ {
149
+ $lists = $this->li_get_api_lists($this->options['li_gr_api_key']);
150
+
151
+ $sanitized_lists = array();
152
+ if ( count($lists) )
153
+ {
154
+ foreach ( $lists as $list_id => $list )
155
+ {
156
+ $list_obj = (Object)NULL;
157
+ $list_obj->id = $list_id;
158
+ $list_obj->name = $list->name;
159
+
160
+ array_push($sanitized_lists, $list_obj);;
161
+ }
162
+ }
163
+
164
+ return $sanitized_lists;
165
+ }
166
+
167
+ /**
168
+ * Get lists from GetResponse account
169
+ *
170
+ * @param string
171
+ * @return array
172
+ */
173
+ function li_get_api_lists ( $api_key )
174
+ {
175
+ $gr = new LI_GetResponse($api_key);
176
+ $campaigns = $gr->getCampaigns();
177
+
178
+ return $campaigns;
179
+ }
180
+
181
+ /**
182
+ * Use MailChimp API key to try to grab corresponding user profile to check validity of key
183
+ *
184
+ * @param string
185
+ * @return bool
186
+ */
187
+ function li_check_invalid_api_key ( $api_key )
188
+ {
189
+ $gr = new LI_GetResponse($api_key);
190
+ $ping = $gr->ping();
191
+
192
+ if ( ! empty($ping) )
193
+ $invalid_key = FALSE;
194
+ else
195
+ {
196
+ unset($this->options['li_gr_api_key']);
197
+ update_option($this->power_option_name, $this->options);
198
+
199
+ $invalid_key = TRUE;
200
+ }
201
+
202
+ return $invalid_key;
203
+ }
204
+ }
205
+
206
+ ?>
power-ups/getresponse-connect/inc/LI_GetResponseAPI.php ADDED
@@ -0,0 +1,558 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * GetResponsePHP is a PHP5 implementation of the GetResponse API
5
+ * @internal This wrapper is incomplete and subject to change.
6
+ * @authors Ben Tadiar <ben@bentadiar.co.uk>, Robert Staddon <robert@abundantdesigns.com>
7
+ * @copyright Copyright (c) 2010 Assembly Studios
8
+ * @link http://www.assemblystudios.co.uk
9
+ * @package GetResponsePHP
10
+ * @version 0.1.1
11
+ */
12
+
13
+ /**
14
+ * GetResponse Class
15
+ * @package GetResponsePHP
16
+ */
17
+ class LI_GetResponse
18
+ {
19
+ /**
20
+ * GetResponse API key
21
+ * http://www.getresponse.com/my_api_key.html
22
+ * @var string
23
+ */
24
+ public $apiKey = 'PASS_API_KEY_WHEN_INSTANTIATING_CLASS';
25
+
26
+ /**
27
+ * GetResponse API URL
28
+ * @var string
29
+ * @access private
30
+ */
31
+ private $apiURL = 'http://api2.getresponse.com';
32
+
33
+ /**
34
+ * Text comparison operators used to filter results
35
+ * @var array
36
+ * @access private
37
+ */
38
+ private $textOperators = array('EQUALS', 'NOT_EQUALS', 'CONTAINS', 'NOT_CONTAINS', 'MATCHES');
39
+
40
+ /**
41
+ * Check cURL extension is loaded and that an API key has been passed
42
+ * @param string $apiKey GetResponse API key
43
+ * @return void
44
+ */
45
+ public function __construct($apiKey = null)
46
+ {
47
+ if(!extension_loaded('curl')) trigger_error('GetResponsePHP requires PHP cURL', E_USER_ERROR);
48
+ if(is_null($apiKey)) trigger_error('API key must be supplied', E_USER_ERROR);
49
+ $this->apiKey = $apiKey;
50
+ }
51
+
52
+ /**
53
+ * Test connection to the API, returns "pong" on success
54
+ * @return string
55
+ */
56
+ public function ping()
57
+ {
58
+ $request = $this->prepRequest('ping');
59
+ $response = $this->execute($request);
60
+ return $response->ping;
61
+ }
62
+
63
+ /**
64
+ * Get basic user account information
65
+ * @return object
66
+ */
67
+ public function getAccountInfo()
68
+ {
69
+ $request = $this->prepRequest('get_account_info');
70
+ $response = $this->execute($request);
71
+ return $response;
72
+ }
73
+
74
+ /**
75
+ * Get list of email addresses assigned to account
76
+ * @return object
77
+ */
78
+ public function getAccountFromFields()
79
+ {
80
+ $request = $this->prepRequest('get_account_from_fields');
81
+ $response = $this->execute($request);
82
+ return $response;
83
+ }
84
+
85
+ /**
86
+ * Get single email address assigned to an account using the account From Field ID
87
+ * @param string $id
88
+ * @return object
89
+ */
90
+ public function getAccountFromFieldByID($id)
91
+ {
92
+ $request = $this->prepRequest('get_account_from_field', array('account_from_field' => $id));
93
+ $response = $this->execute($request);
94
+ return $response;
95
+ }
96
+
97
+ /**
98
+ * Get single email address assigned to an account using an email address
99
+ * @param string $email
100
+ * @return object
101
+ */
102
+ public function getAccountFromFieldsByEmail($email)
103
+ {
104
+ $request = $this->prepRequest('get_account_from_fields');
105
+ $response = $this->execute($request);
106
+ foreach($response as $key => $account) if($account->email!=$email) unset($response->$key);
107
+ return $response;
108
+ }
109
+
110
+ /**
111
+ * Get a list of active campaigns, optionally filtered
112
+ * @param string $operator Comparison operator
113
+ * @param string $comparison Text/expression to compare against
114
+ * @return object
115
+ */
116
+ public function getCampaigns($operator = 'CONTAINS', $comparison = '%')
117
+ {
118
+ $params = null;
119
+ if(in_array($operator, $this->textOperators)) $params = array('name' => array($operator => $comparison));
120
+ $request = $this->prepRequest('get_campaigns', $params);
121
+ $response = $this->execute($request);
122
+ return $response;
123
+ }
124
+
125
+ /**
126
+ * Return a campaign by ID
127
+ * @param string $id Campaign ID
128
+ * @return object
129
+ */
130
+ public function getCampaignByID($id)
131
+ {
132
+ $request = $this->prepRequest('get_campaign', array('campaign' => $id));
133
+ $response = $this->execute($request);
134
+ return $response;
135
+ }
136
+
137
+ /**
138
+ * Return a campaign ID by name
139
+ * @param string $name Campaign Name
140
+ * @return string Campaign ID
141
+ */
142
+ public function getCampaignByName($name)
143
+ {
144
+ $request = $this->prepRequest('get_campaigns', array('name' => array('EQUALS' => $name)));
145
+ $response = $this->execute($request);
146
+ return key($response);
147
+ }
148
+
149
+ /**
150
+ * Return a list of messages, optionally filtered by multiple conditions
151
+ * @todo Implement all conditions, this is unfinished
152
+ * @param array|null $campaigns Optional argument to narrow results by campaign ID
153
+ * @param string|null $type Optional argument to narrow results by "newsletter", "autoresponder", or "draft"
154
+ * @param string $operator
155
+ * @param string $comparison
156
+ * @return object
157
+ */
158
+ public function getMessages($campaigns = null, $type = null, $operator = 'CONTAINS', $comparison = '%')
159
+ {
160
+ $params = null;
161
+ if(is_array($campaigns)) $params['campaigns'] = $campaigns;
162
+ if(is_string($type)) $params['type'] = $type;
163
+ $request = $this->prepRequest('get_messages', $params);
164
+ $response = $this->execute($request);
165
+ return $response;
166
+ }
167
+
168
+ /**
169
+ * Return a message by ID
170
+ * @param string $id Message ID
171
+ * @return object
172
+ */
173
+ public function getMessageByID($id)
174
+ {
175
+ $request = $this->prepRequest('get_message', array('message' => $id));
176
+ $response = $this->execute($request);
177
+ return $response;
178
+ }
179
+
180
+ /**
181
+ * Return an autoresponder message from a campaign by Cycle Day
182
+ * @param string $campaign Campaign ID
183
+ * @param string $cycle_day Cycle Day
184
+ * @return object
185
+ */
186
+ public function getMessageByCycleDay($campaign, $cycle_day)
187
+ {
188
+ $params['campaigns'] = array($campaign);
189
+ $params['type'] = "autoresponder";
190
+ $request = $this->prepRequest('get_messages', $params);
191
+ $response = $this->execute($request);
192
+ foreach($response as $key => $message) if($message->day_of_cycle!=$cycle_day) unset($response->$key);
193
+ return $response;
194
+ }
195
+
196
+ /**
197
+ * Return message contents by ID
198
+ * @param string $id Message ID
199
+ * @return object
200
+ */
201
+ public function getMessageContents($id)
202
+ {
203
+ $request = $this->prepRequest('get_message_contents', array('message' => $id));
204
+ $response = $this->execute($request);
205
+ return $response;
206
+ }
207
+
208
+ /**
209
+ * Return autoresponder message contents by Cycle Day
210
+ * @param string $campaign Campaign ID
211
+ * @param string $cycle_day Cycle Day
212
+ * @return object|null
213
+ */
214
+ public function getMessageContentsByCycleDay($campaign, $cycle_day)
215
+ {
216
+ $params['campaigns'] = array($campaign);
217
+ $params['type'] = "autoresponder";
218
+ $request = $this->prepRequest('get_messages', $params);
219
+ $response = $this->execute($request);
220
+ foreach($response as $key => $message) if($message->day_of_cycle==$cycle_day) return $this->getMessageContents($key);
221
+ return null;
222
+ }
223
+
224
+ /**
225
+ * Add autoresponder to a campaign at a specific day of cycle
226
+ * @param string $campaign Campaign ID
227
+ * @param string $subject Subject of message
228
+ * @param array $contents Allowed keys are "plain" and "html", at least one is mandatory
229
+ * @param int $cycle_day
230
+ * @param string $from_field From Field ID obtained through getAccountFromFields()
231
+ * @param array $flags Enables extra functionality for a message: "clicktrack", "subscription_reminder", "openrate", "google_analytics"
232
+ * @return object
233
+ */
234
+ public function addAutoresponder($campaign, $subject, $cycle_day, $html = null, $plain = null, $from_field = null, $flags = null)
235
+ {
236
+ $params = array('campaign' => $campaign, 'subject' => $subject, 'day_of_cycle' => $cycle_day);
237
+ if(is_string($html)) $params['contents']['html'] = $html;
238
+ if(is_string($plain)) $params['contents']['plain'] = $plain;
239
+ if(is_string($from_field)) $params['from_field'] = $from_field;
240
+ if(is_array($flags)) $params['flags'] = $flags;
241
+ $request = $this->prepRequest('add_autoresponder', $params);
242
+ $response = $this->execute($request);
243
+ return $response;
244
+ }
245
+
246
+ /**
247
+ * Delete an autoresponder
248
+ * @param string $id
249
+ * @return object
250
+ */
251
+ public function deleteAutoresponder($id)
252
+ {
253
+ $request = $this->prepRequest('delete_autoresponder', array('message' => $id));
254
+ $response = $this->execute($request);
255
+ return $response;
256
+ }
257
+
258
+ /**
259
+ * Return a list of contacts, optionally filtered by multiple conditions
260
+ * @todo Implement all conditions, this is unfinished
261
+ * @param array|null $campaigns Optional argument to narrow results by campaign ID
262
+ * @param string $operator Optional argument to change operator (default is 'CONTAINS')
263
+ * See https://github.com/GetResponse/DevZone/tree/master/API#operators for additional operator options
264
+ * @param string $comparison
265
+ * @param array $fields (an associative array, the keys of which should enable/disable comparing name or email)
266
+ * @return object
267
+ */
268
+ public function getContacts($campaigns = null, $operator = 'CONTAINS', $comparison = '%', $fields = array('name' => true, 'email' => false))
269
+ {
270
+ $params = null;
271
+ if(is_array($campaigns)) $params['campaigns'] = $campaigns;
272
+ if($fields['name']) $params['name'] = $this->prepTextOp($operator, $comparison);
273
+ if($fields['email']) $params['email'] = $this->prepTextOp($operator, $comparison);
274
+ $request = $this->prepRequest('get_contacts', $params);
275
+ $response = $this->execute($request);
276
+ return $response;
277
+ }
278
+
279
+ /**
280
+ * Return a list of contacts by email address (optionally narrowed by campaign)
281
+ * @param string $email Email Address of Contact (or a string contained in the email address)
282
+ * @param array|null $campaigns Optional argument to narrow results by campaign ID
283
+ * @param string $operator Optional argument to change operator (default is 'CONTAINS')
284
+ * See https://github.com/GetResponse/DevZone/tree/master/API#operators for additional operator options
285
+ * @return object
286
+ */
287
+ public function getContactsByEmail($email, $campaigns = null, $operator = 'CONTAINS')
288
+ {
289
+ $params = null;
290
+ $params['email'] = $this->prepTextOp($operator, $email);
291
+ if(is_array($campaigns)) $params['campaigns'] = $campaigns;
292
+ $request = $this->prepRequest('get_contacts', $params);
293
+ $response = $this->execute($request);
294
+ return $response;
295
+ }
296
+
297
+ /**
298
+ * Return a list of contacts filtered by custom contact information
299
+ * $customs is an associative arrays, the keys of which should correspond to the
300
+ * custom field names of the customers you wish to retrieve.
301
+ * @param array|null $campaigns Optional argument to narrow results by campaign ID
302
+ * @param string $operator
303
+ * @param array $customs
304
+ * @param string $comparison
305
+ * @return object
306
+ */
307
+ public function getContactsByCustoms($campaigns = null, $customs, $operator = 'EQUALS')
308
+ {
309
+ $params = null;
310
+ if(is_array($campaigns)) $params['campaigns'] = $campaigns;
311
+ if(!is_array($customs)) trigger_error('Second argument must be an array', E_USER_ERROR);
312
+ foreach($customs as $key => $val) $params['customs'][] = array('name' => $key, 'content' => $this->prepTextOp($operator, $val));
313
+ $request = $this->prepRequest('get_contacts', $params);
314
+ $response = $this->execute($request);
315
+ return $response;
316
+ }
317
+
318
+ /**
319
+ * Return a contact by ID
320
+ * @param string $id User ID
321
+ * @return object
322
+ */
323
+ public function getContactByID($id)
324
+ {
325
+ $request = $this->prepRequest('get_contact', array('contact' => $id));
326
+ $response = $this->execute($request);
327
+ return $response;
328
+ }
329
+
330
+
331
+ /**
332
+ * Set a contact name
333
+ * @param string $id User ID
334
+ * @return object
335
+ */
336
+ public function setContactName($id, $name)
337
+ {
338
+ $request = $this->prepRequest('set_contact_name', array('contact' => $id, 'name' => $name));
339
+ $response = $this->execute($request);
340
+ return $response;
341
+ }
342
+
343
+ /**
344
+ * Set a contact cycle
345
+ * @param string $id User ID
346
+ * @param int $cycle_day Cycle Day
347
+ * @return object
348
+ */
349
+ public function setContactCycle($id, $cycle_day)
350
+ {
351
+ $request = $this->prepRequest('set_contact_cycle', array('contact' => $id, 'cycle_day' => $cycle_day));
352
+ $response = $this->execute($request);
353
+ return $response;
354
+ }
355
+
356
+ /**
357
+ * Set a contact campaign
358
+ * @param string $id User ID
359
+ * @param string $campaign Campaign ID
360
+ * @return object
361
+ */
362
+ public function setContactCampaign($id, $campaign)
363
+ {
364
+ $request = $this->prepRequest('move_contact', array('contact' => $id, 'campaign' => $campaign));
365
+ $response = $this->execute($request);
366
+ return $response;
367
+ }
368
+
369
+ /**
370
+ * Return a contacts custom information
371
+ * @param string $id User ID
372
+ * @return object
373
+ */
374
+ public function getContactCustoms($id)
375
+ {
376
+ $request = $this->prepRequest('get_contact_customs', array('contact' => $id));
377
+ $response = $this->execute($request);
378
+ return $response;
379
+ }
380
+
381
+
382
+ /**
383
+ * Set custom contact information
384
+ * $customs is an associative array, the keys of which should correspond to the
385
+ * custom field name you wish to add/modify/remove.
386
+ * Actions: added if not present, updated if present, removed if value is null
387
+ * @todo Implement multivalue customs.
388
+ * @param string $id User ID
389
+ * @param array $customs
390
+ * @return object
391
+ */
392
+ public function setContactCustoms($id, $customs)
393
+ {
394
+ if(!is_array($customs)) trigger_error('Second argument must be an array', E_USER_ERROR);
395
+ foreach($customs as $key => $val) $params[] = array('name' => $key, 'content' => $val);
396
+ $request = $this->prepRequest('set_contact_customs', array('contact' => $id, 'customs' => $params));
397
+ $response = $this->execute($request);
398
+ return $response;
399
+ }
400
+
401
+ /**
402
+ * Return a contacts GeoIP
403
+ * @param string $id User ID
404
+ * @return object
405
+ */
406
+ public function getContactGeoIP($id)
407
+ {
408
+ $request = $this->prepRequest('get_contact_geoip', array('contact' => $id));
409
+ $response = $this->execute($request);
410
+ return $response;
411
+ }
412
+
413
+ /**
414
+ * List dates when the messages were opened by contacts
415
+ * @param string $id User ID
416
+ * @return object
417
+ */
418
+ public function getContactOpens($id)
419
+ {
420
+ $request = $this->prepRequest('get_contact_opens', array('contact' => $id));
421
+ $response = $this->execute($request);
422
+ return $response;
423
+ }
424
+
425
+ /**
426
+ * List dates when the links in messages were clicked by contacts
427
+ * @param string $id User ID
428
+ * @return object
429
+ */
430
+ public function getContactClicks($id)
431
+ {
432
+ $request = $this->prepRequest('get_contact_clicks', array('contact' => $id));
433
+ $response = $this->execute($request);
434
+ return $response;
435
+ }
436
+
437
+ /**
438
+ * Add contact to the specified list (Requires email verification by contact)
439
+ * The return value of this function will be "queued", and on subsequent
440
+ * submission of the same email address will be "duplicated".
441
+ * @param string $campaign Campaign ID
442
+ * @param string $name Name of contact
443
+ * @param string $email Email address of contact
444
+ * @return object
445
+ */
446
+ public function addContact($campaign, $name, $email)
447
+ {
448
+ $params = array (
449
+ 'campaign' => $campaign,
450
+ 'email' => $email,
451
+ 'name' => $name
452
+ );
453
+
454
+ $request = $this->prepRequest('add_contact', $params);
455
+ $response = $this->execute($request);
456
+ return $response;
457
+ }
458
+
459
+ /**
460
+ * Delete a contact
461
+ * @param string $id
462
+ * @return object
463
+ */
464
+ public function deleteContact($id)
465
+ {
466
+ $request = $this->prepRequest('delete_contact', array('contact' => $id));
467
+ $response = $this->execute($request);
468
+ return $response;
469
+ }
470
+
471
+ /**
472
+ * Get blacklist masks on account level
473
+ * Account is determined by API key
474
+ * @return object
475
+ */
476
+ public function getAccountBlacklist()
477
+ {
478
+ $request = $this->prepRequest('get_account_blacklist');
479
+ $response = $this->execute($request);
480
+ return $response;
481
+ }
482
+
483
+ /**
484
+ * Adds blacklist mask on account level
485
+ * @param string $mask
486
+ * @return object
487
+ */
488
+ public function addAccountBlacklist($mask)
489
+ {
490
+ $request = $this->prepRequest('add_account_blacklist', array('mask' => $mask));
491
+ $response = $this->execute($request);
492
+ return $response;
493
+ }
494
+
495
+ /**
496
+ * Delete blacklist mask on account level
497
+ * @param string $mask
498
+ * @return object
499
+ */
500
+ public function deleteAccountBlacklist($mask)
501
+ {
502
+ $request = $this->prepRequest('delete_account_blacklist', array('mask' => $mask));
503
+ $response = $this->execute($request);
504
+ return $response;
505
+ }
506
+
507
+ /**
508
+ * Return a key => value array for text comparison
509
+ * @param string $operator
510
+ * @param mixed $comparison
511
+ * @return array
512
+ * @access private
513
+ */
514
+ private function prepTextOp($operator, $comparison)
515
+ {
516
+ if(!in_array($operator, $this->textOperators)) trigger_error('Invalid text operator', E_USER_ERROR);
517
+ if($operator === 'CONTAINS') $comparison = '%'.$comparison.'%';
518
+ return array($operator => $comparison);
519
+ }
520
+
521
+ /**
522
+ * Return array as a JSON encoded string
523
+ * @param string $method API method to call
524
+ * @param array $params Array of parameters
525
+ * @return string JSON encoded string
526
+ * @access private
527
+ */
528
+ private function prepRequest($method, $params = null, $id = null)
529
+ {
530
+ $array = array($this->apiKey);
531
+ if(!is_null($params)) $array[1] = $params;
532
+ $request = json_encode(array('method' => $method, 'params' => $array, 'id' => $id));
533
+ return $request;
534
+ }
535
+
536
+ /**
537
+ * Executes an API call
538
+ * @param string $request JSON encoded array
539
+ * @return object
540
+ * @access private
541
+ */
542
+ private function execute($request)
543
+ {
544
+ $handle = curl_init($this->apiURL);
545
+ curl_setopt($handle, CURLOPT_POST, 1);
546
+ curl_setopt($handle, CURLOPT_POSTFIELDS, $request);
547
+ curl_setopt($handle, CURLOPT_HEADER, 'Content-type: application/json');
548
+ curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
549
+ $response = json_decode(curl_exec($handle));
550
+ if(curl_error($handle)) trigger_error(curl_error($handle), E_USER_ERROR);
551
+ $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
552
+ if(!(($httpCode == '200') || ($httpCode == '204'))) trigger_error('API call failed. Server returned status code '.$httpCode, E_USER_ERROR);
553
+ curl_close($handle);
554
+ if(!$response->error) return $response->result;
555
+ }
556
+ }
557
+
558
+ ?>
power-ups/lookups.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Power-up Name: Contact Lookups
4
+ * Power-up Class: WPLeadInLookups
5
+ * Power-up Menu Text:
6
+ * Power-up Menu Link: settings
7
+ * Power-up Slug: lookups
8
+ * Power-up URI: http://leadin.com/wordpress-lead-prospecting-plugin/
9
+ * Power-up Description: See social profiles and company information for every contact.
10
+ * Power-up Icon: powerup-icon-lookups
11
+ * Power-up Icon Small:
12
+ * First Introduced: 2.3.0
13
+ * Power-up Tags: Lookups
14
+ * Auto Activate: No
15
+ * Permanently Enabled: Yes
16
+ * Hidden: No
17
+ * cURL Required: Yes
18
+ * Pro Only: Yes
19
+ */
20
+
21
+ //=============================================
22
+ // Define Constants
23
+ //=============================================
24
+
25
+ if ( !defined('LEADIN_LOOKUPS_PATH') )
26
+ define('LEADIN_LOOKUPS_PATH', LEADIN_PATH . '/power-ups/lookups');
27
+
28
+ if ( !defined('LEADIN_LOOKUPS_PLUGIN_DIR') )
29
+ define('LEADIN_LOOKUPS_PLUGIN_DIR', LEADIN_PLUGIN_DIR . '/power-ups/lookups');
30
+
31
+ if ( !defined('LEADIN_LOOKUPS_PLUGIN_SLUG') )
32
+ define('LEADIN_LOOKUPS_PLUGIN_SLUG', basename(dirname(__FILE__)));
33
+
34
+ //=============================================
35
+ // Include Needed Files
36
+ //=============================================
37
+
38
+ require_once(LEADIN_LOOKUPS_PLUGIN_DIR . '/admin/lookups-admin.php');
39
+
40
+ //=============================================
41
+ // WPLeadInLookups Class
42
+ //=============================================
43
+ class WPLeadInLookups extends WPLeadIn {
44
+
45
+ var $admin;
46
+ var $options;
47
+
48
+ /**
49
+ * Class constructor
50
+ */
51
+ function __construct ( $activated )
52
+ {
53
+ //=============================================
54
+ // Hooks & Filters
55
+ //=============================================
56
+
57
+ if ( ! $activated )
58
+ return false;
59
+
60
+ global $leadin_lookups;
61
+ $leadin_lookups = $this;
62
+ }
63
+
64
+ public function admin_init ( )
65
+ {
66
+ $admin_class = get_class($this) . 'Admin';
67
+ $this->admin = new $admin_class($this->icon_small);
68
+ }
69
+
70
+ function power_up_setup_callback ( )
71
+ {
72
+ $this->admin->power_up_setup_callback();
73
+ }
74
+ }
75
+
76
+ global $leadin_lookups;
77
+
78
+ ?>
power-ups/lookups/admin/inc/blacklist_domains.php ADDED
@@ -0,0 +1,3025 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ global $blacklist_freemail_domains;
4
+ global $blacklist_nonmail_domains;
5
+
6
+ $blacklist_nonmail_domains = array(
7
+ 'calendar-server.bounces.google.com', 'postmaster.twitter.com',
8
+ 'exg6.exghost.com', 'reply.ticketmaster.com', 'plus.google.com', 'bounces.amazon.com', 'facebookmail.com', 'mlb.bounce.ed10.net',
9
+ 'emailer.hubspot.com', 'playstation.sony.com', 'amazonses.com', 'docs.google.com', 'resource.calendar.google.com',
10
+ 'emails.incisivemedia.com', 'doclist.bounces.google.com', 'googlegroups.com', 'message.myspace.com', 'joelonsoftware.com'
11
+ );
12
+
13
+ $blacklist_freemail_domains = array('123.com',
14
+ '123box.net',
15
+ '123india.com',
16
+ '123mail.cl',
17
+ '123qwe.co.uk',
18
+ '150ml.com',
19
+ '15meg4free.com',
20
+ '163.com',
21
+ '1coolplace.com',
22
+ '1freeemail.com',
23
+ '1funplace.com',
24
+ '1internetdrive.com',
25
+ '1mail.net',
26
+ '1me.net',
27
+ '1mum.com',
28
+ '1musicrow.com',
29
+ '1netdrive.com',
30
+ '1nsyncfan.com',
31
+ '1under.com',
32
+ '1webave.com',
33
+ '1webhighway.com',
34
+ '212.com',
35
+ '24horas.com',
36
+ '2911.net',
37
+ '2d2i.com',
38
+ '2die4.com',
39
+ '3000.it',
40
+ '37.com',
41
+ '3ammagazine.com',
42
+ '3email.com',
43
+ '3xl.net',
44
+ '444.net',
45
+ '4email.com',
46
+ '4email.net',
47
+ '4mg.com',
48
+ '4newyork.com',
49
+ '4x4man.com',
50
+ '5iron.com',
51
+ '88.am',
52
+ '8848.net',
53
+ 'aaronkwok.net',
54
+ 'abbeyroadlondon.co.uk',
55
+ 'abdulnour.com',
56
+ 'aberystwyth.com',
57
+ 'about.com',
58
+ 'academycougars.com',
59
+ 'acceso.or.cr',
60
+ 'access4less.net',
61
+ 'accessgcc.com',
62
+ 'ace-of-base.com',
63
+ 'acmemail.net',
64
+ 'acninc.net',
65
+ 'adexec.com',
66
+ 'adios.net',
67
+ 'ados.fr',
68
+ 'advalvas.be',
69
+ 'aeiou.pt',
70
+ 'aemail4u.com',
71
+ 'aeneasmail.com',
72
+ 'afreeinternet.com',
73
+ 'africamail.com',
74
+ 'agoodmail.com',
75
+ 'ahaa.dk',
76
+ 'aichi.com',
77
+ 'airpost.net',
78
+ 'ajacied.com',
79
+ 'ak47.hu',
80
+ 'aknet.kg',
81
+ 'albawaba.com',
82
+ 'alex4all.com',
83
+ 'alexandria.cc',
84
+ 'algeria.com',
85
+ 'alhilal.net',
86
+ 'alibaba.com',
87
+ 'alive.cz',
88
+ 'allmail.net',
89
+ 'alloymail.com',
90
+ 'allsaintsfan.com',
91
+ 'alskens.dk',
92
+ 'altavista.com',
93
+ 'altavista.se',
94
+ 'alternativagratis.com',
95
+ 'alumnidirector.com',
96
+ 'alvilag.hu',
97
+ 'amele.com',
98
+ 'america.hm',
99
+ 'amnetsal.com',
100
+ 'amrer.net',
101
+ 'amuro.net',
102
+ 'amuromail.com',
103
+ 'ananzi.co.za',
104
+ 'andylau.net',
105
+ 'anfmail.com',
106
+ 'angelfire.com',
107
+ 'animalwoman.net',
108
+ 'anjungcafe.com',
109
+ 'another.com',
110
+ 'antisocial.com',
111
+ 'antongijsen.com',
112
+ 'antwerpen.com',
113
+ 'anymoment.com',
114
+ 'anytimenow.com',
115
+ 'aol.com',
116
+ 'apexmail.com',
117
+ 'apollo.lv',
118
+ 'approvers.net',
119
+ 'arabia.com',
120
+ 'arabtop.net',
121
+ 'archaeologist.com',
122
+ 'arcor.de',
123
+ 'arcotronics.bg',
124
+ 'argentina.com',
125
+ 'arnet.com.ar',
126
+ 'artlover.com',
127
+ 'artlover.com.au',
128
+ 'as-if.com',
129
+ 'asean-mail.com',
130
+ 'asheville.com',
131
+ 'asia-links.com',
132
+ 'asia.com',
133
+ 'asianavenue.com',
134
+ 'asiancityweb.com',
135
+ 'asianwired.net',
136
+ 'assala.com',
137
+ 'assamesemail.com',
138
+ 'astroboymail.com',
139
+ 'astrolover.com',
140
+ 'asurfer.com',
141
+ 'athenachu.net',
142
+ 'atina.cl',
143
+ 'atl.lv',
144
+ 'atlaswebmail.com',
145
+ 'atozasia.com',
146
+ 'att.net',
147
+ 'au.ru',
148
+ 'ausi.com',
149
+ 'australia.edu',
150
+ 'australiamail.com',
151
+ 'austrosearch.net',
152
+ 'autoescuelanerja.com',
153
+ 'avh.hu',
154
+ 'ayna.com',
155
+ 'azimiweb.com',
156
+ 'bachelorboy.com',
157
+ 'bachelorgal.com',
158
+ 'backstreet-boys.com',
159
+ 'backstreetboysclub.com',
160
+ 'bagherpour.com',
161
+ 'baptistmail.com',
162
+ 'baptized.com',
163
+ 'barcelona.com',
164
+ 'batuta.net',
165
+ 'baudoinconsulting.com',
166
+ 'bcvibes.com',
167
+ 'beeebank.com',
168
+ 'beenhad.com',
169
+ 'beep.ru',
170
+ 'beer.com',
171
+ 'beethoven.com',
172
+ 'belice.com',
173
+ 'belizehome.com',
174
+ 'bellsouth.net',
175
+ 'berlin.com',
176
+ 'berlin.de',
177
+ 'berlinexpo.de',
178
+ 'bestmail.us',
179
+ 'bharatmail.com',
180
+ 'bigblue.net.au',
181
+ 'bigboab.com',
182
+ 'bigfoot.com',
183
+ 'bigfoot.de',
184
+ 'bigger.com',
185
+ 'bigmailbox.com',
186
+ 'bigramp.com',
187
+ 'bikemechanics.com',
188
+ 'bikeracers.net',
189
+ 'bikerider.com',
190
+ 'bimla.net',
191
+ 'birdowner.net',
192
+ 'bitpage.net',
193
+ 'bizhosting.com',
194
+ 'blackburnmail.com',
195
+ 'blackplanet.com',
196
+ 'blazemail.com',
197
+ 'bluehyppo.com',
198
+ 'bluemail.ch',
199
+ 'bluemail.dk',
200
+ 'blushmail.com',
201
+ 'bmlsports.net',
202
+ 'boardermail.com',
203
+ 'bol.com.br',
204
+ 'bolando.com',
205
+ 'bollywoodz.com',
206
+ 'bolt.com',
207
+ 'boltonfans.com',
208
+ 'bonbon.net',
209
+ 'boom.com',
210
+ 'bootmail.com',
211
+ 'bornnaked.com',
212
+ 'bostonoffice.com',
213
+ 'bounce.net',
214
+ 'box.az',
215
+ 'boxbg.com',
216
+ 'boxemail.com',
217
+ 'boxfrog.com',
218
+ 'boyzoneclub.com',
219
+ 'bradfordfans.com',
220
+ 'brasilia.net',
221
+ 'brazilmail.com.br',
222
+ 'breathe.com',
223
+ 'brfree.com.br',
224
+ 'britneyclub.com',
225
+ 'brittonsign.com',
226
+ 'btinternet.com',
227
+ 'btopenworld.co.uk',
228
+ 'bullsfan.com',
229
+ 'bullsgame.com',
230
+ 'bumerang.ro',
231
+ 'buryfans.com',
232
+ 'business-man.com',
233
+ 'businessman.net',
234
+ 'bvimailbox.com',
235
+ 'c2i.net',
236
+ 'c3.hu',
237
+ 'c4.com',
238
+ 'cable.comcast.com',
239
+ 'caere.it',
240
+ 'cairomail.com',
241
+ 'callnetuk.com',
242
+ 'caltanet.it',
243
+ 'camidge.com',
244
+ 'canada-11.com',
245
+ 'canada.com',
246
+ 'canoemail.com',
247
+ 'canwetalk.com',
248
+ 'caramail.com',
249
+ 'care2.com',
250
+ 'carioca.net',
251
+ 'carolina.rr.com',
252
+ 'cartestraina.ro',
253
+ 'catcha.com',
254
+ 'catlover.com',
255
+ 'cd2.com',
256
+ 'celineclub.com',
257
+ 'centoper.it',
258
+ 'centralpets.com',
259
+ 'centrum.cz',
260
+ 'centrum.sk',
261
+ 'cfl.rr.com',
262
+ 'cgac.es',
263
+ 'chaiyomail.com',
264
+ 'chance2mail.com',
265
+ 'chandrasekar.net',
266
+ 'charter.net',
267
+ 'chat.ru',
268
+ 'chattown.com',
269
+ 'chauhanweb.com',
270
+ 'check1check.com',
271
+ 'cheerful.com',
272
+ 'chemist.com',
273
+ 'chequemail.com',
274
+ 'chickmail.com',
275
+ 'china.net.vg',
276
+ 'chirk.com',
277
+ 'chocaholic.com.au',
278
+ 'cia-agent.com',
279
+ 'cia.hu',
280
+ 'ciaoweb.it',
281
+ 'cicciociccio.com',
282
+ 'city-of-bath.org',
283
+ 'city-of-birmingham.com',
284
+ 'city-of-brighton.org',
285
+ 'city-of-cambridge.com',
286
+ 'city-of-coventry.com',
287
+ 'city-of-edinburgh.com',
288
+ 'city-of-lichfield.com',
289
+ 'city-of-lincoln.com',
290
+ 'city-of-liverpool.com',
291
+ 'city-of-manchester.com',
292
+ 'city-of-nottingham.com',
293
+ 'city-of-oxford.com',
294
+ 'city-of-swansea.com',
295
+ 'city-of-westminster.com',
296
+ 'city-of-westminster.net',
297
+ 'city-of-york.net',
298
+ 'cityofcardiff.net',
299
+ 'cityoflondon.org',
300
+ 'claramail.com',
301
+ 'classicmail.co.za',
302
+ 'clearwire.net',
303
+ 'clerk.com',
304
+ 'cliffhanger.com',
305
+ 'close2you.net',
306
+ 'club4x4.net',
307
+ 'clubalfa.com',
308
+ 'clubbers.net',
309
+ 'clubducati.com',
310
+ 'clubhonda.net',
311
+ 'cluemail.com',
312
+ 'coder.hu',
313
+ 'coid.biz',
314
+ 'columnist.com',
315
+ 'comcast.net',
316
+ 'comic.com',
317
+ 'compuserve.com',
318
+ 'computer-freak.com',
319
+ 'computermail.net',
320
+ 'conexcol.com',
321
+ 'connect4free.net',
322
+ 'connectbox.com',
323
+ 'consultant.com',
324
+ 'cookiemonster.com',
325
+ 'cool.br',
326
+ 'coolgoose.ca',
327
+ 'coolgoose.com',
328
+ 'coolkiwi.com',
329
+ 'coollist.com',
330
+ 'coolmail.com',
331
+ 'coolmail.net',
332
+ 'coolsend.com',
333
+ 'cooooool.com',
334
+ 'cooperation.net',
335
+ 'cooperationtogo.net',
336
+ 'copacabana.com',
337
+ 'cornerpub.com',
338
+ 'corporatedirtbag.com',
339
+ 'correo.terra.com.gt',
340
+ 'cortinet.com',
341
+ 'cotas.net',
342
+ 'counsellor.com',
343
+ 'countrylover.com',
344
+ 'cox.net',
345
+ 'cracker.hu',
346
+ 'crazedanddazed.com',
347
+ 'crazysexycool.com',
348
+ 'critterpost.com',
349
+ 'croeso.com',
350
+ 'crosswinds.net',
351
+ 'cry4helponline.com',
352
+ 'cs.com',
353
+ 'csinibaba.hu',
354
+ 'curio-city.com',
355
+ 'cute-girl.com',
356
+ 'cuteandcuddly.com',
357
+ 'cutey.com',
358
+ 'cww.de',
359
+ 'cyberbabies.com',
360
+ 'cyberforeplay.net',
361
+ 'cyberinbox.com',
362
+ 'cyberleports.com',
363
+ 'cybernet.it',
364
+ 'dabsol.net',
365
+ 'dadacasa.com',
366
+ 'dailypioneer.com',
367
+ 'dangerous-minds.com',
368
+ 'dansegulvet.com',
369
+ 'data54.com',
370
+ 'davegracey.com',
371
+ 'dazedandconfused.com',
372
+ 'dbzmail.com',
373
+ 'dcemail.com',
374
+ 'deadlymob.org',
375
+ 'deal-maker.com',
376
+ 'dearriba.com',
377
+ 'death-star.com',
378
+ 'deliveryman.com',
379
+ 'desertmail.com',
380
+ 'desilota.com',
381
+ 'deskpilot.com',
382
+ 'detik.com',
383
+ 'devotedcouples.com',
384
+ 'dfwatson.com',
385
+ 'di-ve.com',
386
+ 'diplomats.com',
387
+ 'disinfo.net',
388
+ 'dmailman.com',
389
+ 'dnsmadeeasy.com',
390
+ 'doctor.com',
391
+ 'doglover.com',
392
+ 'dogmail.co.uk',
393
+ 'dogsnob.net',
394
+ 'doityourself.com',
395
+ 'doneasy.com',
396
+ 'donjuan.com',
397
+ 'dontgotmail.com',
398
+ 'dontmesswithtexas.com',
399
+ 'doramail.com',
400
+ 'dostmail.com',
401
+ 'dotcom.fr',
402
+ 'dott.it',
403
+ 'dplanet.ch',
404
+ 'dr.com',
405
+ 'dragoncon.net',
406
+ 'dropzone.com',
407
+ 'dubaimail.com',
408
+ 'dublin.com',
409
+ 'dublin.ie',
410
+ 'dygo.com',
411
+ 'dynamitemail.com',
412
+ 'e-apollo.lv',
413
+ 'e-mail.dk',
414
+ 'e-mail.ru',
415
+ 'e-mailanywhere.com',
416
+ 'e-mails.ru',
417
+ 'e-tapaal.com',
418
+ 'earthalliance.com',
419
+ 'earthdome.com',
420
+ 'earthlink.net',
421
+ 'eastcoast.co.za',
422
+ 'eastmail.com',
423
+ 'ecbsolutions.net',
424
+ 'echina.com',
425
+ 'ednatx.com',
426
+ 'educacao.te.pt',
427
+ 'eircom.net',
428
+ 'elsitio.com',
429
+ 'elvis.com',
430
+ 'email-london.co.uk',
431
+ 'email.com',
432
+ 'email.cz',
433
+ 'email.ee',
434
+ 'email.it',
435
+ 'email.nu',
436
+ 'email.ro',
437
+ 'email.ru',
438
+ 'email.si',
439
+ 'email2me.net',
440
+ 'emailacc.com',
441
+ 'emailaccount.com',
442
+ 'emailchoice.com',
443
+ 'emailcorner.net',
444
+ 'emailengine.net',
445
+ 'emailforyou.net',
446
+ 'emailgroups.net',
447
+ 'emailpinoy.com',
448
+ 'emailplanet.com',
449
+ 'emails.ru',
450
+ 'emailuser.net',
451
+ 'emailx.net',
452
+ 'ematic.com',
453
+ 'end-war.com',
454
+ 'enel.net',
455
+ 'engineer.com',
456
+ 'england.com',
457
+ 'england.edu',
458
+ 'epatra.com',
459
+ 'epost.de',
460
+ 'eposta.hu',
461
+ 'eqqu.com',
462
+ 'eramail.co.za',
463
+ 'eresmas.com',
464
+ 'eriga.lv',
465
+ 'estranet.it',
466
+ 'etoast.com',
467
+ 'eudoramail.com',
468
+ 'europe.com',
469
+ 'euroseek.com',
470
+ 'every1.net',
471
+ 'everyday.com.kh',
472
+ 'everyone.net',
473
+ 'examnotes.net',
474
+ 'excite.co.jp',
475
+ 'excite.com',
476
+ 'excite.it',
477
+ 'execs.com',
478
+ 'expressasia.com',
479
+ 'extended.com',
480
+ 'eyou.com',
481
+ 'ezcybersearch.com',
482
+ 'ezmail.egine.com',
483
+ 'ezmail.ru',
484
+ 'ezrs.com',
485
+ 'f1fans.net',
486
+ 'fantasticmail.com',
487
+ 'faroweb.com',
488
+ 'fastem.com',
489
+ 'fastemail.us',
490
+ 'fastemailer.com',
491
+ 'fastermail.com',
492
+ 'fastimap.com',
493
+ 'fastmail.fm',
494
+ 'fastmailbox.net',
495
+ 'fastmessaging.com',
496
+ 'fatcock.net',
497
+ 'fathersrightsne.org',
498
+ 'fbi-agent.com',
499
+ 'fbi.hu',
500
+ 'federalcontractors.com',
501
+ 'femenino.com',
502
+ 'feyenoorder.com',
503
+ 'ffanet.com',
504
+ 'fiberia.com',
505
+ 'filipinolinks.com',
506
+ 'financemail.net',
507
+ 'financier.com',
508
+ 'findmail.com',
509
+ 'finebody.com',
510
+ 'fire-brigade.com',
511
+ 'fishburne.org',
512
+ 'flashmail.com',
513
+ 'flipcode.com',
514
+ 'fmail.co.uk',
515
+ 'fmailbox.com',
516
+ 'fmgirl.com',
517
+ 'fmguy.com',
518
+ 'fnbmail.co.za',
519
+ 'fnmail.com',
520
+ 'for-president.com',
521
+ 'forfree.at',
522
+ 'forpresident.com',
523
+ 'fortuncity.com',
524
+ 'forum.dk',
525
+ 'free.com.pe',
526
+ 'free.fr',
527
+ 'freeaccess.nl',
528
+ 'freeandsingle.com',
529
+ 'freedomlover.com',
530
+ 'freegates.be',
531
+ 'freeghana.com',
532
+ 'freeler.nl',
533
+ 'freemail.com.au',
534
+ 'freemail.com.pk',
535
+ 'freemail.de',
536
+ 'freemail.et',
537
+ 'freemail.gr',
538
+ 'freemail.hu',
539
+ 'freemail.it',
540
+ 'freemail.lt',
541
+ 'freemail.nl',
542
+ 'freemail.org.mk',
543
+ 'freenet.de',
544
+ 'freenet.kg',
545
+ 'freeola.com',
546
+ 'freeola.net',
547
+ 'freeserve.co.uk',
548
+ 'freestart.hu',
549
+ 'freesurf.fr',
550
+ 'freesurf.nl',
551
+ 'freeuk.com',
552
+ 'freeuk.net',
553
+ 'freeukisp.co.uk',
554
+ 'freeweb.org',
555
+ 'freewebemail.com',
556
+ 'freeyellow.com',
557
+ 'freezone.co.uk',
558
+ 'fresnomail.com',
559
+ 'friendsfan.com',
560
+ 'from-africa.com',
561
+ 'from-america.com',
562
+ 'from-argentina.com',
563
+ 'from-asia.com',
564
+ 'from-australia.com',
565
+ 'from-belgium.com',
566
+ 'from-brazil.com',
567
+ 'from-canada.com',
568
+ 'from-china.net',
569
+ 'from-england.com',
570
+ 'from-europe.com',
571
+ 'from-france.net',
572
+ 'from-germany.net',
573
+ 'from-holland.com',
574
+ 'from-israel.com',
575
+ 'from-italy.net',
576
+ 'from-japan.net',
577
+ 'from-korea.com',
578
+ 'from-mexico.com',
579
+ 'from-outerspace.com',
580
+ 'from-russia.com',
581
+ 'from-spain.net',
582
+ 'fromalabama.com',
583
+ 'fromalaska.com',
584
+ 'fromarizona.com',
585
+ 'fromarkansas.com',
586
+ 'fromcalifornia.com',
587
+ 'fromcolorado.com',
588
+ 'fromconnecticut.com',
589
+ 'fromdelaware.com',
590
+ 'fromflorida.net',
591
+ 'fromgeorgia.com',
592
+ 'fromhawaii.net',
593
+ 'fromidaho.com',
594
+ 'fromillinois.com',
595
+ 'fromindiana.com',
596
+ 'fromiowa.com',
597
+ 'fromjupiter.com',
598
+ 'fromkansas.com',
599
+ 'fromkentucky.com',
600
+ 'fromlouisiana.com',
601
+ 'frommaine.net',
602
+ 'frommaryland.com',
603
+ 'frommassachusetts.com',
604
+ 'frommiami.com',
605
+ 'frommichigan.com',
606
+ 'fromminnesota.com',
607
+ 'frommississippi.com',
608
+ 'frommissouri.com',
609
+ 'frommontana.com',
610
+ 'fromnebraska.com',
611
+ 'fromnevada.com',
612
+ 'fromnewhampshire.com',
613
+ 'fromnewjersey.com',
614
+ 'fromnewmexico.com',
615
+ 'fromnewyork.net',
616
+ 'fromnorthcarolina.com',
617
+ 'fromnorthdakota.com',
618
+ 'fromohio.com',
619
+ 'fromoklahoma.com',
620
+ 'fromoregon.net',
621
+ 'frompennsylvania.com',
622
+ 'fromrhodeisland.com',
623
+ 'fromru.com',
624
+ 'fromsouthcarolina.com',
625
+ 'fromsouthdakota.com',
626
+ 'fromtennessee.com',
627
+ 'fromtexas.com',
628
+ 'fromthestates.com',
629
+ 'fromutah.com',
630
+ 'fromvermont.com',
631
+ 'fromvirginia.com',
632
+ 'fromwashington.com',
633
+ 'fromwashingtondc.com',
634
+ 'fromwestvirginia.com',
635
+ 'fromwisconsin.com',
636
+ 'fromwyoming.com',
637
+ 'front.ru',
638
+ 'frostbyte.uk.net',
639
+ 'fsmail.net',
640
+ 'ftml.net',
641
+ 'fuorissimo.com',
642
+ 'furnitureprovider.com',
643
+ 'fut.es',
644
+ 'fxsmails.com',
645
+ 'galaxy5.com',
646
+ 'gamebox.net',
647
+ 'gardener.com',
648
+ 'gawab.com',
649
+ 'gaza.net',
650
+ 'gazeta.pl',
651
+ 'gazibooks.com',
652
+ 'geek.hu',
653
+ 'geeklife.com',
654
+ 'general-hospital.com',
655
+ 'geologist.com',
656
+ 'geopia.com',
657
+ 'giga4u.de',
658
+ 'givepeaceachance.com',
659
+ 'glay.org',
660
+ 'glendale.net',
661
+ 'globalfree.it',
662
+ 'globalpagan.com',
663
+ 'globalsite.com.br',
664
+ 'gmail.com',
665
+ 'gmail.co.za',
666
+ 'gmx.at',
667
+ 'gmx.de',
668
+ 'gmx.li',
669
+ 'gmx.net',
670
+ 'go.com',
671
+ 'go.ro',
672
+ 'go.ru',
673
+ 'go2net.com',
674
+ 'gofree.co.uk',
675
+ 'gol.com',
676
+ 'goldenmail.ru',
677
+ 'goldmail.ru',
678
+ 'golfemail.com',
679
+ 'golfmail.be',
680
+ 'googlemail.com',
681
+ 'goplay.com',
682
+ 'gorontalo.net',
683
+ 'gothere.uk.com',
684
+ 'gotmail.com',
685
+ 'gotomy.com',
686
+ 'gportal.hu',
687
+ 'graffiti.net',
688
+ 'gratisweb.com',
689
+ 'grungecafe.com',
690
+ 'gua.net',
691
+ 'guessmail.com',
692
+ 'guju.net',
693
+ 'guy.com',
694
+ 'guy2.com',
695
+ 'guyanafriends.com',
696
+ 'gyorsposta.com',
697
+ 'gyorsposta.hu',
698
+ 'hackermail.net',
699
+ 'hailmail.net',
700
+ 'hairdresser.net',
701
+ 'hamptonroads.com',
702
+ 'handbag.com',
703
+ 'hang-ten.com',
704
+ 'happemail.com',
705
+ 'happycounsel.com',
706
+ 'hardcorefreak.com',
707
+ 'heartthrob.com',
708
+ 'heerschap.com',
709
+ 'heesun.net',
710
+ 'hehe.com',
711
+ 'hello.hu',
712
+ 'helter-skelter.com',
713
+ 'herediano.com',
714
+ 'herono1.com',
715
+ 'highmilton.com',
716
+ 'highquality.com',
717
+ 'highveldmail.co.za',
718
+ 'hispavista.com',
719
+ 'hkstarphoto.com',
720
+ 'hollywoodkids.com',
721
+ 'home.no.net',
722
+ 'home.ro',
723
+ 'home.se',
724
+ 'homelocator.com',
725
+ 'homestead.com',
726
+ 'hongkong.com',
727
+ 'hookup.net',
728
+ 'horrormail.com',
729
+ 'hot-shot.com',
730
+ 'hot.ee',
731
+ 'hotbot.com',
732
+ 'hotbrev.com',
733
+ 'hotfire.net',
734
+ 'hotletter.com',
735
+ 'hotmail.co.il',
736
+ 'hotmail.com',
737
+ 'hotmail.ca',
738
+ 'hotmail.com.br',
739
+ 'hotmail.fr',
740
+ 'hotmail.kg',
741
+ 'hotmail.co.uk',
742
+ 'hotmail.kz',
743
+ 'hotmail.ru',
744
+ 'hotmail.it',
745
+ 'hotpop.com',
746
+ 'hotpop3.com',
747
+ 'hotvoice.com',
748
+ 'hsuchi.net',
749
+ 'hunsa.com',
750
+ 'hushmail.com',
751
+ 'i-france.com',
752
+ 'i-mail.com.au',
753
+ 'i-p.com',
754
+ 'i12.com',
755
+ 'iamawoman.com',
756
+ 'iamwaiting.com',
757
+ 'iamwasted.com',
758
+ 'iamyours.com',
759
+ 'icestorm.com',
760
+ 'icloud.com',
761
+ 'icmsconsultants.com',
762
+ 'icq.com',
763
+ 'icqmail.com',
764
+ 'icrazy.com',
765
+ 'ididitmyway.com',
766
+ 'idirect.com',
767
+ 'iespana.es',
768
+ 'ignazio.it',
769
+ 'ignmail.com',
770
+ 'ijustdontcare.com',
771
+ 'ilovechocolate.com',
772
+ 'ilovetocollect.net',
773
+ 'ilse.nl',
774
+ 'imail.ru',
775
+ 'imailbox.com',
776
+ 'imel.org',
777
+ 'imneverwrong.com',
778
+ 'imposter.co.uk',
779
+ 'imstressed.com',
780
+ 'imtoosexy.com',
781
+ 'in-box.net',
782
+ 'iname.com',
783
+ 'inbox.net',
784
+ 'inbox.ru',
785
+ 'incamail.com',
786
+ 'incredimail.com',
787
+ 'indexa.fr',
788
+ 'india.com',
789
+ 'indiatimes.com',
790
+ 'infohq.com',
791
+ 'infomail.es',
792
+ 'infomart.or.jp',
793
+ 'infovia.com.ar',
794
+ 'inicia.es',
795
+ 'inmail.sk',
796
+ 'inorbit.com',
797
+ 'insurer.com',
798
+ 'interfree.it',
799
+ 'interia.pl',
800
+ 'interlap.com.ar',
801
+ 'intermail.co.il',
802
+ 'internet-police.com',
803
+ 'internetbiz.com',
804
+ 'internetdrive.com',
805
+ 'internetegypt.com',
806
+ 'internetemails.net',
807
+ 'internetmailing.net',
808
+ 'inwind.it',
809
+ 'inbox.com',
810
+ 'iobox.com',
811
+ 'iobox.fi',
812
+ 'iol.it',
813
+ 'ip3.com',
814
+ 'iqemail.com',
815
+ 'irangate.net',
816
+ 'iraqmail.com',
817
+ 'irj.hu',
818
+ 'isellcars.com',
819
+ 'islamonline.net',
820
+ 'ismart.net',
821
+ 'isonfire.com',
822
+ 'isp9.net',
823
+ 'itloox.com',
824
+ 'itmom.com',
825
+ 'ivebeenframed.com',
826
+ 'ivillage.com',
827
+ 'iwan-fals.com',
828
+ 'iwon.com',
829
+ 'izadpanah.com',
830
+ 'jakuza.hu',
831
+ 'japan.com',
832
+ 'jaydemail.com',
833
+ 'jazzandjava.com',
834
+ 'jazzgame.com',
835
+ 'jetemail.net',
836
+ 'jippii.fi',
837
+ 'jmail.co.za',
838
+ 'joinme.com',
839
+ 'jordanmail.com',
840
+ 'journalist.com',
841
+ 'jovem.te.pt',
842
+ 'joymail.com',
843
+ 'jpopmail.com',
844
+ 'jubiimail.dk',
845
+ 'jumpy.it',
846
+ 'juno.com',
847
+ 'justemail.net',
848
+ 'kaazoo.com',
849
+ 'kaixo.com',
850
+ 'kalpoint.com',
851
+ 'kapoorweb.com',
852
+ 'karachian.com',
853
+ 'karachioye.com',
854
+ 'karbasi.com',
855
+ 'katamail.com',
856
+ 'kayafmmail.co.za',
857
+ 'keg-party.com',
858
+ 'keko.com.ar',
859
+ 'kellychen.com',
860
+ 'keromail.com',
861
+ 'kgb.hu',
862
+ 'khosropour.com',
863
+ 'kickassmail.com',
864
+ 'killermail.com',
865
+ 'kimo.com',
866
+ 'kinki-kids.com',
867
+ 'kittymail.com',
868
+ 'kiwibox.com',
869
+ 'kiwitown.com',
870
+ 'krunis.com',
871
+ 'kukamail.com',
872
+ 'kumarweb.com',
873
+ 'kuwait-mail.com',
874
+ 'ladymail.cz',
875
+ 'lagerlouts.com',
876
+ 'lahoreoye.com',
877
+ 'lakmail.com',
878
+ 'lamer.hu',
879
+ 'land.ru',
880
+ 'lankamail.com',
881
+ 'laposte.net',
882
+ 'latinmail.com',
883
+ 'lawyer.com',
884
+ 'leehom.net',
885
+ 'legalactions.com',
886
+ 'legislator.com',
887
+ 'leonlai.net',
888
+ 'levele.com',
889
+ 'levele.hu',
890
+ 'lex.bg',
891
+ 'liberomail.com',
892
+ 'linkmaster.com',
893
+ 'linuxfreemail.com',
894
+ 'linuxmail.org',
895
+ 'lionsfan.com.au',
896
+ 'liontrucks.com',
897
+ 'list.ru',
898
+ 'live.ca',
899
+ 'live.com',
900
+ 'live.com.au',
901
+ 'live.co.uk',
902
+ 'live.se',
903
+ 'liverpoolfans.com',
904
+ 'llandudno.com',
905
+ 'llangollen.com',
906
+ 'lmxmail.sk',
907
+ 'lobbyist.com',
908
+ 'localbar.com',
909
+ 'london.com',
910
+ 'looksmart.co.uk',
911
+ 'looksmart.com',
912
+ 'looksmart.com.au',
913
+ 'lopezclub.com',
914
+ 'louiskoo.com',
915
+ 'love.cz',
916
+ 'loveable.com',
917
+ 'lovelygirl.net',
918
+ 'lovemail.com',
919
+ 'lover-boy.com',
920
+ 'lovergirl.com',
921
+ 'lovingjesus.com',
922
+ 'luso.pt',
923
+ 'luukku.com',
924
+ 'lycos.co.uk',
925
+ 'lycos.com',
926
+ 'lycos.es',
927
+ 'lycos.it',
928
+ 'lycos.ne.jp',
929
+ 'lycosmail.com',
930
+ 'm-a-i-l.com',
931
+ 'mac.com',
932
+ 'machinecandy.com',
933
+ 'macmail.com',
934
+ 'madrid.com',
935
+ 'maffia.hu',
936
+ 'magicmail.co.za',
937
+ 'mahmoodweb.com',
938
+ 'mail-awu.de',
939
+ 'mail-box.cz',
940
+ 'mail-center.com',
941
+ 'mail-central.com',
942
+ 'mail-page.com',
943
+ 'mail.austria.com',
944
+ 'mail.az',
945
+ 'mail.be',
946
+ 'mail.bulgaria.com',
947
+ 'mail.co.za',
948
+ 'mail.com',
949
+ 'mail.ee',
950
+ 'mail.gr',
951
+ 'mail.md',
952
+ 'mail.nu',
953
+ 'mail.pf',
954
+ 'mail.pt',
955
+ 'mail.r-o-o-t.com',
956
+ 'mail.ru',
957
+ 'mail.sisna.com',
958
+ 'mail.vasarhely.hu',
959
+ 'mail15.com',
960
+ 'mail2007.com',
961
+ 'mail2aaron.com',
962
+ 'mail2abby.com',
963
+ 'mail2abc.com',
964
+ 'mail2actor.com',
965
+ 'mail2admiral.com',
966
+ 'mail2adorable.com',
967
+ 'mail2adoration.com',
968
+ 'mail2adore.com',
969
+ 'mail2adventure.com',
970
+ 'mail2aeolus.com',
971
+ 'mail2aether.com',
972
+ 'mail2affection.com',
973
+ 'mail2afghanistan.com',
974
+ 'mail2africa.com',
975
+ 'mail2agent.com',
976
+ 'mail2aha.com',
977
+ 'mail2ahoy.com',
978
+ 'mail2aim.com',
979
+ 'mail2air.com',
980
+ 'mail2airbag.com',
981
+ 'mail2airforce.com',
982
+ 'mail2airport.com',
983
+ 'mail2alabama.com',
984
+ 'mail2alan.com',
985
+ 'mail2alaska.com',
986
+ 'mail2albania.com',
987
+ 'mail2alcoholic.com',
988
+ 'mail2alec.com',
989
+ 'mail2alexa.com',
990
+ 'mail2algeria.com',
991
+ 'mail2alicia.com',
992
+ 'mail2alien.com',
993
+ 'mail2allan.com',
994
+ 'mail2allen.com',
995
+ 'mail2allison.com',
996
+ 'mail2alpha.com',
997
+ 'mail2alyssa.com',
998
+ 'mail2amanda.com',
999
+ 'mail2amazing.com',
1000
+ 'mail2amber.com',
1001
+ 'mail2america.com',
1002
+ 'mail2american.com',
1003
+ 'mail2andorra.com',
1004
+ 'mail2andrea.com',
1005
+ 'mail2andy.com',
1006
+ 'mail2anesthesiologist.com',
1007
+ 'mail2angela.com',
1008
+ 'mail2angola.com',
1009
+ 'mail2ann.com',
1010
+ 'mail2anna.com',
1011
+ 'mail2anne.com',
1012
+ 'mail2anthony.com',
1013
+ 'mail2anything.com',
1014
+ 'mail2aphrodite.com',
1015
+ 'mail2apollo.com',
1016
+ 'mail2april.com',
1017
+ 'mail2aquarius.com',
1018
+ 'mail2arabia.com',
1019
+ 'mail2arabic.com',
1020
+ 'mail2architect.com',
1021
+ 'mail2ares.com',
1022
+ 'mail2argentina.com',
1023
+ 'mail2aries.com',
1024
+ 'mail2arizona.com',
1025
+ 'mail2arkansas.com',
1026
+ 'mail2armenia.com',
1027
+ 'mail2army.com',
1028
+ 'mail2arnold.com',
1029
+ 'mail2art.com',
1030
+ 'mail2artemus.com',
1031
+ 'mail2arthur.com',
1032
+ 'mail2artist.com',
1033
+ 'mail2ashley.com',
1034
+ 'mail2ask.com',
1035
+ 'mail2astronomer.com',
1036
+ 'mail2athena.com',
1037
+ 'mail2athlete.com',
1038
+ 'mail2atlas.com',
1039
+ 'mail2atom.com',
1040
+ 'mail2attitude.com',
1041
+ 'mail2auction.com',
1042
+ 'mail2aunt.com',
1043
+ 'mail2australia.com',
1044
+ 'mail2austria.com',
1045
+ 'mail2azerbaijan.com',
1046
+ 'mail2baby.com',
1047
+ 'mail2bahamas.com',
1048
+ 'mail2bahrain.com',
1049
+ 'mail2ballerina.com',
1050
+ 'mail2ballplayer.com',
1051
+ 'mail2band.com',
1052
+ 'mail2bangladesh.com',
1053
+ 'mail2bank.com',
1054
+ 'mail2banker.com',
1055
+ 'mail2bankrupt.com',
1056
+ 'mail2baptist.com',
1057
+ 'mail2bar.com',
1058
+ 'mail2barbados.com',
1059
+ 'mail2barbara.com',
1060
+ 'mail2barter.com',
1061
+ 'mail2basketball.com',
1062
+ 'mail2batter.com',
1063
+ 'mail2beach.com',
1064
+ 'mail2beast.com',
1065
+ 'mail2beatles.com',
1066
+ 'mail2beauty.com',
1067
+ 'mail2becky.com',
1068
+ 'mail2beijing.com',
1069
+ 'mail2belgium.com',
1070
+ 'mail2belize.com',
1071
+ 'mail2ben.com',
1072
+ 'mail2bernard.com',
1073
+ 'mail2beth.com',
1074
+ 'mail2betty.com',
1075
+ 'mail2beverly.com',
1076
+ 'mail2beyond.com',
1077
+ 'mail2biker.com',
1078
+ 'mail2bill.com',
1079
+ 'mail2billionaire.com',
1080
+ 'mail2billy.com',
1081
+ 'mail2bio.com',
1082
+ 'mail2biologist.com',
1083
+ 'mail2black.com',
1084
+ 'mail2blackbelt.com',
1085
+ 'mail2blake.com',
1086
+ 'mail2blind.com',
1087
+ 'mail2blonde.com',
1088
+ 'mail2blues.com',
1089
+ 'mail2bob.com',
1090
+ 'mail2bobby.com',
1091
+ 'mail2bolivia.com',
1092
+ 'mail2bombay.com',
1093
+ 'mail2bonn.com',
1094
+ 'mail2bookmark.com',
1095
+ 'mail2boreas.com',
1096
+ 'mail2bosnia.com',
1097
+ 'mail2boston.com',
1098
+ 'mail2botswana.com',
1099
+ 'mail2bradley.com',
1100
+ 'mail2brazil.com',
1101
+ 'mail2breakfast.com',
1102
+ 'mail2brian.com',
1103
+ 'mail2bride.com',
1104
+ 'mail2brittany.com',
1105
+ 'mail2broker.com',
1106
+ 'mail2brook.com',
1107
+ 'mail2bruce.com',
1108
+ 'mail2brunei.com',
1109
+ 'mail2brunette.com',
1110
+ 'mail2brussels.com',
1111
+ 'mail2bryan.com',
1112
+ 'mail2bug.com',
1113
+ 'mail2bulgaria.com',
1114
+ 'mail2business.com',
1115
+ 'mail2buy.com',
1116
+ 'mail2ca.com',
1117
+ 'mail2california.com',
1118
+ 'mail2calvin.com',
1119
+ 'mail2cambodia.com',
1120
+ 'mail2cameroon.com',
1121
+ 'mail2canada.com',
1122
+ 'mail2cancer.com',
1123
+ 'mail2capeverde.com',
1124
+ 'mail2capricorn.com',
1125
+ 'mail2cardinal.com',
1126
+ 'mail2cardiologist.com',
1127
+ 'mail2care.com',
1128
+ 'mail2caroline.com',
1129
+ 'mail2carolyn.com',
1130
+ 'mail2casey.com',
1131
+ 'mail2cat.com',
1132
+ 'mail2caterer.com',
1133
+ 'mail2cathy.com',
1134
+ 'mail2catlover.com',
1135
+ 'mail2catwalk.com',
1136
+ 'mail2cell.com',
1137
+ 'mail2chad.com',
1138
+ 'mail2champaign.com',
1139
+ 'mail2charles.com',
1140
+ 'mail2chef.com',
1141
+ 'mail2chemist.com',
1142
+ 'mail2cherry.com',
1143
+ 'mail2chicago.com',
1144
+ 'mail2chile.com',
1145
+ 'mail2china.com',
1146
+ 'mail2chinese.com',
1147
+ 'mail2chocolate.com',
1148
+ 'mail2christian.com',
1149
+ 'mail2christie.com',
1150
+ 'mail2christmas.com',
1151
+ 'mail2christy.com',
1152
+ 'mail2chuck.com',
1153
+ 'mail2cindy.com',
1154
+ 'mail2clark.com',
1155
+ 'mail2classifieds.com',
1156
+ 'mail2claude.com',
1157
+ 'mail2cliff.com',
1158
+ 'mail2clinic.com',
1159
+ 'mail2clint.com',
1160
+ 'mail2close.com',
1161
+ 'mail2club.com',
1162
+ 'mail2coach.com',
1163
+ 'mail2coastguard.com',
1164
+ 'mail2colin.com',
1165
+ 'mail2college.com',
1166
+ 'mail2colombia.com',
1167
+ 'mail2color.com',
1168
+ 'mail2colorado.com',
1169
+ 'mail2columbia.com',
1170
+ 'mail2comedian.com',
1171
+ 'mail2composer.com',
1172
+ 'mail2computer.com',
1173
+ 'mail2computers.com',
1174
+ 'mail2concert.com',
1175
+ 'mail2congo.com',
1176
+ 'mail2connect.com',
1177
+ 'mail2connecticut.com',
1178
+ 'mail2consultant.com',
1179
+ 'mail2convict.com',
1180
+ 'mail2cook.com',
1181
+ 'mail2cool.com',
1182
+ 'mail2cory.com',
1183
+ 'mail2costarica.com',
1184
+ 'mail2country.com',
1185
+ 'mail2courtney.com',
1186
+ 'mail2cowboy.com',
1187
+ 'mail2cowgirl.com',
1188
+ 'mail2craig.com',
1189
+ 'mail2crave.com',
1190
+ 'mail2crazy.com',
1191
+ 'mail2create.com',
1192
+ 'mail2croatia.com',
1193
+ 'mail2cry.com',
1194
+ 'mail2crystal.com',
1195
+ 'mail2cuba.com',
1196
+ 'mail2culture.com',
1197
+ 'mail2curt.com',
1198
+ 'mail2customs.com',
1199
+ 'mail2cute.com',
1200
+ 'mail2cutey.com',
1201
+ 'mail2cynthia.com',
1202
+ 'mail2cyprus.com',
1203
+ 'mail2czechrepublic.com',
1204
+ 'mail2dad.com',
1205
+ 'mail2dale.com',
1206
+ 'mail2dallas.com',
1207
+ 'mail2dan.com',
1208
+ 'mail2dana.com',
1209
+ 'mail2dance.com',
1210
+ 'mail2dancer.com',
1211
+ 'mail2danielle.com',
1212
+ 'mail2danny.com',
1213
+ 'mail2darlene.com',
1214
+ 'mail2darling.com',
1215
+ 'mail2darren.com',
1216
+ 'mail2daughter.com',
1217
+ 'mail2dave.com',
1218
+ 'mail2dawn.com',
1219
+ 'mail2dc.com',
1220
+ 'mail2dealer.com',
1221
+ 'mail2deanna.com',
1222
+ 'mail2dearest.com',
1223
+ 'mail2debbie.com',
1224
+ 'mail2debby.com',
1225
+ 'mail2deer.com',
1226
+ 'mail2delaware.com',
1227
+ 'mail2delicious.com',
1228
+ 'mail2demeter.com',
1229
+ 'mail2democrat.com',
1230
+ 'mail2denise.com',
1231
+ 'mail2denmark.com',
1232
+ 'mail2dennis.com',
1233
+ 'mail2dentist.com',
1234
+ 'mail2derek.com',
1235
+ 'mail2desert.com',
1236
+ 'mail2devoted.com',
1237
+ 'mail2devotion.com',
1238
+ 'mail2diamond.com',
1239
+ 'mail2diana.com',
1240
+ 'mail2diane.com',
1241
+ 'mail2diehard.com',
1242
+ 'mail2dilemma.com',
1243
+ 'mail2dillon.com',
1244
+ 'mail2dinner.com',
1245
+ 'mail2dinosaur.com',
1246
+ 'mail2dionysos.com',
1247
+ 'mail2diplomat.com',
1248
+ 'mail2director.com',
1249
+ 'mail2dirk.com',
1250
+ 'mail2disco.com',
1251
+ 'mail2dive.com',
1252
+ 'mail2diver.com',
1253
+ 'mail2divorced.com',
1254
+ 'mail2djibouti.com',
1255
+ 'mail2doctor.com',
1256
+ 'mail2doglover.com',
1257
+ 'mail2dominic.com',
1258
+ 'mail2dominica.com',
1259
+ 'mail2dominicanrepublic.com',
1260
+ 'mail2don.com',
1261
+ 'mail2donald.com',
1262
+ 'mail2donna.com',
1263
+ 'mail2doris.com',
1264
+ 'mail2dorothy.com',
1265
+ 'mail2doug.com',
1266
+ 'mail2dough.com',
1267
+ 'mail2douglas.com',
1268
+ 'mail2dow.com',
1269
+ 'mail2downtown.com',
1270
+ 'mail2dream.com',
1271
+ 'mail2dreamer.com',
1272
+ 'mail2dude.com',
1273
+ 'mail2dustin.com',
1274
+ 'mail2dyke.com',
1275
+ 'mail2dylan.com',
1276
+ 'mail2earl.com',
1277
+ 'mail2earth.com',
1278
+ 'mail2eastend.com',
1279
+ 'mail2eat.com',
1280
+ 'mail2economist.com',
1281
+ 'mail2ecuador.com',
1282
+ 'mail2eddie.com',
1283
+ 'mail2edgar.com',
1284
+ 'mail2edwin.com',
1285
+ 'mail2egypt.com',
1286
+ 'mail2electron.com',
1287
+ 'mail2eli.com',
1288
+ 'mail2elizabeth.com',
1289
+ 'mail2ellen.com',
1290
+ 'mail2elliot.com',
1291
+ 'mail2elsalvador.com',
1292
+ 'mail2elvis.com',
1293
+ 'mail2emergency.com',
1294
+ 'mail2emily.com',
1295
+ 'mail2engineer.com',
1296
+ 'mail2english.com',
1297
+ 'mail2environmentalist.com',
1298
+ 'mail2eos.com',
1299
+ 'mail2eric.com',
1300
+ 'mail2erica.com',
1301
+ 'mail2erin.com',
1302
+ 'mail2erinyes.com',
1303
+ 'mail2eris.com',
1304
+ 'mail2eritrea.com',
1305
+ 'mail2ernie.com',
1306
+ 'mail2eros.com',
1307
+ 'mail2estonia.com',
1308
+ 'mail2ethan.com',
1309
+ 'mail2ethiopia.com',
1310
+ 'mail2eu.com',
1311
+ 'mail2europe.com',
1312
+ 'mail2eurus.com',
1313
+ 'mail2eva.com',
1314
+ 'mail2evan.com',
1315
+ 'mail2evelyn.com',
1316
+ 'mail2everything.com',
1317
+ 'mail2exciting.com',
1318
+ 'mail2expert.com',
1319
+ 'mail2fairy.com',
1320
+ 'mail2faith.com',
1321
+ 'mail2fanatic.com',
1322
+ 'mail2fancy.com',
1323
+ 'mail2fantasy.com',
1324
+ 'mail2farm.com',
1325
+ 'mail2farmer.com',
1326
+ 'mail2fashion.com',
1327
+ 'mail2fat.com',
1328
+ 'mail2feeling.com',
1329
+ 'mail2female.com',
1330
+ 'mail2fever.com',
1331
+ 'mail2fighter.com',
1332
+ 'mail2fiji.com',
1333
+ 'mail2filmfestival.com',
1334
+ 'mail2films.com',
1335
+ 'mail2finance.com',
1336
+ 'mail2finland.com',
1337
+ 'mail2fireman.com',
1338
+ 'mail2firm.com',
1339
+ 'mail2fisherman.com',
1340
+ 'mail2flexible.com',
1341
+ 'mail2florence.com',
1342
+ 'mail2florida.com',
1343
+ 'mail2floyd.com',
1344
+ 'mail2fly.com',
1345
+ 'mail2fond.com',
1346
+ 'mail2fondness.com',
1347
+ 'mail2football.com',
1348
+ 'mail2footballfan.com',
1349
+ 'mail2found.com',
1350
+ 'mail2france.com',
1351
+ 'mail2frank.com',
1352
+ 'mail2frankfurt.com',
1353
+ 'mail2franklin.com',
1354
+ 'mail2fred.com',
1355
+ 'mail2freddie.com',
1356
+ 'mail2free.com',
1357
+ 'mail2freedom.com',
1358
+ 'mail2french.com',
1359
+ 'mail2freudian.com',
1360
+ 'mail2friendship.com',
1361
+ 'mail2from.com',
1362
+ 'mail2fun.com',
1363
+ 'mail2gabon.com',
1364
+ 'mail2gabriel.com',
1365
+ 'mail2gail.com',
1366
+ 'mail2galaxy.com',
1367
+ 'mail2gambia.com',
1368
+ 'mail2games.com',
1369
+ 'mail2gary.com',
1370
+ 'mail2gavin.com',
1371
+ 'mail2gemini.com',
1372
+ 'mail2gene.com',
1373
+ 'mail2genes.com',
1374
+ 'mail2geneva.com',
1375
+ 'mail2george.com',
1376
+ 'mail2georgia.com',
1377
+ 'mail2gerald.com',
1378
+ 'mail2german.com',
1379
+ 'mail2germany.com',
1380
+ 'mail2ghana.com',
1381
+ 'mail2gilbert.com',
1382
+ 'mail2gina.com',
1383
+ 'mail2girl.com',
1384
+ 'mail2glen.com',
1385
+ 'mail2gloria.com',
1386
+ 'mail2goddess.com',
1387
+ 'mail2gold.com',
1388
+ 'mail2golfclub.com',
1389
+ 'mail2golfer.com',
1390
+ 'mail2gordon.com',
1391
+ 'mail2government.com',
1392
+ 'mail2grab.com',
1393
+ 'mail2grace.com',
1394
+ 'mail2graham.com',
1395
+ 'mail2grandma.com',
1396
+ 'mail2grandpa.com',
1397
+ 'mail2grant.com',
1398
+ 'mail2greece.com',
1399
+ 'mail2green.com',
1400
+ 'mail2greg.com',
1401
+ 'mail2grenada.com',
1402
+ 'mail2gsm.com',
1403
+ 'mail2guard.com',
1404
+ 'mail2guatemala.com',
1405
+ 'mail2guy.com',
1406
+ 'mail2hades.com',
1407
+ 'mail2haiti.com',
1408
+ 'mail2hal.com',
1409
+ 'mail2handhelds.com',
1410
+ 'mail2hank.com',
1411
+ 'mail2hannah.com',
1412
+ 'mail2harold.com',
1413
+ 'mail2harry.com',
1414
+ 'mail2hawaii.com',
1415
+ 'mail2headhunter.com',
1416
+ 'mail2heal.com',
1417
+ 'mail2heather.com',
1418
+ 'mail2heaven.com',
1419
+ 'mail2hebe.com',
1420
+ 'mail2hecate.com',
1421
+ 'mail2heidi.com',
1422
+ 'mail2helen.com',
1423
+ 'mail2hell.com',
1424
+ 'mail2help.com',
1425
+ 'mail2helpdesk.com',
1426
+ 'mail2henry.com',
1427
+ 'mail2hephaestus.com',
1428
+ 'mail2hera.com',
1429
+ 'mail2hercules.com',
1430
+ 'mail2herman.com',
1431
+ 'mail2hermes.com',
1432
+ 'mail2hespera.com',
1433
+ 'mail2hestia.com',
1434
+ 'mail2highschool.com',
1435
+ 'mail2hindu.com',
1436
+ 'mail2hip.com',
1437
+ 'mail2hiphop.com',
1438
+ 'mail2holland.com',
1439
+ 'mail2holly.com',
1440
+ 'mail2hollywood.com',
1441
+ 'mail2homer.com',
1442
+ 'mail2honduras.com',
1443
+ 'mail2honey.com',
1444
+ 'mail2hongkong.com',
1445
+ 'mail2hope.com',
1446
+ 'mail2horse.com',
1447
+ 'mail2hot.com',
1448
+ 'mail2hotel.com',
1449
+ 'mail2houston.com',
1450
+ 'mail2howard.com',
1451
+ 'mail2hugh.com',
1452
+ 'mail2human.com',
1453
+ 'mail2hungary.com',
1454
+ 'mail2hungry.com',
1455
+ 'mail2hygeia.com',
1456
+ 'mail2hyperspace.com',
1457
+ 'mail2hypnos.com',
1458
+ 'mail2ian.com',
1459
+ 'mail2ice-cream.com',
1460
+ 'mail2iceland.com',
1461
+ 'mail2idaho.com',
1462
+ 'mail2idontknow.com',
1463
+ 'mail2illinois.com',
1464
+ 'mail2imam.com',
1465
+ 'mail2in.com',
1466
+ 'mail2india.com',
1467
+ 'mail2indian.com',
1468
+ 'mail2indiana.com',
1469
+ 'mail2indonesia.com',
1470
+ 'mail2infinity.com',
1471
+ 'mail2intense.com',
1472
+ 'mail2iowa.com',
1473
+ 'mail2iran.com',
1474
+ 'mail2iraq.com',
1475
+ 'mail2ireland.com',
1476
+ 'mail2irene.com',
1477
+ 'mail2iris.com',
1478
+ 'mail2irresistible.com',
1479
+ 'mail2irving.com',
1480
+ 'mail2irwin.com',
1481
+ 'mail2isaac.com',
1482
+ 'mail2israel.com',
1483
+ 'mail2italian.com',
1484
+ 'mail2italy.com',
1485
+ 'mail2jackie.com',
1486
+ 'mail2jacob.com',
1487
+ 'mail2jail.com',
1488
+ 'mail2jaime.com',
1489
+ 'mail2jake.com',
1490
+ 'mail2jamaica.com',
1491
+ 'mail2james.com',
1492
+ 'mail2jamie.com',
1493
+ 'mail2jan.com',
1494
+ 'mail2jane.com',
1495
+ 'mail2janet.com',
1496
+ 'mail2janice.com',
1497
+ 'mail2japan.com',
1498
+ 'mail2japanese.com',
1499
+ 'mail2jasmine.com',
1500
+ 'mail2jason.com',
1501
+ 'mail2java.com',
1502
+ 'mail2jay.com',
1503
+ 'mail2jazz.com',
1504
+ 'mail2jed.com',
1505
+ 'mail2jeffrey.com',
1506
+ 'mail2jennifer.com',
1507
+ 'mail2jenny.com',
1508
+ 'mail2jeremy.com',
1509
+ 'mail2jerry.com',
1510
+ 'mail2jessica.com',
1511
+ 'mail2jessie.com',
1512
+ 'mail2jesus.com',
1513
+ 'mail2jew.com',
1514
+ 'mail2jeweler.com',
1515
+ 'mail2jim.com',
1516
+ 'mail2jimmy.com',
1517
+ 'mail2joan.com',
1518
+ 'mail2joann.com',
1519
+ 'mail2joanna.com',
1520
+ 'mail2jody.com',
1521
+ 'mail2joe.com',
1522
+ 'mail2joel.com',
1523
+ 'mail2joey.com',
1524
+ 'mail2john.com',
1525
+ 'mail2join.com',
1526
+ 'mail2jon.com',
1527
+ 'mail2jonathan.com',
1528
+ 'mail2jones.com',
1529
+ 'mail2jordan.com',
1530
+ 'mail2joseph.com',
1531
+ 'mail2josh.com',
1532
+ 'mail2joy.com',
1533
+ 'mail2juan.com',
1534
+ 'mail2judge.com',
1535
+ 'mail2judy.com',
1536
+ 'mail2juggler.com',
1537
+ 'mail2julian.com',
1538
+ 'mail2julie.com',
1539
+ 'mail2jumbo.com',
1540
+ 'mail2junk.com',
1541
+ 'mail2justin.com',
1542
+ 'mail2justme.com',
1543
+ 'mail2kansas.com',
1544
+ 'mail2karate.com',
1545
+ 'mail2karen.com',
1546
+ 'mail2karl.com',
1547
+ 'mail2karma.com',
1548
+ 'mail2kathleen.com',
1549
+ 'mail2kathy.com',
1550
+ 'mail2katie.com',
1551
+ 'mail2kay.com',
1552
+ 'mail2kazakhstan.com',
1553
+ 'mail2keen.com',
1554
+ 'mail2keith.com',
1555
+ 'mail2kelly.com',
1556
+ 'mail2kelsey.com',
1557
+ 'mail2ken.com',
1558
+ 'mail2kendall.com',
1559
+ 'mail2kennedy.com',
1560
+ 'mail2kenneth.com',
1561
+ 'mail2kenny.com',
1562
+ 'mail2kentucky.com',
1563
+ 'mail2kenya.com',
1564
+ 'mail2kerry.com',
1565
+ 'mail2kevin.com',
1566
+ 'mail2kim.com',
1567
+ 'mail2kimberly.com',
1568
+ 'mail2king.com',
1569
+ 'mail2kirk.com',
1570
+ 'mail2kiss.com',
1571
+ 'mail2kosher.com',
1572
+ 'mail2kristin.com',
1573
+ 'mail2kurt.com',
1574
+ 'mail2kuwait.com',
1575
+ 'mail2kyle.com',
1576
+ 'mail2kyrgyzstan.com',
1577
+ 'mail2la.com',
1578
+ 'mail2lacrosse.com',
1579
+ 'mail2lance.com',
1580
+ 'mail2lao.com',
1581
+ 'mail2larry.com',
1582
+ 'mail2latvia.com',
1583
+ 'mail2laugh.com',
1584
+ 'mail2laura.com',
1585
+ 'mail2lauren.com',
1586
+ 'mail2laurie.com',
1587
+ 'mail2lawrence.com',
1588
+ 'mail2lawyer.com',
1589
+ 'mail2lebanon.com',
1590
+ 'mail2lee.com',
1591
+ 'mail2leo.com',
1592
+ 'mail2leon.com',
1593
+ 'mail2leonard.com',
1594
+ 'mail2leone.com',
1595
+ 'mail2leslie.com',
1596
+ 'mail2letter.com',
1597
+ 'mail2liberia.com',
1598
+ 'mail2libertarian.com',
1599
+ 'mail2libra.com',
1600
+ 'mail2libya.com',
1601
+ 'mail2liechtenstein.com',
1602
+ 'mail2life.com',
1603
+ 'mail2linda.com',
1604
+ 'mail2linux.com',
1605
+ 'mail2lionel.com',
1606
+ 'mail2lipstick.com',
1607
+ 'mail2liquid.com',
1608
+ 'mail2lisa.com',
1609
+ 'mail2lithuania.com',
1610
+ 'mail2litigator.com',
1611
+ 'mail2liz.com',
1612
+ 'mail2lloyd.com',
1613
+ 'mail2lois.com',
1614
+ 'mail2lola.com',
1615
+ 'mail2london.com',
1616
+ 'mail2looking.com',
1617
+ 'mail2lori.com',
1618
+ 'mail2lost.com',
1619
+ 'mail2lou.com',
1620
+ 'mail2louis.com',
1621
+ 'mail2louisiana.com',
1622
+ 'mail2lovable.com',
1623
+ 'mail2love.com',
1624
+ 'mail2lucky.com',
1625
+ 'mail2lucy.com',
1626
+ 'mail2lunch.com',
1627
+ 'mail2lust.com',
1628
+ 'mail2luxembourg.com',
1629
+ 'mail2luxury.com',
1630
+ 'mail2lyle.com',
1631
+ 'mail2lynn.com',
1632
+ 'mail2madagascar.com',
1633
+ 'mail2madison.com',
1634
+ 'mail2madrid.com',
1635
+ 'mail2maggie.com',
1636
+ 'mail2mail4.com',
1637
+ 'mail2maine.com',
1638
+ 'mail2malawi.com',
1639
+ 'mail2malaysia.com',
1640
+ 'mail2maldives.com',
1641
+ 'mail2mali.com',
1642
+ 'mail2malta.com',
1643
+ 'mail2mambo.com',
1644
+ 'mail2man.com',
1645
+ 'mail2mandy.com',
1646
+ 'mail2manhunter.com',
1647
+ 'mail2mankind.com',
1648
+ 'mail2many.com',
1649
+ 'mail2marc.com',
1650
+ 'mail2marcia.com',
1651
+ 'mail2margaret.com',
1652
+ 'mail2margie.com',
1653
+ 'mail2marhaba.com',
1654
+ 'mail2maria.com',
1655
+ 'mail2marilyn.com',
1656
+ 'mail2marines.com',
1657
+ 'mail2mark.com',
1658
+ 'mail2marriage.com',
1659
+ 'mail2married.com',
1660
+ 'mail2marries.com',
1661
+ 'mail2mars.com',
1662
+ 'mail2marsha.com',
1663
+ 'mail2marshallislands.com',
1664
+ 'mail2martha.com',
1665
+ 'mail2martin.com',
1666
+ 'mail2marty.com',
1667
+ 'mail2marvin.com',
1668
+ 'mail2mary.com',
1669
+ 'mail2maryland.com',
1670
+ 'mail2mason.com',
1671
+ 'mail2massachusetts.com',
1672
+ 'mail2matt.com',
1673
+ 'mail2matthew.com',
1674
+ 'mail2maurice.com',
1675
+ 'mail2mauritania.com',
1676
+ 'mail2mauritius.com',
1677
+ 'mail2max.com',
1678
+ 'mail2maxwell.com',
1679
+ 'mail2maybe.com',
1680
+ 'mail2mba.com',
1681
+ 'mail2me4u.com',
1682
+ 'mail2mechanic.com',
1683
+ 'mail2medieval.com',
1684
+ 'mail2megan.com',
1685
+ 'mail2mel.com',
1686
+ 'mail2melanie.com',
1687
+ 'mail2melissa.com',
1688
+ 'mail2melody.com',
1689
+ 'mail2member.com',
1690
+ 'mail2memphis.com',
1691
+ 'mail2methodist.com',
1692
+ 'mail2mexican.com',
1693
+ 'mail2mexico.com',
1694
+ 'mail2mgz.com',
1695
+ 'mail2miami.com',
1696
+ 'mail2michael.com',
1697
+ 'mail2michelle.com',
1698
+ 'mail2michigan.com',
1699
+ 'mail2mike.com',
1700
+ 'mail2milan.com',
1701
+ 'mail2milano.com',
1702
+ 'mail2mildred.com',
1703
+ 'mail2milkyway.com',
1704
+ 'mail2millennium.com',
1705
+ 'mail2millionaire.com',
1706
+ 'mail2milton.com',
1707
+ 'mail2mime.com',
1708
+ 'mail2mindreader.com',
1709
+ 'mail2mini.com',
1710
+ 'mail2minister.com',
1711
+ 'mail2minneapolis.com',
1712
+ 'mail2minnesota.com',
1713
+ 'mail2miracle.com',
1714
+ 'mail2missionary.com',
1715
+ 'mail2mississippi.com',
1716
+ 'mail2missouri.com',
1717
+ 'mail2mitch.com',
1718
+ 'mail2model.com',
1719
+ 'mail2moldova.commail2molly.com',
1720
+ 'mail2mom.com',
1721
+ 'mail2monaco.com',
1722
+ 'mail2money.com',
1723
+ 'mail2mongolia.com',
1724
+ 'mail2monica.com',
1725
+ 'mail2montana.com',
1726
+ 'mail2monty.com',
1727
+ 'mail2moon.com',
1728
+ 'mail2morocco.com',
1729
+ 'mail2morpheus.com',
1730
+ 'mail2mors.com',
1731
+ 'mail2moscow.com',
1732
+ 'mail2moslem.com',
1733
+ 'mail2mouseketeer.com',
1734
+ 'mail2movies.com',
1735
+ 'mail2mozambique.com',
1736
+ 'mail2mp3.com',
1737
+ 'mail2mrright.com',
1738
+ 'mail2msright.com',
1739
+ 'mail2museum.com',
1740
+ 'mail2music.com',
1741
+ 'mail2musician.com',
1742
+ 'mail2muslim.com',
1743
+ 'mail2my.com',
1744
+ 'mail2myboat.com',
1745
+ 'mail2mycar.com',
1746
+ 'mail2mycell.com',
1747
+ 'mail2mygsm.com',
1748
+ 'mail2mylaptop.com',
1749
+ 'mail2mymac.com',
1750
+ 'mail2mypager.com',
1751
+ 'mail2mypalm.com',
1752
+ 'mail2mypc.com',
1753
+ 'mail2myphone.com',
1754
+ 'mail2myplane.com',
1755
+ 'mail2namibia.com',
1756
+ 'mail2nancy.com',
1757
+ 'mail2nasdaq.com',
1758
+ 'mail2nathan.com',
1759
+ 'mail2nauru.com',
1760
+ 'mail2navy.com',
1761
+ 'mail2neal.com',
1762
+ 'mail2nebraska.com',
1763
+ 'mail2ned.com',
1764
+ 'mail2neil.com',
1765
+ 'mail2nelson.com',
1766
+ 'mail2nemesis.com',
1767
+ 'mail2nepal.com',
1768
+ 'mail2netherlands.com',
1769
+ 'mail2network.com',
1770
+ 'mail2nevada.com',
1771
+ 'mail2newhampshire.com',
1772
+ 'mail2newjersey.com',
1773
+ 'mail2newmexico.com',
1774
+ 'mail2newyork.com',
1775
+ 'mail2newzealand.com',
1776
+ 'mail2nicaragua.com',
1777
+ 'mail2nick.com',
1778
+ 'mail2nicole.com',
1779
+ 'mail2niger.com',
1780
+ 'mail2nigeria.com',
1781
+ 'mail2nike.com',
1782
+ 'mail2no.com',
1783
+ 'mail2noah.com',
1784
+ 'mail2noel.com',
1785
+ 'mail2noelle.com',
1786
+ 'mail2normal.com',
1787
+ 'mail2norman.com',
1788
+ 'mail2northamerica.com',
1789
+ 'mail2northcarolina.com',
1790
+ 'mail2northdakota.com',
1791
+ 'mail2northpole.com',
1792
+ 'mail2norway.com',
1793
+ 'mail2notus.com',
1794
+ 'mail2noway.com',
1795
+ 'mail2nowhere.com',
1796
+ 'mail2nuclear.com',
1797
+ 'mail2nun.com',
1798
+ 'mail2ny.com',
1799
+ 'mail2oasis.com',
1800
+ 'mail2oceanographer.com',
1801
+ 'mail2ohio.com',
1802
+ 'mail2ok.com',
1803
+ 'mail2oklahoma.com',
1804
+ 'mail2oliver.com',
1805
+ 'mail2oman.com',
1806
+ 'mail2one.com',
1807
+ 'mail2onfire.com',
1808
+ 'mail2online.com',
1809
+ 'mail2oops.com',
1810
+ 'mail2open.com',
1811
+ 'mail2ophthalmologist.com',
1812
+ 'mail2optometrist.com',
1813
+ 'mail2oregon.com',
1814
+ 'mail2oscars.com',
1815
+ 'mail2oslo.com',
1816
+ 'mail2painter.com',
1817
+ 'mail2pakistan.com',
1818
+ 'mail2palau.com',
1819
+ 'mail2pan.com',
1820
+ 'mail2panama.com',
1821
+ 'mail2paraguay.com',
1822
+ 'mail2paralegal.com',
1823
+ 'mail2paris.com',
1824
+ 'mail2park.com',
1825
+ 'mail2parker.com',
1826
+ 'mail2party.com',
1827
+ 'mail2passion.com',
1828
+ 'mail2pat.com',
1829
+ 'mail2patricia.com',
1830
+ 'mail2patrick.com',
1831
+ 'mail2patty.com',
1832
+ 'mail2paul.com',
1833
+ 'mail2paula.com',
1834
+ 'mail2pay.com',
1835
+ 'mail2peace.com',
1836
+ 'mail2pediatrician.com',
1837
+ 'mail2peggy.com',
1838
+ 'mail2pennsylvania.com',
1839
+ 'mail2perry.com',
1840
+ 'mail2persephone.com',
1841
+ 'mail2persian.com',
1842
+ 'mail2peru.com',
1843
+ 'mail2pete.com',
1844
+ 'mail2peter.com',
1845
+ 'mail2pharmacist.com',
1846
+ 'mail2phil.com',
1847
+ 'mail2philippines.com',
1848
+ 'mail2phoenix.com',
1849
+ 'mail2phonecall.com',
1850
+ 'mail2phyllis.com',
1851
+ 'mail2pickup.com',
1852
+ 'mail2pilot.com',
1853
+ 'mail2pisces.com',
1854
+ 'mail2planet.com',
1855
+ 'mail2platinum.com',
1856
+ 'mail2plato.com',
1857
+ 'mail2pluto.com',
1858
+ 'mail2pm.com',
1859
+ 'mail2podiatrist.com',
1860
+ 'mail2poet.com',
1861
+ 'mail2poland.com',
1862
+ 'mail2policeman.com',
1863
+ 'mail2policewoman.com',
1864
+ 'mail2politician.com',
1865
+ 'mail2pop.com',
1866
+ 'mail2pope.com',
1867
+ 'mail2popular.com',
1868
+ 'mail2portugal.com',
1869
+ 'mail2poseidon.com',
1870
+ 'mail2potatohead.com',
1871
+ 'mail2power.com',
1872
+ 'mail2presbyterian.com',
1873
+ 'mail2president.com',
1874
+ 'mail2priest.com',
1875
+ 'mail2prince.com',
1876
+ 'mail2princess.com',
1877
+ 'mail2producer.com',
1878
+ 'mail2professor.com',
1879
+ 'mail2protect.com',
1880
+ 'mail2psychiatrist.com',
1881
+ 'mail2psycho.com',
1882
+ 'mail2psychologist.com',
1883
+ 'mail2qatar.com',
1884
+ 'mail2queen.com',
1885
+ 'mail2rabbi.com',
1886
+ 'mail2race.com',
1887
+ 'mail2racer.com',
1888
+ 'mail2rachel.com',
1889
+ 'mail2rage.com',
1890
+ 'mail2rainmaker.com',
1891
+ 'mail2ralph.com',
1892
+ 'mail2randy.com',
1893
+ 'mail2rap.com',
1894
+ 'mail2rare.com',
1895
+ 'mail2rave.com',
1896
+ 'mail2ray.com',
1897
+ 'mail2raymond.com',
1898
+ 'mail2realtor.com',
1899
+ 'mail2rebecca.com',
1900
+ 'mail2recruiter.com',
1901
+ 'mail2recycle.com',
1902
+ 'mail2redhead.com',
1903
+ 'mail2reed.com',
1904
+ 'mail2reggie.com',
1905
+ 'mail2register.com',
1906
+ 'mail2rent.com',
1907
+ 'mail2republican.com',
1908
+ 'mail2resort.com',
1909
+ 'mail2rex.com',
1910
+ 'mail2rhodeisland.com',
1911
+ 'mail2rich.com',
1912
+ 'mail2richard.com',
1913
+ 'mail2ricky.com',
1914
+ 'mail2ride.com',
1915
+ 'mail2riley.com',
1916
+ 'mail2rita.com',
1917
+ 'mail2rob.com',
1918
+ 'mail2robert.com',
1919
+ 'mail2roberta.com',
1920
+ 'mail2robin.com',
1921
+ 'mail2rock.com',
1922
+ 'mail2rocker.com',
1923
+ 'mail2rod.com',
1924
+ 'mail2rodney.com',
1925
+ 'mail2romania.com',
1926
+ 'mail2rome.com',
1927
+ 'mail2ron.com',
1928
+ 'mail2ronald.com',
1929
+ 'mail2ronnie.com',
1930
+ 'mail2rose.com',
1931
+ 'mail2rosie.com',
1932
+ 'mail2roy.com',
1933
+ 'mail2rudy.com',
1934
+ 'mail2rugby.com',
1935
+ 'mail2runner.com',
1936
+ 'mail2russell.com',
1937
+ 'mail2russia.com',
1938
+ 'mail2russian.com',
1939
+ 'mail2rusty.com',
1940
+ 'mail2ruth.com',
1941
+ 'mail2rwanda.com',
1942
+ 'mail2ryan.com',
1943
+ 'mail2sa.com',
1944
+ 'mail2sabrina.com',
1945
+ 'mail2safe.com',
1946
+ 'mail2sagittarius.com',
1947
+ 'mail2sail.com',
1948
+ 'mail2sailor.com',
1949
+ 'mail2sal.com',
1950
+ 'mail2salaam.com',
1951
+ 'mail2sam.com',
1952
+ 'mail2samantha.com',
1953
+ 'mail2samoa.com',
1954
+ 'mail2samurai.com',
1955
+ 'mail2sandra.com',
1956
+ 'mail2sandy.com',
1957
+ 'mail2sanfrancisco.com',
1958
+ 'mail2sanmarino.com',
1959
+ 'mail2santa.com',
1960
+ 'mail2sara.com',
1961
+ 'mail2sarah.com',
1962
+ 'mail2sat.com',
1963
+ 'mail2saturn.com',
1964
+ 'mail2saudi.com',
1965
+ 'mail2saudiarabia.com',
1966
+ 'mail2save.com',
1967
+ 'mail2savings.com',
1968
+ 'mail2school.com',
1969
+ 'mail2scientist.com',
1970
+ 'mail2scorpio.com',
1971
+ 'mail2scott.com',
1972
+ 'mail2sean.com',
1973
+ 'mail2search.com',
1974
+ 'mail2seattle.com',
1975
+ 'mail2secretagent.com',
1976
+ 'mail2senate.com',
1977
+ 'mail2senegal.com',
1978
+ 'mail2sensual.com',
1979
+ 'mail2seth.com',
1980
+ 'mail2sevenseas.com',
1981
+ 'mail2sexy.com',
1982
+ 'mail2seychelles.com',
1983
+ 'mail2shane.com',
1984
+ 'mail2sharon.com',
1985
+ 'mail2shawn.com',
1986
+ 'mail2ship.com',
1987
+ 'mail2shirley.com',
1988
+ 'mail2shoot.com',
1989
+ 'mail2shuttle.com',
1990
+ 'mail2sierraleone.com',
1991
+ 'mail2simon.com',
1992
+ 'mail2singapore.com',
1993
+ 'mail2single.com',
1994
+ 'mail2site.com',
1995
+ 'mail2skater.com',
1996
+ 'mail2skier.com',
1997
+ 'mail2sky.com',
1998
+ 'mail2sleek.com',
1999
+ 'mail2slim.com',
2000
+ 'mail2slovakia.com',
2001
+ 'mail2slovenia.com',
2002
+ 'mail2smile.com',
2003
+ 'mail2smith.com',
2004
+ 'mail2smooth.com',
2005
+ 'mail2soccer.com',
2006
+ 'mail2soccerfan.com',
2007
+ 'mail2socialist.com',
2008
+ 'mail2soldier.com',
2009
+ 'mail2somalia.com',
2010
+ 'mail2son.com',
2011
+ 'mail2song.com',
2012
+ 'mail2sos.com',
2013
+ 'mail2sound.com',
2014
+ 'mail2southafrica.com',
2015
+ 'mail2southamerica.com',
2016
+ 'mail2southcarolina.com',
2017
+ 'mail2southdakota.com',
2018
+ 'mail2southkorea.com',
2019
+ 'mail2southpole.com',
2020
+ 'mail2spain.com',
2021
+ 'mail2spanish.com',
2022
+ 'mail2spare.com',
2023
+ 'mail2spectrum.com',
2024
+ 'mail2splash.com',
2025
+ 'mail2sponsor.com',
2026
+ 'mail2sports.com',
2027
+ 'mail2srilanka.com',
2028
+ 'mail2stacy.com',
2029
+ 'mail2stan.com',
2030
+ 'mail2stanley.com',
2031
+ 'mail2star.com',
2032
+ 'mail2state.com',
2033
+ 'mail2stephanie.com',
2034
+ 'mail2steve.com',
2035
+ 'mail2steven.com',
2036
+ 'mail2stewart.com',
2037
+ 'mail2stlouis.com',
2038
+ 'mail2stock.com',
2039
+ 'mail2stockholm.com',
2040
+ 'mail2stockmarket.com',
2041
+ 'mail2storage.com',
2042
+ 'mail2store.com',
2043
+ 'mail2strong.com',
2044
+ 'mail2student.com',
2045
+ 'mail2studio.com',
2046
+ 'mail2studio54.com',
2047
+ 'mail2stuntman.com',
2048
+ 'mail2subscribe.com',
2049
+ 'mail2sudan.com',
2050
+ 'mail2superstar.com',
2051
+ 'mail2surfer.com',
2052
+ 'mail2suriname.com',
2053
+ 'mail2susan.com',
2054
+ 'mail2suzie.com',
2055
+ 'mail2swaziland.com',
2056
+ 'mail2sweden.com',
2057
+ 'mail2sweetheart.com',
2058
+ 'mail2swim.com',
2059
+ 'mail2swimmer.com',
2060
+ 'mail2swiss.com',
2061
+ 'mail2switzerland.com',
2062
+ 'mail2sydney.com',
2063
+ 'mail2sylvia.com',
2064
+ 'mail2syria.com',
2065
+ 'mail2taboo.com',
2066
+ 'mail2taiwan.com',
2067
+ 'mail2tajikistan.com',
2068
+ 'mail2tammy.com',
2069
+ 'mail2tango.com',
2070
+ 'mail2tanya.com',
2071
+ 'mail2tanzania.com',
2072
+ 'mail2tara.com',
2073
+ 'mail2taurus.com',
2074
+ 'mail2taxi.com',
2075
+ 'mail2taxidermist.com',
2076
+ 'mail2taylor.com',
2077
+ 'mail2taz.com',
2078
+ 'mail2teacher.com',
2079
+ 'mail2technician.com',
2080
+ 'mail2ted.com',
2081
+ 'mail2telephone.com',
2082
+ 'mail2teletubbie.com',
2083
+ 'mail2tenderness.com',
2084
+ 'mail2tennessee.com',
2085
+ 'mail2tennis.com',
2086
+ 'mail2tennisfan.com',
2087
+ 'mail2terri.com',
2088
+ 'mail2terry.com',
2089
+ 'mail2test.com',
2090
+ 'mail2texas.com',
2091
+ 'mail2thailand.com',
2092
+ 'mail2therapy.com',
2093
+ 'mail2think.com',
2094
+ 'mail2tickets.com',
2095
+ 'mail2tiffany.com',
2096
+ 'mail2tim.com',
2097
+ 'mail2time.com',
2098
+ 'mail2timothy.com',
2099
+ 'mail2tina.com',
2100
+ 'mail2titanic.com',
2101
+ 'mail2toby.com',
2102
+ 'mail2todd.com',
2103
+ 'mail2togo.com',
2104
+ 'mail2tom.com',
2105
+ 'mail2tommy.com',
2106
+ 'mail2tonga.com',
2107
+ 'mail2tony.com',
2108
+ 'mail2touch.com',
2109
+ 'mail2tourist.com',
2110
+ 'mail2tracey.com',
2111
+ 'mail2tracy.com',
2112
+ 'mail2tramp.com',
2113
+ 'mail2travel.com',
2114
+ 'mail2traveler.com',
2115
+ 'mail2travis.com',
2116
+ 'mail2trekkie.com',
2117
+ 'mail2trex.com',
2118
+ 'mail2triallawyer.com',
2119
+ 'mail2trick.com',
2120
+ 'mail2trillionaire.com',
2121
+ 'mail2troy.com',
2122
+ 'mail2truck.com',
2123
+ 'mail2trump.com',
2124
+ 'mail2try.com',
2125
+ 'mail2tunisia.com',
2126
+ 'mail2turbo.com',
2127
+ 'mail2turkey.com',
2128
+ 'mail2turkmenistan.com',
2129
+ 'mail2tv.com',
2130
+ 'mail2tycoon.com',
2131
+ 'mail2tyler.com',
2132
+ 'mail2u4me.com',
2133
+ 'mail2uae.com',
2134
+ 'mail2uganda.com',
2135
+ 'mail2uk.com',
2136
+ 'mail2ukraine.com',
2137
+ 'mail2uncle.com',
2138
+ 'mail2unsubscribe.com',
2139
+ 'mail2uptown.com',
2140
+ 'mail2uruguay.com',
2141
+ 'mail2usa.com',
2142
+ 'mail2utah.com',
2143
+ 'mail2uzbekistan.com',
2144
+ 'mail2v.com',
2145
+ 'mail2vacation.com',
2146
+ 'mail2valentines.com',
2147
+ 'mail2valerie.com',
2148
+ 'mail2valley.com',
2149
+ 'mail2vamoose.com',
2150
+ 'mail2vanessa.com',
2151
+ 'mail2vanuatu.com',
2152
+ 'mail2venezuela.com',
2153
+ 'mail2venous.com',
2154
+ 'mail2venus.com',
2155
+ 'mail2vermont.com',
2156
+ 'mail2vickie.com',
2157
+ 'mail2victor.com',
2158
+ 'mail2victoria.com',
2159
+ 'mail2vienna.com',
2160
+ 'mail2vietnam.com',
2161
+ 'mail2vince.com',
2162
+ 'mail2virginia.com',
2163
+ 'mail2virgo.com',
2164
+ 'mail2visionary.com',
2165
+ 'mail2vodka.com',
2166
+ 'mail2volleyball.com',
2167
+ 'mail2waiter.com',
2168
+ 'mail2wallstreet.com',
2169
+ 'mail2wally.com',
2170
+ 'mail2walter.com',
2171
+ 'mail2warren.com',
2172
+ 'mail2washington.com',
2173
+ 'mail2wave.com',
2174
+ 'mail2way.com',
2175
+ 'mail2waycool.com',
2176
+ 'mail2wayne.com',
2177
+ 'mail2webmaster.com',
2178
+ 'mail2webtop.com',
2179
+ 'mail2webtv.com',
2180
+ 'mail2weird.com',
2181
+ 'mail2wendell.com',
2182
+ 'mail2wendy.com',
2183
+ 'mail2westend.com',
2184
+ 'mail2westvirginia.com',
2185
+ 'mail2whether.com',
2186
+ 'mail2whip.com',
2187
+ 'mail2white.com',
2188
+ 'mail2whitehouse.com',
2189
+ 'mail2whitney.com',
2190
+ 'mail2why.com',
2191
+ 'mail2wilbur.com',
2192
+ 'mail2wild.com',
2193
+ 'mail2willard.com',
2194
+ 'mail2willie.com',
2195
+ 'mail2wine.com',
2196
+ 'mail2winner.com',
2197
+ 'mail2wired.com',
2198
+ 'mail2wisconsin.com',
2199
+ 'mail2woman.com',
2200
+ 'mail2wonder.com',
2201
+ 'mail2world.com',
2202
+ 'mail2worship.com',
2203
+ 'mail2wow.com',
2204
+ 'mail2www.com',
2205
+ 'mail2wyoming.com',
2206
+ 'mail2xfiles.com',
2207
+ 'mail2xox.com',
2208
+ 'mail2yachtclub.com',
2209
+ 'mail2yahalla.com',
2210
+ 'mail2yemen.com',
2211
+ 'mail2yes.com',
2212
+ 'mail2yugoslavia.com',
2213
+ 'mail2zack.com',
2214
+ 'mail2zambia.com',
2215
+ 'mail2zenith.com',
2216
+ 'mail2zephir.com',
2217
+ 'mail2zeus.com',
2218
+ 'mail2zipper.com',
2219
+ 'mail2zoo.com',
2220
+ 'mail2zoologist.com',
2221
+ 'mail2zurich.com',
2222
+ 'mail3000.com',
2223
+ 'mail333.com',
2224
+ 'mailandftp.com',
2225
+ 'mailandnews.com',
2226
+ 'mailas.com',
2227
+ 'mailasia.com',
2228
+ 'mailbolt.com',
2229
+ 'mailbomb.net',
2230
+ 'mailbox.as',
2231
+ 'mailbox.co.za',
2232
+ 'mailbox.gr',
2233
+ 'mailbox.hu',
2234
+ 'mailbr.com.br',
2235
+ 'mailc.net',
2236
+ 'mailcan.com',
2237
+ 'mailchoose.co',
2238
+ 'mailcity.com',
2239
+ 'mailclub.fr',
2240
+ 'mailclub.net',
2241
+ 'mailexcite.com',
2242
+ 'mailforce.net',
2243
+ 'mailftp.com',
2244
+ 'mailgenie.net',
2245
+ 'mailhaven.com',
2246
+ 'mailhood.com',
2247
+ 'mailingweb.com',
2248
+ 'mailisent.com',
2249
+ 'mailite.com',
2250
+ 'mailme.dk',
2251
+ 'mailmight.com',
2252
+ 'mailmij.nl',
2253
+ 'mailnew.com',
2254
+ 'mailops.com',
2255
+ 'mailoye.com',
2256
+ 'mailpanda.com',
2257
+ 'mailpride.com',
2258
+ 'mailpuppy.com',
2259
+ 'mailroom.com',
2260
+ 'mailru.com',
2261
+ 'mailsent.net',
2262
+ 'mailsurf.com',
2263
+ 'mailup.net',
2264
+ 'maktoob.com',
2265
+ 'malayalamtelevision.net',
2266
+ 'manager.de',
2267
+ 'mantrafreenet.com',
2268
+ 'mantramail.com',
2269
+ 'mantraonline.com',
2270
+ 'marchmail.com',
2271
+ 'marijuana.nl',
2272
+ 'married-not.com',
2273
+ 'marsattack.com',
2274
+ 'masrawy.com',
2275
+ 'mauimail.com',
2276
+ 'maxleft.com',
2277
+ 'mbox.com.au',
2278
+ 'mchsi.com',
2279
+ 'me.com',
2280
+ 'me-mail.hu',
2281
+ 'meetingmall.com',
2282
+ 'megago.com',
2283
+ 'megamail.pt',
2284
+ 'mehrani.com',
2285
+ 'mehtaweb.com',
2286
+ 'melodymail.com',
2287
+ 'meloo.com',
2288
+ 'message.hu',
2289
+ 'metacrawler.com',
2290
+ 'metta.lk',
2291
+ 'miesto.sk',
2292
+ 'mighty.co.za',
2293
+ 'miho-nakayama.com',
2294
+ 'millionaireintraining.com',
2295
+ 'milmail.com',
2296
+ 'misery.net',
2297
+ 'mittalweb.com',
2298
+ 'mixmail.com',
2299
+ 'ml1.net',
2300
+ 'mobilbatam.com',
2301
+ 'mohammed.com',
2302
+ 'moldova.cc',
2303
+ 'moldova.com',
2304
+ 'moldovacc.com',
2305
+ 'montevideo.com.uy',
2306
+ 'moonman.com',
2307
+ 'moose-mail.com',
2308
+ 'mortaza.com',
2309
+ 'mosaicfx.com',
2310
+ 'most-wanted.com',
2311
+ 'mostlysunny.com',
2312
+ 'motormania.com',
2313
+ 'movemail.com',
2314
+ 'mp4.it',
2315
+ 'mr-potatohead.com',
2316
+ 'mscold.com',
2317
+ 'msgbox.com',
2318
+ 'msn.com',
2319
+ 'msn.cn',
2320
+ 'mundomail.net',
2321
+ 'munich.com',
2322
+ 'musician.org',
2323
+ 'musicscene.org',
2324
+ 'mybox.it',
2325
+ 'mycabin.com',
2326
+ 'mycity.com',
2327
+ 'mycool.com',
2328
+ 'mydomain.com',
2329
+ 'mydotcomaddress.com',
2330
+ 'myfamily.com',
2331
+ 'myiris.com',
2332
+ 'mynamedot.com',
2333
+ 'mynetaddress.com',
2334
+ 'myownemail.com',
2335
+ 'myownfriends.com',
2336
+ 'mypersonalemail.com',
2337
+ 'myplace.com',
2338
+ 'myrealbox.com',
2339
+ 'myself.com',
2340
+ 'mystupidjob.com',
2341
+ 'myway.com',
2342
+ 'myworldmail.com',
2343
+ 'n2.com',
2344
+ 'n2business.com',
2345
+ 'n2mail.com',
2346
+ 'n2software.com',
2347
+ 'nabc.biz',
2348
+ 'nagpal.net',
2349
+ 'nakedgreens.com',
2350
+ 'name.com',
2351
+ 'nameplanet.com',
2352
+ 'nandomail.com',
2353
+ 'naseej.com',
2354
+ 'nativestar.net',
2355
+ 'nativeweb.net',
2356
+ 'navigator.lv',
2357
+ 'neeva.net',
2358
+ 'nemra1.com',
2359
+ 'nenter.com',
2360
+ 'nervhq.org',
2361
+ 'net4b.pt',
2362
+ 'net4you.at',
2363
+ 'netbounce.com',
2364
+ 'netbroadcaster.com',
2365
+ 'netcenter-vn.net',
2366
+ 'netcourrier.com',
2367
+ 'netexecutive.com',
2368
+ 'netexpressway.com',
2369
+ 'netian.com',
2370
+ 'netizen.com.ar',
2371
+ 'netlane.com',
2372
+ 'netlimit.com',
2373
+ 'netmongol.com',
2374
+ 'netpiper.com',
2375
+ 'netposta.net',
2376
+ 'netralink.com',
2377
+ 'netscape.net',
2378
+ 'netscapeonline.co.uk',
2379
+ 'netspeedway.com',
2380
+ 'netsquare.com',
2381
+ 'netster.com',
2382
+ 'nettaxi.com',
2383
+ 'netzero.com',
2384
+ 'netzero.net',
2385
+ 'newmail.com',
2386
+ 'newmail.net',
2387
+ 'newmail.ru',
2388
+ 'newyork.com',
2389
+ 'nfmail.com',
2390
+ 'nicegal.com',
2391
+ 'nicholastse.net',
2392
+ 'nicolastse.com',
2393
+ 'nightmail.com',
2394
+ 'nikopage.com',
2395
+ 'nirvanafan.com',
2396
+ 'noavar.com',
2397
+ 'norika-fujiwara.com',
2398
+ 'norikomail.com',
2399
+ 'northgates.net',
2400
+ 'nospammail.net',
2401
+ 'ny.com',
2402
+ 'nyc.com',
2403
+ 'nycmail.com',
2404
+ 'nzoomail.com',
2405
+ 'o-tay.com',
2406
+ 'o2.co.uk',
2407
+ 'oceanfree.net',
2408
+ 'oddpost.com',
2409
+ 'odmail.com',
2410
+ 'oicexchange.com',
2411
+ 'okbank.com',
2412
+ 'okhuman.com',
2413
+ 'okmad.com',
2414
+ 'okmagic.com',
2415
+ 'okname.net',
2416
+ 'okuk.com',
2417
+ 'ole.com',
2418
+ 'olemail.com',
2419
+ 'olympist.net',
2420
+ 'omaninfo.com',
2421
+ 'onebox.com',
2422
+ 'onenet.com.ar',
2423
+ 'onet.pl',
2424
+ 'oninet.pt',
2425
+ 'online.ie',
2426
+ 'onlinewiz.com',
2427
+ 'onmilwaukee.com',
2428
+ 'onobox.com',
2429
+ 'operamail.com',
2430
+ 'optician.com',
2431
+ 'optonline.net',
2432
+ 'orbitel.bg',
2433
+ 'orgmail.net',
2434
+ 'osite.com.br',
2435
+ 'oso.com',
2436
+ 'otakumail.com',
2437
+ 'our-computer.com',
2438
+ 'our-office.com',
2439
+ 'ourbrisbane.com',
2440
+ 'ournet.md',
2441
+ 'outgun.com',
2442
+ 'outlook.com',
2443
+ 'over-the-rainbow.com',
2444
+ 'ownmail.net',
2445
+ 'packersfan.com',
2446
+ 'pakistanoye.com',
2447
+ 'palestinemail.com',
2448
+ 'parkjiyoon.com',
2449
+ 'parrot.com',
2450
+ 'partlycloudy.com',
2451
+ 'partynight.at',
2452
+ 'parvazi.com',
2453
+ 'pcpostal.com',
2454
+ 'pediatrician.com',
2455
+ 'penpen.com',
2456
+ 'peopleweb.com',
2457
+ 'perfectmail.com',
2458
+ 'personal.ro',
2459
+ 'personales.com',
2460
+ 'petml.com',
2461
+ 'pettypool.com',
2462
+ 'pezeshkpour.com',
2463
+ 'phayze.com',
2464
+ 'phreaker.net',
2465
+ 'picusnet.com',
2466
+ 'pigpig.net',
2467
+ 'pinoymail.com',
2468
+ 'piracha.net',
2469
+ 'pisem.net',
2470
+ 'planetaccess.com',
2471
+ 'planetout.com',
2472
+ 'plasa.com',
2473
+ 'playersodds.com',
2474
+ 'playful.com',
2475
+ 'plusmail.com.br',
2476
+ 'pmail.net',
2477
+ 'pobox.hu',
2478
+ 'pobox.sk',
2479
+ 'pochta.ru',
2480
+ 'poczta.fm',
2481
+ 'poetic.com',
2482
+ 'polbox.com',
2483
+ 'policeoffice.com',
2484
+ 'pool-sharks.com',
2485
+ 'poond.com',
2486
+ 'popmail.com',
2487
+ 'popsmail.com',
2488
+ 'popstar.com',
2489
+ 'portugalmail.com',
2490
+ 'portugalmail.pt',
2491
+ 'portugalnet.com',
2492
+ 'positive-thinking.com',
2493
+ 'post.com',
2494
+ 'post.cz',
2495
+ 'post.sk',
2496
+ 'postaccesslite.com',
2497
+ 'postafree.com',
2498
+ 'postaweb.com',
2499
+ 'postinbox.com',
2500
+ 'postino.ch',
2501
+ 'postmaster.co.uk',
2502
+ 'postpro.net',
2503
+ 'powerfan.com',
2504
+ 'praize.com',
2505
+ 'premiumservice.com',
2506
+ 'presidency.com',
2507
+ 'press.co.jp',
2508
+ 'priest.com',
2509
+ 'primposta.com',
2510
+ 'primposta.hu',
2511
+ 'pro.hu',
2512
+ 'progetplus.it',
2513
+ 'programmer.net',
2514
+ 'programozo.hu',
2515
+ 'proinbox.com',
2516
+ 'project2k.com',
2517
+ 'promessage.com',
2518
+ 'prontomail.com',
2519
+ 'psv-supporter.com',
2520
+ 'publicist.com',
2521
+ 'pulp-fiction.com',
2522
+ 'punkass.com',
2523
+ 'qatarmail.com',
2524
+ 'qprfans.com',
2525
+ 'qrio.com',
2526
+ 'quackquack.com',
2527
+ 'qudsmail.com',
2528
+ 'quepasa.com',
2529
+ 'quickwebmail.com',
2530
+ 'r-o-o-t.com',
2531
+ 'raakim.com',
2532
+ 'racingfan.com.au',
2533
+ 'radicalz.com',
2534
+ 'ragingbull.com',
2535
+ 'ranmamail.com',
2536
+ 'rastogi.net',
2537
+ 'rattle-snake.com',
2538
+ 'ravearena.com',
2539
+ 'razormail.com',
2540
+ 'rccgmail.org',
2541
+ 'realemail.net',
2542
+ 'reallyfast.biz',
2543
+ 'rediffmail.com',
2544
+ 'rediffmailpro.com',
2545
+ 'rednecks.com',
2546
+ 'redseven.de',
2547
+ 'redsfans.com',
2548
+ 'registerednurses.com',
2549
+ 'repairman.com',
2550
+ 'reply.hu',
2551
+ 'representative.com',
2552
+ 'rescueteam.com',
2553
+ 'rezai.com',
2554
+ 'rickymail.com',
2555
+ 'rin.ru',
2556
+ 'rn.com',
2557
+ 'rock.com',
2558
+ 'rocketmail.com',
2559
+ 'rodrun.com',
2560
+ 'rogers.com',
2561
+ 'rome.com',
2562
+ 'roughnet.com',
2563
+ 'rubyridge.com',
2564
+ 'runbox.com',
2565
+ 'rushpost.com',
2566
+ 'ruttolibero.com',
2567
+ 's-mail.com',
2568
+ 'sabreshockey.com',
2569
+ 'sacbeemail.com',
2570
+ 'safe-mail.net',
2571
+ 'sailormoon.com',
2572
+ 'saintly.com',
2573
+ 'sale-sale-sale.com',
2574
+ 'salehi.net',
2575
+ 'samerica.com',
2576
+ 'samilan.net',
2577
+ 'sammimail.com',
2578
+ 'sanfranmail.com',
2579
+ 'sanook.com',
2580
+ 'sapo.pt',
2581
+ 'saudia.com',
2582
+ 'sayhi.net',
2583
+ 'sbcglobal.net',
2584
+ 'scandalmail.com',
2585
+ 'schweiz.org',
2586
+ 'sci.fi',
2587
+ 'scientist.com',
2588
+ 'scifianime.com',
2589
+ 'scottishmail.co.uk',
2590
+ 'scubadiving.com',
2591
+ 'searchwales.com',
2592
+ 'sebil.com',
2593
+ 'secret-police.com',
2594
+ 'secretservices.net',
2595
+ 'seductive.com',
2596
+ 'seekstoyboy.com',
2597
+ 'send.hu',
2598
+ 'sendme.cz',
2599
+ 'sent.com',
2600
+ 'serga.com.ar',
2601
+ 'servemymail.com',
2602
+ 'sesmail.com',
2603
+ 'sexmagnet.com',
2604
+ 'seznam.cz',
2605
+ 'shahweb.net',
2606
+ 'shaniastuff.com',
2607
+ 'sharmaweb.com',
2608
+ 'shaw.ca',
2609
+ 'she.com',
2610
+ 'shootmail.com',
2611
+ 'shotgun.hu',
2612
+ 'shuf.com',
2613
+ 'sialkotcity.com',
2614
+ 'sialkotian.com',
2615
+ 'sialkotoye.com',
2616
+ 'sify.com',
2617
+ 'sinamail.com',
2618
+ 'singapore.com',
2619
+ 'singmail.com',
2620
+ 'singnet.com.sg',
2621
+ 'skim.com',
2622
+ 'skizo.hu',
2623
+ 'slamdunkfan.com',
2624
+ 'slingshot.com',
2625
+ 'slo.net',
2626
+ 'slotter.com',
2627
+ 'smapxsmap.net',
2628
+ 'smileyface.comsmithemail.net',
2629
+ 'smoothmail.com',
2630
+ 'snail-mail.net',
2631
+ 'snakemail.com',
2632
+ 'sndt.net',
2633
+ 'sneakemail.com',
2634
+ 'sniper.hu',
2635
+ 'snoopymail.com',
2636
+ 'snowboarding.com',
2637
+ 'snowdonia.net',
2638
+ 'socamail.com',
2639
+ 'sociologist.com',
2640
+ 'softhome.net',
2641
+ 'sol.dk',
2642
+ 'soldier.hu',
2643
+ 'soon.com',
2644
+ 'soulfoodcookbook.com',
2645
+ 'sp.nl',
2646
+ 'space.com',
2647
+ 'spacetowns.com',
2648
+ 'spamex.com',
2649
+ 'spartapiet.com',
2650
+ 'spazmail.com',
2651
+ 'speedpost.net',
2652
+ 'spils.com',
2653
+ 'spinfinder.com',
2654
+ 'sportemail.com',
2655
+ 'spray.no',
2656
+ 'spray.se',
2657
+ 'spymac.com',
2658
+ 'srilankan.net',
2659
+ 'st-davids.net',
2660
+ 'stade.fr',
2661
+ 'stargateradio.com',
2662
+ 'starmail.com',
2663
+ 'starmail.org',
2664
+ 'starmedia.com',
2665
+ 'starplace.com',
2666
+ 'starspath.com',
2667
+ 'start.com.au',
2668
+ 'stopdropandroll.com',
2669
+ 'stribmail.com',
2670
+ 'strompost.com',
2671
+ 'strongguy.com',
2672
+ 'subram.com',
2673
+ 'sudanmail.net',
2674
+ 'suhabi.com',
2675
+ 'suisse.org',
2676
+ 'sunpoint.net',
2677
+ 'sunrise-sunset.com',
2678
+ 'sunsgame.com',
2679
+ 'sunumail.sn',
2680
+ 'superdada.com',
2681
+ 'supereva.it',
2682
+ 'supermail.ru',
2683
+ 'surf3.net',
2684
+ 'surfy.net',
2685
+ 'surimail.com',
2686
+ 'survivormail.com',
2687
+ 'sweb.cz',
2688
+ 'swiftdesk.com',
2689
+ 'swirve.com',
2690
+ 'swissinfo.org',
2691
+ 'swissmail.net',
2692
+ 'switchboardmail.com',
2693
+ 'switzerland.org',
2694
+ 'sx172.com',
2695
+ 'syom.com',
2696
+ 'syriamail.com',
2697
+ 't2mail.com',
2698
+ 'takuyakimura.com',
2699
+ 'talk21.com',
2700
+ 'talkcity.com',
2701
+ 'tamil.com',
2702
+ 'tatanova.com',
2703
+ 'tech4peace.org',
2704
+ 'techemail.com',
2705
+ 'techie.com',
2706
+ 'technisamail.co.za',
2707
+ 'technologist.com',
2708
+ 'teenagedirtbag.com',
2709
+ 'telebot.com',
2710
+ 'teleline.es',
2711
+ 'telinco.net',
2712
+ 'telkom.net',
2713
+ 'telpage.net',
2714
+ 'tenchiclub.com',
2715
+ 'tenderkiss.com',
2716
+ 'terra.cl',
2717
+ 'terra.com',
2718
+ 'terra.com.ar',
2719
+ 'terra.com.br',
2720
+ 'terra.es',
2721
+ 'tfanus.com.er',
2722
+ 'tfz.net',
2723
+ 'thai.com',
2724
+ 'thaimail.com',
2725
+ 'thaimail.net',
2726
+ 'the-african.com',
2727
+ 'the-airforce.com',
2728
+ 'the-aliens.com',
2729
+ 'the-american.com',
2730
+ 'the-animal.com',
2731
+ 'the-army.com',
2732
+ 'the-astronaut.com',
2733
+ 'the-beauty.com',
2734
+ 'the-big-apple.com',
2735
+ 'the-biker.com',
2736
+ 'the-boss.com',
2737
+ 'the-brazilian.com',
2738
+ 'the-canadian.com',
2739
+ 'the-canuck.com',
2740
+ 'the-captain.com',
2741
+ 'the-chinese.com',
2742
+ 'the-country.com',
2743
+ 'the-cowboy.com',
2744
+ 'the-davis-home.com',
2745
+ 'the-dutchman.com',
2746
+ 'the-eagles.com',
2747
+ 'the-englishman.com',
2748
+ 'the-fastest.net',
2749
+ 'the-fool.com',
2750
+ 'the-frenchman.com',
2751
+ 'the-galaxy.net',
2752
+ 'the-genius.com',
2753
+ 'the-gentleman.com',
2754
+ 'the-german.com',
2755
+ 'the-gremlin.com',
2756
+ 'the-hooligan.com',
2757
+ 'the-italian.com',
2758
+ 'the-japanese.com',
2759
+ 'the-lair.com',
2760
+ 'the-madman.com',
2761
+ 'the-mailinglist.com',
2762
+ 'the-marine.com',
2763
+ 'the-master.com',
2764
+ 'the-mexican.com',
2765
+ 'the-ministry.com',
2766
+ 'the-monkey.com',
2767
+ 'the-newsletter.net',
2768
+ 'the-pentagon.com',
2769
+ 'the-police.com',
2770
+ 'the-prayer.com',
2771
+ 'the-professional.com',
2772
+ 'the-quickest.com',
2773
+ 'the-russian.com',
2774
+ 'the-snake.com',
2775
+ 'the-spaceman.com',
2776
+ 'the-stock-market.com',
2777
+ 'the-student.net',
2778
+ 'the-whitehouse.net',
2779
+ 'the-wild-west.com',
2780
+ 'the18th.com',
2781
+ 'thecoolguy.com',
2782
+ 'thecriminals.com',
2783
+ 'thedoghousemail.com',
2784
+ 'theend.hu',
2785
+ 'thegolfcourse.com',
2786
+ 'thegooner.com',
2787
+ 'theheadoffice.com',
2788
+ 'thelanddownunder.com',
2789
+ 'theoffice.net',
2790
+ 'thepokerface.com',
2791
+ 'thepostmaster.net',
2792
+ 'theraces.com',
2793
+ 'theracetrack.com',
2794
+ 'thestreetfighter.com',
2795
+ 'theteebox.com',
2796
+ 'thewatercooler.com',
2797
+ 'thewebpros.co.uk',
2798
+ 'thewizzard.com',
2799
+ 'thewizzkid.com',
2800
+ 'thezhangs.net',
2801
+ 'thirdage.com',
2802
+ 'thundermail.com',
2803
+ 'tidni.com',
2804
+ 'timein.net',
2805
+ 'tiscali.at',
2806
+ 'tiscali.be',
2807
+ 'tiscali.co.uk',
2808
+ 'tiscali.lu',
2809
+ 'tiscali.se',
2810
+ 'tkcity.com',
2811
+ 'topchat.com',
2812
+ 'topgamers.co.uk',
2813
+ 'topletter.com',
2814
+ 'topmail.com.ar',
2815
+ 'topsurf.com',
2816
+ 'torchmail.com',
2817
+ 'townisp.com',
2818
+ 'travel.li',
2819
+ 'trialbytrivia.com',
2820
+ 'trmailbox.com',
2821
+ 'tropicalstorm.com',
2822
+ 'trust-me.com',
2823
+ 'tsamail.co.za',
2824
+ 'ttml.co.in',
2825
+ 'tunisiamail.com',
2826
+ 'turkey.com',
2827
+ 'twinstarsmail.com',
2828
+ 'tx.rr.com',
2829
+ 'tycoonmail.com',
2830
+ 'typemail.com',
2831
+ 'u2club.com',
2832
+ 'uae.ac',
2833
+ 'uaemail.com',
2834
+ 'ubbi.com',
2835
+ 'ubbi.com.br',
2836
+ 'uboot.com',
2837
+ 'uk2k.com',
2838
+ 'uk2net.com',
2839
+ 'uk7.net',
2840
+ 'uk8.net',
2841
+ 'ukbuilder.com',
2842
+ 'ukcool.com',
2843
+ 'ukdreamcast.com',
2844
+ 'ukr.net',
2845
+ 'uku.co.uk',
2846
+ 'ultapulta.com',
2847
+ 'ultrapostman.com',
2848
+ 'ummah.org',
2849
+ 'umpire.com',
2850
+ 'unbounded.com',
2851
+ 'unican.es',
2852
+ 'unihome.com',
2853
+ 'universal.pt',
2854
+ 'uno.ee',
2855
+ 'uno.it',
2856
+ 'unofree.it',
2857
+ 'uol.com.ar',
2858
+ 'uol.com.br',
2859
+ 'uol.com.co',
2860
+ 'uol.com.mx',
2861
+ 'uol.com.ve',
2862
+ 'uole.com',
2863
+ 'uole.com.ve',
2864
+ 'uolmail.com',
2865
+ 'uomail.com',
2866
+ 'ureach.com',
2867
+ 'urgentmail.biz',
2868
+ 'usa.com',
2869
+ 'usanetmail.com',
2870
+ 'uymail.com',
2871
+ 'uyuyuy.com',
2872
+ 'v-sexi.com',
2873
+ 'velnet.co.uk',
2874
+ 'velocall.com',
2875
+ 'verizon.net',
2876
+ 'verizonmail.com',
2877
+ 'veryfast.biz',
2878
+ 'veryspeedy.net',
2879
+ 'violinmakers.co.uk',
2880
+ 'vip.gr',
2881
+ 'vipmail.ru',
2882
+ 'virgilio.it',
2883
+ 'virgin.net',
2884
+ 'virtualmail.com',
2885
+ 'visitmail.com',
2886
+ 'visto.com',
2887
+ 'vivianhsu.net',
2888
+ 'vjtimail.com',
2889
+ 'vnn.vn',
2890
+ 'volcanomail.com',
2891
+ 'vote-democrats.com',
2892
+ 'vote-hillary.com',
2893
+ 'vote-republicans.com',
2894
+ 'wahoye.com',
2895
+ 'wales2000.net',
2896
+ 'wam.co.za',
2897
+ 'wanadoo.es',
2898
+ 'warmmail.com',
2899
+ 'warpmail.net',
2900
+ 'warrior.hu',
2901
+ 'waumail.com',
2902
+ 'wearab.net',
2903
+ 'web-mail.com.ar',
2904
+ 'web-police.com',
2905
+ 'web.de',
2906
+ 'webave.com',
2907
+ 'webcity.ca',
2908
+ 'webdream.com',
2909
+ 'webindia123.com',
2910
+ 'webjump.com',
2911
+ 'webmail.co.yu',
2912
+ 'webmail.co.za',
2913
+ 'webmail.hu',
2914
+ 'webmails.com',
2915
+ 'webprogramming.com',
2916
+ 'webstation.com',
2917
+ 'websurfer.co.za',
2918
+ 'webtopmail.com',
2919
+ 'weedmail.com',
2920
+ 'weekonline.com',
2921
+ 'wehshee.com',
2922
+ 'welsh-lady.com',
2923
+ 'whartontx.com',
2924
+ 'wheelweb.com',
2925
+ 'whipmail.com',
2926
+ 'whoever.com',
2927
+ 'whoopymail.com',
2928
+ 'wildmail.com',
2929
+ 'windstream.com',
2930
+ 'winmail.com.au',
2931
+ 'winning.com',
2932
+ 'witty.com',
2933
+ 'wolf-web.com',
2934
+ 'wombles.com',
2935
+ 'wongfaye.com',
2936
+ 'wooow.it',
2937
+ 'workmail.com',
2938
+ 'worldemail.com',
2939
+ 'wosaddict.com',
2940
+ 'wouldilie.com',
2941
+ 'wowmail.com',
2942
+ 'wp.pl',
2943
+ 'wrexham.net',
2944
+ 'writeme.com',
2945
+ 'writemeback.com',
2946
+ 'wrongmail.com',
2947
+ 'www.com',
2948
+ 'wx88.net',
2949
+ 'wxs.net',
2950
+ 'x-mail.net',
2951
+ 'x5g.com',
2952
+ 'xmsg.com',
2953
+ 'xoom.com',
2954
+ 'xsmail.com',
2955
+ 'xuno.com',
2956
+ 'xzapmail.com',
2957
+ 'yada-yada.com',
2958
+ 'yaho.com',
2959
+ 'yahoo.ca',
2960
+ 'yahoo.co.in',
2961
+ 'yahoo.co.jp',
2962
+ 'yahoo.co.kr',
2963
+ 'yahoo.co.nz',
2964
+ 'yahoo.co.uk',
2965
+ 'yahoo.com',
2966
+ 'yahoo.com.ar',
2967
+ 'yahoo.com.au',
2968
+ 'yahoo.com.br',
2969
+ 'yahoo.com.cn',
2970
+ 'yahoo.com.hk',
2971
+ 'yahoo.com.is',
2972
+ 'yahoo.com.mx',
2973
+ 'yahoo.com.ru',
2974
+ 'yahoo.com.sg',
2975
+ 'yahoo.de',
2976
+ 'yahoo.dk',
2977
+ 'yahoo.es',
2978
+ 'yahoo.fr',
2979
+ 'yahoo.ie',
2980
+ 'yahoo.it',
2981
+ 'yahoo.jp',
2982
+ 'yahoo.ru',
2983
+ 'yahoo.se',
2984
+ 'yahoofs.com',
2985
+ 'yalla.com',
2986
+ 'yalla.com.lb',
2987
+ 'yalook.com',
2988
+ 'yam.com',
2989
+ 'yandex.ru',
2990
+ 'yapost.com',
2991
+ 'yebox.com',
2992
+ 'yehey.com',
2993
+ 'yemenmail.com',
2994
+ 'yepmail.net',
2995
+ 'yifan.net',
2996
+ 'ymail.com',
2997
+ 'yopolis.com',
2998
+ 'youareadork.com',
2999
+ 'your-house.com',
3000
+ 'yourinbox.com',
3001
+ 'yourlover.net',
3002
+ 'yournightmare.com',
3003
+ 'yours.com',
3004
+ 'yourssincerely.com',
3005
+ 'yourteacher.net',
3006
+ 'yourwap.com',
3007
+ 'yuuhuu.net',
3008
+ 'yyhmail.com',
3009
+ 'zahadum.com',
3010
+ 'zeepost.nl',
3011
+ 'zhaowei.net',
3012
+ 'zip.net',
3013
+ 'zipido.com',
3014
+ 'ziplip.com',
3015
+ 'zipmail.com',
3016
+ 'zipmail.com.br',
3017
+ 'zipmax.com',
3018
+ 'zmail.ru',
3019
+ 'zonnet.nl',
3020
+ 'zubee.com',
3021
+ 'zuvio.com',
3022
+ 'zwallet.com',
3023
+ 'zybermail.com',
3024
+ 'zzn.com',
3025
+ 'zzom.co.uk');
power-ups/lookups/admin/lookups-admin.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //=============================================
3
+ // Include Needed Files
4
+ //=============================================
5
+
6
+ //=============================================
7
+ // WPLeadInLookupsAdmin Class
8
+ //=============================================
9
+ class WPLeadInLookupsAdmin extends WPLeadInAdmin {
10
+
11
+ /**
12
+ * Class constructor
13
+ */
14
+ var $action;
15
+
16
+ function __construct ()
17
+ {
18
+ //=============================================
19
+ // Hooks & Filters
20
+ //=============================================
21
+
22
+
23
+ }
24
+
25
+ //=============================================
26
+ // Settings Page
27
+ //=============================================
28
+
29
+ /**
30
+ * Creates settings page
31
+ */
32
+ function power_up_setup_callback ()
33
+ {
34
+
35
+ }
36
+
37
+ //=============================================
38
+ // Admin Styles & Scripts
39
+ //=============================================
40
+
41
+
42
+ }
43
+
44
+ ?>
power-ups/mailchimp-connect.php CHANGED
@@ -43,6 +43,7 @@ class WPMailChimpConnect extends WPLeadIn {
43
 
44
  var $admin;
45
  var $options;
 
46
 
47
  /**
48
  * Class constructor
@@ -58,7 +59,7 @@ class WPMailChimpConnect extends WPLeadIn {
58
 
59
  global $leadin_mailchimp_connect_wp;
60
  $leadin_mailchimp_connect_wp = $this;
61
- $this->options = get_option('leadin_mls_options');
62
  }
63
 
64
  public function admin_init ( )
@@ -111,33 +112,9 @@ class WPMailChimpConnect extends WPLeadIn {
111
  )
112
  ));
113
 
114
- return $contact_synced;
115
- }
116
-
117
- return FALSE;
118
- }
119
 
120
- /**
121
- * Removes an email address from a specific list
122
- *
123
- * @param string
124
- * @param string
125
- * @return int/bool API status code OR false if api key not set
126
- */
127
- function remove_contact_from_list ( $list_id = '', $email = '' )
128
- {
129
- if ( isset($this->options['li_mls_api_key']) && $this->options['li_mls_api_key'] && $list_id )
130
- {
131
- $MailChimp = new LI_MailChimp($this->options['li_mls_api_key']);
132
- $contact_removed = $MailChimp->call("lists/unsubscribe ", array(
133
- "id" => $list_id,
134
- "email" => array('email' => $email),
135
- "delete_member" => TRUE,
136
- "send_goodbye" => FALSE,
137
- "send_notify" => FALSE
138
- ));
139
-
140
- return $contact_removed;
141
  }
142
 
143
  return FALSE;
@@ -182,6 +159,8 @@ class WPMailChimpConnect extends WPLeadIn {
182
  "batch" => $batch_contacts,
183
  ));
184
 
 
 
185
  return $list_updated;
186
  }
187
 
@@ -190,7 +169,7 @@ class WPMailChimpConnect extends WPLeadIn {
190
  }
191
 
192
  //=============================================
193
- // Subscribe Widget Init
194
  //=============================================
195
 
196
  global $leadin_mailchimp_connect_wp;
43
 
44
  var $admin;
45
  var $options;
46
+ var $power_option_name = 'leadin_mls_options';
47
 
48
  /**
49
  * Class constructor
59
 
60
  global $leadin_mailchimp_connect_wp;
61
  $leadin_mailchimp_connect_wp = $this;
62
+ $this->options = get_option($this->power_option_name);
63
  }
64
 
65
  public function admin_init ( )
112
  )
113
  ));
114
 
115
+ leadin_track_plugin_activity('Contact Pushed to List', array('esp_connector' => 'mailchimp'));
 
 
 
 
116
 
117
+ return $contact_synced;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
 
120
  return FALSE;
159
  "batch" => $batch_contacts,
160
  ));
161
 
162
+ leadin_track_plugin_activity('Bulk Contacts Pushed to List', array('esp_connector' => 'mailchimp'));
163
+
164
  return $list_updated;
165
  }
166
 
169
  }
170
 
171
  //=============================================
172
+ // ESP Connect Init
173
  //=============================================
174
 
175
  global $leadin_mailchimp_connect_wp;
power-ups/mailchimp-connect/admin/mailchimp-connect-admin.php CHANGED
@@ -5,6 +5,7 @@
5
  class WPMailChimpConnectAdmin extends WPLeadInAdmin {
6
 
7
  var $power_up_settings_section = 'leadin_mls_options_section';
 
8
  var $power_up_icon;
9
  var $options;
10
  var $authed = FALSE;
@@ -22,8 +23,8 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
22
  if ( is_admin() )
23
  {
24
  $this->power_up_icon = $power_up_icon_small;
25
- add_action('admin_init', array($this, 'leadin_mls_build_settings_page'));
26
- $this->options = get_option('leadin_mls_options');
27
  $this->authed = ( isset($this->options['li_mls_api_key']) && $this->options['li_mls_api_key'] ? TRUE : FALSE );
28
 
29
  if ( $this->authed )
@@ -38,9 +39,9 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
38
  /**
39
  * Creates settings options
40
  */
41
- function leadin_mls_build_settings_page ()
42
  {
43
- register_setting('leadin_settings_options', 'leadin_mls_options', array($this, 'sanitize'));
44
  add_settings_section($this->power_up_settings_section, $this->power_up_icon . "MailChimp", '', LEADIN_ADMIN_PATH);
45
  add_settings_field('li_mls_api_key', 'API key', array($this, 'li_mls_api_key_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
46
 
@@ -63,9 +64,6 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
63
  if( isset( $input['li_mls_api_key'] ) )
64
  $new_input['li_mls_api_key'] = sanitize_text_field( $input['li_mls_api_key'] );
65
 
66
- if( isset( $input['li_mls_subscribers_to_list'] ) )
67
- $new_input['li_mls_subscribers_to_list'] = sanitize_text_field( $input['li_mls_subscribers_to_list'] );
68
-
69
  return $new_input;
70
  }
71
 
@@ -77,12 +75,12 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
77
  $li_mls_api_key = ( $this->options['li_mls_api_key'] ? $this->options['li_mls_api_key'] : '' ); // Get header from options, or show default
78
 
79
  printf(
80
- '<input id="li_mls_api_key" type="text" id="title" name="leadin_mls_options[li_mls_api_key]" value="%s" size="50"/>',
81
  $li_mls_api_key
82
  );
83
 
84
  if ( ! isset($li_mls_api_key) || ! $li_mls_api_key )
85
- echo '<p><a href="http://admin.mailchimp.com/account/api/" target="_blank">Get an API key from MailChimp.com</a></p>';
86
  }
87
 
88
  /**
@@ -109,7 +107,7 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
109
  echo '<td class="synced-list-cell"><span class="icon-tag"></span> ' . $synced_list->tag_text . '</td>';
110
  echo '<td class="synced-list-cell"><span class="synced-list-arrow">&#8594;</span></td>';
111
  echo '<td class="synced-list-cell"><span class="icon-envelope"></span> ' . $tag_synced_list['list_name'] . '</td>';
112
- echo '<td class="synced-list-edit"><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_contacts&action=edit_tag&tag=' . $synced_list->tag_id . '">edit tag</a></td>';
113
  echo '</tr>';
114
 
115
  $synced_list_count++;
@@ -141,42 +139,6 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
141
  return $synced_lists;
142
  }
143
 
144
- /**
145
- * Prints email input for settings page
146
- */
147
- function li_mls_subscribers_to_list_callback ()
148
- {
149
- $li_mls_subscribers_to_list = ( isset($this->options['li_mls_subscribers_to_list']) ? $this->options['li_mls_subscribers_to_list'] : '' );
150
-
151
- $lists = $this->li_mls_get_mailchimp_lists($this->options['li_mls_api_key']);
152
-
153
- echo '<select id="li_mls_subscribers_to_list" name="leadin_mls_options[li_mls_subscribers_to_list]" ' . ( ! count($lists['data']) ? 'disabled' : '' ) . '>';
154
-
155
- if ( count($lists['data']) )
156
- {
157
- $list_set = FALSE;
158
-
159
- foreach ( $lists['data'] as $list )
160
- {
161
- if ( $list['id'] == $li_mls_subscribers_to_list && !$list_set )
162
- $list_set = TRUE;
163
-
164
- echo '<option ' . ( $list['id'] == $li_mls_subscribers_to_list ? 'selected' : '' ) . ' value="' . $list['id'] . '">' . $list['name'] . '</option>';
165
- }
166
-
167
- if ( !$list_set )
168
- echo '<option selected value="">No list set...</option>';
169
- }
170
- else
171
- {
172
- echo '<option value="No lists...">No lists...</option>';
173
- }
174
-
175
- echo '</select>';
176
-
177
- echo '<p><a href="http://admin.mailchimp.com/lists/new-list/" target="_blank">Create a new list on MailChimp.com</a></p>';
178
- }
179
-
180
  /**
181
  * Format API-returned lists into parseable format on front end
182
  *
@@ -184,7 +146,7 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
184
  */
185
  function li_get_lists ( )
186
  {
187
- $lists = $this->li_mls_get_mailchimp_lists($this->options['li_mls_api_key']);
188
 
189
  $sanitized_lists = array();
190
  if ( count($lists['data']) )
@@ -208,7 +170,7 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
208
  * @param string
209
  * @return array
210
  */
211
- function li_mls_get_mailchimp_lists ( $api_key )
212
  {
213
  $MailChimp = new LI_MailChimp($api_key);
214
 
@@ -237,7 +199,12 @@ class WPMailChimpConnectAdmin extends WPLeadInAdmin {
237
  if ( $user_profile )
238
  $invalid_key = FALSE;
239
  else
 
 
 
 
240
  $invalid_key = TRUE;
 
241
 
242
  return $invalid_key;
243
  }
5
  class WPMailChimpConnectAdmin extends WPLeadInAdmin {
6
 
7
  var $power_up_settings_section = 'leadin_mls_options_section';
8
+ var $power_option_name = 'leadin_mls_options';
9
  var $power_up_icon;
10
  var $options;
11
  var $authed = FALSE;
23
  if ( is_admin() )
24
  {
25
  $this->power_up_icon = $power_up_icon_small;
26
+ add_action('admin_init', array($this, 'leadin_build_esp_settings_page'));
27
+ $this->options = get_option($this->power_option_name);
28
  $this->authed = ( isset($this->options['li_mls_api_key']) && $this->options['li_mls_api_key'] ? TRUE : FALSE );
29
 
30
  if ( $this->authed )
39
  /**
40
  * Creates settings options
41
  */
42
+ function leadin_build_esp_settings_page ()
43
  {
44
+ register_setting('leadin_settings_options', $this->power_option_name, array($this, 'sanitize'));
45
  add_settings_section($this->power_up_settings_section, $this->power_up_icon . "MailChimp", '', LEADIN_ADMIN_PATH);
46
  add_settings_field('li_mls_api_key', 'API key', array($this, 'li_mls_api_key_callback'), LEADIN_ADMIN_PATH, $this->power_up_settings_section);
47
 
64
  if( isset( $input['li_mls_api_key'] ) )
65
  $new_input['li_mls_api_key'] = sanitize_text_field( $input['li_mls_api_key'] );
66
 
 
 
 
67
  return $new_input;
68
  }
69
 
75
  $li_mls_api_key = ( $this->options['li_mls_api_key'] ? $this->options['li_mls_api_key'] : '' ); // Get header from options, or show default
76
 
77
  printf(
78
+ '<input id="li_mls_api_key" type="text" id="title" name="' . $this->power_option_name . '[li_mls_api_key]" value="%s" style="width: 430px;"/>',
79
  $li_mls_api_key
80
  );
81
 
82
  if ( ! isset($li_mls_api_key) || ! $li_mls_api_key )
83
+ echo '<p><a target="_blank" href="http://kb.mailchimp.com/accounts/management/about-api-keys#Find-or-Generate-Your-API-Key">Get your API key</a> from <a href="http://admin.mailchimp.com/account/api/" target="_blank">MailChimp.com</a></p>';
84
  }
85
 
86
  /**
107
  echo '<td class="synced-list-cell"><span class="icon-tag"></span> ' . $synced_list->tag_text . '</td>';
108
  echo '<td class="synced-list-cell"><span class="synced-list-arrow">&#8594;</span></td>';
109
  echo '<td class="synced-list-cell"><span class="icon-envelope"></span> ' . $tag_synced_list['list_name'] . '</td>';
110
+ echo '<td class="synced-list-edit"><a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=leadin_tags&action=edit_tag&tag=' . $synced_list->tag_id . '">edit tag</a></td>';
111
  echo '</tr>';
112
 
113
  $synced_list_count++;
139
  return $synced_lists;
140
  }
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  /**
143
  * Format API-returned lists into parseable format on front end
144
  *
146
  */
147
  function li_get_lists ( )
148
  {
149
+ $lists = $this->li_get_api_lists($this->options['li_mls_api_key']);
150
 
151
  $sanitized_lists = array();
152
  if ( count($lists['data']) )
170
  * @param string
171
  * @return array
172
  */
173
+ function li_get_api_lists ( $api_key )
174
  {
175
  $MailChimp = new LI_MailChimp($api_key);
176
 
199
  if ( $user_profile )
200
  $invalid_key = FALSE;
201
  else
202
+ {
203
+ unset($this->options['li_mc_api_key']);
204
+ update_option($this->power_option_name, $this->options);
205
+
206
  $invalid_key = TRUE;
207
+ }
208
 
209
  return $invalid_key;
210
  }
power-ups/subscribe-widget.php CHANGED
@@ -177,8 +177,6 @@ class WPLeadInSubscribe extends WPLeadIn {
177
  if ( $_SERVER["REQUEST_URI"] == '/' && ! isset ($options['li_subscribe_template_home']) )
178
  return FALSE;
179
  }
180
-
181
-
182
 
183
  if ( ! is_admin() && $pagenow != 'wp-login.php' )
184
  {
@@ -187,15 +185,6 @@ class WPLeadInSubscribe extends WPLeadIn {
187
 
188
  wp_register_style('leadin-subscribe-css', LEADIN_PATH . '/assets/css/build/leadin-subscribe.css');
189
  wp_enqueue_style('leadin-subscribe-css');
190
-
191
- if ( isset($li_options['premium']) )
192
- {
193
- if ( $li_options['premium'] )
194
- {
195
- wp_register_style('leadin-subscribe-premium-css', LEADIN_PATH . '/assets/css/build/leadin-subscribe-premium.css');
196
- wp_enqueue_style('leadin-subscribe-premium-css');
197
- }
198
- }
199
  }
200
  }
201
  }
177
  if ( $_SERVER["REQUEST_URI"] == '/' && ! isset ($options['li_subscribe_template_home']) )
178
  return FALSE;
179
  }
 
 
180
 
181
  if ( ! is_admin() && $pagenow != 'wp-login.php' )
182
  {
185
 
186
  wp_register_style('leadin-subscribe-css', LEADIN_PATH . '/assets/css/build/leadin-subscribe.css');
187
  wp_enqueue_style('leadin-subscribe-css');
 
 
 
 
 
 
 
 
 
188
  }
189
  }
190
  }
power-ups/subscribe-widget/admin/subscribe-widget-admin.php CHANGED
@@ -297,13 +297,13 @@ class WPLeadInSubscribeAdmin extends WPLeadInAdmin {
297
  $options = $this->options;
298
 
299
  $preview_link = get_bloginfo('wpurl') . '?preview-subscribe=1';
300
- $preview_link .= '&lis_heading=' . ( $options['li_subscribe_heading'] ? $options['li_subscribe_heading'] : 'Sign up for email updates' );
301
- $preview_link .= '&lis_desc=' . ( $options['li_subscribe_text'] ? $options['li_subscribe_text'] : '' );
302
  $preview_link .= '&lis_show_names=' . ( isset($options['li_subscribe_name_fields']) ? $options['li_subscribe_name_fields'] : 0 );
303
  $preview_link .= '&lis_show_phone=' . ( isset($options['li_subscribe_phone_field']) ? $options['li_subscribe_phone_field'] : 0 );
304
- $preview_link .= '&lis_btn_label=' . ( $options['li_subscribe_btn_label'] ? $options['li_subscribe_btn_label'] : 'SUBSCRIBE' );
305
- $preview_link .= '&lis_vex_class=' . ( $options['li_subscribe_vex_class'] ? $options['li_subscribe_vex_class'] : 'vex-theme-bottom-right-corner' );
306
- $preview_link .= '&lis_confirmation=' . ( $options['li_subscribe_confirmation'] ? $options['li_subscribe_confirmation'] : 1 );
307
 
308
  printf(
309
  '<p><a id="preview-popup-link" href="%s" target="_blank" class="button button-secondary">Preview Pop-up Form</a></p>',
297
  $options = $this->options;
298
 
299
  $preview_link = get_bloginfo('wpurl') . '?preview-subscribe=1';
300
+ $preview_link .= '&lis_heading=' . ( isset($options['li_subscribe_heading']) ? $options['li_subscribe_heading'] : 'Sign up for email updates' );
301
+ $preview_link .= '&lis_desc=' . ( isset($options['li_subscribe_text']) ? $options['li_subscribe_text'] : '' );
302
  $preview_link .= '&lis_show_names=' . ( isset($options['li_subscribe_name_fields']) ? $options['li_subscribe_name_fields'] : 0 );
303
  $preview_link .= '&lis_show_phone=' . ( isset($options['li_subscribe_phone_field']) ? $options['li_subscribe_phone_field'] : 0 );
304
+ $preview_link .= '&lis_btn_label=' . ( isset($options['li_subscribe_btn_label']) ? $options['li_subscribe_btn_label'] : 'SUBSCRIBE' );
305
+ $preview_link .= '&lis_vex_class=' . ( isset($options['li_subscribe_vex_class']) ? $options['li_subscribe_vex_class'] : 'vex-theme-bottom-right-corner' );
306
+ $preview_link .= '&lis_confirmation=' . ( isset($options['li_subscribe_confirmation']) ? $options['li_subscribe_confirmation'] : 1 );
307
 
308
  printf(
309
  '<p><a id="preview-popup-link" href="%s" target="_blank" class="button button-secondary">Preview Pop-up Form</a></p>',
readme.txt CHANGED
@@ -2,49 +2,49 @@
2
  Contributors: andygcook, nelsonjoyce
3
  Tags: crm, contacts, lead tracking, click tracking, visitor tracking, analytics, marketing automation, inbound marketing, subscription, marketing, lead generation, mailchimp, constant contact, newsletter, popup, popover, email list, email, contacts database, contact form, forms, form widget, popup form
4
  Requires at least: 3.7
5
- Tested up to: 4.1
6
- Stable tag: 2.2.11
7
 
8
  Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
9
 
10
  == Description ==
11
 
12
- = Get personal with your leads =
13
 
14
- <a href="http://leadin.com" alt="WordPress marketing automation and lead tracking plugin">Leadin</a> is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
15
 
16
- When a person submits a form on your WordPress site, you want to know more about them. What pages they've visited, when they return, and what social networks they’re on. Our WordPress marketing automation and lead tracking plugin gives you the details you need to make your next move. Because business isn’t business unless it’s personal.
17
 
18
- = How does it work? =
19
-
20
- 1. When you activate the WordPress plugin, Leadin will track each anonymous visitor to your site with a cookie.
21
- 2. Leadin automatically identifies and watches each existing form on your site for submissions.
22
- 3. Once someone fills out any other form on your site, Leadin will identify that person with their email address. and add them to your contact list.
23
- 4. You'll also receive an email with a link to the new contact record with all of their visit history.
24
-
25
- If you don't enjoy reading about how it works, watch this video from Brian Duffy explaining how he uses Leadin for <a href="http://wpapplied.com/track-visitors-wordpress-leadin-plugin">WPApplied</a>.
26
 
27
- [youtube http://www.youtube.com/watch?v=SGrsyWV988U]
 
28
 
29
- = Multisite Compatible =
 
30
 
31
- Leadin is fully Multisite compatible. The plugin will all data to each site's installaion just fine without requiring any additional setup.
32
-
33
- = Who's using Leadin? =
34
 
35
- **Alan Perlman**: *“I can use Leadin to get a sense of how engaged certain contacts are, and I can learn more about their behavior on my website to better drive the conversation and understand what they’re interested in or looking for.”*
 
36
 
37
- <a href="http://www.extremeinbound.com/leadin-wordpress-crm-inbound-plugin/">Read more from Alan</a>
38
 
 
 
 
 
39
 
40
- **Adam W. Warner**: *“…the Leadin plugin has been very useful so far in giving us an idea of the actual visitor paths to our contact forms vs. the paths we’ve intended.”*
41
 
42
- <a href="http://thewpvalet.com/wordpress-lead-tracking/">Read more from Adam</a>
43
 
 
44
 
45
- = Note: =
46
 
47
- Leadin collects usage information about this plugin so that we can better serve our customers and know what features to add. By installing and activating the Leadin for WordPress plugin you agree to these terms.
48
 
49
  == Installation ==
50
 
@@ -52,67 +52,84 @@ Leadin collects usage information about this plugin so that we can better serve
52
  2. Activate the plugin through the 'Plugins' menu in WordPress
53
  3. Add an email address under 'Leadin' in your settings panel
54
 
55
- == Frequently Asked Questions ==
56
-
57
- = How does Leadin integrate with my forms? =
58
 
59
- Leadin automatically integrates with your contact and comment forms that contain an email address field on your web site. There's no setup required.
 
60
 
61
- = Where are my contact submission stored? =
62
 
63
- Leadin creates a new contact in your Contacts Tabke whenever an email address is detected in your visitor's form submission.
 
 
 
 
 
64
 
65
- There is no limit to the number of contacts you can store in your Contacts Table.
66
 
67
- = Which contact form building plugins are supported? =
 
68
 
69
- Leadin is intended to work with any HTML form out of the box, but does not support forms created by Javascript or loaded through an iFrame.
 
 
 
 
70
 
71
- To ensure quality we've tested the most popular WordPress form builder plugins.
 
 
 
 
 
 
72
 
73
- = Tested + supported: =
 
 
74
 
75
- - Contact Form 7
76
- - JetPack
77
- - Fast Secure Contact Form
78
- - Contact Form
79
- - Gravity Forms
80
- - Formidable
81
- - Ninja Forms
82
- - Contact Form Clean and Simple
83
- - HubSpot
84
- - Native WordPress comment forms
85
- - Most custom forms
86
 
87
- = Tested + unsupported: =
 
 
88
 
89
- - Wufoo
90
- - Easy Contact Forms
91
- - Disqus comments
92
- - SumoMe
93
- - JotForm
94
- - Ninja Popups
95
- - Forms contained in an iFrame
96
 
97
- = Does Leadin work on Multisite? =
 
 
 
 
98
 
99
- You betcha! Leadin should work just fine on Multisite right out-of-the-box without requiring any additional setup.
 
 
100
 
101
- == Screenshots ==
 
 
102
 
103
- 1. See the visit history of each contact.
104
- 2. Get an email notification for every new lead.
105
- 3. Leadin stats show you where your leads are coming from.
106
- 4. Segment your contact list based on page views and submissinos.
107
- 5. Collect more contacts with the pop-up subscribe widget.
108
- 6. Create custom tagged lists, choose the form triggers to add contacts and sync your contacts to third-party email services
109
 
110
- == Changelog ==
111
 
112
- - Current version: 2.2.11
113
- - Current version release: 2015-02-18
114
 
115
  = 2.2.11 (2015.02.18) =
 
116
  = Enhancements =
117
  - Don't show the "You should receive a confirmation email shortly" message in the popup thank you if the confirmation email setting is toggled off
118
 
@@ -159,6 +176,15 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
159
  - Bug fixes
160
  - Fixed bug with non-tagged contacts being added to tagged lists
161
 
 
 
 
 
 
 
 
 
 
162
  = 2.2.5 (2014.11.20) =
163
  - Bug fixes
164
  - Fixes to bulk action labels
@@ -192,7 +218,7 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
192
  - Retooled tag editor to only pull down unique selectors
193
  - Contact list now will go back to the previous page when clicking the back link
194
  - Fixed mysterious bug where popup ignored new visitors
195
- - NOW the subscription confirmation stays checked/uncheckedon save (Thanks Kate!)
196
 
197
  = 2.2.1 (2014.10.01) =
198
  = Enhancements =
@@ -214,11 +240,11 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
214
  - Added ability to ignore logged in user roles from tracking
215
  - Popup can be previewed on the front end site before saving changes
216
  - MailChimp Connect checks for faulty API keys and prompts the user to enter in one that works on the tag editor page
217
- - Email headers for contact notificatons come from the person who filled in the form
218
  - Added traffic source URL parameters to contact notification emails
219
 
220
  - Bug fixes
221
- - Leadin now accounts for timezones descrepency on some MySQL databases and offsets to local time
222
  - Filters are now persistent when clicking the link back to the contact list from a contact timeline
223
  - cURL dependency no longer prints the raw error to the screen on installation and gracefully disables cURL-dependant features
224
  - Stats page and contact list totals didn't match up - fixed
@@ -308,7 +334,7 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
308
  = 0.10.0 (2014.06.03) =
309
  - Bug fixes
310
  - Fixed original referrer in contact timeline
311
- - Fixed unncessary queries on contact timeline
312
  - Only run the update check if the version number is different than the saved number
313
  - Remove "fakepath" from file path text in uploaded file input types
314
 
@@ -333,7 +359,7 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
333
 
334
  = 0.9.1 (2014.05.14) =
335
  - Bug fixes
336
- - Fixed pop-up location dropdown not defualting to saved options value
337
  - Hooked subscribe widget into get_footer action instead of loop_end filter
338
 
339
  = 0.9.0 (2014.05.12) =
@@ -361,7 +387,7 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
361
  - Bug fixes
362
  - Merge duplicate contacts into one record
363
  - Remove url parameters from source links in contact list
364
- - Downgrade use of singletons so classes are compatabile with PHP 5.2
365
 
366
  = Enhancements =
367
  - Swap out delete statements in favor of binary "deleted" flags to minimize data loss risk
@@ -406,7 +432,7 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
406
 
407
  = 0.6.2 (2014.04.07) =
408
  - Bug fixes
409
- - Fixed activation error for some installs by removing error ouput
410
  - MySQL query optimizations
411
  - Fixed bug with MySQL V5.0+ by adding default NULL values for insert statements on contacts table
412
  - Changed title for returning lead email notifications
@@ -455,7 +481,7 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
455
  - Improved contact history styling + interface
456
  - Added visit, pageview and submission stats to the contact view
457
  - Added Live Chat into the Leadin WordPress admin screens
458
- - New Leadin icons for WordPres sidebar and admin nav menu
459
 
460
  = 0.4.6 (2013.02.11) =
461
  - Bug fixes
@@ -463,7 +489,7 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
463
  - Bug fixes to contact type headings
464
  - Bug fix "Select All" export
465
  - Bug fix for CSS "page views" hover triangle breaking to next line
466
- - Backwards compability for < jQuery 1.7.0
467
  - Add Leadin link to admin bar
468
 
469
  = Enhancements =
@@ -553,4 +579,4 @@ You betcha! Leadin should work just fine on Multisite right out-of-the-box witho
553
  - Added social media avatars to emails
554
 
555
  = 0.1.0 (2013.11.22) =
556
- - Plugin released
2
  Contributors: andygcook, nelsonjoyce
3
  Tags: crm, contacts, lead tracking, click tracking, visitor tracking, analytics, marketing automation, inbound marketing, subscription, marketing, lead generation, mailchimp, constant contact, newsletter, popup, popover, email list, email, contacts database, contact form, forms, form widget, popup form
4
  Requires at least: 3.7
5
+ Tested up to: 4.1.1
6
+ Stable tag: 3.1.4
7
 
8
  Leadin is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
9
 
10
  == Description ==
11
 
12
+ = Get to know your website visitors =
13
 
14
+ <a href="http://leadin.com" alt="WordPress marketing automation and lead tracking plugin" target="_blank">Leadin</a> is an easy-to-use marketing automation and lead tracking plugin for WordPress that helps you better understand your web site visitors.
15
 
16
+ [youtube https://www.youtube.com/watch?v=tcMYv2r3ecg]
17
 
18
+ = Find out who's on your site and what they're doing =
19
+ When someone visits your site, you want to know more about them. What pages they've visited, when they return, and what social networks they’re on. Leadin gives you the details you need to make your next move.
 
 
 
 
 
 
20
 
21
+ = More context for your conversations =
22
+ Leadin automatically finds publicly available information about each of your contacts. Details such as location, work history, and company info can give you more context when you reach out.
23
 
24
+ = Convert more visitors to contacts =
25
+ Use the optional popup form to prevent people from slipping through the cracks. The popup also uses the contact data to intelligently know when to appear.
26
 
27
+ = Keep your contacts in sync with your email tool =
28
+ Leadin syncs your contacts to an email list of your choice without replacing any forms.
 
29
 
30
+ = Find out what content and traffic sources convert the best =
31
+ Our simple analytics show you what sources of traffic and content are driving the most contacts. No more complicated Google Analytics reports.
32
 
33
+ = How does it work? =
34
 
35
+ 1. When you activate the WordPress plugin, Leadin will track each anonymous visitor to your site with a cookie.
36
+ 2. Leadin automatically identifies and watches each existing form on your site for submissions.
37
+ 3. Once someone fills out any other form on your site, Leadin will identify that person with their email address. and add them to your contact list.
38
+ 4. You'll also receive an email with a link to the new contact record with all of their visit history. (check the screenshots sections to see it in action)
39
 
40
+ = Who's using Leadin? =
41
 
42
+ **<a href="http://www.extremeinbound.com/leadin-wordpress-crm-inbound-plugin/" target="_blank">Alan Perlman</a>**: *“I can use Leadin to get a sense of how engaged certain contacts are, and I can learn more about their behavior on my website to better drive the conversation and understand what they’re interested in or looking for.”*
43
 
44
+ **<a href="http://thewpvalet.com/wordpress-lead-tracking/" target="_blank">Adam W. Warner</a>**: *“…the Leadin plugin has been very useful so far in giving us an idea of the actual visitor paths to our contact forms vs. the paths we’ve intended.”*
45
 
 
46
 
47
+ Having trouble? Check out our <a href="http://support.leadin.com/">help documentation & support</a>
48
 
49
  == Installation ==
50
 
52
  2. Activate the plugin through the 'Plugins' menu in WordPress
53
  3. Add an email address under 'Leadin' in your settings panel
54
 
55
+ Having trouble? Check out our <a href="http://support.leadin.com/" target="_blank">help documentation & support</a>
 
 
56
 
57
+ == Frequently Asked Questions ==
58
+ = <a href="http://support.leadin.com/article/13-frequently-asked-questions" target="_blank">Full FAQ Here</a> =
59
 
60
+ == Screenshots ==
61
 
62
+ 1. See the visit history of each contact.
63
+ 2. Get an email notification for every new lead.
64
+ 3. Leadin stats show you where your leads are coming from.
65
+ 4. Segment your contact list based on page views and submissions.
66
+ 5. Collect more contacts with the pop-up subscribe widget.
67
+ 6. Create custom tagged lists, choose the form triggers to add contacts and sync your contacts to third-party email services
68
 
69
+ == Changelog ==
70
 
71
+ - Current version: 3.1.4
72
+ - Current version release: 2015-03-17
73
 
74
+ = 3.1.4 (2015.03.17) =
75
+ = Enhancements =
76
+ - Intercom added to plugin for in-app support
77
+ - Onboarding improved for non-setup installs
78
+ - Contact notifications are now sent through email delivery service to improve deliverability
79
 
80
+ - Bug fixes
81
+ - Namespaced AWeber oauth libraries with LI_ prefix to avoid duplicate class warnings
82
+ - SVG icon permanently fixed for servers that don't natively support that file type
83
+ - Check if database options are set for subscribe preview button
84
+ - Added in check for default leadin_options in case they were deleted and recreate them if they are not there
85
+ - Add in checks for the contact lookups to account for default object warnings
86
+ -
87
 
88
+ = 3.1.3 (2015.02.19) =
89
+ = Enhancements =
90
+ - Don't show the "You should receive a confirmation email shortly" message in the popup thank you if the confirmation email setting is toggled off
91
 
92
+ - Bug fixes
93
+ - Fixed SVG icon
94
+ - Fixed the default object warnings in class-leadin-contact for the enrichment lookups
95
+ - Tested NinjaPopups and added to readme as unsupported form plugin
96
+ - "Namespace" AWeber with "LI_" prefix to avoid conflicts
 
 
 
 
 
 
97
 
98
+ = 3.1.2 (2015.01.26) =
99
+ = Enhancements =
100
+ - Tested JotForm + added compatibility to the ReadMe file
101
 
102
+ - Bug fixes
103
+ - Add in support for like_escape for < WordPress 4.0
104
+ - Add first + last names to bulk MailChimp connector
105
+ - Remove rogue WPDB prepare in tag list table
106
+ - Check for existence of ESP connector when pushing to an email list
107
+ - Bug fix for multisite installs with broken onboarding
 
108
 
109
+ = 3.1.1 (2014.01.20) =
110
+ = Enhancements =
111
+ - Added ability to toggle Leadin data access by user role
112
+ - Hide Leadin nav menu item for user roles without access to Leadin data
113
+ - Discontinued and disabled the beta program
114
 
115
+ - Bug fixes
116
+ - Fixed broken onboarding in WordPress Multisite after adding a new site to the network
117
+ - Contact totals in tag editor now link to tagged list
118
 
119
+ = 3.1.0 (2015.1.06) =
120
+ = Enhancements =
121
+ - GetResponse, Campaign Monitor and AWeber integrations launched
122
 
123
+ = 3.0.0 (2014.12.10) =
124
+ = Enhancements =
125
+ - Jumping to version 3.0.0 to indefinitely override repository version of Leadin
 
 
 
126
 
127
+ = Leadin 2.2.7 - 2.2.11 =
128
 
129
+ *Leadin was split into Leadin and <a href="http://leadin.com/pro-upgrade" target="_blank">Leadin Pro</a> after version 2.2.6 and later merged back together, so versions 2.2.7 - 2.2.11 and 3.0.0 - 3.1.3 share similar updates.*
 
130
 
131
  = 2.2.11 (2015.02.18) =
132
+
133
  = Enhancements =
134
  - Don't show the "You should receive a confirmation email shortly" message in the popup thank you if the confirmation email setting is toggled off
135
 
176
  - Bug fixes
177
  - Fixed bug with non-tagged contacts being added to tagged lists
178
 
179
+ = 2.2.6 (2014.12.08) =
180
+ = Enhancements =
181
+ - Contact Lookup power-up
182
+ - Added names to contact exports
183
+ - Added “tagged as” to the email subject lines
184
+
185
+ - Bug fixes
186
+ - Fixed bug where Leadin would add non-tagged emails to ESP lists when it was not supposed to do those contacts
187
+
188
  = 2.2.5 (2014.11.20) =
189
  - Bug fixes
190
  - Fixes to bulk action labels
218
  - Retooled tag editor to only pull down unique selectors
219
  - Contact list now will go back to the previous page when clicking the back link
220
  - Fixed mysterious bug where popup ignored new visitors
221
+ - NOW the subscription confirmation stays checked/unchecked on save (Thanks Kate!)
222
 
223
  = 2.2.1 (2014.10.01) =
224
  = Enhancements =
240
  - Added ability to ignore logged in user roles from tracking
241
  - Popup can be previewed on the front end site before saving changes
242
  - MailChimp Connect checks for faulty API keys and prompts the user to enter in one that works on the tag editor page
243
+ - Email headers for contact notificaitons come from the person who filled in the form
244
  - Added traffic source URL parameters to contact notification emails
245
 
246
  - Bug fixes
247
+ - Leadin now accounts for timezones discrepancy on some MySQL databases and offsets to local time
248
  - Filters are now persistent when clicking the link back to the contact list from a contact timeline
249
  - cURL dependency no longer prints the raw error to the screen on installation and gracefully disables cURL-dependant features
250
  - Stats page and contact list totals didn't match up - fixed
334
  = 0.10.0 (2014.06.03) =
335
  - Bug fixes
336
  - Fixed original referrer in contact timeline
337
+ - Fixed unnecessary queries on contact timeline
338
  - Only run the update check if the version number is different than the saved number
339
  - Remove "fakepath" from file path text in uploaded file input types
340
 
359
 
360
  = 0.9.1 (2014.05.14) =
361
  - Bug fixes
362
+ - Fixed pop-up location dropdown not defaulting to saved options value
363
  - Hooked subscribe widget into get_footer action instead of loop_end filter
364
 
365
  = 0.9.0 (2014.05.12) =
387
  - Bug fixes
388
  - Merge duplicate contacts into one record
389
  - Remove url parameters from source links in contact list
390
+ - Downgrade use of singletons so classes are compatible with PHP 5.2
391
 
392
  = Enhancements =
393
  - Swap out delete statements in favor of binary "deleted" flags to minimize data loss risk
432
 
433
  = 0.6.2 (2014.04.07) =
434
  - Bug fixes
435
+ - Fixed activation error for some installs by removing error output
436
  - MySQL query optimizations
437
  - Fixed bug with MySQL V5.0+ by adding default NULL values for insert statements on contacts table
438
  - Changed title for returning lead email notifications
481
  - Improved contact history styling + interface
482
  - Added visit, pageview and submission stats to the contact view
483
  - Added Live Chat into the Leadin WordPress admin screens
484
+ - New Leadin icons for WordPress sidebar and admin nav menu
485
 
486
  = 0.4.6 (2013.02.11) =
487
  - Bug fixes
489
  - Bug fixes to contact type headings
490
  - Bug fix "Select All" export
491
  - Bug fix for CSS "page views" hover triangle breaking to next line
492
+ - Backwards compatibility for < jQuery 1.7.0
493
  - Add Leadin link to admin bar
494
 
495
  = Enhancements =
579
  - Added social media avatars to emails
580
 
581
  = 0.1.0 (2013.11.22) =
582
+ - Plugin released