Ad Inserter – WordPress Ads Management with AdSense Header Integration - Version 2.4.2

Version Description

  • Added support for visual HTML element selection
  • Fix for client-side insertion inside HTML elements
  • Few minor bug fixes, cosmetic changes and code improvements
Download this release

Release Info

Developer spacetime
Plugin Icon 128x128 Ad Inserter – WordPress Ads Management with AdSense Header Integration
Version 2.4.2
Comparing to
See all releases

Code changes from version 2.4.1 to 2.4.2

ad-inserter.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  /*
4
  Plugin Name: Ad Inserter
5
- Version: 2.4.1
6
  Description: Ad management plugin with many advanced advertising features to insert ads at optimal positions
7
  Author: Igor Funa
8
  Author URI: http://igorfuna.com/
@@ -13,6 +13,11 @@ Plugin URI: https://adinserter.pro/documentation
13
 
14
  Change Log
15
 
 
 
 
 
 
16
  Ad Inserter 2.4.1 - 2018-10-05
17
  - Added option to insert into HTML element (prepend, append, replace content)
18
  - Added option to remove HTML element
@@ -720,7 +725,16 @@ function ai_buffering_end () {
720
  $content_before = '';
721
  $insertions = array ();
722
  foreach ($markers as $marker) {
723
- if (strpos ($marker, AI_MARKER_START) === 0) {
 
 
 
 
 
 
 
 
 
724
  switch ($insertion_position) {
725
  case 'replace-content':
726
  case 'replace-element':
@@ -778,10 +792,9 @@ function ai_buffering_end () {
778
  $content_before = '';
779
  $insertions2 = array ();
780
  foreach ($markers2 as $marker) {
781
- if (strpos ($marker, AI_MARKER_START) === 0) {
782
  $tag = str_replace (array (AI_MARKER_START.'=', '='.AI_MARKER_END), '', $marker);
783
  $tag_string = "</{$tag}>";
784
-
785
  preg_match_all ("#{$tag_string}#i", $content_before, $tag_matches);
786
 
787
  switch ($insertion_position) {
@@ -1111,7 +1124,11 @@ function ai_wp_hook () {
1111
  }
1112
  }
1113
 
1114
- if (($ai_wp_data [AI_WP_USER] & AI_USER_LOGGED_IN) == 0 &&
 
 
 
 
1115
  ((get_remote_debugging () && ($ai_wp_data [AI_WP_DEBUGGING] != 0 || (isset ($_GET [AI_URL_DEBUG]) && $_GET [AI_URL_DEBUG] == 1))) ||
1116
  defined ('AI_DEBUGGING_DEMO'))) {
1117
  function ai_login_adminbar ($wp_admin_bar) {
@@ -1452,6 +1469,7 @@ function ai_wp_enqueue_scripts_hook () {
1452
  $ai_wp_data [AI_STICK_TO_THE_CONTENT] ||
1453
  $ai_wp_data [AI_ANIMATION] ||
1454
  $ai_wp_data [AI_CLOSE_BUTTONS] ||
 
1455
  $ai_wp_data [AI_LAZY_LOADING] ||
1456
  $ai_wp_data [AI_CLIENT_SIDE_INSERTION] ||
1457
  (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION && $ai_wp_data [AI_ADB_DETECTION]);
@@ -1465,9 +1483,24 @@ function ai_wp_enqueue_scripts_hook () {
1465
  $ai_wp_data [AI_ANIMATION]) {
1466
 
1467
  // force loading of jquery on frontend
1468
- wp_enqueue_script ('ai-jquery-js', plugins_url ('includes/js/ai-jquery.js', __FILE__), array (
1469
- 'jquery',
1470
- ), $wp_version . '+' . AD_INSERTER_VERSION);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1471
 
1472
  if ($ai_wp_data [AI_FRONTEND_JS_DEBUGGING]) {
1473
  wp_add_inline_script ('ai-jquery-js', 'ai_debugging = true;');
@@ -1513,6 +1546,7 @@ function add_head_inline_styles_and_scripts () {
1513
  get_dynamic_blocks () == AI_DYNAMIC_BLOCKS_CLIENT_SIDE_SHOW ||
1514
  isset ($ai_wp_data [AI_CLIENT_SIDE_ROTATION]) ||
1515
  $ai_wp_data [AI_CLOSE_BUTTONS] ||
 
1516
  !get_inline_styles () ||
1517
  get_admin_toolbar_debugging () && (get_remote_debugging () || ($ai_wp_data [AI_WP_USER] & AI_USER_LOGGED_IN) != 0) ||
1518
  defined ('AI_DEBUGGING_DEMO') ||
@@ -1549,6 +1583,8 @@ function add_head_inline_styles_and_scripts () {
1549
 
1550
  if ($ai_wp_data [AI_WP_DEBUGGING] != 0) generate_debug_css ();
1551
 
 
 
1552
  if ((get_admin_toolbar_debugging () && (get_remote_debugging () || ($ai_wp_data [AI_WP_USER] & AI_USER_LOGGED_IN) != 0)) || defined ('AI_DEBUGGING_DEMO'))
1553
  echo "#wp-admin-bar-ai-toolbar-settings .ab-icon:before {
1554
  content: '\\f111';
@@ -1693,6 +1729,13 @@ function ai_replace_js_data ($js) {
1693
  }
1694
  }
1695
 
 
 
 
 
 
 
 
1696
  if (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION) {
1697
  if (strpos ($js, 'AI_ADB_STATUS_MESSAGE') !== false) {
1698
  $adb = $block_object [AI_ADB_MESSAGE_OPTION_NAME];
@@ -1729,6 +1772,8 @@ function ai_replace_js_data ($js) {
1729
  $js = str_replace ('AI_NONCE', wp_create_nonce ("adinserter_data"), $js);
1730
  $js = str_replace ('AI_AJAXURL', admin_url ('admin-ajax.php'), $js);
1731
  $js = str_replace ('AI_SITE_URL', wp_make_link_relative (get_site_url()), $js);
 
 
1732
  if (defined ('AI_STATISTICS') && AI_STATISTICS) {
1733
  $js = str_replace ('AI_INTERNAL_TRACKING', get_internal_tracking () == AI_ENABLED ? 1 : 0, $js);
1734
  $js = str_replace ('AI_EXTERNAL_TRACKING', get_external_tracking () == AI_ENABLED ? 1 : 0, $js);
@@ -1791,6 +1836,7 @@ function add_footer_inline_scripts () {
1791
  $ai_wp_data [AI_STICK_TO_THE_CONTENT] ||
1792
  $ai_wp_data [AI_ANIMATION] ||
1793
  $ai_wp_data [AI_CLOSE_BUTTONS] ||
 
1794
  $ai_wp_data [AI_LAZY_LOADING] ||
1795
  $ai_wp_data [AI_CLIENT_SIDE_INSERTION] ||
1796
  (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION && $ai_wp_data [AI_ADB_DETECTION]);
@@ -1837,6 +1883,10 @@ function add_footer_inline_scripts () {
1837
  echo ai_get_js ('ai-close');
1838
  }
1839
 
 
 
 
 
1840
  if ($ai_wp_data [AI_CLIENT_SIDE_INSERTION]) {
1841
  echo 'setTimeout (function() {Array.prototype.forEach.call (document.querySelectorAll (".ai-viewports"), function (element, index) {ai_insert_viewport (element);});}, 10);', PHP_EOL;
1842
  }
@@ -2118,7 +2168,7 @@ function ai_meta_box_callback ($post) {
2118
  AD_INSERTER_NAME, ' Settings</a> page - selection next to <strong>Posts</strong> / <strong>Static pages</strong> checkbox.<br />',
2119
  'Default value is <strong>blank</strong> and means no individual exceptions (even if previously defined here).<br />',
2120
  'Set to <strong>Individually disabled</strong> or <strong>Individually enabled</strong> to enable individual exception settings on this page.<br />',
2121
- 'For more information check <a href="https://adinserter.pro/exceptions" style="text-decoration: none; box-shadow: 0 0 0;" target="_blank">Ad Inserter Exceptions</a>.</p>';
2122
  }
2123
 
2124
  function ai_save_meta_box_data_hook ($post_id) {
@@ -2222,7 +2272,7 @@ function ai_header_noindex () {
2222
 
2223
  function get_code_debug_block ($name, $message, $right_text, $code, $inserted_code, $javascript = false) {
2224
  if (strpos ($code, 'enable_page_level_ads') !== false)
2225
- $message = 'Code for <a style="text-decoration: none; color: #fff; font-weight: bold; box-shadow: none;" href="https://adinserter.pro/adsense-ads#auto-ads" target="_blank">AdSense Auto Ads</a> detected - Code will automatically insert AdSense ads at optimal positions ';
2226
 
2227
  $debug_script = new ai_block_labels ('ai-debug-script');
2228
  $debug_block_start = $debug_script->block_start ();
@@ -4626,7 +4676,6 @@ function generate_alignment_css () {
4626
 
4627
  return $alignment_css;
4628
  }
4629
-
4630
  function generate_debug_css () {
4631
  ?>
4632
 
@@ -4718,6 +4767,65 @@ section.ai-debug-block {padding: 0; margin: 0;}
4718
  <?php
4719
  }
4720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4721
  function ai_settings () {
4722
  global $ai_db_options, $block_object, $wpdb, $ai_db_options_extract;
4723
 
@@ -4936,7 +5044,7 @@ function ai_settings () {
4936
 
4937
  $ai_options [AI_OPTION_GLOBAL]['TIMESTAMP'] = time ();
4938
 
4939
- if (get_option (AI_INSTALL_NAME) === false) {
4940
  update_option (AI_INSTALL_NAME, time ());
4941
  }
4942
 
@@ -6762,6 +6870,7 @@ $ai_wp_data [AI_CLIENT_SIDE_INSERTION] = false;
6762
  $ai_wp_data [AI_LAZY_LOADING] = false;
6763
  $ai_wp_data [AI_PAGE_BLOCKS] = 0;
6764
  $ai_wp_data [AI_GEOLOCATION] = false;
 
6765
 
6766
  ai_load_settings ();
6767
 
@@ -6877,12 +6986,16 @@ if (is_admin () === true) {
6877
  add_action ('wp_ajax_nopriv_ai_ajax', 'ai_ajax');
6878
  }
6879
 
 
 
 
 
6880
  if (defined ('AI_PLUGIN_TRACKING') && AI_PLUGIN_TRACKING) {
6881
  if (!class_exists ('DST_Client')) {
6882
  require_once dirname (__FILE__) . '/includes/dst/dst.php';
6883
  }
6884
 
6885
- if (!function_exists ('ai_start_dst')) {
6886
  function ai_start_dst () {
6887
  global $ai_dst;
6888
 
@@ -6902,6 +7015,7 @@ if (defined ('AI_PLUGIN_TRACKING') && AI_PLUGIN_TRACKING) {
6902
 
6903
  $ai_dst = new DST_Client ($dst_settings);
6904
  }
 
6905
  function ai_notice_text ($text) {
6906
  $text = __('Thank you for installing [STRONG][NAME][/STRONG]. We would like to <a href="https://wordpress.org/plugins/ad-inserter/#what%%20is%%20usage%%20tracking%%3F" target=_blank" style="text-decoration: none; box-shadow: 0 0 0;">track its usage</a> on your site. This is completely optional and can be disabled at any time.[P]
6907
  We don\'t record any sensitive data, only information regarding the WordPress environment and %1$s usage, which will help us to make improvements to the %1$s.', 'ad-inserter');
2
 
3
  /*
4
  Plugin Name: Ad Inserter
5
+ Version: 2.4.2
6
  Description: Ad management plugin with many advanced advertising features to insert ads at optimal positions
7
  Author: Igor Funa
8
  Author URI: http://igorfuna.com/
13
 
14
  Change Log
15
 
16
+ Ad Inserter 2.4.2 - 2018-10-21
17
+ - Added support for visual HTML element selection
18
+ - Fix for client-side insertion inside HTML elements
19
+ - Few minor bug fixes, cosmetic changes and code improvements
20
+
21
  Ad Inserter 2.4.1 - 2018-10-05
22
  - Added option to insert into HTML element (prepend, append, replace content)
23
  - Added option to remove HTML element
725
  $content_before = '';
726
  $insertions = array ();
727
  foreach ($markers as $marker) {
728
+ switch ($insertion_position) {
729
+ case 'replace-content':
730
+ case 'replace-element':
731
+ $marker_start_string = AI_MARKER_START.'-';
732
+ break;
733
+ default:
734
+ $marker_start_string = AI_MARKER_START;
735
+ break;
736
+ }
737
+ if (strpos ($marker, $marker_start_string) === 0) {
738
  switch ($insertion_position) {
739
  case 'replace-content':
740
  case 'replace-element':
792
  $content_before = '';
793
  $insertions2 = array ();
794
  foreach ($markers2 as $marker) {
795
+ if (strpos ($marker, AI_MARKER_START.'=') === 0) {
796
  $tag = str_replace (array (AI_MARKER_START.'=', '='.AI_MARKER_END), '', $marker);
797
  $tag_string = "</{$tag}>";
 
798
  preg_match_all ("#{$tag_string}#i", $content_before, $tag_matches);
799
 
800
  switch ($insertion_position) {
1124
  }
1125
  }
1126
 
1127
+ if ($ai_wp_data [AI_HTML_ELEMENT_SELECTION]) {
1128
+ add_filter ('show_admin_bar', '__return_false', 999999);
1129
+ $ai_wp_data [AI_WP_DEBUGGING] = 0;
1130
+ }
1131
+ elseif (($ai_wp_data [AI_WP_USER] & AI_USER_LOGGED_IN) == 0 &&
1132
  ((get_remote_debugging () && ($ai_wp_data [AI_WP_DEBUGGING] != 0 || (isset ($_GET [AI_URL_DEBUG]) && $_GET [AI_URL_DEBUG] == 1))) ||
1133
  defined ('AI_DEBUGGING_DEMO'))) {
1134
  function ai_login_adminbar ($wp_admin_bar) {
1469
  $ai_wp_data [AI_STICK_TO_THE_CONTENT] ||
1470
  $ai_wp_data [AI_ANIMATION] ||
1471
  $ai_wp_data [AI_CLOSE_BUTTONS] ||
1472
+ $ai_wp_data [AI_HTML_ELEMENT_SELECTION] ||
1473
  $ai_wp_data [AI_LAZY_LOADING] ||
1474
  $ai_wp_data [AI_CLIENT_SIDE_INSERTION] ||
1475
  (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION && $ai_wp_data [AI_ADB_DETECTION]);
1483
  $ai_wp_data [AI_ANIMATION]) {
1484
 
1485
  // force loading of jquery on frontend
1486
+ $jquery_required = array (
1487
+ 'jquery'
1488
+ );
1489
+ if ($ai_wp_data [AI_HTML_ELEMENT_SELECTION]) {
1490
+ $jquery_required []= 'jquery-ui-button';
1491
+ }
1492
+ wp_enqueue_script ('ai-jquery-js', plugins_url ('includes/js/ai-jquery.js', __FILE__), $jquery_required, $wp_version . '+' . AD_INSERTER_VERSION);
1493
+
1494
+ if ($ai_wp_data [AI_HTML_ELEMENT_SELECTION]) {
1495
+ $wp_scripts = wp_scripts();
1496
+ wp_enqueue_style (
1497
+ 'jquery-ui-theme-smoothness',
1498
+ sprintf (
1499
+ '//ajax.googleapis.com/ajax/libs/jqueryui/%s/themes/smoothness/jquery-ui.css',
1500
+ $wp_scripts->registered ['jquery-ui-core']->ver
1501
+ )
1502
+ );
1503
+ }
1504
 
1505
  if ($ai_wp_data [AI_FRONTEND_JS_DEBUGGING]) {
1506
  wp_add_inline_script ('ai-jquery-js', 'ai_debugging = true;');
1546
  get_dynamic_blocks () == AI_DYNAMIC_BLOCKS_CLIENT_SIDE_SHOW ||
1547
  isset ($ai_wp_data [AI_CLIENT_SIDE_ROTATION]) ||
1548
  $ai_wp_data [AI_CLOSE_BUTTONS] ||
1549
+ $ai_wp_data [AI_HTML_ELEMENT_SELECTION] ||
1550
  !get_inline_styles () ||
1551
  get_admin_toolbar_debugging () && (get_remote_debugging () || ($ai_wp_data [AI_WP_USER] & AI_USER_LOGGED_IN) != 0) ||
1552
  defined ('AI_DEBUGGING_DEMO') ||
1583
 
1584
  if ($ai_wp_data [AI_WP_DEBUGGING] != 0) generate_debug_css ();
1585
 
1586
+ if ($ai_wp_data [AI_HTML_ELEMENT_SELECTION]) generate_selection_css ();
1587
+
1588
  if ((get_admin_toolbar_debugging () && (get_remote_debugging () || ($ai_wp_data [AI_WP_USER] & AI_USER_LOGGED_IN) != 0)) || defined ('AI_DEBUGGING_DEMO'))
1589
  echo "#wp-admin-bar-ai-toolbar-settings .ab-icon:before {
1590
  content: '\\f111';
1729
  }
1730
  }
1731
 
1732
+ if (preg_match_all ('/AI_POST_([_A-Z0-9]+)/', $js, $match)) {
1733
+ foreach ($match [1] as $index => $post) {
1734
+ $post_name = strtolower ($post);
1735
+ $js = str_replace ($match [0][$index], isset ($_POST [$post_name]) ? urldecode ($_POST [$post_name]) : '', $js);
1736
+ }
1737
+ }
1738
+
1739
  if (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION) {
1740
  if (strpos ($js, 'AI_ADB_STATUS_MESSAGE') !== false) {
1741
  $adb = $block_object [AI_ADB_MESSAGE_OPTION_NAME];
1772
  $js = str_replace ('AI_NONCE', wp_create_nonce ("adinserter_data"), $js);
1773
  $js = str_replace ('AI_AJAXURL', admin_url ('admin-ajax.php'), $js);
1774
  $js = str_replace ('AI_SITE_URL', wp_make_link_relative (get_site_url()), $js);
1775
+ $js = str_replace ('AI_HOME_URL', home_url (), $js);
1776
+
1777
  if (defined ('AI_STATISTICS') && AI_STATISTICS) {
1778
  $js = str_replace ('AI_INTERNAL_TRACKING', get_internal_tracking () == AI_ENABLED ? 1 : 0, $js);
1779
  $js = str_replace ('AI_EXTERNAL_TRACKING', get_external_tracking () == AI_ENABLED ? 1 : 0, $js);
1836
  $ai_wp_data [AI_STICK_TO_THE_CONTENT] ||
1837
  $ai_wp_data [AI_ANIMATION] ||
1838
  $ai_wp_data [AI_CLOSE_BUTTONS] ||
1839
+ $ai_wp_data [AI_HTML_ELEMENT_SELECTION] ||
1840
  $ai_wp_data [AI_LAZY_LOADING] ||
1841
  $ai_wp_data [AI_CLIENT_SIDE_INSERTION] ||
1842
  (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION && $ai_wp_data [AI_ADB_DETECTION]);
1883
  echo ai_get_js ('ai-close');
1884
  }
1885
 
1886
+ if ($ai_wp_data [AI_HTML_ELEMENT_SELECTION]) {
1887
+ echo ai_get_js ('ai-select');
1888
+ }
1889
+
1890
  if ($ai_wp_data [AI_CLIENT_SIDE_INSERTION]) {
1891
  echo 'setTimeout (function() {Array.prototype.forEach.call (document.querySelectorAll (".ai-viewports"), function (element, index) {ai_insert_viewport (element);});}, 10);', PHP_EOL;
1892
  }
2168
  AD_INSERTER_NAME, ' Settings</a> page - selection next to <strong>Posts</strong> / <strong>Static pages</strong> checkbox.<br />',
2169
  'Default value is <strong>blank</strong> and means no individual exceptions (even if previously defined here).<br />',
2170
  'Set to <strong>Individually disabled</strong> or <strong>Individually enabled</strong> to enable individual exception settings on this page.<br />',
2171
+ 'For more information check <a href="https://adinserter.pro/documentation/individual-post-and-page-exceptions" style="text-decoration: none; box-shadow: 0 0 0;" target="_blank">Ad Inserter Exceptions</a>.</p>';
2172
  }
2173
 
2174
  function ai_save_meta_box_data_hook ($post_id) {
2272
 
2273
  function get_code_debug_block ($name, $message, $right_text, $code, $inserted_code, $javascript = false) {
2274
  if (strpos ($code, 'enable_page_level_ads') !== false)
2275
+ $message = 'Code for <a style="text-decoration: none; color: #fff; font-weight: bold; box-shadow: none;" href="https://adinserter.pro/documentation/adsense-ads#auto-ads" target="_blank">AdSense Auto Ads</a> detected - Code will automatically insert AdSense ads at optimal positions ';
2276
 
2277
  $debug_script = new ai_block_labels ('ai-debug-script');
2278
  $debug_block_start = $debug_script->block_start ();
4676
 
4677
  return $alignment_css;
4678
  }
 
4679
  function generate_debug_css () {
4680
  ?>
4681
 
4767
  <?php
4768
  }
4769
 
4770
+ function generate_selection_css () {
4771
+ ?>
4772
+ #ai-selector-data {
4773
+ position: fixed;
4774
+ top: 0;
4775
+ z-index: 999999;
4776
+ background: #fff;
4777
+ width: 100%;
4778
+ border: 1px solid #000;
4779
+ }
4780
+ #ai-selector-data table {
4781
+ width: 100%;
4782
+ margin: 5px;
4783
+ }
4784
+ #ai-selector-data td {
4785
+ padding: 5px 10px;
4786
+ vertical-align: middle;
4787
+ }
4788
+ #ai-selector-data td button {
4789
+ margin: 0 15px;
4790
+ }
4791
+ #ai-selector-data .ui-button-text-only .ui-button-text {
4792
+ padding: 3px 10px;
4793
+ }
4794
+ #ai-selector-data td.data-name {
4795
+ width: 100px;
4796
+ }
4797
+ #ai-selector-element, #ai-selector-path {
4798
+ user-select: text;
4799
+ }
4800
+ #ai-selector {
4801
+ width: 100%;
4802
+ display: inline-block;
4803
+ border-radius: 4px;
4804
+ font-size: 12px;
4805
+ font-family: Courier, 'Courier New', monospace;
4806
+ font-weight: bold;
4807
+ }
4808
+ .ai-highlighted {
4809
+ outline: 3px dashed #00f;
4810
+ background: rgba(50, 140, 220, 0.2);
4811
+ cursor: default;
4812
+ }
4813
+ .ai-selected {
4814
+ outline: 3px dashed #f00;
4815
+ background: rgba(255, 0, 0, 0.2);
4816
+ }
4817
+ .ai-highlighted.ai-selected {
4818
+ }
4819
+ .ai-html-element {
4820
+ color: #00a;
4821
+ cursor: pointer;
4822
+ }
4823
+ .ai-html-element:hover {
4824
+ color: #00f;
4825
+ }
4826
+ <?php
4827
+ }
4828
+
4829
  function ai_settings () {
4830
  global $ai_db_options, $block_object, $wpdb, $ai_db_options_extract;
4831
 
5044
 
5045
  $ai_options [AI_OPTION_GLOBAL]['TIMESTAMP'] = time ();
5046
 
5047
+ if (!get_option (AI_INSTALL_NAME)) {
5048
  update_option (AI_INSTALL_NAME, time ());
5049
  }
5050
 
6870
  $ai_wp_data [AI_LAZY_LOADING] = false;
6871
  $ai_wp_data [AI_PAGE_BLOCKS] = 0;
6872
  $ai_wp_data [AI_GEOLOCATION] = false;
6873
+ $ai_wp_data [AI_HTML_ELEMENT_SELECTION] = isset ($_POST ['html_element_selection']) ? $_POST ['html_element_selection'] : false;
6874
 
6875
  ai_load_settings ();
6876
 
6986
  add_action ('wp_ajax_nopriv_ai_ajax', 'ai_ajax');
6987
  }
6988
 
6989
+ if (!get_option (AI_INSTALL_NAME)) {
6990
+ update_option (AI_INSTALL_NAME, time ());
6991
+ }
6992
+
6993
  if (defined ('AI_PLUGIN_TRACKING') && AI_PLUGIN_TRACKING) {
6994
  if (!class_exists ('DST_Client')) {
6995
  require_once dirname (__FILE__) . '/includes/dst/dst.php';
6996
  }
6997
 
6998
+ if (!function_exists ('ai_start_dst') && defined ('DST_Client::DST_FILTER_OPTIONS')) {
6999
  function ai_start_dst () {
7000
  global $ai_dst;
7001
 
7015
 
7016
  $ai_dst = new DST_Client ($dst_settings);
7017
  }
7018
+
7019
  function ai_notice_text ($text) {
7020
  $text = __('Thank you for installing [STRONG][NAME][/STRONG]. We would like to <a href="https://wordpress.org/plugins/ad-inserter/#what%%20is%%20usage%%20tracking%%3F" target=_blank" style="text-decoration: none; box-shadow: 0 0 0;">track its usage</a> on your site. This is completely optional and can be disabled at any time.[P]
7021
  We don\'t record any sensitive data, only information regarding the WordPress environment and %1$s usage, which will help us to make improvements to the %1$s.', 'ad-inserter');
changelog.txt CHANGED
@@ -2,6 +2,104 @@
2
 
3
  This is an archive of older changelog entries. Most recent entries are maintained in readme.txt
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  = 2.2.16 =
6
  - Fix for error when saving settings on multisite installation
7
 
2
 
3
  This is an archive of older changelog entries. Most recent entries are maintained in readme.txt
4
 
5
+
6
+ = 2.3.16 =
7
+ - Added option to insert block only when WP loop is currently active
8
+ - Added support for Better AMP plugin
9
+ - Code generator for placeholders on https sites now generates https urls
10
+ - Optimized loading of plugin settings
11
+ - Few minor bug fixes, cosmetic changes and code improvements
12
+
13
+ = 2.3.15 =
14
+ - Fix for insertion on AMP pages
15
+
16
+ = 2.3.14 =
17
+ - Simplified AdSense integration
18
+ - Added setting to define maximum number of blocks (ads) per page
19
+ - Optimized the_content filter processing
20
+ - Added setting for lazy loading offset (Pro only)
21
+ - Fix for url parameter list when using client-side dynamic blocks
22
+ - Few minor bug fixes, cosmetic changes and code improvements
23
+
24
+ = 2.3.13 =
25
+ - Added support for lazy loading (Pro only)
26
+ - Fix for unwanted insertions with some paragraph settings
27
+ - Few minor bug fixes, cosmetic changes and code improvements
28
+
29
+ = 2.3.12 =
30
+ - Fix for urlencode error
31
+ - Few other minor bug fixes
32
+
33
+ = 2.3.11 =
34
+ - Added support for W3TC/client-side check for cookies (in url parameter list) to support showing ads based on visitor's cookie consent
35
+ - Added support for W3TC/client-side check for referers
36
+ - Improved paragraph processing
37
+ - Few minor bug fixes, cosmetic changes and code improvements
38
+
39
+ = 2.3.10 =
40
+ - Added support for timed rotation
41
+ - Added support for client-side insertion of dynamic blocks
42
+ - Improved word count function
43
+ - Few minor bug fixes, cosmetic changes and code improvements
44
+
45
+ = 2.3.9 =
46
+ - Added option to easily disable insertion of individual code block
47
+ - Changes for compatibility with PHP 7.2
48
+ - Added non-interaction parameter to external tracking (Pro only)
49
+ - Few minor bug fixes, cosmetic changes and code improvements
50
+
51
+ = 2.3.8 =
52
+ - Added support for rotation option shares
53
+ - Added support for sticky ad settings and animations (Pro only)
54
+ - Few minor bug fixes, cosmetic changes and code improvements
55
+
56
+ = 2.3.7 =
57
+ - Added support for ad labels
58
+ - Blocked search indexing while debugging
59
+ - Close button setting moved to tab Display (Pro only)
60
+ - Few minor bug fixes, cosmetic changes and code improvements
61
+
62
+ = 2.3.6 =
63
+ - Added widget for debugging tools
64
+ - Fix for AdSense ad overlays not displayed with some themes
65
+ - Few minor bug fixes, cosmetic changes and code improvements
66
+
67
+ = 2.3.5 =
68
+ - Added display of header and footer code in Label blocks debugging function
69
+ - Added AdSense ad overlays in Label blocks debugging function (experimental)
70
+ - Fixed bug for removed square brackets in HTML element selectors
71
+ - Fixed preview of AdSense ad units
72
+ - Few minor bug fixes
73
+
74
+ = 2.3.4 =
75
+ - Added support for author:author-username items in taxonomy list
76
+ - Fixed errors when downgrading from Pro
77
+ - Few minor bug fixes
78
+
79
+ = 2.3.3 =
80
+ - Added list editors
81
+ - Added Label blocks debugging function for AdSense Auto ads
82
+
83
+ = 2.3.2 =
84
+ - Added AdSense code generator for ad sizes using CSS media queries
85
+ - Fix for slow updates caused by changed user agent (Pro only, credits Olivier Langlois)
86
+ - Fix for client-side insertion of non-English characters before/after HTML element
87
+
88
+ = 2.3.1 =
89
+ - Added support for server-side insertion before/after any HTML element
90
+ - Few minor bug fixes
91
+
92
+ = 2.3.0 =
93
+ - Added support for client-side insertion before/after any HTML element
94
+ - Inplemented AdSense integration
95
+ - Added option to define close button position
96
+ - Fix for code generator import and code preview error with non ASCII characters
97
+ - Fix for post/page exceptions and page types not processed in the header
98
+ - Fix for close button in preview window
99
+ - Fix for errors when rearranging blocks
100
+ - Fix for errors when importing code
101
+ - Few minor bug fixes, cosmetic changes and code improvements
102
+
103
  = 2.2.16 =
104
  - Fix for error when saving settings on multisite installation
105
 
constants.php CHANGED
@@ -29,7 +29,7 @@ if (!defined( 'AD_INSERTER_NAME'))
29
  define ('AD_INSERTER_NAME', 'Ad Inserter');
30
 
31
  if (!defined( 'AD_INSERTER_VERSION'))
32
- define ('AD_INSERTER_VERSION', '2.4.1');
33
 
34
  if (!defined ('AD_INSERTER_PLUGIN_BASENAME'))
35
  define ('AD_INSERTER_PLUGIN_BASENAME', plugin_basename (__FILE__));
@@ -859,6 +859,7 @@ define ('AI_CLIENT_SIDE_CSS', 36);
859
  define ('AI_LAZY_LOADING', 37);
860
  define ('AI_PAGE_BLOCKS', 38);
861
  define ('AI_GEOLOCATION', 39);
 
862
 
863
  define ('AI_CONTEXT_NONE', 0);
864
  define ('AI_CONTEXT_CONTENT', 1);
29
  define ('AD_INSERTER_NAME', 'Ad Inserter');
30
 
31
  if (!defined( 'AD_INSERTER_VERSION'))
32
+ define ('AD_INSERTER_VERSION', '2.4.2');
33
 
34
  if (!defined ('AD_INSERTER_PLUGIN_BASENAME'))
35
  define ('AD_INSERTER_PLUGIN_BASENAME', plugin_basename (__FILE__));
859
  define ('AI_LAZY_LOADING', 37);
860
  define ('AI_PAGE_BLOCKS', 38);
861
  define ('AI_GEOLOCATION', 39);
862
+ define ('AI_HTML_ELEMENT_SELECTION', 40);
863
 
864
  define ('AI_CONTEXT_NONE', 0);
865
  define ('AI_CONTEXT_CONTENT', 1);
css/ad-inserter.css CHANGED
@@ -1,5 +1,5 @@
1
  #ai-data {
2
- font-family: "2.4.1"; /* Used for version number of the file */
3
  }
