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

Version Description

  • Added list editors
  • Added Label blocks debugging function for AdSense Auto ads
Download this release

Release Info

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

Code changes from version 2.3.2 to 2.3.3

ad-inserter.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  /*
4
  Plugin Name: Ad Inserter
5
- Version: 2.3.2
6
  Description: Ad management plugin with advanced advertising options to automatically insert ad codes on your website
7
  Author: Igor Funa
8
  Author URI: http://igorfuna.com/
@@ -13,6 +13,10 @@ Plugin URI: http://adinserter.pro/documentation
13
 
14
  Change Log
15
 
 
 
 
 
16
  Ad Inserter 2.3.2 - 2018-02-01
17
  - Added AdSense code generator for ad sizes using CSS media queries
18
  - Fix for slow updates caused by changed user agent (Pro only, credits Olivier Langlois, https://juicingforyourmanhood.com/affiliate_tools.html)
@@ -1592,6 +1596,7 @@ function ai_admin_enqueue_scripts ($hook_suffix) {
1592
 
1593
  if (function_exists ('ai_admin_enqueue_scripts_1')) ai_admin_enqueue_scripts_1 ();
1594
 
 
1595
  wp_enqueue_style ('ai-image-picker', plugins_url ('css/image-picker.css', __FILE__), array (), AD_INSERTER_VERSION);
1596
  wp_add_inline_style ('ai-image-picker', '.thumbnail {border-radius: 6px;}');
1597
 
@@ -1603,6 +1608,9 @@ function ai_admin_enqueue_scripts ($hook_suffix) {
1603
 
1604
  if (function_exists ('ai_admin_enqueue_scripts_2')) ai_admin_enqueue_scripts_2 ();
1605
 
 
 
 
1606
  // Located in the header to load datepicker js file to prevent error when async tags used
1607
  wp_enqueue_script ('ai-image-picker-js', plugins_url ('includes/js/image-picker.min.js', __FILE__ ), array (
1608
  'jquery',
@@ -1647,7 +1655,7 @@ function ai_wp_enqueue_scripts_hook () {
1647
  $ai_wp_data [AI_STICKY_WIDGETS] ||
1648
  (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION && $ai_wp_data [AI_ADB_DETECTION]);
1649
 
1650
- if ($footer_inline_scripts || $ai_wp_data [AI_CLIENT_SIDE_INSERTION] || $ai_wp_data [AI_FRONTEND_JS_DEBUGGING]) {
1651
  // force loading of jquery on frontend
1652
  wp_enqueue_script ('ai-jquery-js', plugins_url ('includes/js/ai-jquery.js', __FILE__ ), array (
1653
  'jquery',
@@ -2370,8 +2378,7 @@ function ai_wp_head_hook () {
2370
  }
2371
 
2372
  // No scripts on AMP pages
2373
- // if (($ai_wp_data [AI_WP_DEBUGGING] & AI_DEBUG_POSITIONS) != 0 && !$ai_wp_data [AI_WP_AMP_PAGE]) {
2374
- if (($ai_wp_data [AI_WP_DEBUGGING] & AI_DEBUG_POSITIONS) != 0 /*&& !$ai_wp_data [AI_WP_AMP_PAGE]*/) {
2375
  echo "<script>
2376
  jQuery(document).ready(function($) {
2377
  $('body').prepend (\"", get_page_type_debug_info () , "\");
@@ -2379,6 +2386,17 @@ function ai_wp_head_hook () {
2379
  </script>\n";
2380
  }
2381
 
 
 
 
 
 
 
 
 
 
 
 
2382
  if (defined ('AI_BUFFERING')) {
2383
  if (get_output_buffering ()) {
2384
  if ($ai_wp_data [AI_WP_PAGE_TYPE] != AI_PT_AJAX) {
@@ -3977,6 +3995,10 @@ function ai_ajax_backend () {
3977
  generate_settings_form ();
3978
  }
3979
 
 
 
 
 
3980
  elseif (isset ($_GET ["update"])) {
3981
  if ($_GET ["update"] == 'block-code-demo') {
3982
  ai_block_code_demo (urldecode ($_GET ["block_class_name"]), $_GET ["block_class"], $_GET ["block_number_class"], $_GET ["inline_styles"]);
@@ -4427,6 +4449,9 @@ a.ai-debug-center {text-align: center; font-size: 10px; text-decoration: none; c
4427
  .ai-debug-block.ai-debug-adb-status {border-color: #000;}
4428
  .ai-debug-bar.ai-debug-adb-status {background: #000;}
4429
 
 
 
 
4430
  .ai-debug-adb-status.on {color: #f00;}
4431
  .ai-debug-adb-status.off {color: #0f0;}
4432
 
2
 
3
  /*
4
  Plugin Name: Ad Inserter
5
+ Version: 2.3.3
6
  Description: Ad management plugin with advanced advertising options to automatically insert ad codes on your website
7
  Author: Igor Funa
8
  Author URI: http://igorfuna.com/
13
 
14
  Change Log
15
 
16
+ Ad Inserter 2.3.3 - 2018-02-08
17
+ - Added list editors
18
+ - Added Label blocks debugging function for AdSense Auto ads
19
+
20
  Ad Inserter 2.3.2 - 2018-02-01
21
  - Added AdSense code generator for ad sizes using CSS media queries
22
  - Fix for slow updates caused by changed user agent (Pro only, credits Olivier Langlois, https://juicingforyourmanhood.com/affiliate_tools.html)
1596
 
1597
  if (function_exists ('ai_admin_enqueue_scripts_1')) ai_admin_enqueue_scripts_1 ();
1598
 
1599
+ wp_enqueue_style ('ai-admin-multi-select', plugins_url ('css/multi-select.css', AD_INSERTER_FILE), array (), AD_INSERTER_VERSION);
1600
  wp_enqueue_style ('ai-image-picker', plugins_url ('css/image-picker.css', __FILE__), array (), AD_INSERTER_VERSION);
1601
  wp_add_inline_style ('ai-image-picker', '.thumbnail {border-radius: 6px;}');
1602
 
1608
 
1609
  if (function_exists ('ai_admin_enqueue_scripts_2')) ai_admin_enqueue_scripts_2 ();
1610
 
1611
+ wp_enqueue_script ('ai-multi-select', plugins_url ('includes/js/jquery.multi-select.js', AD_INSERTER_FILE ), array (), AD_INSERTER_VERSION, true);
1612
+ wp_enqueue_script ('ai-quicksearch', plugins_url ('includes/js/jquery.quicksearch.js', AD_INSERTER_FILE ), array (), AD_INSERTER_VERSION, true);
1613
+
1614
  // Located in the header to load datepicker js file to prevent error when async tags used
1615
  wp_enqueue_script ('ai-image-picker-js', plugins_url ('includes/js/image-picker.min.js', __FILE__ ), array (
1616
  'jquery',
1655
  $ai_wp_data [AI_STICKY_WIDGETS] ||
1656
  (defined ('AI_ADBLOCKING_DETECTION') && AI_ADBLOCKING_DETECTION && $ai_wp_data [AI_ADB_DETECTION]);
1657
 
1658
+ if ($footer_inline_scripts || $ai_wp_data [AI_CLIENT_SIDE_INSERTION] || $ai_wp_data [AI_FRONTEND_JS_DEBUGGING] || ($ai_wp_data [AI_WP_DEBUGGING] & (AI_DEBUG_POSITIONS | AI_DEBUG_BLOCKS)) != 0) {
1659
  // force loading of jquery on frontend
1660
  wp_enqueue_script ('ai-jquery-js', plugins_url ('includes/js/ai-jquery.js', __FILE__ ), array (
1661
  'jquery',
2378
  }
2379
 
2380
  // No scripts on AMP pages
2381
+ if (($ai_wp_data [AI_WP_DEBUGGING] & AI_DEBUG_POSITIONS) != 0) {
 
2382
  echo "<script>
2383
  jQuery(document).ready(function($) {
2384
  $('body').prepend (\"", get_page_type_debug_info () , "\");
2386
  </script>\n";
2387
  }
2388
 
2389
+ if (($ai_wp_data [AI_WP_DEBUGGING] & AI_DEBUG_BLOCKS) != 0) {
2390
+ echo "<script>
2391
+ jQuery(document).ready(function($) {
2392
+ setTimeout (function() {
2393
+ var google_auto_placed = jQuery ('.google-auto-placed');
2394
+ google_auto_placed.before ('<section class=\"ai-debug-bar ai-debug-adsense\">Automatically placed by AdSense Auto ads code</section>');
2395
+ }, 3000);
2396
+ });
2397
+ </script>\n";
2398
+ }
2399
+
2400
  if (defined ('AI_BUFFERING')) {
2401
  if (get_output_buffering ()) {
2402
  if ($ai_wp_data [AI_WP_PAGE_TYPE] != AI_PT_AJAX) {
3995
  generate_settings_form ();
3996
  }
3997
 
3998
+ elseif (isset ($_GET ["list-options"])) {
3999
+ generate_list_options ($_GET ["list-options"]);
4000
+ }
4001
+
4002
  elseif (isset ($_GET ["update"])) {
4003
  if ($_GET ["update"] == 'block-code-demo') {
4004
  ai_block_code_demo (urldecode ($_GET ["block_class_name"]), $_GET ["block_class"], $_GET ["block_number_class"], $_GET ["inline_styles"]);
4449
  .ai-debug-block.ai-debug-adb-status {border-color: #000;}
4450
  .ai-debug-bar.ai-debug-adb-status {background: #000;}
4451
 
4452
+ .ai-debug-block.ai-debug-adsense {border-color: #e0a;}
4453
+ .ai-debug-bar.ai-debug-adsense {background: #e0a;}
4454
+
4455
  .ai-debug-adb-status.on {color: #f00;}
4456
  .ai-debug-adb-status.off {color: #0f0;}
4457
 
class.php CHANGED
@@ -3513,17 +3513,20 @@ abstract class ai_CodeBlock extends ai_BaseCodeBlock {
3513
 
3514
  if ($urls == AD_EMPTY_DATA) return !$return;
3515
 
3516
- $urls_listed = explode (" ", $urls);
 
 
 
3517
  foreach ($urls_listed as $index => $url_listed) {
3518
  if (trim ($url_listed) == "") unset ($urls_listed [$index]); else
3519
  $urls_listed [$index] = trim ($url_listed);
3520
  }
3521
 
3522
- // print_r ($urls_listed);
3523
- // echo "<br />\n";
3524
- // echo ' page url: ' . $page_url, "<br />\n";
3525
- // echo ' listed urls: ' . $urls, "\n";
3526
- // echo "<br />\n";
3527
 
3528
  foreach ($urls_listed as $url_listed) {
3529
  if ($url_listed == '*') return $return;
3513
 
3514
  if ($urls == AD_EMPTY_DATA) return !$return;
3515
 
3516
+ $list_separator = ',';
3517
+ if (strpos ($urls, ' ') !== false && strpos ($urls, ',') === false) $list_separator = ' ';
3518
+
3519
+ $urls_listed = explode ($list_separator, $urls);
3520
  foreach ($urls_listed as $index => $url_listed) {
3521
  if (trim ($url_listed) == "") unset ($urls_listed [$index]); else
3522
  $urls_listed [$index] = trim ($url_listed);
3523
  }
3524
 
3525
+ // print_r ($urls_listed);
3526
+ // echo "<br />\n";
3527
+ // echo ' page url: ' . $page_url, "<br />\n";
3528
+ // echo ' listed urls: ' . $urls, "\n";
3529
+ // echo "<br />\n";
3530
 
3531
  foreach ($urls_listed as $url_listed) {
3532
  if ($url_listed == '*') return $return;
constants.php CHANGED
@@ -24,7 +24,7 @@ if (!defined( 'AD_INSERTER_NAME'))
24
  define ('AD_INSERTER_NAME', 'Ad Inserter');
25
 
26
  if (!defined( 'AD_INSERTER_VERSION'))
27
- define ('AD_INSERTER_VERSION', '2.3.2');
28
 
29
  if (!defined ('AD_INSERTER_PLUGIN_BASENAME'))
30
  define ('AD_INSERTER_PLUGIN_BASENAME', plugin_basename (__FILE__));
24
  define ('AD_INSERTER_NAME', 'Ad Inserter');
25
 
26
  if (!defined( 'AD_INSERTER_VERSION'))
27
+ define ('AD_INSERTER_VERSION', '2.3.3');
28
 
29
  if (!defined ('AD_INSERTER_PLUGIN_BASENAME'))
30
  define ('AD_INSERTER_PLUGIN_BASENAME', plugin_basename (__FILE__));
css/ad-inserter.css CHANGED
@@ -1,5 +1,5 @@
1
  #ai-data {
2
- font-family: "2.3.2"; /* Used for version number of the file */
3
  }
4
 
5
  #blocked-warning {
@@ -936,6 +936,16 @@ img.automatic-insertion.preview {
936
  background-size: cover;
937
  }
938
 
 
 
 
 
 
 
 
 
 
 
939
  .banner-preview {
940
  float: left;
941
  margin: 0 10px 0 0;
1
  #ai-data {
2
+ font-family: "2.3.3"; /* Used for version number of the file */
3
  }
4
 
5
  #blocked-warning {
936
  background-size: cover;
937
  }
938
 
939
+ .ai-button .ui-button-text.ai-button-active {
940
+ background: #f44;
941
+ border: 1px solid #f44;
942
+ border-radius: 8px;
943
+ width: 5px;
944
+ height: 5px;
945
+ padding: 0;
946
+ margin: 1px 0px 1px 3px;
947
+ }
948
+
949
  .banner-preview {
950
  float: left;
951
  margin: 0 10px 0 0;
css/images/switch.png ADDED
Binary file
css/multi-select.css ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ms-container{
2
+ background: transparent url('images/switch.png') no-repeat 50% 50%;
3
+ width: 370px;
4
+ }
5
+
6
+ .ms-container:after{
7
+ content: ".";
8
+ display: block;
9
+ height: 0;
10
+ line-height: 0;
11
+ font-size: 0;
12
+ clear: both;
13
+ min-height: 0;
14
+ visibility: hidden;
15
+ }
16
+
17
+ .ms-container .ms-selectable, .ms-container .ms-selection{
18
+ background: #fff;
19
+ color: #555555;
20
+ float: left;
21
+ width: 45%;
22
+ }
23
+ .ms-container .ms-selection{
24
+ float: right;
25
+ }
26
+
27
+ .ms-container .ms-list{
28
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
29
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
30
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
31
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
32
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
33
+ -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
34
+ -o-transition: border linear 0.2s, box-shadow linear 0.2s;
35
+ transition: border linear 0.2s, box-shadow linear 0.2s;
36
+ border: 1px solid #ccc;
37
+ -webkit-border-radius: 3px;
38
+ -moz-border-radius: 3px;
39
+ border-radius: 3px;
40
+ position: relative;
41
+ height: 200px;
42
+ padding: 0;
43
+ overflow-y: auto;
44
+ }
45
+
46
+ .ms-container .ms-list.ms-focus{
47
+ border-color: rgba(82, 168, 236, 0.8);
48
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
49
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
50
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
51
+ outline: 0;
52
+ outline: thin dotted \9;
53
+ }
54
+
55
+ .ms-container ul{
56
+ margin: 0;
57
+ list-style-type: none;
58
+ padding: 0;
59
+ }
60
+
61
+ .ms-container .ms-optgroup-container{
62
+ width: 100%;
63
+ }
64
+
65
+ .ms-container .ms-optgroup-label{
66
+ margin: 0;
67
+ padding: 5px 0px 0px 5px;
68
+ cursor: pointer;
69
+ color: #999;
70
+ }
71
+
72
+ .ms-container .ms-selectable li.ms-elem-selectable,
73
+ .ms-container .ms-selection li.ms-elem-selection{
74
+ border-bottom: 1px #eee solid;
75
+ padding: 2px 10px;
76
+ color: #555;
77
+ font-size: 14px;
78
+ }
79
+
80
+ .ms-container .ms-selectable li.ms-hover,
81
+ .ms-container .ms-selection li.ms-hover{
82
+ cursor: pointer;
83
+ color: #fff;
84
+ text-decoration: none;
85
+ background-color: #08c;
86
+ }
87
+
88
+ .ms-container .ms-selectable li.disabled,
89
+ .ms-container .ms-selection li.disabled{
90
+ background-color: #eee;
91
+ color: #aaa;
92
+ cursor: text;
93
+ }
css/multi-select.dev.css ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* line 1, ../scss/multi-select.scss */
2
+ .ms-container {
3
+ background: transparent url("../img/switch.png") no-repeat 50% 50%;
4
+ width: 370px;
5
+ }
6
+
7
+ /* line 6, ../scss/multi-select.scss */
8
+ .ms-container:after {
9
+ content: ".";
10
+ display: block;
11
+ height: 0;
12
+ line-height: 0;
13
+ font-size: 0;
14
+ clear: both;
15
+ min-height: 0;
16
+ visibility: hidden;
17
+ }
18
+
19
+ /* line 17, ../scss/multi-select.scss */
20
+ .ms-container .ms-selectable, .ms-container .ms-selection {
21
+ background: #fff;
22
+ color: #555555;
23
+ float: left;
24
+ width: 45%;
25
+ }
26
+
27
+ /* line 23, ../scss/multi-select.scss */
28
+ .ms-container .ms-selection {
29
+ float: right;
30
+ }
31
+
32
+ /* line 27, ../scss/multi-select.scss */
33
+ .ms-container .ms-list {
34
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
35
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
36
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
37
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
38
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
39
+ -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
40
+ -o-transition: border linear 0.2s, box-shadow linear 0.2s;
41
+ transition: border linear 0.2s, box-shadow linear 0.2s;
42
+ border: 1px solid #ccc;
43
+ -webkit-border-radius: 3px;
44
+ -moz-border-radius: 3px;
45
+ border-radius: 3px;
46
+ position: relative;
47
+ height: 200px;
48
+ padding: 0;
49
+ overflow-y: auto;
50
+ }
51
+
52
+ /* line 46, ../scss/multi-select.scss */
53
+ .ms-container .ms-list.ms-focus {
54
+ border-color: rgba(82, 168, 236, 0.8);
55
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
56
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
57
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
58
+ outline: 0;
59
+ outline: thin dotted \9;
60
+ }
61
+
62
+ /* line 55, ../scss/multi-select.scss */
63
+ .ms-container ul {
64
+ margin: 0;
65
+ list-style-type: none;
66
+ padding: 0;
67
+ }
68
+
69
+ /* line 61, ../scss/multi-select.scss */
70
+ .ms-container .ms-optgroup-container {
71
+ width: 100%;
72
+ }
73
+
74
+ /* line 65, ../scss/multi-select.scss */
75
+ .ms-container .ms-optgroup-label {
76
+ margin: 0;
77
+ padding: 5px 0px 0px 5px;
78
+ cursor: pointer;
79
+ color: #999;
80
+ }
81
+
82
+ /* line 72, ../scss/multi-select.scss */
83
+ .ms-container .ms-selectable li.ms-elem-selectable,
84
+ .ms-container .ms-selection li.ms-elem-selection {
85
+ border-bottom: 1px #eee solid;
86
+ padding: 2px 10px;
87
+ color: #555;
88
+ font-size: 14px;
89
+ }
90
+
91
+ /* line 80, ../scss/multi-select.scss */
92
+ .ms-container .ms-selectable li.ms-hover,
93
+ .ms-container .ms-selection li.ms-hover {
94
+ cursor: pointer;
95
+ color: #fff;
96
+ text-decoration: none;
97
+ background-color: #08c;
98
+ }
99
+
100
+ /* line 88, ../scss/multi-select.scss */
101
+ .ms-container .ms-selectable li.disabled,
102
+ .ms-container .ms-selection li.disabled {
103
+ background-color: #eee;
104
+ color: #aaa;
105
+ cursor: text;
106
+ }
107
+
108
+ /*# sourceMappingURL=multi-select.dev.css.map */
css/multi-select.dev.css.map ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ {
2
+ "version": 3,
3
+ "mappings": ";AAAA,aAAa;EACX,UAAU,EAAE,sDAAsD;EAClE,KAAK,EAAE,KAAK;;;;AAGd,mBAAmB;EACjB,OAAO,EAAE,GAAG;EACZ,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,CAAC;EACd,SAAS,EAAE,CAAC;EACZ,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,CAAC;EACb,UAAU,EAAE,MAAM;;;;AAGpB,yDAAyD;EACvD,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,OAAO;EACd,KAAK,EAAE,IAAI;EACX,KAAK,EAAE,GAAG;;;;AAEZ,2BAA2B;EACzB,KAAK,EAAE,KAAK;;;;AAGd,sBAAsB;EACpB,kBAAkB,EAAE,oCAAoC;EACxD,eAAe,EAAE,oCAAoC;EACrD,UAAU,EAAE,oCAAoC;EAChD,kBAAkB,EAAE,0CAA0C;EAC9D,eAAe,EAAE,0CAA0C;EAC3D,cAAc,EAAE,0CAA0C;EAC1D,aAAa,EAAE,0CAA0C;EACzD,UAAU,EAAE,0CAA0C;EACtD,MAAM,EAAE,cAAc;EACtB,qBAAqB,EAAE,GAAG;EAC1B,kBAAkB,EAAE,GAAG;EACvB,aAAa,EAAE,GAAG;EAClB,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,CAAC;EACV,UAAU,EAAE,IAAI;;;;AAGlB,+BAA+B;EAC7B,YAAY,EAAE,uBAAuB;EACrC,kBAAkB,EAAE,qEAAqE;EACzF,eAAe,EAAE,qEAAqE;EACtF,UAAU,EAAE,qEAAqE;EACjF,OAAO,EAAE,CAAC;EACV,OAAO,EAAE,cAAc;;;;AAGzB,gBAAgB;EACd,MAAM,EAAE,CAAC;EACT,eAAe,EAAE,IAAI;EACrB,OAAO,EAAE,CAAC;;;;AAGZ,oCAAoC;EAClC,KAAK,EAAE,IAAI;;;;AAGb,gCAAgC;EAC9B,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,eAAe;EACxB,MAAM,EAAE,OAAO;EACf,KAAK,EAAE,IAAI;;;;AAGb;gDACgD;EAC9C,aAAa,EAAE,cAAc;EAC7B,OAAO,EAAE,QAAQ;EACjB,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,IAAI;;;;AAGjB;uCACuC;EACrC,MAAM,EAAE,OAAO;EACf,KAAK,EAAE,IAAI;EACX,eAAe,EAAE,IAAI;EACrB,gBAAgB,EAAE,IAAI;;;;AAGxB;uCACuC;EACrC,gBAAgB,EAAE,IAAI;EACtB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI",
4
+ "sources": ["../scss/multi-select.scss"],
5
+ "names": [],
6
+ "file": "multi-select.dev.css"
7
+ }
css/multi-select.dist.css ADDED
@@ -0,0 +1 @@
 
1
+ .ms-container{background:transparent url("../img/switch.png") no-repeat 50% 50%;width:370px}.ms-container:after{content:".";display:block;height:0;line-height:0;font-size:0;clear:both;min-height:0;visibility:hidden}.ms-container .ms-selectable,.ms-container .ms-selection{background:#fff;color:#555555;float:left;width:45%}.ms-container .ms-selection{float:right}.ms-container .ms-list{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear 0.2s, box-shadow linear 0.2s;-moz-transition:border linear 0.2s, box-shadow linear 0.2s;-ms-transition:border linear 0.2s, box-shadow linear 0.2s;-o-transition:border linear 0.2s, box-shadow linear 0.2s;transition:border linear 0.2s, box-shadow linear 0.2s;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;position:relative;height:200px;padding:0;overflow-y:auto}.ms-container .ms-list.ms-focus{border-color:rgba(82,168,236,0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);outline:0;outline:thin dotted \9}.ms-container ul{margin:0;list-style-type:none;padding:0}.ms-container .ms-optgroup-container{width:100%}.ms-container .ms-optgroup-label{margin:0;padding:5px 0px 0px 5px;cursor:pointer;color:#999}.ms-container .ms-selectable li.ms-elem-selectable,.ms-container .ms-selection li.ms-elem-selection{border-bottom:1px #eee solid;padding:2px 10px;color:#555;font-size:14px}.ms-container .ms-selectable li.ms-hover,.ms-container .ms-selection li.ms-hover{cursor:pointer;color:#fff;text-decoration:none;background-color:#08c}.ms-container .ms-selectable li.disabled,.ms-container .ms-selection li.disabled{background-color:#eee;color:#aaa;cursor:text}
includes/js/jquery.multi-select.js ADDED
@@ -0,0 +1,549 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * MultiSelect v0.9.12
3
+ * Copyright (c) 2012 Louis Cuny
4
+ *
5
+ * This program is free software. It comes without any warranty, to
6
+ * the extent permitted by applicable law. You can redistribute it
7
+ * and/or modify it under the terms of the Do What The Fuck You Want
8
+ * To Public License, Version 2, as published by Sam Hocevar. See
9
+ * http://sam.zoy.org/wtfpl/COPYING for more details.
10
+ */
11
+
12
+ !function ($) {
13
+
14
+ "use strict";
15
+
16
+
17
+ /* MULTISELECT CLASS DEFINITION
18
+ * ====================== */
19
+
20
+ var MultiSelect = function (element, options) {
21
+ this.options = options;
22
+ this.$element = $(element);
23
+ this.$container = $('<div/>', { 'class': "ms-container" });
24
+ this.$selectableContainer = $('<div/>', { 'class': 'ms-selectable' });
25
+ this.$selectionContainer = $('<div/>', { 'class': 'ms-selection' });
26
+ this.$selectableUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
27
+ this.$selectionUl = $('<ul/>', { 'class': "ms-list", 'tabindex' : '-1' });
28
+ this.scrollTo = 0;
29
+ this.elemsSelector = 'li:visible:not(.ms-optgroup-label,.ms-optgroup-container,.'+options.disabledClass+')';
30
+ };
31
+
32
+ MultiSelect.prototype = {
33
+ constructor: MultiSelect,
34
+
35
+ init: function(){
36
+ var that = this,
37
+ ms = this.$element;
38
+
39
+ if (ms.next('.ms-container').length === 0){
40
+ ms.css({ position: 'absolute', left: '-9999px' });
41
+ ms.attr('id', ms.attr('id') ? ms.attr('id') : Math.ceil(Math.random()*1000)+'multiselect');
42
+ this.$container.attr('id', 'ms-'+ms.attr('id'));
43
+ this.$container.addClass(that.options.cssClass);
44
+ ms.find('option').each(function(){
45
+ that.generateLisFromOption(this);
46
+ });
47
+
48
+ this.$selectionUl.find('.ms-optgroup-label').hide();
49
+
50
+ if (that.options.selectableHeader){
51
+ that.$selectableContainer.append(that.options.selectableHeader);
52
+ }
53
+ that.$selectableContainer.append(that.$selectableUl);
54
+ if (that.options.selectableFooter){
55
+ that.$selectableContainer.append(that.options.selectableFooter);
56
+ }
57
+
58
+ if (that.options.selectionHeader){
59
+ that.$selectionContainer.append(that.options.selectionHeader);
60
+ }
61
+ that.$selectionContainer.append(that.$selectionUl);
62
+ if (that.options.selectionFooter){
63
+ that.$selectionContainer.append(that.options.selectionFooter);
64
+ }
65
+
66
+ that.$container.append(that.$selectableContainer);
67
+ that.$container.append(that.$selectionContainer);
68
+ ms.after(that.$container);
69
+
70
+ that.activeMouse(that.$selectableUl);
71
+ that.activeKeyboard(that.$selectableUl);
72
+
73
+ var action = that.options.dblClick ? 'dblclick' : 'click';
74
+
75
+ that.$selectableUl.on(action, '.ms-elem-selectable', function(){
76
+ that.select($(this).data('ms-value'));
77
+ });
78
+ that.$selectionUl.on(action, '.ms-elem-selection', function(){
79
+ that.deselect($(this).data('ms-value'));
80
+ });
81
+
82
+ that.activeMouse(that.$selectionUl);
83
+ that.activeKeyboard(that.$selectionUl);
84
+
85
+ ms.on('focus', function(){
86
+ that.$selectableUl.focus();
87
+ });
88
+ }
89
+
90
+ var selectedValues = ms.find('option:selected').map(function(){ return $(this).val(); }).get();
91
+ that.select(selectedValues, 'init');
92
+
93
+ if (typeof that.options.afterInit === 'function') {
94
+ that.options.afterInit.call(this, this.$container);
95
+ }
96
+ },
97
+
98
+ 'generateLisFromOption' : function(option, index, $container){
99
+ var that = this,
100
+ ms = that.$element,
101
+ attributes = "",
102
+ $option = $(option);
103
+
104
+ for (var cpt = 0; cpt < option.attributes.length; cpt++){
105
+ var attr = option.attributes[cpt];
106
+
107
+ if(attr.name !== 'value' && attr.name !== 'disabled'){
108
+ attributes += attr.name+'="'+attr.value+'" ';
109
+ }
110
+ }
111
+ var selectableLi = $('<li '+attributes+'><span>'+that.escapeHTML($option.text())+'</span></li>'),
112
+ selectedLi = selectableLi.clone(),
113
+ value = $option.val(),
114
+ elementId = that.sanitize(value);
115
+
116
+ selectableLi
117
+ .data('ms-value', value)
118
+ .addClass('ms-elem-selectable')
119
+ .attr('id', elementId+'-selectable');
120
+
121
+ selectedLi
122
+ .data('ms-value', value)
123
+ .addClass('ms-elem-selection')
124
+ .attr('id', elementId+'-selection')
125
+ .hide();
126
+
127
+ if ($option.prop('disabled') || ms.prop('disabled')){
128
+ selectedLi.addClass(that.options.disabledClass);
129
+ selectableLi.addClass(that.options.disabledClass);
130
+ }
131
+
132
+ var $optgroup = $option.parent('optgroup');
133
+
134
+ if ($optgroup.length > 0){
135
+ var optgroupLabel = $optgroup.attr('label'),
136
+ optgroupId = that.sanitize(optgroupLabel),
137
+ $selectableOptgroup = that.$selectableUl.find('#optgroup-selectable-'+optgroupId),
138
+ $selectionOptgroup = that.$selectionUl.find('#optgroup-selection-'+optgroupId);
139
+
140
+ if ($selectableOptgroup.length === 0){
141
+ var optgroupContainerTpl = '<li class="ms-optgroup-container"></li>',
142
+ optgroupTpl = '<ul class="ms-optgroup"><li class="ms-optgroup-label"><span>'+optgroupLabel+'</span></li></ul>';
143
+
144
+ $selectableOptgroup = $(optgroupContainerTpl);
145
+ $selectionOptgroup = $(optgroupContainerTpl);
146
+ $selectableOptgroup.attr('id', 'optgroup-selectable-'+optgroupId);
147
+ $selectionOptgroup.attr('id', 'optgroup-selection-'+optgroupId);
148
+ $selectableOptgroup.append($(optgroupTpl));
149
+ $selectionOptgroup.append($(optgroupTpl));
150
+ if (that.options.selectableOptgroup){
151
+ $selectableOptgroup.find('.ms-optgroup-label').on('click', function(){
152
+ var values = $optgroup.children(':not(:selected, :disabled)').map(function(){ return $(this).val();}).get();
153
+ that.select(values);
154
+ });
155
+ $selectionOptgroup.find('.ms-optgroup-label').on('click', function(){
156
+ var values = $optgroup.children(':selected:not(:disabled)').map(function(){ return $(this).val();}).get();
157
+ that.deselect(values);
158
+ });
159
+ }
160
+ that.$selectableUl.append($selectableOptgroup);
161
+ that.$selectionUl.append($selectionOptgroup);
162
+ }
163
+ index = index === undefined ? $selectableOptgroup.find('ul').children().length : index + 1;
164
+ selectableLi.insertAt(index, $selectableOptgroup.children());
165
+ selectedLi.insertAt(index, $selectionOptgroup.children());
166
+ } else {
167
+ index = index === undefined ? that.$selectableUl.children().length : index;
168
+
169
+ selectableLi.insertAt(index, that.$selectableUl);
170
+ selectedLi.insertAt(index, that.$selectionUl);
171
+ }
172
+ },
173
+
174
+ 'addOption' : function(options){
175
+ var that = this;
176
+
177
+ if (options.value !== undefined && options.value !== null){
178
+ options = [options];
179
+ }
180
+ $.each(options, function(index, option){
181
+ if (option.value !== undefined && option.value !== null &&
182
+ that.$element.find("option[value='"+option.value+"']").length === 0){
183
+ var $option = $('<option value="'+option.value+'">'+option.text+'</option>'),
184
+ $container = option.nested === undefined ? that.$element : $("optgroup[label='"+option.nested+"']"),
185
+ index = parseInt((typeof option.index === 'undefined' ? $container.children().length : option.index));
186
+
187
+ if (option.optionClass) {
188
+ $option.addClass(option.optionClass);
189
+ }
190
+
191
+ if (option.disabled) {
192
+ $option.prop('disabled', true);
193
+ }
194
+
195
+ $option.insertAt(index, $container);
196
+ that.generateLisFromOption($option.get(0), index, option.nested);
197
+ }
198
+ });
199
+ },
200
+
201
+ 'escapeHTML' : function(text){
202
+ return $("<div>").text(text).html();
203
+ },
204
+
205
+ 'activeKeyboard' : function($list){
206
+ var that = this;
207
+
208
+ $list.on('focus', function(){
209
+ $(this).addClass('ms-focus');
210
+ })
211
+ .on('blur', function(){
212
+ $(this).removeClass('ms-focus');
213
+ })
214
+ .on('keydown', function(e){
215
+ switch (e.which) {
216
+ case 40:
217
+ case 38:
218
+ e.preventDefault();
219
+ e.stopPropagation();
220
+ that.moveHighlight($(this), (e.which === 38) ? -1 : 1);
221
+ return;
222
+ case 37:
223
+ case 39:
224
+ e.preventDefault();
225
+ e.stopPropagation();
226
+ that.switchList($list);
227
+ return;
228
+ case 9:
229
+ if(that.$element.is('[tabindex]')){
230
+ e.preventDefault();
231
+ var tabindex = parseInt(that.$element.attr('tabindex'), 10);
232
+ tabindex = (e.shiftKey) ? tabindex-1 : tabindex+1;
233
+ $('[tabindex="'+(tabindex)+'"]').focus();
234
+ return;
235
+ }else{
236
+ if(e.shiftKey){
237
+ that.$element.trigger('focus');
238
+ }
239
+ }
240
+ }
241
+ if($.inArray(e.which, that.options.keySelect) > -1){
242
+ e.preventDefault();
243
+ e.stopPropagation();
244
+ that.selectHighlighted($list);
245
+ return;
246
+ }
247
+ });
248
+ },
249
+
250
+ 'moveHighlight': function($list, direction){
251
+ var $elems = $list.find(this.elemsSelector),
252
+ $currElem = $elems.filter('.ms-hover'),
253
+ $nextElem = null,
254
+ elemHeight = $elems.first().outerHeight(),
255
+ containerHeight = $list.height(),
256
+ containerSelector = '#'+this.$container.prop('id');
257
+
258
+ $elems.removeClass('ms-hover');
259
+ if (direction === 1){ // DOWN
260
+
261
+ $nextElem = $currElem.nextAll(this.elemsSelector).first();
262
+ if ($nextElem.length === 0){
263
+ var $optgroupUl = $currElem.parent();
264
+
265
+ if ($optgroupUl.hasClass('ms-optgroup')){
266
+ var $optgroupLi = $optgroupUl.parent(),
267
+ $nextOptgroupLi = $optgroupLi.next(':visible');
268
+
269
+ if ($nextOptgroupLi.length > 0){
270
+ $nextElem = $nextOptgroupLi.find(this.elemsSelector).first();
271
+ } else {
272
+ $nextElem = $elems.first();
273
+ }
274
+ } else {
275
+ $nextElem = $elems.first();
276
+ }
277
+ }
278
+ } else if (direction === -1){ // UP
279
+
280
+ $nextElem = $currElem.prevAll(this.elemsSelector).first();
281
+ if ($nextElem.length === 0){
282
+ var $optgroupUl = $currElem.parent();
283
+
284
+ if ($optgroupUl.hasClass('ms-optgroup')){
285
+ var $optgroupLi = $optgroupUl.parent(),
286
+ $prevOptgroupLi = $optgroupLi.prev(':visible');
287
+
288
+ if ($prevOptgroupLi.length > 0){
289
+ $nextElem = $prevOptgroupLi.find(this.elemsSelector).last();
290
+ } else {
291
+ $nextElem = $elems.last();
292
+ }
293
+ } else {
294
+ $nextElem = $elems.last();
295
+ }
296
+ }
297
+ }
298
+ if ($nextElem.length > 0){
299
+ $nextElem.addClass('ms-hover');
300
+ var scrollTo = $list.scrollTop() + $nextElem.position().top -
301
+ containerHeight / 2 + elemHeight / 2;
302
+
303
+ $list.scrollTop(scrollTo);
304
+ }
305
+ },
306
+
307
+ 'selectHighlighted' : function($list){
308
+ var $elems = $list.find(this.elemsSelector),
309
+ $highlightedElem = $elems.filter('.ms-hover').first();
310
+
311
+ if ($highlightedElem.length > 0){
312
+ if ($list.parent().hasClass('ms-selectable')){
313
+ this.select($highlightedElem.data('ms-value'));
314
+ } else {
315
+ this.deselect($highlightedElem.data('ms-value'));
316
+ }
317
+ $elems.removeClass('ms-hover');
318
+ }
319
+ },
320
+
321
+ 'switchList' : function($list){
322
+ $list.blur();
323
+ this.$container.find(this.elemsSelector).removeClass('ms-hover');
324
+ if ($list.parent().hasClass('ms-selectable')){
325
+ this.$selectionUl.focus();
326
+ } else {
327
+ this.$selectableUl.focus();
328
+ }
329
+ },
330
+
331
+ 'activeMouse' : function($list){
332
+ var that = this;
333
+
334
+ this.$container.on('mouseenter', that.elemsSelector, function(){
335
+ $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover');
336
+ $(this).addClass('ms-hover');
337
+ });
338
+
339
+ this.$container.on('mouseleave', that.elemsSelector, function () {
340
+ $(this).parents('.ms-container').find(that.elemsSelector).removeClass('ms-hover');
341
+ });
342
+ },
343
+
344
+ 'refresh' : function() {
345
+ this.destroy();
346
+ this.$element.multiSelect(this.options);
347
+ },
348
+
349
+ 'destroy' : function(){
350
+ $("#ms-"+this.$element.attr("id")).remove();
351
+ this.$element.off('focus');
352
+ this.$element.css('position', '').css('left', '');
353
+ this.$element.removeData('multiselect');
354
+ },
355
+
356
+ 'select' : function(value, method){
357
+ if (typeof value === 'string'){ value = [value]; }
358
+
359
+ var that = this,
360
+ ms = this.$element,
361
+ msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
362
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable').filter(':not(.'+that.options.disabledClass+')'),
363
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection').filter(':not(.'+that.options.disabledClass+')'),
364
+ options = ms.find('option:not(:disabled)').filter(function(){ return($.inArray(this.value, value) > -1); });
365
+
366
+ if (method === 'init'){
367
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
368
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #') + '-selection');
369
+ }
370
+
371
+ if (selectables.length > 0){
372
+ selectables.addClass('ms-selected').hide();
373
+ selections.addClass('ms-selected').show();
374
+
375
+ options.prop('selected', true);
376
+
377
+ that.$container.find(that.elemsSelector).removeClass('ms-hover');
378
+
379
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
380
+ if (selectableOptgroups.length > 0){
381
+ selectableOptgroups.each(function(){
382
+ var selectablesLi = $(this).find('.ms-elem-selectable');
383
+ if (selectablesLi.length === selectablesLi.filter('.ms-selected').length){
384
+ $(this).find('.ms-optgroup-label').hide();
385
+ }
386
+ });
387
+
388
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
389
+ selectionOptgroups.each(function(){
390
+ var selectionsLi = $(this).find('.ms-elem-selection');
391
+ if (selectionsLi.filter('.ms-selected').length > 0){
392
+ $(this).find('.ms-optgroup-label').show();
393
+ }
394
+ });
395
+ } else {
396
+ if (that.options.keepOrder && method !== 'init'){
397
+ var selectionLiLast = that.$selectionUl.find('.ms-selected');
398
+ if((selectionLiLast.length > 1) && (selectionLiLast.last().get(0) != selections.get(0))) {
399
+ selections.insertAfter(selectionLiLast.last());
400
+ }
401
+ }
402
+ }
403
+ if (method !== 'init'){
404
+ ms.trigger('change');
405
+ if (typeof that.options.afterSelect === 'function') {
406
+ that.options.afterSelect.call(this, value);
407
+ }
408
+ }
409
+ }
410
+ },
411
+
412
+ 'deselect' : function(value){
413
+ if (typeof value === 'string'){ value = [value]; }
414
+
415
+ var that = this,
416
+ ms = this.$element,
417
+ msIds = $.map(value, function(val){ return(that.sanitize(val)); }),
418
+ selectables = this.$selectableUl.find('#' + msIds.join('-selectable, #')+'-selectable'),
419
+ selections = this.$selectionUl.find('#' + msIds.join('-selection, #')+'-selection').filter('.ms-selected').filter(':not(.'+that.options.disabledClass+')'),
420
+ options = ms.find('option').filter(function(){ return($.inArray(this.value, value) > -1); });
421
+
422
+ if (selections.length > 0){
423
+ selectables.removeClass('ms-selected').show();
424
+ selections.removeClass('ms-selected').hide();
425
+ options.prop('selected', false);
426
+
427
+ that.$container.find(that.elemsSelector).removeClass('ms-hover');
428
+
429
+ var selectableOptgroups = that.$selectableUl.children('.ms-optgroup-container');
430
+ if (selectableOptgroups.length > 0){
431
+ selectableOptgroups.each(function(){
432
+ var selectablesLi = $(this).find('.ms-elem-selectable');
433
+ if (selectablesLi.filter(':not(.ms-selected)').length > 0){
434
+ $(this).find('.ms-optgroup-label').show();
435
+ }
436
+ });
437
+
438
+ var selectionOptgroups = that.$selectionUl.children('.ms-optgroup-container');
439
+ selectionOptgroups.each(function(){
440
+ var selectionsLi = $(this).find('.ms-elem-selection');
441
+ if (selectionsLi.filter('.ms-selected').length === 0){
442
+ $(this).find('.ms-optgroup-label').hide();
443
+ }
444
+ });
445
+ }
446
+ ms.trigger('change');
447
+ if (typeof that.options.afterDeselect === 'function') {
448
+ that.options.afterDeselect.call(this, value);
449
+ }
450
+ }
451
+ },
452
+
453
+ 'select_all' : function(){
454
+ var ms = this.$element,
455
+ values = ms.val();
456
+
457
+ ms.find('option:not(":disabled")').prop('selected', true);
458
+ this.$selectableUl.find('.ms-elem-selectable').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').hide();
459
+ this.$selectionUl.find('.ms-optgroup-label').show();
460
+ this.$selectableUl.find('.ms-optgroup-label').hide();
461
+ this.$selectionUl.find('.ms-elem-selection').filter(':not(.'+this.options.disabledClass+')').addClass('ms-selected').show();
462
+ this.$selectionUl.focus();
463
+ ms.trigger('change');
464
+ if (typeof this.options.afterSelect === 'function') {
465
+ var selectedValues = $.grep(ms.val(), function(item){
466
+ return $.inArray(item, values) < 0;
467
+ });
468
+ this.options.afterSelect.call(this, selectedValues);
469
+ }
470
+ },
471
+
472
+ 'deselect_all' : function(){
473
+ var ms = this.$element,
474
+ values = ms.val();
475
+
476
+ ms.find('option').prop('selected', false);
477
+ this.$selectableUl.find('.ms-elem-selectable').removeClass('ms-selected').show();
478
+ this.$selectionUl.find('.ms-optgroup-label').hide();
479
+ this.$selectableUl.find('.ms-optgroup-label').show();
480
+ this.$selectionUl.find('.ms-elem-selection').removeClass('ms-selected').hide();
481
+ this.$selectableUl.focus();
482
+ ms.trigger('change');
483
+ if (typeof this.options.afterDeselect === 'function') {
484
+ this.options.afterDeselect.call(this, values);
485
+ }
486
+ },
487
+
488
+ sanitize: function(value){
489
+ var hash = 0, i, character;
490
+ if (value.length == 0) return hash;
491
+ var ls = 0;
492
+ for (i = 0, ls = value.length; i < ls; i++) {
493
+ character = value.charCodeAt(i);
494
+
495
+ // hash = ((hash<<5)-hash)+character;
496
+
497
+ // prevent duplicate hash values
498
+ hash = ((hash<<8)-hash)+character;
499
+
500
+ hash |= 0; // Convert to 32bit integer
501
+ }
502
+ return hash;
503
+ }
504
+ };
505
+
506
+ /* MULTISELECT PLUGIN DEFINITION
507
+ * ======================= */
508
+
509
+ $.fn.multiSelect = function () {
510
+ var option = arguments[0],
511
+ args = arguments;
512
+
513
+ return this.each(function () {
514
+ var $this = $(this),
515
+ data = $this.data('multiselect'),
516
+ options = $.extend({}, $.fn.multiSelect.defaults, $this.data(), typeof option === 'object' && option);
517
+
518
+ if (!data){ $this.data('multiselect', (data = new MultiSelect(this, options))); }
519
+
520
+ if (typeof option === 'string'){
521
+ data[option](args[1]);
522
+ } else {
523
+ data.init();
524
+ }
525
+ });
526
+ };
527
+
528
+ $.fn.multiSelect.defaults = {
529
+ keySelect: [32],
530
+ selectableOptgroup: false,
531
+ disabledClass : 'disabled',
532
+ dblClick : false,
533
+ keepOrder: false,
534
+ cssClass: ''
535
+ };
536
+
537
+ $.fn.multiSelect.Constructor = MultiSelect;
538
+
539
+ $.fn.insertAt = function(index, $parent) {
540
+ return this.each(function() {
541
+ if (index === 0) {
542
+ $parent.prepend(this);
543
+ } else {
544
+ $parent.children().eq(index - 1).after(this);
545
+ }
546
+ });
547
+ };
548
+
549
+ }(window.jQuery);
includes/js/jquery.quicksearch.js ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function($, window, document, undefined) {
2
+ $.fn.quicksearch = function (target, opt) {
3
+
4
+ var timeout, cache, rowcache, jq_results, val = '', e = this, options = $.extend({
5
+ delay: 100,
6
+ selector: null,
7
+ stripeRows: null,
8
+ loader: null,
9
+ noResults: '',
10
+ matchedResultsCount: 0,
11
+ bind: 'keyup',
12
+ onBefore: function () {
13
+ return;
14
+ },
15
+ onAfter: function () {
16
+ return;
17
+ },
18
+ show: function () {
19
+ this.style.display = "";
20
+ },
21
+ hide: function () {
22
+ this.style.display = "none";
23
+ },
24
+ prepareQuery: function (val) {
25
+ return val.toLowerCase().split(' ');
26
+ },
27
+ testQuery: function (query, txt, _row) {
28
+ for (var i = 0; i < query.length; i += 1) {
29
+ if (txt.indexOf(query[i]) === -1) {
30
+ return false;
31
+ }
32
+ }
33
+ return true;
34
+ }
35
+ }, opt);
36
+
37
+ this.go = function () {
38
+
39
+ var i = 0,
40
+ numMatchedRows = 0,
41
+ noresults = true,
42
+ query = options.prepareQuery(val),
43
+ val_empty = (val.replace(' ', '').length === 0);
44
+
45
+ for (var i = 0, len = rowcache.length; i < len; i++) {
46
+ if (val_empty || options.testQuery(query, cache[i], rowcache[i])) {
47
+ options.show.apply(rowcache[i]);
48
+ noresults = false;
49
+ numMatchedRows++;
50
+ } else {
51
+ options.hide.apply(rowcache[i]);
52
+ }
53
+ }
54
+
55
+ if (noresults) {
56
+ this.results(false);
57
+ } else {
58
+ this.results(true);
59
+ this.stripe();
60
+ }
61
+
62
+ this.matchedResultsCount = numMatchedRows;
63
+ this.loader(false);
64
+ options.onAfter();
65
+
66
+ return this;
67
+ };
68
+
69
+ /*
70
+ * External API so that users can perform search programatically.
71
+ * */
72
+ this.search = function (submittedVal) {
73
+ val = submittedVal;
74
+ e.trigger();
75
+ };
76
+
77
+ /*
78
+ * External API to get the number of matched results as seen in
79
+ * https://github.com/ruiz107/quicksearch/commit/f78dc440b42d95ce9caed1d087174dd4359982d6
80
+ * */
81
+ this.currentMatchedResults = function() {
82
+ return this.matchedResultsCount;
83
+ };
84
+
85
+ this.stripe = function () {
86
+
87
+ if (typeof options.stripeRows === "object" && options.stripeRows !== null)
88
+ {
89
+ var joined = options.stripeRows.join(' ');
90
+ var stripeRows_length = options.stripeRows.length;
91
+
92
+ jq_results.not(':hidden').each(function (i) {
93
+ $(this).removeClass(joined).addClass(options.stripeRows[i % stripeRows_length]);
94
+ });
95
+ }
96
+
97
+ return this;
98
+ };
99
+
100
+ this.strip_html = function (input) {
101
+ var output = input.replace(new RegExp('<[^<]+\>', 'g'), "");
102
+ output = $.trim(output.toLowerCase());
103
+ return output;
104
+ };
105
+
106
+ this.results = function (bool) {
107
+ if (typeof options.noResults === "string" && options.noResults !== "") {
108
+ if (bool) {
109
+ $(options.noResults).hide();
110
+ } else {
111
+ $(options.noResults).show();
112
+ }
113
+ }
114
+ return this;
115
+ };
116
+
117
+ this.loader = function (bool) {
118
+ if (typeof options.loader === "string" && options.loader !== "") {
119
+ (bool) ? $(options.loader).show() : $(options.loader).hide();
120
+ }
121
+ return this;
122
+ };
123
+
124
+ this.cache = function () {
125
+
126
+ jq_results = $(target);
127
+
128
+ if (typeof options.noResults === "string" && options.noResults !== "") {
129
+ jq_results = jq_results.not(options.noResults);
130
+ }
131
+
132
+ var t = (typeof options.selector === "string") ? jq_results.find(options.selector) : $(target).not(options.noResults);
133
+ cache = t.map(function () {
134
+ return e.strip_html(this.innerHTML);
135
+ });
136
+
137
+ rowcache = jq_results.map(function () {
138
+ return this;
139
+ });
140
+
141
+ /*
142
+ * Modified fix for sync-ing "val".
143
+ * Original fix https://github.com/michaellwest/quicksearch/commit/4ace4008d079298a01f97f885ba8fa956a9703d1
144
+ * */
145
+ val = val || this.val() || "";
146
+
147
+ return this.go();
148
+ };
149
+
150
+ this.trigger = function () {
151
+ this.loader(true);
152
+ options.onBefore();
153
+
154
+ window.clearTimeout(timeout);
155
+ timeout = window.setTimeout(function () {
156
+ e.go();
157
+ }, options.delay);
158
+
159
+ return this;
160
+ };
161
+
162
+ this.cache();
163
+ this.results(true);
164
+ this.stripe();
165
+ this.loader(false);
166
+
167
+ return this.each(function () {
168
+
169
+ /*
170
+ * Changed from .bind to .on.
171
+ * */
172
+ $(this).on(options.bind, function () {
173
+
174
+ val = $(this).val();
175
+ e.trigger();
176
+ });
177
+ });
178
+
179
+ };
180
+
181
+ }(jQuery, this, document));
index.html CHANGED
@@ -14,7 +14,7 @@
14
  64 blocks, GEO targeting, impression and click tracking (supports also Javascript ads like AdSense), A/B testing, sticky positions, 6 viewports, import/export of plugin settings and has additional multisite support.
15
  </p>
16
  <div>
17
- <a href="http://adinserter.pro/documentation" target="_blank"><img style="display: block;margin: 0 auto;" src="https://ps.w.org/ad-inserter/assets/screenshot-1.jpg" alt="Ad Inserter Documentation" /></a>
18
  </div>
19
  <p>
20
  Settings for one code block. Up to 16 blocks can be configured.
14
  64 blocks, GEO targeting, impression and click tracking (supports also Javascript ads like AdSense), A/B testing, sticky positions, 6 viewports, import/export of plugin settings and has additional multisite support.
15
  </p>
16
  <div>
17
+ <a href="http://adinserter.pro/documentation" target="_blank"><img style="display: block;margin: 0 auto;" src="https://ps.w.org/ad-inserter/assets/screenshot-1.png" alt="Ad Inserter Documentation" /></a>
18
  </div>
19
  <p>
20
  Settings for one code block. Up to 16 blocks can be configured.
js/ad-inserter.js CHANGED
@@ -1,4 +1,4 @@
1
- var javascript_version = "2.3.2";
2
  var ignore_key = true;
3
  var start = 1;
4
  var end = 16;
@@ -1307,7 +1307,7 @@ jQuery(document).ready(function($) {
1307
 
1308
  $('#tab-0').addClass ('configured');
1309
 
1310
- $('#tab-0 input[type=submit]').button().show ();
1311
 
1312
  configure_editor ('h');
1313
  configure_editor ('f');
@@ -1352,7 +1352,7 @@ jQuery(document).ready(function($) {
1352
  if (syntax_highlighting) configure_editor_language ('a');
1353
 
1354
  for (var index = 1; index <= geo_groups; index ++) {
1355
- generate_country_list ('group-country', index);
1356
  }
1357
 
1358
  $('#enable-header').checkboxButton ();
@@ -1549,11 +1549,6 @@ jQuery(document).ready(function($) {
1549
 
1550
  process_display_elements (tab);
1551
 
1552
- $("#widgets-button-"+tab).button ({
1553
- }).click (function () {
1554
- window.location.href = "widgets.php";
1555
- });
1556
-
1557
  $("#exceptions-button-"+tab).button ({
1558
  }).click (function () {
1559
  var block = $(this).attr ("id").replace ("exceptions-button-","");
@@ -1855,7 +1850,15 @@ jQuery(document).ready(function($) {
1855
  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);
1856
  });
1857
 
1858
- generate_country_list ('country', tab);
 
 
 
 
 
 
 
 
1859
 
1860
  $('#tracking-' + tab).checkboxButton ();
1861
  $('#simple-editor-' + tab).checkboxButton ().click (function () {
@@ -2452,73 +2455,246 @@ jQuery(document).ready(function($) {
2452
  ul.closest ('.ai-rotate').data ('option', new_option + 1);
2453
  }
2454
 
2455
- function generate_country_list (element_name_prefix, index) {
2456
- if ($('#'+element_name_prefix+'-select-'+index).length !== 0) {
2457
-
2458
- $('#'+element_name_prefix+'-list-'+index).click (function () {
2459
-
2460
- if (!$('#'+element_name_prefix+'-select-'+index).hasClass ('multi-select')) {
2461
- $('#'+element_name_prefix+'-select-'+index).addClass ('multi-select');
2462
- $('#'+element_name_prefix+'-select-'+index).multiSelect({
2463
- selectableHeader: "<input type='text' class='search-input' autocomplete='off' placeholder='Search...'>",
2464
- selectedHeader: "Selected Countries",
2465
- afterInit: function(ms){
2466
- var that = this,
2467
- $selectableSearch = that.$selectableUl.prev(),
2468
- $selectionSearch = that.$selectionUl.prev(),
2469
- selectableSearchString = '#'+that.$container.attr('id')+' .ms-elem-selectable:not(.ms-selected)',
2470
- selectionSearchString = '#'+that.$container.attr('id')+' .ms-elem-selection.ms-selected';
2471
-
2472
- that.qs1 = $selectableSearch.quicksearch (selectableSearchString)
2473
- .on('keydown', function(e){
2474
- if (e.which === 40){
2475
- that.$selectableUl.focus();
2476
- return false;
2477
- }
2478
- });
 
 
 
 
 
 
 
 
 
2479
 
2480
- that.qs2 = $selectionSearch.quicksearch (selectionSearchString)
2481
- .on('keydown', function(e){
2482
- if (e.which == 40){
2483
- that.$selectionUl.focus();
2484
- return false;
2485
- }
2486
- });
2487
- },
2488
- afterSelect: function(values){
2489
- update_country_list (this, element_name_prefix);
2490
- },
2491
- afterDeselect: function(values){
2492
- update_country_list (this, element_name_prefix);
2493
- }
2494
- });
2495
- $('#ms-'+element_name_prefix+'-select-'+index).hide();
2496
  }
2497
- update_country_selection ($(this), element_name_prefix, true)
2498
- // $(this).focus ();
2499
- }).focusout (function () {
2500
- update_country_selection ($(this), element_name_prefix, false)
 
2501
  });
2502
  }
2503
  }
2504
 
2505
- function update_country_list (select_element, element_name_prefix) {
 
2506
  var ms = select_element.$element;
2507
  var ms_val = ms.val();
 
2508
  var index = ms.attr ('id').replace (element_name_prefix+'-select-','');
2509
- $('#'+element_name_prefix+'-list-'+index).attr ('value', ms_val);
 
 
 
 
 
 
 
 
 
 
 
2510
  select_element.qs1.cache();
2511
  select_element.qs2.cache();
2512
  }
2513
 
2514
- function update_country_selection (select_element, element_name_prefix, toggle) {
2515
- var index = select_element.attr ('id');
2516
- var index = index.replace (element_name_prefix+'-list-','');
2517
- if (toggle) $('#ms-'+element_name_prefix+'-select-'+index).toggle();
2518
- if ($('#ms-'+element_name_prefix+'-select-'+index).is(':visible')) {
2519
- var country_array = $('#'+element_name_prefix+'-list-'+index).attr ('value').replace(/ /g , '').toUpperCase().split (',');
2520
- $('#'+element_name_prefix+'-select-'+index).multiSelect ('deselect_all').multiSelect ('select', country_array).multiSelect('refresh');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2521
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2522
  }
2523
 
2524
  function configure_hidden_tab () {
1
+ var javascript_version = "2.3.3";
2
  var ignore_key = true;
3
  var start = 1;
4
  var end = 16;
1307
 
1308
  $('#tab-0').addClass ('configured');
1309
 
1310
+ $('#tab-0 input[type=submit], #tab-0 button.ai-button').button().show ();
1311
 
1312
  configure_editor ('h');
1313
  configure_editor ('f');
1352
  if (syntax_highlighting) configure_editor_language ('a');
1353
 
1354
  for (var index = 1; index <= geo_groups; index ++) {
1355
+ create_list_selector ('group-country', index);
1356
  }
1357
 
1358
  $('#enable-header').checkboxButton ();
1549
 
1550
  process_display_elements (tab);
1551
 
 
 
 
 
 
1552
  $("#exceptions-button-"+tab).button ({
1553
  }).click (function () {
1554
  var block = $(this).attr ("id").replace ("exceptions-button-","");
1850
  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);
1851
  });
1852
 
1853
+ create_list_selector ('category', tab);
1854
+ create_list_selector ('tag', tab);
1855
+ create_list_selector ('taxonomy', tab);
1856
+ create_list_selector ('id', tab);
1857
+ create_list_editor ('url', tab);
1858
+ create_list_editor ('url-parameter',tab);
1859
+ create_list_editor ('referer', tab);
1860
+ create_list_editor ('ip-address', tab);
1861
+ create_list_selector ('country', tab);
1862
 
1863
  $('#tracking-' + tab).checkboxButton ();
1864
  $('#simple-editor-' + tab).checkboxButton ().click (function () {
2455
  ul.closest ('.ai-rotate').data ('option', new_option + 1);
2456
  }
2457
 
2458
+ function create_list_selector (element_name_prefix, index) {
2459
+ var select = $('#'+element_name_prefix+'-select-'+index);
2460
+ if (select.length !== 0) {
2461
+ var button = $('#'+element_name_prefix+'-button-'+index);
2462
+ button.click (function () {
2463
+
2464
+ if (!select.hasClass ('multi-select')) {
2465
+ var options = select.find ('option');
2466
+ if (options.length == 0) {
2467
+ var nonce = $("#ai-form").attr ('nonce');
2468
+
2469
+ var select_data = select.data ('select');
2470
+ var data = typeof select_data == 'undefined' ? '' : select_data;
2471
+
2472
+ $('#ai-loading').show ();
2473
+ button.find ('span.ui-button-text').addClass ('ai-button-active');
2474
+ $.get (ajaxurl + '?action=ai_ajax_backend&list-options=' + element_name_prefix + '&data=' + data + '&ai_check=' + nonce, function (data) {
2475
+ if (data != '') {
2476
+ select.html (data);
2477
+ create_multi_select (select, element_name_prefix, index);
2478
+ update_selection_from_list ($('#'+element_name_prefix+'-list-'+index), element_name_prefix, true);
2479
+ }
2480
+
2481
+ }).fail (function (xhr, status, error) {
2482
+ var message = "Error loading " + element_name_prefix + " options: " + xhr.status + " " + xhr.statusText ;
2483
+ console.log (message);
2484
+ })
2485
+ .always (function () {
2486
+ $('#ai-loading').hide ();
2487
+ button.find ('span.ui-button-text').removeClass ('ai-button-active');
2488
+ });
2489
+
2490
+ } else create_multi_select (select, element_name_prefix, index);
2491
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2492
  }
2493
+ update_selection_from_list ($('#'+element_name_prefix+'-list-'+index), element_name_prefix, true);
2494
+ });
2495
+
2496
+ $('#'+element_name_prefix+'-list-'+index).focusout (function () {
2497
+ update_selection_from_list ($(this), element_name_prefix, false);
2498
  });
2499
  }
2500
  }
2501
 
2502
+ function update_list_from_selection (select_element, element_name_prefix) {
2503
+
2504
  var ms = select_element.$element;
2505
  var ms_val = ms.val();
2506
+ if (ms_val != null) var ms_val = ms_val.join (', ');
2507
  var index = ms.attr ('id').replace (element_name_prefix+'-select-','');
2508
+ var list = $('#'+element_name_prefix+'-list-'+index);
2509
+
2510
+ var custom_data = list.attr ('data-custom');
2511
+
2512
+ if (typeof custom_data != 'undefined' && custom_data != '') {
2513
+ if (ms_val != null) {
2514
+ if (ms_val != '') ms_val = ms_val + ', ';
2515
+ ms_val = ms_val + custom_data;
2516
+ } else ms_val = custom_data;
2517
+ }
2518
+
2519
+ list.attr ('value', ms_val);
2520
  select_element.qs1.cache();
2521
  select_element.qs2.cache();
2522
  }
2523
 
2524
+ function update_selection_from_list (list_element, element_name_prefix, toggle) {
2525
+
2526
+ Array.prototype.diff = function (a) {
2527
+ return this.filter(function (i) {
2528
+ return a.indexOf(i) === -1;
2529
+ });
2530
+ };
2531
+
2532
+ var index = list_element.attr ('id').replace (element_name_prefix+'-list-','');
2533
+ var selection_container = $('#ms-'+element_name_prefix+'-select-'+index);
2534
+ if (toggle) selection_container.toggle();
2535
+ if (selection_container.is(':visible')) {
2536
+ var list_items = list_element.attr ('value').split (',').map (Function.prototype.call, String.prototype.trim);
2537
+
2538
+ if (list_element.hasClass ('ai-list-filter'))
2539
+ for (var i = 0; i < list_items.length; i++) {
2540
+ list_items [i] = list_items [i].replace (/ /g , '-').replace (/[\!\@\#\$%\^&\*\(\)\=\+\{\}\|\[\]\\\;\'\:\"\.\/\?]/g , '');
2541
+ }
2542
+
2543
+ if (list_element.hasClass ('ai-list-uppercase'))
2544
+ list_items = list_items.map (Function.prototype.call, String.prototype.toUpperCase); else
2545
+ list_items = list_items.map (Function.prototype.call, String.prototype.toLowerCase);
2546
+
2547
+ // Set multiSelect
2548
+ $('#'+element_name_prefix+'-select-'+index).multiSelect ('deselect_all').multiSelect ('select', list_items).multiSelect('refresh');
2549
+
2550
+ if (list_element.hasClass ('ai-list-custom')) {
2551
+ var custom_values = list_items;
2552
+ var selected_values = $('#'+element_name_prefix+'-select-'+index).val ();
2553
+ if (selected_values != null) custom_values = list_items.diff (selected_values);
2554
+
2555
+ if (custom_values != null) var custom_values = custom_values.join (', ');
2556
+
2557
+ list_element.attr ('data-custom', custom_values);
2558
+
2559
+ // Set multiSelect again to add custom items
2560
+ $('#'+element_name_prefix+'-select-'+index).multiSelect ('deselect_all').multiSelect ('select', list_items).multiSelect('refresh');
2561
+ }
2562
+ } }
2563
+
2564
+ function create_multi_select (select, element_name_prefix, index) {
2565
+ select.addClass ('multi-select');
2566
+
2567
+ select.multiSelect ({
2568
+ selectableHeader: "<input type='text' class='search-input' autocomplete='off' placeholder='Search...'>",
2569
+ selectedHeader: "Selected Countries",
2570
+ afterInit: function(ms){
2571
+ var that = this,
2572
+ $selectableSearch = that.$selectableUl.prev(),
2573
+ $selectionSearch = that.$selectionUl.prev(),
2574
+ selectableSearchString = '#'+that.$container.attr('id')+' .ms-elem-selectable:not(.ms-selected)',
2575
+ selectionSearchString = '#'+that.$container.attr('id')+' .ms-elem-selection.ms-selected';
2576
+
2577
+ that.qs1 = $selectableSearch.quicksearch (selectableSearchString)
2578
+ .on('keydown', function(e){
2579
+ if (e.which === 40){
2580
+ that.$selectableUl.focus();
2581
+ return false;
2582
+ }
2583
+ });
2584
+
2585
+ that.qs2 = $selectionSearch.quicksearch (selectionSearchString)
2586
+ .on('keydown', function(e){
2587
+ if (e.which == 40){
2588
+ that.$selectionUl.focus();
2589
+ return false;
2590
+ }
2591
+ });
2592
+ },
2593
+ afterSelect: function(values){
2594
+ update_list_from_selection (this, element_name_prefix);
2595
+ },
2596
+ afterDeselect: function(values){
2597
+ update_list_from_selection (this, element_name_prefix);
2598
+ }
2599
+ });
2600
+ $('#ms-'+element_name_prefix+'-select-' + index).hide();
2601
+ }
2602
+
2603
+ function create_list_editor (element_name_prefix, index) {
2604
+ var editor = $('#'+element_name_prefix+'-editor-'+index);
2605
+ var list = $('#'+element_name_prefix+'-list-'+index);
2606
+ if (editor.length !== 0) {
2607
+ $('#'+element_name_prefix+'-button-'+index).click (function () {
2608
+ update_editor_from_list (list, element_name_prefix, true);
2609
+ });
2610
+
2611
+ editor.focusout (function () {
2612
+ update_list_from_editor (editor, element_name_prefix)
2613
+ });
2614
+
2615
+ list.focusout (function () {
2616
+ if (editor.is(':visible'))
2617
+ update_editor_from_list ($(this), element_name_prefix, false);
2618
+ });
2619
+ }
2620
+ }
2621
+
2622
+ function clean_url_list (list_element, list_items) {
2623
+
2624
+ var clean_protocol = list_element.hasClass ('ai-clean-protocol');
2625
+ var clean_domain = list_element.hasClass ('ai-clean-domain');
2626
+ var only_domain = list_element.hasClass ('ai-only-domain');
2627
+ var sort_list = list_element.hasClass ('ai-list-sort');
2628
+
2629
+ function onlyUnique (value, index, self) {
2630
+ return self.indexOf (value) === index;
2631
  }
2632
+
2633
+ list_items = list_items.filter (onlyUnique);
2634
+
2635
+ var clean_list_items = [];
2636
+
2637
+ for (var i = 0; i < list_items.length; i++) {
2638
+ var list_item = list_items [i];
2639
+
2640
+ if (clean_protocol && list_item.indexOf ('http') == 0) {
2641
+ list_item = list_item.replace ('http://', '');
2642
+ list_item = list_item.replace ('https://', '');
2643
+
2644
+ var slash = list_item.indexOf ("/");
2645
+
2646
+ if (clean_domain) {
2647
+ if (slash > 0) {
2648
+ list_item = list_item.substring (slash);
2649
+ } else list_item = '';
2650
+ } else
2651
+ if (only_domain) {
2652
+ if (slash > 0) {
2653
+ list_item = list_item.substring (0, slash);
2654
+ }
2655
+ }
2656
+ }
2657
+
2658
+ if (list_item != '') clean_list_items.push (list_item);
2659
+ }
2660
+
2661
+ if (sort_list) {
2662
+ clean_list_items.sort();
2663
+ }
2664
+
2665
+ return clean_list_items;
2666
+ }
2667
+
2668
+ function update_editor_from_list (list_element, element_name_prefix, toggle) {
2669
+ var index = list_element.attr ('id').replace (element_name_prefix+'-list-','');
2670
+ var editor = $('#'+element_name_prefix+'-editor-'+index);
2671
+ if (toggle) editor.toggle();
2672
+ if (editor.is(':visible')) {
2673
+
2674
+ var list = list_element.attr ('value');
2675
+ var list_separator = ',';
2676
+
2677
+ if (list_element.hasClass ('ai-list-space')) {
2678
+ if (list.indexOf (' ') > - 1 && list.indexOf (',') == - 1) list_separator = ' ';
2679
+ }
2680
+
2681
+ var list_items = list.split (list_separator).map (Function.prototype.call, String.prototype.trim);
2682
+
2683
+ clean_list_items = clean_url_list (list_element, list_items);
2684
+
2685
+ editor.val (clean_list_items.join ("\n"));
2686
+ } else update_list_from_editor (editor, element_name_prefix)
2687
+ }
2688
+
2689
+ function update_list_from_editor (editor, element_name_prefix) {
2690
+ var list_items = editor.val ().split ("\n").map (Function.prototype.call, String.prototype.trim);
2691
+
2692
+ var index = editor.attr ('id').replace (element_name_prefix+'-editor-','');
2693
+ var list_element = $('#'+element_name_prefix+'-list-'+index);
2694
+
2695
+ clean_list_items = clean_url_list (list_element, list_items);
2696
+
2697
+ list_element.attr ('value', clean_list_items.join (', '));
2698
  }
2699
 
2700
  function configure_hidden_tab () {
readme.txt CHANGED
@@ -6,7 +6,7 @@ Tags: ads, adsense, ad management, advertising manager, advanced contextual ads,
6
  Requires at least: 4.0
7
  Tested up to: 4.9
8
  Requires PHP: 5.3
9
- Stable tag: 2.3.1
10
  License: GPLv3
11
 
12
  Insert and manage ads: AdSense, Amazon, banners, ad rotation, sticky ad widgets, shortcodes, AMP, PHP, HTML, CSS, form, tracking, header, footer code
@@ -20,6 +20,27 @@ Ad Inserter is more than just ad manager plugin. It provides many advanced optio
20
  **Ad Inserter can insert ads where other plugins fail**.
21
  It's all about the settings.
22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  **Features**
24
 
25
  * 16 code (ad) blocks
@@ -95,26 +116,6 @@ Ad Inserter Wordpress plugin is an advanced advertising manager - it has many fe
95
  * Check <a href="http://adinserter.pro/documentation" target="_blank">Ad Inserter documentation pages</a> for detailed description of all the features and some <a href="http://adinserter.pro/settings" target="_blank">common settings</a> for quick start
96
  * Download **PDF user guide** for Ad Inserter: go to <a href="http://adinserter.pro/" target="_blank">Ad Inserter Pro plugin</a> page and below you can find button for free download of Ad Inserter User Guide
97
 
98
- **AdSense integration**
99
-
100
- Get <a href="https://adinserter.pro/adsense-ads#integration">AdSense ad codes</a> from the plugin settings page - no need to copy ad codes from the AdSense admin pages and paste them to code blocks. List ad units, preview AdSense ads and get ad codes where you need them.
101
-
102
- **Endorsed by WordPress users**
103
-
104
- Average Rating: 5 out of 5 stars
105
-
106
- > Perfect plugin to insert anything anywhere on your WordPress website
107
-
108
- Check Ad Inserter <a href="https://wordpress.org/support/plugin/ad-inserter/reviews/">reviews</a>
109
-
110
- **Endorsed by Amazon**
111
-
112
- Amazon suggests to use Ad Inserter to add Native Shopping Ads to Wordpress posts.
113
-
114
- > Native Shopping Ads provide highly relevant and dynamic product recommendations in a stylishly designed and responsive ad unit that can be placed at the end of your content or within your content to create a more compelling visitor experience and shopping opportunity.
115
-
116
- Check <a href="https://affiliate-program.amazon.com/help/topic/t405" target="_blank">Wordpress Integration Guide for Native Shopping Ads</a>. Ad Inserter supports also advanced contextual ads: check settings for <a href="https://adinserter.pro/settings#amazon">contextual Native Shopping Ads</a> that show items related to the post content (using post tags).
117
-
118
  **Ad Inserter Ad Manager - One Plugin - Many Functions**
119
 
120
  Ad Inserter is not just another plugin for WordPress ads. Do you enjoy finding the right plugin to solve a particular problem on your site? For example:
@@ -784,9 +785,13 @@ AD CODE RIGHT
784
 
785
  == Changelog ==
786
 
 
 
 
 
787
  = 2.3.2 =
788
  - Added AdSense code generator for ad sizes using CSS media queries
789
- - Fix for slow updates caused by changed user agent (credits Olivier Langlois)
790
  - Fix for client-side insertion of non-English characters before/after HTML element
791
 
792
  = 2.3.1 =
@@ -987,9 +992,13 @@ AD CODE RIGHT
987
 
988
  == Upgrade Notice ==
989
 
 
 
 
 
990
  = 2.3.2 =
991
  Added AdSense code generator for ad sizes using CSS media queries;
992
- Fix for slow updates caused by changed user agent (credits Olivier Langlois);
993
  Fix for client-side insertion of non-English characters before/after HTML element
994
 
995
  = 2.3.1 =
6
  Requires at least: 4.0
7
  Tested up to: 4.9
8
  Requires PHP: 5.3
9
+ Stable tag: 2.3.2
10
  License: GPLv3
11
 
12
  Insert and manage ads: AdSense, Amazon, banners, ad rotation, sticky ad widgets, shortcodes, AMP, PHP, HTML, CSS, form, tracking, header, footer code
20
  **Ad Inserter can insert ads where other plugins fail**.
21
  It's all about the settings.
22
 
23
+ **Endorsed by WordPress users**
24
+
25
+ Average Rating: 5 out of 5 stars
26
+
27
+ > Perfect plugin to insert anything anywhere on your WordPress website
28
+
29
+ Check Ad Inserter <a href="https://wordpress.org/support/plugin/ad-inserter/reviews/">reviews</a>
30
+
31
+ **AdSense integration**
32
+
33
+ Get <a href="https://adinserter.pro/adsense-ads#integration">AdSense ad codes</a> from the plugin settings page - no need to copy ad codes from the AdSense admin pages and paste them to code blocks. List ad units, preview AdSense ads and get ad codes where you need them.
34
+
35
+ **Endorsed by Amazon**
36
+
37
+ Amazon suggests to use Ad Inserter to add Native Shopping Ads to Wordpress posts.
38
+
39
+ > Native Shopping Ads provide highly relevant and dynamic product recommendations in a stylishly designed and responsive ad unit that can be placed at the end of your content or within your content to create a more compelling visitor experience and shopping opportunity.
40
+
41
+ Check <a href="https://affiliate-program.amazon.com/help/topic/t405" target="_blank">Wordpress Integration Guide for Native Shopping Ads</a>. Ad Inserter supports also advanced contextual ads: check settings for <a href="https://adinserter.pro/settings#amazon">contextual Native Shopping Ads</a> that show items related to the post content (using post tags).
42
+
43
+
44
  **Features**
45
 
46
  * 16 code (ad) blocks
116
  * Check <a href="http://adinserter.pro/documentation" target="_blank">Ad Inserter documentation pages</a> for detailed description of all the features and some <a href="http://adinserter.pro/settings" target="_blank">common settings</a> for quick start
117
  * Download **PDF user guide** for Ad Inserter: go to <a href="http://adinserter.pro/" target="_blank">Ad Inserter Pro plugin</a> page and below you can find button for free download of Ad Inserter User Guide
118
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  **Ad Inserter Ad Manager - One Plugin - Many Functions**
120
 
121
  Ad Inserter is not just another plugin for WordPress ads. Do you enjoy finding the right plugin to solve a particular problem on your site? For example:
785
 
786
  == Changelog ==
787
 
788
+ = 2.3.3 =
789
+ - Added list editors
790
+ - Added Label blocks debugging function for AdSense Auto ads
791
+
792
  = 2.3.2 =
793
  - Added AdSense code generator for ad sizes using CSS media queries
794
+ - Fix for slow updates caused by changed user agent (Pro only, credits Olivier Langlois)
795
  - Fix for client-side insertion of non-English characters before/after HTML element
796
 
797
  = 2.3.1 =
992
 
993
  == Upgrade Notice ==
994
 
995
+ = 2.3.3 =
996
+ Added list editors;
997
+ Added Label blocks debugging function for AdSense Auto ads
998
+
999
  = 2.3.2 =
1000
  Added AdSense code generator for ad sizes using CSS media queries;
1001
+ Fix for slow updates caused by changed user agent (Pro only, credits Olivier Langlois);
1002
  Fix for client-side insertion of non-English characters before/after HTML element
1003
 
1004
  = 2.3.1 =
settings.php CHANGED
@@ -66,7 +66,6 @@ function generate_settings_form (){
66
 
67
  $default = $block_object [0];
68
 
69
-
70
  $exceptions = false;
71
  $block_exceptions = array ();
72
  if (ai_current_user_role_ok () && (!is_multisite() || is_main_site () || multisite_exceptions_enabled ())) {
@@ -843,11 +842,11 @@ function generate_settings_form (){
843
 
844
  <div style="padding: 0; min-height: 28px;">
845
  <div style="float: left;">
846
- <button id="lists-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; margin-right: 4px;" title="White/Black-list Category, Tag, Url, Referer (domain) or Country"><span style="<?php echo $lists_style; ?>">Lists</span></button>
847
- <button id="manual-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; margin-right: 4px;" title="Widget, Shortcode and PHP function call"><span style="<?php echo $manual_style; ?>">Manual</span></button>
848
- <button id="device-detection-button-<?php echo $block; ?>" class='ai-button' type="button" style="display: none; margin-right: 4px;" title="Client/Server-side Device Detection (Desktop, Tablet, Phone,...)"><span style="<?php echo $devices_style; ?>">Devices</span></button>
849
- <button id="misc-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; margin-right: 4px;" title="Check for user status, Limit insertions, [error 404 page, Ajax requests, RSS feeds], Filter, Scheduling, General tag"><span style="<?php echo $misc_style; ?>">Misc</span></button>
850
- <button id="preview-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; margin-right: 4px;" title="Preview saved code above" site-url="<?php echo wp_make_link_relative (get_site_url()); ?>">Preview</button>
851
  </div>
852
  <div style="float: right;">
853
  <?php if (function_exists ('ai_settings_bottom_buttons')) ai_settings_bottom_buttons ($start, $end); else { ?>
@@ -1277,11 +1276,14 @@ function generate_settings_form (){
1277
  <table>
1278
  <tbody>
1279
  <tr>
1280
- <td style="padding-right: 7px;">
1281
  Categories
1282
  </td>
1283
- <td style="padding-right: 7px; width: 70%;">
1284
- <input style="width: 100%;" title="Comma separated category slugs" type="text" name="<?php echo AI_OPTION_CATEGORY_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_block_cat(); ?>" value="<?php echo $cat_list; ?>" size="54" maxlength="500" />
 
 
 
1285
  </td>
1286
  <td style="padding-right: 7px;">
1287
  <input type="radio" name="<?php echo AI_OPTION_CATEGORY_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="category-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_block_cat_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_block_cat_type() == AD_BLACK_LIST) echo 'checked '; ?> />
@@ -1293,11 +1295,21 @@ function generate_settings_form (){
1293
  </td>
1294
  </tr>
1295
  <tr>
1296
- <td style="padding-right: 7px;">
 
 
 
 
 
 
 
1297
  Tags
1298
  </td>
 
 
 
1299
  <td style="padding-right: 7px;">
1300
- <input style="width: 100%;" title="Comma separated tags" type="text" name="<?php echo AI_OPTION_TAG_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_block_tag(); ?>" value="<?php echo $tag_list; ?>" size="54" maxlength="500"/>
1301
  </td>
1302
  <td style="padding-right: 7px;">
1303
  <input type="radio" name="<?php echo AI_OPTION_TAG_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="tag-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_block_tag_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_block_tag_type() == AD_BLACK_LIST) echo 'checked '; ?> />
@@ -1309,11 +1321,21 @@ function generate_settings_form (){
1309
  </td>
1310
  </tr>
1311
  <tr>
1312
- <td style="padding-right: 7px;">
 
 
 
 
 
 
 
1313
  Taxonomies
1314
  </td>
1315
- <td style="padding-right: 7px; width: 70%;">
1316
- <input style="width: 100%;" title="Comma separated slugs: taxonomy, term or taxonomy:term" type="text" name="<?php echo AI_OPTION_TAXONOMY_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_block_taxonomy(); ?>" value="<?php echo $taxonomy_list; ?>" size="54" maxlength="500" />
 
 
 
1317
  </td>
1318
  <td style="padding-right: 7px;">
1319
  <input type="radio" name="<?php echo AI_OPTION_TAXONOMY_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="taxonomy-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_block_taxonomy_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_block_taxonomy_type() == AD_BLACK_LIST) echo 'checked '; ?> />
@@ -1325,11 +1347,21 @@ function generate_settings_form (){
1325
  </td>
1326
  </tr>
1327
  <tr>
1328
- <td style="padding-right: 7px;">
 
 
 
 
 
 
 
1329
  Post IDs
1330
  </td>
 
 
 
1331
  <td style="padding-right: 7px;">
1332
- <input style="width: 100%;" title="Comma separated post/page IDs" type="text" name="<?php echo AI_OPTION_ID_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_id_list(); ?>" value="<?php echo $id_list; ?>" size="54" maxlength="500"/>
1333
  </td>
1334
  <td style="padding-right: 7px;">
1335
  <input type="radio" name="<?php echo AI_OPTION_ID_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="id-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_id_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_id_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
@@ -1341,13 +1373,21 @@ function generate_settings_form (){
1341
  </td>
1342
  </tr>
1343
  <tr>
1344
- <td style="padding-right: 7px;">
 
 
 
 
 
 
 
1345
  Urls
1346
  </td>
 
 
 
1347
  <td style="padding-right: 7px;">
1348
- <input style="width: 100%;" type="text" name="<?php echo AI_OPTION_URL_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_url_list(); ?>" value="<?php echo $url_list; ?>" size="54" maxlength="500" title="SPACE separated urls (page addresses) starting with / after domain name (e.g. /permalink-url, use only when you need to taget a specific url not accessible by other means). You can also use partial urls with * (/url-start*. *url-pattern*, *url-end)" />
1349
- <br />
1350
- <!-- <textarea id="urls2-<?php echo $block; ?>" style="width: 100%; height: 100px; font-family: Courier, 'Courier New', monospace; font-weight: bold;" name="XX_<?php echo AI_OPTION_CODE, WP_FORM_FIELD_POSTFIX, $block; ?>"><?php echo esc_textarea (str_replace (' ', "\n", $url_list)); ?></textarea>-->
1351
  </td>
1352
  <td style="padding-right: 7px;">
1353
  <input type="radio" name="<?php echo AI_OPTION_URL_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="url-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_url_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_url_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
@@ -1359,11 +1399,21 @@ function generate_settings_form (){
1359
  </td>
1360
  </tr>
1361
  <tr>
1362
- <td style="padding-right: 7px;">
 
 
 
 
 
 
1363
  Url parameters
 
 
 
 
1364
  </td>
1365
  <td style="padding-right: 7px;">
1366
- <input style="width: 100%;" title="Comma separated url query parameters or cookies with optional values (use 'prameter', 'prameter=value', 'cookie' or 'cookie=value')" type="text" name="<?php echo AI_OPTION_URL_PARAMETER_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_url_parameter_list(); ?>" value="<?php echo $url_parameter_list; ?>" size="54" maxlength="500"/>
1367
  </td>
1368
  <td style="padding-right: 7px;">
1369
  <input type="radio" name="<?php echo AI_OPTION_URL_PARAMETER_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="url-parameter-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_url_parameter_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_url_parameter_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
@@ -1375,11 +1425,20 @@ function generate_settings_form (){
1375
  </td>
1376
  </tr>
1377
  <tr>
1378
- <td style="padding-right: 7px;">
 
 
 
 
 
 
1379
  Referers
1380
  </td>
 
 
 
1381
  <td style="padding-right: 7px;">
1382
- <input style="width: 100%;" title="Comma separated domains, use # for no referer" type="text" name="<?php echo AI_OPTION_DOMAIN_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_domain_list(); ?>" value="<?php echo $domain_list; ?>" size="54" maxlength="500"/>
1383
  </td>
1384
  <td style="padding-right: 7px;">
1385
  <input type="radio" name="<?php echo AI_OPTION_DOMAIN_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="referer-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_domain_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_domain_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
@@ -1390,6 +1449,12 @@ function generate_settings_form (){
1390
  <label for="referer-whitelist-<?php echo $block; ?>" title="Whitelist referers"><?php echo AD_WHITE_LIST; ?></label>
1391
  </td>
1392
  </tr>
 
 
 
 
 
 
1393
  <?php if (function_exists ('ai_list_rows')) ai_list_rows ($block, $default, $obj); ?>
1394
  </tbody>
1395
  </table>
@@ -1407,7 +1472,6 @@ function generate_settings_form (){
1407
  </td>
1408
  <td>
1409
  <pre class="ai-sidebars" style= "margin: 0; display: inline; color: blue; white-space: pre-wrap; word-wrap: break-word;" title="Sidebars (or widget positions) where this widged is used"><?php echo $sidebars [$block], !empty ($sidebars [$block]) ? " &nbsp;" : ""; ?></pre>
1410
- <button id="widgets-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; width: 15px; height: 15px;" title="Manage Widgets"></button>
1411
  </td>
1412
  </tr>
1413
  <tr>
@@ -2968,7 +3032,6 @@ function adsense_list () {
2968
 
2969
  }
2970
 
2971
-
2972
  function adsense_code ($ad_slot_id) {
2973
  if (defined ('AI_ADSENSE_API')) {
2974
  require_once AD_INSERTER_PLUGIN_DIR.'includes/adsense-api.php';
@@ -2981,6 +3044,109 @@ function adsense_code ($ad_slot_id) {
2981
  }
2982
  }
2983
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2984
 
2985
  function sidebar_addense_alternative () { ?>
2986
 
66
 
67
  $default = $block_object [0];
68
 
 
69
  $exceptions = false;
70
  $block_exceptions = array ();
71
  if (ai_current_user_role_ok () && (!is_multisite() || is_main_site () || multisite_exceptions_enabled ())) {
842
 
843
  <div style="padding: 0; min-height: 28px;">
844
  <div style="float: left;">
845
+ <button id="lists-button-<?php echo $block; ?>" type="button" class='ai-button2' style="display: none; margin-right: 4px;" title="White/Black-list Category, Tag, Url, Referer (domain) or Country"><span style="<?php echo $lists_style; ?>">Lists</span></button>
846
+ <button id="manual-button-<?php echo $block; ?>" type="button" class='ai-button2' style="display: none; margin-right: 4px;" title="Widget, Shortcode and PHP function call"><span style="<?php echo $manual_style; ?>">Manual</span></button>
847
+ <button id="device-detection-button-<?php echo $block; ?>" class='ai-button2' type="button" style="display: none; margin-right: 4px;" title="Client/Server-side Device Detection (Desktop, Tablet, Phone,...)"><span style="<?php echo $devices_style; ?>">Devices</span></button>
848
+ <button id="misc-button-<?php echo $block; ?>" type="button" class='ai-button2' style="display: none; margin-right: 4px;" title="Check for user status, Limit insertions, [error 404 page, Ajax requests, RSS feeds], Filter, Scheduling, General tag"><span style="<?php echo $misc_style; ?>">Misc</span></button>
849
+ <button id="preview-button-<?php echo $block; ?>" type="button" class='ai-button2' style="display: none; margin-right: 4px;" title="Preview saved code above" site-url="<?php echo wp_make_link_relative (get_site_url()); ?>">Preview</button>
850
  </div>
851
  <div style="float: right;">
852
  <?php if (function_exists ('ai_settings_bottom_buttons')) ai_settings_bottom_buttons ($start, $end); else { ?>
1276
  <table>
1277
  <tbody>
1278
  <tr>
1279
+ <td>
1280
  Categories
1281
  </td>
1282
+ <td>
1283
+ <button id="category-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Toggle category editor"></button>
1284
+ </td>
1285
+ <td style="padding-right: 7px; width: 65%;">
1286
+ <input id="category-list-<?php echo $block; ?>" class="ai-list-filter ai-list-custom" style="width: 100%;" title="Comma separated category slugs" type="text" name="<?php echo AI_OPTION_CATEGORY_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_block_cat(); ?>" value="<?php echo $cat_list; ?>" size="54" maxlength="500" />
1287
  </td>
1288
  <td style="padding-right: 7px;">
1289
  <input type="radio" name="<?php echo AI_OPTION_CATEGORY_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="category-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_block_cat_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_block_cat_type() == AD_BLACK_LIST) echo 'checked '; ?> />
1295
  </td>
1296
  </tr>
1297
  <tr>
1298
+ <td colspan="5">
1299
+ <select id="category-select-<?php echo $block; ?>" multiple="multiple" style="display: none;">
1300
+ </select>
1301
+ </td>
1302
+ </tr>
1303
+
1304
+ <tr>
1305
+ <td>
1306
  Tags
1307
  </td>
1308
+ <td>
1309
+ <button id="tag-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Toggle tag editor"></button>
1310
+ </td>
1311
  <td style="padding-right: 7px;">
1312
+ <input id="tag-list-<?php echo $block; ?>" class="ai-list-filter ai-list-custom" style="width: 100%;" title="Comma separated tag slugs" type="text" name="<?php echo AI_OPTION_TAG_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_block_tag(); ?>" value="<?php echo $tag_list; ?>" size="54" maxlength="500"/>
1313
  </td>
1314
  <td style="padding-right: 7px;">
1315
  <input type="radio" name="<?php echo AI_OPTION_TAG_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="tag-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_block_tag_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_block_tag_type() == AD_BLACK_LIST) echo 'checked '; ?> />
1321
  </td>
1322
  </tr>
1323
  <tr>
1324
+ <td colspan="5">
1325
+ <select id="tag-select-<?php echo $block; ?>" multiple="multiple" style="display: none;">
1326
+ </select>
1327
+ </td>
1328
+ </tr>
1329
+
1330
+ <tr>
1331
+ <td>
1332
  Taxonomies
1333
  </td>
1334
+ <td>
1335
+ <button id="taxonomy-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Toggle taxonomy editor"></button>
1336
+ </td>
1337
+ <td style="padding-right: 7px;">
1338
+ <input id="taxonomy-list-<?php echo $block; ?>" class="ai-list-custom" style="width: 100%;" title="Comma separated slugs: taxonomy, term or taxonomy:term" type="text" name="<?php echo AI_OPTION_TAXONOMY_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_block_taxonomy(); ?>" value="<?php echo $taxonomy_list; ?>" size="54" maxlength="500" />
1339
  </td>
1340
  <td style="padding-right: 7px;">
1341
  <input type="radio" name="<?php echo AI_OPTION_TAXONOMY_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="taxonomy-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_block_taxonomy_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_block_taxonomy_type() == AD_BLACK_LIST) echo 'checked '; ?> />
1347
  </td>
1348
  </tr>
1349
  <tr>
1350
+ <td colspan="5">
1351
+ <select id="taxonomy-select-<?php echo $block; ?>" multiple="multiple" style="display: none;">
1352
+ </select>
1353
+ </td>
1354
+ </tr>
1355
+
1356
+ <tr>
1357
+ <td>
1358
  Post IDs
1359
  </td>
1360
+ <td>
1361
+ <button id="id-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Toggle post/page ID editor"></button>
1362
+ </td>
1363
  <td style="padding-right: 7px;">
1364
+ <input id="id-list-<?php echo $block; ?>" class="ai-list-custom" style="width: 100%;" title="Comma separated post/page IDs" type="text" name="<?php echo AI_OPTION_ID_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_id_list(); ?>" value="<?php echo $id_list; ?>" size="54" maxlength="500"/>
1365
  </td>
1366
  <td style="padding-right: 7px;">
1367
  <input type="radio" name="<?php echo AI_OPTION_ID_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="id-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_id_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_id_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
1373
  </td>
1374
  </tr>
1375
  <tr>
1376
+ <td colspan="5">
1377
+ <select id="id-select-<?php echo $block; ?>" multiple="multiple" style="display: none;">
1378
+ </select>
1379
+ </td>
1380
+ </tr>
1381
+
1382
+ <tr>
1383
+ <td>
1384
  Urls
1385
  </td>
1386
+ <td>
1387
+ <button id="url-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Toggle url editor"></button>
1388
+ </td>
1389
  <td style="padding-right: 7px;">
1390
+ <input id="url-list-<?php echo $block; ?>" class="ai-list-space ai-clean-protocol ai-clean-domain" style="width: 100%;" type="text" name="<?php echo AI_OPTION_URL_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_url_list(); ?>" value="<?php echo $url_list; ?>" size="54" maxlength="500" title="Comma separated urls (page addresses) starting with / after domain name (e.g. /permalink-url, use only when you need to taget a specific url not accessible by other means). You can also use partial urls with * (/url-start*. *url-pattern*, *url-end)" />
 
 
1391
  </td>
1392
  <td style="padding-right: 7px;">
1393
  <input type="radio" name="<?php echo AI_OPTION_URL_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="url-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_url_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_url_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
1399
  </td>
1400
  </tr>
1401
  <tr>
1402
+ <td colspan="5">
1403
+ <textarea id="url-editor-<?php echo $block; ?>" style="width: 100%; height: 220px; font-family: Courier, 'Courier New', monospace; font-weight: bold; display: none;"></textarea>
1404
+ </td>
1405
+ </tr>
1406
+
1407
+ <tr>
1408
+ <td>
1409
  Url parameters
1410
+ &nbsp;
1411
+ </td>
1412
+ <td>
1413
+ <button id="url-parameter-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Toggle url parameter editor"></button>
1414
  </td>
1415
  <td style="padding-right: 7px;">
1416
+ <input id="url-parameter-list-<?php echo $block; ?>" style="width: 100%;" title="Comma separated url query parameters or cookies with optional values (use 'prameter', 'prameter=value', 'cookie' or 'cookie=value')" type="text" name="<?php echo AI_OPTION_URL_PARAMETER_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_url_parameter_list(); ?>" value="<?php echo $url_parameter_list; ?>" size="54" maxlength="500"/>
1417
  </td>
1418
  <td style="padding-right: 7px;">
1419
  <input type="radio" name="<?php echo AI_OPTION_URL_PARAMETER_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="url-parameter-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_url_parameter_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_url_parameter_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
1425
  </td>
1426
  </tr>
1427
  <tr>
1428
+ <td colspan="5">
1429
+ <textarea id="url-parameter-editor-<?php echo $block; ?>" style="width: 100%; height: 220px; font-family: Courier, 'Courier New', monospace; font-weight: bold; display: none;"></textarea>
1430
+ </td>
1431
+ </tr>
1432
+
1433
+ <tr>
1434
+ <td>
1435
  Referers
1436
  </td>
1437
+ <td>
1438
+ <button id="referer-button-<?php echo $block; ?>" type="button" class='ai-button' style="display: none; outline: transparent; float: right; margin-top: 1px; width: 15px; height: 15px;" title="Toggle referer editor"></button>
1439
+ </td>
1440
  <td style="padding-right: 7px;">
1441
+ <input id="referer-list-<?php echo $block; ?>" class="ai-clean-protocol ai-only-domain ai-list-sort" style="width: 100%;" title="Comma separated domains, use # for no referer" type="text" name="<?php echo AI_OPTION_DOMAIN_LIST, WP_FORM_FIELD_POSTFIX, $block; ?>" default="<?php echo $default->get_ad_domain_list(); ?>" value="<?php echo $domain_list; ?>" size="54" maxlength="500"/>
1442
  </td>
1443
  <td style="padding-right: 7px;">
1444
  <input type="radio" name="<?php echo AI_OPTION_DOMAIN_LIST_TYPE, WP_FORM_FIELD_POSTFIX, $block; ?>" id="referer-blacklist-<?php echo $block; ?>" default="<?php echo $default->get_ad_domain_list_type() == AD_BLACK_LIST; ?>" value="<?php echo AD_BLACK_LIST; ?>" <?php if ($obj->get_ad_domain_list_type() == AD_BLACK_LIST) echo 'checked '; ?> />
1449
  <label for="referer-whitelist-<?php echo $block; ?>" title="Whitelist referers"><?php echo AD_WHITE_LIST; ?></label>
1450
  </td>
1451
  </tr>
1452
+ <tr>
1453
+ <td colspan="5">
1454
+ <textarea id="referer-editor-<?php echo $block; ?>" style="width: 100%; height: 220px; font-family: Courier, 'Courier New', monospace; font-weight: bold; display: none;"></textarea>
1455
+ </td>
1456
+ </tr>
1457
+
1458
  <?php if (function_exists ('ai_list_rows')) ai_list_rows ($block, $default, $obj); ?>
1459
  </tbody>
1460
  </table>
1472
  </td>
1473
  <td>
1474
  <pre class="ai-sidebars" style= "margin: 0; display: inline; color: blue; white-space: pre-wrap; word-wrap: break-word;" title="Sidebars (or widget positions) where this widged is used"><?php echo $sidebars [$block], !empty ($sidebars [$block]) ? " &nbsp;" : ""; ?></pre>
 
1475
  </td>
1476
  </tr>
1477
  <tr>
3032
 
3033
  }
3034
 
 
3035
  function adsense_code ($ad_slot_id) {
3036
  if (defined ('AI_ADSENSE_API')) {
3037
  require_once AD_INSERTER_PLUGIN_DIR.'includes/adsense-api.php';
3044
  }
3045
  }
3046
 
3047
+ function generate_list_options ($options) {
3048
+ $max_items = 2000;
3049
+
3050
+ switch ($options) {
3051
+ case 'category':
3052
+ $category_data = get_categories ();
3053
+ $category_data = array_slice ($category_data, 0, $max_items);
3054
+ foreach ($category_data as $category) {
3055
+ echo " <option value='{$category->slug}'>{$category->slug} ({$category->name})</option>\n";
3056
+ }
3057
+ break;
3058
+
3059
+ case 'tag':
3060
+ $tag_data = get_tags ();
3061
+ $tag_data = array_slice ($tag_data, 0, $max_items);
3062
+ foreach ($tag_data as $tag) {
3063
+ echo " <option value='{$tag->slug}'>{$tag->slug} ({$tag->name})</option>\n";
3064
+ }
3065
+ break;
3066
+
3067
+ case 'taxonomy':
3068
+ $term_data = get_terms ();
3069
+ $taxonomies = array ();
3070
+ foreach ($term_data as $term) {
3071
+ if ($term->taxonomy == 'category') continue;
3072
+ if ($term->taxonomy == 'post_tag') continue;
3073
+ $taxonomies [strtolower ($term->taxonomy) . ':' . strtolower ($term->slug)] = $term->name;
3074
+ if (count ($taxonomies) >= $max_items) break;
3075
+ }
3076
+
3077
+ $args = array (
3078
+ 'public' => true,
3079
+ // '_builtin' => false,
3080
+ );
3081
+ $custom_post_types = get_post_types ($args, 'objects', 'and');
3082
+ foreach ($custom_post_types as $custom_post_type => $custom_post_data) {
3083
+ $taxonomies ['post-type:' . strtolower ($custom_post_type)] = $custom_post_data->labels->singular_name;
3084
+ }
3085
+
3086
+ $editable_roles = get_editable_roles ();
3087
+ foreach ($editable_roles as $editable_role_slug => $editable_role) {
3088
+ $taxonomies ['user-role:' . strtolower ($editable_role_slug)] = $editable_role ['name'];
3089
+ }
3090
+
3091
+ $users = get_users ();
3092
+ foreach ($users as $user) {
3093
+ $taxonomies ['user:' . strtolower ($user->data->user_login)] = $user->data->display_name;
3094
+ if (count ($taxonomies) >= $max_items) break;
3095
+ }
3096
+
3097
+ ksort ($taxonomies);
3098
+
3099
+ foreach ($taxonomies as $taxonomy => $taxonomy_name) {
3100
+ if ($taxonomy_name != '')
3101
+ echo " <option value='{$taxonomy}'>{$taxonomy} ({$taxonomy_name})</option>\n"; else
3102
+ echo " <option value='{$taxonomy}'>{$taxonomy}</option>\n";
3103
+ }
3104
+ break;
3105
+
3106
+ case 'id':
3107
+ $args = array (
3108
+ 'public' => true,
3109
+ '_builtin' => false
3110
+ );
3111
+ $custom_post_types = get_post_types ($args, 'names', 'and');
3112
+ $screens = array_values (array_merge (array ('post', 'page'), $custom_post_types));
3113
+
3114
+ $args = array (
3115
+ 'posts_per_page' => 3 * $max_items,
3116
+ 'offset' => 0,
3117
+ 'category' => '',
3118
+ 'category_name' => '',
3119
+ 'orderby' => 'ID',
3120
+ 'order' => 'ASC',
3121
+ 'include' => '',
3122
+ 'exclude' => '',
3123
+ 'meta_key' => '',
3124
+ 'meta_value' => '',
3125
+ 'post_type' => $screens,
3126
+ 'post_mime_type' => '',
3127
+ 'post_parent' => '',
3128
+ 'author' => '',
3129
+ 'author_name' => '',
3130
+ 'post_status' => '',
3131
+ 'suppress_filters' => true,
3132
+ );
3133
+ $posts_pages = get_posts ($args);
3134
+
3135
+ $counter = 0;
3136
+ foreach ($posts_pages as $post_page) {
3137
+ if ($post_page->post_title == '') continue;
3138
+ echo " <option value='{$post_page->ID}'>{$post_page->ID} ({$post_page->post_type} \"{$post_page->post_title}\")</option>\n";
3139
+ $counter ++;
3140
+ if ($counter >= $max_items) break;
3141
+ }
3142
+ break;
3143
+
3144
+ default:
3145
+ if (function_exists ('ai_generate_list_options')) ai_generate_list_options ($options);
3146
+ break;
3147
+ }
3148
+ }
3149
+
3150
 
3151
  function sidebar_addense_alternative () { ?>
3152