WordPress Landing Pages - Version 1.7.3

Version Description

  • See changelog here: https://github.com/inboundnow/landing-pages/issues?q=is%3Aissue+is%3Aclosed+label%3Av1.7.3
Download this release

Release Info

Developer DavidWells
Plugin Icon 128x128 WordPress Landing Pages
Version 1.7.3
Comparing to
See all releases

Code changes from version 1.7.2 to 1.7.3

Files changed (63) hide show
  1. js/jquery.form-population.js +1 -1
  2. js/page_view_track.js +6 -3
  3. landing-pages.php +2 -2
  4. modules/module.ab-testing.php +18 -16
  5. modules/module.clone.php +1 -1
  6. modules/module.global-settings.php +10 -4
  7. modules/module.install.php +1 -1
  8. modules/module.javascript-frontend.php +1 -2
  9. modules/module.metaboxes-global.php +1 -0
  10. modules/module.redirect-ab-testing.php +12 -4
  11. modules/module.store.php +1 -1
  12. modules/module.templates.php +18 -17
  13. modules/module.track.php +1 -1
  14. readme.txt +5 -2
  15. shared/assets/assets.loader.class.php +22 -6
  16. shared/assets/frontend/js/analytics-src/analytics.events.js +511 -109
  17. shared/assets/frontend/js/analytics-src/analytics.examples.js +185 -0
  18. shared/assets/frontend/js/analytics-src/analytics.forms.js +933 -104
  19. shared/assets/frontend/js/analytics-src/analytics.hooks.js +404 -0
  20. shared/assets/frontend/js/analytics-src/analytics.init.js +121 -32
  21. shared/assets/frontend/js/analytics-src/analytics.lead.js +90 -0
  22. shared/assets/frontend/js/analytics-src/analytics.page.js +361 -0
  23. shared/assets/frontend/js/analytics-src/analytics.start.js +16 -0
  24. shared/assets/frontend/js/analytics-src/analytics.storage.js +19 -22
  25. shared/assets/frontend/js/analytics-src/analytics.utils.js +641 -351
  26. shared/assets/frontend/js/analytics/inboundAnalytics.js +3060 -1179
  27. shared/assets/frontend/js/analytics/inboundAnalytics.min.js +3 -2
  28. shared/assets/frontend/js/inbound.js +839 -0
  29. shared/assets/frontend/js/store.lead.ajax.js +11 -0
  30. shared/classes/class.debug.php +2 -2
  31. shared/classes/class.feedback.php +8 -8
  32. shared/classes/class.form.php +39 -286
  33. shared/classes/class.lead-fields.php +87 -55
  34. shared/classes/class.load-shared.php +50 -39
  35. shared/classes/class.post-type.email-template.php +2 -2
  36. shared/classes/class.shortcodes.email-template.php +1 -1
  37. shared/docs/analytics.events.md +352 -0
  38. shared/docs/css/blur.jpg +0 -0
  39. shared/docs/css/style.css +885 -0
  40. shared/docs/css/theme.css +84 -0
  41. shared/docs/index.html +94 -0
  42. shared/docs/js/flatdoc.js +515 -0
  43. shared/docs/js/jquery.js +5 -0
  44. shared/docs/js/legacy.js +369 -0
  45. shared/docs/js/script.js +250 -0
  46. shared/docs/js/theme.js +33 -0
  47. shared/docs/main.md +1029 -0
  48. shared/shortcodes/css/frontend-render.css +5 -1
  49. shared/shortcodes/js/tinymce.js +3 -3
  50. shared/shortcodes/shortcodes-includes.php +0 -9
  51. shared/tracking/new.store.lead.php +644 -0
  52. shared/tracking/page-tracking.js +1 -1
  53. shared/tracking/sources/Snowplow/RefererParser/Config/INBOUND_ConfigFileReaderTrait.php +54 -0
  54. shared/tracking/sources/Snowplow/RefererParser/Config/INBOUND_ConfigReaderInterface.php +15 -0
  55. shared/tracking/sources/Snowplow/RefererParser/Config/INBOUND_JsonConfigReader.php +57 -0
  56. shared/tracking/sources/Snowplow/RefererParser/Exception/INBOUND_InvalidArgumentException.php +9 -0
  57. shared/tracking/sources/Snowplow/RefererParser/INBOUND_Medium.php +16 -0
  58. shared/tracking/sources/Snowplow/RefererParser/INBOUND_Parser.php +266 -0
  59. shared/tracking/sources/Snowplow/RefererParser/INBOUND_Referer.php +78 -0
  60. shared/tracking/sources/referers.json +3890 -0
  61. shared/tracking/store.lead.php +7 -7
  62. templates/svtle/index.php +7 -6
  63. templates/tubelar/index.php +8 -0
js/jquery.form-population.js CHANGED
@@ -1 +1 @@
1
- function wpl_remember_inputs( selector ){
2
  jQuery(selector).each(
3
  function(){
4
  //if this item has been cookied, restore it
5
  var name = ( jQuery(this).attr('name') ) ? jQuery(this).attr('name') : '';
6
  if( jQuery.cookie( name ) && type_input != 'submit' && type_input != 'hidden' && type_input != 'file' && name != 'comment' ){
7
  jQuery(this).val( jQuery.cookie(name) );
8
  }
9
  //assign a change function to the item to cookie it
10
  jQuery(this).change(
11
  function(){
12
  jQuery.cookie(name, jQuery(this).val(), { path: '/', expires: 365 });
13
  }
14
  );
15
  }
16
  );
17
  jQuery(selector).each(
18
  function(){
19
  var form_name = jQuery(this).attr('name');
20
  var form_id = jQuery(this).attr('id');
21
  var form_class = jQuery(this).attr('class');
22
  if(typeof(form_name) != "undefined" && form_name !== null) {
23
  jQuery.cookie("lp_form_uid", form_name, { path: '/', expires: 365 });
24
  }
25
  else if(typeof(form_id) != "undefined" && form_id !== null) {
26
  jQuery.cookie("lp_form_uid", form_id, { path: '/', expires: 365 });
27
  }
28
  else if (typeof(form_class) != "undefined" && form_class !== null) {
29
  jQuery.cookie("lp_form_uid", form_class, { path: '/', expires: 365 });
30
  } else {
31
  jQuery.cookie("lp_form_uid", 'form_generic', { path: '/', expires: 365 });
32
  }
33
  }
34
  );
35
  // Fill Form Inputs from Cookies
36
  });
 
37
  <input type="text" name="name" />
38
  <input type="email" name="email" />
39
  <input type="text" name="address[addr1]" />
40
  <input type="text" name="address[city]" />
41
  <input type="text" name="address[state]" />
42
  "email": "john@doe.com",
43
  "name": "John Doe",
44
  "address": {
45
  "addr1": "Street name",
46
  "city": "City name",
47
  "state": "State"
48
  }
49
  for(var key in data) {
50
  var name = key;
51
  var value = data[key];
52
  // no need to set empty values
53
  if(value == "") {
54
  continue;
55
  }
56
  // handle array name attributes
57
  if(typeof(basename) !== "undefined") {
58
  name = basename + "[" + key + "]";
59
  }
60
  if(value.constructor == Array) {
61
  name += '[]';
62
  } else if(typeof value == "object") {
63
  populateFields(container, value, name);
64
  continue;
65
  }
66
  // populate field
67
  var elements = container.querySelectorAll('input[name="'+ name +'"], select[name="'+ name +'"], textarea[name="'+ name +'"]');
68
  // Dirty: abandon if we did not find the element
69
  if(!elements) {
70
  return;
71
  }
72
  // loop through found elements to set their values
73
  for(var i = 0; i < elements.length; i++) {
74
  var element = elements[i];
75
  // check element type
76
  switch(element.type || element.tagName) {
77
  case 'text':
78
  case 'email':
79
  case 'date':
80
  case 'tel':
81
  element.value = value;
82
  break;
83
  case 'radio':
84
  element.checked = (element.value === value);
85
  break;
86
  case 'checkbox':
87
  for(var j = 0; j < value.length; j++) {
88
  element.checked = (element.value === value[j]);
89
  }
90
  break;
91
  case 'select-multiple':
92
  var values = value.constructor == Array ? value : [value];
93
  for(var k = 0; k < element.options.length; k++)
94
  {
95
  for(var l = 0; l < values.length; l++)
96
  {
97
  element.options[k].selected |= (element.options[k].value == values[l]);
98
  }
99
  }
100
  break;
101
  case 'select':
102
  case 'select-one':
103
  element.value = value.toString() || value;
104
  break;
105
  }
106
  }
107
  }
108
  var name = ( elements[i].name ) ? elements[i].name : '';
 
1
  jQuery(selector).each(
2
  function(){
3
  //if this item has been cookied, restore it
4
  var name = ( jQuery(this).attr('name') ) ? jQuery(this).attr('name') : '';
5
  if( jQuery.cookie( name ) && type_input != 'submit' && type_input != 'hidden' && type_input != 'file' && name != 'comment' ){
6
  jQuery(this).val( jQuery.cookie(name) );
7
  }
8
  //assign a change function to the item to cookie it
9
  jQuery(this).change(
10
  function(){
11
  jQuery.cookie(name, jQuery(this).val(), { path: '/', expires: 365 });
12
  }
13
  );
14
  }
15
  );
16
  jQuery(selector).each(
17
  function(){
18
  var form_name = jQuery(this).attr('name');
19
  var form_id = jQuery(this).attr('id');
20
  var form_class = jQuery(this).attr('class');
21
  if(typeof(form_name) != "undefined" && form_name !== null) {
22
  jQuery.cookie("lp_form_uid", form_name, { path: '/', expires: 365 });
23
  }
24
  else if(typeof(form_id) != "undefined" && form_id !== null) {
25
  jQuery.cookie("lp_form_uid", form_id, { path: '/', expires: 365 });
26
  }
27
  else if (typeof(form_class) != "undefined" && form_class !== null) {
28
  jQuery.cookie("lp_form_uid", form_class, { path: '/', expires: 365 });
29
  } else {
30
  jQuery.cookie("lp_form_uid", 'form_generic', { path: '/', expires: 365 });
31
  }
32
  }
33
  );
34
  // Fill Form Inputs from Cookies
35
  });
36
+ /*
37
  <input type="text" name="name" />
38
  <input type="email" name="email" />
39
  <input type="text" name="address[addr1]" />
40
  <input type="text" name="address[city]" />
41
  <input type="text" name="address[state]" />
42
  "email": "john@doe.com",
43
  "name": "John Doe",
44
  "address": {
45
  "addr1": "Street name",
46
  "city": "City name",
47
  "state": "State"
48
  }
49
  for(var key in data) {
50
  var name = key;
51
  var value = data[key];
52
  // no need to set empty values
53
  if(value == "") {
54
  continue;
55
  }
56
  // handle array name attributes
57
  if(typeof(basename) !== "undefined") {
58
  name = basename + "[" + key + "]";
59
  }
60
  if(value.constructor == Array) {
61
  name += '[]';
62
  } else if(typeof value == "object") {
63
  populateFields(container, value, name);
64
  continue;
65
  }
66
  // populate field
67
  var elements = container.querySelectorAll('input[name="'+ name +'"], select[name="'+ name +'"], textarea[name="'+ name +'"]');
68
  // Dirty: abandon if we did not find the element
69
  if(!elements) {
70
  return;
71
  }
72
  // loop through found elements to set their values
73
  for(var i = 0; i < elements.length; i++) {
74
  var element = elements[i];
75
  // check element type
76
  switch(element.type || element.tagName) {
77
  case 'text':
78
  case 'email':
79
  case 'date':
80
  case 'tel':
81
  element.value = value;
82
  break;
83
  case 'radio':
84
  element.checked = (element.value === value);
85
  break;
86
  case 'checkbox':
87
  for(var j = 0; j < value.length; j++) {
88
  element.checked = (element.value === value[j]);
89
  }
90
  break;
91
  case 'select-multiple':
92
  var values = value.constructor == Array ? value : [value];
93
  for(var k = 0; k < element.options.length; k++)
94
  {
95
  for(var l = 0; l < values.length; l++)
96
  {
97
  element.options[k].selected |= (element.options[k].value == values[l]);
98
  }
99
  }
100
  break;
101
  case 'select':
102
  case 'select-one':
103
  element.value = value.toString() || value;
104
  break;
105
  }
106
  }
107
  }
108
  var name = ( elements[i].name ) ? elements[i].name : '';
js/page_view_track.js CHANGED
@@ -1,8 +1,11 @@
1
  jQuery(document).ready(function($) {
2
 
3
- jQuery('form').each(function(){
4
- jQuery(this).addClass('wpl-track-me');
5
- });
 
 
 
6
 
7
  // Saves variation page views
8
 
1
  jQuery(document).ready(function($) {
2
 
3
+ setTimeout(function() {
4
+ jQuery('form').each(function(){
5
+ //jQuery(this).addClass('inbound-track');
6
+ });
7
+ }, 700);
8
+
9
 
10
  // Saves variation page views
11
 
landing-pages.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Landing Pages
4
  Plugin URI: http://www.inboundnow.com/landing-pages/
5
  Description: The first true all-in-one Landing Page solution for WordPress, including ongoing conversion metrics, a/b split testing, unlimited design options and so much more!
6
- Version: 1.7.2
7
  Author: Inbound Now
8
  Author URI: http://www.inboundnow.com/
9
  Text Domain: landing-pages
@@ -102,7 +102,7 @@ if (!class_exists('Inbound_Landing_Pages_Plugin')) {
102
  */
103
  private static function load_constants() {
104
 
105
- define('LANDINGPAGES_CURRENT_VERSION', '1.7.2' );
106
  define('LANDINGPAGES_URLPATH', plugins_url( '/' , __FILE__ ) );
107
  define('LANDINGPAGES_PATH', WP_PLUGIN_DIR.'/'.plugin_basename( dirname(__FILE__) ).'/' );
108
  define('LANDINGPAGES_PLUGIN_SLUG', plugin_basename( dirname(__FILE__) ) );
3
  Plugin Name: Landing Pages
4
  Plugin URI: http://www.inboundnow.com/landing-pages/
5
  Description: The first true all-in-one Landing Page solution for WordPress, including ongoing conversion metrics, a/b split testing, unlimited design options and so much more!
6
+ Version: 1.7.3
7
  Author: Inbound Now
8
  Author URI: http://www.inboundnow.com/
9
  Text Domain: landing-pages
102
  */
103
  private static function load_constants() {
104
 
105
+ define('LANDINGPAGES_CURRENT_VERSION', '1.7.3' );
106
  define('LANDINGPAGES_URLPATH', plugins_url( '/' , __FILE__ ) );
107
  define('LANDINGPAGES_PATH', WP_PLUGIN_DIR.'/'.plugin_basename( dirname(__FILE__) ).'/' );
108
  define('LANDINGPAGES_PLUGIN_SLUG', plugin_basename( dirname(__FILE__) ) );
modules/module.ab-testing.php CHANGED
@@ -74,15 +74,15 @@ if (is_admin())
74
  {
75
  $array_variations = explode(',',$variations);
76
  $array_variations = lp_ab_unset_variation($array_variations,$_GET['lp-variation-id']);
77
-
78
  /* set next variation to be open */
79
- $current_variation_id = current($array_variations);
80
  $_SESSION['lp_ab_test_open_variation'] = $current_variation_id;
81
-
82
  $variations = implode(',' , $array_variations);
83
  update_post_meta($post->ID,'lp-ab-variations', $variations);
84
-
85
-
86
  if (isset($_GET['lp-variation-id']) && $_GET['lp-variation-id'] > 0 ) {
87
  $suffix = '-'.$_GET['lp-variation-id'];
88
  $len = strlen($suffix);
@@ -90,7 +90,7 @@ if (is_admin())
90
  $suffix = '';
91
  $len = strlen($suffix);
92
  }
93
-
94
  //delete each meta value associated with variation
95
  global $wpdb;
96
  $data = array();
@@ -111,7 +111,7 @@ if (is_admin())
111
  delete_post_meta($_GET['post'], $key, $value);
112
  }
113
  }
114
-
115
  $_GET['lp-variation-id'] = $current_variation_id;
116
  }
117
 
@@ -346,14 +346,14 @@ if (is_admin())
346
  foreach ($lp_custom_fields as $key=>$field)
347
  {
348
  $default = get_post_meta($post_id, $field['id'], true);
349
-
350
  $id = $field['id'];
351
  $field['id'] = $id.'-'.$current_variation_id ;
352
-
353
  if ($default) {
354
  $field['default'] = $default;
355
  }
356
-
357
  $lp_custom_fields[$key] = $field;
358
  }
359
  return $lp_custom_fields;
@@ -767,9 +767,11 @@ function lp_ab_testing_add_rewrite_rules()
767
 
768
  $slug = get_option( 'lp-main-landing-page-permalink-prefix', 'go' );
769
  //echo $slug;exit;
 
 
770
  add_rewrite_rule("$slug/([^/]*)?", $this_path."modules/module.redirect-ab-testing.php?permalink_name=$1 ",'top');
771
  add_rewrite_rule("landing-page=([^/]*)?", $this_path.'modules/module.redirect-ab-testing.php?permalink_name=$1','top');
772
-
773
  add_filter('mod_rewrite_rules', 'lp_ab_testing_modify_rules', 1);
774
  function lp_ab_testing_modify_rules($rules)
775
  {
@@ -885,7 +887,7 @@ function lp_ab_testing_prepare_variation_callback()
885
  die();
886
  }
887
 
888
-
889
  }
890
 
891
 
@@ -898,7 +900,7 @@ function lp_ab_testing_alter_content_area($content)
898
  if ( !isset($post) || $post->post_type != 'landing-page' ) {
899
  return $content;
900
  }
901
-
902
  $variation_id = lp_ab_testing_get_current_variation_id();
903
 
904
  if ($variation_id>0)
@@ -932,14 +934,14 @@ function lp_ab_testing_record_impression($post_id, $post_type = 'landing-page' ,
932
  /* If Landing Page Post Type */
933
  if ( $post_type == 'landing-page' ) {
934
  $meta_key = 'lp-ab-variation-impressions-'.$variation_id;
935
- }
936
  /* If Non Landing Page Post Type */
937
  else {
938
  $meta_key = '_inbound_impressions_count';
939
  }
940
-
941
  $impressions = get_post_meta($post_id, $meta_key , true);
942
-
943
  if (!is_numeric($impressions)) {
944
  $impressions = 1;
945
  } else {
74
  {
75
  $array_variations = explode(',',$variations);
76
  $array_variations = lp_ab_unset_variation($array_variations,$_GET['lp-variation-id']);
77
+
78
  /* set next variation to be open */
79
+ $current_variation_id = current($array_variations);
80
  $_SESSION['lp_ab_test_open_variation'] = $current_variation_id;
81
+
82
  $variations = implode(',' , $array_variations);
83
  update_post_meta($post->ID,'lp-ab-variations', $variations);
84
+
85
+
86
  if (isset($_GET['lp-variation-id']) && $_GET['lp-variation-id'] > 0 ) {
87
  $suffix = '-'.$_GET['lp-variation-id'];
88
  $len = strlen($suffix);
90
  $suffix = '';
91
  $len = strlen($suffix);
92
  }
93
+
94
  //delete each meta value associated with variation
95
  global $wpdb;
96
  $data = array();
111
  delete_post_meta($_GET['post'], $key, $value);
112
  }
113
  }
114
+
115
  $_GET['lp-variation-id'] = $current_variation_id;
116
  }
117
 
346
  foreach ($lp_custom_fields as $key=>$field)
347
  {
348
  $default = get_post_meta($post_id, $field['id'], true);
349
+
350
  $id = $field['id'];
351
  $field['id'] = $id.'-'.$current_variation_id ;
352
+
353
  if ($default) {
354
  $field['default'] = $default;
355
  }
356
+
357
  $lp_custom_fields[$key] = $field;
358
  }
359
  return $lp_custom_fields;
767
 
768
  $slug = get_option( 'lp-main-landing-page-permalink-prefix', 'go' );
769
  //echo $slug;exit;
770
+ $ab_testing = get_option( 'lp-main-landing-page-disable-turn-off-ab', "0");
771
+ if($ab_testing === "0") {
772
  add_rewrite_rule("$slug/([^/]*)?", $this_path."modules/module.redirect-ab-testing.php?permalink_name=$1 ",'top');
773
  add_rewrite_rule("landing-page=([^/]*)?", $this_path.'modules/module.redirect-ab-testing.php?permalink_name=$1','top');
774
+ }
775
  add_filter('mod_rewrite_rules', 'lp_ab_testing_modify_rules', 1);
776
  function lp_ab_testing_modify_rules($rules)
777
  {
887
  die();
888
  }
889
 
890
+
891
  }
892
 
893
 
900
  if ( !isset($post) || $post->post_type != 'landing-page' ) {
901
  return $content;
902
  }
903
+
904
  $variation_id = lp_ab_testing_get_current_variation_id();
905
 
906
  if ($variation_id>0)
934
  /* If Landing Page Post Type */
935
  if ( $post_type == 'landing-page' ) {
936
  $meta_key = 'lp-ab-variation-impressions-'.$variation_id;
937
+ }
938
  /* If Non Landing Page Post Type */
939
  else {
940
  $meta_key = '_inbound_impressions_count';
941
  }
942
+
943
  $impressions = get_post_meta($post_id, $meta_key , true);
944
+
945
  if (!is_numeric($impressions)) {
946
  $impressions = 1;
947
  } else {
modules/module.clone.php CHANGED
@@ -1 +1 @@
1
- <?php
1
+ <?php
modules/module.global-settings.php CHANGED
@@ -84,6 +84,14 @@ function lp_get_global_settings() {
84
  'default' => '0',
85
  'options' => array('1'=>'On','0'=>'Off')
86
  ),
 
 
 
 
 
 
 
 
87
  );
88
 
89
 
@@ -122,10 +130,8 @@ function lp_get_global_settings() {
122
 
123
  /* Add Extensions License Key Header if Extensions are present */
124
  add_filter('lp_define_global_settings', 'lp_add_extension_license_key_header', 2, 1);
125
- function lp_add_extension_license_key_header($lp_global_settings)
126
- {
127
- if (array_key_exists('lp-license-keys',$lp_global_settings))
128
- {
129
  $lp_global_settings['lp-license-keys']['settings'][] = array(
130
  'id' => 'extensions-license-keys-header',
131
  'description' => __( "Head to http://www.inboundnow.com/ to retrieve your license key for this template." , 'landing-pages'),
84
  'default' => '0',
85
  'options' => array('1'=>'On','0'=>'Off')
86
  ),
87
+ array(
88
+ 'id' => 'landing-page-disable-turn-off-ab',
89
+ 'label' => __('Turn Off AB Testing?' , 'landing-pages') ,
90
+ 'description' => __("This will disable the AB testing functionality of your landing pages. This is to comply with Googles new PPC regulations with redirects. After saving this option <a href='/wp-admin/options-permalink.php'>visit this page to flush/reset your permalinks</a>" , 'landing-pages'),
91
+ 'type' => 'radio',
92
+ 'default' => '0',
93
+ 'options' => array('0'=>'No Keep it on','1'=>'Yes turn AB testing Off')
94
+ )
95
  );
96
 
97
 
130
 
131
  /* Add Extensions License Key Header if Extensions are present */
132
  add_filter('lp_define_global_settings', 'lp_add_extension_license_key_header', 2, 1);
133
+ function lp_add_extension_license_key_header($lp_global_settings) {
134
+ if (array_key_exists('lp-license-keys',$lp_global_settings)) {
 
 
135
  $lp_global_settings['lp-license-keys']['settings'][] = array(
136
  'id' => 'extensions-license-keys-header',
137
  'description' => __( "Head to http://www.inboundnow.com/ to retrieve your license key for this template." , 'landing-pages'),
modules/module.install.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  // Added Demo Landing on Install
3
- add_action('init', 'inbound_create_default_post_type');
4
  function inbound_create_default_post_type(){
5
  // NEED to insert custom meta as well
6
 
1
  <?php
2
  // Added Demo Landing on Install
3
+ add_action('admin_init', 'inbound_create_default_post_type');
4
  function inbound_create_default_post_type(){
5
  // NEED to insert custom meta as well
6
 
modules/module.javascript-frontend.php CHANGED
@@ -35,8 +35,7 @@ function lp_fontend_enqueue_scripts($hook) {
35
  $form_prepopulation = get_option( 'lp-main-landing-page-prepopulate-forms' , 1);
36
  // load form pre-population script
37
  if ($form_prepopulation) {
38
- wp_register_script('form-population',LANDINGPAGES_URLPATH . 'js/jquery.form-population.js', array( 'jquery', 'jquery-cookie' ));
39
- wp_enqueue_script('form-population');
40
  }
41
 
42
  if (isset($_GET['template-customize']) &&$_GET['template-customize']=='on') {
35
  $form_prepopulation = get_option( 'lp-main-landing-page-prepopulate-forms' , 1);
36
  // load form pre-population script
37
  if ($form_prepopulation) {
38
+ /* TODO set global option */
 
39
  }
40
 
41
  if (isset($_GET['template-customize']) &&$_GET['template-customize']=='on') {
modules/module.metaboxes-global.php CHANGED
@@ -20,6 +20,7 @@ function lp_add_global_meta_box( $post_type )
20
  $exclude[] = 'inbound-email';
21
  $exclude[] = 'inbound-log';
22
  $exclude[] = 'landing-page';
 
23
  // add filter
24
 
25
  if ( $pagenow === 'post.php' && !in_array($post_type,$exclude) ) {
20
  $exclude[] = 'inbound-email';
21
  $exclude[] = 'inbound-log';
22
  $exclude[] = 'landing-page';
23
+ $exclude[] = 'acf-field-group';
24
  // add filter
25
 
26
  if ( $pagenow === 'post.php' && !in_array($post_type,$exclude) ) {
modules/module.redirect-ab-testing.php CHANGED
@@ -18,6 +18,7 @@ class LP_Variation_Rotation {
18
 
19
  static $permalink_name;
20
  static $post_id;
 
21
  static $last_loaded_variation;
22
  static $variations;
23
  static $marker;
@@ -42,11 +43,18 @@ class LP_Variation_Rotation {
42
  {
43
  self::$permalink_name = (isset($_GET['permalink_name'])) ? sanitize_text_field($_GET['permalink_name']) : null;
44
  self::$post_id = self::load_post_id();
 
45
  self::$last_loaded_variation = ( isset( $_COOKIE['lp-loaded-variation-'.self::$permalink_name] ) ) ? $_COOKIE['lp-loaded-variation-'.self::$permalink_name] : null;
46
- self::$variations = self::load_variations();
47
- self::$marker = self::load_marker();
48
- self::$next_marker = self::discover_next_variation();
49
- self::$destination_url = self::build_destination_url();
 
 
 
 
 
 
50
  }
51
 
52
  /**
18
 
19
  static $permalink_name;
20
  static $post_id;
21
+ static $sticky_variations;
22
  static $last_loaded_variation;
23
  static $variations;
24
  static $marker;
43
  {
44
  self::$permalink_name = (isset($_GET['permalink_name'])) ? sanitize_text_field($_GET['permalink_name']) : null;
45
  self::$post_id = self::load_post_id();
46
+ self::$sticky_variations = get_option( 'lp-main-landing-page-rotation-halt' , false );
47
  self::$last_loaded_variation = ( isset( $_COOKIE['lp-loaded-variation-'.self::$permalink_name] ) ) ? $_COOKIE['lp-loaded-variation-'.self::$permalink_name] : null;
48
+
49
+ if ( self::$sticky_variations && self::$last_loaded_variation ) {
50
+ self::$destination_url = self::$last_loaded_variation;
51
+ } else {
52
+ self::$variations = self::load_variations();
53
+ self::$marker = self::load_marker();
54
+ self::$next_marker = self::discover_next_variation();
55
+ self::$destination_url = self::build_destination_url();
56
+ }
57
+
58
  }
59
 
60
  /**
modules/module.store.php CHANGED
@@ -1 +1 @@
1
- <?php
1
+ <?php
modules/module.templates.php CHANGED
@@ -32,24 +32,28 @@ else if (isset($_GET['page'])&&$_GET['page']=='lp_manage_templates')
32
  private $singular;
33
  private $plural;
34
 
35
- function __construct()
36
- {
37
  $lp_data = lp_get_extension_data();
38
  $final_data = array();
39
-
40
  foreach ($lp_data as $key=>$data)
41
  {
42
  $array_core_templates = array('countdown-lander','default','demo','dropcap','half-and-half','simple-two-column','super-slick','svtle','tubelar','rsvp-envelope', 'simple-solid-lite', 'three-column-lander');
43
 
44
- if ($key == 'lp' || substr($key,0,4) == 'ext-' )
45
  continue;
 
46
 
47
- if (isset($data['info']['data_type']) && $data['info']['data_type']=='metabox')
48
- continue;
49
 
50
- if (in_array($key,$array_core_templates))
51
  continue;
 
52
 
 
 
 
 
53
  //if (stristr($data['category'],'Theme Integrated'))
54
  //continue;
55
 
@@ -60,12 +64,13 @@ else if (isset($_GET['page'])&&$_GET['page']=='lp_manage_templates')
60
  }
61
  }
62
 
63
- if (isset($data['thumbnail']))
64
  $thumbnail = $data['thumbnail'];
65
- else if ($key=='default')
66
  $thumbnail = get_bloginfo('template_directory')."/screenshot.png";
67
- else
68
  $thumbnail = LANDINGPAGES_UPLOADS_URLPATH.$key."/thumbnail.png";
 
69
 
70
  $this_data['ID'] = $key;
71
  $this_data['template'] = $key;
@@ -75,12 +80,9 @@ else if (isset($_GET['page'])&&$_GET['page']=='lp_manage_templates')
75
  ( array_key_exists('info',$data) ) ? $this_data['description'] = $data['info']['description'] : $this_data['description'] = $data['description'];
76
 
77
  $this_data['thumbnail'] = $thumbnail;
78
- if (isset($data['info']['version'])&&!empty($data['info']['version']))
79
- {
80
  $this_data['version'] = $data['info']['version'];
81
- }
82
- else
83
- {
84
  $this_data['version'] = "1.0.1";
85
  }
86
 
@@ -102,8 +104,7 @@ else if (isset($_GET['page'])&&$_GET['page']=='lp_manage_templates')
102
  $this->_args = $args;
103
  }
104
 
105
- function get_columns()
106
- {
107
  $columns = array(
108
  'cb' => '<input type="checkbox" />',
109
  'template' => __( 'Template' , 'landing-pages'),
32
  private $singular;
33
  private $plural;
34
 
35
+ function __construct() {
36
+
37
  $lp_data = lp_get_extension_data();
38
  $final_data = array();
39
+
40
  foreach ($lp_data as $key=>$data)
41
  {
42
  $array_core_templates = array('countdown-lander','default','demo','dropcap','half-and-half','simple-two-column','super-slick','svtle','tubelar','rsvp-envelope', 'simple-solid-lite', 'three-column-lander');
43
 
44
+ if ($key == 'lp' || substr($key,0,4) == 'ext-' ) {
45
  continue;
46
+ }
47
 
 
 
48
 
49
+ if (isset($data['info']['data_type']) && $data['info']['data_type']=='metabox') {
50
  continue;
51
+ }
52
 
53
+
54
+ if (in_array($key,$array_core_templates)) {
55
+ continue;
56
+ }
57
  //if (stristr($data['category'],'Theme Integrated'))
58
  //continue;
59
 
64
  }
65
  }
66
 
67
+ if (isset($data['thumbnail'])) {
68
  $thumbnail = $data['thumbnail'];
69
+ } else if ($key=='default') {
70
  $thumbnail = get_bloginfo('template_directory')."/screenshot.png";
71
+ } else {
72
  $thumbnail = LANDINGPAGES_UPLOADS_URLPATH.$key."/thumbnail.png";
73
+ }
74
 
75
  $this_data['ID'] = $key;
76
  $this_data['template'] = $key;
80
  ( array_key_exists('info',$data) ) ? $this_data['description'] = $data['info']['description'] : $this_data['description'] = $data['description'];
81
 
82
  $this_data['thumbnail'] = $thumbnail;
83
+ if (isset($data['info']['version'])&&!empty($data['info']['version'])) {
 
84
  $this_data['version'] = $data['info']['version'];
85
+ } else {
 
 
86
  $this_data['version'] = "1.0.1";
87
  }
88
 
104
  $this->_args = $args;
105
  }
106
 
107
+ function get_columns() {
 
108
  $columns = array(
109
  'cb' => '<input type="checkbox" />',
110
  'template' => __( 'Template' , 'landing-pages'),
modules/module.track.php CHANGED
@@ -1 +1 @@
1
- <?php
2
  $count_key = 'lp_page_views_count';
3
  $count = get_post_meta($postID, $count_key, true);
4
  if($count==''){
5
  $count = 0;
6
  delete_post_meta($postID, $count_key);
7
  add_post_meta($postID, $count_key, '0');
8
  }else{
9
  $count++;
10
  update_post_meta($postID, $count_key, $count);
11
  }
12
  $count_key = 'lp_page_conversions_count';
13
  $count = get_post_meta($postID, $count_key, true);
14
  if($count==''){
15
  delete_post_meta($postID, $count_key);
16
  add_post_meta($postID, $count_key, '0');
17
  return "0";
18
  }
19
  return $count;
20
  $count_key = 'lp_page_conversions_count';
21
  $count = get_post_meta($postID, $count_key, true);
22
  if($count==''){
23
  $count = 0;
24
  delete_post_meta($postID, $count_key);
25
  add_post_meta($postID, $count_key, '0');
26
  }else{
27
  $count++;
28
  update_post_meta($postID, $count_key, $count);
29
  }
30
  $count_key = 'lp_page_views_count';
31
  $count = get_post_meta($postID, $count_key, true);
32
  if($count==''){
33
  delete_post_meta($postID, $count_key);
34
  add_post_meta($postID, $count_key, '0');
35
  return;
36
  }
37
  return $count;
 
38
  $count_key = 'lp_page_views_count';
39
  $count = get_post_meta($postID, $count_key, true);
40
  if($count==''){
41
  $count = 0;
42
  delete_post_meta($postID, $count_key);
43
  add_post_meta($postID, $count_key, '0');
44
  }else{
45
  $count++;
46
  update_post_meta($postID, $count_key, $count);
47
  }
48
  $count_key = 'lp_page_conversions_count';
49
  $count = get_post_meta($postID, $count_key, true);
50
  if($count==''){
51
  delete_post_meta($postID, $count_key);
52
  add_post_meta($postID, $count_key, '0');
53
  return "0";
54
  }
55
  return $count;
56
  $count_key = 'lp_page_conversions_count';
57
  $count = get_post_meta($postID, $count_key, true);
58
  if($count==''){
59
  $count = 0;
60
  delete_post_meta($postID, $count_key);
61
  add_post_meta($postID, $count_key, '0');
62
  }else{
63
  $count++;
64
  update_post_meta($postID, $count_key, $count);
65
  }
66
  $count_key = 'lp_page_views_count';
67
  $count = get_post_meta($postID, $count_key, true);
68
  if($count==''){
69
  delete_post_meta($postID, $count_key);
70
  add_post_meta($postID, $count_key, '0');
71
  return;
72
  }
73
  return $count;
 
1
  $count_key = 'lp_page_views_count';
2
  $count = get_post_meta($postID, $count_key, true);
3
  if($count==''){
4
  $count = 0;
5
  delete_post_meta($postID, $count_key);
6
  add_post_meta($postID, $count_key, '0');
7
  }else{
8
  $count++;
9
  update_post_meta($postID, $count_key, $count);
10
  }
11
  $count_key = 'lp_page_conversions_count';
12
  $count = get_post_meta($postID, $count_key, true);
13
  if($count==''){
14
  delete_post_meta($postID, $count_key);
15
  add_post_meta($postID, $count_key, '0');
16
  return "0";
17
  }
18
  return $count;
19
  $count_key = 'lp_page_conversions_count';
20
  $count = get_post_meta($postID, $count_key, true);
21
  if($count==''){
22
  $count = 0;
23
  delete_post_meta($postID, $count_key);
24
  add_post_meta($postID, $count_key, '0');
25
  }else{
26
  $count++;
27
  update_post_meta($postID, $count_key, $count);
28
  }
29
  $count_key = 'lp_page_views_count';
30
  $count = get_post_meta($postID, $count_key, true);
31
  if($count==''){
32
  delete_post_meta($postID, $count_key);
33
  add_post_meta($postID, $count_key, '0');
34
  return;
35
  }
36
  return $count;
37
+ <?php
38
  $count_key = 'lp_page_views_count';
39
  $count = get_post_meta($postID, $count_key, true);
40
  if($count==''){
41
  $count = 0;
42
  delete_post_meta($postID, $count_key);
43
  add_post_meta($postID, $count_key, '0');
44
  }else{
45
  $count++;
46
  update_post_meta($postID, $count_key, $count);
47
  }
48
  $count_key = 'lp_page_conversions_count';
49
  $count = get_post_meta($postID, $count_key, true);
50
  if($count==''){
51
  delete_post_meta($postID, $count_key);
52
  add_post_meta($postID, $count_key, '0');
53
  return "0";
54
  }
55
  return $count;
56
  $count_key = 'lp_page_conversions_count';
57
  $count = get_post_meta($postID, $count_key, true);
58
  if($count==''){
59
  $count = 0;
60
  delete_post_meta($postID, $count_key);
61
  add_post_meta($postID, $count_key, '0');
62
  }else{
63
  $count++;
64
  update_post_meta($postID, $count_key, $count);
65
  }
66
  $count_key = 'lp_page_views_count';
67
  $count = get_post_meta($postID, $count_key, true);
68
  if($count==''){
69
  delete_post_meta($postID, $count_key);
70
  add_post_meta($postID, $count_key, '0');
71
  return;
72
  }
73
  return $count;
readme.txt CHANGED
@@ -6,8 +6,8 @@ License: GPLv2 or later
6
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
7
  Tags: landing pages, inbound marketing, conversion pages, split testing, a b test, a b testing, a/b test, a/b testing, coming soon page, email list, landing page, list building, maintenance page, squeeze page, inbound now, landing-pages, splash pages, cpa, click tracking, goal tracking, analytics, free landing page templates
8
  Requires at least: 3.8
9
- Tested up to: 3.9
10
- Stable Tag: 1.7.2
11
 
12
  Create landing pages for your WordPress site. Monitor and improve conversion rates, run A/B split tests, customize your own templates and more.
13
 
@@ -72,6 +72,9 @@ The plugin is also fully extendable and has a number of actions, filters, and ho
72
  4. Choose from a ton of pre-made templates, use your existing design, or design your own theme!
73
 
74
  == Changelog ==
 
 
 
75
  = 1.7.2 =
76
  * Improved form email typo detection
77
  * Improved Template Styles
6
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
7
  Tags: landing pages, inbound marketing, conversion pages, split testing, a b test, a b testing, a/b test, a/b testing, coming soon page, email list, landing page, list building, maintenance page, squeeze page, inbound now, landing-pages, splash pages, cpa, click tracking, goal tracking, analytics, free landing page templates
8
  Requires at least: 3.8
9
+ Tested up to: 4.0.1
10
+ Stable Tag: 1.7.3
11
 
12
  Create landing pages for your WordPress site. Monitor and improve conversion rates, run A/B split tests, customize your own templates and more.
13
 
72
  4. Choose from a ton of pre-made templates, use your existing design, or design your own theme!
73
 
74
  == Changelog ==
75
+ = 1.7.3 =
76
+ * See changelog here: https://github.com/inboundnow/landing-pages/issues?q=is%3Aissue+is%3Aclosed+label%3Av1.7.3
77
+
78
  = 1.7.2 =
79
  * Improved form email typo detection
80
  * Improved Template Styles
shared/assets/assets.loader.class.php CHANGED
@@ -55,11 +55,14 @@ class Inbound_Asset_Loader {
55
  wp_dequeue_script( $handle );
56
  }
57
  }
58
-
59
- self::load_file('funnel-tracking', 'frontend/js/page-tracking.js', array( 'jquery','jquery-cookie', 'jquery-total-storage'), 'wplft', self::localize_lead_data());
60
- //self::load_file('funnel-tracking', 'frontend/js/analytics/inboundAnalytics.js', array( 'jquery','jquery-cookie', 'jquery-total-storage'), 'wplft', self::localize_lead_data());
61
- // TODO: Merge Localize of wplft into inbound_ajax
62
  self::load_file('store-lead-ajax', 'frontend/js/store.lead.ajax.js', array( 'jquery','jquery-cookie', 'jquery-total-storage'), 'inbound_ajax', self::localize_lead_data());
 
 
 
 
 
63
 
64
  if (is_array($store)) {
65
  foreach ( $store as $handle ) {
@@ -165,8 +168,21 @@ class Inbound_Asset_Loader {
165
  $lead_data_array['lead_uid'] = ($lead_uid) ? $lead_uid : null;
166
  $time = current_time( 'timestamp', 0 ); // Current wordpress time from settings
167
  $wordpress_date_time = date("Y/m/d G:i:s", $time);
168
-
169
- $inbound_localized_data = array( 'post_id' => $post_id, 'ip_address' => $ip_address, 'wp_lead_data' => $lead_data_array, 'admin_url' => admin_url( 'admin-ajax.php' ), 'track_time' => $wordpress_date_time, 'post_type' => $post_type, 'page_tracking' => $page_tracking, 'search_tracking' => $search_tracking, 'comment_tracking' => $comment_tracking, 'custom_mapping' => $custom_map_values);
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
  return $inbound_localized_data;
172
  } // end localize lead data
55
  wp_dequeue_script( $handle );
56
  }
57
  }
58
+ /*if (!defined('InboundAnalytics_v2')) {
59
+ self::load_file('funnel-tracking', 'frontend/js/inbound.js', array( 'jquery','jquery-cookie', 'jquery-total-storage'), 'wplft', self::localize_lead_data());
 
 
60
  self::load_file('store-lead-ajax', 'frontend/js/store.lead.ajax.js', array( 'jquery','jquery-cookie', 'jquery-total-storage'), 'inbound_ajax', self::localize_lead_data());
61
+ } else {
62
+ */
63
+
64
+ self::load_file('funnel-tracking', 'frontend/js/analytics/inboundAnalytics.js', array( 'jquery' ), 'inbound_settings', self::localize_lead_data());
65
+ /* } */
66
 
67
  if (is_array($store)) {
68
  foreach ( $store as $handle ) {
168
  $lead_data_array['lead_uid'] = ($lead_uid) ? $lead_uid : null;
169
  $time = current_time( 'timestamp', 0 ); // Current wordpress time from settings
170
  $wordpress_date_time = date("Y/m/d G:i:s", $time);
171
+ $inbound_track_include = get_option( 'wpl-main-tracking-ids');
172
+ $inbound_track_exclude = get_option( 'wpl-main-exclude-tracking-ids');
173
+ $inbound_localized_data = array('post_id' => $post_id,
174
+ 'ip_address' => $ip_address,
175
+ 'wp_lead_data' => $lead_data_array,
176
+ 'admin_url' => admin_url('admin-ajax.php'),
177
+ 'track_time' => $wordpress_date_time,
178
+ 'post_type' => $post_type,
179
+ 'page_tracking' => $page_tracking,
180
+ 'search_tracking' => $search_tracking,
181
+ 'comment_tracking' => $comment_tracking,
182
+ 'custom_mapping' => $custom_map_values,
183
+ 'inbound_track_exclude' => $inbound_track_exclude,
184
+ 'inbound_track_include' => $inbound_track_include
185
+ );
186
 
187
  return $inbound_localized_data;
188
  } // end localize lead data
shared/assets/frontend/js/analytics-src/analytics.events.js CHANGED
@@ -1,117 +1,519 @@
1
  /**
2
- * Event functions
3
- * @param Object InboundAnalytics - Main JS object
4
- * @return Object - include event triggers
 
 
 
 
 
5
  */
6
- // https://github.com/carldanley/WP-JS-Hooks/blob/master/src/event-manager.js
7
- var InboundAnalyticsEvents = (function (InboundAnalytics) {
8
-
9
- InboundAnalytics.Events = {
10
- // Create cookie
11
- loadEvents: function() {
12
- this.analyticsLoaded();
13
- },
14
- triggerJQueryEvent: function(eventName, data){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (window.jQuery) {
16
  var data = data || {};
17
  jQuery(document).trigger(eventName, data);
18
- /* var something = (function() {
19
- var executed = false;
20
- return function () {
21
- if (!executed) {
22
- executed = true;
23
- console.log(eventName + " RAN");
24
-
25
- }
26
- };
27
- })();*/
28
  }
29
- },
30
- analyticsLoaded: function() {
31
- var eventName = "inbound_analytics_loaded";
32
- var loaded = new CustomEvent(eventName);
33
- window.dispatchEvent(loaded);
34
- this.triggerJQueryEvent(eventName);
35
- },
36
- analyticsTriggered: function() {
37
- var triggered = new CustomEvent("inbound_analytics_triggered");
38
- window.dispatchEvent(triggered);
39
- },
40
- analyticsSaved: function() {
41
- var page_view_saved = new CustomEvent("inbound_analytics_saved");
42
- window.dispatchEvent(page_view_saved);
43
- console.log('Page View Saved');
44
- },
45
- analyticsError: function(MLHttpRequest, textStatus, errorThrown) {
46
- var error = new CustomEvent("inbound_analytics_error", {
47
- detail: {
48
- MLHttpRequest: MLHttpRequest,
49
- textStatus: textStatus,
50
- errorThrown: errorThrown
51
- }
52
- });
53
- window.dispatchEvent(error);
54
- console.log('Page Save Error');
55
- },
56
- pageFirstView: function(page_seen_count) {
57
- var page_first_view = new CustomEvent("inbound_analytics_page_first_view", {
58
- detail: {
59
- count: 1,
60
- time: new Date(),
61
- },
62
- bubbles: true,
63
- cancelable: true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
- );
66
- window.dispatchEvent(page_first_view);
67
-
68
- console.log('First Ever Page View of this Page');
69
- },
70
- pageRevisit: function(page_seen_count) {
71
- var eventName = "inbound_analytics_page_revisit";
72
- var data = { count: page_seen_count,
73
- time: new Date()
74
- };
75
- var page_revisit = new CustomEvent(eventName, {
76
- detail: data,
77
- bubbles: true,
78
- cancelable: true
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
- );
81
- window.dispatchEvent(page_revisit);
82
- this.triggerJQueryEvent(eventName, data);
83
- console.log('Page Revisit');
84
- },
85
- /* get idle times https://github.com/robflaherty/riveted/blob/master/riveted.js */
86
- browserTabHidden: function() {
87
- /* http://www.thefutureoftheweb.com/demo/2007-05-16-detect-browser-window-focus/ */
88
- var eventName = "inbound_analytics_tab_hidden";
89
- var tab_hidden = new CustomEvent(eventName);
90
- window.dispatchEvent(tab_hidden);
91
- console.log('Tab Hidden');
92
- this.triggerJQueryEvent(eventName);
93
- },
94
- browserTabVisible: function() {
95
- var eventName = "inbound_analytics_tab_visible";
96
- var tab_visible = new CustomEvent(eventName);
97
- window.dispatchEvent(tab_visible);
98
- console.log('Tab Visible');
99
- this.triggerJQueryEvent(eventName);
100
- },
101
- /* Scrol depth https://github.com/robflaherty/jquery-scrolldepth/blob/master/jquery.scrolldepth.js */
102
- sessionStart: function() {
103
- var session_start = new CustomEvent("inbound_analytics_session_start");
104
- window.dispatchEvent(session_start);
105
- console.log('Session Start');
106
- },
107
- sessionActive: function() {
108
- var session_active = new CustomEvent("inbound_analytics_session_active");
109
- window.dispatchEvent(session_active);
110
- console.log('Session Active');
111
- },
112
-
113
- };
114
-
115
- return InboundAnalytics;
116
-
117
- })(InboundAnalytics || {});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /**
2
+ * # Analytics Events
3
+ *
4
+ * Events are triggered throughout the visitors journey through the site. See more on [Inbound Now][in]
5
+ *
6
+ * @author David Wells <david@inboundnow.com>
7
+ * @version 0.0.1
8
+ *
9
+ * [in]: http://www.inboundnow.com/
10
  */
11
+
12
+ // Add object to _inbound
13
+ var _inboundEvents = (function(_inbound) {
14
+
15
+
16
+ _inbound.trigger = function(trigger, data) {
17
+ _inbound.Events[trigger](data);
18
+
19
+ };
20
+
21
+ /*!
22
+ *
23
+ * Private Function that Fires & Emits Events
24
+ *
25
+ * There are three options for firing events and they trigger in this order:
26
+ *
27
+ * 1. Vanilla JS dispatch event
28
+ * 2. `_inbound.add_action('namespace', callback, priority)`
29
+ * 3. jQuery Trigger `jQuery.trigger('namespace', callback);`
30
+ *
31
+ * The Event `data` can be filtered before events are triggered
32
+ * with filters. Example: filter_ + "namespace"
33
+ *
34
+ * ```js
35
+ * // Filter Form Data before submissionsz
36
+ * _inbound.add_filter( 'filter_form_before_submission', event_filter_data_example, 10);
37
+ *
38
+ * function event_filter_data_example(data) {
39
+ * var data = data || {};
40
+ * // Do something with data
41
+ * return data;
42
+ * }
43
+ * ```
44
+ *
45
+ * @param {string} eventName Name of the event
46
+ * @param {object} data Data passed to external functions/triggers
47
+ * @param {object} options Options for configuring events
48
+ * @return {null} Nothing returned
49
+ */
50
+ function fireEvent(eventName, data, options) {
51
+ var data = data || {};
52
+ options = options || {};
53
+ //alert('ran + ' + eventName);
54
+ //console.log(eventName);
55
+ //console.log(data);
56
+ /*! defaults for JS dispatch event */
57
+ options.bubbles = options.bubbles || true,
58
+ options.cancelable = options.cancelable || true;
59
+
60
+ /*! Customize Data via filter_ + "namespace" */
61
+ data = _inbound.apply_filters('filter_' + eventName, data);
62
+
63
+ var TriggerEvent = new CustomEvent(eventName, {
64
+ detail: data,
65
+ bubbles: options.bubbles,
66
+ cancelable: options.cancelable
67
+ });
68
+
69
+ // console.log('Action:' + eventName + " ran on ->", data);
70
+
71
+ /*! 1. Trigger Pure Javascript Event See: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events for example on creating events */
72
+ window.dispatchEvent(TriggerEvent);
73
+ /*! 2. Trigger _inbound action */
74
+ _inbound.do_action(eventName, data);
75
+ /*! 3. jQuery trigger */
76
+ triggerJQueryEvent(eventName, data);
77
+
78
+ }
79
+
80
+ function triggerJQueryEvent(eventName, data) {
81
  if (window.jQuery) {
82
  var data = data || {};
83
  jQuery(document).trigger(eventName, data);
 
 
 
 
 
 
 
 
 
 
84
  }
85
+ };
86
+
87
+ var universalGA,
88
+ classicGA,
89
+ googleTagManager;
90
+
91
+ _inbound.Events = {
92
+
93
+ /**
94
+ * # Event Usage
95
+ *
96
+ * Events are triggered throughout the visitors path through the site.
97
+ * You can hook into these custom actions and filters much like WordPress Core
98
+ *
99
+ * See below for examples
100
+ */
101
+
102
+ /**
103
+ * Adding Custom Actions
104
+ * ------------------
105
+ * You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
106
+ *
107
+ * `
108
+ * _inbound.add_action( 'action_name', callback, priority );
109
+ * `
110
+ *
111
+ * ```js
112
+ * // example:
113
+ *
114
+ * // Add custom function to `page_visit` event
115
+ * _inbound.add_action( 'page_visit', callback, 10 );
116
+ *
117
+ * // add custom callback to trigger when `page_visit` fires
118
+ * function callback(pageData){
119
+ * var pageData = pageData || {};
120
+ * // run callback on 'page_visit' trigger
121
+ * alert(pageData.title);
122
+ * }
123
+ * ```
124
+ *
125
+ * @param {string} action_name Name of the event trigger
126
+ * @param {function} callback function to trigger when event happens
127
+ * @param {int} priority Order to trigger the event in
128
+ *
129
+ */
130
+
131
+ /**
132
+ * Removing Custom Actions
133
+ * ------------------
134
+ * You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
135
+ *
136
+ * `
137
+ * _inbound.remove_action( 'action_name');
138
+ * `
139
+ *
140
+ * ```js
141
+ * // example:
142
+ *
143
+ * _inbound.remove_action( 'page_visit');
144
+ * // all 'page_visit' actions have been deregistered
145
+ * ```
146
+ *
147
+ * @param {string} action_name Name of the event trigger
148
+ *
149
+ */
150
+
151
+ /**
152
+ * # Event List
153
+ *
154
+ * Events are triggered throughout the visitors journey through the site
155
+ */
156
+
157
+ /**
158
+ * Triggers when analyics has finished loading
159
+ */
160
+ analytics_ready: function() {
161
+ var ops = {
162
+ 'opt1': true
163
+ };
164
+ var data = {
165
+ 'data': 'xyxy'
166
+ };
167
+ fireEvent('analytics_ready', data, ops);
168
+ },
169
+ /**
170
+ * Triggers when the browser url params are parsed. You can perform custom actions
171
+ * if specific url params exist.
172
+ *
173
+ * ```js
174
+ * // Usage:
175
+ *
176
+ * // Add function to 'url_parameters' event
177
+ * _inbound.add_action( 'url_parameters', url_parameters_func_example, 10);
178
+ *
179
+ * function url_parameters_func_example(urlParams) {
180
+ * var urlParams = urlParams || {};
181
+ * for( var param in urlParams ) {
182
+ * var key = param;
183
+ * var value = urlParams[param];
184
+ * }
185
+ * // All URL Params
186
+ * alert(JSON.stringify(urlParams));
187
+ *
188
+ * // Check if URL parameter `utm_source` exists and matches value
189
+ * if(urlParams.utm_source === "twitter") {
190
+ * alert('This person is from twitter!');
191
+ * }
192
+ * }
193
+ * ```
194
+ */
195
+ url_parameters: function(data) {
196
+ fireEvent('url_parameters', data);
197
+ },
198
+ /**
199
+ * Triggers when session starts
200
+ *
201
+ * ```js
202
+ * // Usage:
203
+ *
204
+ * // Add function to 'session_start' event
205
+ * _inbound.add_action( 'session_start', session_start_func_example, 10);
206
+ *
207
+ * function session_start_func_example(data) {
208
+ * var data = data || {};
209
+ * // session start. Do something for new visitor
210
+ * }
211
+ * ```
212
+ */
213
+ session_start: function() {
214
+ console.log('');
215
+ fireEvent('session_start');
216
+ },
217
+ /**
218
+ * Triggers when visitor session goes idle for more than 30 minutes.
219
+ *
220
+ * ```js
221
+ * // Usage:
222
+ *
223
+ * // Add function to 'session_end' event
224
+ * _inbound.add_action( 'session_end', session_end_func_example, 10);
225
+ *
226
+ * function session_end_func_example(data) {
227
+ * var data = data || {};
228
+ * // Do something when session ends
229
+ * alert("Hey! It's been 30 minutes... where did you go?");
230
+ * }
231
+ * ```
232
+ */
233
+ session_end: function(clockTime) {
234
+ fireEvent('session_end', clockTime);
235
+ console.log('Session End');
236
+ },
237
+ /**
238
+ * Triggers if active session is detected
239
+ *
240
+ * ```js
241
+ * // Usage:
242
+ *
243
+ * // Add function to 'session_active' event
244
+ * _inbound.add_action( 'session_active', session_active_func_example, 10);
245
+ *
246
+ * function session_active_func_example(data) {
247
+ * var data = data || {};
248
+ * // session active
249
+ * }
250
+ * ```
251
+ */
252
+ session_active: function() {
253
+ fireEvent('session_active');
254
+ },
255
+ /**
256
+ * Triggers when visitor session goes idle. Idling occurs after 60 seconds of
257
+ * inactivity or when the visitor switches browser tabs
258
+ *
259
+ * ```js
260
+ * // Usage:
261
+ *
262
+ * // Add function to 'session_idle' event
263
+ * _inbound.add_action( 'session_idle', session_idle_func_example, 10);
264
+ *
265
+ * function session_idle_func_example(data) {
266
+ * var data = data || {};
267
+ * // Do something when session idles
268
+ * alert('Here is a special offer for you!');
269
+ * }
270
+ * ```
271
+ */
272
+ session_idle: function(clockTime) {
273
+ fireEvent('session_idle', clockTime);
274
+ },
275
+ /**
276
+ * Triggers when session is already active and gets resumed
277
+ *
278
+ * ```js
279
+ * // Usage:
280
+ *
281
+ * // Add function to 'session_resume' event
282
+ * _inbound.add_action( 'session_resume', session_resume_func_example, 10);
283
+ *
284
+ * function session_resume_func_example(data) {
285
+ * var data = data || {};
286
+ * // Session exists and is being resumed
287
+ * }
288
+ * ```
289
+ */
290
+ session_resume: function() {
291
+ fireEvent('session_resume');
292
+ },
293
+ /**
294
+ * Session emitter. Runs every 10 seconds. This is a useful function for
295
+ * pinging third party services
296
+ *
297
+ * ```js
298
+ * // Usage:
299
+ *
300
+ * // Add session_heartbeat_func_example function to 'session_heartbeat' event
301
+ * _inbound.add_action( 'session_heartbeat', session_heartbeat_func_example, 10);
302
+ *
303
+ * function session_heartbeat_func_example(data) {
304
+ * var data = data || {};
305
+ * // Do something with every 10 seconds
306
+ * }
307
+ * ```
308
+ */
309
+ session_heartbeat: function(clockTime) {
310
+ var data = {
311
+ 'clock': clockTime,
312
+ 'leadData': InboundLeadData
313
+ };
314
+ fireEvent('session_heartbeat', data);
315
+ },
316
+ /**
317
+ * Triggers Every Page View
318
+ *
319
+ * ```js
320
+ * // Usage:
321
+ *
322
+ * // Add function to 'page_visit' event
323
+ * _inbound.add_action( 'page_visit', page_visit_func_example, 10);
324
+ *
325
+ * function session_idle_func_example(pageData) {
326
+ * var pageData = pageData || {};
327
+ * if( pageData.view_count > 8 ){
328
+ * alert('Wow you have been to this page more than 8 times.');
329
+ * }
330
+ * }
331
+ * ```
332
+ */
333
+ page_visit: function(pageData) {
334
+ fireEvent('page_view', pageData);
335
+ },
336
+ /**
337
+ * Triggers If the visitor has never seen the page before
338
+ *
339
+ * ```js
340
+ * // Usage:
341
+ *
342
+ * // Add function to 'page_first_visit' event
343
+ * _inbound.add_action( 'page_first_visit', page_first_visit_func_example, 10);
344
+ *
345
+ * function page_first_visit_func_example(pageData) {
346
+ * var pageData = pageData || {};
347
+ * alert('Welcome to this page! Its the first time you have seen it')
348
+ * }
349
+ * ```
350
+ */
351
+ page_first_visit: function(pageData) {
352
+ fireEvent('page_first_visit');
353
+ _inbound.deBugger('pages', 'First Ever Page View of this Page');
354
+ },
355
+ /**
356
+ * Triggers If the visitor has seen the page before
357
+ *
358
+ * ```js
359
+ * // Usage:
360
+ *
361
+ * // Add function to 'page_revisit' event
362
+ * _inbound.add_action( 'page_revisit', page_revisit_func_example, 10);
363
+ *
364
+ * function page_revisit_func_example(pageData) {
365
+ * var pageData = pageData || {};
366
+ * alert('Welcome back to this page!');
367
+ * // Show visitor special content/offer
368
+ * }
369
+ * ```
370
+ */
371
+ page_revisit: function(pageData) {
372
+
373
+ fireEvent('page_revisit', pageData);
374
+
375
+ var logger = function() {
376
+ console.log('pageData', pageData);
377
+ console.log('Page Revisit viewed ' + pageData + " times");
378
  }
379
+ _inbound.deBugger('pages', status, logger);
380
+ },
381
+
382
+ /**
383
+ * `tab_hidden` is triggered when the visitor switches browser tabs
384
+ *
385
+ * ```js
386
+ * // Usage:
387
+ *
388
+ * // Adding the callback
389
+ * function tab_hidden_function( data ) {
390
+ * alert('The Tab is Hidden');
391
+ * };
392
+ *
393
+ * // Hook the function up the the `tab_hidden` event
394
+ * _inbound.add_action( 'tab_hidden', tab_hidden_function, 10 );
395
+ * ```
396
+ */
397
+ tab_hidden: function(data) {
398
+ _inbound.deBugger('pages', 'Tab Hidden');
399
+ fireEvent('tab_hidden');
400
+ },
401
+ /**
402
+ * `tab_visible` is triggered when the visitor switches back to the sites tab
403
+ *
404
+ * ```js
405
+ * // Usage:
406
+ *
407
+ * // Adding the callback
408
+ * function tab_visible_function( data ) {
409
+ * alert('Welcome back to this tab!');
410
+ * // trigger popup or offer special discount etc.
411
+ * };
412
+ *
413
+ * // Hook the function up the the `tab_visible` event
414
+ * _inbound.add_action( 'tab_visible', tab_visible_function, 10 );
415
+ * ```
416
+ */
417
+ tab_visible: function(data) {
418
+ _inbound.deBugger('pages', 'Tab Visible');
419
+ fireEvent('tab_visible');
420
+ },
421
+ /**
422
+ * `tab_mouseout` is triggered when the visitor mouses out of the browser window.
423
+ * This is especially useful for exit popups
424
+ *
425
+ * ```js
426
+ * // Usage:
427
+ *
428
+ * // Adding the callback
429
+ * function tab_mouseout_function( data ) {
430
+ * alert("Wait don't Go");
431
+ * // trigger popup or offer special discount etc.
432
+ * };
433
+ *
434
+ * // Hook the function up the the `tab_mouseout` event
435
+ * _inbound.add_action( 'tab_mouseout', tab_mouseout_function, 10 );
436
+ * ```
437
+ */
438
+ tab_mouseout: function(data) {
439
+ _inbound.deBugger('pages', 'Tab Mouseout');
440
+ fireEvent('tab_mouseout');
441
+ },
442
+ /**
443
+ * `form_input_change` is triggered when tracked form inputs change
444
+ * You can use this to add additional validation or set conditional triggers
445
+ *
446
+ * ```js
447
+ * // Usage:
448
+ *
449
+ * ```
450
+ */
451
+ form_input_change: function(inputData) {
452
+ var logger = function() {
453
+ console.log(inputData);
454
+ //console.log('Page Revisit viewed ' + pageData + " times");
455
  }
456
+ _inbound.deBugger('forms', 'inputData change. Data=', logger);
457
+ fireEvent('form_input_change', inputData);
458
+ },
459
+ /**
460
+ * `form_before_submission` is triggered before the form is submitted to the server.
461
+ * You can filter the data here or send it to third party services
462
+ *
463
+ * ```js
464
+ * // Usage:
465
+ *
466
+ * // Adding the callback
467
+ * function form_before_submission_function( data ) {
468
+ * var data = data || {};
469
+ * // filter form data
470
+ * };
471
+ *
472
+ * // Hook the function up the the `form_before_submission` event
473
+ * _inbound.add_action( 'form_before_submission', form_before_submission_function, 10 );
474
+ * ```
475
+ */
476
+ form_before_submission: function(formData) {
477
+ fireEvent('form_before_submission', formData);
478
+ },
479
+ /**
480
+ * `form_after_submission` is triggered after the form is submitted to the server.
481
+ * You can filter the data here or send it to third party services
482
+ *
483
+ * ```js
484
+ * // Usage:
485
+ *
486
+ * // Adding the callback
487
+ * function form_after_submission_function( data ) {
488
+ * var data = data || {};
489
+ * // filter form data
490
+ * };
491
+ *
492
+ * // Hook the function up the the `form_after_submission` event
493
+ * _inbound.add_action( 'form_after_submission', form_after_submission_function, 10 );
494
+ * ```
495
+ */
496
+ form_after_submission: function(formData) {
497
+
498
+ fireEvent('form_after_submission', formData);
499
+
500
+ },
501
+ /*! Scrol depth https://github.com/robflaherty/jquery-scrolldepth/blob/master/jquery.scrolldepth.js */
502
+
503
+ analyticsError: function(MLHttpRequest, textStatus, errorThrown) {
504
+ var error = new CustomEvent("inbound_analytics_error", {
505
+ detail: {
506
+ MLHttpRequest: MLHttpRequest,
507
+ textStatus: textStatus,
508
+ errorThrown: errorThrown
509
+ }
510
+ });
511
+ window.dispatchEvent(error);
512
+ console.log('Page Save Error');
513
+ },
514
+
515
+ };
516
+
517
+ return _inbound;
518
+
519
+ })(_inbound || {});
shared/assets/frontend/js/analytics-src/analytics.examples.js ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ URL param action
3
+ */
4
+ // Add to page
5
+ _inbound.add_action('url_parameters', URL_Param_Function, 10);
6
+ // callback function
7
+ function URL_Param_Function(urlParams) {
8
+
9
+ //urlParams = _inbound.apply_filters( 'urlParamFilter', urlParams);
10
+
11
+ for (var param in urlParams) {
12
+ var key = param;
13
+ var value = urlParams[param];
14
+ }
15
+
16
+ //alert(JSON.stringify(urlParams));
17
+
18
+ /* Check if URL parameter exists and matches value */
19
+ if (urlParams.test === "true") {
20
+ alert('url param true is true');
21
+ }
22
+ }
23
+
24
+ /* Applying filters to your actions */
25
+ _inbound.add_filter('filter_url_parameters', URL_Param_Filter, 10);
26
+
27
+ function URL_Param_Filter(urlParams) {
28
+
29
+ var params = urlParams || {};
30
+ /* check for item in object */
31
+ if (params.utm_source !== "undefined") {
32
+ //alert('its here');
33
+ }
34
+ /* delete item from object */
35
+ delete params.utm_source;
36
+
37
+ return params;
38
+
39
+ }
40
+
41
+ /* Applying filters to your actions */
42
+ _inbound.add_filter('filter_inbound_analytics_loaded', event_filter_data_example, 10);
43
+
44
+ function event_filter_data_example(data) {
45
+
46
+ var data = data || {};
47
+
48
+ /* Add property to data */
49
+ data.add_this = 'additional data';
50
+
51
+ /* check for item in object */
52
+ if (data.opt1 === true) {
53
+ alert('options.opt1 = true');
54
+ }
55
+
56
+ /* Add or modifiy option to event */
57
+ data.new_options = 'new option';
58
+
59
+ /* delete item from data */
60
+ delete data.utm_source;
61
+
62
+ return data;
63
+
64
+ }
65
+
66
+ _inbound.add_action('tab_hidden', Tab_Hidden_Function, 10);
67
+
68
+ function Tab_Hidden_Function(data) {
69
+ //alert('NOPE! LOOK AT ME!!!!');
70
+ }
71
+
72
+ _inbound.add_action('tab_visible', tab_visible_function, 9);
73
+
74
+ function tab_visible_function(data) {
75
+ //alert('Welcome back to the tab');
76
+ }
77
+
78
+ _inbound.add_action('tab_mouseout', tab_mouseout_function, 10);
79
+
80
+ function tab_mouseout_function(data) {
81
+ //alert('You moused out of the tab');
82
+ document.body.style.background = 'red';
83
+ }
84
+
85
+ _inbound.add_action('page_first_visit', Tab_vis_Function, 10);
86
+
87
+ function Tab_vis_Function(data) {
88
+ //alert('Welcome back bro 2');
89
+ }
90
+
91
+ _inbound.add_action('page_revisit', page_revisit_Function, 10);
92
+
93
+ function page_revisit_Function(data) {
94
+ console.log('Welcome page_revisit');
95
+ }
96
+
97
+ window.addEventListener("page_revisit", page_seen_function, false);
98
+
99
+ function page_seen_function(e) {
100
+ var view_count = e.detail.count;
101
+ console.log("This page has been seen " + e.detail.count + " times");
102
+ if (view_count > 10) {
103
+ console.log("Page has been viewed more than 10 times");
104
+ }
105
+ }
106
+
107
+ _inbound.add_action('session_start', session_start_func, 10);
108
+
109
+ function session_start_func(data) {
110
+ //alert('Session starting Now');
111
+ }
112
+
113
+ _inbound.add_action('session_resume', session_resume_func, 10);
114
+
115
+ function session_resume_func(data) {
116
+ //alert('Session Resume');
117
+ }
118
+
119
+
120
+
121
+ _inbound.add_action('session_init', session_end_func, 10);
122
+
123
+ function session_end_func(data) {
124
+ //alert('Session session_end');
125
+ }
126
+
127
+
128
+ _inbound.add_action('session_end', session_end_func, 10);
129
+
130
+ function session_end_func(data) {
131
+ //alert('Session session_end');
132
+ }
133
+
134
+ _inbound.add_action('analytics_ready', analytics_ready_func, 10);
135
+
136
+ function analytics_ready_func(data) {
137
+ //alert('analytics_ready');
138
+ }
139
+
140
+ _inbound.add_action('form_input_change', form_input_change_func, 10);
141
+
142
+ function form_input_change_func(inputData) {
143
+ var inputData = inputData || {};
144
+ console.log(inputData); // View input data object
145
+ console.log(inputData.node + '[name="' + inputData.name + '"]');
146
+ /*jQuery(inputData.node + '[name="'+inputData.name+'"]')
147
+ .animate({
148
+ opacity: 0.50,
149
+ left: "+=50",
150
+ }, 1000, function() {
151
+ jQuery(this).css('color', 'green');
152
+ });*/
153
+ }
154
+
155
+ _inbound.add_action('form_after_submission', form_after_submission_func, 10);
156
+
157
+ function form_after_submission_func(data) {
158
+ console.log('do this');
159
+ // alert(JSON.stringify(data));
160
+ }
161
+
162
+ /* Jquery Examples */
163
+
164
+ _inbound.add_action('form_before_submission', alert_form_data, 10);
165
+
166
+ function alert_form_data(data) {
167
+ console.log(JSON.stringify(data));
168
+ }
169
+ //_inbound.remove_action( 'inbound_form_form_before_submission');
170
+ /* raw_js_trigger event trigger */
171
+ window.addEventListener("form_before_submission", raw_js_trigger, false);
172
+
173
+ function raw_js_trigger(e) {
174
+ var data = e.detail;
175
+ console.log('Pure Javascript form_before_submission action fire');
176
+ //alert(JSON.stringify(data.raw_params));
177
+ }
178
+
179
+ if (window.jQuery) {
180
+ jQuery(document).on('form_before_submission', function(event, data) {
181
+
182
+ console.log('Run jQuery form_before_submission trigger');
183
+
184
+ });
185
+ }
shared/assets/frontend/js/analytics-src/analytics.forms.js CHANGED
@@ -1,141 +1,970 @@
1
  /**
2
- * Form functions
3
- * @param Object InboundAnalytics - Form tracking functionality
4
- * @return Object - form functions
 
 
 
 
5
  */
6
- var InboundForms = (function (InboundAnalytics) {
7
-
8
- InboundAnalytics.Forms = {
9
- // Init Form functions
10
- init: function() {
11
- this.attachFormSubmitEvent();
12
- },
13
- formLoop: function(){
14
- for(var i=0; i<window.document.forms.length; i++){
15
- var form = window.document.forms[i];
16
- var trackForm = InboundAnalytics.Utils.hasClass("wpl-track-me", form);
17
- if (trackForm) {
18
- this.attachFormSubmitEvent(form); /* attach form listener */
19
-
20
- }
21
- }
22
- },
23
- formSubmit: function(form) {
24
-
25
- },
26
- mapFormValues: function(form) {
27
- var inputByName = {};
28
- var params = [];
29
- /* test for [] array syntax */
30
- var fieldNameExp = /\[([^\[]*)\]/g;
31
- for (var i=0; i < form.elements.length; i++) {
32
-
33
- formField = form.elements[i];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  multiple = false;
35
 
36
- if (formField.name) {
37
- /* test for [] array syntax */
38
- cleanName = formField.name.replace(fieldNameExp, "_$1");
39
- if (!inputByName[cleanName]) { inputByName[cleanName] = []; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
- switch (formField.nodeName) {
42
 
43
  case 'INPUT':
44
- value = this.getInputValue(formField);
45
- console.log(value);
46
- if (value === false) { continue; }
 
 
 
 
 
 
 
47
  break;
48
 
49
  case 'SELECT':
50
- if (formField.multiple) {
51
  values = [];
52
  multiple = true;
53
 
54
- for (var j = 0; j < formField.length; j++) {
55
- if (formField[j].selected) {
56
- values.push(encodeURIComponent(formField[j].value));
57
  }
58
  }
59
 
60
  } else {
61
- value = (formField.value);
62
  }
63
- break;
64
 
65
- case 'TEXTAREA':
66
- value = formField.value;
67
  break;
68
-
69
  }
70
 
 
 
 
71
  if (value) {
72
- inputByName[cleanName].push(multiple ? values.join(',') : encodeURIComponent(value));
 
 
 
 
 
 
73
  }
74
 
75
  }
76
-
77
  }
 
 
 
 
 
78
  var matchCommon = /name|first name|last name|email|e-mail|phone|website|job title|company|tele|address|comment/;
79
- for (var inputName in inputByName) {
80
- if (matchCommon.test(inputName) !== false) {
81
- console.log(inputName + " Matches Regex");
82
- /* run mapping loop only for the matches here */
83
- }
84
- params.push( inputName + '=' + inputByName[inputName].join(',') );
85
- }
86
- var final_params = params.join('&');
87
- console.log(final_params);
88
- },
89
- getInputValue = function(input) {
90
- var value = false;
91
-
92
- switch (input.type) {
93
- case 'radio':
94
- case 'checkbox':
95
- if (input.checked) {
96
- value = input.value;
97
- }
98
- break;
99
-
100
- case 'text':
101
- case 'hidden':
102
- default:
103
- value = input.value;
104
- break;
105
-
106
- }
107
-
108
- return value;
109
-
110
- },
111
- /*
112
- inbound_form_classes: function(forms, functionName, classes) {
113
- jQuery.each(forms, function(index, id) {
114
- var selector = jQuery.trim(id);
115
- for (var this_class in classes) {
116
- if (selector.indexOf('#')>-1) {
117
- jQuery(selector)[functionName](classes[this_class]);
118
- //console.log(selector);
119
- } else if (selector.indexOf('.')>-1) {
120
- jQuery(selector)[functionName](classes[this_class]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  } else {
122
- jQuery("#" + selector)[functionName](classes[this_class]);
123
  }
124
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
 
126
- });
127
- }*/
128
- /* Add tracking class to forms */
129
- attachFormSubmitEvent: function (form) {
 
 
 
 
 
 
 
 
130
 
131
- console.log("The Form has the class wpl-track-me", hasClass);
132
- InboundAnalytics.Utils.addListener(form, 'submit', InboundAnalytics.LeadsAPI.formSubmit );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
- },
 
 
 
 
 
 
135
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
 
137
- };
138
 
139
- return InboundAnalytics;
140
 
141
- })(InboundAnalytics || {});
1
  /**
2
+ * # Inbound Forms
3
+ *
4
+ * This file contains all of the form functions of the main _inbound object.
5
+ * Filters and actions are described below
6
+ *
7
+ * @author David Wells <david@inboundnow.com>
8
+ * @version 0.0.1
9
  */
10
+ /* Finish Exclusions for CC */
11
+
12
+ /* Launches form class */
13
+ var InboundForms = (function(_inbound) {
14
+
15
+ var debugMode = false,
16
+ utils = _inbound.Utils,
17
+ no_match = [],
18
+ rawParams = [],
19
+ mappedParams = [],
20
+ settings = _inbound.Settings;
21
+
22
+ var FieldMapArray = [
23
+ "first name",
24
+ "last name",
25
+ "name",
26
+ "email",
27
+ "e-mail",
28
+ "phone",
29
+ "website",
30
+ "job title",
31
+ "your favorite food",
32
+ "company",
33
+ "tele",
34
+ "address",
35
+ "comment"
36
+ /* Adding values here maps them */
37
+ ];
38
+
39
+ _inbound.Forms = {
40
+
41
+ // Init Form functions
42
+ init: function() {
43
+ _inbound.Forms.runFieldMappingFilters();
44
+ _inbound.Forms.assignTrackClass();
45
+ _inbound.Forms.formTrackInit();
46
+ },
47
+ /**
48
+ * This triggers the forms.field_map filter on the mapping array.
49
+ * This will allow you to add or remore Items from the mapping lookup
50
+ *
51
+ * ### Example inbound.form_map_before filter
52
+ *
53
+ * This is an example of how form mapping can be filtered and
54
+ * additional fields can be mapped via javascript
55
+ *
56
+ * ```js
57
+ * // Adding the filter function
58
+ * function Inbound_Add_Filter_Example( FieldMapArray ) {
59
+ * var map = FieldMapArray || [];
60
+ * map.push('new lookup value');
61
+ *
62
+ * return map;
63
+ * };
64
+ *
65
+ * // Adding the filter on dom ready
66
+ * _inbound.hooks.addFilter( 'inbound.form_map_before', Inbound_Add_Filter_Example, 10 );
67
+ * ```
68
+ *
69
+ * @return {[type]} [description]
70
+ */
71
+ runFieldMappingFilters: function() {
72
+ FieldMapArray = _inbound.hooks.applyFilters('forms.field_map', FieldMapArray);
73
+ //alert(FieldMapArray);
74
+ },
75
+ debug: function(msg, callback) {
76
+ //if app not in debug mode, exit immediately
77
+ if (!debugMode || !console) {
78
+ return
79
+ };
80
+ var msg = msg || false;
81
+ //console.log the message
82
+ if (msg && (typeof msg === 'string')) {
83
+ console.log(msg)
84
+ };
85
+
86
+ //execute the callback if one was passed-in
87
+ if (callback && (callback instanceof Function)) {
88
+ callback();
89
+ };
90
+ },
91
+ formTrackInit: function() {
92
+
93
+ for (var i = 0; i < window.document.forms.length; i++) {
94
+ var trackForm = false;
95
+ var form = window.document.forms[i];
96
+ /* process forms only once */
97
+ if (!form.dataset.formProcessed) {
98
+ form.dataset.formProcessed = true;
99
+ trackForm = this.checkTrackStatus(form);
100
+ // var trackForm = _inbound.Utils.hasClass("wpl-track-me", form);
101
+ if (trackForm) {
102
+ this.attachFormSubmitEvent(form); /* attach form listener */
103
+ this.initFormMapping(form);
104
+ }
105
+ }
106
+ }
107
+ },
108
+ checkTrackStatus: function(form) {
109
+ var ClassIs = form.getAttribute('class');
110
+ if (ClassIs !== "" && ClassIs !== null) {
111
+ if (ClassIs.toLowerCase().indexOf("wpl-track-me") > -1) {
112
+ return true;
113
+ } else if (ClassIs.toLowerCase().indexOf("inbound-track") > -1) {
114
+ return true;
115
+ } else {
116
+ cb = function(){
117
+ console.log(form);
118
+ }
119
+ _inbound.deBugger('forms', "This form not tracked. Please assign on in settings...", cb);
120
+ return false;
121
+ }
122
+ }
123
+ },
124
+ assignTrackClass: function() {
125
+ if (window.inbound_settings) {
126
+ if (inbound_settings.inbound_track_include) {
127
+ var selectors = inbound_settings.inbound_track_include.split(',');
128
+ var msg = 'add selectors ' + inbound_settings.inbound_track_include;
129
+ _inbound.deBugger('forms', msg);
130
+ this.loopClassSelectors(selectors, 'add');
131
+ }
132
+ if (inbound_settings.inbound_track_exclude) {
133
+ var selectors = inbound_settings.inbound_track_exclude.split(',');
134
+ var msg = 'remove selectors ' + inbound_settings.inbound_track_exclude;
135
+ _inbound.deBugger('forms', msg);
136
+ this.loopClassSelectors(selectors, 'remove');
137
+ }
138
+ }
139
+ },
140
+ /* Loop through include/exclude items for tracking */
141
+ loopClassSelectors: function(selectors, action) {
142
+ for (var i = selectors.length - 1; i >= 0; i--) {
143
+
144
+ //if(selectors[i] match . or # )
145
+ selector = document.querySelector(utils.trim(selectors[i]));
146
+ //console.log("SELECTOR", selector);
147
+ if (selector) {
148
+ if (action === 'add') {
149
+ _inbound.Utils.addClass('wpl-track-me', selector);
150
+ _inbound.Utils.addClass('inbound-track', selector);
151
+ } else {
152
+ _inbound.Utils.removeClass('wpl-track-me', selector);
153
+ _inbound.Utils.removeClass('inbound-track', selector);
154
+ }
155
+ }
156
+ };
157
+ },
158
+ /* Map field fields on load */
159
+ initFormMapping: function(form) {
160
+ var hiddenInputs = [];
161
+
162
+ for (var i = 0; i < form.elements.length; i++) {
163
+ formInput = form.elements[i];
164
+
165
+ if (formInput.type === 'hidden') {
166
+ hiddenInputs.push(formInput);
167
+ continue;
168
+ }
169
+ /* Map form fields */
170
+ this.mapField(formInput);
171
+ /* Remember visible inputs */
172
+ this.rememberInputValues(formInput);
173
+ /* Fill visible inputs */
174
+ if (settings.formAutoPopulation) {
175
+ this.fillInputValues(formInput);
176
+ }
177
+
178
+ }
179
+ for (var i = hiddenInputs.length - 1; i >= 0; i--) {
180
+ formInput = hiddenInputs[i];
181
+ this.mapField(formInput);
182
+ };
183
+
184
+ //console.log('mapping on load completed');
185
+ },
186
+ /* prevent default submission temporarily */
187
+ formListener: function(event) {
188
+ //console.log(event);
189
+ event.preventDefault();
190
+ _inbound.Forms.saveFormData(event.target);
191
+ document.body.style.cursor = "wait";
192
+ },
193
+ /* attach form listeners */
194
+ attachFormSubmitEvent: function(form) {
195
+ utils.addListener(form, 'submit', this.formListener);
196
+ var email_input = document.querySelector('.inbound-email');
197
+ utils.addListener(email_input, 'blur', this.mailCheck);
198
+ },
199
+ ignoreFields: function(input) {
200
+
201
+ var ignore_field = false,
202
+ label = "",
203
+ value = "";
204
+
205
+ // Ignore any fields with labels that indicate a credit card field
206
+ if (label.toLowerCase().indexOf('credit card') != -1 || label.toLowerCase().indexOf('card number') != -1) {
207
+ ignore_field = true;
208
+ }
209
+
210
+
211
+ if (label.toLowerCase().indexOf('expiration') != -1 || label.toLowerCase().indexOf('expiry') != -1) {
212
+ ignore_field = true;
213
+ }
214
+
215
+
216
+ if (label.toLowerCase() == 'month' || label.toLowerCase() == 'mm' || label.toLowerCase() == 'yy' || label.toLowerCase() == 'yyyy' || label.toLowerCase() == 'year') {
217
+ ignore_field = true;
218
+ }
219
+
220
+
221
+ if (label.toLowerCase().indexOf('cvv') != -1 || label.toLowerCase().indexOf('cvc') != -1 || label.toLowerCase().indexOf('secure code') != -1 || label.toLowerCase().indexOf('security code') != -1) {
222
+ ignore_field = true;
223
+ }
224
+
225
+
226
+ if (value.toLowerCase() == 'visa' || value.toLowerCase() == 'mastercard' || value.toLowerCase() == 'american express' || value.toLowerCase() == 'amex' || value.toLowerCase() == 'discover') {
227
+ ignore_field = true;
228
+ }
229
+
230
+ // Check if value has integers, strip out spaces, then ignore anything with a credit card length (>16) or an expiration/cvv length (<5)
231
+ var int_regex = new RegExp("/^[0-9]+$/");
232
+ if (int_regex.test(value)) {
233
+ var value_no_spaces = value.replace(' ', '');
234
+
235
+ if (this.isInt(value_no_spaces) && value_no_spaces.length >= 16) {
236
+ ignore_field = true;
237
+ }
238
+
239
+ }
240
+
241
+ return ignore_field;
242
+
243
+ },
244
+ isInt: function(n) {
245
+ return typeof n == "number" && isFinite(n) && n % 1 === 0;
246
+ },
247
+ releaseFormSubmit: function(form) {
248
+ //console.log('remove form listener event');
249
+ document.body.style.cursor = "default";
250
+ utils.removeClass('wpl-track-me', form);
251
+ utils.removeListener(form, 'submit', this.formListener);
252
+ form.submit();
253
+ /* fallback if submit name="submit" */
254
+ setTimeout(function() {
255
+ for (var i = 0; i < form.elements.length; i++) {
256
+ formInput = form.elements[i];
257
+ type = formInput.type || false;
258
+ if (type === "submit") {
259
+ form.elements[i].click();
260
+ }
261
+ }
262
+ }, 1300);
263
+
264
+ },
265
+ saveFormData: function(form) {
266
+ var inputsObject = inputsObject || {};
267
+ for (var i = 0; i < form.elements.length; i++) {
268
+
269
+ // console.log(inputsObject);
270
+
271
+ formInput = form.elements[i];
272
  multiple = false;
273
 
274
+ if (formInput.name) {
275
+
276
+ if (formInput.dataset.ignoreFormField) {
277
+ _inbound.deBugger('forms', 'ignore ' + formInput.name);
278
+ continue;
279
+ }
280
+
281
+ inputName = formInput.name.replace(/\[([^\[]*)\]/g, "%5B%5D$1");
282
+ //inputName = inputName.replace(/-/g, "_");
283
+ if (!inputsObject[inputName]) {
284
+ inputsObject[inputName] = {};
285
+ }
286
+ if (formInput.type) {
287
+ inputsObject[inputName]['type'] = formInput.type;
288
+ }
289
+ if (!inputsObject[inputName]['name']) {
290
+ inputsObject[inputName]['name'] = formInput.name;
291
+ }
292
+ if (formInput.dataset.mapFormField) {
293
+ inputsObject[inputName]['map'] = formInput.dataset.mapFormField;
294
+ }
295
+ /*if (formInput.id) { inputsObject[inputName]['id'] = formInput.id; }
296
+ if ('classList' in document.documentElement) {
297
+ if (formInput.classList) { inputsObject[inputName]['class'] = formInput.classList; }
298
+ }*/
299
 
300
+ switch (formInput.nodeName) {
301
 
302
  case 'INPUT':
303
+ value = this.getInputValue(formInput);
304
+
305
+
306
+ if (value === false) {
307
+ continue;
308
+ }
309
+ break;
310
+
311
+ case 'TEXTAREA':
312
+ value = formInput.value;
313
  break;
314
 
315
  case 'SELECT':
316
+ if (formInput.multiple) {
317
  values = [];
318
  multiple = true;
319
 
320
+ for (var j = 0; j < formInput.length; j++) {
321
+ if (formInput[j].selected) {
322
+ values.push(encodeURIComponent(formInput[j].value));
323
  }
324
  }
325
 
326
  } else {
327
+ value = (formInput.value);
328
  }
 
329
 
330
+ console.log('select val', value);
 
331
  break;
 
332
  }
333
 
334
+ _inbound.deBugger('forms', 'Input Value = ' + value);
335
+
336
+
337
  if (value) {
338
+ /* inputsObject[inputName].push(multiple ? values.join(',') : encodeURIComponent(value)); */
339
+ if (!inputsObject[inputName]['value']) {
340
+ inputsObject[inputName]['value'] = [];
341
+ }
342
+ inputsObject[inputName]['value'].push(multiple ? values.join(',') : encodeURIComponent(value));
343
+ var value = multiple ? values.join(',') : encodeURIComponent(value);
344
+
345
  }
346
 
347
  }
 
348
  }
349
+ _inbound.deBugger('forms', inputsObject);
350
+ //console.log('These are the raw values', inputsObject);
351
+ //_inbound.totalStorage('the_key', inputsObject);
352
+ //var inputsObject = sortInputs(inputsObject);
353
+
354
  var matchCommon = /name|first name|last name|email|e-mail|phone|website|job title|company|tele|address|comment/;
355
+
356
+ for (var input in inputsObject) {
357
+ //console.log(input);
358
+
359
+ var inputValue = inputsObject[input]['value'];
360
+ var inputMappedField = inputsObject[input]['map'];
361
+ //if (matchCommon.test(input) !== false) {
362
+ //console.log(input + " Matches Regex run mapping test");
363
+ //var map = inputsObject[input];
364
+ //console.log("MAPP", map);
365
+ //mappedParams.push( input + '=' + inputsObject[input]['value'].join(',') );
366
+ //}
367
+
368
+ /* Add custom hook here to look for additional values */
369
+ if (typeof(inputValue) != "undefined" && inputValue != null && inputValue != "") {
370
+ rawParams.push(input + '=' + inputsObject[input]['value'].join(','));
371
+ }
372
+
373
+ if (typeof(inputMappedField) != "undefined" && inputMappedField != null && inputsObject[input]['value']) {
374
+ //console.log('Data ATTR', formInput.dataset.mapFormField);
375
+ mappedParams.push(inputMappedField + "=" + inputsObject[input]['value'].join(','));
376
+ if (input === 'email') {
377
+ var email = inputsObject[input]['value'].join(',');
378
+ //alert(email);
379
+
380
+ }
381
+ }
382
+ }
383
+
384
+ var raw_params = rawParams.join('&');
385
+ _inbound.deBugger('forms', "Stringified Raw Form PARAMS: " + raw_params);
386
+
387
+ var mapped_params = mappedParams.join('&');
388
+ _inbound.deBugger('forms', "Stringified Mapped PARAMS" + mapped_params);
389
+
390
+ /* Check Use form Email or Cookie */
391
+ var email = utils.getParameterVal('email', mapped_params) || utils.readCookie('wp_lead_email');
392
+
393
+ /* Legacy Email map */
394
+ if (!email) {
395
+ email = utils.getParameterVal('wpleads_email_address', mapped_params);
396
+ }
397
+
398
+ var fullName = utils.getParameterVal('name', mapped_params);
399
+ var fName = utils.getParameterVal('first_name', mapped_params);
400
+ var lName = utils.getParameterVal('last_name', mapped_params);
401
+
402
+ // Fallbacks for empty values
403
+ if (!lName && fName) {
404
+ var parts = decodeURI(fName).split(" ");
405
+ if (parts.length > 0) {
406
+ fName = parts[0];
407
+ lName = parts[1];
408
+ }
409
+ }
410
+
411
+ if (fullName && !lName && !fName) {
412
+ var parts = decodeURI(fullName).split(" ");
413
+ if (parts.length > 0) {
414
+ fName = parts[0];
415
+ lName = parts[1];
416
+ }
417
+ }
418
+
419
+ fullName = (fName && lName) ? fName + " " + lName : fullName;
420
+
421
+ _inbound.deBugger('forms', "fName = " + fName);
422
+ _inbound.deBugger('forms', "lName = " + lName);
423
+ _inbound.deBugger('forms', "fullName = " + fullName);
424
+
425
+ //return false;
426
+ var page_views = _inbound.totalStorage('page_views') || {};
427
+ var urlParams = _inbound.totalStorage('inbound_url_params') || {};
428
+
429
+ var inboundDATA = {
430
+ 'email': email
431
+ };
432
+ /* Get Variation ID */
433
+ if (typeof(landing_path_info) != "undefined") {
434
+ var variation = landing_path_info.variation;
435
+ } else if (typeof(cta_path_info) != "undefined") {
436
+ var variation = cta_path_info.variation;
437
  } else {
438
+ var variation = 0;
439
  }
440
+ var post_type = inbound_settings.post_type || 'page';
441
+ var page_id = inbound_settings.post_id || 0;
442
+ // data['wp_lead_uid'] = jQuery.cookie("wp_lead_uid") || null;
443
+ // data['search_data'] = JSON.stringify(jQuery.totalStorage('inbound_search')) || {};
444
+ search_data = {};
445
+ /* Filter here for raw */
446
+ //alert(mapped_params);
447
+ /**
448
+ * Old data model
449
+ var return_data = {
450
+ "action": 'inbound_store_lead',
451
+ "emailTo": data['email'],
452
+ "first_name": data['first_name'],
453
+ "last_name": data['last_name'],
454
+ "phone": data['phone'],
455
+ "address": data['address'],
456
+ "company_name": data['company'],
457
+ "page_views": data['page_views'],
458
+ "form_input_values": all_form_fields,
459
+ "Mapped_Data": mapped_form_data,
460
+ "Search_Data": data['search_data']
461
+ };
462
+ */
463
+ formData = {
464
+ 'action': 'inbound_lead_store',
465
+ 'email': email,
466
+ "full_name": fullName,
467
+ "first_name": fName,
468
+ "last_name": lName,
469
+ 'raw_params': raw_params,
470
+ 'mapped_params': mapped_params,
471
+ 'url_params': JSON.stringify(urlParams),
472
+ 'search_data': 'test',
473
+ 'page_views': JSON.stringify(page_views),
474
+ 'post_type': post_type,
475
+ 'page_id': page_id,
476
+ 'variation': variation,
477
+ 'source': utils.readCookie("inbound_referral_site")
478
+ };
479
 
480
+ callback = function(leadID) {
481
+ /* Action Example */
482
+
483
+ _inbound.deBugger('forms', 'Lead Created with ID: ' + leadID);
484
+ leadID = parseInt(leadID, 10);
485
+ formData.leadID = leadID;
486
+ /* Set Lead cookie ID */
487
+ if (leadID) {
488
+ utils.createCookie("wp_lead_id", leadID);
489
+ _inbound.totalStorage.deleteItem('page_views'); // remove pageviews
490
+ _inbound.totalStorage.deleteItem('tracking_events'); // remove events
491
+ }
492
 
493
+ _inbound.trigger('form_after_submission', formData);
494
+
495
+ /* Resume normal form functionality */
496
+ _inbound.Forms.releaseFormSubmit(form);
497
+
498
+ }
499
+ //_inbound.LeadsAPI.makeRequest(landing_path_info.admin_url);
500
+ //_inbound.Events.form_before_submission(formData);
501
+ _inbound.trigger('form_before_submission', formData);
502
+ //_inbound.trigger('inbound_form_before_submission', formData, true);
503
+
504
+ utils.ajaxPost(inbound_settings.admin_url, formData, callback);
505
+ },
506
+ rememberInputValues: function(input) {
507
+ var name = (input.name) ? "inbound_" + input.name : '';
508
+ var type = (input.type) ? input.type : 'text';
509
+ if (type === 'submit' || type === 'hidden' || type === 'file' || type === "password") {
510
+ return false;
511
+ }
512
+
513
+ utils.addListener(input, 'change', function(e) {
514
+
515
+ if (e.target.name) {
516
+ /* Check for input type */
517
+ if (type !== "checkbox") {
518
+ var value = e.target.value;
519
+ } else {
520
+ var values = [];
521
+ var checkboxes = document.querySelectorAll('input[name="' + e.target.name + '"]');
522
+ for (var i = 0; i < checkboxes.length; i++) {
523
+ var checked = checkboxes[i].checked;
524
+ if (checked) {
525
+ values.push(checkboxes[i].value);
526
+ }
527
+ value = values.join(',');
528
+ };
529
+ }
530
+ //console.log(e.target.nodeName);
531
+ //console.log('change ' + e.target.name + " " + encodeURIComponent(value));
532
 
533
+ inputData = {
534
+ name: e.target.name,
535
+ node: e.target.nodeName.toLowerCase(),
536
+ type: type,
537
+ value: value,
538
+ mapping: e.target.dataset.mapFormField
539
+ };
540
 
541
+ _inbound.trigger('form_input_change', inputData);
542
+ /* Set Field Input Cookies */
543
+ utils.createCookie("inbound_" + e.target.name, encodeURIComponent(value));
544
+ // _inbound.totalStorage('the_key', FormStore);
545
+ /* Push to 'unsubmitted form object' */
546
+ }
547
+
548
+ });
549
+ },
550
+ fillInputValues: function(input) {
551
+ var name = (input.name) ? "inbound_" + input.name : '';
552
+ var type = (input.type) ? input.type : 'text';
553
+ if (type === 'submit' || type === 'hidden' || type === 'file' || type === "password") {
554
+ return false;
555
+ }
556
+ if (utils.readCookie(name) && name != 'comment') {
557
+
558
+ value = decodeURIComponent(utils.readCookie(name));
559
+ if (type === 'checkbox' || type === 'radio') {
560
+ var checkbox_vals = value.split(',');
561
+ for (var i = 0; i < checkbox_vals.length; i++) {
562
+ if (input.value.indexOf(checkbox_vals[i]) > -1) {
563
+ input.checked = true;
564
+ }
565
+ }
566
+ } else {
567
+ if (value !== "undefined") {
568
+ input.value = value;
569
+ }
570
+ }
571
+ }
572
+ },
573
+ /* Maps data attributes to fields on page load */
574
+ mapField: function(input) {
575
+
576
+ var input_id = input.id || false;
577
+ var input_name = input.name || false;
578
+
579
+ /* Loop through all match possiblities */
580
+ for (i = 0; i < FieldMapArray.length; i++) {
581
+ //for (var i = FieldMapArray.length - 1; i >= 0; i--) {
582
+ var found = false;
583
+ var match = FieldMapArray[i];
584
+ var lookingFor = utils.trim(match);
585
+ var nice_name = lookingFor.replace(/ /g, '_');
586
+
587
+
588
+ //console.log("NICE NAME", nice_name);
589
+ //console.log('looking for match on ' + lookingFor);
590
+ //_inbound.deBugger('forms', 'looking for match on ' + lookingFor + " nice_name= " + nice_name);
591
+
592
+ // Check if input has an attached lable using for= tag
593
+ //var $laxbel = $("label[for='" + $element.attr('id') + "']").text();
594
+ //var labxel = 'label[for="' + input_id + '"]';
595
+
596
+ /* look for name attribute match */
597
+ if (input_name && input_name.toLowerCase().indexOf(lookingFor) > -1) {
598
+
599
+ found = true;
600
+ _inbound.deBugger('forms', 'Found matching name attribute for -> ' + lookingFor);
601
+
602
+ /* look for id match */
603
+ } else if (input_id && input_id.toLowerCase().indexOf(lookingFor) > -1) {
604
+
605
+ found = true;
606
+ _inbound.deBugger('forms', 'Found matching ID attribute for ->' + lookingFor);
607
+
608
+ /* Check siblings for label */
609
+ } else if (label = this.siblingsIsLabel(input)) {
610
+
611
+ //var label = (label.length > 1 ? label[0] : label);
612
+ //console.log('label', label);
613
+ if (label[0].innerText.toLowerCase().indexOf(lookingFor) > -1) {
614
+
615
+ found = true;
616
+ _inbound.deBugger('forms', 'Found matching sibling label for -> ' + lookingFor);
617
+
618
+ }
619
+ /* Check closest li for label */
620
+ } else if (labelText = this.CheckParentForLabel(input)) {
621
+
622
+ //console.log(labelText)
623
+
624
+ if (labelText.toLowerCase().indexOf(lookingFor) > -1) {
625
+ found = true;
626
+ _inbound.deBugger('forms', 'Found Matching parent label for -> ' + lookingFor);
627
+
628
+ }
629
+
630
+ } else {
631
+ /* no match found */
632
+ //_inbound.deBugger('forms', 'NO Match on ' + lookingFor + " in " + input_name);
633
+ no_match.push(lookingFor);
634
+
635
+ }
636
+
637
+ /* Map the field */
638
+ if (found) {
639
+ this.addDataAttr(input, nice_name);
640
+ this.removeArrayItem(FieldMapArray, lookingFor);
641
+ i--; //decrement count
642
+ }
643
+
644
+ }
645
+
646
+ return inbound_data;
647
+
648
+ },
649
+ /* Get correct input values */
650
+ getInputValue: function(input) {
651
+ var value = false;
652
+
653
+ switch (input.type) {
654
+ case 'radio':
655
+ case 'checkbox':
656
+ if (input.checked) {
657
+ value = input.value;
658
+ //console.log("CHECKBOX VAL", value)
659
+ }
660
+ break;
661
+
662
+ case 'text':
663
+ case 'hidden':
664
+ default:
665
+ value = input.value;
666
+ break;
667
+
668
+ }
669
+
670
+ return value;
671
+ },
672
+ /* Add data-map-form-field attr to input */
673
+ addDataAttr: function(formInput, match) {
674
+
675
+ var getAllInputs = document.getElementsByName(formInput.name);
676
+ for (var i = getAllInputs.length - 1; i >= 0; i--) {
677
+ if (!formInput.dataset.mapFormField) {
678
+ getAllInputs[i].dataset.mapFormField = match;
679
+ }
680
+ };
681
+ },
682
+ /* Optimize FieldMapArray array for fewer lookups */
683
+ removeArrayItem: function(array, item) {
684
+ if (array.indexOf) {
685
+ index = array.indexOf(item);
686
+ } else {
687
+ for (index = array.length - 1; index >= 0; --index) {
688
+ if (array[index] === item) {
689
+ break;
690
+ }
691
+ }
692
+ }
693
+ if (index >= 0) {
694
+ array.splice(index, 1);
695
+ }
696
+ //_inbound.deBugger('forms', 'removed ' + item + " from array");
697
+ //console.log('removed ' + item + " from array");
698
+ return;
699
+ },
700
+ /* Look for siblings that are form labels */
701
+ siblingsIsLabel: function(input) {
702
+ var siblings = this.getSiblings(input);
703
+ var labels = [];
704
+ for (var i = siblings.length - 1; i >= 0; i--) {
705
+ if (siblings[i].nodeName.toLowerCase() === 'label') {
706
+ labels.push(siblings[i]);
707
+ }
708
+ };
709
+ /* if only 1 label */
710
+ if (labels.length > 0 && labels.length < 2) {
711
+ return labels;
712
+ }
713
+
714
+ return false;
715
+ },
716
+ getChildren: function(n, skipMe) {
717
+ var r = [];
718
+ var elem = null;
719
+ for (; n; n = n.nextSibling)
720
+ if (n.nodeType == 1 && n != skipMe)
721
+ r.push(n);
722
+ return r;
723
+ },
724
+ getSiblings: function(n) {
725
+ return this.getChildren(n.parentNode.firstChild, n);
726
+ },
727
+ /* Check parent elements inside form for labels */
728
+ CheckParentForLabel: function(element) {
729
+ if (element.nodeName === 'FORM') {
730
+ return null;
731
+ }
732
+ do {
733
+ var labels = element.getElementsByTagName("label");
734
+ if (labels.length > 0 && labels.length < 2) {
735
+ return element.getElementsByTagName("label")[0].innerText;
736
+ }
737
+
738
+ } while (element = element.parentNode);
739
+
740
+ return null;
741
+ },
742
+ /* Validate Common Email addresses */
743
+ mailCheck: function() {
744
+ var email_input = document.querySelector('.inbound-email');
745
+ if (email_input) {
746
+ //
747
+ utils.addListener(email_input, 'blur', this.mailCheck);
748
+
749
+ Mailcheck.run({
750
+ email: document.querySelector('.inbound-email').value,
751
+ suggested: function(suggestion) {
752
+ // callback code
753
+
754
+ var suggest = document.querySelector('.email_suggestion');
755
+ if (suggest) {
756
+ utils.removeElement(suggest);
757
+ }
758
+ var el = document.createElement("span");
759
+ el.innerHTML = "<span class=\"email_suggestion\">Did you mean <b><i id='email_correction' style='cursor: pointer;' title=\"click to update\">" + suggestion.full + "</b></i>?</span>";
760
+ email_input.parentNode.insertBefore(el, email_input.nextSibling);
761
+ var update = document.getElementById('email_correction');
762
+ utils.addListener(update, 'click', function() {
763
+ email_input.value = update.innerHTML;
764
+ update.parentNode.parentNode.innerHTML = "Fixed!";
765
+ });
766
+ },
767
+ empty: function() {
768
+ //$(".email_suggestion").html("No Suggestions :(");
769
+ }
770
+ });
771
+ }
772
+ }
773
+
774
+ };
775
+ /* Mailcheck */
776
+ if (typeof Mailcheck === "undefined") {
777
+ var Mailcheck = {
778
+ domainThreshold: 1,
779
+ topLevelThreshold: 3,
780
+
781
+ defaultDomains: ["yahoo.com", "google.com", "hotmail.com", "gmail.com", "me.com", "aol.com", "mac.com",
782
+ "live.com", "comcast.net", "googlemail.com", "msn.com", "hotmail.co.uk", "yahoo.co.uk",
783
+ "facebook.com", "verizon.net", "sbcglobal.net", "att.net", "gmx.com", "mail.com", "outlook.com", "icloud.com"
784
+ ],
785
+
786
+ defaultTopLevelDomains: ["co.jp", "co.uk", "com", "net", "org", "info", "edu", "gov", "mil", "ca"],
787
+
788
+ run: function(opts) {
789
+ opts.domains = opts.domains || Mailcheck.defaultDomains;
790
+ opts.topLevelDomains = opts.topLevelDomains || Mailcheck.defaultTopLevelDomains;
791
+ opts.distanceFunction = opts.distanceFunction || Mailcheck.sift3Distance;
792
+
793
+ var defaultCallback = function(result) {
794
+ return result
795
+ };
796
+ var suggestedCallback = opts.suggested || defaultCallback;
797
+ var emptyCallback = opts.empty || defaultCallback;
798
+
799
+ var result = Mailcheck.suggest(Mailcheck.encodeEmail(opts.email), opts.domains, opts.topLevelDomains, opts.distanceFunction);
800
+
801
+ return result ? suggestedCallback(result) : emptyCallback()
802
+ },
803
+
804
+ suggest: function(email, domains, topLevelDomains, distanceFunction) {
805
+ email = email.toLowerCase();
806
+
807
+ var emailParts = this.splitEmail(email);
808
+
809
+ var closestDomain = this.findClosestDomain(emailParts.domain, domains, distanceFunction, this.domainThreshold);
810
+
811
+ if (closestDomain) {
812
+ if (closestDomain != emailParts.domain) {
813
+ // The email address closely matches one of the supplied domains; return a suggestion
814
+ return {
815
+ address: emailParts.address,
816
+ domain: closestDomain,
817
+ full: emailParts.address + "@" + closestDomain
818
+ };
819
+ }
820
+ } else {
821
+ // The email address does not closely match one of the supplied domains
822
+ var closestTopLevelDomain = this.findClosestDomain(emailParts.topLevelDomain, topLevelDomains, distanceFunction, this.topLevelThreshold);
823
+ if (emailParts.domain && closestTopLevelDomain && closestTopLevelDomain != emailParts.topLevelDomain) {
824
+ // The email address may have a mispelled top-level domain; return a suggestion
825
+ var domain = emailParts.domain;
826
+ closestDomain = domain.substring(0, domain.lastIndexOf(emailParts.topLevelDomain)) + closestTopLevelDomain;
827
+ return {
828
+ address: emailParts.address,
829
+ domain: closestDomain,
830
+ full: emailParts.address + "@" + closestDomain
831
+ };
832
+ }
833
+ }
834
+ /* The email address exactly matches one of the supplied domains, does not closely
835
+ * match any domain and does not appear to simply have a mispelled top-level domain,
836
+ * or is an invalid email address; do not return a suggestion.
837
+ */
838
+ return false;
839
+ },
840
+
841
+ findClosestDomain: function(domain, domains, distanceFunction, threshold) {
842
+ threshold = threshold || this.topLevelThreshold;
843
+ var dist;
844
+ var minDist = 99;
845
+ var closestDomain = null;
846
+
847
+ if (!domain || !domains) {
848
+ return false;
849
+ }
850
+ if (!distanceFunction) {
851
+ distanceFunction = this.sift3Distance;
852
+ }
853
+
854
+ for (var i = 0; i < domains.length; i++) {
855
+ if (domain === domains[i]) {
856
+ return domain;
857
+ }
858
+ dist = distanceFunction(domain, domains[i]);
859
+ if (dist < minDist) {
860
+ minDist = dist;
861
+ closestDomain = domains[i];
862
+ }
863
+ }
864
+
865
+ if (minDist <= threshold && closestDomain !== null) {
866
+ return closestDomain;
867
+ } else {
868
+ return false;
869
+ }
870
+ },
871
+
872
+ sift3Distance: function(s1, s2) {
873
+ // sift3: http://siderite.blogspot.com/2007/04/super-fast-and-accurate-string-distance.html
874
+ if (s1 == null || s1.length === 0) {
875
+ if (s2 == null || s2.length === 0) {
876
+ return 0;
877
+ } else {
878
+ return s2.length;
879
+ }
880
+ }
881
+
882
+ if (s2 == null || s2.length === 0) {
883
+ return s1.length;
884
+ }
885
+
886
+ var c = 0;
887
+ var offset1 = 0;
888
+ var offset2 = 0;
889
+ var lcs = 0;
890
+ var maxOffset = 5;
891
+
892
+ while ((c + offset1 < s1.length) && (c + offset2 < s2.length)) {
893
+ if (s1.charAt(c + offset1) == s2.charAt(c + offset2)) {
894
+ lcs++;
895
+ } else {
896
+ offset1 = 0;
897
+ offset2 = 0;
898
+ for (var i = 0; i < maxOffset; i++) {
899
+ if ((c + i < s1.length) && (s1.charAt(c + i) == s2.charAt(c))) {
900
+ offset1 = i;
901
+ break;
902
+ }
903
+ if ((c + i < s2.length) && (s1.charAt(c) == s2.charAt(c + i))) {
904
+ offset2 = i;
905
+ break;
906
+ }
907
+ }
908
+ }
909
+ c++;
910
+ }
911
+ return (s1.length + s2.length) / 2 - lcs;
912
+ },
913
+
914
+ splitEmail: function(email) {
915
+ var parts = email.trim().split("@");
916
+
917
+ if (parts.length < 2) {
918
+ return false;
919
+ }
920
+
921
+ for (var i = 0; i < parts.length; i++) {
922
+ if (parts[i] === "") {
923
+ return false;
924
+ }
925
+ }
926
+
927
+ var domain = parts.pop();
928
+ var domainParts = domain.split(".");
929
+ var tld = "";
930
+
931
+ if (domainParts.length == 0) {
932
+ // The address does not have a top-level domain
933
+ return false;
934
+ } else if (domainParts.length == 1) {
935
+ // The address has only a top-level domain (valid under RFC)
936
+ tld = domainParts[0];
937
+ } else {
938
+ // The address has a domain and a top-level domain
939
+ for (var i = 1; i < domainParts.length; i++) {
940
+ tld += domainParts[i] + ".";
941
+ }
942
+ if (domainParts.length >= 2) {
943
+ tld = tld.substring(0, tld.length - 1);
944
+ }
945
+ }
946
+
947
+ return {
948
+ topLevelDomain: tld,
949
+ domain: domain,
950
+ address: parts.join("@")
951
+ }
952
+ },
953
+
954
+ // Encode the email address to prevent XSS but leave in valid
955
+ // characters, following this official spec:
956
+ // http://en.wikipedia.org/wiki/Email_address#Syntax
957
+ encodeEmail: function(email) {
958
+ var result = encodeURI(email);
959
+ result = result.replace("%20", " ").replace("%25", "%").replace("%5E", "^")
960
+ .replace("%60", "`").replace("%7B", "{").replace("%7C", "|")
961
+ .replace("%7D", "}");
962
+ return result;
963
+ }
964
+ }
965
+ } // End Mailcheck
966
 
 
967
 
968
+ return _inbound;
969
 
970
+ })(_inbound || {});
shared/assets/frontend/js/analytics-src/analytics.hooks.js ADDED
@@ -0,0 +1,404 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * # Hooks & Filters
3
+ *
4
+ * This file contains all of the form functions of the main _inbound object.
5
+ * Filters and actions are described below
6
+ *
7
+ * Forked from https://github.com/carldanley/WP-JS-Hooks/blob/master/src/event-manager.js
8
+ *
9
+ * @author David Wells <david@inboundnow.com>
10
+ * @version 0.0.1
11
+ */
12
+
13
+ var _inboundHooks = (function (_inbound) {
14
+
15
+ /**
16
+ * # EventManager
17
+ *
18
+ * Actions and filters List
19
+ * addAction( 'namespace.identifier', callback, priority )
20
+ * addFilter( 'namespace.identifier', callback, priority )
21
+ * removeAction( 'namespace.identifier' )
22
+ * removeFilter( 'namespace.identifier' )
23
+ * doAction( 'namespace.identifier', arg1, arg2, moreArgs, finalArg )
24
+ * applyFilters( 'namespace.identifier', content )
25
+ * @return {[type]} [description]
26
+ */
27
+
28
+ /**
29
+ * Handles managing all events for whatever you plug it into. Priorities for hooks are based on lowest to highest in
30
+ * that, lowest priority hooks are fired first.
31
+ */
32
+ var EventManager = function() {
33
+ /**
34
+ * Maintain a reference to the object scope so our public methods never get confusing.
35
+ */
36
+ var MethodsAvailable = {
37
+ removeFilter : removeFilter,
38
+ applyFilters : applyFilters,
39
+ addFilter : addFilter,
40
+ removeAction : removeAction,
41
+ doAction : doAction,
42
+ addAction : addAction
43
+ };
44
+
45
+ /**
46
+ * Contains the hooks that get registered with this EventManager. The array for storage utilizes a "flat"
47
+ * object literal such that looking up the hook utilizes the native object literal hash.
48
+ */
49
+ var STORAGE = {
50
+ actions : {},
51
+ filters : {}
52
+ };
53
+
54
+ /**
55
+ * Adds an action to the event manager.
56
+ *
57
+ * @param action Must contain namespace.identifier
58
+ * @param callback Must be a valid callback function before this action is added
59
+ * @param [priority=10] Used to control when the function is executed in relation to other callbacks bound to the same hook
60
+ * @param [context] Supply a value to be used for this
61
+ */
62
+ function addAction( action, callback, priority, context ) {
63
+ if( typeof action === 'string' && typeof callback === 'function' ) {
64
+ priority = parseInt( ( priority || 10 ), 10 );
65
+ _addHook( 'actions', action, callback, priority, context );
66
+ }
67
+
68
+ return MethodsAvailable;
69
+ }
70
+
71
+ /**
72
+ * Performs an action if it exists. You can pass as many arguments as you want to this function; the only rule is
73
+ * that the first argument must always be the action.
74
+ */
75
+ function doAction( /* action, arg1, arg2, ... */ ) {
76
+ var args = Array.prototype.slice.call( arguments );
77
+ var action = args.shift();
78
+
79
+ if( typeof action === 'string' ) {
80
+ _runHook( 'actions', action, args );
81
+ }
82
+
83
+ return MethodsAvailable;
84
+ }
85
+
86
+ /**
87
+ * Removes the specified action if it contains a namespace.identifier & exists.
88
+ *
89
+ * @param action The action to remove
90
+ * @param [callback] Callback function to remove
91
+ */
92
+ function removeAction( action, callback ) {
93
+ if( typeof action === 'string' ) {
94
+ _removeHook( 'actions', action, callback );
95
+ }
96
+
97
+ return MethodsAvailable;
98
+ }
99
+
100
+ /**
101
+ * Adds a filter to the event manager.
102
+ *
103
+ * @param filter Must contain namespace.identifier
104
+ * @param callback Must be a valid callback function before this action is added
105
+ * @param [priority=10] Used to control when the function is executed in relation to other callbacks bound to the same hook
106
+ * @param [context] Supply a value to be used for this
107
+ */
108
+ function addFilter( filter, callback, priority, context ) {
109
+ if( typeof filter === 'string' && typeof callback === 'function' ) {
110
+ //console.log('add filter', filter);
111
+ priority = parseInt( ( priority || 10 ), 10 );
112
+ _addHook( 'filters', filter, callback, priority );
113
+ }
114
+
115
+ return MethodsAvailable;
116
+ }
117
+
118
+ /**
119
+ * Performs a filter if it exists. You should only ever pass 1 argument to be filtered. The only rule is that
120
+ * the first argument must always be the filter.
121
+ */
122
+ function applyFilters( /* filter, filtered arg, arg2, ... */ ) {
123
+ var args = Array.prototype.slice.call( arguments );
124
+ var filter = args.shift();
125
+
126
+ if( typeof filter === 'string' ) {
127
+ return _runHook( 'filters', filter, args );
128
+ }
129
+
130
+ return MethodsAvailable;
131
+ }
132
+
133
+ /**
134
+ * Removes the specified filter if it contains a namespace.identifier & exists.
135
+ *
136
+ * @param filter The action to remove
137
+ * @param [callback] Callback function to remove
138
+ */
139
+ function removeFilter( filter, callback ) {
140
+ if( typeof filter === 'string') {
141
+ _removeHook( 'filters', filter, callback );
142
+ }
143
+
144
+ return MethodsAvailable;
145
+ }
146
+
147
+ /**
148
+ * Removes the specified hook by resetting the value of it.
149
+ *
150
+ * @param type Type of hook, either 'actions' or 'filters'
151
+ * @param hook The hook (namespace.identifier) to remove
152
+ * @private
153
+ */
154
+ function _removeHook( type, hook, callback, context ) {
155
+ if ( !STORAGE[ type ][ hook ] ) {
156
+ return;
157
+ }
158
+ if ( !callback ) {
159
+ STORAGE[ type ][ hook ] = [];
160
+ } else {
161
+ var handlers = STORAGE[ type ][ hook ];
162
+ var i;
163
+ if ( !context ) {
164
+ for ( i = handlers.length; i--; ) {
165
+ if ( handlers[i].callback === callback ) {
166
+ handlers.splice( i, 1 );
167
+ }
168
+ }
169
+ }
170
+ else {
171
+ for ( i = handlers.length; i--; ) {
172
+ var handler = handlers[i];
173
+ if ( handler.callback === callback && handler.context === context) {
174
+ handlers.splice( i, 1 );
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Adds the hook to the appropriate storage container
183
+ *
184
+ * @param type 'actions' or 'filters'
185
+ * @param hook The hook (namespace.identifier) to add to our event manager
186
+ * @param callback The function that will be called when the hook is executed.
187
+ * @param priority The priority of this hook. Must be an integer.
188
+ * @param [context] A value to be used for this
189
+ * @private
190
+ */
191
+ function _addHook( type, hook, callback, priority, context ) {
192
+ var hookObject = {
193
+ callback : callback,
194
+ priority : priority,
195
+ context : context
196
+ };
197
+
198
+ // Utilize 'prop itself' : http://jsperf.com/hasownproperty-vs-in-vs-undefined/19
199
+ var hooks = STORAGE[ type ][ hook ];
200
+ if( hooks ) {
201
+ hooks.push( hookObject );
202
+ hooks = _hookInsertSort( hooks );
203
+ }
204
+ else {
205
+ hooks = [ hookObject ];
206
+ }
207
+
208
+ STORAGE[ type ][ hook ] = hooks;
209
+ }
210
+
211
+ /**
212
+ * Use an insert sort for keeping our hooks organized based on priority. This function is ridiculously faster
213
+ * than bubble sort, etc: http://jsperf.com/javascript-sort
214
+ *
215
+ * @param hooks The custom array containing all of the appropriate hooks to perform an insert sort on.
216
+ * @private
217
+ */
218
+ function _hookInsertSort( hooks ) {
219
+ var tmpHook, j, prevHook;
220
+ for( var i = 1, len = hooks.length; i < len; i++ ) {
221
+ tmpHook = hooks[ i ];
222
+ j = i;
223
+ while( ( prevHook = hooks[ j - 1 ] ) && prevHook.priority > tmpHook.priority ) {
224
+ hooks[ j ] = hooks[ j - 1 ];
225
+ --j;
226
+ }
227
+ hooks[ j ] = tmpHook;
228
+ }
229
+
230
+ return hooks;
231
+ }
232
+
233
+ /**
234
+ * Runs the specified hook. If it is an action, the value is not modified but if it is a filter, it is.
235
+ *
236
+ * @param type 'actions' or 'filters'
237
+ * @param hook The hook ( namespace.identifier ) to be ran.
238
+ * @param args Arguments to pass to the action/filter. If it's a filter, args is actually a single parameter.
239
+ * @private
240
+ */
241
+ function _runHook( type, hook, args ) {
242
+ var handlers = STORAGE[ type ][ hook ];
243
+
244
+ if ( !handlers ) {
245
+ return (type === 'filters') ? args[0] : false;
246
+ }
247
+
248
+ var i = 0, len = handlers.length;
249
+ if ( type === 'filters' ) {
250
+ for ( ; i < len; i++ ) {
251
+ args[ 0 ] = handlers[ i ].callback.apply( handlers[ i ].context, args );
252
+ }
253
+ } else {
254
+ for ( ; i < len; i++ ) {
255
+ handlers[ i ].callback.apply( handlers[ i ].context, args );
256
+ }
257
+ }
258
+
259
+ return ( type === 'filters' ) ? args[ 0 ] : true;
260
+ }
261
+
262
+ // return all of the publicly available methods
263
+ return MethodsAvailable;
264
+
265
+ };
266
+
267
+ _inbound.hooks = new EventManager();
268
+
269
+
270
+ /**
271
+ * Event Hooks and Filters public methods
272
+ */
273
+ /*
274
+ * add_action
275
+ *
276
+ * This function uses _inbound.hooks to mimics WP add_action
277
+ *
278
+ * ```js
279
+ * function Inbound_Add_Action_Example(data) {
280
+ * // Do stuff here.
281
+ * };
282
+ * // Add action to the hook
283
+ * _inbound.add_action( 'name_of_action', Inbound_Add_Action_Example, 10 );
284
+ * ```
285
+ */
286
+ _inbound.add_action = function() {
287
+ // allow multiple action parameters such as 'ready append'
288
+ var actions = arguments[0].split(' ');
289
+
290
+ for( k in actions ) {
291
+
292
+ // prefix action
293
+ arguments[0] = 'inbound.' + actions[ k ];
294
+
295
+ _inbound.hooks.addAction.apply(this, arguments);
296
+ }
297
+
298
+ return this;
299
+
300
+ };
301
+ /*
302
+ * remove_action
303
+ *
304
+ * This function uses _inbound.hooks to mimics WP remove_action
305
+ *
306
+ * ```js
307
+ * // Add remove action 'name_of_action'
308
+ * _inbound.remove_action( 'name_of_action');
309
+ * ```
310
+ *
311
+ */
312
+ _inbound.remove_action = function() {
313
+ // prefix action
314
+ arguments[0] = 'inbound.' + arguments[0];
315
+ _inbound.hooks.removeAction.apply(this, arguments);
316
+
317
+ return this;
318
+
319
+ };
320
+ /*
321
+ * do_action
322
+ *
323
+ * This function uses _inbound.hooks to mimics WP do_action
324
+ * This is used if you want to allow for third party JS plugins to act on your functions
325
+ *
326
+ */
327
+ _inbound.do_action = function() {
328
+ // prefix action
329
+ arguments[0] = 'inbound.' + arguments[0];
330
+ _inbound.hooks.doAction.apply(this, arguments);
331
+
332
+ return this;
333
+
334
+ };
335
+ /*
336
+ * add_filter
337
+ *
338
+ * This function uses _inbound.hooks to mimics WP add_filter
339
+ *
340
+ * ```js
341
+ * _inbound.add_filter( 'urlParamFilter', URL_Param_Filter, 10 );
342
+ * function URL_Param_Filter(urlParams) {
343
+ *
344
+ * var params = urlParams || {};
345
+ * // check for item in object
346
+ * if(params.utm_source !== "undefined"){
347
+ * //alert('url param "utm_source" is here');
348
+ * }
349
+ *
350
+ * // delete item from object
351
+ * delete params.utm_source;
352
+ *
353
+ * return params;
354
+ *
355
+ * }
356
+ * ```
357
+ */
358
+ _inbound.add_filter = function() {
359
+ // prefix action
360
+ arguments[0] = 'inbound.' + arguments[0];
361
+ _inbound.hooks.addFilter.apply(this, arguments);
362
+
363
+ return this;
364
+
365
+ };
366
+ /*
367
+ * remove_filter
368
+ *
369
+ * This function uses _inbound.hooks to mimics WP remove_filter
370
+ *
371
+ * ```js
372
+ * // Add remove filter 'urlParamFilter'
373
+ * _inbound.remove_action( 'urlParamFilter');
374
+ * ```
375
+ *
376
+ */
377
+ _inbound.remove_filter = function() {
378
+ // prefix action
379
+ arguments[0] = 'inbound.' + arguments[0];
380
+
381
+ _inbound.hooks.removeFilter.apply(this, arguments);
382
+
383
+ return this;
384
+
385
+ };
386
+ /*
387
+ * apply_filters
388
+ *
389
+ * This function uses _inbound.hooks to mimics WP apply_filters
390
+ *
391
+ */
392
+ _inbound.apply_filters = function() {
393
+ //console.log('Filter:' + arguments[0] + " ran on ->", arguments[1]);
394
+ // prefix action
395
+ arguments[0] = 'inbound.' + arguments[0];
396
+
397
+ return _inbound.hooks.applyFilters.apply(this, arguments);
398
+
399
+ };
400
+
401
+
402
+ return _inbound;
403
+
404
+ })(_inbound || {});
shared/assets/frontend/js/analytics-src/analytics.init.js CHANGED
@@ -1,7 +1,10 @@
1
  /**
2
- * Lead Tracking JS
3
- * http://www.inboundnow.com
4
- * This is the main analytics entry point
 
 
 
5
  */
6
 
7
  var inbound_data = inbound_data || {};
@@ -9,34 +12,120 @@ var _inboundOptions = _inboundOptions || {};
9
  /* Ensure global _gaq Google Analytics queue has been initialized. */
10
  var _gaq = _gaq || [];
11
 
12
- var InboundAnalytics = (function (Options) {
13
-
14
- /* Constants */
15
- var debugMode = false;
16
-
17
- var App = {
18
- /* Initialize individual modules */
19
- init: function () {
20
- InboundAnalytics.Utils.init();
21
- InboundAnalytics.PageTracking.StorePageView();
22
- InboundAnalytics.Events.loadEvents();
23
- InboundAnalytics.Forms.init();
24
- },
25
- /* Debugger Function toggled by var debugMode */
26
- debug: function(msg, callback){
27
- //if app not in debug mode, exit immediately
28
- if(!debugMode || !console){return};
29
- var msg = msg || false;
30
- //console.log the message
31
- if(msg && (typeof msg === 'string')){console.log(msg)};
32
-
33
- //execute the callback if one was passed-in
34
- if(callback && (callback instanceof Function)){
35
- callback();
36
- };
37
- }
38
- };
39
-
40
- return App;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  })(_inboundOptions);
1
  /**
2
+ * # _inbound
3
+ *
4
+ * This main the _inbound class
5
+ *
6
+ * @author David Wells <david@inboundnow.com>
7
+ * @version 0.0.1
8
  */
9
 
10
  var inbound_data = inbound_data || {};
12
  /* Ensure global _gaq Google Analytics queue has been initialized. */
13
  var _gaq = _gaq || [];
14
 
15
+ var _inbound = (function(options) {
16
+ /* Constants */
17
+ var defaults = {
18
+
19
+ timeout: 30000,
20
+ formAutoTracking: true,
21
+ formAutoPopulation: true
22
+ };
23
+
24
+ var Analytics = {
25
+ /* Initialize individual modules */
26
+ init: function() {
27
+ _inbound.Utils.init();
28
+
29
+ _inbound.Utils.domReady(window, function() {
30
+ /* On Load Analytics Events */
31
+ _inbound.DomLoaded();
32
+
33
+ });
34
+ },
35
+ DomLoaded: function() {
36
+ _inbound.PageTracking.init();
37
+ /* run form mapping */
38
+ _inbound.Forms.init();
39
+ /* set URL params */
40
+ _inbound.Utils.setUrlParams();
41
+ _inbound.LeadsAPI.init();
42
+ /* run form mapping for dynamically generated forms */
43
+ setTimeout(function() {
44
+ _inbound.Forms.init();
45
+ }, 2000);
46
+
47
+
48
+ _inbound.trigger('analytics_ready');
49
+
50
+ },
51
+ /**
52
+ * Merge script defaults with user options
53
+ * @private
54
+ * @param {Object} defaults Default settings
55
+ * @param {Object} options User options
56
+ * @returns {Object} Merged values of defaults and options
57
+ */
58
+ extend: function(defaults, options) {
59
+ var extended = {};
60
+ var prop;
61
+ for (prop in defaults) {
62
+ if (Object.prototype.hasOwnProperty.call(defaults, prop)) {
63
+ extended[prop] = defaults[prop];
64
+ }
65
+ }
66
+ for (prop in options) {
67
+ if (Object.prototype.hasOwnProperty.call(options, prop)) {
68
+ extended[prop] = options[prop];
69
+ }
70
+ }
71
+ return extended;
72
+ },
73
+ /* Debugger Function toggled by var debugMode */
74
+ debug: function(msg, callback) {
75
+ /* legacy */
76
+ },
77
+ deBugger: function(context, msg, callback) {
78
+
79
+ if (!console) {
80
+ return;
81
+ }
82
+ //if app not in debug mode, exit immediately
83
+ // check for hash
84
+ var hash = (document.location.hash) ? document.location.hash : '',
85
+ debugHash = hash.indexOf("#debug") > -1,
86
+ msg = msg || false,
87
+ logCookie,
88
+ logAllMessages,
89
+ hashcontext;
90
+
91
+ if (hash && hash.match(/debug/)) {
92
+ hash = hash.split('-');
93
+ hashcontext = hash[1];
94
+ }
95
+
96
+
97
+ logAllMessages = (_inbound.Utils.readCookie("inbound_debug") === "true") ? true : false;
98
+ logCookie = (_inbound.Utils.readCookie("inbound_debug_" + context) === "true") ? true : false;
99
+
100
+ if (!logCookie && !debugHash && !logAllMessages) {
101
+ // no logger set. exit.
102
+ return;
103
+ };
104
+
105
+ //console.log the message
106
+ if (msg && (typeof msg === 'string')) {
107
+
108
+ if (logAllMessages || hashcontext === 'all') {
109
+ console.log('logAll "' + context + '" =>', msg)
110
+ } else if (logCookie) {
111
+ console.log('log "' + context + '" =>', msg)
112
+ } else if (context === hashcontext) {
113
+ console.log('#log "' + context + '" =>', msg)
114
+ }
115
+
116
+ };
117
+
118
+ //execute the callback if one was passed-in
119
+ if (callback && (callback instanceof Function)) {
120
+ callback();
121
+ };
122
+ }
123
+ };
124
+
125
+ var settings = Analytics.extend(defaults, options);
126
+ /* Set globals */
127
+ Analytics.Settings = settings || {};
128
+
129
+ return Analytics;
130
 
131
  })(_inboundOptions);
shared/assets/frontend/js/analytics-src/analytics.lead.js ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Leads API functions
3
+ * @param Object _inbound - Main JS object
4
+ * @return Object - include event triggers
5
+ */
6
+ var _inboundLeadsAPI = (function(_inbound) {
7
+ var httpRequest;
8
+ _inbound.LeadsAPI = {
9
+ init: function() {
10
+
11
+ var utils = _inbound.Utils,
12
+ wp_lead_uid = utils.readCookie("wp_lead_uid"),
13
+ wp_lead_id = utils.readCookie("wp_lead_id"),
14
+ expire_check = utils.readCookie("lead_session_expire"); // check for session
15
+
16
+ if (!expire_check) {
17
+ _inbound.deBugger('leads', 'expired vistor. Run Processes');
18
+ //var data_to_lookup = global-localized-vars;
19
+ if (wp_lead_id) {
20
+ /* Get InboundLeadData */
21
+ _inbound.LeadsAPI.getAllLeadData();
22
+ /* Lead list check */
23
+ _inbound.LeadsAPI.getLeadLists();
24
+ }
25
+ }
26
+ },
27
+ setGlobalLeadData: function(data) {
28
+ InboundLeadData = data;
29
+ },
30
+ getAllLeadData: function(expire_check) {
31
+ var wp_lead_id = _inbound.Utils.readCookie("wp_lead_id"),
32
+ leadData = _inbound.totalStorage('inbound_lead_data'),
33
+ leadDataExpire = _inbound.Utils.readCookie("lead_data_expire");
34
+ data = {
35
+ action: 'inbound_get_all_lead_data',
36
+ wp_lead_id: wp_lead_id,
37
+ },
38
+ success = function(returnData) {
39
+ var leadData = JSON.parse(returnData);
40
+ _inbound.LeadsAPI.setGlobalLeadData(leadData);
41
+ _inbound.totalStorage('inbound_lead_data', leadData); // store lead data
42
+
43
+ /* Set 3 day timeout for checking DB for new lead data for Lead_Global var */
44
+ var d = new Date();
45
+ d.setTime(d.getTime() + 30 * 60 * 1000);
46
+ var expire = _inbound.Utils.addDays(d, 3);
47
+ _inbound.Utils.createCookie("lead_data_expire", true, expire);
48
+
49
+ };
50
+
51
+ if (!leadData) {
52
+ // Get New Lead Data from DB
53
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, success);
54
+
55
+ } else {
56
+ // set global lead var with localstorage data
57
+ _inbound.LeadsAPI.setGlobalLeadData(leadData);
58
+ _inbound.deBugger('lead', 'Set Global Lead Data from Localstorage');
59
+
60
+ if (!leadDataExpire) {
61
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, success);
62
+ //console.log('Set Global Lead Data from Localstorage');
63
+ _inbound.deBugger('lead', 'localized data old. Pull new from DB');
64
+ //console.log('localized data old. Pull new from DB');
65
+ }
66
+ }
67
+
68
+ },
69
+ getLeadLists: function() {
70
+ var wp_lead_id = _inbound.Utils.readCookie("wp_lead_id");
71
+ var data = {
72
+ action: 'wpl_check_lists',
73
+ wp_lead_id: wp_lead_id,
74
+ };
75
+ var success = function(user_id) {
76
+ _inbound.Utils.createCookie("lead_session_list_check", true, {
77
+ path: '/',
78
+ expires: 1
79
+ });
80
+ _inbound.deBugger('lead', "Lists checked");
81
+ //console.log("Lists checked");
82
+ };
83
+ //_inbound.Utils.doAjax(data, success);
84
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, success);
85
+ }
86
+ };
87
+
88
+ return _inbound;
89
+
90
+ })(_inbound || {});
shared/assets/frontend/js/analytics-src/analytics.page.js ADDED
@@ -0,0 +1,361 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * # Page View Tracking
3
+ *
4
+ * Page view tracking
5
+ *
6
+ * @author David Wells <david@inboundnow.com>
7
+ * @version 0.0.1
8
+ */
9
+ /* Launches view tracking */
10
+ var _inboundPageTracking = (function(_inbound) {
11
+
12
+ var started = false,
13
+ stopped = false,
14
+ turnedOff = false,
15
+ clockTime = parseInt(_inbound.Utils.readCookie("lead_session"), 10) || 0,
16
+ inactiveClockTime = 0,
17
+ startTime = new Date(),
18
+ clockTimer = null,
19
+ inactiveClockTimer = null,
20
+ idleTimer = null,
21
+ reportInterval,
22
+ idleTimeout,
23
+ utils = _inbound.Utils,
24
+ Pages = _inbound.totalStorage('page_views') || {},
25
+ timeNow = _inbound.Utils.GetDate(),
26
+ /*!
27
+ Todo: Use UTC offset
28
+ var x = new Date();
29
+ var currentTime = x.getTimezoneOffset() / 60;
30
+ console.log(currentTime) // gets UTC offset
31
+ */
32
+ id = inbound_settings.post_id || window.location.pathname,
33
+ analyticsTimeout = _inbound.Settings.timeout || 30000;
34
+
35
+ _inbound.PageTracking = {
36
+
37
+ init: function(options) {
38
+
39
+ this.CheckTimeOut();
40
+ // Set up options and defaults
41
+ options = options || {};
42
+ reportInterval = parseInt(options.reportInterval, 10) || 10;
43
+ idleTimeout = parseInt(options.idleTimeout, 10) || 3;
44
+
45
+ // Basic activity event listeners
46
+ utils.addListener(document, 'keydown', utils.throttle(_inbound.PageTracking.pingSession, 1000));
47
+ utils.addListener(document, 'click', utils.throttle(_inbound.PageTracking.pingSession, 1000));
48
+ utils.addListener(window, 'mousemove', utils.throttle(_inbound.PageTracking.pingSession, 1000));
49
+ //utils.addListener(window, 'scroll', utils.throttle(_inbound.PageTracking.pingSession, 1000));
50
+
51
+ // Page visibility listeners
52
+ _inbound.PageTracking.checkVisibility();
53
+
54
+ /* Start Session on page load */
55
+ this.startSession();
56
+
57
+ },
58
+
59
+ setIdle: function(reason) {
60
+ var reason = reason || "No Movement",
61
+ msg = 'Session IDLE. Activity Timeout due to ' + reason;
62
+
63
+ _inbound.deBugger('pages', msg);
64
+
65
+ clearTimeout(_inbound.PageTracking.idleTimer);
66
+ _inbound.PageTracking.stopClock();
67
+ _inbound.trigger('session_idle');
68
+
69
+ },
70
+
71
+ checkVisibility: function() {
72
+ var hidden, visibilityState, visibilityChange;
73
+
74
+ if (typeof document.hidden !== "undefined") {
75
+ hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
76
+ } else if (typeof document.mozHidden !== "undefined") {
77
+ hidden = "mozHidden", visibilityChange = "mozvisibilitychange", visibilityState = "mozVisibilityState";
78
+ } else if (typeof document.msHidden !== "undefined") {
79
+ hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
80
+ } else if (typeof document.webkitHidden !== "undefined") {
81
+ hidden = "webkitHidden", visibilityChange = "webkitvisibilitychange", visibilityState = "webkitVisibilityState";
82
+ }
83
+
84
+ var document_hidden = document[hidden];
85
+
86
+ _inbound.Utils.addListener(document, visibilityChange, function(e) {
87
+ /*! Listen for visibility changes */
88
+ if (document_hidden != document[hidden]) {
89
+ if (document[hidden]) {
90
+ // Document hidden
91
+ _inbound.trigger('tab_hidden');
92
+ _inbound.PageTracking.setIdle('browser tab switch');
93
+ } else {
94
+ // Document shown
95
+ _inbound.trigger('tab_visible');
96
+ _inbound.PageTracking.pingSession();
97
+ }
98
+
99
+ document_hidden = document[hidden];
100
+ }
101
+ });
102
+ },
103
+ clock: function() {
104
+ clockTime += 1;
105
+ var niceTime = clockTime / 60;
106
+ var msg = 'Total time spent on Page in this Session: ' + niceTime.toFixed(2) + " min";
107
+ _inbound.deBugger('pages', msg);
108
+ if (clockTime > 0 && (clockTime % reportInterval === 0)) {
109
+
110
+ var d = new Date();
111
+ d.setTime(d.getTime() + 30 * 60 * 1000);
112
+ utils.createCookie("lead_session", clockTime, d); // Set cookie on page load
113
+
114
+ /*! every 10 seconds run this */
115
+ //console.log('Session Heartbeat every ' + reportInterval + ' secs');
116
+ _inbound.trigger('session_heartbeat', clockTime);
117
+
118
+ }
119
+
120
+ },
121
+ inactiveClock: function() {
122
+ inactiveClockTime += 1;
123
+ var TimeUntilTimeOut = (1800 - inactiveClockTime) / 60;
124
+ var msg = 'Time until Session Timeout: ' + TimeUntilTimeOut.toFixed(2) + " min";
125
+ _inbound.deBugger('pages', msg);
126
+ //console.log('Time until Session Timeout: ', TimeUntilTimeOut.toFixed(2) + " min");
127
+ /* Session timeout after 30min */
128
+ if (inactiveClockTime > 1800) {
129
+
130
+ // sendEvent(clockTime);
131
+ /*! End session after 30min timeout */
132
+ _inbound.trigger('session_end', InboundLeadData);
133
+ _inbound.Utils.eraseCookie("lead_session");
134
+ /* todo maybe? remove session Cookie */
135
+ inactiveClockTime = 0;
136
+ clearTimeout(inactiveClockTimer);
137
+ }
138
+
139
+
140
+ },
141
+ stopClock: function() {
142
+ stopped = true;
143
+ clearTimeout(clockTimer);
144
+ clearTimeout(inactiveClockTimer);
145
+ inactiveClockTimer = setInterval(_inbound.PageTracking.inactiveClock, 1000);
146
+ },
147
+
148
+ restartClock: function() {
149
+ stopped = false;
150
+
151
+
152
+ _inbound.trigger('session_resume');
153
+ _inbound.deBugger('pages', 'Activity resumed. Session Active');
154
+ /* todo add session_resume */
155
+ clearTimeout(clockTimer);
156
+ inactiveClockTime = 0;
157
+ clearTimeout(inactiveClockTimer);
158
+ clockTimer = setInterval(_inbound.PageTracking.clock, 1000);
159
+ },
160
+
161
+ turnOff: function() {
162
+ _inbound.PageTracking.setIdle();
163
+ turnedOff = true;
164
+ },
165
+
166
+ turnOn: function() {
167
+ turnedOff = false;
168
+ },
169
+ /* This start only runs once */
170
+ startSession: function() {
171
+ /* todo add session Cookie */
172
+ // Calculate seconds from start to first interaction
173
+ var currentTime = new Date();
174
+ var diff = currentTime - startTime;
175
+
176
+
177
+ started = true; // Set global
178
+
179
+ // Send User Timing Event
180
+ /* Todo session start here */
181
+
182
+ // Start clock
183
+ clockTimer = setInterval(_inbound.PageTracking.clock, 1000);
184
+ //utils.eraseCookie("lead_session");
185
+ var session = utils.readCookie("lead_session");
186
+
187
+ if (!session) {
188
+ _inbound.trigger('session_start'); // trigger 'inbound_analytics_session_start'
189
+ var d = new Date();
190
+ d.setTime(d.getTime() + 30 * 60 * 1000);
191
+ _inbound.Utils.createCookie("lead_session", 1, d); // Set cookie on page load
192
+ } else {
193
+ _inbound.trigger('session_active');
194
+ //console.log("count of secs " + session);
195
+ //_inbound.trigger('session_active'); // trigger 'inbound_analytics_session_active'
196
+ }
197
+
198
+ this.pingSession();
199
+
200
+
201
+ },
202
+ resetInactiveFunc: function() {
203
+ inactiveClockTime = 0;
204
+ clearTimeout(inactiveClockTimer);
205
+ },
206
+ /* Ping Session to keep active */
207
+ pingSession: function(e) {
208
+
209
+
210
+ if (turnedOff) {
211
+ return;
212
+ }
213
+
214
+ if (!started) {
215
+ _inbound.PageTracking.startSession();
216
+ }
217
+
218
+ if (stopped) {
219
+ _inbound.PageTracking.restartClock();
220
+ }
221
+
222
+ clearTimeout(idleTimer);
223
+
224
+ idleTimer = setTimeout(_inbound.PageTracking.setIdle, idleTimeout * 1000 + 100);
225
+
226
+ if (typeof(e) != "undefined") {
227
+ if (e.type === "mousemove") {
228
+ _inbound.PageTracking.mouseEvents(e);
229
+ }
230
+ }
231
+
232
+ },
233
+ mouseEvents: function(e) {
234
+
235
+ if (e.pageY <= 5) {
236
+ _inbound.trigger('tab_mouseout');
237
+ }
238
+
239
+ },
240
+ /**
241
+ * Returns the pages viewed by the site visitor
242
+ *
243
+ * ```js
244
+ * var pageViews = _inbound.PageTracking.getPageViews();
245
+ * // returns page view object
246
+ * ```
247
+ *
248
+ * @return {object} page view object with page ID as key and timestamp
249
+ */
250
+ getPageViews: function() {
251
+ var local_store = _inbound.Utils.checkLocalStorage();
252
+ if (local_store) {
253
+ var page_views = localStorage.getItem("page_views"),
254
+ local_object = JSON.parse(page_views);
255
+ if (typeof local_object == 'object' && local_object) {
256
+ //this.triggerPageView();
257
+ }
258
+ return local_object;
259
+ }
260
+ },
261
+ isRevisit: function(Pages) {
262
+ var revisitCheck = false;
263
+ var Pages = Pages || {};
264
+ var pageSeen = Pages[id];
265
+ if (typeof(pageSeen) != "undefined" && pageSeen !== null) {
266
+ revisitCheck = true;
267
+ }
268
+ return revisitCheck;
269
+ },
270
+ triggerPageView: function(pageRevisit) {
271
+
272
+ var pageData = {
273
+ title: document.title,
274
+ url: document.location.href,
275
+ path: document.location.pathname,
276
+ count: 1 // default
277
+ };
278
+
279
+ if (pageRevisit) {
280
+ /* Page Revisit Trigger */
281
+ Pages[id].push(timeNow);
282
+ pageData.count = Pages[id].length;
283
+ _inbound.trigger('page_revisit', pageData);
284
+
285
+ } else {
286
+ /* Page First Seen Trigger */
287
+ Pages[id] = [];
288
+ Pages[id].push(timeNow);
289
+ _inbound.trigger('page_first_visit', pageData);
290
+ }
291
+
292
+ _inbound.trigger('page_visit', pageData);
293
+
294
+ _inbound.totalStorage('page_views', Pages);
295
+
296
+ this.storePageView();
297
+
298
+ },
299
+ CheckTimeOut: function() {
300
+ var pageRevisit = this.isRevisit(Pages),
301
+ status,
302
+ timeout;
303
+
304
+ /* Default */
305
+ if (pageRevisit) {
306
+ var prev = Pages[id].length - 1,
307
+ lastView = Pages[id][prev],
308
+ timeDiff = Math.abs(new Date(lastView).getTime() - new Date(timeNow).getTime());
309
+
310
+ timeout = timeDiff > analyticsTimeout;
311
+
312
+ if (timeout) {
313
+ status = 'Timeout Happened. Page view fired';
314
+ this.triggerPageView(pageRevisit);
315
+ } else {
316
+ time_left = Math.abs((analyticsTimeout - timeDiff)) * 0.001;
317
+ status = analyticsTimeout / 1000 + ' sec timeout not done: ' + time_left + " seconds left";
318
+ }
319
+
320
+ } else {
321
+ /*! Page never seen before save view */
322
+ this.triggerPageView(pageRevisit);
323
+ }
324
+
325
+ _inbound.deBugger('pages', status);
326
+ },
327
+ storePageView: function() {
328
+ var leadID = _inbound.Utils.readCookie('wp_lead_id'),
329
+ lead_uid = _inbound.Utils.readCookie('wp_lead_uid');
330
+
331
+ if (leadID) {
332
+
333
+ var data = {
334
+ action: 'wpl_track_user',
335
+ wp_lead_uid: lead_uid,
336
+ wp_lead_id: leadID,
337
+ page_id: inbound_settings.post_id,
338
+ current_url: window.location.href,
339
+ json: '0'
340
+ };
341
+ var firePageCallback = function(leadID) {
342
+ //_inbound.Events.page_view_saved(leadID);
343
+ };
344
+ //_inbound.Utils.doAjax(data, firePageCallback);
345
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, firePageCallback);
346
+ }
347
+ }
348
+ /*! GA functions
349
+ function log_event(category, action, label) {
350
+ _gaq.push(['_trackEvent', category, action, label]);
351
+ }
352
+
353
+ function log_click(category, link) {
354
+ log_event(category, 'Click', $(link).text());
355
+ }
356
+ */
357
+ };
358
+
359
+ return _inbound;
360
+
361
+ })(_inbound || {});
shared/assets/frontend/js/analytics-src/analytics.start.js ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * # Start
3
+ *
4
+ * Runs init functions
5
+ *
6
+ * @author David Wells <david@inboundnow.com>
7
+ * @version 0.0.1
8
+ */
9
+
10
+
11
+ /* Initialize _inbound */
12
+ _inbound.init();
13
+
14
+ /* Set Global Lead Data */
15
+ InboundLeadData = _inbound.totalStorage('inbound_lead_data') || null;
16
+
shared/assets/frontend/js/analytics-src/analytics.storage.js CHANGED
@@ -1,9 +1,7 @@
1
- /* Fork of jquery.total-storage.js */
2
- var InboundTotalStorage = (function (InboundAnalytics){
3
 
4
- /* Variables I'll need throghout */
5
-
6
- var supported, ls, mod = 'inboundAnalytics';
7
  if ('localStorage' in window){
8
  try {
9
  ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
@@ -21,29 +19,28 @@ var InboundTotalStorage = (function (InboundAnalytics){
21
  }
22
 
23
  /* Make the methods public */
24
- InboundAnalytics.totalStorage = function(key, value, options){
25
- return InboundAnalytics.totalStorage.impl.init(key, value);
26
  };
27
 
28
- InboundAnalytics.totalStorage.setItem = function(key, value){
29
- return InboundAnalytics.totalStorage.impl.setItem(key, value);
30
  };
31
 
32
- InboundAnalytics.totalStorage.getItem = function(key){
33
- return InboundAnalytics.totalStorage.impl.getItem(key);
34
  };
35
 
36
- InboundAnalytics.totalStorage.getAll = function(){
37
- return InboundAnalytics.totalStorage.impl.getAll();
38
  };
39
 
40
- InboundAnalytics.totalStorage.deleteItem = function(key){
41
- return InboundAnalytics.totalStorage.impl.deleteItem(key);
42
  };
43
 
44
- /* Object to hold all methods: public and private */
45
 
46
- InboundAnalytics.totalStorage.impl = {
47
 
48
  init: function(key, value){
49
  if (typeof value != 'undefined') {
@@ -56,7 +53,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
56
  setItem: function(key, value){
57
  if (!supported){
58
  try {
59
- InboundAnalytics.Utils.createCookie(key, value);
60
  return value;
61
  } catch(e){
62
  console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie');
@@ -69,7 +66,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
69
  getItem: function(key){
70
  if (!supported){
71
  try {
72
- return this.parseResult(InboundAnalytics.Utils.readCookie(key));
73
  } catch(e){
74
  return null;
75
  }
@@ -80,7 +77,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
80
  deleteItem: function(key){
81
  if (!supported){
82
  try {
83
- InboundAnalytics.Utils.eraseCookie(key, null);
84
  return true;
85
  } catch(e){
86
  return false;
@@ -97,7 +94,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
97
  for (var i = 0; i<pairs.length; i++){
98
  var pair = pairs[i].split('=');
99
  var key = pair[0];
100
- items.push({key:key, value:this.parseResult(InboundAnalytics.Utils.readCookie(key))});
101
  }
102
  } catch(e){
103
  return null;
@@ -133,4 +130,4 @@ var InboundTotalStorage = (function (InboundAnalytics){
133
  return ret;
134
  }
135
  };
136
- })(InboundAnalytics || {});
1
+ /* LocalStorage Component */
2
+ var InboundTotalStorage = (function (_inbound){
3
 
4
+ var supported, ls, mod = '_inbound';
 
 
5
  if ('localStorage' in window){
6
  try {
7
  ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
19
  }
20
 
21
  /* Make the methods public */
22
+ _inbound.totalStorage = function(key, value, options){
23
+ return _inbound.totalStorage.impl.init(key, value);
24
  };
25
 
26
+ _inbound.totalStorage.setItem = function(key, value){
27
+ return _inbound.totalStorage.impl.setItem(key, value);
28
  };
29
 
30
+ _inbound.totalStorage.getItem = function(key){
31
+ return _inbound.totalStorage.impl.getItem(key);
32
  };
33
 
34
+ _inbound.totalStorage.getAll = function(){
35
+ return _inbound.totalStorage.impl.getAll();
36
  };
37
 
38
+ _inbound.totalStorage.deleteItem = function(key){
39
+ return _inbound.totalStorage.impl.deleteItem(key);
40
  };
41
 
 
42
 
43
+ _inbound.totalStorage.impl = {
44
 
45
  init: function(key, value){
46
  if (typeof value != 'undefined') {
53
  setItem: function(key, value){
54
  if (!supported){
55
  try {
56
+ _inbound.Utils.createCookie(key, value);
57
  return value;
58
  } catch(e){
59
  console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie');
66
  getItem: function(key){
67
  if (!supported){
68
  try {
69
+ return this.parseResult(_inbound.Utils.readCookie(key));
70
  } catch(e){
71
  return null;
72
  }
77
  deleteItem: function(key){
78
  if (!supported){
79
  try {
80
+ _inbound.Utils.eraseCookie(key, null);
81
  return true;
82
  } catch(e){
83
  return false;
94
  for (var i = 0; i<pairs.length; i++){
95
  var pair = pairs[i].split('=');
96
  var key = pair[0];
97
+ items.push({key:key, value:this.parseResult(_inbound.Utils.readCookie(key))});
98
  }
99
  } catch(e){
100
  return null;
130
  return ret;
131
  }
132
  };
133
+ })(_inbound || {});
shared/assets/frontend/js/analytics-src/analytics.utils.js CHANGED
@@ -1,374 +1,664 @@
1
  /**
2
- * Utility functions
3
- * @param Object InboundAnalytics - Main JS object
4
- * include util functions
 
 
 
5
  */
6
- var InboundAnalyticsUtils = (function (InboundAnalytics) {
7
-
8
- InboundAnalytics.Utils = {
9
- init: function() {
10
- this.polyFills();
11
- this.setUrlParams();
12
- this.SetUID();
13
- this.getReferer();
14
-
15
- },
16
- /* Polyfills for missing browser functionality */
17
- polyFills: function() {
18
- /* Console.log fix for old browsers */
19
- if (!window.console) { window.console = {}; }
20
- var m = [
21
- "log", "info", "warn", "error", "debug", "trace", "dir", "group",
22
- "groupCollapsed", "groupEnd", "time", "timeEnd", "profile", "profileEnd",
23
- "dirxml", "assert", "count", "markTimeline", "timeStamp", "clear"
24
- ];
25
- // define undefined methods as noops to prevent errors
26
- for (var i = 0; i < m.length; i++) {
27
- if (!window.console[m[i]]) {
28
- window.console[m[i]] = function() {};
29
- }
30
- }
31
- /* Event trigger polyfill for IE9 and 10 */
32
- (function () {
33
- function CustomEvent ( event, params ) {
34
- params = params || { bubbles: false, cancelable: false, detail: undefined };
35
- var evt = document.createEvent( 'CustomEvent' );
36
- evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
37
- return evt;
38
- };
39
 
40
- CustomEvent.prototype = window.Event.prototype;
41
-
42
- window.CustomEvent = CustomEvent;
43
- })();
44
- },
45
- // Create cookie
46
- createCookie: function(name, value, days, custom_time) {
47
- var expires = "";
48
- if (days) {
49
- var date = new Date();
50
- date.setTime(date.getTime()+(days*24*60*60*1000));
51
- expires = "; expires="+date.toGMTString();
52
- }
53
- if(custom_time){
54
- expires = "; expires="+days.toGMTString();
55
- }
56
- document.cookie = name+"="+value+expires+"; path=/";
57
- },
58
- /* Read cookie */
59
- readCookie: function(name) {
60
- var nameEQ = name + "=";
61
- var ca = document.cookie.split(';');
62
- for(var i=0;i < ca.length;i++) {
63
- var c = ca[i];
64
- while (c.charAt(0) === ' ') {
65
- c = c.substring(1,c.length);
66
- }
67
- if (c.indexOf(nameEQ) === 0) {
68
- return c.substring(nameEQ.length,c.length);
69
- }
70
- }
71
- return null;
72
- },
73
- /* Erase cookies */
74
- eraseCookie: function(name) {
75
- createCookie(name,"",-1);
76
- },
77
- /* Get All Cookies */
78
- getAllCookies: function(){
79
- var cookies = {};
80
- if (document.cookie && document.cookie != '') {
81
- var split = document.cookie.split(';');
82
- for (var i = 0; i < split.length; i++) {
83
- var name_value = split[i].split("=");
84
- name_value[0] = name_value[0].replace(/^ /, '');
85
- cookies[decodeURIComponent(name_value[0])] = decodeURIComponent(name_value[1]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  }
87
- }
88
- jQuery.totalStorage('inbound_cookies', cookies); // store cookie data
89
- return cookies;
90
- },
91
- /* Grab URL params and save */
92
- setUrlParams: function() {
93
- var urlParams = {},
94
- local_store = this.checkLocalStorage();
95
-
96
- (function () {
97
- var e,
98
- d = function (s) { return decodeURIComponent(s).replace(/\+/g, " "); },
99
- q = window.location.search.substring(1),
100
- r = /([^&=]+)=?([^&]*)/g;
101
-
102
- while (e = r.exec(q)) {
103
- if (e[1].indexOf("[") == "-1")
104
- urlParams[d(e[1])] = d(e[2]);
105
- else {
106
- var b1 = e[1].indexOf("["),
107
- aN = e[1].slice(b1+1, e[1].indexOf("]", b1)),
108
- pN = d(e[1].slice(0, b1));
109
-
110
- if (typeof urlParams[pN] != "object")
111
- urlParams[d(pN)] = {},
112
- urlParams[d(pN)].length = 0;
113
-
114
- if (aN)
115
- urlParams[d(pN)][d(aN)] = d(e[2]);
116
- else
117
- Array.prototype.push.call(urlParams[d(pN)], d(e[2]));
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
- }
121
  })();
122
 
123
- if (JSON) {
124
- for (var k in urlParams) {
125
- if (typeof urlParams[k] == "object") {
126
  for (var k2 in urlParams[k])
127
- this.createCookie(k2, urlParams[k][k2], 30);
128
- } else {
129
  this.createCookie(k, urlParams[k], 30);
130
- }
131
- }
 
 
 
 
 
132
  }
133
 
134
- if(local_store){
135
- var pastParams = jQuery.totalStorage('inbound_url_params');
136
- var params = this.mergeObjs(pastParams, urlParams);
137
- jQuery.totalStorage('inbound_url_params', params); // store cookie data
 
 
 
 
 
138
  }
139
- },
140
- getUrlParams: function(){
141
- var local_store = this.checkLocalStorage(),
142
- get_params = {};
143
- if(local_store){
144
- var get_params = jQuery.totalStorage('inbound_url_params');
145
- }
146
- return get_params;
147
- },
148
- // Check local storage
149
- // provate browsing safari fix https://github.com/marcuswestin/store.js/issues/42#issuecomment-25274685
150
- checkLocalStorage: function() {
151
- if ('localStorage' in window) {
152
- try {
153
- ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
154
- if (typeof ls == 'undefined' || typeof window.JSON == 'undefined'){
155
- supported = false;
156
- } else {
157
- supported = true;
158
- }
159
-
160
- }
161
- catch (err){
162
- supported = false;
163
  }
164
- }
165
- return supported;
166
- /* http://spin.atomicobject.com/2013/01/23/ios-private-browsing-localstorage/
167
- var hasStorage;
168
- hasStorage = function() {
169
- var mod, result;
170
- try {
171
- mod = new Date;
172
- localStorage.setItem(mod, mod.toString());
173
- result = localStorage.getItem(mod) === mod.toString();
174
- localStorage.removeItem(mod);
175
- return result;
176
- } catch (_error) {}
177
- };
178
- */
179
- },
180
- /* Add days to datetime */
181
- addDays: function(myDate,days) {
182
- return new Date(myDate.getTime() + days*24*60*60*1000);
183
- },
184
- GetDate: function(){
185
- var time_now = new Date(),
186
- day = time_now.getDate() + 1;
187
- year = time_now.getFullYear(),
188
- hour = time_now.getHours(),
189
- minutes = time_now.getMinutes(),
190
- seconds = time_now.getSeconds(),
191
- month = time_now.getMonth() + 1;
192
- if (month < 10) { month = '0' + month; }
193
- InboundAnalytics.debug('Current Date:',function(){
194
- console.log(year + '/' + month + "/" + day + " " + hour + ":" + minutes + ":" + seconds);
195
- });
196
- var datetime = year + '/' + month + "/" + day + " " + hour + ":" + minutes + ":" + seconds;
197
- return datetime;
198
- },
199
- /* Set Expiration Date of Session Logging */
200
- SetSessionTimeout: function(){
201
- var session_check = this.readCookie("lead_session_expire");
202
- //console.log(session_check);
203
- if(session_check === null){
204
- InboundAnalytics.Events.sessionStart(); // trigger 'inbound_analytics_session_start'
205
- } else {
206
- InboundAnalytics.Events.sessionActive(); // trigger 'inbound_analytics_session_active'
207
- }
208
- var d = new Date();
209
- d.setTime(d.getTime() + 30*60*1000);
210
-
211
- this.createCookie("lead_session_expire", true, d, true); // Set cookie on page loads
212
- var lead_data_expiration = this.readCookie("lead_data_expiration");
213
- if (lead_data_expiration === null){
214
- /* Set 3 day timeout for checking DB for new lead data for Lead_Global var */
215
- var ex = this.addDays(d, 3);
216
- this.createCookie("lead_data_expiration", ex, ex, true);
217
- }
218
 
219
- },
220
- getReferer: function(){
221
- //console.log(expire_time);
222
- var d = new Date();
223
- d.setTime(d.getTime() + 30*60*1000);
224
- var referrer_cookie = InboundAnalytics.Utils.readCookie("wp_lead_referral_site");
225
- if (typeof (referrer_cookie) === "undefined" || referrer_cookie === null || referrer_cookie === "") {
226
- var referrer = document.referrer || "NA";
227
- this.createCookie("wp_lead_referral_site", referrer, d, true); // Set cookie on page loads
228
- }
229
- },
230
- CreateUID: function(length) {
231
- var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(''),
232
- str = '';
233
- if (! length) {
234
- length = Math.floor(Math.random() * chars.length);
235
- }
236
- for (var i = 0; i < length; i++) {
237
- str += chars[Math.floor(Math.random() * chars.length)];
238
- }
239
- return str;
240
- },
241
- SetUID: function () {
242
- /* Set Lead UID */
243
-
244
- if(this.readCookie("wp_lead_uid") === null) {
245
- var wp_lead_uid = this.CreateUID(35);
246
- this.createCookie("wp_lead_uid", wp_lead_uid );
247
- InboundAnalytics.debug('Set UID');
248
- }
249
- },
250
- /* Count number of session visits */
251
- countProperties: function (obj) {
252
- var count = 0;
253
- for(var prop in obj) {
254
- if(obj.hasOwnProperty(prop))
255
- ++count;
256
- }
257
- return count;
258
- },
259
- mergeObjs: function(obj1,obj2){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  var obj3 = {};
261
- for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
262
- for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
 
 
 
 
263
  return obj3;
264
- },
265
- hasClass: function(className, el) {
266
- var hasClass = false;
267
- if ('classList' in document.documentElement) {
268
- var hasClass = el.classList.contains(className);
269
- } else {
270
- var hasClass = new RegExp('(^|\\s)' + className + '(\\s|$)').test(el.className); /* IE Polyfill */
271
- }
272
- return hasClass;
273
- },
274
- trim: function(s) {
275
- s = s.replace(/(^\s*)|(\s*$)/gi,"");
276
- s = s.replace(/[ ]{2,}/gi," ");
277
- s = s.replace(/\n /,"\n"); return s;
278
- },
279
- doAjax: function(data, responseHandler, method, async){
280
- // Set the variables
281
- var url = wplft.admin_url || "",
282
- method = method || "POST",
283
- async = async || true,
284
- data = data || null,
285
- action = data.action;
286
-
287
- InboundAnalytics.debug('Ajax Processed:',function(){
288
- console.log('ran ajax action: ' + action);
289
- });
290
-
291
- jQuery.ajax({
292
- type: method,
293
- url: wplft.admin_url,
294
- data: data,
295
- success: responseHandler,
296
- error: function(MLHttpRequest, textStatus, errorThrown){
297
- console.log(MLHttpRequest+' '+errorThrown+' '+textStatus);
298
- InboundAnalytics.Events.analyticsError(MLHttpRequest, textStatus, errorThrown);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  }
300
 
301
- });
302
- },
303
- makeRequest: function(url) {
304
- if (window.XMLHttpRequest) { // Mozilla, Safari, ...
305
- httpRequest = new XMLHttpRequest();
306
- } else if (window.ActiveXObject) { // IE
307
- try {
308
- httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
309
  }
310
- catch (e) {
311
- try {
312
- httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
313
- }
314
- catch (e) {}
315
  }
316
- }
317
 
318
- if (!httpRequest) {
319
- alert('Giving up :( Cannot create an XMLHTTP instance');
320
- return false;
321
  }
322
- httpRequest.onreadystatechange = InboundAnalytics.LeadsAPI.alertContents;
323
- httpRequest.open('GET', url);
324
- httpRequest.send();
325
- },
326
- contentLoaded: function(win, fn) {
327
-
328
- var done = false, top = true,
329
-
330
- doc = win.document, root = doc.documentElement,
331
-
332
- add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
333
- rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
334
- pre = doc.addEventListener ? '' : 'on',
335
-
336
- init = function(e) {
337
- if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
338
- (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
339
- if (!done && (done = true)) fn.call(win, e.type || e);
340
- },
341
-
342
- poll = function() {
343
- try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
344
- init('poll');
345
- };
346
-
347
- if (doc.readyState == 'complete') fn.call(win, 'lazy');
348
- else {
349
- if (doc.createEventObject && root.doScroll) {
350
- try { top = !win.frameElement; } catch(e) { }
351
- if (top) poll();
352
- }
353
- doc[add](pre + 'DOMContentLoaded', init, false);
354
- doc[add](pre + 'readystatechange', init, false);
355
- win[add](pre + 'load', init, false);
356
- }
357
-
358
- },
359
- /* Cross-browser event listening */
360
- addListener: function(obj, eventName, listener) {
361
- if(obj.addEventListener) {
362
- obj.addEventListener(eventName, listener, false);
363
- } else if (obj.attachEvent) {
364
- obj.attachEvent("on" + eventName, listener);
365
- } else {
366
- obj['on' + eventName] = listener;
367
- }
368
- }
369
-
370
- };
371
-
372
- return InboundAnalytics;
373
-
374
- })(InboundAnalytics || {});
1
  /**
2
+ * # _inbound UTILS
3
+ *
4
+ * This file contains all of the utility functions used by analytics
5
+ *
6
+ * @author David Wells <david@inboundnow.com>
7
+ * @version 0.0.1
8
  */
9
+ var _inboundUtils = (function(_inbound) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ var storageSupported;
12
+
13
+ _inbound.Utils = {
14
+ init: function() {
15
+
16
+ this.polyFills();
17
+ this.checkLocalStorage();
18
+ this.SetUID();
19
+ this.storeReferralData();
20
+
21
+ },
22
+ /*! http://stackoverflow.com/questions/951791/javascript-global-error-handling */
23
+ /* Polyfills for missing browser functionality */
24
+ polyFills: function() {
25
+ /* Console.log fix for old browsers */
26
+ if (!window.console) {
27
+ window.console = {};
28
+ }
29
+ var m = [
30
+ "log", "info", "warn", "error", "debug", "trace", "dir", "group",
31
+ "groupCollapsed", "groupEnd", "time", "timeEnd", "profile", "profileEnd",
32
+ "dirxml", "assert", "count", "markTimeline", "timeStamp", "clear"
33
+ ];
34
+ // define undefined methods as noops to prevent errors
35
+ for (var i = 0; i < m.length; i++) {
36
+ if (!window.console[m[i]]) {
37
+ window.console[m[i]] = function() {};
38
+ }
39
+ }
40
+ /* Event trigger polyfill for IE9 and 10
41
+ (function() {
42
+ function CustomEvent(event, params) {
43
+ params = params || {
44
+ bubbles: false,
45
+ cancelable: false,
46
+ detail: undefined
47
+ };
48
+ var evt = document.createEvent('CustomEvent');
49
+ evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
50
+ return evt;
51
+ }
52
+
53
+ CustomEvent.prototype = window.Event.prototype;
54
+
55
+ window.CustomEvent = CustomEvent;
56
+ })();*/
57
+ /* custom event for ie8+ https://gist.github.com/WebReflection/6693661 */
58
+ try{new CustomEvent('?');}catch(o_O){
59
+ /*!(C) Andrea Giammarchi -- WTFPL License*/
60
+ this.CustomEvent = function(
61
+ eventName,
62
+ defaultInitDict
63
+ ){
64
+
65
+ // the infamous substitute
66
+ function CustomEvent(type, eventInitDict) {
67
+ var event = document.createEvent(eventName);
68
+ if (type !== null) {
69
+ initCustomEvent.call(
70
+ event,
71
+ type,
72
+ (eventInitDict || (
73
+ // if falsy we can just use defaults
74
+ eventInitDict = defaultInitDict
75
+ )).bubbles,
76
+ eventInitDict.cancelable,
77
+ eventInitDict.detail
78
+ );
79
+ } else {
80
+ // no need to put the expando property otherwise
81
+ // since an event cannot be initialized twice
82
+ // previous case is the most common one anyway
83
+ // but if we end up here ... there it goes
84
+ event.initCustomEvent = initCustomEvent;
85
  }
86
+ return event;
87
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
+ // borrowed or attached at runtime
90
+ function initCustomEvent(
91
+ type, bubbles, cancelable, detail
92
+ ) {
93
+ this['init' + eventName](type, bubbles, cancelable, detail);
94
+ 'detail' in this || (this.detail = detail);
95
+ }
96
+
97
+ // that's it
98
+ return CustomEvent;
99
+ }(
100
+ // is this IE9 or IE10 ?
101
+ // where CustomEvent is there
102
+ // but not usable as construtor ?
103
+ this.CustomEvent ?
104
+ // use the CustomEvent interface in such case
105
+ 'CustomEvent' : 'Event',
106
+ // otherwise the common compatible one
107
+ {
108
+ bubbles: false,
109
+ cancelable: false,
110
+ detail: null
111
+ }
112
+ );
113
+ }
114
+ /* querySelectorAll polyfill for ie7+ */
115
+ if (!document.querySelectorAll) {
116
+ document.querySelectorAll = function (selectors) {
117
+ var style = document.createElement('style'), elements = [], element;
118
+ document.documentElement.firstChild.appendChild(style);
119
+ document._qsa = [];
120
+
121
+ style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
122
+ window.scrollBy(0, 0);
123
+ style.parentNode.removeChild(style);
124
+
125
+ while (document._qsa.length) {
126
+ element = document._qsa.shift();
127
+ element.style.removeAttribute('x-qsa');
128
+ elements.push(element);
129
+ }
130
+ document._qsa = null;
131
+ return elements;
132
+ };
133
+ }
134
+
135
+ if (!document.querySelector) {
136
+ document.querySelector = function (selectors) {
137
+ var elements = document.querySelectorAll(selectors);
138
+ return (elements.length) ? elements[0] : null;
139
+ };
140
+ }
141
+ /* Innertext shim for firefox https://github.com/duckinator/innerText-polyfill/blob/master/innertext.js */
142
+ if ( (!('innerText' in document.createElement('a'))) && ('getSelection' in window) ) {
143
+ HTMLElement.prototype.__defineGetter__("innerText", function() {
144
+ var selection = window.getSelection(),
145
+ ranges = [],
146
+ str;
147
+
148
+ // Save existing selections.
149
+ for (var i = 0; i < selection.rangeCount; i++) {
150
+ ranges[i] = selection.getRangeAt(i);
151
+ }
152
+
153
+ // Deselect everything.
154
+ selection.removeAllRanges();
155
+
156
+ // Select `el` and all child nodes.
157
+ // 'this' is the element .innerText got called on
158
+ selection.selectAllChildren(this);
159
+
160
+ // Get the string representation of the selected nodes.
161
+ str = selection.toString();
162
+
163
+ // Deselect everything. Again.
164
+ selection.removeAllRanges();
165
+
166
+ // Restore all formerly existing selections.
167
+ for (var i = 0; i < ranges.length; i++) {
168
+ selection.addRange(ranges[i]);
169
+ }
170
+
171
+ // Oh look, this is what we wanted.
172
+ // String representation of the element, close to as rendered.
173
+ return str;
174
+ })
175
+ }
176
+ },
177
+ /**
178
+ * Create cookie
179
+ *
180
+ * ```js
181
+ * // Creates cookie for 10 days
182
+ * _inbound.utils.createCookie( 'cookie_name', 'value', 10 );
183
+ * ```
184
+ *
185
+ * @param {string} name Name of cookie
186
+ * @param {string} value Value of cookie
187
+ * @param {string} days Length of storage
188
+ */
189
+ createCookie: function(name, value, days) {
190
+ var expires = "";
191
+ if (days) {
192
+ var date = new Date();
193
+ date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
194
+ expires = "; expires=" + date.toGMTString();
195
+ }
196
+ document.cookie = name + "=" + value + expires + "; path=/";
197
+ },
198
+ /**
199
+ * Read cookie value
200
+ *
201
+ * ```js
202
+ * var cookie = _inbound.utils.readCookie( 'cookie_name' );
203
+ * console.log(cookie); // cookie value
204
+ * ```
205
+ * @param {string} name name of cookie
206
+ * @return {string} value of cookie
207
+ */
208
+ readCookie: function(name) {
209
+ var nameEQ = name + "=";
210
+ var ca = document.cookie.split(';');
211
+ for (var i = 0; i < ca.length; i++) {
212
+ var c = ca[i];
213
+ while (c.charAt(0) === ' ') {
214
+ c = c.substring(1, c.length);
215
+ }
216
+ if (c.indexOf(nameEQ) === 0) {
217
+ return c.substring(nameEQ.length, c.length);
218
+ }
219
+ }
220
+ return null;
221
+ },
222
+ /**
223
+ * Erase cookie
224
+ *
225
+ * ```js
226
+ * // usage:
227
+ * _inbound.utils.eraseCookie( 'cookie_name' );
228
+ * // deletes 'cookie_name' value
229
+ * ```
230
+ * @param {string} name name of cookie
231
+ * @return {string} value of cookie
232
+ */
233
+ eraseCookie: function(name) {
234
+ this.createCookie(name, "", -1);
235
+ },
236
+ /* Get All Cookies */
237
+ getAllCookies: function() {
238
+ var cookies = {};
239
+ if (document.cookie && document.cookie !== '') {
240
+ var split = document.cookie.split(';');
241
+ for (var i = 0; i < split.length; i++) {
242
+ var name_value = split[i].split("=");
243
+ name_value[0] = name_value[0].replace(/^ /, '');
244
+ cookies[decodeURIComponent(name_value[0])] = decodeURIComponent(name_value[1]);
245
+ }
246
+ }
247
+ _inbound.totalStorage('inbound_cookies', cookies); // store cookie data
248
+ return cookies;
249
+ },
250
+ /* Grab URL params and save */
251
+ setUrlParams: function() {
252
+ var urlParams = {};
253
+
254
+ (function() {
255
+ var e,
256
+ d = function(s) {
257
+ return decodeURIComponent(s).replace(/\+/g, " ");
258
+ },
259
+ q = window.location.search.substring(1),
260
+ r = /([^&=]+)=?([^&]*)/g;
261
+
262
+ while (e = r.exec(q)) {
263
+ if (e[1].indexOf("[") == "-1")
264
+ urlParams[d(e[1])] = d(e[2]);
265
+ else {
266
+ var b1 = e[1].indexOf("["),
267
+ aN = e[1].slice(b1 + 1, e[1].indexOf("]", b1)),
268
+ pN = d(e[1].slice(0, b1));
269
+
270
+ if (typeof urlParams[pN] != "object")
271
+ urlParams[d(pN)] = {},
272
+ urlParams[d(pN)].length = 0;
273
+
274
+ if (aN)
275
+ urlParams[d(pN)][d(aN)] = d(e[2]);
276
+ else
277
+ Array.prototype.push.call(urlParams[d(pN)], d(e[2]));
278
+
279
+ }
280
  }
 
281
  })();
282
 
283
+ /* Set Param Cookies */
284
+ for (var k in urlParams) {
285
+ if (typeof urlParams[k] == "object") {
286
  for (var k2 in urlParams[k])
287
+ this.createCookie(k2, urlParams[k][k2], 30);
288
+ } else {
289
  this.createCookie(k, urlParams[k], 30);
290
+ }
291
+ }
292
+ /* Set Param LocalStorage */
293
+ if (storageSupported) {
294
+ var pastParams = _inbound.totalStorage('inbound_url_params') || {};
295
+ var params = this.mergeObjs(pastParams, urlParams);
296
+ _inbound.totalStorage('inbound_url_params', params); // store cookie data
297
  }
298
 
299
+ var options = {'option1': 'yo', 'option2': 'woooo'};
300
+
301
+ _inbound.trigger('url_parameters', urlParams, options);
302
+
303
+ },
304
+ getAllUrlParams: function() {
305
+ var get_params = {};
306
+ if (storageSupported) {
307
+ var get_params = _inbound.totalStorage('inbound_url_params');
308
  }
309
+ return get_params;
310
+ },
311
+ /* Get url param */
312
+ getParameterVal: function(name, string) {
313
+ return (RegExp(name + '=' + '(.+?)(&|$)').exec(string)||[,false])[1];
314
+ },
315
+ // Check local storage
316
+ // provate browsing safari fix https://github.com/marcuswestin/store.js/issues/42#issuecomment-25274685
317
+ checkLocalStorage: function() {
318
+ if ('localStorage' in window) {
319
+ try {
320
+ ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
321
+ if (typeof ls == 'undefined' || typeof window.JSON == 'undefined') {
322
+ storageSupported = false;
323
+ } else {
324
+ storageSupported = true;
325
+ }
326
+
327
+ } catch (err) {
328
+ storageSupported = false;
329
+ }
 
 
 
330
  }
331
+ return storageSupported;
332
+ /* http://spin.atomicobject.com/2013/01/23/ios-private-browsing-localstorage/
333
+ var hasStorage;
334
+ hasStorage = function() {
335
+ var mod, result;
336
+ try {
337
+ mod = new Date;
338
+ localStorage.setItem(mod, mod.toString());
339
+ result = localStorage.getItem(mod) === mod.toString();
340
+ localStorage.removeItem(mod);
341
+ return result;
342
+ } catch (_error) {}
343
+ };
344
+ */
345
+ },
346
+ /* Add days to datetime */
347
+ addDays: function(myDate, days) {
348
+ return new Date(myDate.getTime() + days * 24 * 60 * 60 * 1000);
349
+ },
350
+ GetDate: function() {
351
+ var timeNow = new Date(),
352
+ d = timeNow.getDate(),
353
+ dPre = (d < 10) ? "0" : "",
354
+ y = timeNow.getFullYear(),
355
+ h = timeNow.getHours(),
356
+ hPre = (h < 10) ? "0" : "",
357
+ min = timeNow.getMinutes(),
358
+ minPre = (min < 10) ? "0" : "",
359
+ sec = timeNow.getSeconds(),
360
+ secPre = (sec < 10) ? "0" : "",
361
+ m = timeNow.getMonth() + 1,
362
+ mPre = (m < 10) ? "0" : "";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
363
 
364
+ var datetime = y + '/' + mPre+m + "/" + dPre+d + " " + hPre+h + ":" + minPre+min + ":" + secPre+sec;
365
+ /* format 2014/11/13 18:22:02 */
366
+ return datetime;
367
+ },
368
+ /* Set Expiration Date of Session Logging. LEGACY Not in Use */
369
+ SetSessionTimeout: function() {
370
+ var session = this.readCookie("lead_session_expire");
371
+ //console.log(session_check);
372
+ if (!session) {
373
+ //_inbound.trigger('session_start'); // trigger 'inbound_analytics_session_start'
374
+ } else {
375
+ //_inbound.trigger('session_resume'); // trigger 'inbound_analytics_session_active'
376
+ }
377
+ var d = new Date();
378
+ d.setTime(d.getTime() + 30 * 60 * 1000);
379
+
380
+ this.createCookie("lead_session_expire", true, d, true); // Set cookie on page load
381
+
382
+ },
383
+ storeReferralData: function() {
384
+ //console.log(expire_time);
385
+ var d = new Date(),
386
+ referrer = document.referrer || "Direct Traffic",
387
+ referrer_cookie = _inbound.Utils.readCookie("inbound_referral_site"),
388
+ original_src = _inbound.totalStorage('inbound_original_referral');
389
+
390
+ d.setTime(d.getTime() + 30 * 60 * 1000);
391
+
392
+ if (!referrer_cookie) {
393
+ this.createCookie("inbound_referral_site", referrer, d, true);
394
+ }
395
+ if (!original_src) {
396
+ _inbound.totalStorage('inbound_original_referral', original_src);
397
+ }
398
+ },
399
+ CreateUID: function(length) {
400
+ var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(''),
401
+ str = '';
402
+ if (!length) {
403
+ length = Math.floor(Math.random() * chars.length);
404
+ }
405
+ for (var i = 0; i < length; i++) {
406
+ str += chars[Math.floor(Math.random() * chars.length)];
407
+ }
408
+ return str;
409
+ },
410
+ SetUID: function(leadUID) {
411
+ /* Set Lead UID */
412
+ if (!this.readCookie("wp_lead_uid")) {
413
+ var wp_lead_uid = leadUID || this.CreateUID(35);
414
+ this.createCookie("wp_lead_uid", wp_lead_uid);
415
+ }
416
+ },
417
+ /* Count number of session visits */
418
+ countProperties: function(obj) {
419
+ var count = 0;
420
+ for (var prop in obj) {
421
+ if (obj.hasOwnProperty(prop))
422
+ ++count;
423
+ }
424
+ return count;
425
+ },
426
+ mergeObjs: function(obj1, obj2) {
427
  var obj3 = {};
428
+ for (var attrname in obj1) {
429
+ obj3[attrname] = obj1[attrname];
430
+ }
431
+ for (var attrname in obj2) {
432
+ obj3[attrname] = obj2[attrname];
433
+ }
434
  return obj3;
435
+ },
436
+ hasClass: function(className, el) {
437
+ var hasClass = false;
438
+ if ('classList' in document.documentElement) {
439
+ var hasClass = el.classList.contains(className);
440
+ } else {
441
+ var hasClass = new RegExp('(^|\\s)' + className + '(\\s|$)').test(el.className); /* IE Polyfill */
442
+ }
443
+ return hasClass;
444
+ },
445
+ addClass: function(className, elem) {
446
+ if ('classList' in document.documentElement) {
447
+ elem.classList.add(className);
448
+ } else {
449
+ if (!this.hasClass(elem, className)) {
450
+ elem.className += (elem.className ? ' ' : '') + className;
451
+ }
452
+ }
453
+ },
454
+ removeClass: function(className, elem) {
455
+ if ('classList' in document.documentElement) {
456
+
457
+ elem.classList.remove(className);
458
+ } else {
459
+ if (this.hasClass(elem, className)) {
460
+ elem.className = elem.className.replace(new RegExp('(^|\\s)*' + className + '(\\s|$)*', 'g'), '');
461
+ }
462
+ }
463
+ },
464
+ removeElement: function (el) {
465
+ el.parentNode.removeChild(el);
466
+ },
467
+ trim: function(s) {
468
+ s = s.replace(/(^\s*)|(\s*$)/gi, "");
469
+ s = s.replace(/[ ]{2,}/gi, " ");
470
+ s = s.replace(/\n /, "\n");
471
+ return s;
472
+ },
473
+ ajaxPolyFill: function() {
474
+ if (typeof XMLHttpRequest !== 'undefined') {
475
+ return new XMLHttpRequest();
476
+ }
477
+ var versions = [
478
+ "MSXML2.XmlHttp.5.0",
479
+ "MSXML2.XmlHttp.4.0",
480
+ "MSXML2.XmlHttp.3.0",
481
+ "MSXML2.XmlHttp.2.0",
482
+ "Microsoft.XmlHttp"
483
+ ];
484
+
485
+ var xhr;
486
+ for (var i = 0; i < versions.length; i++) {
487
+ try {
488
+ xhr = new ActiveXObject(versions[i]);
489
+ break;
490
+ } catch (e) {}
491
+ }
492
+ return xhr;
493
+ },
494
+ ajaxSendData: function(url, callback, method, data, sync) {
495
+ var x = this.ajaxPolyFill();
496
+ x.open(method, url, sync);
497
+ x.onreadystatechange = function() {
498
+ if (x.readyState == 4) {
499
+ callback(x.responseText)
500
+ }
501
+ };
502
+ if (method == 'POST') {
503
+ x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
504
+ }
505
+ x.send(data);
506
+ },
507
+ ajaxGet: function(url, data, callback, sync) {
508
+ var query = [];
509
+ for (var key in data) {
510
+ query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
511
+ }
512
+ this.ajaxSendData(url + '?' + query.join('&'), callback, 'GET', null, sync)
513
+ },
514
+ ajaxPost: function(url, data, callback, sync) {
515
+ var query = [];
516
+ for (var key in data) {
517
+ query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
518
+ }
519
+ this.ajaxSendData(url, callback, 'POST', query.join('&'), sync)
520
+ },
521
+ makeRequest: function(url, data) {
522
+ if (window.XMLHttpRequest) { // Mozilla, Safari, ...
523
+ httpRequest = new XMLHttpRequest();
524
+ } else if (window.ActiveXObject) { // IE
525
+ try {
526
+ httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
527
+ } catch (e) {
528
+ try {
529
+ httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
530
+ } catch (e) {}
531
+ }
532
+ }
533
+
534
+ if (!httpRequest) {
535
+ alert('Giving up :( Cannot create an XMLHTTP instance');
536
+ return false;
537
+ }
538
+ httpRequest.onreadystatechange = _inbound.LeadsAPI.alertContents;
539
+ httpRequest.open('GET', url);
540
+ httpRequest.send(data);
541
+ },
542
+ domReady: function(win, fn) {
543
+
544
+ var done = false,
545
+ top = true,
546
+
547
+ doc = win.document,
548
+ root = doc.documentElement,
549
+
550
+ add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
551
+ rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
552
+ pre = doc.addEventListener ? '' : 'on',
553
+
554
+ init = function(e) {
555
+ if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
556
+ (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
557
+ if (!done && (done = true)) fn.call(win, e.type || e);
558
+ },
559
+
560
+ poll = function() {
561
+ try {
562
+ root.doScroll('left');
563
+ } catch (e) {
564
+ setTimeout(poll, 50);
565
+ return;
566
+ }
567
+ init('poll');
568
+ };
569
+
570
+ if (doc.readyState == 'complete') fn.call(win, 'lazy');
571
+ else {
572
+ if (doc.createEventObject && root.doScroll) {
573
+ try {
574
+ top = !win.frameElement;
575
+ } catch (e) {}
576
+ if (top) poll();
577
+ }
578
+ doc[add](pre + 'DOMContentLoaded', init, false);
579
+ doc[add](pre + 'readystatechange', init, false);
580
+ win[add](pre + 'load', init, false);
581
+ }
582
+
583
+ },
584
+ /* Cross-browser event listening */
585
+ addListener: function(element, eventName, listener) {
586
+ if(!element){
587
+ return;
588
+ }
589
+ //console.log(eventName);
590
+ //console.log(listener);
591
+ if (element.addEventListener) {
592
+ element.addEventListener(eventName, listener, false);
593
+ } else if (element.attachEvent) {
594
+ element.attachEvent("on" + eventName, listener);
595
+ } else {
596
+ element['on' + eventName] = listener;
597
+ }
598
+ },
599
+ removeListener: function(element, eventName, listener) {
600
+
601
+ if (element.removeEventListener) {
602
+ element.removeEventListener(eventName, listener, false);
603
+ } else if (element.detachEvent) {
604
+ element.detachEvent("on" + eventName, listener);
605
+ } else {
606
+ element["on" + eventName] = null;
607
+ }
608
+ },
609
+ /*
610
+ * Throttle function borrowed from:
611
+ * Underscore.js 1.5.2
612
+ * http://underscorejs.org
613
+ * (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
614
+ * Underscore may be freely distributed under the MIT license.
615
+ */
616
+ throttle: function (func, wait) {
617
+ var context, args, result;
618
+ var timeout = null;
619
+ var previous = 0;
620
+ var later = function() {
621
+ previous = new Date;
622
+ timeout = null;
623
+ result = func.apply(context, args);
624
+ };
625
+ return function() {
626
+ var now = new Date;
627
+ if (!previous) previous = now;
628
+ var remaining = wait - (now - previous);
629
+ context = this;
630
+ args = arguments;
631
+ if (remaining <= 0) {
632
+ clearTimeout(timeout);
633
+ timeout = null;
634
+ previous = now;
635
+ result = func.apply(context, args);
636
+ } else if (!timeout) {
637
+ timeout = setTimeout(later, remaining);
638
+ }
639
+ return result;
640
+ };
641
+ },
642
+ /*
643
+ * Determine which version of GA is being used
644
+ * "ga", "_gaq", and "dataLayer" are the possible globals
645
+ */
646
+ checkTypeofGA: function() {
647
+ if (typeof ga === "function") {
648
+ universalGA = true;
649
  }
650
 
651
+ if (typeof _gaq !== "undefined" && typeof _gaq.push === "function") {
652
+ classicGA = true;
 
 
 
 
 
 
653
  }
654
+
655
+ if (typeof dataLayer !== "undefined" && typeof dataLayer.push === "function") {
656
+ googleTagManager = true;
 
 
657
  }
 
658
 
 
 
 
659
  }
660
+ };
661
+
662
+ return _inbound;
663
+
664
+ })(_inbound || {});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
shared/assets/frontend/js/analytics/inboundAnalytics.js CHANGED
@@ -1,683 +1,2696 @@
1
  /*! Inbound Analyticsv1.0.0 | (c) 2014 Inbound Now | https://github.com/inboundnow/cta */
2
  /**
3
- * Lead Tracking JS
4
- * http://www.inboundnow.com
5
- * This is the main analytics entry point
 
 
 
6
  */
 
7
  var inbound_data = inbound_data || {};
8
  var _inboundOptions = _inboundOptions || {};
9
  /* Ensure global _gaq Google Analytics queue has been initialized. */
10
  var _gaq = _gaq || [];
11
 
12
- var InboundAnalytics = (function (Options) {
13
-
14
- /* Constants */
15
- var debugMode = false;
16
-
17
- var App = {
18
- /* Initialize individual modules */
19
- init: function () {
20
- InboundAnalytics.Utils.init();
21
- InboundAnalytics.PageTracking.StorePageView();
22
- InboundAnalytics.Events.loadEvents();
23
- InboundAnalytics.Forms.init();
24
- },
25
- /* Debugger Function toggled by var debugMode */
26
- debug: function(msg, callback){
27
- //if app not in debug mode, exit immediately
28
- if(!debugMode || !console){return};
29
- var msg = msg || false;
30
- //console.log the message
31
- if(msg && (typeof msg === 'string')){console.log(msg)};
32
-
33
- //execute the callback if one was passed-in
34
- if(callback && (callback instanceof Function)){
35
- callback();
36
- };
37
- }
38
- };
39
-
40
- return App;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  })(_inboundOptions);
43
  /**
44
- * Utility functions
45
- * @param Object InboundAnalytics - Main JS object
46
- * include util functions
 
 
 
 
 
 
47
  */
48
- var InboundAnalyticsUtils = (function (InboundAnalytics) {
49
-
50
- InboundAnalytics.Utils = {
51
- init: function() {
52
- this.polyFills();
53
- this.setUrlParams();
54
- this.SetUID();
55
- this.getReferer();
56
-
57
- },
58
- /* Polyfills for missing browser functionality */
59
- polyFills: function() {
60
- /* Console.log fix for old browsers */
61
- if (!window.console) { window.console = {}; }
62
- var m = [
63
- "log", "info", "warn", "error", "debug", "trace", "dir", "group",
64
- "groupCollapsed", "groupEnd", "time", "timeEnd", "profile", "profileEnd",
65
- "dirxml", "assert", "count", "markTimeline", "timeStamp", "clear"
66
- ];
67
- // define undefined methods as noops to prevent errors
68
- for (var i = 0; i < m.length; i++) {
69
- if (!window.console[m[i]]) {
70
- window.console[m[i]] = function() {};
71
- }
72
- }
73
- /* Event trigger polyfill for IE9 and 10 */
74
- (function () {
75
- function CustomEvent ( event, params ) {
76
- params = params || { bubbles: false, cancelable: false, detail: undefined };
77
- var evt = document.createEvent( 'CustomEvent' );
78
- evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
79
- return evt;
80
- };
81
 
82
- CustomEvent.prototype = window.Event.prototype;
83
-
84
- window.CustomEvent = CustomEvent;
85
- })();
86
- },
87
- // Create cookie
88
- createCookie: function(name, value, days, custom_time) {
89
- var expires = "";
90
- if (days) {
91
- var date = new Date();
92
- date.setTime(date.getTime()+(days*24*60*60*1000));
93
- expires = "; expires="+date.toGMTString();
94
- }
95
- if(custom_time){
96
- expires = "; expires="+days.toGMTString();
97
- }
98
- document.cookie = name+"="+value+expires+"; path=/";
99
- },
100
- /* Read cookie */
101
- readCookie: function(name) {
102
- var nameEQ = name + "=";
103
- var ca = document.cookie.split(';');
104
- for(var i=0;i < ca.length;i++) {
105
- var c = ca[i];
106
- while (c.charAt(0) === ' ') {
107
- c = c.substring(1,c.length);
108
- }
109
- if (c.indexOf(nameEQ) === 0) {
110
- return c.substring(nameEQ.length,c.length);
111
- }
112
- }
113
- return null;
114
- },
115
- /* Erase cookies */
116
- eraseCookie: function(name) {
117
- createCookie(name,"",-1);
118
- },
119
- /* Get All Cookies */
120
- getAllCookies: function(){
121
- var cookies = {};
122
- if (document.cookie && document.cookie != '') {
123
- var split = document.cookie.split(';');
124
- for (var i = 0; i < split.length; i++) {
125
- var name_value = split[i].split("=");
126
- name_value[0] = name_value[0].replace(/^ /, '');
127
- cookies[decodeURIComponent(name_value[0])] = decodeURIComponent(name_value[1]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  }
129
- }
130
- jQuery.totalStorage('inbound_cookies', cookies); // store cookie data
131
- return cookies;
132
- },
133
- /* Grab URL params and save */
134
- setUrlParams: function() {
135
- var urlParams = {},
136
- local_store = this.checkLocalStorage();
137
-
138
- (function () {
139
- var e,
140
- d = function (s) { return decodeURIComponent(s).replace(/\+/g, " "); },
141
- q = window.location.search.substring(1),
142
- r = /([^&=]+)=?([^&]*)/g;
143
-
144
- while (e = r.exec(q)) {
145
- if (e[1].indexOf("[") == "-1")
146
- urlParams[d(e[1])] = d(e[2]);
147
- else {
148
- var b1 = e[1].indexOf("["),
149
- aN = e[1].slice(b1+1, e[1].indexOf("]", b1)),
150
- pN = d(e[1].slice(0, b1));
151
-
152
- if (typeof urlParams[pN] != "object")
153
- urlParams[d(pN)] = {},
154
- urlParams[d(pN)].length = 0;
155
-
156
- if (aN)
157
- urlParams[d(pN)][d(aN)] = d(e[2]);
158
- else
159
- Array.prototype.push.call(urlParams[d(pN)], d(e[2]));
160
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
- }
163
  })();
164
 
165
- if (JSON) {
166
- for (var k in urlParams) {
167
- if (typeof urlParams[k] == "object") {
168
  for (var k2 in urlParams[k])
169
- this.createCookie(k2, urlParams[k][k2], 30);
170
- } else {
171
  this.createCookie(k, urlParams[k], 30);
172
- }
173
- }
174
  }
 
 
 
 
 
 
 
 
 
 
175
 
176
- if(local_store){
177
- var pastParams = jQuery.totalStorage('inbound_url_params');
178
- var params = this.mergeObjs(pastParams, urlParams);
179
- jQuery.totalStorage('inbound_url_params', params); // store cookie data
 
180
  }
181
- },
182
- getUrlParams: function(){
183
- var local_store = this.checkLocalStorage(),
184
- get_params = {};
185
- if(local_store){
186
- var get_params = jQuery.totalStorage('inbound_url_params');
187
- }
188
- return get_params;
189
- },
190
- // Check local storage
191
- // provate browsing safari fix https://github.com/marcuswestin/store.js/issues/42#issuecomment-25274685
192
- checkLocalStorage: function() {
193
- if ('localStorage' in window) {
194
- try {
195
- ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
196
- if (typeof ls == 'undefined' || typeof window.JSON == 'undefined'){
197
- supported = false;
198
- } else {
199
- supported = true;
200
- }
201
-
202
- }
203
- catch (err){
204
- supported = false;
205
  }
206
- }
207
- return supported;
208
- /* http://spin.atomicobject.com/2013/01/23/ios-private-browsing-localstorage/
209
- var hasStorage;
210
- hasStorage = function() {
211
- var mod, result;
212
- try {
213
- mod = new Date;
214
- localStorage.setItem(mod, mod.toString());
215
- result = localStorage.getItem(mod) === mod.toString();
216
- localStorage.removeItem(mod);
217
- return result;
218
- } catch (_error) {}
219
- };
220
- */
221
- },
222
- /* Add days to datetime */
223
- addDays: function(myDate,days) {
224
- return new Date(myDate.getTime() + days*24*60*60*1000);
225
- },
226
- GetDate: function(){
227
- var time_now = new Date(),
228
- day = time_now.getDate() + 1;
229
- year = time_now.getFullYear(),
230
- hour = time_now.getHours(),
231
- minutes = time_now.getMinutes(),
232
- seconds = time_now.getSeconds(),
233
- month = time_now.getMonth() + 1;
234
- if (month < 10) { month = '0' + month; }
235
- InboundAnalytics.debug('Current Date:',function(){
236
- console.log(year + '/' + month + "/" + day + " " + hour + ":" + minutes + ":" + seconds);
237
- });
238
- var datetime = year + '/' + month + "/" + day + " " + hour + ":" + minutes + ":" + seconds;
239
- return datetime;
240
- },
241
- /* Set Expiration Date of Session Logging */
242
- SetSessionTimeout: function(){
243
- var session_check = this.readCookie("lead_session_expire");
244
- //console.log(session_check);
245
- if(session_check === null){
246
- InboundAnalytics.Events.sessionStart(); // trigger 'inbound_analytics_session_start'
247
- } else {
248
- InboundAnalytics.Events.sessionActive(); // trigger 'inbound_analytics_session_active'
249
- }
250
- var d = new Date();
251
- d.setTime(d.getTime() + 30*60*1000);
252
-
253
- this.createCookie("lead_session_expire", true, d, true); // Set cookie on page loads
254
- var lead_data_expiration = this.readCookie("lead_data_expiration");
255
- if (lead_data_expiration === null){
256
- /* Set 3 day timeout for checking DB for new lead data for Lead_Global var */
257
- var ex = this.addDays(d, 3);
258
- this.createCookie("lead_data_expiration", ex, ex, true);
259
- }
260
 
261
- },
262
- getReferer: function(){
263
- //console.log(expire_time);
264
- var d = new Date();
265
- d.setTime(d.getTime() + 30*60*1000);
266
- var referrer_cookie = InboundAnalytics.Utils.readCookie("wp_lead_referral_site");
267
- if (typeof (referrer_cookie) === "undefined" || referrer_cookie === null || referrer_cookie === "") {
268
- var referrer = document.referrer || "NA";
269
- this.createCookie("wp_lead_referral_site", referrer, d, true); // Set cookie on page loads
270
- }
271
- },
272
- CreateUID: function(length) {
273
- var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(''),
274
- str = '';
275
- if (! length) {
276
- length = Math.floor(Math.random() * chars.length);
277
- }
278
- for (var i = 0; i < length; i++) {
279
- str += chars[Math.floor(Math.random() * chars.length)];
280
- }
281
- return str;
282
- },
283
- SetUID: function () {
284
- /* Set Lead UID */
285
-
286
- if(this.readCookie("wp_lead_uid") === null) {
287
- var wp_lead_uid = this.CreateUID(35);
288
- this.createCookie("wp_lead_uid", wp_lead_uid );
289
- InboundAnalytics.debug('Set UID');
290
- }
291
- },
292
- /* Count number of session visits */
293
- countProperties: function (obj) {
294
- var count = 0;
295
- for(var prop in obj) {
296
- if(obj.hasOwnProperty(prop))
297
- ++count;
298
- }
299
- return count;
300
- },
301
- mergeObjs: function(obj1,obj2){
 
 
 
 
 
 
302
  var obj3 = {};
303
- for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
304
- for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
 
 
 
 
305
  return obj3;
306
- },
307
- hasClass: function(className, el) {
308
- var hasClass = false;
309
- if ('classList' in document.documentElement) {
310
- var hasClass = el.classList.contains(className);
311
- } else {
312
- var hasClass = new RegExp('(^|\\s)' + className + '(\\s|$)').test(el.className); /* IE Polyfill */
313
- }
314
- return hasClass;
315
- },
316
- trim: function(s) {
317
- s = s.replace(/(^\s*)|(\s*$)/gi,"");
318
- s = s.replace(/[ ]{2,}/gi," ");
319
- s = s.replace(/\n /,"\n"); return s;
320
- },
321
- doAjax: function(data, responseHandler, method, async){
322
- // Set the variables
323
- var url = wplft.admin_url || "",
324
- method = method || "POST",
325
- async = async || true,
326
- data = data || null,
327
- action = data.action;
328
-
329
- InboundAnalytics.debug('Ajax Processed:',function(){
330
- console.log('ran ajax action: ' + action);
331
- });
332
-
333
- jQuery.ajax({
334
- type: method,
335
- url: wplft.admin_url,
336
- data: data,
337
- success: responseHandler,
338
- error: function(MLHttpRequest, textStatus, errorThrown){
339
- console.log(MLHttpRequest+' '+errorThrown+' '+textStatus);
340
- InboundAnalytics.Events.analyticsError(MLHttpRequest, textStatus, errorThrown);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  }
342
 
343
- });
344
- },
345
- makeRequest: function(url) {
346
- if (window.XMLHttpRequest) { // Mozilla, Safari, ...
347
- httpRequest = new XMLHttpRequest();
348
- } else if (window.ActiveXObject) { // IE
349
- try {
350
- httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
351
  }
352
- catch (e) {
353
- try {
354
- httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
355
- }
356
- catch (e) {}
357
  }
358
- }
359
 
360
- if (!httpRequest) {
361
- alert('Giving up :( Cannot create an XMLHTTP instance');
362
- return false;
363
- }
364
- httpRequest.onreadystatechange = InboundAnalytics.LeadsAPI.alertContents;
365
- httpRequest.open('GET', url);
366
- httpRequest.send();
367
- },
368
- contentLoaded: function(win, fn) {
369
-
370
- var done = false, top = true,
371
-
372
- doc = win.document, root = doc.documentElement,
373
-
374
- add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
375
- rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
376
- pre = doc.addEventListener ? '' : 'on',
377
-
378
- init = function(e) {
379
- if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
380
- (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
381
- if (!done && (done = true)) fn.call(win, e.type || e);
382
- },
383
-
384
- poll = function() {
385
- try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
386
- init('poll');
387
- };
388
-
389
- if (doc.readyState == 'complete') fn.call(win, 'lazy');
390
- else {
391
- if (doc.createEventObject && root.doScroll) {
392
- try { top = !win.frameElement; } catch(e) { }
393
- if (top) poll();
394
  }
395
- doc[add](pre + 'DOMContentLoaded', init, false);
396
- doc[add](pre + 'readystatechange', init, false);
397
- win[add](pre + 'load', init, false);
398
- }
399
 
400
- },
401
- /* Cross-browser event listening */
402
- addListener: function(obj, eventName, listener) {
403
- if(obj.addEventListener) {
404
- obj.addEventListener(eventName, listener, false);
405
- } else if (obj.attachEvent) {
406
- obj.attachEvent("on" + eventName, listener);
407
- } else {
408
- obj['on' + eventName] = listener;
409
- }
410
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
411
 
412
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413
 
414
- return InboundAnalytics;
415
 
416
- })(InboundAnalytics || {});
417
- /**
418
- * Form functions
419
- * @param Object InboundAnalytics - Form tracking functionality
420
- * @return Object - form functions
421
- */
422
- var InboundForms = (function (InboundAnalytics) {
423
 
424
- InboundAnalytics.Forms = {
425
- // Init Form functions
426
- init: function() {
427
- this.attachFormSubmitEvent();
428
- },
429
- formLoop: function(){
430
- for(var i=0; i<window.document.forms.length; i++){
431
- var form = window.document.forms[i];
432
- var trackForm = InboundAnalytics.Utils.hasClass("wpl-track-me", form);
433
- if (trackForm) {
434
- this.attachFormSubmitEvent(form); /* attach form listener */
435
 
436
- }
437
- }
438
- },
439
- formSubmit: function(form) {
440
-
441
- },
442
- mapFormValues: function(form) {
443
- var inputByName = {};
444
- var params = [];
445
- /* test for [] array syntax */
446
- var fieldNameExp = /\[([^\[]*)\]/g;
447
- for (var i=0; i < form.elements.length; i++) {
448
-
449
- formField = form.elements[i];
450
- multiple = false;
451
 
452
- if (formField.name) {
453
- /* test for [] array syntax */
454
- cleanName = formField.name.replace(fieldNameExp, "_$1");
455
- if (!inputByName[cleanName]) { inputByName[cleanName] = []; }
456
 
457
- switch (formField.nodeName) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
458
 
459
- case 'INPUT':
460
- value = this.getInputValue(formField);
461
- console.log(value);
462
- if (value === false) { continue; }
463
- break;
 
 
 
 
 
464
 
465
- case 'SELECT':
466
- if (formField.multiple) {
467
- values = [];
468
- multiple = true;
 
 
 
 
 
 
 
 
 
 
 
 
469
 
470
- for (var j = 0; j < formField.length; j++) {
471
- if (formField[j].selected) {
472
- values.push(encodeURIComponent(formField[j].value));
473
- }
474
- }
475
 
476
- } else {
477
- value = (formField.value);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  }
479
- break;
 
 
 
 
 
 
 
 
 
480
 
481
- case 'TEXTAREA':
482
- value = formField.value;
483
- break;
484
 
485
- }
 
 
486
 
487
- if (value) {
488
- inputByName[cleanName].push(multiple ? values.join(',') : encodeURIComponent(value));
 
489
  }
 
490
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
491
  }
492
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
  }
494
- var matchCommon = /name|first name|last name|email|e-mail|phone|website|job title|company|tele|address|comment/;
495
- for (var inputName in inputByName) {
496
- if (matchCommon.test(inputName) !== false) {
497
- console.log(inputName + " Matches Regex");
498
- /* run mapping loop only for the matches here */
499
- }
500
- params.push( inputName + '=' + inputByName[inputName].join(',') );
501
- }
502
- var final_params = params.join('&');
503
- console.log(final_params);
504
- },
505
- getInputValue = function(input) {
506
- var value = false;
507
-
508
- switch (input.type) {
509
- case 'radio':
510
- case 'checkbox':
511
- if (input.checked) {
512
- value = input.value;
513
- }
514
- break;
515
-
516
- case 'text':
517
- case 'hidden':
518
- default:
519
- value = input.value;
520
- break;
521
-
522
- }
523
-
524
- return value;
525
-
526
- },
527
- /*
528
- inbound_form_classes: function(forms, functionName, classes) {
529
- jQuery.each(forms, function(index, id) {
530
- var selector = jQuery.trim(id);
531
- for (var this_class in classes) {
532
- if (selector.indexOf('#')>-1) {
533
- jQuery(selector)[functionName](classes[this_class]);
534
- //console.log(selector);
535
- } else if (selector.indexOf('.')>-1) {
536
- jQuery(selector)[functionName](classes[this_class]);
537
- } else {
538
- jQuery("#" + selector)[functionName](classes[this_class]);
539
- }
540
- }
541
 
542
- });
543
- }*/
544
- /* Add tracking class to forms */
545
- attachFormSubmitEvent: function (form) {
546
 
547
- console.log("The Form has the class wpl-track-me", hasClass);
548
- InboundAnalytics.Utils.addListener(form, 'submit', InboundAnalytics.LeadsAPI.formSubmit );
549
 
550
- },
 
 
 
 
 
 
 
 
 
 
551
 
 
 
552
 
553
- };
554
 
555
- return InboundAnalytics;
 
556
 
557
- })(InboundAnalytics || {});
558
- /**
559
- * Event functions
560
- * @param Object InboundAnalytics - Main JS object
561
- * @return Object - include event triggers
562
- */
563
- // https://github.com/carldanley/WP-JS-Hooks/blob/master/src/event-manager.js
564
- var InboundAnalyticsEvents = (function (InboundAnalytics) {
565
-
566
- InboundAnalytics.Events = {
567
- // Create cookie
568
- loadEvents: function() {
569
- this.analyticsLoaded();
570
- },
571
- triggerJQueryEvent: function(eventName, data){
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572
  if (window.jQuery) {
573
  var data = data || {};
574
  jQuery(document).trigger(eventName, data);
575
- /* var something = (function() {
576
- var executed = false;
577
- return function () {
578
- if (!executed) {
579
- executed = true;
580
- console.log(eventName + " RAN");
581
-
582
- }
583
- };
584
- })();*/
585
  }
586
- },
587
- analyticsLoaded: function() {
588
- var eventName = "inbound_analytics_loaded";
589
- var loaded = new CustomEvent(eventName);
590
- window.dispatchEvent(loaded);
591
- this.triggerJQueryEvent(eventName);
592
- },
593
- analyticsTriggered: function() {
594
- var triggered = new CustomEvent("inbound_analytics_triggered");
595
- window.dispatchEvent(triggered);
596
- },
597
- analyticsSaved: function() {
598
- var page_view_saved = new CustomEvent("inbound_analytics_saved");
599
- window.dispatchEvent(page_view_saved);
600
- console.log('Page View Saved');
601
- },
602
- analyticsError: function(MLHttpRequest, textStatus, errorThrown) {
603
- var error = new CustomEvent("inbound_analytics_error", {
604
- detail: {
605
- MLHttpRequest: MLHttpRequest,
606
- textStatus: textStatus,
607
- errorThrown: errorThrown
608
- }
609
- });
610
- window.dispatchEvent(error);
611
- console.log('Page Save Error');
612
- },
613
- pageFirstView: function(page_seen_count) {
614
- var page_first_view = new CustomEvent("inbound_analytics_page_first_view", {
615
- detail: {
616
- count: 1,
617
- time: new Date(),
618
- },
619
- bubbles: true,
620
- cancelable: true
621
- }
622
- );
623
- window.dispatchEvent(page_first_view);
624
-
625
- console.log('First Ever Page View of this Page');
626
- },
627
- pageRevisit: function(page_seen_count) {
628
- var eventName = "inbound_analytics_page_revisit";
629
- var data = { count: page_seen_count,
630
- time: new Date()
631
- };
632
- var page_revisit = new CustomEvent(eventName, {
633
- detail: data,
634
- bubbles: true,
635
- cancelable: true
636
- }
637
- );
638
- window.dispatchEvent(page_revisit);
639
- this.triggerJQueryEvent(eventName, data);
640
- console.log('Page Revisit');
641
- },
642
- /* get idle times https://github.com/robflaherty/riveted/blob/master/riveted.js */
643
- browserTabHidden: function() {
644
- /* http://www.thefutureoftheweb.com/demo/2007-05-16-detect-browser-window-focus/ */
645
- var eventName = "inbound_analytics_tab_hidden";
646
- var tab_hidden = new CustomEvent(eventName);
647
- window.dispatchEvent(tab_hidden);
648
- console.log('Tab Hidden');
649
- this.triggerJQueryEvent(eventName);
650
- },
651
- browserTabVisible: function() {
652
- var eventName = "inbound_analytics_tab_visible";
653
- var tab_visible = new CustomEvent(eventName);
654
- window.dispatchEvent(tab_visible);
655
- console.log('Tab Visible');
656
- this.triggerJQueryEvent(eventName);
657
- },
658
- /* Scrol depth https://github.com/robflaherty/jquery-scrolldepth/blob/master/jquery.scrolldepth.js */
659
- sessionStart: function() {
660
- var session_start = new CustomEvent("inbound_analytics_session_start");
661
- window.dispatchEvent(session_start);
662
- console.log('Session Start');
663
- },
664
- sessionActive: function() {
665
- var session_active = new CustomEvent("inbound_analytics_session_active");
666
- window.dispatchEvent(session_active);
667
- console.log('Session Active');
668
- },
669
 
670
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
671
 
672
- return InboundAnalytics;
673
 
674
- })(InboundAnalytics || {});
675
- /* Fork of jquery.total-storage.js */
676
- var InboundTotalStorage = (function (InboundAnalytics){
677
 
678
- /* Variables I'll need throghout */
 
 
679
 
680
- var supported, ls, mod = 'inboundAnalytics';
681
  if ('localStorage' in window){
682
  try {
683
  ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
@@ -695,29 +2708,28 @@ var InboundTotalStorage = (function (InboundAnalytics){
695
  }
696
 
697
  /* Make the methods public */
698
- InboundAnalytics.totalStorage = function(key, value, options){
699
- return InboundAnalytics.totalStorage.impl.init(key, value);
700
  };
701
 
702
- InboundAnalytics.totalStorage.setItem = function(key, value){
703
- return InboundAnalytics.totalStorage.impl.setItem(key, value);
704
  };
705
 
706
- InboundAnalytics.totalStorage.getItem = function(key){
707
- return InboundAnalytics.totalStorage.impl.getItem(key);
708
  };
709
 
710
- InboundAnalytics.totalStorage.getAll = function(){
711
- return InboundAnalytics.totalStorage.impl.getAll();
712
  };
713
 
714
- InboundAnalytics.totalStorage.deleteItem = function(key){
715
- return InboundAnalytics.totalStorage.impl.deleteItem(key);
716
  };
717
 
718
- /* Object to hold all methods: public and private */
719
 
720
- InboundAnalytics.totalStorage.impl = {
721
 
722
  init: function(key, value){
723
  if (typeof value != 'undefined') {
@@ -730,7 +2742,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
730
  setItem: function(key, value){
731
  if (!supported){
732
  try {
733
- InboundAnalytics.Utils.createCookie(key, value);
734
  return value;
735
  } catch(e){
736
  console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie');
@@ -743,7 +2755,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
743
  getItem: function(key){
744
  if (!supported){
745
  try {
746
- return this.parseResult(InboundAnalytics.Utils.readCookie(key));
747
  } catch(e){
748
  return null;
749
  }
@@ -754,7 +2766,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
754
  deleteItem: function(key){
755
  if (!supported){
756
  try {
757
- InboundAnalytics.Utils.eraseCookie(key, null);
758
  return true;
759
  } catch(e){
760
  return false;
@@ -771,7 +2783,7 @@ var InboundTotalStorage = (function (InboundAnalytics){
771
  for (var i = 0; i<pairs.length; i++){
772
  var pair = pairs[i].split('=');
773
  var key = pair[0];
774
- items.push({key:key, value:this.parseResult(InboundAnalytics.Utils.readCookie(key))});
775
  }
776
  } catch(e){
777
  return null;
@@ -807,602 +2819,471 @@ var InboundTotalStorage = (function (InboundAnalytics){
807
  return ret;
808
  }
809
  };
810
- })(InboundAnalytics || {});
811
  /**
812
  * Leads API functions
813
- * @param Object InboundAnalytics - Main JS object
814
  * @return Object - include event triggers
815
  */
816
- var InboundAnalyticsLeadsAPI = (function (InboundAnalytics) {
817
  var httpRequest;
818
- InboundAnalytics.LeadsAPI = {
819
- init: function() {
820
-
821
- },
822
- storeLeadData: function(){
823
- if(element.addEventListener) {
824
- element.addEventListener("submit", function(evt){
825
- evt.preventDefault();
826
- window.history.back();
827
- }, true);
828
- } else {
829
- element.attachEvent('onsubmit', function(evt){
830
- evt.preventDefault();
831
- window.history.back();
832
- });
833
- }
834
- },
835
- inbound_map_fields: function (el, value, Obj) {
836
- var formObj = [];
837
- var $this = el;
838
- var clean_output = value;
839
- var label = $this.closest('label').text();
840
- var exclude = ['credit-card']; // exlcude values from formObj
841
- var inarray = jQuery.inArray(clean_output, exclude);
842
- if(inarray == 0){
843
- return null;
844
- }
845
- // Add items to formObj
846
- formObj.push({
847
- field_label: label,
848
- field_name: $this.attr("name"),
849
- field_value: $this.attr("value"),
850
- field_id: $this.attr("id"),
851
- field_class: $this.attr("class"),
852
- field_type: $this.attr("type"),
853
- match: clean_output,
854
- js_selector: $this.attr("data-js-selector")
855
- });
856
- return formObj;
857
- },
858
- run_field_map_function: function (el, lookingfor) {
859
- var return_form;
860
- var formObj = new Array();
861
- var $this = el;
862
- var body = jQuery("body");
863
- var input_id = $this.attr("id") || "NULL";
864
- var input_name = $this.attr("name") || "NULL";
865
- var this_val = $this.attr("value");
866
- var array = lookingfor.split(",");
867
- var array_length = array.length - 1;
868
-
869
- // Main Loop
870
- for (var i = 0; i < array.length; i++) {
871
- var clean_output = InboundAnalytics.Utils.trim(array[i]);
872
- var nice_name = clean_output.replace(/^\s+|\s+$/g,'');
873
- var nice_name = nice_name.replace(" ",'_');
874
- var in_object_already = nice_name in inbound_data;
875
- //console.log(clean_output);
876
-
877
- if (input_name.toLowerCase().indexOf(clean_output)>-1) {
878
- /* Look for attr name match */
879
- var the_map = InboundAnalytics.LeadsAPI.inbound_map_fields($this, clean_output, formObj);
880
- InboundAnalytics.LeadsAPI.add_inbound_form_class($this, clean_output);
881
- console.log('match name: ' + clean_output);
882
- console.log(nice_name in inbound_data);
883
- if (!in_object_already) {
884
- inbound_data[nice_name] = this_val;
885
- }
886
- } else if (input_id.toLowerCase().indexOf(clean_output)>-1) {
887
- /* look for id match */
888
- var the_map = InboundAnalytics.LeadsAPI.inbound_map_fields($this, clean_output, formObj);
889
- InboundAnalytics.LeadsAPI.add_inbound_form_class($this, clean_output);
890
- console.log('match id: ' + clean_output);
891
-
892
- if (!in_object_already) {
893
- inbound_data[nice_name] = this_val;
894
- }
895
 
896
- } else if ($this.closest('li').children('label').length>0) {
897
- /* Look for label name match */
898
- var closest_label = $this.closest('li').children('label').html() || "NULL";
899
- if (closest_label.toLowerCase().indexOf(clean_output)>-1) {
900
-
901
- var the_map = InboundAnalytics.LeadsAPI.inbound_map_fields($this, clean_output, formObj);
902
- InboundAnalytics.LeadsAPI.add_inbound_form_class($this, clean_output);
903
- console.log($this.context);
904
-
905
- var exists_in_dom = body.find("[data-inbound-form-map='inbound_map_" + nice_name + "']").length;
906
- console.log(exists_in_dom);
907
- console.log('match li: ' + clean_output);
908
-
909
- if (!in_object_already) {
910
- inbound_data[nice_name] = this_val;
911
- }
912
-
913
- }
914
- } else if ($this.closest('div').children('label').length>0) {
915
- /* Look for closest div label name match */
916
- var closest_div = $this.closest('div').children('label').html() || "NULL";
917
- if (closest_div.toLowerCase().indexOf(clean_output)>-1)
918
- {
919
- var the_map = InboundAnalytics.LeadsAPI.inbound_map_fields($this, clean_output, formObj);
920
- InboundAnalytics.LeadsAPI.add_inbound_form_class($this, clean_output);
921
- console.log('match div: ' + clean_output);
922
- if (!in_object_already) {
923
- inbound_data[nice_name] = this_val;
924
- }
925
- }
926
- } else if ($this.closest('p').children('label').length>0) {
927
- /* Look for closest p label name match */
928
- var closest_p = $this.closest('p').children('label').html() || "NULL";
929
- if (closest_p.toLowerCase().indexOf(clean_output)>-1)
930
- {
931
- var the_map = InboundAnalytics.LeadsAPI.inbound_map_fields($this, clean_output, formObj);
932
- InboundAnalytics.LeadsAPI.add_inbound_form_class($this, clean_output);
933
- console.log('match p: ' + clean_output);
934
- if (!in_object_already) {
935
- inbound_data[nice_name] = this_val;
936
- }
937
- }
938
- } else {
939
- console.log('Need additional mapping data');
940
- }
941
- }
942
- return_form = the_map;
943
-
944
- return inbound_data;
945
- },
946
- add_inbound_form_class: function(el, value) {
947
- var value = value.replace(" ", "_");
948
- var value = value.replace("-", "_");
949
- el.addClass('inbound_map_value');
950
- el.attr('data-inbound-form-map', 'inbound_map_' + value);
951
- },
952
- inbound_form_type: function(this_form) {
953
- var inbound_data = inbound_data || {},
954
- form_type = 'normal';
955
- if ( this_form.is( ".wpl-comment-form" ) ) {
956
- inbound_data['form_type'] = 'comment';
957
- form_type = 'comment';
958
- } else if ( this_form.is( ".wpl-search-box" ) ) {
959
- var is_search = true;
960
- form_type = 'search';
961
- inbound_data['form_type'] = 'search';
962
- } else if ( this_form.is( '.wpl-track-me-link' ) ){
963
- var have_email = readCookie('wp_lead_email');
964
- console.log(have_email);
965
- inbound_data['form_type'] = 'link';
966
- form_type = 'search';
967
- }
968
- return form_type;
969
- },
970
- grab_all_form_input_vals: function(this_form){
971
- var post_values = post_values || {},
972
- inbound_exclude = inbound_exclude || [],
973
- form_inputs = this_form.find('input,textarea,select');
974
- inbound_exclude.push('inbound_furl', 'inbound_current_page_url', 'inbound_notify', 'inbound_submitted', 'post_type', 'post_status', 's', 'inbound_form_name', 'inbound_form_id', 'inbound_form_lists');
975
- var form_type = InboundAnalytics.LeadsAPI.inbound_form_type(this_form),
976
- inbound_data = inbound_data || {},
977
- email = inbound_data['email'] || false;
978
-
979
- form_inputs.each(function() {
980
- var $input = jQuery(this),
981
- input_type = $input.attr('type'),
982
- input_val = $input.val();
983
- if (input_type === 'checkbox') {
984
- input_checked = $input.attr("checked");
985
- console.log(input_val);
986
- console.log(input_checked);
987
- console.log(post_values[this.name]);
988
- if (input_checked === "checked"){
989
- if (typeof (post_values[this.name]) != "undefined") {
990
- post_values[this.name] = post_values[this.name] + "," + input_val;
991
- console.log(post_values[this.name]);
992
  } else {
993
- post_values[this.name] = input_val;
 
 
 
 
 
 
 
 
 
994
  }
995
 
996
- }
997
- }
998
- if (jQuery.inArray(this.name, inbound_exclude) === -1 && input_type != 'checkbox'){
999
- post_values[this.name] = input_val;
1000
- }
1001
- if (this.value.indexOf('@')>-1&&!email){
1002
- email = input_val;
1003
- inbound_data['email'] = email;
1004
- }
1005
- if (form_type === 'search') {
1006
- inbound_data['search_keyword'] = input_val.replace('"', "'");
1007
- }
1008
- });
1009
- var all_form_fields = JSON.stringify(post_values);
1010
- return all_form_fields;
1011
- },
1012
- return_mapped_values: function (this_form) {
1013
- // Map form fields
1014
- jQuery(this_form).find('input[type!="hidden"],textarea,select').each(function() {
1015
- console.log('run');
1016
- var this_input = jQuery(this);
1017
- var this_input_val = this_input.val();
1018
- if (typeof (this_input_val) != "undefined" && this_input_val != null && this_input_val != "") {
1019
- var inbound_data = InboundAnalytics.LeadsAPI.run_field_map_function( this_input, "name, first name, last name, email, e-mail, phone, website, job title, company, tele, address, comment");
1020
- }
1021
- return inbound_data;
1022
- });
1023
- return inbound_data;
1024
- },
1025
- inbound_form_submit: function(this_form, e) {
1026
- /* Define Variables */
1027
- var data = inbound_data || {};
1028
- // Dynamic JS object for passing custom values. This can be hooked into by third parties by using the below syntax.
1029
- var pageviewObj = jQuery.totalStorage('page_views');
1030
- data['page_view_count'] = InboundAnalytics.Utils.countProperties(pageviewObj);
1031
- data['leads_list'] = jQuery(this_form).find('#inbound_form_lists').val();
1032
- data['source'] = jQuery.cookie("wp_lead_referral_site") || "NA";
1033
- data['page_id'] = inbound_ajax.post_id;
1034
- data['page_views'] = JSON.stringify(pageviewObj);
1035
-
1036
- // Map form fields
1037
- var returned_form_data = InboundAnalytics.LeadsAPI.return_mapped_values(this_form); //console.log(returned_form_data);
1038
- var data = InboundAnalytics.Utils.mergeObjs(data,returned_form_data); //console.log(data);
1039
- var this_form = jQuery(this_form);
1040
- // Set variables after mapping
1041
- data['email'] = (!data['email']) ? this_form.find('.inbound-email').val() : data['email'];
1042
- data['form_name'] = this_form.find('.inbound_form_name').val() || "Not Found";
1043
- data['form_id'] = this_form.find('.inbound_form_id').val() || "Not Found";
1044
- data['first_name'] = (!data['first_name']) ? data['name'] : data['first_name'];
1045
- data['last_name'] = data['last_name'] || '';
1046
- data['phone'] = data['phone'] || '';
1047
- data['company'] = data['company'] || '';
1048
- data['address'] = data['address'] || '';
1049
-
1050
- // Fallbacks for values
1051
- data['name'] = (data['first_name'] && data['last_name']) ? data['first_name'] + " " + data['last_name'] : data['name'];
1052
-
1053
- if (!data['last_name'] && data['first_name']) {
1054
- var parts = data['first_name'].split(" ");
1055
- data['first_name'] = parts[0];
1056
- data['last_name'] = parts[1];
1057
  }
 
1058
 
1059
- /* Store form fields & exclude field values */
1060
- var all_form_fields = InboundAnalytics.LeadsAPI.grab_all_form_input_vals(this_form);
1061
- /* end Store form fields & exclude field values */
1062
 
1063
- if(data['email']){
1064
- InboundAnalytics.Utils.createCookie("wp_lead_email", data['email'], 365); /* set email cookie */
1065
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1066
 
1067
- //var variation = (typeof (landing_path_info) != "undefined") ? landing_path_info.variation : false;
1068
 
1069
- if (typeof (landing_path_info) != "undefined") {
1070
- var variation = landing_path_info.variation;
1071
- } else if (typeof (cta_path_info) != "undefined") {
1072
- var variation = cta_path_info.variation;
1073
- } else {
1074
- var variation = 0;
1075
- }
1076
 
1077
- data['variation'] = variation;
1078
- data['post_type'] = inbound_ajax.post_type;
1079
- data['wp_lead_uid'] = jQuery.cookie("wp_lead_uid") || null;
1080
- data['ip_address'] = inbound_ajax.ip_address;
1081
- data['search_data'] = JSON.stringify(jQuery.totalStorage('inbound_search')) || {};
1082
-
1083
- var lp_check = (inbound_ajax.post_type === 'landing-page') ? 'Landing Page' : "";
1084
- var cta_check = (inbound_ajax.post_type === 'wp-call-to-action') ? 'Call to Action' : "";
1085
- var page_type = (!cta_check && !lp_check) ? inbound_ajax.post_type : lp_check + cta_check;
1086
-
1087
- // jsonify data
1088
- var mapped_form_data = JSON.stringify(data);
1089
-
1090
- var return_data = {};
1091
- var return_data = {
1092
- "action": 'inbound_store_lead',
1093
- "emailTo": data['email'],
1094
- "first_name": data['first_name'],
1095
- "last_name": data['last_name'],
1096
- "phone": data['phone'],
1097
- "address": data['address'],
1098
- "company_name": data['company'],
1099
- "page_views": data['page_views'],
1100
- "form_input_values": all_form_fields,
1101
- "Mapped_Data": mapped_form_data,
1102
- "Search_Data": data['search_data']
1103
- }
1104
- return return_data;
1105
- },
1106
- formSubmit: function (e){
1107
- /*if(!confirm('Are you sure?')) {
1108
- e.returnValue = false;
1109
- if(e.preventDefault) e.preventDefault();
1110
- return false;
1111
- }
1112
- return true;*/
1113
- /*var inbound_data = inbound_data || {},
1114
- this_form = e.target,
1115
- event_type = e.type,
1116
- is_search = false,
1117
- form_type = 'normal';*/
1118
-
1119
- e.preventDefault(); /* Halt form processing */
1120
- console.log("This works");
1121
- var data = InboundAnalytics.LeadsAPI.inbound_form_submit(e.target, e); // big function for processing
1122
- console.log(data);
1123
- alert('Working');
1124
- //document.getElementById("ajaxButton").onclick = function() { makeRequest('test.html'); };
1125
-
1126
- /* Final Ajax Call on Submit */
1127
- InboundAnalytics.LeadsAPI.makeRequest('test.html');
1128
- },
1129
- alertContents: function() {
1130
- if (httpRequest.readyState === 4) {
1131
- if (httpRequest.status === 200) {
1132
- alert(httpRequest.responseText);
1133
- } else if(xmlhttp.status == 400) {
1134
- alert('There was an error 400');
1135
- } else {
1136
- alert('There was a problem with the request.');
1137
- }
1138
- }
1139
- },
1140
- getAllLeadData: function(expire_check) {
1141
- var wp_lead_id = InboundAnalytics.Utils.readCookie("wp_lead_id"),
1142
- old_data = jQuery.totalStorage('inbound_lead_data'),
1143
- data = {
1144
- action: 'inbound_get_all_lead_data',
1145
- wp_lead_id: wp_lead_id,
1146
- },
1147
- success = function(returnData){
1148
- var obj = JSON.parse(returnData);
1149
- console.log('Got all the lead data check ');
1150
- setGlobalLeadVar(obj);
1151
- jQuery.totalStorage('inbound_lead_data', obj); // store lead data
1152
- };
1153
 
1154
- if(!old_data) {
1155
- console.log("No old data");
1156
- }
 
 
1157
 
1158
- if (expire_check === 'true'){
1159
- console.log("Session has not expired");
1160
- }
1161
 
1162
- if(!old_data && expire_check === null) {
1163
- InboundAnalytics.debug('Go to Database',function(){
1164
- console.log(expire_check);
1165
- console.log(old_data);
1166
- });
1167
- InboundAnalytics.Utils.doAjax(data, success);
1168
- } else {
1169
- setGlobalLeadVar(old_data); // set global lead var with localstorage data
1170
- var lead_data_expiration = InboundAnalytics.Utils.readCookie("lead_data_expiration");
1171
- if (lead_data_expiration === null) {
1172
- InboundAnalytics.Utils.doAjax(data, success);
1173
- console.log('localized data old. Pull new from DB');
1174
- }
1175
- }
1176
 
1177
- },
1178
- getLeadLists: function() {
1179
- var wp_lead_id = InboundAnalytics.Utils.readCookie("wp_lead_id");
1180
- var data = {
1181
- action: 'wpl_check_lists',
1182
- wp_lead_id: wp_lead_id,
1183
- };
1184
- var success = function(user_id){
1185
- jQuery.cookie("lead_session_list_check", true, { path: '/', expires: 1 });
1186
- console.log("Lists checked");
1187
- };
1188
- InboundAnalytics.Utils.doAjax(data, success);
1189
- }
1190
- };
1191
 
1192
- return InboundAnalytics;
 
 
1193
 
1194
- })(InboundAnalytics || {});
1195
- var InboundAnalyticsPageTracking = (function (InboundAnalytics) {
1196
 
1197
- InboundAnalytics.PageTracking = {
 
 
1198
 
1199
- getPageViews: function () {
1200
- var local_store = InboundAnalytics.Utils.checkLocalStorage();
1201
- if(local_store){
1202
- var page_views = localStorage.getItem("page_views"),
1203
- local_object = JSON.parse(page_views);
1204
- if (typeof local_object =='object' && local_object) {
1205
- this.StorePageView();
1206
- }
1207
- return local_object;
1208
- }
1209
- },
1210
- StorePageView: function() {
1211
- var timeout = this.CheckTimeOut();
1212
- var pageviewObj = jQuery.totalStorage('page_views');
1213
- if(pageviewObj === null) {
1214
- pageviewObj = {};
1215
- }
1216
- var current_page_id = wplft.post_id;
1217
- var datetime = InboundAnalytics.Utils.GetDate();
1218
 
1219
- if (timeout) {
1220
- // If pageviewObj exists, do this
1221
- var page_seen = pageviewObj[current_page_id];
 
 
 
 
 
 
 
 
 
1222
 
1223
- if(typeof(page_seen) != "undefined" && page_seen !== null) {
1224
- pageviewObj[current_page_id].push(datetime);
1225
- /* Page Revisit Trigger */
1226
- var page_seen_count = pageviewObj[current_page_id].length;
1227
- InboundAnalytics.Events.pageRevisit(page_seen_count);
 
 
 
 
 
 
 
 
 
1228
 
1229
- } else {
1230
- pageviewObj[current_page_id] = [];
1231
- pageviewObj[current_page_id].push(datetime);
1232
- /* Page First Seen Trigger */
1233
- var page_seen_count = 1;
1234
- InboundAnalytics.Events.pageFirstView(page_seen_count);
1235
- }
 
 
 
1236
 
1237
- jQuery.totalStorage('page_views', pageviewObj);
 
 
1238
 
1239
- }
1240
- },
1241
- CheckTimeOut: function() {
1242
- var PageViews = jQuery.totalStorage('page_views');
1243
- if(PageViews === null) {
1244
- var PageViews = {};
1245
- }
1246
- var page_id = wplft.post_id,
1247
- pageviewTimeout = true, /* Default */
1248
- page_seen = PageViews[page_id];
1249
- if(typeof(page_seen) != "undefined" && page_seen !== null) {
1250
-
1251
- var time_now = InboundAnalytics.Utils.GetDate(),
1252
- vc = PageViews[page_id].length - 1,
1253
- last_view = PageViews[page_id][vc],
1254
- last_view_ms = new Date(last_view).getTime(),
1255
- time_now_ms = new Date(time_now).getTime(),
1256
- timeout_ms = last_view_ms + 30*1000,
1257
- time_check = Math.abs(last_view_ms - time_now_ms),
1258
- wait_time = 30000;
1259
-
1260
- InboundAnalytics.debug('Timeout Checks =',function(){
1261
- console.log('Current Time is: ' + time_now);
1262
- console.log('Last view is: ' + last_view);
1263
- console.log("Last view milliseconds " + last_view_ms);
1264
- console.log("time now milliseconds " + time_now_ms);
1265
- console.log("Wait Check: " + wait_time);
1266
- console.log("TIME CHECK: " + time_check);
1267
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1268
 
1269
- //var wait_time = Math.abs(last_view_ms - timeout_ms) // output timeout time 30sec;
1270
 
1271
- if (time_check < wait_time){
1272
- time_left = Math.abs((wait_time - time_check)) * .001;
1273
- pageviewTimeout = false;
1274
- var status = '30 sec timeout not done: ' + time_left + " seconds left";
 
 
 
 
 
 
 
 
 
 
 
1275
  } else {
1276
- var status = 'Timeout Happened. Page view fired';
1277
- this.firePageView();
1278
- pageviewTimeout = true;
1279
- InboundAnalytics.Events.analyticsTriggered();
1280
  }
1281
 
1282
- //InboundAnalytics.debug('',function(){
1283
- console.log(status);
1284
- //});
1285
- } else {
1286
- /* Page never seen before */
1287
- this.firePageView();
1288
- }
1289
 
1290
- return pageviewTimeout;
1291
 
1292
- },
1293
- firePageView: function() {
1294
- var lead_id = InboundAnalytics.Utils.readCookie('wp_lead_id'),
1295
- lead_uid = InboundAnalytics.Utils.readCookie('wp_lead_uid');
 
 
 
1296
 
1297
- if (typeof (lead_id) != "undefined" && lead_id != null && lead_id != "") {
1298
 
1299
- InboundAnalytics.debug('Run page view ajax');
 
 
1300
 
1301
- var data = {
1302
- action: 'wpl_track_user',
1303
- wp_lead_uid: lead_uid,
1304
- wp_lead_id: lead_id,
1305
- page_id: wplft.post_id,
1306
- current_url: window.location.href,
1307
- json: '0'
1308
- };
1309
- var firePageCallback = function(user_id){
1310
- InboundAnalytics.Events.analyticsSaved();
1311
- };
1312
- InboundAnalytics.Utils.doAjax(data, firePageCallback);
1313
- }
1314
- },
1315
- tabSwitch: function() {
1316
- /* test out simplier script
1317
- function onBlur() {
1318
- document.body.className = 'blurred';
1319
- };
1320
- function onFocus(){
1321
- document.body.className = 'focused';
1322
- };
1323
-
1324
- if (false) { // check for Internet Explorer
1325
- document.onfocusin = onFocus;
1326
- document.onfocusout = onBlur;
1327
- } else {
1328
- window.onfocus = onFocus;
1329
- window.onblur = onBlur;
1330
- }
1331
- */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1332
 
1333
- var hidden, visibilityState, visibilityChange;
1334
-
1335
- if (typeof document.hidden !== "undefined") {
1336
- hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
1337
- } else if (typeof document.mozHidden !== "undefined") {
1338
- hidden = "mozHidden", visibilityChange = "mozvisibilitychange", visibilityState = "mozVisibilityState";
1339
- } else if (typeof document.msHidden !== "undefined") {
1340
- hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
1341
- } else if (typeof document.webkitHidden !== "undefined") {
1342
- hidden = "webkitHidden", visibilityChange = "webkitvisibilitychange", visibilityState = "webkitVisibilityState";
1343
- } // if
1344
-
1345
- var document_hidden = document[hidden];
1346
-
1347
- document.addEventListener(visibilityChange, function() {
1348
- if(document_hidden != document[hidden]) {
1349
- if(document[hidden]) {
1350
- // Document hidden
1351
- console.log('hidden');
1352
- InboundAnalytics.Events.browserTabHidden();
1353
  } else {
1354
- // Document shown
1355
- console.log('shown');
1356
- InboundAnalytics.Events.browserTabVisible();
1357
- } // if
 
1358
 
1359
- document_hidden = document[hidden];
1360
- } // if
1361
- });
1362
- }
1363
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1364
 
1365
- return InboundAnalytics;
1366
 
1367
- })(InboundAnalytics || {});
1368
  /**
1369
- * Init Inbound Analytics
1370
- * - initializes analytics
 
 
 
 
1371
  */
1372
 
1373
- var InboundLeadData = jQuery.totalStorage('inbound_lead_data') || null;
1374
- function setGlobalLeadVar(retString){
1375
- InboundLeadData = retString;
1376
- }
1377
-
1378
- InboundAnalytics.init(); // run analytics
1379
-
1380
- /* run on ready */
1381
- jQuery(document).ready(function($) {
1382
- //record non conversion status
1383
- var in_u = InboundAnalytics.Utils,
1384
- wp_lead_uid = in_u.readCookie("wp_lead_uid"),
1385
- wp_lead_id = in_u.readCookie("wp_lead_id"),
1386
- expire_check = in_u.readCookie("lead_session_expire"); // check for session
1387
-
1388
- if (expire_check === null) {
1389
- console.log('expired vistor. Run Processes');
1390
- //var data_to_lookup = global-localized-vars;
1391
- if (typeof (wp_lead_id) != "undefined" && wp_lead_id != null && wp_lead_id != "") {
1392
- /* Get InboundLeadData */
1393
- InboundAnalytics.LeadsAPI.getAllLeadData(expire_check);
1394
- /* Lead list check */
1395
- InboundAnalytics.LeadsAPI.getLeadLists();
1396
- }
1397
- }
1398
-
1399
- //window.addEventListener('load',function(){
1400
- // InboundAnalytics.LeadsAPI.attachSubmitEvent(window,InboundAnalytics.LeadsAPI.formSubmit);
1401
- //}, false);
1402
-
1403
- in_u.contentLoaded(window, InboundAnalytics.LeadsAPI.attachFormSubmitEvent);
1404
-
1405
- /* Set Session Timeout */
1406
- in_u.SetSessionTimeout();
1407
-
1408
- });
1
  /*! Inbound Analyticsv1.0.0 | (c) 2014 Inbound Now | https://github.com/inboundnow/cta */
2
  /**
3
+ * # _inbound
4
+ *
5
+ * This main the _inbound class
6
+ *
7
+ * @author David Wells <david@inboundnow.com>
8
+ * @version 0.0.1
9
  */
10
+
11
  var inbound_data = inbound_data || {};
12
  var _inboundOptions = _inboundOptions || {};
13
  /* Ensure global _gaq Google Analytics queue has been initialized. */
14
  var _gaq = _gaq || [];
15
 
16
+ var _inbound = (function(options) {
17
+ /* Constants */
18
+ var defaults = {
19
+
20
+ timeout: 30000,
21
+ formAutoTracking: true,
22
+ formAutoPopulation: true
23
+ };
24
+
25
+ var Analytics = {
26
+ /* Initialize individual modules */
27
+ init: function() {
28
+ _inbound.Utils.init();
29
+
30
+ _inbound.Utils.domReady(window, function() {
31
+ /* On Load Analytics Events */
32
+ _inbound.DomLoaded();
33
+
34
+ });
35
+ },
36
+ DomLoaded: function() {
37
+ _inbound.PageTracking.init();
38
+ /* run form mapping */
39
+ _inbound.Forms.init();
40
+ /* set URL params */
41
+ _inbound.Utils.setUrlParams();
42
+ _inbound.LeadsAPI.init();
43
+ /* run form mapping for dynamically generated forms */
44
+ setTimeout(function() {
45
+ _inbound.Forms.init();
46
+ }, 2000);
47
+
48
+
49
+ _inbound.trigger('analytics_ready');
50
+
51
+ },
52
+ /**
53
+ * Merge script defaults with user options
54
+ * @private
55
+ * @param {Object} defaults Default settings
56
+ * @param {Object} options User options
57
+ * @returns {Object} Merged values of defaults and options
58
+ */
59
+ extend: function(defaults, options) {
60
+ var extended = {};
61
+ var prop;
62
+ for (prop in defaults) {
63
+ if (Object.prototype.hasOwnProperty.call(defaults, prop)) {
64
+ extended[prop] = defaults[prop];
65
+ }
66
+ }
67
+ for (prop in options) {
68
+ if (Object.prototype.hasOwnProperty.call(options, prop)) {
69
+ extended[prop] = options[prop];
70
+ }
71
+ }
72
+ return extended;
73
+ },
74
+ /* Debugger Function toggled by var debugMode */
75
+ debug: function(msg, callback) {
76
+ /* legacy */
77
+ },
78
+ deBugger: function(context, msg, callback) {
79
+
80
+ if (!console) {
81
+ return;
82
+ }
83
+ //if app not in debug mode, exit immediately
84
+ // check for hash
85
+ var hash = (document.location.hash) ? document.location.hash : '',
86
+ debugHash = hash.indexOf("#debug") > -1,
87
+ msg = msg || false,
88
+ logCookie,
89
+ logAllMessages,
90
+ hashcontext;
91
+
92
+ if (hash && hash.match(/debug/)) {
93
+ hash = hash.split('-');
94
+ hashcontext = hash[1];
95
+ }
96
+
97
+
98
+ logAllMessages = (_inbound.Utils.readCookie("inbound_debug") === "true") ? true : false;
99
+ logCookie = (_inbound.Utils.readCookie("inbound_debug_" + context) === "true") ? true : false;
100
+
101
+ if (!logCookie && !debugHash && !logAllMessages) {
102
+ // no logger set. exit.
103
+ return;
104
+ };
105
+
106
+ //console.log the message
107
+ if (msg && (typeof msg === 'string')) {
108
+
109
+ if (logAllMessages || hashcontext === 'all') {
110
+ console.log('logAll "' + context + '" =>', msg)
111
+ } else if (logCookie) {
112
+ console.log('log "' + context + '" =>', msg)
113
+ } else if (context === hashcontext) {
114
+ console.log('#log "' + context + '" =>', msg)
115
+ }
116
+
117
+ };
118
+
119
+ //execute the callback if one was passed-in
120
+ if (callback && (callback instanceof Function)) {
121
+ callback();
122
+ };
123
+ }
124
+ };
125
+
126
+ var settings = Analytics.extend(defaults, options);
127
+ /* Set globals */
128
+ Analytics.Settings = settings || {};
129
+
130
+ return Analytics;
131
 
132
  })(_inboundOptions);
133
  /**
134
+ * # Hooks & Filters
135
+ *
136
+ * This file contains all of the form functions of the main _inbound object.
137
+ * Filters and actions are described below
138
+ *
139
+ * Forked from https://github.com/carldanley/WP-JS-Hooks/blob/master/src/event-manager.js
140
+ *
141
+ * @author David Wells <david@inboundnow.com>
142
+ * @version 0.0.1
143
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
+ var _inboundHooks = (function (_inbound) {
146
+
147
+ /**
148
+ * # EventManager
149
+ *
150
+ * Actions and filters List
151
+ * addAction( 'namespace.identifier', callback, priority )
152
+ * addFilter( 'namespace.identifier', callback, priority )
153
+ * removeAction( 'namespace.identifier' )
154
+ * removeFilter( 'namespace.identifier' )
155
+ * doAction( 'namespace.identifier', arg1, arg2, moreArgs, finalArg )
156
+ * applyFilters( 'namespace.identifier', content )
157
+ * @return {[type]} [description]
158
+ */
159
+
160
+ /**
161
+ * Handles managing all events for whatever you plug it into. Priorities for hooks are based on lowest to highest in
162
+ * that, lowest priority hooks are fired first.
163
+ */
164
+ var EventManager = function() {
165
+ /**
166
+ * Maintain a reference to the object scope so our public methods never get confusing.
167
+ */
168
+ var MethodsAvailable = {
169
+ removeFilter : removeFilter,
170
+ applyFilters : applyFilters,
171
+ addFilter : addFilter,
172
+ removeAction : removeAction,
173
+ doAction : doAction,
174
+ addAction : addAction
175
+ };
176
+
177
+ /**
178
+ * Contains the hooks that get registered with this EventManager. The array for storage utilizes a "flat"
179
+ * object literal such that looking up the hook utilizes the native object literal hash.
180
+ */
181
+ var STORAGE = {
182
+ actions : {},
183
+ filters : {}
184
+ };
185
+
186
+ /**
187
+ * Adds an action to the event manager.
188
+ *
189
+ * @param action Must contain namespace.identifier
190
+ * @param callback Must be a valid callback function before this action is added
191
+ * @param [priority=10] Used to control when the function is executed in relation to other callbacks bound to the same hook
192
+ * @param [context] Supply a value to be used for this
193
+ */
194
+ function addAction( action, callback, priority, context ) {
195
+ if( typeof action === 'string' && typeof callback === 'function' ) {
196
+ priority = parseInt( ( priority || 10 ), 10 );
197
+ _addHook( 'actions', action, callback, priority, context );
198
+ }
199
+
200
+ return MethodsAvailable;
201
+ }
202
+
203
+ /**
204
+ * Performs an action if it exists. You can pass as many arguments as you want to this function; the only rule is
205
+ * that the first argument must always be the action.
206
+ */
207
+ function doAction( /* action, arg1, arg2, ... */ ) {
208
+ var args = Array.prototype.slice.call( arguments );
209
+ var action = args.shift();
210
+
211
+ if( typeof action === 'string' ) {
212
+ _runHook( 'actions', action, args );
213
+ }
214
+
215
+ return MethodsAvailable;
216
+ }
217
+
218
+ /**
219
+ * Removes the specified action if it contains a namespace.identifier & exists.
220
+ *
221
+ * @param action The action to remove
222
+ * @param [callback] Callback function to remove
223
+ */
224
+ function removeAction( action, callback ) {
225
+ if( typeof action === 'string' ) {
226
+ _removeHook( 'actions', action, callback );
227
+ }
228
+
229
+ return MethodsAvailable;
230
+ }
231
+
232
+ /**
233
+ * Adds a filter to the event manager.
234
+ *
235
+ * @param filter Must contain namespace.identifier
236
+ * @param callback Must be a valid callback function before this action is added
237
+ * @param [priority=10] Used to control when the function is executed in relation to other callbacks bound to the same hook
238
+ * @param [context] Supply a value to be used for this
239
+ */
240
+ function addFilter( filter, callback, priority, context ) {
241
+ if( typeof filter === 'string' && typeof callback === 'function' ) {
242
+ //console.log('add filter', filter);
243
+ priority = parseInt( ( priority || 10 ), 10 );
244
+ _addHook( 'filters', filter, callback, priority );
245
+ }
246
+
247
+ return MethodsAvailable;
248
+ }
249
+
250
+ /**
251
+ * Performs a filter if it exists. You should only ever pass 1 argument to be filtered. The only rule is that
252
+ * the first argument must always be the filter.
253
+ */
254
+ function applyFilters( /* filter, filtered arg, arg2, ... */ ) {
255
+ var args = Array.prototype.slice.call( arguments );
256
+ var filter = args.shift();
257
+
258
+ if( typeof filter === 'string' ) {
259
+ return _runHook( 'filters', filter, args );
260
+ }
261
+
262
+ return MethodsAvailable;
263
+ }
264
+
265
+ /**
266
+ * Removes the specified filter if it contains a namespace.identifier & exists.
267
+ *
268
+ * @param filter The action to remove
269
+ * @param [callback] Callback function to remove
270
+ */
271
+ function removeFilter( filter, callback ) {
272
+ if( typeof filter === 'string') {
273
+ _removeHook( 'filters', filter, callback );
274
+ }
275
+
276
+ return MethodsAvailable;
277
+ }
278
+
279
+ /**
280
+ * Removes the specified hook by resetting the value of it.
281
+ *
282
+ * @param type Type of hook, either 'actions' or 'filters'
283
+ * @param hook The hook (namespace.identifier) to remove
284
+ * @private
285
+ */
286
+ function _removeHook( type, hook, callback, context ) {
287
+ if ( !STORAGE[ type ][ hook ] ) {
288
+ return;
289
+ }
290
+ if ( !callback ) {
291
+ STORAGE[ type ][ hook ] = [];
292
+ } else {
293
+ var handlers = STORAGE[ type ][ hook ];
294
+ var i;
295
+ if ( !context ) {
296
+ for ( i = handlers.length; i--; ) {
297
+ if ( handlers[i].callback === callback ) {
298
+ handlers.splice( i, 1 );
299
+ }
300
+ }
301
+ }
302
+ else {
303
+ for ( i = handlers.length; i--; ) {
304
+ var handler = handlers[i];
305
+ if ( handler.callback === callback && handler.context === context) {
306
+ handlers.splice( i, 1 );
307
+ }
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Adds the hook to the appropriate storage container
315
+ *
316
+ * @param type 'actions' or 'filters'
317
+ * @param hook The hook (namespace.identifier) to add to our event manager
318
+ * @param callback The function that will be called when the hook is executed.
319
+ * @param priority The priority of this hook. Must be an integer.
320
+ * @param [context] A value to be used for this
321
+ * @private
322
+ */
323
+ function _addHook( type, hook, callback, priority, context ) {
324
+ var hookObject = {
325
+ callback : callback,
326
+ priority : priority,
327
+ context : context
328
+ };
329
+
330
+ // Utilize 'prop itself' : http://jsperf.com/hasownproperty-vs-in-vs-undefined/19
331
+ var hooks = STORAGE[ type ][ hook ];
332
+ if( hooks ) {
333
+ hooks.push( hookObject );
334
+ hooks = _hookInsertSort( hooks );
335
+ }
336
+ else {
337
+ hooks = [ hookObject ];
338
+ }
339
+
340
+ STORAGE[ type ][ hook ] = hooks;
341
+ }
342
+
343
+ /**
344
+ * Use an insert sort for keeping our hooks organized based on priority. This function is ridiculously faster
345
+ * than bubble sort, etc: http://jsperf.com/javascript-sort
346
+ *
347
+ * @param hooks The custom array containing all of the appropriate hooks to perform an insert sort on.
348
+ * @private
349
+ */
350
+ function _hookInsertSort( hooks ) {
351
+ var tmpHook, j, prevHook;
352
+ for( var i = 1, len = hooks.length; i < len; i++ ) {
353
+ tmpHook = hooks[ i ];
354
+ j = i;
355
+ while( ( prevHook = hooks[ j - 1 ] ) && prevHook.priority > tmpHook.priority ) {
356
+ hooks[ j ] = hooks[ j - 1 ];
357
+ --j;
358
+ }
359
+ hooks[ j ] = tmpHook;
360
+ }
361
+
362
+ return hooks;
363
+ }
364
+
365
+ /**
366
+ * Runs the specified hook. If it is an action, the value is not modified but if it is a filter, it is.
367
+ *
368
+ * @param type 'actions' or 'filters'
369
+ * @param hook The hook ( namespace.identifier ) to be ran.
370
+ * @param args Arguments to pass to the action/filter. If it's a filter, args is actually a single parameter.
371
+ * @private
372
+ */
373
+ function _runHook( type, hook, args ) {
374
+ var handlers = STORAGE[ type ][ hook ];
375
+
376
+ if ( !handlers ) {
377
+ return (type === 'filters') ? args[0] : false;
378
+ }
379
+
380
+ var i = 0, len = handlers.length;
381
+ if ( type === 'filters' ) {
382
+ for ( ; i < len; i++ ) {
383
+ args[ 0 ] = handlers[ i ].callback.apply( handlers[ i ].context, args );
384
+ }
385
+ } else {
386
+ for ( ; i < len; i++ ) {
387
+ handlers[ i ].callback.apply( handlers[ i ].context, args );
388
+ }
389
+ }
390
+
391
+ return ( type === 'filters' ) ? args[ 0 ] : true;
392
+ }
393
+
394
+ // return all of the publicly available methods
395
+ return MethodsAvailable;
396
+
397
+ };
398
+
399
+ _inbound.hooks = new EventManager();
400
+
401
+
402
+ /**
403
+ * Event Hooks and Filters public methods
404
+ */
405
+ /*
406
+ * add_action
407
+ *
408
+ * This function uses _inbound.hooks to mimics WP add_action
409
+ *
410
+ * ```js
411
+ * function Inbound_Add_Action_Example(data) {
412
+ * // Do stuff here.
413
+ * };
414
+ * // Add action to the hook
415
+ * _inbound.add_action( 'name_of_action', Inbound_Add_Action_Example, 10 );
416
+ * ```
417
+ */
418
+ _inbound.add_action = function() {
419
+ // allow multiple action parameters such as 'ready append'
420
+ var actions = arguments[0].split(' ');
421
+
422
+ for( k in actions ) {
423
+
424
+ // prefix action
425
+ arguments[0] = 'inbound.' + actions[ k ];
426
+
427
+ _inbound.hooks.addAction.apply(this, arguments);
428
+ }
429
+
430
+ return this;
431
+
432
+ };
433
+ /*
434
+ * remove_action
435
+ *
436
+ * This function uses _inbound.hooks to mimics WP remove_action
437
+ *
438
+ * ```js
439
+ * // Add remove action 'name_of_action'
440
+ * _inbound.remove_action( 'name_of_action');
441
+ * ```
442
+ *
443
+ */
444
+ _inbound.remove_action = function() {
445
+ // prefix action
446
+ arguments[0] = 'inbound.' + arguments[0];
447
+ _inbound.hooks.removeAction.apply(this, arguments);
448
+
449
+ return this;
450
+
451
+ };
452
+ /*
453
+ * do_action
454
+ *
455
+ * This function uses _inbound.hooks to mimics WP do_action
456
+ * This is used if you want to allow for third party JS plugins to act on your functions
457
+ *
458
+ */
459
+ _inbound.do_action = function() {
460
+ // prefix action
461
+ arguments[0] = 'inbound.' + arguments[0];
462
+ _inbound.hooks.doAction.apply(this, arguments);
463
+
464
+ return this;
465
+
466
+ };
467
+ /*
468
+ * add_filter
469
+ *
470
+ * This function uses _inbound.hooks to mimics WP add_filter
471
+ *
472
+ * ```js
473
+ * _inbound.add_filter( 'urlParamFilter', URL_Param_Filter, 10 );
474
+ * function URL_Param_Filter(urlParams) {
475
+ *
476
+ * var params = urlParams || {};
477
+ * // check for item in object
478
+ * if(params.utm_source !== "undefined"){
479
+ * //alert('url param "utm_source" is here');
480
+ * }
481
+ *
482
+ * // delete item from object
483
+ * delete params.utm_source;
484
+ *
485
+ * return params;
486
+ *
487
+ * }
488
+ * ```
489
+ */
490
+ _inbound.add_filter = function() {
491
+ // prefix action
492
+ arguments[0] = 'inbound.' + arguments[0];
493
+ _inbound.hooks.addFilter.apply(this, arguments);
494
+
495
+ return this;
496
+
497
+ };
498
+ /*
499
+ * remove_filter
500
+ *
501
+ * This function uses _inbound.hooks to mimics WP remove_filter
502
+ *
503
+ * ```js
504
+ * // Add remove filter 'urlParamFilter'
505
+ * _inbound.remove_action( 'urlParamFilter');
506
+ * ```
507
+ *
508
+ */
509
+ _inbound.remove_filter = function() {
510
+ // prefix action
511
+ arguments[0] = 'inbound.' + arguments[0];
512
+
513
+ _inbound.hooks.removeFilter.apply(this, arguments);
514
+
515
+ return this;
516
+
517
+ };
518
+ /*
519
+ * apply_filters
520
+ *
521
+ * This function uses _inbound.hooks to mimics WP apply_filters
522
+ *
523
+ */
524
+ _inbound.apply_filters = function() {
525
+ //console.log('Filter:' + arguments[0] + " ran on ->", arguments[1]);
526
+ // prefix action
527
+ arguments[0] = 'inbound.' + arguments[0];
528
+
529
+ return _inbound.hooks.applyFilters.apply(this, arguments);
530
+
531
+ };
532
+
533
+
534
+ return _inbound;
535
+
536
+ })(_inbound || {});
537
+ /**
538
+ * # _inbound UTILS
539
+ *
540
+ * This file contains all of the utility functions used by analytics
541
+ *
542
+ * @author David Wells <david@inboundnow.com>
543
+ * @version 0.0.1
544
+ */
545
+ var _inboundUtils = (function(_inbound) {
546
+
547
+ var storageSupported;
548
+
549
+ _inbound.Utils = {
550
+ init: function() {
551
+
552
+ this.polyFills();
553
+ this.checkLocalStorage();
554
+ this.SetUID();
555
+ this.storeReferralData();
556
+
557
+ },
558
+ /*! http://stackoverflow.com/questions/951791/javascript-global-error-handling */
559
+ /* Polyfills for missing browser functionality */
560
+ polyFills: function() {
561
+ /* Console.log fix for old browsers */
562
+ if (!window.console) {
563
+ window.console = {};
564
+ }
565
+ var m = [
566
+ "log", "info", "warn", "error", "debug", "trace", "dir", "group",
567
+ "groupCollapsed", "groupEnd", "time", "timeEnd", "profile", "profileEnd",
568
+ "dirxml", "assert", "count", "markTimeline", "timeStamp", "clear"
569
+ ];
570
+ // define undefined methods as noops to prevent errors
571
+ for (var i = 0; i < m.length; i++) {
572
+ if (!window.console[m[i]]) {
573
+ window.console[m[i]] = function() {};
574
+ }
575
+ }
576
+ /* Event trigger polyfill for IE9 and 10
577
+ (function() {
578
+ function CustomEvent(event, params) {
579
+ params = params || {
580
+ bubbles: false,
581
+ cancelable: false,
582
+ detail: undefined
583
+ };
584
+ var evt = document.createEvent('CustomEvent');
585
+ evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
586
+ return evt;
587
+ }
588
+
589
+ CustomEvent.prototype = window.Event.prototype;
590
+
591
+ window.CustomEvent = CustomEvent;
592
+ })();*/
593
+ /* custom event for ie8+ https://gist.github.com/WebReflection/6693661 */
594
+ try{new CustomEvent('?');}catch(o_O){
595
+ /*!(C) Andrea Giammarchi -- WTFPL License*/
596
+ this.CustomEvent = function(
597
+ eventName,
598
+ defaultInitDict
599
+ ){
600
+
601
+ // the infamous substitute
602
+ function CustomEvent(type, eventInitDict) {
603
+ var event = document.createEvent(eventName);
604
+ if (type !== null) {
605
+ initCustomEvent.call(
606
+ event,
607
+ type,
608
+ (eventInitDict || (
609
+ // if falsy we can just use defaults
610
+ eventInitDict = defaultInitDict
611
+ )).bubbles,
612
+ eventInitDict.cancelable,
613
+ eventInitDict.detail
614
+ );
615
+ } else {
616
+ // no need to put the expando property otherwise
617
+ // since an event cannot be initialized twice
618
+ // previous case is the most common one anyway
619
+ // but if we end up here ... there it goes
620
+ event.initCustomEvent = initCustomEvent;
621
  }
622
+ return event;
623
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
624
 
625
+ // borrowed or attached at runtime
626
+ function initCustomEvent(
627
+ type, bubbles, cancelable, detail
628
+ ) {
629
+ this['init' + eventName](type, bubbles, cancelable, detail);
630
+ 'detail' in this || (this.detail = detail);
631
+ }
632
+
633
+ // that's it
634
+ return CustomEvent;
635
+ }(
636
+ // is this IE9 or IE10 ?
637
+ // where CustomEvent is there
638
+ // but not usable as construtor ?
639
+ this.CustomEvent ?
640
+ // use the CustomEvent interface in such case
641
+ 'CustomEvent' : 'Event',
642
+ // otherwise the common compatible one
643
+ {
644
+ bubbles: false,
645
+ cancelable: false,
646
+ detail: null
647
+ }
648
+ );
649
+ }
650
+ /* querySelectorAll polyfill for ie7+ */
651
+ if (!document.querySelectorAll) {
652
+ document.querySelectorAll = function (selectors) {
653
+ var style = document.createElement('style'), elements = [], element;
654
+ document.documentElement.firstChild.appendChild(style);
655
+ document._qsa = [];
656
+
657
+ style.styleSheet.cssText = selectors + '{x-qsa:expression(document._qsa && document._qsa.push(this))}';
658
+ window.scrollBy(0, 0);
659
+ style.parentNode.removeChild(style);
660
+
661
+ while (document._qsa.length) {
662
+ element = document._qsa.shift();
663
+ element.style.removeAttribute('x-qsa');
664
+ elements.push(element);
665
+ }
666
+ document._qsa = null;
667
+ return elements;
668
+ };
669
+ }
670
+
671
+ if (!document.querySelector) {
672
+ document.querySelector = function (selectors) {
673
+ var elements = document.querySelectorAll(selectors);
674
+ return (elements.length) ? elements[0] : null;
675
+ };
676
+ }
677
+ /* Innertext shim for firefox https://github.com/duckinator/innerText-polyfill/blob/master/innertext.js */
678
+ if ( (!('innerText' in document.createElement('a'))) && ('getSelection' in window) ) {
679
+ HTMLElement.prototype.__defineGetter__("innerText", function() {
680
+ var selection = window.getSelection(),
681
+ ranges = [],
682
+ str;
683
+
684
+ // Save existing selections.
685
+ for (var i = 0; i < selection.rangeCount; i++) {
686
+ ranges[i] = selection.getRangeAt(i);
687
+ }
688
+
689
+ // Deselect everything.
690
+ selection.removeAllRanges();
691
+
692
+ // Select `el` and all child nodes.
693
+ // 'this' is the element .innerText got called on
694
+ selection.selectAllChildren(this);
695
+
696
+ // Get the string representation of the selected nodes.
697
+ str = selection.toString();
698
+
699
+ // Deselect everything. Again.
700
+ selection.removeAllRanges();
701
+
702
+ // Restore all formerly existing selections.
703
+ for (var i = 0; i < ranges.length; i++) {
704
+ selection.addRange(ranges[i]);
705
+ }
706
+
707
+ // Oh look, this is what we wanted.
708
+ // String representation of the element, close to as rendered.
709
+ return str;
710
+ })
711
+ }
712
+ },
713
+ /**
714
+ * Create cookie
715
+ *
716
+ * ```js
717
+ * // Creates cookie for 10 days
718
+ * _inbound.utils.createCookie( 'cookie_name', 'value', 10 );
719
+ * ```
720
+ *
721
+ * @param {string} name Name of cookie
722
+ * @param {string} value Value of cookie
723
+ * @param {string} days Length of storage
724
+ */
725
+ createCookie: function(name, value, days) {
726
+ var expires = "";
727
+ if (days) {
728
+ var date = new Date();
729
+ date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
730
+ expires = "; expires=" + date.toGMTString();
731
+ }
732
+ document.cookie = name + "=" + value + expires + "; path=/";
733
+ },
734
+ /**
735
+ * Read cookie value
736
+ *
737
+ * ```js
738
+ * var cookie = _inbound.utils.readCookie( 'cookie_name' );
739
+ * console.log(cookie); // cookie value
740
+ * ```
741
+ * @param {string} name name of cookie
742
+ * @return {string} value of cookie
743
+ */
744
+ readCookie: function(name) {
745
+ var nameEQ = name + "=";
746
+ var ca = document.cookie.split(';');
747
+ for (var i = 0; i < ca.length; i++) {
748
+ var c = ca[i];
749
+ while (c.charAt(0) === ' ') {
750
+ c = c.substring(1, c.length);
751
+ }
752
+ if (c.indexOf(nameEQ) === 0) {
753
+ return c.substring(nameEQ.length, c.length);
754
+ }
755
+ }
756
+ return null;
757
+ },
758
+ /**
759
+ * Erase cookie
760
+ *
761
+ * ```js
762
+ * // usage:
763
+ * _inbound.utils.eraseCookie( 'cookie_name' );
764
+ * // deletes 'cookie_name' value
765
+ * ```
766
+ * @param {string} name name of cookie
767
+ * @return {string} value of cookie
768
+ */
769
+ eraseCookie: function(name) {
770
+ this.createCookie(name, "", -1);
771
+ },
772
+ /* Get All Cookies */
773
+ getAllCookies: function() {
774
+ var cookies = {};
775
+ if (document.cookie && document.cookie !== '') {
776
+ var split = document.cookie.split(';');
777
+ for (var i = 0; i < split.length; i++) {
778
+ var name_value = split[i].split("=");
779
+ name_value[0] = name_value[0].replace(/^ /, '');
780
+ cookies[decodeURIComponent(name_value[0])] = decodeURIComponent(name_value[1]);
781
+ }
782
+ }
783
+ _inbound.totalStorage('inbound_cookies', cookies); // store cookie data
784
+ return cookies;
785
+ },
786
+ /* Grab URL params and save */
787
+ setUrlParams: function() {
788
+ var urlParams = {};
789
+
790
+ (function() {
791
+ var e,
792
+ d = function(s) {
793
+ return decodeURIComponent(s).replace(/\+/g, " ");
794
+ },
795
+ q = window.location.search.substring(1),
796
+ r = /([^&=]+)=?([^&]*)/g;
797
+
798
+ while (e = r.exec(q)) {
799
+ if (e[1].indexOf("[") == "-1")
800
+ urlParams[d(e[1])] = d(e[2]);
801
+ else {
802
+ var b1 = e[1].indexOf("["),
803
+ aN = e[1].slice(b1 + 1, e[1].indexOf("]", b1)),
804
+ pN = d(e[1].slice(0, b1));
805
+
806
+ if (typeof urlParams[pN] != "object")
807
+ urlParams[d(pN)] = {},
808
+ urlParams[d(pN)].length = 0;
809
+
810
+ if (aN)
811
+ urlParams[d(pN)][d(aN)] = d(e[2]);
812
+ else
813
+ Array.prototype.push.call(urlParams[d(pN)], d(e[2]));
814
+
815
+ }
816
  }
 
817
  })();
818
 
819
+ /* Set Param Cookies */
820
+ for (var k in urlParams) {
821
+ if (typeof urlParams[k] == "object") {
822
  for (var k2 in urlParams[k])
823
+ this.createCookie(k2, urlParams[k][k2], 30);
824
+ } else {
825
  this.createCookie(k, urlParams[k], 30);
826
+ }
 
827
  }
828
+ /* Set Param LocalStorage */
829
+ if (storageSupported) {
830
+ var pastParams = _inbound.totalStorage('inbound_url_params') || {};
831
+ var params = this.mergeObjs(pastParams, urlParams);
832
+ _inbound.totalStorage('inbound_url_params', params); // store cookie data
833
+ }
834
+
835
+ var options = {'option1': 'yo', 'option2': 'woooo'};
836
+
837
+ _inbound.trigger('url_parameters', urlParams, options);
838
 
839
+ },
840
+ getAllUrlParams: function() {
841
+ var get_params = {};
842
+ if (storageSupported) {
843
+ var get_params = _inbound.totalStorage('inbound_url_params');
844
  }
845
+ return get_params;
846
+ },
847
+ /* Get url param */
848
+ getParameterVal: function(name, string) {
849
+ return (RegExp(name + '=' + '(.+?)(&|$)').exec(string)||[,false])[1];
850
+ },
851
+ // Check local storage
852
+ // provate browsing safari fix https://github.com/marcuswestin/store.js/issues/42#issuecomment-25274685
853
+ checkLocalStorage: function() {
854
+ if ('localStorage' in window) {
855
+ try {
856
+ ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
857
+ if (typeof ls == 'undefined' || typeof window.JSON == 'undefined') {
858
+ storageSupported = false;
859
+ } else {
860
+ storageSupported = true;
861
+ }
862
+
863
+ } catch (err) {
864
+ storageSupported = false;
865
+ }
 
 
 
866
  }
867
+ return storageSupported;
868
+ /* http://spin.atomicobject.com/2013/01/23/ios-private-browsing-localstorage/
869
+ var hasStorage;
870
+ hasStorage = function() {
871
+ var mod, result;
872
+ try {
873
+ mod = new Date;
874
+ localStorage.setItem(mod, mod.toString());
875
+ result = localStorage.getItem(mod) === mod.toString();
876
+ localStorage.removeItem(mod);
877
+ return result;
878
+ } catch (_error) {}
879
+ };
880
+ */
881
+ },
882
+ /* Add days to datetime */
883
+ addDays: function(myDate, days) {
884
+ return new Date(myDate.getTime() + days * 24 * 60 * 60 * 1000);
885
+ },
886
+ GetDate: function() {
887
+ var timeNow = new Date(),
888
+ d = timeNow.getDate(),
889
+ dPre = (d < 10) ? "0" : "",
890
+ y = timeNow.getFullYear(),
891
+ h = timeNow.getHours(),
892
+ hPre = (h < 10) ? "0" : "",
893
+ min = timeNow.getMinutes(),
894
+ minPre = (min < 10) ? "0" : "",
895
+ sec = timeNow.getSeconds(),
896
+ secPre = (sec < 10) ? "0" : "",
897
+ m = timeNow.getMonth() + 1,
898
+ mPre = (m < 10) ? "0" : "";
899
+
900
+ var datetime = y + '/' + mPre+m + "/" + dPre+d + " " + hPre+h + ":" + minPre+min + ":" + secPre+sec;
901
+ /* format 2014/11/13 18:22:02 */
902
+ return datetime;
903
+ },
904
+ /* Set Expiration Date of Session Logging. LEGACY Not in Use */
905
+ SetSessionTimeout: function() {
906
+ var session = this.readCookie("lead_session_expire");
907
+ //console.log(session_check);
908
+ if (!session) {
909
+ //_inbound.trigger('session_start'); // trigger 'inbound_analytics_session_start'
910
+ } else {
911
+ //_inbound.trigger('session_resume'); // trigger 'inbound_analytics_session_active'
912
+ }
913
+ var d = new Date();
914
+ d.setTime(d.getTime() + 30 * 60 * 1000);
 
 
 
 
 
 
915
 
916
+ this.createCookie("lead_session_expire", true, d, true); // Set cookie on page load
917
+
918
+ },
919
+ storeReferralData: function() {
920
+ //console.log(expire_time);
921
+ var d = new Date(),
922
+ referrer = document.referrer || "Direct Traffic",
923
+ referrer_cookie = _inbound.Utils.readCookie("inbound_referral_site"),
924
+ original_src = _inbound.totalStorage('inbound_original_referral');
925
+
926
+ d.setTime(d.getTime() + 30 * 60 * 1000);
927
+
928
+ if (!referrer_cookie) {
929
+ this.createCookie("inbound_referral_site", referrer, d, true);
930
+ }
931
+ if (!original_src) {
932
+ _inbound.totalStorage('inbound_original_referral', original_src);
933
+ }
934
+ },
935
+ CreateUID: function(length) {
936
+ var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(''),
937
+ str = '';
938
+ if (!length) {
939
+ length = Math.floor(Math.random() * chars.length);
940
+ }
941
+ for (var i = 0; i < length; i++) {
942
+ str += chars[Math.floor(Math.random() * chars.length)];
943
+ }
944
+ return str;
945
+ },
946
+ SetUID: function(leadUID) {
947
+ /* Set Lead UID */
948
+ if (!this.readCookie("wp_lead_uid")) {
949
+ var wp_lead_uid = leadUID || this.CreateUID(35);
950
+ this.createCookie("wp_lead_uid", wp_lead_uid);
951
+ }
952
+ },
953
+ /* Count number of session visits */
954
+ countProperties: function(obj) {
955
+ var count = 0;
956
+ for (var prop in obj) {
957
+ if (obj.hasOwnProperty(prop))
958
+ ++count;
959
+ }
960
+ return count;
961
+ },
962
+ mergeObjs: function(obj1, obj2) {
963
  var obj3 = {};
964
+ for (var attrname in obj1) {
965
+ obj3[attrname] = obj1[attrname];
966
+ }
967
+ for (var attrname in obj2) {
968
+ obj3[attrname] = obj2[attrname];
969
+ }
970
  return obj3;
971
+ },
972
+ hasClass: function(className, el) {
973
+ var hasClass = false;
974
+ if ('classList' in document.documentElement) {
975
+ var hasClass = el.classList.contains(className);
976
+ } else {
977
+ var hasClass = new RegExp('(^|\\s)' + className + '(\\s|$)').test(el.className); /* IE Polyfill */
978
+ }
979
+ return hasClass;
980
+ },
981
+ addClass: function(className, elem) {
982
+ if ('classList' in document.documentElement) {
983
+ elem.classList.add(className);
984
+ } else {
985
+ if (!this.hasClass(elem, className)) {
986
+ elem.className += (elem.className ? ' ' : '') + className;
987
+ }
988
+ }
989
+ },
990
+ removeClass: function(className, elem) {
991
+ if ('classList' in document.documentElement) {
992
+
993
+ elem.classList.remove(className);
994
+ } else {
995
+ if (this.hasClass(elem, className)) {
996
+ elem.className = elem.className.replace(new RegExp('(^|\\s)*' + className + '(\\s|$)*', 'g'), '');
997
+ }
998
+ }
999
+ },
1000
+ removeElement: function (el) {
1001
+ el.parentNode.removeChild(el);
1002
+ },
1003
+ trim: function(s) {
1004
+ s = s.replace(/(^\s*)|(\s*$)/gi, "");
1005
+ s = s.replace(/[ ]{2,}/gi, " ");
1006
+ s = s.replace(/\n /, "\n");
1007
+ return s;
1008
+ },
1009
+ ajaxPolyFill: function() {
1010
+ if (typeof XMLHttpRequest !== 'undefined') {
1011
+ return new XMLHttpRequest();
1012
+ }
1013
+ var versions = [
1014
+ "MSXML2.XmlHttp.5.0",
1015
+ "MSXML2.XmlHttp.4.0",
1016
+ "MSXML2.XmlHttp.3.0",
1017
+ "MSXML2.XmlHttp.2.0",
1018
+ "Microsoft.XmlHttp"
1019
+ ];
1020
+
1021
+ var xhr;
1022
+ for (var i = 0; i < versions.length; i++) {
1023
+ try {
1024
+ xhr = new ActiveXObject(versions[i]);
1025
+ break;
1026
+ } catch (e) {}
1027
+ }
1028
+ return xhr;
1029
+ },
1030
+ ajaxSendData: function(url, callback, method, data, sync) {
1031
+ var x = this.ajaxPolyFill();
1032
+ x.open(method, url, sync);
1033
+ x.onreadystatechange = function() {
1034
+ if (x.readyState == 4) {
1035
+ callback(x.responseText)
1036
+ }
1037
+ };
1038
+ if (method == 'POST') {
1039
+ x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
1040
+ }
1041
+ x.send(data);
1042
+ },
1043
+ ajaxGet: function(url, data, callback, sync) {
1044
+ var query = [];
1045
+ for (var key in data) {
1046
+ query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
1047
+ }
1048
+ this.ajaxSendData(url + '?' + query.join('&'), callback, 'GET', null, sync)
1049
+ },
1050
+ ajaxPost: function(url, data, callback, sync) {
1051
+ var query = [];
1052
+ for (var key in data) {
1053
+ query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
1054
+ }
1055
+ this.ajaxSendData(url, callback, 'POST', query.join('&'), sync)
1056
+ },
1057
+ makeRequest: function(url, data) {
1058
+ if (window.XMLHttpRequest) { // Mozilla, Safari, ...
1059
+ httpRequest = new XMLHttpRequest();
1060
+ } else if (window.ActiveXObject) { // IE
1061
+ try {
1062
+ httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
1063
+ } catch (e) {
1064
+ try {
1065
+ httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
1066
+ } catch (e) {}
1067
+ }
1068
+ }
1069
+
1070
+ if (!httpRequest) {
1071
+ alert('Giving up :( Cannot create an XMLHTTP instance');
1072
+ return false;
1073
+ }
1074
+ httpRequest.onreadystatechange = _inbound.LeadsAPI.alertContents;
1075
+ httpRequest.open('GET', url);
1076
+ httpRequest.send(data);
1077
+ },
1078
+ domReady: function(win, fn) {
1079
+
1080
+ var done = false,
1081
+ top = true,
1082
+
1083
+ doc = win.document,
1084
+ root = doc.documentElement,
1085
+
1086
+ add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
1087
+ rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
1088
+ pre = doc.addEventListener ? '' : 'on',
1089
+
1090
+ init = function(e) {
1091
+ if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
1092
+ (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
1093
+ if (!done && (done = true)) fn.call(win, e.type || e);
1094
+ },
1095
+
1096
+ poll = function() {
1097
+ try {
1098
+ root.doScroll('left');
1099
+ } catch (e) {
1100
+ setTimeout(poll, 50);
1101
+ return;
1102
+ }
1103
+ init('poll');
1104
+ };
1105
+
1106
+ if (doc.readyState == 'complete') fn.call(win, 'lazy');
1107
+ else {
1108
+ if (doc.createEventObject && root.doScroll) {
1109
+ try {
1110
+ top = !win.frameElement;
1111
+ } catch (e) {}
1112
+ if (top) poll();
1113
+ }
1114
+ doc[add](pre + 'DOMContentLoaded', init, false);
1115
+ doc[add](pre + 'readystatechange', init, false);
1116
+ win[add](pre + 'load', init, false);
1117
+ }
1118
+
1119
+ },
1120
+ /* Cross-browser event listening */
1121
+ addListener: function(element, eventName, listener) {
1122
+ if(!element){
1123
+ return;
1124
+ }
1125
+ //console.log(eventName);
1126
+ //console.log(listener);
1127
+ if (element.addEventListener) {
1128
+ element.addEventListener(eventName, listener, false);
1129
+ } else if (element.attachEvent) {
1130
+ element.attachEvent("on" + eventName, listener);
1131
+ } else {
1132
+ element['on' + eventName] = listener;
1133
+ }
1134
+ },
1135
+ removeListener: function(element, eventName, listener) {
1136
+
1137
+ if (element.removeEventListener) {
1138
+ element.removeEventListener(eventName, listener, false);
1139
+ } else if (element.detachEvent) {
1140
+ element.detachEvent("on" + eventName, listener);
1141
+ } else {
1142
+ element["on" + eventName] = null;
1143
+ }
1144
+ },
1145
+ /*
1146
+ * Throttle function borrowed from:
1147
+ * Underscore.js 1.5.2
1148
+ * http://underscorejs.org
1149
+ * (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
1150
+ * Underscore may be freely distributed under the MIT license.
1151
+ */
1152
+ throttle: function (func, wait) {
1153
+ var context, args, result;
1154
+ var timeout = null;
1155
+ var previous = 0;
1156
+ var later = function() {
1157
+ previous = new Date;
1158
+ timeout = null;
1159
+ result = func.apply(context, args);
1160
+ };
1161
+ return function() {
1162
+ var now = new Date;
1163
+ if (!previous) previous = now;
1164
+ var remaining = wait - (now - previous);
1165
+ context = this;
1166
+ args = arguments;
1167
+ if (remaining <= 0) {
1168
+ clearTimeout(timeout);
1169
+ timeout = null;
1170
+ previous = now;
1171
+ result = func.apply(context, args);
1172
+ } else if (!timeout) {
1173
+ timeout = setTimeout(later, remaining);
1174
+ }
1175
+ return result;
1176
+ };
1177
+ },
1178
+ /*
1179
+ * Determine which version of GA is being used
1180
+ * "ga", "_gaq", and "dataLayer" are the possible globals
1181
+ */
1182
+ checkTypeofGA: function() {
1183
+ if (typeof ga === "function") {
1184
+ universalGA = true;
1185
  }
1186
 
1187
+ if (typeof _gaq !== "undefined" && typeof _gaq.push === "function") {
1188
+ classicGA = true;
 
 
 
 
 
 
1189
  }
1190
+
1191
+ if (typeof dataLayer !== "undefined" && typeof dataLayer.push === "function") {
1192
+ googleTagManager = true;
 
 
1193
  }
 
1194
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1195
  }
1196
+ };
 
 
 
1197
 
1198
+ return _inbound;
1199
+
1200
+ })(_inbound || {});
1201
+ /**
1202
+ * # Inbound Forms
1203
+ *
1204
+ * This file contains all of the form functions of the main _inbound object.
1205
+ * Filters and actions are described below
1206
+ *
1207
+ * @author David Wells <david@inboundnow.com>
1208
+ * @version 0.0.1
1209
+ */
1210
+ /* Finish Exclusions for CC */
1211
+
1212
+ /* Launches form class */
1213
+ var InboundForms = (function(_inbound) {
1214
+
1215
+ var debugMode = false,
1216
+ utils = _inbound.Utils,
1217
+ no_match = [],
1218
+ rawParams = [],
1219
+ mappedParams = [],
1220
+ settings = _inbound.Settings;
1221
+
1222
+ var FieldMapArray = [
1223
+ "first name",
1224
+ "last name",
1225
+ "name",
1226
+ "email",
1227
+ "e-mail",
1228
+ "phone",
1229
+ "website",
1230
+ "job title",
1231
+ "your favorite food",
1232
+ "company",
1233
+ "tele",
1234
+ "address",
1235
+ "comment"
1236
+ /* Adding values here maps them */
1237
+ ];
1238
+
1239
+ _inbound.Forms = {
1240
+
1241
+ // Init Form functions
1242
+ init: function() {
1243
+ _inbound.Forms.runFieldMappingFilters();
1244
+ _inbound.Forms.assignTrackClass();
1245
+ _inbound.Forms.formTrackInit();
1246
+ },
1247
+ /**
1248
+ * This triggers the forms.field_map filter on the mapping array.
1249
+ * This will allow you to add or remore Items from the mapping lookup
1250
+ *
1251
+ * ### Example inbound.form_map_before filter
1252
+ *
1253
+ * This is an example of how form mapping can be filtered and
1254
+ * additional fields can be mapped via javascript
1255
+ *
1256
+ * ```js
1257
+ * // Adding the filter function
1258
+ * function Inbound_Add_Filter_Example( FieldMapArray ) {
1259
+ * var map = FieldMapArray || [];
1260
+ * map.push('new lookup value');
1261
+ *
1262
+ * return map;
1263
+ * };
1264
+ *
1265
+ * // Adding the filter on dom ready
1266
+ * _inbound.hooks.addFilter( 'inbound.form_map_before', Inbound_Add_Filter_Example, 10 );
1267
+ * ```
1268
+ *
1269
+ * @return {[type]} [description]
1270
+ */
1271
+ runFieldMappingFilters: function() {
1272
+ FieldMapArray = _inbound.hooks.applyFilters('forms.field_map', FieldMapArray);
1273
+ //alert(FieldMapArray);
1274
+ },
1275
+ debug: function(msg, callback) {
1276
+ //if app not in debug mode, exit immediately
1277
+ if (!debugMode || !console) {
1278
+ return
1279
+ };
1280
+ var msg = msg || false;
1281
+ //console.log the message
1282
+ if (msg && (typeof msg === 'string')) {
1283
+ console.log(msg)
1284
+ };
1285
+
1286
+ //execute the callback if one was passed-in
1287
+ if (callback && (callback instanceof Function)) {
1288
+ callback();
1289
+ };
1290
+ },
1291
+ formTrackInit: function() {
1292
+
1293
+ for (var i = 0; i < window.document.forms.length; i++) {
1294
+ var trackForm = false;
1295
+ var form = window.document.forms[i];
1296
+ /* process forms only once */
1297
+ if (!form.dataset.formProcessed) {
1298
+ form.dataset.formProcessed = true;
1299
+ trackForm = this.checkTrackStatus(form);
1300
+ // var trackForm = _inbound.Utils.hasClass("wpl-track-me", form);
1301
+ if (trackForm) {
1302
+ this.attachFormSubmitEvent(form); /* attach form listener */
1303
+ this.initFormMapping(form);
1304
+ }
1305
+ }
1306
+ }
1307
+ },
1308
+ checkTrackStatus: function(form) {
1309
+ var ClassIs = form.getAttribute('class');
1310
+ if (ClassIs !== "" && ClassIs !== null) {
1311
+ if (ClassIs.toLowerCase().indexOf("wpl-track-me") > -1) {
1312
+ return true;
1313
+ } else if (ClassIs.toLowerCase().indexOf("inbound-track") > -1) {
1314
+ return true;
1315
+ } else {
1316
+ cb = function(){
1317
+ console.log(form);
1318
+ }
1319
+ _inbound.deBugger('forms', "This form not tracked. Please assign on in settings...", cb);
1320
+ return false;
1321
+ }
1322
+ }
1323
+ },
1324
+ assignTrackClass: function() {
1325
+ if (window.inbound_settings) {
1326
+ if (inbound_settings.inbound_track_include) {
1327
+ var selectors = inbound_settings.inbound_track_include.split(',');
1328
+ var msg = 'add selectors ' + inbound_settings.inbound_track_include;
1329
+ _inbound.deBugger('forms', msg);
1330
+ this.loopClassSelectors(selectors, 'add');
1331
+ }
1332
+ if (inbound_settings.inbound_track_exclude) {
1333
+ var selectors = inbound_settings.inbound_track_exclude.split(',');
1334
+ var msg = 'remove selectors ' + inbound_settings.inbound_track_exclude;
1335
+ _inbound.deBugger('forms', msg);
1336
+ this.loopClassSelectors(selectors, 'remove');
1337
+ }
1338
+ }
1339
+ },
1340
+ /* Loop through include/exclude items for tracking */
1341
+ loopClassSelectors: function(selectors, action) {
1342
+ for (var i = selectors.length - 1; i >= 0; i--) {
1343
+
1344
+ //if(selectors[i] match . or # )
1345
+ selector = document.querySelector(utils.trim(selectors[i]));
1346
+ //console.log("SELECTOR", selector);
1347
+ if (selector) {
1348
+ if (action === 'add') {
1349
+ _inbound.Utils.addClass('wpl-track-me', selector);
1350
+ _inbound.Utils.addClass('inbound-track', selector);
1351
+ } else {
1352
+ _inbound.Utils.removeClass('wpl-track-me', selector);
1353
+ _inbound.Utils.removeClass('inbound-track', selector);
1354
+ }
1355
+ }
1356
+ };
1357
+ },
1358
+ /* Map field fields on load */
1359
+ initFormMapping: function(form) {
1360
+ var hiddenInputs = [];
1361
+
1362
+ for (var i = 0; i < form.elements.length; i++) {
1363
+ formInput = form.elements[i];
1364
+
1365
+ if (formInput.type === 'hidden') {
1366
+ hiddenInputs.push(formInput);
1367
+ continue;
1368
+ }
1369
+ /* Map form fields */
1370
+ this.mapField(formInput);
1371
+ /* Remember visible inputs */
1372
+ this.rememberInputValues(formInput);
1373
+ /* Fill visible inputs */
1374
+ if (settings.formAutoPopulation) {
1375
+ this.fillInputValues(formInput);
1376
+ }
1377
+
1378
+ }
1379
+ for (var i = hiddenInputs.length - 1; i >= 0; i--) {
1380
+ formInput = hiddenInputs[i];
1381
+ this.mapField(formInput);
1382
+ };
1383
+
1384
+ //console.log('mapping on load completed');
1385
+ },
1386
+ /* prevent default submission temporarily */
1387
+ formListener: function(event) {
1388
+ //console.log(event);
1389
+ event.preventDefault();
1390
+ _inbound.Forms.saveFormData(event.target);
1391
+ document.body.style.cursor = "wait";
1392
+ },
1393
+ /* attach form listeners */
1394
+ attachFormSubmitEvent: function(form) {
1395
+ utils.addListener(form, 'submit', this.formListener);
1396
+ var email_input = document.querySelector('.inbound-email');
1397
+ utils.addListener(email_input, 'blur', this.mailCheck);
1398
+ },
1399
+ ignoreFields: function(input) {
1400
+
1401
+ var ignore_field = false,
1402
+ label = "",
1403
+ value = "";
1404
+
1405
+ // Ignore any fields with labels that indicate a credit card field
1406
+ if (label.toLowerCase().indexOf('credit card') != -1 || label.toLowerCase().indexOf('card number') != -1) {
1407
+ ignore_field = true;
1408
+ }
1409
+
1410
+
1411
+ if (label.toLowerCase().indexOf('expiration') != -1 || label.toLowerCase().indexOf('expiry') != -1) {
1412
+ ignore_field = true;
1413
+ }
1414
+
1415
+
1416
+ if (label.toLowerCase() == 'month' || label.toLowerCase() == 'mm' || label.toLowerCase() == 'yy' || label.toLowerCase() == 'yyyy' || label.toLowerCase() == 'year') {
1417
+ ignore_field = true;
1418
+ }
1419
+
1420
+
1421
+ if (label.toLowerCase().indexOf('cvv') != -1 || label.toLowerCase().indexOf('cvc') != -1 || label.toLowerCase().indexOf('secure code') != -1 || label.toLowerCase().indexOf('security code') != -1) {
1422
+ ignore_field = true;
1423
+ }
1424
+
1425
+
1426
+ if (value.toLowerCase() == 'visa' || value.toLowerCase() == 'mastercard' || value.toLowerCase() == 'american express' || value.toLowerCase() == 'amex' || value.toLowerCase() == 'discover') {
1427
+ ignore_field = true;
1428
+ }
1429
+
1430
+ // Check if value has integers, strip out spaces, then ignore anything with a credit card length (>16) or an expiration/cvv length (<5)
1431
+ var int_regex = new RegExp("/^[0-9]+$/");
1432
+ if (int_regex.test(value)) {
1433
+ var value_no_spaces = value.replace(' ', '');
1434
+
1435
+ if (this.isInt(value_no_spaces) && value_no_spaces.length >= 16) {
1436
+ ignore_field = true;
1437
+ }
1438
+
1439
+ }
1440
+
1441
+ return ignore_field;
1442
+
1443
+ },
1444
+ isInt: function(n) {
1445
+ return typeof n == "number" && isFinite(n) && n % 1 === 0;
1446
+ },
1447
+ releaseFormSubmit: function(form) {
1448
+ //console.log('remove form listener event');
1449
+ document.body.style.cursor = "default";
1450
+ utils.removeClass('wpl-track-me', form);
1451
+ utils.removeListener(form, 'submit', this.formListener);
1452
+ form.submit();
1453
+ /* fallback if submit name="submit" */
1454
+ setTimeout(function() {
1455
+ for (var i = 0; i < form.elements.length; i++) {
1456
+ formInput = form.elements[i];
1457
+ type = formInput.type || false;
1458
+ if (type === "submit") {
1459
+ form.elements[i].click();
1460
+ }
1461
+ }
1462
+ }, 1300);
1463
+
1464
+ },
1465
+ saveFormData: function(form) {
1466
+ var inputsObject = inputsObject || {};
1467
+ for (var i = 0; i < form.elements.length; i++) {
1468
+
1469
+ // console.log(inputsObject);
1470
+
1471
+ formInput = form.elements[i];
1472
+ multiple = false;
1473
+
1474
+ if (formInput.name) {
1475
+
1476
+ if (formInput.dataset.ignoreFormField) {
1477
+ _inbound.deBugger('forms', 'ignore ' + formInput.name);
1478
+ continue;
1479
+ }
1480
+
1481
+ inputName = formInput.name.replace(/\[([^\[]*)\]/g, "%5B%5D$1");
1482
+ //inputName = inputName.replace(/-/g, "_");
1483
+ if (!inputsObject[inputName]) {
1484
+ inputsObject[inputName] = {};
1485
+ }
1486
+ if (formInput.type) {
1487
+ inputsObject[inputName]['type'] = formInput.type;
1488
+ }
1489
+ if (!inputsObject[inputName]['name']) {
1490
+ inputsObject[inputName]['name'] = formInput.name;
1491
+ }
1492
+ if (formInput.dataset.mapFormField) {
1493
+ inputsObject[inputName]['map'] = formInput.dataset.mapFormField;
1494
+ }
1495
+ /*if (formInput.id) { inputsObject[inputName]['id'] = formInput.id; }
1496
+ if ('classList' in document.documentElement) {
1497
+ if (formInput.classList) { inputsObject[inputName]['class'] = formInput.classList; }
1498
+ }*/
1499
+
1500
+ switch (formInput.nodeName) {
1501
+
1502
+ case 'INPUT':
1503
+ value = this.getInputValue(formInput);
1504
+
1505
+
1506
+ if (value === false) {
1507
+ continue;
1508
+ }
1509
+ break;
1510
+
1511
+ case 'TEXTAREA':
1512
+ value = formInput.value;
1513
+ break;
1514
+
1515
+ case 'SELECT':
1516
+ if (formInput.multiple) {
1517
+ values = [];
1518
+ multiple = true;
1519
+
1520
+ for (var j = 0; j < formInput.length; j++) {
1521
+ if (formInput[j].selected) {
1522
+ values.push(encodeURIComponent(formInput[j].value));
1523
+ }
1524
+ }
1525
+
1526
+ } else {
1527
+ value = (formInput.value);
1528
+ }
1529
+
1530
+ console.log('select val', value);
1531
+ break;
1532
+ }
1533
+
1534
+ _inbound.deBugger('forms', 'Input Value = ' + value);
1535
+
1536
+
1537
+ if (value) {
1538
+ /* inputsObject[inputName].push(multiple ? values.join(',') : encodeURIComponent(value)); */
1539
+ if (!inputsObject[inputName]['value']) {
1540
+ inputsObject[inputName]['value'] = [];
1541
+ }
1542
+ inputsObject[inputName]['value'].push(multiple ? values.join(',') : encodeURIComponent(value));
1543
+ var value = multiple ? values.join(',') : encodeURIComponent(value);
1544
+
1545
+ }
1546
+
1547
+ }
1548
+ }
1549
+ _inbound.deBugger('forms', inputsObject);
1550
+ //console.log('These are the raw values', inputsObject);
1551
+ //_inbound.totalStorage('the_key', inputsObject);
1552
+ //var inputsObject = sortInputs(inputsObject);
1553
+
1554
+ var matchCommon = /name|first name|last name|email|e-mail|phone|website|job title|company|tele|address|comment/;
1555
+
1556
+ for (var input in inputsObject) {
1557
+ //console.log(input);
1558
+
1559
+ var inputValue = inputsObject[input]['value'];
1560
+ var inputMappedField = inputsObject[input]['map'];
1561
+ //if (matchCommon.test(input) !== false) {
1562
+ //console.log(input + " Matches Regex run mapping test");
1563
+ //var map = inputsObject[input];
1564
+ //console.log("MAPP", map);
1565
+ //mappedParams.push( input + '=' + inputsObject[input]['value'].join(',') );
1566
+ //}
1567
+
1568
+ /* Add custom hook here to look for additional values */
1569
+ if (typeof(inputValue) != "undefined" && inputValue != null && inputValue != "") {
1570
+ rawParams.push(input + '=' + inputsObject[input]['value'].join(','));
1571
+ }
1572
+
1573
+ if (typeof(inputMappedField) != "undefined" && inputMappedField != null && inputsObject[input]['value']) {
1574
+ //console.log('Data ATTR', formInput.dataset.mapFormField);
1575
+ mappedParams.push(inputMappedField + "=" + inputsObject[input]['value'].join(','));
1576
+ if (input === 'email') {
1577
+ var email = inputsObject[input]['value'].join(',');
1578
+ //alert(email);
1579
+
1580
+ }
1581
+ }
1582
+ }
1583
+
1584
+ var raw_params = rawParams.join('&');
1585
+ _inbound.deBugger('forms', "Stringified Raw Form PARAMS: " + raw_params);
1586
+
1587
+ var mapped_params = mappedParams.join('&');
1588
+ _inbound.deBugger('forms', "Stringified Mapped PARAMS" + mapped_params);
1589
+
1590
+ /* Check Use form Email or Cookie */
1591
+ var email = utils.getParameterVal('email', mapped_params) || utils.readCookie('wp_lead_email');
1592
+
1593
+ /* Legacy Email map */
1594
+ if (!email) {
1595
+ email = utils.getParameterVal('wpleads_email_address', mapped_params);
1596
+ }
1597
+
1598
+ var fullName = utils.getParameterVal('name', mapped_params);
1599
+ var fName = utils.getParameterVal('first_name', mapped_params);
1600
+ var lName = utils.getParameterVal('last_name', mapped_params);
1601
+
1602
+ // Fallbacks for empty values
1603
+ if (!lName && fName) {
1604
+ var parts = decodeURI(fName).split(" ");
1605
+ if (parts.length > 0) {
1606
+ fName = parts[0];
1607
+ lName = parts[1];
1608
+ }
1609
+ }
1610
+
1611
+ if (fullName && !lName && !fName) {
1612
+ var parts = decodeURI(fullName).split(" ");
1613
+ if (parts.length > 0) {
1614
+ fName = parts[0];
1615
+ lName = parts[1];
1616
+ }
1617
+ }
1618
+
1619
+ fullName = (fName && lName) ? fName + " " + lName : fullName;
1620
+
1621
+ _inbound.deBugger('forms', "fName = " + fName);
1622
+ _inbound.deBugger('forms', "lName = " + lName);
1623
+ _inbound.deBugger('forms', "fullName = " + fullName);
1624
+
1625
+ //return false;
1626
+ var page_views = _inbound.totalStorage('page_views') || {};
1627
+ var urlParams = _inbound.totalStorage('inbound_url_params') || {};
1628
+
1629
+ var inboundDATA = {
1630
+ 'email': email
1631
+ };
1632
+ /* Get Variation ID */
1633
+ if (typeof(landing_path_info) != "undefined") {
1634
+ var variation = landing_path_info.variation;
1635
+ } else if (typeof(cta_path_info) != "undefined") {
1636
+ var variation = cta_path_info.variation;
1637
+ } else {
1638
+ var variation = 0;
1639
+ }
1640
+ var post_type = inbound_settings.post_type || 'page';
1641
+ var page_id = inbound_settings.post_id || 0;
1642
+ // data['wp_lead_uid'] = jQuery.cookie("wp_lead_uid") || null;
1643
+ // data['search_data'] = JSON.stringify(jQuery.totalStorage('inbound_search')) || {};
1644
+ search_data = {};
1645
+ /* Filter here for raw */
1646
+ //alert(mapped_params);
1647
+ /**
1648
+ * Old data model
1649
+ var return_data = {
1650
+ "action": 'inbound_store_lead',
1651
+ "emailTo": data['email'],
1652
+ "first_name": data['first_name'],
1653
+ "last_name": data['last_name'],
1654
+ "phone": data['phone'],
1655
+ "address": data['address'],
1656
+ "company_name": data['company'],
1657
+ "page_views": data['page_views'],
1658
+ "form_input_values": all_form_fields,
1659
+ "Mapped_Data": mapped_form_data,
1660
+ "Search_Data": data['search_data']
1661
+ };
1662
+ */
1663
+ formData = {
1664
+ 'action': 'inbound_lead_store',
1665
+ 'email': email,
1666
+ "full_name": fullName,
1667
+ "first_name": fName,
1668
+ "last_name": lName,
1669
+ 'raw_params': raw_params,
1670
+ 'mapped_params': mapped_params,
1671
+ 'url_params': JSON.stringify(urlParams),
1672
+ 'search_data': 'test',
1673
+ 'page_views': JSON.stringify(page_views),
1674
+ 'post_type': post_type,
1675
+ 'page_id': page_id,
1676
+ 'variation': variation,
1677
+ 'source': utils.readCookie("inbound_referral_site")
1678
+ };
1679
+
1680
+ callback = function(leadID) {
1681
+ /* Action Example */
1682
+
1683
+ _inbound.deBugger('forms', 'Lead Created with ID: ' + leadID);
1684
+ leadID = parseInt(leadID, 10);
1685
+ formData.leadID = leadID;
1686
+ /* Set Lead cookie ID */
1687
+ if (leadID) {
1688
+ utils.createCookie("wp_lead_id", leadID);
1689
+ _inbound.totalStorage.deleteItem('page_views'); // remove pageviews
1690
+ _inbound.totalStorage.deleteItem('tracking_events'); // remove events
1691
+ }
1692
+
1693
+ _inbound.trigger('form_after_submission', formData);
1694
+
1695
+ /* Resume normal form functionality */
1696
+ _inbound.Forms.releaseFormSubmit(form);
1697
+
1698
+ }
1699
+ //_inbound.LeadsAPI.makeRequest(landing_path_info.admin_url);
1700
+ //_inbound.Events.form_before_submission(formData);
1701
+ _inbound.trigger('form_before_submission', formData);
1702
+ //_inbound.trigger('inbound_form_before_submission', formData, true);
1703
+
1704
+ utils.ajaxPost(inbound_settings.admin_url, formData, callback);
1705
+ },
1706
+ rememberInputValues: function(input) {
1707
+ var name = (input.name) ? "inbound_" + input.name : '';
1708
+ var type = (input.type) ? input.type : 'text';
1709
+ if (type === 'submit' || type === 'hidden' || type === 'file' || type === "password") {
1710
+ return false;
1711
+ }
1712
+
1713
+ utils.addListener(input, 'change', function(e) {
1714
+
1715
+ if (e.target.name) {
1716
+ /* Check for input type */
1717
+ if (type !== "checkbox") {
1718
+ var value = e.target.value;
1719
+ } else {
1720
+ var values = [];
1721
+ var checkboxes = document.querySelectorAll('input[name="' + e.target.name + '"]');
1722
+ for (var i = 0; i < checkboxes.length; i++) {
1723
+ var checked = checkboxes[i].checked;
1724
+ if (checked) {
1725
+ values.push(checkboxes[i].value);
1726
+ }
1727
+ value = values.join(',');
1728
+ };
1729
+ }
1730
+ //console.log(e.target.nodeName);
1731
+ //console.log('change ' + e.target.name + " " + encodeURIComponent(value));
1732
+
1733
+ inputData = {
1734
+ name: e.target.name,
1735
+ node: e.target.nodeName.toLowerCase(),
1736
+ type: type,
1737
+ value: value,
1738
+ mapping: e.target.dataset.mapFormField
1739
+ };
1740
+
1741
+ _inbound.trigger('form_input_change', inputData);
1742
+ /* Set Field Input Cookies */
1743
+ utils.createCookie("inbound_" + e.target.name, encodeURIComponent(value));
1744
+ // _inbound.totalStorage('the_key', FormStore);
1745
+ /* Push to 'unsubmitted form object' */
1746
+ }
1747
+
1748
+ });
1749
+ },
1750
+ fillInputValues: function(input) {
1751
+ var name = (input.name) ? "inbound_" + input.name : '';
1752
+ var type = (input.type) ? input.type : 'text';
1753
+ if (type === 'submit' || type === 'hidden' || type === 'file' || type === "password") {
1754
+ return false;
1755
+ }
1756
+ if (utils.readCookie(name) && name != 'comment') {
1757
+
1758
+ value = decodeURIComponent(utils.readCookie(name));
1759
+ if (type === 'checkbox' || type === 'radio') {
1760
+ var checkbox_vals = value.split(',');
1761
+ for (var i = 0; i < checkbox_vals.length; i++) {
1762
+ if (input.value.indexOf(checkbox_vals[i]) > -1) {
1763
+ input.checked = true;
1764
+ }
1765
+ }
1766
+ } else {
1767
+ if (value !== "undefined") {
1768
+ input.value = value;
1769
+ }
1770
+ }
1771
+ }
1772
+ },
1773
+ /* Maps data attributes to fields on page load */
1774
+ mapField: function(input) {
1775
+
1776
+ var input_id = input.id || false;
1777
+ var input_name = input.name || false;
1778
+
1779
+ /* Loop through all match possiblities */
1780
+ for (i = 0; i < FieldMapArray.length; i++) {
1781
+ //for (var i = FieldMapArray.length - 1; i >= 0; i--) {
1782
+ var found = false;
1783
+ var match = FieldMapArray[i];
1784
+ var lookingFor = utils.trim(match);
1785
+ var nice_name = lookingFor.replace(/ /g, '_');
1786
+
1787
+
1788
+ //console.log("NICE NAME", nice_name);
1789
+ //console.log('looking for match on ' + lookingFor);
1790
+ //_inbound.deBugger('forms', 'looking for match on ' + lookingFor + " nice_name= " + nice_name);
1791
+
1792
+ // Check if input has an attached lable using for= tag
1793
+ //var $laxbel = $("label[for='" + $element.attr('id') + "']").text();
1794
+ //var labxel = 'label[for="' + input_id + '"]';
1795
+
1796
+ /* look for name attribute match */
1797
+ if (input_name && input_name.toLowerCase().indexOf(lookingFor) > -1) {
1798
+
1799
+ found = true;
1800
+ _inbound.deBugger('forms', 'Found matching name attribute for -> ' + lookingFor);
1801
+
1802
+ /* look for id match */
1803
+ } else if (input_id && input_id.toLowerCase().indexOf(lookingFor) > -1) {
1804
+
1805
+ found = true;
1806
+ _inbound.deBugger('forms', 'Found matching ID attribute for ->' + lookingFor);
1807
+
1808
+ /* Check siblings for label */
1809
+ } else if (label = this.siblingsIsLabel(input)) {
1810
+
1811
+ //var label = (label.length > 1 ? label[0] : label);
1812
+ //console.log('label', label);
1813
+ if (label[0].innerText.toLowerCase().indexOf(lookingFor) > -1) {
1814
+
1815
+ found = true;
1816
+ _inbound.deBugger('forms', 'Found matching sibling label for -> ' + lookingFor);
1817
+
1818
+ }
1819
+ /* Check closest li for label */
1820
+ } else if (labelText = this.CheckParentForLabel(input)) {
1821
+
1822
+ //console.log(labelText)
1823
+
1824
+ if (labelText.toLowerCase().indexOf(lookingFor) > -1) {
1825
+ found = true;
1826
+ _inbound.deBugger('forms', 'Found Matching parent label for -> ' + lookingFor);
1827
+
1828
+ }
1829
+
1830
+ } else {
1831
+ /* no match found */
1832
+ //_inbound.deBugger('forms', 'NO Match on ' + lookingFor + " in " + input_name);
1833
+ no_match.push(lookingFor);
1834
+
1835
+ }
1836
+
1837
+ /* Map the field */
1838
+ if (found) {
1839
+ this.addDataAttr(input, nice_name);
1840
+ this.removeArrayItem(FieldMapArray, lookingFor);
1841
+ i--; //decrement count
1842
+ }
1843
+
1844
+ }
1845
+
1846
+ return inbound_data;
1847
+
1848
+ },
1849
+ /* Get correct input values */
1850
+ getInputValue: function(input) {
1851
+ var value = false;
1852
+
1853
+ switch (input.type) {
1854
+ case 'radio':
1855
+ case 'checkbox':
1856
+ if (input.checked) {
1857
+ value = input.value;
1858
+ //console.log("CHECKBOX VAL", value)
1859
+ }
1860
+ break;
1861
+
1862
+ case 'text':
1863
+ case 'hidden':
1864
+ default:
1865
+ value = input.value;
1866
+ break;
1867
+
1868
+ }
1869
+
1870
+ return value;
1871
+ },
1872
+ /* Add data-map-form-field attr to input */
1873
+ addDataAttr: function(formInput, match) {
1874
+
1875
+ var getAllInputs = document.getElementsByName(formInput.name);
1876
+ for (var i = getAllInputs.length - 1; i >= 0; i--) {
1877
+ if (!formInput.dataset.mapFormField) {
1878
+ getAllInputs[i].dataset.mapFormField = match;
1879
+ }
1880
+ };
1881
+ },
1882
+ /* Optimize FieldMapArray array for fewer lookups */
1883
+ removeArrayItem: function(array, item) {
1884
+ if (array.indexOf) {
1885
+ index = array.indexOf(item);
1886
+ } else {
1887
+ for (index = array.length - 1; index >= 0; --index) {
1888
+ if (array[index] === item) {
1889
+ break;
1890
+ }
1891
+ }
1892
+ }
1893
+ if (index >= 0) {
1894
+ array.splice(index, 1);
1895
+ }
1896
+ //_inbound.deBugger('forms', 'removed ' + item + " from array");
1897
+ //console.log('removed ' + item + " from array");
1898
+ return;
1899
+ },
1900
+ /* Look for siblings that are form labels */
1901
+ siblingsIsLabel: function(input) {
1902
+ var siblings = this.getSiblings(input);
1903
+ var labels = [];
1904
+ for (var i = siblings.length - 1; i >= 0; i--) {
1905
+ if (siblings[i].nodeName.toLowerCase() === 'label') {
1906
+ labels.push(siblings[i]);
1907
+ }
1908
+ };
1909
+ /* if only 1 label */
1910
+ if (labels.length > 0 && labels.length < 2) {
1911
+ return labels;
1912
+ }
1913
+
1914
+ return false;
1915
+ },
1916
+ getChildren: function(n, skipMe) {
1917
+ var r = [];
1918
+ var elem = null;
1919
+ for (; n; n = n.nextSibling)
1920
+ if (n.nodeType == 1 && n != skipMe)
1921
+ r.push(n);
1922
+ return r;
1923
+ },
1924
+ getSiblings: function(n) {
1925
+ return this.getChildren(n.parentNode.firstChild, n);
1926
+ },
1927
+ /* Check parent elements inside form for labels */
1928
+ CheckParentForLabel: function(element) {
1929
+ if (element.nodeName === 'FORM') {
1930
+ return null;
1931
+ }
1932
+ do {
1933
+ var labels = element.getElementsByTagName("label");
1934
+ if (labels.length > 0 && labels.length < 2) {
1935
+ return element.getElementsByTagName("label")[0].innerText;
1936
+ }
1937
+
1938
+ } while (element = element.parentNode);
1939
+
1940
+ return null;
1941
+ },
1942
+ /* Validate Common Email addresses */
1943
+ mailCheck: function() {
1944
+ var email_input = document.querySelector('.inbound-email');
1945
+ if (email_input) {
1946
+ //
1947
+ utils.addListener(email_input, 'blur', this.mailCheck);
1948
+
1949
+ Mailcheck.run({
1950
+ email: document.querySelector('.inbound-email').value,
1951
+ suggested: function(suggestion) {
1952
+ // callback code
1953
+
1954
+ var suggest = document.querySelector('.email_suggestion');
1955
+ if (suggest) {
1956
+ utils.removeElement(suggest);
1957
+ }
1958
+ var el = document.createElement("span");
1959
+ el.innerHTML = "<span class=\"email_suggestion\">Did you mean <b><i id='email_correction' style='cursor: pointer;' title=\"click to update\">" + suggestion.full + "</b></i>?</span>";
1960
+ email_input.parentNode.insertBefore(el, email_input.nextSibling);
1961
+ var update = document.getElementById('email_correction');
1962
+ utils.addListener(update, 'click', function() {
1963
+ email_input.value = update.innerHTML;
1964
+ update.parentNode.parentNode.innerHTML = "Fixed!";
1965
+ });
1966
+ },
1967
+ empty: function() {
1968
+ //$(".email_suggestion").html("No Suggestions :(");
1969
+ }
1970
+ });
1971
+ }
1972
+ }
1973
 
1974
+ };
1975
+ /* Mailcheck */
1976
+ if (typeof Mailcheck === "undefined") {
1977
+ var Mailcheck = {
1978
+ domainThreshold: 1,
1979
+ topLevelThreshold: 3,
1980
+
1981
+ defaultDomains: ["yahoo.com", "google.com", "hotmail.com", "gmail.com", "me.com", "aol.com", "mac.com",
1982
+ "live.com", "comcast.net", "googlemail.com", "msn.com", "hotmail.co.uk", "yahoo.co.uk",
1983
+ "facebook.com", "verizon.net", "sbcglobal.net", "att.net", "gmx.com", "mail.com", "outlook.com", "icloud.com"
1984
+ ],
1985
+
1986
+ defaultTopLevelDomains: ["co.jp", "co.uk", "com", "net", "org", "info", "edu", "gov", "mil", "ca"],
1987
+
1988
+ run: function(opts) {
1989
+ opts.domains = opts.domains || Mailcheck.defaultDomains;
1990
+ opts.topLevelDomains = opts.topLevelDomains || Mailcheck.defaultTopLevelDomains;
1991
+ opts.distanceFunction = opts.distanceFunction || Mailcheck.sift3Distance;
1992
+
1993
+ var defaultCallback = function(result) {
1994
+ return result
1995
+ };
1996
+ var suggestedCallback = opts.suggested || defaultCallback;
1997
+ var emptyCallback = opts.empty || defaultCallback;
1998
 
1999
+ var result = Mailcheck.suggest(Mailcheck.encodeEmail(opts.email), opts.domains, opts.topLevelDomains, opts.distanceFunction);
2000
 
2001
+ return result ? suggestedCallback(result) : emptyCallback()
2002
+ },
 
 
 
 
 
2003
 
2004
+ suggest: function(email, domains, topLevelDomains, distanceFunction) {
2005
+ email = email.toLowerCase();
 
 
 
 
 
 
 
 
 
2006
 
2007
+ var emailParts = this.splitEmail(email);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2008
 
2009
+ var closestDomain = this.findClosestDomain(emailParts.domain, domains, distanceFunction, this.domainThreshold);
 
 
 
2010
 
2011
+ if (closestDomain) {
2012
+ if (closestDomain != emailParts.domain) {
2013
+ // The email address closely matches one of the supplied domains; return a suggestion
2014
+ return {
2015
+ address: emailParts.address,
2016
+ domain: closestDomain,
2017
+ full: emailParts.address + "@" + closestDomain
2018
+ };
2019
+ }
2020
+ } else {
2021
+ // The email address does not closely match one of the supplied domains
2022
+ var closestTopLevelDomain = this.findClosestDomain(emailParts.topLevelDomain, topLevelDomains, distanceFunction, this.topLevelThreshold);
2023
+ if (emailParts.domain && closestTopLevelDomain && closestTopLevelDomain != emailParts.topLevelDomain) {
2024
+ // The email address may have a mispelled top-level domain; return a suggestion
2025
+ var domain = emailParts.domain;
2026
+ closestDomain = domain.substring(0, domain.lastIndexOf(emailParts.topLevelDomain)) + closestTopLevelDomain;
2027
+ return {
2028
+ address: emailParts.address,
2029
+ domain: closestDomain,
2030
+ full: emailParts.address + "@" + closestDomain
2031
+ };
2032
+ }
2033
+ }
2034
+ /* The email address exactly matches one of the supplied domains, does not closely
2035
+ * match any domain and does not appear to simply have a mispelled top-level domain,
2036
+ * or is an invalid email address; do not return a suggestion.
2037
+ */
2038
+ return false;
2039
+ },
2040
+
2041
+ findClosestDomain: function(domain, domains, distanceFunction, threshold) {
2042
+ threshold = threshold || this.topLevelThreshold;
2043
+ var dist;
2044
+ var minDist = 99;
2045
+ var closestDomain = null;
2046
+
2047
+ if (!domain || !domains) {
2048
+ return false;
2049
+ }
2050
+ if (!distanceFunction) {
2051
+ distanceFunction = this.sift3Distance;
2052
+ }
2053
 
2054
+ for (var i = 0; i < domains.length; i++) {
2055
+ if (domain === domains[i]) {
2056
+ return domain;
2057
+ }
2058
+ dist = distanceFunction(domain, domains[i]);
2059
+ if (dist < minDist) {
2060
+ minDist = dist;
2061
+ closestDomain = domains[i];
2062
+ }
2063
+ }
2064
 
2065
+ if (minDist <= threshold && closestDomain !== null) {
2066
+ return closestDomain;
2067
+ } else {
2068
+ return false;
2069
+ }
2070
+ },
2071
+
2072
+ sift3Distance: function(s1, s2) {
2073
+ // sift3: http://siderite.blogspot.com/2007/04/super-fast-and-accurate-string-distance.html
2074
+ if (s1 == null || s1.length === 0) {
2075
+ if (s2 == null || s2.length === 0) {
2076
+ return 0;
2077
+ } else {
2078
+ return s2.length;
2079
+ }
2080
+ }
2081
 
2082
+ if (s2 == null || s2.length === 0) {
2083
+ return s1.length;
2084
+ }
 
 
2085
 
2086
+ var c = 0;
2087
+ var offset1 = 0;
2088
+ var offset2 = 0;
2089
+ var lcs = 0;
2090
+ var maxOffset = 5;
2091
+
2092
+ while ((c + offset1 < s1.length) && (c + offset2 < s2.length)) {
2093
+ if (s1.charAt(c + offset1) == s2.charAt(c + offset2)) {
2094
+ lcs++;
2095
+ } else {
2096
+ offset1 = 0;
2097
+ offset2 = 0;
2098
+ for (var i = 0; i < maxOffset; i++) {
2099
+ if ((c + i < s1.length) && (s1.charAt(c + i) == s2.charAt(c))) {
2100
+ offset1 = i;
2101
+ break;
2102
  }
2103
+ if ((c + i < s2.length) && (s1.charAt(c) == s2.charAt(c + i))) {
2104
+ offset2 = i;
2105
+ break;
2106
+ }
2107
+ }
2108
+ }
2109
+ c++;
2110
+ }
2111
+ return (s1.length + s2.length) / 2 - lcs;
2112
+ },
2113
 
2114
+ splitEmail: function(email) {
2115
+ var parts = email.trim().split("@");
 
2116
 
2117
+ if (parts.length < 2) {
2118
+ return false;
2119
+ }
2120
 
2121
+ for (var i = 0; i < parts.length; i++) {
2122
+ if (parts[i] === "") {
2123
+ return false;
2124
  }
2125
+ }
2126
 
2127
+ var domain = parts.pop();
2128
+ var domainParts = domain.split(".");
2129
+ var tld = "";
2130
+
2131
+ if (domainParts.length == 0) {
2132
+ // The address does not have a top-level domain
2133
+ return false;
2134
+ } else if (domainParts.length == 1) {
2135
+ // The address has only a top-level domain (valid under RFC)
2136
+ tld = domainParts[0];
2137
+ } else {
2138
+ // The address has a domain and a top-level domain
2139
+ for (var i = 1; i < domainParts.length; i++) {
2140
+ tld += domainParts[i] + ".";
2141
+ }
2142
+ if (domainParts.length >= 2) {
2143
+ tld = tld.substring(0, tld.length - 1);
2144
+ }
2145
  }
2146
 
2147
+ return {
2148
+ topLevelDomain: tld,
2149
+ domain: domain,
2150
+ address: parts.join("@")
2151
+ }
2152
+ },
2153
+
2154
+ // Encode the email address to prevent XSS but leave in valid
2155
+ // characters, following this official spec:
2156
+ // http://en.wikipedia.org/wiki/Email_address#Syntax
2157
+ encodeEmail: function(email) {
2158
+ var result = encodeURI(email);
2159
+ result = result.replace("%20", " ").replace("%25", "%").replace("%5E", "^")
2160
+ .replace("%60", "`").replace("%7B", "{").replace("%7C", "|")
2161
+ .replace("%7D", "}");
2162
+ return result;
2163
  }
2164
+ }
2165
+ } // End Mailcheck
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2166
 
 
 
 
 
2167
 
2168
+ return _inbound;
 
2169
 
2170
+ })(_inbound || {});
2171
+ /**
2172
+ * # Analytics Events
2173
+ *
2174
+ * Events are triggered throughout the visitors journey through the site. See more on [Inbound Now][in]
2175
+ *
2176
+ * @author David Wells <david@inboundnow.com>
2177
+ * @version 0.0.1
2178
+ *
2179
+ * [in]: http://www.inboundnow.com/
2180
+ */
2181
 
2182
+ // Add object to _inbound
2183
+ var _inboundEvents = (function(_inbound) {
2184
 
 
2185
 
2186
+ _inbound.trigger = function(trigger, data) {
2187
+ _inbound.Events[trigger](data);
2188
 
2189
+ };
2190
+
2191
+ /*!
2192
+ *
2193
+ * Private Function that Fires & Emits Events
2194
+ *
2195
+ * There are three options for firing events and they trigger in this order:
2196
+ *
2197
+ * 1. Vanilla JS dispatch event
2198
+ * 2. `_inbound.add_action('namespace', callback, priority)`
2199
+ * 3. jQuery Trigger `jQuery.trigger('namespace', callback);`
2200
+ *
2201
+ * The Event `data` can be filtered before events are triggered
2202
+ * with filters. Example: filter_ + "namespace"
2203
+ *
2204
+ * ```js
2205
+ * // Filter Form Data before submissionsz
2206
+ * _inbound.add_filter( 'filter_form_before_submission', event_filter_data_example, 10);
2207
+ *
2208
+ * function event_filter_data_example(data) {
2209
+ * var data = data || {};
2210
+ * // Do something with data
2211
+ * return data;
2212
+ * }
2213
+ * ```
2214
+ *
2215
+ * @param {string} eventName Name of the event
2216
+ * @param {object} data Data passed to external functions/triggers
2217
+ * @param {object} options Options for configuring events
2218
+ * @return {null} Nothing returned
2219
+ */
2220
+ function fireEvent(eventName, data, options) {
2221
+ var data = data || {};
2222
+ options = options || {};
2223
+ //alert('ran + ' + eventName);
2224
+ //console.log(eventName);
2225
+ //console.log(data);
2226
+ /*! defaults for JS dispatch event */
2227
+ options.bubbles = options.bubbles || true,
2228
+ options.cancelable = options.cancelable || true;
2229
+
2230
+ /*! Customize Data via filter_ + "namespace" */
2231
+ data = _inbound.apply_filters('filter_' + eventName, data);
2232
+
2233
+ var TriggerEvent = new CustomEvent(eventName, {
2234
+ detail: data,
2235
+ bubbles: options.bubbles,
2236
+ cancelable: options.cancelable
2237
+ });
2238
+
2239
+ // console.log('Action:' + eventName + " ran on ->", data);
2240
+
2241
+ /*! 1. Trigger Pure Javascript Event See: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events for example on creating events */
2242
+ window.dispatchEvent(TriggerEvent);
2243
+ /*! 2. Trigger _inbound action */
2244
+ _inbound.do_action(eventName, data);
2245
+ /*! 3. jQuery trigger */
2246
+ triggerJQueryEvent(eventName, data);
2247
+
2248
+ }
2249
+
2250
+ function triggerJQueryEvent(eventName, data) {
2251
  if (window.jQuery) {
2252
  var data = data || {};
2253
  jQuery(document).trigger(eventName, data);
 
 
 
 
 
 
 
 
 
 
2254
  }
2255
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2256
 
2257
+ var universalGA,
2258
+ classicGA,
2259
+ googleTagManager;
2260
+
2261
+ _inbound.Events = {
2262
+
2263
+ /**
2264
+ * # Event Usage
2265
+ *
2266
+ * Events are triggered throughout the visitors path through the site.
2267
+ * You can hook into these custom actions and filters much like WordPress Core
2268
+ *
2269
+ * See below for examples
2270
+ */
2271
+
2272
+ /**
2273
+ * Adding Custom Actions
2274
+ * ------------------
2275
+ * You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
2276
+ *
2277
+ * `
2278
+ * _inbound.add_action( 'action_name', callback, priority );
2279
+ * `
2280
+ *
2281
+ * ```js
2282
+ * // example:
2283
+ *
2284
+ * // Add custom function to `page_visit` event
2285
+ * _inbound.add_action( 'page_visit', callback, 10 );
2286
+ *
2287
+ * // add custom callback to trigger when `page_visit` fires
2288
+ * function callback(pageData){
2289
+ * var pageData = pageData || {};
2290
+ * // run callback on 'page_visit' trigger
2291
+ * alert(pageData.title);
2292
+ * }
2293
+ * ```
2294
+ *
2295
+ * @param {string} action_name Name of the event trigger
2296
+ * @param {function} callback function to trigger when event happens
2297
+ * @param {int} priority Order to trigger the event in
2298
+ *
2299
+ */
2300
+
2301
+ /**
2302
+ * Removing Custom Actions
2303
+ * ------------------
2304
+ * You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
2305
+ *
2306
+ * `
2307
+ * _inbound.remove_action( 'action_name');
2308
+ * `
2309
+ *
2310
+ * ```js
2311
+ * // example:
2312
+ *
2313
+ * _inbound.remove_action( 'page_visit');
2314
+ * // all 'page_visit' actions have been deregistered
2315
+ * ```
2316
+ *
2317
+ * @param {string} action_name Name of the event trigger
2318
+ *
2319
+ */
2320
+
2321
+ /**
2322
+ * # Event List
2323
+ *
2324
+ * Events are triggered throughout the visitors journey through the site
2325
+ */
2326
+
2327
+ /**
2328
+ * Triggers when analyics has finished loading
2329
+ */
2330
+ analytics_ready: function() {
2331
+ var ops = {
2332
+ 'opt1': true
2333
+ };
2334
+ var data = {
2335
+ 'data': 'xyxy'
2336
+ };
2337
+ fireEvent('analytics_ready', data, ops);
2338
+ },
2339
+ /**
2340
+ * Triggers when the browser url params are parsed. You can perform custom actions
2341
+ * if specific url params exist.
2342
+ *
2343
+ * ```js
2344
+ * // Usage:
2345
+ *
2346
+ * // Add function to 'url_parameters' event
2347
+ * _inbound.add_action( 'url_parameters', url_parameters_func_example, 10);
2348
+ *
2349
+ * function url_parameters_func_example(urlParams) {
2350
+ * var urlParams = urlParams || {};
2351
+ * for( var param in urlParams ) {
2352
+ * var key = param;
2353
+ * var value = urlParams[param];
2354
+ * }
2355
+ * // All URL Params
2356
+ * alert(JSON.stringify(urlParams));
2357
+ *
2358
+ * // Check if URL parameter `utm_source` exists and matches value
2359
+ * if(urlParams.utm_source === "twitter") {
2360
+ * alert('This person is from twitter!');
2361
+ * }
2362
+ * }
2363
+ * ```
2364
+ */
2365
+ url_parameters: function(data) {
2366
+ fireEvent('url_parameters', data);
2367
+ },
2368
+ /**
2369
+ * Triggers when session starts
2370
+ *
2371
+ * ```js
2372
+ * // Usage:
2373
+ *
2374
+ * // Add function to 'session_start' event
2375
+ * _inbound.add_action( 'session_start', session_start_func_example, 10);
2376
+ *
2377
+ * function session_start_func_example(data) {
2378
+ * var data = data || {};
2379
+ * // session start. Do something for new visitor
2380
+ * }
2381
+ * ```
2382
+ */
2383
+ session_start: function() {
2384
+ console.log('');
2385
+ fireEvent('session_start');
2386
+ },
2387
+ /**
2388
+ * Triggers when visitor session goes idle for more than 30 minutes.
2389
+ *
2390
+ * ```js
2391
+ * // Usage:
2392
+ *
2393
+ * // Add function to 'session_end' event
2394
+ * _inbound.add_action( 'session_end', session_end_func_example, 10);
2395
+ *
2396
+ * function session_end_func_example(data) {
2397
+ * var data = data || {};
2398
+ * // Do something when session ends
2399
+ * alert("Hey! It's been 30 minutes... where did you go?");
2400
+ * }
2401
+ * ```
2402
+ */
2403
+ session_end: function(clockTime) {
2404
+ fireEvent('session_end', clockTime);
2405
+ console.log('Session End');
2406
+ },
2407
+ /**
2408
+ * Triggers if active session is detected
2409
+ *
2410
+ * ```js
2411
+ * // Usage:
2412
+ *
2413
+ * // Add function to 'session_active' event
2414
+ * _inbound.add_action( 'session_active', session_active_func_example, 10);
2415
+ *
2416
+ * function session_active_func_example(data) {
2417
+ * var data = data || {};
2418
+ * // session active
2419
+ * }
2420
+ * ```
2421
+ */
2422
+ session_active: function() {
2423
+ fireEvent('session_active');
2424
+ },
2425
+ /**
2426
+ * Triggers when visitor session goes idle. Idling occurs after 60 seconds of
2427
+ * inactivity or when the visitor switches browser tabs
2428
+ *
2429
+ * ```js
2430
+ * // Usage:
2431
+ *
2432
+ * // Add function to 'session_idle' event
2433
+ * _inbound.add_action( 'session_idle', session_idle_func_example, 10);
2434
+ *
2435
+ * function session_idle_func_example(data) {
2436
+ * var data = data || {};
2437
+ * // Do something when session idles
2438
+ * alert('Here is a special offer for you!');
2439
+ * }
2440
+ * ```
2441
+ */
2442
+ session_idle: function(clockTime) {
2443
+ fireEvent('session_idle', clockTime);
2444
+ },
2445
+ /**
2446
+ * Triggers when session is already active and gets resumed
2447
+ *
2448
+ * ```js
2449
+ * // Usage:
2450
+ *
2451
+ * // Add function to 'session_resume' event
2452
+ * _inbound.add_action( 'session_resume', session_resume_func_example, 10);
2453
+ *
2454
+ * function session_resume_func_example(data) {
2455
+ * var data = data || {};
2456
+ * // Session exists and is being resumed
2457
+ * }
2458
+ * ```
2459
+ */
2460
+ session_resume: function() {
2461
+ fireEvent('session_resume');
2462
+ },
2463
+ /**
2464
+ * Session emitter. Runs every 10 seconds. This is a useful function for
2465
+ * pinging third party services
2466
+ *
2467
+ * ```js
2468
+ * // Usage:
2469
+ *
2470
+ * // Add session_heartbeat_func_example function to 'session_heartbeat' event
2471
+ * _inbound.add_action( 'session_heartbeat', session_heartbeat_func_example, 10);
2472
+ *
2473
+ * function session_heartbeat_func_example(data) {
2474
+ * var data = data || {};
2475
+ * // Do something with every 10 seconds
2476
+ * }
2477
+ * ```
2478
+ */
2479
+ session_heartbeat: function(clockTime) {
2480
+ var data = {
2481
+ 'clock': clockTime,
2482
+ 'leadData': InboundLeadData
2483
+ };
2484
+ fireEvent('session_heartbeat', data);
2485
+ },
2486
+ /**
2487
+ * Triggers Every Page View
2488
+ *
2489
+ * ```js
2490
+ * // Usage:
2491
+ *
2492
+ * // Add function to 'page_visit' event
2493
+ * _inbound.add_action( 'page_visit', page_visit_func_example, 10);
2494
+ *
2495
+ * function session_idle_func_example(pageData) {
2496
+ * var pageData = pageData || {};
2497
+ * if( pageData.view_count > 8 ){
2498
+ * alert('Wow you have been to this page more than 8 times.');
2499
+ * }
2500
+ * }
2501
+ * ```
2502
+ */
2503
+ page_visit: function(pageData) {
2504
+ fireEvent('page_view', pageData);
2505
+ },
2506
+ /**
2507
+ * Triggers If the visitor has never seen the page before
2508
+ *
2509
+ * ```js
2510
+ * // Usage:
2511
+ *
2512
+ * // Add function to 'page_first_visit' event
2513
+ * _inbound.add_action( 'page_first_visit', page_first_visit_func_example, 10);
2514
+ *
2515
+ * function page_first_visit_func_example(pageData) {
2516
+ * var pageData = pageData || {};
2517
+ * alert('Welcome to this page! Its the first time you have seen it')
2518
+ * }
2519
+ * ```
2520
+ */
2521
+ page_first_visit: function(pageData) {
2522
+ fireEvent('page_first_visit');
2523
+ _inbound.deBugger('pages', 'First Ever Page View of this Page');
2524
+ },
2525
+ /**
2526
+ * Triggers If the visitor has seen the page before
2527
+ *
2528
+ * ```js
2529
+ * // Usage:
2530
+ *
2531
+ * // Add function to 'page_revisit' event
2532
+ * _inbound.add_action( 'page_revisit', page_revisit_func_example, 10);
2533
+ *
2534
+ * function page_revisit_func_example(pageData) {
2535
+ * var pageData = pageData || {};
2536
+ * alert('Welcome back to this page!');
2537
+ * // Show visitor special content/offer
2538
+ * }
2539
+ * ```
2540
+ */
2541
+ page_revisit: function(pageData) {
2542
+
2543
+ fireEvent('page_revisit', pageData);
2544
+
2545
+ var logger = function() {
2546
+ console.log('pageData', pageData);
2547
+ console.log('Page Revisit viewed ' + pageData + " times");
2548
+ }
2549
+ _inbound.deBugger('pages', status, logger);
2550
+ },
2551
+
2552
+ /**
2553
+ * `tab_hidden` is triggered when the visitor switches browser tabs
2554
+ *
2555
+ * ```js
2556
+ * // Usage:
2557
+ *
2558
+ * // Adding the callback
2559
+ * function tab_hidden_function( data ) {
2560
+ * alert('The Tab is Hidden');
2561
+ * };
2562
+ *
2563
+ * // Hook the function up the the `tab_hidden` event
2564
+ * _inbound.add_action( 'tab_hidden', tab_hidden_function, 10 );
2565
+ * ```
2566
+ */
2567
+ tab_hidden: function(data) {
2568
+ _inbound.deBugger('pages', 'Tab Hidden');
2569
+ fireEvent('tab_hidden');
2570
+ },
2571
+ /**
2572
+ * `tab_visible` is triggered when the visitor switches back to the sites tab
2573
+ *
2574
+ * ```js
2575
+ * // Usage:
2576
+ *
2577
+ * // Adding the callback
2578
+ * function tab_visible_function( data ) {
2579
+ * alert('Welcome back to this tab!');
2580
+ * // trigger popup or offer special discount etc.
2581
+ * };
2582
+ *
2583
+ * // Hook the function up the the `tab_visible` event
2584
+ * _inbound.add_action( 'tab_visible', tab_visible_function, 10 );
2585
+ * ```
2586
+ */
2587
+ tab_visible: function(data) {
2588
+ _inbound.deBugger('pages', 'Tab Visible');
2589
+ fireEvent('tab_visible');
2590
+ },
2591
+ /**
2592
+ * `tab_mouseout` is triggered when the visitor mouses out of the browser window.
2593
+ * This is especially useful for exit popups
2594
+ *
2595
+ * ```js
2596
+ * // Usage:
2597
+ *
2598
+ * // Adding the callback
2599
+ * function tab_mouseout_function( data ) {
2600
+ * alert("Wait don't Go");
2601
+ * // trigger popup or offer special discount etc.
2602
+ * };
2603
+ *
2604
+ * // Hook the function up the the `tab_mouseout` event
2605
+ * _inbound.add_action( 'tab_mouseout', tab_mouseout_function, 10 );
2606
+ * ```
2607
+ */
2608
+ tab_mouseout: function(data) {
2609
+ _inbound.deBugger('pages', 'Tab Mouseout');
2610
+ fireEvent('tab_mouseout');
2611
+ },
2612
+ /**
2613
+ * `form_input_change` is triggered when tracked form inputs change
2614
+ * You can use this to add additional validation or set conditional triggers
2615
+ *
2616
+ * ```js
2617
+ * // Usage:
2618
+ *
2619
+ * ```
2620
+ */
2621
+ form_input_change: function(inputData) {
2622
+ var logger = function() {
2623
+ console.log(inputData);
2624
+ //console.log('Page Revisit viewed ' + pageData + " times");
2625
+ }
2626
+ _inbound.deBugger('forms', 'inputData change. Data=', logger);
2627
+ fireEvent('form_input_change', inputData);
2628
+ },
2629
+ /**
2630
+ * `form_before_submission` is triggered before the form is submitted to the server.
2631
+ * You can filter the data here or send it to third party services
2632
+ *
2633
+ * ```js
2634
+ * // Usage:
2635
+ *
2636
+ * // Adding the callback
2637
+ * function form_before_submission_function( data ) {
2638
+ * var data = data || {};
2639
+ * // filter form data
2640
+ * };
2641
+ *
2642
+ * // Hook the function up the the `form_before_submission` event
2643
+ * _inbound.add_action( 'form_before_submission', form_before_submission_function, 10 );
2644
+ * ```
2645
+ */
2646
+ form_before_submission: function(formData) {
2647
+ fireEvent('form_before_submission', formData);
2648
+ },
2649
+ /**
2650
+ * `form_after_submission` is triggered after the form is submitted to the server.
2651
+ * You can filter the data here or send it to third party services
2652
+ *
2653
+ * ```js
2654
+ * // Usage:
2655
+ *
2656
+ * // Adding the callback
2657
+ * function form_after_submission_function( data ) {
2658
+ * var data = data || {};
2659
+ * // filter form data
2660
+ * };
2661
+ *
2662
+ * // Hook the function up the the `form_after_submission` event
2663
+ * _inbound.add_action( 'form_after_submission', form_after_submission_function, 10 );
2664
+ * ```
2665
+ */
2666
+ form_after_submission: function(formData) {
2667
+
2668
+ fireEvent('form_after_submission', formData);
2669
+
2670
+ },
2671
+ /*! Scrol depth https://github.com/robflaherty/jquery-scrolldepth/blob/master/jquery.scrolldepth.js */
2672
+
2673
+ analyticsError: function(MLHttpRequest, textStatus, errorThrown) {
2674
+ var error = new CustomEvent("inbound_analytics_error", {
2675
+ detail: {
2676
+ MLHttpRequest: MLHttpRequest,
2677
+ textStatus: textStatus,
2678
+ errorThrown: errorThrown
2679
+ }
2680
+ });
2681
+ window.dispatchEvent(error);
2682
+ console.log('Page Save Error');
2683
+ },
2684
 
2685
+ };
2686
 
2687
+ return _inbound;
 
 
2688
 
2689
+ })(_inbound || {});
2690
+ /* LocalStorage Component */
2691
+ var InboundTotalStorage = (function (_inbound){
2692
 
2693
+ var supported, ls, mod = '_inbound';
2694
  if ('localStorage' in window){
2695
  try {
2696
  ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
2708
  }
2709
 
2710
  /* Make the methods public */
2711
+ _inbound.totalStorage = function(key, value, options){
2712
+ return _inbound.totalStorage.impl.init(key, value);
2713
  };
2714
 
2715
+ _inbound.totalStorage.setItem = function(key, value){
2716
+ return _inbound.totalStorage.impl.setItem(key, value);
2717
  };
2718
 
2719
+ _inbound.totalStorage.getItem = function(key){
2720
+ return _inbound.totalStorage.impl.getItem(key);
2721
  };
2722
 
2723
+ _inbound.totalStorage.getAll = function(){
2724
+ return _inbound.totalStorage.impl.getAll();
2725
  };
2726
 
2727
+ _inbound.totalStorage.deleteItem = function(key){
2728
+ return _inbound.totalStorage.impl.deleteItem(key);
2729
  };
2730
 
 
2731
 
2732
+ _inbound.totalStorage.impl = {
2733
 
2734
  init: function(key, value){
2735
  if (typeof value != 'undefined') {
2742
  setItem: function(key, value){
2743
  if (!supported){
2744
  try {
2745
+ _inbound.Utils.createCookie(key, value);
2746
  return value;
2747
  } catch(e){
2748
  console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie');
2755
  getItem: function(key){
2756
  if (!supported){
2757
  try {
2758
+ return this.parseResult(_inbound.Utils.readCookie(key));
2759
  } catch(e){
2760
  return null;
2761
  }
2766
  deleteItem: function(key){
2767
  if (!supported){
2768
  try {
2769
+ _inbound.Utils.eraseCookie(key, null);
2770
  return true;
2771
  } catch(e){
2772
  return false;
2783
  for (var i = 0; i<pairs.length; i++){
2784
  var pair = pairs[i].split('=');
2785
  var key = pair[0];
2786
+ items.push({key:key, value:this.parseResult(_inbound.Utils.readCookie(key))});
2787
  }
2788
  } catch(e){
2789
  return null;
2819
  return ret;
2820
  }
2821
  };
2822
+ })(_inbound || {});
2823
  /**
2824
  * Leads API functions
2825
+ * @param Object _inbound - Main JS object
2826
  * @return Object - include event triggers
2827
  */
2828
+ var _inboundLeadsAPI = (function(_inbound) {
2829
  var httpRequest;
2830
+ _inbound.LeadsAPI = {
2831
+ init: function() {
2832
+
2833
+ var utils = _inbound.Utils,
2834
+ wp_lead_uid = utils.readCookie("wp_lead_uid"),
2835
+ wp_lead_id = utils.readCookie("wp_lead_id"),
2836
+ expire_check = utils.readCookie("lead_session_expire"); // check for session
2837
+
2838
+ if (!expire_check) {
2839
+ _inbound.deBugger('leads', 'expired vistor. Run Processes');
2840
+ //var data_to_lookup = global-localized-vars;
2841
+ if (wp_lead_id) {
2842
+ /* Get InboundLeadData */
2843
+ _inbound.LeadsAPI.getAllLeadData();
2844
+ /* Lead list check */
2845
+ _inbound.LeadsAPI.getLeadLists();
2846
+ }
2847
+ }
2848
+ },
2849
+ setGlobalLeadData: function(data) {
2850
+ InboundLeadData = data;
2851
+ },
2852
+ getAllLeadData: function(expire_check) {
2853
+ var wp_lead_id = _inbound.Utils.readCookie("wp_lead_id"),
2854
+ leadData = _inbound.totalStorage('inbound_lead_data'),
2855
+ leadDataExpire = _inbound.Utils.readCookie("lead_data_expire");
2856
+ data = {
2857
+ action: 'inbound_get_all_lead_data',
2858
+ wp_lead_id: wp_lead_id,
2859
+ },
2860
+ success = function(returnData) {
2861
+ var leadData = JSON.parse(returnData);
2862
+ _inbound.LeadsAPI.setGlobalLeadData(leadData);
2863
+ _inbound.totalStorage('inbound_lead_data', leadData); // store lead data
2864
+
2865
+ /* Set 3 day timeout for checking DB for new lead data for Lead_Global var */
2866
+ var d = new Date();
2867
+ d.setTime(d.getTime() + 30 * 60 * 1000);
2868
+ var expire = _inbound.Utils.addDays(d, 3);
2869
+ _inbound.Utils.createCookie("lead_data_expire", true, expire);
2870
+
2871
+ };
2872
+
2873
+ if (!leadData) {
2874
+ // Get New Lead Data from DB
2875
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, success);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2876
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2877
  } else {
2878
+ // set global lead var with localstorage data
2879
+ _inbound.LeadsAPI.setGlobalLeadData(leadData);
2880
+ _inbound.deBugger('lead', 'Set Global Lead Data from Localstorage');
2881
+
2882
+ if (!leadDataExpire) {
2883
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, success);
2884
+ //console.log('Set Global Lead Data from Localstorage');
2885
+ _inbound.deBugger('lead', 'localized data old. Pull new from DB');
2886
+ //console.log('localized data old. Pull new from DB');
2887
+ }
2888
  }
2889
 
2890
+ },
2891
+ getLeadLists: function() {
2892
+ var wp_lead_id = _inbound.Utils.readCookie("wp_lead_id");
2893
+ var data = {
2894
+ action: 'wpl_check_lists',
2895
+ wp_lead_id: wp_lead_id,
2896
+ };
2897
+ var success = function(user_id) {
2898
+ _inbound.Utils.createCookie("lead_session_list_check", true, {
2899
+ path: '/',
2900
+ expires: 1
2901
+ });
2902
+ _inbound.deBugger('lead', "Lists checked");
2903
+ //console.log("Lists checked");
2904
+ };
2905
+ //_inbound.Utils.doAjax(data, success);
2906
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, success);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2907
  }
2908
+ };
2909
 
2910
+ return _inbound;
 
 
2911
 
2912
+ })(_inbound || {});
2913
+ /**
2914
+ * # Page View Tracking
2915
+ *
2916
+ * Page view tracking
2917
+ *
2918
+ * @author David Wells <david@inboundnow.com>
2919
+ * @version 0.0.1
2920
+ */
2921
+ /* Launches view tracking */
2922
+ var _inboundPageTracking = (function(_inbound) {
2923
+
2924
+ var started = false,
2925
+ stopped = false,
2926
+ turnedOff = false,
2927
+ clockTime = parseInt(_inbound.Utils.readCookie("lead_session"), 10) || 0,
2928
+ inactiveClockTime = 0,
2929
+ startTime = new Date(),
2930
+ clockTimer = null,
2931
+ inactiveClockTimer = null,
2932
+ idleTimer = null,
2933
+ reportInterval,
2934
+ idleTimeout,
2935
+ utils = _inbound.Utils,
2936
+ Pages = _inbound.totalStorage('page_views') || {},
2937
+ timeNow = _inbound.Utils.GetDate(),
2938
+ /*!
2939
+ Todo: Use UTC offset
2940
+ var x = new Date();
2941
+ var currentTime = x.getTimezoneOffset() / 60;
2942
+ console.log(currentTime) // gets UTC offset
2943
+ */
2944
+ id = inbound_settings.post_id || window.location.pathname,
2945
+ analyticsTimeout = _inbound.Settings.timeout || 30000;
2946
 
2947
+ _inbound.PageTracking = {
2948
 
2949
+ init: function(options) {
 
 
 
 
 
 
2950
 
2951
+ this.CheckTimeOut();
2952
+ // Set up options and defaults
2953
+ options = options || {};
2954
+ reportInterval = parseInt(options.reportInterval, 10) || 10;
2955
+ idleTimeout = parseInt(options.idleTimeout, 10) || 3;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2956
 
2957
+ // Basic activity event listeners
2958
+ utils.addListener(document, 'keydown', utils.throttle(_inbound.PageTracking.pingSession, 1000));
2959
+ utils.addListener(document, 'click', utils.throttle(_inbound.PageTracking.pingSession, 1000));
2960
+ utils.addListener(window, 'mousemove', utils.throttle(_inbound.PageTracking.pingSession, 1000));
2961
+ //utils.addListener(window, 'scroll', utils.throttle(_inbound.PageTracking.pingSession, 1000));
2962
 
2963
+ // Page visibility listeners
2964
+ _inbound.PageTracking.checkVisibility();
 
2965
 
2966
+ /* Start Session on page load */
2967
+ this.startSession();
 
 
 
 
 
 
 
 
 
 
 
 
2968
 
2969
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
2970
 
2971
+ setIdle: function(reason) {
2972
+ var reason = reason || "No Movement",
2973
+ msg = 'Session IDLE. Activity Timeout due to ' + reason;
2974
 
2975
+ _inbound.deBugger('pages', msg);
 
2976
 
2977
+ clearTimeout(_inbound.PageTracking.idleTimer);
2978
+ _inbound.PageTracking.stopClock();
2979
+ _inbound.trigger('session_idle');
2980
 
2981
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2982
 
2983
+ checkVisibility: function() {
2984
+ var hidden, visibilityState, visibilityChange;
2985
+
2986
+ if (typeof document.hidden !== "undefined") {
2987
+ hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
2988
+ } else if (typeof document.mozHidden !== "undefined") {
2989
+ hidden = "mozHidden", visibilityChange = "mozvisibilitychange", visibilityState = "mozVisibilityState";
2990
+ } else if (typeof document.msHidden !== "undefined") {
2991
+ hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
2992
+ } else if (typeof document.webkitHidden !== "undefined") {
2993
+ hidden = "webkitHidden", visibilityChange = "webkitvisibilitychange", visibilityState = "webkitVisibilityState";
2994
+ }
2995
 
2996
+ var document_hidden = document[hidden];
2997
+
2998
+ _inbound.Utils.addListener(document, visibilityChange, function(e) {
2999
+ /*! Listen for visibility changes */
3000
+ if (document_hidden != document[hidden]) {
3001
+ if (document[hidden]) {
3002
+ // Document hidden
3003
+ _inbound.trigger('tab_hidden');
3004
+ _inbound.PageTracking.setIdle('browser tab switch');
3005
+ } else {
3006
+ // Document shown
3007
+ _inbound.trigger('tab_visible');
3008
+ _inbound.PageTracking.pingSession();
3009
+ }
3010
 
3011
+ document_hidden = document[hidden];
3012
+ }
3013
+ });
3014
+ },
3015
+ clock: function() {
3016
+ clockTime += 1;
3017
+ var niceTime = clockTime / 60;
3018
+ var msg = 'Total time spent on Page in this Session: ' + niceTime.toFixed(2) + " min";
3019
+ _inbound.deBugger('pages', msg);
3020
+ if (clockTime > 0 && (clockTime % reportInterval === 0)) {
3021
 
3022
+ var d = new Date();
3023
+ d.setTime(d.getTime() + 30 * 60 * 1000);
3024
+ utils.createCookie("lead_session", clockTime, d); // Set cookie on page load
3025
 
3026
+ /*! every 10 seconds run this */
3027
+ //console.log('Session Heartbeat every ' + reportInterval + ' secs');
3028
+ _inbound.trigger('session_heartbeat', clockTime);
3029
+
3030
+ }
3031
+
3032
+ },
3033
+ inactiveClock: function() {
3034
+ inactiveClockTime += 1;
3035
+ var TimeUntilTimeOut = (1800 - inactiveClockTime) / 60;
3036
+ var msg = 'Time until Session Timeout: ' + TimeUntilTimeOut.toFixed(2) + " min";
3037
+ _inbound.deBugger('pages', msg);
3038
+ //console.log('Time until Session Timeout: ', TimeUntilTimeOut.toFixed(2) + " min");
3039
+ /* Session timeout after 30min */
3040
+ if (inactiveClockTime > 1800) {
3041
+
3042
+ // sendEvent(clockTime);
3043
+ /*! End session after 30min timeout */
3044
+ _inbound.trigger('session_end', InboundLeadData);
3045
+ _inbound.Utils.eraseCookie("lead_session");
3046
+ /* todo maybe? remove session Cookie */
3047
+ inactiveClockTime = 0;
3048
+ clearTimeout(inactiveClockTimer);
3049
+ }
3050
+
3051
+
3052
+ },
3053
+ stopClock: function() {
3054
+ stopped = true;
3055
+ clearTimeout(clockTimer);
3056
+ clearTimeout(inactiveClockTimer);
3057
+ inactiveClockTimer = setInterval(_inbound.PageTracking.inactiveClock, 1000);
3058
+ },
3059
+
3060
+ restartClock: function() {
3061
+ stopped = false;
3062
+
3063
+
3064
+ _inbound.trigger('session_resume');
3065
+ _inbound.deBugger('pages', 'Activity resumed. Session Active');
3066
+ /* todo add session_resume */
3067
+ clearTimeout(clockTimer);
3068
+ inactiveClockTime = 0;
3069
+ clearTimeout(inactiveClockTimer);
3070
+ clockTimer = setInterval(_inbound.PageTracking.clock, 1000);
3071
+ },
3072
+
3073
+ turnOff: function() {
3074
+ _inbound.PageTracking.setIdle();
3075
+ turnedOff = true;
3076
+ },
3077
+
3078
+ turnOn: function() {
3079
+ turnedOff = false;
3080
+ },
3081
+ /* This start only runs once */
3082
+ startSession: function() {
3083
+ /* todo add session Cookie */
3084
+ // Calculate seconds from start to first interaction
3085
+ var currentTime = new Date();
3086
+ var diff = currentTime - startTime;
3087
 
 
3088
 
3089
+ started = true; // Set global
3090
+
3091
+ // Send User Timing Event
3092
+ /* Todo session start here */
3093
+
3094
+ // Start clock
3095
+ clockTimer = setInterval(_inbound.PageTracking.clock, 1000);
3096
+ //utils.eraseCookie("lead_session");
3097
+ var session = utils.readCookie("lead_session");
3098
+
3099
+ if (!session) {
3100
+ _inbound.trigger('session_start'); // trigger 'inbound_analytics_session_start'
3101
+ var d = new Date();
3102
+ d.setTime(d.getTime() + 30 * 60 * 1000);
3103
+ _inbound.Utils.createCookie("lead_session", 1, d); // Set cookie on page load
3104
  } else {
3105
+ _inbound.trigger('session_active');
3106
+ //console.log("count of secs " + session);
3107
+ //_inbound.trigger('session_active'); // trigger 'inbound_analytics_session_active'
 
3108
  }
3109
 
3110
+ this.pingSession();
 
 
 
 
 
 
3111
 
 
3112
 
3113
+ },
3114
+ resetInactiveFunc: function() {
3115
+ inactiveClockTime = 0;
3116
+ clearTimeout(inactiveClockTimer);
3117
+ },
3118
+ /* Ping Session to keep active */
3119
+ pingSession: function(e) {
3120
 
 
3121
 
3122
+ if (turnedOff) {
3123
+ return;
3124
+ }
3125
 
3126
+ if (!started) {
3127
+ _inbound.PageTracking.startSession();
3128
+ }
3129
+
3130
+ if (stopped) {
3131
+ _inbound.PageTracking.restartClock();
3132
+ }
3133
+
3134
+ clearTimeout(idleTimer);
3135
+
3136
+ idleTimer = setTimeout(_inbound.PageTracking.setIdle, idleTimeout * 1000 + 100);
3137
+
3138
+ if (typeof(e) != "undefined") {
3139
+ if (e.type === "mousemove") {
3140
+ _inbound.PageTracking.mouseEvents(e);
3141
+ }
3142
+ }
3143
+
3144
+ },
3145
+ mouseEvents: function(e) {
3146
+
3147
+ if (e.pageY <= 5) {
3148
+ _inbound.trigger('tab_mouseout');
3149
+ }
3150
+
3151
+ },
3152
+ /**
3153
+ * Returns the pages viewed by the site visitor
3154
+ *
3155
+ * ```js
3156
+ * var pageViews = _inbound.PageTracking.getPageViews();
3157
+ * // returns page view object
3158
+ * ```
3159
+ *
3160
+ * @return {object} page view object with page ID as key and timestamp
3161
+ */
3162
+ getPageViews: function() {
3163
+ var local_store = _inbound.Utils.checkLocalStorage();
3164
+ if (local_store) {
3165
+ var page_views = localStorage.getItem("page_views"),
3166
+ local_object = JSON.parse(page_views);
3167
+ if (typeof local_object == 'object' && local_object) {
3168
+ //this.triggerPageView();
3169
+ }
3170
+ return local_object;
3171
+ }
3172
+ },
3173
+ isRevisit: function(Pages) {
3174
+ var revisitCheck = false;
3175
+ var Pages = Pages || {};
3176
+ var pageSeen = Pages[id];
3177
+ if (typeof(pageSeen) != "undefined" && pageSeen !== null) {
3178
+ revisitCheck = true;
3179
+ }
3180
+ return revisitCheck;
3181
+ },
3182
+ triggerPageView: function(pageRevisit) {
3183
+
3184
+ var pageData = {
3185
+ title: document.title,
3186
+ url: document.location.href,
3187
+ path: document.location.pathname,
3188
+ count: 1 // default
3189
+ };
3190
+
3191
+ if (pageRevisit) {
3192
+ /* Page Revisit Trigger */
3193
+ Pages[id].push(timeNow);
3194
+ pageData.count = Pages[id].length;
3195
+ _inbound.trigger('page_revisit', pageData);
3196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3197
  } else {
3198
+ /* Page First Seen Trigger */
3199
+ Pages[id] = [];
3200
+ Pages[id].push(timeNow);
3201
+ _inbound.trigger('page_first_visit', pageData);
3202
+ }
3203
 
3204
+ _inbound.trigger('page_visit', pageData);
3205
+
3206
+ _inbound.totalStorage('page_views', Pages);
3207
+
3208
+ this.storePageView();
3209
+
3210
+ },
3211
+ CheckTimeOut: function() {
3212
+ var pageRevisit = this.isRevisit(Pages),
3213
+ status,
3214
+ timeout;
3215
+
3216
+ /* Default */
3217
+ if (pageRevisit) {
3218
+ var prev = Pages[id].length - 1,
3219
+ lastView = Pages[id][prev],
3220
+ timeDiff = Math.abs(new Date(lastView).getTime() - new Date(timeNow).getTime());
3221
+
3222
+ timeout = timeDiff > analyticsTimeout;
3223
+
3224
+ if (timeout) {
3225
+ status = 'Timeout Happened. Page view fired';
3226
+ this.triggerPageView(pageRevisit);
3227
+ } else {
3228
+ time_left = Math.abs((analyticsTimeout - timeDiff)) * 0.001;
3229
+ status = analyticsTimeout / 1000 + ' sec timeout not done: ' + time_left + " seconds left";
3230
+ }
3231
+
3232
+ } else {
3233
+ /*! Page never seen before save view */
3234
+ this.triggerPageView(pageRevisit);
3235
+ }
3236
+
3237
+ _inbound.deBugger('pages', status);
3238
+ },
3239
+ storePageView: function() {
3240
+ var leadID = _inbound.Utils.readCookie('wp_lead_id'),
3241
+ lead_uid = _inbound.Utils.readCookie('wp_lead_uid');
3242
+
3243
+ if (leadID) {
3244
+
3245
+ var data = {
3246
+ action: 'wpl_track_user',
3247
+ wp_lead_uid: lead_uid,
3248
+ wp_lead_id: leadID,
3249
+ page_id: inbound_settings.post_id,
3250
+ current_url: window.location.href,
3251
+ json: '0'
3252
+ };
3253
+ var firePageCallback = function(leadID) {
3254
+ //_inbound.Events.page_view_saved(leadID);
3255
+ };
3256
+ //_inbound.Utils.doAjax(data, firePageCallback);
3257
+ _inbound.Utils.ajaxPost(inbound_settings.admin_url, data, firePageCallback);
3258
+ }
3259
+ }
3260
+ /*! GA functions
3261
+ function log_event(category, action, label) {
3262
+ _gaq.push(['_trackEvent', category, action, label]);
3263
+ }
3264
+
3265
+ function log_click(category, link) {
3266
+ log_event(category, 'Click', $(link).text());
3267
+ }
3268
+ */
3269
+ };
3270
 
3271
+ return _inbound;
3272
 
3273
+ })(_inbound || {});
3274
  /**
3275
+ * # Start
3276
+ *
3277
+ * Runs init functions
3278
+ *
3279
+ * @author David Wells <david@inboundnow.com>
3280
+ * @version 0.0.1
3281
  */
3282
 
3283
+
3284
+ /* Initialize _inbound */
3285
+ _inbound.init();
3286
+
3287
+ /* Set Global Lead Data */
3288
+ InboundLeadData = _inbound.totalStorage('inbound_lead_data') || null;
3289
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
shared/assets/frontend/js/analytics/inboundAnalytics.min.js CHANGED
@@ -1,2 +1,3 @@
1
- /*! cta v1.0.0 | (c) 2014 Inbound Now | https://github.com/inboundnow/cta */
2
- function setGlobalLeadVar(e){Lead_Globals=e}var inbound_data=inbound_data||{},_gaq=_gaq||[],InboundAnalytics=function(){var e=!1,t={init:function(){InboundAnalytics.Utils.init(),InboundAnalytics.PageTracking.StorePageView(),InboundAnalytics.Events.loadEvents()},debug:function(t,a){if(e&&console){var t=t||!1;t&&"string"==typeof t&&console.log(t),a&&a instanceof Function&&a()}}};return t}(),InboundTotalStorage=function(e){var t,a,n="inboundAnalytics";if("localStorage"in window)try{a="undefined"==typeof window.localStorage?void 0:window.localStorage,t="undefined"==typeof a||"undefined"==typeof window.JSON?!1:!0,window.localStorage.setItem(n,"1"),window.localStorage.removeItem(n)}catch(o){t=!1}e.totalStorage=function(t,a){return e.totalStorage.impl.init(t,a)},e.totalStorage.setItem=function(t,a){return e.totalStorage.impl.setItem(t,a)},e.totalStorage.getItem=function(t){return e.totalStorage.impl.getItem(t)},e.totalStorage.getAll=function(){return e.totalStorage.impl.getAll()},e.totalStorage.deleteItem=function(t){return e.totalStorage.impl.deleteItem(t)},e.totalStorage.impl={init:function(e,t){return"undefined"!=typeof t?this.setItem(e,t):this.getItem(e)},setItem:function(n,o){if(!t)try{return e.Utils.createCookie(n,o),o}catch(i){console.log("Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie")}var l=JSON.stringify(o);return a.setItem(n,l),this.parseResult(l)},getItem:function(n){if(!t)try{return this.parseResult(e.Utils.readCookie(n))}catch(o){return null}var i=a.getItem(n);return this.parseResult(i)},deleteItem:function(n){if(!t)try{return e.Utils.eraseCookie(n,null),!0}catch(o){return!1}return a.removeItem(n),!0},getAll:function(){var n=[];if(t)for(var o in a)o.length&&n.push({key:o,value:this.parseResult(a.getItem(o))});else try{for(var i=document.cookie.split(";"),l=0;l<i.length;l++){var s=i[l].split("="),r=s[0];n.push({key:r,value:this.parseResult(e.Utils.readCookie(r))})}}catch(d){return null}return n},parseResult:function(e){var t;try{t=JSON.parse(e),"undefined"==typeof t&&(t=e),"true"==t&&(t=!0),"false"==t&&(t=!1),parseFloat(t)==t&&"object"!=typeof t&&(t=parseFloat(t))}catch(a){t=e}return t}}}(InboundAnalytics||{}),InboundAnalyticsLeadsAPI=function(e){var t;return e.LeadsAPI={init:function(){},storeLeadData:function(){element.addEventListener?element.addEventListener("submit",function(e){e.preventDefault(),window.history.back()},!0):element.attachEvent("onsubmit",function(e){e.preventDefault(),window.history.back()})},attachFormSubmitEvent:function(){for(var t=0;t<window.document.forms.length;t++){var a=window.document.forms[t],n="wpl-track-me";if("classList"in document.documentElement)var o=a.classList.contains(n);else var o=new RegExp("(^|\\s)"+n+"(\\s|$)").test(a.className);o&&(console.log("Has Class",o),e.Utils.addListener(a,"submit",e.LeadsAPI.formSubmit),console.log(a))}console.log("RAN attach event")},makeRequest:function(a){if(window.XMLHttpRequest)t=new XMLHttpRequest;else if(window.ActiveXObject)try{t=new ActiveXObject("Msxml2.XMLHTTP")}catch(n){try{t=new ActiveXObject("Microsoft.XMLHTTP")}catch(n){}}return t?(t.onreadystatechange=e.LeadsAPI.alertContents,t.open("GET",a),t.send(),void 0):(alert("Giving up :( Cannot create an XMLHTTP instance"),!1)},inbound_map_fields:function(e,t){var a=[],n=e,o=t,i=n.closest("label").text(),l=["credit-card"],s=jQuery.inArray(o,l);return 0==s?null:(a.push({field_label:i,field_name:n.attr("name"),field_value:n.attr("value"),field_id:n.attr("id"),field_class:n.attr("class"),field_type:n.attr("type"),match:o,js_selector:n.attr("data-js-selector")}),a)},run_field_map_function:function(t,a){for(var n,o=new Array,i=t,l=jQuery("body"),s=i.attr("id")||"NULL",r=i.attr("name")||"NULL",d=i.attr("value"),u=a.split(","),c=(u.length-1,0);c<u.length;c++){var _=e.Utils.trim(u[c]),f=_.replace(/^\s+|\s+$/g,""),f=f.replace(" ","_"),m=f in inbound_data;if(r.toLowerCase().indexOf(_)>-1){var p=e.LeadsAPI.inbound_map_fields(i,_,o);e.LeadsAPI.add_inbound_form_class(i,_),console.log("match name: "+_),console.log(f in inbound_data),m||(inbound_data[f]=d)}else if(s.toLowerCase().indexOf(_)>-1){var p=e.LeadsAPI.inbound_map_fields(i,_,o);e.LeadsAPI.add_inbound_form_class(i,_),console.log("match id: "+_),m||(inbound_data[f]=d)}else if(i.closest("li").children("label").length>0){var g=i.closest("li").children("label").html()||"NULL";if(g.toLowerCase().indexOf(_)>-1){var p=e.LeadsAPI.inbound_map_fields(i,_,o);e.LeadsAPI.add_inbound_form_class(i,_),console.log(i.context);var b=l.find("[data-inbound-form-map='inbound_map_"+f+"']").length;console.log(b),console.log("match li: "+_),m||(inbound_data[f]=d)}}else if(i.closest("div").children("label").length>0){var v=i.closest("div").children("label").html()||"NULL";if(v.toLowerCase().indexOf(_)>-1){var p=e.LeadsAPI.inbound_map_fields(i,_,o);e.LeadsAPI.add_inbound_form_class(i,_),console.log("match div: "+_),m||(inbound_data[f]=d)}}else if(i.closest("p").children("label").length>0){var h=i.closest("p").children("label").html()||"NULL";if(h.toLowerCase().indexOf(_)>-1){var p=e.LeadsAPI.inbound_map_fields(i,_,o);e.LeadsAPI.add_inbound_form_class(i,_),console.log("match p: "+_),m||(inbound_data[f]=d)}}else console.log("Need additional mapping data")}return n=p,inbound_data},add_inbound_form_class:function(e,t){var t=t.replace(" ","_"),t=t.replace("-","_");e.addClass("inbound_map_value"),e.attr("data-inbound-form-map","inbound_map_"+t)},inbound_form_type:function(e){var t=t||{},a="normal";if(e.is(".wpl-comment-form"))t.form_type="comment",a="comment";else if(e.is(".wpl-search-box")){a="search",t.form_type="search"}else if(e.is(".wpl-track-me-link")){var n=readCookie("wp_lead_email");console.log(n),t.form_type="link",a="search"}return a},grab_all_form_input_vals:function(t){var a=a||{},n=n||[],o=t.find("input,textarea,select");n.push("inbound_furl","inbound_current_page_url","inbound_notify","inbound_submitted","post_type","post_status","s","inbound_form_name","inbound_form_id","inbound_form_lists");var i=e.LeadsAPI.inbound_form_type(t),l=l||{},s=l.email||!1;o.each(function(){var e=jQuery(this),t=e.attr("type"),o=e.val();"checkbox"===t&&(input_checked=e.attr("checked"),console.log(o),console.log(input_checked),console.log(a[this.name]),"checked"===input_checked&&("undefined"!=typeof a[this.name]?(a[this.name]=a[this.name]+","+o,console.log(a[this.name])):a[this.name]=o)),-1===jQuery.inArray(this.name,n)&&"checkbox"!=t&&(a[this.name]=o),this.value.indexOf("@")>-1&&!s&&(s=o,l.email=s),"search"===i&&(l.search_keyword=o.replace('"',"'"))});var r=JSON.stringify(a);return r},return_mapped_values:function(t){return jQuery(t).find('input[type!="hidden"],textarea,select').each(function(){console.log("run");var t=jQuery(this),a=t.val();if("undefined"!=typeof a&&null!=a&&""!=a)var n=e.LeadsAPI.run_field_map_function(t,"name, first name, last name, email, e-mail, phone, website, job title, company, tele, address, comment");return n}),inbound_data},inbound_form_submit:function(t){var a=inbound_data||{},n=jQuery.totalStorage("page_views");a.page_view_count=e.Utils.countProperties(n),a.leads_list=jQuery(t).find("#inbound_form_lists").val(),a.source=jQuery.cookie("wp_lead_referral_site")||"NA",a.page_id=inbound_ajax.post_id,a.page_views=JSON.stringify(n);var o=e.LeadsAPI.return_mapped_values(t),a=e.Utils.mergeObjs(a,o),t=jQuery(t);if(a.email=a.email?a.email:t.find(".inbound-email").val(),a.form_name=t.find(".inbound_form_name").val()||"Not Found",a.form_id=t.find(".inbound_form_id").val()||"Not Found",a.first_name=a.first_name?a.first_name:a.name,a.last_name=a.last_name||"",a.phone=a.phone||"",a.company=a.company||"",a.address=a.address||"",a.name=a.first_name&&a.last_name?a.first_name+" "+a.last_name:a.name,!a.last_name&&a.first_name){var i=a.first_name.split(" ");a.first_name=i[0],a.last_name=i[1]}var l=e.LeadsAPI.grab_all_form_input_vals(t);if(a.email&&e.Utils.createCookie("wp_lead_email",a.email,365),"undefined"!=typeof landing_path_info)var s=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)var s=cta_path_info.variation;else var s=0;a.variation=s,a.post_type=inbound_ajax.post_type,a.wp_lead_uid=jQuery.cookie("wp_lead_uid")||null,a.ip_address=inbound_ajax.ip_address,a.search_data=JSON.stringify(jQuery.totalStorage("inbound_search"))||{};var r="landing-page"===inbound_ajax.post_type?"Landing Page":"",d="wp-call-to-action"===inbound_ajax.post_type?"Call to Action":"",u=(d||r?r+d:inbound_ajax.post_type,JSON.stringify(a)),c={},c={action:"inbound_store_lead",emailTo:a.email,first_name:a.first_name,last_name:a.last_name,phone:a.phone,address:a.address,company_name:a.company,page_views:a.page_views,form_input_values:l,Mapped_Data:u,Search_Data:a.search_data};return c},formSubmit:function(t){t.preventDefault(),console.log("This works");var a=e.LeadsAPI.inbound_form_submit(t.target,t);console.log(a),alert("Working"),e.LeadsAPI.makeRequest("test.html")},alertContents:function(){4===t.readyState&&(200===t.status?alert(t.responseText):400==xmlhttp.status?alert("There was an error 400"):alert("There was a problem with the request."))},getAllLeadData:function(t){var a=e.Utils.readCookie("wp_lead_id"),n=jQuery.totalStorage("inbound_lead_data"),o={action:"inbound_get_all_lead_data",wp_lead_id:a},i=function(e){var t=JSON.parse(e);console.log("RAAAAAAn"),setGlobalLeadVar(t),jQuery.totalStorage("inbound_lead_data",t)};if(n||console.log("No old data"),"true"===t&&console.log("Session has not expired"),n||null!==t){setGlobalLeadVar(n);var l=e.Utils.readCookie("lead_data_expiration");null===l&&(e.Utils.doAjax(o,i),console.log("localized data old. Pull new from DB"))}else e.debug("Go to Database",function(){console.log(t),console.log(n)}),e.Utils.doAjax(o,i)},getLeadLists:function(){var t=e.Utils.readCookie("wp_lead_id"),a={action:"wpl_check_lists",wp_lead_id:t},n=function(){jQuery.cookie("lead_session_list_check",!0,{path:"/",expires:1}),console.log("Lists checked")};e.Utils.doAjax(a,n)}},e}(InboundAnalytics||{}),InboundAnalyticsPageTracking=function(e){return e.PageTracking={getPageViews:function(){var t=e.Utils.checkLocalStorage();if(t){var a=localStorage.getItem("page_views"),n=JSON.parse(a);return"object"==typeof n&&n&&this.StorePageView(),n}},StorePageView:function(){var t=this.CheckTimeOut(),a=jQuery.totalStorage("page_views");null===a&&(a={});var n=wplft.post_id,o=e.Utils.GetDate();if(t){var i=a[n];if("undefined"!=typeof i&&null!==i){a[n].push(o);var l=a[n].length;e.Events.pageRevisit(l)}else{a[n]=[],a[n].push(o);var l=1;e.Events.pageFirstView(l)}jQuery.totalStorage("page_views",a)}},CheckTimeOut:function(){var t=jQuery.totalStorage("page_views");if(null===t)var t={};var a=wplft.post_id,n=!0,o=t[a];if("undefined"!=typeof o&&null!==o){var i=e.Utils.GetDate(),l=t[a].length-1,s=t[a][l],r=new Date(s).getTime(),d=new Date(i).getTime(),u=Math.abs(r-d),c=3e4;if(e.debug("Timeout Checks =",function(){console.log("Current Time is: "+i),console.log("Last view is: "+s),console.log("Last view milliseconds "+r),console.log("time now milliseconds "+d),console.log("Wait Check: "+c),console.log("TIME CHECK: "+u)}),c>u){time_left=.001*Math.abs(c-u),n=!1;var _="30 sec timeout not done: "+time_left+" seconds left"}else{var _="Timeout Happened. Page view fired";this.firePageView(),n=!0,e.Events.analyticsTriggered()}console.log(_)}else this.firePageView();return n},firePageView:function(){var t=e.Utils.readCookie("wp_lead_id"),a=e.Utils.readCookie("wp_lead_uid");if("undefined"!=typeof t&&null!=t&&""!=t){e.debug("Run page view ajax");var n={action:"wpl_track_user",wp_lead_uid:a,wp_lead_id:t,page_id:wplft.post_id,current_url:window.location.href,json:"0"},o=function(){e.Events.analyticsSaved()};e.Utils.doAjax(n,o)}},tabSwitch:function(){var t,a,n;"undefined"!=typeof document.hidden?(t="hidden",n="visibilitychange",a="visibilityState"):"undefined"!=typeof document.mozHidden?(t="mozHidden",n="mozvisibilitychange",a="mozVisibilityState"):"undefined"!=typeof document.msHidden?(t="msHidden",n="msvisibilitychange",a="msVisibilityState"):"undefined"!=typeof document.webkitHidden&&(t="webkitHidden",n="webkitvisibilitychange",a="webkitVisibilityState");var o=document[t];document.addEventListener(n,function(){o!=document[t]&&(document[t]?(console.log("hidden"),e.Events.browserTabHidden()):(console.log("shown"),e.Events.browserTabVisible()),o=document[t])})}},e}(InboundAnalytics||{}),Lead_Globals=jQuery.totalStorage("inbound_lead_data")||null;InboundAnalytics.init(),jQuery(document).ready(function(){var e=InboundAnalytics.Utils,t=(e.readCookie("wp_lead_uid"),e.readCookie("wp_lead_id")),a=e.readCookie("lead_session_expire");null===a&&(console.log("expired vistor. Run Processes"),"undefined"!=typeof t&&null!=t&&""!=t&&(InboundAnalytics.LeadsAPI.getAllLeadData(a),InboundAnalytics.LeadsAPI.getLeadLists())),e.contentLoaded(window,InboundAnalytics.LeadsAPI.attachFormSubmitEvent),e.SetSessionTimeout()});
 
1
+ /*! Inbound Analyticsv1.0.0 | (c) 2014 Inbound Now | https://github.com/inboundnow/cta */
2
+ var inbound_data=inbound_data||{},_inboundOptions=_inboundOptions||{},_gaq=_gaq||[],_inbound=function(e){var t={timeout:3e4,formAutoTracking:!0,formAutoPopulation:!0},n={init:function(){_inbound.Utils.init(),_inbound.Utils.domReady(window,function(){_inbound.DomLoaded()})},DomLoaded:function(){_inbound.PageTracking.init(),_inbound.Forms.init(),_inbound.Utils.setUrlParams(),_inbound.LeadsAPI.init(),setTimeout(function(){_inbound.Forms.init()},2e3),_inbound.trigger("analytics_ready")},extend:function(e,t){var n,o={};for(n in e)Object.prototype.hasOwnProperty.call(e,n)&&(o[n]=e[n]);for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(o[n]=t[n]);return o},debug:function(){},deBugger:function(e,t,n){if(console){var o,i,a,r=document.location.hash?document.location.hash:"",s=r.indexOf("#debug")>-1,t=t||!1;r&&r.match(/debug/)&&(r=r.split("-"),a=r[1]),i="true"===_inbound.Utils.readCookie("inbound_debug")?!0:!1,o="true"===_inbound.Utils.readCookie("inbound_debug_"+e)?!0:!1,(o||s||i)&&(t&&"string"==typeof t&&(i||"all"===a?console.log('logAll "'+e+'" =>',t):o?console.log('log "'+e+'" =>',t):e===a&&console.log('#log "'+e+'" =>',t)),n&&n instanceof Function&&n())}}},o=n.extend(t,e);return n.Settings=o||{},n}(_inboundOptions),_inboundHooks=function(e){var t=function(){function e(e,t,n,o){return"string"==typeof e&&"function"==typeof t&&(n=parseInt(n||10,10),s("actions",e,t,n,o)),c}function t(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t&&u("actions",t,e),c}function n(e,t){return"string"==typeof e&&r("actions",e,t),c}function o(e,t,n){return"string"==typeof e&&"function"==typeof t&&(n=parseInt(n||10,10),s("filters",e,t,n)),c}function i(){var e=Array.prototype.slice.call(arguments),t=e.shift();return"string"==typeof t?u("filters",t,e):c}function a(e,t){return"string"==typeof e&&r("filters",e,t),c}function r(e,t,n,o){if(d[e][t])if(n){var i,a=d[e][t];if(o)for(i=a.length;i--;){var r=a[i];r.callback===n&&r.context===o&&a.splice(i,1)}else for(i=a.length;i--;)a[i].callback===n&&a.splice(i,1)}else d[e][t]=[]}function s(e,t,n,o,i){var a={callback:n,priority:o,context:i},r=d[e][t];r?(r.push(a),r=l(r)):r=[a],d[e][t]=r}function l(e){for(var t,n,o,i=1,a=e.length;a>i;i++){for(t=e[i],n=i;(o=e[n-1])&&o.priority>t.priority;)e[n]=e[n-1],--n;e[n]=t}return e}function u(e,t,n){var o=d[e][t];if(!o)return"filters"===e?n[0]:!1;var i=0,a=o.length;if("filters"===e)for(;a>i;i++)n[0]=o[i].callback.apply(o[i].context,n);else for(;a>i;i++)o[i].callback.apply(o[i].context,n);return"filters"===e?n[0]:!0}var c={removeFilter:a,applyFilters:i,addFilter:o,removeAction:n,doAction:t,addAction:e},d={actions:{},filters:{}};return c};return e.hooks=new t,e.add_action=function(){var t=arguments[0].split(" ");for(k in t)arguments[0]="inbound."+t[k],e.hooks.addAction.apply(this,arguments);return this},e.remove_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeAction.apply(this,arguments),this},e.do_action=function(){return arguments[0]="inbound."+arguments[0],e.hooks.doAction.apply(this,arguments),this},e.add_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.addFilter.apply(this,arguments),this},e.remove_filter=function(){return arguments[0]="inbound."+arguments[0],e.hooks.removeFilter.apply(this,arguments),this},e.apply_filters=function(){return arguments[0]="inbound."+arguments[0],e.hooks.applyFilters.apply(this,arguments)},e}(_inbound||{}),_inboundUtils=function(e){var t;return e.Utils={init:function(){this.polyFills(),this.checkLocalStorage(),this.SetUID(),this.storeReferralData()},polyFills:function(){window.console||(window.console={});for(var e=["log","info","warn","error","debug","trace","dir","group","groupCollapsed","groupEnd","time","timeEnd","profile","profileEnd","dirxml","assert","count","markTimeline","timeStamp","clear"],t=0;t<e.length;t++)window.console[e[t]]||(window.console[e[t]]=function(){});try{new CustomEvent("?")}catch(n){this.CustomEvent=function(e,t){function n(n,i){var a=document.createEvent(e);return null!==n?o.call(a,n,(i||(i=t)).bubbles,i.cancelable,i.detail):a.initCustomEvent=o,a}function o(t,n,o,i){this["init"+e](t,n,o,i),"detail"in this||(this.detail=i)}return n}(this.CustomEvent?"CustomEvent":"Event",{bubbles:!1,cancelable:!1,detail:null})}document.querySelectorAll||(document.querySelectorAll=function(e){var t,n=document.createElement("style"),o=[];for(document.documentElement.firstChild.appendChild(n),document._qsa=[],n.styleSheet.cssText=e+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",window.scrollBy(0,0),n.parentNode.removeChild(n);document._qsa.length;)t=document._qsa.shift(),t.style.removeAttribute("x-qsa"),o.push(t);return document._qsa=null,o}),document.querySelector||(document.querySelector=function(e){var t=document.querySelectorAll(e);return t.length?t[0]:null}),!("innerText"in document.createElement("a"))&&"getSelection"in window&&HTMLElement.prototype.__defineGetter__("innerText",function(){for(var e,t=window.getSelection(),n=[],o=0;o<t.rangeCount;o++)n[o]=t.getRangeAt(o);t.removeAllRanges(),t.selectAllChildren(this),e=t.toString(),t.removeAllRanges();for(var o=0;o<n.length;o++)t.addRange(n[o]);return e})},createCookie:function(e,t,n){var o="";if(n){var i=new Date;i.setTime(i.getTime()+24*n*60*60*1e3),o="; expires="+i.toGMTString()}document.cookie=e+"="+t+o+"; path=/"},readCookie:function(e){for(var t=e+"=",n=document.cookie.split(";"),o=0;o<n.length;o++){for(var i=n[o];" "===i.charAt(0);)i=i.substring(1,i.length);if(0===i.indexOf(t))return i.substring(t.length,i.length)}return null},eraseCookie:function(e){this.createCookie(e,"",-1)},getAllCookies:function(){var t={};if(document.cookie&&""!==document.cookie)for(var n=document.cookie.split(";"),o=0;o<n.length;o++){var i=n[o].split("=");i[0]=i[0].replace(/^ /,""),t[decodeURIComponent(i[0])]=decodeURIComponent(i[1])}return e.totalStorage("inbound_cookies",t),t},setUrlParams:function(){var n={};!function(){for(var e,t=function(e){return decodeURIComponent(e).replace(/\+/g," ")},o=window.location.search.substring(1),i=/([^&=]+)=?([^&]*)/g;e=i.exec(o);)if("-1"==e[1].indexOf("["))n[t(e[1])]=t(e[2]);else{var a=e[1].indexOf("["),r=e[1].slice(a+1,e[1].indexOf("]",a)),s=t(e[1].slice(0,a));"object"!=typeof n[s]&&(n[t(s)]={},n[t(s)].length=0),r?n[t(s)][t(r)]=t(e[2]):Array.prototype.push.call(n[t(s)],t(e[2]))}}();for(var o in n)if("object"==typeof n[o])for(var i in n[o])this.createCookie(i,n[o][i],30);else this.createCookie(o,n[o],30);if(t){var a=e.totalStorage("inbound_url_params")||{},r=this.mergeObjs(a,n);e.totalStorage("inbound_url_params",r)}var s={option1:"yo",option2:"woooo"};e.trigger("url_parameters",n,s)},getAllUrlParams:function(){var n={};if(t)var n=e.totalStorage("inbound_url_params");return n},getParameterVal:function(e,t){return(RegExp(e+"=(.+?)(&|$)").exec(t)||[,!1])[1]},checkLocalStorage:function(){if("localStorage"in window)try{ls="undefined"==typeof window.localStorage?void 0:window.localStorage,t="undefined"==typeof ls||"undefined"==typeof window.JSON?!1:!0}catch(e){t=!1}return t},addDays:function(e,t){return new Date(e.getTime()+24*t*60*60*1e3)},GetDate:function(){var e=new Date,t=e.getDate(),n=10>t?"0":"",o=e.getFullYear(),i=e.getHours(),a=10>i?"0":"",r=e.getMinutes(),s=10>r?"0":"",l=e.getSeconds(),u=10>l?"0":"",c=e.getMonth()+1,d=10>c?"0":"",m=o+"/"+d+c+"/"+n+t+" "+a+i+":"+s+r+":"+u+l;return m},SetSessionTimeout:function(){var e=(this.readCookie("lead_session_expire"),new Date);e.setTime(e.getTime()+18e5),this.createCookie("lead_session_expire",!0,e,!0)},storeReferralData:function(){var t=new Date,n=document.referrer||"Direct Traffic",o=e.Utils.readCookie("inbound_referral_site"),i=e.totalStorage("inbound_original_referral");t.setTime(t.getTime()+18e5),o||this.createCookie("inbound_referral_site",n,t,!0),i||e.totalStorage("inbound_original_referral",i)},CreateUID:function(e){var t="0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".split(""),n="";e||(e=Math.floor(Math.random()*t.length));for(var o=0;e>o;o++)n+=t[Math.floor(Math.random()*t.length)];return n},SetUID:function(e){if(!this.readCookie("wp_lead_uid")){var t=e||this.CreateUID(35);this.createCookie("wp_lead_uid",t)}},countProperties:function(e){var t=0;for(var n in e)e.hasOwnProperty(n)&&++t;return t},mergeObjs:function(e,t){var n={};for(var o in e)n[o]=e[o];for(var o in t)n[o]=t[o];return n},hasClass:function(e,t){var n=!1;if("classList"in document.documentElement)var n=t.classList.contains(e);else var n=new RegExp("(^|\\s)"+e+"(\\s|$)").test(t.className);return n},addClass:function(e,t){"classList"in document.documentElement?t.classList.add(e):this.hasClass(t,e)||(t.className+=(t.className?" ":"")+e)},removeClass:function(e,t){"classList"in document.documentElement?t.classList.remove(e):this.hasClass(t,e)&&(t.className=t.className.replace(new RegExp("(^|\\s)*"+e+"(\\s|$)*","g"),""))},removeElement:function(e){e.parentNode.removeChild(e)},trim:function(e){return e=e.replace(/(^\s*)|(\s*$)/gi,""),e=e.replace(/[ ]{2,}/gi," "),e=e.replace(/\n /,"\n")},ajaxPolyFill:function(){if("undefined"!=typeof XMLHttpRequest)return new XMLHttpRequest;for(var e,t=["MSXML2.XmlHttp.5.0","MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0","MSXML2.XmlHttp.2.0","Microsoft.XmlHttp"],n=0;n<t.length;n++)try{e=new ActiveXObject(t[n]);break}catch(o){}return e},ajaxSendData:function(e,t,n,o,i){var a=this.ajaxPolyFill();a.open(n,e,i),a.onreadystatechange=function(){4==a.readyState&&t(a.responseText)},"POST"==n&&a.setRequestHeader("Content-type","application/x-www-form-urlencoded"),a.send(o)},ajaxGet:function(e,t,n,o){var i=[];for(var a in t)i.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e+"?"+i.join("&"),n,"GET",null,o)},ajaxPost:function(e,t,n,o){var i=[];for(var a in t)i.push(encodeURIComponent(a)+"="+encodeURIComponent(t[a]));this.ajaxSendData(e,n,"POST",i.join("&"),o)},makeRequest:function(t,n){if(window.XMLHttpRequest)httpRequest=new XMLHttpRequest;else if(window.ActiveXObject)try{httpRequest=new ActiveXObject("Msxml2.XMLHTTP")}catch(o){try{httpRequest=new ActiveXObject("Microsoft.XMLHTTP")}catch(o){}}return httpRequest?(httpRequest.onreadystatechange=e.LeadsAPI.alertContents,httpRequest.open("GET",t),httpRequest.send(n),void 0):(alert("Giving up :( Cannot create an XMLHTTP instance"),!1)},domReady:function(e,t){var n=!1,o=!0,i=e.document,a=i.documentElement,r=i.addEventListener?"addEventListener":"attachEvent",s=i.addEventListener?"removeEventListener":"detachEvent",l=i.addEventListener?"":"on",u=function(o){("readystatechange"!=o.type||"complete"==i.readyState)&&(("load"==o.type?e:i)[s](l+o.type,u,!1),!n&&(n=!0)&&t.call(e,o.type||o))},c=function(){try{a.doScroll("left")}catch(e){return setTimeout(c,50),void 0}u("poll")};if("complete"==i.readyState)t.call(e,"lazy");else{if(i.createEventObject&&a.doScroll){try{o=!e.frameElement}catch(d){}o&&c()}i[r](l+"DOMContentLoaded",u,!1),i[r](l+"readystatechange",u,!1),e[r](l+"load",u,!1)}},addListener:function(e,t,n){e&&(e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):e["on"+t]=n)},removeListener:function(e,t,n){e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):e["on"+t]=null},throttle:function(e,t){var n,o,i,a=null,r=0,s=function(){r=new Date,a=null,i=e.apply(n,o)};return function(){var l=new Date;r||(r=l);var u=t-(l-r);return n=this,o=arguments,0>=u?(clearTimeout(a),a=null,r=l,i=e.apply(n,o)):a||(a=setTimeout(s,u)),i}},checkTypeofGA:function(){"function"==typeof ga&&(universalGA=!0),"undefined"!=typeof _gaq&&"function"==typeof _gaq.push&&(classicGA=!0),"undefined"!=typeof dataLayer&&"function"==typeof dataLayer.push&&(googleTagManager=!0)}},e}(_inbound||{}),InboundForms=function(e){var t=!1,n=e.Utils,o=[],a=[],r=[],s=e.Settings,l=["first name","last name","name","email","e-mail","phone","website","job title","your favorite food","company","tele","address","comment"];if(e.Forms={init:function(){e.Forms.runFieldMappingFilters(),e.Forms.assignTrackClass(),e.Forms.formTrackInit()},runFieldMappingFilters:function(){l=e.hooks.applyFilters("forms.field_map",l)},debug:function(e,n){if(t&&console){var e=e||!1;e&&"string"==typeof e&&console.log(e),n&&n instanceof Function&&n()}},formTrackInit:function(){for(var e=0;e<window.document.forms.length;e++){var t=!1,n=window.document.forms[e];n.dataset.formProcessed||(n.dataset.formProcessed=!0,t=this.checkTrackStatus(n),t&&(this.attachFormSubmitEvent(n),this.initFormMapping(n)))}},checkTrackStatus:function(t){var n=t.getAttribute("class");return""!==n&&null!==n?n.toLowerCase().indexOf("wpl-track-me")>-1?!0:n.toLowerCase().indexOf("inbound-track")>-1?!0:(cb=function(){console.log(t)},e.deBugger("forms","This form not tracked. Please assign on in settings...",cb),!1):void 0},assignTrackClass:function(){if(window.inbound_settings){if(inbound_settings.inbound_track_include){var t=inbound_settings.inbound_track_include.split(","),n="add selectors "+inbound_settings.inbound_track_include;e.deBugger("forms",n),this.loopClassSelectors(t,"add")}if(inbound_settings.inbound_track_exclude){var t=inbound_settings.inbound_track_exclude.split(","),n="remove selectors "+inbound_settings.inbound_track_exclude;e.deBugger("forms",n),this.loopClassSelectors(t,"remove")}}},loopClassSelectors:function(t,o){for(var i=t.length-1;i>=0;i--)selector=document.querySelector(n.trim(t[i])),selector&&("add"===o?(e.Utils.addClass("wpl-track-me",selector),e.Utils.addClass("inbound-track",selector)):(e.Utils.removeClass("wpl-track-me",selector),e.Utils.removeClass("inbound-track",selector)))},initFormMapping:function(e){for(var t=[],n=0;n<e.elements.length;n++)formInput=e.elements[n],"hidden"!==formInput.type?(this.mapField(formInput),this.rememberInputValues(formInput),s.formAutoPopulation&&this.fillInputValues(formInput)):t.push(formInput);for(var n=t.length-1;n>=0;n--)formInput=t[n],this.mapField(formInput)},formListener:function(t){t.preventDefault(),e.Forms.saveFormData(t.target),document.body.style.cursor="wait"},attachFormSubmitEvent:function(e){n.addListener(e,"submit",this.formListener);var t=document.querySelector(".inbound-email");n.addListener(t,"blur",this.mailCheck)},ignoreFields:function(){var e=!1,t="",n="";(-1!=t.toLowerCase().indexOf("credit card")||-1!=t.toLowerCase().indexOf("card number"))&&(e=!0),(-1!=t.toLowerCase().indexOf("expiration")||-1!=t.toLowerCase().indexOf("expiry"))&&(e=!0),("month"==t.toLowerCase()||"mm"==t.toLowerCase()||"yy"==t.toLowerCase()||"yyyy"==t.toLowerCase()||"year"==t.toLowerCase())&&(e=!0),(-1!=t.toLowerCase().indexOf("cvv")||-1!=t.toLowerCase().indexOf("cvc")||-1!=t.toLowerCase().indexOf("secure code")||-1!=t.toLowerCase().indexOf("security code"))&&(e=!0),("visa"==n.toLowerCase()||"mastercard"==n.toLowerCase()||"american express"==n.toLowerCase()||"amex"==n.toLowerCase()||"discover"==n.toLowerCase())&&(e=!0);var o=new RegExp("/^[0-9]+$/");if(o.test(n)){var i=n.replace(" ","");this.isInt(i)&&i.length>=16&&(e=!0)}return e},isInt:function(e){return"number"==typeof e&&isFinite(e)&&e%1===0},releaseFormSubmit:function(e){document.body.style.cursor="default",n.removeClass("wpl-track-me",e),n.removeListener(e,"submit",this.formListener),e.submit(),setTimeout(function(){for(var t=0;t<e.elements.length;t++)formInput=e.elements[t],type=formInput.type||!1,"submit"===type&&e.elements[t].click()},1300)},saveFormData:function(t){for(var o=o||{},i=0;i<t.elements.length;i++)if(formInput=t.elements[i],multiple=!1,formInput.name){if(formInput.dataset.ignoreFormField){e.deBugger("forms","ignore "+formInput.name);continue}switch(inputName=formInput.name.replace(/\[([^\[]*)\]/g,"%5B%5D$1"),o[inputName]||(o[inputName]={}),formInput.type&&(o[inputName].type=formInput.type),o[inputName].name||(o[inputName].name=formInput.name),formInput.dataset.mapFormField&&(o[inputName].map=formInput.dataset.mapFormField),formInput.nodeName){case"INPUT":if(l=this.getInputValue(formInput),l===!1)continue;break;case"TEXTAREA":l=formInput.value;break;case"SELECT":if(formInput.multiple){values=[],multiple=!0;for(var s=0;s<formInput.length;s++)formInput[s].selected&&values.push(encodeURIComponent(formInput[s].value))}else l=formInput.value;console.log("select val",l)}if(e.deBugger("forms","Input Value = "+l),l){o[inputName].value||(o[inputName].value=[]),o[inputName].value.push(multiple?values.join(","):encodeURIComponent(l));var l=multiple?values.join(","):encodeURIComponent(l)}}e.deBugger("forms",o);for(var u in o){var c=o[u].value,d=o[u].map;if("undefined"!=typeof c&&null!=c&&""!=c&&a.push(u+"="+o[u].value.join(",")),"undefined"!=typeof d&&null!=d&&o[u].value&&(r.push(d+"="+o[u].value.join(",")),"email"===u))var m=o[u].value.join(",")}var f=a.join("&");e.deBugger("forms","Stringified Raw Form PARAMS: "+f);var g=r.join("&");e.deBugger("forms","Stringified Mapped PARAMS"+g);var m=n.getParameterVal("email",g)||n.readCookie("wp_lead_email");m||(m=n.getParameterVal("wpleads_email_address",g));var p=n.getParameterVal("name",g),v=n.getParameterVal("first_name",g),h=n.getParameterVal("last_name",g);if(!h&&v){var _=decodeURI(v).split(" ");_.length>0&&(v=_[0],h=_[1])}if(p&&!h&&!v){var _=decodeURI(p).split(" ");_.length>0&&(v=_[0],h=_[1])}p=v&&h?v+" "+h:p,e.deBugger("forms","fName = "+v),e.deBugger("forms","lName = "+h),e.deBugger("forms","fullName = "+p);var b=e.totalStorage("page_views")||{},y=e.totalStorage("inbound_url_params")||{};if("undefined"!=typeof landing_path_info)var w=landing_path_info.variation;else if("undefined"!=typeof cta_path_info)var w=cta_path_info.variation;else var w=0;var k=inbound_settings.post_type||"page",C=inbound_settings.post_id||0;search_data={},formData={action:"inbound_lead_store",email:m,full_name:p,first_name:v,last_name:h,raw_params:f,mapped_params:g,url_params:JSON.stringify(y),search_data:"test",page_views:JSON.stringify(b),post_type:k,page_id:C,variation:w,source:n.readCookie("inbound_referral_site")},callback=function(o){e.deBugger("forms","Lead Created with ID: "+o),o=parseInt(o,10),formData.leadID=o,o&&(n.createCookie("wp_lead_id",o),e.totalStorage.deleteItem("page_views"),e.totalStorage.deleteItem("tracking_events")),e.trigger("form_after_submission",formData),e.Forms.releaseFormSubmit(t)},e.trigger("form_before_submission",formData),n.ajaxPost(inbound_settings.admin_url,formData,callback)},rememberInputValues:function(t){var o=(t.name?"inbound_"+t.name:"",t.type?t.type:"text");return"submit"===o||"hidden"===o||"file"===o||"password"===o?!1:(n.addListener(t,"change",function(t){if(t.target.name){if("checkbox"!==o)var i=t.target.value;else for(var a=[],r=document.querySelectorAll('input[name="'+t.target.name+'"]'),s=0;s<r.length;s++){var l=r[s].checked;l&&a.push(r[s].value),i=a.join(",")}inputData={name:t.target.name,node:t.target.nodeName.toLowerCase(),type:o,value:i,mapping:t.target.dataset.mapFormField},e.trigger("form_input_change",inputData),n.createCookie("inbound_"+t.target.name,encodeURIComponent(i))}}),void 0)},fillInputValues:function(e){var t=e.name?"inbound_"+e.name:"",o=e.type?e.type:"text";if("submit"===o||"hidden"===o||"file"===o||"password"===o)return!1;if(n.readCookie(t)&&"comment"!=t)if(value=decodeURIComponent(n.readCookie(t)),"checkbox"===o||"radio"===o)for(var i=value.split(","),a=0;a<i.length;a++)e.value.indexOf(i[a])>-1&&(e.checked=!0);else"undefined"!==value&&(e.value=value)},mapField:function(t){var a=t.id||!1,r=t.name||!1;for(i=0;i<l.length;i++){var s=!1,u=l[i],c=n.trim(u),d=c.replace(/ /g,"_");r&&r.toLowerCase().indexOf(c)>-1?(s=!0,e.deBugger("forms","Found matching name attribute for -> "+c)):a&&a.toLowerCase().indexOf(c)>-1?(s=!0,e.deBugger("forms","Found matching ID attribute for ->"+c)):(label=this.siblingsIsLabel(t))?label[0].innerText.toLowerCase().indexOf(c)>-1&&(s=!0,e.deBugger("forms","Found matching sibling label for -> "+c)):(labelText=this.CheckParentForLabel(t))?labelText.toLowerCase().indexOf(c)>-1&&(s=!0,e.deBugger("forms","Found Matching parent label for -> "+c)):o.push(c),s&&(this.addDataAttr(t,d),this.removeArrayItem(l,c),i--)}return inbound_data},getInputValue:function(e){var t=!1;switch(e.type){case"radio":case"checkbox":e.checked&&(t=e.value);break;case"text":case"hidden":default:t=e.value}return t},addDataAttr:function(e,t){for(var n=document.getElementsByName(e.name),o=n.length-1;o>=0;o--)e.dataset.mapFormField||(n[o].dataset.mapFormField=t)},removeArrayItem:function(e,t){if(e.indexOf)index=e.indexOf(t);else for(index=e.length-1;index>=0&&e[index]!==t;--index);index>=0&&e.splice(index,1)},siblingsIsLabel:function(e){for(var t=this.getSiblings(e),n=[],o=t.length-1;o>=0;o--)"label"===t[o].nodeName.toLowerCase()&&n.push(t[o]);return n.length>0&&n.length<2?n:!1},getChildren:function(e,t){for(var n=[];e;e=e.nextSibling)1==e.nodeType&&e!=t&&n.push(e);return n},getSiblings:function(e){return this.getChildren(e.parentNode.firstChild,e)},CheckParentForLabel:function(e){if("FORM"===e.nodeName)return null;do{var t=e.getElementsByTagName("label");if(t.length>0&&t.length<2)return e.getElementsByTagName("label")[0].innerText}while(e=e.parentNode);return null},mailCheck:function(){var e=document.querySelector(".inbound-email");e&&(n.addListener(e,"blur",this.mailCheck),u.run({email:document.querySelector(".inbound-email").value,suggested:function(t){var o=document.querySelector(".email_suggestion");o&&n.removeElement(o);var i=document.createElement("span");i.innerHTML="<span class=\"email_suggestion\">Did you mean <b><i id='email_correction' style='cursor: pointer;' title=\"click to update\">"+t.full+"</b></i>?</span>",e.parentNode.insertBefore(i,e.nextSibling);var a=document.getElementById("email_correction");n.addListener(a,"click",function(){e.value=a.innerHTML,a.parentNode.parentNode.innerHTML="Fixed!"})},empty:function(){}}))}},"undefined"==typeof u)var u={domainThreshold:1,topLevelThreshold:3,defaultDomains:["yahoo.com","google.com","hotmail.com","gmail.com","me.com","aol.com","mac.com","live.com","comcast.net","googlemail.com","msn.com","hotmail.co.uk","yahoo.co.uk","facebook.com","verizon.net","sbcglobal.net","att.net","gmx.com","mail.com","outlook.com","icloud.com"],defaultTopLevelDomains:["co.jp","co.uk","com","net","org","info","edu","gov","mil","ca"],run:function(e){e.domains=e.domains||u.defaultDomains,e.topLevelDomains=e.topLevelDomains||u.defaultTopLevelDomains,e.distanceFunction=e.distanceFunction||u.sift3Distance;var t=function(e){return e},n=e.suggested||t,o=e.empty||t,i=u.suggest(u.encodeEmail(e.email),e.domains,e.topLevelDomains,e.distanceFunction);return i?n(i):o()},suggest:function(e,t,n,o){e=e.toLowerCase();var i=this.splitEmail(e),a=this.findClosestDomain(i.domain,t,o,this.domainThreshold);if(a){if(a!=i.domain)return{address:i.address,domain:a,full:i.address+"@"+a}}else{var r=this.findClosestDomain(i.topLevelDomain,n,o,this.topLevelThreshold);if(i.domain&&r&&r!=i.topLevelDomain){var s=i.domain;return a=s.substring(0,s.lastIndexOf(i.topLevelDomain))+r,{address:i.address,domain:a,full:i.address+"@"+a}}}return!1},findClosestDomain:function(e,t,n,o){o=o||this.topLevelThreshold;var i,a=99,r=null;if(!e||!t)return!1;n||(n=this.sift3Distance);for(var s=0;s<t.length;s++){if(e===t[s])return e;i=n(e,t[s]),a>i&&(a=i,r=t[s])}return o>=a&&null!==r?r:!1},sift3Distance:function(e,t){if(null==e||0===e.length)return null==t||0===t.length?0:t.length;if(null==t||0===t.length)return e.length;for(var n=0,o=0,i=0,a=0,r=5;n+o<e.length&&n+i<t.length;){if(e.charAt(n+o)==t.charAt(n+i))a++;else{o=0,i=0;for(var s=0;r>s;s++){if(n+s<e.length&&e.charAt(n+s)==t.charAt(n)){o=s;break}if(n+s<t.length&&e.charAt(n)==t.charAt(n+s)){i=s;break}}}n++}return(e.length+t.length)/2-a},splitEmail:function(e){var t=e.trim().split("@");if(t.length<2)return!1;for(var n=0;n<t.length;n++)if(""===t[n])return!1;var o=t.pop(),i=o.split("."),a="";if(0==i.length)return!1;if(1==i.length)a=i[0];else{for(var n=1;n<i.length;n++)a+=i[n]+".";i.length>=2&&(a=a.substring(0,a.length-1))}return{topLevelDomain:a,domain:o,address:t.join("@")}},encodeEmail:function(e){var t=encodeURI(e);return t=t.replace("%20"," ").replace("%25","%").replace("%5E","^").replace("%60","`").replace("%7B","{").replace("%7C","|").replace("%7D","}")}};return e}(_inbound||{}),_inboundEvents=function(e){function t(t,o,i){var o=o||{};i=i||{},i.bubbles=i.bubbles||!0,i.cancelable=i.cancelable||!0,o=e.apply_filters("filter_"+t,o);var a=new CustomEvent(t,{detail:o,bubbles:i.bubbles,cancelable:i.cancelable});window.dispatchEvent(a),e.do_action(t,o),n(t,o)}function n(e,t){if(window.jQuery){var t=t||{};jQuery(document).trigger(e,t)}}e.trigger=function(t,n){e.Events[t](n)};return e.Events={analytics_ready:function(){var e={opt1:!0},n={data:"xyxy"};t("analytics_ready",n,e)},url_parameters:function(e){t("url_parameters",e)},session_start:function(){console.log(""),t("session_start")},session_end:function(e){t("session_end",e),console.log("Session End")},session_active:function(){t("session_active")},session_idle:function(e){t("session_idle",e)},session_resume:function(){t("session_resume")},session_heartbeat:function(e){var n={clock:e,leadData:InboundLeadData};t("session_heartbeat",n)},page_visit:function(e){t("page_view",e)},page_first_visit:function(){t("page_first_visit"),e.deBugger("pages","First Ever Page View of this Page")},page_revisit:function(n){t("page_revisit",n);var o=function(){console.log("pageData",n),console.log("Page Revisit viewed "+n+" times")};e.deBugger("pages",status,o)},tab_hidden:function(){e.deBugger("pages","Tab Hidden"),t("tab_hidden")},tab_visible:function(){e.deBugger("pages","Tab Visible"),t("tab_visible")},tab_mouseout:function(){e.deBugger("pages","Tab Mouseout"),t("tab_mouseout")},form_input_change:function(n){var o=function(){console.log(n)};e.deBugger("forms","inputData change. Data=",o),t("form_input_change",n)},form_before_submission:function(e){t("form_before_submission",e)},form_after_submission:function(e){t("form_after_submission",e)},analyticsError:function(e,t,n){var o=new CustomEvent("inbound_analytics_error",{detail:{MLHttpRequest:e,textStatus:t,errorThrown:n}});window.dispatchEvent(o),console.log("Page Save Error")}},e}(_inbound||{}),InboundTotalStorage=function(e){var t,n,o="_inbound";if("localStorage"in window)try{n="undefined"==typeof window.localStorage?void 0:window.localStorage,t="undefined"==typeof n||"undefined"==typeof window.JSON?!1:!0,window.localStorage.setItem(o,"1"),window.localStorage.removeItem(o)}catch(i){t=!1}e.totalStorage=function(t,n){return e.totalStorage.impl.init(t,n)},e.totalStorage.setItem=function(t,n){return e.totalStorage.impl.setItem(t,n)},e.totalStorage.getItem=function(t){return e.totalStorage.impl.getItem(t)},e.totalStorage.getAll=function(){return e.totalStorage.impl.getAll()},e.totalStorage.deleteItem=function(t){return e.totalStorage.impl.deleteItem(t)},e.totalStorage.impl={init:function(e,t){return"undefined"!=typeof t?this.setItem(e,t):this.getItem(e)},setItem:function(o,i){if(!t)try{return e.Utils.createCookie(o,i),i}catch(a){console.log("Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie")}var r=JSON.stringify(i);return n.setItem(o,r),this.parseResult(r)},getItem:function(o){if(!t)try{return this.parseResult(e.Utils.readCookie(o))}catch(i){return null}var a=n.getItem(o);return this.parseResult(a)},deleteItem:function(o){if(!t)try{return e.Utils.eraseCookie(o,null),!0}catch(i){return!1}return n.removeItem(o),!0},getAll:function(){var o=[];if(t)for(var i in n)i.length&&o.push({key:i,value:this.parseResult(n.getItem(i))});else try{for(var a=document.cookie.split(";"),r=0;r<a.length;r++){var s=a[r].split("="),l=s[0];o.push({key:l,value:this.parseResult(e.Utils.readCookie(l))})}}catch(u){return null}return o},parseResult:function(e){var t;try{t=JSON.parse(e),"undefined"==typeof t&&(t=e),"true"==t&&(t=!0),"false"==t&&(t=!1),parseFloat(t)==t&&"object"!=typeof t&&(t=parseFloat(t))}catch(n){t=e}return t}}}(_inbound||{}),_inboundLeadsAPI=function(e){return e.LeadsAPI={init:function(){var t=e.Utils,n=(t.readCookie("wp_lead_uid"),t.readCookie("wp_lead_id")),o=t.readCookie("lead_session_expire");o||(e.deBugger("leads","expired vistor. Run Processes"),n&&(e.LeadsAPI.getAllLeadData(),e.LeadsAPI.getLeadLists()))},setGlobalLeadData:function(e){InboundLeadData=e},getAllLeadData:function(){var t=e.Utils.readCookie("wp_lead_id"),n=e.totalStorage("inbound_lead_data"),o=e.Utils.readCookie("lead_data_expire");data={action:"inbound_get_all_lead_data",wp_lead_id:t},success=function(t){var n=JSON.parse(t);e.LeadsAPI.setGlobalLeadData(n),e.totalStorage("inbound_lead_data",n);var o=new Date;o.setTime(o.getTime()+18e5);var i=e.Utils.addDays(o,3);e.Utils.createCookie("lead_data_expire",!0,i)},n?(e.LeadsAPI.setGlobalLeadData(n),e.deBugger("lead","Set Global Lead Data from Localstorage"),o||(e.Utils.ajaxPost(inbound_settings.admin_url,data,success),e.deBugger("lead","localized data old. Pull new from DB"))):e.Utils.ajaxPost(inbound_settings.admin_url,data,success)},getLeadLists:function(){var t=e.Utils.readCookie("wp_lead_id"),n={action:"wpl_check_lists",wp_lead_id:t},o=function(){e.Utils.createCookie("lead_session_list_check",!0,{path:"/",expires:1}),e.deBugger("lead","Lists checked")};e.Utils.ajaxPost(inbound_settings.admin_url,n,o)}},e}(_inbound||{}),_inboundPageTracking=function(e){var t,n,o=!1,i=!1,a=!1,r=parseInt(e.Utils.readCookie("lead_session"),10)||0,s=0,l=(new Date,null),u=null,c=null,d=e.Utils,m=e.totalStorage("page_views")||{},f=e.Utils.GetDate(),g=inbound_settings.post_id||window.location.pathname,p=e.Settings.timeout||3e4;return e.PageTracking={init:function(o){this.CheckTimeOut(),o=o||{},t=parseInt(o.reportInterval,10)||10,n=parseInt(o.idleTimeout,10)||3,d.addListener(document,"keydown",d.throttle(e.PageTracking.pingSession,1e3)),d.addListener(document,"click",d.throttle(e.PageTracking.pingSession,1e3)),d.addListener(window,"mousemove",d.throttle(e.PageTracking.pingSession,1e3)),e.PageTracking.checkVisibility(),this.startSession()},setIdle:function(t){var t=t||"No Movement",n="Session IDLE. Activity Timeout due to "+t;e.deBugger("pages",n),clearTimeout(e.PageTracking.idleTimer),e.PageTracking.stopClock(),e.trigger("session_idle")},checkVisibility:function(){var t,n,o;"undefined"!=typeof document.hidden?(t="hidden",o="visibilitychange",n="visibilityState"):"undefined"!=typeof document.mozHidden?(t="mozHidden",o="mozvisibilitychange",n="mozVisibilityState"):"undefined"!=typeof document.msHidden?(t="msHidden",o="msvisibilitychange",n="msVisibilityState"):"undefined"!=typeof document.webkitHidden&&(t="webkitHidden",o="webkitvisibilitychange",n="webkitVisibilityState");var i=document[t];e.Utils.addListener(document,o,function(){i!=document[t]&&(document[t]?(e.trigger("tab_hidden"),e.PageTracking.setIdle("browser tab switch")):(e.trigger("tab_visible"),e.PageTracking.pingSession()),i=document[t])})},clock:function(){r+=1;var n=r/60,o="Total time spent on Page in this Session: "+n.toFixed(2)+" min";if(e.deBugger("pages",o),r>0&&r%t===0){var i=new Date;i.setTime(i.getTime()+18e5),d.createCookie("lead_session",r,i),e.trigger("session_heartbeat",r)}},inactiveClock:function(){s+=1;var t=(1800-s)/60,n="Time until Session Timeout: "+t.toFixed(2)+" min";e.deBugger("pages",n),s>1800&&(e.trigger("session_end",InboundLeadData),e.Utils.eraseCookie("lead_session"),s=0,clearTimeout(u))},stopClock:function(){i=!0,clearTimeout(l),clearTimeout(u),u=setInterval(e.PageTracking.inactiveClock,1e3)},restartClock:function(){i=!1,e.trigger("session_resume"),e.deBugger("pages","Activity resumed. Session Active"),clearTimeout(l),s=0,clearTimeout(u),l=setInterval(e.PageTracking.clock,1e3)},turnOff:function(){e.PageTracking.setIdle(),a=!0},turnOn:function(){a=!1},startSession:function(){new Date;o=!0,l=setInterval(e.PageTracking.clock,1e3);var t=d.readCookie("lead_session");if(t)e.trigger("session_active");else{e.trigger("session_start");var n=new Date;n.setTime(n.getTime()+18e5),e.Utils.createCookie("lead_session",1,n)
3
+ }this.pingSession()},resetInactiveFunc:function(){s=0,clearTimeout(u)},pingSession:function(t){a||(o||e.PageTracking.startSession(),i&&e.PageTracking.restartClock(),clearTimeout(c),c=setTimeout(e.PageTracking.setIdle,1e3*n+100),"undefined"!=typeof t&&"mousemove"===t.type&&e.PageTracking.mouseEvents(t))},mouseEvents:function(t){t.pageY<=5&&e.trigger("tab_mouseout")},getPageViews:function(){var t=e.Utils.checkLocalStorage();if(t){var n=localStorage.getItem("page_views"),o=JSON.parse(n);return o}},isRevisit:function(e){var t=!1,e=e||{},n=e[g];return"undefined"!=typeof n&&null!==n&&(t=!0),t},triggerPageView:function(t){var n={title:document.title,url:document.location.href,path:document.location.pathname,count:1};t?(m[g].push(f),n.count=m[g].length,e.trigger("page_revisit",n)):(m[g]=[],m[g].push(f),e.trigger("page_first_visit",n)),e.trigger("page_visit",n),e.totalStorage("page_views",m),this.storePageView()},CheckTimeOut:function(){var t,n,o=this.isRevisit(m);if(o){var i=m[g].length-1,a=m[g][i],r=Math.abs(new Date(a).getTime()-new Date(f).getTime());n=r>p,n?(t="Timeout Happened. Page view fired",this.triggerPageView(o)):(time_left=.001*Math.abs(p-r),t=p/1e3+" sec timeout not done: "+time_left+" seconds left")}else this.triggerPageView(o);e.deBugger("pages",t)},storePageView:function(){var t=e.Utils.readCookie("wp_lead_id"),n=e.Utils.readCookie("wp_lead_uid");if(t){var o={action:"wpl_track_user",wp_lead_uid:n,wp_lead_id:t,page_id:inbound_settings.post_id,current_url:window.location.href,json:"0"},i=function(){};e.Utils.ajaxPost(inbound_settings.admin_url,o,i)}}},e}(_inbound||{});_inbound.init(),InboundLeadData=_inbound.totalStorage("inbound_lead_data")||null;
shared/assets/frontend/js/inbound.js ADDED
@@ -0,0 +1,839 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Lead Tracking JS
3
+ * http://www.inboundnow.com
4
+ */
5
+ var InboundAnalytics = (function () {
6
+
7
+ var debugMode = false;
8
+
9
+ var _privateMethod = function () {
10
+ console.log('Run private');
11
+ };
12
+
13
+ var App = {
14
+ init: function () {
15
+ this.polyFills();
16
+ InboundAnalytics.PageTracking.StorePageView();
17
+ InboundAnalytics.Events.loadEvents();
18
+ InboundAnalytics.Utils.init();
19
+ },
20
+ polyFills: function() {
21
+ /* Console.log fix for old browsers */
22
+ if (!window.console) { window.console = {}; }
23
+ var m = [
24
+ "log", "info", "warn", "error", "debug", "trace", "dir", "group",
25
+ "groupCollapsed", "groupEnd", "time", "timeEnd", "profile", "profileEnd",
26
+ "dirxml", "assert", "count", "markTimeline", "timeStamp", "clear"
27
+ ];
28
+ // define undefined methods as noops to prevent errors
29
+ for (var i = 0; i < m.length; i++) {
30
+ if (!window.console[m[i]]) {
31
+ window.console[m[i]] = function() {};
32
+ }
33
+ }
34
+ },
35
+ /* Debugger Function toggled by var debugMode */
36
+ debug: function(msg,callback){
37
+ //if app not in debug mode, exit immediately
38
+ if(!debugMode || !console){return};
39
+ var msg = msg || false;
40
+ //console.log the message
41
+ if(msg && (typeof msg === 'string')){console.log(msg)};
42
+
43
+ //execute the callback if one was passed-in
44
+ if(callback && (callback instanceof Function)){
45
+ callback();
46
+ };
47
+ }
48
+ };
49
+
50
+ return App;
51
+
52
+ })();
53
+
54
+
55
+ /**
56
+ * Utility functions
57
+ * @param Object InboundAnalytics - Main JS object
58
+ * @return Object - include util functions
59
+ */
60
+ var InboundAnalyticsUtils = (function (InboundAnalytics) {
61
+
62
+ InboundAnalytics.Utils = {
63
+ init: function() {
64
+ this.setUrlParams();
65
+ this.SetUID();
66
+ this.getReferer();
67
+
68
+ },
69
+ // Create cookie
70
+ createCookie: function(name, value, days, custom_time) {
71
+ var expires = "";
72
+ if (days) {
73
+ var date = new Date();
74
+ date.setTime(date.getTime()+(days*24*60*60*1000));
75
+ expires = "; expires="+date.toGMTString();
76
+ }
77
+ if(custom_time){
78
+ expires = "; expires="+days.toGMTString();
79
+ }
80
+ document.cookie = name+"="+value+expires+"; path=/";
81
+ },
82
+ // Read cookie
83
+ readCookie: function(name) {
84
+ var nameEQ = name + "=";
85
+ var ca = document.cookie.split(';');
86
+ for(var i=0;i < ca.length;i++) {
87
+ var c = ca[i];
88
+ while (c.charAt(0) === ' ') {
89
+ c = c.substring(1,c.length);
90
+ }
91
+ if (c.indexOf(nameEQ) === 0) {
92
+ return c.substring(nameEQ.length,c.length);
93
+ }
94
+ }
95
+ return null;
96
+ },
97
+ // Erase cookie
98
+ eraseCookie: function(name) {
99
+ createCookie(name,"",-1);
100
+ },
101
+ getAllCookies: function(){
102
+ var cookies = {};
103
+ if (document.cookie && document.cookie != '') {
104
+ var split = document.cookie.split(';');
105
+ for (var i = 0; i < split.length; i++) {
106
+ var name_value = split[i].split("=");
107
+ name_value[0] = name_value[0].replace(/^ /, '');
108
+ cookies[decodeURIComponent(name_value[0])] = decodeURIComponent(name_value[1]);
109
+ }
110
+ }
111
+ jQuery.totalStorage('inbound_cookies', cookies); // store cookie data
112
+ return cookies;
113
+ },
114
+ /* Grab URL params and save */
115
+ setUrlParams: function() {
116
+ var urlParams = {},
117
+ local_store = InboundAnalytics.Utils.checkLocalStorage();
118
+
119
+ (function () {
120
+ var e,
121
+ d = function (s) { return decodeURIComponent(s).replace(/\+/g, " "); },
122
+ q = window.location.search.substring(1),
123
+ r = /([^&=]+)=?([^&]*)/g;
124
+
125
+ while (e = r.exec(q)) {
126
+ if (e[1].indexOf("[") == "-1")
127
+ urlParams[d(e[1])] = d(e[2]);
128
+ else {
129
+ var b1 = e[1].indexOf("["),
130
+ aN = e[1].slice(b1+1, e[1].indexOf("]", b1)),
131
+ pN = d(e[1].slice(0, b1));
132
+
133
+ if (typeof urlParams[pN] != "object")
134
+ urlParams[d(pN)] = {},
135
+ urlParams[d(pN)].length = 0;
136
+
137
+ if (aN)
138
+ urlParams[d(pN)][d(aN)] = d(e[2]);
139
+ else
140
+ Array.prototype.push.call(urlParams[d(pN)], d(e[2]));
141
+
142
+ }
143
+ }
144
+ })();
145
+
146
+ if (JSON) {
147
+ for (var k in urlParams) {
148
+ if (typeof urlParams[k] == "object") {
149
+ for (var k2 in urlParams[k])
150
+ this.createCookie(k2, urlParams[k][k2], 30);
151
+ } else {
152
+ this.createCookie(k, urlParams[k], 30);
153
+ }
154
+ }
155
+ }
156
+
157
+ if(local_store){
158
+ var pastParams = jQuery.totalStorage('inbound_url_params');
159
+ var params = this.mergeObjs(pastParams, urlParams);
160
+ jQuery.totalStorage('inbound_url_params', params); // store cookie data
161
+ }
162
+ },
163
+ getUrlParams: function(){
164
+ var local_store = this.checkLocalStorage(),
165
+ get_params = {};
166
+ if(local_store){
167
+ var get_params = jQuery.totalStorage('inbound_url_params');
168
+ }
169
+ return get_params;
170
+ },
171
+ // Check local storage
172
+ // provate browsing safari fix https://github.com/marcuswestin/store.js/issues/42#issuecomment-25274685
173
+ checkLocalStorage: function() {
174
+ if ('localStorage' in window) {
175
+ try {
176
+ ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
177
+ if (typeof ls == 'undefined' || typeof window.JSON == 'undefined'){
178
+ supported = false;
179
+ } else {
180
+ supported = true;
181
+ }
182
+
183
+ }
184
+ catch (err){
185
+ supported = false;
186
+ }
187
+ }
188
+ return supported;
189
+ /* http://spin.atomicobject.com/2013/01/23/ios-private-browsing-localstorage/
190
+ var hasStorage;
191
+ hasStorage = function() {
192
+ var mod, result;
193
+ try {
194
+ mod = new Date;
195
+ localStorage.setItem(mod, mod.toString());
196
+ result = localStorage.getItem(mod) === mod.toString();
197
+ localStorage.removeItem(mod);
198
+ return result;
199
+ } catch (_error) {}
200
+ };
201
+ */
202
+ },
203
+ /* Add days to datetime */
204
+ addDays: function(myDate,days) {
205
+ return new Date(myDate.getTime() + days*24*60*60*1000);
206
+ },
207
+ GetDate: function(){
208
+ var time_now = new Date(),
209
+ day = time_now.getDate() + 1;
210
+ year = time_now.getFullYear(),
211
+ hour = time_now.getHours(),
212
+ minutes = time_now.getMinutes(),
213
+ seconds = time_now.getSeconds(),
214
+ month = time_now.getMonth() + 1;
215
+ if (month < 10) { month = '0' + month; }
216
+ InboundAnalytics.debug('Current Date:',function(){
217
+ console.log(year + '/' + month + "/" + day + " " + hour + ":" + minutes + ":" + seconds);
218
+ });
219
+ var datetime = year + '/' + month + "/" + day + " " + hour + ":" + minutes + ":" + seconds;
220
+ return datetime;
221
+ },
222
+ /* Set Expiration Date of Session Logging */
223
+ SetSessionTimeout: function(){
224
+ var session_check = this.readCookie("lead_session_expire");
225
+ //console.log(session_check);
226
+ if(session_check === null){
227
+ InboundAnalytics.Events.sessionStart(); // trigger 'inbound_analytics_session_start'
228
+ } else {
229
+ InboundAnalytics.Events.sessionActive(); // trigger 'inbound_analytics_session_active'
230
+ }
231
+ var d = new Date();
232
+ d.setTime(d.getTime() + 30*60*1000);
233
+
234
+ this.createCookie("lead_session_expire", true, d, true); // Set cookie on page loads
235
+ var lead_data_expiration = this.readCookie("lead_data_expiration");
236
+ if (lead_data_expiration === null){
237
+ /* Set 3 day timeout for checking DB for new lead data for Lead_Global var */
238
+ var ex = this.addDays(d, 3);
239
+ this.createCookie("lead_data_expiration", ex, ex, true);
240
+ }
241
+
242
+ },
243
+ getReferer: function(){
244
+ //console.log(expire_time);
245
+ var d = new Date();
246
+ d.setTime(d.getTime() + 30*60*1000);
247
+ var referrer_cookie = InboundAnalytics.Utils.readCookie("wp_lead_referral_site");
248
+ if (typeof (referrer_cookie) === "undefined" || referrer_cookie === null || referrer_cookie === "") {
249
+ var referrer = document.referrer || "NA";
250
+ this.createCookie("wp_lead_referral_site", referrer, d, true); // Set cookie on page loads
251
+ }
252
+ },
253
+ CreateUID: function(length) {
254
+ var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(''),
255
+ str = '';
256
+ if (! length) {
257
+ length = Math.floor(Math.random() * chars.length);
258
+ }
259
+ for (var i = 0; i < length; i++) {
260
+ str += chars[Math.floor(Math.random() * chars.length)];
261
+ }
262
+ return str;
263
+ },
264
+ SetUID: function () {
265
+ /* Set Lead UID */
266
+
267
+ if(this.readCookie("wp_lead_uid") === null) {
268
+ var wp_lead_uid = this.CreateUID(35);
269
+ this.createCookie("wp_lead_uid", wp_lead_uid );
270
+ InboundAnalytics.debug('Set UID');
271
+ }
272
+ },
273
+ /* Count number of session visits */
274
+ countProperties: function (obj) {
275
+ var count = 0;
276
+ for(var prop in obj) {
277
+ if(obj.hasOwnProperty(prop))
278
+ ++count;
279
+ }
280
+ return count;
281
+ },
282
+ mergeObjs: function(obj1,obj2){
283
+ var obj3 = {};
284
+ for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
285
+ for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
286
+ return obj3;
287
+ },
288
+ doAjax: function(data, responseHandler, method, async){
289
+ // Set the variables
290
+ var url = wplft.admin_url || "",
291
+ method = method || "POST",
292
+ async = async || true,
293
+ data = data || null,
294
+ action = data.action;
295
+
296
+ InboundAnalytics.debug('Ajax Processed:',function(){
297
+ console.log('ran ajax action: ' + action);
298
+ });
299
+
300
+ jQuery.ajax({
301
+ type: method,
302
+ url: wplft.admin_url,
303
+ data: data,
304
+ success: responseHandler,
305
+ error: function(MLHttpRequest, textStatus, errorThrown){
306
+ console.log(MLHttpRequest+' '+errorThrown+' '+textStatus);
307
+ InboundAnalytics.Events.analyticsError(MLHttpRequest, textStatus, errorThrown);
308
+ }
309
+
310
+ });
311
+ },
312
+ /* Cross-browser event listening */
313
+ addListener: function(obj, eventName, listener) {
314
+ if(obj.addEventListener) {
315
+ obj.addEventListener(eventName, listener, false);
316
+ } else if (obj.attachEvent) {
317
+ obj.attachEvent("on" + eventName, listener);
318
+ } else {
319
+ obj['on' + eventName] = listener;
320
+ }
321
+ }
322
+
323
+ };
324
+
325
+ return InboundAnalytics;
326
+
327
+ })(InboundAnalytics || {});
328
+
329
+
330
+ var InboundAnalyticsPageTracking = (function (InboundAnalytics) {
331
+
332
+ InboundAnalytics.PageTracking = {
333
+
334
+ getPageViews: function () {
335
+ var local_store = InboundAnalytics.Utils.checkLocalStorage();
336
+ if(local_store){
337
+ var page_views = localStorage.getItem("page_views"),
338
+ local_object = JSON.parse(page_views);
339
+ if (typeof local_object =='object' && local_object) {
340
+ this.StorePageView();
341
+ }
342
+ return local_object;
343
+ }
344
+ },
345
+ StorePageView: function() {
346
+ var timeout = this.CheckTimeOut();
347
+ var pageviewObj = jQuery.totalStorage('page_views');
348
+ if(pageviewObj === null) {
349
+ pageviewObj = {};
350
+ }
351
+ var current_page_id = wplft.post_id;
352
+ var datetime = InboundAnalytics.Utils.GetDate();
353
+
354
+ if (timeout) {
355
+ // If pageviewObj exists, do this
356
+ var page_seen = pageviewObj[current_page_id];
357
+
358
+ if(typeof(page_seen) != "undefined" && page_seen !== null) {
359
+ pageviewObj[current_page_id].push(datetime);
360
+ /* Page Revisit Trigger */
361
+ var page_seen_count = pageviewObj[current_page_id].length;
362
+ InboundAnalytics.Events.pageRevisit(page_seen_count);
363
+
364
+ } else {
365
+ pageviewObj[current_page_id] = [];
366
+ pageviewObj[current_page_id].push(datetime);
367
+ /* Page First Seen Trigger */
368
+ var page_seen_count = 1;
369
+ InboundAnalytics.Events.pageFirstView(page_seen_count);
370
+ }
371
+
372
+ jQuery.totalStorage('page_views', pageviewObj);
373
+
374
+ }
375
+ },
376
+ CheckTimeOut: function() {
377
+ var PageViews = jQuery.totalStorage('page_views');
378
+ if(PageViews === null) {
379
+ var PageViews = {};
380
+ }
381
+ var page_id = wplft.post_id,
382
+ pageviewTimeout = true, /* Default */
383
+ page_seen = PageViews[page_id];
384
+ if(typeof(page_seen) != "undefined" && page_seen !== null) {
385
+
386
+ var time_now = InboundAnalytics.Utils.GetDate(),
387
+ vc = PageViews[page_id].length - 1,
388
+ last_view = PageViews[page_id][vc],
389
+ last_view_ms = new Date(last_view).getTime(),
390
+ time_now_ms = new Date(time_now).getTime(),
391
+ timeout_ms = last_view_ms + 30*1000,
392
+ time_check = Math.abs(last_view_ms - time_now_ms),
393
+ wait_time = 30000;
394
+
395
+ InboundAnalytics.debug('Timeout Checks =',function(){
396
+ console.log('Current Time is: ' + time_now);
397
+ console.log('Last view is: ' + last_view);
398
+ console.log("Last view milliseconds " + last_view_ms);
399
+ console.log("time now milliseconds " + time_now_ms);
400
+ console.log("Wait Check: " + wait_time);
401
+ console.log("TIME CHECK: " + time_check);
402
+ });
403
+
404
+ //var wait_time = Math.abs(last_view_ms - timeout_ms) // output timeout time 30sec;
405
+
406
+ if (time_check < wait_time){
407
+ time_left = Math.abs((wait_time - time_check)) * .001;
408
+ pageviewTimeout = false;
409
+ var status = '30 sec timeout not done: ' + time_left + " seconds left";
410
+ } else {
411
+ var status = 'Timeout Happened. Page view fired';
412
+ this.firePageView();
413
+ pageviewTimeout = true;
414
+ InboundAnalytics.Events.analyticsTriggered();
415
+ }
416
+
417
+ //InboundAnalytics.debug('',function(){
418
+ console.log(status);
419
+ //});
420
+ } else {
421
+ /* Page never seen before */
422
+ this.firePageView();
423
+ }
424
+
425
+ return pageviewTimeout;
426
+
427
+ },
428
+ firePageView: function() {
429
+ var lead_id = InboundAnalytics.Utils.readCookie('wp_lead_id'),
430
+ lead_uid = InboundAnalytics.Utils.readCookie('wp_lead_uid');
431
+
432
+ if (typeof (lead_id) != "undefined" && lead_id != null && lead_id != "") {
433
+
434
+ InboundAnalytics.debug('Run page view ajax');
435
+
436
+ var data = {
437
+ action: 'wpl_track_user',
438
+ wp_lead_uid: lead_uid,
439
+ wp_lead_id: lead_id,
440
+ page_id: wplft.post_id,
441
+ current_url: window.location.href,
442
+ json: '0'
443
+ };
444
+ var firePageCallback = function(user_id){
445
+ InboundAnalytics.Events.analyticsSaved();
446
+ };
447
+ InboundAnalytics.Utils.doAjax(data, firePageCallback);
448
+ }
449
+ }
450
+ }
451
+
452
+ return InboundAnalytics;
453
+
454
+ })(InboundAnalytics || {});
455
+
456
+
457
+ /**
458
+ * Leads API functions
459
+ * @param Object InboundAnalytics - Main JS object
460
+ * @return Object - include event triggers
461
+ */
462
+ var InboundAnalyticsLeadsAPI = (function (InboundAnalytics) {
463
+
464
+ InboundAnalytics.LeadsAPI = {
465
+ init: function() {
466
+
467
+ },
468
+ getAllLeadData: function(expire_check) {
469
+ var wp_lead_id = InboundAnalytics.Utils.readCookie("wp_lead_id"),
470
+ old_data = jQuery.totalStorage('inbound_lead_data'),
471
+ data = {
472
+ action: 'inbound_get_all_lead_data',
473
+ wp_lead_id: wp_lead_id,
474
+ },
475
+ success = function(returnData){
476
+ var obj = JSON.parse(returnData);
477
+ console.log('RAAAAAAn');
478
+ setGlobalLeadVar(obj);
479
+ jQuery.totalStorage('inbound_lead_data', obj); // store lead data
480
+ };
481
+
482
+ if(!old_data) {
483
+ console.log("No old data");
484
+ }
485
+
486
+ if (expire_check === 'true'){
487
+ console.log("Session has not expired");
488
+ }
489
+
490
+ if(!old_data && expire_check === null) {
491
+ InboundAnalytics.debug('Go to Database',function(){
492
+ console.log(expire_check);
493
+ console.log(old_data);
494
+ });
495
+ InboundAnalytics.Utils.doAjax(data, success);
496
+ } else {
497
+ setGlobalLeadVar(old_data); // set global lead var with localstorage data
498
+ var lead_data_expiration = InboundAnalytics.Utils.readCookie("lead_data_expiration");
499
+ if (lead_data_expiration === null) {
500
+ InboundAnalytics.Utils.doAjax(data, success);
501
+ console.log('localized data old. Pull new from DB');
502
+ }
503
+ }
504
+
505
+ },
506
+ getLeadLists: function() {
507
+ var wp_lead_id = InboundAnalytics.Utils.readCookie("wp_lead_id");
508
+ var data = {
509
+ action: 'wpl_check_lists',
510
+ wp_lead_id: wp_lead_id,
511
+ };
512
+ var success = function(user_id){
513
+ jQuery.cookie("lead_session_list_check", true, { path: '/', expires: 1 });
514
+ console.log("Lists checked");
515
+ };
516
+ InboundAnalytics.Utils.doAjax(data, success);
517
+ }
518
+ };
519
+
520
+ return InboundAnalytics;
521
+
522
+ })(InboundAnalytics || {});
523
+
524
+
525
+ /**
526
+ * Custom Event Triggers for Leads -
527
+ * The below functions illustrate how to use custom javascript callbacks to fire events
528
+ * based on lead data and what they have and have not done on the site.
529
+ */
530
+ /**
531
+
532
+ // Raw Javascript Version - trigger custom function on page view trigger
533
+
534
+ window.addEventListener("inbound_analytics_triggered", fireOnPageViewTrigger, false);
535
+ function fireOnPageViewTrigger(){
536
+ alert("page view was triggered");
537
+ }
538
+
539
+ // jQuery version - trigger custom function on analytics loaded
540
+
541
+ jQuery(document).on('inbound_analytics_loaded', function (event, data) {
542
+ console.log("inbound_analytics_loaded");
543
+ });
544
+
545
+ // Raw Javascript Version - trigger custom function on page first seen
546
+
547
+ window.addEventListener("inbound_analytics_page_first_view", page_first_seen_function, false);
548
+ function page_first_seen_function(){
549
+ alert("This is the first time you have seen this page");
550
+ }
551
+
552
+ // Raw Javascript Version - trigger custom function on page already seen
553
+
554
+ window.addEventListener("inbound_analytics_page_revisit", page_seen_function, false);
555
+ function page_seen_function(e){
556
+ var view_count = e.detail.count;
557
+ console.log("This page has been seen " + e.detail.count + " times");
558
+ if(view_count > 10){
559
+ console.log("Page has been viewed more than 10 times");
560
+ }
561
+ }
562
+
563
+ // jQuery version - trigger custom function on page already seen via jQuery
564
+
565
+ jQuery(document).on('inbound_analytics_page_revisit', function (event, data) {
566
+ console.log("inbound_analytics_page_revisit action triggered");
567
+ //console.log(data);
568
+ if(data.count > 10){
569
+ console.log("Page has been viewed more than 10 times");
570
+ }
571
+ });
572
+ */
573
+
574
+ /**
575
+ * Event functions
576
+ * @param Object InboundAnalytics - Main JS object
577
+ * @return Object - include event triggers
578
+ */
579
+ var InboundAnalyticsEvents = (function (InboundAnalytics) {
580
+
581
+ InboundAnalytics.Events = {
582
+ // Create cookie
583
+ loadEvents: function() {
584
+ this.analyticsLoaded();
585
+ },
586
+ triggerJQueryEvent: function(eventName, data){
587
+ if (window.jQuery) {
588
+ var data = data || {};
589
+ jQuery(document).trigger(eventName, data);
590
+ /* var something = (function() {
591
+ var executed = false;
592
+ return function () {
593
+ if (!executed) {
594
+ executed = true;
595
+ console.log(eventName + " RAN");
596
+
597
+ }
598
+ };
599
+ })();*/
600
+ }
601
+ },
602
+ analyticsLoaded: function() {
603
+ var eventName = "inbound_analytics_loaded";
604
+ var loaded = new CustomEvent(eventName);
605
+ window.dispatchEvent(loaded);
606
+ this.triggerJQueryEvent(eventName);
607
+ },
608
+ analyticsTriggered: function() {
609
+ var triggered = new CustomEvent("inbound_analytics_triggered");
610
+ window.dispatchEvent(triggered);
611
+ },
612
+ analyticsSaved: function() {
613
+ var page_view_saved = new CustomEvent("inbound_analytics_saved");
614
+ window.dispatchEvent(page_view_saved);
615
+ console.log('Page View Saved');
616
+ },
617
+ analyticsError: function(MLHttpRequest, textStatus, errorThrown) {
618
+ var error = new CustomEvent("inbound_analytics_error", {
619
+ detail: {
620
+ MLHttpRequest: MLHttpRequest,
621
+ textStatus: textStatus,
622
+ errorThrown: errorThrown
623
+ }
624
+ });
625
+ window.dispatchEvent(error);
626
+ console.log('Page Save Error');
627
+ },
628
+ pageFirstView: function(page_seen_count) {
629
+ var page_first_view = new CustomEvent("inbound_analytics_page_first_view", {
630
+ detail: {
631
+ count: 1,
632
+ time: new Date(),
633
+ },
634
+ bubbles: true,
635
+ cancelable: true
636
+ }
637
+ );
638
+ window.dispatchEvent(page_first_view);
639
+
640
+ console.log('First Ever Page View of this Page');
641
+ },
642
+ pageRevisit: function(page_seen_count) {
643
+ var eventName = "inbound_analytics_page_revisit";
644
+ var data = { count: page_seen_count,
645
+ time: new Date()
646
+ };
647
+ var page_revisit = new CustomEvent(eventName, {
648
+ detail: data,
649
+ bubbles: true,
650
+ cancelable: true
651
+ }
652
+ );
653
+ window.dispatchEvent(page_revisit);
654
+ this.triggerJQueryEvent(eventName, data);
655
+ console.log('Page Revisit');
656
+ },
657
+ sessionStart: function() {
658
+ var session_start = new CustomEvent("inbound_analytics_session_start");
659
+ window.dispatchEvent(session_start);
660
+ console.log('Session Start');
661
+ },
662
+ sessionActive: function() {
663
+ var session_active = new CustomEvent("inbound_analytics_session_active");
664
+ window.dispatchEvent(session_active);
665
+ console.log('Session Active');
666
+ },
667
+
668
+ };
669
+
670
+ return InboundAnalytics;
671
+
672
+ })(InboundAnalytics || {});
673
+
674
+ /* LocalStorage Component */
675
+ var InboundTotalStorage = (function (InboundAnalytics){
676
+
677
+ var supported, ls, mod = 'inboundAnalytics';
678
+ if ('localStorage' in window){
679
+ try {
680
+ ls = (typeof window.localStorage === 'undefined') ? undefined : window.localStorage;
681
+ if (typeof ls == 'undefined' || typeof window.JSON == 'undefined'){
682
+ supported = false;
683
+ } else {
684
+ supported = true;
685
+ }
686
+ window.localStorage.setItem(mod, '1');
687
+ window.localStorage.removeItem(mod);
688
+ }
689
+ catch (err){
690
+ supported = false;
691
+ }
692
+ }
693
+
694
+ /* Make the methods public */
695
+ InboundAnalytics.totalStorage = function(key, value, options){
696
+ return InboundAnalytics.totalStorage.impl.init(key, value);
697
+ };
698
+
699
+ InboundAnalytics.totalStorage.setItem = function(key, value){
700
+ return InboundAnalytics.totalStorage.impl.setItem(key, value);
701
+ };
702
+
703
+ InboundAnalytics.totalStorage.getItem = function(key){
704
+ return InboundAnalytics.totalStorage.impl.getItem(key);
705
+ };
706
+
707
+ InboundAnalytics.totalStorage.getAll = function(){
708
+ return InboundAnalytics.totalStorage.impl.getAll();
709
+ };
710
+
711
+ InboundAnalytics.totalStorage.deleteItem = function(key){
712
+ return InboundAnalytics.totalStorage.impl.deleteItem(key);
713
+ };
714
+
715
+ /* Object to hold all methods: public and private */
716
+
717
+ InboundAnalytics.totalStorage.impl = {
718
+
719
+ init: function(key, value){
720
+ if (typeof value != 'undefined') {
721
+ return this.setItem(key, value);
722
+ } else {
723
+ return this.getItem(key);
724
+ }
725
+ },
726
+
727
+ setItem: function(key, value){
728
+ if (!supported){
729
+ try {
730
+ InboundAnalytics.Utils.createCookie(key, value);
731
+ return value;
732
+ } catch(e){
733
+ console.log('Local Storage not supported by this browser. Install the cookie plugin on your site to take advantage of the same functionality. You can get it at https://github.com/carhartl/jquery-cookie');
734
+ }
735
+ }
736
+ var saver = JSON.stringify(value);
737
+ ls.setItem(key, saver);
738
+ return this.parseResult(saver);
739
+ },
740
+ getItem: function(key){
741
+ if (!supported){
742
+ try {
743
+ return this.parseResult(InboundAnalytics.Utils.readCookie(key));
744
+ } catch(e){
745
+ return null;
746
+ }
747
+ }
748
+ var item = ls.getItem(key);
749
+ return this.parseResult(item);
750
+ },
751
+ deleteItem: function(key){
752
+ if (!supported){
753
+ try {
754
+ InboundAnalytics.Utils.eraseCookie(key, null);
755
+ return true;
756
+ } catch(e){
757
+ return false;
758
+ }
759
+ }
760
+ ls.removeItem(key);
761
+ return true;
762
+ },
763
+ getAll: function(){
764
+ var items = [];
765
+ if (!supported){
766
+ try {
767
+ var pairs = document.cookie.split(";");
768
+ for (var i = 0; i<pairs.length; i++){
769
+ var pair = pairs[i].split('=');
770
+ var key = pair[0];
771
+ items.push({key:key, value:this.parseResult(InboundAnalytics.Utils.readCookie(key))});
772
+ }
773
+ } catch(e){
774
+ return null;
775
+ }
776
+ } else {
777
+ for (var j in ls){
778
+ if (j.length){
779
+ items.push({key:j, value:this.parseResult(ls.getItem(j))});
780
+ }
781
+ }
782
+ }
783
+ return items;
784
+ },
785
+ parseResult: function(res){
786
+ var ret;
787
+ try {
788
+ ret = JSON.parse(res);
789
+ if (typeof ret == 'undefined'){
790
+ ret = res;
791
+ }
792
+ if (ret == 'true'){
793
+ ret = true;
794
+ }
795
+ if (ret == 'false'){
796
+ ret = false;
797
+ }
798
+ if (parseFloat(ret) == ret && typeof ret != "object"){
799
+ ret = parseFloat(ret);
800
+ }
801
+ } catch(e){
802
+ ret = res;
803
+ }
804
+ return ret;
805
+ }
806
+ };
807
+ })(InboundAnalytics || {});
808
+
809
+
810
+ var Lead_Globals = jQuery.totalStorage('inbound_lead_data') || null;
811
+ function setGlobalLeadVar(retString){
812
+ Lead_Globals = retString;
813
+ }
814
+
815
+ InboundAnalytics.init(); // run analytics
816
+
817
+ /* run on ready */
818
+ jQuery(document).ready(function($) {
819
+ //record non conversion status
820
+ var in_u = InboundAnalytics.Utils,
821
+ wp_lead_uid = in_u.readCookie("wp_lead_uid"),
822
+ wp_lead_id = in_u.readCookie("wp_lead_id"),
823
+ expire_check = in_u.readCookie("lead_session_expire"); // check for session
824
+
825
+ if (expire_check === null) {
826
+ console.log('expired vistor. Run Processes');
827
+ //var data_to_lookup = global-localized-vars;
828
+ if (typeof (wp_lead_id) != "undefined" && wp_lead_id != null && wp_lead_id != "") {
829
+ /* Get Lead_Globals */
830
+ InboundAnalytics.LeadsAPI.getAllLeadData(expire_check);
831
+ /* Lead list check */
832
+ InboundAnalytics.LeadsAPI.getLeadLists();
833
+ }
834
+ }
835
+
836
+ /* Set Session Timeout */
837
+ InboundAnalytics.Utils.SetSessionTimeout();
838
+
839
+ });
shared/assets/frontend/js/store.lead.ajax.js CHANGED
@@ -217,6 +217,17 @@ function release_form_sub(this_form, element_type, form_type){
217
  this_form.unbind('submit');
218
  this_form.submit();
219
 
 
 
 
 
 
 
 
 
 
 
 
220
  if (form_type === "comment"){
221
  console.log("RELEASE ME");
222
  setTimeout(function() {
217
  this_form.unbind('submit');
218
  this_form.submit();
219
 
220
+ /* fallback if submit name="submit" */
221
+ setTimeout(function() {
222
+ var inputs = jQuery(this_form).find('input');
223
+ jQuery(inputs).each(function(){
224
+ var type = jQuery(this).attr('type');
225
+ if (type === "submit") {
226
+ jQuery(this).click();
227
+ }
228
+ });
229
+ }, 1000);
230
+
231
  if (form_type === "comment"){
232
  console.log("RELEASE ME");
233
  setTimeout(function() {
shared/classes/class.debug.php CHANGED
@@ -8,7 +8,7 @@ if (!defined('INBOUND_CLASS_URL'))
8
  define('INBOUND_CLASS_URL', plugin_dir_url(__FILE__));
9
 
10
  //update_option( 'inbound_global_dequeue', "" );
11
- /**
12
  $global_array = get_option( 'inbound_global_dequeue' );
13
  print_r($global_array);
14
  /**/
@@ -396,7 +396,7 @@ display: inline-block;}
396
  echo "</div>";
397
 
398
  // This will control the dequing
399
- /**
400
  foreach ($scripts_queued as $key => $value) {
401
  //echo $key . $value;
402
  if (!in_array($value, $white_list_scripts)){
8
  define('INBOUND_CLASS_URL', plugin_dir_url(__FILE__));
9
 
10
  //update_option( 'inbound_global_dequeue', "" );
11
+ /*
12
  $global_array = get_option( 'inbound_global_dequeue' );
13
  print_r($global_array);
14
  /**/
396
  echo "</div>";
397
 
398
  // This will control the dequing
399
+ /*
400
  foreach ($scripts_queued as $key => $value) {
401
  //echo $key . $value;
402
  if (!in_array($value, $white_list_scripts)){
shared/classes/class.feedback.php CHANGED
@@ -97,7 +97,7 @@ if (!class_exists('Inbound_Feedback')) {
97
  if ( ! self::$add_feedback || ! is_admin()) {
98
  return;
99
  }
100
-
101
  $screen = get_current_screen();
102
 
103
  $show_array = array(
@@ -117,7 +117,7 @@ if (!class_exists('Inbound_Feedback')) {
117
  "wp-call-to-action_page_wp_cta_manage_templates",
118
  "wp-call-to-action_page_wp_cta_global_settings"
119
  );
120
-
121
  $lp_page_array = array(
122
  "edit-landing-page",
123
  "landing-page_page_lp_global_settings",
@@ -125,14 +125,14 @@ if (!class_exists('Inbound_Feedback')) {
125
  "landing-page_page_lp_manage_templates",
126
  "edit-landing_page_category"
127
  );
128
-
129
  $leads_page_array = array(
130
  "wp-lead",
131
  "edit-wp-lead",
132
  "edit-list",
133
  "wp-lead_page_wpleads_global_settings",
134
  );
135
-
136
  $cta_page_array = array(
137
  "edit-wp-call-to-action",
138
  "wp-call-to-action",
@@ -140,11 +140,11 @@ if (!class_exists('Inbound_Feedback')) {
140
  "wp-call-to-action_page_wp_cta_manage_templates",
141
  "wp-call-to-action_page_wp_cta_global_settings"
142
  );
143
-
144
  if (!in_array($screen->id, $show_array)) {
145
- return;
146
  }
147
-
148
  $plugin_name = "Inbound Now Marketing Plugins"; // default
149
  if (in_array($screen->id, $lp_page_array)) {
150
  $plugin_name = "Landing Pages plugin";
@@ -160,7 +160,7 @@ if (!class_exists('Inbound_Feedback')) {
160
  <div class="inbound-close-fb">close</div>
161
  <div id="lp-slide-toggle">
162
  <header id="header" class='inbound-customhead'>
163
- <img src="<?php echo INBOUDNOW_SHARED_URLPATH . 'assets/admin/images/inbound-now-logo.png';?>" width="315px">
164
  <h3 class="main-feedback-header" >We love hearing from You!</h3>
165
  <h4>Please leave your <strong>idea/feature request</strong> to make the <?php echo $plugin_name;?> better below!</h4>
166
  </header>
97
  if ( ! self::$add_feedback || ! is_admin()) {
98
  return;
99
  }
100
+
101
  $screen = get_current_screen();
102
 
103
  $show_array = array(
117
  "wp-call-to-action_page_wp_cta_manage_templates",
118
  "wp-call-to-action_page_wp_cta_global_settings"
119
  );
120
+
121
  $lp_page_array = array(
122
  "edit-landing-page",
123
  "landing-page_page_lp_global_settings",
125
  "landing-page_page_lp_manage_templates",
126
  "edit-landing_page_category"
127
  );
128
+
129
  $leads_page_array = array(
130
  "wp-lead",
131
  "edit-wp-lead",
132
  "edit-list",
133
  "wp-lead_page_wpleads_global_settings",
134
  );
135
+
136
  $cta_page_array = array(
137
  "edit-wp-call-to-action",
138
  "wp-call-to-action",
140
  "wp-call-to-action_page_wp_cta_manage_templates",
141
  "wp-call-to-action_page_wp_cta_global_settings"
142
  );
143
+
144
  if (!in_array($screen->id, $show_array)) {
145
+ return;
146
  }
147
+
148
  $plugin_name = "Inbound Now Marketing Plugins"; // default
149
  if (in_array($screen->id, $lp_page_array)) {
150
  $plugin_name = "Landing Pages plugin";
160
  <div class="inbound-close-fb">close</div>
161
  <div id="lp-slide-toggle">
162
  <header id="header" class='inbound-customhead'>
163
+ <a href="http://www.inboundnow.com" target="_blank" title="Visit Inbound Now"><img src="<?php echo INBOUDNOW_SHARED_URLPATH . 'assets/admin/images/inbound-now-logo.png';?>" width="315px"></a>
164
  <h3 class="main-feedback-header" >We love hearing from You!</h3>
165
  <h4>Please leave your <strong>idea/feature request</strong> to make the <?php echo $plugin_name;?> better below!</h4>
166
  </header>
shared/classes/class.form.php CHANGED
@@ -111,15 +111,13 @@ class Inbound_Forms {
111
  $form_width = ($width != "") ? $width_output : '';
112
 
113
  //if (!preg_match_all("/(.?)\[(inbound_field)\b(.*?)(?:(\/))?\](?:(.+?)\[\/inbound_field\])?(.?)/s", $content, $matches)) {
114
- if (!preg_match_all('/(.?)\[(inbound_field)(.*?)\]/s',$content, $matches))
115
- {
116
  return '';
117
 
118
- }
119
- else
120
- {
121
- for($i = 0; $i < count($matches[0]); $i++)
122
- {
123
  $matches[3][$i] = shortcode_parse_atts($matches[3][$i]);
124
  }
125
  //print_r($matches[3]);
@@ -129,7 +127,7 @@ class Inbound_Forms {
129
 
130
 
131
  $form = '<div id="inbound-form-wrapper" class="">';
132
- $form .= '<form class="inbound-now-form wpl-track-me" method="post" id="'.$form_id.'" action="" style="'.$form_width.'">';
133
  $main_layout = ($form_layout != "") ? 'inbound-'.$form_layout : 'inbound-normal';
134
  for($i = 0; $i < count($matches[0]); $i++)
135
  {
@@ -143,16 +141,11 @@ class Inbound_Forms {
143
 
144
  $placeholder_use = ($field_placeholder != "") ? $field_placeholder : $label;
145
 
146
- if ($field_placeholder != "")
147
- {
148
  $form_placeholder = "placeholder='".$placeholder_use."'";
149
- }
150
- else if (isset($form_labels) && $form_labels === "placeholder")
151
- {
152
  $form_placeholder = "placeholder='".$placeholder_use."'";
153
- }
154
- else
155
- {
156
  $form_placeholder = "";
157
  }
158
 
@@ -170,6 +163,7 @@ class Inbound_Forms {
170
  $field_name = strtolower(str_replace(array(' ','_'),'-',$label));
171
  }
172
 
 
173
 
174
  /* Map Common Fields */
175
  (preg_match( '/Email|e-mail|email/i', $label, $email_input)) ? $email_input = " inbound-email" : $email_input = "";
@@ -192,18 +186,17 @@ class Inbound_Forms {
192
  $show_labels = false;
193
  }
194
 
195
- $form .= '<div class="inbound-field '.$main_layout.' label-'.$form_labels_class.' '.$field_container_class.'">';
196
 
197
- if ($show_labels && $form_labels != "bottom" || $type === "radio")
198
- {
199
  $form .= '<label for="'. $field_name .'" class="inbound-label '.$formatted_label.' '.$form_labels_class.' inbound-input-'.$type.'" style="'.$font_size.'">' . $matches[3][$i]['label'] . $req_label . '</label>';
200
  }
201
 
202
  if ($type === 'textarea') {
203
- $form .= '<textarea placeholder="'.$placeholder_use.'" class="inbound-input inbound-input-textarea '.$field_input_class.'" name="'.$field_name.'" id="in_'.$field_name.'" '.$req.'/></textarea>';
204
- }
205
- else if ($type === 'dropdown')
206
- {
207
  $dropdown_fields = array();
208
  $dropdown = $matches[3][$i]['dropdown'];
209
  $dropdown_fields = explode(",", $dropdown);
@@ -235,9 +228,9 @@ class Inbound_Forms {
235
  $form .= '<option value="'.$key.'">'. utf8_encode($value) .'</option>';
236
  }
237
  $form .= '</select>';
238
- }
239
- else if ($type === 'date-selector')
240
- {
241
  $m = date('m');
242
  $d = date('d');
243
  $y = date('Y');
@@ -267,21 +260,21 @@ class Inbound_Forms {
267
  $form .= ' </select>';
268
  $form .= '</div>';
269
 
270
- }
271
- else if ($type === 'radio')
272
- {
273
  $radio_fields = array();
274
  $radio = $matches[3][$i]['radio'];
275
  $radio_fields = explode(",", $radio);
276
  // $clean_radio = str_replace(array(' ','_'),'-',$value) // clean leading spaces. finish
277
 
278
- foreach ($radio_fields as $key => $value)
279
- {
280
  $radio_val_trimmed = trim($value);
281
  $radio_val = strtolower(str_replace(array(' ','_'),'-',$radio_val_trimmed));
282
  $form .= '<span class="radio-'.$main_layout.' radio-'.$form_labels_class.' '.$field_input_class.'"><input type="radio" name="'. $field_name .'" value="'. $radio_val .'">'. $radio_val_trimmed .'</span>';
283
  }
 
284
  } else if ($type === 'checkbox') {
 
285
  $checkbox_fields = array();
286
 
287
  $checkbox = $matches[3][$i]['checkbox'];
@@ -298,19 +291,25 @@ class Inbound_Forms {
298
  $form .= '<input class="checkbox-'.$main_layout.' checkbox-'.$form_labels_class.' '.$field_input_class.'" type="checkbox" name="'. $field_name .'[]" value="'. $checkbox_val .'" '.$required_id.'>'.$checkbox_val_trimmed.'<br>';
299
  }
300
  } else if ($type === 'html-block') {
 
301
  $html = $matches[3][$i]['html'];
302
  //echo $html;
303
  $form .= "<div class={$field_input_class}>";
304
  $form .= do_shortcode(html_entity_decode($html));
305
  $form .= "</div>";
 
306
  } else if ($type === 'divider') {
 
307
  $divider = $matches[3][$i]['divider_options'];
308
  //echo $html;
309
  $form .= "<div class='inbound-form-divider {$field_input_class}'>" . $divider . "<hr></div>";
 
310
  } else if ($type === 'editor') {
311
  //wp_editor(); // call wp editor
312
  } else if ($type === 'honeypot') {
 
313
  $form .= '<input type="hidden" name="stop_dirty_subs" class="stop_dirty_subs" value="">';
 
314
  } else {
315
  $hidden_param = (isset($matches[3][$i]['dynamic'])) ? $matches[3][$i]['dynamic'] : '';
316
  $fill_value = (isset($matches[3][$i]['default'])) ? $matches[3][$i]['default'] : '';
@@ -318,8 +317,9 @@ class Inbound_Forms {
318
  if ($type === 'hidden' && $dynamic_value != "") {
319
  $fill_value = $dynamic_value;
320
  }
321
- $form .= '<input class="inbound-input inbound-input-text '.$formatted_label . $input_classes.' '.$field_input_class.'" name="'.$field_name.'" '.$form_placeholder.' id="'.$formatted_label.'" value="'.$fill_value.'" type="'.$type.'" '.$req.'/>';
322
  }
 
323
  if ($show_labels && $form_labels === "bottom" && $type != "radio") {
324
  $form .= '<label for="'. $field_name .'" class="inbound-label '.$formatted_label.' '.$form_labels_class.' inbound-input-'.$type.'" style="'.$font_size.'">' . $matches[3][$i]['label'] . $req_label . '</label>';
325
  }
@@ -333,11 +333,11 @@ class Inbound_Forms {
333
  // End Loop
334
 
335
  $current_page = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
336
- $form .= '<div class="inbound-field '.$main_layout.' inbound-submit-area"><button type="submit" class="inbound-button-submit inbound-submit-action" value="'.$submit_button.'" name="send" id="inbound_form_submit" style="'.$submit_bg.$submit_color.$image_button.'">
337
- '.$icon_insert.''.$submit_button.$inner_button.'</button></div><input type="hidden" name="inbound_submitted" value="1">';
338
  // <!--<input type="submit" '.$submit_button_type.' class="button" value="'.$submit_button.'" name="send" id="inbound_form_submit" />-->
339
 
340
- $form .= '<input type="hidden" name="inbound_form_name" class="inbound_form_name" value="'.$form_name.'"><input type="hidden" name="inbound_form_lists" id="inbound_form_lists" value="'.$lists.'"><input type="hidden" name="inbound_form_id" class="inbound_form_id" value="'.$id.'"><input type="hidden" name="inbound_current_page_url" value="'.$current_page.'"><input type="hidden" name="inbound_furl" value="'. base64_encode($redirect) .'"><input type="hidden" name="inbound_notify" value="'. base64_encode($notify) .'"><input type="hidden" class="inbound_params" name="inbound_params" value=""></form></div>';
341
  $form .= "<style type='text/css'>.inbound-button-submit{ {$font_size} }</style>";
342
  $form = preg_replace('/<br class="inbr".\/>/', '', $form); // remove editor br tags
343
 
@@ -421,215 +421,7 @@ class Inbound_Forms {
421
  return;
422
 
423
  echo '<script type="text/javascript">
424
- if (typeof Mailcheck === "undefined") {
425
- var Mailcheck = {
426
- domainThreshold: 1,
427
- topLevelThreshold: 3,
428
-
429
- defaultDomains: ["yahoo.com", "google.com", "hotmail.com", "gmail.com", "me.com", "aol.com", "mac.com",
430
- "live.com", "comcast.net", "googlemail.com", "msn.com", "hotmail.co.uk", "yahoo.co.uk",
431
- "facebook.com", "verizon.net", "sbcglobal.net", "att.net", "gmx.com", "mail.com", "outlook.com", "icloud.com"],
432
-
433
- defaultTopLevelDomains: ["co.jp", "co.uk", "com", "net", "org", "info", "edu", "gov", "mil", "ca"],
434
-
435
- run: function(opts) {
436
- opts.domains = opts.domains || Mailcheck.defaultDomains;
437
- opts.topLevelDomains = opts.topLevelDomains || Mailcheck.defaultTopLevelDomains;
438
- opts.distanceFunction = opts.distanceFunction || Mailcheck.sift3Distance;
439
-
440
- var defaultCallback = function(result){ return result };
441
- var suggestedCallback = opts.suggested || defaultCallback;
442
- var emptyCallback = opts.empty || defaultCallback;
443
-
444
- var result = Mailcheck.suggest(Mailcheck.encodeEmail(opts.email), opts.domains, opts.topLevelDomains, opts.distanceFunction);
445
-
446
- return result ? suggestedCallback(result) : emptyCallback()
447
- },
448
-
449
- suggest: function(email, domains, topLevelDomains, distanceFunction) {
450
- email = email.toLowerCase();
451
-
452
- var emailParts = this.splitEmail(email);
453
-
454
- var closestDomain = this.findClosestDomain(emailParts.domain, domains, distanceFunction, this.domainThreshold);
455
-
456
- if (closestDomain) {
457
- if (closestDomain != emailParts.domain) {
458
- // The email address closely matches one of the supplied domains; return a suggestion
459
- return { address: emailParts.address, domain: closestDomain, full: emailParts.address + "@" + closestDomain };
460
- }
461
- } else {
462
- // The email address does not closely match one of the supplied domains
463
- var closestTopLevelDomain = this.findClosestDomain(emailParts.topLevelDomain, topLevelDomains, distanceFunction, this.topLevelThreshold);
464
- if (emailParts.domain && closestTopLevelDomain && closestTopLevelDomain != emailParts.topLevelDomain) {
465
- // The email address may have a mispelled top-level domain; return a suggestion
466
- var domain = emailParts.domain;
467
- closestDomain = domain.substring(0, domain.lastIndexOf(emailParts.topLevelDomain)) + closestTopLevelDomain;
468
- return { address: emailParts.address, domain: closestDomain, full: emailParts.address + "@" + closestDomain };
469
- }
470
- }
471
- /* The email address exactly matches one of the supplied domains, does not closely
472
- * match any domain and does not appear to simply have a mispelled top-level domain,
473
- * or is an invalid email address; do not return a suggestion.
474
- */
475
- return false;
476
- },
477
-
478
- findClosestDomain: function(domain, domains, distanceFunction, threshold) {
479
- threshold = threshold || this.topLevelThreshold;
480
- var dist;
481
- var minDist = 99;
482
- var closestDomain = null;
483
-
484
- if (!domain || !domains) {
485
- return false;
486
- }
487
- if(!distanceFunction) {
488
- distanceFunction = this.sift3Distance;
489
- }
490
-
491
- for (var i = 0; i < domains.length; i++) {
492
- if (domain === domains[i]) {
493
- return domain;
494
- }
495
- dist = distanceFunction(domain, domains[i]);
496
- if (dist < minDist) {
497
- minDist = dist;
498
- closestDomain = domains[i];
499
- }
500
- }
501
-
502
- if (minDist <= threshold && closestDomain !== null) {
503
- return closestDomain;
504
- } else {
505
- return false;
506
- }
507
- },
508
-
509
- sift3Distance: function(s1, s2) {
510
- // sift3: http://siderite.blogspot.com/2007/04/super-fast-and-accurate-string-distance.html
511
- if (s1 == null || s1.length === 0) {
512
- if (s2 == null || s2.length === 0) {
513
- return 0;
514
- } else {
515
- return s2.length;
516
- }
517
- }
518
-
519
- if (s2 == null || s2.length === 0) {
520
- return s1.length;
521
- }
522
-
523
- var c = 0;
524
- var offset1 = 0;
525
- var offset2 = 0;
526
- var lcs = 0;
527
- var maxOffset = 5;
528
-
529
- while ((c + offset1 < s1.length) && (c + offset2 < s2.length)) {
530
- if (s1.charAt(c + offset1) == s2.charAt(c + offset2)) {
531
- lcs++;
532
- } else {
533
- offset1 = 0;
534
- offset2 = 0;
535
- for (var i = 0; i < maxOffset; i++) {
536
- if ((c + i < s1.length) && (s1.charAt(c + i) == s2.charAt(c))) {
537
- offset1 = i;
538
- break;
539
- }
540
- if ((c + i < s2.length) && (s1.charAt(c) == s2.charAt(c + i))) {
541
- offset2 = i;
542
- break;
543
- }
544
- }
545
- }
546
- c++;
547
- }
548
- return (s1.length + s2.length) /2 - lcs;
549
- },
550
-
551
- splitEmail: function(email) {
552
- var parts = email.trim().split("@");
553
-
554
- if (parts.length < 2) {
555
- return false;
556
- }
557
-
558
- for (var i = 0; i < parts.length; i++) {
559
- if (parts[i] === "") {
560
- return false;
561
- }
562
- }
563
-
564
- var domain = parts.pop();
565
- var domainParts = domain.split(".");
566
- var tld = "";
567
-
568
- if (domainParts.length == 0) {
569
- // The address does not have a top-level domain
570
- return false;
571
- } else if (domainParts.length == 1) {
572
- // The address has only a top-level domain (valid under RFC)
573
- tld = domainParts[0];
574
- } else {
575
- // The address has a domain and a top-level domain
576
- for (var i = 1; i < domainParts.length; i++) {
577
- tld += domainParts[i] + ".";
578
- }
579
- if (domainParts.length >= 2) {
580
- tld = tld.substring(0, tld.length - 1);
581
- }
582
- }
583
-
584
- return {
585
- topLevelDomain: tld,
586
- domain: domain,
587
- address: parts.join("@")
588
- }
589
- },
590
-
591
- // Encode the email address to prevent XSS but leave in valid
592
- // characters, following this official spec:
593
- // http://en.wikipedia.org/wiki/Email_address#Syntax
594
- encodeEmail: function(email) {
595
- var result = encodeURI(email);
596
- result = result.replace("%20", " ").replace("%25", "%").replace("%5E", "^")
597
- .replace("%60", "`").replace("%7B", "{").replace("%7C", "|")
598
- .replace("%7D", "}");
599
- return result;
600
- }
601
- };
602
-
603
- // Export the mailcheck object if we"re in a CommonJS env (e.g. Node).
604
- // Modeled off of Underscore.js.
605
- if (typeof module !== "undefined" && module.exports) {
606
- module.exports = Mailcheck;
607
- }
608
 
609
- if (typeof window !== "undefined" && window.jQuery) {
610
- (function($){
611
- $.fn.mailcheck = function(opts) {
612
- var self = this;
613
- if (opts.suggested) {
614
- var oldSuggested = opts.suggested;
615
- opts.suggested = function(result) {
616
- oldSuggested(self, result);
617
- };
618
- }
619
-
620
- if (opts.empty) {
621
- var oldEmpty = opts.empty;
622
- opts.empty = function() {
623
- oldEmpty.call(null, self);
624
- };
625
- }
626
-
627
- opts.email = this.val();
628
- Mailcheck.run(opts);
629
- }
630
- })(jQuery);
631
- };
632
- }
633
  jQuery(document).ready(function($){
634
 
635
  jQuery("form").submit(function(e) {
@@ -643,25 +435,7 @@ class Inbound_Forms {
643
  }
644
  });
645
  });
646
- $(".inbound-email").on("blur", function(event) {
647
- //console.log("event ", event);
648
- //console.log("this ", $(this));
649
- var that = $(this);
650
- $(this).mailcheck({
651
-
652
- suggested: function(element, suggestion) {
653
- // callback code
654
- console.log("suggestion ", suggestion.full);
655
- $(".email_suggestion").remove();
656
- var insert = "<span class=\"email_suggestion\">Did you mean <b><i>" + suggestion.full + "</b></i>?</span>";
657
- $(that).after(insert);
658
- },
659
- empty: function(element) {
660
- // callback code
661
- $(".email_suggestion").html("No Suggestions :(");
662
- }
663
- });
664
- });
665
  jQuery("#inbound_form_submit br").remove(); // remove br tags
666
  function validateEmail(email) {
667
 
@@ -780,7 +554,7 @@ class Inbound_Forms {
780
  //print_r($_POST);
781
  foreach ( $_POST as $field => $value ) {
782
 
783
- if ( get_magic_quotes_gpc() ) {
784
  $value = stripslashes( $value );
785
  }
786
 
@@ -793,17 +567,6 @@ class Inbound_Forms {
793
  }
794
  }
795
 
796
- if (preg_match( '/(?<!((last |last_)))name(?!\=)/im', $field) && !isset($form_post_data['wpleads_first_name'])) {
797
- $field = "wpleads_first_name";
798
- }
799
-
800
- if (preg_match( '/(?<!((first)))(last name|last_name|last)(?!\=)/im', $field) && !isset($form_post_data['wpleads_last_name'])) {
801
- $field = "wpleads_last_name";
802
- }
803
-
804
- if (preg_match( '/Phone|phone number|telephone/i', $field)) {
805
- $field = "wpleads_work_phone";
806
- }
807
 
808
  $form_post_data[$field] = (!is_array($value)) ? strip_tags( $value ) : $value;
809
 
@@ -958,19 +721,9 @@ class Inbound_Forms {
958
  $content = apply_filters('the_content', $content);
959
  $content = str_replace(']]>', ']]&gt;', $content);
960
 
961
- $confirm_email_message = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
962
- <html>
963
- <head>
964
- <meta http-equiv="Content-Type" content="text/html;' . get_option('blog_charset') . '" />
965
- </head>
966
- <body style="margin: 0px; background-color: #F4F3F4; font-family: Helvetica, Arial, sans-serif; font-size:12px;" text="#444444" bgcolor="#F4F3F4" link="#21759B" alink="#21759B" vlink="#21759B" marginheight="0" topmargin="0" marginwidth="0" leftmargin="0">
967
- <table cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff" border="0">
968
- <tr>';
969
  $confirm_email_message .= $content;
970
- $confirm_email_message .= '</tr>
971
- </table>
972
- </body>
973
- </html>';
974
  }
975
 
976
 
111
  $form_width = ($width != "") ? $width_output : '';
112
 
113
  //if (!preg_match_all("/(.?)\[(inbound_field)\b(.*?)(?:(\/))?\](?:(.+?)\[\/inbound_field\])?(.?)/s", $content, $matches)) {
114
+ if (!preg_match_all('/(.?)\[(inbound_field)(.*?)\]/s',$content, $matches)) {
115
+
116
  return '';
117
 
118
+ } else {
119
+
120
+ for($i = 0; $i < count($matches[0]); $i++) {
 
 
121
  $matches[3][$i] = shortcode_parse_atts($matches[3][$i]);
122
  }
123
  //print_r($matches[3]);
127
 
128
 
129
  $form = '<div id="inbound-form-wrapper" class="">';
130
+ $form .= '<form class="inbound-now-form wpl-track-me inbound-track" method="post" id="'.$form_id.'" action="" style="'.$form_width.'">';
131
  $main_layout = ($form_layout != "") ? 'inbound-'.$form_layout : 'inbound-normal';
132
  for($i = 0; $i < count($matches[0]); $i++)
133
  {
141
 
142
  $placeholder_use = ($field_placeholder != "") ? $field_placeholder : $label;
143
 
144
+ if ($field_placeholder != "") {
 
145
  $form_placeholder = "placeholder='".$placeholder_use."'";
146
+ } else if (isset($form_labels) && $form_labels === "placeholder") {
 
 
147
  $form_placeholder = "placeholder='".$placeholder_use."'";
148
+ } else {
 
 
149
  $form_placeholder = "";
150
  }
151
 
163
  $field_name = strtolower(str_replace(array(' ','_'),'-',$label));
164
  }
165
 
166
+ $data_mapping_attr = ($map_field != "") ? ' data-map-form-field="'.$map_field.'" ' : '';
167
 
168
  /* Map Common Fields */
169
  (preg_match( '/Email|e-mail|email/i', $label, $email_input)) ? $email_input = " inbound-email" : $email_input = "";
186
  $show_labels = false;
187
  }
188
 
189
+ $form .= '<div class="inbound-field '.$main_layout.' label-'.$form_labels_class.' '.$form_labels_class.' '.$field_container_class.'">';
190
 
191
+ if ($show_labels && $form_labels != "bottom" || $type === "radio") {
 
192
  $form .= '<label for="'. $field_name .'" class="inbound-label '.$formatted_label.' '.$form_labels_class.' inbound-input-'.$type.'" style="'.$font_size.'">' . $matches[3][$i]['label'] . $req_label . '</label>';
193
  }
194
 
195
  if ($type === 'textarea') {
196
+ $form .= '<textarea placeholder="'.$placeholder_use.'" class="inbound-input inbound-input-textarea '.$field_input_class.'" name="'.$field_name.'" id="'.$field_name.'" '.$req.'/></textarea>';
197
+
198
+ } else if ($type === 'dropdown') {
199
+
200
  $dropdown_fields = array();
201
  $dropdown = $matches[3][$i]['dropdown'];
202
  $dropdown_fields = explode(",", $dropdown);
228
  $form .= '<option value="'.$key.'">'. utf8_encode($value) .'</option>';
229
  }
230
  $form .= '</select>';
231
+
232
+ } else if ($type === 'date-selector') {
233
+
234
  $m = date('m');
235
  $d = date('d');
236
  $y = date('Y');
260
  $form .= ' </select>';
261
  $form .= '</div>';
262
 
263
+ } else if ($type === 'radio') {
264
+
 
265
  $radio_fields = array();
266
  $radio = $matches[3][$i]['radio'];
267
  $radio_fields = explode(",", $radio);
268
  // $clean_radio = str_replace(array(' ','_'),'-',$value) // clean leading spaces. finish
269
 
270
+ foreach ($radio_fields as $key => $value) {
 
271
  $radio_val_trimmed = trim($value);
272
  $radio_val = strtolower(str_replace(array(' ','_'),'-',$radio_val_trimmed));
273
  $form .= '<span class="radio-'.$main_layout.' radio-'.$form_labels_class.' '.$field_input_class.'"><input type="radio" name="'. $field_name .'" value="'. $radio_val .'">'. $radio_val_trimmed .'</span>';
274
  }
275
+
276
  } else if ($type === 'checkbox') {
277
+
278
  $checkbox_fields = array();
279
 
280
  $checkbox = $matches[3][$i]['checkbox'];
291
  $form .= '<input class="checkbox-'.$main_layout.' checkbox-'.$form_labels_class.' '.$field_input_class.'" type="checkbox" name="'. $field_name .'[]" value="'. $checkbox_val .'" '.$required_id.'>'.$checkbox_val_trimmed.'<br>';
292
  }
293
  } else if ($type === 'html-block') {
294
+
295
  $html = $matches[3][$i]['html'];
296
  //echo $html;
297
  $form .= "<div class={$field_input_class}>";
298
  $form .= do_shortcode(html_entity_decode($html));
299
  $form .= "</div>";
300
+
301
  } else if ($type === 'divider') {
302
+
303
  $divider = $matches[3][$i]['divider_options'];
304
  //echo $html;
305
  $form .= "<div class='inbound-form-divider {$field_input_class}'>" . $divider . "<hr></div>";
306
+
307
  } else if ($type === 'editor') {
308
  //wp_editor(); // call wp editor
309
  } else if ($type === 'honeypot') {
310
+
311
  $form .= '<input type="hidden" name="stop_dirty_subs" class="stop_dirty_subs" value="">';
312
+
313
  } else {
314
  $hidden_param = (isset($matches[3][$i]['dynamic'])) ? $matches[3][$i]['dynamic'] : '';
315
  $fill_value = (isset($matches[3][$i]['default'])) ? $matches[3][$i]['default'] : '';
317
  if ($type === 'hidden' && $dynamic_value != "") {
318
  $fill_value = $dynamic_value;
319
  }
320
+ $form .= '<input class="inbound-input inbound-input-text '.$formatted_label . $input_classes.' '.$field_input_class.'" name="'.$field_name.'" '.$form_placeholder.' id="'.$field_name.'" value="'.$fill_value.'" type="'.$type.'"'.$data_mapping_attr.' '.$req.'/>';
321
  }
322
+
323
  if ($show_labels && $form_labels === "bottom" && $type != "radio") {
324
  $form .= '<label for="'. $field_name .'" class="inbound-label '.$formatted_label.' '.$form_labels_class.' inbound-input-'.$type.'" style="'.$font_size.'">' . $matches[3][$i]['label'] . $req_label . '</label>';
325
  }
333
  // End Loop
334
 
335
  $current_page = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
336
+ $form .= '<div class="inbound-field '.$main_layout.' inbound-submit-area"><button type="submit" class="inbound-button-submit inbound-submit-action" value="'.$submit_button.'" name="send" id="inbound_form_submit" data-ignore-form-field="true" style="'.$submit_bg.$submit_color.$image_button.'">
337
+ '.$icon_insert.''.$submit_button.$inner_button.'</button></div><input data-ignore-form-field="true" type="hidden" name="inbound_submitted" value="1">';
338
  // <!--<input type="submit" '.$submit_button_type.' class="button" value="'.$submit_button.'" name="send" id="inbound_form_submit" />-->
339
 
340
+ $form .= '<input type="hidden" name="inbound_form_name" class="inbound_form_name" value="'.$form_name.'"><input type="hidden" name="inbound_form_lists" id="inbound_form_lists" value="'.$lists.'" data-map-form-field="inbound_form_lists"><input type="hidden" name="inbound_form_id" class="inbound_form_id" value="'.$id.'"><input type="hidden" name="inbound_current_page_url" value="'.$current_page.'"><input type="hidden" name="inbound_furl" value="'. base64_encode($redirect) .'"><input type="hidden" name="inbound_notify" value="'. base64_encode($notify) .'"><input type="hidden" class="inbound_params" name="inbound_params" value=""></form></div>';
341
  $form .= "<style type='text/css'>.inbound-button-submit{ {$font_size} }</style>";
342
  $form = preg_replace('/<br class="inbr".\/>/', '', $form); // remove editor br tags
343
 
421
  return;
422
 
423
  echo '<script type="text/javascript">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
425
  jQuery(document).ready(function($){
426
 
427
  jQuery("form").submit(function(e) {
435
  }
436
  });
437
  });
438
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  jQuery("#inbound_form_submit br").remove(); // remove br tags
440
  function validateEmail(email) {
441
 
554
  //print_r($_POST);
555
  foreach ( $_POST as $field => $value ) {
556
 
557
+ if ( get_magic_quotes_gpc() && is_string($value) ) {
558
  $value = stripslashes( $value );
559
  }
560
 
567
  }
568
  }
569
 
 
 
 
 
 
 
 
 
 
 
 
570
 
571
  $form_post_data[$field] = (!is_array($value)) ? strip_tags( $value ) : $value;
572
 
721
  $content = apply_filters('the_content', $content);
722
  $content = str_replace(']]>', ']]&gt;', $content);
723
 
724
+ $confirm_email_message = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html><head><meta http-equiv="Content-Type" content="text/html;' . get_option('blog_charset') . '" /></head><body style="margin: 0px; background-color: #F4F3F4; font-family: Helvetica, Arial, sans-serif; font-size:12px;" text="#444444" bgcolor="#F4F3F4" link="#21759B" alink="#21759B" vlink="#21759B" marginheight="0" topmargin="0" marginwidth="0" leftmargin="0"><table cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff" border="0"><tr>';
 
 
 
 
 
 
 
725
  $confirm_email_message .= $content;
726
+ $confirm_email_message .= '</tr></table></body></html>';
 
 
 
727
  }
728
 
729
 
shared/classes/class.lead-fields.php CHANGED
@@ -3,235 +3,235 @@
3
  if ( !class_exists('Leads_Field_Map') ) {
4
 
5
  class Leads_Field_Map {
6
-
7
- static $field_map;
8
-
9
  /* Define Default Lead Fields */
10
  public static function get_lead_fields() {
11
-
12
  $lead_fields = array(
13
  array(
14
  'label' => __( 'First Name' , 'leads' ) ,
15
  'key' => 'wpleads_first_name',
16
- 'priority' => 1,
17
  'type' => 'text'
18
  ),
19
  array(
20
  'label' => __( 'Last Name' , 'leads' ) ,
21
  'key' => 'wpleads_last_name',
22
- 'priority' => 10,
23
  'type' => 'text'
24
  ),
25
  array(
26
  'label' => __( 'Email' , 'leads' ) ,
27
  'key' => 'wpleads_email_address',
28
- 'priority' => 20,
29
  'type' => 'text'
30
  ),
31
  array(
32
  'label' => __( 'Website' , 'leads' ) ,
33
  'key' => 'wpleads_website',
34
- 'priority' => 30,
35
  'type' => 'text'
36
  ),
37
  array(
38
  'label' => __( 'Job Title' , 'leads' ) ,
39
  'key' => 'wpleads_job_title',
40
- 'priority' => 40,
41
  'type' => 'text'
42
  ),
43
  array(
44
  'label' => __( 'Company Name' , 'leads' ) ,
45
  'key' => 'wpleads_company_name',
46
- 'priority' => 50,
47
  'type' => 'text'
48
  ),
49
  array(
50
  'label' => __( 'Mobile Phone' , 'leads' ) ,
51
  'key' => 'wpleads_mobile_phone',
52
- 'priority' => 60,
53
  'type' => 'text'
54
  ),
55
  array(
56
  'label' => __( 'Work Phone' , 'leads' ) ,
57
  'key' => 'wpleads_work_phone',
58
- 'priority' => 70,
59
  'type' => 'text'
60
  ),
61
  array(
62
  'label' => __( 'Address' , 'leads' ) ,
63
  'key' => 'wpleads_address_line_1',
64
- 'priority' => 80,
65
  'type' => 'text'
66
  ),
67
  array(
68
  'label' => __( 'Address Continued' , 'leads' ) ,
69
  'key' => 'wpleads_address_line_2',
70
- 'priority' => 81,
71
  'type' => 'text'
72
  ),
73
  array(
74
  'label' => __( 'City' , 'leads' ) ,
75
  'key' => 'wpleads_city',
76
- 'priority' => 90,
77
  'type' => 'text'
78
  ),
79
  array(
80
  'label' => __( 'State/Region' , 'leads' ) ,
81
  'key' => 'wpleads_region_name',
82
- 'priority' => 100,
83
  'type' => 'text'
84
  ),
85
  array(
86
  'label' => __( 'Zip-code' , 'leads' ) ,
87
  'key' => 'wpleads_zip',
88
- 'priority' => 110,
89
  'type' => 'text'
90
- ),
91
 
92
  array(
93
  'label' => __( 'Country' , 'leads' ) ,
94
  'key' => 'wpleads_country_code',
95
- 'priority' => 120,
96
  'type' => 'text'
97
- ),
98
  array(
99
  'label' => __( 'Billing First Name' , 'leads' ) ,
100
  'key' => 'wpleads_billing_first_name',
101
- 'priority' => 130,
102
  'type' => 'text'
103
- ),
104
  array(
105
  'label' => __( 'Billing Last Name' , 'leads' ) ,
106
  'key' => 'wpleads_billing_last_name',
107
  'priority' => 120,
108
  'type' => 'text'
109
- ),
110
  array(
111
  'label' => __( 'Billing Company' , 'leads' ) ,
112
  'key' => 'wpleads_billing_company_name',
113
- 'priority' => 120,
114
  'type' => 'text'
115
- ),
116
  array(
117
  'label' => __( 'Billing Address' , 'leads' ) ,
118
  'key' => 'wpleads_billing_address_line_1',
119
- 'priority' => 140,
120
  'type' => 'text'
121
  ),
122
  array(
123
  'label' => __( 'Billing Address Continued' , 'leads' ) ,
124
  'key' => 'wpleads_billing_address_line_2',
125
- 'priority' => 150,
126
  'type' => 'text'
127
  ),
128
  array(
129
  'label' => __( 'Billing City' , 'leads' ) ,
130
  'key' => 'wpleads_billing_city',
131
- 'priority' => 160,
132
  'type' => 'text'
133
  ),
134
  array(
135
  'label' => __( 'Billing State/Region' , 'leads' ) ,
136
  'key' => 'wpleads_billing_region_name',
137
- 'priority' => 170,
138
  'type' => 'text'
139
  ),
140
  array(
141
  'label' => __( 'Billing Zip-code' , 'leads' ) ,
142
  'key' => 'wpleads_billing_zip',
143
- 'priority' => 180,
144
  'type' => 'text'
145
- ),
146
 
147
  array(
148
  'label' => __( 'Billing Country' , 'leads' ) ,
149
  'key' => 'wpleads_billing_country_code',
150
- 'priority' => 190,
151
  'type' => 'text'
152
- ),
153
  array(
154
  'label' => __( 'Shipping First Name' , 'leads' ) ,
155
  'key' => 'wpleads_shipping_first_name',
156
- 'priority' => 200,
157
  'type' => 'text'
158
  ),
159
  array(
160
  'label' => __( 'Shipping Last Name' , 'leads' ) ,
161
  'key' => 'wpleads_shipping_last_name',
162
- 'priority' => 210,
163
  'type' => 'text'
164
- ),
165
  array(
166
  'label' => __( 'Shipping Company Name' , 'leads' ) ,
167
  'key' => 'wpleads_shipping_company_name',
168
- 'priority' => 210,
169
  'type' => 'text'
170
- ),
171
  array(
172
  'label' => __( 'Shipping Address' , 'leads' ) ,
173
  'key' => 'wpleads_shipping_address_line_1',
174
- 'priority' => 220,
175
  'type' => 'text'
176
  ),
177
  array(
178
  'label' => __( 'Shipping Address Continued' , 'leads' ) ,
179
  'key' => 'wpleads_shipping_address_line_2',
180
- 'priority' => 230,
181
  'type' => 'text'
182
  ),
183
  array(
184
  'label' => __( 'Shipping City' , 'leads' ) ,
185
  'key' => 'wpleads_shipping_city',
186
- 'priority' => 240,
187
  'type' => 'text'
188
  ),
189
  array(
190
  'label' => __( 'Shipping State/Region' , 'leads' ) ,
191
  'key' => 'wpleads_shipping_region_name',
192
- 'priority' => 250,
193
  'type' => 'text'
194
  ),
195
  array(
196
  'label' => __( 'Shipping Zip-code' , 'leads' ) ,
197
  'key' => 'wpleads_shipping_zip',
198
- 'priority' => 260,
199
  'type' => 'text'
200
  ),
201
  array(
202
  'label' => __( 'Shipping Country' , 'leads' ) ,
203
  'key' => 'wpleads_shipping_country_code',
204
- 'priority' => 270,
205
  'type' => 'text'
206
  ),
207
  array(
208
  'label' => __( 'Related Websites' , 'leads' ) ,
209
  'key' => 'wpleads_websites',
210
- 'priority' => 280,
211
  'type' => 'links'
212
  ),
213
  array(
214
  'label' => __( 'Notes' , 'leads' ) ,
215
  'key' => 'wpleads_notes',
216
- 'priority' => 290,
217
  'type' => 'textarea'
218
  ),
219
  array(
220
  'label' => __( 'Twitter Account' , 'leads' ) ,
221
  'key' => 'wpleads_social_youtube',
222
- 'priority' => 290,
223
  'type' => 'text'
224
  ),
225
  array(
226
  'label' => __( 'Youtube Account' , 'leads' ) ,
227
  'key' => 'wpleads_social_youtube',
228
- 'priority' => 290,
229
  'type' => 'text'
230
  ),
231
  array(
232
  'label' => __( 'Facebook Account' , 'leads' ) ,
233
  'key' => 'wpleads_social_facebook',
234
- 'priority' => 290,
235
  'type' => 'text'
236
  )
237
 
@@ -243,10 +243,14 @@ if ( !class_exists('Leads_Field_Map') ) {
243
  }
244
 
245
 
246
- /* Builds key=>label array of lead fields */
 
 
 
247
  public static function build_map_array() {
248
- $lead_fields = Leads_Field_Map::get_lead_fields();
249
 
 
 
250
 
251
  $field_map = array();
252
  $field_map[''] = 'No Mapping'; // default empty
@@ -255,15 +259,44 @@ if ( !class_exists('Leads_Field_Map') ) {
255
  $key = $field['key'];
256
  $field_map[$key] = $label;
257
  }
258
-
259
  return $field_map;
260
  }
261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
263
 
264
  }
265
 
266
-
267
  /**
268
  * Add in custom lead fields
269
  *
@@ -274,7 +307,7 @@ if ( !class_exists('Leads_Field_Map') ) {
274
  * type: type of user area. 'text' or 'textarea'
275
  */
276
 
277
- /**
278
  add_filter('wp_leads_add_lead_field', 'custom_add_more_lead_fields', 10, 1);
279
  function custom_add_more_lead_fields($lead_fields) {
280
 
@@ -313,4 +346,3 @@ function custom_add_more_lead_fields($lead_fields) {
313
 
314
  }
315
  /**/
316
- ?>
3
  if ( !class_exists('Leads_Field_Map') ) {
4
 
5
  class Leads_Field_Map {
6
+
7
+ static $field_map;
8
+
9
  /* Define Default Lead Fields */
10
  public static function get_lead_fields() {
11
+
12
  $lead_fields = array(
13
  array(
14
  'label' => __( 'First Name' , 'leads' ) ,
15
  'key' => 'wpleads_first_name',
16
+ 'priority' => 20,
17
  'type' => 'text'
18
  ),
19
  array(
20
  'label' => __( 'Last Name' , 'leads' ) ,
21
  'key' => 'wpleads_last_name',
22
+ 'priority' => 30,
23
  'type' => 'text'
24
  ),
25
  array(
26
  'label' => __( 'Email' , 'leads' ) ,
27
  'key' => 'wpleads_email_address',
28
+ 'priority' => 40,
29
  'type' => 'text'
30
  ),
31
  array(
32
  'label' => __( 'Website' , 'leads' ) ,
33
  'key' => 'wpleads_website',
34
+ 'priority' => 50,
35
  'type' => 'text'
36
  ),
37
  array(
38
  'label' => __( 'Job Title' , 'leads' ) ,
39
  'key' => 'wpleads_job_title',
40
+ 'priority' => 60,
41
  'type' => 'text'
42
  ),
43
  array(
44
  'label' => __( 'Company Name' , 'leads' ) ,
45
  'key' => 'wpleads_company_name',
46
+ 'priority' => 70,
47
  'type' => 'text'
48
  ),
49
  array(
50
  'label' => __( 'Mobile Phone' , 'leads' ) ,
51
  'key' => 'wpleads_mobile_phone',
52
+ 'priority' => 80,
53
  'type' => 'text'
54
  ),
55
  array(
56
  'label' => __( 'Work Phone' , 'leads' ) ,
57
  'key' => 'wpleads_work_phone',
58
+ 'priority' => 90,
59
  'type' => 'text'
60
  ),
61
  array(
62
  'label' => __( 'Address' , 'leads' ) ,
63
  'key' => 'wpleads_address_line_1',
64
+ 'priority' => 100,
65
  'type' => 'text'
66
  ),
67
  array(
68
  'label' => __( 'Address Continued' , 'leads' ) ,
69
  'key' => 'wpleads_address_line_2',
70
+ 'priority' => 110,
71
  'type' => 'text'
72
  ),
73
  array(
74
  'label' => __( 'City' , 'leads' ) ,
75
  'key' => 'wpleads_city',
76
+ 'priority' => 120,
77
  'type' => 'text'
78
  ),
79
  array(
80
  'label' => __( 'State/Region' , 'leads' ) ,
81
  'key' => 'wpleads_region_name',
82
+ 'priority' => 130,
83
  'type' => 'text'
84
  ),
85
  array(
86
  'label' => __( 'Zip-code' , 'leads' ) ,
87
  'key' => 'wpleads_zip',
88
+ 'priority' => 140,
89
  'type' => 'text'
90
+ ),
91
 
92
  array(
93
  'label' => __( 'Country' , 'leads' ) ,
94
  'key' => 'wpleads_country_code',
95
+ 'priority' => 150,
96
  'type' => 'text'
97
+ ),
98
  array(
99
  'label' => __( 'Billing First Name' , 'leads' ) ,
100
  'key' => 'wpleads_billing_first_name',
101
+ 'priority' => 160,
102
  'type' => 'text'
103
+ ),
104
  array(
105
  'label' => __( 'Billing Last Name' , 'leads' ) ,
106
  'key' => 'wpleads_billing_last_name',
107
  'priority' => 120,
108
  'type' => 'text'
109
+ ),
110
  array(
111
  'label' => __( 'Billing Company' , 'leads' ) ,
112
  'key' => 'wpleads_billing_company_name',
113
+ 'priority' => 170,
114
  'type' => 'text'
115
+ ),
116
  array(
117
  'label' => __( 'Billing Address' , 'leads' ) ,
118
  'key' => 'wpleads_billing_address_line_1',
119
+ 'priority' => 180,
120
  'type' => 'text'
121
  ),
122
  array(
123
  'label' => __( 'Billing Address Continued' , 'leads' ) ,
124
  'key' => 'wpleads_billing_address_line_2',
125
+ 'priority' => 190,
126
  'type' => 'text'
127
  ),
128
  array(
129
  'label' => __( 'Billing City' , 'leads' ) ,
130
  'key' => 'wpleads_billing_city',
131
+ 'priority' => 200,
132
  'type' => 'text'
133
  ),
134
  array(
135
  'label' => __( 'Billing State/Region' , 'leads' ) ,
136
  'key' => 'wpleads_billing_region_name',
137
+ 'priority' => 210,
138
  'type' => 'text'
139
  ),
140
  array(
141
  'label' => __( 'Billing Zip-code' , 'leads' ) ,
142
  'key' => 'wpleads_billing_zip',
143
+ 'priority' => 220,
144
  'type' => 'text'
145
+ ),
146
 
147
  array(
148
  'label' => __( 'Billing Country' , 'leads' ) ,
149
  'key' => 'wpleads_billing_country_code',
150
+ 'priority' => 230,
151
  'type' => 'text'
152
+ ),
153
  array(
154
  'label' => __( 'Shipping First Name' , 'leads' ) ,
155
  'key' => 'wpleads_shipping_first_name',
156
+ 'priority' => 240,
157
  'type' => 'text'
158
  ),
159
  array(
160
  'label' => __( 'Shipping Last Name' , 'leads' ) ,
161
  'key' => 'wpleads_shipping_last_name',
162
+ 'priority' => 250,
163
  'type' => 'text'
164
+ ),
165
  array(
166
  'label' => __( 'Shipping Company Name' , 'leads' ) ,
167
  'key' => 'wpleads_shipping_company_name',
168
+ 'priority' => 260,
169
  'type' => 'text'
170
+ ),
171
  array(
172
  'label' => __( 'Shipping Address' , 'leads' ) ,
173
  'key' => 'wpleads_shipping_address_line_1',
174
+ 'priority' => 270,
175
  'type' => 'text'
176
  ),
177
  array(
178
  'label' => __( 'Shipping Address Continued' , 'leads' ) ,
179
  'key' => 'wpleads_shipping_address_line_2',
180
+ 'priority' => 280,
181
  'type' => 'text'
182
  ),
183
  array(
184
  'label' => __( 'Shipping City' , 'leads' ) ,
185
  'key' => 'wpleads_shipping_city',
186
+ 'priority' => 290,
187
  'type' => 'text'
188
  ),
189
  array(
190
  'label' => __( 'Shipping State/Region' , 'leads' ) ,
191
  'key' => 'wpleads_shipping_region_name',
192
+ 'priority' => 300,
193
  'type' => 'text'
194
  ),
195
  array(
196
  'label' => __( 'Shipping Zip-code' , 'leads' ) ,
197
  'key' => 'wpleads_shipping_zip',
198
+ 'priority' => 310,
199
  'type' => 'text'
200
  ),
201
  array(
202
  'label' => __( 'Shipping Country' , 'leads' ) ,
203
  'key' => 'wpleads_shipping_country_code',
204
+ 'priority' => 320,
205
  'type' => 'text'
206
  ),
207
  array(
208
  'label' => __( 'Related Websites' , 'leads' ) ,
209
  'key' => 'wpleads_websites',
210
+ 'priority' => 330,
211
  'type' => 'links'
212
  ),
213
  array(
214
  'label' => __( 'Notes' , 'leads' ) ,
215
  'key' => 'wpleads_notes',
216
+ 'priority' => 340,
217
  'type' => 'textarea'
218
  ),
219
  array(
220
  'label' => __( 'Twitter Account' , 'leads' ) ,
221
  'key' => 'wpleads_social_youtube',
222
+ 'priority' => 350,
223
  'type' => 'text'
224
  ),
225
  array(
226
  'label' => __( 'Youtube Account' , 'leads' ) ,
227
  'key' => 'wpleads_social_youtube',
228
+ 'priority' => 360,
229
  'type' => 'text'
230
  ),
231
  array(
232
  'label' => __( 'Facebook Account' , 'leads' ) ,
233
  'key' => 'wpleads_social_facebook',
234
+ 'priority' => 370,
235
  'type' => 'text'
236
  )
237
 
243
  }
244
 
245
 
246
+
247
+ /**
248
+ * Builds key=>label array of lead fields
249
+ */
250
  public static function build_map_array() {
 
251
 
252
+ $lead_fields = Leads_Field_Map::get_lead_fields();
253
+ $lead_fields = Leads_Field_Map::prioritize_lead_fields( $lead_fields );
254
 
255
  $field_map = array();
256
  $field_map[''] = 'No Mapping'; // default empty
259
  $key = $field['key'];
260
  $field_map[$key] = $label;
261
  }
262
+
263
  return $field_map;
264
  }
265
 
266
+ /**
267
+ * Priorize Lead Fields Array
268
+ * @param ARRAY $fields simplified id => label array of lead fields
269
+ * @param STRING $sort_flags default = SORT_ASC
270
+ */
271
+ public static function prioritize_lead_fields( $fields , $sort_flags=SORT_ASC) {
272
+
273
+ $prioritized = array();
274
+ foreach ($fields as $key => $value) {
275
+ while (isset($prioritized[$value['priority']])) {
276
+ $value['priority']++;
277
+ }
278
+ $prioritized[$value['priority']] = $value;
279
+ }
280
+
281
+ ksort($prioritized, $sort_flags);
282
+
283
+ return array_values($prioritized);
284
+
285
+ }
286
+
287
+ /**
288
+ * Gets lead field
289
+ * @param $lead_id
290
+ * @param $field_key
291
+ */
292
+ public static function get_field( $lead_id , $field_key ) {
293
+ return get_post_meta( $lead_id , $field_key , true);
294
+ }
295
+
296
  }
297
 
298
  }
299
 
 
300
  /**
301
  * Add in custom lead fields
302
  *
307
  * type: type of user area. 'text' or 'textarea'
308
  */
309
 
310
+ /*
311
  add_filter('wp_leads_add_lead_field', 'custom_add_more_lead_fields', 10, 1);
312
  function custom_add_more_lead_fields($lead_fields) {
313
 
346
 
347
  }
348
  /**/
 
shared/classes/class.load-shared.php CHANGED
@@ -4,10 +4,10 @@
4
  if (!class_exists('Inbound_Load_Shared')) {
5
 
6
  class Inbound_Load_Shared {
7
-
8
  /**
9
  * Initialize shared component loading only once.
10
- *
11
  */
12
  public static function init() {
13
  /* Bail if shared files already loaded */
@@ -19,12 +19,12 @@ if (!class_exists('Inbound_Load_Shared')) {
19
  self::load_files();
20
  self::load_legacy_elements();
21
  self::load_activation_rules();
22
-
23
  }
24
-
25
  /**
26
  * Define constants used by shared files here
27
- *
28
  */
29
  public static function load_constants() {
30
  define( 'INBOUDNOW_SHARED' , 'loaded' );
@@ -32,27 +32,38 @@ if (!class_exists('Inbound_Load_Shared')) {
32
  define( 'INBOUDNOW_SHARED_URLPATH' , self::get_shared_urlpath() );
33
  define( 'INBOUDNOW_SHARED_FILE' , self::get_shared_file() );
34
  }
35
-
36
  /**
37
  * Include shared php files here
38
- *
39
  */
40
- public static function load_files() {
41
 
42
- include_once( INBOUDNOW_SHARED_PATH . 'classes/class.post-type.wp-lead.php');
43
- include_once( INBOUDNOW_SHARED_PATH . 'classes/class.post-type.email-template.php');
44
- include_once( INBOUDNOW_SHARED_PATH . 'classes/class.form.php'); // Mirrored forms
45
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.menu.php'); // Inbound Marketing Menu
46
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.feedback.php'); // Inbound Feedback Form
47
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.debug.php'); // Inbound Debug & Scripts Class
48
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.compatibility.php'); // Inbound Compatibility Class
49
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.templating-engine.php'); // {{token}} Replacement Engine
50
- include_once( INBOUDNOW_SHARED_PATH . 'classes/class.shortcodes.email-template.php');
51
- include_once( INBOUDNOW_SHARED_PATH . 'classes/class.lead-fields.php');
52
- include_once( INBOUDNOW_SHARED_PATH . 'classes/class.inbound-forms.akismet.php');
53
- include_once( INBOUDNOW_SHARED_PATH . 'classes/class.welcome.php');
54
- include_once( INBOUDNOW_SHARED_PATH . 'tracking/store.lead.php'); // Lead Storage from landing pages
55
-
 
 
 
 
 
 
 
 
 
 
 
56
  include_once( INBOUDNOW_SHARED_PATH . 'shortcodes/inbound-shortcodes.php'); // Shared Shortcodes
57
  include_once( INBOUDNOW_SHARED_PATH . 'extend/inboundnow.extend.php');
58
  include_once( INBOUDNOW_SHARED_PATH . 'extend/inboundnow.global-settings.php'); // Inboundnow Global Settings
@@ -62,29 +73,29 @@ if (!class_exists('Inbound_Load_Shared')) {
62
 
63
  self::load_legacy_elements();
64
  }
65
-
66
  /**
67
  * Legacy constants go here
68
- *
69
- *
70
  */
71
  public static function load_legacy_elements() {
72
-
73
  if ( !defined( 'LANDINGPAGES_TEXT_DOMAIN' ) ) {
74
  define('LANDINGPAGES_TEXT_DOMAIN', 'landing-pages' );
75
  }
76
-
77
  if (!defined('INBOUNDNOW_LABEL')) {
78
  define('INBOUNDNOW_LABEL', 'inboundnow-legacy' );
79
  }
80
-
81
  }
82
-
83
  /**
84
  * Returns the correct absolute path to the Inbound Now shared directory
85
- *
86
  * @return Path to shared folder
87
- *
88
  */
89
  public static function get_shared_path() {
90
  if ( defined('WP_CTA_PATH') ) {
@@ -95,12 +106,12 @@ if (!class_exists('Inbound_Load_Shared')) {
95
  return WPL_PATH . '/shared/';
96
  }
97
  }
98
-
99
  /**
100
  * Returns the correct URL path to the Inbound Now Shared directory
101
- *
102
  * @return URL path to shared directory
103
- *
104
  */
105
  public static function get_shared_urlpath() {
106
  if ( defined('WP_CTA_URLPATH') ) {
@@ -111,12 +122,12 @@ if (!class_exists('Inbound_Load_Shared')) {
111
  return WPL_URLPATH . '/shared/';
112
  }
113
  }
114
-
115
  /**
116
- * Returns the correct __FILE__ string
117
- *
118
  * @return plugin path/filename.php
119
- *
120
  */
121
  public static function get_shared_file() {
122
  if ( defined('WP_CTA_FILE') ) {
@@ -127,26 +138,26 @@ if (!class_exists('Inbound_Load_Shared')) {
127
  return WPL_FILE;
128
  }
129
  }
130
-
131
  /**
132
  * Hooks shared activation rules into admin_init
133
  */
134
  public static function load_activation_rules() {
135
  add_action('admin_init' , array( __CLASS__ , 'run_activation_rules') );
136
  }
137
-
138
  /**
139
- * Run activation rules hosted in shared directory
140
  */
141
  public static function run_activation_rules() {
142
  if ( is_admin() && get_option( 'Inbound_Activate' ) ) {
143
-
144
  /* Delete activation trigger */
145
  delete_option( 'Inbound_Activate' );
146
-
147
  /* Run activation action hook for shared components */
148
  do_action( 'inbound_shared_activate' );
149
  }
150
  }
151
- }
152
  }
4
  if (!class_exists('Inbound_Load_Shared')) {
5
 
6
  class Inbound_Load_Shared {
7
+
8
  /**
9
  * Initialize shared component loading only once.
10
+ *
11
  */
12
  public static function init() {
13
  /* Bail if shared files already loaded */
19
  self::load_files();
20
  self::load_legacy_elements();
21
  self::load_activation_rules();
22
+
23
  }
24
+
25
  /**
26
  * Define constants used by shared files here
27
+ *
28
  */
29
  public static function load_constants() {
30
  define( 'INBOUDNOW_SHARED' , 'loaded' );
32
  define( 'INBOUDNOW_SHARED_URLPATH' , self::get_shared_urlpath() );
33
  define( 'INBOUDNOW_SHARED_FILE' , self::get_shared_file() );
34
  }
35
+
36
  /**
37
  * Include shared php files here
38
+ *
39
  */
40
+ public static function load_files() {
41
 
42
+ include_once( INBOUDNOW_SHARED_PATH . 'classes/class.post-type.wp-lead.php');
43
+ include_once( INBOUDNOW_SHARED_PATH . 'classes/class.post-type.email-template.php');
44
+ include_once( INBOUDNOW_SHARED_PATH . 'classes/class.form.php'); // Mirrored forms
45
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.menu.php'); // Inbound Marketing Menu
46
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.feedback.php'); // Inbound Feedback Form
47
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.debug.php'); // Inbound Debug & Scripts Class
48
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.compatibility.php'); // Inbound Compatibility Class
49
  include_once( INBOUDNOW_SHARED_PATH . 'classes/class.templating-engine.php'); // {{token}} Replacement Engine
50
+ include_once( INBOUDNOW_SHARED_PATH . 'classes/class.shortcodes.email-template.php');
51
+ include_once( INBOUDNOW_SHARED_PATH . 'classes/class.lead-fields.php');
52
+ include_once( INBOUDNOW_SHARED_PATH . 'classes/class.inbound-forms.akismet.php');
53
+ include_once( INBOUDNOW_SHARED_PATH . 'classes/class.welcome.php');
54
+
55
+ //include_once( INBOUDNOW_SHARED_PATH . 'tracking/store.lead.php'); // Lead Storage from landing pages
56
+
57
+ include_once( INBOUDNOW_SHARED_PATH . 'tracking/new.store.lead.php'); // Lead Storage from landing pages
58
+
59
+ /*
60
+ if (!defined('InboundAnalytics_v2')) {
61
+ include_once( INBOUDNOW_SHARED_PATH . 'tracking/store.lead.php'); // Lead Storage from landing pages
62
+ } else {
63
+ include_once( INBOUDNOW_SHARED_PATH . 'tracking/new.store.lead.php'); // Lead Storage from landing pages
64
+ }*/
65
+
66
+
67
  include_once( INBOUDNOW_SHARED_PATH . 'shortcodes/inbound-shortcodes.php'); // Shared Shortcodes
68
  include_once( INBOUDNOW_SHARED_PATH . 'extend/inboundnow.extend.php');
69
  include_once( INBOUDNOW_SHARED_PATH . 'extend/inboundnow.global-settings.php'); // Inboundnow Global Settings
73
 
74
  self::load_legacy_elements();
75
  }
76
+
77
  /**
78
  * Legacy constants go here
79
+ *
80
+ *
81
  */
82
  public static function load_legacy_elements() {
83
+
84
  if ( !defined( 'LANDINGPAGES_TEXT_DOMAIN' ) ) {
85
  define('LANDINGPAGES_TEXT_DOMAIN', 'landing-pages' );
86
  }
87
+
88
  if (!defined('INBOUNDNOW_LABEL')) {
89
  define('INBOUNDNOW_LABEL', 'inboundnow-legacy' );
90
  }
91
+
92
  }
93
+
94
  /**
95
  * Returns the correct absolute path to the Inbound Now shared directory
96
+ *
97
  * @return Path to shared folder
98
+ *
99
  */
100
  public static function get_shared_path() {
101
  if ( defined('WP_CTA_PATH') ) {
106
  return WPL_PATH . '/shared/';
107
  }
108
  }
109
+
110
  /**
111
  * Returns the correct URL path to the Inbound Now Shared directory
112
+ *
113
  * @return URL path to shared directory
114
+ *
115
  */
116
  public static function get_shared_urlpath() {
117
  if ( defined('WP_CTA_URLPATH') ) {
122
  return WPL_URLPATH . '/shared/';
123
  }
124
  }
125
+
126
  /**
127
+ * Returns the correct __FILE__ string
128
+ *
129
  * @return plugin path/filename.php
130
+ *
131
  */
132
  public static function get_shared_file() {
133
  if ( defined('WP_CTA_FILE') ) {
138
  return WPL_FILE;
139
  }
140
  }
141
+
142
  /**
143
  * Hooks shared activation rules into admin_init
144
  */
145
  public static function load_activation_rules() {
146
  add_action('admin_init' , array( __CLASS__ , 'run_activation_rules') );
147
  }
148
+
149
  /**
150
+ * Run activation rules hosted in shared directory
151
  */
152
  public static function run_activation_rules() {
153
  if ( is_admin() && get_option( 'Inbound_Activate' ) ) {
154
+
155
  /* Delete activation trigger */
156
  delete_option( 'Inbound_Activate' );
157
+
158
  /* Run activation action hook for shared components */
159
  do_action( 'inbound_shared_activate' );
160
  }
161
  }
162
+ }
163
  }
shared/classes/class.post-type.email-template.php CHANGED
@@ -69,7 +69,7 @@ if ( !class_exists('Inbound_Email_Templates_Post_Type') ) {
69
 
70
  $args = array(
71
  'labels' => $labels,
72
- 'public' => true,
73
  'publicly_queryable' => true,
74
  'show_ui' => true,
75
  'query_var' => true,
@@ -247,7 +247,7 @@ Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC
247
  'wp_user_password' => stripslashes($plaintext_pass),
248
  'wp_user_nicename' => stripslashes($user->nice_name),
249
  'wp_user_displayname' => stripslashes($user->display_name),
250
- 'wp_user_gravatar_url' => 'http://www.gravatar.com/avatar/00000000000000000000000000000000',
251
  ),
252
  /* lead data */
253
  array(
69
 
70
  $args = array(
71
  'labels' => $labels,
72
+ 'public' => false,
73
  'publicly_queryable' => true,
74
  'show_ui' => true,
75
  'query_var' => true,
247
  'wp_user_password' => stripslashes($plaintext_pass),
248
  'wp_user_nicename' => stripslashes($user->nice_name),
249
  'wp_user_displayname' => stripslashes($user->display_name),
250
+ 'wp_user_gravatar_url' => '//www.gravatar.com/avatar/00000000000000000000000000000000',
251
  ),
252
  /* lead data */
253
  array(
shared/classes/class.shortcodes.email-template.php CHANGED
@@ -133,7 +133,7 @@ class Inbound_Email_Template_Shortcodes {
133
  'default' => 'mm'
134
  ), $atts ) );
135
 
136
- return "http://www.gravatar.com/avatar/" . md5( strtolower( trim( $email ) ) ) . "?d=" . urlencode( $default ) . "&s=" . $size;
137
 
138
  }
139
  }
133
  'default' => 'mm'
134
  ), $atts ) );
135
 
136
+ return "//www.gravatar.com/avatar/" . md5( strtolower( trim( $email ) ) ) . "?d=" . urlencode( $default ) . "&s=" . $size;
137
 
138
  }
139
  }
shared/docs/analytics.events.md ADDED
@@ -0,0 +1,352 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.events.js -->
4
+
5
+ # Analytics Events
6
+
7
+ Events are triggered throughout the visitors journey through the site. See more on [Inbound Now][in]
8
+
9
+ Author: David Wells <david@inboundnow.com>
10
+
11
+ Version: 0.0.1
12
+ [in]: http://www.inboundnow.com/
13
+
14
+ # Event Usage
15
+
16
+ Events are triggered throughout the visitors path through the site.
17
+ You can hook into these custom actions and filters much like WordPress Core
18
+
19
+ See below for examples
20
+
21
+ Adding Custom Actions
22
+ ------------------
23
+ You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
24
+
25
+ `
26
+ _inbound.add_action( 'action_name', callback, priority );
27
+ `
28
+
29
+ ```js
30
+ // example:
31
+
32
+ // Add custom function to `page_visit` event
33
+ _inbound.add_action( 'page_visit', callback, 10 );
34
+
35
+ // add custom callback to trigger when `page_visit` fires
36
+ function callback(pageData){
37
+ var pageData = pageData || {};
38
+ // run callback on 'page_visit' trigger
39
+ alert(pageData.title);
40
+ }
41
+ ```
42
+
43
+ ### Params:
44
+
45
+ * **string** *action_name* Name of the event trigger
46
+ * **function** *callback* function to trigger when event happens
47
+ * **int** *priority* Order to trigger the event in
48
+
49
+ Removing Custom Actions
50
+ ------------------
51
+ You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
52
+
53
+ `
54
+ _inbound.remove_action( 'action_name');
55
+ `
56
+
57
+ ```js
58
+ // example:
59
+
60
+ _inbound.remove_action( 'page_visit');
61
+ // all 'page_visit' actions have been deregistered
62
+ ```
63
+
64
+ ### Params:
65
+
66
+ * **string** *action_name* Name of the event trigger
67
+
68
+ # Event List
69
+
70
+ Events are triggered throughout the visitors journey through the site
71
+
72
+ ## analytics_ready()
73
+
74
+ Triggers when analyics has finished loading
75
+
76
+ ## url_parameters()
77
+
78
+ Triggers when the browser url params are parsed. You can perform custom actions
79
+ if specific url params exist.
80
+
81
+ ```js
82
+ // Usage:
83
+
84
+ // Add function to 'url_parameters' event
85
+ _inbound.add_action( 'url_parameters', url_parameters_func_example, 10);
86
+
87
+ function url_parameters_func_example(urlParams) {
88
+ var urlParams = urlParams || {};
89
+ for( var param in urlParams ) {
90
+ var key = param;
91
+ var value = urlParams[param];
92
+ }
93
+ // All URL Params
94
+ alert(JSON.stringify(urlParams));
95
+
96
+ // Check if URL parameter `utm_source` exists and matches value
97
+ if(urlParams.utm_source === "twitter") {
98
+ alert('This person is from twitter!');
99
+ }
100
+ }
101
+ ```
102
+
103
+ ## session_start()
104
+
105
+ Triggers when session starts
106
+
107
+ ```js
108
+ // Usage:
109
+
110
+ // Add function to 'session_start' event
111
+ _inbound.add_action( 'session_start', session_start_func_example, 10);
112
+
113
+ function session_start_func_example(data) {
114
+ var data = data || {};
115
+ // session start. Do something for new visitor
116
+ }
117
+ ```
118
+
119
+ ## session_end()
120
+
121
+ Triggers when visitor session goes idle for more than 30 minutes.
122
+
123
+ ```js
124
+ // Usage:
125
+
126
+ // Add function to 'session_end' event
127
+ _inbound.add_action( 'session_end', session_end_func_example, 10);
128
+
129
+ function session_end_func_example(data) {
130
+ var data = data || {};
131
+ // Do something when session ends
132
+ alert("Hey! It's been 30 minutes... where did you go?");
133
+ }
134
+ ```
135
+
136
+ ## session_active()
137
+
138
+ Triggers if active session is detected
139
+
140
+ ```js
141
+ // Usage:
142
+
143
+ // Add function to 'session_active' event
144
+ _inbound.add_action( 'session_active', session_active_func_example, 10);
145
+
146
+ function session_active_func_example(data) {
147
+ var data = data || {};
148
+ // session active
149
+ }
150
+ ```
151
+
152
+ ## session_idle()
153
+
154
+ Triggers when visitor session goes idle. Idling occurs after 60 seconds of
155
+ inactivity or when the visitor switches browser tabs
156
+
157
+ ```js
158
+ // Usage:
159
+
160
+ // Add function to 'session_idle' event
161
+ _inbound.add_action( 'session_idle', session_idle_func_example, 10);
162
+
163
+ function session_idle_func_example(data) {
164
+ var data = data || {};
165
+ // Do something when session idles
166
+ alert('Here is a special offer for you!');
167
+ }
168
+ ```
169
+
170
+ ## session_resume()
171
+
172
+ Triggers when session is already active and gets resumed
173
+
174
+ ```js
175
+ // Usage:
176
+
177
+ // Add function to 'session_resume' event
178
+ _inbound.add_action( 'session_resume', session_resume_func_example, 10);
179
+
180
+ function session_resume_func_example(data) {
181
+ var data = data || {};
182
+ // Session exists and is being resumed
183
+ }
184
+ ```
185
+
186
+ ## session_heartbeat()
187
+
188
+ Session emitter. Runs every 10 seconds. This is a useful function for
189
+ pinging third party services
190
+
191
+ ```js
192
+ // Usage:
193
+
194
+ // Add session_heartbeat_func_example function to 'session_heartbeat' event
195
+ _inbound.add_action( 'session_heartbeat', session_heartbeat_func_example, 10);
196
+
197
+ function session_heartbeat_func_example(data) {
198
+ var data = data || {};
199
+ // Do something with every 10 seconds
200
+ }
201
+ ```
202
+
203
+ ## page_visit()
204
+
205
+ Triggers Every Page View
206
+
207
+ ```js
208
+ // Usage:
209
+
210
+ // Add function to 'page_visit' event
211
+ _inbound.add_action( 'page_visit', page_visit_func_example, 10);
212
+
213
+ function session_idle_func_example(pageData) {
214
+ var pageData = pageData || {};
215
+ if( pageData.view_count > 8 ){
216
+ alert('Wow you have been to this page more than 8 times.');
217
+ }
218
+ }
219
+ ```
220
+
221
+ ## page_first_visit()
222
+
223
+ Triggers If the visitor has never seen the page before
224
+
225
+ ```js
226
+ // Usage:
227
+
228
+ // Add function to 'page_first_visit' event
229
+ _inbound.add_action( 'page_first_visit', page_first_visit_func_example, 10);
230
+
231
+ function page_first_visit_func_example(pageData) {
232
+ var pageData = pageData || {};
233
+ alert('Welcome to this page! Its the first time you have seen it')
234
+ }
235
+ ```
236
+
237
+ ## page_revisit()
238
+
239
+ Triggers If the visitor has seen the page before
240
+
241
+ ```js
242
+ // Usage:
243
+
244
+ // Add function to 'page_revisit' event
245
+ _inbound.add_action( 'page_revisit', page_revisit_func_example, 10);
246
+
247
+ function page_revisit_func_example(pageData) {
248
+ var pageData = pageData || {};
249
+ alert('Welcome back to this page!');
250
+ // Show visitor special content/offer
251
+ }
252
+ ```
253
+
254
+ ## tab_hidden()
255
+
256
+ `tab_hidden` is triggered when the visitor switches browser tabs
257
+
258
+ ```js
259
+ // Usage:
260
+
261
+ // Adding the callback
262
+ function tab_hidden_function( data ) {
263
+ alert('The Tab is Hidden');
264
+ };
265
+
266
+ // Hook the function up the the `tab_hidden` event
267
+ _inbound.add_action( 'tab_hidden', tab_hidden_function, 10 );
268
+ ```
269
+
270
+ ## tab_visible()
271
+
272
+ `tab_visible` is triggered when the visitor switches back to the sites tab
273
+
274
+ ```js
275
+ // Usage:
276
+
277
+ // Adding the callback
278
+ function tab_visible_function( data ) {
279
+ alert('Welcome back to this tab!');
280
+ // trigger popup or offer special discount etc.
281
+ };
282
+
283
+ // Hook the function up the the `tab_visible` event
284
+ _inbound.add_action( 'tab_visible', tab_visible_function, 10 );
285
+ ```
286
+
287
+ ## tab_mouseout()
288
+
289
+ `tab_mouseout` is triggered when the visitor mouses out of the browser window.
290
+ This is especially useful for exit popups
291
+
292
+ ```js
293
+ // Usage:
294
+
295
+ // Adding the callback
296
+ function tab_mouseout_function( data ) {
297
+ alert("Wait don't Go");
298
+ // trigger popup or offer special discount etc.
299
+ };
300
+
301
+ // Hook the function up the the `tab_mouseout` event
302
+ _inbound.add_action( 'tab_mouseout', tab_mouseout_function, 10 );
303
+ ```
304
+
305
+ ## form_input_change()
306
+
307
+ `form_input_change` is triggered when tracked form inputs change
308
+ You can use this to add additional validation or set conditional triggers
309
+
310
+ ```js
311
+ // Usage:
312
+
313
+ ```
314
+
315
+ ## form_before_submission()
316
+
317
+ `form_before_submission` is triggered before the form is submitted to the server.
318
+ You can filter the data here or send it to third party services
319
+
320
+ ```js
321
+ // Usage:
322
+
323
+ // Adding the callback
324
+ function form_before_submission_function( data ) {
325
+ var data = data || {};
326
+ // filter form data
327
+ };
328
+
329
+ // Hook the function up the the `form_before_submission` event
330
+ _inbound.add_action( 'form_before_submission', form_before_submission_function, 10 );
331
+ ```
332
+
333
+ ## form_after_submission()
334
+
335
+ `form_after_submission` is triggered after the form is submitted to the server.
336
+ You can filter the data here or send it to third party services
337
+
338
+ ```js
339
+ // Usage:
340
+
341
+ // Adding the callback
342
+ function form_after_submission_function( data ) {
343
+ var data = data || {};
344
+ // filter form data
345
+ };
346
+
347
+ // Hook the function up the the `form_after_submission` event
348
+ _inbound.add_action( 'form_after_submission', form_after_submission_function, 10 );
349
+ ```
350
+
351
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.events.js -->
352
+
shared/docs/css/blur.jpg ADDED
Binary file
shared/docs/css/style.css ADDED
@@ -0,0 +1,885 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Please don't edit this file directly.
4
+ Instead, edit the stylus (.styl) files and compile it to CSS on your machine.
5
+
6
+ */
7
+ /* ----------------------------------------------------------------------------
8
+ * Fonts
9
+ */
10
+ @import url("//fonts.googleapis.com/css?family=Montserrat:700|Open+Sans:300");
11
+ /* ----------------------------------------------------------------------------
12
+ * Base
13
+ */
14
+ html,
15
+ body,
16
+ div,
17
+ span,
18
+ applet,
19
+ object,
20
+ iframe,
21
+ h1,
22
+ h2,
23
+ h3,
24
+ h4,
25
+ h5,
26
+ h6,
27
+ p,
28
+ blockquote,
29
+ pre,
30
+ a,
31
+ abbr,
32
+ acronym,
33
+ address,
34
+ big,
35
+ cite,
36
+ code,
37
+ del,
38
+ dfn,
39
+ em,
40
+ img,
41
+ ins,
42
+ kbd,
43
+ q,
44
+ s,
45
+ samp,
46
+ small,
47
+ strike,
48
+ strong,
49
+ sub,
50
+ sup,
51
+ tt,
52
+ var,
53
+ dl,
54
+ dt,
55
+ dd,
56
+ ol,
57
+ ul,
58
+ li,
59
+ fieldset,
60
+ form,
61
+ label,
62
+ legend,
63
+ table,
64
+ caption,
65
+ tbody,
66
+ tfoot,
67
+ thead,
68
+ tr,
69
+ th,
70
+ td {
71
+ margin: 0;
72
+ padding: 0;
73
+ border: 0;
74
+ outline: 0;
75
+ font-weight: inherit;
76
+ font-style: inherit;
77
+ font-family: inherit;
78
+ font-size: 100%;
79
+ vertical-align: baseline;
80
+ }
81
+ body {
82
+ line-height: 1;
83
+ color: #000;
84
+ background: #fff;
85
+ }
86
+ ol,
87
+ ul {
88
+ list-style: none;
89
+ }
90
+ table {
91
+ border-collapse: separate;
92
+ border-spacing: 0;
93
+ vertical-align: middle;
94
+ }
95
+ caption,
96
+ th,
97
+ td {
98
+ text-align: left;
99
+ font-weight: normal;
100
+ vertical-align: middle;
101
+ }
102
+ a img {
103
+ border: none;
104
+ }
105
+ html,
106
+ body {
107
+ height: 100%;
108
+ }
109
+ html {
110
+ overflow-x: hidden;
111
+ }
112
+ body,
113
+ td,
114
+ textarea,
115
+ input {
116
+ font-family: Helvetica Neue, Open Sans, sans-serif;
117
+ line-height: 1.6;
118
+ font-size: 13px;
119
+ color: #505050;
120
+ }
121
+ @media (max-width: 480px) {
122
+ body,
123
+ td,
124
+ textarea,
125
+ input {
126
+ font-size: 12px;
127
+ }
128
+ }
129
+ a {
130
+ color: #2badad;
131
+ text-decoration: none;
132
+ }
133
+ a:hover {
134
+ color: #228a8a;
135
+ }
136
+ /* ----------------------------------------------------------------------------
137
+ * Content styling
138
+ */
139
+ .content p,
140
+ .content ul,
141
+ .content ol,
142
+ .content h1,
143
+ .content h2,
144
+ .content h3,
145
+ .content h4,
146
+ .content h5,
147
+ .content h6,
148
+ .content pre,
149
+ .content blockquote {
150
+ padding: 10px 0;
151
+ -webkit-box-sizing: border-box;
152
+ -moz-box-sizing: border-box;
153
+ box-sizing: border-box;
154
+ }
155
+ .content h1,
156
+ .content h2,
157
+ .content h3,
158
+ .content h4,
159
+ .content h5,
160
+ .content h6 {
161
+ font-weight: bold;
162
+ -webkit-font-smoothing: antialiased;
163
+ text-rendering: optimizeLegibility;
164
+ }
165
+ .content pre {
166
+ font-family: Menlo, monospace;
167
+ }
168
+ .content ul > li {
169
+ list-style-type: disc;
170
+ }
171
+ .content ol > li {
172
+ list-style-type: decimal;
173
+ }
174
+ .content ul,
175
+ .content ol {
176
+ margin-left: 20px;
177
+ }
178
+ .content ul > li {
179
+ list-style-type: none;
180
+ position: relative;
181
+ }
182
+ .content ul > li:before {
183
+ content: '';
184
+ display: block;
185
+ position: absolute;
186
+ left: -17px;
187
+ top: 7px;
188
+ width: 5px;
189
+ height: 5px;
190
+ -webkit-border-radius: 4px;
191
+ border-radius: 4px;
192
+ -webkit-box-sizing: border-box;
193
+ -moz-box-sizing: border-box;
194
+ box-sizing: border-box;
195
+ background: #fff;
196
+ border: solid 1px #9090aa;
197
+ }
198
+ .content li > :first-child {
199
+ padding-top: 0;
200
+ }
201
+ .content strong,
202
+ .content b {
203
+ font-weight: bold;
204
+ }
205
+ .content i,
206
+ .content em {
207
+ font-style: italic;
208
+ color: #9090aa;
209
+ }
210
+ .content code {
211
+ font-family: Menlo, monospace;
212
+ background: #f3f6fb;
213
+ padding: 1px 3px;
214
+ font-size: 0.95em;
215
+ }
216
+ .content pre > code {
217
+ display: block;
218
+ background: transparent;
219
+ font-size: 0.85em;
220
+ letter-spacing: -1px;
221
+ }
222
+ .content blockquote :first-child {
223
+ padding-top: 0;
224
+ }
225
+ .content blockquote :last-child {
226
+ padding-bottom: 0;
227
+ }
228
+ .content table {
229
+ margin-top: 10px;
230
+ margin-bottom: 10px;
231
+ padding: 0;
232
+ border-collapse: collapse;
233
+ clear: both;
234
+ }
235
+ .content table tr {
236
+ border-top: 1px solid #ccc;
237
+ background-color: #fff;
238
+ margin: 0;
239
+ padding: 0;
240
+ }
241
+ .content table tr :nth-child(2n) {
242
+ background-color: #f8f8f8;
243
+ }
244
+ .content table tr th {
245
+ text-align: auto;
246
+ font-weight: bold;
247
+ border: 1px solid #ccc;
248
+ margin: 0;
249
+ padding: 6px 13px;
250
+ }
251
+ .content table tr td {
252
+ text-align: auto;
253
+ border: 1px solid #ccc;
254
+ margin: 0;
255
+ padding: 6px 13px;
256
+ }
257
+ .content table tr th :first-child,
258
+ .content table tr td :first-child {
259
+ margin-top: 0;
260
+ }
261
+ .content table tr th :last-child,
262
+ .content table tr td :last-child {
263
+ margin-bottom: 0;
264
+ }
265
+ /* ----------------------------------------------------------------------------
266
+ * Content
267
+ */
268
+ .content-root {
269
+ min-height: 90%;
270
+ position: relative;
271
+ }
272
+ .content {
273
+ padding-top: 30px;
274
+ padding-bottom: 40px;
275
+ padding-left: 40px;
276
+ padding-right: 40px;
277
+ zoom: 1;
278
+ max-width: 700px;
279
+ }
280
+ .content:before,
281
+ .content:after {
282
+ content: "";
283
+ display: table;
284
+ }
285
+ .content:after {
286
+ clear: both;
287
+ }
288
+ .content blockquote {
289
+ color: #9090aa;
290
+ text-shadow: 0 1px 0 rgba(255,255,255,0.5);
291
+ }
292
+ .content h1,
293
+ .content h2,
294
+ .content h3 {
295
+ -webkit-font-smoothing: antialiased;
296
+ text-rendering: optimizeLegibility;
297
+ font-family: montserrat;
298
+ padding-bottom: 0;
299
+ }
300
+ .content h1 + p,
301
+ .content h2 + p,
302
+ .content h3 + p,
303
+ .content h1 ul,
304
+ .content h2 ul,
305
+ .content h3 ul,
306
+ .content h1 ol,
307
+ .content h2 ol,
308
+ .content h3 ol {
309
+ padding-top: 10px;
310
+ }
311
+ .content h1,
312
+ .content h2 {
313
+
314
+ letter-spacing: 0px;
315
+ font-size: 1.5em;
316
+ }
317
+ .content h1 {
318
+ font-size: 2em;
319
+ }
320
+ .content h3 {
321
+ font-size: 1.2em;
322
+ }
323
+ .content h1,
324
+ .content h2,
325
+ .content .big-heading
326
+ /*body.big-h3 .content h3*/ {
327
+ padding-top: 80px;
328
+ }
329
+ .content h1:before,
330
+ .content h2:before,
331
+ .content .big-heading:before
332
+ /*body.big-h3 .content h3:before */{
333
+ display: block;
334
+ content: '';
335
+ background: -webkit-gradient(linear, left top, right top, color-stop(0.8, #dfe2e7), color-stop(1, rgba(223,226,231,0)));
336
+ background: -webkit-linear-gradient(left, #dfe2e7 80%, rgba(223,226,231,0) 100%);
337
+ background: -moz-linear-gradient(left, #dfe2e7 80%, rgba(223,226,231,0) 100%);
338
+ background: -o-linear-gradient(left, #dfe2e7 80%, rgba(223,226,231,0) 100%);
339
+ background: -ms-linear-gradient(left, #dfe2e7 80%, rgba(223,226,231,0) 100%);
340
+ background: linear-gradient(left, #dfe2e7 80%, rgba(223,226,231,0) 100%);
341
+ -webkit-box-shadow: 0 1px 0 rgba(255,255,255,0.4);
342
+ box-shadow: 0 1px 0 rgba(255,255,255,0.4);
343
+ height: 1px;
344
+ position: relative;
345
+ top: -40px;
346
+ left: -40px;
347
+ width: 100%;
348
+ }
349
+ @media (max-width: 768px) {
350
+ .content h1,
351
+ .content h2,
352
+ .content .big-heading,
353
+ body.big-h3 .content h3 {
354
+ padding-top: 40px;
355
+ }
356
+ .content h1:before,
357
+ .content h2:before,
358
+ .content .big-heading:before,
359
+ body.big-h3 .content h3:before {
360
+ background: #dfe2e7;
361
+ left: -40px;
362
+ top: -20px;
363
+ width: 120%;
364
+ }
365
+ }
366
+ .content h4,
367
+ .content h5,
368
+ .content .small-heading,
369
+ body:not(.big-h3) .content h3 {
370
+ border-bottom: solid 1px rgba(0,0,0,0.07);
371
+ color: #9090aa;
372
+ padding-top: 30px;
373
+ padding-bottom: 10px;
374
+ }
375
+ body:not(.big-h3) .content h3 {
376
+ font-size: 0.9em;
377
+ }
378
+ .content h1:first-child {
379
+ padding-top: 0;
380
+ }
381
+ .content h1:first-child,
382
+ .content h1:first-child a,
383
+ .content h1:first-child a:visited {
384
+ color: #505050;
385
+ }
386
+ .content h1:first-child:before {
387
+ display: none;
388
+ }
389
+ @media (max-width: 768px) {
390
+ .content h4,
391
+ .content h5,
392
+ .content .small-heading,
393
+ body:not(.big-h3) .content h3 {
394
+ padding-top: 20px;
395
+ }
396
+ }
397
+ @media (max-width: 480px) {
398
+ .content {
399
+ padding: 20px;
400
+ padding-top: 40px;
401
+ }
402
+ .content h4,
403
+ .content h5,
404
+ .content .small-heading,
405
+ body:not(.big-h3) .content h3 {
406
+ padding-top: 10px;
407
+ }
408
+ }
409
+ body.no-literate .content pre > code {
410
+ background: #f3f6fb;
411
+ border: solid 1px #e7eaee;
412
+ border-top: solid 1px #dbdde2;
413
+ border-left: solid 1px #e2e5e9;
414
+ display: block;
415
+ padding: 10px;
416
+ -webkit-border-radius: 2px;
417
+ border-radius: 2px;
418
+ overflow: auto;
419
+ }
420
+ body.no-literate .content pre > code {
421
+ -webkit-overflow-scrolling: touch;
422
+ }
423
+ body.no-literate .content pre > code::-webkit-scrollbar {
424
+ width: 15px;
425
+ height: 15px;
426
+ }
427
+ body.no-literate .content pre > code::-webkit-scrollbar-thumb {
428
+ background: #ddd;
429
+ -webkit-border-radius: 8px;
430
+ border-radius: 8px;
431
+ border: solid 4px #f3f6fb;
432
+ }
433
+ body.no-literate .content pre > code:hover::-webkit-scrollbar-thumb {
434
+ background: #999;
435
+ -webkit-box-shadow: inset 2px 2px 3px rgba(0,0,0,0.2);
436
+ box-shadow: inset 2px 2px 3px rgba(0,0,0,0.2);
437
+ }
438
+ @media (max-width: 1180px) {
439
+ .content pre > code {
440
+ background: #f3f6fb;
441
+ border: solid 1px #e7eaee;
442
+ border-top: solid 1px #dbdde2;
443
+ border-left: solid 1px #e2e5e9;
444
+ display: block;
445
+ padding: 10px;
446
+ -webkit-border-radius: 2px;
447
+ border-radius: 2px;
448
+ overflow: auto;
449
+ }
450
+ .content pre > code {
451
+ -webkit-overflow-scrolling: touch;
452
+ }
453
+ .content pre > code::-webkit-scrollbar {
454
+ width: 15px;
455
+ height: 15px;
456
+ }
457
+ .content pre > code::-webkit-scrollbar-thumb {
458
+ background: #ddd;
459
+ -webkit-border-radius: 8px;
460
+ border-radius: 8px;
461
+ border: solid 4px #f3f6fb;
462
+ }
463
+ .content pre > code:hover::-webkit-scrollbar-thumb {
464
+ background: #999;
465
+ -webkit-box-shadow: inset 2px 2px 3px rgba(0,0,0,0.2);
466
+ box-shadow: inset 2px 2px 3px rgba(0,0,0,0.2);
467
+ }
468
+ }
469
+ .button {
470
+ -webkit-font-smoothing: antialiased;
471
+ text-rendering: optimizeLegibility;
472
+ font-family: montserrat, sans-serif;
473
+ letter-spacing: -1px;
474
+ font-weight: bold;
475
+ display: inline-block;
476
+ padding: 3px 25px;
477
+ border: solid 2px #2badad;
478
+ -webkit-border-radius: 20px;
479
+ border-radius: 20px;
480
+ margin-right: 15px;
481
+ }
482
+ .button,
483
+ .button:visited {
484
+ background: #2badad;
485
+ color: #fff;
486
+ text-shadow: none;
487
+ }
488
+ .button:hover {
489
+ border-color: #111;
490
+ background: #111;
491
+ color: #fff;
492
+ }
493
+ .button.light,
494
+ .button.light:visited {
495
+ background: transparent;
496
+ color: #9090aa;
497
+ border-color: #9090aa;
498
+ text-shadow: none;
499
+ }
500
+ .button.light:hover {
501
+ border-color: #9090aa;
502
+ background: #9090aa;
503
+ color: #fff;
504
+ }
505
+ .content .button + em {
506
+ color: #9090aa;
507
+ }
508
+ @media (min-width: 1180px) {
509
+ body:not(.no-literate) .content-root {
510
+ background-color: #f3f6fb;
511
+ -webkit-box-shadow: inset 780px 0 #fff, inset 781px 0 #dfe2e7, inset 790px 0 5px -10px rgba(0,0,0,0.1);
512
+ box-shadow: inset 780px 0 #fff, inset 781px 0 #dfe2e7, inset 790px 0 5px -10px rgba(0,0,0,0.1);
513
+ }
514
+ }
515
+ @media (min-width: 1180px) {
516
+ body:not(.no-literate) .content {
517
+ padding-left: 0;
518
+ padding-right: 0;
519
+ width: 930px;
520
+ max-width: none;
521
+ }
522
+ body:not(.no-literate) .content > p,
523
+ body:not(.no-literate) .content > ul,
524
+ body:not(.no-literate) .content > ol,
525
+ body:not(.no-literate) .content > h1,
526
+ body:not(.no-literate) .content > h2,
527
+ body:not(.no-literate) .content > h3,
528
+ body:not(.no-literate) .content > h4,
529
+ body:not(.no-literate) .content > h5,
530
+ body:not(.no-literate) .content > h6,
531
+ body:not(.no-literate) .content > pre,
532
+ body:not(.no-literate) .content > blockquote {
533
+ width: 550px;
534
+ -webkit-box-sizing: border-box;
535
+ -moz-box-sizing: border-box;
536
+ box-sizing: border-box;
537
+ padding-right: 40px;
538
+ padding-left: 40px;
539
+ }
540
+ body:not(.no-literate) .content > h1,
541
+ body:not(.no-literate) .content > h2,
542
+ body:not(.no-literate) .content > h3 {
543
+ clear: both;
544
+ width: 100%;
545
+ }
546
+ body:not(.no-literate) .content > pre,
547
+ body:not(.no-literate) .content > blockquote {
548
+ width: 380px;
549
+ padding-left: 20px;
550
+ padding-right: 20px;
551
+ float: right;
552
+ clear: right;
553
+ }
554
+ body:not(.no-literate) .content > pre + p,
555
+ body:not(.no-literate) .content > blockquote + p,
556
+ body:not(.no-literate) .content > pre + ul,
557
+ body:not(.no-literate) .content > blockquote + ul,
558
+ body:not(.no-literate) .content > pre + ol,
559
+ body:not(.no-literate) .content > blockquote + ol,
560
+ body:not(.no-literate) .content > pre + h4,
561
+ body:not(.no-literate) .content > blockquote + h4,
562
+ body:not(.no-literate) .content > pre + h5,
563
+ body:not(.no-literate) .content > blockquote + h5,
564
+ body:not(.no-literate) .content > pre + h6,
565
+ body:not(.no-literate) .content > blockquote + h6 {
566
+ clear: both;
567
+ }
568
+ body:not(.no-literate) .content > p,
569
+ body:not(.no-literate) .content > ul,
570
+ body:not(.no-literate) .content > ol,
571
+ body:not(.no-literate) .content > h4,
572
+ body:not(.no-literate) .content > h5,
573
+ body:not(.no-literate) .content > h6 {
574
+ float: left;
575
+ clear: left;
576
+ }
577
+ body:not(.no-literate) .content > h4,
578
+ body:not(.no-literate) .content > h5,
579
+ body:not(.no-literate) .content > .small-heading,
580
+ body:not(.big-h3) body:not(.no-literate) .content > h3 {
581
+ margin-left: 40px;
582
+ width: 470px;
583
+ margin-bottom: 3px;
584
+ padding-left: 0;
585
+ padding-right: 0;
586
+ }
587
+ body:not(.no-literate) .content > table {
588
+ margin-left: 40px;
589
+ margin-right: 40px;
590
+ max-width: 470px;
591
+ }
592
+ body:not(.no-literate):not(.big-h3) .content > h3 {
593
+ margin-left: 40px;
594
+ width: 470px;
595
+ margin-bottom: 3px;
596
+ padding-left: 0;
597
+ padding-right: 0;
598
+ }
599
+ }
600
+ .header {
601
+ background: #f3f6fb;
602
+ text-shadow: 0 1px 0 rgba(255,255,255,0.5);
603
+ border-bottom: solid 1px #dfe2e7;
604
+ padding: 15px 15px 15px 30px;
605
+ zoom: 1;
606
+ line-height: 20px;
607
+ position: relative;
608
+ }
609
+ .header:before,
610
+ .header:after {
611
+ content: "";
612
+ display: table;
613
+ }
614
+ .header:after {
615
+ clear: both;
616
+ }
617
+ .header .left {
618
+ float: left;
619
+ }
620
+ .header .right {
621
+ text-align: right;
622
+ position: absolute;
623
+ right: 15px;
624
+ top: 15px;
625
+ }
626
+ .header .right iframe {
627
+ display: inline-block;
628
+ vertical-align: middle;
629
+ }
630
+ .header h1 {
631
+ -webkit-font-smoothing: antialiased;
632
+ text-rendering: optimizeLegibility;
633
+ font-weight: bold;
634
+ font-family: montserrat, sans-serif;
635
+ font-size: 13px;
636
+ }
637
+ .header h1,
638
+ .header h1 a,
639
+ .header h1 a:visited {
640
+ color: #9090aa;
641
+ }
642
+ .header h1 a:hover {
643
+ color: #505050;
644
+ }
645
+ .header li a {
646
+ font-size: 0.88em;
647
+ color: #9090aa;
648
+ display: block;
649
+ }
650
+ .header li a:hover {
651
+ color: #3a3a44;
652
+ }
653
+ @media (min-width: 480px) {
654
+ .header h1 {
655
+ float: left;
656
+ }
657
+ .header ul,
658
+ .header li {
659
+ display: block;
660
+ float: left;
661
+ }
662
+ .header ul {
663
+ margin-left: -15px;
664
+ }
665
+ .header h1 + ul {
666
+ border-left: solid 1px #dfe2e7;
667
+ margin-left: 15px;
668
+ }
669
+ .header li {
670
+ border-left: solid 1px rgba(255,255,255,0.5);
671
+ border-right: solid 1px #dfe2e7;
672
+ }
673
+ .header li:last-child {
674
+ border-right: 0;
675
+ }
676
+ .header li a {
677
+ padding: 0 15px;
678
+ }
679
+ }
680
+ @media (max-width: 480px) {
681
+ .right {
682
+ display: none;
683
+ }
684
+ }
685
+ .menubar {
686
+ -webkit-font-smoothing: antialiased;
687
+ text-rendering: optimizeLegibility;
688
+ }
689
+ .menubar .section {
690
+ padding: 30px 30px;
691
+ -webkit-box-sizing: border-box;
692
+ -moz-box-sizing: border-box;
693
+ box-sizing: border-box;
694
+ }
695
+ .menubar .section + .section {
696
+ border-top: solid 1px #dfe2e7;
697
+ }
698
+ .menubar .section.no-line {
699
+ border-top: 0;
700
+ padding-top: 0;
701
+ }
702
+ a.big.button {
703
+ display: block;
704
+ -webkit-box-sizing: border-box;
705
+ -moz-box-sizing: border-box;
706
+ box-sizing: border-box;
707
+ width: 100%;
708
+ padding: 10px 20px;
709
+ text-align: center;
710
+ font-weight: bold;
711
+ font-size: 1.1em;
712
+ background: transparent;
713
+ border: solid 3px #2badad;
714
+ -webkit-border-radius: 30px;
715
+ border-radius: 30px;
716
+ font-family: montserrat, sans-serif;
717
+ }
718
+ a.big.button,
719
+ a.big.button:visited {
720
+ color: #2badad;
721
+ text-decoration: none;
722
+ }
723
+ a.big.button:hover {
724
+ background: #2badad;
725
+ }
726
+ a.big.button:hover,
727
+ a.big.button:hover:visited {
728
+ color: #fff;
729
+ }
730
+ @media (max-width: 480px) {
731
+ .menubar {
732
+ padding: 20px;
733
+ border-bottom: solid 1px #dfe2e7;
734
+ }
735
+ }
736
+ @media (max-width: 768px) {
737
+ .menubar {
738
+ display: none;
739
+ }
740
+ }
741
+ @media (min-width: 768px) {
742
+ .content-root {
743
+ padding-left: 230px;
744
+ }
745
+ .menubar {
746
+ position: absolute;
747
+ left: 0;
748
+ top: 0;
749
+ bottom: 0;
750
+ width: 230px;
751
+ border-right: solid 1px #dfe2e7;
752
+ }
753
+ .menubar.fixed {
754
+ position: fixed;
755
+ overflow-y: auto;
756
+ }
757
+ .menubar.fixed {
758
+ -webkit-overflow-scrolling: touch;
759
+ }
760
+ .menubar.fixed::-webkit-scrollbar {
761
+ width: 15px;
762
+ height: 15px;
763
+ }
764
+ .menubar.fixed::-webkit-scrollbar-thumb {
765
+ background: #ddd;
766
+ -webkit-border-radius: 8px;
767
+ border-radius: 8px;
768
+ border: solid 4px #fff;
769
+ }
770
+ .menubar.fixed:hover::-webkit-scrollbar-thumb {
771
+ background: #999;
772
+ -webkit-box-shadow: inset 2px 2px 3px rgba(0,0,0,0.2);
773
+ box-shadow: inset 2px 2px 3px rgba(0,0,0,0.2);
774
+ }
775
+ }
776
+ .menubar {
777
+ font-size: 0.9em;
778
+ }
779
+ .menu ul.level-1 > li + li {
780
+ margin-top: 20px;
781
+ }
782
+ .menu a {
783
+ -webkit-box-sizing: border-box;
784
+ -moz-box-sizing: border-box;
785
+ box-sizing: border-box;
786
+ position: relative;
787
+ display: block;
788
+ padding-top: 1px;
789
+ padding-bottom: 1px;
790
+ margin-right: -30px;
791
+ }
792
+ .menu a,
793
+ .menu a:visited {
794
+ color: #2badad;
795
+ }
796
+ .menu a:hover {
797
+ color: #228a8a;
798
+ }
799
+ .menu a.level-1 {
800
+ font-family: montserrat, sans-serif;
801
+ text-transform: uppercase;
802
+ font-size: 0.9em;
803
+ font-weight: bold;
804
+ }
805
+ .menu a.level-1,
806
+ .menu a.level-1:visited {
807
+ color: #9090aa;
808
+ }
809
+ .menu a.level-1:hover {
810
+ color: #565666;
811
+ }
812
+ .menu a.level-2 {
813
+ font-weight: normal;
814
+ }
815
+ .menu a.level-3 {
816
+ font-weight: normal;
817
+ font-size: 0.9em;
818
+ padding-left: 10px;
819
+ }
820
+ .menu a.active {
821
+ font-weight: bold !important;
822
+ }
823
+ .menu a.active,
824
+ .menu a.active:visited,
825
+ .menu a.active:hover {
826
+ color: #505050 !important;
827
+ }
828
+ .menu a.active:after {
829
+ content: '';
830
+ display: block;
831
+ -webkit-box-sizing: border-box;
832
+ -moz-box-sizing: border-box;
833
+ box-sizing: border-box;
834
+ position: absolute;
835
+ top: 10px;
836
+ right: 30px;
837
+ width: 9px;
838
+ height: 3px;
839
+ -webkit-border-radius: 2px;
840
+ border-radius: 2px;
841
+ background: #2badad;
842
+ }
843
+ code .string,
844
+ code .number {
845
+ color: #3ac;
846
+ }
847
+ code .init {
848
+ color: #383;
849
+ }
850
+ code .keyword {
851
+ font-weight: bold;
852
+ }
853
+ code .comment {
854
+ color: #adadcc;
855
+ }
856
+ .large-brief .content > h1:first-child + p,
857
+ .content > p.brief {
858
+ font-size: 1.3em;
859
+ font-family: Open Sans, sans-serif;
860
+ font-weight: 300;
861
+ }
862
+ .title-area {
863
+ min-height: 100px;
864
+ -webkit-box-sizing: border-box;
865
+ -moz-box-sizing: border-box;
866
+ box-sizing: border-box;
867
+ -webkit-font-smoothing: antialiased;
868
+ text-rendering: optimizeLegibility;
869
+ text-align: center;
870
+ border-bottom: solid 1px #dfe2e7;
871
+ overflow: hidden;
872
+ }
873
+ .title-area > img.bg {
874
+ z-index: 0;
875
+ position: absolute;
876
+ left: -9999px;
877
+ }
878
+ .title-area > div {
879
+ position: relative;
880
+ z-index: 1;
881
+ }
882
+ .level-3 {
883
+ display:none;
884
+ }
885
+
shared/docs/css/theme.css ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .title-card {
2
+ text-rendering: optimizeLegibility !important;
3
+ -webkit-font-smoothing: antialiased !important;
4
+ -moz-osx-font-smoothing: grayscale; }
5
+
6
+ .title-card {
7
+ background: #1d3b47;
8
+ background-position: center center;
9
+ background-size: cover;
10
+ color: #ccc;
11
+ text-align: center;
12
+
13
+ position: relative;
14
+ z-index: 1;
15
+
16
+ width: 100%;
17
+ display: table; }
18
+
19
+ .title-card > .in {
20
+ display: table-cell;
21
+ vertical-align: middle; }
22
+
23
+ .title-card .headline {
24
+ vertical-align: middle;
25
+ display: inline-block;
26
+ -webkit-box-sizing: border-box;
27
+ box-sizing: border-box;
28
+
29
+ /* text-shadow: 0 0 4px rgba(0, 0, 0, 0.5); */
30
+
31
+ padding-left: 40px;
32
+ padding-right: 40px;
33
+ max-width: 800px;
34
+ line-height: 1.7; }
35
+
36
+ .title-card h1 {
37
+ font-family: 'Open Sans', sans-serif;
38
+ font-size: 3.3em;
39
+ font-weight: 300;
40
+ line-height: 1.1;
41
+ margin-bottom: 0.5em;
42
+ color: #fff; }
43
+
44
+ .title-card p {
45
+ font-family: montserrat, sans-serif;
46
+ color: #b8eaea;
47
+ font-weight: bold;
48
+ font-size: 1.3em; }
49
+
50
+ .title-card h5 {
51
+ margin-top: 150px;
52
+
53
+ font-family: montserrat, sans-serif;
54
+ font-weight: bold;
55
+ color: #fff;
56
+ text-transform: uppercase;
57
+ letter-spacing: 2px;
58
+ font-size: 1.8em; }
59
+
60
+ .title-card h5 span {
61
+ display: inline-block;
62
+ padding: 5px 20px;
63
+ border: solid 3px #fff; }
64
+
65
+ @media (max-width: 768px) /* Tablet */ {
66
+ .title-card h5 {
67
+ margin-top: 100px; }
68
+ }
69
+
70
+ @media (max-width: 480px) /* Mobile */ {
71
+ .title-card {
72
+ padding: 50px 0; }
73
+ .title-card .headline {
74
+ padding-left: 10px;
75
+ padding-right: 10px;
76
+ min-height: none; }
77
+ .title-card h1 {
78
+ font-size: 2.2em; }
79
+ .title-card p {
80
+ font-size: 1.1em; }
81
+ .title-card h5 {
82
+ margin-top: 40px;
83
+ font-size: 0.9em; }
84
+ }
shared/docs/index.html ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset='utf-8'>
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6
+ <meta name="viewport" content="width=device-width">
7
+
8
+ <title>Flatdoc</title>
9
+
10
+ <!-- Flatdoc -->
11
+ <script src='js/jquery.js'></script>
12
+ <script src='js/legacy.js'></script>
13
+ <script src='js/flatdoc.js?94850'></script>
14
+
15
+ <!-- Flatdoc theme -->
16
+ <link href='css/style.css?94850' rel='stylesheet'>
17
+ <script src='js/script.js?94850'></script>
18
+ <link href='css/theme.css?94850' rel='stylesheet'>
19
+ <script src='js/theme.js?94850'></script>
20
+
21
+ <!-- Initializer -->
22
+ <script>
23
+ //*
24
+ Flatdoc.run({
25
+ fetcher: Flatdoc.file('analytics.events.md')
26
+ });
27
+ /**/
28
+ /*
29
+ Flatdoc.run({
30
+ fetcher: Flatdoc.file('main.md')
31
+ });
32
+ /**/
33
+
34
+ </script>
35
+
36
+ <!-- Meta -->
37
+ <meta content="Flatdoc" property="og:site_name">
38
+ <meta content="Flatdoc" property="og:title">
39
+ <meta content="website" property="og:type">
40
+ <meta content="Flatdoc is the fastest way to create a site for your open source project." name="description">
41
+ <meta content="Flatdoc is the fastest way to create a site for your open source project." property="og:description">
42
+ <!-- <meta content="http://ricostacruz.com/flatdoc/support/preview.jpg" property="og:image"> -->
43
+
44
+
45
+ </head>
46
+ <body role='flatdoc' class='big-h3 large-brief'>
47
+
48
+ <div class='title-area title-card' style='background-image: url(css/blur.jpg)'>
49
+ <div class='in'>
50
+ <div class='headline'>
51
+ <h1>Inbound Now Documentation</h1>
52
+ <p>Learn how to leverage the power of the inbound marketing suite</h5>
53
+ <h5><span>Inbound Docs</span></h5>
54
+ </div>
55
+ </div>
56
+ </div>
57
+
58
+ <div class='header'>
59
+ <div class='left'>
60
+ <h1><a href='.'>Inbound Now</a></h1>
61
+ <ul>
62
+ <li><a href='https://github.com/inboundnow'>View on GitHub</a></li>
63
+ <li><a href='https://github.com/rstacruz/flatdoc/issues'>Issues</a></li>
64
+ <li><a href='reference.html'>API reference</a></li>
65
+ </ul>
66
+ </div>
67
+ <div class='right'>
68
+ <iframe src="http://ghbtns.com/github-btn.html?user=davidwells&amp;type=follow&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="170" height="20"></iframe>
69
+ <iframe src="http://ghbtns.com/github-btn.html?user=davidwells&amp;repo=flatdoc&amp;type=watch&amp;count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
70
+ </div>
71
+ </div>
72
+
73
+ <div class='content-root'>
74
+ <div class='menubar'>
75
+ <div class='section'>
76
+ <a class='big button' href='https://raw.github.com/rstacruz/flatdoc/gh-pages/templates/template.html' target='_blank'>Download</a>
77
+ <!-- <a href='https://github.com/rstacruz/flatdoc' target='_blank'>View in GitHub</a> -->
78
+ </div>
79
+ <div class='menu section' role='flatdoc-menu'></div>
80
+ <div class='bottom section'>
81
+ <iframe src='http://ghbtns.com/github-btn.html?user=rstacruz&amp;repo=flatdoc&amp;type=watch&amp;count=true' allowtransparency="true" frameborder="0" scrolling="0" width="170" height="20"></iframe>
82
+ <br>
83
+ <a href="https://news.ycombinator.com/submit" class="hn-button" data-title="Flatdoc is the fastest way to create a site for your open source project" data-url="http://ricostacruz.com/flatdoc/" data-count="horizontal" data-style="twitter">HN</a>
84
+ <br>
85
+ <a href='https://github.com/rstacruz/flatdoc'>View on GitHub</a><br>
86
+ <a href='main.md' target='_blank'>See .md source</a>
87
+ </div>
88
+ </div>
89
+ <div role='flatdoc-content' class='content'></div>
90
+ </div>
91
+
92
+ <script>var HN=[];HN.factory=function(e){return function(){HN.push([e].concat(Array.prototype.slice.call(arguments,0)))};},HN.on=HN.factory("on"),HN.once=HN.factory("once"),HN.off=HN.factory("off"),HN.emit=HN.factory("emit"),HN.load=function(){var e="hn-button.js";if(document.getElementById(e))return;var t=document.createElement("script");t.id=e,t.src="//hn-button.herokuapp.com/hn-button.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n)},HN.load();</script>
93
+ </body>
94
+ </html>
shared/docs/js/flatdoc.js ADDED
@@ -0,0 +1,515 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Flatdoc - (c) 2013, 2014 Rico Sta. Cruz
3
+ * http://ricostacruz.com/flatdoc
4
+ * @license MIT
5
+ */
6
+
7
+ (function($) {
8
+ var exports = this;
9
+
10
+ var marked;
11
+
12
+ /**
13
+ * Basic Flatdoc module.
14
+ *
15
+ * The main entry point is `Flatdoc.run()`, which invokes the [Runner].
16
+ *
17
+ * Flatdoc.run({
18
+ * fetcher: Flatdoc.github('rstacruz/backbone-patterns');
19
+ * });
20
+ */
21
+
22
+ var Flatdoc = exports.Flatdoc = {};
23
+
24
+ /**
25
+ * Creates a runner.
26
+ * See [Flatdoc].
27
+ */
28
+
29
+ Flatdoc.run = function(options) {
30
+ $(function() { (new Flatdoc.runner(options)).run(); });
31
+ };
32
+
33
+ /**
34
+ * File fetcher function.
35
+ *
36
+ * Fetches a given `url` via AJAX.
37
+ * See [Runner#run()] for a description of fetcher functions.
38
+ */
39
+
40
+ Flatdoc.file = function(url) {
41
+ return function(callback) {
42
+ $.get(url)
43
+ .fail(function(e) { callback(e, null); })
44
+ .done(function(data) { callback(null, data); });
45
+ };
46
+ };
47
+
48
+ /**
49
+ * Github fetcher.
50
+ * Fetches from repo `repo` (in format 'user/repo').
51
+ *
52
+ * If the parameter `filepath` is supplied, it fetches the contents of that
53
+ * given file in the repo.
54
+ *
55
+ * See [Runner#run()] for a description of fetcher functions.
56
+ *
57
+ * See: http://developer.github.com/v3/repos/contents/
58
+ */
59
+ Flatdoc.github = function(repo, filepath) {
60
+ var url;
61
+ if (filepath) {
62
+ url = 'https://api.github.com/repos/'+repo+'/contents/'+filepath;
63
+ } else {
64
+ url = 'https://api.github.com/repos/'+repo+'/readme';
65
+ }
66
+ return function(callback) {
67
+ $.get(url)
68
+ .fail(function(e) { callback(e, null); })
69
+ .done(function(data) {
70
+ var markdown = exports.Base64.decode(data.content);
71
+ callback(null, markdown);
72
+ });
73
+ };
74
+ };
75
+
76
+ /**
77
+ * Bitbucket fetcher.
78
+ * Fetches from repo `repo` (in format 'user/repo').
79
+ *
80
+ * If the parameter `filepath` is supplied, it fetches the contents of that
81
+ * given file in the repo.
82
+ *
83
+ * See [Runner#run()] for a description of fetcher functions.
84
+ *
85
+ * See: https://confluence.atlassian.com/display/BITBUCKET/src+Resources#srcResources-GETrawcontentofanindividualfile
86
+ * See: http://ben.onfabrik.com/posts/embed-bitbucket-source-code-on-your-website
87
+ * Bitbucket appears to have stricter restrictions on
88
+ * Access-Control-Allow-Origin, and so the method here is a bit
89
+ * more complicated than for Github
90
+ *
91
+ * If you don't pass a branch name, then 'default' for Hg repos is assumed
92
+ * For git, you should pass 'master'. In both cases, you should also be able
93
+ * to pass in a revision number here -- in Mercurial, this also includes
94
+ * things like 'tip' or the repo-local integer revision number
95
+ * Default to Mercurial because Git users historically tend to use GitHub
96
+ */
97
+ Flatdoc.bitbucket = function(repo, filepath, branch) {
98
+ if (!filepath) filepath = 'readme.md';
99
+ if (!branch) branch = 'default';
100
+
101
+ var url = 'https://bitbucket.org/api/1.0/repositories/'+repo+'/src/'+branch+'/'+filepath;
102
+
103
+ return function(callback) {
104
+ $.ajax({
105
+ url: url,
106
+ dataType: 'jsonp',
107
+ error: function(xhr, status, error) {
108
+ alert(error);
109
+ },
110
+ success: function(response) {
111
+ var markdown = response.data;
112
+ callback(null, markdown);
113
+ }
114
+ });
115
+ };
116
+ };
117
+
118
+ /**
119
+ * Parser module.
120
+ * Parses a given Markdown document and returns a JSON object with data
121
+ * on the Markdown document.
122
+ *
123
+ * var data = Flatdoc.parser.parse('markdown source here');
124
+ * console.log(data);
125
+ *
126
+ * data == {
127
+ * title: 'My Project',
128
+ * content: '<p>This project is a...',
129
+ * menu: {...}
130
+ * }
131
+ */
132
+
133
+ var Parser = Flatdoc.parser = {};
134
+
135
+ /**
136
+ * Parses a given Markdown document.
137
+ * See `Parser` for more info.
138
+ */
139
+ Parser.parse = function(source, highlight) {
140
+ marked = exports.marked;
141
+
142
+ Parser.setMarkedOptions(highlight);
143
+
144
+ var html = $("<div>" + marked(source));
145
+ var h1 = html.find('h1').eq(0);
146
+ var title = h1.text();
147
+
148
+ // Mangle content
149
+ Transformer.mangle(html);
150
+ var menu = Transformer.getMenu(html);
151
+
152
+ return { title: title, content: html, menu: menu };
153
+ };
154
+
155
+ Parser.setMarkedOptions = function(highlight) {
156
+ marked.setOptions({
157
+ highlight: function(code, lang) {
158
+ if (lang) {
159
+ return highlight(code, lang);
160
+ }
161
+ return code;
162
+ }
163
+ });
164
+ };
165
+
166
+ /**
167
+ * Transformer module.
168
+ * This takes care of any HTML mangling needed. The main entry point is
169
+ * `.mangle()` which applies all transformations needed.
170
+ *
171
+ * var $content = $("<p>Hello there, this is a docu...");
172
+ * Flatdoc.transformer.mangle($content);
173
+ *
174
+ * If you would like to change any of the transformations, decorate any of
175
+ * the functions in `Flatdoc.transformer`.
176
+ */
177
+
178
+ var Transformer = Flatdoc.transformer = {};
179
+
180
+ /**
181
+ * Takes a given HTML `$content` and improves the markup of it by executing
182
+ * the transformations.
183
+ *
184
+ * > See: [Transformer](#transformer)
185
+ */
186
+ Transformer.mangle = function($content) {
187
+ this.addIDs($content);
188
+ this.buttonize($content);
189
+ this.smartquotes($content);
190
+ };
191
+
192
+ /**
193
+ * Adds IDs to headings.
194
+ */
195
+
196
+ Transformer.addIDs = function($content) {
197
+ var slugs = ['', '', ''];
198
+ $content.find('h1, h2, h3').each(function() {
199
+ var $el = $(this);
200
+ var num = parseInt(this.nodeName[1]);
201
+ var text = $el.text();
202
+ var slug = slugify(text);
203
+ if (num > 1) slug = slugs[num - 2] + '-' + slug;
204
+ slugs.length = num - 1;
205
+ slugs = slugs.concat([slug, slug]);
206
+ $el.attr('id', slug);
207
+ });
208
+ };
209
+
210
+ /**
211
+ * Returns menu data for a given HTML.
212
+ *
213
+ * menu = Flatdoc.transformer.getMenu($content);
214
+ * menu == {
215
+ * level: 0,
216
+ * items: [{
217
+ * section: "Getting started",
218
+ * level: 1,
219
+ * items: [...]}, ...]}
220
+ */
221
+
222
+ Transformer.getMenu = function($content) {
223
+ var root = {items: [], id: '', level: 0};
224
+ var cache = [root];
225
+
226
+ function mkdir_p(level) {
227
+ cache.length = level + 1;
228
+ var obj = cache[level];
229
+ if (!obj) {
230
+ var parent = (level > 1) ? mkdir_p(level-1) : root;
231
+ obj = { items: [], level: level };
232
+ cache = cache.concat([obj, obj]);
233
+ parent.items.push(obj);
234
+ }
235
+ return obj;
236
+ }
237
+
238
+ $content.find('h1, h2, h3').each(function() {
239
+ var $el = $(this);
240
+ var level = +(this.nodeName.substr(1));
241
+
242
+ var parent = mkdir_p(level-1);
243
+
244
+ var obj = { section: $el.text(), items: [], level: level, id: $el.attr('id') };
245
+ parent.items.push(obj);
246
+ cache[level] = obj;
247
+ });
248
+
249
+ return root;
250
+ };
251
+
252
+ /**
253
+ * Changes "button >" text to buttons.
254
+ */
255
+
256
+ Transformer.buttonize = function($content) {
257
+ $content.find('a').each(function() {
258
+ var $a = $(this);
259
+
260
+ var m = $a.text().match(/^(.*) >$/);
261
+ if (m) $a.text(m[1]).addClass('button');
262
+ });
263
+ };
264
+
265
+ /**
266
+ * Applies smart quotes to a given element.
267
+ * It leaves `code` and `pre` blocks alone.
268
+ */
269
+
270
+ Transformer.smartquotes = function ($content) {
271
+ var nodes = getTextNodesIn($content), len = nodes.length;
272
+ for (var i=0; i<len; i++) {
273
+ var node = nodes[i];
274
+ node.nodeValue = quotify(node.nodeValue);
275
+ }
276
+ };
277
+
278
+ /**
279
+ * Syntax highlighters.
280
+ *
281
+ * You may add or change more highlighters via the `Flatdoc.highlighters`
282
+ * object.
283
+ *
284
+ * Flatdoc.highlighters.js = function(code) {
285
+ * };
286
+ *
287
+ * Each of these functions
288
+ */
289
+
290
+ var Highlighters = Flatdoc.highlighters = {};
291
+
292
+ /**
293
+ * JavaScript syntax highlighter.
294
+ *
295
+ * Thanks @visionmedia!
296
+ */
297
+
298
+ Highlighters.js = Highlighters.javascript = function(code) {
299
+ return code
300
+ .replace(/</g, '&lt;')
301
+ .replace(/>/g, '&gt;')
302
+ .replace(/("[^\"]*?")/g, '<span class="string">$1</span>')
303
+ .replace(/('[^\']*?')/g, '<span class="string">$1</span>')
304
+ .replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
305
+ .replace(/\/\*(.*)\*\//gm, '<span class="comment">/*$1*/</span>')
306
+ .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
307
+ .replace(/(\d+)/gm, '<span class="number">$1</span>')
308
+ .replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
309
+ .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>');
310
+ };
311
+
312
+ Highlighters.html = function(code) {
313
+ return code
314
+ .replace(/</g, '&lt;')
315
+ .replace(/>/g, '&gt;')
316
+ .replace(/("[^\"]*?")/g, '<span class="string">$1</span>')
317
+ .replace(/('[^\']*?')/g, '<span class="string">$1</span>')
318
+ .replace(/&lt;!--(.*)--&gt;/g, '<span class="comment">&lt;!--$1--&gt;</span>')
319
+ .replace(/&lt;([^!][^\s&]*)/g, '&lt;<span class="keyword">$1</span>');
320
+ };
321
+
322
+ Highlighters.generic = function(code) {
323
+ return code
324
+ .replace(/</g, '&lt;')
325
+ .replace(/>/g, '&gt;')
326
+ .replace(/("[^\"]*?")/g, '<span class="string">$1</span>')
327
+ .replace(/('[^\']*?')/g, '<span class="string">$1</span>')
328
+ .replace(/(\/\/|#)(.*)/gm, '<span class="comment">$1$2</span>')
329
+ .replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
330
+ .replace(/(\d+)/gm, '<span class="number">$1</span>');
331
+ };
332
+
333
+ /**
334
+ * Menu view. Renders menus
335
+ */
336
+
337
+ var MenuView = Flatdoc.menuView = function(menu) {
338
+ var $el = $("<ul>");
339
+
340
+ function process(node, $parent) {
341
+ var id = node.id || 'root';
342
+
343
+ var $li = $('<li>')
344
+ .attr('id', id + '-item')
345
+ .addClass('level-' + node.level)
346
+ .appendTo($parent);
347
+
348
+ if (node.section) {
349
+ var $a = $('<a>')
350
+ .html(node.section)
351
+ .attr('id', id + '-link')
352
+ .attr('href', '#' + node.id)
353
+ .addClass('level-' + node.level)
354
+ .appendTo($li);
355
+ }
356
+
357
+ if (node.items.length > 0) {
358
+ var $ul = $('<ul>')
359
+ .addClass('level-' + (node.level+1))
360
+ .attr('id', id + '-list')
361
+ .appendTo($li);
362
+
363
+ node.items.forEach(function(item) {
364
+ process(item, $ul);
365
+ });
366
+ }
367
+ }
368
+
369
+ process(menu, $el);
370
+ return $el;
371
+ };
372
+
373
+ /**
374
+ * A runner module that fetches via a `fetcher` function.
375
+ *
376
+ * var runner = new Flatdoc.runner({
377
+ * fetcher: Flatdoc.url('readme.txt')
378
+ * });
379
+ * runner.run();
380
+ *
381
+ * The following options are available:
382
+ *
383
+ * - `fetcher` - a function that takes a callback as an argument and
384
+ * executes that callback when data is returned.
385
+ *
386
+ * See: [Flatdoc.run()]
387
+ */
388
+
389
+ var Runner = Flatdoc.runner = function(options) {
390
+ this.initialize(options);
391
+ };
392
+
393
+ Runner.prototype.root = '[role~="flatdoc"]';
394
+ Runner.prototype.menu = '[role~="flatdoc-menu"]';
395
+ Runner.prototype.title = '[role~="flatdoc-title"]';
396
+ Runner.prototype.content = '[role~="flatdoc-content"]';
397
+
398
+ Runner.prototype.initialize = function(options) {
399
+ $.extend(this, options);
400
+ };
401
+
402
+ /**
403
+ * Syntax highlighting.
404
+ *
405
+ * You may define a custom highlight function such as `highlight` from
406
+ * the highlight.js library.
407
+ *
408
+ * Flatdoc.run({
409
+ * highlight: function (code, value) {
410
+ * return hljs.highlight(lang, code).value;
411
+ * },
412
+ * ...
413
+ * });
414
+ *
415
+ */
416
+
417
+ Runner.prototype.highlight = function(code, lang) {
418
+ var fn = Flatdoc.highlighters[lang] || Flatdoc.highlighters.generic;
419
+ return fn(code);
420
+ };
421
+
422
+ /**
423
+ * Loads the Markdown document (via the fetcher), parses it, and applies it
424
+ * to the elements.
425
+ */
426
+
427
+ Runner.prototype.run = function() {
428
+ var doc = this;
429
+ $(doc.root).trigger('flatdoc:loading');
430
+ doc.fetcher(function(err, markdown) {
431
+ if (err) {
432
+ console.error('[Flatdoc] fetching Markdown data failed.', err);
433
+ return;
434
+ }
435
+ var data = Flatdoc.parser.parse(markdown, doc.highlight);
436
+ doc.applyData(data, doc);
437
+ var id = location.hash.substr(1);
438
+ if (id) {
439
+ var el = document.getElementById(id);
440
+ if (el) el.scrollIntoView(true);
441
+ };
442
+ $(doc.root).trigger('flatdoc:ready');
443
+ });
444
+ };
445
+
446
+ /**
447
+ * Applies given doc data `data` to elements in object `elements`.
448
+ */
449
+
450
+ Runner.prototype.applyData = function(data) {
451
+ var elements = this;
452
+
453
+ elements.el('title').html(data.title);
454
+ elements.el('content').html(data.content.find('>*'));
455
+ elements.el('menu').html(MenuView(data.menu));
456
+ };
457
+
458
+ /**
459
+ * Fetches a given element from the DOM.
460
+ *
461
+ * Returns a jQuery object.
462
+ * @api private
463
+ */
464
+
465
+ Runner.prototype.el = function(aspect) {
466
+ return $(this[aspect], this.root);
467
+ };
468
+
469
+ /*
470
+ * Helpers
471
+ */
472
+
473
+ // http://stackoverflow.com/questions/298750/how-do-i-select-text-nodes-with-jquery
474
+ function getTextNodesIn(el) {
475
+ var exclude = 'iframe,pre,code';
476
+ return $(el).find(':not('+exclude+')').andSelf().contents().filter(function() {
477
+ return this.nodeType == 3 && $(this).closest(exclude).length === 0;
478
+ });
479
+ }
480
+
481
+ // http://www.leancrew.com/all-this/2010/11/smart-quotes-in-javascript/
482
+ function quotify(a) {
483
+ a = a.replace(/(^|[\-\u2014\s(\["])'/g, "$1\u2018"); // opening singles
484
+ a = a.replace(/'/g, "\u2019"); // closing singles & apostrophes
485
+ a = a.replace(/(^|[\-\u2014\/\[(\u2018\s])"/g, "$1\u201c"); // opening doubles
486
+ a = a.replace(/"/g, "\u201d"); // closing doubles
487
+ a = a.replace(/\.\.\./g, "\u2026"); // ellipses
488
+ a = a.replace(/--/g, "\u2014"); // em-dashes
489
+ return a;
490
+ }
491
+
492
+ function slugify(text) {
493
+ if (typeof text !== 'string') return "";
494
+ return text.toLowerCase().match(/[a-z0-9]+/g).join('-');
495
+ }
496
+ })(jQuery);
497
+
498
+ /* jshint ignore:start */
499
+
500
+ /*!
501
+ * marked - a markdown parser
502
+ * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
503
+ * https://github.com/chjj/marked
504
+ */
505
+
506
+ (function(){var t={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:o,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:o,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:o,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};t.bullet=/(?:[*+-]|\d+\.)/;t.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;t.item=l(t.item,"gm")(/bull/g,t.bullet)();t.list=l(t.list)(/bull/g,t.bullet)("hr",/\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();t._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b";t.html=l(t.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,t._tag)();t.paragraph=l(t.paragraph)("hr",t.hr)("heading",t.heading)("lheading",t.lheading)("blockquote",t.blockquote)("tag","<"+t._tag)("def",t.def)();t.normal=h({},t);t.gfm=h({},t.normal,{fences:/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});t.gfm.paragraph=l(t.paragraph)("(?!","(?!"+t.gfm.fences.source.replace("\\1","\\2")+"|")();t.tables=h({},t.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function e(e){this.tokens=[];this.tokens.links={};this.options=e||a.defaults;this.rules=t.normal;if(this.options.gfm){if(this.options.tables){this.rules=t.tables}else{this.rules=t.gfm}}}e.rules=t;e.lex=function(t,n){var s=new e(n);return s.lex(t)};e.prototype.lex=function(t){t=t.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(t,true)};e.prototype.token=function(e,n){var e=e.replace(/^ +$/gm,""),s,i,r,l,o,h,a,u,p;while(e){if(r=this.rules.newline.exec(e)){e=e.substring(r[0].length);if(r[0].length>1){this.tokens.push({type:"space"})}}if(r=this.rules.code.exec(e)){e=e.substring(r[0].length);r=r[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?r.replace(/\n+$/,""):r});continue}if(r=this.rules.fences.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"code",lang:r[2],text:r[3]});continue}if(r=this.rules.heading.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"heading",depth:r[1].length,text:r[2]});continue}if(n&&(r=this.rules.nptable.exec(e))){e=e.substring(r[0].length);h={type:"table",header:r[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:r[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:r[3].replace(/\n$/,"").split("\n")};for(u=0;u<h.align.length;u++){if(/^ *-+: *$/.test(h.align[u])){h.align[u]="right"}else if(/^ *:-+: *$/.test(h.align[u])){h.align[u]="center"}else if(/^ *:-+ *$/.test(h.align[u])){h.align[u]="left"}else{h.align[u]=null}}for(u=0;u<h.cells.length;u++){h.cells[u]=h.cells[u].split(/ *\| */)}this.tokens.push(h);continue}if(r=this.rules.lheading.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"heading",depth:r[2]==="="?1:2,text:r[1]});continue}if(r=this.rules.hr.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"hr"});continue}if(r=this.rules.blockquote.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"blockquote_start"});r=r[0].replace(/^ *> ?/gm,"");this.token(r,n);this.tokens.push({type:"blockquote_end"});continue}if(r=this.rules.list.exec(e)){e=e.substring(r[0].length);l=r[2];this.tokens.push({type:"list_start",ordered:l.length>1});r=r[0].match(this.rules.item);s=false;p=r.length;u=0;for(;u<p;u++){h=r[u];a=h.length;h=h.replace(/^ *([*+-]|\d+\.) +/,"");if(~h.indexOf("\n ")){a-=h.length;h=!this.options.pedantic?h.replace(new RegExp("^ {1,"+a+"}","gm"),""):h.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&u!==p-1){o=t.bullet.exec(r[u+1])[0];if(l!==o&&!(l.length>1&&o.length>1)){e=r.slice(u+1).join("\n")+e;u=p-1}}i=s||/\n\n(?!\s*$)/.test(h);if(u!==p-1){s=h[h.length-1]==="\n";if(!i)i=s}this.tokens.push({type:i?"loose_item_start":"list_item_start"});this.token(h,false);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(r=this.rules.html.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:r[1]==="pre"||r[1]==="script",text:r[0]});continue}if(n&&(r=this.rules.def.exec(e))){e=e.substring(r[0].length);this.tokens.links[r[1].toLowerCase()]={href:r[2],title:r[3]};continue}if(n&&(r=this.rules.table.exec(e))){e=e.substring(r[0].length);h={type:"table",header:r[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:r[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:r[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(u=0;u<h.align.length;u++){if(/^ *-+: *$/.test(h.align[u])){h.align[u]="right"}else if(/^ *:-+: *$/.test(h.align[u])){h.align[u]="center"}else if(/^ *:-+ *$/.test(h.align[u])){h.align[u]="left"}else{h.align[u]=null}}for(u=0;u<h.cells.length;u++){h.cells[u]=h.cells[u].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(h);continue}if(n&&(r=this.rules.paragraph.exec(e))){e=e.substring(r[0].length);this.tokens.push({type:"paragraph",text:r[1][r[1].length-1]==="\n"?r[1].slice(0,-1):r[1]});continue}if(r=this.rules.text.exec(e)){e=e.substring(r[0].length);this.tokens.push({type:"text",text:r[0]});continue}if(e){throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}}return this.tokens};var n={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:o,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:o,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};n._inside=/(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;n._href=/\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;n.link=l(n.link)("inside",n._inside)("href",n._href)();n.reflink=l(n.reflink)("inside",n._inside)();n.normal=h({},n);n.pedantic=h({},n.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});n.gfm=h({},n.normal,{escape:l(n.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:l(n.text)("]|","~]|")("|","|https?://|")()});n.breaks=h({},n.gfm,{br:l(n.br)("{2,}","*")(),text:l(n.gfm.text)("{2,}","*")()});function s(t,e){this.options=e||a.defaults;this.links=t;this.rules=n.normal;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=n.breaks}else{this.rules=n.gfm}}else if(this.options.pedantic){this.rules=n.pedantic}}s.rules=n;s.output=function(t,e,n){var i=new s(e,n);return i.output(t)};s.prototype.output=function(t){var e="",n,s,i,l;while(t){if(l=this.rules.escape.exec(t)){t=t.substring(l[0].length);e+=l[1];continue}if(l=this.rules.autolink.exec(t)){t=t.substring(l[0].length);if(l[2]==="@"){s=l[1][6]===":"?this.mangle(l[1].substring(7)):this.mangle(l[1]);i=this.mangle("mailto:")+s}else{s=r(l[1]);i=s}e+='<a href="'+i+'">'+s+"</a>";continue}if(l=this.rules.url.exec(t)){t=t.substring(l[0].length);s=r(l[1]);i=s;e+='<a href="'+i+'">'+s+"</a>";continue}if(l=this.rules.tag.exec(t)){t=t.substring(l[0].length);e+=this.options.sanitize?r(l[0]):l[0];continue}if(l=this.rules.link.exec(t)){t=t.substring(l[0].length);e+=this.outputLink(l,{href:l[2],title:l[3]});continue}if((l=this.rules.reflink.exec(t))||(l=this.rules.nolink.exec(t))){t=t.substring(l[0].length);n=(l[2]||l[1]).replace(/\s+/g," ");n=this.links[n.toLowerCase()];if(!n||!n.href){e+=l[0][0];t=l[0].substring(1)+t;continue}e+=this.outputLink(l,n);continue}if(l=this.rules.strong.exec(t)){t=t.substring(l[0].length);e+="<strong>"+this.output(l[2]||l[1])+"</strong>";continue}if(l=this.rules.em.exec(t)){t=t.substring(l[0].length);e+="<em>"+this.output(l[2]||l[1])+"</em>";continue}if(l=this.rules.code.exec(t)){t=t.substring(l[0].length);e+="<code>"+r(l[2],true)+"</code>";continue}if(l=this.rules.br.exec(t)){t=t.substring(l[0].length);e+="<br>";continue}if(l=this.rules.del.exec(t)){t=t.substring(l[0].length);e+="<del>"+this.output(l[1])+"</del>";continue}if(l=this.rules.text.exec(t)){t=t.substring(l[0].length);e+=r(l[0]);continue}if(t){throw new Error("Infinite loop on byte: "+t.charCodeAt(0))}}return e};s.prototype.outputLink=function(t,e){if(t[0][0]!=="!"){return'<a href="'+r(e.href)+'"'+(e.title?' title="'+r(e.title)+'"':"")+">"+this.output(t[1])+"</a>"}else{return'<img src="'+r(e.href)+'" alt="'+r(t[1])+'"'+(e.title?' title="'+r(e.title)+'"':"")+">"}};s.prototype.smartypants=function(t){if(!this.options.smartypants)return t;return t.replace(/--/g,"—").replace(/'([^']*)'/g,"‘$1’").replace(/"([^"]*)"/g,"“$1”").replace(/\.{3}/g,"…")};s.prototype.mangle=function(t){var e="",n=t.length,s=0,i;for(;s<n;s++){i=t.charCodeAt(s);if(Math.random()>.5){i="x"+i.toString(16)}e+="&#"+i+";"}return e};function i(t){this.tokens=[];this.token=null;this.options=t||a.defaults}i.parse=function(t,e){var n=new i(e);return n.parse(t)};i.prototype.parse=function(t){this.inline=new s(t.links,this.options);this.tokens=t.reverse();var e="";while(this.next()){e+=this.tok()}return e};i.prototype.next=function(){return this.token=this.tokens.pop()};i.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};i.prototype.parseText=function(){var t=this.token.text;while(this.peek().type==="text"){t+="\n"+this.next().text}return this.inline.output(t)};i.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return"<hr>\n"}case"heading":{return"<h"+this.token.depth+">"+this.inline.output(this.token.text)+"</h"+this.token.depth+">\n"}case"code":{if(this.options.highlight){var t=this.options.highlight(this.token.text,this.token.lang);if(t!=null&&t!==this.token.text){this.token.escaped=true;this.token.text=t}}if(!this.token.escaped){this.token.text=r(this.token.text,true)}return"<pre><code"+(this.token.lang?' class="'+this.options.langPrefix+this.token.lang+'"':"")+">"+this.token.text+"</code></pre>\n"}case"table":{var e="",n,s,i,l,o;e+="<thead>\n<tr>\n";for(s=0;s<this.token.header.length;s++){n=this.inline.output(this.token.header[s]);e+=this.token.align[s]?'<th align="'+this.token.align[s]+'">'+n+"</th>\n":"<th>"+n+"</th>\n"}e+="</tr>\n</thead>\n";e+="<tbody>\n";for(s=0;s<this.token.cells.length;s++){i=this.token.cells[s];e+="<tr>\n";for(o=0;o<i.length;o++){l=this.inline.output(i[o]);e+=this.token.align[o]?'<td align="'+this.token.align[o]+'">'+l+"</td>\n":"<td>"+l+"</td>\n"}e+="</tr>\n"}e+="</tbody>\n";return"<table>\n"+e+"</table>\n"}case"blockquote_start":{var e="";while(this.next().type!=="blockquote_end"){e+=this.tok()}return"<blockquote>\n"+e+"</blockquote>\n"}case"list_start":{var h=this.token.ordered?"ol":"ul",e="";while(this.next().type!=="list_end"){e+=this.tok()}return"<"+h+">\n"+e+"</"+h+">\n"}case"list_item_start":{var e="";while(this.next().type!=="list_item_end"){e+=this.token.type==="text"?this.parseText():this.tok()}return"<li>"+e+"</li>\n"}case"loose_item_start":{var e="";while(this.next().type!=="list_item_end"){e+=this.tok()}return"<li>"+e+"</li>\n"}case"html":{return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text}case"paragraph":{return"<p>"+this.inline.output(this.token.text)+"</p>\n"}case"text":{return"<p>"+this.parseText()+"</p>\n"}}};function r(t,e){return t.replace(!e?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function l(t,e){t=t.source;e=e||"";return function n(s,i){if(!s)return new RegExp(t,e);i=i.source||i;i=i.replace(/(^|[^\[])\^/g,"$1");t=t.replace(s,i);return n}}function o(){}o.exec=o;function h(t){var e=1,n,s;for(;e<arguments.length;e++){n=arguments[e];for(s in n){if(Object.prototype.hasOwnProperty.call(n,s)){t[s]=n[s]}}}return t}function a(t,n,s){if(s||typeof n==="function"){if(!s){s=n;n=null}if(n)n=h({},a.defaults,n);var l=e.lex(l,n),o=n.highlight,u=0,p=l.length,g=0;if(!o||o.length<3){return s(null,i.parse(l,n))}var c=function(){delete n.highlight;var t=i.parse(l,n);n.highlight=o;return s(null,t)};for(;g<p;g++){(function(t){if(t.type!=="code")return;u++;return o(t.text,t.lang,function(e,n){if(n==null||n===t.text){return--u||c()}t.text=n;t.escaped=true;--u||c()})})(l[g])}return}try{if(n)n=h({},a.defaults,n);return i.parse(e.lex(t,n),n)}catch(f){f.message+="\nPlease report this to https://github.com/chjj/marked.";if((n||a.defaults).silent){return"<p>An error occured:</p><pre>"+r(f.message+"",true)+"</pre>"}throw f}}a.options=a.setOptions=function(t){h(a.defaults,t);return a};a.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:"lang-"};a.Parser=i;a.parser=i.parse;a.Lexer=e;a.lexer=e.lex;a.InlineLexer=s;a.inlineLexer=s.output;a.parse=a;if(typeof exports==="object"){module.exports=a}else if(typeof define==="function"&&define.amd){define(function(){return a})}else{this.marked=a}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
507
+
508
+ /*!
509
+ * base64.js
510
+ * http://github.com/dankogai/js-base64
511
+ */
512
+
513
+ (function(r){"use strict";if(r.Base64)return;var e="2.1.2";var t;if(typeof module!=="undefined"&&module.exports){t=require("buffer").Buffer}var n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var a=function(r){var e={};for(var t=0,n=r.length;t<n;t++)e[r.charAt(t)]=t;return e}(n);var o=String.fromCharCode;var u=function(r){if(r.length<2){var e=r.charCodeAt(0);return e<128?r:e<2048?o(192|e>>>6)+o(128|e&63):o(224|e>>>12&15)+o(128|e>>>6&63)+o(128|e&63)}else{var e=65536+(r.charCodeAt(0)-55296)*1024+(r.charCodeAt(1)-56320);return o(240|e>>>18&7)+o(128|e>>>12&63)+o(128|e>>>6&63)+o(128|e&63)}};var c=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;var i=function(r){return r.replace(c,u)};var f=function(r){var e=[0,2,1][r.length%3],t=r.charCodeAt(0)<<16|(r.length>1?r.charCodeAt(1):0)<<8|(r.length>2?r.charCodeAt(2):0),a=[n.charAt(t>>>18),n.charAt(t>>>12&63),e>=2?"=":n.charAt(t>>>6&63),e>=1?"=":n.charAt(t&63)];return a.join("")};var h=r.btoa||function(r){return r.replace(/[\s\S]{1,3}/g,f)};var d=t?function(r){return new t(r).toString("base64")}:function(r){return h(i(r))};var v=function(r,e){return!e?d(r):d(r).replace(/[+\/]/g,function(r){return r=="+"?"-":"_"}).replace(/=/g,"")};var g=function(r){return v(r,true)};var l=new RegExp(["[À-ß][€-¿]","[à-ï][€-¿]{2}","[ð-÷][€-¿]{3}"].join("|"),"g");var A=function(r){switch(r.length){case 4:var e=(7&r.charCodeAt(0))<<18|(63&r.charCodeAt(1))<<12|(63&r.charCodeAt(2))<<6|63&r.charCodeAt(3),t=e-65536;return o((t>>>10)+55296)+o((t&1023)+56320);case 3:return o((15&r.charCodeAt(0))<<12|(63&r.charCodeAt(1))<<6|63&r.charCodeAt(2));default:return o((31&r.charCodeAt(0))<<6|63&r.charCodeAt(1))}};var s=function(r){return r.replace(l,A)};var p=function(r){var e=r.length,t=e%4,n=(e>0?a[r.charAt(0)]<<18:0)|(e>1?a[r.charAt(1)]<<12:0)|(e>2?a[r.charAt(2)]<<6:0)|(e>3?a[r.charAt(3)]:0),u=[o(n>>>16),o(n>>>8&255),o(n&255)];u.length-=[0,0,2,1][t];return u.join("")};var C=r.atob||function(r){return r.replace(/[\s\S]{1,4}/g,p)};var b=t?function(r){return new t(r,"base64").toString()}:function(r){return s(C(r))};var B=function(r){return b(r.replace(/[-_]/g,function(r){return r=="-"?"+":"/"}).replace(/[^A-Za-z0-9\+\/]/g,""))};r.Base64={VERSION:e,atob:C,btoa:h,fromBase64:B,toBase64:v,utob:i,encode:v,encodeURI:g,btou:s,decode:B};if(typeof Object.defineProperty==="function"){var S=function(r){return{value:r,enumerable:false,writable:true,configurable:true}};r.Base64.extendString=function(){Object.defineProperty(String.prototype,"fromBase64",S(function(){return B(this)}));Object.defineProperty(String.prototype,"toBase64",S(function(r){return v(this,r)}));Object.defineProperty(String.prototype,"toBase64URI",S(function(){return v(this,true)}))}}})(this);
514
+
515
+ /* jshint ignore:end */
shared/docs/js/jquery.js ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*! jQuery v1.9.1 | (c) 2005, 2012 jQuery Foundation, Inc. | jquery.org/license
2
+ //@ sourceMappingURL=jquery.min.map
3
+ */(function(e,t){var n,r,i=typeof t,o=e.document,a=e.location,s=e.jQuery,u=e.$,l={},c=[],p="1.9.1",f=c.concat,d=c.push,h=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,b=function(e,t){return new b.fn.init(e,t,r)},x=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^[\],:{}\s]*$/,E=/(?:^|:|,)(?:\s*\[)+/g,S=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,A=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,j=/^-ms-/,D=/-([\da-z])/gi,L=function(e,t){return t.toUpperCase()},H=function(e){(o.addEventListener||"load"===e.type||"complete"===o.readyState)&&(q(),b.ready())},q=function(){o.addEventListener?(o.removeEventListener("DOMContentLoaded",H,!1),e.removeEventListener("load",H,!1)):(o.detachEvent("onreadystatechange",H),e.detachEvent("onload",H))};b.fn=b.prototype={jquery:p,constructor:b,init:function(e,n,r){var i,a;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof b?n[0]:n,b.merge(this,b.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:o,!0)),C.test(i[1])&&b.isPlainObject(n))for(i in n)b.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(a=o.getElementById(i[2]),a&&a.parentNode){if(a.id!==i[2])return r.find(e);this.length=1,this[0]=a}return this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):b.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),b.makeArray(e,this))},selector:"",length:0,size:function(){return this.length},toArray:function(){return h.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=b.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return b.each(this,e,t)},ready:function(e){return b.ready.promise().done(e),this},slice:function(){return this.pushStack(h.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(b.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:d,sort:[].sort,splice:[].splice},b.fn.init.prototype=b.fn,b.extend=b.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},u=1,l=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},u=2),"object"==typeof s||b.isFunction(s)||(s={}),l===u&&(s=this,--u);l>u;u++)if(null!=(o=arguments[u]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(b.isPlainObject(r)||(n=b.isArray(r)))?(n?(n=!1,a=e&&b.isArray(e)?e:[]):a=e&&b.isPlainObject(e)?e:{},s[i]=b.extend(c,a,r)):r!==t&&(s[i]=r));return s},b.extend({noConflict:function(t){return e.$===b&&(e.$=u),t&&e.jQuery===b&&(e.jQuery=s),b},isReady:!1,readyWait:1,holdReady:function(e){e?b.readyWait++:b.ready(!0)},ready:function(e){if(e===!0?!--b.readyWait:!b.isReady){if(!o.body)return setTimeout(b.ready);b.isReady=!0,e!==!0&&--b.readyWait>0||(n.resolveWith(o,[b]),b.fn.trigger&&b(o).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===b.type(e)},isArray:Array.isArray||function(e){return"array"===b.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if(!e||"object"!==b.type(e)||e.nodeType||b.isWindow(e))return!1;try{if(e.constructor&&!y.call(e,"constructor")&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||y.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=b.buildFragment([e],t,i),i&&b(i).remove(),b.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=b.trim(n),n&&k.test(n.replace(S,"@").replace(A,"]").replace(E,"")))?Function("return "+n)():(b.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||b.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&b.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(j,"ms-").replace(D,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:v&&!v.call("\ufeff\u00a0")?function(e){return null==e?"":v.call(e)}:function(e){return null==e?"":(e+"").replace(T,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?b.merge(n,"string"==typeof e?[e]:e):d.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(g)return g.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return f.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),b.isFunction(e)?(r=h.call(arguments,2),i=function(){return e.apply(n||this,r.concat(h.call(arguments)))},i.guid=e.guid=e.guid||b.guid++,i):t},access:function(e,n,r,i,o,a,s){var u=0,l=e.length,c=null==r;if("object"===b.type(r)){o=!0;for(u in r)b.access(e,n,u,r[u],!0,a,s)}else if(i!==t&&(o=!0,b.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(b(e),n)})),n))for(;l>u;u++)n(e[u],r,s?i:i.call(e[u],u,n(e[u],r)));return o?e:c?n.call(e):l?n(e[0],r):a},now:function(){return(new Date).getTime()}}),b.ready.promise=function(t){if(!n)if(n=b.Deferred(),"complete"===o.readyState)setTimeout(b.ready);else if(o.addEventListener)o.addEventListener("DOMContentLoaded",H,!1),e.addEventListener("load",H,!1);else{o.attachEvent("onreadystatechange",H),e.attachEvent("onload",H);var r=!1;try{r=null==e.frameElement&&o.documentElement}catch(i){}r&&r.doScroll&&function a(){if(!b.isReady){try{r.doScroll("left")}catch(e){return setTimeout(a,50)}q(),b.ready()}}()}return n.promise(t)},b.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=b.type(e);return b.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=b(o);var _={};function F(e){var t=_[e]={};return b.each(e.match(w)||[],function(e,n){t[n]=!0}),t}b.Callbacks=function(e){e="string"==typeof e?_[e]||F(e):b.extend({},e);var n,r,i,o,a,s,u=[],l=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=u.length,n=!0;u&&o>a;a++)if(u[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,u&&(l?l.length&&c(l.shift()):r?u=[]:p.disable())},p={add:function(){if(u){var t=u.length;(function i(t){b.each(t,function(t,n){var r=b.type(n);"function"===r?e.unique&&p.has(n)||u.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=u.length:r&&(s=t,c(r))}return this},remove:function(){return u&&b.each(arguments,function(e,t){var r;while((r=b.inArray(t,u,r))>-1)u.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?b.inArray(e,u)>-1:!(!u||!u.length)},empty:function(){return u=[],this},disable:function(){return u=l=r=t,this},disabled:function(){return!u},lock:function(){return l=t,r||p.disable(),this},locked:function(){return!l},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],!u||i&&!l||(n?l.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},b.extend({Deferred:function(e){var t=[["resolve","done",b.Callbacks("once memory"),"resolved"],["reject","fail",b.Callbacks("once memory"),"rejected"],["notify","progress",b.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return b.Deferred(function(n){b.each(t,function(t,o){var a=o[0],s=b.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&b.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?b.extend(e,r):r}},i={};return r.pipe=r.then,b.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=h.call(arguments),r=n.length,i=1!==r||e&&b.isFunction(e.promise)?r:0,o=1===i?e:b.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?h.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,u,l;if(r>1)for(s=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&b.isFunction(n[t].promise)?n[t].promise().done(a(t,l,n)).fail(o.reject).progress(a(t,u,s)):--i;return i||o.resolveWith(l,n),o.promise()}}),b.support=function(){var t,n,r,a,s,u,l,c,p,f,d=o.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*"),r=d.getElementsByTagName("a")[0],!n||!r||!n.length)return{};s=o.createElement("select"),l=s.appendChild(o.createElement("option")),a=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={getSetAttribute:"t"!==d.className,leadingWhitespace:3===d.firstChild.nodeType,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:"/a"===r.getAttribute("href"),opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:!!a.value,optSelected:l.selected,enctype:!!o.createElement("form").enctype,html5Clone:"<:nav></:nav>"!==o.createElement("nav").cloneNode(!0).outerHTML,boxModel:"CSS1Compat"===o.compatMode,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},a.checked=!0,t.noCloneChecked=a.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!l.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}a=o.createElement("input"),a.setAttribute("value",""),t.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),t.radioValue="t"===a.value,a.setAttribute("checked","t"),a.setAttribute("name","t"),u=o.createDocumentFragment(),u.appendChild(a),t.appendChecked=a.checked,t.checkClone=u.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;return d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip,b(function(){var n,r,a,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",u=o.getElementsByTagName("body")[0];u&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",u.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",a=d.getElementsByTagName("td"),a[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===a[0].offsetHeight,a[0].style.display="",a[1].style.display="none",t.reliableHiddenOffsets=p&&0===a[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=4===d.offsetWidth,t.doesNotIncludeMarginInBodyOffset=1!==u.offsetTop,e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(o.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(u.style.zoom=1)),u.removeChild(n),n=d=a=r=null)}),n=s=u=l=r=a=null,t}();var O=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,B=/([A-Z])/g;function P(e,n,r,i){if(b.acceptData(e)){var o,a,s=b.expando,u="string"==typeof n,l=e.nodeType,p=l?b.cache:e,f=l?e[s]:e[s]&&s;if(f&&p[f]&&(i||p[f].data)||!u||r!==t)return f||(l?e[s]=f=c.pop()||b.guid++:f=s),p[f]||(p[f]={},l||(p[f].toJSON=b.noop)),("object"==typeof n||"function"==typeof n)&&(i?p[f]=b.extend(p[f],n):p[f].data=b.extend(p[f].data,n)),o=p[f],i||(o.data||(o.data={}),o=o.data),r!==t&&(o[b.camelCase(n)]=r),u?(a=o[n],null==a&&(a=o[b.camelCase(n)])):a=o,a}}function R(e,t,n){if(b.acceptData(e)){var r,i,o,a=e.nodeType,s=a?b.cache:e,u=a?e[b.expando]:b.expando;if(s[u]){if(t&&(o=n?s[u]:s[u].data)){b.isArray(t)?t=t.concat(b.map(t,b.camelCase)):t in o?t=[t]:(t=b.camelCase(t),t=t in o?[t]:t.split(" "));for(r=0,i=t.length;i>r;r++)delete o[t[r]];if(!(n?$:b.isEmptyObject)(o))return}(n||(delete s[u].data,$(s[u])))&&(a?b.cleanData([e],!0):b.support.deleteExpando||s!=s.window?delete s[u]:s[u]=null)}}}b.extend({cache:{},expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?b.cache[e[b.expando]]:e[b.expando],!!e&&!$(e)},data:function(e,t,n){return P(e,t,n)},removeData:function(e,t){return R(e,t)},_data:function(e,t,n){return P(e,t,n,!0)},_removeData:function(e,t){return R(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&b.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),b.fn.extend({data:function(e,n){var r,i,o=this[0],a=0,s=null;if(e===t){if(this.length&&(s=b.data(o),1===o.nodeType&&!b._data(o,"parsedAttrs"))){for(r=o.attributes;r.length>a;a++)i=r[a].name,i.indexOf("data-")||(i=b.camelCase(i.slice(5)),W(o,i,s[i]));b._data(o,"parsedAttrs",!0)}return s}return"object"==typeof e?this.each(function(){b.data(this,e)}):b.access(this,function(n){return n===t?o?W(o,e,b.data(o,e)):null:(this.each(function(){b.data(this,e,n)}),t)},null,n,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function W(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(B,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:O.test(r)?b.parseJSON(r):r}catch(o){}b.data(e,n,r)}else r=t}return r}function $(e){var t;for(t in e)if(("data"!==t||!b.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}b.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=b._data(e,n),r&&(!i||b.isArray(r)?i=b._data(e,n,b.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=b.queue(e,t),r=n.length,i=n.shift(),o=b._queueHooks(e,t),a=function(){b.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),o.cur=i,i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return b._data(e,n)||b._data(e,n,{empty:b.Callbacks("once memory").add(function(){b._removeData(e,t+"queue"),b._removeData(e,n)})})}}),b.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?b.queue(this[0],e):n===t?this:this.each(function(){var t=b.queue(this,e,n);b._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&b.dequeue(this,e)})},dequeue:function(e){return this.each(function(){b.dequeue(this,e)})},delay:function(e,t){return e=b.fx?b.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=b.Deferred(),a=this,s=this.length,u=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=b._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(u));return u(),o.promise(n)}});var I,z,X=/[\t\r\n]/g,U=/\r/g,V=/^(?:input|select|textarea|button|object)$/i,Y=/^(?:a|area)$/i,J=/^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,G=/^(?:checked|selected)$/i,Q=b.support.getSetAttribute,K=b.support.input;b.fn.extend({attr:function(e,t){return b.access(this,b.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,t){return b.access(this,b.prop,e,t,arguments.length>1)},removeProp:function(e){return e=b.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,u="string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=b.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,u=0===arguments.length||"string"==typeof e&&e;if(b.isFunction(e))return this.each(function(t){b(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(X," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?b.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e,r="boolean"==typeof t;return b.isFunction(e)?this.each(function(n){b(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var o,a=0,s=b(this),u=t,l=e.match(w)||[];while(o=l[a++])u=r?u:!s.hasClass(o),s[u?"addClass":"removeClass"](o)}else(n===i||"boolean"===n)&&(this.className&&b._data(this,"__className__",this.className),this.className=this.className||e===!1?"":b._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(X," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=b.isFunction(e),this.each(function(n){var o,a=b(this);1===this.nodeType&&(o=i?e.call(this,n,a.val()):e,null==o?o="":"number"==typeof o?o+="":b.isArray(o)&&(o=b.map(o,function(e){return null==e?"":e+""})),r=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=b.valHooks[o.type]||b.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(U,""):null==n?"":n)}}}),b.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,u=0>i?s:o?i:0;for(;s>u;u++)if(n=r[u],!(!n.selected&&u!==i||(b.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&b.nodeName(n.parentNode,"optgroup"))){if(t=b(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n=b.makeArray(t);return b(e).find("option").each(function(){this.selected=b.inArray(b(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attr:function(e,n,r){var o,a,s,u=e.nodeType;if(e&&3!==u&&8!==u&&2!==u)return typeof e.getAttribute===i?b.prop(e,n,r):(a=1!==u||!b.isXMLDoc(e),a&&(n=n.toLowerCase(),o=b.attrHooks[n]||(J.test(n)?z:I)),r===t?o&&a&&"get"in o&&null!==(s=o.get(e,n))?s:(typeof e.getAttribute!==i&&(s=e.getAttribute(n)),null==s?t:s):null!==r?o&&a&&"set"in o&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r):(b.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=b.propFix[n]||n,J.test(n)?!Q&&G.test(n)?e[b.camelCase("default-"+n)]=e[r]=!1:e[r]=!1:b.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!b.support.radioValue&&"radio"===t&&b.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!b.isXMLDoc(e),a&&(n=b.propFix[n]||n,o=b.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):V.test(e.nodeName)||Y.test(e.nodeName)&&e.href?0:t}}}}),z={get:function(e,n){var r=b.prop(e,n),i="boolean"==typeof r&&e.getAttribute(n),o="boolean"==typeof r?K&&Q?null!=i:G.test(n)?e[b.camelCase("default-"+n)]:!!i:e.getAttributeNode(n);return o&&o.value!==!1?n.toLowerCase():t},set:function(e,t,n){return t===!1?b.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&b.propFix[n]||n,n):e[b.camelCase("default-"+n)]=e[n]=!0,n}},K&&Q||(b.attrHooks.value={get:function(e,n){var r=e.getAttributeNode(n);return b.nodeName(e,"input")?e.defaultValue:r&&r.specified?r.value:t},set:function(e,n,r){return b.nodeName(e,"input")?(e.defaultValue=n,t):I&&I.set(e,n,r)}}),Q||(I=b.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&("id"===n||"name"===n||"coords"===n?""!==r.value:r.specified)?r.value:t},set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},b.attrHooks.contenteditable={get:I.get,set:function(e,t,n){I.set(e,""===t?!1:t,n)}},b.each(["width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}})})),b.support.hrefNormalized||(b.each(["href","src","width","height"],function(e,n){b.attrHooks[n]=b.extend(b.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return null==r?t:r}})}),b.each(["href","src"],function(e,t){b.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}})),b.support.style||(b.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),b.support.optSelected||(b.propHooks.selected=b.extend(b.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),b.support.enctype||(b.propFix.enctype="encoding"),b.support.checkOn||b.each(["radio","checkbox"],function(){b.valHooks[this]={get:function(e){return null===e.getAttribute("value")?"on":e.value}}}),b.each(["radio","checkbox"],function(){b.valHooks[this]=b.extend(b.valHooks[this],{set:function(e,n){return b.isArray(n)?e.checked=b.inArray(b(e).val(),n)>=0:t}})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}b.event={global:{},add:function(e,n,r,o,a){var s,u,l,c,p,f,d,h,g,m,y,v=b._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=b.guid++),(u=v.events)||(u=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof b===i||e&&b.event.triggered===e.type?t:b.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(w)||[""],l=n.length;while(l--)s=rt.exec(n[l])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),p=b.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=b.event.special[g]||{},d=b.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&b.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=u[g])||(h=u[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),b.event.global[g]=!0;e=null}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,p,f,d,h,g,m=b.hasData(e)&&b._data(e);if(m&&(c=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(s=rt.exec(t[l])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=b.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),u=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));u&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||b.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)b.event.remove(e,d+t[l],n,r,!0);b.isEmptyObject(c)&&(delete m.handle,b._removeData(e,"events"))}},trigger:function(n,r,i,a){var s,u,l,c,p,f,d,h=[i||o],g=y.call(n,"type")?n.type:n,m=y.call(n,"namespace")?n.namespace.split("."):[];if(l=f=i=i||o,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+b.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),u=0>g.indexOf(":")&&"on"+g,n=n[b.expando]?n:new b.Event(g,"object"==typeof n&&n),n.isTrigger=!0,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:b.makeArray(r,[n]),p=b.event.special[g]||{},a||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!a&&!p.noBubble&&!b.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(l=l.parentNode);l;l=l.parentNode)h.push(l),f=l;f===(i.ownerDocument||o)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((l=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(b._data(l,"events")||{})[n.type]&&b._data(l,"handle"),s&&s.apply(l,r),s=u&&l[u],s&&b.acceptData(l)&&s.apply&&s.apply(l,r)===!1&&n.preventDefault();if(n.type=g,!(a||n.isDefaultPrevented()||p._default&&p._default.apply(i.ownerDocument,r)!==!1||"click"===g&&b.nodeName(i,"a")||!b.acceptData(i)||!u||!i[g]||b.isWindow(i))){f=i[u],f&&(i[u]=null),b.event.triggered=g;try{i[g]()}catch(v){}b.event.triggered=t,f&&(i[u]=f)}return n.result}},dispatch:function(e){e=b.event.fix(e);var n,r,i,o,a,s=[],u=h.call(arguments),l=(b._data(this,"events")||{})[e.type]||[],c=b.event.special[e.type]||{};if(u[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=b.event.handlers.call(this,e,l),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((b.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,u),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],u=n.delegateCount,l=e.target;if(u&&l.nodeType&&(!e.button||"click"!==e.type))for(;l!=this;l=l.parentNode||this)if(1===l.nodeType&&(l.disabled!==!0||"click"!==e.type)){for(o=[],a=0;u>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?b(r,this).index(l)>=0:b.find(r,this,null,[l]).length),o[r]&&o.push(i);o.length&&s.push({elem:l,handlers:o})}return n.length>u&&s.push({elem:this,handlers:n.slice(u)}),s},fix:function(e){if(e[b.expando])return e;var t,n,r,i=e.type,a=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new b.Event(a),t=r.length;while(t--)n=r[t],e[n]=a[n];return e.target||(e.target=a.srcElement||o),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,a):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,a,s=n.button,u=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||o,a=i.documentElement,r=i.body,e.pageX=n.clientX+(a&&a.scrollLeft||r&&r.scrollLeft||0)-(a&&a.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(a&&a.scrollTop||r&&r.scrollTop||0)-(a&&a.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&u&&(e.relatedTarget=u===e.target?n.toElement:u),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},click:{trigger:function(){return b.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t}},focus:{trigger:function(){if(this!==o.activeElement&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===o.activeElement&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=b.extend(new b.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?b.event.trigger(i,null,t):b.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},b.removeEvent=o.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},b.Event=function(e,n){return this instanceof b.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&b.extend(this,n),this.timeStamp=e&&e.timeStamp||b.now(),this[b.expando]=!0,t):new b.Event(e,n)},b.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},b.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){b.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;
4
+ return(!i||i!==r&&!b.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),b.support.submitBubbles||(b.event.special.submit={setup:function(){return b.nodeName(this,"form")?!1:(b.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=b.nodeName(n,"input")||b.nodeName(n,"button")?n.form:t;r&&!b._data(r,"submitBubbles")&&(b.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),b._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&b.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return b.nodeName(this,"form")?!1:(b.event.remove(this,"._submit"),t)}}),b.support.changeBubbles||(b.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(b.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),b.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),b.event.simulate("change",this,e,!0)})),!1):(b.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!b._data(t,"changeBubbles")&&(b.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||b.event.simulate("change",this.parentNode,e,!0)}),b._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return b.event.remove(this,"._change"),!Z.test(this.nodeName)}}),b.support.focusinBubbles||b.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){b.event.simulate(t,e.target,b.event.fix(e),!0)};b.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),b.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return b().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=b.guid++)),this.each(function(){b.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,b(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){b.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){b.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?b.event.trigger(e,n,r,!0):t}}),function(e,t){var n,r,i,o,a,s,u,l,c,p,f,d,h,g,m,y,v,x="sizzle"+-new Date,w=e.document,T={},N=0,C=0,k=it(),E=it(),S=it(),A=typeof t,j=1<<31,D=[],L=D.pop,H=D.push,q=D.slice,M=D.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},_="[\\x20\\t\\r\\n\\f]",F="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=F.replace("w","w#"),B="([*^$|!~]?=)",P="\\["+_+"*("+F+")"+_+"*(?:"+B+_+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+O+")|)|)"+_+"*\\]",R=":("+F+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+P.replace(3,8)+")*)|.*)\\)|)",W=RegExp("^"+_+"+|((?:^|[^\\\\])(?:\\\\.)*)"+_+"+$","g"),$=RegExp("^"+_+"*,"+_+"*"),I=RegExp("^"+_+"*([\\x20\\t\\r\\n\\f>+~])"+_+"*"),z=RegExp(R),X=RegExp("^"+O+"$"),U={ID:RegExp("^#("+F+")"),CLASS:RegExp("^\\.("+F+")"),NAME:RegExp("^\\[name=['\"]?("+F+")['\"]?\\]"),TAG:RegExp("^("+F.replace("w","w*")+")"),ATTR:RegExp("^"+P),PSEUDO:RegExp("^"+R),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+_+"*(even|odd|(([+-]|)(\\d*)n|)"+_+"*(?:([+-]|)"+_+"*(\\d+)|))"+_+"*\\)|)","i"),needsContext:RegExp("^"+_+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+_+"*((?:-\\d)?\\d*)"+_+"*\\)|)(?=[^-]|$)","i")},V=/[\x20\t\r\n\f]*[+~]/,Y=/^[^{]+\{\s*\[native code/,J=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,G=/^(?:input|select|textarea|button)$/i,Q=/^h\d$/i,K=/'|\\/g,Z=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,et=/\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,tt=function(e,t){var n="0x"+t-65536;return n!==n?t:0>n?String.fromCharCode(n+65536):String.fromCharCode(55296|n>>10,56320|1023&n)};try{q.call(w.documentElement.childNodes,0)[0].nodeType}catch(nt){q=function(e){var t,n=[];while(t=this[e++])n.push(t);return n}}function rt(e){return Y.test(e+"")}function it(){var e,t=[];return e=function(n,r){return t.push(n+=" ")>i.cacheLength&&delete e[t.shift()],e[n]=r}}function ot(e){return e[x]=!0,e}function at(e){var t=p.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}}function st(e,t,n,r){var i,o,a,s,u,l,f,g,m,v;if((t?t.ownerDocument||t:w)!==p&&c(t),t=t||p,n=n||[],!e||"string"!=typeof e)return n;if(1!==(s=t.nodeType)&&9!==s)return[];if(!d&&!r){if(i=J.exec(e))if(a=i[1]){if(9===s){if(o=t.getElementById(a),!o||!o.parentNode)return n;if(o.id===a)return n.push(o),n}else if(t.ownerDocument&&(o=t.ownerDocument.getElementById(a))&&y(t,o)&&o.id===a)return n.push(o),n}else{if(i[2])return H.apply(n,q.call(t.getElementsByTagName(e),0)),n;if((a=i[3])&&T.getByClassName&&t.getElementsByClassName)return H.apply(n,q.call(t.getElementsByClassName(a),0)),n}if(T.qsa&&!h.test(e)){if(f=!0,g=x,m=t,v=9===s&&e,1===s&&"object"!==t.nodeName.toLowerCase()){l=ft(e),(f=t.getAttribute("id"))?g=f.replace(K,"\\$&"):t.setAttribute("id",g),g="[id='"+g+"'] ",u=l.length;while(u--)l[u]=g+dt(l[u]);m=V.test(e)&&t.parentNode||t,v=l.join(",")}if(v)try{return H.apply(n,q.call(m.querySelectorAll(v),0)),n}catch(b){}finally{f||t.removeAttribute("id")}}}return wt(e.replace(W,"$1"),t,n,r)}a=st.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},c=st.setDocument=function(e){var n=e?e.ownerDocument||e:w;return n!==p&&9===n.nodeType&&n.documentElement?(p=n,f=n.documentElement,d=a(n),T.tagNameNoComments=at(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),T.attributes=at(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return"boolean"!==t&&"string"!==t}),T.getByClassName=at(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",e.getElementsByClassName&&e.getElementsByClassName("e").length?(e.lastChild.className="e",2===e.getElementsByClassName("e").length):!1}),T.getByName=at(function(e){e.id=x+0,e.innerHTML="<a name='"+x+"'></a><div name='"+x+"'></div>",f.insertBefore(e,f.firstChild);var t=n.getElementsByName&&n.getElementsByName(x).length===2+n.getElementsByName(x+0).length;return T.getIdNotName=!n.getElementById(x),f.removeChild(e),t}),i.attrHandle=at(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==A&&"#"===e.firstChild.getAttribute("href")})?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},T.getIdNotName?(i.find.ID=function(e,t){if(typeof t.getElementById!==A&&!d){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){return e.getAttribute("id")===t}}):(i.find.ID=function(e,n){if(typeof n.getElementById!==A&&!d){var r=n.getElementById(e);return r?r.id===e||typeof r.getAttributeNode!==A&&r.getAttributeNode("id").value===e?[r]:t:[]}},i.filter.ID=function(e){var t=e.replace(et,tt);return function(e){var n=typeof e.getAttributeNode!==A&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=T.tagNameNoComments?function(e,n){return typeof n.getElementsByTagName!==A?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.NAME=T.getByName&&function(e,n){return typeof n.getElementsByName!==A?n.getElementsByName(name):t},i.find.CLASS=T.getByClassName&&function(e,n){return typeof n.getElementsByClassName===A||d?t:n.getElementsByClassName(e)},g=[],h=[":focus"],(T.qsa=rt(n.querySelectorAll))&&(at(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||h.push("\\["+_+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||h.push(":checked")}),at(function(e){e.innerHTML="<input type='hidden' i=''/>",e.querySelectorAll("[i^='']").length&&h.push("[*^$]="+_+"*(?:\"\"|'')"),e.querySelectorAll(":enabled").length||h.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),h.push(",.*:")})),(T.matchesSelector=rt(m=f.matchesSelector||f.mozMatchesSelector||f.webkitMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&at(function(e){T.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",R)}),h=RegExp(h.join("|")),g=RegExp(g.join("|")),y=rt(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},v=f.compareDocumentPosition?function(e,t){var r;return e===t?(u=!0,0):(r=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t))?1&r||e.parentNode&&11===e.parentNode.nodeType?e===n||y(w,e)?-1:t===n||y(w,t)?1:0:4&r?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return u=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:0;if(o===a)return ut(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?ut(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},u=!1,[0,0].sort(v),T.detectDuplicates=u,p):p},st.matches=function(e,t){return st(e,null,null,t)},st.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Z,"='$1']"),!(!T.matchesSelector||d||g&&g.test(t)||h.test(t)))try{var n=m.call(e,t);if(n||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(r){}return st(t,p,null,[e]).length>0},st.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},st.attr=function(e,t){var n;return(e.ownerDocument||e)!==p&&c(e),d||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):d||T.attributes?e.getAttribute(t):((n=e.getAttributeNode(t))||e.getAttribute(t))&&e[t]===!0?t:n&&n.specified?n.value:null},st.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},st.uniqueSort=function(e){var t,n=[],r=1,i=0;if(u=!T.detectDuplicates,e.sort(v),u){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e};function ut(e,t){var n=t&&e,r=n&&(~t.sourceIndex||j)-(~e.sourceIndex||j);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function lt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ct(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function pt(e){return ot(function(t){return t=+t,ot(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}o=st.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=st.selectors={cacheLength:50,createPseudo:ot,match:U,find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(et,tt),e[3]=(e[4]||e[5]||"").replace(et,tt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||st.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&st.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return U.CHILD.test(e[0])?null:(e[4]?e[2]=e[4]:n&&z.test(n)&&(t=ft(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){return"*"===e?function(){return!0}:(e=e.replace(et,tt).toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[e+" "];return t||(t=RegExp("(^|"+_+")"+e+"("+_+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==A&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=st.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!u&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[x]||(m[x]={}),l=c[e]||[],d=l[0]===N&&l[1],f=l[0]===N&&l[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[N,d,f];break}}else if(v&&(l=(t[x]||(t[x]={}))[e])&&l[0]===N)f=l[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[x]||(p[x]={}))[e]=[N,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||st.error("unsupported pseudo: "+e);return r[x]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?ot(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=M.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:ot(function(e){var t=[],n=[],r=s(e.replace(W,"$1"));return r[x]?ot(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:ot(function(e){return function(t){return st(e,t).length>0}}),contains:ot(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:ot(function(e){return X.test(e||"")||st.error("unsupported lang: "+e),e=e.replace(et,tt).toLowerCase(),function(t){var n;do if(n=d?t.getAttribute("xml:lang")||t.getAttribute("lang"):t.lang)return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return Q.test(e.nodeName)},input:function(e){return G.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:pt(function(){return[0]}),last:pt(function(e,t){return[t-1]}),eq:pt(function(e,t,n){return[0>n?n+t:n]}),even:pt(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:pt(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:pt(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:pt(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}};for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[n]=lt(n);for(n in{submit:!0,reset:!0})i.pseudos[n]=ct(n);function ft(e,t){var n,r,o,a,s,u,l,c=E[e+" "];if(c)return t?0:c.slice(0);s=e,u=[],l=i.preFilter;while(s){(!n||(r=$.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),u.push(o=[])),n=!1,(r=I.exec(s))&&(n=r.shift(),o.push({value:n,type:r[0].replace(W," ")}),s=s.slice(n.length));for(a in i.filter)!(r=U[a].exec(s))||l[a]&&!(r=l[a](r))||(n=r.shift(),o.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?st.error(e):E(e,u).slice(0)}function dt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function ht(e,t,n){var i=t.dir,o=n&&"parentNode"===i,a=C++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,s){var u,l,c,p=N+" "+a;if(s){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[x]||(t[x]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,s)||r,l[1]===!0)return!0}}function gt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function mt(e,t,n,r,i){var o,a=[],s=0,u=e.length,l=null!=t;for(;u>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),l&&t.push(s));return a}function yt(e,t,n,r,i,o){return r&&!r[x]&&(r=yt(r)),i&&!i[x]&&(i=yt(i,o)),ot(function(o,a,s,u){var l,c,p,f=[],d=[],h=a.length,g=o||xt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:mt(g,f,e,s,u),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,u),r){l=mt(y,d),r(l,[],s,u),c=l.length;while(c--)(p=l[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?M.call(o,p):f[c])>-1&&(o[l]=!(a[l]=p))}}else y=mt(y===a?y.splice(h,y.length):y),i?i(null,a,y,u):H.apply(a,y)})}function vt(e){var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],u=a?1:0,c=ht(function(e){return e===t},s,!0),p=ht(function(e){return M.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==l)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>u;u++)if(n=i.relative[e[u].type])f=[ht(gt(f),n)];else{if(n=i.filter[e[u].type].apply(null,e[u].matches),n[x]){for(r=++u;o>r;r++)if(i.relative[e[r].type])break;return yt(u>1&&gt(f),u>1&&dt(e.slice(0,u-1)).replace(W,"$1"),n,r>u&&vt(e.slice(u,r)),o>r&&vt(e=e.slice(r)),o>r&&dt(e))}f.push(n)}return gt(f)}function bt(e,t){var n=0,o=t.length>0,a=e.length>0,s=function(s,u,c,f,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,T=l,C=s||a&&i.find.TAG("*",d&&u.parentNode||u),k=N+=null==T?1:Math.random()||.1;for(w&&(l=u!==p&&u,r=n);null!=(h=C[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,u,c)){f.push(h);break}w&&(N=k,r=++n)}o&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,o&&b!==v){g=0;while(m=t[g++])m(x,y,u,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=L.call(f));y=mt(y)}H.apply(f,y),w&&!s&&y.length>0&&v+t.length>1&&st.uniqueSort(f)}return w&&(N=k,l=T),x};return o?ot(s):s}s=st.compile=function(e,t){var n,r=[],i=[],o=S[e+" "];if(!o){t||(t=ft(e)),n=t.length;while(n--)o=vt(t[n]),o[x]?r.push(o):i.push(o);o=S(e,bt(i,r))}return o};function xt(e,t,n){var r=0,i=t.length;for(;i>r;r++)st(e,t[r],n);return n}function wt(e,t,n,r){var o,a,u,l,c,p=ft(e);if(!r&&1===p.length){if(a=p[0]=p[0].slice(0),a.length>2&&"ID"===(u=a[0]).type&&9===t.nodeType&&!d&&i.relative[a[1].type]){if(t=i.find.ID(u.matches[0].replace(et,tt),t)[0],!t)return n;e=e.slice(a.shift().value.length)}o=U.needsContext.test(e)?0:a.length;while(o--){if(u=a[o],i.relative[l=u.type])break;if((c=i.find[l])&&(r=c(u.matches[0].replace(et,tt),V.test(a[0].type)&&t.parentNode||t))){if(a.splice(o,1),e=r.length&&dt(a),!e)return H.apply(n,q.call(r,0)),n;break}}}return s(e,p)(r,t,d,n,V.test(e)),n}i.pseudos.nth=i.pseudos.eq;function Tt(){}i.filters=Tt.prototype=i.pseudos,i.setFilters=new Tt,c(),st.attr=b.attr,b.find=st,b.expr=st.selectors,b.expr[":"]=b.expr.pseudos,b.unique=st.uniqueSort,b.text=st.getText,b.isXMLDoc=st.isXML,b.contains=st.contains}(e);var at=/Until$/,st=/^(?:parents|prev(?:Until|All))/,ut=/^.[^:#\[\.,]*$/,lt=b.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};b.fn.extend({find:function(e){var t,n,r,i=this.length;if("string"!=typeof e)return r=this,this.pushStack(b(e).filter(function(){for(t=0;i>t;t++)if(b.contains(r[t],this))return!0}));for(n=[],t=0;i>t;t++)b.find(e,this[t],n);return n=this.pushStack(i>1?b.unique(n):n),n.selector=(this.selector?this.selector+" ":"")+e,n},has:function(e){var t,n=b(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(b.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1))},filter:function(e){return this.pushStack(ft(this,e,!0))},is:function(e){return!!e&&("string"==typeof e?lt.test(e)?b(e,this.context).index(this[0])>=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,o=[],a=lt.test(e)||"string"!=typeof e?b(e,t||this.context):0;for(;i>r;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&11!==n.nodeType){if(a?a.index(n)>-1:b.find.matchesSelector(n,e)){o.push(n);break}n=n.parentNode}}return this.pushStack(o.length>1?b.unique(o):o)},index:function(e){return e?"string"==typeof e?b.inArray(this[0],b(e)):b.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?b(e,t):b.makeArray(e&&e.nodeType?[e]:e),r=b.merge(this.get(),n);return this.pushStack(b.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),b.fn.andSelf=b.fn.addBack;function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}b.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(e,t,n){return b.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(e,t,n){return b.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return b.dir(e,"previousSibling",n)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.merge([],e.childNodes)}},function(e,t){b.fn[e]=function(n,r){var i=b.map(this,t,n);return at.test(e)||(r=n),r&&"string"==typeof r&&(i=b.filter(r,i)),i=this.length>1&&!ct[e]?b.unique(i):i,this.length>1&&st.test(e)&&(i=i.reverse()),this.pushStack(i)}}),b.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),1===t.length?b.find.matchesSelector(t[0],e)?[t[0]]:[]:b.find.matches(e,t)},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!b(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(t=t||0,b.isFunction(t))return b.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return b.grep(e,function(e){return e===t===n});if("string"==typeof t){var r=b.grep(e,function(e){return 1===e.nodeType});if(ut.test(t))return b.filter(t,r,!n);t=b.filter(t,r)}return b.grep(e,function(e){return b.inArray(e,t)>=0===n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Nt=/^(?:checkbox|radio)$/i,Ct=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:b.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(o),Dt=jt.appendChild(o.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,b.fn.extend({text:function(e){return b.access(this,function(e){return e===t?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e))return this.each(function(t){b(this).wrapAll(e.call(this,t))});if(this[0]){var t=b(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return b.isFunction(e)?this.each(function(t){b(this).wrapInner(e.call(this,t))}):this.each(function(){var t=b(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=b.isFunction(e);return this.each(function(n){b(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){b.nodeName(this,"body")||b(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&this.insertBefore(e,this.firstChild)})},before:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,!1,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=0;for(;null!=(n=this[r]);r++)(!e||b.filter(e,[n]).length>0)&&(t||1!==n.nodeType||b.cleanData(Ot(n)),n.parentNode&&(t&&b.contains(n.ownerDocument,n)&&Mt(Ot(n,"script")),n.parentNode.removeChild(n)));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&b.cleanData(Ot(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&b.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return b.clone(this,e,t)})},html:function(e){return b.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!b.support.htmlSerialize&&mt.test(e)||!b.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(b.cleanData(Ot(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){var t=b.isFunction(e);return t||"string"==typeof e||(e=b(e).not(this).detach()),this.domManip([e],!0,function(e){var t=this.nextSibling,n=this.parentNode;n&&(b(this).remove(),n.insertBefore(e,t))})},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=f.apply([],e);var i,o,a,s,u,l,c=0,p=this.length,d=this,h=p-1,g=e[0],m=b.isFunction(g);if(m||!(1>=p||"string"!=typeof g||b.support.checkClone)&&Ct.test(g))return this.each(function(i){var o=d.eq(i);m&&(e[0]=g.call(this,i,n?o.html():t)),o.domManip(e,n,r)});if(p&&(l=b.buildFragment(e,this[0].ownerDocument,!1,this),i=l.firstChild,1===l.childNodes.length&&(l=i),i)){for(n=n&&b.nodeName(i,"tr"),s=b.map(Ot(l,"script"),Ht),a=s.length;p>c;c++)o=l,c!==h&&(o=b.clone(o,!0,!0),a&&b.merge(s,Ot(o,"script"))),r.call(n&&b.nodeName(this[c],"table")?Lt(this[c],"tbody"):this[c],o,c);if(a)for(u=s[s.length-1].ownerDocument,b.map(s,qt),c=0;a>c;c++)o=s[c],kt.test(o.type||"")&&!b._data(o,"globalEval")&&b.contains(u,o)&&(o.src?b.ajax({url:o.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):b.globalEval((o.text||o.textContent||o.innerHTML||"").replace(St,"")));l=i=null}return this}});function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function Ht(e){var t=e.getAttributeNode("type");return e.type=(t&&t.specified)+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Mt(e,t){var n,r=0;for(;null!=(n=e[r]);r++)b._data(n,"globalEval",!t||b._data(t[r],"globalEval"))}function _t(e,t){if(1===t.nodeType&&b.hasData(e)){var n,r,i,o=b._data(e),a=b._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)b.event.add(t,n,s[n][r])}a.data&&(a.data=b.extend({},a.data))}}function Ft(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!b.support.noCloneEvent&&t[b.expando]){i=b._data(t);for(r in i.events)b.removeEvent(t,r,i.handle);t.removeAttribute(b.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),b.support.html5Clone&&e.innerHTML&&!b.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Nt.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}b.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){b.fn[e]=function(e){var n,r=0,i=[],o=b(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),b(o[r])[t](n),d.apply(i,n.get());return this.pushStack(i)}});function Ot(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||b.nodeName(o,n)?s.push(o):b.merge(s,Ot(o,n));return n===t||n&&b.nodeName(e,n)?b.merge([e],s):s}function Bt(e){Nt.test(e.type)&&(e.defaultChecked=e.checked)}b.extend({clone:function(e,t,n){var r,i,o,a,s,u=b.contains(e.ownerDocument,e);if(b.support.html5Clone||b.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(b.support.noCloneEvent&&b.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||b.isXMLDoc(e)))for(r=Ot(o),s=Ot(e),a=0;null!=(i=s[a]);++a)r[a]&&Ft(i,r[a]);if(t)if(n)for(s=s||Ot(e),r=r||Ot(o),a=0;null!=(i=s[a]);a++)_t(i,r[a]);else _t(e,o);return r=Ot(o,"script"),r.length>0&&Mt(r,!u&&Ot(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,u,l,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===b.type(o))b.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),u=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[u]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!b.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!b.support.tbody){o="table"!==u||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)b.nodeName(l=o.childNodes[i],"tbody")&&!l.childNodes.length&&o.removeChild(l)
5
+ }b.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),b.support.appendChecked||b.grep(Ot(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===b.inArray(o,r))&&(a=b.contains(o.ownerDocument,o),s=Ot(f.appendChild(o),"script"),a&&Mt(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,u=b.expando,l=b.cache,p=b.support.deleteExpando,f=b.event.special;for(;null!=(n=e[s]);s++)if((t||b.acceptData(n))&&(o=n[u],a=o&&l[o])){if(a.events)for(r in a.events)f[r]?b.event.remove(n,r):b.removeEvent(n,r,a.handle);l[o]&&(delete l[o],p?delete n[u]:typeof n.removeAttribute!==i?n.removeAttribute(u):n[u]=null,c.push(o))}}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+x+")(.*)$","i"),Yt=RegExp("^("+x+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+x+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===b.css(e,"display")||!b.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=b._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=b._data(r,"olddisplay",un(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&b._data(r,"olddisplay",i?n:b.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}b.fn.extend({css:function(e,n){return b.access(this,function(e,n,r){var i,o,a={},s=0;if(b.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=b.css(e,n[s],!1,o);return a}return r!==t?b.style(e,n,r):b.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){var t="boolean"==typeof e;return this.each(function(){(t?e:nn(this))?b(this).show():b(this).hide()})}}),b.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,u=b.camelCase(n),l=e.style;if(n=b.cssProps[u]||(b.cssProps[u]=tn(l,u)),s=b.cssHooks[n]||b.cssHooks[u],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:l[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(b.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||b.cssNumber[u]||(r+="px"),b.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(l[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{l[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,u=b.camelCase(n);return n=b.cssProps[u]||(b.cssProps[u]=tn(e.style,u)),s=b.cssHooks[n]||b.cssHooks[u],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||b.isNumeric(o)?o||0:a):a},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s.getPropertyValue(n)||s[n]:t,l=e.style;return s&&(""!==u||b.contains(e.ownerDocument,e)||(u=b.style(e,n)),Yt.test(u)&&Ut.test(n)&&(i=l.width,o=l.minWidth,a=l.maxWidth,l.minWidth=l.maxWidth=l.width=u,u=s.width,l.width=i,l.minWidth=o,l.maxWidth=a)),u}):o.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),u=s?s[n]:t,l=e.style;return null==u&&l&&l[n]&&(u=l[n]),Yt.test(u)&&!zt.test(n)&&(i=l.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),l.left="fontSize"===n?"1em":u,u=l.pixelLeft+"px",l.left=i,a&&(o.left=a)),""===u?"auto":u});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=b.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=b.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=b.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=b.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=b.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(b.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function un(e){var t=o,n=Gt[e];return n||(n=ln(e,t),"none"!==n&&n||(Pt=(Pt||b("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=ln(e,t),Pt.detach()),Gt[e]=n),n}function ln(e,t){var n=b(t.createElement(e)).appendTo(t.body),r=b.css(n[0],"display");return n.remove(),r}b.each(["height","width"],function(e,n){b.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(b.css(e,"display"))?b.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,b.support.boxSizing&&"border-box"===b.css(e,"boxSizing",!1,i),i):0)}}}),b.support.opacity||(b.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=b.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===b.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),b(function(){b.support.reliableMarginRight||(b.cssHooks.marginRight={get:function(e,n){return n?b.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!b.support.pixelPosition&&b.fn.position&&b.each(["top","left"],function(e,n){b.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?b(e).position()[n]+"px":r):t}}})}),b.expr&&b.expr.filters&&(b.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!b.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||b.css(e,"display"))},b.expr.filters.visible=function(e){return!b.expr.filters.hidden(e)}),b.each({margin:"",padding:"",border:"Width"},function(e,t){b.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(b.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;b.fn.extend({serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=b.prop(this,"elements");return e?b.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!b(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Nt.test(e))}).map(function(e,t){var n=b(this).val();return null==n?null:b.isArray(n)?b.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),b.param=function(e,n){var r,i=[],o=function(e,t){t=b.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=b.ajaxSettings&&b.ajaxSettings.traditional),b.isArray(e)||e.jquery&&!b.isPlainObject(e))b.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(b.isArray(t))b.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==b.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}b.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){b.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),b.fn.hover=function(e,t){return this.mouseenter(e).mouseleave(t||e)};var mn,yn,vn=b.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Nn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Cn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=b.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=a.href}catch(Ln){yn=o.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(b.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(u){var l;return o[u]=!0,b.each(e[u]||[],function(e,u){var c=u(n,r,i);return"string"!=typeof c||a||o[c]?a?!(l=c):t:(n.dataTypes.unshift(c),s(c),!1)}),l}return s(n.dataTypes[0])||!o["*"]&&s("*")}function Mn(e,n){var r,i,o=b.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&b.extend(!0,e,r),e}b.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,u=e.indexOf(" ");return u>=0&&(i=e.slice(u,e.length),e=e.slice(0,u)),b.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&b.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?b("<div>").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
shared/docs/js/legacy.js ADDED
@@ -0,0 +1,369 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+
3
+ Support JS for legacy browsers.
4
+ Includes:
5
+
6
+ HTML5 Shiv
7
+ @afarkas @jdalton @jon_neal @rem
8
+ MIT/GPL2 Licensed
9
+ https://github.com/aFarkas/html5shiv
10
+
11
+ matchMedia() polyfill
12
+ (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license
13
+
14
+ Respond.js
15
+ min/max-width media query polyfill
16
+ (c) Scott Jehl. MIT/GPLv2 Lic.
17
+ http://j.mp/respondjs
18
+
19
+ */
20
+ /*
21
+ HTML5 Shiv v3.6.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
22
+ */
23
+ (function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
24
+ a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}</style>";
25
+ c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
26
+ "undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup main mark meter nav output progress section summary time video",version:"3.6.2",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();
27
+ for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
28
+ /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
29
+ /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
30
+
31
+ window.matchMedia = window.matchMedia || (function( doc, undefined ) {
32
+
33
+ "use strict";
34
+
35
+ var bool,
36
+ docElem = doc.documentElement,
37
+ refNode = docElem.firstElementChild || docElem.firstChild,
38
+ // fakeBody required for <FF4 when executed in <head>
39
+ fakeBody = doc.createElement( "body" ),
40
+ div = doc.createElement( "div" );
41
+
42
+ div.id = "mq-test-1";
43
+ div.style.cssText = "position:absolute;top:-100em";
44
+ fakeBody.style.background = "none";
45
+ fakeBody.appendChild(div);
46
+
47
+ return function(q){
48
+
49
+ div.innerHTML = "&shy;<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
50
+
51
+ docElem.insertBefore( fakeBody, refNode );
52
+ bool = div.offsetWidth === 42;
53
+ docElem.removeChild( fakeBody );
54
+
55
+ return {
56
+ matches: bool,
57
+ media: q
58
+ };
59
+
60
+ };
61
+
62
+ }( document ));
63
+
64
+
65
+
66
+
67
+
68
+ /*! Respond.js v1.1.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */
69
+ (function( win ){
70
+
71
+ "use strict";
72
+
73
+ //exposed namespace
74
+ var respond = {};
75
+ win.respond = respond;
76
+
77
+ //define update even in native-mq-supporting browsers, to avoid errors
78
+ respond.update = function(){};
79
+
80
+ //expose media query support flag for external use
81
+ respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches;
82
+
83
+ //if media queries are supported, exit here
84
+ if( respond.mediaQueriesSupported ){
85
+ return;
86
+ }
87
+
88
+ //define vars
89
+ var doc = win.document,
90
+ docElem = doc.documentElement,
91
+ mediastyles = [],
92
+ rules = [],
93
+ appendedEls = [],
94
+ parsedSheets = {},
95
+ resizeThrottle = 30,
96
+ head = doc.getElementsByTagName( "head" )[0] || docElem,
97
+ base = doc.getElementsByTagName( "base" )[0],
98
+ links = head.getElementsByTagName( "link" ),
99
+ requestQueue = [],
100
+
101
+ //loop stylesheets, send text content to translate
102
+ ripCSS = function(){
103
+
104
+ for( var i = 0; i < links.length; i++ ){
105
+ var sheet = links[ i ],
106
+ href = sheet.href,
107
+ media = sheet.media,
108
+ isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet";
109
+
110
+ //only links plz and prevent re-parsing
111
+ if( !!href && isCSS && !parsedSheets[ href ] ){
112
+ // selectivizr exposes css through the rawCssText expando
113
+ if (sheet.styleSheet && sheet.styleSheet.rawCssText) {
114
+ translate( sheet.styleSheet.rawCssText, href, media );
115
+ parsedSheets[ href ] = true;
116
+ } else {
117
+ if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) ||
118
+ href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){
119
+ requestQueue.push( {
120
+ href: href,
121
+ media: media
122
+ } );
123
+ }
124
+ }
125
+ }
126
+ }
127
+ makeRequests();
128
+ },
129
+
130
+ //recurse through request queue, get css text
131
+ makeRequests = function(){
132
+ if( requestQueue.length ){
133
+ var thisRequest = requestQueue.shift();
134
+
135
+ ajax( thisRequest.href, function( styles ){
136
+ translate( styles, thisRequest.href, thisRequest.media );
137
+ parsedSheets[ thisRequest.href ] = true;
138
+
139
+ // by wrapping recursive function call in setTimeout
140
+ // we prevent "Stack overflow" error in IE7
141
+ win.setTimeout(function(){ makeRequests(); },0);
142
+ } );
143
+ }
144
+ },
145
+
146
+ //find media blocks in css text, convert to style blocks
147
+ translate = function( styles, href, media ){
148
+ var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ),
149
+ ql = qs && qs.length || 0;
150
+
151
+ //try to get CSS path
152
+ href = href.substring( 0, href.lastIndexOf( "/" ) );
153
+
154
+ var repUrls = function( css ){
155
+ return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" );
156
+ },
157
+ useMedia = !ql && media;
158
+
159
+ //if path exists, tack on trailing slash
160
+ if( href.length ){ href += "/"; }
161
+
162
+ //if no internal queries exist, but media attr does, use that
163
+ //note: this currently lacks support for situations where a media attr is specified on a link AND
164
+ //its associated stylesheet has internal CSS media queries.
165
+ //In those cases, the media attribute will currently be ignored.
166
+ if( useMedia ){
167
+ ql = 1;
168
+ }
169
+
170
+ for( var i = 0; i < ql; i++ ){
171
+ var fullq, thisq, eachq, eql;
172
+
173
+ //media attr
174
+ if( useMedia ){
175
+ fullq = media;
176
+ rules.push( repUrls( styles ) );
177
+ }
178
+ //parse for styles
179
+ else{
180
+ fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1;
181
+ rules.push( RegExp.$2 && repUrls( RegExp.$2 ) );
182
+ }
183
+
184
+ eachq = fullq.split( "," );
185
+ eql = eachq.length;
186
+
187
+ for( var j = 0; j < eql; j++ ){
188
+ thisq = eachq[ j ];
189
+ mediastyles.push( {
190
+ media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all",
191
+ rules : rules.length - 1,
192
+ hasquery : thisq.indexOf("(") > -1,
193
+ minw : thisq.match( /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ),
194
+ maxw : thisq.match( /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" )
195
+ } );
196
+ }
197
+ }
198
+
199
+ applyMedia();
200
+ },
201
+
202
+ lastCall,
203
+
204
+ resizeDefer,
205
+
206
+ // returns the value of 1em in pixels
207
+ getEmValue = function() {
208
+ var ret,
209
+ div = doc.createElement('div'),
210
+ body = doc.body,
211
+ fakeUsed = false;
212
+
213
+ div.style.cssText = "position:absolute;font-size:1em;width:1em";
214
+
215
+ if( !body ){
216
+ body = fakeUsed = doc.createElement( "body" );
217
+ body.style.background = "none";
218
+ }
219
+
220
+ body.appendChild( div );
221
+
222
+ docElem.insertBefore( body, docElem.firstChild );
223
+
224
+ ret = div.offsetWidth;
225
+
226
+ if( fakeUsed ){
227
+ docElem.removeChild( body );
228
+ }
229
+ else {
230
+ body.removeChild( div );
231
+ }
232
+
233
+ //also update eminpx before returning
234
+ ret = eminpx = parseFloat(ret);
235
+
236
+ return ret;
237
+ },
238
+
239
+ //cached container for 1em value, populated the first time it's needed
240
+ eminpx,
241
+
242
+ //enable/disable styles
243
+ applyMedia = function( fromResize ){
244
+ var name = "clientWidth",
245
+ docElemProp = docElem[ name ],
246
+ currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp,
247
+ styleBlocks = {},
248
+ lastLink = links[ links.length-1 ],
249
+ now = (new Date()).getTime();
250
+
251
+ //throttle resize calls
252
+ if( fromResize && lastCall && now - lastCall < resizeThrottle ){
253
+ win.clearTimeout( resizeDefer );
254
+ resizeDefer = win.setTimeout( applyMedia, resizeThrottle );
255
+ return;
256
+ }
257
+ else {
258
+ lastCall = now;
259
+ }
260
+
261
+ for( var i in mediastyles ){
262
+ if( mediastyles.hasOwnProperty( i ) ){
263
+ var thisstyle = mediastyles[ i ],
264
+ min = thisstyle.minw,
265
+ max = thisstyle.maxw,
266
+ minnull = min === null,
267
+ maxnull = max === null,
268
+ em = "em";
269
+
270
+ if( !!min ){
271
+ min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
272
+ }
273
+ if( !!max ){
274
+ max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 );
275
+ }
276
+
277
+ // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true
278
+ if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){
279
+ if( !styleBlocks[ thisstyle.media ] ){
280
+ styleBlocks[ thisstyle.media ] = [];
281
+ }
282
+ styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] );
283
+ }
284
+ }
285
+ }
286
+
287
+ //remove any existing respond style element(s)
288
+ for( var j in appendedEls ){
289
+ if( appendedEls.hasOwnProperty( j ) ){
290
+ if( appendedEls[ j ] && appendedEls[ j ].parentNode === head ){
291
+ head.removeChild( appendedEls[ j ] );
292
+ }
293
+ }
294
+ }
295
+
296
+ //inject active styles, grouped by media type
297
+ for( var k in styleBlocks ){
298
+ if( styleBlocks.hasOwnProperty( k ) ){
299
+ var ss = doc.createElement( "style" ),
300
+ css = styleBlocks[ k ].join( "\n" );
301
+
302
+ ss.type = "text/css";
303
+ ss.media = k;
304
+
305
+ //originally, ss was appended to a documentFragment and sheets were appended in bulk.
306
+ //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one!
307
+ head.insertBefore( ss, lastLink.nextSibling );
308
+
309
+ if ( ss.styleSheet ){
310
+ ss.styleSheet.cssText = css;
311
+ }
312
+ else {
313
+ ss.appendChild( doc.createTextNode( css ) );
314
+ }
315
+
316
+ //push to appendedEls to track for later removal
317
+ appendedEls.push( ss );
318
+ }
319
+ }
320
+ },
321
+ //tweaked Ajax functions from Quirksmode
322
+ ajax = function( url, callback ) {
323
+ var req = xmlHttp();
324
+ if (!req){
325
+ return;
326
+ }
327
+ req.open( "GET", url, true );
328
+ req.onreadystatechange = function () {
329
+ if ( req.readyState !== 4 || req.status !== 200 && req.status !== 304 ){
330
+ return;
331
+ }
332
+ callback( req.responseText );
333
+ };
334
+ if ( req.readyState === 4 ){
335
+ return;
336
+ }
337
+ req.send( null );
338
+ },
339
+ //define ajax obj
340
+ xmlHttp = (function() {
341
+ var xmlhttpmethod = false;
342
+ try {
343
+ xmlhttpmethod = new win.XMLHttpRequest();
344
+ }
345
+ catch( e ){
346
+ xmlhttpmethod = new win.ActiveXObject( "Microsoft.XMLHTTP" );
347
+ }
348
+ return function(){
349
+ return xmlhttpmethod;
350
+ };
351
+ })();
352
+
353
+ //translate CSS
354
+ ripCSS();
355
+
356
+ //expose update for re-running respond later on
357
+ respond.update = ripCSS;
358
+
359
+ //adjust on resize
360
+ function callMedia(){
361
+ applyMedia( true );
362
+ }
363
+ if( win.addEventListener ){
364
+ win.addEventListener( "resize", callMedia, false );
365
+ }
366
+ else if( win.attachEvent ){
367
+ win.attachEvent( "onresize", callMedia );
368
+ }
369
+ })(this);
shared/docs/js/script.js ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+ var $window = $(window);
3
+ var $document = $(document);
4
+
5
+ /*
6
+ * Scrollspy.
7
+ */
8
+
9
+ $document.on('flatdoc:ready', function() {
10
+ $("h2, h3").scrollagent(function(cid, pid, currentElement, previousElement) {
11
+ if (pid) {
12
+ $("[href='#"+pid+"']").removeClass('active');
13
+ }
14
+ if (cid) {
15
+ $("[href='#"+cid+"']").addClass('active');
16
+ }
17
+ });
18
+ });
19
+
20
+ /*
21
+ * Anchor jump links.
22
+ */
23
+
24
+ $document.on('flatdoc:ready', function() {
25
+ $('.menu a').anchorjump();
26
+ });
27
+
28
+ /*
29
+ * Title card.
30
+ */
31
+
32
+ $(function() {
33
+ var $card = $('.title-card');
34
+ if (!$card.length) return;
35
+
36
+ var $header = $('.header');
37
+ var headerHeight = $header.length ? $header.outerHeight() : 0;
38
+
39
+ $window
40
+ .on('resize.title-card', function() {
41
+ var windowWidth = $window.width();
42
+
43
+ if (windowWidth < 480) {
44
+ $card.css('height', '');
45
+ } else {
46
+ var height = $window.height();
47
+ $card.css('height', height - headerHeight);
48
+ }
49
+ })
50
+ .trigger('resize.title-card');
51
+ });
52
+
53
+ /*
54
+ * Sidebar stick.
55
+ */
56
+
57
+ $(function() {
58
+ var $sidebar = $('.menubar');
59
+ var elTop;
60
+
61
+ $window
62
+ .on('resize.sidestick', function() {
63
+ $sidebar.removeClass('fixed');
64
+ elTop = $sidebar.offset().top;
65
+ $window.trigger('scroll.sidestick');
66
+ })
67
+ .on('scroll.sidestick', function() {
68
+ var scrollY = $window.scrollTop();
69
+ $sidebar.toggleClass('fixed', (scrollY >= elTop));
70
+ })
71
+ .trigger('resize.sidestick');
72
+ });
73
+
74
+ })(jQuery);
75
+ /*! jQuery.scrollagent (c) 2012, Rico Sta. Cruz. MIT License.
76
+ * https://github.com/rstacruz/jquery-stuff/tree/master/scrollagent */
77
+
78
+ // Call $(...).scrollagent() with a callback function.
79
+ //
80
+ // The callback will be called everytime the focus changes.
81
+ //
82
+ // Example:
83
+ //
84
+ // $("h2").scrollagent(function(cid, pid, currentElement, previousElement) {
85
+ // if (pid) {
86
+ // $("[href='#"+pid+"']").removeClass('active');
87
+ // }
88
+ // if (cid) {
89
+ // $("[href='#"+cid+"']").addClass('active');
90
+ // }
91
+ // });
92
+
93
+ (function($) {
94
+
95
+ $.fn.scrollagent = function(options, callback) {
96
+ // Account for $.scrollspy(function)
97
+ if (typeof callback === 'undefined') {
98
+ callback = options;
99
+ options = {};
100
+ }
101
+
102
+ var $sections = $(this);
103
+ var $parent = options.parent || $(window);
104
+
105
+ // Find the top offsets of each section
106
+ var offsets = [];
107
+ $sections.each(function(i) {
108
+ var offset = $(this).attr('data-anchor-offset') ?
109
+ parseInt($(this).attr('data-anchor-offset'), 10) :
110
+ (options.offset || 0);
111
+
112
+ offsets.push({
113
+ top: $(this).offset().top + offset,
114
+ id: $(this).attr('id'),
115
+ index: i,
116
+ el: this
117
+ });
118
+ });
119
+
120
+ // State
121
+ var current = null;
122
+ var height = null;
123
+ var range = null;
124
+
125
+ // Save the height. Do this only whenever the window is resized so we don't
126
+ // recalculate often.
127
+ $(window).on('resize', function() {
128
+ height = $parent.height();
129
+ range = $(document).height();
130
+ });
131
+
132
+ // Find the current active section every scroll tick.
133
+ $parent.on('scroll', function() {
134
+ var y = $parent.scrollTop();
135
+ y += height * (0.3 + 0.7 * Math.pow(y/range, 2));
136
+
137
+ var latest = null;
138
+
139
+ for (var i in offsets) {
140
+ if (offsets.hasOwnProperty(i)) {
141
+ var offset = offsets[i];
142
+ if (offset.top < y) latest = offset;
143
+ }
144
+ }
145
+
146
+ if (latest && (!current || (latest.index !== current.index))) {
147
+ callback.call($sections,
148
+ latest ? latest.id : null,
149
+ current ? current.id : null,
150
+ latest ? latest.el : null,
151
+ current ? current.el : null);
152
+ current = latest;
153
+ }
154
+ });
155
+
156
+ $(window).trigger('resize');
157
+ $parent.trigger('scroll');
158
+
159
+ return this;
160
+ };
161
+
162
+ })(jQuery);
163
+ /*! Anchorjump (c) 2012, Rico Sta. Cruz. MIT License.
164
+ * http://github.com/rstacruz/jquery-stuff/tree/master/anchorjump */
165
+
166
+ // Makes anchor jumps happen with smooth scrolling.
167
+ //
168
+ // $("#menu a").anchorjump();
169
+ // $("#menu a").anchorjump({ offset: -30 });
170
+ //
171
+ // // Via delegate:
172
+ // $("#menu").anchorjump({ for: 'a', offset: -30 });
173
+ //
174
+ // You may specify a parent. This makes it scroll down to the parent.
175
+ // Great for tabbed views.
176
+ //
177
+ // $('#menu a').anchorjump({ parent: '.anchor' });
178
+ //
179
+ // You can jump to a given area.
180
+ //
181
+ // $.anchorjump('#bank-deposit', options);
182
+
183
+ (function($) {
184
+ var defaults = {
185
+ 'speed': 500,
186
+ 'offset': 0,
187
+ 'for': null,
188
+ 'parent': null
189
+ };
190
+
191
+ $.fn.anchorjump = function(options) {
192
+ options = $.extend({}, defaults, options);
193
+
194
+ if (options['for']) {
195
+ this.on('click', options['for'], onClick);
196
+ } else {
197
+ this.on('click', onClick);
198
+ }
199
+
200
+ function onClick(e) {
201
+ var $a = $(e.target).closest('a');
202
+ if (e.ctrlKey || e.metaKey || e.altKey || $a.attr('target')) return;
203
+
204
+ e.preventDefault();
205
+ var href = $a.attr('href');
206
+
207
+ $.anchorjump(href, options);
208
+ }
209
+ };
210
+
211
+ // Jump to a given area.
212
+ $.anchorjump = function(href, options) {
213
+ options = $.extend({}, defaults, options);
214
+
215
+ var top = 0;
216
+
217
+ if (href != '#') {
218
+ var $area = $(href);
219
+ // Find the parent
220
+ if (options.parent) {
221
+ var $parent = $area.closest(options.parent);
222
+ if ($parent.length) { $area = $parent; }
223
+ }
224
+ if (!$area.length) { return; }
225
+
226
+ // Determine the pixel offset; use the default if not available
227
+ var offset =
228
+ $area.attr('data-anchor-offset') ?
229
+ parseInt($area.attr('data-anchor-offset'), 10) :
230
+ options.offset;
231
+
232
+ top = Math.max(0, $area.offset().top + offset);
233
+ }
234
+
235
+ $('html, body').animate({ scrollTop: top }, options.speed);
236
+ $('body').trigger('anchor', href);
237
+
238
+ // Add the location hash via pushState.
239
+ if (window.history.pushState) {
240
+ window.history.pushState({ href: href }, "", href);
241
+ }
242
+ };
243
+ })(jQuery);
244
+
245
+ /* Custom */
246
+ jQuery(document).ready(function($) {
247
+
248
+
249
+ });
250
+
shared/docs/js/theme.js ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($) {
2
+
3
+ $(document).on('flatdoc:ready', function() {
4
+ $("#misc, #basic").remove();
5
+
6
+ $("pre > code").each(function() {
7
+ var $code = $(this);
8
+ var m = $code.text().match(/<body class='([^']*)'/);
9
+ if (m) {
10
+ var $q = $("<blockquote><a href='#"+m[1]+"' class='button light'>Toggle</a></blockquote>");
11
+ $q.find('a').click(function() {
12
+ var klass = $(this).attr('href').substr(1);
13
+ $('body').toggleClass(klass);
14
+ if (klass === 'big-h3') $.anchorjump('#theme-options');
15
+ if (klass === 'large-brief') $.anchorjump('#flatdoc');
16
+
17
+ });
18
+ $code.after($q);
19
+ }
20
+ });
21
+
22
+ jQuery('#event-list-list a').each(function(){
23
+ var text = $(this).text().replace("()", "");
24
+ $(this).text(text);
25
+ var head = text.replace(/_/g, "-");
26
+ var heading = $('#event-list-' + head).text().replace("()", "")
27
+ $('#event-list-' + head).text(heading);
28
+ console.log('#event-list-' + heading);
29
+ });
30
+
31
+ });
32
+
33
+ })(jQuery);
shared/docs/main.md ADDED
@@ -0,0 +1,1029 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.events.js -->
4
+
5
+ # Analytics Events
6
+
7
+ Events are triggered throughout the visitors journey through the site. See more on [Inbound Now][in]
8
+
9
+ Author: David Wells <david@inboundnow.com>
10
+
11
+ Version: 0.0.1
12
+ [in]: http://www.inboundnow.com/
13
+
14
+ # Event Usage
15
+
16
+ Adding Custom Actions
17
+ ------------------
18
+ You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
19
+
20
+ `
21
+ _inbound.add_action( 'action_name', callback, priority );
22
+ `
23
+
24
+ ```js
25
+ // example:
26
+
27
+ _inbound.add_action( 'page_visit', callback, 10 );
28
+
29
+ // add custom callback
30
+ function callback(data){
31
+ // run callback on 'page_visit' trigger
32
+ }
33
+ ```
34
+
35
+ ### Params:
36
+
37
+ * **string** *action_name* Name of the event trigger
38
+ * **function** *callback* function to trigger when event happens
39
+ * **int** *priority* Order to trigger the event in
40
+
41
+ Removing Custom Actions
42
+ ------------------
43
+ You can hook into custom events throughout analytics. See the full list of available [events below](#all-events)
44
+
45
+ `
46
+ _inbound.remove_action( 'action_name');
47
+ `
48
+
49
+ ```js
50
+ // example:
51
+
52
+ _inbound.remove_action( 'page_visit');
53
+ // all 'page_visit' actions have been deregistered
54
+ ```
55
+
56
+ ### Params:
57
+
58
+ * **string** *action_name* Name of the event trigger
59
+
60
+ # Event List
61
+
62
+ Events are triggered throughout the visitors journey through the site
63
+
64
+ ## analytics_loaded()
65
+
66
+ Triggers when the browser url params are parsed. You can perform custom actions
67
+ if specific url params exist.
68
+
69
+ ## url_parameters()
70
+
71
+ Triggers when the browser url params are parsed. You can perform custom actions
72
+ if specific url params exist.
73
+
74
+ ```js
75
+ // Usage:
76
+
77
+ // Add function to 'url_parameters' event
78
+ _inbound.add_action( 'url_parameters', url_parameters_func_example, 10);
79
+
80
+ function url_parameters_func_example(urlParams) {
81
+ var urlParams = urlParams || {};
82
+ for( var param in urlParams ) {
83
+ var key = param;
84
+ var value = urlParams[param];
85
+ }
86
+ // All URL Params
87
+ alert(JSON.stringify(urlParams));
88
+
89
+ // Check if URL parameter `utm_source` exists and matches value
90
+ if(urlParams.utm_source === "twitter") {
91
+ alert('This person is from twitter!');
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## session_start()
97
+
98
+ Triggers when session starts
99
+
100
+ ```js
101
+ // Usage:
102
+
103
+ // Add session_start_func_example function to 'session_start' event
104
+ _inbound.add_action( 'session_start', session_start_func_example, 10);
105
+
106
+ function session_start_func_example(data) {
107
+ var data = data || {};
108
+ // session active
109
+ }
110
+ ```
111
+
112
+ ## session_active()
113
+
114
+ Triggers when session is already active
115
+
116
+ ```js
117
+ // Usage:
118
+
119
+ // Add session_heartbeat_func_example function to 'session_heartbeat' event
120
+ _inbound.add_action( 'session_heartbeat', session_heartbeat_func_example, 10);
121
+
122
+ function session_heartbeat_func_example(data) {
123
+ var data = data || {};
124
+ // Do something with every 10 seconds
125
+ }
126
+ ```
127
+
128
+ ## session_heartbeat()
129
+
130
+ Session emitter. Runs every 10 seconds. This is a useful function for
131
+ pinging third party services
132
+
133
+ ```js
134
+ // Usage:
135
+
136
+ // Add session_heartbeat_func_example function to 'session_heartbeat' event
137
+ _inbound.add_action( 'session_heartbeat', session_heartbeat_func_example, 10);
138
+
139
+ function session_heartbeat_func_example(data) {
140
+ var data = data || {};
141
+ // Do something with every 10 seconds
142
+ }
143
+ ```
144
+
145
+ ## session_idle()
146
+
147
+ Triggers when visitor session goes idle. Idling occurs after 60 seconds of
148
+ inactivity or when the visitor switches browser tabs
149
+
150
+ ```js
151
+ // Usage:
152
+
153
+ // Add function to 'session_idle' event
154
+ _inbound.add_action( 'session_idle', session_idle_func_example, 10);
155
+
156
+ function session_idle_func_example(data) {
157
+ var data = data || {};
158
+ // Do something when session idles
159
+ alert('Here is a special offer for you!');
160
+ }
161
+ ```
162
+
163
+ Page Visit Events
164
+
165
+ ## page_visit()
166
+
167
+ Triggers Every Page View
168
+
169
+ ```js
170
+ // Usage:
171
+
172
+ // Add function to 'page_visit' event
173
+ _inbound.add_action( 'page_visit', page_visit_func_example, 10);
174
+
175
+ function session_idle_func_example(pageData) {
176
+ var pageData = pageData || {};
177
+ if( pageData.view_count > 8 ){
178
+ alert('Wow you have been to this page more than 8 times.');
179
+ }
180
+ }
181
+ ```
182
+
183
+ ## page_first_visit()
184
+
185
+ Triggers If the visitor has never seen the page before
186
+
187
+ ```js
188
+ // Usage:
189
+
190
+ // Add function to 'page_first_visit' event
191
+ _inbound.add_action( 'page_first_visit', page_first_visit_func_example, 10);
192
+
193
+ function page_first_visit_func_example(pageData) {
194
+ var pageData = pageData || {};
195
+ alert('Welcome to this page! Its the first time you have seen it')
196
+ }
197
+ ```
198
+
199
+ ## page_revisit()
200
+
201
+ Triggers If the visitor has seen the page before
202
+
203
+ ```js
204
+ // Usage:
205
+
206
+ // Add function to 'page_revisit' event
207
+ _inbound.add_action( 'page_revisit', page_revisit_func_example, 10);
208
+
209
+ function page_revisit_func_example(pageData) {
210
+ var pageData = pageData || {};
211
+ alert('Welcome back to this page!');
212
+ // Show visitor special content/offer
213
+ }
214
+ ```
215
+
216
+ ## tab_hidden()
217
+
218
+ `tab_hidden` is triggered when the visitor switches browser tabs
219
+
220
+ ```js
221
+ // Usage:
222
+
223
+ // Adding the callback
224
+ function tab_hidden_function( data ) {
225
+ alert('The Tab is Hidden');
226
+ };
227
+
228
+ // Hook the function up the the `tab_hidden` event
229
+ _inbound.add_action( 'tab_hidden', tab_hidden_function, 10 );
230
+ ```
231
+
232
+ ## tab_visible()
233
+
234
+ `tab_visible` is triggered when the visitor switches back to the sites tab
235
+
236
+ ```js
237
+ // Usage:
238
+
239
+ // Adding the callback
240
+ function tab_visible_function( data ) {
241
+ alert('Welcome back to this tab!');
242
+ // trigger popup or offer special discount etc.
243
+ };
244
+
245
+ // Hook the function up the the `tab_visible` event
246
+ _inbound.add_action( 'tab_visible', tab_visible_function, 10 );
247
+ ```
248
+
249
+ ## tab_mouseout()
250
+
251
+ `tab_mouseout` is triggered when the visitor mouses out of the browser window.
252
+ This is especially useful for exit popups
253
+
254
+ ```js
255
+ // Usage:
256
+
257
+ // Adding the callback
258
+ function tab_mouseout_function( data ) {
259
+ alert("Wait don't Go");
260
+ // trigger popup or offer special discount etc.
261
+ };
262
+
263
+ // Hook the function up the the `tab_mouseout` event
264
+ _inbound.add_action( 'tab_mouseout', tab_mouseout_function, 10 );
265
+ ```
266
+
267
+ ## before_form_submission()
268
+
269
+ `before_form_submission` is triggered before the form is submitted to the server.
270
+ You can filter the data here or send it to third party services
271
+
272
+ ```js
273
+ // Usage:
274
+
275
+ // Adding the callback
276
+ function before_form_submission_function( data ) {
277
+ var data = data || {};
278
+ // filter form data
279
+ };
280
+
281
+ // Hook the function up the the `before_form_submission` event
282
+ _inbound.add_action( 'before_form_submission', before_form_submission_function, 10 );
283
+ ```
284
+
285
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.events.js -->
286
+
287
+
288
+
289
+
290
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.examples.js -->
291
+
292
+ URL param action
293
+
294
+ Check if URL parameter exists and matches value
295
+
296
+ Applying filters to your actions
297
+
298
+ check for item in object
299
+
300
+ delete item from object
301
+
302
+ Applying filters to your actions
303
+
304
+ ## add_this
305
+
306
+ Add property to data
307
+
308
+ check for item in object
309
+
310
+ ## new_options
311
+
312
+ Add or modifiy option to event
313
+
314
+ delete item from data
315
+
316
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.examples.js -->
317
+
318
+
319
+
320
+
321
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.forms.js -->
322
+
323
+ # Inbound Forms
324
+
325
+ This file contains all of the form functions of the main _inbound object.
326
+ Filters and actions are described below
327
+
328
+ Author: David Wells <david@inboundnow.com>
329
+
330
+ Version: 0.0.1
331
+
332
+ ## InboundForms
333
+
334
+ Launches form class
335
+
336
+ Adding values here maps them
337
+
338
+ ## runFieldMappingFilters()
339
+
340
+ This triggers the forms.field_map filter on the mapping array.
341
+ This will allow you to add or remore Items from the mapping lookup
342
+
343
+ ### Example inbound.form_map_before filter
344
+
345
+ This is an example of how form mapping can be filtered and
346
+ additional fields can be mapped via javascript
347
+
348
+ ```js
349
+ // Adding the filter function
350
+ function Inbound_Add_Filter_Example( FieldMapArray ) {
351
+ var map = FieldMapArray || [];
352
+ map.push('new lookup value');
353
+
354
+ return map;
355
+ };
356
+
357
+ // Adding the filter on dom ready
358
+ _inbound.hooks.addFilter( 'inbound.form_map_before', Inbound_Add_Filter_Example, 10 );
359
+ ```
360
+
361
+ ### Return:
362
+
363
+ * **[type]** [description]
364
+
365
+ attach form listener
366
+
367
+ ## loopClassSelectors()
368
+
369
+ Loop through include/exclude items for tracking
370
+
371
+ ## initFormMapping()
372
+
373
+ Map field fields on load
374
+
375
+ Map form fields
376
+
377
+ Remember visible inputs
378
+
379
+ Fill visible inputs
380
+
381
+ ## formListener()
382
+
383
+ prevent default submission temporarily
384
+
385
+ ## attachFormSubmitEvent()
386
+
387
+ attach form listeners
388
+
389
+ ## Timeout
390
+
391
+ fallback if submit name="submit"
392
+
393
+ if (formInput.id) { inputsObject[inputName]['id'] = formInput.id; }
394
+ if ('classList' in document.documentElement) {
395
+ if (formInput.classList) { inputsObject[inputName]['class'] = formInput.classList; }
396
+ }
397
+
398
+ inputsObject[inputName].push(multiple ? values.join(',') : encodeURIComponent(value));
399
+
400
+ Add custom hook here to look for additional values
401
+
402
+ ## email
403
+
404
+ Check Use form Email or Cookie
405
+
406
+ Get Variation ID
407
+
408
+ Filter here for raw
409
+
410
+ Old data model
411
+ var return_data = {
412
+ "action": 'inbound_store_lead',
413
+ "emailTo": data['email'],
414
+ "first_name": data['first_name'],
415
+ "last_name": data['last_name'],
416
+ "phone": data['phone'],
417
+ "address": data['address'],
418
+ "company_name": data['company'],
419
+ "page_views": data['page_views'],
420
+ "form_input_values": all_form_fields,
421
+ "Mapped_Data": mapped_form_data,
422
+ "Search_Data": data['search_data']
423
+ };
424
+
425
+ Action Example
426
+
427
+ Set Lead cookie ID
428
+
429
+ Resume normal form functionality
430
+
431
+ Check for input type
432
+
433
+ Set Field Input Cookies
434
+
435
+ Push to 'unsubmitted form object'
436
+
437
+ ## mapField()
438
+
439
+ Maps data attributes to fields on page load
440
+
441
+ Loop through all match possiblities
442
+
443
+ look for name attribute match
444
+
445
+ look for id match
446
+
447
+ Check siblings for label
448
+
449
+ Check closest li for label
450
+
451
+ Map the field
452
+
453
+ ## getInputValue()
454
+
455
+ Get correct input values
456
+
457
+ ## addDataAttr()
458
+
459
+ Add data-map-form-field attr to input
460
+
461
+ ## removeArrayItem()
462
+
463
+ Optimize FieldMapArray array for fewer lookups
464
+
465
+ ## siblingsIsLabel()
466
+
467
+ Look for siblings that are form labels
468
+
469
+ if only 1 label
470
+
471
+ ## CheckParentForLabel()
472
+
473
+ Check parent elements inside form for labels
474
+
475
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.forms.js -->
476
+
477
+
478
+
479
+
480
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.hooks.js -->
481
+
482
+ ## _inboundHooks
483
+
484
+ # Hooks & Filters
485
+
486
+ This file contains all of the form functions of the main _inbound object.
487
+ Filters and actions are described below
488
+
489
+ Author: David Wells <david@inboundnow.com>
490
+
491
+ Version: 0.0.1
492
+
493
+ # EventManager
494
+
495
+ Actions and filters List
496
+ addAction( 'namespace.identifier', callback, priority )
497
+ addFilter( 'namespace.identifier', callback, priority )
498
+ removeAction( 'namespace.identifier' )
499
+ removeFilter( 'namespace.identifier' )
500
+ doAction( 'namespace.identifier', arg1, arg2, moreArgs, finalArg )
501
+ applyFilters( 'namespace.identifier', content )
502
+
503
+ ### Return:
504
+
505
+ * **[type]** [description]
506
+
507
+ ## EventManager()
508
+
509
+ Handles managing all events for whatever you plug it into. Priorities for hooks are based on lowest to highest in
510
+ that, lowest priority hooks are fired first.
511
+
512
+ ## MethodsAvailable
513
+
514
+ Maintain a reference to the object scope so our public methods never get confusing.
515
+
516
+ ## STORAGE
517
+
518
+ Contains the hooks that get registered with this EventManager. The array for storage utilizes a "flat"
519
+ object literal such that looking up the hook utilizes the native object literal hash.
520
+
521
+ ## addAction(Must, Must, Used, Supply)
522
+
523
+ Adds an action to the event manager.
524
+
525
+ ### Params:
526
+
527
+ * **action** *Must* contain namespace.identifier
528
+ * **callback** *Must* be a valid callback function before this action is added
529
+ * **[priority=10]** *Used* to control when the function is executed in relation to other callbacks bound to the same hook
530
+ * **[context]** *Supply* a value to be used for this
531
+
532
+ ## doAction()
533
+
534
+ Performs an action if it exists. You can pass as many arguments as you want to this function; the only rule is
535
+ that the first argument must always be the action.
536
+
537
+ action, arg1, arg2, ...
538
+
539
+ ## removeAction(The, Callback)
540
+
541
+ Removes the specified action if it contains a namespace.identifier & exists.
542
+
543
+ ### Params:
544
+
545
+ * **action** *The* action to remove
546
+ * **[callback]** *Callback* function to remove
547
+
548
+ ## addFilter(Must, Must, Used, Supply)
549
+
550
+ Adds a filter to the event manager.
551
+
552
+ ### Params:
553
+
554
+ * **filter** *Must* contain namespace.identifier
555
+ * **callback** *Must* be a valid callback function before this action is added
556
+ * **[priority=10]** *Used* to control when the function is executed in relation to other callbacks bound to the same hook
557
+ * **[context]** *Supply* a value to be used for this
558
+
559
+ ## applyFilters()
560
+
561
+ Performs a filter if it exists. You should only ever pass 1 argument to be filtered. The only rule is that
562
+ the first argument must always be the filter.
563
+
564
+ filter, filtered arg, arg2, ...
565
+
566
+ ## removeFilter(The, Callback)
567
+
568
+ Removes the specified filter if it contains a namespace.identifier & exists.
569
+
570
+ ### Params:
571
+
572
+ * **filter** *The* action to remove
573
+ * **[callback]** *Callback* function to remove
574
+
575
+ ## _removeHook(Type, The)
576
+
577
+ Removes the specified hook by resetting the value of it.
578
+
579
+ ### Params:
580
+
581
+ * **type** *Type* of hook, either 'actions' or 'filters'
582
+ * **hook** *The* hook (namespace.identifier) to remove
583
+
584
+ ## _addHook('actions', The, The, The, A)
585
+
586
+ Adds the hook to the appropriate storage container
587
+
588
+ ### Params:
589
+
590
+ * **type** *'actions'* or 'filters'
591
+ * **hook** *The* hook (namespace.identifier) to add to our event manager
592
+ * **callback** *The* function that will be called when the hook is executed.
593
+ * **priority** *The* priority of this hook. Must be an integer.
594
+ * **[context]** *A* value to be used for this
595
+
596
+ ## _hookInsertSort(The)
597
+
598
+ Use an insert sort for keeping our hooks organized based on priority. This function is ridiculously faster
599
+ than bubble sort, etc: http://jsperf.com/javascript-sort
600
+
601
+ ### Params:
602
+
603
+ * **hooks** *The* custom array containing all of the appropriate hooks to perform an insert sort on.
604
+
605
+ ## _runHook('actions', The, Arguments)
606
+
607
+ Runs the specified hook. If it is an action, the value is not modified but if it is a filter, it is.
608
+
609
+ ### Params:
610
+
611
+ * **type** *'actions'* or 'filters'
612
+ * **hook** *The* hook ( namespace.identifier ) to be ran.
613
+ * **args** *Arguments* to pass to the action/filter. If it's a filter, args is actually a single parameter.
614
+
615
+ Event Hooks and Filters public methods
616
+
617
+ ## add_action()
618
+
619
+ add_action
620
+
621
+ This function uses _inbound.hooks to mimics WP add_action
622
+
623
+ ```js
624
+ function Inbound_Add_Action_Example(data) {
625
+ // Do stuff here.
626
+ };
627
+ // Add action to the hook
628
+ _inbound.add_action( 'name_of_action', Inbound_Add_Action_Example, 10 );
629
+ ```
630
+
631
+ ## remove_action()
632
+
633
+ remove_action
634
+
635
+ This function uses _inbound.hooks to mimics WP remove_action
636
+
637
+ ```js
638
+ // Add remove action 'name_of_action'
639
+ _inbound.remove_action( 'name_of_action');
640
+ ```
641
+
642
+ ## do_action()
643
+
644
+ do_action
645
+
646
+ This function uses _inbound.hooks to mimics WP do_action
647
+ This is used if you want to allow for third party JS plugins to act on your functions
648
+
649
+ ## add_filter()
650
+
651
+ add_filter
652
+
653
+ This function uses _inbound.hooks to mimics WP add_filter
654
+
655
+ ```js
656
+ _inbound.add_filter( 'urlParamFilter', URL_Param_Filter, 10 );
657
+ function URL_Param_Filter(urlParams) {
658
+
659
+ var params = urlParams || {};
660
+ // check for item in object
661
+ if(params.utm_source !== "undefined"){
662
+ //alert('url param "utm_source" is here');
663
+ }
664
+
665
+ // delete item from object
666
+ delete params.utm_source;
667
+
668
+ return params;
669
+
670
+ }
671
+ ```
672
+
673
+ ## remove_filter()
674
+
675
+ remove_filter
676
+
677
+ This function uses _inbound.hooks to mimics WP remove_filter
678
+
679
+ ```js
680
+ // Add remove filter 'urlParamFilter'
681
+ _inbound.remove_action( 'urlParamFilter');
682
+ ```
683
+
684
+ ## apply_filters()
685
+
686
+ apply_filters
687
+
688
+ This function uses _inbound.hooks to mimics WP apply_filters
689
+
690
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.hooks.js -->
691
+
692
+
693
+
694
+
695
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.init.js -->
696
+
697
+ ## inbound_data
698
+
699
+ # _inbound
700
+
701
+ This main the _inbound class
702
+
703
+ Author: David Wells <david@inboundnow.com>
704
+
705
+ Version: 0.0.1
706
+
707
+ ## _gaq
708
+
709
+ Ensure global _gaq Google Analytics queue has been initialized.
710
+
711
+ ## url
712
+
713
+ load dummy data for testing
714
+
715
+ ## defaults
716
+
717
+ Constants
718
+
719
+ ## init()
720
+
721
+ Initialize individual modules
722
+
723
+ run form mapping
724
+
725
+ set URL params
726
+
727
+ ## Timeout
728
+
729
+ run form mapping for dynamically generated forms
730
+
731
+ ## extend(defaults, options)
732
+
733
+ Merge script defaults with user options
734
+
735
+ ### Params:
736
+
737
+ * **Object** *defaults* Default settings
738
+ * **Object** *options* User options
739
+
740
+ ### Return:
741
+
742
+ * **Object** Merged values of defaults and options
743
+
744
+ ## debug()
745
+
746
+ Debugger Function toggled by var debugMode
747
+
748
+ ## Settings
749
+
750
+ Set globals
751
+
752
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.init.js -->
753
+
754
+
755
+
756
+
757
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.lead.js -->
758
+
759
+ ## _inboundLeadsAPI
760
+
761
+ Leads API functions
762
+
763
+ ### Params:
764
+
765
+ * **Object** *_inbound* - Main JS object
766
+
767
+ ### Return:
768
+
769
+ * **Object** - include event triggers
770
+
771
+ ## d
772
+
773
+ Set 3 day timeout for checking DB for new lead data for Lead_Global var
774
+
775
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.lead.js -->
776
+
777
+
778
+
779
+
780
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.page.js -->
781
+
782
+ # Page View Tracking
783
+
784
+ Page view tracking
785
+
786
+ Author: David Wells <david@inboundnow.com>
787
+
788
+ Version: 0.0.1
789
+
790
+ ## _inboundPageTracking
791
+
792
+ Launches view tracking
793
+
794
+ Start Session on page load
795
+
796
+ ## startSession()
797
+
798
+ This start only runs once
799
+
800
+ Todo session start here
801
+
802
+ ## pingSession()
803
+
804
+ Ping Session to keep active
805
+
806
+ ## getPageViews()
807
+
808
+ Returns the pages viewed by the site visitor
809
+
810
+ ```js
811
+ var pageViews = _inbound.PageTracking.getPageViews();
812
+ // returns page view object
813
+ ```
814
+
815
+ ### Return:
816
+
817
+ * **object** page view object with page ID as key and timestamp
818
+
819
+ Page Revisit Trigger
820
+
821
+ Page First Seen Trigger
822
+
823
+ Default
824
+
825
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.page.js -->
826
+
827
+
828
+
829
+
830
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.start.js -->
831
+
832
+ # Start
833
+
834
+ Runs init functions and runs the domReady functions
835
+
836
+ Author: David Wells <david@inboundnow.com>
837
+
838
+ Version: 0.0.1
839
+
840
+ raw_js_trigger event trigger
841
+
842
+ Filter Example
843
+
844
+ On Load Analytics Events
845
+
846
+ Action Example
847
+
848
+ Get InboundLeadData
849
+
850
+ Lead list check
851
+
852
+ Set Session Timeout
853
+
854
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.start.js -->
855
+
856
+
857
+
858
+
859
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.storage.js -->
860
+
861
+ ## InboundTotalStorage
862
+
863
+ LocalStorage Component
864
+
865
+ ## totalStorage()
866
+
867
+ Make the methods public
868
+
869
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.storage.js -->
870
+
871
+
872
+
873
+
874
+ <!-- Start shared/assets/frontend/js/analytics-src/analytics.utils.js -->
875
+
876
+ ## _inboundUtils
877
+
878
+ # _inbound UTILS
879
+
880
+ This file contains all of the utility functions used by analytics
881
+
882
+ Author: David Wells <david@inboundnow.com>
883
+
884
+ Version: 0.0.1
885
+
886
+ ## polyFills()
887
+
888
+ Polyfills for missing browser functionality
889
+
890
+ Console.log fix for old browsers
891
+
892
+ Event trigger polyfill for IE9 and 10
893
+ (function() {
894
+ function CustomEvent(event, params) {
895
+ params = params || {
896
+ bubbles: false,
897
+ cancelable: false,
898
+ detail: undefined
899
+ };
900
+ var evt = document.createEvent('CustomEvent');
901
+ evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
902
+ return evt;
903
+ }
904
+
905
+ CustomEvent.prototype = window.Event.prototype;
906
+
907
+ window.CustomEvent = CustomEvent;
908
+ })();
909
+
910
+ custom event for ie8+ https://gist.github.com/WebReflection/6693661
911
+
912
+ querySelectorAll polyfill for ie7+
913
+
914
+ Innertext shim for firefox https://github.com/duckinator/innerText-polyfill/blob/master/innertext.js
915
+
916
+ ## createCookie(name, value, days)
917
+
918
+ Create cookie
919
+
920
+ ```js
921
+ // Creates cookie for 10 days
922
+ _inbound.utils.createCookie( 'cookie_name', 'value', 10 );
923
+ ```
924
+
925
+ ### Params:
926
+
927
+ * **string** *name* Name of cookie
928
+ * **string** *value* Value of cookie
929
+ * **string** *days* Length of storage
930
+
931
+ ## readCookie(name)
932
+
933
+ Read cookie value
934
+
935
+ ```js
936
+ var cookie = _inbound.utils.readCookie( 'cookie_name' );
937
+ console.log(cookie); // cookie value
938
+ ```
939
+
940
+ ### Params:
941
+
942
+ * **string** *name* name of cookie
943
+
944
+ ### Return:
945
+
946
+ * **string** value of cookie
947
+
948
+ ## eraseCookie(name)
949
+
950
+ Erase cookie
951
+
952
+ ```js
953
+ // usage:
954
+ _inbound.utils.eraseCookie( 'cookie_name' );
955
+ // deletes 'cookie_name' value
956
+ ```
957
+
958
+ ### Params:
959
+
960
+ * **string** *name* name of cookie
961
+
962
+ ### Return:
963
+
964
+ * **string** value of cookie
965
+
966
+ ## getAllCookies()
967
+
968
+ Get All Cookies
969
+
970
+ ## setUrlParams()
971
+
972
+ Grab URL params and save
973
+
974
+ Set Param Cookies
975
+
976
+ Set Param LocalStorage
977
+
978
+ ## getParameterVal()
979
+
980
+ Get url param
981
+
982
+ http://spin.atomicobject.com/2013/01/23/ios-private-browsing-localstorage/
983
+ var hasStorage;
984
+ hasStorage = function() {
985
+ var mod, result;
986
+ try {
987
+ mod = new Date;
988
+ localStorage.setItem(mod, mod.toString());
989
+ result = localStorage.getItem(mod) === mod.toString();
990
+ localStorage.removeItem(mod);
991
+ return result;
992
+ } catch (_error) {}
993
+ };
994
+
995
+ ## addDays()
996
+
997
+ Add days to datetime
998
+
999
+ ## SetSessionTimeout()
1000
+
1001
+ Set Expiration Date of Session Logging
1002
+
1003
+ Set Lead UID
1004
+
1005
+ ## countProperties()
1006
+
1007
+ Count number of session visits
1008
+
1009
+ IE Polyfill
1010
+
1011
+ ## addListener()
1012
+
1013
+ Cross-browser event listening
1014
+
1015
+ ## throttle()
1016
+
1017
+ Throttle function borrowed from:
1018
+ Underscore.js 1.5.2
1019
+ http://underscorejs.org
1020
+ (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
1021
+ Underscore may be freely distributed under the MIT license.
1022
+
1023
+ ## checkTypeofGA()
1024
+
1025
+ Determine which version of GA is being used
1026
+ "ga", "_gaq", and "dataLayer" are the possible globals
1027
+
1028
+ <!-- End shared/assets/frontend/js/analytics-src/analytics.utils.js -->
1029
+
shared/shortcodes/css/frontend-render.css CHANGED
@@ -34,6 +34,7 @@ padding-right: 5px;
34
  }
35
  #inbound_form_submit {
36
  text-transform: none;
 
37
  }
38
  /* global fixes */
39
  .inbound-field {
@@ -108,7 +109,9 @@ display: inline-block;
108
  padding-right: 10px;
109
  text-align: right;
110
  }
111
-
 
 
112
  .inbound-label.inbound-input-radio {
113
  display: block;
114
  }
@@ -875,6 +878,7 @@ a.inbound-button, a.inbound-button.inbound-special-class{
875
  }
876
  input[type=submit].inbound-button, button.inbound-button{
877
  -webkit-appearance:none;
 
878
  }
879
  .inbound-button.black{
880
  background-color: #4A4845;
34
  }
35
  #inbound_form_submit {
36
  text-transform: none;
37
+ cursor: pointer;
38
  }
39
  /* global fixes */
40
  .inbound-field {
109
  padding-right: 10px;
110
  text-align: right;
111
  }
112
+ #inbound-form-wrapper .label-inbound-label-inline input {
113
+ display: inline-block;
114
+ }
115
  .inbound-label.inbound-input-radio {
116
  display: block;
117
  }
878
  }
879
  input[type=submit].inbound-button, button.inbound-button{
880
  -webkit-appearance:none;
881
+ cursor: pointer;
882
  }
883
  .inbound-button.black{
884
  background-color: #4A4845;
shared/shortcodes/js/tinymce.js CHANGED
@@ -31,13 +31,13 @@ var active_plugins = inbound_load.inbound_plugins,
31
  leads_status = indexOf.call(active_plugins, leads_check);
32
  // End Check Active Plugins
33
  if (leads_status > -1) {
34
- console.log("leads on");
35
  }
36
  if (lp_status > -1) {
37
- console.log("lp on");
38
  }
39
  if (cta_status > -1) {
40
- console.log("cta on");
41
  }
42
 
43
 
31
  leads_status = indexOf.call(active_plugins, leads_check);
32
  // End Check Active Plugins
33
  if (leads_status > -1) {
34
+ //console.log("leads on");
35
  }
36
  if (lp_status > -1) {
37
+ //console.log("lp on");
38
  }
39
  if (cta_status > -1) {
40
+ //console.log("cta on");
41
  }
42
 
43
 
shared/shortcodes/shortcodes-includes.php CHANGED
@@ -31,15 +31,6 @@ jQuery(".lead").append('"' + clean + '" => "' + toTitleCase(new_name) + '", ');
31
  $lead_mapping_fields = Leads_Field_Map::build_map_array();
32
  $lead_list_names = get_transient( 'inbound-list-names' );
33
 
34
- add_filter( 'excerpt_length', 'inbound_excerpt_length' );
35
- if (!function_exists('inbound_excerpt_length')) {
36
- function inbound_excerpt_length( $length ) {
37
- $custom = '';
38
- return ( $custom != '' ? $custom : 40 );
39
- }
40
- }
41
-
42
-
43
  /* Global Inbound Now Shortcodes */
44
  require_once ('shortcodes/forms.php'); // Form Builder
45
  require_once ('shortcodes/column.php'); // Columned Layouts
31
  $lead_mapping_fields = Leads_Field_Map::build_map_array();
32
  $lead_list_names = get_transient( 'inbound-list-names' );
33
 
 
 
 
 
 
 
 
 
 
34
  /* Global Inbound Now Shortcodes */
35
  require_once ('shortcodes/forms.php'); // Form Builder
36
  require_once ('shortcodes/column.php'); // Columned Layouts
shared/tracking/new.store.lead.php ADDED
@@ -0,0 +1,644 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Inbound Lead Storage
4
+ *
5
+ * - Handles lead creation and data storage
6
+ */
7
+
8
+ if (!class_exists('LeadStorage')) {
9
+ class LeadStorage {
10
+ static $mapped_fields;
11
+ static $is_ajax;
12
+
13
+ /**
14
+ * Initialize class
15
+ */
16
+ static function init() {
17
+ /* determines if in ajax mode */
18
+ self::set_mode();
19
+
20
+ /* sets up ajax listeners */
21
+ add_action('wp_ajax_inbound_lead_store', array(__CLASS__, 'inbound_lead_store'), 10, 1);
22
+ add_action('wp_ajax_nopriv_inbound_lead_store', array(__CLASS__, 'inbound_lead_store'), 10, 1);
23
+
24
+ /* filters name data to build a more comprehensive data set */
25
+ add_filter( 'inboundnow_store_lead_pre_filter_data', array(__CLASS__, 'improve_lead_name'), 10 , 1);
26
+ }
27
+
28
+ /**
29
+ * Checks if running in ajax mode
30
+ */
31
+ static function set_mode( $mode = 'auto' ) {
32
+ switch( $mode ) {
33
+ case 'auto':
34
+ self::$is_ajax = ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ? true : false;
35
+ BREAK;
36
+ case 'ajax':
37
+ self::$is_ajax = true;
38
+ BREAK;
39
+ case 'return':
40
+ self::$is_ajax = false;
41
+ BREAK;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Stores lead
47
+ */
48
+ static function inbound_lead_store( $args ) {
49
+ global $user_ID, $wpdb;
50
+ if (!is_array($args)) { $args = array(); }
51
+
52
+ /* Mergs $args with POST request for support of ajax and direct calls */
53
+ if(isset($_POST)){
54
+ $args = array_merge( $args, $_POST );
55
+ }
56
+
57
+ $lead = array();
58
+ if(isset($user_ID)){
59
+ $lead['user_ID'] = $user_ID;
60
+ }
61
+ /* Current wordpress time from settings */
62
+ $time = current_time( 'timestamp', 0 );
63
+ $lead['wordpress_date_time'] = date("Y-m-d G:i:s T", $time);
64
+
65
+ $lead['email'] = str_replace("%40", "@", self::check_val('email', $args));
66
+ $lead['name'] = str_replace("%20", " ", self::check_val('full_name', $args));
67
+ $lead['first_name'] = str_replace("%20", "", self::check_val('first_name', $args));
68
+ $lead['last_name'] = str_replace("%20", "", self::check_val('last_name', $args));
69
+ $lead['page_id'] = self::check_val('page_id', $args);
70
+ $lead['page_views'] = self::check_val('page_views', $args);
71
+ $lead['raw_params'] = self::check_val('raw_params', $args);
72
+
73
+ $lead['mapped_params'] = self::check_val('mapped_params', $args);
74
+ $lead['url_params'] = self::check_val('url_params', $args);
75
+ $lead['variation'] = self::check_val('variation', $args);
76
+ $lead['source'] = self::check_val('source', $args);
77
+ $lead['ip_address'] = self::lookup_ip_address();
78
+
79
+ if($lead['mapped_params']){
80
+ parse_str($lead['mapped_params'], $mappedData);
81
+ } else {
82
+ $mappedData = array();
83
+ }
84
+
85
+ $mappedData = self::improve_mapping($mappedData, $lead);
86
+
87
+ $lead['lead_lists'] = (array_key_exists('inbound_form_lists', $mappedData)) ? explode(",", $mappedData['inbound_form_lists']) : false;
88
+ //print_r($lead['lead_lists']); wp_die();
89
+
90
+ /* Look for direct key matches & clean up $lead_data */
91
+ $lead = apply_filters( 'inboundnow_store_lead_pre_filter_data', $lead, $args);
92
+
93
+ /* TODO have fallbacks for existing lead ID or Lead UID lookups*/
94
+ /* check for set email */
95
+ if ( (isset($lead['email']) && !empty($lead['email']) && strstr($lead['email'] ,'@'))) {
96
+
97
+
98
+ $leadExists = self::lookup_lead_by_email($lead['email']);
99
+ //print_r($leadExists); wp_die();
100
+ /* Update Lead if Exists else Create New Lead */
101
+ if ( $leadExists ) {
102
+ $lead['id'] = $leadExists;
103
+ /* action hook on existing leads only */
104
+ do_action('wpleads_existing_lead_update', $lead);
105
+ } else {
106
+ /* Create new lead if one doesnt exist */
107
+ $lead['id'] = self::store_new_lead($lead);
108
+ }
109
+
110
+ /* do everything else for lead storage */
111
+ self::update_common_meta($lead);
112
+
113
+ do_action('wpleads_after_conversion_lead_insert', $lead['id']); // action hook on all lead inserts
114
+
115
+ /* Add Leads to List on creation */
116
+ if(!empty($lead['lead_lists']) && is_array($lead['lead_lists'])){
117
+ global $Inbound_Leads;
118
+ $Inbound_Leads->add_lead_to_list($lead['id'], $lead['lead_lists'], 'wplead_list_category');
119
+ }
120
+
121
+ /* Store page views for people with ajax tracking off */
122
+ $ajax_tracking_off = false; // get_option
123
+ if($lead['page_views'] && $ajax_tracking_off ) {
124
+ self::store_page_views($lead);
125
+ }
126
+
127
+ /* Store Mapped Form Data */
128
+ if(!empty($mappedData)){
129
+ self::store_mapped_data($lead, $mappedData);
130
+ }
131
+
132
+ /* Store past search history */
133
+ if(isset($lead['search_data'])){
134
+ self::store_search_history($lead);
135
+ }
136
+
137
+ /* Store ConversionData */
138
+ if ( isset($lead['page_id']) ) {
139
+ self::store_conversion_data($lead);
140
+ }
141
+
142
+ /* Store Lead Source */
143
+ if ( isset($lead['source']) ) {
144
+ self::store_referral_data($lead);
145
+ }
146
+
147
+ /* Store URL Params */
148
+ if($lead['url_params']) {
149
+ $param_array = json_decode(stripslashes($lead['url_params']));
150
+ //print_r($param_array); exit;
151
+ if(is_array($param_array)){
152
+
153
+ }
154
+ }
155
+
156
+ /* Store Conversion Data to LANDING PAGE/CTA DATA */
157
+ if (isset($lead['post_type']) && $lead['post_type'] == 'landing-page' || isset($lead['post_type']) && $lead['post_type'] == 'wp-call-to-action') {
158
+ self::store_conversion_stats($lead);
159
+ }
160
+
161
+ /* Store IP addresss & Store GEO Data */
162
+ if ($lead['ip_address']) {
163
+ self::store_geolocation_data($lead);
164
+ }
165
+
166
+ //setcookie('wp_lead_id' , $lead['id'], time() + (20 * 365 * 24 * 60 * 60),'/');
167
+
168
+ do_action('inbound_store_lead_post', $lead );
169
+ do_action('wp_cta_store_lead_post', $lead );
170
+ do_action('wpl_store_lead_post', $lead );
171
+ do_action('lp_store_lead_post', $lead );
172
+
173
+ if ( self::$is_ajax ) {
174
+ echo $lead['id'];
175
+ die();
176
+ } else {
177
+ return $lead['id'];
178
+ }
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Creates new lead in wp-lead post type
184
+ */
185
+ static function store_new_lead($lead){
186
+ /* Create New Lead */
187
+ $post = array(
188
+ 'post_title' => $lead['email'],
189
+ //'post_content' => $json,
190
+ 'post_status' => 'publish',
191
+ 'post_type' => 'wp-lead',
192
+ 'post_author' => 1
193
+ );
194
+
195
+ //$post = add_filter('lp_leads_post_vars',$post);
196
+ $id = wp_insert_post($post);
197
+ /* specific updates for new leads */
198
+ update_post_meta( $id, 'wpleads_email_address', $lead['email'] );
199
+ /* new lead run simple page_view storage */
200
+ update_post_meta( $id, 'page_views', $lead['page_views']);
201
+ /* dont need update_post_meta( $id, 'wpleads_page_view_count', $lead['page_view_count']); */
202
+
203
+ do_action('wpleads_new_lead_insert', $lead ); // action hook on new leads only
204
+ return $id;
205
+ }
206
+
207
+ /**
208
+ * Updates pages viewed object
209
+ */
210
+ static function store_page_views($lead){
211
+ $page_view_data = get_post_meta( $lead['id'], 'page_views', TRUE );
212
+ $page_view_data = json_decode($page_view_data,true);
213
+
214
+ // If page_view meta exists do this
215
+ if (is_array($page_view_data)) {
216
+ $new_page_views = self::json_array_merge( $page_view_data, $lead['page_views']);
217
+ $page_views = json_encode($new_page_views);
218
+ } else {
219
+ // Create page_view meta if it doesn't exist
220
+ $page_views = $lead['page_views'];
221
+ $page_views = json_encode($page_views);
222
+ }
223
+ update_post_meta($lead['id'], 'page_views', $page_views );
224
+ }
225
+
226
+ /**
227
+ * Prefixes keys with wpleads_ if key is not prepended with wpleads_
228
+ */
229
+ static function store_mapped_data($lead, $mappedData){
230
+ foreach ($mappedData as $key => $value) {
231
+ update_post_meta($lead['id'], $key, $value);
232
+ /* Old convention with wpleads_ prefix */
233
+ if( !strstr($key,'wpleads_') ) {
234
+ update_post_meta($lead['id'], 'wpleads_'.$key, $value);
235
+ }
236
+
237
+ /* old convention
238
+ //print_r($mappedData); wp_die();
239
+
240
+ /* Update mappable fields
241
+ $lead_fields = Leads_Field_Map::build_map_array();
242
+ foreach ( $lead_fields as $key => $value ) {
243
+ if (isset($lead_data[$key])) {
244
+ update_post_meta( $lead_data['lead_id'], $key , $lead_data[ $key ] );
245
+ }
246
+ }*/
247
+ //$mappedData = json_decode(stripslashes($lead['mapped_params']), true );
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Updates search history object
253
+ */
254
+ static function store_search_history($lead){
255
+ $search = $lead['search_data'];
256
+ $search_data = get_post_meta( $lead['id'], 'wpleads_search_data', TRUE );
257
+ $search_data = json_decode($search_data,true);
258
+ if (is_array($search_data)){
259
+ $s_count = count($search_data) + 1;
260
+ $loop_count = 1;
261
+ foreach ($search as $key => $value) {
262
+ $search_data[$s_count]['date'] = $search[$loop_count]['date'];
263
+ $search_data[$s_count]['value'] = $search[$loop_count]['value'];
264
+ $s_count++; $loop_count++;
265
+ }
266
+ } else {
267
+ // Create search obj
268
+ $s_count = 1;
269
+ $loop_count = 1;
270
+ foreach ($search as $key => $value) {
271
+ $search_data[$s_count]['date'] = $search[$loop_count]['date'];
272
+ $search_data[$s_count]['value'] = $search[$loop_count]['value'];
273
+ $s_count++; $loop_count++;
274
+ }
275
+ }
276
+ $search_data = json_encode($search_data);
277
+ update_post_meta($lead['id'], 'wpleads_search_data', $search_data); // Store search object
278
+ }
279
+ /**
280
+ * updates conversion data object
281
+ */
282
+ static function store_conversion_data( $lead ) {
283
+
284
+ $conversion_data = get_post_meta( $lead['id'], 'wpleads_conversion_data', TRUE );
285
+ $conversion_data = json_decode($conversion_data,true);
286
+ $variation = $lead['variation'];
287
+
288
+ if ( is_array($conversion_data)) {
289
+ $c_count = count($conversion_data) + 1;
290
+ $conversion_data[$c_count]['id'] = $lead['page_id'];
291
+ $conversion_data[$c_count]['variation'] = $variation;
292
+ $conversion_data[$c_count]['datetime'] = $lead['wordpress_date_time'];
293
+ } else {
294
+ $c_count = 1;
295
+ $conversion_data[1]['id'] = $lead['page_id'];
296
+ $conversion_data[1]['variation'] = $variation;
297
+ $conversion_data[1]['datetime'] = $lead['wordpress_date_time'];
298
+ $conversion_data[1]['first_time'] = 1;
299
+ }
300
+
301
+ $lead['conversion_data'] = json_encode($conversion_data);
302
+ update_post_meta($lead['id'],'wpleads_conversion_count', $c_count); // Store conversions count
303
+ update_post_meta($lead['id'], 'wpleads_conversion_data', $lead['conversion_data']);// Store conversion obj
304
+
305
+ }
306
+ /**
307
+ * Store Conversion Data to LANDING PAGE/CTA DATA
308
+ */
309
+ static function store_conversion_stats($lead){
310
+ $page_conversion_data = get_post_meta( $lead['page_id'], 'inbound_conversion_data', TRUE );
311
+ $page_conversion_data = json_decode($page_conversion_data,true);
312
+ $version = ($lead['variation'] != 'default') ? $lead['variation'] : '0';
313
+ if (is_array($page_conversion_data)) {
314
+ $convert_count = count($page_conversion_data) + 1;
315
+ $page_conversion_data[$convert_count]['lead_id'] = $lead['id'];
316
+ $page_conversion_data[$convert_count]['variation'] = $version;
317
+ $page_conversion_data[$convert_count]['datetime'] = $lead['wordpress_date_time'];
318
+ } else {
319
+ $page_conversion_data[1]['lead_id'] = $lead['id'];
320
+ $page_conversion_data[1]['variation'] = $version;
321
+ $page_conversion_data[1]['datetime'] = $lead['wordpress_date_time'];
322
+ }
323
+ $page_conversion_data = json_encode($page_conversion_data);
324
+ update_post_meta($lead['page_id'], 'inbound_conversion_data', $page_conversion_data);
325
+ }
326
+
327
+ /**
328
+ * Stores referral data
329
+ */
330
+ static function store_referral_data($lead) {
331
+ $referral_data = get_post_meta( $lead['id'], 'wpleads_referral_data', TRUE );
332
+
333
+ // Parse referral for additional data
334
+ include_once('sources/Snowplow/RefererParser/INBOUND_Parser.php');
335
+ include_once('sources/Snowplow/RefererParser/INBOUND_Referer.php');
336
+ include_once('sources/Snowplow/RefererParser/INBOUND_Medium.php');
337
+ // intialized the parser class
338
+ $parser = new INBOUND_Parser();
339
+ //$array = array('http://google.com', 'http://twitter.com', 'http://tumblr.com?query=test', '');
340
+ $referer = $parser->parse($lead['source']);
341
+
342
+ if ( $referer->isKnown() ) {
343
+ $ref_type = $referer->getMedium();
344
+
345
+ } else {
346
+ // check if ref exists
347
+ $ref_type = ($lead['source'] === "Direct Traffic") ? 'Direct Traffic' : 'referral';
348
+
349
+ }
350
+
351
+ $referral_data = json_decode($referral_data,true);
352
+ if (is_array($referral_data)){
353
+ $r_count = count($referral_data) + 1;
354
+ $referral_data[$r_count]['source'] = $lead['source'];
355
+ $referral_data[$r_count]['type'] = $ref_type;
356
+ $referral_data[$r_count]['datetime'] = $lead['wordpress_date_time'];
357
+ } else {
358
+ $referral_data[1]['source'] = $lead['source'];
359
+ $referral_data[1]['type'] = $ref_type;
360
+ $referral_data[1]['datetime'] = $lead['wordpress_date_time'];
361
+ $referral_data[1]['original_source'] = 1;
362
+ }
363
+
364
+ $lead['referral_data'] = json_encode($referral_data);
365
+ //echo $lead['referral_data']; exit;
366
+ update_post_meta($lead['id'], 'wpleads_referral_data', $lead['referral_data']); // Store referral object
367
+ update_post_meta($lead['id'], 'wpleads_referral_type', $ref_type); // Store referral object
368
+ }
369
+
370
+ /**
371
+ * Loop trough lead_data array and update post meta
372
+ */
373
+ static function update_common_meta($lead) {
374
+
375
+
376
+ if (!empty($lead['user_ID'])) {
377
+ /* Update user_ID if exists */
378
+ update_post_meta( $lead['id'], 'wpleads_wordpress_user_id', $lead['user_ID'] );
379
+ }
380
+
381
+ /* Update wp_lead_uid if exist */
382
+ if (!empty($lead['wp_lead_uid'])) {
383
+ update_post_meta( $lead['id'], 'wp_leads_uid', $lead['wp_lead_uid'] );
384
+ }
385
+
386
+ /* Update email address */
387
+ if (!empty($lead['email'])) {
388
+ update_post_meta( $lead['id'], 'wplead_email_address', $lead['email'] );
389
+ }
390
+
391
+ /* Update mappable fields that have a value associated with them */
392
+ $lead_fields = Leads_Field_Map::build_map_array();
393
+ foreach ( $lead_fields as $key => $value ) {
394
+ $shortkey = str_replace('wpleads_' , '' , $key );
395
+ if (isset($lead[$shortkey])) {
396
+ echo $key . ':' . $lead[$shortkey] . "\r\n";
397
+ update_post_meta( $lead['id'], $key, $lead[$shortkey] );
398
+ }
399
+ }
400
+
401
+ }
402
+
403
+ /**
404
+ * Connects to geoplugin.net and gets data on IP address and sets it into historical log
405
+ * @param ARRAY $lead_data
406
+ */
407
+ static function store_geolocation_data( $lead ) {
408
+
409
+ $ip_addresses = get_post_meta( $lead['id'], 'wpleads_ip_address', true );
410
+ $ip_addresses = json_decode( stripslashes($ip_addresses) , true);
411
+
412
+ if (!$ip_addresses) {
413
+ $ip_addresses = array();
414
+ }
415
+
416
+ $new_record[ $lead['ip_address'] ]['ip_address'] = $lead['ip_address'];
417
+
418
+
419
+ /* ignore for local environments */
420
+ if ($lead['ip_address']!= "127.0.0.1"){ // exclude localhost
421
+ $response = wp_remote_get('http://www.geoplugin.net/php.gp?ip='.$lead['ip_address']);
422
+ if ( isset($response['body']) ) {
423
+ $geo_array = @unserialize($response['body']);
424
+ $new_record[ $lead['ip_address'] ]['geodata'] = $geo_array;
425
+ }
426
+
427
+ }
428
+
429
+ $ip_addresses = array_merge( $new_record, $ip_addresses );
430
+ $ip_addresses = json_encode( $ip_addresses );
431
+
432
+ update_post_meta( $lead['id'], 'wpleads_ip_address', $ip_addresses );
433
+ }
434
+
435
+ /**
436
+ * Updates raw form data object
437
+ */
438
+ static function store_raw_form_data($lead){
439
+ /* Raw Form Values Store */
440
+ if ($lead_data['form_input_values']) {
441
+ $raw_post_data = get_post_meta($$lead['id'],'wpleads_raw_post_data', true);
442
+ $a1 = json_decode( $raw_post_data, true );
443
+ $a2 = json_decode( stripslashes($lead_data['form_input_values']), true );
444
+ $exclude_array = array('card_number','card_cvc','card_exp_month','card_exp_year'); // add filter
445
+ $lead_mapping_fields = Leads_Field_Map::build_map_array();
446
+
447
+ foreach ($a2 as $key=>$value)
448
+ {
449
+ if (array_key_exists( $key , $exclude_array )) {
450
+ unset($a2[$key]);
451
+ continue;
452
+ }
453
+ if (preg_match("/\[\]/", $key)) {
454
+ $key = str_replace("[]", "", $key); // fix array value keys
455
+ }
456
+ if (array_key_exists($key, $lead_mapping_fields)) {
457
+ update_post_meta( $lead_id, $key, $value );
458
+ }
459
+
460
+ if (stristr($key,'company'))
461
+ {
462
+ update_post_meta( $lead_id, 'wpleads_company_name', $value );
463
+ }
464
+ else if (stristr($key,'website'))
465
+ {
466
+ $websites = get_post_meta( $lead_id, 'wpleads_websites', $value );
467
+ if(is_array($websites)) {
468
+ $array_websites = explode(';',$websites);
469
+ }
470
+ $array_websites[] = $value;
471
+ $websites = implode(';',$array_websites);
472
+ update_post_meta( $lead_id, 'wpleads_websites', $websites );
473
+ }
474
+ }
475
+ // Merge form fields if exist
476
+ if (is_array($a1)) {
477
+ $new_raw_post_data = array_merge_recursive( $a1, $a2 );
478
+ } else {
479
+ $new_raw_post_data = $a2;
480
+ }
481
+ $new_raw_post_data = json_encode( $new_raw_post_data );
482
+ update_post_meta( $lead_id,'wpleads_raw_post_data', $new_raw_post_data );
483
+ }
484
+ }
485
+
486
+ /**
487
+ * Parses & improves lead name
488
+ */
489
+ static function improve_lead_name( $lead ) {
490
+
491
+ /* if last name empty and full name present */
492
+ if ( empty($lead['last_name']) && $lead['name'] ) {
493
+ $parts = explode(' ' , $lead['name']);
494
+
495
+ /* Set first name */
496
+ $lead['first_name'] = $parts[0];
497
+
498
+ /* Set last name */
499
+ if (isset($parts[1])) {
500
+ $lead['last_name'] = $parts[1];
501
+ }
502
+ }
503
+ /* if last name empty and first name present */
504
+ else if (empty($lead['last_name']) && $lead['first_name'] ) {
505
+ $parts = explode(' ' , $lead['first_name']);
506
+
507
+ /* Set First Name */
508
+ $lead['first_name'] = $parts[0];
509
+
510
+ /* Set Last Name */
511
+ if (isset($parts[1])) {
512
+ $lead['last_name'] = $parts[1];
513
+ }
514
+ }
515
+
516
+ /* set full name */
517
+ if (!$lead['name'] && $lead['first_name'] && $lead['last_name'] ) {
518
+ $lead['name'] = $lead['first_name'] .' '. $lead['last_name'];
519
+ }
520
+
521
+ return $lead;
522
+ }
523
+
524
+ /**
525
+ * Uses mapped data if not programatically set
526
+ */
527
+ static function improve_mapping($mappedData, $lead) {
528
+ $arr = $mappedData;
529
+ /* Set names if not mapped */
530
+ $arr['first_name'] = (!isset($arr['first_name'])) ? $lead['first_name'] : $arr['first_name'];
531
+ $arr['last_name'] = (!isset($arr['last_name'])) ? $lead['last_name'] : $arr['last_name'];
532
+ /* Add filter and preg matches here */
533
+
534
+ return $arr;
535
+ }
536
+
537
+ /**
538
+ * Search lead by email
539
+ */
540
+ static function lookup_lead_by_email($email){
541
+ global $wpdb;
542
+ $query = $wpdb->prepare(
543
+ 'SELECT ID FROM ' . $wpdb->posts . '
544
+ WHERE post_title = %s
545
+ AND post_type = \'wp-lead\'',
546
+ $email
547
+ );
548
+ $wpdb->query( $query );
549
+ if ( $wpdb->num_rows ) {
550
+ $lead_id = $wpdb->get_var( $query );
551
+ return $lead_id;
552
+ } else {
553
+ return false;
554
+ }
555
+
556
+ }
557
+
558
+ static function check_val($key, $args) {
559
+ $val = (isset($args[$key])) ? $args[$key] : false;
560
+ return $val;
561
+ }
562
+ static function json_array_merge( $arr1, $arr2 ) {
563
+ $keys = array_keys( $arr2 );
564
+ foreach( $keys as $key ) {
565
+ if( isset( $arr1[$key] )
566
+ && is_array( $arr1[$key] )
567
+ && is_array( $arr2[$key] )
568
+ ) {
569
+ $arr1[$key] = my_merge( $arr1[$key], $arr2[$key] );
570
+ } else {
571
+ $arr1[$key] = $arr2[$key];
572
+ }
573
+ }
574
+ return $arr1;
575
+ }
576
+
577
+ /**
578
+ * Discover session IP address
579
+ */
580
+ static function lookup_ip_address() {
581
+ if(isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
582
+ if(isset($_SERVER["HTTP_CLIENT_IP"])) {
583
+ $proxy = $_SERVER["HTTP_CLIENT_IP"];
584
+ } else {
585
+ $proxy = $_SERVER["REMOTE_ADDR"];
586
+ }
587
+ $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
588
+ } else {
589
+ if(isset($_SERVER["HTTP_CLIENT_IP"])) {
590
+ $ip = $_SERVER["HTTP_CLIENT_IP"];
591
+ } else {
592
+ $ip = $_SERVER["REMOTE_ADDR"];
593
+ }
594
+ }
595
+ return $ip;
596
+ }
597
+
598
+ }
599
+
600
+ LeadStorage::init();
601
+ }
602
+
603
+ /**
604
+ * Legacy function used by some extensions
605
+ * @param ARRAY $args legacy dataset of mapped lead fields
606
+ * @param BOOL $return set to true to disable printing of lead id
607
+ */
608
+ if (!function_exists('inbound_store_lead')) {
609
+ function inbound_store_lead( $args , $return = true ) {
610
+ global $user_ID, $wpdb;
611
+
612
+ if (!is_array($args)) {
613
+ $args = array();
614
+ }
615
+
616
+ /* Mergs $args with POST request for support of ajax and direct calls */
617
+ $args = array_merge( $args , $_POST );
618
+
619
+ /* wpleads_email_address becomes wpleads_email */
620
+ $args['email'] = $args['wpleads_email_address'];
621
+
622
+ /* loop through and remove wpleads_ (we will add them back in the new method ) */
623
+ foreach ($args as $key => $value) {
624
+ $newkey = str_replace( 'wpleads_' , '' , $key );
625
+ unset($args[$key]);
626
+ $args[$newkey] = $value;
627
+ }
628
+
629
+ /* Send data through new method */
630
+ $Leads = new LeadStorage();
631
+ if ($return) {
632
+ $Leads->set_mode('return');
633
+ } else {
634
+ $Leads->set_mode('ajax');
635
+ }
636
+
637
+ $lead_id = $Leads::inbound_lead_store( $args );
638
+
639
+ return $lead_id;
640
+
641
+
642
+ }
643
+ }
644
+
shared/tracking/page-tracking.js CHANGED
@@ -1 +1 @@
1
- /* moved to /shared/assets/frontend/js */
1
+ /* moved to /shared/assets/frontend/js/inbound.js */
shared/tracking/sources/Snowplow/RefererParser/Config/INBOUND_ConfigFileReaderTrait.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class INBOUND_ConfigFileReaderTrait
4
+ {
5
+ /** @var string */
6
+ private $fileName;
7
+
8
+ /** @var array */
9
+ private $referers = array();
10
+
11
+ public function __construct ()
12
+ {
13
+
14
+ }
15
+
16
+ private function init($fileName)
17
+ {
18
+ if (!file_exists($fileName)) {
19
+ throw INBOUND_InvalidArgumentException::fileNotExists($fileName);
20
+ }
21
+
22
+ $this->fileName = $fileName;
23
+ }
24
+
25
+ abstract protected function parse($content);
26
+
27
+ private function read()
28
+ {
29
+ if ($this->referers) {
30
+ return;
31
+ }
32
+
33
+ $hash = $this->parse(file_get_contents($this->fileName));
34
+
35
+ foreach ($hash as $medium => $referers) {
36
+ foreach ($referers as $source => $referer) {
37
+ foreach ($referer['domains'] as $domain) {
38
+ $this->referers[$domain] = array(
39
+ 'source' => $source,
40
+ 'medium' => $medium,
41
+ 'parameters' => isset($referer['parameters']) ? $referer['parameters'] : array(),
42
+ );
43
+ }
44
+ }
45
+ }
46
+ }
47
+
48
+ public function lookup($lookupString)
49
+ {
50
+ $this->read();
51
+
52
+ return isset($this->referers[$lookupString]) ? $this->referers[$lookupString] : null;
53
+ }
54
+ }
shared/tracking/sources/Snowplow/RefererParser/Config/INBOUND_ConfigReaderInterface.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include('INBOUND_ConfigFileReaderTrait.php');
4
+
5
+ abstract class INBOUND_ConfigReaderInterface extends INBOUND_ConfigFileReaderTrait
6
+ {
7
+ /**
8
+ * @param string $lookupString
9
+ * @return array
10
+ */
11
+ public function lookup($lookupString)
12
+ {
13
+
14
+ }
15
+ }
shared/tracking/sources/Snowplow/RefererParser/Config/INBOUND_JsonConfigReader.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class INBOUND_JsonConfigReader extends INBOUND_ConfigReaderInterface
4
+ {
5
+ /** @var string */
6
+ private $fileName;
7
+
8
+ /** @var array */
9
+ private $referers = array();
10
+
11
+ public function __construct ( $fileName )
12
+ {
13
+ $this->fileName = $fileName;
14
+ }
15
+
16
+ private function init($fileName)
17
+ {
18
+ if (!file_exists($fileName)) {
19
+ throw INBOUND_InvalidArgumentException::fileNotExists($fileName);
20
+ }
21
+
22
+ $this->fileName = $fileName;
23
+ }
24
+
25
+ private function read()
26
+ {
27
+ if ($this->referers) {
28
+ return;
29
+ }
30
+
31
+ $hash = $this->parse(file_get_contents($this->fileName));
32
+
33
+ foreach ($hash as $medium => $referers) {
34
+ foreach ($referers as $source => $referer) {
35
+ foreach ($referer['domains'] as $domain) {
36
+ $this->referers[$domain] = array(
37
+ 'source' => $source,
38
+ 'medium' => $medium,
39
+ 'parameters' => isset($referer['parameters']) ? $referer['parameters'] : array(),
40
+ );
41
+ }
42
+ }
43
+ }
44
+ }
45
+
46
+ public function lookup($lookupString)
47
+ {
48
+ $this->read();
49
+
50
+ return isset($this->referers[$lookupString]) ? $this->referers[$lookupString] : null;
51
+ }
52
+
53
+ protected function parse($content)
54
+ {
55
+ return json_decode($content, true);
56
+ }
57
+ }
shared/tracking/sources/Snowplow/RefererParser/Exception/INBOUND_InvalidArgumentException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class INBOUND_InvalidArgumentException extends BaseInvalidArgumentException
4
+ {
5
+ public static function fileNotExists($fileName)
6
+ {
7
+ return new static(sprintf('File "%s" does not exist', $fileName));
8
+ }
9
+ }
shared/tracking/sources/Snowplow/RefererParser/INBOUND_Medium.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ final class INBOUND_Medium
4
+ {
5
+ const SEARCH = 'search';
6
+
7
+ const SOCIAL = 'social';
8
+
9
+ const UNKNOWN = 'unknown';
10
+
11
+ const INTERNAL = 'internal';
12
+
13
+ const EMAIL = 'email';
14
+
15
+ const INVALID = 'invalid';
16
+ }
shared/tracking/sources/Snowplow/RefererParser/INBOUND_Parser.php ADDED
@@ -0,0 +1,266 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Usage:
4
+
5
+ include_once(WP_CTA_URLPATH . '/shared/tracking/sources/Snowplow/RefererParser/INBOUND_Parser.php');
6
+ include_once(WP_CTA_URLPATH . '/shared/tracking/sources/Snowplow/RefererParser/INBOUND_Referer.php');
7
+ include_once(WP_CTA_URLPATH . '/shared/tracking/sources/Snowplow/RefererParser/INBOUND_Medium.php');
8
+
9
+ // intialized the parser class
10
+ $this->parser = new INBOUND_Parser();
11
+
12
+ $referer = $this->parser->parse($source);
13
+ if ( $referer->isKnown() ) {
14
+ return $referer->getMedium();
15
+ } else {
16
+ return 'referral';
17
+ }
18
+ */
19
+
20
+ /*
21
+
22
+ Functions to use in plugin
23
+
24
+ // $source ex = http://clean.dev/
25
+ // $origin ex = http://glocal.dev/?utm_source=the_source&utm_medium=camp%20med&utm_term=Bought%20keyword&utm_content=Funny%20Text&utm_campaign=400kpromo
26
+
27
+ // ORIGIN URL grabbed from first ever page view
28
+
29
+ function check_lead_source ( $source, $origin_url = '' )
30
+ {
31
+ if ( $source )
32
+ {
33
+ $decoded_source = urldecode($source);
34
+
35
+ if ( stristr($decoded_source, 'utm_medium=cpc') || stristr($decoded_source, 'utm_medium=ppc') || stristr($decoded_source, 'aclk') || stristr($decoded_source, 'gclid') )
36
+ return 'paid';
37
+
38
+ if ( stristr($source, 'utm_') )
39
+ {
40
+ $url = $source;
41
+ $url_parts = parse_url($url);
42
+ parse_str($url_parts['query'], $path_parts);
43
+
44
+ if ( isset($path_parts['adurl']) )
45
+ return 'paid';
46
+
47
+ if ( isset($path_parts['utm_medium']) )
48
+ {
49
+ if ( $path_parts['utm_medium'] == 'cpc' || $path_parts['utm_medium'] == 'ppc' )
50
+ return 'paid';
51
+
52
+ if ( $path_parts['utm_medium'] == 'social' )
53
+ return 'social';
54
+
55
+ if ( $path_parts['utm_medium'] == 'email' )
56
+ return 'email';
57
+ }
58
+
59
+ if ( isset($path_parts['utm_source']) )
60
+ {
61
+ if ( stristr($path_parts['utm_source'], 'email') )
62
+ return 'email';
63
+ }
64
+ }
65
+
66
+ $referer = $this->parser->parse(
67
+ $source
68
+ );
69
+
70
+ if ( $referer->isKnown() )
71
+ return $referer->getMedium();
72
+ else
73
+ return 'referral';
74
+ }
75
+ else
76
+ {
77
+ $decoded_origin_url = urldecode($origin_url);
78
+
79
+ if ( stristr($decoded_origin_url, 'utm_medium=cpc') || stristr($decoded_origin_url, 'utm_medium=ppc') || stristr($decoded_origin_url, 'aclk') || stristr($decoded_origin_url, 'gclid') )
80
+ return 'paid';
81
+
82
+ if ( stristr($decoded_origin_url, 'utm_') )
83
+ {
84
+ $url = $decoded_origin_url;
85
+ $url_parts = parse_url($url);
86
+ parse_str($url_parts['query'], $path_parts);
87
+
88
+ if ( isset($path_parts['adurl']) )
89
+ return 'paid';
90
+
91
+ if ( isset($path_parts['utm_medium']) )
92
+ {
93
+ if ( $path_parts['utm_medium'] == 'cpc' || $path_parts['utm_medium'] == 'ppc' )
94
+ return 'paid';
95
+
96
+ if ( $path_parts['utm_medium'] == 'social' )
97
+ return 'social';
98
+
99
+ if ( $path_parts['utm_medium'] == 'email' )
100
+ return 'email';
101
+ }
102
+
103
+ if ( isset($path_parts['utm_source']) )
104
+ {
105
+ if ( stristr($path_parts['utm_source'], 'email') )
106
+ return 'email';
107
+ }
108
+ }
109
+
110
+ return 'direct';
111
+ }
112
+ }
113
+
114
+ function print_readable_source ( $source )
115
+ {
116
+ switch ( $source )
117
+ {
118
+ case 'search' :
119
+ return 'Organic Search';
120
+ break;
121
+
122
+ case 'social' :
123
+ return 'Social Media';
124
+ break;
125
+
126
+ case 'email' :
127
+ return 'Email Marketing';
128
+ break;
129
+
130
+ case 'referral' :
131
+ return 'Referral';
132
+ break;
133
+
134
+ case 'paid' :
135
+ return 'Paid';
136
+ break;
137
+
138
+ case 'direct' :
139
+ return 'Direct';
140
+ break;
141
+ }
142
+ }
143
+
144
+ */
145
+
146
+ //echo 'hi';
147
+ include_once('Config/INBOUND_ConfigReaderInterface.php');
148
+ include_once('Config/INBOUND_JsonConfigReader.php');
149
+
150
+ class INBOUND_Parser
151
+ {
152
+ /** @var ConfigReaderInterface */
153
+ private $configReader;
154
+
155
+ /**
156
+ * @var string[]
157
+ */
158
+ private $internalHosts = array();
159
+
160
+ public function __construct(INBOUND_ConfigReaderInterface $configReader = null, array $internalHosts = array() )
161
+ {
162
+ $this->configReader = $configReader ? $configReader : self::createDefaultConfigReader();
163
+ $this->internalHosts = $internalHosts;
164
+ }
165
+
166
+ /**
167
+ * Parse referer URL
168
+ *
169
+ * @param string $refererUrl
170
+ * @param string $pageUrl
171
+ * @return Referer
172
+ */
173
+ public function parse($refererUrl, $pageUrl = null)
174
+ {
175
+ $refererParts = $this->parseUrl($refererUrl);
176
+ if (!$refererParts) {
177
+ return INBOUND_Referer::createInvalid();
178
+ }
179
+
180
+ $pageUrlParts = $this->parseUrl($pageUrl);
181
+
182
+ //print_r($refererParts);
183
+
184
+ if ($pageUrlParts
185
+ && $pageUrlParts['host'] === $refererParts['host']
186
+ || in_array($refererParts['host'], $this->internalHosts)) {
187
+ return INBOUND_Referer::createInternal();
188
+ }
189
+
190
+ $referer = $this->lookup($refererParts['host'], $refererParts['path']);
191
+
192
+ if (!$referer) {
193
+ return INBOUND_Referer::createUnknown();
194
+ }
195
+
196
+ $searchTerm = null;
197
+
198
+ if (is_array($referer['parameters'])) {
199
+ parse_str($refererParts['query'], $queryParts);
200
+
201
+ //foreach ($queryParts as $key => $parameter) {
202
+ $searchTerm = isset($queryParts['q']) ? $queryParts['q'] : $searchTerm;
203
+ //}
204
+ }
205
+
206
+ return INBOUND_Referer::createKnown($referer['medium'], $referer['source'], $searchTerm);
207
+ }
208
+
209
+ private static function parseUrl($url)
210
+ {
211
+ if ($url === null) {
212
+ return null;
213
+ }
214
+
215
+ $parts = parse_url($url);
216
+ if (!isset($parts['scheme']) || !in_array(strtolower($parts['scheme']), array('http', 'https'))) {
217
+ return null;
218
+ }
219
+
220
+ return array_merge(array('query' => null, 'path' => '/'), $parts);
221
+ }
222
+
223
+ private function lookup($host, $path)
224
+ {
225
+ $referer = $this->lookupPath($host, $path);
226
+
227
+ if ($referer) {
228
+ return $referer;
229
+ }
230
+
231
+ return $this->lookupHost($host);
232
+ }
233
+
234
+ private function lookupPath($host, $path)
235
+ {
236
+ $referer = $this->lookupHost($host, $path);
237
+
238
+ if ($referer) {
239
+ return $referer;
240
+ }
241
+
242
+ $path = substr($path, 0, strrpos($path, '/'));
243
+
244
+ if (!$path) {
245
+ return null;
246
+ }
247
+
248
+ return $this->lookupPath($host, $path);
249
+ }
250
+
251
+ private function lookupHost($host, $path = null)
252
+ {
253
+ do {
254
+ $referer = $this->configReader->lookup($host . $path);
255
+ $host = substr($host, strpos($host, '.') + 1);
256
+ } while (!$referer && substr_count($host, '.') > 0);
257
+
258
+ return $referer;
259
+ }
260
+
261
+ private static function createDefaultConfigReader()
262
+ {
263
+ //TODO FIX WITH GLOBAL SHARED CONSTANT
264
+ return new INBOUND_JsonConfigReader(WP_CTA_PATH . 'shared/tracking/sources/referers.json');
265
+ }
266
+ }
shared/tracking/sources/Snowplow/RefererParser/INBOUND_Referer.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class INBOUND_Referer
4
+ {
5
+ /** @var string */
6
+ private $medium;
7
+
8
+ /** @var string */
9
+ private $source;
10
+
11
+ /** @var string|null */
12
+ private $searchTerm;
13
+
14
+ private function __construct()
15
+ {}
16
+
17
+ public static function createKnown($medium, $source, $searchTerm = null)
18
+ {
19
+ $referer = new self();
20
+ $referer->medium = $medium;
21
+ $referer->source = $source;
22
+ $referer->searchTerm = $searchTerm;
23
+
24
+ return $referer;
25
+ }
26
+
27
+ public static function createUnknown()
28
+ {
29
+ $referer = new self();
30
+ $referer->medium = INBOUND_Medium::UNKNOWN;
31
+
32
+ return $referer;
33
+ }
34
+
35
+ public static function createInternal()
36
+ {
37
+ $referer = new self();
38
+ $referer->medium = INBOUND_Medium::INTERNAL;
39
+
40
+ return $referer;
41
+ }
42
+
43
+ public static function createInvalid()
44
+ {
45
+ $referer = new self();
46
+ $referer->medium = INBOUND_Medium::INVALID;
47
+
48
+ return $referer;
49
+ }
50
+
51
+ /** @return boolean */
52
+ public function isValid()
53
+ {
54
+ return $this->medium !== INBOUND_Medium::INVALID;
55
+ }
56
+
57
+ /** @return boolean */
58
+ public function isKnown()
59
+ {
60
+ return !in_array($this->medium, array(INBOUND_Medium::UNKNOWN, INBOUND_Medium::INTERNAL, INBOUND_Medium::INVALID), true);
61
+ }
62
+
63
+ /** @return string */
64
+ public function getMedium()
65
+ {
66
+ return $this->medium;
67
+ }
68
+
69
+ public function getSource()
70
+ {
71
+ return $this->source;
72
+ }
73
+
74
+ public function getSearchTerm()
75
+ {
76
+ return $this->searchTerm;
77
+ }
78
+ }
shared/tracking/sources/referers.json ADDED
@@ -0,0 +1,3890 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "unknown": {
3
+ "Google": {
4
+ "domains": [
5
+ "support.google.com",
6
+ "developers.google.com",
7
+ "maps.google.com",
8
+ "accounts.google.com",
9
+ "drive.google.com",
10
+ "sites.google.com",
11
+ "groups.google.com",
12
+ "groups.google.co.uk",
13
+ "news.google.co.uk"
14
+ ]
15
+ },
16
+ "Yahoo!": {
17
+ "domains": [
18
+ "finance.yahoo.com",
19
+ "news.yahoo.com",
20
+ "eurosport.yahoo.com",
21
+ "sports.yahoo.com",
22
+ "astrology.yahoo.com",
23
+ "travel.yahoo.com",
24
+ "answers.yahoo.com",
25
+ "screen.yahoo.com",
26
+ "weather.yahoo.com",
27
+ "messenger.yahoo.com",
28
+ "games.yahoo.com",
29
+ "shopping.yahoo.net",
30
+ "movies.yahoo.com",
31
+ "cars.yahoo.com",
32
+ "lifestyle.yahoo.com",
33
+ "omg.yahoo.com",
34
+ "match.yahoo.net"
35
+ ]
36
+ }
37
+ },
38
+ "search": {
39
+ "TalkTalk": {
40
+ "domains": [
41
+ "www.talktalk.co.uk"
42
+ ],
43
+ "parameters": [
44
+ "query"
45
+ ]
46
+ },
47
+ "1.cz": {
48
+ "domains": [
49
+ "1.cz"
50
+ ],
51
+ "parameters": [
52
+ "q"
53
+ ]
54
+ },
55
+ "Softonic": {
56
+ "domains": [
57
+ "search.softonic.com"
58
+ ],
59
+ "parameters": [
60
+ "q"
61
+ ]
62
+ },
63
+ "GAIS": {
64
+ "domains": [
65
+ "gais.cs.ccu.edu.tw"
66
+ ],
67
+ "parameters": [
68
+ "q"
69
+ ]
70
+ },
71
+ "Freecause": {
72
+ "domains": [
73
+ "search.freecause.com"
74
+ ],
75
+ "parameters": [
76
+ "p"
77
+ ]
78
+ },
79
+ "RPMFind": {
80
+ "domains": [
81
+ "rpmfind.net",
82
+ "fr2.rpmfind.net"
83
+ ],
84
+ "parameters": [
85
+ "rpmfind.net",
86
+ "fr2.rpmfind.net"
87
+ ]
88
+ },
89
+ "Comcast": {
90
+ "domains": [
91
+ "serach.comcast.net"
92
+ ],
93
+ "parameters": [
94
+ "q"
95
+ ]
96
+ },
97
+ "Voila": {
98
+ "domains": [
99
+ "search.ke.voila.fr",
100
+ "www.lemoteur.fr"
101
+ ],
102
+ "parameters": [
103
+ "rdata"
104
+ ]
105
+ },
106
+ "Nifty": {
107
+ "domains": [
108
+ "search.nifty.com"
109
+ ],
110
+ "parameters": [
111
+ "q"
112
+ ]
113
+ },
114
+ "Atlas": {
115
+ "domains": [
116
+ "searchatlas.centrum.cz"
117
+ ],
118
+ "parameters": [
119
+ "q"
120
+ ]
121
+ },
122
+ "Lo.st": {
123
+ "domains": [
124
+ "lo.st"
125
+ ],
126
+ "parameters": [
127
+ "x_query"
128
+ ]
129
+ },
130
+ "DasTelefonbuch": {
131
+ "domains": [
132
+ "www1.dastelefonbuch.de"
133
+ ],
134
+ "parameters": [
135
+ "kw"
136
+ ]
137
+ },
138
+ "Fireball": {
139
+ "domains": [
140
+ "www.fireball.de"
141
+ ],
142
+ "parameters": [
143
+ "q"
144
+ ]
145
+ },
146
+ "1und1": {
147
+ "domains": [
148
+ "search.1und1.de"
149
+ ],
150
+ "parameters": [
151
+ "su"
152
+ ]
153
+ },
154
+ "Virgilio": {
155
+ "domains": [
156
+ "ricerca.virgilio.it",
157
+ "ricercaimmagini.virgilio.it",
158
+ "ricercavideo.virgilio.it",
159
+ "ricercanews.virgilio.it",
160
+ "mobile.virgilio.it"
161
+ ],
162
+ "parameters": [
163
+ "qs"
164
+ ]
165
+ },
166
+ "Web.nl": {
167
+ "domains": [
168
+ "www.web.nl"
169
+ ],
170
+ "parameters": [
171
+ "zoekwoord"
172
+ ]
173
+ },
174
+ "Plazoo": {
175
+ "domains": [
176
+ "www.plazoo.com"
177
+ ],
178
+ "parameters": [
179
+ "q"
180
+ ]
181
+ },
182
+ "Goyellow.de": {
183
+ "domains": [
184
+ "www.goyellow.de"
185
+ ],
186
+ "parameters": [
187
+ "MDN"
188
+ ]
189
+ },
190
+ "AOL": {
191
+ "domains": [
192
+ "search.aol.com",
193
+ "search.aol.it",
194
+ "aolsearch.aol.com",
195
+ "aolsearch.com",
196
+ "www.aolrecherche.aol.fr",
197
+ "www.aolrecherches.aol.fr",
198
+ "www.aolimages.aol.fr",
199
+ "aim.search.aol.com",
200
+ "www.recherche.aol.fr",
201
+ "find.web.aol.com",
202
+ "recherche.aol.ca",
203
+ "aolsearch.aol.co.uk",
204
+ "search.aol.co.uk",
205
+ "aolrecherche.aol.fr",
206
+ "sucheaol.aol.de",
207
+ "suche.aol.de",
208
+ "suche.aolsvc.de",
209
+ "aolbusqueda.aol.com.mx",
210
+ "alicesuche.aol.de",
211
+ "alicesuchet.aol.de",
212
+ "suchet2.aol.de",
213
+ "search.hp.my.aol.com.au",
214
+ "search.hp.my.aol.de",
215
+ "search.hp.my.aol.it",
216
+ "search-intl.netscape.com"
217
+ ],
218
+ "parameters": [
219
+ "q",
220
+ "query"
221
+ ]
222
+ },
223
+ "Acoon": {
224
+ "domains": [
225
+ "www.acoon.de"
226
+ ],
227
+ "parameters": [
228
+ "begriff"
229
+ ]
230
+ },
231
+ "Free": {
232
+ "domains": [
233
+ "search.free.fr",
234
+ "search1-2.free.fr",
235
+ "search1-1.free.fr"
236
+ ],
237
+ "parameters": [
238
+ "q"
239
+ ]
240
+ },
241
+ "Apollo Latvia": {
242
+ "domains": [
243
+ "apollo.lv/portal/search/"
244
+ ],
245
+ "parameters": [
246
+ "q"
247
+ ]
248
+ },
249
+ "HighBeam": {
250
+ "domains": [
251
+ "www.highbeam.com"
252
+ ],
253
+ "parameters": [
254
+ "q"
255
+ ]
256
+ },
257
+ "I-play": {
258
+ "domains": [
259
+ "start.iplay.com"
260
+ ],
261
+ "parameters": [
262
+ "q"
263
+ ]
264
+ },
265
+ "FriendFeed": {
266
+ "domains": [
267
+ "friendfeed.com"
268
+ ],
269
+ "parameters": [
270
+ "q"
271
+ ]
272
+ },
273
+ "Yasni": {
274
+ "domains": [
275
+ "www.yasni.de",
276
+ "www.yasni.com",
277
+ "www.yasni.co.uk",
278
+ "www.yasni.ch",
279
+ "www.yasni.at"
280
+ ],
281
+ "parameters": [
282
+ "query"
283
+ ]
284
+ },
285
+ "Gigablast": {
286
+ "domains": [
287
+ "www.gigablast.com",
288
+ "dir.gigablast.com"
289
+ ],
290
+ "parameters": [
291
+ "q"
292
+ ]
293
+ },
294
+ "arama": {
295
+ "domains": [
296
+ "arama.com"
297
+ ],
298
+ "parameters": [
299
+ "q"
300
+ ]
301
+ },
302
+ "Fixsuche": {
303
+ "domains": [
304
+ "www.fixsuche.de"
305
+ ],
306
+ "parameters": [
307
+ "q"
308
+ ]
309
+ },
310
+ "Apontador": {
311
+ "domains": [
312
+ "apontador.com.br",
313
+ "www.apontador.com.br"
314
+ ],
315
+ "parameters": [
316
+ "q"
317
+ ]
318
+ },
319
+ "Search.com": {
320
+ "domains": [
321
+ "www.search.com"
322
+ ],
323
+ "parameters": [
324
+ "q"
325
+ ]
326
+ },
327
+ "Monstercrawler": {
328
+ "domains": [
329
+ "www.monstercrawler.com"
330
+ ],
331
+ "parameters": [
332
+ "qry"
333
+ ]
334
+ },
335
+ "Google Images": {
336
+ "domains": [
337
+ "google.ac/imgres",
338
+ "google.ad/imgres",
339
+ "google.ae/imgres",
340
+ "google.am/imgres",
341
+ "google.as/imgres",
342
+ "google.at/imgres",
343
+ "google.az/imgres",
344
+ "google.ba/imgres",
345
+ "google.be/imgres",
346
+ "google.bf/imgres",
347
+ "google.bg/imgres",
348
+ "google.bi/imgres",
349
+ "google.bj/imgres",
350
+ "google.bs/imgres",
351
+ "google.by/imgres",
352
+ "google.ca/imgres",
353
+ "google.cat/imgres",
354
+ "google.cc/imgres",
355
+ "google.cd/imgres",
356
+ "google.cf/imgres",
357
+ "google.cg/imgres",
358
+ "google.ch/imgres",
359
+ "google.ci/imgres",
360
+ "google.cl/imgres",
361
+ "google.cm/imgres",
362
+ "google.cn/imgres",
363
+ "google.co.bw/imgres",
364
+ "google.co.ck/imgres",
365
+ "google.co.cr/imgres",
366
+ "google.co.id/imgres",
367
+ "google.co.il/imgres",
368
+ "google.co.in/imgres",
369
+ "google.co.jp/imgres",
370
+ "google.co.ke/imgres",
371
+ "google.co.kr/imgres",
372
+ "google.co.ls/imgres",
373
+ "google.co.ma/imgres",
374
+ "google.co.mz/imgres",
375
+ "google.co.nz/imgres",
376
+ "google.co.th/imgres",
377
+ "google.co.tz/imgres",
378
+ "google.co.ug/imgres",
379
+ "google.co.uk/imgres",
380
+ "google.co.uz/imgres",
381
+ "google.co.ve/imgres",
382
+ "google.co.vi/imgres",
383
+ "google.co.za/imgres",
384
+ "google.co.zm/imgres",
385
+ "google.co.zw/imgres",
386
+ "google.com/imgres",
387
+ "google.com.af/imgres",
388
+ "google.com.ag/imgres",
389
+ "google.com.ai/imgres",
390
+ "google.com.ar/imgres",
391
+ "google.com.au/imgres",
392
+ "google.com.bd/imgres",
393
+ "google.com.bh/imgres",
394
+ "google.com.bn/imgres",
395
+ "google.com.bo/imgres",
396
+ "google.com.br/imgres",
397
+ "google.com.by/imgres",
398
+ "google.com.bz/imgres",
399
+ "google.com.co/imgres",
400
+ "google.com.cu/imgres",
401
+ "google.com.cy/imgres",
402
+ "google.com.do/imgres",
403
+ "google.com.ec/imgres",
404
+ "google.com.eg/imgres",
405
+ "google.com.et/imgres",
406
+ "google.com.fj/imgres",
407
+ "google.com.gh/imgres",
408
+ "google.com.gi/imgres",
409
+ "google.com.gt/imgres",
410
+ "google.com.hk/imgres",
411
+ "google.com.jm/imgres",
412
+ "google.com.kh/imgres",
413
+ "google.com.kh/imgres",
414
+ "google.com.kw/imgres",
415
+ "google.com.lb/imgres",
416
+ "google.com.lc/imgres",
417
+ "google.com.ly/imgres",
418
+ "google.com.mt/imgres",
419
+ "google.com.mx/imgres",
420
+ "google.com.my/imgres",
421
+ "google.com.na/imgres",
422
+ "google.com.nf/imgres",
423
+ "google.com.ng/imgres",
424
+ "google.com.ni/imgres",
425
+ "google.com.np/imgres",
426
+ "google.com.om/imgres",
427
+ "google.com.pa/imgres",
428
+ "google.com.pe/imgres",
429
+ "google.com.ph/imgres",
430
+ "google.com.pk/imgres",
431
+ "google.com.pr/imgres",
432
+ "google.com.py/imgres",
433
+ "google.com.qa/imgres",
434
+ "google.com.sa/imgres",
435
+ "google.com.sb/imgres",
436
+ "google.com.sg/imgres",
437
+ "google.com.sl/imgres",
438
+ "google.com.sv/imgres",
439
+ "google.com.tj/imgres",
440
+ "google.com.tn/imgres",
441
+ "google.com.tr/imgres",
442
+ "google.com.tw/imgres",
443
+ "google.com.ua/imgres",
444
+ "google.com.uy/imgres",
445
+ "google.com.vc/imgres",
446
+ "google.com.vn/imgres",
447
+ "google.cv/imgres",
448
+ "google.cz/imgres",
449
+ "google.de/imgres",
450
+ "google.dj/imgres",
451
+ "google.dk/imgres",
452
+ "google.dm/imgres",
453
+ "google.dz/imgres",
454
+ "google.ee/imgres",
455
+ "google.es/imgres",
456
+ "google.fi/imgres",
457
+ "google.fm/imgres",
458
+ "google.fr/imgres",
459
+ "google.ga/imgres",
460
+ "google.gd/imgres",
461
+ "google.ge/imgres",
462
+ "google.gf/imgres",
463
+ "google.gg/imgres",
464
+ "google.gl/imgres",
465
+ "google.gm/imgres",
466
+ "google.gp/imgres",
467
+ "google.gr/imgres",
468
+ "google.gy/imgres",
469
+ "google.hn/imgres",
470
+ "google.hr/imgres",
471
+ "google.ht/imgres",
472
+ "google.hu/imgres",
473
+ "google.ie/imgres",
474
+ "google.im/imgres",
475
+ "google.io/imgres",
476
+ "google.iq/imgres",
477
+ "google.is/imgres",
478
+ "google.it/imgres",
479
+ "google.it.ao/imgres",
480
+ "google.je/imgres",
481
+ "google.jo/imgres",
482
+ "google.kg/imgres",
483
+ "google.ki/imgres",
484
+ "google.kz/imgres",
485
+ "google.la/imgres",
486
+ "google.li/imgres",
487
+ "google.lk/imgres",
488
+ "google.lt/imgres",
489
+ "google.lu/imgres",
490
+ "google.lv/imgres",
491
+ "google.md/imgres",
492
+ "google.me/imgres",
493
+ "google.mg/imgres",
494
+ "google.mk/imgres",
495
+ "google.ml/imgres",
496
+ "google.mn/imgres",
497
+ "google.ms/imgres",
498
+ "google.mu/imgres",
499
+ "google.mv/imgres",
500
+ "google.mw/imgres",
501
+ "google.ne/imgres",
502
+ "google.nl/imgres",
503
+ "google.no/imgres",
504
+ "google.nr/imgres",
505
+ "google.nu/imgres",
506
+ "google.pl/imgres",
507
+ "google.pn/imgres",
508
+ "google.ps/imgres",
509
+ "google.pt/imgres",
510
+ "google.ro/imgres",
511
+ "google.rs/imgres",
512
+ "google.ru/imgres",
513
+ "google.rw/imgres",
514
+ "google.sc/imgres",
515
+ "google.se/imgres",
516
+ "google.sh/imgres",
517
+ "google.si/imgres",
518
+ "google.sk/imgres",
519
+ "google.sm/imgres",
520
+ "google.sn/imgres",
521
+ "google.so/imgres",
522
+ "google.st/imgres",
523
+ "google.td/imgres",
524
+ "google.tg/imgres",
525
+ "google.tk/imgres",
526
+ "google.tl/imgres",
527
+ "google.tm/imgres",
528
+ "google.to/imgres",
529
+ "google.tt/imgres",
530
+ "google.us/imgres",
531
+ "google.vg/imgres",
532
+ "google.vu/imgres",
533
+ "images.google.ws",
534
+ "images.google.ac",
535
+ "images.google.ad",
536
+ "images.google.ae",
537
+ "images.google.am",
538
+ "images.google.as",
539
+ "images.google.at",
540
+ "images.google.az",
541
+ "images.google.ba",
542
+ "images.google.be",
543
+ "images.google.bf",
544
+ "images.google.bg",
545
+ "images.google.bi",
546
+ "images.google.bj",
547
+ "images.google.bs",
548
+ "images.google.by",
549
+ "images.google.ca",
550
+ "images.google.cat",
551
+ "images.google.cc",
552
+ "images.google.cd",
553
+ "images.google.cf",
554
+ "images.google.cg",
555
+ "images.google.ch",
556
+ "images.google.ci",
557
+ "images.google.cl",
558
+ "images.google.cm",
559
+ "images.google.cn",
560
+ "images.google.co.bw",
561
+ "images.google.co.ck",
562
+ "images.google.co.cr",
563
+ "images.google.co.id",
564
+ "images.google.co.il",
565
+ "images.google.co.in",
566
+ "images.google.co.jp",
567
+ "images.google.co.ke",
568
+ "images.google.co.kr",
569
+ "images.google.co.ls",
570
+ "images.google.co.ma",
571
+ "images.google.co.mz",
572
+ "images.google.co.nz",
573
+ "images.google.co.th",
574
+ "images.google.co.tz",
575
+ "images.google.co.ug",
576
+ "images.google.co.uk",
577
+ "images.google.co.uz",
578
+ "images.google.co.ve",
579
+ "images.google.co.vi",
580
+ "images.google.co.za",
581
+ "images.google.co.zm",
582
+ "images.google.co.zw",
583
+ "images.google.com",
584
+ "images.google.com.af",
585
+ "images.google.com.ag",
586
+ "images.google.com.ai",
587
+ "images.google.com.ar",
588
+ "images.google.com.au",
589
+ "images.google.com.bd",
590
+ "images.google.com.bh",
591
+ "images.google.com.bn",
592
+ "images.google.com.bo",
593
+ "images.google.com.br",
594
+ "images.google.com.by",
595
+ "images.google.com.bz",
596
+ "images.google.com.co",
597
+ "images.google.com.cu",
598
+ "images.google.com.cy",
599
+ "images.google.com.do",
600
+ "images.google.com.ec",
601
+ "images.google.com.eg",
602
+ "images.google.com.et",
603
+ "images.google.com.fj",
604
+ "images.google.com.gh",
605
+ "images.google.com.gi",
606
+ "images.google.com.gt",
607
+ "images.google.com.hk",
608
+ "images.google.com.jm",
609
+ "images.google.com.kh",
610
+ "images.google.com.kh",
611
+ "images.google.com.kw",
612
+ "images.google.com.lb",
613
+ "images.google.com.lc",
614
+ "images.google.com.ly",
615
+ "images.google.com.mt",
616
+ "images.google.com.mx",
617
+ "images.google.com.my",
618
+ "images.google.com.na",
619
+ "images.google.com.nf",
620
+ "images.google.com.ng",
621
+ "images.google.com.ni",
622
+ "images.google.com.np",
623
+ "images.google.com.om",
624
+ "images.google.com.pa",
625
+ "images.google.com.pe",
626
+ "images.google.com.ph",
627
+ "images.google.com.pk",
628
+ "images.google.com.pr",
629
+ "images.google.com.py",
630
+ "images.google.com.qa",
631
+ "images.google.com.sa",
632
+ "images.google.com.sb",
633
+ "images.google.com.sg",
634
+ "images.google.com.sl",
635
+ "images.google.com.sv",
636
+ "images.google.com.tj",
637
+ "images.google.com.tn",
638
+ "images.google.com.tr",
639
+ "images.google.com.tw",
640
+ "images.google.com.ua",
641
+ "images.google.com.uy",
642
+ "images.google.com.vc",
643
+ "images.google.com.vn",
644
+ "images.google.cv",
645
+ "images.google.cz",
646
+ "images.google.de",
647
+ "images.google.dj",
648
+ "images.google.dk",
649
+ "images.google.dm",
650
+ "images.google.dz",
651
+ "images.google.ee",
652
+ "images.google.es",
653
+ "images.google.fi",
654
+ "images.google.fm",
655
+ "images.google.fr",
656
+ "images.google.ga",
657
+ "images.google.gd",
658
+ "images.google.ge",
659
+ "images.google.gf",
660
+ "images.google.gg",
661
+ "images.google.gl",
662
+ "images.google.gm",
663
+ "images.google.gp",
664
+ "images.google.gr",
665
+ "images.google.gy",
666
+ "images.google.hn",
667
+ "images.google.hr",
668
+ "images.google.ht",
669
+ "images.google.hu",
670
+ "images.google.ie",
671
+ "images.google.im",
672
+ "images.google.io",
673
+ "images.google.iq",
674
+ "images.google.is",
675
+ "images.google.it",
676
+ "images.google.it.ao",
677
+ "images.google.je",
678
+ "images.google.jo",
679
+ "images.google.kg",
680
+ "images.google.ki",
681
+ "images.google.kz",
682
+ "images.google.la",
683
+ "images.google.li",
684
+ "images.google.lk",
685
+ "images.google.lt",
686
+ "images.google.lu",
687
+ "images.google.lv",
688
+ "images.google.md",
689
+ "images.google.me",
690
+ "images.google.mg",
691
+ "images.google.mk",
692
+ "images.google.ml",
693
+ "images.google.mn",
694
+ "images.google.ms",
695
+ "images.google.mu",
696
+ "images.google.mv",
697
+ "images.google.mw",
698
+ "images.google.ne",
699
+ "images.google.nl",
700
+ "images.google.no",
701
+ "images.google.nr",
702
+ "images.google.nu",
703
+ "images.google.pl",
704
+ "images.google.pn",
705
+ "images.google.ps",
706
+ "images.google.pt",
707
+ "images.google.ro",
708
+ "images.google.rs",
709
+ "images.google.ru",
710
+ "images.google.rw",
711
+ "images.google.sc",
712
+ "images.google.se",
713
+ "images.google.sh",
714
+ "images.google.si",
715
+ "images.google.sk",
716
+ "images.google.sm",
717
+ "images.google.sn",
718
+ "images.google.so",
719
+ "images.google.st",
720
+ "images.google.td",
721
+ "images.google.tg",
722
+ "images.google.tk",
723
+ "images.google.tl",
724
+ "images.google.tm",
725
+ "images.google.to",
726
+ "images.google.tt",
727
+ "images.google.us",
728
+ "images.google.vg",
729
+ "images.google.vu",
730
+ "images.google.ws"
731
+ ],
732
+ "parameters": [
733
+ "q"
734
+ ]
735
+ },
736
+ "ABCs\u00f8k": {
737
+ "domains": [
738
+ "abcsolk.no",
739
+ "verden.abcsok.no"
740
+ ],
741
+ "parameters": [
742
+ "q"
743
+ ]
744
+ },
745
+ "Google Product Search": {
746
+ "domains": [
747
+ "google.ac/products",
748
+ "google.ad/products",
749
+ "google.ae/products",
750
+ "google.am/products",
751
+ "google.as/products",
752
+ "google.at/products",
753
+ "google.az/products",
754
+ "google.ba/products",
755
+ "google.be/products",
756
+ "google.bf/products",
757
+ "google.bg/products",
758
+ "google.bi/products",
759
+ "google.bj/products",
760
+ "google.bs/products",
761
+ "google.by/products",
762
+ "google.ca/products",
763
+ "google.cat/products",
764
+ "google.cc/products",
765
+ "google.cd/products",
766
+ "google.cf/products",
767
+ "google.cg/products",
768
+ "google.ch/products",
769
+ "google.ci/products",
770
+ "google.cl/products",
771
+ "google.cm/products",
772
+ "google.cn/products",
773
+ "google.co.bw/products",
774
+ "google.co.ck/products",
775
+ "google.co.cr/products",
776
+ "google.co.id/products",
777
+ "google.co.il/products",
778
+ "google.co.in/products",
779
+ "google.co.jp/products",
780
+ "google.co.ke/products",
781
+ "google.co.kr/products",
782
+ "google.co.ls/products",
783
+ "google.co.ma/products",
784
+ "google.co.mz/products",
785
+ "google.co.nz/products",
786
+ "google.co.th/products",
787
+ "google.co.tz/products",
788
+ "google.co.ug/products",
789
+ "google.co.uk/products",
790
+ "google.co.uz/products",
791
+ "google.co.ve/products",
792
+ "google.co.vi/products",
793
+ "google.co.za/products",
794
+ "google.co.zm/products",
795
+ "google.co.zw/products",
796
+ "google.com/products",
797
+ "google.com.af/products",
798
+ "google.com.ag/products",
799
+ "google.com.ai/products",
800
+ "google.com.ar/products",
801
+ "google.com.au/products",
802
+ "google.com.bd/products",
803
+ "google.com.bh/products",
804
+ "google.com.bn/products",
805
+ "google.com.bo/products",
806
+ "google.com.br/products",
807
+ "google.com.by/products",
808
+ "google.com.bz/products",
809
+ "google.com.co/products",
810
+ "google.com.cu/products",
811
+ "google.com.cy/products",
812
+ "google.com.do/products",
813
+ "google.com.ec/products",
814
+ "google.com.eg/products",
815
+ "google.com.et/products",
816
+ "google.com.fj/products",
817
+ "google.com.gh/products",
818
+ "google.com.gi/products",
819
+ "google.com.gt/products",
820
+ "google.com.hk/products",
821
+ "google.com.jm/products",
822
+ "google.com.kh/products",
823
+ "google.com.kh/products",
824
+ "google.com.kw/products",
825
+ "google.com.lb/products",
826
+ "google.com.lc/products",
827
+ "google.com.ly/products",
828
+ "google.com.mt/products",
829
+ "google.com.mx/products",
830
+ "google.com.my/products",
831
+ "google.com.na/products",
832
+ "google.com.nf/products",
833
+ "google.com.ng/products",
834
+ "google.com.ni/products",
835
+ "google.com.np/products",
836
+ "google.com.om/products",
837
+ "google.com.pa/products",
838
+ "google.com.pe/products",
839
+ "google.com.ph/products",
840
+ "google.com.pk/products",
841
+ "google.com.pr/products",
842
+ "google.com.py/products",
843
+ "google.com.qa/products",
844
+ "google.com.sa/products",
845
+ "google.com.sb/products",
846
+ "google.com.sg/products",
847
+ "google.com.sl/products",
848
+ "google.com.sv/products",
849
+ "google.com.tj/products",
850
+ "google.com.tn/products",
851
+ "google.com.tr/products",
852
+ "google.com.tw/products",
853
+ "google.com.ua/products",
854
+ "google.com.uy/products",
855
+ "google.com.vc/products",
856
+ "google.com.vn/products",
857
+ "google.cv/products",
858
+ "google.cz/products",
859
+ "google.de/products",
860
+ "google.dj/products",
861
+ "google.dk/products",
862
+ "google.dm/products",
863
+ "google.dz/products",
864
+ "google.ee/products",
865
+ "google.es/products",
866
+ "google.fi/products",
867
+ "google.fm/products",
868
+ "google.fr/products",
869
+ "google.ga/products",
870
+ "google.gd/products",
871
+ "google.ge/products",
872
+ "google.gf/products",
873
+ "google.gg/products",
874
+ "google.gl/products",
875
+ "google.gm/products",
876
+ "google.gp/products",
877
+ "google.gr/products",
878
+ "google.gy/products",
879
+ "google.hn/products",
880
+ "google.hr/products",
881
+ "google.ht/products",
882
+ "google.hu/products",
883
+ "google.ie/products",
884
+ "google.im/products",
885
+ "google.io/products",
886
+ "google.iq/products",
887
+ "google.is/products",
888
+ "google.it/products",
889
+ "google.it.ao/products",
890
+ "google.je/products",
891
+ "google.jo/products",
892
+ "google.kg/products",
893
+ "google.ki/products",
894
+ "google.kz/products",
895
+ "google.la/products",
896
+ "google.li/products",
897
+ "google.lk/products",
898
+ "google.lt/products",
899
+ "google.lu/products",
900
+ "google.lv/products",
901
+ "google.md/products",
902
+ "google.me/products",
903
+ "google.mg/products",
904
+ "google.mk/products",
905
+ "google.ml/products",
906
+ "google.mn/products",
907
+ "google.ms/products",
908
+ "google.mu/products",
909
+ "google.mv/products",
910
+ "google.mw/products",
911
+ "google.ne/products",
912
+ "google.nl/products",
913
+ "google.no/products",
914
+ "google.nr/products",
915
+ "google.nu/products",
916
+ "google.pl/products",
917
+ "google.pn/products",
918
+ "google.ps/products",
919
+ "google.pt/products",
920
+ "google.ro/products",
921
+ "google.rs/products",
922
+ "google.ru/products",
923
+ "google.rw/products",
924
+ "google.sc/products",
925
+ "google.se/products",
926
+ "google.sh/products",
927
+ "google.si/products",
928
+ "google.sk/products",
929
+ "google.sm/products",
930
+ "google.sn/products",
931
+ "google.so/products",
932
+ "google.st/products",
933
+ "google.td/products",
934
+ "google.tg/products",
935
+ "google.tk/products",
936
+ "google.tl/products",
937
+ "google.tm/products",
938
+ "google.to/products",
939
+ "google.tt/products",
940
+ "google.us/products",
941
+ "google.vg/products",
942
+ "google.vu/products",
943
+ "google.ws/products",
944
+ "www.google.ac/products",
945
+ "www.google.ad/products",
946
+ "www.google.ae/products",
947
+ "www.google.am/products",
948
+ "www.google.as/products",
949
+ "www.google.at/products",
950
+ "www.google.az/products",
951
+ "www.google.ba/products",
952
+ "www.google.be/products",
953
+ "www.google.bf/products",
954
+ "www.google.bg/products",
955
+ "www.google.bi/products",
956
+ "www.google.bj/products",
957
+ "www.google.bs/products",
958
+ "www.google.by/products",
959
+ "www.google.ca/products",
960
+ "www.google.cat/products",
961
+ "www.google.cc/products",
962
+ "www.google.cd/products",
963
+ "www.google.cf/products",
964
+ "www.google.cg/products",
965
+ "www.google.ch/products",
966
+ "www.google.ci/products",
967
+ "www.google.cl/products",
968
+ "www.google.cm/products",
969
+ "www.google.cn/products",
970
+ "www.google.co.bw/products",
971
+ "www.google.co.ck/products",
972
+ "www.google.co.cr/products",
973
+ "www.google.co.id/products",
974
+ "www.google.co.il/products",
975
+ "www.google.co.in/products",
976
+ "www.google.co.jp/products",
977
+ "www.google.co.ke/products",
978
+ "www.google.co.kr/products",
979
+ "www.google.co.ls/products",
980
+ "www.google.co.ma/products",
981
+ "www.google.co.mz/products",
982
+ "www.google.co.nz/products",
983
+ "www.google.co.th/products",
984
+ "www.google.co.tz/products",
985
+ "www.google.co.ug/products",
986
+ "www.google.co.uk/products",
987
+ "www.google.co.uz/products",
988
+ "www.google.co.ve/products",
989
+ "www.google.co.vi/products",
990
+ "www.google.co.za/products",
991
+ "www.google.co.zm/products",
992
+ "www.google.co.zw/products",
993
+ "www.google.com/products",
994
+ "www.google.com.af/products",
995
+ "www.google.com.ag/products",
996
+ "www.google.com.ai/products",
997
+ "www.google.com.ar/products",
998
+ "www.google.com.au/products",
999
+ "www.google.com.bd/products",
1000
+ "www.google.com.bh/products",
1001
+ "www.google.com.bn/products",
1002
+ "www.google.com.bo/products",
1003
+ "www.google.com.br/products",
1004
+ "www.google.com.by/products",
1005
+ "www.google.com.bz/products",
1006
+ "www.google.com.co/products",
1007
+ "www.google.com.cu/products",
1008
+ "www.google.com.cy/products",
1009
+ "www.google.com.do/products",
1010
+ "www.google.com.ec/products",
1011
+ "www.google.com.eg/products",
1012
+ "www.google.com.et/products",
1013
+ "www.google.com.fj/products",
1014
+ "www.google.com.gh/products",
1015
+ "www.google.com.gi/products",
1016
+ "www.google.com.gt/products",
1017
+ "www.google.com.hk/products",
1018
+ "www.google.com.jm/products",
1019
+ "www.google.com.kh/products",
1020
+ "www.google.com.kh/products",
1021
+ "www.google.com.kw/products",
1022
+ "www.google.com.lb/products",
1023
+ "www.google.com.lc/products",
1024
+ "www.google.com.ly/products",
1025
+ "www.google.com.mt/products",
1026
+ "www.google.com.mx/products",
1027
+ "www.google.com.my/products",
1028
+ "www.google.com.na/products",
1029
+ "www.google.com.nf/products",
1030
+ "www.google.com.ng/products",
1031
+ "www.google.com.ni/products",
1032
+ "www.google.com.np/products",
1033
+ "www.google.com.om/products",
1034
+ "www.google.com.pa/products",
1035
+ "www.google.com.pe/products",
1036
+ "www.google.com.ph/products",
1037
+ "www.google.com.pk/products",
1038
+ "www.google.com.pr/products",
1039
+ "www.google.com.py/products",
1040
+ "www.google.com.qa/products",
1041
+ "www.google.com.sa/products",
1042
+ "www.google.com.sb/products",
1043
+ "www.google.com.sg/products",
1044
+ "www.google.com.sl/products",
1045
+ "www.google.com.sv/products",
1046
+ "www.google.com.tj/products",
1047
+ "www.google.com.tn/products",
1048
+ "www.google.com.tr/products",
1049
+ "www.google.com.tw/products",
1050
+ "www.google.com.ua/products",
1051
+ "www.google.com.uy/products",
1052
+ "www.google.com.vc/products",
1053
+ "www.google.com.vn/products",
1054
+ "www.google.cv/products",
1055
+ "www.google.cz/products",
1056
+ "www.google.de/products",
1057
+ "www.google.dj/products",
1058
+ "www.google.dk/products",
1059
+ "www.google.dm/products",
1060
+ "www.google.dz/products",
1061
+ "www.google.ee/products",
1062
+ "www.google.es/products",
1063
+ "www.google.fi/products",
1064
+ "www.google.fm/products",
1065
+ "www.google.fr/products",
1066
+ "www.google.ga/products",
1067
+ "www.google.gd/products",
1068
+ "www.google.ge/products",
1069
+ "www.google.gf/products",
1070
+ "www.google.gg/products",
1071
+ "www.google.gl/products",
1072
+ "www.google.gm/products",
1073
+ "www.google.gp/products",
1074
+ "www.google.gr/products",
1075
+ "www.google.gy/products",
1076
+ "www.google.hn/products",
1077
+ "www.google.hr/products",
1078
+ "www.google.ht/products",
1079
+ "www.google.hu/products",
1080
+ "www.google.ie/products",
1081
+ "www.google.im/products",
1082
+ "www.google.io/products",
1083
+ "www.google.iq/products",
1084
+ "www.google.is/products",
1085
+ "www.google.it/products",
1086
+ "www.google.it.ao/products",
1087
+ "www.google.je/products",
1088
+ "www.google.jo/products",
1089
+ "www.google.kg/products",
1090
+ "www.google.ki/products",
1091
+ "www.google.kz/products",
1092
+ "www.google.la/products",
1093
+ "www.google.li/products",
1094
+ "www.google.lk/products",
1095
+ "www.google.lt/products",
1096
+ "www.google.lu/products",
1097
+ "www.google.lv/products",
1098
+ "www.google.md/products",
1099
+ "www.google.me/products",
1100
+ "www.google.mg/products",
1101
+ "www.google.mk/products",
1102
+ "www.google.ml/products",
1103
+ "www.google.mn/products",
1104
+ "www.google.ms/products",
1105
+ "www.google.mu/products",
1106
+ "www.google.mv/products",
1107
+ "www.google.mw/products",
1108
+ "www.google.ne/products",
1109
+ "www.google.nl/products",
1110
+ "www.google.no/products",
1111
+ "www.google.nr/products",
1112
+ "www.google.nu/products",
1113
+ "www.google.pl/products",
1114
+ "www.google.pn/products",
1115
+ "www.google.ps/products",
1116
+ "www.google.pt/products",
1117
+ "www.google.ro/products",
1118
+ "www.google.rs/products",
1119
+ "www.google.ru/products",
1120
+ "www.google.rw/products",
1121
+ "www.google.sc/products",
1122
+ "www.google.se/products",
1123
+ "www.google.sh/products",
1124
+ "www.google.si/products",
1125
+ "www.google.sk/products",
1126
+ "www.google.sm/products",
1127
+ "www.google.sn/products",
1128
+ "www.google.so/products",
1129
+ "www.google.st/products",
1130
+ "www.google.td/products",
1131
+ "www.google.tg/products",
1132
+ "www.google.tk/products",
1133
+ "www.google.tl/products",
1134
+ "www.google.tm/products",
1135
+ "www.google.to/products",
1136
+ "www.google.tt/products",
1137
+ "www.google.us/products",
1138
+ "www.google.vg/products",
1139
+ "www.google.vu/products",
1140
+ "www.google.ws/products"
1141
+ ],
1142
+ "parameters": [
1143
+ "q"
1144
+ ]
1145
+ },
1146
+ "DasOertliche": {
1147
+ "domains": [
1148
+ "www.dasoertliche.de"
1149
+ ],
1150
+ "parameters": [
1151
+ "kw"
1152
+ ]
1153
+ },
1154
+ "InfoSpace": {
1155
+ "domains": [
1156
+ "infospace.com",
1157
+ "dogpile.com",
1158
+ "www.dogpile.com",
1159
+ "metacrawler.com",
1160
+ "webfetch.com",
1161
+ "webcrawler.com",
1162
+ "search.kiwee.com",
1163
+ "isearch.babylon.com",
1164
+ "start.facemoods.com",
1165
+ "search.magnetic.com",
1166
+ "search.searchcompletion.com",
1167
+ "clusty.com"
1168
+ ],
1169
+ "parameters": [
1170
+ "q",
1171
+ "s"
1172
+ ]
1173
+ },
1174
+ "Weborama": {
1175
+ "domains": [
1176
+ "www.weborama.com"
1177
+ ],
1178
+ "parameters": [
1179
+ "QUERY"
1180
+ ]
1181
+ },
1182
+ "Bluewin": {
1183
+ "domains": [
1184
+ "search.bluewin.ch"
1185
+ ],
1186
+ "parameters": [
1187
+ "searchTerm"
1188
+ ]
1189
+ },
1190
+ "Neti": {
1191
+ "domains": [
1192
+ "www.neti.ee"
1193
+ ],
1194
+ "parameters": [
1195
+ "query"
1196
+ ]
1197
+ },
1198
+ "Winamp": {
1199
+ "domains": [
1200
+ "search.winamp.com"
1201
+ ],
1202
+ "parameters": [
1203
+ "q"
1204
+ ]
1205
+ },
1206
+ "Nigma": {
1207
+ "domains": [
1208
+ "nigma.ru"
1209
+ ],
1210
+ "parameters": [
1211
+ "s"
1212
+ ]
1213
+ },
1214
+ "Yahoo! Images": {
1215
+ "domains": [
1216
+ "image.yahoo.cn",
1217
+ "images.search.yahoo.com"
1218
+ ],
1219
+ "parameters": [
1220
+ "p",
1221
+ "q"
1222
+ ]
1223
+ },
1224
+ "Exalead": {
1225
+ "domains": [
1226
+ "www.exalead.fr",
1227
+ "www.exalead.com"
1228
+ ],
1229
+ "parameters": [
1230
+ "q"
1231
+ ]
1232
+ },
1233
+ "Teoma": {
1234
+ "domains": [
1235
+ "www.teoma.com"
1236
+ ],
1237
+ "parameters": [
1238
+ "q"
1239
+ ]
1240
+ },
1241
+ "Needtofind": {
1242
+ "domains": [
1243
+ "ko.search.need2find.com"
1244
+ ],
1245
+ "parameters": [
1246
+ "searchfor"
1247
+ ]
1248
+ },
1249
+ "Looksmart": {
1250
+ "domains": [
1251
+ "www.looksmart.com"
1252
+ ],
1253
+ "parameters": [
1254
+ "key"
1255
+ ]
1256
+ },
1257
+ "Wirtualna Polska": {
1258
+ "domains": [
1259
+ "szukaj.wp.pl"
1260
+ ],
1261
+ "parameters": [
1262
+ "szukaj"
1263
+ ]
1264
+ },
1265
+ "Toolbarhome": {
1266
+ "domains": [
1267
+ "www.toolbarhome.com",
1268
+ "vshare.toolbarhome.com"
1269
+ ],
1270
+ "parameters": [
1271
+ "q"
1272
+ ]
1273
+ },
1274
+ "Searchalot": {
1275
+ "domains": [
1276
+ "searchalot.com"
1277
+ ],
1278
+ "parameters": [
1279
+ "q"
1280
+ ]
1281
+ },
1282
+ "Yandex": {
1283
+ "domains": [
1284
+ "yandex.ru",
1285
+ "yandex.ua",
1286
+ "yandex.com",
1287
+ "www.yandex.ru",
1288
+ "www.yandex.ua",
1289
+ "www.yandex.com"
1290
+ ],
1291
+ "parameters": [
1292
+ "text"
1293
+ ]
1294
+ },
1295
+ "canoe.ca": {
1296
+ "domains": [
1297
+ "web.canoe.ca"
1298
+ ],
1299
+ "parameters": [
1300
+ "q"
1301
+ ]
1302
+ },
1303
+ "Compuserve": {
1304
+ "domains": [
1305
+ "websearch.cs.com"
1306
+ ],
1307
+ "parameters": [
1308
+ "query"
1309
+ ]
1310
+ },
1311
+ "Startpagina": {
1312
+ "domains": [
1313
+ "startgoogle.startpagina.nl"
1314
+ ],
1315
+ "parameters": [
1316
+ "q"
1317
+ ]
1318
+ },
1319
+ "eo": {
1320
+ "domains": [
1321
+ "eo.st"
1322
+ ],
1323
+ "parameters": [
1324
+ "x_query"
1325
+ ]
1326
+ },
1327
+ "Zhongsou": {
1328
+ "domains": [
1329
+ "p.zhongsou.com"
1330
+ ],
1331
+ "parameters": [
1332
+ "w"
1333
+ ]
1334
+ },
1335
+ "La Toile Du Quebec Via Google": {
1336
+ "domains": [
1337
+ "www.toile.com",
1338
+ "web.toile.com"
1339
+ ],
1340
+ "parameters": [
1341
+ "q"
1342
+ ]
1343
+ },
1344
+ "Paperball": {
1345
+ "domains": [
1346
+ "www.paperball.de"
1347
+ ],
1348
+ "parameters": [
1349
+ "q"
1350
+ ]
1351
+ },
1352
+ "Jungle Spider": {
1353
+ "domains": [
1354
+ "www.jungle-spider.de"
1355
+ ],
1356
+ "parameters": [
1357
+ "q"
1358
+ ]
1359
+ },
1360
+ "PeoplePC": {
1361
+ "domains": [
1362
+ "search.peoplepc.com"
1363
+ ],
1364
+ "parameters": [
1365
+ "q"
1366
+ ]
1367
+ },
1368
+ "MetaCrawler.de": {
1369
+ "domains": [
1370
+ "s1.metacrawler.de",
1371
+ "s2.metacrawler.de",
1372
+ "s3.metacrawler.de"
1373
+ ],
1374
+ "parameters": [
1375
+ "qry"
1376
+ ]
1377
+ },
1378
+ "Orange": {
1379
+ "domains": [
1380
+ "busca.orange.es",
1381
+ "search.orange.co.uk"
1382
+ ],
1383
+ "parameters": [
1384
+ "q"
1385
+ ]
1386
+ },
1387
+ "Gule Sider": {
1388
+ "domains": [
1389
+ "www.gulesider.no"
1390
+ ],
1391
+ "parameters": [
1392
+ "q"
1393
+ ]
1394
+ },
1395
+ "Francite": {
1396
+ "domains": [
1397
+ "recherche.francite.com"
1398
+ ],
1399
+ "parameters": [
1400
+ "name"
1401
+ ]
1402
+ },
1403
+ "Ask Toolbar": {
1404
+ "domains": [
1405
+ "search.tb.ask.com"
1406
+ ],
1407
+ "parameters": [
1408
+ "searchfor"
1409
+ ]
1410
+ },
1411
+ "Aport": {
1412
+ "domains": [
1413
+ "sm.aport.ru"
1414
+ ],
1415
+ "parameters": [
1416
+ "r"
1417
+ ]
1418
+ },
1419
+ "Trusted-Search": {
1420
+ "domains": [
1421
+ "www.trusted--search.com"
1422
+ ],
1423
+ "parameters": [
1424
+ "w"
1425
+ ]
1426
+ },
1427
+ "goo": {
1428
+ "domains": [
1429
+ "search.goo.ne.jp",
1430
+ "ocnsearch.goo.ne.jp"
1431
+ ],
1432
+ "parameters": [
1433
+ "MT"
1434
+ ]
1435
+ },
1436
+ "Fast Browser Search": {
1437
+ "domains": [
1438
+ "www.fastbrowsersearch.com"
1439
+ ],
1440
+ "parameters": [
1441
+ "q"
1442
+ ]
1443
+ },
1444
+ "Blogpulse": {
1445
+ "domains": [
1446
+ "www.blogpulse.com"
1447
+ ],
1448
+ "parameters": [
1449
+ "query"
1450
+ ]
1451
+ },
1452
+ "Volny": {
1453
+ "domains": [
1454
+ "web.volny.cz"
1455
+ ],
1456
+ "parameters": [
1457
+ "search"
1458
+ ]
1459
+ },
1460
+ "Icerockeet": {
1461
+ "domains": [
1462
+ "blogs.icerocket.com"
1463
+ ],
1464
+ "parameters": [
1465
+ "q"
1466
+ ]
1467
+ },
1468
+ "Terra": {
1469
+ "domains": [
1470
+ "buscador.terra.es",
1471
+ "buscador.terra.cl",
1472
+ "buscador.terra.com.br"
1473
+ ],
1474
+ "parameters": [
1475
+ "query"
1476
+ ]
1477
+ },
1478
+ "Searchy": {
1479
+ "domains": [
1480
+ "www.searchy.co.uk"
1481
+ ],
1482
+ "parameters": [
1483
+ "q"
1484
+ ]
1485
+ },
1486
+ "Onet": {
1487
+ "domains": [
1488
+ "szukaj.onet.pl"
1489
+ ],
1490
+ "parameters": [
1491
+ "qt"
1492
+ ]
1493
+ },
1494
+ "Digg": {
1495
+ "domains": [
1496
+ "digg.com"
1497
+ ],
1498
+ "parameters": [
1499
+ "s"
1500
+ ]
1501
+ },
1502
+ "Abacho": {
1503
+ "domains": [
1504
+ "www.abacho.de",
1505
+ "www.abacho.com",
1506
+ "www.abacho.co.uk",
1507
+ "www.se.abacho.com",
1508
+ "www.tr.abacho.com",
1509
+ "www.abacho.at",
1510
+ "www.abacho.fr",
1511
+ "www.abacho.es",
1512
+ "www.abacho.ch",
1513
+ "www.abacho.it"
1514
+ ],
1515
+ "parameters": [
1516
+ "q"
1517
+ ]
1518
+ },
1519
+ "maailm": {
1520
+ "domains": [
1521
+ "www.maailm.com"
1522
+ ],
1523
+ "parameters": [
1524
+ "tekst"
1525
+ ]
1526
+ },
1527
+ "Flix": {
1528
+ "domains": [
1529
+ "www.flix.de"
1530
+ ],
1531
+ "parameters": [
1532
+ "keyword"
1533
+ ]
1534
+ },
1535
+ "Suchnase": {
1536
+ "domains": [
1537
+ "www.suchnase.de"
1538
+ ],
1539
+ "parameters": [
1540
+ "q"
1541
+ ]
1542
+ },
1543
+ "Freenet": {
1544
+ "domains": [
1545
+ "suche.freenet.de"
1546
+ ],
1547
+ "parameters": [
1548
+ "query",
1549
+ "Keywords"
1550
+ ]
1551
+ },
1552
+ "DuckDuckGoL": {
1553
+ "domains": [
1554
+ "duckduckgo.com"
1555
+ ],
1556
+ "parameters": [
1557
+ "q"
1558
+ ]
1559
+ },
1560
+ "Poisk.ru": {
1561
+ "domains": [
1562
+ "www.plazoo.com"
1563
+ ],
1564
+ "parameters": [
1565
+ "q"
1566
+ ]
1567
+ },
1568
+ "Sharelook": {
1569
+ "domains": [
1570
+ "www.sharelook.fr"
1571
+ ],
1572
+ "parameters": [
1573
+ "keyword"
1574
+ ]
1575
+ },
1576
+ "Najdi": {
1577
+ "domains": [
1578
+ "www.najdi.si"
1579
+ ],
1580
+ "parameters": [
1581
+ "q"
1582
+ ]
1583
+ },
1584
+ "Picsearch": {
1585
+ "domains": [
1586
+ "www.picsearch.com"
1587
+ ],
1588
+ "parameters": [
1589
+ "q"
1590
+ ]
1591
+ },
1592
+ "Mail.ru": {
1593
+ "domains": [
1594
+ "go.mail.ru"
1595
+ ],
1596
+ "parameters": [
1597
+ "q"
1598
+ ]
1599
+ },
1600
+ "Alexa": {
1601
+ "domains": [
1602
+ "alexa.com",
1603
+ "search.toolbars.alexa.com"
1604
+ ],
1605
+ "parameters": [
1606
+ "q"
1607
+ ]
1608
+ },
1609
+ "Metager": {
1610
+ "domains": [
1611
+ "meta.rrzn.uni-hannover.de",
1612
+ "www.metager.de"
1613
+ ],
1614
+ "parameters": [
1615
+ "eingabe"
1616
+ ]
1617
+ },
1618
+ "Technorati": {
1619
+ "domains": [
1620
+ "technorati.com"
1621
+ ],
1622
+ "parameters": [
1623
+ "q"
1624
+ ]
1625
+ },
1626
+ "WWW": {
1627
+ "domains": [
1628
+ "search.www.ee"
1629
+ ],
1630
+ "parameters": [
1631
+ "query"
1632
+ ]
1633
+ },
1634
+ "Trouvez.com": {
1635
+ "domains": [
1636
+ "www.trouvez.com"
1637
+ ],
1638
+ "parameters": [
1639
+ "query"
1640
+ ]
1641
+ },
1642
+ "IXquick": {
1643
+ "domains": [
1644
+ "ixquick.com",
1645
+ "www.eu.ixquick.com",
1646
+ "ixquick.de",
1647
+ "www.ixquick.de",
1648
+ "us.ixquick.com",
1649
+ "s1.us.ixquick.com",
1650
+ "s2.us.ixquick.com",
1651
+ "s3.us.ixquick.com",
1652
+ "s4.us.ixquick.com",
1653
+ "s5.us.ixquick.com",
1654
+ "eu.ixquick.com",
1655
+ "s8-eu.ixquick.com",
1656
+ "s1-eu.ixquick.de"
1657
+ ],
1658
+ "parameters": [
1659
+ "query"
1660
+ ]
1661
+ },
1662
+ "Zapmeta": {
1663
+ "domains": [
1664
+ "www.zapmeta.com",
1665
+ "www.zapmeta.nl",
1666
+ "www.zapmeta.de",
1667
+ "uk.zapmeta.com"
1668
+ ],
1669
+ "parameters": [
1670
+ "q",
1671
+ "query"
1672
+ ]
1673
+ },
1674
+ "Yippy": {
1675
+ "domains": [
1676
+ "search.yippy.com"
1677
+ ],
1678
+ "parameters": [
1679
+ "q",
1680
+ "query"
1681
+ ]
1682
+ },
1683
+ "Gomeo": {
1684
+ "domains": [
1685
+ "www.gomeo.com"
1686
+ ],
1687
+ "parameters": [
1688
+ "Keywords"
1689
+ ]
1690
+ },
1691
+ "Walhello": {
1692
+ "domains": [
1693
+ "www.walhello.info",
1694
+ "www.walhello.com",
1695
+ "www.walhello.de",
1696
+ "www.walhello.nl"
1697
+ ],
1698
+ "parameters": [
1699
+ "key"
1700
+ ]
1701
+ },
1702
+ "Meta": {
1703
+ "domains": [
1704
+ "meta.ua"
1705
+ ],
1706
+ "parameters": [
1707
+ "q"
1708
+ ]
1709
+ },
1710
+ "Skynet": {
1711
+ "domains": [
1712
+ "www.skynet.be"
1713
+ ],
1714
+ "parameters": [
1715
+ "q"
1716
+ ]
1717
+ },
1718
+ "Blogdigger": {
1719
+ "domains": [
1720
+ "www.blogdigger.com"
1721
+ ],
1722
+ "parameters": [
1723
+ "q"
1724
+ ]
1725
+ },
1726
+ "WebSearch": {
1727
+ "domains": [
1728
+ "www.websearch.com"
1729
+ ],
1730
+ "parameters": [
1731
+ "qkw",
1732
+ "q"
1733
+ ]
1734
+ },
1735
+ "Rambler": {
1736
+ "domains": [
1737
+ "nova.rambler.ru"
1738
+ ],
1739
+ "parameters": [
1740
+ "query",
1741
+ "words"
1742
+ ]
1743
+ },
1744
+ "Latne": {
1745
+ "domains": [
1746
+ "www.latne.lv"
1747
+ ],
1748
+ "parameters": [
1749
+ "q"
1750
+ ]
1751
+ },
1752
+ "MySearch": {
1753
+ "domains": [
1754
+ "www.mysearch.com",
1755
+ "ms114.mysearch.com",
1756
+ "ms146.mysearch.com",
1757
+ "kf.mysearch.myway.com",
1758
+ "ki.mysearch.myway.com",
1759
+ "search.myway.com",
1760
+ "search.mywebsearch.com"
1761
+ ],
1762
+ "parameters": [
1763
+ "searchfor",
1764
+ "searchFor"
1765
+ ]
1766
+ },
1767
+ "Cuil": {
1768
+ "domains": [
1769
+ "www.cuil.com"
1770
+ ],
1771
+ "parameters": [
1772
+ "q"
1773
+ ]
1774
+ },
1775
+ "Tixuma": {
1776
+ "domains": [
1777
+ "www.tixuma.de"
1778
+ ],
1779
+ "parameters": [
1780
+ "sc"
1781
+ ]
1782
+ },
1783
+ "Sapo": {
1784
+ "domains": [
1785
+ "pesquisa.sapo.pt"
1786
+ ],
1787
+ "parameters": [
1788
+ "q"
1789
+ ]
1790
+ },
1791
+ "Gnadenmeer": {
1792
+ "domains": [
1793
+ "www.gnadenmeer.de"
1794
+ ],
1795
+ "parameters": [
1796
+ "keyword"
1797
+ ]
1798
+ },
1799
+ "Arcor": {
1800
+ "domains": [
1801
+ "www.arcor.de"
1802
+ ],
1803
+ "parameters": [
1804
+ "Keywords"
1805
+ ]
1806
+ },
1807
+ "Naver": {
1808
+ "domains": [
1809
+ "search.naver.com"
1810
+ ],
1811
+ "parameters": [
1812
+ "query"
1813
+ ]
1814
+ },
1815
+ "Zoeken": {
1816
+ "domains": [
1817
+ "www.zoeken.nl"
1818
+ ],
1819
+ "parameters": [
1820
+ "q"
1821
+ ]
1822
+ },
1823
+ "Yam": {
1824
+ "domains": [
1825
+ "search.yam.com"
1826
+ ],
1827
+ "parameters": [
1828
+ "k"
1829
+ ]
1830
+ },
1831
+ "Eniro": {
1832
+ "domains": [
1833
+ "www.eniro.se"
1834
+ ],
1835
+ "parameters": [
1836
+ "q",
1837
+ "search_word"
1838
+ ]
1839
+ },
1840
+ "APOLL07": {
1841
+ "domains": [
1842
+ "apollo7.de"
1843
+ ],
1844
+ "parameters": [
1845
+ "query"
1846
+ ]
1847
+ },
1848
+ "Biglobe": {
1849
+ "domains": [
1850
+ "cgi.search.biglobe.ne.jp"
1851
+ ],
1852
+ "parameters": [
1853
+ "q"
1854
+ ]
1855
+ },
1856
+ "Mozbot": {
1857
+ "domains": [
1858
+ "www.mozbot.fr",
1859
+ "www.mozbot.co.uk",
1860
+ "www.mozbot.com"
1861
+ ],
1862
+ "parameters": [
1863
+ "q"
1864
+ ]
1865
+ },
1866
+ "ICQ": {
1867
+ "domains": [
1868
+ "www.icq.com",
1869
+ "search.icq.com"
1870
+ ],
1871
+ "parameters": [
1872
+ "q"
1873
+ ]
1874
+ },
1875
+ "Baidu": {
1876
+ "domains": [
1877
+ "www.baidu.com",
1878
+ "www1.baidu.com",
1879
+ "zhidao.baidu.com",
1880
+ "tieba.baidu.com",
1881
+ "news.baidu.com",
1882
+ "web.gougou.com"
1883
+ ],
1884
+ "parameters": [
1885
+ "wd",
1886
+ "word",
1887
+ "kw",
1888
+ "k"
1889
+ ]
1890
+ },
1891
+ "Conduit": {
1892
+ "domains": [
1893
+ "search.conduit.com"
1894
+ ],
1895
+ "parameters": [
1896
+ "q"
1897
+ ]
1898
+ },
1899
+ "Austronaut": {
1900
+ "domains": [
1901
+ "www2.austronaut.at",
1902
+ "www1.astronaut.at"
1903
+ ],
1904
+ "parameters": [
1905
+ "q"
1906
+ ]
1907
+ },
1908
+ "Vindex": {
1909
+ "domains": [
1910
+ "www.vindex.nl",
1911
+ "search.vindex.nl"
1912
+ ],
1913
+ "parameters": [
1914
+ "search_for"
1915
+ ]
1916
+ },
1917
+ "TrovaRapido": {
1918
+ "domains": [
1919
+ "www.trovarapido.com"
1920
+ ],
1921
+ "parameters": [
1922
+ "q"
1923
+ ]
1924
+ },
1925
+ "Suchmaschine.com": {
1926
+ "domains": [
1927
+ "www.suchmaschine.com"
1928
+ ],
1929
+ "parameters": [
1930
+ "suchstr"
1931
+ ]
1932
+ },
1933
+ "Lycos": {
1934
+ "domains": [
1935
+ "search.lycos.com",
1936
+ "www.lycos.com",
1937
+ "lycos.com"
1938
+ ],
1939
+ "parameters": [
1940
+ "query"
1941
+ ]
1942
+ },
1943
+ "Vinden": {
1944
+ "domains": [
1945
+ "www.vinden.nl"
1946
+ ],
1947
+ "parameters": [
1948
+ "q"
1949
+ ]
1950
+ },
1951
+ "Altavista": {
1952
+ "domains": [
1953
+ "www.altavista.com",
1954
+ "search.altavista.com",
1955
+ "listings.altavista.com",
1956
+ "altavista.de",
1957
+ "altavista.fr",
1958
+ "be-nl.altavista.com",
1959
+ "be-fr.altavista.com"
1960
+ ],
1961
+ "parameters": [
1962
+ "q"
1963
+ ]
1964
+ },
1965
+ "dmoz": {
1966
+ "domains": [
1967
+ "dmoz.org",
1968
+ "editors.dmoz.org"
1969
+ ],
1970
+ "parameters": [
1971
+ "q"
1972
+ ]
1973
+ },
1974
+ "Ecosia": {
1975
+ "domains": [
1976
+ "ecosia.org"
1977
+ ],
1978
+ "parameters": [
1979
+ "q"
1980
+ ]
1981
+ },
1982
+ "Maxwebsearch": {
1983
+ "domains": [
1984
+ "maxwebsearch.com"
1985
+ ],
1986
+ "parameters": [
1987
+ "query"
1988
+ ]
1989
+ },
1990
+ "Euroseek": {
1991
+ "domains": [
1992
+ "www.euroseek.com"
1993
+ ],
1994
+ "parameters": [
1995
+ "string"
1996
+ ]
1997
+ },
1998
+ "Bing": {
1999
+ "domains": [
2000
+ "bing.com",
2001
+ "www.bing.com",
2002
+ "msnbc.msn.com",
2003
+ "dizionario.it.msn.com",
2004
+ "cc.bingj.com",
2005
+ "m.bing.com"
2006
+ ],
2007
+ "parameters": [
2008
+ "q",
2009
+ "Q"
2010
+ ]
2011
+ },
2012
+ "X-recherche": {
2013
+ "domains": [
2014
+ "www.x-recherche.com"
2015
+ ],
2016
+ "parameters": [
2017
+ "MOTS"
2018
+ ]
2019
+ },
2020
+ "Yandex Images": {
2021
+ "domains": [
2022
+ "images.yandex.ru",
2023
+ "images.yandex.ua",
2024
+ "images.yandex.com"
2025
+ ],
2026
+ "parameters": [
2027
+ "text"
2028
+ ]
2029
+ },
2030
+ "GMX": {
2031
+ "domains": [
2032
+ "suche.gmx.net"
2033
+ ],
2034
+ "parameters": [
2035
+ "su"
2036
+ ]
2037
+ },
2038
+ "Daemon search": {
2039
+ "domains": [
2040
+ "daemon-search.com",
2041
+ "my.daemon-search.com"
2042
+ ],
2043
+ "parameters": [
2044
+ "q"
2045
+ ]
2046
+ },
2047
+ "Jungle Key": {
2048
+ "domains": [
2049
+ "junglekey.com",
2050
+ "junglekey.fr"
2051
+ ],
2052
+ "parameters": [
2053
+ "query"
2054
+ ]
2055
+ },
2056
+ "Firstfind": {
2057
+ "domains": [
2058
+ "www.firstsfind.com"
2059
+ ],
2060
+ "parameters": [
2061
+ "qry"
2062
+ ]
2063
+ },
2064
+ "Crawler": {
2065
+ "domains": [
2066
+ "www.crawler.com"
2067
+ ],
2068
+ "parameters": [
2069
+ "q"
2070
+ ]
2071
+ },
2072
+ "Holmes": {
2073
+ "domains": [
2074
+ "holmes.ge"
2075
+ ],
2076
+ "parameters": [
2077
+ "q"
2078
+ ]
2079
+ },
2080
+ "Charter": {
2081
+ "domains": [
2082
+ "www.charter.net"
2083
+ ],
2084
+ "parameters": [
2085
+ "q"
2086
+ ]
2087
+ },
2088
+ "Ilse": {
2089
+ "domains": [
2090
+ "www.ilse.nl"
2091
+ ],
2092
+ "parameters": [
2093
+ "search_for"
2094
+ ]
2095
+ },
2096
+ "earthlink": {
2097
+ "domains": [
2098
+ "search.earthlink.net"
2099
+ ],
2100
+ "parameters": [
2101
+ "q"
2102
+ ]
2103
+ },
2104
+ "Qualigo": {
2105
+ "domains": [
2106
+ "www.qualigo.at",
2107
+ "www.qualigo.ch",
2108
+ "www.qualigo.de",
2109
+ "www.qualigo.nl"
2110
+ ],
2111
+ "parameters": [
2112
+ "q"
2113
+ ]
2114
+ },
2115
+ "El Mundo": {
2116
+ "domains": [
2117
+ "ariadna.elmundo.es"
2118
+ ],
2119
+ "parameters": [
2120
+ "q"
2121
+ ]
2122
+ },
2123
+ "Metager2": {
2124
+ "domains": [
2125
+ "metager2.de"
2126
+ ],
2127
+ "parameters": [
2128
+ "q"
2129
+ ]
2130
+ },
2131
+ "Forestle": {
2132
+ "domains": [
2133
+ "forestle.org",
2134
+ "www.forestle.org",
2135
+ "forestle.mobi"
2136
+ ],
2137
+ "parameters": [
2138
+ "q"
2139
+ ]
2140
+ },
2141
+ "Search.ch": {
2142
+ "domains": [
2143
+ "www.search.ch"
2144
+ ],
2145
+ "parameters": [
2146
+ "q"
2147
+ ]
2148
+ },
2149
+ "Meinestadt": {
2150
+ "domains": [
2151
+ "www.meinestadt.de"
2152
+ ],
2153
+ "parameters": [
2154
+ "words"
2155
+ ]
2156
+ },
2157
+ "Freshweather": {
2158
+ "domains": [
2159
+ "www.fresh-weather.com"
2160
+ ],
2161
+ "parameters": [
2162
+ "q"
2163
+ ]
2164
+ },
2165
+ "AllTheWeb": {
2166
+ "domains": [
2167
+ "www.alltheweb.com"
2168
+ ],
2169
+ "parameters": [
2170
+ "q"
2171
+ ]
2172
+ },
2173
+ "Zoek": {
2174
+ "domains": [
2175
+ "www3.zoek.nl"
2176
+ ],
2177
+ "parameters": [
2178
+ "q"
2179
+ ]
2180
+ },
2181
+ "Daum": {
2182
+ "domains": [
2183
+ "search.daum.net"
2184
+ ],
2185
+ "parameters": [
2186
+ "q"
2187
+ ]
2188
+ },
2189
+ "Marktplaats": {
2190
+ "domains": [
2191
+ "www.marktplaats.nl"
2192
+ ],
2193
+ "parameters": [
2194
+ "query"
2195
+ ]
2196
+ },
2197
+ "suche.info": {
2198
+ "domains": [
2199
+ "suche.info"
2200
+ ],
2201
+ "parameters": [
2202
+ "q"
2203
+ ]
2204
+ },
2205
+ "Google News": {
2206
+ "domains": [
2207
+ "news.google.ac",
2208
+ "news.google.ad",
2209
+ "news.google.ae",
2210
+ "news.google.am",
2211
+ "news.google.as",
2212
+ "news.google.at",
2213
+ "news.google.az",
2214
+ "news.google.ba",
2215
+ "news.google.be",
2216
+ "news.google.bf",
2217
+ "news.google.bg",
2218
+ "news.google.bi",
2219
+ "news.google.bj",
2220
+ "news.google.bs",
2221
+ "news.google.by",
2222
+ "news.google.ca",
2223
+ "news.google.cat",
2224
+ "news.google.cc",
2225
+ "news.google.cd",
2226
+ "news.google.cf",
2227
+ "news.google.cg",
2228
+ "news.google.ch",
2229
+ "news.google.ci",
2230
+ "news.google.cl",
2231
+ "news.google.cm",
2232
+ "news.google.cn",
2233
+ "news.google.co.bw",
2234
+ "news.google.co.ck",
2235
+ "news.google.co.cr",
2236
+ "news.google.co.id",
2237
+ "news.google.co.il",
2238
+ "news.google.co.in",
2239
+ "news.google.co.jp",
2240
+ "news.google.co.ke",
2241
+ "news.google.co.kr",
2242
+ "news.google.co.ls",
2243
+ "news.google.co.ma",
2244
+ "news.google.co.mz",
2245
+ "news.google.co.nz",
2246
+ "news.google.co.th",
2247
+ "news.google.co.tz",
2248
+ "news.google.co.ug",
2249
+ "news.google.co.uk",
2250
+ "news.google.co.uz",
2251
+ "news.google.co.ve",
2252
+ "news.google.co.vi",
2253
+ "news.google.co.za",
2254
+ "news.google.co.zm",
2255
+ "news.google.co.zw",
2256
+ "news.google.com",
2257
+ "news.google.com.af",
2258
+ "news.google.com.ag",
2259
+ "news.google.com.ai",
2260
+ "news.google.com.ar",
2261
+ "news.google.com.au",
2262
+ "news.google.com.bd",
2263
+ "news.google.com.bh",
2264
+ "news.google.com.bn",
2265
+ "news.google.com.bo",
2266
+ "news.google.com.br",
2267
+ "news.google.com.by",
2268
+ "news.google.com.bz",
2269
+ "news.google.com.co",
2270
+ "news.google.com.cu",
2271
+ "news.google.com.cy",
2272
+ "news.google.com.do",
2273
+ "news.google.com.ec",
2274
+ "news.google.com.eg",
2275
+ "news.google.com.et",
2276
+ "news.google.com.fj",
2277
+ "news.google.com.gh",
2278
+ "news.google.com.gi",
2279
+ "news.google.com.gt",
2280
+ "news.google.com.hk",
2281
+ "news.google.com.jm",
2282
+ "news.google.com.kh",
2283
+ "news.google.com.kh",
2284
+ "news.google.com.kw",
2285
+ "news.google.com.lb",
2286
+ "news.google.com.lc",
2287
+ "news.google.com.ly",
2288
+ "news.google.com.mt",
2289
+ "news.google.com.mx",
2290
+ "news.google.com.my",
2291
+ "news.google.com.na",
2292
+ "news.google.com.nf",
2293
+ "news.google.com.ng",
2294
+ "news.google.com.ni",
2295
+ "news.google.com.np",
2296
+ "news.google.com.om",
2297
+ "news.google.com.pa",
2298
+ "news.google.com.pe",
2299
+ "news.google.com.ph",
2300
+ "news.google.com.pk",
2301
+ "news.google.com.pr",
2302
+ "news.google.com.py",
2303
+ "news.google.com.qa",
2304
+ "news.google.com.sa",
2305
+ "news.google.com.sb",
2306
+ "news.google.com.sg",
2307
+ "news.google.com.sl",
2308
+ "news.google.com.sv",
2309
+ "news.google.com.tj",
2310
+ "news.google.com.tn",
2311
+ "news.google.com.tr",
2312
+ "news.google.com.tw",
2313
+ "news.google.com.ua",
2314
+ "news.google.com.uy",
2315
+ "news.google.com.vc",
2316
+ "news.google.com.vn",
2317
+ "news.google.cv",
2318
+ "news.google.cz",
2319
+ "news.google.de",
2320
+ "news.google.dj",
2321
+ "news.google.dk",
2322
+ "news.google.dm",
2323
+ "news.google.dz",
2324
+ "news.google.ee",
2325
+ "news.google.es",
2326
+ "news.google.fi",
2327
+ "news.google.fm",
2328
+ "news.google.fr",
2329
+ "news.google.ga",
2330
+ "news.google.gd",
2331
+ "news.google.ge",
2332
+ "news.google.gf",
2333
+ "news.google.gg",
2334
+ "news.google.gl",
2335
+ "news.google.gm",
2336
+ "news.google.gp",
2337
+ "news.google.gr",
2338
+ "news.google.gy",
2339
+ "news.google.hn",
2340
+ "news.google.hr",
2341
+ "news.google.ht",
2342
+ "news.google.hu",
2343
+ "news.google.ie",
2344
+ "news.google.im",
2345
+ "news.google.io",
2346
+ "news.google.iq",
2347
+ "news.google.is",
2348
+ "news.google.it",
2349
+ "news.google.it.ao",
2350
+ "news.google.je",
2351
+ "news.google.jo",
2352
+ "news.google.kg",
2353
+ "news.google.ki",
2354
+ "news.google.kz",
2355
+ "news.google.la",
2356
+ "news.google.li",
2357
+ "news.google.lk",
2358
+ "news.google.lt",
2359
+ "news.google.lu",
2360
+ "news.google.lv",
2361
+ "news.google.md",
2362
+ "news.google.me",
2363
+ "news.google.mg",
2364
+ "news.google.mk",
2365
+ "news.google.ml",
2366
+ "news.google.mn",
2367
+ "news.google.ms",
2368
+ "news.google.mu",
2369
+ "news.google.mv",
2370
+ "news.google.mw",
2371
+ "news.google.ne",
2372
+ "news.google.nl",
2373
+ "news.google.no",
2374
+ "news.google.nr",
2375
+ "news.google.nu",
2376
+ "news.google.pl",
2377
+ "news.google.pn",
2378
+ "news.google.ps",
2379
+ "news.google.pt",
2380
+ "news.google.ro",
2381
+ "news.google.rs",
2382
+ "news.google.ru",
2383
+ "news.google.rw",
2384
+ "news.google.sc",
2385
+ "news.google.se",
2386
+ "news.google.sh",
2387
+ "news.google.si",
2388
+ "news.google.sk",
2389
+ "news.google.sm",
2390
+ "news.google.sn",
2391
+ "news.google.so",
2392
+ "news.google.st",
2393
+ "news.google.td",
2394
+ "news.google.tg",
2395
+ "news.google.tk",
2396
+ "news.google.tl",
2397
+ "news.google.tm",
2398
+ "news.google.to",
2399
+ "news.google.tt",
2400
+ "news.google.us",
2401
+ "news.google.vg",
2402
+ "news.google.vu",
2403
+ "news.google.ws"
2404
+ ],
2405
+ "parameters": [
2406
+ "q"
2407
+ ]
2408
+ },
2409
+ "Zoohoo": {
2410
+ "domains": [
2411
+ "zoohoo.cz"
2412
+ ],
2413
+ "parameters": [
2414
+ "q"
2415
+ ]
2416
+ },
2417
+ "Seznam": {
2418
+ "domains": [
2419
+ "search.seznam.cz"
2420
+ ],
2421
+ "parameters": [
2422
+ "q"
2423
+ ]
2424
+ },
2425
+ "Online.no": {
2426
+ "domains": [
2427
+ "online.no"
2428
+ ],
2429
+ "parameters": [
2430
+ "q"
2431
+ ]
2432
+ },
2433
+ "Eurip": {
2434
+ "domains": [
2435
+ "www.eurip.com"
2436
+ ],
2437
+ "parameters": [
2438
+ "q"
2439
+ ]
2440
+ },
2441
+ "all.by": {
2442
+ "domains": [
2443
+ "all.by"
2444
+ ],
2445
+ "parameters": [
2446
+ "query"
2447
+ ]
2448
+ },
2449
+ "Road Runner Search": {
2450
+ "domains": [
2451
+ "search.rr.com"
2452
+ ],
2453
+ "parameters": [
2454
+ "q"
2455
+ ]
2456
+ },
2457
+ "Opplysningen 1881": {
2458
+ "domains": [
2459
+ "www.1881.no"
2460
+ ],
2461
+ "parameters": [
2462
+ "Query"
2463
+ ]
2464
+ },
2465
+ "YouGoo": {
2466
+ "domains": [
2467
+ "www.yougoo.fr"
2468
+ ],
2469
+ "parameters": [
2470
+ "q"
2471
+ ]
2472
+ },
2473
+ "Bing Images": {
2474
+ "domains": [
2475
+ "bing.com/images/search",
2476
+ "www.bing.com/images/search"
2477
+ ],
2478
+ "parameters": [
2479
+ "q",
2480
+ "Q"
2481
+ ]
2482
+ },
2483
+ "Geona": {
2484
+ "domains": [
2485
+ "geona.net"
2486
+ ],
2487
+ "parameters": [
2488
+ "q"
2489
+ ]
2490
+ },
2491
+ "Nate": {
2492
+ "domains": [
2493
+ "search.nate.com"
2494
+ ],
2495
+ "parameters": [
2496
+ "q"
2497
+ ]
2498
+ },
2499
+ "T-Online": {
2500
+ "domains": [
2501
+ "suche.t-online.de",
2502
+ "brisbane.t-online.de",
2503
+ "navigationshilfe.t-online.de"
2504
+ ],
2505
+ "parameters": [
2506
+ "q"
2507
+ ]
2508
+ },
2509
+ "Hotbot": {
2510
+ "domains": [
2511
+ "www.hotbot.com"
2512
+ ],
2513
+ "parameters": [
2514
+ "query"
2515
+ ]
2516
+ },
2517
+ "Kvasir": {
2518
+ "domains": [
2519
+ "www.kvasir.no"
2520
+ ],
2521
+ "parameters": [
2522
+ "q"
2523
+ ]
2524
+ },
2525
+ "Babylon": {
2526
+ "domains": [
2527
+ "search.babylon.com",
2528
+ "searchassist.babylon.com"
2529
+ ],
2530
+ "parameters": [
2531
+ "q"
2532
+ ]
2533
+ },
2534
+ "Excite": {
2535
+ "domains": [
2536
+ "search.excite.it",
2537
+ "search.excite.fr",
2538
+ "search.excite.de",
2539
+ "search.excite.co.uk",
2540
+ "serach.excite.es",
2541
+ "search.excite.nl",
2542
+ "msxml.excite.com",
2543
+ "www.excite.co.jp"
2544
+ ],
2545
+ "parameters": [
2546
+ "q",
2547
+ "search"
2548
+ ]
2549
+ },
2550
+ "qip": {
2551
+ "domains": [
2552
+ "search.qip.ru"
2553
+ ],
2554
+ "parameters": [
2555
+ "query"
2556
+ ]
2557
+ },
2558
+ "Yahoo!": {
2559
+ "domains": [
2560
+ "search.yahoo.com",
2561
+ "yahoo.com",
2562
+ "ar.search.yahoo.com",
2563
+ "ar.yahoo.com",
2564
+ "au.search.yahoo.com",
2565
+ "au.yahoo.com",
2566
+ "br.search.yahoo.com",
2567
+ "br.yahoo.com",
2568
+ "cade.searchde.yahoo.com",
2569
+ "cade.yahoo.com",
2570
+ "chinese.searchinese.yahoo.com",
2571
+ "chinese.yahoo.com",
2572
+ "cn.search.yahoo.com",
2573
+ "cn.yahoo.com",
2574
+ "de.search.yahoo.com",
2575
+ "de.yahoo.com",
2576
+ "dk.search.yahoo.com",
2577
+ "dk.yahoo.com",
2578
+ "es.search.yahoo.com",
2579
+ "es.yahoo.com",
2580
+ "espanol.searchpanol.yahoo.com",
2581
+ "espanol.searchpanol.yahoo.com",
2582
+ "espanol.yahoo.com",
2583
+ "espanol.yahoo.com",
2584
+ "fr.search.yahoo.com",
2585
+ "fr.yahoo.com",
2586
+ "ie.search.yahoo.com",
2587
+ "ie.yahoo.com",
2588
+ "it.search.yahoo.com",
2589
+ "it.yahoo.com",
2590
+ "kr.search.yahoo.com",
2591
+ "kr.yahoo.com",
2592
+ "mx.search.yahoo.com",
2593
+ "mx.yahoo.com",
2594
+ "no.search.yahoo.com",
2595
+ "no.yahoo.com",
2596
+ "nz.search.yahoo.com",
2597
+ "nz.yahoo.com",
2598
+ "one.cn.yahoo.com",
2599
+ "one.searchn.yahoo.com",
2600
+ "qc.search.yahoo.com",
2601
+ "qc.search.yahoo.com",
2602
+ "qc.search.yahoo.com",
2603
+ "qc.yahoo.com",
2604
+ "qc.yahoo.com",
2605
+ "se.search.yahoo.com",
2606
+ "se.search.yahoo.com",
2607
+ "se.yahoo.com",
2608
+ "search.searcharch.yahoo.com",
2609
+ "search.yahoo.com",
2610
+ "uk.search.yahoo.com",
2611
+ "uk.yahoo.com",
2612
+ "www.yahoo.co.jp",
2613
+ "search.yahoo.co.jp",
2614
+ "www.cercato.it",
2615
+ "search.offerbox.com",
2616
+ "ys.mirostart.com"
2617
+ ],
2618
+ "parameters": [
2619
+ "p",
2620
+ "q"
2621
+ ]
2622
+ },
2623
+ "URL.ORGanizier": {
2624
+ "domains": [
2625
+ "www.url.org"
2626
+ ],
2627
+ "parameters": [
2628
+ "q"
2629
+ ]
2630
+ },
2631
+ "Witch": {
2632
+ "domains": [
2633
+ "www.witch.de"
2634
+ ],
2635
+ "parameters": [
2636
+ "search"
2637
+ ]
2638
+ },
2639
+ "Mister Wong": {
2640
+ "domains": [
2641
+ "www.mister-wong.com",
2642
+ "www.mister-wong.de"
2643
+ ],
2644
+ "parameters": [
2645
+ "Keywords"
2646
+ ]
2647
+ },
2648
+ "Startsiden": {
2649
+ "domains": [
2650
+ "www.startsiden.no"
2651
+ ],
2652
+ "parameters": [
2653
+ "q"
2654
+ ]
2655
+ },
2656
+ "Web.de": {
2657
+ "domains": [
2658
+ "suche.web.de"
2659
+ ],
2660
+ "parameters": [
2661
+ "su"
2662
+ ]
2663
+ },
2664
+ "Ask": {
2665
+ "domains": [
2666
+ "ask.com",
2667
+ "www.ask.com",
2668
+ "web.ask.com",
2669
+ "int.ask.com",
2670
+ "mws.ask.com",
2671
+ "uk.ask.com",
2672
+ "images.ask.com",
2673
+ "ask.reference.com",
2674
+ "www.askkids.com",
2675
+ "iwon.ask.com",
2676
+ "www.ask.co.uk",
2677
+ "www.qbyrd.com",
2678
+ "search-results.com",
2679
+ "uk.search-results.com",
2680
+ "www.search-results.com",
2681
+ "int.search-results.com"
2682
+ ],
2683
+ "parameters": [
2684
+ "q"
2685
+ ]
2686
+ },
2687
+ "Centrum": {
2688
+ "domains": [
2689
+ "serach.centrum.cz",
2690
+ "morfeo.centrum.cz"
2691
+ ],
2692
+ "parameters": [
2693
+ "q"
2694
+ ]
2695
+ },
2696
+ "Everyclick": {
2697
+ "domains": [
2698
+ "www.everyclick.com"
2699
+ ],
2700
+ "parameters": [
2701
+ "keyword"
2702
+ ]
2703
+ },
2704
+ "Google Video": {
2705
+ "domains": [
2706
+ "video.google.com"
2707
+ ],
2708
+ "parameters": [
2709
+ "q"
2710
+ ]
2711
+ },
2712
+ "Delfi": {
2713
+ "domains": [
2714
+ "otsing.delfi.ee"
2715
+ ],
2716
+ "parameters": [
2717
+ "q"
2718
+ ]
2719
+ },
2720
+ "blekko": {
2721
+ "domains": [
2722
+ "blekko.com"
2723
+ ],
2724
+ "parameters": [
2725
+ "q"
2726
+ ]
2727
+ },
2728
+ "Jyxo": {
2729
+ "domains": [
2730
+ "jyxo.1188.cz"
2731
+ ],
2732
+ "parameters": [
2733
+ "q"
2734
+ ]
2735
+ },
2736
+ "Kataweb": {
2737
+ "domains": [
2738
+ "www.kataweb.it"
2739
+ ],
2740
+ "parameters": [
2741
+ "q"
2742
+ ]
2743
+ },
2744
+ "uol.com.br": {
2745
+ "domains": [
2746
+ "busca.uol.com.br"
2747
+ ],
2748
+ "parameters": [
2749
+ "q"
2750
+ ]
2751
+ },
2752
+ "Arianna": {
2753
+ "domains": [
2754
+ "arianna.libero.it",
2755
+ "www.arianna.com"
2756
+ ],
2757
+ "parameters": [
2758
+ "query"
2759
+ ]
2760
+ },
2761
+ "Mamma": {
2762
+ "domains": [
2763
+ "www.mamma.com",
2764
+ "mamma75.mamma.com"
2765
+ ],
2766
+ "parameters": [
2767
+ "query"
2768
+ ]
2769
+ },
2770
+ "Yatedo": {
2771
+ "domains": [
2772
+ "www.yatedo.com",
2773
+ "www.yatedo.fr"
2774
+ ],
2775
+ "parameters": [
2776
+ "q"
2777
+ ]
2778
+ },
2779
+ "Twingly": {
2780
+ "domains": [
2781
+ "www.twingly.com"
2782
+ ],
2783
+ "parameters": [
2784
+ "q"
2785
+ ]
2786
+ },
2787
+ "Delfi latvia": {
2788
+ "domains": [
2789
+ "smart.delfi.lv"
2790
+ ],
2791
+ "parameters": [
2792
+ "q"
2793
+ ]
2794
+ },
2795
+ "PriceRunner": {
2796
+ "domains": [
2797
+ "www.pricerunner.co.uk"
2798
+ ],
2799
+ "parameters": [
2800
+ "q"
2801
+ ]
2802
+ },
2803
+ "Rakuten": {
2804
+ "domains": [
2805
+ "websearch.rakuten.co.jp"
2806
+ ],
2807
+ "parameters": [
2808
+ "qt"
2809
+ ]
2810
+ },
2811
+ "Google": {
2812
+ "domains": [
2813
+ "www.google.com",
2814
+ "www.google.ac",
2815
+ "www.google.ad",
2816
+ "www.google.com.af",
2817
+ "www.google.com.ag",
2818
+ "www.google.com.ai",
2819
+ "www.google.am",
2820
+ "www.google.it.ao",
2821
+ "www.google.com.ar",
2822
+ "www.google.as",
2823
+ "www.google.at",
2824
+ "www.google.com.au",
2825
+ "www.google.az",
2826
+ "www.google.ba",
2827
+ "www.google.com.bd",
2828
+ "www.google.be",
2829
+ "www.google.bf",
2830
+ "www.google.bg",
2831
+ "www.google.com.bh",
2832
+ "www.google.bi",
2833
+ "www.google.bj",
2834
+ "www.google.com.bn",
2835
+ "www.google.com.bo",
2836
+ "www.google.com.br",
2837
+ "www.google.bs",
2838
+ "www.google.co.bw",
2839
+ "www.google.com.by",
2840
+ "www.google.by",
2841
+ "www.google.com.bz",
2842
+ "www.google.ca",
2843
+ "www.google.com.kh",
2844
+ "www.google.cc",
2845
+ "www.google.cd",
2846
+ "www.google.cf",
2847
+ "www.google.cat",
2848
+ "www.google.cg",
2849
+ "www.google.ch",
2850
+ "www.google.ci",
2851
+ "www.google.co.ck",
2852
+ "www.google.cl",
2853
+ "www.google.cm",
2854
+ "www.google.cn",
2855
+ "www.google.com.co",
2856
+ "www.google.co.cr",
2857
+ "www.google.com.cu",
2858
+ "www.google.cv",
2859
+ "www.google.com.cy",
2860
+ "www.google.cz",
2861
+ "www.google.de",
2862
+ "www.google.dj",
2863
+ "www.google.dk",
2864
+ "www.google.dm",
2865
+ "www.google.com.do",
2866
+ "www.google.dz",
2867
+ "www.google.com.ec",
2868
+ "www.google.ee",
2869
+ "www.google.com.eg",
2870
+ "www.google.es",
2871
+ "www.google.com.et",
2872
+ "www.google.fi",
2873
+ "www.google.com.fj",
2874
+ "www.google.fm",
2875
+ "www.google.fr",
2876
+ "www.google.ga",
2877
+ "www.google.gd",
2878
+ "www.google.ge",
2879
+ "www.google.gf",
2880
+ "www.google.gg",
2881
+ "www.google.com.gh",
2882
+ "www.google.com.gi",
2883
+ "www.google.gl",
2884
+ "www.google.gm",
2885
+ "www.google.gp",
2886
+ "www.google.gr",
2887
+ "www.google.com.gt",
2888
+ "www.google.gy",
2889
+ "www.google.com.hk",
2890
+ "www.google.hn",
2891
+ "www.google.hr",
2892
+ "www.google.ht",
2893
+ "www.google.hu",
2894
+ "www.google.co.id",
2895
+ "www.google.iq",
2896
+ "www.google.ie",
2897
+ "www.google.co.il",
2898
+ "www.google.im",
2899
+ "www.google.co.in",
2900
+ "www.google.io",
2901
+ "www.google.is",
2902
+ "www.google.it",
2903
+ "www.google.je",
2904
+ "www.google.com.jm",
2905
+ "www.google.jo",
2906
+ "www.google.co.jp",
2907
+ "www.google.co.ke",
2908
+ "www.google.com.kh",
2909
+ "www.google.ki",
2910
+ "www.google.kg",
2911
+ "www.google.co.kr",
2912
+ "www.google.com.kw",
2913
+ "www.google.kz",
2914
+ "www.google.la",
2915
+ "www.google.com.lb",
2916
+ "www.google.com.lc",
2917
+ "www.google.li",
2918
+ "www.google.lk",
2919
+ "www.google.co.ls",
2920
+ "www.google.lt",
2921
+ "www.google.lu",
2922
+ "www.google.lv",
2923
+ "www.google.com.ly",
2924
+ "www.google.co.ma",
2925
+ "www.google.md",
2926
+ "www.google.me",
2927
+ "www.google.mg",
2928
+ "www.google.mk",
2929
+ "www.google.ml",
2930
+ "www.google.mn",
2931
+ "www.google.ms",
2932
+ "www.google.com.mt",
2933
+ "www.google.mu",
2934
+ "www.google.mv",
2935
+ "www.google.mw",
2936
+ "www.google.com.mx",
2937
+ "www.google.com.my",
2938
+ "www.google.co.mz",
2939
+ "www.google.com.na",
2940
+ "www.google.ne",
2941
+ "www.google.com.nf",
2942
+ "www.google.com.ng",
2943
+ "www.google.com.ni",
2944
+ "www.google.nl",
2945
+ "www.google.no",
2946
+ "www.google.com.np",
2947
+ "www.google.nr",
2948
+ "www.google.nu",
2949
+ "www.google.co.nz",
2950
+ "www.google.com.om",
2951
+ "www.google.com.pa",
2952
+ "www.google.com.pe",
2953
+ "www.google.com.ph",
2954
+ "www.google.com.pk",
2955
+ "www.google.pl",
2956
+ "www.google.pn",
2957
+ "www.google.com.pr",
2958
+ "www.google.ps",
2959
+ "www.google.pt",
2960
+ "www.google.com.py",
2961
+ "www.google.com.qa",
2962
+ "www.google.ro",
2963
+ "www.google.rs",
2964
+ "www.google.ru",
2965
+ "www.google.rw",
2966
+ "www.google.com.sa",
2967
+ "www.google.com.sb",
2968
+ "www.google.sc",
2969
+ "www.google.se",
2970
+ "www.google.com.sg",
2971
+ "www.google.sh",
2972
+ "www.google.si",
2973
+ "www.google.sk",
2974
+ "www.google.com.sl",
2975
+ "www.google.sn",
2976
+ "www.google.sm",
2977
+ "www.google.so",
2978
+ "www.google.st",
2979
+ "www.google.com.sv",
2980
+ "www.google.td",
2981
+ "www.google.tg",
2982
+ "www.google.co.th",
2983
+ "www.google.com.tj",
2984
+ "www.google.tk",
2985
+ "www.google.tl",
2986
+ "www.google.tm",
2987
+ "www.google.to",
2988
+ "www.google.com.tn",
2989
+ "www.google.com.tr",
2990
+ "www.google.tt",
2991
+ "www.google.com.tw",
2992
+ "www.google.co.tz",
2993
+ "www.google.com.ua",
2994
+ "www.google.co.ug",
2995
+ "www.google.ae",
2996
+ "www.google.co.uk",
2997
+ "www.google.us",
2998
+ "www.google.com.uy",
2999
+ "www.google.co.uz",
3000
+ "www.google.com.vc",
3001
+ "www.google.co.ve",
3002
+ "www.google.vg",
3003
+ "www.google.co.vi",
3004
+ "www.google.com.vn",
3005
+ "www.google.vu",
3006
+ "www.google.ws",
3007
+ "www.google.co.za",
3008
+ "www.google.co.zm",
3009
+ "www.google.co.zw",
3010
+ "google.com",
3011
+ "google.ac",
3012
+ "google.ad",
3013
+ "google.com.af",
3014
+ "google.com.ag",
3015
+ "google.com.ai",
3016
+ "google.am",
3017
+ "google.it.ao",
3018
+ "google.com.ar",
3019
+ "google.as",
3020
+ "google.at",
3021
+ "google.com.au",
3022
+ "google.az",
3023
+ "google.ba",
3024
+ "google.com.bd",
3025
+ "google.be",
3026
+ "google.bf",
3027
+ "google.bg",
3028
+ "google.com.bh",
3029
+ "google.bi",
3030
+ "google.bj",
3031
+ "google.com.bn",
3032
+ "google.com.bo",
3033
+ "google.com.br",
3034
+ "google.bs",
3035
+ "google.co.bw",
3036
+ "google.com.by",
3037
+ "google.by",
3038
+ "google.com.bz",
3039
+ "google.ca",
3040
+ "google.com.kh",
3041
+ "google.cc",
3042
+ "google.cd",
3043
+ "google.cf",
3044
+ "google.cat",
3045
+ "google.cg",
3046
+ "google.ch",
3047
+ "google.ci",
3048
+ "google.co.ck",
3049
+ "google.cl",
3050
+ "google.cm",
3051
+ "google.cn",
3052
+ "google.com.co",
3053
+ "google.co.cr",
3054
+ "google.com.cu",
3055
+ "google.cv",
3056
+ "google.com.cy",
3057
+ "google.cz",
3058
+ "google.de",
3059
+ "google.dj",
3060
+ "google.dk",
3061
+ "google.dm",
3062
+ "google.com.do",
3063
+ "google.dz",
3064
+ "google.com.ec",
3065
+ "google.ee",
3066
+ "google.com.eg",
3067
+ "google.es",
3068
+ "google.com.et",
3069
+ "google.fi",
3070
+ "google.com.fj",
3071
+ "google.fm",
3072
+ "google.fr",
3073
+ "google.ga",
3074
+ "google.gd",
3075
+ "google.ge",
3076
+ "google.gf",
3077
+ "google.gg",
3078
+ "google.com.gh",
3079
+ "google.com.gi",
3080
+ "google.gl",
3081
+ "google.gm",
3082
+ "google.gp",
3083
+ "google.gr",
3084
+ "google.com.gt",
3085
+ "google.gy",
3086
+ "google.com.hk",
3087
+ "google.hn",
3088
+ "google.hr",
3089
+ "google.ht",
3090
+ "google.hu",
3091
+ "google.co.id",
3092
+ "google.iq",
3093
+ "google.ie",
3094
+ "google.co.il",
3095
+ "google.im",
3096
+ "google.co.in",
3097
+ "google.io",
3098
+ "google.is",
3099
+ "google.it",
3100
+ "google.je",
3101
+ "google.com.jm",
3102
+ "google.jo",
3103
+ "google.co.jp",
3104
+ "google.co.ke",
3105
+ "google.com.kh",
3106
+ "google.ki",
3107
+ "google.kg",
3108
+ "google.co.kr",
3109
+ "google.com.kw",
3110
+ "google.kz",
3111
+ "google.la",
3112
+ "google.com.lb",
3113
+ "google.com.lc",
3114
+ "google.li",
3115
+ "google.lk",
3116
+ "google.co.ls",
3117
+ "google.lt",
3118
+ "google.lu",
3119
+ "google.lv",
3120
+ "google.com.ly",
3121
+ "google.co.ma",
3122
+ "google.md",
3123
+ "google.me",
3124
+ "google.mg",
3125
+ "google.mk",
3126
+ "google.ml",
3127
+ "google.mn",
3128
+ "google.ms",
3129
+ "google.com.mt",
3130
+ "google.mu",
3131
+ "google.mv",
3132
+ "google.mw",
3133
+ "google.com.mx",
3134
+ "google.com.my",
3135
+ "google.co.mz",
3136
+ "google.com.na",
3137
+ "google.ne",
3138
+ "google.com.nf",
3139
+ "google.com.ng",
3140
+ "google.com.ni",
3141
+ "google.nl",
3142
+ "google.no",
3143
+ "google.com.np",
3144
+ "google.nr",
3145
+ "google.nu",
3146
+ "google.co.nz",
3147
+ "google.com.om",
3148
+ "google.com.pa",
3149
+ "google.com.pe",
3150
+ "google.com.ph",
3151
+ "google.com.pk",
3152
+ "google.pl",
3153
+ "google.pn",
3154
+ "google.com.pr",
3155
+ "google.ps",
3156
+ "google.pt",
3157
+ "google.com.py",
3158
+ "google.com.qa",
3159
+ "google.ro",
3160
+ "google.rs",
3161
+ "google.ru",
3162
+ "google.rw",
3163
+ "google.com.sa",
3164
+ "google.com.sb",
3165
+ "google.sc",
3166
+ "google.se",
3167
+ "google.com.sg",
3168
+ "google.sh",
3169
+ "google.si",
3170
+ "google.sk",
3171
+ "google.com.sl",
3172
+ "google.sn",
3173
+ "google.sm",
3174
+ "google.so",
3175
+ "google.st",
3176
+ "google.com.sv",
3177
+ "google.td",
3178
+ "google.tg",
3179
+ "google.co.th",
3180
+ "google.com.tj",
3181
+ "google.tk",
3182
+ "google.tl",
3183
+ "google.tm",
3184
+ "google.to",
3185
+ "google.com.tn",
3186
+ "google.com.tr",
3187
+ "google.tt",
3188
+ "google.com.tw",
3189
+ "google.co.tz",
3190
+ "google.com.ua",
3191
+ "google.co.ug",
3192
+ "google.ae",
3193
+ "google.co.uk",
3194
+ "google.us",
3195
+ "google.com.uy",
3196
+ "google.co.uz",
3197
+ "google.com.vc",
3198
+ "google.co.ve",
3199
+ "google.vg",
3200
+ "google.co.vi",
3201
+ "google.com.vn",
3202
+ "google.vu",
3203
+ "google.ws",
3204
+ "google.co.za",
3205
+ "google.co.zm",
3206
+ "google.co.zw",
3207
+ "search.avg.com",
3208
+ "isearch.avg.com",
3209
+ "www.cnn.com",
3210
+ "darkoogle.com",
3211
+ "search.darkoogle.com",
3212
+ "search.foxtab.com",
3213
+ "www.gooofullsearch.com",
3214
+ "search.hiyo.com",
3215
+ "search.incredimail.com",
3216
+ "search1.incredimail.com",
3217
+ "search2.incredimail.com",
3218
+ "search3.incredimail.com",
3219
+ "search4.incredimail.com",
3220
+ "search.incredibar.com",
3221
+ "search.sweetim.com",
3222
+ "www.fastweb.it",
3223
+ "search.juno.com",
3224
+ "find.tdc.dk",
3225
+ "searchresults.verizon.com",
3226
+ "search.walla.co.il",
3227
+ "search.alot.com",
3228
+ "www.googleearth.de",
3229
+ "www.googleearth.fr",
3230
+ "webcache.googleusercontent.com",
3231
+ "encrypted.google.com",
3232
+ "googlesyndicatedsearch.com"
3233
+ ],
3234
+ "parameters": [
3235
+ "q",
3236
+ "query",
3237
+ "Keywords"
3238
+ ]
3239
+ },
3240
+ "Google Blogsearch": {
3241
+ "domains": [
3242
+ "blogsearch.google.ac",
3243
+ "blogsearch.google.ad",
3244
+ "blogsearch.google.ae",
3245
+ "blogsearch.google.am",
3246
+ "blogsearch.google.as",
3247
+ "blogsearch.google.at",
3248
+ "blogsearch.google.az",
3249
+ "blogsearch.google.ba",
3250
+ "blogsearch.google.be",
3251
+ "blogsearch.google.bf",
3252
+ "blogsearch.google.bg",
3253
+ "blogsearch.google.bi",
3254
+ "blogsearch.google.bj",
3255
+ "blogsearch.google.bs",
3256
+ "blogsearch.google.by",
3257
+ "blogsearch.google.ca",
3258
+ "blogsearch.google.cat",
3259
+ "blogsearch.google.cc",
3260
+ "blogsearch.google.cd",
3261
+ "blogsearch.google.cf",
3262
+ "blogsearch.google.cg",
3263
+ "blogsearch.google.ch",
3264
+ "blogsearch.google.ci",
3265
+ "blogsearch.google.cl",
3266
+ "blogsearch.google.cm",
3267
+ "blogsearch.google.cn",
3268
+ "blogsearch.google.co.bw",
3269
+ "blogsearch.google.co.ck",
3270
+ "blogsearch.google.co.cr",
3271
+ "blogsearch.google.co.id",
3272
+ "blogsearch.google.co.il",
3273
+ "blogsearch.google.co.in",
3274
+ "blogsearch.google.co.jp",
3275
+ "blogsearch.google.co.ke",
3276
+ "blogsearch.google.co.kr",
3277
+ "blogsearch.google.co.ls",
3278
+ "blogsearch.google.co.ma",
3279
+ "blogsearch.google.co.mz",
3280
+ "blogsearch.google.co.nz",
3281
+ "blogsearch.google.co.th",
3282
+ "blogsearch.google.co.tz",
3283
+ "blogsearch.google.co.ug",
3284
+ "blogsearch.google.co.uk",
3285
+ "blogsearch.google.co.uz",
3286
+ "blogsearch.google.co.ve",
3287
+ "blogsearch.google.co.vi",
3288
+ "blogsearch.google.co.za",
3289
+ "blogsearch.google.co.zm",
3290
+ "blogsearch.google.co.zw",
3291
+ "blogsearch.google.com",
3292
+ "blogsearch.google.com.af",
3293
+ "blogsearch.google.com.ag",
3294
+ "blogsearch.google.com.ai",
3295
+ "blogsearch.google.com.ar",
3296
+ "blogsearch.google.com.au",
3297
+ "blogsearch.google.com.bd",
3298
+ "blogsearch.google.com.bh",
3299
+ "blogsearch.google.com.bn",
3300
+ "blogsearch.google.com.bo",
3301
+ "blogsearch.google.com.br",
3302
+ "blogsearch.google.com.by",
3303
+ "blogsearch.google.com.bz",
3304
+ "blogsearch.google.com.co",
3305
+ "blogsearch.google.com.cu",
3306
+ "blogsearch.google.com.cy",
3307
+ "blogsearch.google.com.do",
3308
+ "blogsearch.google.com.ec",
3309
+ "blogsearch.google.com.eg",
3310
+ "blogsearch.google.com.et",
3311
+ "blogsearch.google.com.fj",
3312
+ "blogsearch.google.com.gh",
3313
+ "blogsearch.google.com.gi",
3314
+ "blogsearch.google.com.gt",
3315
+ "blogsearch.google.com.hk",
3316
+ "blogsearch.google.com.jm",
3317
+ "blogsearch.google.com.kh",
3318
+ "blogsearch.google.com.kh",
3319
+ "blogsearch.google.com.kw",
3320
+ "blogsearch.google.com.lb",
3321
+ "blogsearch.google.com.lc",
3322
+ "blogsearch.google.com.ly",
3323
+ "blogsearch.google.com.mt",
3324
+ "blogsearch.google.com.mx",
3325
+ "blogsearch.google.com.my",
3326
+ "blogsearch.google.com.na",
3327
+ "blogsearch.google.com.nf",
3328
+ "blogsearch.google.com.ng",
3329
+ "blogsearch.google.com.ni",
3330
+ "blogsearch.google.com.np",
3331
+ "blogsearch.google.com.om",
3332
+ "blogsearch.google.com.pa",
3333
+ "blogsearch.google.com.pe",
3334
+ "blogsearch.google.com.ph",
3335
+ "blogsearch.google.com.pk",
3336
+ "blogsearch.google.com.pr",
3337
+ "blogsearch.google.com.py",
3338
+ "blogsearch.google.com.qa",
3339
+ "blogsearch.google.com.sa",
3340
+ "blogsearch.google.com.sb",
3341
+ "blogsearch.google.com.sg",
3342
+ "blogsearch.google.com.sl",
3343
+ "blogsearch.google.com.sv",
3344
+ "blogsearch.google.com.tj",
3345
+ "blogsearch.google.com.tn",
3346
+ "blogsearch.google.com.tr",
3347
+ "blogsearch.google.com.tw",
3348
+ "blogsearch.google.com.ua",
3349
+ "blogsearch.google.com.uy",
3350
+ "blogsearch.google.com.vc",
3351
+ "blogsearch.google.com.vn",
3352
+ "blogsearch.google.cv",
3353
+ "blogsearch.google.cz",
3354
+ "blogsearch.google.de",
3355
+ "blogsearch.google.dj",
3356
+ "blogsearch.google.dk",
3357
+ "blogsearch.google.dm",
3358
+ "blogsearch.google.dz",
3359
+ "blogsearch.google.ee",
3360
+ "blogsearch.google.es",
3361
+ "blogsearch.google.fi",
3362
+ "blogsearch.google.fm",
3363
+ "blogsearch.google.fr",
3364
+ "blogsearch.google.ga",
3365
+ "blogsearch.google.gd",
3366
+ "blogsearch.google.ge",
3367
+ "blogsearch.google.gf",
3368
+ "blogsearch.google.gg",
3369
+ "blogsearch.google.gl",
3370
+ "blogsearch.google.gm",
3371
+ "blogsearch.google.gp",
3372
+ "blogsearch.google.gr",
3373
+ "blogsearch.google.gy",
3374
+ "blogsearch.google.hn",
3375
+ "blogsearch.google.hr",
3376
+ "blogsearch.google.ht",
3377
+ "blogsearch.google.hu",
3378
+ "blogsearch.google.ie",
3379
+ "blogsearch.google.im",
3380
+ "blogsearch.google.io",
3381
+ "blogsearch.google.iq",
3382
+ "blogsearch.google.is",
3383
+ "blogsearch.google.it",
3384
+ "blogsearch.google.it.ao",
3385
+ "blogsearch.google.je",
3386
+ "blogsearch.google.jo",
3387
+ "blogsearch.google.kg",
3388
+ "blogsearch.google.ki",
3389
+ "blogsearch.google.kz",
3390
+ "blogsearch.google.la",
3391
+ "blogsearch.google.li",
3392
+ "blogsearch.google.lk",
3393
+ "blogsearch.google.lt",
3394
+ "blogsearch.google.lu",
3395
+ "blogsearch.google.lv",
3396
+ "blogsearch.google.md",
3397
+ "blogsearch.google.me",
3398
+ "blogsearch.google.mg",
3399
+ "blogsearch.google.mk",
3400
+ "blogsearch.google.ml",
3401
+ "blogsearch.google.mn",
3402
+ "blogsearch.google.ms",
3403
+ "blogsearch.google.mu",
3404
+ "blogsearch.google.mv",
3405
+ "blogsearch.google.mw",
3406
+ "blogsearch.google.ne",
3407
+ "blogsearch.google.nl",
3408
+ "blogsearch.google.no",
3409
+ "blogsearch.google.nr",
3410
+ "blogsearch.google.nu",
3411
+ "blogsearch.google.pl",
3412
+ "blogsearch.google.pn",
3413
+ "blogsearch.google.ps",
3414
+ "blogsearch.google.pt",
3415
+ "blogsearch.google.ro",
3416
+ "blogsearch.google.rs",
3417
+ "blogsearch.google.ru",
3418
+ "blogsearch.google.rw",
3419
+ "blogsearch.google.sc",
3420
+ "blogsearch.google.se",
3421
+ "blogsearch.google.sh",
3422
+ "blogsearch.google.si",
3423
+ "blogsearch.google.sk",
3424
+ "blogsearch.google.sm",
3425
+ "blogsearch.google.sn",
3426
+ "blogsearch.google.so",
3427
+ "blogsearch.google.st",
3428
+ "blogsearch.google.td",
3429
+ "blogsearch.google.tg",
3430
+ "blogsearch.google.tk",
3431
+ "blogsearch.google.tl",
3432
+ "blogsearch.google.tm",
3433
+ "blogsearch.google.to",
3434
+ "blogsearch.google.tt",
3435
+ "blogsearch.google.us",
3436
+ "blogsearch.google.vg",
3437
+ "blogsearch.google.vu",
3438
+ "blogsearch.google.ws"
3439
+ ],
3440
+ "parameters": [
3441
+ "q"
3442
+ ]
3443
+ },
3444
+ "Amazon": {
3445
+ "domains": [
3446
+ "amazon.com",
3447
+ "www.amazon.com"
3448
+ ],
3449
+ "parameters": [
3450
+ "keywords"
3451
+ ]
3452
+ },
3453
+ "Hooseek.com": {
3454
+ "domains": [
3455
+ "www.hooseek.com"
3456
+ ],
3457
+ "parameters": [
3458
+ "recherche"
3459
+ ]
3460
+ },
3461
+ "Dalesearch": {
3462
+ "domains": [
3463
+ "www.dalesearch.com"
3464
+ ],
3465
+ "parameters": [
3466
+ "q"
3467
+ ]
3468
+ },
3469
+ "Alice Adsl": {
3470
+ "domains": [
3471
+ "rechercher.aliceadsl.fr"
3472
+ ],
3473
+ "parameters": [
3474
+ "q"
3475
+ ]
3476
+ },
3477
+ "soso.com": {
3478
+ "domains": [
3479
+ "www.soso.com"
3480
+ ],
3481
+ "parameters": [
3482
+ "w"
3483
+ ]
3484
+ },
3485
+ "Sogou": {
3486
+ "domains": [
3487
+ "www.sougou.com"
3488
+ ],
3489
+ "parameters": [
3490
+ "query"
3491
+ ]
3492
+ },
3493
+ "Hit-Parade": {
3494
+ "domains": [
3495
+ "req.-hit-parade.com",
3496
+ "class.hit-parade.com",
3497
+ "www.hit-parade.com"
3498
+ ],
3499
+ "parameters": [
3500
+ "p7"
3501
+ ]
3502
+ },
3503
+ "SearchCanvas": {
3504
+ "domains": [
3505
+ "www.searchcanvas.com"
3506
+ ],
3507
+ "parameters": [
3508
+ "q"
3509
+ ]
3510
+ },
3511
+ "Interia": {
3512
+ "domains": [
3513
+ "www.google.interia.pl"
3514
+ ],
3515
+ "parameters": [
3516
+ "q"
3517
+ ]
3518
+ },
3519
+ "Tiscali": {
3520
+ "domains": [
3521
+ "search.tiscali.it",
3522
+ "search-dyn.tiscali.it",
3523
+ "hledani.tiscali.cz"
3524
+ ],
3525
+ "parameters": [
3526
+ "q",
3527
+ "key"
3528
+ ]
3529
+ },
3530
+ "Clix": {
3531
+ "domains": [
3532
+ "pesquisa.clix.pt"
3533
+ ],
3534
+ "parameters": [
3535
+ "question"
3536
+ ]
3537
+ }
3538
+ },
3539
+ "email": {
3540
+ "Outlook.com": {
3541
+ "domains": [
3542
+ "mail.live.com"
3543
+ ]
3544
+ },
3545
+ "Orange Webmail": {
3546
+ "domains": [
3547
+ "orange.fr/webmail"
3548
+ ]
3549
+ },
3550
+ "Yahoo! Mail": {
3551
+ "domains": [
3552
+ "mail.yahoo.net",
3553
+ "mail.yahoo.com",
3554
+ "mail.yahoo.co.uk"
3555
+ ]
3556
+ },
3557
+ "Gmail": {
3558
+ "domains": [
3559
+ "mail.google.com"
3560
+ ]
3561
+ }
3562
+ },
3563
+ "social": {
3564
+ "hi5": {
3565
+ "domains": [
3566
+ "hi5.com"
3567
+ ]
3568
+ },
3569
+ "Friendster": {
3570
+ "domains": [
3571
+ "friendster.com"
3572
+ ]
3573
+ },
3574
+ "Weibo": {
3575
+ "domains": [
3576
+ "weibo.com",
3577
+ "t.cn"
3578
+ ]
3579
+ },
3580
+ "Xanga": {
3581
+ "domains": [
3582
+ "xanga.com"
3583
+ ]
3584
+ },
3585
+ "Myspace": {
3586
+ "domains": [
3587
+ "myspace.com"
3588
+ ]
3589
+ },
3590
+ "Buzznet": {
3591
+ "domains": [
3592
+ "wayn.com"
3593
+ ]
3594
+ },
3595
+ "MyLife": {
3596
+ "domains": [
3597
+ "mylife.ru"
3598
+ ]
3599
+ },
3600
+ "Flickr": {
3601
+ "domains": [
3602
+ "flickr.com"
3603
+ ]
3604
+ },
3605
+ "Sonico.com": {
3606
+ "domains": [
3607
+ "sonico.com"
3608
+ ]
3609
+ },
3610
+ "Odnoklassniki": {
3611
+ "domains": [
3612
+ "odnoklassniki.ru"
3613
+ ]
3614
+ },
3615
+ "GitHub": {
3616
+ "domains": [
3617
+ "github.com"
3618
+ ]
3619
+ },
3620
+ "Classmates": {
3621
+ "domains": [
3622
+ "classmates.com"
3623
+ ]
3624
+ },
3625
+ "Friends Reunited": {
3626
+ "domains": [
3627
+ "friendsreunited.com"
3628
+ ]
3629
+ },
3630
+ "Renren": {
3631
+ "domains": [
3632
+ "renren.com"
3633
+ ]
3634
+ },
3635
+ "vKruguDruzei.ru": {
3636
+ "domains": [
3637
+ "vkrugudruzei.ru"
3638
+ ]
3639
+ },
3640
+ "Gaia Online": {
3641
+ "domains": [
3642
+ "gaiaonline.com"
3643
+ ]
3644
+ },
3645
+ "Netlog": {
3646
+ "domains": [
3647
+ "netlog.com"
3648
+ ]
3649
+ },
3650
+ "Orkut": {
3651
+ "domains": [
3652
+ "orkut.com"
3653
+ ]
3654
+ },
3655
+ "MyHeritage": {
3656
+ "domains": [
3657
+ "myheritage.com"
3658
+ ]
3659
+ },
3660
+ "Multiply": {
3661
+ "domains": [
3662
+ "multiply.com"
3663
+ ]
3664
+ },
3665
+ "myYearbook": {
3666
+ "domains": [
3667
+ "myyearbook.com"
3668
+ ]
3669
+ },
3670
+ "WeeWorld": {
3671
+ "domains": [
3672
+ "weeworld.com"
3673
+ ]
3674
+ },
3675
+ "Geni": {
3676
+ "domains": [
3677
+ "geni.com"
3678
+ ]
3679
+ },
3680
+ "SourceForge": {
3681
+ "domains": [
3682
+ "sourceforge.net"
3683
+ ]
3684
+ },
3685
+ "Plaxo": {
3686
+ "domains": [
3687
+ "plaxo.com"
3688
+ ]
3689
+ },
3690
+ "Taringa!": {
3691
+ "domains": [
3692
+ "taringa.net"
3693
+ ]
3694
+ },
3695
+ "Tagged": {
3696
+ "domains": [
3697
+ "login.tagged.com"
3698
+ ]
3699
+ },
3700
+ "XING": {
3701
+ "domains": [
3702
+ "xing.com"
3703
+ ]
3704
+ },
3705
+ "Vkontakte": {
3706
+ "domains": [
3707
+ "vk.com",
3708
+ "vkontakte.ru"
3709
+ ]
3710
+ },
3711
+ "Twitter": {
3712
+ "domains": [
3713
+ "twitter.com",
3714
+ "t.co"
3715
+ ]
3716
+ },
3717
+ "WAYN": {
3718
+ "domains": [
3719
+ "wayn.com"
3720
+ ]
3721
+ },
3722
+ "Tuenti": {
3723
+ "domains": [
3724
+ "tuenti.com"
3725
+ ]
3726
+ },
3727
+ "Mail.ru": {
3728
+ "domains": [
3729
+ "my.mail.ru"
3730
+ ]
3731
+ },
3732
+ "Badoo": {
3733
+ "domains": [
3734
+ "badoo.com"
3735
+ ]
3736
+ },
3737
+ "Habbo": {
3738
+ "domains": [
3739
+ "habbo.com"
3740
+ ]
3741
+ },
3742
+ "Pinterest": {
3743
+ "domains": [
3744
+ "pinterest.com"
3745
+ ]
3746
+ },
3747
+ "LinkedIn": {
3748
+ "domains": [
3749
+ "linkedin.com"
3750
+ ]
3751
+ },
3752
+ "Foursquare": {
3753
+ "domains": [
3754
+ "foursquare.com"
3755
+ ]
3756
+ },
3757
+ "Flixster": {
3758
+ "domains": [
3759
+ "flixster.com"
3760
+ ]
3761
+ },
3762
+ "Windows Live Spaces": {
3763
+ "domains": [
3764
+ "login.live.com"
3765
+ ]
3766
+ },
3767
+ "BlackPlanet": {
3768
+ "domains": [
3769
+ "blackplanet.com"
3770
+ ]
3771
+ },
3772
+ "Cyworld": {
3773
+ "domains": [
3774
+ "global.cyworld.com"
3775
+ ]
3776
+ },
3777
+ "Skyrock": {
3778
+ "domains": [
3779
+ "skyrock.com"
3780
+ ]
3781
+ },
3782
+ "Facebook": {
3783
+ "domains": [
3784
+ "facebook.com",
3785
+ "fb.me"
3786
+ ]
3787
+ },
3788
+ "StudiVZ": {
3789
+ "domains": [
3790
+ "studivz.net"
3791
+ ]
3792
+ },
3793
+ "Fotolog": {
3794
+ "domains": [
3795
+ "fotolog.com"
3796
+ ]
3797
+ },
3798
+ "Google+": {
3799
+ "domains": [
3800
+ "url.google.com",
3801
+ "plus.google.com"
3802
+ ]
3803
+ },
3804
+ "Nasza-klasa.pl": {
3805
+ "domains": [
3806
+ "nk.pl"
3807
+ ]
3808
+ },
3809
+ "Douban": {
3810
+ "domains": [
3811
+ "douban.com"
3812
+ ]
3813
+ },
3814
+ "Bebo": {
3815
+ "domains": [
3816
+ "bebo.com"
3817
+ ]
3818
+ },
3819
+ "Reddit": {
3820
+ "domains": [
3821
+ "reddit.com"
3822
+ ]
3823
+ },
3824
+ "Identi.ca": {
3825
+ "domains": [
3826
+ "identi.ca"
3827
+ ]
3828
+ },
3829
+ "StackOverflow": {
3830
+ "domains": [
3831
+ "stackoverflow.com"
3832
+ ]
3833
+ },
3834
+ "Mixi": {
3835
+ "domains": [
3836
+ "mixi.jp"
3837
+ ]
3838
+ },
3839
+ "StumbleUpon": {
3840
+ "domains": [
3841
+ "stumbleupon.com"
3842
+ ]
3843
+ },
3844
+ "Viadeo": {
3845
+ "domains": [
3846
+ "viadeo.com"
3847
+ ]
3848
+ },
3849
+ "Last.fm": {
3850
+ "domains": [
3851
+ "lastfm.ru"
3852
+ ]
3853
+ },
3854
+ "LiveJournal": {
3855
+ "domains": [
3856
+ "livejournal.ru"
3857
+ ]
3858
+ },
3859
+ "Tumblr": {
3860
+ "domains": [
3861
+ "tumblr.com"
3862
+ ]
3863
+ },
3864
+ "Hacker News": {
3865
+ "domains": [
3866
+ "news.ycombinator.com"
3867
+ ]
3868
+ },
3869
+ "Qzone": {
3870
+ "domains": [
3871
+ "qzone.qq.com"
3872
+ ]
3873
+ },
3874
+ "Hyves": {
3875
+ "domains": [
3876
+ "hyves.nl"
3877
+ ]
3878
+ },
3879
+ "Paper.li": {
3880
+ "domains": [
3881
+ "paper.li"
3882
+ ]
3883
+ },
3884
+ "MoiKrug.ru": {
3885
+ "domains": [
3886
+ "moikrug.ru"
3887
+ ]
3888
+ }
3889
+ }
3890
+ }
shared/tracking/store.lead.php CHANGED
@@ -361,7 +361,7 @@ function inbound_store_lead( $args = array( ) , $return = false ) {
361
  do_action('wpl_store_lead_post', $lead_data );
362
  do_action('lp_store_lead_post', $lead_data );
363
 
364
- if ( defined( 'DOING_AJAX' ) && DOING_AJAX && !$return ) {
365
 
366
  echo $lead_id;
367
  die();
@@ -436,7 +436,7 @@ function inbound_update_common_meta($lead_data)
436
  */
437
  function inbound_update_geolocation_data( $lead_data ) {
438
 
439
- $ip_addresses = get_post_meta( $post->ID , 'wpleads_ip_address', true );
440
  $ip_addresses = json_decode( stripslashes($ip_addresses) , true);
441
 
442
  if (!$ip_addresses) {
@@ -556,11 +556,11 @@ function inbound_load_tracking_cookie( $user_login, $user) {
556
 
557
  $uid = get_post_meta( $results->post->ID , 'wp_leads_uid' , true );
558
 
559
- if (!$uid) {
560
- return;
561
- }
562
-
563
- setcookie( 'wp_lead_uid' , $uid , time() + (20 * 365 * 24 * 60 * 60),'/');
564
  return;
565
  }
566
  }
361
  do_action('wpl_store_lead_post', $lead_data );
362
  do_action('lp_store_lead_post', $lead_data );
363
 
364
+ if ( defined( 'DOING_AJAX' ) && DOING_AJAX && !$return ) {
365
 
366
  echo $lead_id;
367
  die();
436
  */
437
  function inbound_update_geolocation_data( $lead_data ) {
438
 
439
+ $ip_addresses = get_post_meta( $lead_data['lead_id'] , 'wpleads_ip_address', true );
440
  $ip_addresses = json_decode( stripslashes($ip_addresses) , true);
441
 
442
  if (!$ip_addresses) {
556
 
557
  $uid = get_post_meta( $results->post->ID , 'wp_leads_uid' , true );
558
 
559
+ if ($uid) {
560
+ setcookie( 'wp_lead_uid' , $uid , time() + (20 * 365 * 24 * 60 * 60),'/');
561
+ }
562
+
563
+ setcookie( 'wp_lead_id' , $results->post->ID , time() + (20 * 365 * 24 * 60 * 60),'/');
564
  return;
565
  }
566
  }
templates/svtle/index.php CHANGED
@@ -76,9 +76,7 @@ $blue = (isset($RBG_array['b'])) ? $RBG_array['b'] : '0';
76
  <!--[if lt IE 9]>
77
  <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
78
  <![endif]-->
79
- <script type="text/javascript" src="<?php echo $path; ?>assets/js/modernizr.js"></script>
80
- <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
81
- <script type="text/javascript" src="<?php echo $path; ?>assets/js/jquery-picture-min.js"></script>
82
  <style type="text/css">
83
  <?php if ($mobile_form==="on") {
84
  echo "@media (max-width: 630px) { #lp_container {display:none;}}"; // css rule for mobile devices
@@ -125,7 +123,12 @@ $blue = (isset($RBG_array['b'])) ? $RBG_array['b'] : '0';
125
  }
126
 
127
  </style>
128
- <script type="text/javascript">
 
 
 
 
 
129
  jQuery(document).ready(function($) {
130
  $(function () {
131
  $('figure, picture').picture();
@@ -134,8 +137,6 @@ $blue = (isset($RBG_array['b'])) ? $RBG_array['b'] : '0';
134
  jQuery("#river").height(window_size);
135
  });
136
  </script>
137
- <?php wp_head(); // Load Regular WP Head
138
- do_action('lp_head'); // Load Custom Landing Page Specific Header Items ?>
139
  <?php if ($sidebar === "right" ) { echo
140
  "<link rel='stylesheet' href='". $path . "assets/css/flipped-layout.css' type='text/css' media='screen'>"; } ?>
141
  </head>
76
  <!--[if lt IE 9]>
77
  <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
78
  <![endif]-->
79
+
 
 
80
  <style type="text/css">
81
  <?php if ($mobile_form==="on") {
82
  echo "@media (max-width: 630px) { #lp_container {display:none;}}"; // css rule for mobile devices
123
  }
124
 
125
  </style>
126
+
127
+ <?php wp_head(); // Load Regular WP Head
128
+ do_action('lp_head'); // Load Custom Landing Page Specific Header Items ?>
129
+ <script type="text/javascript" src="<?php echo $path; ?>assets/js/modernizr.js"></script>
130
+ <script type="text/javascript" src="<?php echo $path; ?>assets/js/jquery-picture-min.js"></script>
131
+ <script type="text/javascript">
132
  jQuery(document).ready(function($) {
133
  $(function () {
134
  $('figure, picture').picture();
137
  jQuery("#river").height(window_size);
138
  });
139
  </script>
 
 
140
  <?php if ($sidebar === "right" ) { echo
141
  "<link rel='stylesheet' href='". $path . "assets/css/flipped-layout.css' type='text/css' media='screen'>"; } ?>
142
  </head>
templates/tubelar/index.php CHANGED
@@ -76,6 +76,14 @@ $blue = $RBG_array["b"];
76
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
77
  <link href="<?php echo $path; ?>assets/css/screen.css" rel="stylesheet" type="text/css" />
78
  <style type="text/css">
 
 
 
 
 
 
 
 
79
  .black-65 {background: url('<?php echo $path; ?>assets/img/black-65-trans.png');}
80
  <?php if ($sidebar == "lp_left") { echo "#main {float: right;} #sidebar { width: 320px;}"; }?>
81
  <?php if ($textcolor != "") { echo "#wrapper {color: #$textcolor;} #video-controls a {color: #$textcolor;}
76
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
77
  <link href="<?php echo $path; ?>assets/css/screen.css" rel="stylesheet" type="text/css" />
78
  <style type="text/css">
79
+ .inbound-field input[type=text], .inbound-field input[type=url], .inbound-field input[type=email], .inbound-field input[type=tel], .inbound-field input[type=number], .inbound-field input[type=password] {
80
+ width: 93%;
81
+ }
82
+ #inbound_form_submit {
83
+ padding: 10px;
84
+ padding-left: 20px;
85
+ padding-right: 20px;
86
+ }
87
  .black-65 {background: url('<?php echo $path; ?>assets/img/black-65-trans.png');}
88
  <?php if ($sidebar == "lp_left") { echo "#main {float: right;} #sidebar { width: 320px;}"; }?>
89
  <?php if ($textcolor != "") { echo "#wrapper {color: #$textcolor;} #video-controls a {color: #$textcolor;}