4
 
5
  #blocked-warning {
1
  #ai-data {
2
+ font-family: "2.4.2"; /* Used for version number of the file */
3
  }
4
 
5
  #blocked-warning {
includes/dst/dst.php CHANGED
@@ -12,6 +12,9 @@
12
 
13
  Change Log
14
 
 
 
 
15
  DST 1.0.3 - 2018-10-02
16
  - Added option to not show deactivation form again
17
  - Fix to support notice HTML
@@ -81,6 +84,7 @@ class DST_Client {
81
  const DST_TRANSIENT_ADMIN_IP = 'dst_admin_ip';
82
  const DST_TRANSIENT_ADMIN_IP_CACHE_TIME = 10368000;
83
  const DST_TRANSIENT_LAST_ACTION = 'dst_last_action_';
 
84
 
85
  const DST_OPTION_OPTIN_TRACKING = 'dst_optin_tracking';
86
  const DST_OPTION_OPTIN_NEWSLETTER = 'dst_optin_newsletter';
@@ -137,7 +141,7 @@ class DST_Client {
137
  self::DST_OPTION_HIDE_DEACTIVATION_FORM,
138
  );
139
 
140
- private $version = '1.0.3';
141
  private $tracking_url;
142
  private $main_file;
143
  private $slug;
@@ -265,6 +269,14 @@ class DST_Client {
265
 
266
  $this->check_schedule ();
267
 
 
 
 
 
 
 
 
 
268
  if ($this->product_type == self::DST_PRODUCT_TYPE_THEME) {
269
  if ($activation_time = get_transient (self::DST_TRANSIENT_THEME_ACTIVATED . $this->slug)) {
270
  $this->log_event ('THEME ACTIVATED ' .(time () - $activation_time) . ' s ago');
@@ -353,6 +365,7 @@ class DST_Client {
353
  delete_transient (self::DST_TRANSIENT_THEME_ACTIVATED . $this->slug);
354
  delete_transient (self::DST_TRANSIENT_ADMIN_IP);
355
  delete_transient (self::DST_TRANSIENT_LAST_ACTION . $this->slug);
 
356
 
357
  if ($this->product_type == self::DST_PRODUCT_TYPE_THEME) {
358
  remove_theme_mod (self::DST_THEME_MOD_ALLOW_TRACKING);
@@ -384,6 +397,7 @@ class DST_Client {
384
  if ($plugin == $this_plugin) {
385
  $this->action = self::DST_ACTION_UPGRADE;
386
  $this->update (true);
 
387
  break;
388
  }
389
  }
@@ -393,6 +407,7 @@ class DST_Client {
393
  if ($theme == $this->slug) {
394
  $this->action = self::DST_ACTION_UPGRADE;
395
  $this->update (true);
 
396
  break;
397
  }
398
  }
@@ -1272,9 +1287,12 @@ jQuery (document).ready (function ($) {
1272
  color: #fff;
1273
  }
1274
  @media (max-width: 768px) {
1275
- .dst-deactivation-form-footer .button.secondary {
1276
  padding: 6px 6px;
1277
  }
 
 
 
1278
  .row-actions span .dst-deactivation-form {
1279
  padding-top: 0;
1280
  }
12
 
13
  Change Log
14
 
15
+ DST 1.0.4 - 2018-10-05
16
+ - Added additional update after upgrade event
17
+
18
  DST 1.0.3 - 2018-10-02
19
  - Added option to not show deactivation form again
20
  - Fix to support notice HTML
84
  const DST_TRANSIENT_ADMIN_IP = 'dst_admin_ip';
85
  const DST_TRANSIENT_ADMIN_IP_CACHE_TIME = 10368000;
86
  const DST_TRANSIENT_LAST_ACTION = 'dst_last_action_';
87
+ const DST_TRANSIENT_UPGRADED = 'dst_upgraded_';
88
 
89
  const DST_OPTION_OPTIN_TRACKING = 'dst_optin_tracking';
90
  const DST_OPTION_OPTIN_NEWSLETTER = 'dst_optin_newsletter';
141
  self::DST_OPTION_HIDE_DEACTIVATION_FORM,
142
  );
143
 
144
+ private $version = '1.0.4';
145
  private $tracking_url;
146
  private $main_file;
147
  private $slug;
269
 
270
  $this->check_schedule ();
271
 
272
+ if ($upgrade_time = get_transient (self::DST_TRANSIENT_UPGRADED . $this->slug)) {
273
+ $this->log_event ('UPGRADED ' .(time () - $upgrade_time) . ' s ago');
274
+
275
+ delete_transient (self::DST_TRANSIENT_UPGRADED . $this->slug);
276
+ $this->action = self::DST_ACTION_UPGRADE;
277
+ $this->update (true);
278
+ }
279
+
280
  if ($this->product_type == self::DST_PRODUCT_TYPE_THEME) {
281
  if ($activation_time = get_transient (self::DST_TRANSIENT_THEME_ACTIVATED . $this->slug)) {
282
  $this->log_event ('THEME ACTIVATED ' .(time () - $activation_time) . ' s ago');
365
  delete_transient (self::DST_TRANSIENT_THEME_ACTIVATED . $this->slug);
366
  delete_transient (self::DST_TRANSIENT_ADMIN_IP);
367
  delete_transient (self::DST_TRANSIENT_LAST_ACTION . $this->slug);
368
+ delete_transient (self::DST_TRANSIENT_UPGRADED . $this->slug);
369
 
370
  if ($this->product_type == self::DST_PRODUCT_TYPE_THEME) {
371
  remove_theme_mod (self::DST_THEME_MOD_ALLOW_TRACKING);
397
  if ($plugin == $this_plugin) {
398
  $this->action = self::DST_ACTION_UPGRADE;
399
  $this->update (true);
400
+ set_transient (self::DST_TRANSIENT_UPGRADED . $this->slug, time (), 60);
401
  break;
402
  }
403
  }
407
  if ($theme == $this->slug) {
408
  $this->action = self::DST_ACTION_UPGRADE;
409
  $this->update (true);
410
+ set_transient (self::DST_TRANSIENT_UPGRADED . $this->slug, time (), 60);
411
  break;
412
  }
413
  }
1287
  color: #fff;
1288
  }
1289
  @media (max-width: 768px) {
1290
+ .dst-deactivation-form-footer .button.primary {
1291
  padding: 6px 6px;
1292
  }
1293
+ .dst-deactivation-form-footer .button.secondary {
1294
+ padding: 6px 5px;
1295
+ }
1296
  .row-actions span .dst-deactivation-form {
1297
  padding-top: 0;
1298
  }
includes/js/ai-insert.js CHANGED
@@ -31,14 +31,21 @@ function ai_insert (insertion, selector, insertion_code) {
31
  } else
32
  if (insertion == 'after') {
33
  element.parentNode.insertBefore (fragment, element.nextSibling);
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
 
36
- // before first child
37
- // element.insertBefore (fragment, element.firstChild);
38
-
39
- // after last child
40
- // element.insertBefore (fragment, null);
41
-
42
  if (ai_debug) console.log ('AI INSERT', insertion, selector, '(' + element.tagName.toLowerCase() + selector_string + ')');
43
  });
44
  }
31
  } else
32
  if (insertion == 'after') {
33
  element.parentNode.insertBefore (fragment, element.nextSibling);
34
+ } else
35
+ if (insertion == 'prepend') {
36
+ element.insertBefore (fragment, element.firstChild);
37
+ } else
38
+ if (insertion == 'append') {
39
+ element.insertBefore (fragment, null);
40
+ } else
41
+ if (insertion == 'replace-content') {
42
+ element.innerHTML = template.innerHTML;
43
+ } else
44
+ if (insertion == 'replace-element') {
45
+ element.parentNode.insertBefore (fragment, element);
46
+ element.parentNode.removeChild (element);
47
  }
48
 
 
 
 
 
 
 
49
  if (ai_debug) console.log ('AI INSERT', insertion, selector, '(' + element.tagName.toLowerCase() + selector_string + ')');
50
  });
51
  }
includes/js/ai-insert.min.js CHANGED
@@ -1,8 +1,9 @@
1
- function ai_insert(insertion,selector,insertion_code){Array.prototype.forEach.call(document.querySelectorAll(selector),function(element,index){var ai_debug=typeof ai_debugging!=="undefined";if(element.hasAttribute("id"))selector_string="#"+element.getAttribute("id");else if(element.hasAttribute("class"))selector_string="."+element.getAttribute("class").replace(new RegExp(" ","g"),".");else selector_string="";var template=document.createElement("div");template.innerHTML=insertion_code;var ai_selector_counter=
2
- template.getElementsByClassName("ai-selector-counter")[0];if(ai_selector_counter!=null)ai_selector_counter.innerText=index+1;var ai_debug_name_ai_main=template.getElementsByClassName("ai-debug-name ai-main")[0];if(ai_debug_name_ai_main!=null)ai_debug_name_ai_main.innerText=insertion.toUpperCase()+" "+selector+" ("+element.tagName.toLowerCase()+selector_string+")";var range=document.createRange();var fragment=range.createContextualFragment(template.innerHTML);if(insertion=="before")element.parentNode.insertBefore(fragment,
3
- element);else if(insertion=="after")element.parentNode.insertBefore(fragment,element.nextSibling);if(ai_debug)console.log("AI INSERT",insertion,selector,"("+element.tagName.toLowerCase()+selector_string+")")})}
4
- function ai_insert_viewport(element){function hasClass(element,cls){if(element==null)return false;if(element.classList)return element.classList.contains(cls);else return(" "+element.className+" ").indexOf(" "+cls+" ")>-1}function addClass(element,cls){if(element==null)return;if(element.classList)element.classList.add(cls);else element.className+=" "+cls}function removeClass(element,cls){if(element==null)return;if(element.classList)element.classList.remove(cls);else element.className=element.className.replace(new RegExp("(^|\\b)"+
5
- cls.split(" ").join("|")+"(\\b|$)","gi")," ")}var ai_debug=typeof ai_debugging!=="undefined";if(ai_debug)console.log("AI VIEWPORT INSERTION:","class='"+element.getAttribute("class")+"'");var visible=!!(element.offsetWidth||element.offsetHeight||element.getClientRects().length);var block=element.getAttribute("data-block");if(visible){var insertion_code=element.getAttribute("data-code");var insertion_type=element.getAttribute("data-insertion");var selector=element.getAttribute("data-selector");if(insertion_code!=
6
- null)if(insertion_type!=null&&selector!=null){var selector_exists=document.querySelectorAll(selector).length;if(ai_debug)console.log("AI VIEWPORT VISIBLE: block",block,insertion_type,selector,selector_exists?"":"NOT FOUND");if(selector_exists){ai_insert(insertion_type,selector,b64d(insertion_code));removeClass(element,"ai-viewports")}}else{if(ai_debug)console.log("AI VIEWPORT VISIBLE: block",block);var range=document.createRange();var fragment=range.createContextualFragment(b64d(insertion_code));
7
- element.parentNode.insertBefore(fragment,element.nextSibling);removeClass(element,"ai-viewports")}}else{if(ai_debug)console.log("AI VIEWPORT NOT VISIBLE: block",block);var debug_bar=element.previousElementSibling;if(hasClass(debug_bar,"ai-debug-bar")&&hasClass(debug_bar,"ai-debug-script")){removeClass(debug_bar,"ai-debug-script");addClass(debug_bar,"ai-debug-viewport-invisible")}removeClass(element,"ai-viewports")}}
8
- function b64e(str){return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,function toSolidBytes(match,p1){return String.fromCharCode("0x"+p1)}))}function b64d(str){return decodeURIComponent(atob(str).split("").map(function(c){return"%"+("00"+c.charCodeAt(0).toString(16)).slice(-2)}).join(""))};
 
1
+ function ai_insert(insertion,selector,insertion_code){Array.prototype.forEach.call(document.querySelectorAll(selector),function(element,index){var ai_debug=typeof ai_debugging!=="undefined";if(element.hasAttribute("id"))selector_string="#"+element.getAttribute("id");else if(element.hasAttribute("class"))selector_string="."+element.getAttribute("class").replace(new RegExp(" ","g"),".");else selector_string="";var template=document.createElement("div");template.innerHTML=insertion_code;var ai_selector_counter=
2
+ template.getElementsByClassName("ai-selector-counter")[0];if(ai_selector_counter!=null)ai_selector_counter.innerText=index+1;var ai_debug_name_ai_main=template.getElementsByClassName("ai-debug-name ai-main")[0];if(ai_debug_name_ai_main!=null)ai_debug_name_ai_main.innerText=insertion.toUpperCase()+" "+selector+" ("+element.tagName.toLowerCase()+selector_string+")";var range=document.createRange();var fragment=range.createContextualFragment(template.innerHTML);if(insertion=="before")element.parentNode.insertBefore(fragment,
3
+ element);else if(insertion=="after")element.parentNode.insertBefore(fragment,element.nextSibling);else if(insertion=="prepend")element.insertBefore(fragment,element.firstChild);else if(insertion=="append")element.insertBefore(fragment,null);else if(insertion=="replace-content")element.innerHTML=template.innerHTML;else if(insertion=="replace-element"){element.parentNode.insertBefore(fragment,element);element.parentNode.removeChild(element)}if(ai_debug)console.log("AI INSERT",insertion,selector,"("+
4
+ element.tagName.toLowerCase()+selector_string+")")})}
5
+ function ai_insert_viewport(element){function hasClass(element,cls){if(element==null)return false;if(element.classList)return element.classList.contains(cls);else return(" "+element.className+" ").indexOf(" "+cls+" ")>-1}function addClass(element,cls){if(element==null)return;if(element.classList)element.classList.add(cls);else element.className+=" "+cls}function removeClass(element,cls){if(element==null)return;if(element.classList)element.classList.remove(cls);else element.className=element.className.replace(new RegExp("(^|\\b)"+
6
+ cls.split(" ").join("|")+"(\\b|$)","gi")," ")}var ai_debug=typeof ai_debugging!=="undefined";if(ai_debug)console.log("AI VIEWPORT INSERTION:","class='"+element.getAttribute("class")+"'");var visible=!!(element.offsetWidth||element.offsetHeight||element.getClientRects().length);var block=element.getAttribute("data-block");if(visible){var insertion_code=element.getAttribute("data-code");var insertion_type=element.getAttribute("data-insertion");var selector=element.getAttribute("data-selector");if(insertion_code!=
7
+ null)if(insertion_type!=null&&selector!=null){var selector_exists=document.querySelectorAll(selector).length;if(ai_debug)console.log("AI VIEWPORT VISIBLE: block",block,insertion_type,selector,selector_exists?"":"NOT FOUND");if(selector_exists){ai_insert(insertion_type,selector,b64d(insertion_code));removeClass(element,"ai-viewports")}}else{if(ai_debug)console.log("AI VIEWPORT VISIBLE: block",block);var range=document.createRange();var fragment=range.createContextualFragment(b64d(insertion_code));
8
+ element.parentNode.insertBefore(fragment,element.nextSibling);removeClass(element,"ai-viewports")}}else{if(ai_debug)console.log("AI VIEWPORT NOT VISIBLE: block",block);var debug_bar=element.previousElementSibling;if(hasClass(debug_bar,"ai-debug-bar")&&hasClass(debug_bar,"ai-debug-script")){removeClass(debug_bar,"ai-debug-script");addClass(debug_bar,"ai-debug-viewport-invisible")}removeClass(element,"ai-viewports")}}
9
+ function b64e(str){return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,function toSolidBytes(match,p1){return String.fromCharCode("0x"+p1)}))}function b64d(str){return decodeURIComponent(atob(str).split("").map(function(c){return"%"+("00"+c.charCodeAt(0).toString(16)).slice(-2)}).join(""))};
includes/js/ai-select.js ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery (document).ready (function ($) {
2
+
3
+ function interceptClick (event) {
4
+ var element = $(event.target);
5
+ if (element.prop ("tagName") == 'A') {
6
+ event.preventDefault ();
7
+
8
+ if (!ctrl_pressed) {
9
+ var param = {
10
+ 'html_element_selection': block,
11
+ 'selector': $('#ai-selector').val (),
12
+ 'input': settings_input
13
+ };
14
+
15
+ var form = document.createElement ("form");
16
+ form.setAttribute ("method", "post");
17
+ form.setAttribute ("action", event.srcElement.href);
18
+ form.setAttribute ("target", '_self');
19
+ for (var i in param) {
20
+ if (param.hasOwnProperty (i)) {
21
+ var input = document.createElement ('input');
22
+ input.type = 'hidden';
23
+ input.name = i;
24
+ input.value = encodeURI (param [i]);
25
+ form.appendChild (input);
26
+ }
27
+ }
28
+ document.body.appendChild (form);
29
+ form.submit();
30
+ document.body.removeChild (form);
31
+ }
32
+ }
33
+ }
34
+
35
+ function getElementSelector (el) {
36
+ var selector = el.nodeName.toLowerCase ();
37
+
38
+ if (el.hasAttribute ('id') && el.id != '') {
39
+ selector = selector + '#' + el.id;
40
+ }
41
+
42
+ if (el.className) {
43
+ classes = el.className.replace(/ai-selected|ai-highlighted/g, '').trim();
44
+ if (classes) {
45
+ selector = selector + '.' + classes.replace(/\s{2,}/g, ' ').trim().replace (/ /g, '.');
46
+ }
47
+ }
48
+
49
+ return selector;
50
+ }
51
+
52
+ function getDomPath (el) {
53
+ var stack = [];
54
+ while (el.parentNode != null) {
55
+
56
+ var sibCount = 0;
57
+ var sibIndex = 0;
58
+ for (var i = 0; i < el.parentNode.childNodes.length; i++) {
59
+ var sib = el.parentNode.childNodes [i];
60
+ if (sib.nodeName == el.nodeName) {
61
+ if (sib === el) {
62
+ sibIndex = sibCount;
63
+ }
64
+ sibCount++;
65
+ }
66
+ }
67
+ if (el.hasAttribute ('id') && el.id != '') {
68
+ stack.unshift (el.nodeName.toLowerCase () + '#' + el.id);
69
+ } else if (sibCount > 1) {
70
+ stack.unshift (el.nodeName.toLowerCase () + ':eq(' + sibIndex + ')');
71
+ } else {
72
+ stack.unshift (el.nodeName.toLowerCase ());
73
+ }
74
+ el = el.parentNode;
75
+ }
76
+
77
+ return stack.slice (1); // removes the html element
78
+ }
79
+
80
+ function getShortestPath (elements) {
81
+ var stack = [];
82
+ var found = false;
83
+ elements.reverse ().forEach (function (element) {
84
+ if (!found) stack.unshift (element);
85
+ found = element.indexOf ('#') != -1;
86
+ });
87
+ return stack;
88
+ }
89
+
90
+ function cleanSelectors (selectors) {
91
+ selectors = selectors.trim ();
92
+
93
+ if (selectors.slice (0, 1) == ',') {
94
+ selectors = selectors.slice (1, selectors.length);
95
+ }
96
+
97
+ if (selectors.slice (-1) == ',') {
98
+ selectors = selectors.slice (0, selectors.length - 1);
99
+ }
100
+
101
+ return (selectors.trim ());
102
+ }
103
+
104
+ function wrapElement (element) {
105
+ return '<kbd class="ai-html-element">' + element + '</kbd>';
106
+ }
107
+
108
+ function wrapElements (elements) {
109
+ var html_elements = [];
110
+ elements.forEach (function (element) {
111
+ html_elements.push (wrapElement (element));
112
+ });
113
+
114
+ return html_elements;
115
+ }
116
+
117
+ function createClickableElements () {
118
+ $(".ai-html-element").click (function () {
119
+ var element_selector = $(this).text ();
120
+
121
+ $('#ai-selector-element').html (wrapElement (element_selector));
122
+
123
+ $('.ai-highlighted').removeClass ('ai-highlighted');
124
+ $('.ai-selected').removeClass ('ai-selected');
125
+
126
+ $(element_selector).addClass ('ai-selected');
127
+
128
+ $('#ai-selector-data ' + element_selector).removeClass ('ai-selected');
129
+
130
+ $('#ai-selector').val (element_selector);
131
+ });
132
+ }
133
+
134
+ function loadFromSettings () {
135
+ if (window.opener != null && !window.opener.closed) {
136
+ $("#ai-selector").val (cleanSelectors (settings_selector));
137
+ $("#ai-selector").trigger ("input");
138
+ }
139
+ }
140
+
141
+ function applyToSettings (add) {
142
+ if (window.opener != null && !window.opener.closed) {
143
+ var settings = $(window.opener.document).contents ();
144
+ var selector = $("#ai-selector").val ();
145
+
146
+ if (add) {
147
+ var existing_selectors = settings.find (settings_input).val ().trim ();
148
+ existing_selectors = cleanSelectors (existing_selectors);
149
+ if (existing_selectors != '') {
150
+ existing_selectors = existing_selectors + ', ';
151
+ }
152
+ selector = existing_selectors + selector;
153
+ }
154
+
155
+ settings.find (settings_input).val (selector);
156
+ }
157
+ }
158
+
159
+ function changeAction () {
160
+ if (ctrl_pressed) {
161
+ $("#ai-use-button").hide ();
162
+ $("#ai-add-button").show ();
163
+ } else {
164
+ $("#ai-use-button").show ();
165
+ $("#ai-add-button").hide ();
166
+ }
167
+ }
168
+
169
+ var block = "AI_POST_HTML_ELEMENT_SELECTION";
170
+ var settings_selector = "AI_POST_SELECTOR";
171
+ var settings_input = "AI_POST_INPUT";
172
+ var ctrl_pressed = false;
173
+ var selected_element = null;
174
+ var current_element = null;
175
+
176
+ document.onclick = interceptClick;
177
+
178
+ $(document).keydown (function (event) {
179
+ if (event.which == "17") {
180
+ ctrl_pressed = true;
181
+ changeAction ();
182
+
183
+ if (current_element != null && current_element.prop ("tagName") == 'A') {
184
+ $(current_element).trigger ('mouseover');
185
+ }
186
+ }
187
+ });
188
+
189
+ $(document).keyup (function() {
190
+ ctrl_pressed = false;
191
+ changeAction ();
192
+
193
+ if (current_element != null && current_element.prop ("tagName") == 'A') {
194
+ $(current_element).trigger ('mouseout');
195
+ }
196
+ });
197
+
198
+ $('body').css ({'user-select': 'none', 'margin-top': '140px'});
199
+
200
+ $('body').prepend ('<section id="ai-selector-data"> \
201
+ <table> \
202
+ <tbody> \
203
+ <tr> \
204
+ <td class="data-name">ELEMENT</td> \
205
+ <td class="data-value"><section id="ai-selector-element"></section></td> \
206
+ <td><button type="button" id="ai-cancel-button" style="width: 90px;" title="Cancel element selection"> Cancel </button></td> \
207
+ </tr> \
208
+ <tr> \
209
+ <td>PATH</td> \
210
+ <td><section id="ai-selector-path"></section></td> \
211
+ <td><button type="button" id="ai-parent-button" style="width: 90px;" title="Select parent element"> Parent </button></td> \
212
+ </tr> \
213
+ <tr> \
214
+ <td>SELECTOR</td> \
215
+ <td style="width: 100%;"><input id="ai-selector" type="text" value="" maxlength="500" title="CSS selector" /></td> \
216
+ <td><button type="button" id="ai-use-button" style="width: 90px;" title="Use current selector"> Use </button> \
217
+ <button type="button" id="ai-add-button" style="width: 90px; display: none;" title="Add current selector"> Add </button></td> \
218
+ </tr> \
219
+ </tbody> \
220
+ </table> \
221
+ </section>');
222
+
223
+ $('body').bind ('mouseover mouseout click', function (event) {
224
+ var element = $(event.target);
225
+ var elements = getDomPath (element [0]);
226
+ var path = elements.join (' > ');
227
+
228
+ if (path.indexOf ('ai-selector-data') != -1) {
229
+ return;
230
+ }
231
+
232
+ if (element.hasClass ('ai-html-element')) {
233
+ return;
234
+ }
235
+
236
+ switch (event.type) {
237
+ case 'click':
238
+ if (element.prop ("tagName") != 'A' || ctrl_pressed) {
239
+ selected_element = element;
240
+
241
+ $('#ai-selector-element').html (wrapElement (getElementSelector (element [0])));
242
+ $('#ai-selector-path').html (wrapElements (elements).join (' > '));
243
+
244
+ createClickableElements ();
245
+
246
+ $('.ai-highlighted').removeClass ('ai-highlighted');
247
+ $('.ai-selected').removeClass ('ai-selected');
248
+
249
+ element.addClass ('ai-selected');
250
+
251
+ $('#ai-selector').val (getShortestPath (elements).join (' > '));
252
+ }
253
+ break;
254
+ case 'mouseover':
255
+ current_element = element;
256
+ if (element.prop ("tagName") != 'A' || ctrl_pressed) {
257
+ element.addClass ('ai-highlighted');
258
+ }
259
+ break;
260
+ case 'mouseout':
261
+ element.removeClass ('ai-highlighted');
262
+ break;
263
+ }
264
+ });
265
+
266
+ $("#ai-selector").on ('input', function() {
267
+
268
+ $('.ai-highlighted').removeClass ('ai-highlighted');
269
+ $('.ai-selected').removeClass ('ai-selected');
270
+
271
+ var selectors = cleanSelectors ($("#ai-selector").val ());
272
+ $(selectors).addClass ('ai-selected');
273
+
274
+ var elements = selectors.split (',');
275
+ elements.forEach (function (element) {
276
+ $('#ai-selector-data ' + element).removeClass ('ai-selected');
277
+ });
278
+
279
+ if (elements.length == 1 && $(selectors).length == 1) {
280
+ selected_element = $(elements [0]);
281
+
282
+ $('#ai-selector-element').html (wrapElement (getElementSelector (selected_element [0])));
283
+ $('#ai-selector-path').html (wrapElements (getDomPath (selected_element [0])).join (' > '));
284
+
285
+ createClickableElements ();
286
+ } else {
287
+ selected_element = null;
288
+ $('#ai-selector-element').text ('');
289
+ $('#ai-selector-path').text ('');
290
+ }
291
+ });
292
+
293
+ window.onkeydown = function (event) {
294
+ if (event.keyCode === 27 ) {
295
+ window.close();
296
+ }
297
+ };
298
+
299
+ loadFromSettings ();
300
+
301
+ $("#ai-cancel-button").button ({
302
+ }).click (function () {
303
+ window.close();
304
+ });
305
+
306
+ $("#ai-parent-button").button ({
307
+ }).click (function () {
308
+ if (selected_element.prop ("tagName") != 'BODY') {
309
+ selected_element = selected_element.parent ();
310
+ selected_element.click ();
311
+ }
312
+ });
313
+
314
+ $("#ai-use-button").button ({
315
+ }).click (function () {
316
+ applyToSettings (false);
317
+ window.close();
318
+ });
319
+
320
+ $("#ai-add-button").button ({
321
+ }).click (function () {
322
+ applyToSettings (true);
323
+ window.close();
324
+ });
325
+
326
+ });
327
+
328
+
includes/js/ai-select.min.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($){function interceptClick(event){var element=$(event.target);if(element.prop("tagName")=="A"){event.preventDefault();if(!ctrl_pressed){var param={"html_element_selection":block,"selector":$("#ai-selector").val(),"input":settings_input};var form=document.createElement("form");form.setAttribute("method","post");form.setAttribute("action",event.srcElement.href);form.setAttribute("target","_self");for(var i in param)if(param.hasOwnProperty(i)){var input=document.createElement("input");
2
+ input.type="hidden";input.name=i;input.value=encodeURI(param[i]);form.appendChild(input)}document.body.appendChild(form);form.submit();document.body.removeChild(form)}}}function getElementSelector(el){var selector=el.nodeName.toLowerCase();if(el.hasAttribute("id")&&el.id!="")selector=selector+"#"+el.id;if(el.className){classes=el.className.replace(/ai-selected|ai-highlighted/g,"").trim();if(classes)selector=selector+"."+classes.replace(/\s{2,}/g," ").trim().replace(/ /g,".")}return selector}function getDomPath(el){var stack=
3
+ [];while(el.parentNode!=null){var sibCount=0;var sibIndex=0;for(var i=0;i<el.parentNode.childNodes.length;i++){var sib=el.parentNode.childNodes[i];if(sib.nodeName==el.nodeName){if(sib===el)sibIndex=sibCount;sibCount++}}if(el.hasAttribute("id")&&el.id!="")stack.unshift(el.nodeName.toLowerCase()+"#"+el.id);else if(sibCount>1)stack.unshift(el.nodeName.toLowerCase()+":eq("+sibIndex+")");else stack.unshift(el.nodeName.toLowerCase());el=el.parentNode}return stack.slice(1)}function getShortestPath(elements){var stack=
4
+ [];var found=false;elements.reverse().forEach(function(element){if(!found)stack.unshift(element);found=element.indexOf("#")!=-1});return stack}function cleanSelectors(selectors){selectors=selectors.trim();if(selectors.slice(0,1)==",")selectors=selectors.slice(1,selectors.length);if(selectors.slice(-1)==",")selectors=selectors.slice(0,selectors.length-1);return selectors.trim()}function wrapElement(element){return'<kbd class="ai-html-element">'+element+"</kbd>"}function wrapElements(elements){var html_elements=
5
+ [];elements.forEach(function(element){html_elements.push(wrapElement(element))});return html_elements}function createClickableElements(){$(".ai-html-element").click(function(){var element_selector=$(this).text();$("#ai-selector-element").html(wrapElement(element_selector));$(".ai-highlighted").removeClass("ai-highlighted");$(".ai-selected").removeClass("ai-selected");$(element_selector).addClass("ai-selected");$("#ai-selector-data "+element_selector).removeClass("ai-selected");$("#ai-selector").val(element_selector)})}
6
+ function loadFromSettings(){if(window.opener!=null&&!window.opener.closed){$("#ai-selector").val(cleanSelectors(settings_selector));$("#ai-selector").trigger("input")}}function applyToSettings(add){if(window.opener!=null&&!window.opener.closed){var settings=$(window.opener.document).contents();var selector=$("#ai-selector").val();if(add){var existing_selectors=settings.find(settings_input).val().trim();existing_selectors=cleanSelectors(existing_selectors);if(existing_selectors!="")existing_selectors=
7
+ existing_selectors+", ";selector=existing_selectors+selector}settings.find(settings_input).val(selector)}}function changeAction(){if(ctrl_pressed){$("#ai-use-button").hide();$("#ai-add-button").show()}else{$("#ai-use-button").show();$("#ai-add-button").hide()}}var block="AI_POST_HTML_ELEMENT_SELECTION";var settings_selector="AI_POST_SELECTOR";var settings_input="AI_POST_INPUT";var ctrl_pressed=false;var selected_element=null;var current_element=null;document.onclick=interceptClick;$(document).keydown(function(event){if(event.which==
8
+ "17"){ctrl_pressed=true;changeAction();if(current_element!=null&&current_element.prop("tagName")=="A")$(current_element).trigger("mouseover")}});$(document).keyup(function(){ctrl_pressed=false;changeAction();if(current_element!=null&&current_element.prop("tagName")=="A")$(current_element).trigger("mouseout")});$("body").css({"user-select":"none","margin-top":"140px"});$("body").prepend('<section id="ai-selector-data"> <table> <tbody> <tr> <td class="data-name">ELEMENT</td> <td class="data-value"><section id="ai-selector-element"></section></td> <td><button type="button" id="ai-cancel-button" style="width: 90px;" title="Cancel element selection"> Cancel </button></td> </tr> <tr> <td>PATH</td> <td><section id="ai-selector-path"></section></td> <td><button type="button" id="ai-parent-button" style="width: 90px;" title="Select parent element"> Parent </button></td> </tr> <tr> <td>SELECTOR</td> <td style="width: 100%;"><input id="ai-selector" type="text" value="" maxlength="500" title="CSS selector" /></td> <td><button type="button" id="ai-use-button" style="width: 90px;" title="Use current selector"> Use </button> <button type="button" id="ai-add-button" style="width: 90px; display: none;" title="Add current selector"> Add </button></td> </tr> </tbody> </table> </section>');
9
+ $("body").bind("mouseover mouseout click",function(event){var element=$(event.target);var elements=getDomPath(element[0]);var path=elements.join(" > ");if(path.indexOf("ai-selector-data")!=-1)return;if(element.hasClass("ai-html-element"))return;switch(event.type){case "click":if(element.prop("tagName")!="A"||ctrl_pressed){selected_element=element;$("#ai-selector-element").html(wrapElement(getElementSelector(element[0])));$("#ai-selector-path").html(wrapElements(elements).join(" > "));createClickableElements();
10
+ $(".ai-highlighted").removeClass("ai-highlighted");$(".ai-selected").removeClass("ai-selected");element.addClass("ai-selected");$("#ai-selector").val(getShortestPath(elements).join(" > "))}break;case "mouseover":current_element=element;if(element.prop("tagName")!="A"||ctrl_pressed)element.addClass("ai-highlighted");break;case "mouseout":element.removeClass("ai-highlighted");break}});$("#ai-selector").on("input",function(){$(".ai-highlighted").removeClass("ai-highlighted");$(".ai-selected").removeClass("ai-selected");
11
+ var selectors=cleanSelectors($("#ai-selector").val());$(selectors).addClass("ai-selected");var elements=selectors.split(",");elements.forEach(function(element){$("#ai-selector-data "+element).removeClass("ai-selected")});if(elements.length==1&&$(selectors).length==1){selected_element=$(elements[0]);$("#ai-selector-element").html(wrapElement(getElementSelector(selected_element[0])));$("#ai-selector-path").html(wrapElements(getDomPath(selected_element[0])).join(" > "));createClickableElements()}else{selected_element=
12
+ null;$("#ai-selector-element").text("");$("#ai-selector-path").text("")}});window.onkeydown=function(event){if(event.keyCode===27)window.close()};loadFromSettings();$("#ai-cancel-button").button({}).click(function(){window.close()});$("#ai-parent-button").button({}).click(function(){if(selected_element.prop("tagName")!="BODY"){selected_element=selected_element.parent();selected_element.click()}});$("#ai-use-button").button({}).click(function(){applyToSettings(false);window.close()});$("#ai-add-button").button({}).click(function(){applyToSettings(true);
13
+ window.close()})});
js/ad-inserter.js CHANGED
@@ -1,4 +1,4 @@
1
- var javascript_version = "2.4.1";
2
  var ignore_key = true;
3
  var start = 1;
4
  var end = 16;
@@ -85,166 +85,22 @@ var AI_SCROLL_WITH_THE_CONTENT = 2;
85
  var AI_STICK_TO_THE_BOTTOM = 3;
86
 
87
 
 
 
 
 
 
 
 
 
 
88
 
89
- /**
90
- * jQuery BASE64 functions
91
- *
92
- * <code>
93
- * Encodes the given data with base64.
94
- * String $.base64Encode ( String str )
95
- * <br />
96
- * Decodes a base64 encoded data.
97
- * String $.base64Decode ( String str )
98
- * </code>
99
- *
100
- * Encodes and Decodes the given data in base64.
101
- * This encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies.
102
- * Base64-encoded data takes about 33% more space than the original data.
103
- * This javascript code is used to encode / decode data using base64 (this encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean). Script is fully compatible with UTF-8 encoding. You can use base64 encoded data as simple encryption mechanism.
104
- * If you plan using UTF-8 encoding in your project don't forget to set the page encoding to UTF-8 (Content-Type meta tag).
105
- * This function orginally get from the WebToolkit and rewrite for using as the jQuery plugin.
106
- *
107
- * Example
108
- * Code
109
- * <code>
110
- * $.base64Encode("I'm Persian.");
111
- * </code>
112
- * Result
113
- * <code>
114
- * "SSdtIFBlcnNpYW4u"
115
- * </code>
116
- * Code
117
- * <code>
118
- * $.base64Decode("SSdtIFBlcnNpYW4u");
119
- * </code>
120
- * Result
121
- * <code>
122
- * "I'm Persian."
123
- * </code>
124
- *
125
- * @alias Muhammad Hussein Fattahizadeh < muhammad [AT] semnanweb [DOT] com >
126
- * @link http://www.semnanweb.com/jquery-plugin/base64.html (no longer available?)
127
- * @link https://gist.github.com/gists/1602210
128
- * @see http://www.webtoolkit.info/
129
- * @license http://www.gnu.org/licenses/gpl.html [GNU General Public License]
130
- * @param {jQuery} {base64Encode:function(input))
131
- * @param {jQuery} {base64Decode:function(input))
132
- * @return string
133
- */
134
-
135
- // (function($){
136
-
137
- // var keyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
138
-
139
- // var uTF8Encode = function(string) {
140
- // string = string.replace(/\x0d\x0a/g, "\x0a");
141
- // var output = "";
142
- // for (var n = 0; n < string.length; n++) {
143
- // var c = string.charCodeAt(n);
144
- // if (c < 128) {
145
- // output += String.fromCharCode(c);
146
- // } else if ((c > 127) && (c < 2048)) {
147
- // output += String.fromCharCode((c >> 6) | 192);
148
- // output += String.fromCharCode((c & 63) | 128);
149
- // } else {
150
- // output += String.fromCharCode((c >> 12) | 224);
151
- // output += String.fromCharCode(((c >> 6) & 63) | 128);
152
- // output += String.fromCharCode((c & 63) | 128);
153
- // }
154
- // }
155
- // return output;
156
- // };
157
-
158
- // var uTF8Decode = function(input) {
159
- // var string = "";
160
- // var i = 0;
161
- // var c = c1 = c2 = 0;
162
- // while ( i < input.length ) {
163
- // c = input.charCodeAt(i);
164
- // if (c < 128) {
165
- // string += String.fromCharCode(c);
166
- // i++;
167
- // } else if ((c > 191) && (c < 224)) {
168
- // c2 = input.charCodeAt(i+1);
169
- // string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
170
- // i += 2;
171
- // } else {
172
- // c2 = input.charCodeAt(i+1);
173
- // c3 = input.charCodeAt(i+2);
174
- // string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
175
- // i += 3;
176
- // }
177
- // }
178
- // return string;
179
- // }
180
-
181
- // $.extend({
182
- // base64Encode: function(input) {
183
- // var output = "";
184
- // var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
185
- // var i = 0;
186
- // input = uTF8Encode(input);
187
- // while (i < input.length) {
188
- // chr1 = input.charCodeAt(i++);
189
- // chr2 = input.charCodeAt(i++);
190
- // chr3 = input.charCodeAt(i++);
191
- // enc1 = chr1 >> 2;
192
- // enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
193
- // enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
194
- // enc4 = chr3 & 63;
195
- // if (isNaN(chr2)) {
196
- // enc3 = enc4 = 64;
197
- // } else if (isNaN(chr3)) {
198
- // enc4 = 64;
199
- // }
200
- // output = output + keyString.charAt(enc1) + keyString.charAt(enc2) + keyString.charAt(enc3) + keyString.charAt(enc4);
201
- // }
202
- // return output;
203
- // },
204
- // base64Decode: function(input) {
205
- // var output = "";
206
- // var chr1, chr2, chr3;
207
- // var enc1, enc2, enc3, enc4;
208
- // var i = 0;
209
- // input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
210
- // while (i < input.length) {
211
- // enc1 = keyString.indexOf(input.charAt(i++));
212
- // enc2 = keyString.indexOf(input.charAt(i++));
213
- // enc3 = keyString.indexOf(input.charAt(i++));
214
- // enc4 = keyString.indexOf(input.charAt(i++));
215
- // chr1 = (enc1 << 2) | (enc2 >> 4);
216
- // chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
217
- // chr3 = ((enc3 & 3) << 6) | enc4;
218
- // output = output + String.fromCharCode(chr1);
219
- // if (enc3 != 64) {
220
- // output = output + String.fromCharCode(chr2);
221
- // }
222
- // if (enc4 != 64) {
223
- // output = output + String.fromCharCode(chr3);
224
- // }
225
- // }
226
- // output = uTF8Decode(output);
227
- // return output;
228
- // }
229
- // });
230
- // })(jQuery);
231
-
232
- function b64e (str) {
233
- // first we use encodeURIComponent to get percent-encoded UTF-8,
234
- // then we convert the percent encodings into raw bytes which
235
- // can be fed into btoa.
236
- return btoa (encodeURIComponent (str).replace (/%([0-9A-F]{2})/g,
237
- function toSolidBytes (match, p1) {
238
- return String.fromCharCode ('0x' + p1);
239
- }));
240
- }
241
-
242
- function b64d (str) {
243
- // Going backwards: from bytestream, to percent-encoding, to original string.
244
- return decodeURIComponent (atob (str).split ('').map (function(c) {
245
- return '%' + ('00' + c.charCodeAt (0).toString (16)).slice (-2);
246
- }).join (''));
247
- }
248
 
249
  var shSettings = {
250
  "tab_size":"4",
@@ -1580,6 +1436,38 @@ jQuery(document).ready(function($) {
1580
  var param = {'action': 'ai_ajax_backend', 'preview': 'adb', 'ai_check': nonce, 'code': code, 'php': php};
1581
  window_open_post (ajaxurl, 'width='+window_width+',height='+window_height+',top='+window_top+',left='+window_left+',resizable=yes,scrollbars=yes,toolbar=no,location=no,directories=no,status=no,menubar=no', 'preview', param);
1582
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1583
  }
1584
 
1585
  function configure_tab (tab) {
@@ -2488,6 +2376,24 @@ jQuery(document).ready(function($) {
2488
  var block = $(this).attr('id').replace ("close-button2-", "");
2489
  $("select#close-button-"+block+"").val ($("select#close-button2-"+block+" option:selected").attr('value'));
2490
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2491
  }
2492
 
2493
  function configure_sticky_css (block) {
1
+ var javascript_version = "2.4.2";
2
  var ignore_key = true;
3
  var start = 1;
4
  var end = 16;
85
  var AI_STICK_TO_THE_BOTTOM = 3;
86
 
87
 
88
+ function b64e (str) {
89
+ // first we use encodeURIComponent to get percent-encoded UTF-8,
90
+ // then we convert the percent encodings into raw bytes which
91
+ // can be fed into btoa.
92
+ return btoa (encodeURIComponent (str).replace (/%([0-9A-F]{2})/g,
93
+ function toSolidBytes (match, p1) {
94
+ return String.fromCharCode ('0x' + p1);
95
+ }));
96
+ }
97
 
98
+ function b64d (str) {
99
+ // Going backwards: from bytestream, to percent-encoding, to original string.
100
+ return decodeURIComponent (atob (str).split ('').map (function(c) {
101
+ return '%' + ('00' + c.charCodeAt (0).toString (16)).slice (-2);
102
+ }).join (''));
103
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
 
105
  var shSettings = {
106
  "tab_size":"4",
1436
  var param = {'action': 'ai_ajax_backend', 'preview': 'adb', 'ai_check': nonce, 'code': code, 'php': php};
1437
  window_open_post (ajaxurl, 'width='+window_width+',height='+window_height+',top='+window_top+',left='+window_left+',resizable=yes,scrollbars=yes,toolbar=no,location=no,directories=no,status=no,menubar=no', 'preview', param);
1438
  });
1439
+
1440
+ $("#main-content-element-button").click (function () {
1441
+ var selector = $("input#main-content-element").val ();
1442
+ var home_url = $("#ai-settings").data ('home-relative-url');
1443
+ var window_top = screen.availTop;
1444
+ var window_left = screen.availLeft;
1445
+ var window_width = screen.availWidth - 15;
1446
+ var window_height = screen.availHeight - 65;
1447
+
1448
+ var param = {
1449
+ 'html_element_selection': 'main',
1450
+ 'selector': selector,
1451
+ 'input': "input#main-content-element"
1452
+ };
1453
+ window_open_post (home_url, 'width='+window_width+',height='+window_height+',top='+window_top+',left='+window_left+',resizable=yes,scrollbars=yes,toolbar=no,location=no,directories=no,status=no,menubar=no', 'ai-selector', param);
1454
+ });
1455
+
1456
+ $("#custom-selectors-button").click (function () {
1457
+ var selector = $("input#custom-selectors").val ();
1458
+ var home_url = $("#ai-settings").data ('home-relative-url');
1459
+ var window_top = screen.availTop;
1460
+ var window_left = screen.availLeft;
1461
+ var window_width = screen.availWidth - 15;
1462
+ var window_height = screen.availHeight - 65;
1463
+
1464
+ var param = {
1465
+ 'html_element_selection': 'adb',
1466
+ 'selector': selector,
1467
+ 'input': "input#custom-selectors"
1468
+ };
1469
+ window_open_post (home_url, 'width='+window_width+',height='+window_height+',top='+window_top+',left='+window_left+',resizable=yes,scrollbars=yes,toolbar=no,location=no,directories=no,status=no,menubar=no', 'ai-selector', param);
1470
+ });
1471
  }
1472
 
1473
  function configure_tab (tab) {
2376
  var block = $(this).attr('id').replace ("close-button2-", "");
2377
  $("select#close-button-"+block+"").val ($("select#close-button2-"+block+" option:selected").attr('value'));
2378
  });
2379
+
2380
+ $("#html-elements-button-"+tab).click (function () {
2381
+ var block = $(this).attr('id').replace ("html-elements-button-", "");
2382
+
2383
+ var selector = $("input#html-elements-" + block).val ();
2384
+ var home_url = $("#ai-settings").data ('home-relative-url');
2385
+ var window_top = screen.availTop;
2386
+ var window_left = screen.availLeft;
2387
+ var window_width = screen.availWidth - 15;
2388
+ var window_height = screen.availHeight - 65;
2389
+
2390
+ var param = {
2391
+ 'html_element_selection': block,
2392
+ 'selector': selector,
2393
+ 'input': "input#html-elements-" + block
2394
+ };
2395
+ window_open_post (home_url, 'width='+window_width+',height='+window_height+',top='+window_top+',left='+window_left+',resizable=yes,scrollbars=yes,toolbar=no,location=no,directories=no,status=no,menubar=no', 'ai-selector', param);
2396
+ });
2397
  }
2398
 
2399
  function configure_sticky_css (block) {
readme.txt CHANGED
@@ -2,14 +2,14 @@
2
 
3
  Contributors: spacetime
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LHGZEMRTR7WB4
5
- Tags: ads, adsense, header footer code, ad management, sticky fixed widgets, advanced geo targeting ads, amp adverts ad rotation, advertising manager, amazon banners ad injection, ad blocking detection, PHP Javascript HTML insertion, custom fields posts
6
  Requires at least: 4.0
7
  Tested up to: 5.0
8
  Requires PHP: 5.6
9
- Stable tag: 2.4.1
10
  License: GPLv3
11
 
12
- Insert and manage ads: Amazon, Google AdSense ads, banner rotation, sticky widget ads, AMP, PHP, HTML, CSS, Javascript, tracking, footer, header code
13
 
14
  == Description ==
15
 
@@ -69,6 +69,7 @@ Looking for AdSense plugin with simple setup for ads at best positions? A plugin
69
  * Insert ads between comments
70
  * Insert ads at custom hook positions (`do_action ()` WP function)
71
  * Insert ads before or after any HTML element using CSS selectors
 
72
  * Avoid inserting ads near images or headers (AdSense TOS)
73
  * Disable ads on individual posts or pages
74
  * Insert header (`<head>` section) and footer code
@@ -205,6 +206,8 @@ To become familiar with the plugin check [Quick Start](https://adinserter.pro/do
205
 
206
  To learn how to configure the most advanced WordPress AdSense plugin check documentation for [AdSense ads](https://adinserter.pro/documentation/adsense-ads): AdSense ad units, AdSense Auto ads, AdSense in-feed ads, AdSense in-article ads, AdSense AMP ads,...
207
 
 
 
208
  **Main AdSense Features**
209
 
210
  * Get code for AdSense ads directly from your [AdSense account](https://adinserter.pro/documentation/adsense-ads#integration)
@@ -216,8 +219,6 @@ To learn how to configure the most advanced WordPress AdSense plugin check docum
216
  * Insert AdSense In-feed or In-article ads between posts or comments
217
  * Debugging function to label AdSense ad blocks to mark [blank AdSense ads](https://adinserter.pro/documentation/adsense-ads#ads-not-displayed)
218
 
219
- Few typical settings are described on the <a href="https://adinserter.pro/documentation/common-settings" target="_blank">Common Settings</a> page. Please make sure you have also read <a href="https://adinserter.pro/documentation/plugin-installation">plugin installation</a> documentation. For more detailed instructions please read <a href="https://adinserter.pro/documentation" target="_blank">Ad Inserter documentation pages</a>.
220
-
221
  **Insert Any Code Anywhere on the Page - Automate Insertion of Ads**
222
 
223
  * Automatic insertion using standard WP hooks (the_content, the_excerpt, loop_start, loop_end, the_post,...)
@@ -513,6 +514,11 @@ Please note that responsive AdSense ads can not work with floating alignments (a
513
 
514
  == Changelog ==
515
 
 
 
 
 
 
516
  = 2.4.1 =
517
  - Added option to insert into HTML element (prepend, append, replace content)
518
  - Added option to remove HTML element
@@ -562,6 +568,11 @@ For the changelog of earlier versions, please refer to the separate changelog.tx
562
 
563
  == Upgrade Notice ==
564
 
 
 
 
 
 
565
  = 2.4.1 =
566
  Added option to insert into HTML element (prepend, append, replace content);
567
  Added option to remove HTML element;
2
 
3
  Contributors: spacetime
4
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LHGZEMRTR7WB4
5
+ Tags: ads, adsense, ad rotation, ad manager, amp ads, amazon, ad blocking detection, header code, banner, banners, advert, adverts, sticky fixed widgets
6
  Requires at least: 4.0
7
  Tested up to: 5.0
8
  Requires PHP: 5.6
9
+ Stable tag: 2.4.2
10
  License: GPLv3
11
 
12
+ Insert and manage ads: Google AdSense ads, Amazon banners, ad rotation, sticky widget ads, PHP, tracking, footer, AdSense header code, AMP ads
13
 
14
  == Description ==
15
 
69
  * Insert ads between comments
70
  * Insert ads at custom hook positions (`do_action ()` WP function)
71
  * Insert ads before or after any HTML element using CSS selectors
72
+ * Visual HTML element selector (DOM explorer)
73
  * Avoid inserting ads near images or headers (AdSense TOS)
74
  * Disable ads on individual posts or pages
75
  * Insert header (`<head>` section) and footer code
206
 
207
  To learn how to configure the most advanced WordPress AdSense plugin check documentation for [AdSense ads](https://adinserter.pro/documentation/adsense-ads): AdSense ad units, AdSense Auto ads, AdSense in-feed ads, AdSense in-article ads, AdSense AMP ads,...
208
 
209
+ Few typical settings are described on the <a href="https://adinserter.pro/documentation/common-settings" target="_blank">Common Settings</a> page. Please make sure you have also read <a href="https://adinserter.pro/documentation/plugin-installation">plugin installation</a> documentation. For more detailed instructions please read <a href="https://adinserter.pro/documentation" target="_blank">Ad Inserter documentation pages</a>.
210
+
211
  **Main AdSense Features**
212
 
213
  * Get code for AdSense ads directly from your [AdSense account](https://adinserter.pro/documentation/adsense-ads#integration)
219
  * Insert AdSense In-feed or In-article ads between posts or comments
220
  * Debugging function to label AdSense ad blocks to mark [blank AdSense ads](https://adinserter.pro/documentation/adsense-ads#ads-not-displayed)
221
 
 
 
222
  **Insert Any Code Anywhere on the Page - Automate Insertion of Ads**
223
 
224
  * Automatic insertion using standard WP hooks (the_content, the_excerpt, loop_start, loop_end, the_post,...)
514
 
515
  == Changelog ==
516
 
517
+ = 2.4.2 =
518
+ - Added support for visual HTML element selection
519
+ - Fix for client-side insertion inside HTML elements
520
+ - Few minor bug fixes, cosmetic changes and code improvements
521
+
522
  = 2.4.1 =
523
  - Added option to insert into HTML element (prepend, append, replace content)
524
  - Added option to remove HTML element
568
 
569
  == Upgrade Notice ==
570
 
571
+ = 2.4.2 =
572
+ Added support for visual HTML element selection;
573
+ Fix for client-side insertion inside HTML elements;
574
+ Few minor bug fixes, cosmetic changes and code improvements
575
+
576
  = 2.4.1 =
577
  Added option to insert into HTML element (prepend, append, replace content);
578
  Added option to remove HTML element;
settings.php CHANGED
@@ -134,7 +134,7 @@ function generate_settings_form (){
134
 
135
  <div style="clear: both;"></div>
136
 
137
- <div id="ai-settings" style="float: left;">
138
 
139
  <form id="ai-form" class="no-select rounded" style="float: left;" action="<?php echo $save_url; ?>" method="post" name="ai_form" start="<?php echo $start; ?>" end="<?php echo $end; ?>" nonce="<?php echo wp_create_nonce ("adinserter_data"); ?>">
140
 
@@ -1090,9 +1090,13 @@ function generate_settings_form (){
1090
  HTML element(s)
1091
  &nbsp;&nbsp;
1092
  </span>
 
 
 
1093
  <span style="display: table-cell;">
1094
  <input
1095
  type="text"
 
1096
  name="<?php echo AI_OPTION_HTML_SELECTOR, WP_FORM_FIELD_POSTFIX, $block; ?>"
1097
  default="<?php echo $default->get_html_selector (); ?>"
1098
  value="<?php echo $obj->get_html_selector (); ?>"
@@ -1103,7 +1107,7 @@ function generate_settings_form (){
1103
  <span id="inside-element-<?php echo $block; ?>" style="display: table-cell; white-space: nowrap; width: 20%;<?php if ($automatic_insertion != AI_AUTOMATIC_INSERTION_INSIDE_HTML_ELEMENT) echo ' display: none;'; ?>">
1104
  &nbsp;
1105
  Action
1106
- <select style="margin-bottom: 3px;" name="<?php echo AI_OPTION_INSIDE_ELEMENT, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_inside_element (); ?>">
1107
  <option value="<?php echo AI_HTML_PREPEND_CONTENT; ?>" <?php echo ($inside_element == AI_HTML_PREPEND_CONTENT) ? AD_SELECT_SELECTED : AD_EMPTY_VALUE; ?>><?php echo AI_TEXT_PREPEND_CONTENT; ?></option>
1108
  <option value="<?php echo AI_HTML_APPEND_CONTENT; ?>" <?php echo ($inside_element == AI_HTML_APPEND_CONTENT) ? AD_SELECT_SELECTED : AD_EMPTY_VALUE; ?>><?php echo AI_TEXT_APPEND_CONTENT; ?></option>
1109
  <option value="<?php echo AI_HTML_REPLACE_CONTENT; ?>" <?php echo ($inside_element == AI_HTML_REPLACE_CONTENT) ? AD_SELECT_SELECTED : AD_EMPTY_VALUE; ?>><?php echo AI_TEXT_REPLACE_CONTENT; ?></option>
@@ -2347,7 +2351,8 @@ function generate_settings_form (){
2347
  Custom Selectors
2348
  </td>
2349
  <td>
2350
- <input style="width: 100%;" type="text" name="<?php echo AI_OPTION_ADB_SELECTORS; ?>" title="Comma seprarated list of selectors (.class, #id) used for additional ad blocking detection. Invisible or zero height of the element means ad blocking is present." value="<?php echo get_adb_selectors (); ?>" default="" size="50" maxlength="200" />
 
2351
  </td>
2352
  </tr>
2353
  <?php if (function_exists ('ai_adb_settings')) ai_adb_settings (); ?>
134
 
135
  <div style="clear: both;"></div>
136
 
137
+ <div id="ai-settings" style="float: left;" data-home-url="<?php echo home_url (); ?>/" data-home-relative-url="<?php echo wp_make_link_relative (get_site_url ()); ?>/">
138
 
139
  <form id="ai-form" class="no-select rounded" style="float: left;" action="<?php echo $save_url; ?>" method="post" name="ai_form" start="<?php echo $start; ?>" end="<?php echo $end; ?>" nonce="<?php echo wp_create_nonce ("adinserter_data"); ?>">
140
 
1090
  HTML element(s)
1091
  &nbsp;&nbsp;
1092
  </span>
1093
+ <span style="display: table-cell; width: 20px; vertical-align: middle; padding: 0 2px 2px 0;">
1094
+ <button id="html-elements-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Open HTML element selector"></button>
1095
+ </span>
1096
  <span style="display: table-cell;">
1097
  <input
1098
  type="text"
1099
+ id="html-elements-<?php echo $block; ?>"
1100
  name="<?php echo AI_OPTION_HTML_SELECTOR, WP_FORM_FIELD_POSTFIX, $block; ?>"
1101
  default="<?php echo $default->get_html_selector (); ?>"
1102
  value="<?php echo $obj->get_html_selector (); ?>"
1107
  <span id="inside-element-<?php echo $block; ?>" style="display: table-cell; white-space: nowrap; width: 20%;<?php if ($automatic_insertion != AI_AUTOMATIC_INSERTION_INSIDE_HTML_ELEMENT) echo ' display: none;'; ?>">
1108
  &nbsp;
1109
  Action
1110
+ <select style="margin: 0 0 2px 0;" name="<?php echo AI_OPTION_INSIDE_ELEMENT, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_inside_element (); ?>">
1111
  <option value="<?php echo AI_HTML_PREPEND_CONTENT; ?>" <?php echo ($inside_element == AI_HTML_PREPEND_CONTENT) ? AD_SELECT_SELECTED : AD_EMPTY_VALUE; ?>><?php echo AI_TEXT_PREPEND_CONTENT; ?></option>
1112
  <option value="<?php echo AI_HTML_APPEND_CONTENT; ?>" <?php echo ($inside_element == AI_HTML_APPEND_CONTENT) ? AD_SELECT_SELECTED : AD_EMPTY_VALUE; ?>><?php echo AI_TEXT_APPEND_CONTENT; ?></option>
1113
  <option value="<?php echo AI_HTML_REPLACE_CONTENT; ?>" <?php echo ($inside_element == AI_HTML_REPLACE_CONTENT) ? AD_SELECT_SELECTED : AD_EMPTY_VALUE; ?>><?php echo AI_TEXT_REPLACE_CONTENT; ?></option>
2351
  Custom Selectors
2352
  </td>
2353
  <td>
2354
+ <input id="custom-selectors" style="width: 95%;" type="text" name="<?php echo AI_OPTION_ADB_SELECTORS; ?>" title="Comma seprarated list of selectors (.class, #id) used for additional ad blocking detection. Invisible or zero height of the element means ad blocking is present." value="<?php echo get_adb_selectors (); ?>" default="" size="50" maxlength="200" />
2355
+ <button id="custom-selectors-button" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 4px; width: 15px; height: 15px;" title="Open HTML element selector"></button>
2356
  </td>
2357
  </tr>
2358
  <?php if (function_exists ('ai_adb_settings')) ai_adb_settings (); ?>