Header Footer Elementor - Version 1.2.0

Version Description

  • New: Support all the themes, Includes two separate fallback methods so that you can create custom headers and footers for any theme.
  • New: Added target rule engine, which allows you to have different headers/footers for different pages.
  • New: Added Retina Image Elementor widget, which can be used as a Site Logo.
  • New: Added Copyright widget and Shortcode for current year & site title.
  • Improvement: Allow before footer to work on Elementor Canvas Template when not using Astra Theme.
  • Improvement: Added support of Before Footer action for all the themes.
Download this release

Release Info

Developer Nikschavan
Plugin Icon Header Footer Elementor
Version 1.2.0
Comparing to
See all releases

Code changes from version v1.1.4 to 1.2.0

Files changed (93) hide show
  1. admin/assets/css/ehf-admin.css +27 -2
  2. admin/class-hfe-admin.php +204 -29
  3. assets/css/admin-header-footer-elementor.css +43 -0
  4. assets/css/header-footer-elementor.css +2 -1
  5. assets/images/header-footer-elementor-icon.svg +36 -0
  6. assets/js/hfe-sites-notices.js +0 -22
  7. header-footer-elementor.php +10 -10
  8. inc/class-header-footer-elementor.php +152 -76
  9. inc/class-hfe-elementor-canvas-compat.php +16 -7
  10. inc/class-hfe-notices.php +0 -218
  11. inc/class-hfe-update.php +80 -2
  12. inc/compatibility/class-hfe-wpml-compatibility.php +3 -3
  13. inc/hfe-functions.php +55 -0
  14. inc/lib/notices/class-astra-notices.php +350 -0
  15. inc/lib/notices/notices.js +95 -0
  16. inc/lib/target-rule/class-astra-target-rules-fields.php +1618 -0
  17. inc/lib/target-rule/i18n/af.js +3 -0
  18. inc/lib/target-rule/i18n/ar.js +3 -0
  19. inc/lib/target-rule/i18n/az.js +3 -0
  20. inc/lib/target-rule/i18n/bg.js +3 -0
  21. inc/lib/target-rule/i18n/bs.js +3 -0
  22. inc/lib/target-rule/i18n/ca.js +3 -0
  23. inc/lib/target-rule/i18n/cs.js +3 -0
  24. inc/lib/target-rule/i18n/da.js +3 -0
  25. inc/lib/target-rule/i18n/de.js +3 -0
  26. inc/lib/target-rule/i18n/dsb.js +3 -0
  27. inc/lib/target-rule/i18n/el.js +3 -0
  28. inc/lib/target-rule/i18n/en.js +3 -0
  29. inc/lib/target-rule/i18n/es.js +3 -0
  30. inc/lib/target-rule/i18n/et.js +3 -0
  31. inc/lib/target-rule/i18n/eu.js +3 -0
  32. inc/lib/target-rule/i18n/fa.js +3 -0
  33. inc/lib/target-rule/i18n/fi.js +3 -0
  34. inc/lib/target-rule/i18n/fr.js +3 -0
  35. inc/lib/target-rule/i18n/gl.js +3 -0
  36. inc/lib/target-rule/i18n/he.js +3 -0
  37. inc/lib/target-rule/i18n/hi.js +3 -0
  38. inc/lib/target-rule/i18n/hr.js +3 -0
  39. inc/lib/target-rule/i18n/hsb.js +3 -0
  40. inc/lib/target-rule/i18n/hu.js +3 -0
  41. inc/lib/target-rule/i18n/hy.js +3 -0
  42. inc/lib/target-rule/i18n/id.js +3 -0
  43. inc/lib/target-rule/i18n/is.js +3 -0
  44. inc/lib/target-rule/i18n/it.js +3 -0
  45. inc/lib/target-rule/i18n/ja.js +3 -0
  46. inc/lib/target-rule/i18n/km.js +3 -0
  47. inc/lib/target-rule/i18n/ko.js +3 -0
  48. inc/lib/target-rule/i18n/lt.js +3 -0
  49. inc/lib/target-rule/i18n/lv.js +3 -0
  50. inc/lib/target-rule/i18n/mk.js +3 -0
  51. inc/lib/target-rule/i18n/ms.js +3 -0
  52. inc/lib/target-rule/i18n/nb.js +3 -0
  53. inc/lib/target-rule/i18n/nl.js +3 -0
  54. inc/lib/target-rule/i18n/pl.js +3 -0
  55. inc/lib/target-rule/i18n/ps.js +3 -0
  56. inc/lib/target-rule/i18n/pt-BR.js +3 -0
  57. inc/lib/target-rule/i18n/pt.js +3 -0
  58. inc/lib/target-rule/i18n/ro.js +3 -0
  59. inc/lib/target-rule/i18n/ru.js +3 -0
  60. inc/lib/target-rule/i18n/sk.js +3 -0
  61. inc/lib/target-rule/i18n/sl.js +3 -0
  62. inc/lib/target-rule/i18n/sr-Cyrl.js +3 -0
  63. inc/lib/target-rule/i18n/sr.js +3 -0
  64. inc/lib/target-rule/i18n/sv.js +3 -0
  65. inc/lib/target-rule/i18n/th.js +3 -0
  66. inc/lib/target-rule/i18n/tr.js +3 -0
  67. inc/lib/target-rule/i18n/uk.js +3 -0
  68. inc/lib/target-rule/i18n/vi.js +3 -0
  69. inc/lib/target-rule/i18n/zh-CN.js +3 -0
  70. inc/lib/target-rule/i18n/zh-TW.js +3 -0
  71. inc/lib/target-rule/select2.css +1 -0
  72. inc/lib/target-rule/select2.js +5768 -0
  73. inc/lib/target-rule/target-rule.css +104 -0
  74. inc/lib/target-rule/target-rule.js +245 -0
  75. inc/lib/target-rule/user-role.js +75 -0
  76. inc/widgets-manager/class-widgets-loader.php +110 -0
  77. inc/widgets-manager/widgets/class-copyright-shortcode.php +64 -0
  78. inc/widgets-manager/widgets/class-copyright.php +227 -0
  79. inc/widgets-manager/widgets/class-retina.php +842 -0
  80. inc/widgets-manager/widgets/index.php +3 -0
  81. languages/header-footer-elementor.pot +482 -32
  82. readme.txt +23 -22
  83. themes/astra/class-hfe-astra-compat.php +5 -100
  84. themes/bb-theme/class-hfe-bb-theme-compat.php +7 -8
  85. themes/default/class-global-theme-compatibility.php +96 -0
  86. themes/default/class-hfe-default-compat.php +87 -0
  87. themes/default/class-hfe-fallback-theme-support.php +238 -0
  88. themes/default/hfe-footer.php +15 -0
  89. themes/default/hfe-header.php +23 -0
  90. themes/generatepress/class-hfe-generatepress-compat.php +7 -6
  91. themes/genesis/class-hfe-genesis-compat.php +21 -32
  92. themes/oceanwp/class-hfe-oceanwp-compat.php +7 -6
  93. themes/storefront/class-hfe-storefront-compat.php +100 -0
admin/assets/css/ehf-admin.css CHANGED
@@ -52,8 +52,8 @@ input.hfe-large-text{
52
  color: #333;
53
  }
54
 
55
- .hfe-options-table #ehf_template_type {
56
- width: 80%;
57
  }
58
 
59
  .hfe-options-row-heading-help{
@@ -61,4 +61,29 @@ input.hfe-large-text{
61
  cursor: help;
62
  float: right;
63
  font-size: 18px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
52
  color: #333;
53
  }
54
 
55
+ .hfe-options-row-content select {
56
+ width: 95%;
57
  }
58
 
59
  .hfe-options-row-heading-help{
61
  cursor: help;
62
  float: right;
63
  font-size: 18px;
64
+ }
65
+
66
+ .hfe_radio_options {
67
+ display: inline-block;
68
+ }
69
+
70
+ li#toplevel_page_Settings-page {
71
+ display: none;
72
+ }
73
+
74
+ .wp-admin #adminmenu .wp-submenu a[href="themes.php?page=hfe-settings"] {
75
+ display:none;
76
+ }
77
+
78
+ .appearance_page_hfe-settings #adminmenu .wp-submenu a[href ="edit.php?post_type=elementor-hf" ] {
79
+ color: white;
80
+ font-weight: 600;
81
+ }
82
+
83
+ .hfe-heading-inline{
84
+ font-size: 23px;
85
+ font-weight: 400;
86
+ margin: 0;
87
+ padding: 9px 0 4px 0;
88
+ line-height: 1.3;
89
  }
admin/class-hfe-admin.php CHANGED
@@ -5,6 +5,8 @@
5
  * @package header-footer-elementor
6
  */
7
 
 
 
8
  defined( 'ABSPATH' ) or exit;
9
 
10
  /**
@@ -28,7 +30,7 @@ class HFE_Admin {
28
  */
29
  public static function instance() {
30
  if ( ! isset( self::$_instance ) ) {
31
- self::$_instance = new self;
32
  }
33
 
34
  return self::$_instance;
@@ -38,26 +40,115 @@ class HFE_Admin {
38
  * Constructor
39
  */
40
  private function __construct() {
41
- add_action( 'init', array( $this, 'header_footer_posttype' ) );
42
- add_action( 'admin_menu', array( $this, 'register_admin_menu' ), 50 );
43
- add_action( 'add_meta_boxes', array( $this, 'ehf_register_metabox' ) );
44
- add_action( 'save_post', array( $this, 'ehf_save_meta' ) );
45
- add_action( 'admin_notices', array( $this, 'location_notice' ) );
46
- add_action( 'template_redirect', array( $this, 'block_template_frontend' ) );
47
- add_filter( 'single_template', array( $this, 'load_canvas_template' ) );
 
 
 
 
 
 
 
 
48
 
49
- add_filter( 'manage_elementor-hf_posts_columns', array( $this, 'set_shortcode_columns' ) );
 
 
 
 
 
 
 
50
 
51
- add_action( 'manage_elementor-hf_posts_custom_column', array( $this, 'render_shortcode_column' ), 10, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
 
53
  }
54
 
 
55
  /**
56
  * Register Post type for header footer templates
57
  */
58
  public function header_footer_posttype() {
59
-
60
- $labels = array(
61
  'name' => __( 'Header Footers Template', 'header-footer-elementor' ),
62
  'singular_name' => __( 'Elementor Header Footer', 'header-footer-elementor' ),
63
  'menu_name' => __( 'Header Footers Template', 'header-footer-elementor' ),
@@ -72,9 +163,9 @@ class HFE_Admin {
72
  'parent_item_colon' => __( 'Parent Header Footers Templates:', 'header-footer-elementor' ),
73
  'not_found' => __( 'No Header Footers Templates found.', 'header-footer-elementor' ),
74
  'not_found_in_trash' => __( 'No Header Footers Templates found in Trash.', 'header-footer-elementor' ),
75
- );
76
 
77
- $args = array(
78
  'labels' => $labels,
79
  'public' => true,
80
  'show_ui' => true,
@@ -84,8 +175,8 @@ class HFE_Admin {
84
  'capability_type' => 'post',
85
  'hierarchical' => false,
86
  'menu_icon' => 'dashicons-editor-kitchensink',
87
- 'supports' => array( 'title', 'thumbnail', 'elementor' ),
88
- );
89
 
90
  register_post_type( 'elementor-hf', $args );
91
  }
@@ -114,10 +205,10 @@ class HFE_Admin {
114
  add_meta_box(
115
  'ehf-meta-box',
116
  __( 'Elementor Header Footer options', 'header-footer-elementor' ),
117
- array(
118
  $this,
119
  'efh_metabox_render',
120
- ),
121
  'elementor-hf',
122
  'normal',
123
  'high'
@@ -147,14 +238,14 @@ class HFE_Admin {
147
  <select name="ehf_template_type" id="ehf_template_type">
148
  <option value="" <?php selected( $template_type, '' ); ?>><?php _e( 'Select Option', 'header-footer-elementor' ); ?></option>
149
  <option value="type_header" <?php selected( $template_type, 'type_header' ); ?>><?php _e( 'Header', 'header-footer-elementor' ); ?></option>
150
- <?php if ( 'astra' == get_template() ) { ?>
151
- <option value="type_before_footer" <?php selected( $template_type, 'type_before_footer' ); ?>><?php _e( 'Before Footer', 'header-footer-elementor' ); ?></option>
152
- <?php } ?>
153
  <option value="type_footer" <?php selected( $template_type, 'type_footer' ); ?>><?php _e( 'Footer', 'header-footer-elementor' ); ?></option>
154
  <option value="custom" <?php selected( $template_type, 'custom' ); ?>><?php _e( 'Custom Block', 'header-footer-elementor' ); ?></option>
155
  </select>
156
  </td>
157
  </tr>
 
 
158
  <tr class="hfe-options-row hfe-shortcode">
159
  <td class="hfe-options-row-heading">
160
  <label for="ehf_template_type"><?php _e( 'Shortcode', 'header-footer-elementor' ); ?></label>
@@ -183,6 +274,86 @@ class HFE_Admin {
183
  <?php
184
  }
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  /**
187
  * Save meta field.
188
  *
@@ -207,6 +378,18 @@ class HFE_Admin {
207
  return;
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
 
 
210
  if ( isset( $_POST['ehf_template_type'] ) ) {
211
  update_post_meta( $post_id, 'ehf_template_type', esc_attr( $_POST['ehf_template_type'] ) );
212
  }
@@ -216,7 +399,6 @@ class HFE_Admin {
216
  } else {
217
  delete_post_meta( $post_id, 'display-on-canvas-template' );
218
  }
219
-
220
  }
221
 
222
  /**
@@ -225,7 +407,6 @@ class HFE_Admin {
225
  * @since 1.0.0
226
  */
227
  public function location_notice() {
228
-
229
  global $pagenow;
230
  global $post;
231
 
@@ -240,7 +421,6 @@ class HFE_Admin {
240
 
241
  // Check if more than one template is selected for current template type.
242
  if ( is_array( $templates ) && isset( $templates[1] ) && $post->ID != $templates[0] ) {
243
-
244
  $post_title = '<strong>' . get_the_title( $templates[0] ) . '</strong>';
245
  $template_location = '<strong>' . $this->template_location( $template_type ) . '</strong>';
246
  /* Translators: Post title, Template Location */
@@ -251,7 +431,6 @@ class HFE_Admin {
251
  echo '</p></div>';
252
  }
253
  }
254
-
255
  }
256
 
257
  /**
@@ -289,11 +468,9 @@ class HFE_Admin {
289
  * @param String $single_template Single template.
290
  */
291
  function load_canvas_template( $single_template ) {
292
-
293
  global $post;
294
 
295
  if ( 'elementor-hf' == $post->post_type ) {
296
-
297
  $elementor_2_0_canvas = ELEMENTOR_PATH . '/modules/page-templates/templates/canvas.php';
298
 
299
  if ( file_exists( $elementor_2_0_canvas ) ) {
@@ -312,7 +489,6 @@ class HFE_Admin {
312
  * @param array $columns template list columns.
313
  */
314
  function set_shortcode_columns( $columns ) {
315
-
316
  $date_column = $columns['date'];
317
 
318
  unset( $columns['date'] );
@@ -330,7 +506,6 @@ class HFE_Admin {
330
  * @param int $post_id post id.
331
  */
332
  function render_shortcode_column( $column, $post_id ) {
333
-
334
  switch ( $column ) {
335
  case 'shortcode':
336
  ob_start();
5
  * @package header-footer-elementor
6
  */
7
 
8
+ use HFE\Lib\Astra_Target_Rules_Fields;
9
+
10
  defined( 'ABSPATH' ) or exit;
11
 
12
  /**
30
  */
31
  public static function instance() {
32
  if ( ! isset( self::$_instance ) ) {
33
+ self::$_instance = new self();
34
  }
35
 
36
  return self::$_instance;
40
  * Constructor
41
  */
42
  private function __construct() {
43
+ add_action( 'init', [ $this, 'header_footer_posttype' ] );
44
+ add_action( 'admin_menu', [ $this, 'register_admin_menu' ], 50 );
45
+ add_action( 'add_meta_boxes', [ $this, 'ehf_register_metabox' ] );
46
+ add_action( 'save_post', [ $this, 'ehf_save_meta' ] );
47
+ add_action( 'admin_notices', [ $this, 'location_notice' ] );
48
+ add_action( 'template_redirect', [ $this, 'block_template_frontend' ] );
49
+ add_filter( 'single_template', [ $this, 'load_canvas_template' ] );
50
+ add_filter( 'manage_elementor-hf_posts_columns', [ $this, 'set_shortcode_columns' ] );
51
+ add_action( 'manage_elementor-hf_posts_custom_column', [ $this, 'render_shortcode_column' ], 10, 2 );
52
+
53
+ if ( is_admin() ) {
54
+ add_action( 'manage_elementor-hf_posts_custom_column', [ $this, 'column_content' ], 10, 2 );
55
+ add_filter( 'manage_elementor-hf_posts_columns', [ $this, 'column_headings' ] );
56
+ }
57
+ }
58
 
59
+ /**
60
+ * Adds or removes list table column headings.
61
+ *
62
+ * @param array $columns Array of columns.
63
+ * @return array
64
+ */
65
+ public function column_headings( $columns ) {
66
+ unset( $columns['date'] );
67
 
68
+ $columns['elementor_hf_display_rules'] = __( 'Display Rules', 'header-footer-elementor' );
69
+ $columns['date'] = __( 'Date', 'header-footer-elementor' );
70
+
71
+ return $columns;
72
+ }
73
+
74
+ /**
75
+ * Adds the custom list table column content.
76
+ *
77
+ * @since 1.2.0
78
+ * @param array $column Name of column.
79
+ * @param int $post_id Post id.
80
+ * @return void
81
+ */
82
+ public function column_content( $column, $post_id ) {
83
+
84
+ if ( 'elementor_hf_display_rules' == $column ) {
85
+
86
+ $locations = get_post_meta( $post_id, 'ehf_target_include_locations', true );
87
+ if ( ! empty( $locations ) ) {
88
+ echo '<div class="ast-advanced-headers-location-wrap" style="margin-bottom: 5px;">';
89
+ echo '<strong>Display: </strong>';
90
+ $this->column_display_location_rules( $locations );
91
+ echo '</div>';
92
+ }
93
+
94
+ $locations = get_post_meta( $post_id, 'ehf_target_exclude_locations', true );
95
+ if ( ! empty( $locations ) ) {
96
+ echo '<div class="ast-advanced-headers-exclusion-wrap" style="margin-bottom: 5px;">';
97
+ echo '<strong>Exclusion: </strong>';
98
+ $this->column_display_location_rules( $locations );
99
+ echo '</div>';
100
+ }
101
+
102
+ $users = get_post_meta( $post_id, 'ehf_target_user_roles', true );
103
+ if ( isset( $users ) && is_array( $users ) ) {
104
+ if ( isset( $users[0] ) && ! empty( $users[0] ) ) {
105
+ $user_label = [];
106
+ foreach ( $users as $user ) {
107
+ $user_label[] = Astra_Target_Rules_Fields::get_user_by_key( $user );
108
+ }
109
+ echo '<div class="ast-advanced-headers-users-wrap">';
110
+ echo '<strong>Users: </strong>';
111
+ echo join( ', ', $user_label );
112
+ echo '</div>';
113
+ }
114
+ }
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Get Markup of Location rules for Display rule column.
120
+ *
121
+ * @param array $locations Array of locations.
122
+ * @return void
123
+ */
124
+ public function column_display_location_rules( $locations ) {
125
+
126
+ $location_label = [];
127
+ $index = array_search( 'specifics', $locations['rule'] );
128
+ if ( false !== $index && ! empty( $index ) ) {
129
+ unset( $locations['rule'][ $index ] );
130
+ }
131
+
132
+ if ( isset( $locations['rule'] ) && is_array( $locations['rule'] ) ) {
133
+ foreach ( $locations['rule'] as $location ) {
134
+ $location_label[] = Astra_Target_Rules_Fields::get_location_by_key( $location );
135
+ }
136
+ }
137
+ if ( isset( $locations['specific'] ) && is_array( $locations['specific'] ) ) {
138
+ foreach ( $locations['specific'] as $location ) {
139
+ $location_label[] = Astra_Target_Rules_Fields::get_location_by_key( $location );
140
+ }
141
+ }
142
 
143
+ echo join( ', ', $location_label );
144
  }
145
 
146
+
147
  /**
148
  * Register Post type for header footer templates
149
  */
150
  public function header_footer_posttype() {
151
+ $labels = [
 
152
  'name' => __( 'Header Footers Template', 'header-footer-elementor' ),
153
  'singular_name' => __( 'Elementor Header Footer', 'header-footer-elementor' ),
154
  'menu_name' => __( 'Header Footers Template', 'header-footer-elementor' ),
163
  'parent_item_colon' => __( 'Parent Header Footers Templates:', 'header-footer-elementor' ),
164
  'not_found' => __( 'No Header Footers Templates found.', 'header-footer-elementor' ),
165
  'not_found_in_trash' => __( 'No Header Footers Templates found in Trash.', 'header-footer-elementor' ),
166
+ ];
167
 
168
+ $args = [
169
  'labels' => $labels,
170
  'public' => true,
171
  'show_ui' => true,
175
  'capability_type' => 'post',
176
  'hierarchical' => false,
177
  'menu_icon' => 'dashicons-editor-kitchensink',
178
+ 'supports' => [ 'title', 'thumbnail', 'elementor' ],
179
+ ];
180
 
181
  register_post_type( 'elementor-hf', $args );
182
  }
205
  add_meta_box(
206
  'ehf-meta-box',
207
  __( 'Elementor Header Footer options', 'header-footer-elementor' ),
208
+ [
209
  $this,
210
  'efh_metabox_render',
211
+ ],
212
  'elementor-hf',
213
  'normal',
214
  'high'
238
  <select name="ehf_template_type" id="ehf_template_type">
239
  <option value="" <?php selected( $template_type, '' ); ?>><?php _e( 'Select Option', 'header-footer-elementor' ); ?></option>
240
  <option value="type_header" <?php selected( $template_type, 'type_header' ); ?>><?php _e( 'Header', 'header-footer-elementor' ); ?></option>
241
+ <option value="type_before_footer" <?php selected( $template_type, 'type_before_footer' ); ?>><?php _e( 'Before Footer', 'header-footer-elementor' ); ?></option>
 
 
242
  <option value="type_footer" <?php selected( $template_type, 'type_footer' ); ?>><?php _e( 'Footer', 'header-footer-elementor' ); ?></option>
243
  <option value="custom" <?php selected( $template_type, 'custom' ); ?>><?php _e( 'Custom Block', 'header-footer-elementor' ); ?></option>
244
  </select>
245
  </td>
246
  </tr>
247
+
248
+ <?php $this->display_rules_tab(); ?>
249
  <tr class="hfe-options-row hfe-shortcode">
250
  <td class="hfe-options-row-heading">
251
  <label for="ehf_template_type"><?php _e( 'Shortcode', 'header-footer-elementor' ); ?></label>
274
  <?php
275
  }
276
 
277
+ /**
278
+ * Markup for Display Rules Tabs.
279
+ *
280
+ * @since 1.0.0
281
+ */
282
+ public function display_rules_tab() {
283
+ // Load Target Rule assets.
284
+ Astra_Target_Rules_Fields::get_instance()->admin_styles();
285
+
286
+ $include_locations = get_post_meta( get_the_id(), 'ehf_target_include_locations', true );
287
+ $exclude_locations = get_post_meta( get_the_id(), 'ehf_target_exclude_locations', true );
288
+ $users = get_post_meta( get_the_id(), 'ehf_target_user_roles', true );
289
+ ?>
290
+ <tr class="bsf-target-rules-row hfe-options-row">
291
+ <td class="bsf-target-rules-row-heading hfe-options-row-heading">
292
+ <label><?php esc_html_e( 'Display On', 'header-footer-elementor' ); ?></label>
293
+ <i class="bsf-target-rules-heading-help dashicons dashicons-editor-help"
294
+ title="<?php echo esc_attr__( 'Add locations for where this template should appear.', 'header-footer-elementor' ); ?>"></i>
295
+ </td>
296
+ <td class="bsf-target-rules-row-content hfe-options-row-content">
297
+ <?php
298
+ Astra_Target_Rules_Fields::target_rule_settings_field(
299
+ 'bsf-target-rules-location',
300
+ [
301
+ 'title' => __( 'Display Rules', 'header-footer-elementor' ),
302
+ 'value' => '[{"type":"basic-global","specific":null}]',
303
+ 'tags' => 'site,enable,target,pages',
304
+ 'rule_type' => 'display',
305
+ 'add_rule_label' => __( 'Add Display Rule', 'header-footer-elementor' ),
306
+ ],
307
+ $include_locations
308
+ );
309
+ ?>
310
+ </td>
311
+ </tr>
312
+ <tr class="bsf-target-rules-row hfe-options-row">
313
+ <td class="bsf-target-rules-row-heading hfe-options-row-heading">
314
+ <label><?php esc_html_e( 'Do Not Display On', 'header-footer-elementor' ); ?></label>
315
+ <i class="bsf-target-rules-heading-help dashicons dashicons-editor-help"
316
+ title="<?php echo esc_attr__( 'This Advanced Header will not appear at these locations.', 'header-footer-elementor' ); ?>"></i>
317
+ </td>
318
+ <td class="bsf-target-rules-row-content hfe-options-row-content">
319
+ <?php
320
+ Astra_Target_Rules_Fields::target_rule_settings_field(
321
+ 'bsf-target-rules-exclusion',
322
+ [
323
+ 'title' => __( 'Exclude On', 'header-footer-elementor' ),
324
+ 'value' => '[]',
325
+ 'tags' => 'site,enable,target,pages',
326
+ 'add_rule_label' => __( 'Add Exclusion Rule', 'header-footer-elementor' ),
327
+ 'rule_type' => 'exclude',
328
+ ],
329
+ $exclude_locations
330
+ );
331
+ ?>
332
+ </td>
333
+ </tr>
334
+ <tr class="bsf-target-rules-row hfe-options-row">
335
+ <td class="bsf-target-rules-row-heading hfe-options-row-heading">
336
+ <label><?php esc_html_e( 'User Roles', 'header-footer-elementor' ); ?></label>
337
+ <i class="bsf-target-rules-heading-help dashicons dashicons-editor-help" title="<?php echo esc_attr__( 'Display custom template based on user role.', 'header-footer-elementor' ); ?>"></i>
338
+ </td>
339
+ <td class="bsf-target-rules-row-content hfe-options-row-content">
340
+ <?php
341
+ Astra_Target_Rules_Fields::target_user_role_settings_field(
342
+ 'bsf-target-rules-users',
343
+ [
344
+ 'title' => __( 'Users', 'header-footer-elementor' ),
345
+ 'value' => '[]',
346
+ 'tags' => 'site,enable,target,pages',
347
+ 'add_rule_label' => __( 'Add User Rule', 'header-footer-elementor' ),
348
+ ],
349
+ $users
350
+ );
351
+ ?>
352
+ </td>
353
+ </tr>
354
+ <?php
355
+ }
356
+
357
  /**
358
  * Save meta field.
359
  *
378
  return;
379
  }
380
 
381
+ $target_locations = Astra_Target_Rules_Fields::get_format_rule_value( $_POST, 'bsf-target-rules-location' );
382
+ $target_exclusion = Astra_Target_Rules_Fields::get_format_rule_value( $_POST, 'bsf-target-rules-exclusion' );
383
+ $target_users = [];
384
+
385
+ if ( isset( $_POST['bsf-target-rules-users'] ) ) {
386
+ $target_users = array_map( 'sanitize_text_field', $_POST['bsf-target-rules-users'] );
387
+ }
388
+
389
+ update_post_meta( $post_id, 'ehf_target_include_locations', $target_locations );
390
+ update_post_meta( $post_id, 'ehf_target_exclude_locations', $target_exclusion );
391
+ update_post_meta( $post_id, 'ehf_target_user_roles', $target_users );
392
+
393
  if ( isset( $_POST['ehf_template_type'] ) ) {
394
  update_post_meta( $post_id, 'ehf_template_type', esc_attr( $_POST['ehf_template_type'] ) );
395
  }
399
  } else {
400
  delete_post_meta( $post_id, 'display-on-canvas-template' );
401
  }
 
402
  }
403
 
404
  /**
407
  * @since 1.0.0
408
  */
409
  public function location_notice() {
 
410
  global $pagenow;
411
  global $post;
412
 
421
 
422
  // Check if more than one template is selected for current template type.
423
  if ( is_array( $templates ) && isset( $templates[1] ) && $post->ID != $templates[0] ) {
 
424
  $post_title = '<strong>' . get_the_title( $templates[0] ) . '</strong>';
425
  $template_location = '<strong>' . $this->template_location( $template_type ) . '</strong>';
426
  /* Translators: Post title, Template Location */
431
  echo '</p></div>';
432
  }
433
  }
 
434
  }
435
 
436
  /**
468
  * @param String $single_template Single template.
469
  */
470
  function load_canvas_template( $single_template ) {
 
471
  global $post;
472
 
473
  if ( 'elementor-hf' == $post->post_type ) {
 
474
  $elementor_2_0_canvas = ELEMENTOR_PATH . '/modules/page-templates/templates/canvas.php';
475
 
476
  if ( file_exists( $elementor_2_0_canvas ) ) {
489
  * @param array $columns template list columns.
490
  */
491
  function set_shortcode_columns( $columns ) {
 
492
  $date_column = $columns['date'];
493
 
494
  unset( $columns['date'] );
506
  * @param int $post_id post id.
507
  */
508
  function render_shortcode_column( $column, $post_id ) {
 
509
  switch ( $column ) {
510
  case 'shortcode':
511
  ob_start();
assets/css/admin-header-footer-elementor.css ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .astra-review-notice-container {
2
+ display: flex;
3
+ align-items: center;
4
+ padding-top: 10px;
5
+ }
6
+
7
+ .astra-review-notice-container .dashicons {
8
+ font-size: 1.4em;
9
+ padding-left: 10px;
10
+ }
11
+
12
+ .astra-review-notice-container a {
13
+ padding-left: 5px;
14
+ text-decoration: none;
15
+ }
16
+
17
+ .astra-review-notice-container .dashicons:first-child {
18
+ padding-left: 0;
19
+ }
20
+
21
+ .notice-image img {
22
+ max-width: 90px;
23
+ }
24
+
25
+ .notice-content .notice-heading {
26
+ padding-bottom: 5px;
27
+ }
28
+
29
+ .notice-content {
30
+ margin-left: 15px;
31
+ }
32
+
33
+ .notice-container {
34
+ padding-top: 10px;
35
+ padding-bottom: 10px;
36
+ display: flex;
37
+ justify-content: left;
38
+ align-items: center;
39
+ }
40
+
41
+ li#toplevel_page_Settings-page {
42
+ display: none;
43
+ }
assets/css/header-footer-elementor.css CHANGED
@@ -30,4 +30,5 @@
30
  .ehf-header #masthead {
31
  z-index: 200;
32
  position: relative;
33
- }
 
30
  .ehf-header #masthead {
31
  z-index: 200;
32
  position: relative;
33
+ }
34
+
assets/images/header-footer-elementor-icon.svg ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
5
+ width="256px" height="256px" viewBox="0 0 256 256" enable-background="new 0 0 256 256" xml:space="preserve">
6
+ <title>Header, Footer &amp; Blocks for Elementor</title>
7
+ <g>
8
+
9
+ <linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="624.0195" y1="319" x2="815.9805" y2="319" gradientTransform="matrix(1 0 0 1 -592 -191)">
10
+ <stop offset="0" style="stop-color:#1488CC"/>
11
+ <stop offset="1" style="stop-color:#2B32B2"/>
12
+ </linearGradient>
13
+ <path fill="url(#SVGID_1_)" d="M206.656,44.953c3.242,0,5.871,2.628,5.871,5.87v154.354c0,3.243-2.629,5.871-5.871,5.871H49.34
14
+ c-3.241,0-5.868-2.628-5.868-5.871V50.823c0-3.242,2.627-5.87,5.868-5.87H206.656 M206.656,33.5H49.34
15
+ c-9.552,0-17.321,7.771-17.321,17.323v154.354c0,9.554,7.771,17.323,17.321,17.323h157.316c9.553,0,17.324-7.771,17.324-17.323
16
+ V50.823C223.98,41.271,216.209,33.5,206.656,33.5L206.656,33.5z"/>
17
+ </g>
18
+ <g>
19
+
20
+ <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="651.7793" y1="376.8877" x2="788.2207" y2="376.8877" gradientTransform="matrix(1 0 0 1 -592 -191)">
21
+ <stop offset="0" style="stop-color:#1488CC"/>
22
+ <stop offset="1" style="stop-color:#2B32B2"/>
23
+ </linearGradient>
24
+ <path fill="url(#SVGID_2_)" d="M196.221,193.779c0,3.648-2.959,6.607-6.605,6.607H66.386c-3.648,0-6.607-2.959-6.607-6.607v-15.784
25
+ c0-3.647,2.959-6.606,6.607-6.606h123.229c3.646,0,6.605,2.959,6.605,6.606V193.779z"/>
26
+ </g>
27
+ <g>
28
+
29
+ <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="651.7793" y1="263.0508" x2="788.2207" y2="263.0508" gradientTransform="matrix(1 0 0 1 -592 -191)">
30
+ <stop offset="0" style="stop-color:#1488CC"/>
31
+ <stop offset="1" style="stop-color:#2B32B2"/>
32
+ </linearGradient>
33
+ <path fill="url(#SVGID_3_)" d="M196.221,79.943c0,3.649-2.959,6.607-6.605,6.607H66.386c-3.648,0-6.607-2.958-6.607-6.607V64.159
34
+ c0-3.647,2.959-6.607,6.607-6.607h123.229c3.646,0,6.605,2.958,6.605,6.607V79.943z"/>
35
+ </g>
36
+ </svg>
assets/js/hfe-sites-notices.js DELETED
@@ -1,22 +0,0 @@
1
- jQuery(document).ready(function ($) {
2
-
3
- jQuery( '.hfe-notice.is-dismissible .notice-dismiss' ).on( 'click', function() {
4
- _this = jQuery( this ).parents( '.hfe-active-notice' );
5
- var $id = _this.attr( 'id' ) || '';
6
- var $time = _this.attr( 'dismissible-time' ) || '';
7
- var $meta = _this.attr( 'dismissible-meta' ) || '';
8
-
9
- jQuery.ajax({
10
- url: ajaxurl,
11
- type: 'POST',
12
- data: {
13
- action : 'hfe-notices',
14
- id : $id,
15
- meta : $meta,
16
- time : $time,
17
- },
18
- });
19
-
20
- });
21
-
22
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
header-footer-elementor.php CHANGED
@@ -1,18 +1,18 @@
1
  <?php
2
  /**
3
- * Plugin Name: Elementor - Header, Footer & Blocks
4
- * Plugin URI: https://github.com/Nikschavan/header-footer-elementor
5
- * Description: Create Header and Footer for your site using Elementor Page Builder.
6
- * Author: Brainstorm Force, Nikhil Chavan
7
- * Author URI: https://www.brainstormforce.com/
8
- * Text Domain: header-footer-elementor
9
- * Domain Path: /languages
10
- * Version: 1.1.4
11
  *
12
  * @package header-footer-elementor
13
  */
14
 
15
- define( 'HFE_VER', '1.1.4' );
16
  define( 'HFE_DIR', plugin_dir_path( __FILE__ ) );
17
  define( 'HFE_URL', plugins_url( '/', __FILE__ ) );
18
  define( 'HFE_PATH', plugin_basename( __FILE__ ) );
@@ -26,7 +26,7 @@ require_once HFE_DIR . '/inc/class-header-footer-elementor.php';
26
  * Load the Plugin Class.
27
  */
28
  function hfe_init() {
29
- new Header_Footer_Elementor();
30
  }
31
 
32
  add_action( 'plugins_loaded', 'hfe_init' );
1
  <?php
2
  /**
3
+ * Plugin Name: Elementor - Header, Footer & Blocks
4
+ * Plugin URI: https://github.com/Nikschavan/header-footer-elementor
5
+ * Description: Create Header and Footer for your site using Elementor Page Builder.
6
+ * Author: Brainstorm Force, Nikhil Chavan
7
+ * Author URI: https://www.brainstormforce.com/
8
+ * Text Domain: header-footer-elementor
9
+ * Domain Path: /languages
10
+ * Version: 1.2.0
11
  *
12
  * @package header-footer-elementor
13
  */
14
 
15
+ define( 'HFE_VER', '1.2.0' );
16
  define( 'HFE_DIR', plugin_dir_path( __FILE__ ) );
17
  define( 'HFE_URL', plugins_url( '/', __FILE__ ) );
18
  define( 'HFE_PATH', plugin_basename( __FILE__ ) );
26
  * Load the Plugin Class.
27
  */
28
  function hfe_init() {
29
+ Header_Footer_Elementor::instance();
30
  }
31
 
32
  add_action( 'plugins_loaded', 'hfe_init' );
inc/class-header-footer-elementor.php CHANGED
@@ -2,9 +2,11 @@
2
  /**
3
  * Entry point for the plugin. Checks if Elementor is installed and activated and loads it's own files and actions.
4
  *
5
- * @package header-footer-elementor
6
  */
7
 
 
 
8
  /**
9
  * Class Header_Footer_Elementor
10
  */
@@ -23,55 +25,73 @@ class Header_Footer_Elementor {
23
  * @var \Elementor\Frontend()
24
  */
25
  private static $elementor_instance;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  /**
27
  * Constructor
28
  */
29
  function __construct() {
30
-
31
  $this->template = get_template();
32
 
33
  if ( defined( 'ELEMENTOR_VERSION' ) && is_callable( 'Elementor\Plugin::instance' ) ) {
34
-
35
  self::$elementor_instance = Elementor\Plugin::instance();
36
 
37
  $this->includes();
38
  $this->load_textdomain();
39
 
40
  if ( 'genesis' == $this->template ) {
41
-
42
  require HFE_DIR . 'themes/genesis/class-hfe-genesis-compat.php';
43
  } elseif ( 'astra' == $this->template ) {
44
-
45
  require HFE_DIR . 'themes/astra/class-hfe-astra-compat.php';
46
  } elseif ( 'bb-theme' == $this->template || 'beaver-builder-theme' == $this->template ) {
47
  $this->template = 'beaver-builder-theme';
48
  require HFE_DIR . 'themes/bb-theme/class-hfe-bb-theme-compat.php';
49
  } elseif ( 'generatepress' == $this->template ) {
50
-
51
  require HFE_DIR . 'themes/generatepress/class-hfe-generatepress-compat.php';
52
  } elseif ( 'oceanwp' == $this->template ) {
53
-
54
  require HFE_DIR . 'themes/oceanwp/class-hfe-oceanwp-compat.php';
 
 
55
  } else {
56
- add_action( 'init', array( $this, 'setup_unsupported_theme_notice' ) );
 
 
57
  }
58
 
59
  // Scripts and styles.
60
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
61
 
62
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
63
 
64
- add_filter( 'body_class', array( $this, 'body_class' ) );
65
- add_action( 'switch_theme', array( $this, 'reset_unsupported_theme_notice' ) );
66
 
67
- add_shortcode( 'hfe_template', array( $this, 'render_template' ) );
68
 
 
 
69
  } else {
70
-
71
- add_action( 'admin_notices', array( $this, 'elementor_not_available' ) );
72
- add_action( 'network_admin_notices', array( $this, 'elementor_not_available' ) );
73
  }
74
-
75
  }
76
 
77
  /**
@@ -82,14 +102,76 @@ class Header_Footer_Elementor {
82
  * @return void
83
  */
84
  public function reset_unsupported_theme_notice() {
85
- delete_user_meta( get_current_user_id(), 'hfe-sites-notices-id-unsupported-theme' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  }
87
 
88
  /**
89
  * Prints the admin notics when Elementor is not installed or activated.
90
  */
91
  public function elementor_not_available() {
92
-
93
  if ( file_exists( WP_PLUGIN_DIR . '/elementor/elementor.php' ) ) {
94
  $url = network_admin_url() . 'plugins.php?s=elementor';
95
  } else {
@@ -119,10 +201,15 @@ class Header_Footer_Elementor {
119
  }
120
 
121
  // Load the Admin Notice Class.
122
- require_once HFE_DIR . 'inc/class-hfe-notices.php';
123
 
 
 
124
  // Setup upgrade routines.
125
  require_once HFE_DIR . 'inc/class-hfe-update.php';
 
 
 
126
  }
127
 
128
  /**
@@ -136,7 +223,7 @@ class Header_Footer_Elementor {
136
  * Enqueue styles and scripts.
137
  */
138
  public function enqueue_scripts() {
139
- wp_enqueue_style( 'hfe-style', HFE_URL . 'assets/css/header-footer-elementor.css', array(), HFE_VER );
140
 
141
  if ( class_exists( '\Elementor\Plugin' ) ) {
142
  $elementor = \Elementor\Plugin::instance();
@@ -167,6 +254,15 @@ class Header_Footer_Elementor {
167
 
168
  $css_file->enqueue();
169
  }
 
 
 
 
 
 
 
 
 
170
  }
171
 
172
  /**
@@ -177,9 +273,8 @@ class Header_Footer_Elementor {
177
  $screen = get_current_screen();
178
 
179
  if ( ( 'elementor-hf' == $screen->id && ( 'post.php' == $pagenow || 'post-new.php' == $pagenow ) ) || ( 'edit.php' == $pagenow && 'edit-elementor-hf' == $screen->id ) ) {
180
- wp_enqueue_style( 'hfe-admin-style', HFE_URL . 'admin/assets/css/ehf-admin.css', array(), HFE_VER );
181
-
182
- wp_enqueue_script( 'hfe-admin-script', HFE_URL . 'admin/assets/js/ehf-admin.js', array(), HFE_VER );
183
  }
184
  }
185
 
@@ -191,7 +286,6 @@ class Header_Footer_Elementor {
191
  * @return Array array with class names for the body tag.
192
  */
193
  public function body_class( $classes ) {
194
-
195
  if ( hfe_header_enabled() ) {
196
  $classes[] = 'ehf-header';
197
  }
@@ -212,18 +306,17 @@ class Header_Footer_Elementor {
212
  * @since 1.0.3
213
  */
214
  public function setup_unsupported_theme_notice() {
215
-
216
  if ( ! current_theme_supports( 'header-footer-elementor' ) ) {
217
- HFE_Notices::add_notice(
218
- array(
219
- 'id' => 'unsupported-theme',
220
- 'type' => 'error',
221
- 'dismissible' => true,
222
- 'message' => __( 'Hey, your current theme is not supported by Header Footer Elementor, click <a href="https://github.com/Nikschavan/header-footer-elementor#which-themes-are-supported-by-this-plugin">here</a> to check out the supported themes.', 'header-footer-elementor' ),
223
- )
 
224
  );
225
  }
226
-
227
  }
228
 
229
  /**
@@ -237,12 +330,20 @@ class Header_Footer_Elementor {
237
  * Prints the Footer content.
238
  */
239
  public static function get_footer_content() {
240
-
241
  echo "<div class='footer-width-fixer'>";
242
  echo self::$elementor_instance->frontend->get_builder_content_for_display( get_hfe_footer_id() );
243
  echo '</div>';
244
  }
245
 
 
 
 
 
 
 
 
 
 
246
  /**
247
  * Get option for the plugin settings
248
  *
@@ -255,7 +356,8 @@ class Header_Footer_Elementor {
255
  if ( 'type_header' == $setting || 'type_footer' == $setting || 'type_before_footer' == $setting ) {
256
  $templates = self::get_template_id( $setting );
257
 
258
- $template = is_array( $templates ) ? $templates[0] : '';
 
259
  $template = apply_filters( "hfe_get_settings_{$setting}", $template );
260
 
261
  return $template;
@@ -270,43 +372,18 @@ class Header_Footer_Elementor {
270
  * @return Mixed Returns the header or footer template id if found, else returns string ''.
271
  */
272
  public static function get_template_id( $type ) {
 
 
 
 
 
273
 
274
- $cached = wp_cache_get( $type );
275
-
276
- if ( false !== $cached ) {
277
- return $cached;
278
- }
279
-
280
- $args = array(
281
- 'post_type' => 'elementor-hf',
282
- 'meta_key' => 'ehf_template_type',
283
- 'meta_value' => $type,
284
- 'meta_type' => 'post',
285
- 'meta_compare' => '>=',
286
- 'orderby' => 'meta_value',
287
- 'order' => 'ASC',
288
- 'meta_query' => array(
289
- 'relation' => 'OR',
290
- array(
291
- 'key' => 'ehf_template_type',
292
- 'value' => $type,
293
- 'compare' => '==',
294
- 'type' => 'post',
295
- ),
296
- ),
297
- );
298
 
299
- $args = apply_filters( 'hfe_get_template_id_args', $args );
300
-
301
- $template = new WP_Query(
302
- $args
303
- );
304
-
305
- if ( $template->have_posts() ) {
306
- $posts = wp_list_pluck( $template->posts, 'ID' );
307
- wp_cache_set( $type, $posts );
308
-
309
- return $posts;
310
  }
311
 
312
  return '';
@@ -318,11 +395,10 @@ class Header_Footer_Elementor {
318
  * @param array $atts attributes for shortcode.
319
  */
320
  public function render_template( $atts ) {
321
-
322
  $atts = shortcode_atts(
323
- array(
324
  'id' => '',
325
- ),
326
  $atts,
327
  'hfe_template'
328
  );
@@ -336,12 +412,12 @@ class Header_Footer_Elementor {
336
  if ( class_exists( '\Elementor\Core\Files\CSS\Post' ) ) {
337
  $css_file = new \Elementor\Core\Files\CSS\Post( $id );
338
  } elseif ( class_exists( '\Elementor\Post_CSS_File' ) ) {
 
339
  $css_file = new \Elementor\Post_CSS_File( $id );
340
  }
341
- $css_file->enqueue();
342
 
343
  return self::$elementor_instance->frontend->get_builder_content_for_display( $id );
344
-
345
  }
346
 
347
  }
2
  /**
3
  * Entry point for the plugin. Checks if Elementor is installed and activated and loads it's own files and actions.
4
  *
5
+ * @package header-footer-elementor
6
  */
7
 
8
+ use HFE\Lib\Astra_Target_Rules_Fields;
9
+
10
  /**
11
  * Class Header_Footer_Elementor
12
  */
25
  * @var \Elementor\Frontend()
26
  */
27
  private static $elementor_instance;
28
+
29
+ /**
30
+ * Instance of HFE_Admin
31
+ *
32
+ * @var Header_Footer_Elementor
33
+ */
34
+ private static $_instance = null;
35
+
36
+ /**
37
+ * Instance of Header_Footer_Elementor
38
+ *
39
+ * @return Header_Footer_Elementor Instance of Header_Footer_Elementor
40
+ */
41
+ public static function instance() {
42
+ if ( ! isset( self::$_instance ) ) {
43
+ self::$_instance = new self();
44
+ }
45
+
46
+ return self::$_instance;
47
+ }
48
  /**
49
  * Constructor
50
  */
51
  function __construct() {
 
52
  $this->template = get_template();
53
 
54
  if ( defined( 'ELEMENTOR_VERSION' ) && is_callable( 'Elementor\Plugin::instance' ) ) {
 
55
  self::$elementor_instance = Elementor\Plugin::instance();
56
 
57
  $this->includes();
58
  $this->load_textdomain();
59
 
60
  if ( 'genesis' == $this->template ) {
 
61
  require HFE_DIR . 'themes/genesis/class-hfe-genesis-compat.php';
62
  } elseif ( 'astra' == $this->template ) {
 
63
  require HFE_DIR . 'themes/astra/class-hfe-astra-compat.php';
64
  } elseif ( 'bb-theme' == $this->template || 'beaver-builder-theme' == $this->template ) {
65
  $this->template = 'beaver-builder-theme';
66
  require HFE_DIR . 'themes/bb-theme/class-hfe-bb-theme-compat.php';
67
  } elseif ( 'generatepress' == $this->template ) {
 
68
  require HFE_DIR . 'themes/generatepress/class-hfe-generatepress-compat.php';
69
  } elseif ( 'oceanwp' == $this->template ) {
 
70
  require HFE_DIR . 'themes/oceanwp/class-hfe-oceanwp-compat.php';
71
+ } elseif ( 'storefront' == $this->template ) {
72
+ require HFE_DIR . 'themes/storefront/class-hfe-storefront-compat.php';
73
  } else {
74
+ require_once HFE_DIR . 'themes/default/class-hfe-fallback-theme-support.php';
75
+
76
+ add_action( 'init', [ $this, 'setup_unsupported_theme_notice' ] );
77
  }
78
 
79
  // Scripts and styles.
80
+ add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
81
 
82
+ add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_admin_scripts' ] );
83
 
84
+ add_filter( 'body_class', [ $this, 'body_class' ] );
85
+ add_action( 'switch_theme', [ $this, 'reset_unsupported_theme_notice' ] );
86
 
87
+ add_shortcode( 'hfe_template', [ $this, 'render_template' ] );
88
 
89
+ add_action( 'astra_notice_before_markup_header-footer-elementor-rating', [ $this, 'rating_notice_css' ] );
90
+ add_action( 'admin_notices', [ $this, 'register_notices' ] );
91
  } else {
92
+ add_action( 'admin_notices', [ $this, 'elementor_not_available' ] );
93
+ add_action( 'network_admin_notices', [ $this, 'elementor_not_available' ] );
 
94
  }
 
95
  }
96
 
97
  /**
102
  * @return void
103
  */
104
  public function reset_unsupported_theme_notice() {
105
+ delete_user_meta( get_current_user_id(), 'unsupported-theme' );
106
+ }
107
+
108
+ /**
109
+ * Register Astra Notices.
110
+ *
111
+ * @since 1.2.0
112
+ *
113
+ * @return void
114
+ */
115
+ public function register_notices() {
116
+ $image_path = HFE_URL . 'assets/images/header-footer-elementor-icon.svg';
117
+ Astra_Notices::add_notice(
118
+ [
119
+ 'id' => 'header-footer-elementor-rating',
120
+ 'type' => '',
121
+ 'message' => sprintf(
122
+ '<div class="notice-image">
123
+ <img src="%1$s" class="custom-logo" alt="Sidebar Manager" itemprop="logo"></div>
124
+ <div class="notice-content">
125
+ <div class="notice-heading">
126
+ %2$s
127
+ </div>
128
+ %3$s<br />
129
+ <div class="astra-review-notice-container">
130
+ <a href="%4$s" class="astra-notice-close astra-review-notice button-primary" target="_blank">
131
+ %5$s
132
+ </a>
133
+ <span class="dashicons dashicons-calendar"></span>
134
+ <a href="#" data-repeat-notice-after="%6$s" class="astra-notice-close astra-review-notice">
135
+ %7$s
136
+ </a>
137
+ <span class="dashicons dashicons-smiley"></span>
138
+ <a href="#" class="astra-notice-close astra-review-notice">
139
+ %8$s
140
+ </a>
141
+ </div>
142
+ </div>',
143
+ $image_path,
144
+ __( 'Hello! Seems like you have used Elementor - Header, Footer & Blocks to build this website — Thanks a ton!', 'header-footer-elementor' ),
145
+ __( 'Could you please do us a BIG favor and give it a 5-star rating on WordPress? This would boost our motivation and help other users make a comfortable decision while choosing the Elementor - Header, Footer & Blocks.', 'header-footer-elementor' ),
146
+ 'https://wordpress.org/support/plugin/header-footer-elementor/reviews/?filter=5#new-post',
147
+ __( 'Ok, you deserve it', 'header-footer-elementor' ),
148
+ MONTH_IN_SECONDS,
149
+ __( 'Nope, maybe later', 'header-footer-elementor' ),
150
+ __( 'I already did', 'header-footer-elementor' )
151
+ ),
152
+ 'show_if' => ( hfe_header_enabled() || hfe_footer_enabled() || hfe_is_before_footer_enabled() ) ? true : false,
153
+ 'repeat-notice-after' => MONTH_IN_SECONDS,
154
+ 'display-notice-after' => 1296000, // Display notice after 15 days.
155
+ 'priority' => 18,
156
+ 'display-with-other-notices' => false,
157
+ ]
158
+ );
159
+ }
160
+
161
+ /**
162
+ * Enqueue CSS for the Rating Notice.
163
+ *
164
+ * @since 1.2.0
165
+ * @return void
166
+ */
167
+ public function rating_notice_css() {
168
+ wp_enqueue_style( 'hfe-admin-style', HFE_URL . 'assets/css/admin-header-footer-elementor.css', [], HFE_VER );
169
  }
170
 
171
  /**
172
  * Prints the admin notics when Elementor is not installed or activated.
173
  */
174
  public function elementor_not_available() {
 
175
  if ( file_exists( WP_PLUGIN_DIR . '/elementor/elementor.php' ) ) {
176
  $url = network_admin_url() . 'plugins.php?s=elementor';
177
  } else {
201
  }
202
 
203
  // Load the Admin Notice Class.
204
+ require_once HFE_DIR . 'inc/lib/notices/class-astra-notices.php';
205
 
206
+ // Load Target rules.
207
+ require_once HFE_DIR . 'inc/lib/target-rule/class-astra-target-rules-fields.php';
208
  // Setup upgrade routines.
209
  require_once HFE_DIR . 'inc/class-hfe-update.php';
210
+
211
+ // Load the widgets.
212
+ require HFE_DIR . 'inc/widgets-manager/class-widgets-loader.php';
213
  }
214
 
215
  /**
223
  * Enqueue styles and scripts.
224
  */
225
  public function enqueue_scripts() {
226
+ wp_enqueue_style( 'hfe-style', HFE_URL . 'assets/css/header-footer-elementor.css', [], HFE_VER );
227
 
228
  if ( class_exists( '\Elementor\Plugin' ) ) {
229
  $elementor = \Elementor\Plugin::instance();
254
 
255
  $css_file->enqueue();
256
  }
257
+
258
+ if ( hfe_is_before_footer_enabled() ) {
259
+ if ( class_exists( '\Elementor\Core\Files\CSS\Post' ) ) {
260
+ $css_file = new \Elementor\Core\Files\CSS\Post( hfe_get_before_footer_id() );
261
+ } elseif ( class_exists( '\Elementor\Post_CSS_File' ) ) {
262
+ $css_file = new \Elementor\Post_CSS_File( hfe_get_before_footer_id() );
263
+ }
264
+ $css_file->enqueue();
265
+ }
266
  }
267
 
268
  /**
273
  $screen = get_current_screen();
274
 
275
  if ( ( 'elementor-hf' == $screen->id && ( 'post.php' == $pagenow || 'post-new.php' == $pagenow ) ) || ( 'edit.php' == $pagenow && 'edit-elementor-hf' == $screen->id ) ) {
276
+ wp_enqueue_style( 'hfe-admin-style', HFE_URL . 'admin/assets/css/ehf-admin.css', [], HFE_VER );
277
+ wp_enqueue_script( 'hfe-admin-script', HFE_URL . 'admin/assets/js/ehf-admin.js', [], HFE_VER );
 
278
  }
279
  }
280
 
286
  * @return Array array with class names for the body tag.
287
  */
288
  public function body_class( $classes ) {
 
289
  if ( hfe_header_enabled() ) {
290
  $classes[] = 'ehf-header';
291
  }
306
  * @since 1.0.3
307
  */
308
  public function setup_unsupported_theme_notice() {
 
309
  if ( ! current_theme_supports( 'header-footer-elementor' ) ) {
310
+ Astra_Notices::add_notice(
311
+ [
312
+ 'id' => 'unsupported-theme',
313
+ 'type' => 'error',
314
+ 'dismissible' => true,
315
+ 'message' => '<p>' . __( 'Your current theme is not supported by Elementor - Header, Footer & Blocks plugin, click <a href="themes.php?page=hfe-settings">here</a> to check available compatibility methods.', 'header-footer-elementor' ) . '</p>',
316
+ 'repeat-notice-after' => false,
317
+ ]
318
  );
319
  }
 
320
  }
321
 
322
  /**
330
  * Prints the Footer content.
331
  */
332
  public static function get_footer_content() {
 
333
  echo "<div class='footer-width-fixer'>";
334
  echo self::$elementor_instance->frontend->get_builder_content_for_display( get_hfe_footer_id() );
335
  echo '</div>';
336
  }
337
 
338
+ /**
339
+ * Prints the Before Footer content.
340
+ */
341
+ public static function get_before_footer_content() {
342
+ echo "<div class='footer-width-fixer'>";
343
+ echo self::$elementor_instance->frontend->get_builder_content_for_display( hfe_get_before_footer_id() );
344
+ echo '</div>';
345
+ }
346
+
347
  /**
348
  * Get option for the plugin settings
349
  *
356
  if ( 'type_header' == $setting || 'type_footer' == $setting || 'type_before_footer' == $setting ) {
357
  $templates = self::get_template_id( $setting );
358
 
359
+ $template = ! is_array( $templates ) ? $templates : $templates[0];
360
+
361
  $template = apply_filters( "hfe_get_settings_{$setting}", $template );
362
 
363
  return $template;
372
  * @return Mixed Returns the header or footer template id if found, else returns string ''.
373
  */
374
  public static function get_template_id( $type ) {
375
+ $option = [
376
+ 'location' => 'ehf_target_include_locations',
377
+ 'exclusion' => 'ehf_target_exclude_locations',
378
+ 'users' => 'ehf_target_user_roles',
379
+ ];
380
 
381
+ $hfe_templates = Astra_Target_Rules_Fields::get_instance()->get_posts_by_conditions( 'elementor-hf', $option );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
 
383
+ foreach ( $hfe_templates as $template ) {
384
+ if ( get_post_meta( absint( $template['id'] ), 'ehf_template_type', true ) === $type ) {
385
+ return $template['id'];
386
+ }
 
 
 
 
 
 
 
387
  }
388
 
389
  return '';
395
  * @param array $atts attributes for shortcode.
396
  */
397
  public function render_template( $atts ) {
 
398
  $atts = shortcode_atts(
399
+ [
400
  'id' => '',
401
+ ],
402
  $atts,
403
  'hfe_template'
404
  );
412
  if ( class_exists( '\Elementor\Core\Files\CSS\Post' ) ) {
413
  $css_file = new \Elementor\Core\Files\CSS\Post( $id );
414
  } elseif ( class_exists( '\Elementor\Post_CSS_File' ) ) {
415
+ // Load elementor styles.
416
  $css_file = new \Elementor\Post_CSS_File( $id );
417
  }
418
+ $css_file->enqueue();
419
 
420
  return self::$elementor_instance->frontend->get_builder_content_for_display( $id );
 
421
  }
422
 
423
  }
inc/class-hfe-elementor-canvas-compat.php CHANGED
@@ -21,11 +21,10 @@ class HFE_Elementor_Canvas_Compat {
21
  * Initiator
22
  */
23
  public static function instance() {
24
-
25
  if ( ! isset( self::$instance ) ) {
26
  self::$instance = new HFE_Elementor_Canvas_Compat();
27
 
28
- add_action( 'wp', array( self::$instance, 'hooks' ) );
29
  }
30
 
31
  return self::$instance;
@@ -35,14 +34,13 @@ class HFE_Elementor_Canvas_Compat {
35
  * Run all the Actions / Filters.
36
  */
37
  public function hooks() {
38
-
39
  if ( hfe_header_enabled() ) {
40
 
41
  // Action `elementor/page_templates/canvas/before_content` is introduced in Elementor Version 1.4.1.
42
  if ( version_compare( ELEMENTOR_VERSION, '1.4.1', '>=' ) ) {
43
- add_action( 'elementor/page_templates/canvas/before_content', array( $this, 'render_header' ) );
44
  } else {
45
- add_action( 'wp_head', array( $this, 'render_header' ) );
46
  }
47
  }
48
 
@@ -50,12 +48,23 @@ class HFE_Elementor_Canvas_Compat {
50
 
51
  // Action `elementor/page_templates/canvas/after_content` is introduced in Elementor Version 1.9.0.
52
  if ( version_compare( ELEMENTOR_VERSION, '1.9.0', '>=' ) ) {
53
- add_action( 'elementor/page_templates/canvas/after_content', array( $this, 'render_footer' ) );
54
  } else {
55
- add_action( 'wp_footer', array( $this, 'render_footer' ) );
56
  }
57
  }
58
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
  /**
21
  * Initiator
22
  */
23
  public static function instance() {
 
24
  if ( ! isset( self::$instance ) ) {
25
  self::$instance = new HFE_Elementor_Canvas_Compat();
26
 
27
+ add_action( 'wp', [ self::$instance, 'hooks' ] );
28
  }
29
 
30
  return self::$instance;
34
  * Run all the Actions / Filters.
35
  */
36
  public function hooks() {
 
37
  if ( hfe_header_enabled() ) {
38
 
39
  // Action `elementor/page_templates/canvas/before_content` is introduced in Elementor Version 1.4.1.
40
  if ( version_compare( ELEMENTOR_VERSION, '1.4.1', '>=' ) ) {
41
+ add_action( 'elementor/page_templates/canvas/before_content', [ $this, 'render_header' ] );
42
  } else {
43
+ add_action( 'wp_head', [ $this, 'render_header' ] );
44
  }
45
  }
46
 
48
 
49
  // Action `elementor/page_templates/canvas/after_content` is introduced in Elementor Version 1.9.0.
50
  if ( version_compare( ELEMENTOR_VERSION, '1.9.0', '>=' ) ) {
51
+ add_action( 'elementor/page_templates/canvas/after_content', [ $this, 'render_footer' ] );
52
  } else {
53
+ add_action( 'wp_footer', [ $this, 'render_footer' ] );
54
  }
55
  }
56
 
57
+ if ( hfe_is_before_footer_enabled() ) {
58
+
59
+ // check if current page template is Elemenntor Canvas.
60
+ if ( 'elementor_canvas' == get_page_template_slug() ) {
61
+ $override_cannvas_template = get_post_meta( hfe_get_before_footer_id(), 'display-on-canvas-template', true );
62
+
63
+ if ( '1' == $override_cannvas_template ) {
64
+ add_action( 'elementor/page_templates/canvas/after_content', 'hfe_render_before_footer', 9 );
65
+ }
66
+ }
67
+ }
68
  }
69
 
70
  /**
inc/class-hfe-notices.php DELETED
@@ -1,218 +0,0 @@
1
- <?php
2
- /**
3
- * HFE Sites Notices
4
- *
5
- * @package HFE Sites
6
- * @since 1.0.8
7
- */
8
-
9
- if ( ! class_exists( 'HFE_Notices' ) ) :
10
-
11
- /**
12
- * HFE_Notices
13
- *
14
- * @since 1.0.8
15
- */
16
- class HFE_Notices {
17
-
18
- /**
19
- * Notices
20
- *
21
- * @access private
22
- * @var array Notices.
23
- * @since 1.0.8
24
- */
25
- private static $notices = array();
26
-
27
- /**
28
- * Instance
29
- *
30
- * @access private
31
- * @var object Class object.
32
- * @since 1.0.8
33
- */
34
- private static $instance;
35
-
36
- /**
37
- * Initiator
38
- *
39
- * @since 1.0.8
40
- * @return object initialized object of class.
41
- */
42
- public static function get_instance() {
43
- if ( ! isset( self::$instance ) ) {
44
- self::$instance = new self;
45
- }
46
- return self::$instance;
47
- }
48
-
49
- /**
50
- * Constructor
51
- *
52
- * @since 1.0.8
53
- */
54
- public function __construct() {
55
-
56
- add_action( 'admin_notices', array( $this, 'show_notices' ) );
57
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
58
- add_action( 'wp_ajax_hfe-notices', array( $this, 'dismiss' ) );
59
-
60
- }
61
-
62
- /**
63
- * Add Notice.
64
- *
65
- * @since 1.0.8
66
- * @param array $args Notice arguments.
67
- * @return void
68
- */
69
- public static function add_notice( $args = array() ) {
70
- if ( is_array( $args ) ) {
71
- self::$notices[] = $args;
72
- }
73
- }
74
-
75
- /**
76
- * Dismiss Notice.
77
- *
78
- * @since 1.0.8
79
- * @return void
80
- */
81
- function dismiss() {
82
-
83
- $id = ( isset( $_POST['id'] ) ) ? $_POST['id'] : '';
84
- $time = ( isset( $_POST['time'] ) ) ? $_POST['time'] : '';
85
- $meta = ( isset( $_POST['meta'] ) ) ? $_POST['meta'] : '';
86
-
87
- // Valid inputs?
88
- if ( ! empty( $id ) ) {
89
-
90
- if ( 'user' === $meta ) {
91
- update_user_meta( get_current_user_id(), $id, true );
92
- } else {
93
- set_transient( $id, true, $time );
94
- }
95
-
96
- wp_send_json_success();
97
- }
98
-
99
- wp_send_json_error();
100
- }
101
-
102
- /**
103
- * Enqueue Scripts.
104
- *
105
- * @since 1.0.8
106
- * @return void
107
- */
108
- function enqueue_scripts() {
109
- wp_register_script( 'hfe-sites-notices', HFE_URL . 'assets/js/hfe-sites-notices.js', array( 'jquery' ), HFE_VER, true );
110
- }
111
-
112
- /**
113
- * Notice Types
114
- *
115
- * @since 1.0.8
116
- * @return void
117
- */
118
- function show_notices() {
119
-
120
- $defaults = array(
121
- 'id' => '',
122
- 'type' => 'info',
123
- 'show_if' => true,
124
- 'message' => '',
125
- 'class' => 'hfe-active-notice',
126
- 'dismissible' => false,
127
- 'dismissible-meta' => 'user',
128
- 'dismissible-time' => WEEK_IN_SECONDS,
129
-
130
- 'data' => '',
131
- );
132
-
133
- foreach ( self::$notices as $key => $notice ) {
134
-
135
- $notice = wp_parse_args( $notice, $defaults );
136
-
137
- $classes = array( 'hfe-notice', 'notice' );
138
-
139
- $classes[] = $notice['class'];
140
- if ( isset( $notice['type'] ) ) {
141
- $classes[] = 'notice-' . $notice['type'];
142
- }
143
-
144
- // Is notice dismissible?
145
- if ( true === $notice['dismissible'] ) {
146
- $classes[] = 'is-dismissible';
147
-
148
- // Dismissable time.
149
- $notice['data'] = ' dismissible-time=' . esc_attr( $notice['dismissible-time'] ) . ' ';
150
- }
151
-
152
- // Notice ID.
153
- $notice_id = 'hfe-sites-notices-id-' . $notice['id'];
154
- $notice['id'] = $notice_id;
155
- if ( ! isset( $notice['id'] ) ) {
156
- $notice_id = 'hfe-sites-notices-id-' . $notice['id'];
157
- $notice['id'] = $notice_id;
158
- } else {
159
- $notice_id = $notice['id'];
160
- }
161
-
162
- $notice['classes'] = implode( ' ', $classes );
163
-
164
- // User meta.
165
- $notice['data'] .= ' dismissible-meta=' . esc_attr( $notice['dismissible-meta'] ) . ' ';
166
- if ( 'user' === $notice['dismissible-meta'] ) {
167
- $expired = get_user_meta( get_current_user_id(), $notice_id, true );
168
- } elseif ( 'transient' === $notice['dismissible-meta'] ) {
169
- $expired = get_transient( $notice_id );
170
- }
171
-
172
- // Notices visible after transient expire.
173
- if ( isset( $notice['show_if'] ) ) {
174
-
175
- if ( true === $notice['show_if'] ) {
176
-
177
- // Is transient expired?
178
- if ( false === $expired || empty( $expired ) ) {
179
- self::markup( $notice );
180
- }
181
- }
182
- } else {
183
-
184
- // No transient notices.
185
- self::markup( $notice );
186
- }
187
- }
188
-
189
- }
190
-
191
- /**
192
- * Markup Notice.
193
- *
194
- * @since 1.0.8
195
- * @param array $notice Notice markup.
196
- * @return void
197
- */
198
- public static function markup( $notice = array() ) {
199
-
200
- wp_enqueue_script( 'hfe-sites-notices' );
201
-
202
- ?>
203
- <div id="<?php echo esc_attr( $notice['id'] ); ?>" class="<?php echo esc_attr( $notice['classes'] ); ?>" <?php echo $notice['data']; ?>>
204
- <p>
205
- <?php echo $notice['message']; ?>
206
- </p>
207
- </div>
208
- <?php
209
- }
210
-
211
- }
212
-
213
- /**
214
- * Kicking this off by calling 'get_instance()' method
215
- */
216
- HFE_Notices::get_instance();
217
-
218
- endif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/class-hfe-update.php CHANGED
@@ -39,9 +39,9 @@ if ( ! class_exists( 'HFE_Update' ) ) {
39
 
40
  // Theme Updates.
41
  if ( is_admin() ) {
42
- add_action( 'admin_init', array( $this, 'init' ), 5 );
43
  } else {
44
- add_action( 'wp', array( $this, 'init' ), 5 );
45
  }
46
  }
47
 
@@ -57,6 +57,12 @@ if ( ! class_exists( 'HFE_Update' ) ) {
57
  return;
58
  }
59
 
 
 
 
 
 
 
60
  // flush rewrite rules on plugin update.
61
  flush_rewrite_rules();
62
 
@@ -65,6 +71,78 @@ if ( ! class_exists( 'HFE_Update' ) ) {
65
  do_action( 'hfe_update_after' );
66
  }
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  /**
69
  * Check if db upgrade is required.
70
  *
39
 
40
  // Theme Updates.
41
  if ( is_admin() ) {
42
+ add_action( 'admin_init', [ $this, 'init' ], 5 );
43
  } else {
44
+ add_action( 'wp', [ $this, 'init' ], 5 );
45
  }
46
  }
47
 
57
  return;
58
  }
59
 
60
+ $db_version = get_option( $this->db_option_key, false );
61
+
62
+ if ( version_compare( $db_version, '1.2.0-beta.2', '<' ) ) {
63
+ $this->setup_default_terget_rules();
64
+ }
65
+
66
  // flush rewrite rules on plugin update.
67
  flush_rewrite_rules();
68
 
71
  do_action( 'hfe_update_after' );
72
  }
73
 
74
+ /**
75
+ * Set default target rules for header, footer, before footers being used before target rules were added to the plugin.
76
+ *
77
+ * @since 1.2.0-beta.1
78
+ * @return void
79
+ */
80
+ private function setup_default_terget_rules() {
81
+ $default_include_locations = [
82
+ 'rule' => [ 0 => 'basic-global' ],
83
+ 'specific' => [],
84
+ ];
85
+
86
+ $header_id = $this->get_legacy_template_id( 'type_header' );
87
+ $footer_id = $this->get_legacy_template_id( 'type_footer' );
88
+ $before_footer_id = $this->get_legacy_template_id( 'type_before_footer' );
89
+
90
+ // Header.
91
+ if ( ! empty( $header_id ) ) {
92
+ update_post_meta( $header_id, 'ehf_target_include_locations', $default_include_locations );
93
+ }
94
+
95
+ // Footer.
96
+ if ( ! empty( $footer_id ) ) {
97
+ update_post_meta( $footer_id, 'ehf_target_include_locations', $default_include_locations );
98
+ }
99
+
100
+ // Before Footer.
101
+ if ( ! empty( $before_footer_id ) ) {
102
+ update_post_meta( $before_footer_id, 'ehf_target_include_locations', $default_include_locations );
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Get header or footer template id based on the meta query.
108
+ *
109
+ * @param String $type Type of the template header/footer.
110
+ *
111
+ * @return Mixed Returns the header or footer template id if found, else returns string ''.
112
+ */
113
+ public function get_legacy_template_id( $type ) {
114
+ $args = [
115
+ 'post_type' => 'elementor-hf',
116
+ 'meta_key' => 'ehf_template_type',
117
+ 'meta_value' => $type,
118
+ 'meta_type' => 'post',
119
+ 'meta_compare' => '>=',
120
+ 'orderby' => 'meta_value',
121
+ 'order' => 'ASC',
122
+ 'meta_query' => [
123
+ 'relation' => 'OR',
124
+ [
125
+ 'key' => 'ehf_template_type',
126
+ 'value' => $type,
127
+ 'compare' => '==',
128
+ 'type' => 'post',
129
+ ],
130
+ ],
131
+ ];
132
+
133
+ $args = apply_filters( 'hfe_get_template_id_args', $args );
134
+ $template = new WP_Query(
135
+ $args
136
+ );
137
+
138
+ if ( $template->have_posts() ) {
139
+ $posts = wp_list_pluck( $template->posts, 'ID' );
140
+ return $posts[0];
141
+ }
142
+
143
+ return '';
144
+ }
145
+
146
  /**
147
  * Check if db upgrade is required.
148
  *
inc/compatibility/class-hfe-wpml-compatibility.php CHANGED
@@ -44,9 +44,9 @@ class HFE_WPML_Compatibility {
44
  * @since 1.0.9
45
  */
46
  private function __construct() {
47
- add_filter( 'hfe_get_settings_type_header', array( $this, 'get_wpml_object' ) );
48
- add_filter( 'hfe_get_settings_type_footer', array( $this, 'get_wpml_object' ) );
49
- add_filter( 'hfe_render_template_id', array( $this, 'get_wpml_object' ) );
50
  }
51
 
52
  /**
44
  * @since 1.0.9
45
  */
46
  private function __construct() {
47
+ add_filter( 'hfe_get_settings_type_header', [ $this, 'get_wpml_object' ] );
48
+ add_filter( 'hfe_get_settings_type_footer', [ $this, 'get_wpml_object' ] );
49
+ add_filter( 'hfe_render_template_id', [ $this, 'get_wpml_object' ] );
50
  }
51
 
52
  /**
inc/hfe-functions.php CHANGED
@@ -110,3 +110,58 @@ function hfe_render_footer() {
110
  <?php
111
 
112
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  <?php
111
 
112
  }
113
+
114
+
115
+ /**
116
+ * Get HFE Before Footer ID
117
+ *
118
+ * @since 1.0.2
119
+ * @return String|boolean before footer id if it is set else returns false.
120
+ */
121
+ function hfe_get_before_footer_id() {
122
+
123
+ $before_footer_id = Header_Footer_Elementor::get_settings( 'type_before_footer', '' );
124
+
125
+ if ( '' === $before_footer_id ) {
126
+ $before_footer_id = false;
127
+ }
128
+
129
+ return apply_filters( 'get_hfe_before_footer_id', $before_footer_id );
130
+ }
131
+
132
+ /**
133
+ * Checks if Before Footer is enabled from HFE.
134
+ *
135
+ * @since 1.0.2
136
+ * @return bool True if before footer is enabled. False if before footer is not enabled.
137
+ */
138
+ function hfe_is_before_footer_enabled() {
139
+
140
+ $before_footer_id = Header_Footer_Elementor::get_settings( 'type_before_footer', '' );
141
+ $status = false;
142
+
143
+ if ( '' !== $before_footer_id ) {
144
+ $status = true;
145
+ }
146
+
147
+ return apply_filters( 'hfe_before_footer_enabled', $status );
148
+ }
149
+
150
+ /**
151
+ * Display before footer markup.
152
+ *
153
+ * @since 1.0.2
154
+ */
155
+ function hfe_render_before_footer() {
156
+
157
+ if ( false == apply_filters( 'enable_hfe_render_before_footer', true ) ) {
158
+ return;
159
+ }
160
+
161
+ ?>
162
+ <div class="hfe-before-footer-wrap">
163
+ <?php Header_Footer_Elementor::get_before_footer_content(); ?>
164
+ </div>
165
+ <?php
166
+
167
+ }
inc/lib/notices/class-astra-notices.php ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Astra Sites Notices
4
+ *
5
+ * Closing notice on click on `astra-notice-close` class.
6
+ *
7
+ * If notice has the data attribute `data-repeat-notice-after="%2$s"` then notice close for that SPECIFIC TIME.
8
+ * If notice has NO data attribute `data-repeat-notice-after="%2$s"` then notice close for the CURRENT USER FOREVER.
9
+ *
10
+ * > Create custom close notice link in the notice markup. E.g.
11
+ * `<a href="#" data-repeat-notice-after="<?php echo MONTH_IN_SECONDS; ?>" class="astra-notice-close">`
12
+ * It close the notice for 30 days.
13
+ *
14
+ * @package Astra Sites
15
+ * @since 1.4.0
16
+ */
17
+
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit; // Exit if accessed directly.
20
+ }
21
+
22
+ if ( ! class_exists( 'Astra_Notices' ) ) :
23
+
24
+ /**
25
+ * Astra_Notices
26
+ *
27
+ * @since 1.4.0
28
+ */
29
+ class Astra_Notices {
30
+
31
+ /**
32
+ * Notices
33
+ *
34
+ * @access private
35
+ * @var array Notices.
36
+ * @since 1.4.0
37
+ */
38
+ private static $version = '1.1.5';
39
+
40
+ /**
41
+ * Notices
42
+ *
43
+ * @access private
44
+ * @var array Notices.
45
+ * @since 1.4.0
46
+ */
47
+ private static $notices = array();
48
+
49
+ /**
50
+ * Instance
51
+ *
52
+ * @access private
53
+ * @var object Class object.
54
+ * @since 1.4.0
55
+ */
56
+ private static $instance;
57
+
58
+ /**
59
+ * Initiator
60
+ *
61
+ * @since 1.4.0
62
+ * @return object initialized object of class.
63
+ */
64
+ public static function get_instance() {
65
+ if ( ! isset( self::$instance ) ) {
66
+ self::$instance = new self();
67
+ }
68
+ return self::$instance;
69
+ }
70
+
71
+ /**
72
+ * Constructor
73
+ *
74
+ * @since 1.4.0
75
+ */
76
+ public function __construct() {
77
+ add_action( 'admin_notices', array( $this, 'show_notices' ), 30 );
78
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
79
+ add_action( 'wp_ajax_astra-notice-dismiss', array( $this, 'dismiss_notice' ) );
80
+ add_filter( 'wp_kses_allowed_html', array( $this, 'add_data_attributes' ), 10, 2 );
81
+ }
82
+
83
+ /**
84
+ * Filters and Returns a list of allowed tags and attributes for a given context.
85
+ *
86
+ * @param Array $allowedposttags Array of allowed tags.
87
+ * @param String $context Context type (explicit).
88
+ * @since 1.4.0
89
+ * @return Array
90
+ */
91
+ public function add_data_attributes( $allowedposttags, $context ) {
92
+ $allowedposttags['a']['data-repeat-notice-after'] = true;
93
+
94
+ return $allowedposttags;
95
+ }
96
+
97
+ /**
98
+ * Add Notice.
99
+ *
100
+ * @since 1.4.0
101
+ * @param array $args Notice arguments.
102
+ * @return void
103
+ */
104
+ public static function add_notice( $args = array() ) {
105
+ self::$notices[] = $args;
106
+ }
107
+
108
+ /**
109
+ * Dismiss Notice.
110
+ *
111
+ * @since 1.4.0
112
+ * @return void
113
+ */
114
+ public function dismiss_notice() {
115
+ $notice_id = ( isset( $_POST['notice_id'] ) ) ? sanitize_key( $_POST['notice_id'] ) : '';
116
+ $repeat_notice_after = ( isset( $_POST['repeat_notice_after'] ) ) ? absint( $_POST['repeat_notice_after'] ) : '';
117
+ $nonce = ( isset( $_POST['nonce'] ) ) ? sanitize_key( $_POST['nonce'] ) : '';
118
+
119
+ if ( false === wp_verify_nonce( $nonce, 'astra-notices' ) ) {
120
+ wp_send_json_error( _e( 'WordPress Nonce not validated.', 'astra-notices' ) );
121
+ }
122
+
123
+ // Valid inputs?
124
+ if ( ! empty( $notice_id ) ) {
125
+ if ( ! empty( $repeat_notice_after ) ) {
126
+ set_transient( $notice_id, true, $repeat_notice_after );
127
+ } else {
128
+ update_user_meta( get_current_user_id(), $notice_id, 'notice-dismissed' );
129
+ }
130
+
131
+ wp_send_json_success();
132
+ }
133
+
134
+ wp_send_json_error();
135
+ }
136
+
137
+ /**
138
+ * Enqueue Scripts.
139
+ *
140
+ * @since 1.4.0
141
+ * @return void
142
+ */
143
+ public function enqueue_scripts() {
144
+ wp_register_script( 'astra-notices', self::_get_uri() . 'notices.js', array( 'jquery' ), self::$version, true );
145
+ wp_localize_script(
146
+ 'astra-notices',
147
+ 'astraNotices',
148
+ array(
149
+ '_notice_nonce' => wp_create_nonce( 'astra-notices' ),
150
+ )
151
+ );
152
+ }
153
+
154
+ /**
155
+ * Rating priority sort
156
+ *
157
+ * @since 1.5.2
158
+ * @param array $array1 array one.
159
+ * @param array $array2 array two.
160
+ * @return array
161
+ */
162
+ public function sort_notices( $array1, $array2 ) {
163
+ if ( ! isset( $array1['priority'] ) ) {
164
+ $array1['priority'] = 10;
165
+ }
166
+ if ( ! isset( $array2['priority'] ) ) {
167
+ $array2['priority'] = 10;
168
+ }
169
+
170
+ return $array1['priority'] - $array2['priority'];
171
+ }
172
+
173
+ /**
174
+ * Notice Types
175
+ *
176
+ * @since 1.4.0
177
+ * @return void
178
+ */
179
+ public function show_notices() {
180
+ $defaults = array(
181
+ 'id' => '', // Optional, Notice ID. If empty it set `astra-notices-id-<$array-index>`.
182
+ 'type' => 'info', // Optional, Notice type. Default `info`. Expected [info, warning, notice, error].
183
+ 'message' => '', // Optional, Message.
184
+ 'show_if' => true, // Optional, Show notice on custom condition. E.g. 'show_if' => if( is_admin() ) ? true, false, .
185
+ 'repeat-notice-after' => '', // Optional, Dismiss-able notice time. It'll auto show after given time.
186
+ 'display-notice-after' => false, // Optional, Dismiss-able notice time. It'll auto show after given time.
187
+ 'class' => '', // Optional, Additional notice wrapper class.
188
+ 'priority' => 10, // Priority of the notice.
189
+ 'display-with-other-notices' => true, // Should the notice be displayed if other notices are being displayed from Astra_Notices.
190
+ 'is_dismissible' => true,
191
+ );
192
+
193
+ // Count for the notices that are rendered.
194
+ $notices_displayed = 0;
195
+
196
+ // sort the array with priority.
197
+ usort( self::$notices, array( $this, 'sort_notices' ) );
198
+
199
+ foreach ( self::$notices as $key => $notice ) {
200
+ $notice = wp_parse_args( $notice, $defaults );
201
+
202
+ $notice['id'] = self::get_notice_id( $notice, $key );
203
+
204
+ $notice['classes'] = self::get_wrap_classes( $notice );
205
+
206
+ // Notices visible after transient expire.
207
+ if ( isset( $notice['show_if'] ) && true === $notice['show_if'] ) {
208
+
209
+ // don't display the notice if it is not supposed to be displayed with other notices.
210
+ if ( 0 !== $notices_displayed && false === $notice['display-with-other-notices'] ) {
211
+ continue;
212
+ }
213
+
214
+ if ( self::is_expired( $notice ) ) {
215
+ self::markup( $notice );
216
+ ++$notices_displayed;
217
+ }
218
+ }
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Markup Notice.
224
+ *
225
+ * @since 1.4.0
226
+ * @param array $notice Notice markup.
227
+ * @return void
228
+ */
229
+ public static function markup( $notice = array() ) {
230
+ wp_enqueue_script( 'astra-notices' );
231
+
232
+ do_action( 'astra_notice_before_markup' );
233
+
234
+ do_action( "astra_notice_before_markup_{$notice['id']}" );
235
+
236
+ ?>
237
+ <div id="<?php echo esc_attr( $notice['id'] ); ?>" class="<?php echo esc_attr( $notice['classes'] ); ?>" data-repeat-notice-after="<?php echo esc_attr( $notice['repeat-notice-after'] ); ?>">
238
+ <div class="notice-container">
239
+ <?php do_action( "astra_notice_inside_markup_{$notice['id']}" ); ?>
240
+ <?php echo wp_kses_post( $notice['message'] ); ?>
241
+ </div>
242
+ </div>
243
+ <?php
244
+
245
+ do_action( "astra_notice_after_markup_{$notice['id']}" );
246
+
247
+ do_action( 'astra_notice_after_markup' );
248
+ }
249
+
250
+ /**
251
+ * Notice classes.
252
+ *
253
+ * @since 1.4.0
254
+ *
255
+ * @param array $notice Notice arguments.
256
+ * @return array Notice wrapper classes.
257
+ */
258
+ private static function get_wrap_classes( $notice ) {
259
+ $classes = array( 'astra-notice', 'notice' );
260
+
261
+ if ( $notice['is_dismissible'] ) {
262
+ $classes[] = 'is-dismissible';
263
+ }
264
+
265
+ $classes[] = $notice['class'];
266
+ if ( isset( $notice['type'] ) && '' !== $notice['type'] ) {
267
+ $classes[] = 'notice-' . $notice['type'];
268
+ }
269
+
270
+ return esc_attr( implode( ' ', $classes ) );
271
+ }
272
+
273
+ /**
274
+ * Get Notice ID.
275
+ *
276
+ * @since 1.4.0
277
+ *
278
+ * @param array $notice Notice arguments.
279
+ * @param int $key Notice array index.
280
+ * @return string Notice id.
281
+ */
282
+ private static function get_notice_id( $notice, $key ) {
283
+ if ( isset( $notice['id'] ) && ! empty( $notice['id'] ) ) {
284
+ return $notice['id'];
285
+ }
286
+
287
+ return 'astra-notices-id-' . $key;
288
+ }
289
+
290
+ /**
291
+ * Is notice expired?
292
+ *
293
+ * @since 1.4.0
294
+ *
295
+ * @param array $notice Notice arguments.
296
+ * @return boolean
297
+ */
298
+ private static function is_expired( $notice ) {
299
+ $transient_status = get_transient( $notice['id'] );
300
+
301
+ if ( false === $transient_status ) {
302
+ if ( isset( $notice['display-notice-after'] ) && false !== $notice['display-notice-after'] ) {
303
+ if ( 'delayed-notice' !== get_user_meta( get_current_user_id(), $notice['id'], true ) &&
304
+ 'notice-dismissed' !== get_user_meta( get_current_user_id(), $notice['id'], true ) ) {
305
+ set_transient( $notice['id'], 'delayed-notice', $notice['display-notice-after'] );
306
+ update_user_meta( get_current_user_id(), $notice['id'], 'delayed-notice' );
307
+
308
+ return false;
309
+ }
310
+ }
311
+
312
+ // Check the user meta status if current notice is dismissed or delay completed.
313
+ $meta_status = get_user_meta( get_current_user_id(), $notice['id'], true );
314
+
315
+ if ( empty( $meta_status ) || 'delayed-notice' === $meta_status ) {
316
+ return true;
317
+ }
318
+ }
319
+
320
+ return false;
321
+ }
322
+
323
+ /**
324
+ * Get URI
325
+ *
326
+ * @return mixed URL.
327
+ */
328
+ public static function _get_uri() {
329
+ $path = wp_normalize_path( dirname( __FILE__ ) );
330
+ $theme_dir = wp_normalize_path( get_template_directory() );
331
+ $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
332
+
333
+ if ( strpos( $path, $theme_dir ) !== false ) {
334
+ return trailingslashit( get_template_directory_uri() . str_replace( $theme_dir, '', $path ) );
335
+ } elseif ( strpos( $path, $plugin_dir ) !== false ) {
336
+ return plugin_dir_url( __FILE__ );
337
+ } elseif ( strpos( $path, dirname( plugin_basename( __FILE__ ) ) ) !== false ) {
338
+ return plugin_dir_url( __FILE__ );
339
+ }
340
+
341
+ return;
342
+ }
343
+
344
+ }
345
+
346
+ /**
347
+ * Kicking this off by calling 'get_instance()' method
348
+ */
349
+ Astra_Notices::get_instance();
350
+ endif;
inc/lib/notices/notices.js ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Customizer controls toggles
3
+ *
4
+ * @package Astra
5
+ */
6
+
7
+ ( function( $ ) {
8
+
9
+ /**
10
+ * Helper class for the main Customizer interface.
11
+ *
12
+ * @since 1.0.0
13
+ * @class ASTCustomizer
14
+ */
15
+ AstraNotices = {
16
+
17
+ /**
18
+ * Initializes our custom logic for the Customizer.
19
+ *
20
+ * @since 1.0.0
21
+ * @method init
22
+ */
23
+ init: function()
24
+ {
25
+ this._bind();
26
+ },
27
+
28
+ /**
29
+ * Binds events for the Astra Portfolio.
30
+ *
31
+ * @since 1.0.0
32
+ * @access private
33
+ * @method _bind
34
+ */
35
+ _bind: function()
36
+ {
37
+ $( document ).on('click', '.astra-notice-close', AstraNotices._dismissNoticeNew );
38
+ $( document ).on('click', '.astra-notice .notice-dismiss', AstraNotices._dismissNotice );
39
+ },
40
+
41
+ _dismissNotice: function( event ) {
42
+ event.preventDefault();
43
+
44
+ var repeat_notice_after = $( this ).parents('.astra-notice').data( 'repeat-notice-after' ) || '';
45
+ var notice_id = $( this ).parents('.astra-notice').attr( 'id' ) || '';
46
+
47
+ AstraNotices._ajax( notice_id, repeat_notice_after );
48
+ },
49
+
50
+ _dismissNoticeNew: function( event ) {
51
+ event.preventDefault();
52
+
53
+ var repeat_notice_after = $( this ).attr( 'data-repeat-notice-after' ) || '';
54
+ var notice_id = $( this ).parents('.astra-notice').attr( 'id' ) || '';
55
+
56
+ var $el = $( this ).parents('.astra-notice');
57
+ $el.fadeTo( 100, 0, function() {
58
+ $el.slideUp( 100, function() {
59
+ $el.remove();
60
+ });
61
+ });
62
+
63
+ AstraNotices._ajax( notice_id, repeat_notice_after );
64
+
65
+ var link = $( this ).attr( 'href' ) || '';
66
+ var target = $( this ).attr( 'target' ) || '';
67
+ if( '' !== link && '_blank' === target ) {
68
+ window.open(link , '_blank');
69
+ }
70
+ },
71
+
72
+ _ajax: function( notice_id, repeat_notice_after ) {
73
+
74
+ if( '' === notice_id ) {
75
+ return;
76
+ }
77
+
78
+ $.ajax({
79
+ url: ajaxurl,
80
+ type: 'POST',
81
+ data: {
82
+ action : 'astra-notice-dismiss',
83
+ notice_id : notice_id,
84
+ repeat_notice_after : parseInt( repeat_notice_after ),
85
+ nonce : astraNotices._notice_nonce
86
+ },
87
+ });
88
+
89
+ }
90
+ };
91
+
92
+ $( function() {
93
+ AstraNotices.init();
94
+ } );
95
+ } )( jQuery );
inc/lib/target-rule/class-astra-target-rules-fields.php ADDED
@@ -0,0 +1,1618 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Astra Advanced Headers Bar Post Meta Box
4
+ *
5
+ * @package Astra Pro
6
+ */
7
+
8
+ namespace HFE\Lib;
9
+
10
+ /**
11
+ * Meta Boxes setup
12
+ */
13
+ class Astra_Target_Rules_Fields {
14
+
15
+
16
+ /**
17
+ * Instance
18
+ *
19
+ * @since 1.0.0
20
+ *
21
+ * @var $instance
22
+ */
23
+ private static $instance;
24
+
25
+ /**
26
+ * Meta Option
27
+ *
28
+ * @since 1.0.0
29
+ *
30
+ * @var $meta_option
31
+ */
32
+ private static $meta_option;
33
+
34
+ /**
35
+ * Current page type
36
+ *
37
+ * @since 1.0.0
38
+ *
39
+ * @var $current_page_type
40
+ */
41
+ private static $current_page_type = null;
42
+
43
+ /**
44
+ * CUrrent page data
45
+ *
46
+ * @since 1.0.0
47
+ *
48
+ * @var $current_page_data
49
+ */
50
+ private static $current_page_data = array();
51
+
52
+ /**
53
+ * User Selection Option
54
+ *
55
+ * @since 1.0.0
56
+ *
57
+ * @var $user_selection
58
+ */
59
+ private static $user_selection;
60
+
61
+ /**
62
+ * Location Selection Option
63
+ *
64
+ * @since 1.0.0
65
+ *
66
+ * @var $location_selection
67
+ */
68
+ private static $location_selection;
69
+
70
+ /**
71
+ * Initiator
72
+ *
73
+ * @since 1.0.0
74
+ */
75
+ public static function get_instance() {
76
+ if ( ! isset( self::$instance ) ) {
77
+ self::$instance = new self();
78
+ }
79
+
80
+ return self::$instance;
81
+ }
82
+
83
+ /**
84
+ * Constructor
85
+ *
86
+ * @since 1.0.0
87
+ */
88
+ public function __construct() {
89
+ define( 'AST_TARGET_RULE_URI', plugins_url( '/', __FILE__ ) );
90
+ define( 'AST_TARGET_RULE_VER', '1.0.0' );
91
+ define( 'AST_TARGET_RULE_DIR', plugin_dir_path( __FILE__ ) );
92
+
93
+ add_action( 'admin_action_edit', array( $this, 'initialize_options' ) );
94
+ add_action( 'wp_ajax_astra_get_posts_by_query', array( $this, 'astra_get_posts_by_query' ) );
95
+ }
96
+
97
+ /**
98
+ * Initialize member variables.
99
+ *
100
+ * @return void
101
+ */
102
+ public function initialize_options() {
103
+ self::$user_selection = self::get_user_selections();
104
+ self::$location_selection = self::get_location_selections();
105
+ }
106
+
107
+ /**
108
+ * Get location selection options.
109
+ *
110
+ * @return array
111
+ */
112
+ public static function get_location_selections() {
113
+ $args = array(
114
+ 'public' => true,
115
+ '_builtin' => true,
116
+ );
117
+
118
+ $post_types = get_post_types( $args, 'objects' );
119
+ unset( $post_types['attachment'] );
120
+
121
+ $args['_builtin'] = false;
122
+ $custom_post_type = get_post_types( $args, 'objects' );
123
+
124
+ $post_types = apply_filters( 'astra_location_rule_post_types', array_merge( $post_types, $custom_post_type ) );
125
+
126
+ $special_pages = array(
127
+ 'special-404' => __( '404 Page', 'header-footer-elementor' ),
128
+ 'special-search' => __( 'Search Page', 'header-footer-elementor' ),
129
+ 'special-blog' => __( 'Blog / Posts Page', 'header-footer-elementor' ),
130
+ 'special-front' => __( 'Front Page', 'header-footer-elementor' ),
131
+ 'special-date' => __( 'Date Archive', 'header-footer-elementor' ),
132
+ 'special-author' => __( 'Author Archive', 'header-footer-elementor' ),
133
+ );
134
+
135
+ if ( class_exists( 'WooCommerce' ) ) {
136
+ $special_pages['special-woo-shop'] = __( 'WooCommerce Shop Page', 'header-footer-elementor' );
137
+ }
138
+
139
+ $selection_options = array(
140
+ 'basic' => array(
141
+ 'label' => __( 'Basic', 'header-footer-elementor' ),
142
+ 'value' => array(
143
+ 'basic-global' => __( 'Entire Website', 'header-footer-elementor' ),
144
+ 'basic-singulars' => __( 'All Singulars', 'header-footer-elementor' ),
145
+ 'basic-archives' => __( 'All Archives', 'header-footer-elementor' ),
146
+ ),
147
+ ),
148
+
149
+ 'special-pages' => array(
150
+ 'label' => __( 'Special Pages', 'header-footer-elementor' ),
151
+ 'value' => $special_pages,
152
+ ),
153
+ );
154
+
155
+ $args = array(
156
+ 'public' => true,
157
+ );
158
+
159
+ $taxonomies = get_taxonomies( $args, 'objects' );
160
+
161
+ if ( ! empty( $taxonomies ) ) {
162
+ foreach ( $taxonomies as $taxonomy ) {
163
+
164
+ // skip post format taxonomy.
165
+ if ( 'post_format' == $taxonomy->name ) {
166
+ continue;
167
+ }
168
+
169
+ foreach ( $post_types as $post_type ) {
170
+ $post_opt = self::get_post_target_rule_options( $post_type, $taxonomy );
171
+
172
+ if ( isset( $selection_options[ $post_opt['post_key'] ] ) ) {
173
+ if ( ! empty( $post_opt['value'] ) && is_array( $post_opt['value'] ) ) {
174
+ foreach ( $post_opt['value'] as $key => $value ) {
175
+ if ( ! in_array( $value, $selection_options[ $post_opt['post_key'] ]['value'] ) ) {
176
+ $selection_options[ $post_opt['post_key'] ]['value'][ $key ] = $value;
177
+ }
178
+ }
179
+ }
180
+ } else {
181
+ $selection_options[ $post_opt['post_key'] ] = array(
182
+ 'label' => $post_opt['label'],
183
+ 'value' => $post_opt['value'],
184
+ );
185
+ }
186
+ }
187
+ }
188
+ }
189
+
190
+ $selection_options['specific-target'] = array(
191
+ 'label' => __( 'Specific Target', 'header-footer-elementor' ),
192
+ 'value' => array(
193
+ 'specifics' => __( 'Specific Pages / Posts / Taxanomies, etc.', 'header-footer-elementor' ),
194
+ ),
195
+ );
196
+
197
+ /**
198
+ * Filter options displayed in the display conditions select field of Display conditions.
199
+ *
200
+ * @since 1.5.0
201
+ */
202
+ return apply_filters( 'astra_display_on_list', $selection_options );
203
+ }
204
+
205
+ /**
206
+ * Get user selection options.
207
+ *
208
+ * @return array
209
+ */
210
+ public static function get_user_selections() {
211
+ $selection_options = array(
212
+ 'basic' => array(
213
+ 'label' => __( 'Basic', 'header-footer-elementor' ),
214
+ 'value' => array(
215
+ 'all' => __( 'All', 'header-footer-elementor' ),
216
+ 'logged-in' => __( 'Logged In', 'header-footer-elementor' ),
217
+ 'logged-out' => __( 'Logged Out', 'header-footer-elementor' ),
218
+ ),
219
+ ),
220
+
221
+ 'advanced' => array(
222
+ 'label' => __( 'Advanced', 'header-footer-elementor' ),
223
+ 'value' => array(),
224
+ ),
225
+ );
226
+
227
+ /* User roles */
228
+ $roles = get_editable_roles();
229
+
230
+ foreach ( $roles as $slug => $data ) {
231
+ $selection_options['advanced']['value'][ $slug ] = $data['name'];
232
+ }
233
+
234
+ /**
235
+ * Filter options displayed in the user select field of Display conditions.
236
+ *
237
+ * @since 1.5.0
238
+ */
239
+ return apply_filters( 'astra_user_roles_list', $selection_options );
240
+ }
241
+
242
+ /**
243
+ * Get location label by key.
244
+ *
245
+ * @param string $key Location option key.
246
+ * @return string
247
+ */
248
+ public static function get_location_by_key( $key ) {
249
+ if ( ! isset( self::$location_selection ) || empty( self::$location_selection ) ) {
250
+ self::$location_selection = self::get_location_selections();
251
+ }
252
+ $location_selection = self::$location_selection;
253
+
254
+ foreach ( $location_selection as $location_grp ) {
255
+ if ( isset( $location_grp['value'][ $key ] ) ) {
256
+ return $location_grp['value'][ $key ];
257
+ }
258
+ }
259
+
260
+ if ( strpos( $key, 'post-' ) !== false ) {
261
+ $post_id = (int) str_replace( 'post-', '', $key );
262
+ return get_the_title( $post_id );
263
+ }
264
+
265
+ // taxonomy options.
266
+ if ( strpos( $key, 'tax-' ) !== false ) {
267
+ $tax_id = (int) str_replace( 'tax-', '', $key );
268
+ $term = get_term( $tax_id );
269
+
270
+ if ( ! is_wp_error( $term ) ) {
271
+ $term_taxonomy = ucfirst( str_replace( '_', ' ', $term->taxonomy ) );
272
+ return $term->name . ' - ' . $term_taxonomy;
273
+ } else {
274
+ return '';
275
+ }
276
+ }
277
+
278
+ return $key;
279
+ }
280
+
281
+ /**
282
+ * Get user label by key.
283
+ *
284
+ * @param string $key User option key.
285
+ * @return string
286
+ */
287
+ public static function get_user_by_key( $key ) {
288
+ if ( ! isset( self::$user_selection ) || empty( self::$user_selection ) ) {
289
+ self::$user_selection = self::get_user_selections();
290
+ }
291
+ $user_selection = self::$user_selection;
292
+
293
+ if ( isset( $user_selection['basic']['value'][ $key ] ) ) {
294
+ return $user_selection['basic']['value'][ $key ];
295
+ } elseif ( $user_selection['advanced']['value'][ $key ] ) {
296
+ return $user_selection['advanced']['value'][ $key ];
297
+ }
298
+ return $key;
299
+ }
300
+
301
+ /**
302
+ * Ajax handeler to return the posts based on the search query.
303
+ * When searching for the post/pages only titles are searched for.
304
+ *
305
+ * @since 1.0.0
306
+ */
307
+ function astra_get_posts_by_query() {
308
+ $search_string = isset( $_POST['q'] ) ? sanitize_text_field( $_POST['q'] ) : '';
309
+ $data = array();
310
+ $result = array();
311
+
312
+ $args = array(
313
+ 'public' => true,
314
+ '_builtin' => false,
315
+ );
316
+
317
+ $output = 'names'; // names or objects, note names is the default.
318
+ $operator = 'and'; // also supports 'or'.
319
+ $post_types = get_post_types( $args, $output, $operator );
320
+
321
+ $post_types['Posts'] = 'post';
322
+ $post_types['Pages'] = 'page';
323
+
324
+ foreach ( $post_types as $key => $post_type ) {
325
+ $data = array();
326
+
327
+ add_filter( 'posts_search', array( $this, 'search_only_titles' ), 10, 2 );
328
+
329
+ $query = new \WP_Query(
330
+ array(
331
+ 's' => $search_string,
332
+ 'post_type' => $post_type,
333
+ 'posts_per_page' => - 1,
334
+ )
335
+ );
336
+
337
+ if ( $query->have_posts() ) {
338
+ while ( $query->have_posts() ) {
339
+ $query->the_post();
340
+ $title = get_the_title();
341
+ $title .= ( 0 != $query->post->post_parent ) ? ' (' . get_the_title( $query->post->post_parent ) . ')' : '';
342
+ $id = get_the_id();
343
+ $data[] = array(
344
+ 'id' => 'post-' . $id,
345
+ 'text' => $title,
346
+ );
347
+ }
348
+ }
349
+
350
+ if ( is_array( $data ) && ! empty( $data ) ) {
351
+ $result[] = array(
352
+ 'text' => $key,
353
+ 'children' => $data,
354
+ );
355
+ }
356
+ }
357
+
358
+ $data = array();
359
+
360
+ wp_reset_postdata();
361
+
362
+ $args = array(
363
+ 'public' => true,
364
+ );
365
+
366
+ $output = 'objects'; // names or objects, note names is the default.
367
+ $operator = 'and'; // also supports 'or'.
368
+ $taxonomies = get_taxonomies( $args, $output, $operator );
369
+
370
+ foreach ( $taxonomies as $taxonomy ) {
371
+ $terms = get_terms(
372
+ $taxonomy->name,
373
+ array(
374
+ 'orderby' => 'count',
375
+ 'hide_empty' => 0,
376
+ 'name__like' => $search_string,
377
+ )
378
+ );
379
+
380
+ $data = array();
381
+
382
+ $label = ucwords( $taxonomy->label );
383
+
384
+ if ( ! empty( $terms ) ) {
385
+ foreach ( $terms as $term ) {
386
+ $term_taxonomy_name = ucfirst( str_replace( '_', ' ', $taxonomy->name ) );
387
+
388
+ $data[] = array(
389
+ 'id' => 'tax-' . $term->term_id,
390
+ 'text' => $term->name . ' archive page',
391
+ );
392
+
393
+ $data[] = array(
394
+ 'id' => 'tax-' . $term->term_id . '-single-' . $taxonomy->name,
395
+ 'text' => 'All singulars from ' . $term->name,
396
+ );
397
+ }
398
+ }
399
+
400
+ if ( is_array( $data ) && ! empty( $data ) ) {
401
+ $result[] = array(
402
+ 'text' => $label,
403
+ 'children' => $data,
404
+ );
405
+ }
406
+ }
407
+
408
+ // return the result in json.
409
+ wp_send_json( $result );
410
+ }
411
+
412
+ /**
413
+ * Return search results only by post title.
414
+ * This is only run from astra_get_posts_by_query()
415
+ *
416
+ * @param (string) $search Search SQL for WHERE clause.
417
+ * @param (WP_Query) $wp_query The current WP_Query object.
418
+ *
419
+ * @return (string) The Modified Search SQL for WHERE clause.
420
+ */
421
+ function search_only_titles( $search, $wp_query ) {
422
+ if ( ! empty( $search ) && ! empty( $wp_query->query_vars['search_terms'] ) ) {
423
+ global $wpdb;
424
+
425
+ $q = $wp_query->query_vars;
426
+ $n = ! empty( $q['exact'] ) ? '' : '%';
427
+
428
+ $search = array();
429
+
430
+ foreach ( (array) $q['search_terms'] as $term ) {
431
+ $search[] = $wpdb->prepare( "$wpdb->posts.post_title LIKE %s", $n . $wpdb->esc_like( $term ) . $n );
432
+ }
433
+
434
+ if ( ! is_user_logged_in() ) {
435
+ $search[] = "$wpdb->posts.post_password = ''";
436
+ }
437
+
438
+ $search = ' AND ' . implode( ' AND ', $search );
439
+ }
440
+
441
+ return $search;
442
+ }
443
+
444
+ /**
445
+ * Function Name: admin_styles.
446
+ * Function Description: admin_styles.
447
+ */
448
+ public function admin_styles() {
449
+ wp_enqueue_script( 'astra-select2', AST_TARGET_RULE_URI . 'select2.js', array( 'jquery' ), AST_TARGET_RULE_VER, true );
450
+
451
+ $wp_lang = get_locale();
452
+ $ast_lang = '';
453
+ if ( '' !== $wp_lang ) {
454
+ $select2_lang = array(
455
+ '' => 'en',
456
+ 'hi_IN' => 'hi',
457
+ 'mr' => 'mr',
458
+ 'af' => 'af',
459
+ 'ar' => 'ar',
460
+ 'ary' => 'ar',
461
+ 'as' => 'as',
462
+ 'azb' => 'az',
463
+ 'az' => 'az',
464
+ 'bel' => 'be',
465
+ 'bg_BG' => 'bg',
466
+ 'bn_BD' => 'bn',
467
+ 'bo' => 'bo',
468
+ 'bs_BA' => 'bs',
469
+ 'ca' => 'ca',
470
+ 'ceb' => 'ceb',
471
+ 'cs_CZ' => 'cs',
472
+ 'cy' => 'cy',
473
+ 'da_DK' => 'da',
474
+ 'de_CH' => 'de',
475
+ 'de_DE' => 'de',
476
+ 'de_DE_formal' => 'de',
477
+ 'de_CH_informal' => 'de',
478
+ 'dzo' => 'dz',
479
+ 'el' => 'el',
480
+ 'en_CA' => 'en',
481
+ 'en_GB' => 'en',
482
+ 'en_AU' => 'en',
483
+ 'en_NZ' => 'en',
484
+ 'en_ZA' => 'en',
485
+ 'eo' => 'eo',
486
+ 'es_MX' => 'es',
487
+ 'es_VE' => 'es',
488
+ 'es_CR' => 'es',
489
+ 'es_CO' => 'es',
490
+ 'es_GT' => 'es',
491
+ 'es_ES' => 'es',
492
+ 'es_CL' => 'es',
493
+ 'es_PE' => 'es',
494
+ 'es_AR' => 'es',
495
+ 'et' => 'et',
496
+ 'eu' => 'eu',
497
+ 'fa_IR' => 'fa',
498
+ 'fi' => 'fi',
499
+ 'fr_BE' => 'fr',
500
+ 'fr_FR' => 'fr',
501
+ 'fr_CA' => 'fr',
502
+ 'gd' => 'gd',
503
+ 'gl_ES' => 'gl',
504
+ 'gu' => 'gu',
505
+ 'haz' => 'haz',
506
+ 'he_IL' => 'he',
507
+ 'hr' => 'hr',
508
+ 'hu_HU' => 'hu',
509
+ 'hy' => 'hy',
510
+ 'id_ID' => 'id',
511
+ 'is_IS' => 'is',
512
+ 'it_IT' => 'it',
513
+ 'ja' => 'ja',
514
+ 'jv_ID' => 'jv',
515
+ 'ka_GE' => 'ka',
516
+ 'kab' => 'kab',
517
+ 'km' => 'km',
518
+ 'ko_KR' => 'ko',
519
+ 'ckb' => 'ku',
520
+ 'lo' => 'lo',
521
+ 'lt_LT' => 'lt',
522
+ 'lv' => 'lv',
523
+ 'mk_MK' => 'mk',
524
+ 'ml_IN' => 'ml',
525
+ 'mn' => 'mn',
526
+ 'ms_MY' => 'ms',
527
+ 'my_MM' => 'my',
528
+ 'nb_NO' => 'nb',
529
+ 'ne_NP' => 'ne',
530
+ 'nl_NL' => 'nl',
531
+ 'nl_NL_formal' => 'nl',
532
+ 'nl_BE' => 'nl',
533
+ 'nn_NO' => 'nn',
534
+ 'oci' => 'oc',
535
+ 'pa_IN' => 'pa',
536
+ 'pl_PL' => 'pl',
537
+ 'ps' => 'ps',
538
+ 'pt_BR' => 'pt',
539
+ 'pt_PT_ao90' => 'pt',
540
+ 'pt_PT' => 'pt',
541
+ 'rhg' => 'rhg',
542
+ 'ro_RO' => 'ro',
543
+ 'ru_RU' => 'ru',
544
+ 'sah' => 'sah',
545
+ 'si_LK' => 'si',
546
+ 'sk_SK' => 'sk',
547
+ 'sl_SI' => 'sl',
548
+ 'sq' => 'sq',
549
+ 'sr_RS' => 'sr',
550
+ 'sv_SE' => 'sv',
551
+ 'szl' => 'szl',
552
+ 'ta_IN' => 'ta',
553
+ 'te' => 'te',
554
+ 'th' => 'th',
555
+ 'tl' => 'tl',
556
+ 'tr_TR' => 'tr',
557
+ 'tt_RU' => 'tt',
558
+ 'tah' => 'ty',
559
+ 'ug_CN' => 'ug',
560
+ 'uk' => 'uk',
561
+ 'ur' => 'ur',
562
+ 'uz_UZ' => 'uz',
563
+ 'vi' => 'vi',
564
+ 'zh_CN' => 'zh',
565
+ 'zh_TW' => 'zh',
566
+ 'zh_HK' => 'zh',
567
+ );
568
+
569
+ if ( isset( $select2_lang[ $wp_lang ] ) && file_exists( AST_TARGET_RULE_DIR . 'i18n/' . $select2_lang[ $wp_lang ] . '.js' ) ) {
570
+ $ast_lang = $select2_lang[ $wp_lang ];
571
+ wp_enqueue_script(
572
+ 'astra-select2-lang',
573
+ AST_TARGET_RULE_URI . 'i18n/' . $select2_lang[ $wp_lang ] . '.js',
574
+ array(
575
+ 'jquery',
576
+ 'astra-select2',
577
+ ),
578
+ AST_TARGET_RULE_VER,
579
+ true
580
+ );
581
+ }
582
+ }
583
+
584
+ wp_register_script(
585
+ 'astra-target-rule',
586
+ AST_TARGET_RULE_URI . 'target-rule.js',
587
+ array(
588
+ 'jquery',
589
+ 'astra-select2',
590
+ ),
591
+ AST_TARGET_RULE_VER,
592
+ true
593
+ );
594
+
595
+ wp_enqueue_script( 'astra-target-rule' );
596
+
597
+ wp_register_script(
598
+ 'astra-user-role',
599
+ AST_TARGET_RULE_URI . 'user-role.js',
600
+ array(
601
+ 'jquery',
602
+ ),
603
+ AST_TARGET_RULE_VER,
604
+ true
605
+ );
606
+
607
+ wp_enqueue_script( 'astra-user-role' );
608
+
609
+ wp_register_style( 'astra-select2', AST_TARGET_RULE_URI . 'select2.css', '', AST_TARGET_RULE_VER );
610
+ wp_enqueue_style( 'astra-select2' );
611
+ wp_register_style( 'astra-target-rule', AST_TARGET_RULE_URI . 'target-rule.css', '', AST_TARGET_RULE_VER );
612
+ wp_enqueue_style( 'astra-target-rule' );
613
+
614
+ /**
615
+ * Registered localize vars
616
+ */
617
+ $localize_vars = array(
618
+ 'ast_lang' => $ast_lang,
619
+ 'please_enter' => __( 'Please enter', 'header-footer-elementor' ),
620
+ 'please_delete' => __( 'Please delete', 'header-footer-elementor' ),
621
+ 'more_char' => __( 'or more characters', 'header-footer-elementor' ),
622
+ 'character' => __( 'character', 'header-footer-elementor' ),
623
+ 'loading' => __( 'Loading more results…', 'header-footer-elementor' ),
624
+ 'only_select' => __( 'You can only select', 'header-footer-elementor' ),
625
+ 'item' => __( 'item', 'header-footer-elementor' ),
626
+ 'char_s' => __( 's', 'header-footer-elementor' ),
627
+ 'no_result' => __( 'No results found', 'header-footer-elementor' ),
628
+ 'searching' => __( 'Searching…', 'header-footer-elementor' ),
629
+ 'not_loader' => __( 'The results could not be loaded.', 'header-footer-elementor' ),
630
+ 'search' => __( 'Search pages / post / categories', 'header-footer-elementor' ),
631
+ );
632
+ wp_localize_script( 'astra-select2', 'astRules', $localize_vars );
633
+ }
634
+
635
+ /**
636
+ * Function Name: target_rule_settings_field.
637
+ * Function Description: Function to handle new input type.
638
+ *
639
+ * @param string $name string parameter.
640
+ * @param string $settings string parameter.
641
+ * @param string $value string parameter.
642
+ */
643
+ public static function target_rule_settings_field( $name, $settings, $value ) {
644
+ $input_name = $name;
645
+ $type = isset( $settings['type'] ) ? $settings['type'] : 'target_rule';
646
+ $class = isset( $settings['class'] ) ? $settings['class'] : '';
647
+ $rule_type = isset( $settings['rule_type'] ) ? $settings['rule_type'] : 'target_rule';
648
+ $add_rule_label = isset( $settings['add_rule_label'] ) ? $settings['add_rule_label'] : __( 'Add Rule', 'header-footer-elementor' );
649
+ $saved_values = $value;
650
+ $output = '';
651
+
652
+ if ( isset( self::$location_selection ) || empty( self::$location_selection ) ) {
653
+ self::$location_selection = self::get_location_selections();
654
+ }
655
+ $selection_options = self::$location_selection;
656
+
657
+ /* WP Template Format */
658
+ $output .= '<script type="text/html" id="tmpl-astra-target-rule-' . $rule_type . '-condition">';
659
+ $output .= '<div class="astra-target-rule-condition ast-target-rule-{{data.id}}" data-rule="{{data.id}}" >';
660
+ $output .= '<span class="target_rule-condition-delete dashicons dashicons-dismiss"></span>';
661
+ /* Condition Selection */
662
+ $output .= '<div class="target_rule-condition-wrap" >';
663
+ $output .= '<select name="' . esc_attr( $input_name ) . '[rule][{{data.id}}]" class="target_rule-condition form-control ast-input">';
664
+ $output .= '<option value="">' . __( 'Select', 'header-footer-elementor' ) . '</option>';
665
+
666
+ foreach ( $selection_options as $group => $group_data ) {
667
+ $output .= '<optgroup label="' . $group_data['label'] . '">';
668
+ foreach ( $group_data['value'] as $opt_key => $opt_value ) {
669
+ $output .= '<option value="' . $opt_key . '">' . $opt_value . '</option>';
670
+ }
671
+ $output .= '</optgroup>';
672
+ }
673
+ $output .= '</select>';
674
+ $output .= '</div>';
675
+
676
+ $output .= '</div> <!-- astra-target-rule-condition -->';
677
+
678
+ /* Specific page selection */
679
+ $output .= '<div class="target_rule-specific-page-wrap" style="display:none">';
680
+ $output .= '<select name="' . esc_attr( $input_name ) . '[specific][]" class="target-rule-select2 target_rule-specific-page form-control ast-input " multiple="multiple">';
681
+ $output .= '</select>';
682
+ $output .= '</div>';
683
+
684
+ $output .= '</script>';
685
+
686
+ /* Wrapper Start */
687
+ $output .= '<div class="ast-target-rule-wrapper ast-target-rule-' . $rule_type . '-on-wrap" data-type="' . $rule_type . '">';
688
+ // $output .= '<input type="hidden" class="form-control ast-input ast-target_rule-input" name="' . esc_attr( $input_name ) . '" value=' . $value . ' />';
689
+ $output .= '<div class="ast-target-rule-selector-wrapper ast-target-rule-' . $rule_type . '-on">';
690
+ $output .= self::generate_target_rule_selector( $rule_type, $selection_options, $input_name, $saved_values, $add_rule_label );
691
+ $output .= '</div>';
692
+
693
+ /* Wrapper end */
694
+ $output .= '</div>';
695
+
696
+ echo $output;
697
+ }
698
+
699
+ /**
700
+ * Get target rules for generating the markup for rule selector.
701
+ *
702
+ * @since 1.0.0
703
+ *
704
+ * @param object $post_type post type parameter.
705
+ * @param object $taxonomy taxonomy for creating the target rule markup.
706
+ */
707
+ public static function get_post_target_rule_options( $post_type, $taxonomy ) {
708
+ $post_key = str_replace( ' ', '-', strtolower( $post_type->label ) );
709
+ $post_label = ucwords( $post_type->label );
710
+ $post_name = $post_type->name;
711
+ $post_option = array();
712
+
713
+ /* translators: %s post label */
714
+ $all_posts = sprintf( __( 'All %s', 'header-footer-elementor' ), $post_label );
715
+ $post_option[ $post_name . '|all' ] = $all_posts;
716
+
717
+ if ( 'pages' != $post_key ) {
718
+ /* translators: %s post label */
719
+ $all_archive = sprintf( __( 'All %s Archive', 'header-footer-elementor' ), $post_label );
720
+ $post_option[ $post_name . '|all|archive' ] = $all_archive;
721
+ }
722
+
723
+ if ( in_array( $post_type->name, $taxonomy->object_type ) ) {
724
+ $tax_label = ucwords( $taxonomy->label );
725
+ $tax_name = $taxonomy->name;
726
+
727
+ /* translators: %s taxonomy label */
728
+ $tax_archive = sprintf( __( 'All %s Archive', 'header-footer-elementor' ), $tax_label );
729
+
730
+ $post_option[ $post_name . '|all|taxarchive|' . $tax_name ] = $tax_archive;
731
+ }
732
+
733
+ $post_output['post_key'] = $post_key;
734
+ $post_output['label'] = $post_label;
735
+ $post_output['value'] = $post_option;
736
+
737
+ return $post_output;
738
+ }
739
+
740
+ /**
741
+ * Generate markup for rendering the location selction.
742
+ *
743
+ * @since 1.0.0
744
+ * @param String $type Rule type display|exclude.
745
+ * @param Array $selection_options Array for available selection fields.
746
+ * @param String $input_name Input name for the settings.
747
+ * @param Array $saved_values Array of saved valued.
748
+ * @param String $add_rule_label Label for the Add rule button.
749
+ *
750
+ * @return HTML Markup for for the location settings.
751
+ */
752
+ public static function generate_target_rule_selector( $type, $selection_options, $input_name, $saved_values, $add_rule_label ) {
753
+ $output = '<div class="target_rule-builder-wrap">';
754
+
755
+ if ( ! is_array( $saved_values ) || ( is_array( $saved_values ) && empty( $saved_values ) ) ) {
756
+ $saved_values = array();
757
+ $saved_values['rule'][0] = '';
758
+ $saved_values['specific'][0] = '';
759
+ }
760
+
761
+ $index = 0;
762
+
763
+ foreach ( $saved_values['rule'] as $index => $data ) {
764
+ $output .= '<div class="astra-target-rule-condition ast-target-rule-' . $index . '" data-rule="' . $index . '" >';
765
+ /* Condition Selection */
766
+ $output .= '<span class="target_rule-condition-delete dashicons dashicons-dismiss"></span>';
767
+ $output .= '<div class="target_rule-condition-wrap" >';
768
+ $output .= '<select name="' . esc_attr( $input_name ) . '[rule][' . $index . ']" class="target_rule-condition form-control ast-input">';
769
+ $output .= '<option value="">' . __( 'Select', 'header-footer-elementor' ) . '</option>';
770
+
771
+ foreach ( $selection_options as $group => $group_data ) {
772
+ $output .= '<optgroup label="' . $group_data['label'] . '">';
773
+ foreach ( $group_data['value'] as $opt_key => $opt_value ) {
774
+
775
+ // specific rules.
776
+ $selected = '';
777
+
778
+ if ( $data == $opt_key ) {
779
+ $selected = 'selected="selected"';
780
+ }
781
+
782
+ $output .= '<option value="' . $opt_key . '" ' . $selected . '>' . $opt_value . '</option>';
783
+ }
784
+ $output .= '</optgroup>';
785
+ }
786
+ $output .= '</select>';
787
+ $output .= '</div>';
788
+
789
+ $output .= '</div>';
790
+
791
+ /* Specific page selection */
792
+ $output .= '<div class="target_rule-specific-page-wrap" style="display:none">';
793
+ $output .= '<select name="' . esc_attr( $input_name ) . '[specific][]" class="target-rule-select2 target_rule-specific-page form-control ast-input " multiple="multiple">';
794
+
795
+ if ( 'specifics' == $data && isset( $saved_values['specific'] ) && null != $saved_values['specific'] && is_array( $saved_values['specific'] ) ) {
796
+ foreach ( $saved_values['specific'] as $data_key => $sel_value ) {
797
+ // posts.
798
+ if ( strpos( $sel_value, 'post-' ) !== false ) {
799
+ $post_id = (int) str_replace( 'post-', '', $sel_value );
800
+ $post_title = get_the_title( $post_id );
801
+ $output .= '<option value="post-' . $post_id . '" selected="selected" >' . $post_title . '</option>';
802
+ }
803
+
804
+ // taxonomy options.
805
+ if ( strpos( $sel_value, 'tax-' ) !== false ) {
806
+ $tax_data = explode( '-', $sel_value );
807
+
808
+ $tax_id = (int) str_replace( 'tax-', '', $sel_value );
809
+ $term = get_term( $tax_id );
810
+ $term_name = '';
811
+
812
+ if ( ! is_wp_error( $term ) ) {
813
+ $term_taxonomy = ucfirst( str_replace( '_', ' ', $term->taxonomy ) );
814
+
815
+ if ( isset( $tax_data[2] ) && 'single' === $tax_data[2] ) {
816
+ $term_name = 'All singulars from ' . $term->name;
817
+ } else {
818
+ $term_name = $term->name . ' - ' . $term_taxonomy;
819
+ }
820
+ }
821
+
822
+ $output .= '<option value="' . $sel_value . '" selected="selected" >' . $term_name . '</option>';
823
+ }
824
+ }
825
+ }
826
+ $output .= '</select>';
827
+ $output .= '</div>';
828
+ }
829
+
830
+ $output .= '</div>';
831
+
832
+ /* Add new rule */
833
+ $output .= '<div class="target_rule-add-rule-wrap">';
834
+ $output .= '<a href="#" class="button" data-rule-id="' . absint( $index ) . '" data-rule-type="' . $type . '">' . $add_rule_label . '</a>';
835
+ $output .= '</div>';
836
+
837
+ if ( 'display' == $type ) {
838
+ /* Add new rule */
839
+ $output .= '<div class="target_rule-add-exclusion-rule">';
840
+ $output .= '<a href="#" class="button">' . __( 'Add Exclusion Rule', 'header-footer-elementor' ) . '</a>';
841
+ $output .= '</div>';
842
+ }
843
+
844
+ return $output;
845
+ }
846
+
847
+ /**
848
+ * Get current layout.
849
+ * Checks of the passed post id of the layout is to be displayed in the page.
850
+ *
851
+ * @param int $layout_id Layout ID.
852
+ * @param string $option Option prefix.
853
+ *
854
+ * @return int|boolean If the current layout is to be displayed it will be returned back else a boolean will be passed.
855
+ */
856
+ public function get_current_layout( $layout_id, $option ) {
857
+ $post_id = ( ! is_404() && ! is_search() && ! is_archive() && ! is_home() ) ? get_the_id() : false;
858
+ $current_layout = false;
859
+ $is_exclude = false;
860
+ $is_user_role = false;
861
+ $display_on = get_post_meta( $layout_id, $option . '-location', true );
862
+ $exclude_on = get_post_meta( $layout_id, $option . '-exclusion', true );
863
+ $user_roles = get_post_meta( $layout_id, $option . '-users', true );
864
+
865
+ /* Parse Display On Condition */
866
+ $is_display = $this->parse_layout_display_condition( $post_id, $display_on );
867
+
868
+ if ( true == $is_display ) {
869
+ /* Parse Exclude On Condition */
870
+ $is_exclude = $this->parse_layout_display_condition( $post_id, $exclude_on );
871
+ /* Parse User Role Condition */
872
+ $is_user_role = $this->parse_user_role_condition( $post_id, $user_roles );
873
+ }
874
+
875
+ if ( $is_display && ! $is_exclude && $is_user_role ) {
876
+ $current_layout = $layout_id;
877
+ }
878
+
879
+ // filter target page settings.
880
+ $current_layout = apply_filters( 'astra_target_page_settings', $current_layout, $layout_id );
881
+
882
+ return $current_layout;
883
+ }
884
+
885
+ /**
886
+ * Checks for the display condition for the current page/
887
+ *
888
+ * @param int $post_id Current post ID.
889
+ * @param array $rules Array of rules Display on | Exclude on.
890
+ *
891
+ * @return boolean Returns true or false depending on if the $rules match for the current page and the layout is to be displayed.
892
+ */
893
+ public function parse_layout_display_condition( $post_id, $rules ) {
894
+ $display = false;
895
+ $current_post_type = get_post_type( $post_id );
896
+
897
+ if ( isset( $rules['rule'] ) && is_array( $rules['rule'] ) && ! empty( $rules['rule'] ) ) {
898
+ foreach ( $rules['rule'] as $key => $rule ) {
899
+ if ( strrpos( $rule, 'all' ) !== false ) {
900
+ $rule_case = 'all';
901
+ } else {
902
+ $rule_case = $rule;
903
+ }
904
+
905
+ switch ( $rule_case ) {
906
+ case 'basic-global':
907
+ $display = true;
908
+ break;
909
+
910
+ case 'basic-singulars':
911
+ if ( is_singular() ) {
912
+ $display = true;
913
+ }
914
+ break;
915
+
916
+ case 'basic-archives':
917
+ if ( is_archive() ) {
918
+ $display = true;
919
+ }
920
+ break;
921
+
922
+ case 'special-404':
923
+ if ( is_404() ) {
924
+ $display = true;
925
+ }
926
+ break;
927
+
928
+ case 'special-search':
929
+ if ( is_search() ) {
930
+ $display = true;
931
+ }
932
+ break;
933
+
934
+ case 'special-blog':
935
+ if ( is_home() ) {
936
+ $display = true;
937
+ }
938
+ break;
939
+
940
+ case 'special-front':
941
+ if ( is_front_page() ) {
942
+ $display = true;
943
+ }
944
+ break;
945
+
946
+ case 'special-date':
947
+ if ( is_date() ) {
948
+ $display = true;
949
+ }
950
+ break;
951
+
952
+ case 'special-author':
953
+ if ( is_author() ) {
954
+ $display = true;
955
+ }
956
+ break;
957
+
958
+ case 'special-woo-shop':
959
+ if ( function_exists( 'is_shop' ) && is_shop() ) {
960
+ $display = true;
961
+ }
962
+ break;
963
+
964
+ case 'all':
965
+ $rule_data = explode( '|', $rule );
966
+
967
+ $post_type = isset( $rule_data[0] ) ? $rule_data[0] : false;
968
+ $archieve_type = isset( $rule_data[2] ) ? $rule_data[2] : false;
969
+ $taxonomy = isset( $rule_data[3] ) ? $rule_data[3] : false;
970
+ if ( false === $archieve_type ) {
971
+ $current_post_type = get_post_type( $post_id );
972
+
973
+ if ( false !== $post_id && $current_post_type == $post_type ) {
974
+ $display = true;
975
+ }
976
+ } else {
977
+ if ( is_archive() ) {
978
+ $current_post_type = get_post_type();
979
+ if ( $current_post_type == $post_type ) {
980
+ if ( 'archive' == $archieve_type ) {
981
+ $display = true;
982
+ } elseif ( 'taxarchive' == $archieve_type ) {
983
+ $obj = get_queried_object();
984
+ $current_taxonomy = '';
985
+ if ( '' !== $obj && null !== $obj ) {
986
+ $current_taxonomy = $obj->taxonomy;
987
+ }
988
+
989
+ if ( $current_taxonomy == $taxonomy ) {
990
+ $display = true;
991
+ }
992
+ }
993
+ }
994
+ }
995
+ }
996
+ break;
997
+
998
+ case 'specifics':
999
+ if ( isset( $rules['specific'] ) && is_array( $rules['specific'] ) ) {
1000
+ foreach ( $rules['specific'] as $specific_page ) {
1001
+ $specific_data = explode( '-', $specific_page );
1002
+
1003
+ $specific_post_type = isset( $specific_data[0] ) ? $specific_data[0] : false;
1004
+ $specific_post_id = isset( $specific_data[1] ) ? $specific_data[1] : false;
1005
+ if ( 'post' == $specific_post_type ) {
1006
+ if ( $specific_post_id == $post_id ) {
1007
+ $display = true;
1008
+ }
1009
+ } elseif ( isset( $specific_data[2] ) && ( 'single' == $specific_data[2] ) && 'tax' == $specific_post_type ) {
1010
+ if ( is_singular() ) {
1011
+ $term_details = get_term( $specific_post_id );
1012
+
1013
+ if ( isset( $term_details->taxonomy ) ) {
1014
+ $has_term = has_term( (int) $specific_post_id, $term_details->taxonomy, $post_id );
1015
+
1016
+ if ( $has_term ) {
1017
+ $display = true;
1018
+ }
1019
+ }
1020
+ }
1021
+ } elseif ( 'tax' == $specific_post_type ) {
1022
+ $tax_id = get_queried_object_id();
1023
+ if ( $specific_post_id == $tax_id ) {
1024
+ $display = true;
1025
+ }
1026
+ }
1027
+ }
1028
+ }
1029
+ break;
1030
+
1031
+ default:
1032
+ break;
1033
+ }
1034
+
1035
+ if ( $display ) {
1036
+ break;
1037
+ }
1038
+ }
1039
+ }
1040
+
1041
+ return $display;
1042
+ }
1043
+
1044
+ /**
1045
+ * Function Name: target_user_role_settings_field.
1046
+ * Function Description: Function to handle new input type.
1047
+ *
1048
+ * @param string $name string parameter.
1049
+ * @param string $settings string parameter.
1050
+ * @param string $value string parameter.
1051
+ */
1052
+ public static function target_user_role_settings_field( $name, $settings, $value ) {
1053
+ $input_name = $name;
1054
+ $type = isset( $settings['type'] ) ? $settings['type'] : 'target_rule';
1055
+ $class = isset( $settings['class'] ) ? $settings['class'] : '';
1056
+ $rule_type = isset( $settings['rule_type'] ) ? $settings['rule_type'] : 'target_rule';
1057
+ $add_rule_label = isset( $settings['add_rule_label'] ) ? $settings['add_rule_label'] : __( 'Add Rule', 'header-footer-elementor' );
1058
+ $saved_values = $value;
1059
+ $output = '';
1060
+
1061
+ if ( ! isset( self::$user_selection ) || empty( self::$user_selection ) ) {
1062
+ self::$user_selection = self::get_user_selections();
1063
+ }
1064
+ $selection_options = self::$user_selection;
1065
+
1066
+ /* WP Template Format */
1067
+ $output .= '<script type="text/html" id="tmpl-astra-user-role-condition">';
1068
+ $output .= '<div class="astra-user-role-condition ast-user-role-{{data.id}}" data-rule="{{data.id}}" >';
1069
+ $output .= '<span class="user_role-condition-delete dashicons dashicons-dismiss"></span>';
1070
+ /* Condition Selection */
1071
+ $output .= '<div class="user_role-condition-wrap" >';
1072
+ $output .= '<select name="' . esc_attr( $input_name ) . '[{{data.id}}]" class="user_role-condition form-control ast-input">';
1073
+ $output .= '<option value="">' . __( 'Select', 'header-footer-elementor' ) . '</option>';
1074
+
1075
+ foreach ( $selection_options as $group => $group_data ) {
1076
+ $output .= '<optgroup label="' . $group_data['label'] . '">';
1077
+ foreach ( $group_data['value'] as $opt_key => $opt_value ) {
1078
+ $output .= '<option value="' . $opt_key . '">' . $opt_value . '</option>';
1079
+ }
1080
+ $output .= '</optgroup>';
1081
+ }
1082
+ $output .= '</select>';
1083
+ $output .= '</div>';
1084
+ $output .= '</div> <!-- astra-user-role-condition -->';
1085
+ $output .= '</script>';
1086
+
1087
+ if ( ! is_array( $saved_values ) || ( is_array( $saved_values ) && empty( $saved_values ) ) ) {
1088
+ $saved_values = array();
1089
+ $saved_values[0] = '';
1090
+ }
1091
+
1092
+ $index = 0;
1093
+
1094
+ $output .= '<div class="ast-user-role-wrapper ast-user-role-display-on-wrap" data-type="display">';
1095
+ $output .= '<div class="ast-user-role-selector-wrapper ast-user-role-display-on">';
1096
+ $output .= '<div class="user_role-builder-wrap">';
1097
+ foreach ( $saved_values as $index => $data ) {
1098
+ $output .= '<div class="astra-user-role-condition ast-user-role-' . $index . '" data-rule="' . $index . '" >';
1099
+ $output .= '<span class="user_role-condition-delete dashicons dashicons-dismiss"></span>';
1100
+ /* Condition Selection */
1101
+ $output .= '<div class="user_role-condition-wrap" >';
1102
+ $output .= '<select name="' . esc_attr( $input_name ) . '[' . $index . ']" class="user_role-condition form-control ast-input">';
1103
+ $output .= '<option value="">' . __( 'Select', 'header-footer-elementor' ) . '</option>';
1104
+
1105
+ foreach ( $selection_options as $group => $group_data ) {
1106
+ $output .= '<optgroup label="' . $group_data['label'] . '">';
1107
+ foreach ( $group_data['value'] as $opt_key => $opt_value ) {
1108
+ $output .= '<option value="' . $opt_key . '" ' . selected( $data, $opt_key, false ) . '>' . $opt_value . '</option>';
1109
+ }
1110
+ $output .= '</optgroup>';
1111
+ }
1112
+ $output .= '</select>';
1113
+ $output .= '</div>';
1114
+ $output .= '</div> <!-- astra-user-role-condition -->';
1115
+ }
1116
+ $output .= '</div>';
1117
+ /* Add new rule */
1118
+ $output .= '<div class="user_role-add-rule-wrap">';
1119
+ $output .= '<a href="#" class="button" data-rule-id="' . absint( $index ) . '">' . $add_rule_label . '</a>';
1120
+ $output .= '</div>';
1121
+ $output .= '</div>';
1122
+ $output .= '</div>';
1123
+
1124
+ echo $output;
1125
+ }
1126
+
1127
+ /**
1128
+ * Parse user role condition.
1129
+ *
1130
+ * @since 1.0.0
1131
+ * @param int $post_id Post ID.
1132
+ * @param Array $rules Current user rules.
1133
+ *
1134
+ * @return boolean True = user condition passes. False = User condition does not pass.
1135
+ */
1136
+ public function parse_user_role_condition( $post_id, $rules ) {
1137
+ $show_popup = true;
1138
+
1139
+ if ( is_array( $rules ) && ! empty( $rules ) ) {
1140
+ $show_popup = false;
1141
+
1142
+ foreach ( $rules as $i => $rule ) {
1143
+ switch ( $rule ) {
1144
+ case '':
1145
+ case 'all':
1146
+ $show_popup = true;
1147
+ break;
1148
+
1149
+ case 'logged-in':
1150
+ if ( is_user_logged_in() ) {
1151
+ $show_popup = true;
1152
+ }
1153
+ break;
1154
+
1155
+ case 'logged-out':
1156
+ if ( ! is_user_logged_in() ) {
1157
+ $show_popup = true;
1158
+ }
1159
+ break;
1160
+
1161
+ default:
1162
+ if ( is_user_logged_in() ) {
1163
+ $current_user = wp_get_current_user();
1164
+
1165
+ if ( isset( $current_user->roles )
1166
+ && is_array( $current_user->roles )
1167
+ && in_array( $rule, $current_user->roles )
1168
+ ) {
1169
+ $show_popup = true;
1170
+ }
1171
+ }
1172
+ break;
1173
+ }
1174
+
1175
+ if ( $show_popup ) {
1176
+ break;
1177
+ }
1178
+ }
1179
+ }
1180
+
1181
+ return $show_popup;
1182
+ }
1183
+
1184
+ /**
1185
+ * Get current page type
1186
+ *
1187
+ * @since 1.0.0
1188
+ *
1189
+ * @return string Page Type.
1190
+ */
1191
+ public function get_current_page_type() {
1192
+ if ( null === self::$current_page_type ) {
1193
+ $page_type = '';
1194
+ $current_id = false;
1195
+
1196
+ if ( is_404() ) {
1197
+ $page_type = 'is_404';
1198
+ } elseif ( is_search() ) {
1199
+ $page_type = 'is_search';
1200
+ } elseif ( is_archive() ) {
1201
+ $page_type = 'is_archive';
1202
+
1203
+ if ( is_category() || is_tag() || is_tax() ) {
1204
+ $page_type = 'is_tax';
1205
+ } elseif ( is_date() ) {
1206
+ $page_type = 'is_date';
1207
+ } elseif ( is_author() ) {
1208
+ $page_type = 'is_author';
1209
+ } elseif ( function_exists( 'is_shop' ) && is_shop() ) {
1210
+ $page_type = 'is_woo_shop_page';
1211
+ }
1212
+ } elseif ( is_home() ) {
1213
+ $page_type = 'is_home';
1214
+ } elseif ( is_front_page() ) {
1215
+ $page_type = 'is_front_page';
1216
+ $current_id = get_the_id();
1217
+ } elseif ( is_singular() ) {
1218
+ $page_type = 'is_singular';
1219
+ $current_id = get_the_id();
1220
+ } else {
1221
+ $current_id = get_the_id();
1222
+ }
1223
+
1224
+ self::$current_page_data['ID'] = $current_id;
1225
+ self::$current_page_type = $page_type;
1226
+ }
1227
+
1228
+ return self::$current_page_type;
1229
+ }
1230
+
1231
+ /**
1232
+ * Get posts by conditions
1233
+ *
1234
+ * @since 1.0.0
1235
+ * @param string $post_type Post Type.
1236
+ * @param array $option meta option name.
1237
+ *
1238
+ * @return object Posts.
1239
+ */
1240
+ public function get_posts_by_conditions( $post_type, $option ) {
1241
+ global $wpdb;
1242
+ global $post;
1243
+
1244
+ $post_type = $post_type ? esc_sql( $post_type ) : esc_sql( $post->post_type );
1245
+
1246
+ if ( is_array( self::$current_page_data ) && isset( self::$current_page_data[ $post_type ] ) ) {
1247
+ return apply_filters( 'astra_get_display_posts_by_conditions', self::$current_page_data[ $post_type ], $post_type );
1248
+ }
1249
+
1250
+ $current_page_type = $this->get_current_page_type();
1251
+
1252
+ self::$current_page_data[ $post_type ] = array();
1253
+
1254
+ $option['current_post_id'] = self::$current_page_data['ID'];
1255
+ $meta_header = self::get_meta_option_post( $post_type, $option );
1256
+
1257
+ /* Meta option is enabled */
1258
+ if ( false === $meta_header ) {
1259
+ $current_post_type = esc_sql( get_post_type() );
1260
+ $current_post_id = false;
1261
+ $q_obj = get_queried_object();
1262
+
1263
+ $location = isset( $option['location'] ) ? esc_sql( $option['location'] ) : '';
1264
+
1265
+ $query = "SELECT p.ID, pm.meta_value FROM {$wpdb->postmeta} as pm
1266
+ INNER JOIN {$wpdb->posts} as p ON pm.post_id = p.ID
1267
+ WHERE pm.meta_key = '{$location}'
1268
+ AND p.post_type = '{$post_type}'
1269
+ AND p.post_status = 'publish'";
1270
+
1271
+ $orderby = ' ORDER BY p.post_date DESC';
1272
+
1273
+ /* Entire Website */
1274
+ $meta_args = "pm.meta_value LIKE '%\"basic-global\"%'";
1275
+
1276
+ switch ( $current_page_type ) {
1277
+ case 'is_404':
1278
+ $meta_args .= " OR pm.meta_value LIKE '%\"special-404\"%'";
1279
+ break;
1280
+ case 'is_search':
1281
+ $meta_args .= " OR pm.meta_value LIKE '%\"special-search\"%'";
1282
+ break;
1283
+ case 'is_archive':
1284
+ case 'is_tax':
1285
+ case 'is_date':
1286
+ case 'is_author':
1287
+ $meta_args .= " OR pm.meta_value LIKE '%\"basic-archives\"%'";
1288
+ $meta_args .= " OR pm.meta_value LIKE '%\"{$current_post_type}|all|archive\"%'";
1289
+
1290
+ if ( 'is_tax' == $current_page_type && ( is_category() || is_tag() || is_tax() ) ) {
1291
+ if ( is_object( $q_obj ) ) {
1292
+ $meta_args .= " OR pm.meta_value LIKE '%\"{$current_post_type}|all|taxarchive|{$q_obj->taxonomy}\"%'";
1293
+ $meta_args .= " OR pm.meta_value LIKE '%\"tax-{$q_obj->term_id}\"%'";
1294
+ }
1295
+ } elseif ( 'is_date' == $current_page_type ) {
1296
+ $meta_args .= " OR pm.meta_value LIKE '%\"special-date\"%'";
1297
+ } elseif ( 'is_author' == $current_page_type ) {
1298
+ $meta_args .= " OR pm.meta_value LIKE '%\"special-author\"%'";
1299
+ }
1300
+ break;
1301
+ case 'is_home':
1302
+ $meta_args .= " OR pm.meta_value LIKE '%\"special-blog\"%'";
1303
+ break;
1304
+ case 'is_front_page':
1305
+ $current_id = esc_sql( get_the_id() );
1306
+ $current_post_id = $current_id;
1307
+ $meta_args .= " OR pm.meta_value LIKE '%\"special-front\"%'";
1308
+ $meta_args .= " OR pm.meta_value LIKE '%\"{$current_post_type}|all\"%'";
1309
+ $meta_args .= " OR pm.meta_value LIKE '%\"post-{$current_id}\"%'";
1310
+ break;
1311
+ case 'is_singular':
1312
+ $current_id = esc_sql( get_the_id() );
1313
+ $current_post_id = $current_id;
1314
+ $meta_args .= " OR pm.meta_value LIKE '%\"basic-singulars\"%'";
1315
+ $meta_args .= " OR pm.meta_value LIKE '%\"{$current_post_type}|all\"%'";
1316
+ $meta_args .= " OR pm.meta_value LIKE '%\"post-{$current_id}\"%'";
1317
+
1318
+ $taxonomies = get_object_taxonomies( $q_obj->post_type );
1319
+ $terms = wp_get_post_terms( $q_obj->ID, $taxonomies );
1320
+
1321
+ foreach ( $terms as $key => $term ) {
1322
+ $meta_args .= " OR pm.meta_value LIKE '%\"tax-{$term->term_id}-single-{$term->taxonomy}\"%'";
1323
+ }
1324
+
1325
+ break;
1326
+ case 'is_woo_shop_page':
1327
+ $meta_args .= " OR pm.meta_value LIKE '%\"special-woo-shop\"%'";
1328
+ break;
1329
+ case '':
1330
+ $current_post_id = get_the_id();
1331
+ break;
1332
+ }
1333
+
1334
+ // Ignore the PHPCS warning about constant declaration.
1335
+ // @codingStandardsIgnoreStart
1336
+ $posts = $wpdb->get_results( $query . ' AND (' . $meta_args . ')' . $orderby );
1337
+ // @codingStandardsIgnoreEnd
1338
+
1339
+ foreach ( $posts as $local_post ) {
1340
+ self::$current_page_data[ $post_type ][ $local_post->ID ] = array(
1341
+ 'id' => $local_post->ID,
1342
+ 'location' => unserialize( $local_post->meta_value ),
1343
+ );
1344
+ }
1345
+
1346
+ $option['current_post_id'] = $current_post_id;
1347
+
1348
+ $this->remove_exclusion_rule_posts( $post_type, $option );
1349
+ $this->remove_user_rule_posts( $post_type, $option );
1350
+ }
1351
+
1352
+ return apply_filters( 'astra_get_display_posts_by_conditions', self::$current_page_data[ $post_type ], $post_type );
1353
+ }
1354
+
1355
+ /**
1356
+ * Remove exclusion rule posts.
1357
+ *
1358
+ * @since 1.0.0
1359
+ * @param string $post_type Post Type.
1360
+ * @param array $option meta option name.
1361
+ */
1362
+ public function remove_exclusion_rule_posts( $post_type, $option ) {
1363
+ $exclusion = isset( $option['exclusion'] ) ? $option['exclusion'] : '';
1364
+ $current_post_id = isset( $option['current_post_id'] ) ? $option['current_post_id'] : false;
1365
+
1366
+ foreach ( self::$current_page_data[ $post_type ] as $c_post_id => $c_data ) {
1367
+ $exclusion_rules = get_post_meta( $c_post_id, $exclusion, true );
1368
+ $is_exclude = $this->parse_layout_display_condition( $current_post_id, $exclusion_rules );
1369
+
1370
+ if ( $is_exclude ) {
1371
+ unset( self::$current_page_data[ $post_type ][ $c_post_id ] );
1372
+ }
1373
+ }
1374
+ }
1375
+
1376
+ /**
1377
+ * Remove user rule posts.
1378
+ *
1379
+ * @since 1.0.0
1380
+ * @param int $post_type Post Type.
1381
+ * @param array $option meta option name.
1382
+ */
1383
+ public function remove_user_rule_posts( $post_type, $option ) {
1384
+ $users = isset( $option['users'] ) ? $option['users'] : '';
1385
+ $current_post_id = isset( $option['current_post_id'] ) ? $option['current_post_id'] : false;
1386
+
1387
+ foreach ( self::$current_page_data[ $post_type ] as $c_post_id => $c_data ) {
1388
+ $user_rules = get_post_meta( $c_post_id, $users, true );
1389
+ $is_user = $this->parse_user_role_condition( $current_post_id, $user_rules );
1390
+
1391
+ if ( ! $is_user ) {
1392
+ unset( self::$current_page_data[ $post_type ][ $c_post_id ] );
1393
+ }
1394
+ }
1395
+ }
1396
+
1397
+ /**
1398
+ * Same display_on notice.
1399
+ *
1400
+ * @since 1.0.0
1401
+ * @param int $post_type Post Type.
1402
+ * @param array $option meta option name.
1403
+ */
1404
+ public static function same_display_on_notice( $post_type, $option ) {
1405
+ global $wpdb;
1406
+ global $post;
1407
+
1408
+ $all_rules = array();
1409
+ $already_set_rule = array();
1410
+
1411
+ $location = isset( $option['location'] ) ? $option['location'] : '';
1412
+
1413
+ $all_headers = $wpdb->get_results(
1414
+ $wpdb->prepare(
1415
+ "SELECT p.ID, p.post_title, pm.meta_value FROM {$wpdb->postmeta} as pm
1416
+ INNER JOIN {$wpdb->posts} as p ON pm.post_id = p.ID
1417
+ WHERE pm.meta_key = %s
1418
+ AND p.post_type = %s
1419
+ AND p.post_status = 'publish'",
1420
+ $location,
1421
+ $post_type
1422
+ )
1423
+ );
1424
+
1425
+ foreach ( $all_headers as $header ) {
1426
+ $location_rules = unserialize( $header->meta_value );
1427
+
1428
+ if ( is_array( $location_rules ) && isset( $location_rules['rule'] ) ) {
1429
+ foreach ( $location_rules['rule'] as $key => $rule ) {
1430
+ if ( ! isset( $all_rules[ $rule ] ) ) {
1431
+ $all_rules[ $rule ] = array();
1432
+ }
1433
+
1434
+ if ( 'specifics' == $rule && isset( $location_rules['specific'] ) && is_array( $location_rules['specific'] ) ) {
1435
+ foreach ( $location_rules['specific'] as $s_index => $s_value ) {
1436
+ $all_rules[ $rule ][ $s_value ][ $header->ID ] = array(
1437
+ 'ID' => $header->ID,
1438
+ 'name' => $header->post_title,
1439
+ );
1440
+ }
1441
+ } else {
1442
+ $all_rules[ $rule ][ $header->ID ] = array(
1443
+ 'ID' => $header->ID,
1444
+ 'name' => $header->post_title,
1445
+ );
1446
+ }
1447
+ }
1448
+ }
1449
+ }
1450
+ if ( empty( $post ) ) {
1451
+ return;
1452
+ }
1453
+ $current_post_data = get_post_meta( $post->ID, $location, true );
1454
+
1455
+ if ( is_array( $current_post_data ) && isset( $current_post_data['rule'] ) ) {
1456
+ foreach ( $current_post_data['rule'] as $c_key => $c_rule ) {
1457
+ if ( ! isset( $all_rules[ $c_rule ] ) ) {
1458
+ continue;
1459
+ }
1460
+
1461
+ if ( 'specifics' === $c_rule ) {
1462
+ foreach ( $current_post_data['specific'] as $s_index => $s_id ) {
1463
+ if ( ! isset( $all_rules[ $c_rule ][ $s_id ] ) ) {
1464
+ continue;
1465
+ }
1466
+
1467
+ foreach ( $all_rules[ $c_rule ][ $s_id ] as $p_id => $data ) {
1468
+ if ( $p_id == $post->ID ) {
1469
+ continue;
1470
+ }
1471
+
1472
+ $already_set_rule[] = $data['name'];
1473
+ }
1474
+ }
1475
+ } else {
1476
+ foreach ( $all_rules[ $c_rule ] as $p_id => $data ) {
1477
+ if ( $p_id == $post->ID ) {
1478
+ continue;
1479
+ }
1480
+
1481
+ $already_set_rule[] = $data['name'];
1482
+ }
1483
+ }
1484
+ }
1485
+ }
1486
+
1487
+ if ( ! empty( $already_set_rule ) ) {
1488
+ add_action(
1489
+ 'admin_notices',
1490
+ function() use ( $already_set_rule ) {
1491
+ $rule_set_titles = '<strong>' . implode( ',', $already_set_rule ) . '</strong>';
1492
+
1493
+ /* translators: %s post title. */
1494
+ $notice = sprintf( __( 'The same display setting is already exist in %s post/s.', 'header-footer-elementor' ), $rule_set_titles );
1495
+
1496
+ echo '<div class="error">';
1497
+ echo '<p>' . $notice . '</p>';
1498
+ echo '</div>';
1499
+ }
1500
+ );
1501
+ }
1502
+ }
1503
+
1504
+ /**
1505
+ * Meta option post.
1506
+ *
1507
+ * @since 1.0.0
1508
+ * @param string $post_type Post Type.
1509
+ * @param array $option meta option name.
1510
+ *
1511
+ * @return false | object
1512
+ */
1513
+ public static function get_meta_option_post( $post_type, $option ) {
1514
+ $page_meta = ( isset( $option['page_meta'] ) && '' != $option['page_meta'] ) ? $option['page_meta'] : false;
1515
+
1516
+ if ( false !== $page_meta ) {
1517
+ $current_post_id = isset( $option['current_post_id'] ) ? $option['current_post_id'] : false;
1518
+ $meta_id = get_post_meta( $current_post_id, $option['page_meta'], true );
1519
+
1520
+ if ( false !== $meta_id && '' != $meta_id ) {
1521
+ self::$current_page_data[ $post_type ][ $meta_id ] = array(
1522
+ 'id' => $meta_id,
1523
+ 'location' => '',
1524
+ );
1525
+
1526
+ return self::$current_page_data[ $post_type ];
1527
+ }
1528
+ }
1529
+
1530
+ return false;
1531
+ }
1532
+
1533
+ /**
1534
+ * Get post selection.
1535
+ *
1536
+ * @since 1.0.0
1537
+ * @param string $post_type Post Type.
1538
+ *
1539
+ * @return object Posts.
1540
+ */
1541
+ public static function get_post_selection( $post_type ) {
1542
+ $query_args = array(
1543
+ 'post_type' => $post_type,
1544
+ 'posts_per_page' => -1,
1545
+ 'post_status' => 'publish',
1546
+ );
1547
+
1548
+ $all_headers = get_posts( $query_args );
1549
+ $headers = array();
1550
+
1551
+ if ( ! empty( $all_headers ) ) {
1552
+ $headers = array(
1553
+ '' => __( 'Select', 'header-footer-elementor' ),
1554
+ );
1555
+
1556
+ foreach ( $all_headers as $i => $data ) {
1557
+ $headers[ $data->ID ] = $data->post_title;
1558
+ }
1559
+ }
1560
+
1561
+ return $headers;
1562
+ }
1563
+
1564
+ /**
1565
+ * Formated rule meta value to save.
1566
+ *
1567
+ * @since 1.0.0
1568
+ * @param array $save_data PostData.
1569
+ * @param string $key varaible key.
1570
+ *
1571
+ * @return array Rule data.
1572
+ */
1573
+ public static function get_format_rule_value( $save_data, $key ) {
1574
+ $meta_value = array();
1575
+
1576
+ if ( isset( $save_data[ $key ]['rule'] ) ) {
1577
+ $save_data[ $key ]['rule'] = array_unique( $save_data[ $key ]['rule'] );
1578
+ if ( isset( $save_data[ $key ]['specific'] ) ) {
1579
+ $save_data[ $key ]['specific'] = array_unique( $save_data[ $key ]['specific'] );
1580
+ }
1581
+
1582
+ // Unset the specifics from rule. This will be readded conditionally in next condition.
1583
+ $index = array_search( '', $save_data[ $key ]['rule'] );
1584
+ if ( false !== $index ) {
1585
+ unset( $save_data[ $key ]['rule'][ $index ] );
1586
+ }
1587
+ $index = array_search( 'specifics', $save_data[ $key ]['rule'] );
1588
+ if ( false !== $index ) {
1589
+ unset( $save_data[ $key ]['rule'][ $index ] );
1590
+
1591
+ // Only re-add the specifics key if there are specific rules added.
1592
+ if ( isset( $save_data[ $key ]['specific'] ) && is_array( $save_data[ $key ]['specific'] ) ) {
1593
+ array_push( $save_data[ $key ]['rule'], 'specifics' );
1594
+ }
1595
+ }
1596
+
1597
+ foreach ( $save_data[ $key ] as $meta_key => $value ) {
1598
+ if ( ! empty( $value ) ) {
1599
+ $meta_value[ $meta_key ] = array_map( 'esc_attr', $value );
1600
+ }
1601
+ }
1602
+ if ( ! isset( $meta_value['rule'] ) || ! in_array( 'specifics', $meta_value['rule'] ) ) {
1603
+ $meta_value['specific'] = array();
1604
+ }
1605
+
1606
+ if ( empty( $meta_value['rule'] ) ) {
1607
+ $meta_value = array();
1608
+ }
1609
+ }
1610
+
1611
+ return $meta_value;
1612
+ }
1613
+ }
1614
+
1615
+ /**
1616
+ * Kicking this off by calling 'get_instance()' method
1617
+ */
1618
+ Astra_Target_Rules_Fields::get_instance();
inc/lib/target-rule/i18n/af.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Verwyders asseblief "+t+" character";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Voer asseblief "+t+" of meer karakters";return n},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var t="Kies asseblief net "+e.maximum+" item";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ar.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(e){var t=e.input.length-e.maximum;return"الرجاء حذف "+t+" عناصر"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"الرجاء إضافة "+t+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(e){return"تستطيع إختيار "+e.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/az.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/az",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return t+" simvol silin"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(e){return"Sadəcə "+e.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/bg.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/bg",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Моля въведете с "+t+" по-малко символ";return t>1&&(n+="a"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Моля въведете още "+t+" символ";return t>1&&(n+="a"),n},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(e){var t="Можете да направите до "+e.maximum+" ";return e.maximum>1?t+="избора":t+="избор",t},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/bs.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/bs",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Obrišite "+n+" simbol";return r+=e(n,"","a","a"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Ukucajte bar još "+n+" simbol";return r+=e(n,"","a","a"),r},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(t){var n="Možete izabrati samo "+t.maximum+" stavk";return n+=e(t.maximum,"u","e","i"),n},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ca.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Si us plau, elimina "+t+" car";return t==1?n+="àcter":n+="àcters",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Si us plau, introdueix "+t+" car";return t==1?n+="àcter":n+="àcters",n},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var t="Només es pot seleccionar "+e.maximum+" element";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/cs.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/cs",[],function(){function e(e,t){switch(e){case 2:return t?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?"Prosím, zadejte o jeden znak méně.":n<=4?"Prosím, zadejte o "+e(n,!0)+" znaky méně.":"Prosím, zadejte o "+n+" znaků méně."},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím, zadejte ještě jeden znak.":n<=4?"Prosím, zadejte ještě další "+e(n,!0)+" znaky.":"Prosím, zadejte ještě dalších "+n+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(t){var n=t.maximum;return n==1?"Můžete zvolit jen jednu položku.":n<=4?"Můžete zvolit maximálně "+e(n,!1)+" položky.":"Můžete zvolit maximálně "+n+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/da.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Angiv venligst "+t+" tegn mindre"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Angiv venligst "+t+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var t="Du kan kun vælge "+e.maximum+" emne";return e.maximum!=1&&(t+="r"),t},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/de.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Bitte "+t+" Zeichen weniger eingeben"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Bitte "+t+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var t="Sie können nur "+e.maximum+" Eintr";return e.maximum===1?t+="ag":t+="äge",t+=" auswählen",t},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/dsb.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/dsb",[],function(){var e=["znamuško","znamušce","znamuška","znamuškow"],t=["zapisk","zapiska","zapiski","zapiskow"],n=function(t,n){if(t===1)return n[0];if(t===2)return n[1];if(t>2&&t<=4)return n[2];if(t>=5)return n[3]};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Pšosym lašuj "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Pšosym zapódaj nanejmjenjej "+r+" "+n(r,e)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(e){return"Móžoš jano "+e.maximum+" "+n(e.maximum,t)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/el.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Παρακαλώ διαγράψτε "+t+" χαρακτήρ";return t==1&&(n+="α"),t!=1&&(n+="ες"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Παρακαλώ συμπληρώστε "+t+" ή περισσότερους χαρακτήρες";return n},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(e){var t="Μπορείτε να επιλέξετε μόνο "+e.maximum+" επιλογ";return e.maximum==1&&(t+="ή"),e.maximum!=1&&(t+="ές"),t},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/en.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Please delete "+t+" character";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Please enter "+t+" or more characters";return n},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var t="You can only select "+e.maximum+" item";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No results found"},searching:function(){return"Searching…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/es.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor, elimine "+t+" car";return t==1?n+="ácter":n+="acteres",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Por favor, introduzca "+t+" car";return t==1?n+="ácter":n+="acteres",n},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var t="Sólo puede seleccionar "+e.maximum+" elemento";return e.maximum!=1&&(t+="s"),t},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/et.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" vähem",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Sisesta "+t+" täht";return t!=1&&(n+="e"),n+=" rohkem",n},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var t="Saad vaid "+e.maximum+" tulemus";return e.maximum==1?t+="e":t+="t",t+=" valida",t},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/eu.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gutxiago",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return t==1?n+="karaktere bat":n+=t+" karaktere",n+=" gehiago",n},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return e.maximum===1?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/fa.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="لطفاً "+t+" کاراکتر را حذف نمایید";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="لطفاً تعداد "+t+" کاراکتر یا بیشتر وارد نمایید";return n},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(e){var t="شما تنها می‌توانید "+e.maximum+" آیتم را انتخاب نمایید";return t},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/fi.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Ole hyvä ja anna "+t+" merkkiä vähemmän"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Ole hyvä ja anna "+t+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(e){return"Voit valita ainoastaan "+e.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/fr.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Supprimez "+t+" caractère"+(t>1)?"s":""},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Saisissez au moins "+t+" caractère"+(t>1)?"s":""},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1)?"s":""},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/gl.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var t=e.input.length-e.maximum;return t===1?"Elimine un carácter":"Elimine "+t+" caracteres"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t===1?"Engada un carácter":"Engada "+t+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return e.maximum===1?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/he.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="נא למחוק ";return t===1?n+="תו אחד":n+=t+" תווים",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="נא להכניס ";return t===1?n+="תו אחד":n+=t+" תווים",n+=" או יותר",n},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(e){var t="באפשרותך לבחור עד ";return e.maximum===1?t+="פריט אחד":t+=e.maximum+" פריטים",t},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/hi.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" अक्षर को हटा दें";return t>1&&(n=t+" अक्षरों को हटा दें "),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="कृपया "+t+" या अधिक अक्षर दर्ज करें";return n},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(e){var t="आप केवल "+e.maximum+" आइटम का चयन कर सकते हैं";return t},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/hr.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hr",[],function(){function e(e){var t=" "+e+" znak";return e%10<5&&e%10>0&&(e%100<5||e%100>19)?e%10>1&&(t+="a"):t+="ova",t}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Unesite "+e(n)},inputTooShort:function(t){var n=t.minimum-t.input.length;return"Unesite još "+e(n)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(e){return"Maksimalan broj odabranih stavki je "+e.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/hsb.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hsb",[],function(){var e=["znamješko","znamješce","znamješka","znamješkow"],t=["zapisk","zapiskaj","zapiski","zapiskow"],n=function(t,n){if(t===1)return n[0];if(t===2)return n[1];if(t>2&&t<=4)return n[2];if(t>=5)return n[3]};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Prošu zhašej "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Prošu zapodaj znajmjeńša "+r+" "+n(r,e)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(e){return"Móžeš jenož "+e.maximum+" "+n(e.maximum,t)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/hu.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Túl hosszú. "+t+" karakterrel több, mint kellene."},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Túl rövid. Még "+t+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/hy.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Խնդրում ենք հեռացնել "+t+" նշան";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Խնդրում ենք մուտքագրել "+t+" կամ ավել նշաններ";return n},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(e){var t="Դուք կարող եք ընտրել առավելագույնը "+e.maximum+" կետ";return t},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/id.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Hapuskan "+t+" huruf"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Masukkan "+t+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(e){return"Anda hanya dapat memilih "+e.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/is.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/is",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vinsamlegast styttið texta um "+t+" staf";return t<=1?n:n+"i"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vinsamlegast skrifið "+t+" staf";return t>1&&(n+="i"),n+=" í viðbót",n},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(e){return"Þú getur aðeins valið "+e.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/it.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Per favore cancella "+t+" caratter";return t!==1?n+="i":n+="e",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Per favore inserisci "+t+" o più caratteri";return n},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var t="Puoi selezionare solo "+e.maximum+" element";return e.maximum!==1?t+="i":t+="o",t},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ja.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" 文字を削除してください";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="少なくとも "+t+" 文字を入力してください";return n},loadingMore:function(){return"読み込み中…"},maximumSelected:function(e){var t=e.maximum+" 件しか選択できません";return t},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/km.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="សូមលុបចេញ "+t+" អក្សរ";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="សូមបញ្ចូល"+t+" អក្សរ រឺ ច្រើនជាងនេះ";return n},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(e){var t="អ្នកអាចជ្រើសរើសបានតែ "+e.maximum+" ជម្រើសប៉ុណ្ណោះ";return t},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ko.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="너무 깁니다. "+t+" 글자 지워주세요.";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="너무 짧습니다. "+t+" 글자 더 입력해주세요.";return n},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(e){var t="최대 "+e.maximum+"개까지만 선택 가능합니다.";return t},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/lt.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lt",[],function(){function e(e,t,n,r){return e%10===1&&(e%100<11||e%100>19)?t:e%10>=2&&e%10<=9&&(e%100<11||e%100>19)?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Pašalinkite "+n+" simbol";return r+=e(n,"į","ius","ių"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Įrašykite dar "+n+" simbol";return r+=e(n,"į","ius","ių"),r},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(t){var n="Jūs galite pasirinkti tik "+t.maximum+" element";return n+=e(t.maximum,"ą","us","ų"),n},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/lv.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/lv",[],function(){function e(e,t,n,r){return e===11?t:e%10===1?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r="Lūdzu ievadiet par "+n;return r+=" simbol"+e(n,"iem","u","iem"),r+" mazāk"},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Lūdzu ievadiet vēl "+n;return r+=" simbol"+e(n,"us","u","us"),r},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(t){var n="Jūs varat izvēlēties ne vairāk kā "+t.maximum;return n+=" element"+e(t.maximum,"us","u","us"),n},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/mk.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/mk",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Ве молиме внесете "+e.maximum+" помалку карактер";return e.maximum!==1&&(n+="и"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Ве молиме внесете уште "+e.maximum+" карактер";return e.maximum!==1&&(n+="и"),n},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(e){var t="Можете да изберете само "+e.maximum+" ставк";return e.maximum===1?t+="а":t+="и",t},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ms.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Sila hapuskan "+t+" aksara"},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Sila masukkan "+t+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(e){return"Anda hanya boleh memilih "+e.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/nb.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Vennligst fjern "+t+" tegn"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vennligst skriv inn "+t+" tegn til";return n+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/nl.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Gelieve "+t+" karakters te verwijderen";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Gelieve "+t+" of meer karakters in te voeren";return n},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var t=e.maximum==1?"kan":"kunnen",n="Er "+t+" maar "+e.maximum+" item";return e.maximum!=1&&(n+="s"),n+=" worden geselecteerd",n},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/pl.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pl",[],function(){var e=["znak","znaki","znaków"],t=["element","elementy","elementów"],n=function(t,n){if(t===1)return n[0];if(t>1&&t<=4)return n[1];if(t>=5)return n[2]};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(t){var r=t.input.length-t.maximum;return"Usuń "+r+" "+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return"Podaj przynajmniej "+r+" "+n(r,e)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(e){return"Możesz zaznaczyć tylko "+e.maximum+" "+n(e.maximum,t)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ps.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="د مهربانۍ لمخي "+t+" توری ړنګ کړئ";return t!=1&&(n=n.replace("توری","توري")),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="لږ تر لږه "+t+" يا ډېر توري وليکئ";return n},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(e){var t="تاسو يوازي "+e.maximum+" قلم په نښه کولای سی";return e.maximum!=1&&(t=t.replace("قلم","قلمونه")),t},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/pt-BR.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Apague "+t+" caracter";return t!=1&&(n+="es"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Digite "+t+" ou mais caracteres";return n},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var t="Você só pode selecionar "+e.maximum+" ite";return e.maximum==1?t+="m":t+="ns",t},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/pt.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Por favor apague "+t+" ";return n+=t!=1?"caracteres":"caractere",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Introduza "+t+" ou mais caracteres";return n},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var t="Apenas pode seleccionar "+e.maximum+" ";return t+=e.maximum!=1?"itens":"item",t},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ro.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return t!==1&&(n+="e"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vă rugăm să introduceți "+t+" sau mai multe caractere";return n},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",e.maximum!==1&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/ru.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/ru",[],function(){function e(e,t,n,r){return e%10<5&&e%10>0&&e%100<5||e%100>20?e%10>1?n:t:r}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Пожалуйста, введите на "+n+" символ";return r+=e(n,"","a","ов"),r+=" меньше",r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Пожалуйста, введите еще хотя бы "+n+" символ";return r+=e(n,"","a","ов"),r},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(t){var n="Вы можете выбрать не более "+t.maximum+" элемент";return n+=e(t.maximum,"","a","ов"),n},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/sk.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{errorLoading:function(){return"Výsledky sa nepodarilo načítať."},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?"Prosím, zadajte o jeden znak menej":n>=2&&n<=4?"Prosím, zadajte o "+e[n](!0)+" znaky menej":"Prosím, zadajte o "+n+" znakov menej"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?"Prosím, zadajte ešte jeden znak":n<=4?"Prosím, zadajte ešte ďalšie "+e[n](!0)+" znaky":"Prosím, zadajte ešte ďalších "+n+" znakov"},loadingMore:function(){return"Načítanie ďalších výsledkov…"},maximumSelected:function(t){return t.maximum==1?"Môžete zvoliť len jednu položku":t.maximum>=2&&t.maximum<=4?"Môžete zvoliť najviac "+e[t.maximum](!1)+" položky":"Môžete zvoliť najviac "+t.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/sl.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Prosim zbrišite "+t+" znak";return t==2?n+="a":t!=1&&(n+="e"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Prosim vpišite še "+t+" znak";return t==2?n+="a":t!=1&&(n+="e"),n},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var t="Označite lahko največ "+e.maximum+" predmet";return e.maximum==2?t+="a":e.maximum!=1&&(t+="e"),t},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/sr-Cyrl.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr-Cyrl",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Обришите "+n+" симбол";return r+=e(n,"","а","а"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Укуцајте бар још "+n+" симбол";return r+=e(n,"","а","а"),r},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(t){var n="Можете изабрати само "+t.maximum+" ставк";return n+=e(t.maximum,"у","е","и"),n},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/sr.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sr",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(t){var n=t.input.length-t.maximum,r="Obrišite "+n+" simbol";return r+=e(n,"","a","a"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r="Ukucajte bar još "+n+" simbol";return r+=e(n,"","a","a"),r},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(t){var n="Možete izabrati samo "+t.maximum+" stavk";return n+=e(t.maximum,"u","e","i"),n},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/sv.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vänligen sudda ut "+t+" tecken";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vänligen skriv in "+t+" eller fler tecken";return n},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(e){var t="Du kan max välja "+e.maximum+" element";return t},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/th.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/th",[],function(){return{errorLoading:function(){return"ไม่สามารถค้นข้อมูลได้"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="โปรดลบออก "+t+" ตัวอักษร";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="โปรดพิมพ์เพิ่มอีก "+t+" ตัวอักษร";return n},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(e){var t="คุณสามารถเลือกได้ไม่เกิน "+e.maximum+" รายการ";return t},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/tr.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+" karakter daha girmelisiniz";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="En az "+t+" karakter daha girmelisiniz";return n},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(e){var t="Sadece "+e.maximum+" seçim yapabilirsiniz";return t},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/uk.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/uk",[],function(){function e(e,t,n,r){return e%100>10&&e%100<15?r:e%10===1?t:e%10>1&&e%10<5?n:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(t){var n=t.input.length-t.maximum;return"Будь ласка, видаліть "+n+" "+e(t.maximum,"літеру","літери","літер")},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Будь ласка, введіть "+t+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(t){return"Ви можете вибрати лише "+t.maximum+" "+e(t.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/vi.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/vi",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vui lòng nhập ít hơn "+t+" ký tự";return t!=1&&(n+="s"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Vui lòng nhập nhiều hơn "+t+" ký tự";return n},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(e){var t="Chỉ có thể chọn được "+e.maximum+" lựa chọn";return t},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/zh-CN.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(e){var t=e.input.length-e.maximum,n="请删除"+t+"个字符";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="请再输入至少"+t+"个字符";return n},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(e){var t="最多只能选择"+e.maximum+"个项目";return t},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/i18n/zh-TW.js ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /*! Select2 4.0.5 | https://github.com/select2/select2/blob/master/LICENSE.md */
2
+
3
+ (function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="請刪掉"+t+"個字元";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n="請再輸入"+t+"個字元";return n},loadingMore:function(){return"載入中…"},maximumSelected:function(e){var t="你只能選擇最多"+e.maximum+"項";return t},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"}}}),{define:e.define,require:e.require}})();
inc/lib/target-rule/select2.css ADDED
@@ -0,0 +1 @@
 
1
+ .select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;height:1px !important;margin:-1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb}
inc/lib/target-rule/select2.js ADDED
@@ -0,0 +1,5768 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * Select2 4.0.5
3
+ * https://select2.github.io
4
+ *
5
+ * Released under the MIT license
6
+ * https://github.com/select2/select2/blob/master/LICENSE.md
7
+ */
8
+ (function (factory) {
9
+
10
+ /* Whenever you update select2 script please add astselect2 handler */
11
+ /* select2 handler changed to astselect2 */
12
+ var existingVersion = jQuery.fn.select2 || null;
13
+
14
+ if (existingVersion) {
15
+ delete jQuery.fn.select2;
16
+ }
17
+
18
+ if (typeof define === 'function' && define.amd) {
19
+ // AMD. Register as an anonymous module.
20
+ define(['jquery'], factory);
21
+ } else if (typeof module === 'object' && module.exports) {
22
+ // Node/CommonJS
23
+ module.exports = function (root, jQuery) {
24
+
25
+ if (jQuery === undefined) {
26
+ // require('jQuery') returns a factory that requires window to
27
+ // build a jQuery instance, we normalize how we use modules
28
+ // that require this pattern but the window provided is a noop
29
+ // if it's defined (how jquery works)
30
+ if (typeof window !== 'undefined') {
31
+ jQuery = require('jquery');
32
+ }
33
+ else {
34
+ jQuery = require('jquery')(root);
35
+ }
36
+ }
37
+
38
+ factory(jQuery);
39
+
40
+ return jQuery;
41
+ };
42
+ } else {
43
+ // Browser globals
44
+ factory(jQuery);
45
+ }
46
+
47
+ jQuery.fn.astselect2 = jQuery.fn.select2;
48
+
49
+ if (existingVersion) {
50
+ delete jQuery.fn.select2;
51
+ jQuery.fn.select2 = existingVersion;
52
+ }
53
+
54
+ /* select2 handler changed to astselect2 code end */
55
+
56
+ } (function (jQuery) {
57
+ // This is needed so we can catch the AMD loader configuration and use it
58
+ // The inner file should be wrapped (by `banner.start.js`) in a function that
59
+ // returns the AMD loader references.
60
+ var S2 =(function () {
61
+ // Restore the Select2 AMD loader so it can be used
62
+ // Needed mostly in the language files, where the loader is not inserted
63
+ if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
64
+ var S2 = jQuery.fn.select2.amd;
65
+ }
66
+ var S2;(function () { if (!S2 || !S2.requirejs) {
67
+ if (!S2) { S2 = {}; } else { require = S2; }
68
+ /**
69
+ * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
70
+ * Released under MIT license, http://github.com/requirejs/almond/LICENSE
71
+ */
72
+ //Going sloppy to avoid 'use strict' string cost, but strict practices should
73
+ //be followed.
74
+ /*global setTimeout: false */
75
+
76
+ var requirejs, require, define;
77
+ (function (undef) {
78
+ var main, req, makeMap, handlers,
79
+ defined = {},
80
+ waiting = {},
81
+ config = {},
82
+ defining = {},
83
+ hasOwn = Object.prototype.hasOwnProperty,
84
+ aps = [].slice,
85
+ jsSuffixRegExp = /\.js$/;
86
+
87
+ function hasProp(obj, prop) {
88
+ return hasOwn.call(obj, prop);
89
+ }
90
+
91
+ /**
92
+ * Given a relative module name, like ./something, normalize it to
93
+ * a real name that can be mapped to a path.
94
+ * @param {String} name the relative name
95
+ * @param {String} baseName a real name that the name arg is relative
96
+ * to.
97
+ * @returns {String} normalized name
98
+ */
99
+ function normalize(name, baseName) {
100
+ var nameParts, nameSegment, mapValue, foundMap, lastIndex,
101
+ foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
102
+ baseParts = baseName && baseName.split("/"),
103
+ map = config.map,
104
+ starMap = (map && map['*']) || {};
105
+
106
+ //Adjust any relative paths.
107
+ if (name) {
108
+ name = name.split('/');
109
+ lastIndex = name.length - 1;
110
+
111
+ // If wanting node ID compatibility, strip .js from end
112
+ // of IDs. Have to do this here, and not in nameToUrl
113
+ // because node allows either .js or non .js to map
114
+ // to same file.
115
+ if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
116
+ name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
117
+ }
118
+
119
+ // Starts with a '.' so need the baseName
120
+ if (name[0].charAt(0) === '.' && baseParts) {
121
+ //Convert baseName to array, and lop off the last part,
122
+ //so that . matches that 'directory' and not name of the baseName's
123
+ //module. For instance, baseName of 'one/two/three', maps to
124
+ //'one/two/three.js', but we want the directory, 'one/two' for
125
+ //this normalization.
126
+ normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
127
+ name = normalizedBaseParts.concat(name);
128
+ }
129
+
130
+ //start trimDots
131
+ for (i = 0; i < name.length; i++) {
132
+ part = name[i];
133
+ if (part === '.') {
134
+ name.splice(i, 1);
135
+ i -= 1;
136
+ } else if (part === '..') {
137
+ // If at the start, or previous value is still ..,
138
+ // keep them so that when converted to a path it may
139
+ // still work when converted to a path, even though
140
+ // as an ID it is less than ideal. In larger point
141
+ // releases, may be better to just kick out an error.
142
+ if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
143
+ continue;
144
+ } else if (i > 0) {
145
+ name.splice(i - 1, 2);
146
+ i -= 2;
147
+ }
148
+ }
149
+ }
150
+ //end trimDots
151
+
152
+ name = name.join('/');
153
+ }
154
+
155
+ //Apply map config if available.
156
+ if ((baseParts || starMap) && map) {
157
+ nameParts = name.split('/');
158
+
159
+ for (i = nameParts.length; i > 0; i -= 1) {
160
+ nameSegment = nameParts.slice(0, i).join("/");
161
+
162
+ if (baseParts) {
163
+ //Find the longest baseName segment match in the config.
164
+ //So, do joins on the biggest to smallest lengths of baseParts.
165
+ for (j = baseParts.length; j > 0; j -= 1) {
166
+ mapValue = map[baseParts.slice(0, j).join('/')];
167
+
168
+ //baseName segment has config, find if it has one for
169
+ //this name.
170
+ if (mapValue) {
171
+ mapValue = mapValue[nameSegment];
172
+ if (mapValue) {
173
+ //Match, update name to the new value.
174
+ foundMap = mapValue;
175
+ foundI = i;
176
+ break;
177
+ }
178
+ }
179
+ }
180
+ }
181
+
182
+ if (foundMap) {
183
+ break;
184
+ }
185
+
186
+ //Check for a star map match, but just hold on to it,
187
+ //if there is a shorter segment match later in a matching
188
+ //config, then favor over this star map.
189
+ if (!foundStarMap && starMap && starMap[nameSegment]) {
190
+ foundStarMap = starMap[nameSegment];
191
+ starI = i;
192
+ }
193
+ }
194
+
195
+ if (!foundMap && foundStarMap) {
196
+ foundMap = foundStarMap;
197
+ foundI = starI;
198
+ }
199
+
200
+ if (foundMap) {
201
+ nameParts.splice(0, foundI, foundMap);
202
+ name = nameParts.join('/');
203
+ }
204
+ }
205
+
206
+ return name;
207
+ }
208
+
209
+ function makeRequire(relName, forceSync) {
210
+ return function () {
211
+ //A version of a require function that passes a moduleName
212
+ //value for items that may need to
213
+ //look up paths relative to the moduleName
214
+ var args = aps.call(arguments, 0);
215
+
216
+ //If first arg is not require('string'), and there is only
217
+ //one arg, it is the array form without a callback. Insert
218
+ //a null so that the following concat is correct.
219
+ if (typeof args[0] !== 'string' && args.length === 1) {
220
+ args.push(null);
221
+ }
222
+ return req.apply(undef, args.concat([relName, forceSync]));
223
+ };
224
+ }
225
+
226
+ function makeNormalize(relName) {
227
+ return function (name) {
228
+ return normalize(name, relName);
229
+ };
230
+ }
231
+
232
+ function makeLoad(depName) {
233
+ return function (value) {
234
+ defined[depName] = value;
235
+ };
236
+ }
237
+
238
+ function callDep(name) {
239
+ if (hasProp(waiting, name)) {
240
+ var args = waiting[name];
241
+ delete waiting[name];
242
+ defining[name] = true;
243
+ main.apply(undef, args);
244
+ }
245
+
246
+ if (!hasProp(defined, name) && !hasProp(defining, name)) {
247
+ throw new Error('No ' + name);
248
+ }
249
+ return defined[name];
250
+ }
251
+
252
+ //Turns a plugin!resource to [plugin, resource]
253
+ //with the plugin being undefined if the name
254
+ //did not have a plugin prefix.
255
+ function splitPrefix(name) {
256
+ var prefix,
257
+ index = name ? name.indexOf('!') : -1;
258
+ if (index > -1) {
259
+ prefix = name.substring(0, index);
260
+ name = name.substring(index + 1, name.length);
261
+ }
262
+ return [prefix, name];
263
+ }
264
+
265
+ //Creates a parts array for a relName where first part is plugin ID,
266
+ //second part is resource ID. Assumes relName has already been normalized.
267
+ function makeRelParts(relName) {
268
+ return relName ? splitPrefix(relName) : [];
269
+ }
270
+
271
+ /**
272
+ * Makes a name map, normalizing the name, and using a plugin
273
+ * for normalization if necessary. Grabs a ref to plugin
274
+ * too, as an optimization.
275
+ */
276
+ makeMap = function (name, relParts) {
277
+ var plugin,
278
+ parts = splitPrefix(name),
279
+ prefix = parts[0],
280
+ relResourceName = relParts[1];
281
+
282
+ name = parts[1];
283
+
284
+ if (prefix) {
285
+ prefix = normalize(prefix, relResourceName);
286
+ plugin = callDep(prefix);
287
+ }
288
+
289
+ //Normalize according
290
+ if (prefix) {
291
+ if (plugin && plugin.normalize) {
292
+ name = plugin.normalize(name, makeNormalize(relResourceName));
293
+ } else {
294
+ name = normalize(name, relResourceName);
295
+ }
296
+ } else {
297
+ name = normalize(name, relResourceName);
298
+ parts = splitPrefix(name);
299
+ prefix = parts[0];
300
+ name = parts[1];
301
+ if (prefix) {
302
+ plugin = callDep(prefix);
303
+ }
304
+ }
305
+
306
+ //Using ridiculous property names for space reasons
307
+ return {
308
+ f: prefix ? prefix + '!' + name : name, //fullName
309
+ n: name,
310
+ pr: prefix,
311
+ p: plugin
312
+ };
313
+ };
314
+
315
+ function makeConfig(name) {
316
+ return function () {
317
+ return (config && config.config && config.config[name]) || {};
318
+ };
319
+ }
320
+
321
+ handlers = {
322
+ require: function (name) {
323
+ return makeRequire(name);
324
+ },
325
+ exports: function (name) {
326
+ var e = defined[name];
327
+ if (typeof e !== 'undefined') {
328
+ return e;
329
+ } else {
330
+ return (defined[name] = {});
331
+ }
332
+ },
333
+ module: function (name) {
334
+ return {
335
+ id: name,
336
+ uri: '',
337
+ exports: defined[name],
338
+ config: makeConfig(name)
339
+ };
340
+ }
341
+ };
342
+
343
+ main = function (name, deps, callback, relName) {
344
+ var cjsModule, depName, ret, map, i, relParts,
345
+ args = [],
346
+ callbackType = typeof callback,
347
+ usingExports;
348
+
349
+ //Use name if no relName
350
+ relName = relName || name;
351
+ relParts = makeRelParts(relName);
352
+
353
+ //Call the callback to define the module, if necessary.
354
+ if (callbackType === 'undefined' || callbackType === 'function') {
355
+ //Pull out the defined dependencies and pass the ordered
356
+ //values to the callback.
357
+ //Default to [require, exports, module] if no deps
358
+ deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
359
+ for (i = 0; i < deps.length; i += 1) {
360
+ map = makeMap(deps[i], relParts);
361
+ depName = map.f;
362
+
363
+ //Fast path CommonJS standard dependencies.
364
+ if (depName === "require") {
365
+ args[i] = handlers.require(name);
366
+ } else if (depName === "exports") {
367
+ //CommonJS module spec 1.1
368
+ args[i] = handlers.exports(name);
369
+ usingExports = true;
370
+ } else if (depName === "module") {
371
+ //CommonJS module spec 1.1
372
+ cjsModule = args[i] = handlers.module(name);
373
+ } else if (hasProp(defined, depName) ||
374
+ hasProp(waiting, depName) ||
375
+ hasProp(defining, depName)) {
376
+ args[i] = callDep(depName);
377
+ } else if (map.p) {
378
+ map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
379
+ args[i] = defined[depName];
380
+ } else {
381
+ throw new Error(name + ' missing ' + depName);
382
+ }
383
+ }
384
+
385
+ ret = callback ? callback.apply(defined[name], args) : undefined;
386
+
387
+ if (name) {
388
+ //If setting exports via "module" is in play,
389
+ //favor that over return value and exports. After that,
390
+ //favor a non-undefined return value over exports use.
391
+ if (cjsModule && cjsModule.exports !== undef &&
392
+ cjsModule.exports !== defined[name]) {
393
+ defined[name] = cjsModule.exports;
394
+ } else if (ret !== undef || !usingExports) {
395
+ //Use the return value from the function.
396
+ defined[name] = ret;
397
+ }
398
+ }
399
+ } else if (name) {
400
+ //May just be an object definition for the module. Only
401
+ //worry about defining if have a module name.
402
+ defined[name] = callback;
403
+ }
404
+ };
405
+
406
+ requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
407
+ if (typeof deps === "string") {
408
+ if (handlers[deps]) {
409
+ //callback in this case is really relName
410
+ return handlers[deps](callback);
411
+ }
412
+ //Just return the module wanted. In this scenario, the
413
+ //deps arg is the module name, and second arg (if passed)
414
+ //is just the relName.
415
+ //Normalize module name, if it contains . or ..
416
+ return callDep(makeMap(deps, makeRelParts(callback)).f);
417
+ } else if (!deps.splice) {
418
+ //deps is a config object, not an array.
419
+ config = deps;
420
+ if (config.deps) {
421
+ req(config.deps, config.callback);
422
+ }
423
+ if (!callback) {
424
+ return;
425
+ }
426
+
427
+ if (callback.splice) {
428
+ //callback is an array, which means it is a dependency list.
429
+ //Adjust args if there are dependencies
430
+ deps = callback;
431
+ callback = relName;
432
+ relName = null;
433
+ } else {
434
+ deps = undef;
435
+ }
436
+ }
437
+
438
+ //Support require(['a'])
439
+ callback = callback || function () {};
440
+
441
+ //If relName is a function, it is an errback handler,
442
+ //so remove it.
443
+ if (typeof relName === 'function') {
444
+ relName = forceSync;
445
+ forceSync = alt;
446
+ }
447
+
448
+ //Simulate async callback;
449
+ if (forceSync) {
450
+ main(undef, deps, callback, relName);
451
+ } else {
452
+ //Using a non-zero value because of concern for what old browsers
453
+ //do, and latest browsers "upgrade" to 4 if lower value is used:
454
+ //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
455
+ //If want a value immediately, use require('id') instead -- something
456
+ //that works in almond on the global level, but not guaranteed and
457
+ //unlikely to work in other AMD implementations.
458
+ setTimeout(function () {
459
+ main(undef, deps, callback, relName);
460
+ }, 4);
461
+ }
462
+
463
+ return req;
464
+ };
465
+
466
+ /**
467
+ * Just drops the config on the floor, but returns req in case
468
+ * the config return value is used.
469
+ */
470
+ req.config = function (cfg) {
471
+ return req(cfg);
472
+ };
473
+
474
+ /**
475
+ * Expose module registry for debugging and tooling
476
+ */
477
+ requirejs._defined = defined;
478
+
479
+ define = function (name, deps, callback) {
480
+ if (typeof name !== 'string') {
481
+ throw new Error('See almond README: incorrect module build, no module name');
482
+ }
483
+
484
+ //This module may not have dependencies
485
+ if (!deps.splice) {
486
+ //deps is not an array, so probably means
487
+ //an object literal or factory function for
488
+ //the value. Adjust args.
489
+ callback = deps;
490
+ deps = [];
491
+ }
492
+
493
+ if (!hasProp(defined, name) && !hasProp(waiting, name)) {
494
+ waiting[name] = [name, deps, callback];
495
+ }
496
+ };
497
+
498
+ define.amd = {
499
+ jQuery: true
500
+ };
501
+ }());
502
+
503
+ S2.requirejs = requirejs;S2.require = require;S2.define = define;
504
+ }
505
+ }());
506
+ S2.define("almond", function(){});
507
+
508
+ /* global jQuery:false, $:false */
509
+ S2.define('jquery',[],function () {
510
+ var _$ = jQuery || $;
511
+
512
+ if (_$ == null && console && console.error) {
513
+ console.error(
514
+ 'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
515
+ 'found. Make sure that you are including jQuery before Select2 on your ' +
516
+ 'web page.'
517
+ );
518
+ }
519
+
520
+ return _$;
521
+ });
522
+
523
+ S2.define('select2/utils',[
524
+ 'jquery'
525
+ ], function ($) {
526
+ var Utils = {};
527
+
528
+ Utils.Extend = function (ChildClass, SuperClass) {
529
+ var __hasProp = {}.hasOwnProperty;
530
+
531
+ function BaseConstructor () {
532
+ this.constructor = ChildClass;
533
+ }
534
+
535
+ for (var key in SuperClass) {
536
+ if (__hasProp.call(SuperClass, key)) {
537
+ ChildClass[key] = SuperClass[key];
538
+ }
539
+ }
540
+
541
+ BaseConstructor.prototype = SuperClass.prototype;
542
+ ChildClass.prototype = new BaseConstructor();
543
+ ChildClass.__super__ = SuperClass.prototype;
544
+
545
+ return ChildClass;
546
+ };
547
+
548
+ function getMethods (theClass) {
549
+ var proto = theClass.prototype;
550
+
551
+ var methods = [];
552
+
553
+ for (var methodName in proto) {
554
+ var m = proto[methodName];
555
+
556
+ if (typeof m !== 'function') {
557
+ continue;
558
+ }
559
+
560
+ if (methodName === 'constructor') {
561
+ continue;
562
+ }
563
+
564
+ methods.push(methodName);
565
+ }
566
+
567
+ return methods;
568
+ }
569
+
570
+ Utils.Decorate = function (SuperClass, DecoratorClass) {
571
+ var decoratedMethods = getMethods(DecoratorClass);
572
+ var superMethods = getMethods(SuperClass);
573
+
574
+ function DecoratedClass () {
575
+ var unshift = Array.prototype.unshift;
576
+
577
+ var argCount = DecoratorClass.prototype.constructor.length;
578
+
579
+ var calledConstructor = SuperClass.prototype.constructor;
580
+
581
+ if (argCount > 0) {
582
+ unshift.call(arguments, SuperClass.prototype.constructor);
583
+
584
+ calledConstructor = DecoratorClass.prototype.constructor;
585
+ }
586
+
587
+ calledConstructor.apply(this, arguments);
588
+ }
589
+
590
+ DecoratorClass.displayName = SuperClass.displayName;
591
+
592
+ function ctr () {
593
+ this.constructor = DecoratedClass;
594
+ }
595
+
596
+ DecoratedClass.prototype = new ctr();
597
+
598
+ for (var m = 0; m < superMethods.length; m++) {
599
+ var superMethod = superMethods[m];
600
+
601
+ DecoratedClass.prototype[superMethod] =
602
+ SuperClass.prototype[superMethod];
603
+ }
604
+
605
+ var calledMethod = function (methodName) {
606
+ // Stub out the original method if it's not decorating an actual method
607
+ var originalMethod = function () {};
608
+
609
+ if (methodName in DecoratedClass.prototype) {
610
+ originalMethod = DecoratedClass.prototype[methodName];
611
+ }
612
+
613
+ var decoratedMethod = DecoratorClass.prototype[methodName];
614
+
615
+ return function () {
616
+ var unshift = Array.prototype.unshift;
617
+
618
+ unshift.call(arguments, originalMethod);
619
+
620
+ return decoratedMethod.apply(this, arguments);
621
+ };
622
+ };
623
+
624
+ for (var d = 0; d < decoratedMethods.length; d++) {
625
+ var decoratedMethod = decoratedMethods[d];
626
+
627
+ DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
628
+ }
629
+
630
+ return DecoratedClass;
631
+ };
632
+
633
+ var Observable = function () {
634
+ this.listeners = {};
635
+ };
636
+
637
+ Observable.prototype.on = function (event, callback) {
638
+ this.listeners = this.listeners || {};
639
+
640
+ if (event in this.listeners) {
641
+ this.listeners[event].push(callback);
642
+ } else {
643
+ this.listeners[event] = [callback];
644
+ }
645
+ };
646
+
647
+ Observable.prototype.trigger = function (event) {
648
+ var slice = Array.prototype.slice;
649
+ var params = slice.call(arguments, 1);
650
+
651
+ this.listeners = this.listeners || {};
652
+
653
+ // Params should always come in as an array
654
+ if (params == null) {
655
+ params = [];
656
+ }
657
+
658
+ // If there are no arguments to the event, use a temporary object
659
+ if (params.length === 0) {
660
+ params.push({});
661
+ }
662
+
663
+ // Set the `_type` of the first object to the event
664
+ params[0]._type = event;
665
+
666
+ if (event in this.listeners) {
667
+ this.invoke(this.listeners[event], slice.call(arguments, 1));
668
+ }
669
+
670
+ if ('*' in this.listeners) {
671
+ this.invoke(this.listeners['*'], arguments);
672
+ }
673
+ };
674
+
675
+ Observable.prototype.invoke = function (listeners, params) {
676
+ for (var i = 0, len = listeners.length; i < len; i++) {
677
+ listeners[i].apply(this, params);
678
+ }
679
+ };
680
+
681
+ Utils.Observable = Observable;
682
+
683
+ Utils.generateChars = function (length) {
684
+ var chars = '';
685
+
686
+ for (var i = 0; i < length; i++) {
687
+ var randomChar = Math.floor(Math.random() * 36);
688
+ chars += randomChar.toString(36);
689
+ }
690
+
691
+ return chars;
692
+ };
693
+
694
+ Utils.bind = function (func, context) {
695
+ return function () {
696
+ func.apply(context, arguments);
697
+ };
698
+ };
699
+
700
+ Utils._convertData = function (data) {
701
+ for (var originalKey in data) {
702
+ var keys = originalKey.split('-');
703
+
704
+ var dataLevel = data;
705
+
706
+ if (keys.length === 1) {
707
+ continue;
708
+ }
709
+
710
+ for (var k = 0; k < keys.length; k++) {
711
+ var key = keys[k];
712
+
713
+ // Lowercase the first letter
714
+ // By default, dash-separated becomes camelCase
715
+ key = key.substring(0, 1).toLowerCase() + key.substring(1);
716
+
717
+ if (!(key in dataLevel)) {
718
+ dataLevel[key] = {};
719
+ }
720
+
721
+ if (k == keys.length - 1) {
722
+ dataLevel[key] = data[originalKey];
723
+ }
724
+
725
+ dataLevel = dataLevel[key];
726
+ }
727
+
728
+ delete data[originalKey];
729
+ }
730
+
731
+ return data;
732
+ };
733
+
734
+ Utils.hasScroll = function (index, el) {
735
+ // Adapted from the function created by @ShadowScripter
736
+ // and adapted by @BillBarry on the Stack Exchange Code Review website.
737
+ // The original code can be found at
738
+ // http://codereview.stackexchange.com/q/13338
739
+ // and was designed to be used with the Sizzle selector engine.
740
+
741
+ var $el = $(el);
742
+ var overflowX = el.style.overflowX;
743
+ var overflowY = el.style.overflowY;
744
+
745
+ //Check both x and y declarations
746
+ if (overflowX === overflowY &&
747
+ (overflowY === 'hidden' || overflowY === 'visible')) {
748
+ return false;
749
+ }
750
+
751
+ if (overflowX === 'scroll' || overflowY === 'scroll') {
752
+ return true;
753
+ }
754
+
755
+ return ($el.innerHeight() < el.scrollHeight ||
756
+ $el.innerWidth() < el.scrollWidth);
757
+ };
758
+
759
+ Utils.escapeMarkup = function (markup) {
760
+ var replaceMap = {
761
+ '\\': '&#92;',
762
+ '&': '&amp;',
763
+ '<': '&lt;',
764
+ '>': '&gt;',
765
+ '"': '&quot;',
766
+ '\'': '&#39;',
767
+ '/': '&#47;'
768
+ };
769
+
770
+ // Do not try to escape the markup if it's not a string
771
+ if (typeof markup !== 'string') {
772
+ return markup;
773
+ }
774
+
775
+ return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
776
+ return replaceMap[match];
777
+ });
778
+ };
779
+
780
+ // Append an array of jQuery nodes to a given element.
781
+ Utils.appendMany = function ($element, $nodes) {
782
+ // jQuery 1.7.x does not support $.fn.append() with an array
783
+ // Fall back to a jQuery object collection using $.fn.add()
784
+ if ($.fn.jquery.substr(0, 3) === '1.7') {
785
+ var $jqNodes = $();
786
+
787
+ $.map($nodes, function (node) {
788
+ $jqNodes = $jqNodes.add(node);
789
+ });
790
+
791
+ $nodes = $jqNodes;
792
+ }
793
+
794
+ $element.append($nodes);
795
+ };
796
+
797
+ return Utils;
798
+ });
799
+
800
+ S2.define('select2/results',[
801
+ 'jquery',
802
+ './utils'
803
+ ], function ($, Utils) {
804
+ function Results ($element, options, dataAdapter) {
805
+ this.$element = $element;
806
+ this.data = dataAdapter;
807
+ this.options = options;
808
+
809
+ Results.__super__.constructor.call(this);
810
+ }
811
+
812
+ Utils.Extend(Results, Utils.Observable);
813
+
814
+ Results.prototype.render = function () {
815
+ var $results = $(
816
+ '<ul class="select2-results__options" role="tree"></ul>'
817
+ );
818
+
819
+ if (this.options.get('multiple')) {
820
+ $results.attr('aria-multiselectable', 'true');
821
+ }
822
+
823
+ this.$results = $results;
824
+
825
+ return $results;
826
+ };
827
+
828
+ Results.prototype.clear = function () {
829
+ this.$results.empty();
830
+ };
831
+
832
+ Results.prototype.displayMessage = function (params) {
833
+ var escapeMarkup = this.options.get('escapeMarkup');
834
+
835
+ this.clear();
836
+ this.hideLoading();
837
+
838
+ var $message = $(
839
+ '<li role="treeitem" aria-live="assertive"' +
840
+ ' class="select2-results__option"></li>'
841
+ );
842
+
843
+ var message = this.options.get('translations').get(params.message);
844
+
845
+ $message.append(
846
+ escapeMarkup(
847
+ message(params.args)
848
+ )
849
+ );
850
+
851
+ $message[0].className += ' select2-results__message';
852
+
853
+ this.$results.append($message);
854
+ };
855
+
856
+ Results.prototype.hideMessages = function () {
857
+ this.$results.find('.select2-results__message').remove();
858
+ };
859
+
860
+ Results.prototype.append = function (data) {
861
+ this.hideLoading();
862
+
863
+ var $options = [];
864
+
865
+ if (data.results == null || data.results.length === 0) {
866
+ if (this.$results.children().length === 0) {
867
+ this.trigger('results:message', {
868
+ message: 'noResults'
869
+ });
870
+ }
871
+
872
+ return;
873
+ }
874
+
875
+ data.results = this.sort(data.results);
876
+
877
+ for (var d = 0; d < data.results.length; d++) {
878
+ var item = data.results[d];
879
+
880
+ var $option = this.option(item);
881
+
882
+ $options.push($option);
883
+ }
884
+
885
+ this.$results.append($options);
886
+ };
887
+
888
+ Results.prototype.position = function ($results, $dropdown) {
889
+ var $resultsContainer = $dropdown.find('.select2-results');
890
+ $resultsContainer.append($results);
891
+ };
892
+
893
+ Results.prototype.sort = function (data) {
894
+ var sorter = this.options.get('sorter');
895
+
896
+ return sorter(data);
897
+ };
898
+
899
+ Results.prototype.highlightFirstItem = function () {
900
+ var $options = this.$results
901
+ .find('.select2-results__option[aria-selected]');
902
+
903
+ var $selected = $options.filter('[aria-selected=true]');
904
+
905
+ // Check if there are any selected options
906
+ if ($selected.length > 0) {
907
+ // If there are selected options, highlight the first
908
+ $selected.first().trigger('mouseenter');
909
+ } else {
910
+ // If there are no selected options, highlight the first option
911
+ // in the dropdown
912
+ $options.first().trigger('mouseenter');
913
+ }
914
+
915
+ this.ensureHighlightVisible();
916
+ };
917
+
918
+ Results.prototype.setClasses = function () {
919
+ var self = this;
920
+
921
+ this.data.current(function (selected) {
922
+ var selectedIds = $.map(selected, function (s) {
923
+ return s.id.toString();
924
+ });
925
+
926
+ var $options = self.$results
927
+ .find('.select2-results__option[aria-selected]');
928
+
929
+ $options.each(function () {
930
+ var $option = $(this);
931
+
932
+ var item = $.data(this, 'data');
933
+
934
+ // id needs to be converted to a string when comparing
935
+ var id = '' + item.id;
936
+
937
+ if ((item.element != null && item.element.selected) ||
938
+ (item.element == null && $.inArray(id, selectedIds) > -1)) {
939
+ $option.attr('aria-selected', 'true');
940
+ } else {
941
+ $option.attr('aria-selected', 'false');
942
+ }
943
+ });
944
+
945
+ });
946
+ };
947
+
948
+ Results.prototype.showLoading = function (params) {
949
+ this.hideLoading();
950
+
951
+ var loadingMore = this.options.get('translations').get('searching');
952
+
953
+ var loading = {
954
+ disabled: true,
955
+ loading: true,
956
+ text: loadingMore(params)
957
+ };
958
+ var $loading = this.option(loading);
959
+ $loading.className += ' loading-results';
960
+
961
+ this.$results.prepend($loading);
962
+ };
963
+
964
+ Results.prototype.hideLoading = function () {
965
+ this.$results.find('.loading-results').remove();
966
+ };
967
+
968
+ Results.prototype.option = function (data) {
969
+ var option = document.createElement('li');
970
+ option.className = 'select2-results__option';
971
+
972
+ var attrs = {
973
+ 'role': 'treeitem',
974
+ 'aria-selected': 'false'
975
+ };
976
+
977
+ if (data.disabled) {
978
+ delete attrs['aria-selected'];
979
+ attrs['aria-disabled'] = 'true';
980
+ }
981
+
982
+ if (data.id == null) {
983
+ delete attrs['aria-selected'];
984
+ }
985
+
986
+ if (data._resultId != null) {
987
+ option.id = data._resultId;
988
+ }
989
+
990
+ if (data.title) {
991
+ option.title = data.title;
992
+ }
993
+
994
+ if (data.children) {
995
+ attrs.role = 'group';
996
+ attrs['aria-label'] = data.text;
997
+ delete attrs['aria-selected'];
998
+ }
999
+
1000
+ for (var attr in attrs) {
1001
+ var val = attrs[attr];
1002
+
1003
+ option.setAttribute(attr, val);
1004
+ }
1005
+
1006
+ if (data.children) {
1007
+ var $option = $(option);
1008
+
1009
+ var label = document.createElement('strong');
1010
+ label.className = 'select2-results__group';
1011
+
1012
+ var $label = $(label);
1013
+ this.template(data, label);
1014
+
1015
+ var $children = [];
1016
+
1017
+ for (var c = 0; c < data.children.length; c++) {
1018
+ var child = data.children[c];
1019
+
1020
+ var $child = this.option(child);
1021
+
1022
+ $children.push($child);
1023
+ }
1024
+
1025
+ var $childrenContainer = $('<ul></ul>', {
1026
+ 'class': 'select2-results__options select2-results__options--nested'
1027
+ });
1028
+
1029
+ $childrenContainer.append($children);
1030
+
1031
+ $option.append(label);
1032
+ $option.append($childrenContainer);
1033
+ } else {
1034
+ this.template(data, option);
1035
+ }
1036
+
1037
+ $.data(option, 'data', data);
1038
+
1039
+ return option;
1040
+ };
1041
+
1042
+ Results.prototype.bind = function (container, $container) {
1043
+ var self = this;
1044
+
1045
+ var id = container.id + '-results';
1046
+
1047
+ this.$results.attr('id', id);
1048
+
1049
+ container.on('results:all', function (params) {
1050
+ self.clear();
1051
+ self.append(params.data);
1052
+
1053
+ if (container.isOpen()) {
1054
+ self.setClasses();
1055
+ self.highlightFirstItem();
1056
+ }
1057
+ });
1058
+
1059
+ container.on('results:append', function (params) {
1060
+ self.append(params.data);
1061
+
1062
+ if (container.isOpen()) {
1063
+ self.setClasses();
1064
+ }
1065
+ });
1066
+
1067
+ container.on('query', function (params) {
1068
+ self.hideMessages();
1069
+ self.showLoading(params);
1070
+ });
1071
+
1072
+ container.on('select', function () {
1073
+ if (!container.isOpen()) {
1074
+ return;
1075
+ }
1076
+
1077
+ self.setClasses();
1078
+ self.highlightFirstItem();
1079
+ });
1080
+
1081
+ container.on('unselect', function () {
1082
+ if (!container.isOpen()) {
1083
+ return;
1084
+ }
1085
+
1086
+ self.setClasses();
1087
+ self.highlightFirstItem();
1088
+ });
1089
+
1090
+ container.on('open', function () {
1091
+ // When the dropdown is open, aria-expended="true"
1092
+ self.$results.attr('aria-expanded', 'true');
1093
+ self.$results.attr('aria-hidden', 'false');
1094
+
1095
+ self.setClasses();
1096
+ self.ensureHighlightVisible();
1097
+ });
1098
+
1099
+ container.on('close', function () {
1100
+ // When the dropdown is closed, aria-expended="false"
1101
+ self.$results.attr('aria-expanded', 'false');
1102
+ self.$results.attr('aria-hidden', 'true');
1103
+ self.$results.removeAttr('aria-activedescendant');
1104
+ });
1105
+
1106
+ container.on('results:toggle', function () {
1107
+ var $highlighted = self.getHighlightedResults();
1108
+
1109
+ if ($highlighted.length === 0) {
1110
+ return;
1111
+ }
1112
+
1113
+ $highlighted.trigger('mouseup');
1114
+ });
1115
+
1116
+ container.on('results:select', function () {
1117
+ var $highlighted = self.getHighlightedResults();
1118
+
1119
+ if ($highlighted.length === 0) {
1120
+ return;
1121
+ }
1122
+
1123
+ var data = $highlighted.data('data');
1124
+
1125
+ if ($highlighted.attr('aria-selected') == 'true') {
1126
+ self.trigger('close', {});
1127
+ } else {
1128
+ self.trigger('select', {
1129
+ data: data
1130
+ });
1131
+ }
1132
+ });
1133
+
1134
+ container.on('results:previous', function () {
1135
+ var $highlighted = self.getHighlightedResults();
1136
+
1137
+ var $options = self.$results.find('[aria-selected]');
1138
+
1139
+ var currentIndex = $options.index($highlighted);
1140
+
1141
+ // If we are already at te top, don't move further
1142
+ if (currentIndex === 0) {
1143
+ return;
1144
+ }
1145
+
1146
+ var nextIndex = currentIndex - 1;
1147
+
1148
+ // If none are highlighted, highlight the first
1149
+ if ($highlighted.length === 0) {
1150
+ nextIndex = 0;
1151
+ }
1152
+
1153
+ var $next = $options.eq(nextIndex);
1154
+
1155
+ $next.trigger('mouseenter');
1156
+
1157
+ var currentOffset = self.$results.offset().top;
1158
+ var nextTop = $next.offset().top;
1159
+ var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
1160
+
1161
+ if (nextIndex === 0) {
1162
+ self.$results.scrollTop(0);
1163
+ } else if (nextTop - currentOffset < 0) {
1164
+ self.$results.scrollTop(nextOffset);
1165
+ }
1166
+ });
1167
+
1168
+ container.on('results:next', function () {
1169
+ var $highlighted = self.getHighlightedResults();
1170
+
1171
+ var $options = self.$results.find('[aria-selected]');
1172
+
1173
+ var currentIndex = $options.index($highlighted);
1174
+
1175
+ var nextIndex = currentIndex + 1;
1176
+
1177
+ // If we are at the last option, stay there
1178
+ if (nextIndex >= $options.length) {
1179
+ return;
1180
+ }
1181
+
1182
+ var $next = $options.eq(nextIndex);
1183
+
1184
+ $next.trigger('mouseenter');
1185
+
1186
+ var currentOffset = self.$results.offset().top +
1187
+ self.$results.outerHeight(false);
1188
+ var nextBottom = $next.offset().top + $next.outerHeight(false);
1189
+ var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
1190
+
1191
+ if (nextIndex === 0) {
1192
+ self.$results.scrollTop(0);
1193
+ } else if (nextBottom > currentOffset) {
1194
+ self.$results.scrollTop(nextOffset);
1195
+ }
1196
+ });
1197
+
1198
+ container.on('results:focus', function (params) {
1199
+ params.element.addClass('select2-results__option--highlighted');
1200
+ });
1201
+
1202
+ container.on('results:message', function (params) {
1203
+ self.displayMessage(params);
1204
+ });
1205
+
1206
+ if ($.fn.mousewheel) {
1207
+ this.$results.on('mousewheel', function (e) {
1208
+ var top = self.$results.scrollTop();
1209
+
1210
+ var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;
1211
+
1212
+ var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
1213
+ var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
1214
+
1215
+ if (isAtTop) {
1216
+ self.$results.scrollTop(0);
1217
+
1218
+ e.preventDefault();
1219
+ e.stopPropagation();
1220
+ } else if (isAtBottom) {
1221
+ self.$results.scrollTop(
1222
+ self.$results.get(0).scrollHeight - self.$results.height()
1223
+ );
1224
+
1225
+ e.preventDefault();
1226
+ e.stopPropagation();
1227
+ }
1228
+ });
1229
+ }
1230
+
1231
+ this.$results.on('mouseup', '.select2-results__option[aria-selected]',
1232
+ function (evt) {
1233
+ var $this = $(this);
1234
+
1235
+ var data = $this.data('data');
1236
+
1237
+ if ($this.attr('aria-selected') === 'true') {
1238
+ if (self.options.get('multiple')) {
1239
+ self.trigger('unselect', {
1240
+ originalEvent: evt,
1241
+ data: data
1242
+ });
1243
+ } else {
1244
+ self.trigger('close', {});
1245
+ }
1246
+
1247
+ return;
1248
+ }
1249
+
1250
+ self.trigger('select', {
1251
+ originalEvent: evt,
1252
+ data: data
1253
+ });
1254
+ });
1255
+
1256
+ this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
1257
+ function (evt) {
1258
+ var data = $(this).data('data');
1259
+
1260
+ self.getHighlightedResults()
1261
+ .removeClass('select2-results__option--highlighted');
1262
+
1263
+ self.trigger('results:focus', {
1264
+ data: data,
1265
+ element: $(this)
1266
+ });
1267
+ });
1268
+ };
1269
+
1270
+ Results.prototype.getHighlightedResults = function () {
1271
+ var $highlighted = this.$results
1272
+ .find('.select2-results__option--highlighted');
1273
+
1274
+ return $highlighted;
1275
+ };
1276
+
1277
+ Results.prototype.destroy = function () {
1278
+ this.$results.remove();
1279
+ };
1280
+
1281
+ Results.prototype.ensureHighlightVisible = function () {
1282
+ var $highlighted = this.getHighlightedResults();
1283
+
1284
+ if ($highlighted.length === 0) {
1285
+ return;
1286
+ }
1287
+
1288
+ var $options = this.$results.find('[aria-selected]');
1289
+
1290
+ var currentIndex = $options.index($highlighted);
1291
+
1292
+ var currentOffset = this.$results.offset().top;
1293
+ var nextTop = $highlighted.offset().top;
1294
+ var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
1295
+
1296
+ var offsetDelta = nextTop - currentOffset;
1297
+ nextOffset -= $highlighted.outerHeight(false) * 2;
1298
+
1299
+ if (currentIndex <= 2) {
1300
+ this.$results.scrollTop(0);
1301
+ } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
1302
+ this.$results.scrollTop(nextOffset);
1303
+ }
1304
+ };
1305
+
1306
+ Results.prototype.template = function (result, container) {
1307
+ var template = this.options.get('templateResult');
1308
+ var escapeMarkup = this.options.get('escapeMarkup');
1309
+
1310
+ var content = template(result, container);
1311
+
1312
+ if (content == null) {
1313
+ container.style.display = 'none';
1314
+ } else if (typeof content === 'string') {
1315
+ container.innerHTML = escapeMarkup(content);
1316
+ } else {
1317
+ $(container).append(content);
1318
+ }
1319
+ };
1320
+
1321
+ return Results;
1322
+ });
1323
+
1324
+ S2.define('select2/keys',[
1325
+
1326
+ ], function () {
1327
+ var KEYS = {
1328
+ BACKSPACE: 8,
1329
+ TAB: 9,
1330
+ ENTER: 13,
1331
+ SHIFT: 16,
1332
+ CTRL: 17,
1333
+ ALT: 18,
1334
+ ESC: 27,
1335
+ SPACE: 32,
1336
+ PAGE_UP: 33,
1337
+ PAGE_DOWN: 34,
1338
+ END: 35,
1339
+ HOME: 36,
1340
+ LEFT: 37,
1341
+ UP: 38,
1342
+ RIGHT: 39,
1343
+ DOWN: 40,
1344
+ DELETE: 46
1345
+ };
1346
+
1347
+ return KEYS;
1348
+ });
1349
+
1350
+ S2.define('select2/selection/base',[
1351
+ 'jquery',
1352
+ '../utils',
1353
+ '../keys'
1354
+ ], function ($, Utils, KEYS) {
1355
+ function BaseSelection ($element, options) {
1356
+ this.$element = $element;
1357
+ this.options = options;
1358
+
1359
+ BaseSelection.__super__.constructor.call(this);
1360
+ }
1361
+
1362
+ Utils.Extend(BaseSelection, Utils.Observable);
1363
+
1364
+ BaseSelection.prototype.render = function () {
1365
+ var $selection = $(
1366
+ '<span class="select2-selection" role="combobox" ' +
1367
+ ' aria-haspopup="true" aria-expanded="false">' +
1368
+ '</span>'
1369
+ );
1370
+
1371
+ this._tabindex = 0;
1372
+
1373
+ if (this.$element.data('old-tabindex') != null) {
1374
+ this._tabindex = this.$element.data('old-tabindex');
1375
+ } else if (this.$element.attr('tabindex') != null) {
1376
+ this._tabindex = this.$element.attr('tabindex');
1377
+ }
1378
+
1379
+ $selection.attr('title', this.$element.attr('title'));
1380
+ $selection.attr('tabindex', this._tabindex);
1381
+
1382
+ this.$selection = $selection;
1383
+
1384
+ return $selection;
1385
+ };
1386
+
1387
+ BaseSelection.prototype.bind = function (container, $container) {
1388
+ var self = this;
1389
+
1390
+ var id = container.id + '-container';
1391
+ var resultsId = container.id + '-results';
1392
+
1393
+ this.container = container;
1394
+
1395
+ this.$selection.on('focus', function (evt) {
1396
+ self.trigger('focus', evt);
1397
+ });
1398
+
1399
+ this.$selection.on('blur', function (evt) {
1400
+ self._handleBlur(evt);
1401
+ });
1402
+
1403
+ this.$selection.on('keydown', function (evt) {
1404
+ self.trigger('keypress', evt);
1405
+
1406
+ if (evt.which === KEYS.SPACE) {
1407
+ evt.preventDefault();
1408
+ }
1409
+ });
1410
+
1411
+ container.on('results:focus', function (params) {
1412
+ self.$selection.attr('aria-activedescendant', params.data._resultId);
1413
+ });
1414
+
1415
+ container.on('selection:update', function (params) {
1416
+ self.update(params.data);
1417
+ });
1418
+
1419
+ container.on('open', function () {
1420
+ // When the dropdown is open, aria-expanded="true"
1421
+ self.$selection.attr('aria-expanded', 'true');
1422
+ self.$selection.attr('aria-owns', resultsId);
1423
+
1424
+ self._attachCloseHandler(container);
1425
+ });
1426
+
1427
+ container.on('close', function () {
1428
+ // When the dropdown is closed, aria-expanded="false"
1429
+ self.$selection.attr('aria-expanded', 'false');
1430
+ self.$selection.removeAttr('aria-activedescendant');
1431
+ self.$selection.removeAttr('aria-owns');
1432
+
1433
+ self.$selection.focus();
1434
+
1435
+ self._detachCloseHandler(container);
1436
+ });
1437
+
1438
+ container.on('enable', function () {
1439
+ self.$selection.attr('tabindex', self._tabindex);
1440
+ });
1441
+
1442
+ container.on('disable', function () {
1443
+ self.$selection.attr('tabindex', '-1');
1444
+ });
1445
+ };
1446
+
1447
+ BaseSelection.prototype._handleBlur = function (evt) {
1448
+ var self = this;
1449
+
1450
+ // This needs to be delayed as the active element is the body when the tab
1451
+ // key is pressed, possibly along with others.
1452
+ window.setTimeout(function () {
1453
+ // Don't trigger `blur` if the focus is still in the selection
1454
+ if (
1455
+ (document.activeElement == self.$selection[0]) ||
1456
+ ($.contains(self.$selection[0], document.activeElement))
1457
+ ) {
1458
+ return;
1459
+ }
1460
+
1461
+ self.trigger('blur', evt);
1462
+ }, 1);
1463
+ };
1464
+
1465
+ BaseSelection.prototype._attachCloseHandler = function (container) {
1466
+ var self = this;
1467
+
1468
+ $(document.body).on('mousedown.select2.' + container.id, function (e) {
1469
+ var $target = $(e.target);
1470
+
1471
+ var $select = $target.closest('.select2');
1472
+
1473
+ var $all = $('.select2.select2-container--open');
1474
+
1475
+ $all.each(function () {
1476
+ var $this = $(this);
1477
+
1478
+ if (this == $select[0]) {
1479
+ return;
1480
+ }
1481
+
1482
+ var $element = $this.data('element');
1483
+
1484
+ $element.select2('close');
1485
+ });
1486
+ });
1487
+ };
1488
+
1489
+ BaseSelection.prototype._detachCloseHandler = function (container) {
1490
+ $(document.body).off('mousedown.select2.' + container.id);
1491
+ };
1492
+
1493
+ BaseSelection.prototype.position = function ($selection, $container) {
1494
+ var $selectionContainer = $container.find('.selection');
1495
+ $selectionContainer.append($selection);
1496
+ };
1497
+
1498
+ BaseSelection.prototype.destroy = function () {
1499
+ this._detachCloseHandler(this.container);
1500
+ };
1501
+
1502
+ BaseSelection.prototype.update = function (data) {
1503
+ throw new Error('The `update` method must be defined in child classes.');
1504
+ };
1505
+
1506
+ return BaseSelection;
1507
+ });
1508
+
1509
+ S2.define('select2/selection/single',[
1510
+ 'jquery',
1511
+ './base',
1512
+ '../utils',
1513
+ '../keys'
1514
+ ], function ($, BaseSelection, Utils, KEYS) {
1515
+ function SingleSelection () {
1516
+ SingleSelection.__super__.constructor.apply(this, arguments);
1517
+ }
1518
+
1519
+ Utils.Extend(SingleSelection, BaseSelection);
1520
+
1521
+ SingleSelection.prototype.render = function () {
1522
+ var $selection = SingleSelection.__super__.render.call(this);
1523
+
1524
+ $selection.addClass('select2-selection--single');
1525
+
1526
+ $selection.html(
1527
+ '<span class="select2-selection__rendered"></span>' +
1528
+ '<span class="select2-selection__arrow" role="presentation">' +
1529
+ '<b role="presentation"></b>' +
1530
+ '</span>'
1531
+ );
1532
+
1533
+ return $selection;
1534
+ };
1535
+
1536
+ SingleSelection.prototype.bind = function (container, $container) {
1537
+ var self = this;
1538
+
1539
+ SingleSelection.__super__.bind.apply(this, arguments);
1540
+
1541
+ var id = container.id + '-container';
1542
+
1543
+ this.$selection.find('.select2-selection__rendered').attr('id', id);
1544
+ this.$selection.attr('aria-labelledby', id);
1545
+
1546
+ this.$selection.on('mousedown', function (evt) {
1547
+ // Only respond to left clicks
1548
+ if (evt.which !== 1) {
1549
+ return;
1550
+ }
1551
+
1552
+ self.trigger('toggle', {
1553
+ originalEvent: evt
1554
+ });
1555
+ });
1556
+
1557
+ this.$selection.on('focus', function (evt) {
1558
+ // User focuses on the container
1559
+ });
1560
+
1561
+ this.$selection.on('blur', function (evt) {
1562
+ // User exits the container
1563
+ });
1564
+
1565
+ container.on('focus', function (evt) {
1566
+ if (!container.isOpen()) {
1567
+ self.$selection.focus();
1568
+ }
1569
+ });
1570
+
1571
+ container.on('selection:update', function (params) {
1572
+ self.update(params.data);
1573
+ });
1574
+ };
1575
+
1576
+ SingleSelection.prototype.clear = function () {
1577
+ this.$selection.find('.select2-selection__rendered').empty();
1578
+ };
1579
+
1580
+ SingleSelection.prototype.display = function (data, container) {
1581
+ var template = this.options.get('templateSelection');
1582
+ var escapeMarkup = this.options.get('escapeMarkup');
1583
+
1584
+ return escapeMarkup(template(data, container));
1585
+ };
1586
+
1587
+ SingleSelection.prototype.selectionContainer = function () {
1588
+ return $('<span></span>');
1589
+ };
1590
+
1591
+ SingleSelection.prototype.update = function (data) {
1592
+ if (data.length === 0) {
1593
+ this.clear();
1594
+ return;
1595
+ }
1596
+
1597
+ var selection = data[0];
1598
+
1599
+ var $rendered = this.$selection.find('.select2-selection__rendered');
1600
+ var formatted = this.display(selection, $rendered);
1601
+
1602
+ $rendered.empty().append(formatted);
1603
+ $rendered.prop('title', selection.title || selection.text);
1604
+ };
1605
+
1606
+ return SingleSelection;
1607
+ });
1608
+
1609
+ S2.define('select2/selection/multiple',[
1610
+ 'jquery',
1611
+ './base',
1612
+ '../utils'
1613
+ ], function ($, BaseSelection, Utils) {
1614
+ function MultipleSelection ($element, options) {
1615
+ MultipleSelection.__super__.constructor.apply(this, arguments);
1616
+ }
1617
+
1618
+ Utils.Extend(MultipleSelection, BaseSelection);
1619
+
1620
+ MultipleSelection.prototype.render = function () {
1621
+ var $selection = MultipleSelection.__super__.render.call(this);
1622
+
1623
+ $selection.addClass('select2-selection--multiple');
1624
+
1625
+ $selection.html(
1626
+ '<ul class="select2-selection__rendered"></ul>'
1627
+ );
1628
+
1629
+ return $selection;
1630
+ };
1631
+
1632
+ MultipleSelection.prototype.bind = function (container, $container) {
1633
+ var self = this;
1634
+
1635
+ MultipleSelection.__super__.bind.apply(this, arguments);
1636
+
1637
+ this.$selection.on('click', function (evt) {
1638
+ self.trigger('toggle', {
1639
+ originalEvent: evt
1640
+ });
1641
+ });
1642
+
1643
+ this.$selection.on(
1644
+ 'click',
1645
+ '.select2-selection__choice__remove',
1646
+ function (evt) {
1647
+ // Ignore the event if it is disabled
1648
+ if (self.options.get('disabled')) {
1649
+ return;
1650
+ }
1651
+
1652
+ var $remove = $(this);
1653
+ var $selection = $remove.parent();
1654
+
1655
+ var data = $selection.data('data');
1656
+
1657
+ self.trigger('unselect', {
1658
+ originalEvent: evt,
1659
+ data: data
1660
+ });
1661
+ }
1662
+ );
1663
+ };
1664
+
1665
+ MultipleSelection.prototype.clear = function () {
1666
+ this.$selection.find('.select2-selection__rendered').empty();
1667
+ };
1668
+
1669
+ MultipleSelection.prototype.display = function (data, container) {
1670
+ var template = this.options.get('templateSelection');
1671
+ var escapeMarkup = this.options.get('escapeMarkup');
1672
+
1673
+ return escapeMarkup(template(data, container));
1674
+ };
1675
+
1676
+ MultipleSelection.prototype.selectionContainer = function () {
1677
+ var $container = $(
1678
+ '<li class="select2-selection__choice">' +
1679
+ '<span class="select2-selection__choice__remove" role="presentation">' +
1680
+ '&times;' +
1681
+ '</span>' +
1682
+ '</li>'
1683
+ );
1684
+
1685
+ return $container;
1686
+ };
1687
+
1688
+ MultipleSelection.prototype.update = function (data) {
1689
+ this.clear();
1690
+
1691
+ if (data.length === 0) {
1692
+ return;
1693
+ }
1694
+
1695
+ var $selections = [];
1696
+
1697
+ for (var d = 0; d < data.length; d++) {
1698
+ var selection = data[d];
1699
+
1700
+ var $selection = this.selectionContainer();
1701
+ var formatted = this.display(selection, $selection);
1702
+
1703
+ $selection.append(formatted);
1704
+ $selection.prop('title', selection.title || selection.text);
1705
+
1706
+ $selection.data('data', selection);
1707
+
1708
+ $selections.push($selection);
1709
+ }
1710
+
1711
+ var $rendered = this.$selection.find('.select2-selection__rendered');
1712
+
1713
+ Utils.appendMany($rendered, $selections);
1714
+ };
1715
+
1716
+ return MultipleSelection;
1717
+ });
1718
+
1719
+ S2.define('select2/selection/placeholder',[
1720
+ '../utils'
1721
+ ], function (Utils) {
1722
+ function Placeholder (decorated, $element, options) {
1723
+ this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
1724
+
1725
+ decorated.call(this, $element, options);
1726
+ }
1727
+
1728
+ Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
1729
+ if (typeof placeholder === 'string') {
1730
+ placeholder = {
1731
+ id: '',
1732
+ text: placeholder
1733
+ };
1734
+ }
1735
+
1736
+ return placeholder;
1737
+ };
1738
+
1739
+ Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
1740
+ var $placeholder = this.selectionContainer();
1741
+
1742
+ $placeholder.html(this.display(placeholder));
1743
+ $placeholder.addClass('select2-selection__placeholder')
1744
+ .removeClass('select2-selection__choice');
1745
+
1746
+ return $placeholder;
1747
+ };
1748
+
1749
+ Placeholder.prototype.update = function (decorated, data) {
1750
+ var singlePlaceholder = (
1751
+ data.length == 1 && data[0].id != this.placeholder.id
1752
+ );
1753
+ var multipleSelections = data.length > 1;
1754
+
1755
+ if (multipleSelections || singlePlaceholder) {
1756
+ return decorated.call(this, data);
1757
+ }
1758
+
1759
+ this.clear();
1760
+
1761
+ var $placeholder = this.createPlaceholder(this.placeholder);
1762
+
1763
+ this.$selection.find('.select2-selection__rendered').append($placeholder);
1764
+ };
1765
+
1766
+ return Placeholder;
1767
+ });
1768
+
1769
+ S2.define('select2/selection/allowClear',[
1770
+ 'jquery',
1771
+ '../keys'
1772
+ ], function ($, KEYS) {
1773
+ function AllowClear () { }
1774
+
1775
+ AllowClear.prototype.bind = function (decorated, container, $container) {
1776
+ var self = this;
1777
+
1778
+ decorated.call(this, container, $container);
1779
+
1780
+ if (this.placeholder == null) {
1781
+ if (this.options.get('debug') && window.console && console.error) {
1782
+ console.error(
1783
+ 'Select2: The `allowClear` option should be used in combination ' +
1784
+ 'with the `placeholder` option.'
1785
+ );
1786
+ }
1787
+ }
1788
+
1789
+ this.$selection.on('mousedown', '.select2-selection__clear',
1790
+ function (evt) {
1791
+ self._handleClear(evt);
1792
+ });
1793
+
1794
+ container.on('keypress', function (evt) {
1795
+ self._handleKeyboardClear(evt, container);
1796
+ });
1797
+ };
1798
+
1799
+ AllowClear.prototype._handleClear = function (_, evt) {
1800
+ // Ignore the event if it is disabled
1801
+ if (this.options.get('disabled')) {
1802
+ return;
1803
+ }
1804
+
1805
+ var $clear = this.$selection.find('.select2-selection__clear');
1806
+
1807
+ // Ignore the event if nothing has been selected
1808
+ if ($clear.length === 0) {
1809
+ return;
1810
+ }
1811
+
1812
+ evt.stopPropagation();
1813
+
1814
+ var data = $clear.data('data');
1815
+
1816
+ for (var d = 0; d < data.length; d++) {
1817
+ var unselectData = {
1818
+ data: data[d]
1819
+ };
1820
+
1821
+ // Trigger the `unselect` event, so people can prevent it from being
1822
+ // cleared.
1823
+ this.trigger('unselect', unselectData);
1824
+
1825
+ // If the event was prevented, don't clear it out.
1826
+ if (unselectData.prevented) {
1827
+ return;
1828
+ }
1829
+ }
1830
+
1831
+ this.$element.val(this.placeholder.id).trigger('change');
1832
+
1833
+ this.trigger('toggle', {});
1834
+ };
1835
+
1836
+ AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
1837
+ if (container.isOpen()) {
1838
+ return;
1839
+ }
1840
+
1841
+ if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
1842
+ this._handleClear(evt);
1843
+ }
1844
+ };
1845
+
1846
+ AllowClear.prototype.update = function (decorated, data) {
1847
+ decorated.call(this, data);
1848
+
1849
+ if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
1850
+ data.length === 0) {
1851
+ return;
1852
+ }
1853
+
1854
+ var $remove = $(
1855
+ '<span class="select2-selection__clear">' +
1856
+ '&times;' +
1857
+ '</span>'
1858
+ );
1859
+ $remove.data('data', data);
1860
+
1861
+ this.$selection.find('.select2-selection__rendered').prepend($remove);
1862
+ };
1863
+
1864
+ return AllowClear;
1865
+ });
1866
+
1867
+ S2.define('select2/selection/search',[
1868
+ 'jquery',
1869
+ '../utils',
1870
+ '../keys'
1871
+ ], function ($, Utils, KEYS) {
1872
+ function Search (decorated, $element, options) {
1873
+ decorated.call(this, $element, options);
1874
+ }
1875
+
1876
+ Search.prototype.render = function (decorated) {
1877
+ var $search = $(
1878
+ '<li class="select2-search select2-search--inline">' +
1879
+ '<input class="select2-search__field" type="search" tabindex="-1"' +
1880
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
1881
+ ' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
1882
+ '</li>'
1883
+ );
1884
+
1885
+ this.$searchContainer = $search;
1886
+ this.$search = $search.find('input');
1887
+
1888
+ var $rendered = decorated.call(this);
1889
+
1890
+ this._transferTabIndex();
1891
+
1892
+ return $rendered;
1893
+ };
1894
+
1895
+ Search.prototype.bind = function (decorated, container, $container) {
1896
+ var self = this;
1897
+
1898
+ decorated.call(this, container, $container);
1899
+
1900
+ container.on('open', function () {
1901
+ self.$search.trigger('focus');
1902
+ });
1903
+
1904
+ container.on('close', function () {
1905
+ self.$search.val('');
1906
+ self.$search.removeAttr('aria-activedescendant');
1907
+ self.$search.trigger('focus');
1908
+ });
1909
+
1910
+ container.on('enable', function () {
1911
+ self.$search.prop('disabled', false);
1912
+
1913
+ self._transferTabIndex();
1914
+ });
1915
+
1916
+ container.on('disable', function () {
1917
+ self.$search.prop('disabled', true);
1918
+ });
1919
+
1920
+ container.on('focus', function (evt) {
1921
+ self.$search.trigger('focus');
1922
+ });
1923
+
1924
+ container.on('results:focus', function (params) {
1925
+ self.$search.attr('aria-activedescendant', params.id);
1926
+ });
1927
+
1928
+ this.$selection.on('focusin', '.select2-search--inline', function (evt) {
1929
+ self.trigger('focus', evt);
1930
+ });
1931
+
1932
+ this.$selection.on('focusout', '.select2-search--inline', function (evt) {
1933
+ self._handleBlur(evt);
1934
+ });
1935
+
1936
+ this.$selection.on('keydown', '.select2-search--inline', function (evt) {
1937
+ evt.stopPropagation();
1938
+
1939
+ self.trigger('keypress', evt);
1940
+
1941
+ self._keyUpPrevented = evt.isDefaultPrevented();
1942
+
1943
+ var key = evt.which;
1944
+
1945
+ if (key === KEYS.BACKSPACE && self.$search.val() === '') {
1946
+ var $previousChoice = self.$searchContainer
1947
+ .prev('.select2-selection__choice');
1948
+
1949
+ if ($previousChoice.length > 0) {
1950
+ var item = $previousChoice.data('data');
1951
+
1952
+ self.searchRemoveChoice(item);
1953
+
1954
+ evt.preventDefault();
1955
+ }
1956
+ }
1957
+ });
1958
+
1959
+ // Try to detect the IE version should the `documentMode` property that
1960
+ // is stored on the document. This is only implemented in IE and is
1961
+ // slightly cleaner than doing a user agent check.
1962
+ // This property is not available in Edge, but Edge also doesn't have
1963
+ // this bug.
1964
+ var msie = document.documentMode;
1965
+ var disableInputEvents = msie && msie <= 11;
1966
+
1967
+ // Workaround for browsers which do not support the `input` event
1968
+ // This will prevent double-triggering of events for browsers which support
1969
+ // both the `keyup` and `input` events.
1970
+ this.$selection.on(
1971
+ 'input.searchcheck',
1972
+ '.select2-search--inline',
1973
+ function (evt) {
1974
+ // IE will trigger the `input` event when a placeholder is used on a
1975
+ // search box. To get around this issue, we are forced to ignore all
1976
+ // `input` events in IE and keep using `keyup`.
1977
+ if (disableInputEvents) {
1978
+ self.$selection.off('input.search input.searchcheck');
1979
+ return;
1980
+ }
1981
+
1982
+ // Unbind the duplicated `keyup` event
1983
+ self.$selection.off('keyup.search');
1984
+ }
1985
+ );
1986
+
1987
+ this.$selection.on(
1988
+ 'keyup.search input.search',
1989
+ '.select2-search--inline',
1990
+ function (evt) {
1991
+ // IE will trigger the `input` event when a placeholder is used on a
1992
+ // search box. To get around this issue, we are forced to ignore all
1993
+ // `input` events in IE and keep using `keyup`.
1994
+ if (disableInputEvents && evt.type === 'input') {
1995
+ self.$selection.off('input.search input.searchcheck');
1996
+ return;
1997
+ }
1998
+
1999
+ var key = evt.which;
2000
+
2001
+ // We can freely ignore events from modifier keys
2002
+ if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
2003
+ return;
2004
+ }
2005
+
2006
+ // Tabbing will be handled during the `keydown` phase
2007
+ if (key == KEYS.TAB) {
2008
+ return;
2009
+ }
2010
+
2011
+ self.handleSearch(evt);
2012
+ }
2013
+ );
2014
+ };
2015
+
2016
+ /**
2017
+ * This method will transfer the tabindex attribute from the rendered
2018
+ * selection to the search box. This allows for the search box to be used as
2019
+ * the primary focus instead of the selection container.
2020
+ *
2021
+ * @private
2022
+ */
2023
+ Search.prototype._transferTabIndex = function (decorated) {
2024
+ this.$search.attr('tabindex', this.$selection.attr('tabindex'));
2025
+ this.$selection.attr('tabindex', '-1');
2026
+ };
2027
+
2028
+ Search.prototype.createPlaceholder = function (decorated, placeholder) {
2029
+ this.$search.attr('placeholder', placeholder.text);
2030
+ };
2031
+
2032
+ Search.prototype.update = function (decorated, data) {
2033
+ var searchHadFocus = this.$search[0] == document.activeElement;
2034
+
2035
+ this.$search.attr('placeholder', '');
2036
+
2037
+ decorated.call(this, data);
2038
+
2039
+ this.$selection.find('.select2-selection__rendered')
2040
+ .append(this.$searchContainer);
2041
+
2042
+ this.resizeSearch();
2043
+ if (searchHadFocus) {
2044
+ this.$search.focus();
2045
+ }
2046
+ };
2047
+
2048
+ Search.prototype.handleSearch = function () {
2049
+ this.resizeSearch();
2050
+
2051
+ if (!this._keyUpPrevented) {
2052
+ var input = this.$search.val();
2053
+
2054
+ this.trigger('query', {
2055
+ term: input
2056
+ });
2057
+ }
2058
+
2059
+ this._keyUpPrevented = false;
2060
+ };
2061
+
2062
+ Search.prototype.searchRemoveChoice = function (decorated, item) {
2063
+ this.trigger('unselect', {
2064
+ data: item
2065
+ });
2066
+
2067
+ this.$search.val(item.text);
2068
+ this.handleSearch();
2069
+ };
2070
+
2071
+ Search.prototype.resizeSearch = function () {
2072
+ this.$search.css('width', '25px');
2073
+
2074
+ var width = '';
2075
+
2076
+ if (this.$search.attr('placeholder') !== '') {
2077
+ width = this.$selection.find('.select2-selection__rendered').innerWidth();
2078
+ } else {
2079
+ var minimumWidth = this.$search.val().length + 1;
2080
+
2081
+ width = (minimumWidth * 0.75) + 'em';
2082
+ }
2083
+
2084
+ this.$search.css('width', width);
2085
+ };
2086
+
2087
+ return Search;
2088
+ });
2089
+
2090
+ S2.define('select2/selection/eventRelay',[
2091
+ 'jquery'
2092
+ ], function ($) {
2093
+ function EventRelay () { }
2094
+
2095
+ EventRelay.prototype.bind = function (decorated, container, $container) {
2096
+ var self = this;
2097
+ var relayEvents = [
2098
+ 'open', 'opening',
2099
+ 'close', 'closing',
2100
+ 'select', 'selecting',
2101
+ 'unselect', 'unselecting'
2102
+ ];
2103
+
2104
+ var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
2105
+
2106
+ decorated.call(this, container, $container);
2107
+
2108
+ container.on('*', function (name, params) {
2109
+ // Ignore events that should not be relayed
2110
+ if ($.inArray(name, relayEvents) === -1) {
2111
+ return;
2112
+ }
2113
+
2114
+ // The parameters should always be an object
2115
+ params = params || {};
2116
+
2117
+ // Generate the jQuery event for the Select2 event
2118
+ var evt = $.Event('select2:' + name, {
2119
+ params: params
2120
+ });
2121
+
2122
+ self.$element.trigger(evt);
2123
+
2124
+ // Only handle preventable events if it was one
2125
+ if ($.inArray(name, preventableEvents) === -1) {
2126
+ return;
2127
+ }
2128
+
2129
+ params.prevented = evt.isDefaultPrevented();
2130
+ });
2131
+ };
2132
+
2133
+ return EventRelay;
2134
+ });
2135
+
2136
+ S2.define('select2/translation',[
2137
+ 'jquery',
2138
+ 'require'
2139
+ ], function ($, require) {
2140
+ function Translation (dict) {
2141
+ this.dict = dict || {};
2142
+ }
2143
+
2144
+ Translation.prototype.all = function () {
2145
+ return this.dict;
2146
+ };
2147
+
2148
+ Translation.prototype.get = function (key) {
2149
+ return this.dict[key];
2150
+ };
2151
+
2152
+ Translation.prototype.extend = function (translation) {
2153
+ this.dict = $.extend({}, translation.all(), this.dict);
2154
+ };
2155
+
2156
+ // Static functions
2157
+
2158
+ Translation._cache = {};
2159
+
2160
+ Translation.loadPath = function (path) {
2161
+ if (!(path in Translation._cache)) {
2162
+ var translations = require(path);
2163
+
2164
+ Translation._cache[path] = translations;
2165
+ }
2166
+
2167
+ return new Translation(Translation._cache[path]);
2168
+ };
2169
+
2170
+ return Translation;
2171
+ });
2172
+
2173
+ S2.define('select2/diacritics',[
2174
+
2175
+ ], function () {
2176
+ var diacritics = {
2177
+ '\u24B6': 'A',
2178
+ '\uFF21': 'A',
2179
+ '\u00C0': 'A',
2180
+ '\u00C1': 'A',
2181
+ '\u00C2': 'A',
2182
+ '\u1EA6': 'A',
2183
+ '\u1EA4': 'A',
2184
+ '\u1EAA': 'A',
2185
+ '\u1EA8': 'A',
2186
+ '\u00C3': 'A',
2187
+ '\u0100': 'A',
2188
+ '\u0102': 'A',
2189
+ '\u1EB0': 'A',
2190
+ '\u1EAE': 'A',
2191
+ '\u1EB4': 'A',
2192
+ '\u1EB2': 'A',
2193
+ '\u0226': 'A',
2194
+ '\u01E0': 'A',
2195
+ '\u00C4': 'A',
2196
+ '\u01DE': 'A',
2197
+ '\u1EA2': 'A',
2198
+ '\u00C5': 'A',
2199
+ '\u01FA': 'A',
2200
+ '\u01CD': 'A',
2201
+ '\u0200': 'A',
2202
+ '\u0202': 'A',
2203
+ '\u1EA0': 'A',
2204
+ '\u1EAC': 'A',
2205
+ '\u1EB6': 'A',
2206
+ '\u1E00': 'A',
2207
+ '\u0104': 'A',
2208
+ '\u023A': 'A',
2209
+ '\u2C6F': 'A',
2210
+ '\uA732': 'AA',
2211
+ '\u00C6': 'AE',
2212
+ '\u01FC': 'AE',
2213
+ '\u01E2': 'AE',
2214
+ '\uA734': 'AO',
2215
+ '\uA736': 'AU',
2216
+ '\uA738': 'AV',
2217
+ '\uA73A': 'AV',
2218
+ '\uA73C': 'AY',
2219
+ '\u24B7': 'B',
2220
+ '\uFF22': 'B',
2221
+ '\u1E02': 'B',
2222
+ '\u1E04': 'B',
2223
+ '\u1E06': 'B',
2224
+ '\u0243': 'B',
2225
+ '\u0182': 'B',
2226
+ '\u0181': 'B',
2227
+ '\u24B8': 'C',
2228
+ '\uFF23': 'C',
2229
+ '\u0106': 'C',
2230
+ '\u0108': 'C',
2231
+ '\u010A': 'C',
2232
+ '\u010C': 'C',
2233
+ '\u00C7': 'C',
2234
+ '\u1E08': 'C',
2235
+ '\u0187': 'C',
2236
+ '\u023B': 'C',
2237
+ '\uA73E': 'C',
2238
+ '\u24B9': 'D',
2239
+ '\uFF24': 'D',
2240
+ '\u1E0A': 'D',
2241
+ '\u010E': 'D',
2242
+ '\u1E0C': 'D',
2243
+ '\u1E10': 'D',
2244
+ '\u1E12': 'D',
2245
+ '\u1E0E': 'D',
2246
+ '\u0110': 'D',
2247
+ '\u018B': 'D',
2248
+ '\u018A': 'D',
2249
+ '\u0189': 'D',
2250
+ '\uA779': 'D',
2251
+ '\u01F1': 'DZ',
2252
+ '\u01C4': 'DZ',
2253
+ '\u01F2': 'Dz',
2254
+ '\u01C5': 'Dz',
2255
+ '\u24BA': 'E',
2256
+ '\uFF25': 'E',
2257
+ '\u00C8': 'E',
2258
+ '\u00C9': 'E',
2259
+ '\u00CA': 'E',
2260
+ '\u1EC0': 'E',
2261
+ '\u1EBE': 'E',
2262
+ '\u1EC4': 'E',
2263
+ '\u1EC2': 'E',
2264
+ '\u1EBC': 'E',
2265
+ '\u0112': 'E',
2266
+ '\u1E14': 'E',
2267
+ '\u1E16': 'E',
2268
+ '\u0114': 'E',
2269
+ '\u0116': 'E',
2270
+ '\u00CB': 'E',
2271
+ '\u1EBA': 'E',
2272
+ '\u011A': 'E',
2273
+ '\u0204': 'E',
2274
+ '\u0206': 'E',
2275
+ '\u1EB8': 'E',
2276
+ '\u1EC6': 'E',
2277
+ '\u0228': 'E',
2278
+ '\u1E1C': 'E',
2279
+ '\u0118': 'E',
2280
+ '\u1E18': 'E',
2281
+ '\u1E1A': 'E',
2282
+ '\u0190': 'E',
2283
+ '\u018E': 'E',
2284
+ '\u24BB': 'F',
2285
+ '\uFF26': 'F',
2286
+ '\u1E1E': 'F',
2287
+ '\u0191': 'F',
2288
+ '\uA77B': 'F',
2289
+ '\u24BC': 'G',
2290
+ '\uFF27': 'G',
2291
+ '\u01F4': 'G',
2292
+ '\u011C': 'G',
2293
+ '\u1E20': 'G',
2294
+ '\u011E': 'G',
2295
+ '\u0120': 'G',
2296
+ '\u01E6': 'G',
2297
+ '\u0122': 'G',
2298
+ '\u01E4': 'G',
2299
+ '\u0193': 'G',
2300
+ '\uA7A0': 'G',
2301
+ '\uA77D': 'G',
2302
+ '\uA77E': 'G',
2303
+ '\u24BD': 'H',
2304
+ '\uFF28': 'H',
2305
+ '\u0124': 'H',
2306
+ '\u1E22': 'H',
2307
+ '\u1E26': 'H',
2308
+ '\u021E': 'H',
2309
+ '\u1E24': 'H',
2310
+ '\u1E28': 'H',
2311
+ '\u1E2A': 'H',
2312
+ '\u0126': 'H',
2313
+ '\u2C67': 'H',
2314
+ '\u2C75': 'H',
2315
+ '\uA78D': 'H',
2316
+ '\u24BE': 'I',
2317
+ '\uFF29': 'I',
2318
+ '\u00CC': 'I',
2319
+ '\u00CD': 'I',
2320
+ '\u00CE': 'I',
2321
+ '\u0128': 'I',
2322
+ '\u012A': 'I',
2323
+ '\u012C': 'I',
2324
+ '\u0130': 'I',
2325
+ '\u00CF': 'I',
2326
+ '\u1E2E': 'I',
2327
+ '\u1EC8': 'I',
2328
+ '\u01CF': 'I',
2329
+ '\u0208': 'I',
2330
+ '\u020A': 'I',
2331
+ '\u1ECA': 'I',
2332
+ '\u012E': 'I',
2333
+ '\u1E2C': 'I',
2334
+ '\u0197': 'I',
2335
+ '\u24BF': 'J',
2336
+ '\uFF2A': 'J',
2337
+ '\u0134': 'J',
2338
+ '\u0248': 'J',
2339
+ '\u24C0': 'K',
2340
+ '\uFF2B': 'K',
2341
+ '\u1E30': 'K',
2342
+ '\u01E8': 'K',
2343
+ '\u1E32': 'K',
2344
+ '\u0136': 'K',
2345
+ '\u1E34': 'K',
2346
+ '\u0198': 'K',
2347
+ '\u2C69': 'K',
2348
+ '\uA740': 'K',
2349
+ '\uA742': 'K',
2350
+ '\uA744': 'K',
2351
+ '\uA7A2': 'K',
2352
+ '\u24C1': 'L',
2353
+ '\uFF2C': 'L',
2354
+ '\u013F': 'L',
2355
+ '\u0139': 'L',
2356
+ '\u013D': 'L',
2357
+ '\u1E36': 'L',
2358
+ '\u1E38': 'L',
2359
+ '\u013B': 'L',
2360
+ '\u1E3C': 'L',
2361
+ '\u1E3A': 'L',
2362
+ '\u0141': 'L',
2363
+ '\u023D': 'L',
2364
+ '\u2C62': 'L',
2365
+ '\u2C60': 'L',
2366
+ '\uA748': 'L',
2367
+ '\uA746': 'L',
2368
+ '\uA780': 'L',
2369
+ '\u01C7': 'LJ',
2370
+ '\u01C8': 'Lj',
2371
+ '\u24C2': 'M',
2372
+ '\uFF2D': 'M',
2373
+ '\u1E3E': 'M',
2374
+ '\u1E40': 'M',
2375
+ '\u1E42': 'M',
2376
+ '\u2C6E': 'M',
2377
+ '\u019C': 'M',
2378
+ '\u24C3': 'N',
2379
+ '\uFF2E': 'N',
2380
+ '\u01F8': 'N',
2381
+ '\u0143': 'N',
2382
+ '\u00D1': 'N',
2383
+ '\u1E44': 'N',
2384
+ '\u0147': 'N',
2385
+ '\u1E46': 'N',
2386
+ '\u0145': 'N',
2387
+ '\u1E4A': 'N',
2388
+ '\u1E48': 'N',
2389
+ '\u0220': 'N',
2390
+ '\u019D': 'N',
2391
+ '\uA790': 'N',
2392
+ '\uA7A4': 'N',
2393
+ '\u01CA': 'NJ',
2394
+ '\u01CB': 'Nj',
2395
+ '\u24C4': 'O',
2396
+ '\uFF2F': 'O',
2397
+ '\u00D2': 'O',
2398
+ '\u00D3': 'O',
2399
+ '\u00D4': 'O',
2400
+ '\u1ED2': 'O',
2401
+ '\u1ED0': 'O',
2402
+ '\u1ED6': 'O',
2403
+ '\u1ED4': 'O',
2404
+ '\u00D5': 'O',
2405
+ '\u1E4C': 'O',
2406
+ '\u022C': 'O',
2407
+ '\u1E4E': 'O',
2408
+ '\u014C': 'O',
2409
+ '\u1E50': 'O',
2410
+ '\u1E52': 'O',
2411
+ '\u014E': 'O',
2412
+ '\u022E': 'O',
2413
+ '\u0230': 'O',
2414
+ '\u00D6': 'O',
2415
+ '\u022A': 'O',
2416
+ '\u1ECE': 'O',
2417
+ '\u0150': 'O',
2418
+ '\u01D1': 'O',
2419
+ '\u020C': 'O',
2420
+ '\u020E': 'O',
2421
+ '\u01A0': 'O',
2422
+ '\u1EDC': 'O',
2423
+ '\u1EDA': 'O',
2424
+ '\u1EE0': 'O',
2425
+ '\u1EDE': 'O',
2426
+ '\u1EE2': 'O',
2427
+ '\u1ECC': 'O',
2428
+ '\u1ED8': 'O',
2429
+ '\u01EA': 'O',
2430
+ '\u01EC': 'O',
2431
+ '\u00D8': 'O',
2432
+ '\u01FE': 'O',
2433
+ '\u0186': 'O',
2434
+ '\u019F': 'O',
2435
+ '\uA74A': 'O',
2436
+ '\uA74C': 'O',
2437
+ '\u01A2': 'OI',
2438
+ '\uA74E': 'OO',
2439
+ '\u0222': 'OU',
2440
+ '\u24C5': 'P',
2441
+ '\uFF30': 'P',
2442
+ '\u1E54': 'P',
2443
+ '\u1E56': 'P',
2444
+ '\u01A4': 'P',
2445
+ '\u2C63': 'P',
2446
+ '\uA750': 'P',
2447
+ '\uA752': 'P',
2448
+ '\uA754': 'P',
2449
+ '\u24C6': 'Q',
2450
+ '\uFF31': 'Q',
2451
+ '\uA756': 'Q',
2452
+ '\uA758': 'Q',
2453
+ '\u024A': 'Q',
2454
+ '\u24C7': 'R',
2455
+ '\uFF32': 'R',
2456
+ '\u0154': 'R',
2457
+ '\u1E58': 'R',
2458
+ '\u0158': 'R',
2459
+ '\u0210': 'R',
2460
+ '\u0212': 'R',
2461
+ '\u1E5A': 'R',
2462
+ '\u1E5C': 'R',
2463
+ '\u0156': 'R',
2464
+ '\u1E5E': 'R',
2465
+ '\u024C': 'R',
2466
+ '\u2C64': 'R',
2467
+ '\uA75A': 'R',
2468
+ '\uA7A6': 'R',
2469
+ '\uA782': 'R',
2470
+ '\u24C8': 'S',
2471
+ '\uFF33': 'S',
2472
+ '\u1E9E': 'S',
2473
+ '\u015A': 'S',
2474
+ '\u1E64': 'S',
2475
+ '\u015C': 'S',
2476
+ '\u1E60': 'S',
2477
+ '\u0160': 'S',
2478
+ '\u1E66': 'S',
2479
+ '\u1E62': 'S',
2480
+ '\u1E68': 'S',
2481
+ '\u0218': 'S',
2482
+ '\u015E': 'S',
2483
+ '\u2C7E': 'S',
2484
+ '\uA7A8': 'S',
2485
+ '\uA784': 'S',
2486
+ '\u24C9': 'T',
2487
+ '\uFF34': 'T',
2488
+ '\u1E6A': 'T',
2489
+ '\u0164': 'T',
2490
+ '\u1E6C': 'T',
2491
+ '\u021A': 'T',
2492
+ '\u0162': 'T',
2493
+ '\u1E70': 'T',
2494
+ '\u1E6E': 'T',
2495
+ '\u0166': 'T',
2496
+ '\u01AC': 'T',
2497
+ '\u01AE': 'T',
2498
+ '\u023E': 'T',
2499
+ '\uA786': 'T',
2500
+ '\uA728': 'TZ',
2501
+ '\u24CA': 'U',
2502
+ '\uFF35': 'U',
2503
+ '\u00D9': 'U',
2504
+ '\u00DA': 'U',
2505
+ '\u00DB': 'U',
2506
+ '\u0168': 'U',
2507
+ '\u1E78': 'U',
2508
+ '\u016A': 'U',
2509
+ '\u1E7A': 'U',
2510
+ '\u016C': 'U',
2511
+ '\u00DC': 'U',
2512
+ '\u01DB': 'U',
2513
+ '\u01D7': 'U',
2514
+ '\u01D5': 'U',
2515
+ '\u01D9': 'U',
2516
+ '\u1EE6': 'U',
2517
+ '\u016E': 'U',
2518
+ '\u0170': 'U',
2519
+ '\u01D3': 'U',
2520
+ '\u0214': 'U',
2521
+ '\u0216': 'U',
2522
+ '\u01AF': 'U',
2523
+ '\u1EEA': 'U',
2524
+ '\u1EE8': 'U',
2525
+ '\u1EEE': 'U',
2526
+ '\u1EEC': 'U',
2527
+ '\u1EF0': 'U',
2528
+ '\u1EE4': 'U',
2529
+ '\u1E72': 'U',
2530
+ '\u0172': 'U',
2531
+ '\u1E76': 'U',
2532
+ '\u1E74': 'U',
2533
+ '\u0244': 'U',
2534
+ '\u24CB': 'V',
2535
+ '\uFF36': 'V',
2536
+ '\u1E7C': 'V',
2537
+ '\u1E7E': 'V',
2538
+ '\u01B2': 'V',
2539
+ '\uA75E': 'V',
2540
+ '\u0245': 'V',
2541
+ '\uA760': 'VY',
2542
+ '\u24CC': 'W',
2543
+ '\uFF37': 'W',
2544
+ '\u1E80': 'W',
2545
+ '\u1E82': 'W',
2546
+ '\u0174': 'W',
2547
+ '\u1E86': 'W',
2548
+ '\u1E84': 'W',
2549
+ '\u1E88': 'W',
2550
+ '\u2C72': 'W',
2551
+ '\u24CD': 'X',
2552
+ '\uFF38': 'X',
2553
+ '\u1E8A': 'X',
2554
+ '\u1E8C': 'X',
2555
+ '\u24CE': 'Y',
2556
+ '\uFF39': 'Y',
2557
+ '\u1EF2': 'Y',
2558
+ '\u00DD': 'Y',
2559
+ '\u0176': 'Y',
2560
+ '\u1EF8': 'Y',
2561
+ '\u0232': 'Y',
2562
+ '\u1E8E': 'Y',
2563
+ '\u0178': 'Y',
2564
+ '\u1EF6': 'Y',
2565
+ '\u1EF4': 'Y',
2566
+ '\u01B3': 'Y',
2567
+ '\u024E': 'Y',
2568
+ '\u1EFE': 'Y',
2569
+ '\u24CF': 'Z',
2570
+ '\uFF3A': 'Z',
2571
+ '\u0179': 'Z',
2572
+ '\u1E90': 'Z',
2573
+ '\u017B': 'Z',
2574
+ '\u017D': 'Z',
2575
+ '\u1E92': 'Z',
2576
+ '\u1E94': 'Z',
2577
+ '\u01B5': 'Z',
2578
+ '\u0224': 'Z',
2579
+ '\u2C7F': 'Z',
2580
+ '\u2C6B': 'Z',
2581
+ '\uA762': 'Z',
2582
+ '\u24D0': 'a',
2583
+ '\uFF41': 'a',
2584
+ '\u1E9A': 'a',
2585
+ '\u00E0': 'a',
2586
+ '\u00E1': 'a',
2587
+ '\u00E2': 'a',
2588
+ '\u1EA7': 'a',
2589
+ '\u1EA5': 'a',
2590
+ '\u1EAB': 'a',
2591
+ '\u1EA9': 'a',
2592
+ '\u00E3': 'a',
2593
+ '\u0101': 'a',
2594
+ '\u0103': 'a',
2595
+ '\u1EB1': 'a',
2596
+ '\u1EAF': 'a',
2597
+ '\u1EB5': 'a',
2598
+ '\u1EB3': 'a',
2599
+ '\u0227': 'a',
2600
+ '\u01E1': 'a',
2601
+ '\u00E4': 'a',
2602
+ '\u01DF': 'a',
2603
+ '\u1EA3': 'a',
2604
+ '\u00E5': 'a',
2605
+ '\u01FB': 'a',
2606
+ '\u01CE': 'a',
2607
+ '\u0201': 'a',
2608
+ '\u0203': 'a',
2609
+ '\u1EA1': 'a',
2610
+ '\u1EAD': 'a',
2611
+ '\u1EB7': 'a',
2612
+ '\u1E01': 'a',
2613
+ '\u0105': 'a',
2614
+ '\u2C65': 'a',
2615
+ '\u0250': 'a',
2616
+ '\uA733': 'aa',
2617
+ '\u00E6': 'ae',
2618
+ '\u01FD': 'ae',
2619
+ '\u01E3': 'ae',
2620
+ '\uA735': 'ao',
2621
+ '\uA737': 'au',
2622
+ '\uA739': 'av',
2623
+ '\uA73B': 'av',
2624
+ '\uA73D': 'ay',
2625
+ '\u24D1': 'b',
2626
+ '\uFF42': 'b',
2627
+ '\u1E03': 'b',
2628
+ '\u1E05': 'b',
2629
+ '\u1E07': 'b',
2630
+ '\u0180': 'b',
2631
+ '\u0183': 'b',
2632
+ '\u0253': 'b',
2633
+ '\u24D2': 'c',
2634
+ '\uFF43': 'c',
2635
+ '\u0107': 'c',
2636
+ '\u0109': 'c',
2637
+ '\u010B': 'c',
2638
+ '\u010D': 'c',
2639
+ '\u00E7': 'c',
2640
+ '\u1E09': 'c',
2641
+ '\u0188': 'c',
2642
+ '\u023C': 'c',
2643
+ '\uA73F': 'c',
2644
+ '\u2184': 'c',
2645
+ '\u24D3': 'd',
2646
+ '\uFF44': 'd',
2647
+ '\u1E0B': 'd',
2648
+ '\u010F': 'd',
2649
+ '\u1E0D': 'd',
2650
+ '\u1E11': 'd',
2651
+ '\u1E13': 'd',
2652
+ '\u1E0F': 'd',
2653
+ '\u0111': 'd',
2654
+ '\u018C': 'd',
2655
+ '\u0256': 'd',
2656
+ '\u0257': 'd',
2657
+ '\uA77A': 'd',
2658
+ '\u01F3': 'dz',
2659
+ '\u01C6': 'dz',
2660
+ '\u24D4': 'e',
2661
+ '\uFF45': 'e',
2662
+ '\u00E8': 'e',
2663
+ '\u00E9': 'e',
2664
+ '\u00EA': 'e',
2665
+ '\u1EC1': 'e',
2666
+ '\u1EBF': 'e',
2667
+ '\u1EC5': 'e',
2668
+ '\u1EC3': 'e',
2669
+ '\u1EBD': 'e',
2670
+ '\u0113': 'e',
2671
+ '\u1E15': 'e',
2672
+ '\u1E17': 'e',
2673
+ '\u0115': 'e',
2674
+ '\u0117': 'e',
2675
+ '\u00EB': 'e',
2676
+ '\u1EBB': 'e',
2677
+ '\u011B': 'e',
2678
+ '\u0205': 'e',
2679
+ '\u0207': 'e',
2680
+ '\u1EB9': 'e',
2681
+ '\u1EC7': 'e',
2682
+ '\u0229': 'e',
2683
+ '\u1E1D': 'e',
2684
+ '\u0119': 'e',
2685
+ '\u1E19': 'e',
2686
+ '\u1E1B': 'e',
2687
+ '\u0247': 'e',
2688
+ '\u025B': 'e',
2689
+ '\u01DD': 'e',
2690
+ '\u24D5': 'f',
2691
+ '\uFF46': 'f',
2692
+ '\u1E1F': 'f',
2693
+ '\u0192': 'f',
2694
+ '\uA77C': 'f',
2695
+ '\u24D6': 'g',
2696
+ '\uFF47': 'g',
2697
+ '\u01F5': 'g',
2698
+ '\u011D': 'g',
2699
+ '\u1E21': 'g',
2700
+ '\u011F': 'g',
2701
+ '\u0121': 'g',
2702
+ '\u01E7': 'g',
2703
+ '\u0123': 'g',
2704
+ '\u01E5': 'g',
2705
+ '\u0260': 'g',
2706
+ '\uA7A1': 'g',
2707
+ '\u1D79': 'g',
2708
+ '\uA77F': 'g',
2709
+ '\u24D7': 'h',
2710
+ '\uFF48': 'h',
2711
+ '\u0125': 'h',
2712
+ '\u1E23': 'h',
2713
+ '\u1E27': 'h',
2714
+ '\u021F': 'h',
2715
+ '\u1E25': 'h',
2716
+ '\u1E29': 'h',
2717
+ '\u1E2B': 'h',
2718
+ '\u1E96': 'h',
2719
+ '\u0127': 'h',
2720
+ '\u2C68': 'h',
2721
+ '\u2C76': 'h',
2722
+ '\u0265': 'h',
2723
+ '\u0195': 'hv',
2724
+ '\u24D8': 'i',
2725
+ '\uFF49': 'i',
2726
+ '\u00EC': 'i',
2727
+ '\u00ED': 'i',
2728
+ '\u00EE': 'i',
2729
+ '\u0129': 'i',
2730
+ '\u012B': 'i',
2731
+ '\u012D': 'i',
2732
+ '\u00EF': 'i',
2733
+ '\u1E2F': 'i',
2734
+ '\u1EC9': 'i',
2735
+ '\u01D0': 'i',
2736
+ '\u0209': 'i',
2737
+ '\u020B': 'i',
2738
+ '\u1ECB': 'i',
2739
+ '\u012F': 'i',
2740
+ '\u1E2D': 'i',
2741
+ '\u0268': 'i',
2742
+ '\u0131': 'i',
2743
+ '\u24D9': 'j',
2744
+ '\uFF4A': 'j',
2745
+ '\u0135': 'j',
2746
+ '\u01F0': 'j',
2747
+ '\u0249': 'j',
2748
+ '\u24DA': 'k',
2749
+ '\uFF4B': 'k',
2750
+ '\u1E31': 'k',
2751
+ '\u01E9': 'k',
2752
+ '\u1E33': 'k',
2753
+ '\u0137': 'k',
2754
+ '\u1E35': 'k',
2755
+ '\u0199': 'k',
2756
+ '\u2C6A': 'k',
2757
+ '\uA741': 'k',
2758
+ '\uA743': 'k',
2759
+ '\uA745': 'k',
2760
+ '\uA7A3': 'k',
2761
+ '\u24DB': 'l',
2762
+ '\uFF4C': 'l',
2763
+ '\u0140': 'l',
2764
+ '\u013A': 'l',
2765
+ '\u013E': 'l',
2766
+ '\u1E37': 'l',
2767
+ '\u1E39': 'l',
2768
+ '\u013C': 'l',
2769
+ '\u1E3D': 'l',
2770
+ '\u1E3B': 'l',
2771
+ '\u017F': 'l',
2772
+ '\u0142': 'l',
2773
+ '\u019A': 'l',
2774
+ '\u026B': 'l',
2775
+ '\u2C61': 'l',
2776
+ '\uA749': 'l',
2777
+ '\uA781': 'l',
2778
+ '\uA747': 'l',
2779
+ '\u01C9': 'lj',
2780
+ '\u24DC': 'm',
2781
+ '\uFF4D': 'm',
2782
+ '\u1E3F': 'm',
2783
+ '\u1E41': 'm',
2784
+ '\u1E43': 'm',
2785
+ '\u0271': 'm',
2786
+ '\u026F': 'm',
2787
+ '\u24DD': 'n',
2788
+ '\uFF4E': 'n',
2789
+ '\u01F9': 'n',
2790
+ '\u0144': 'n',
2791
+ '\u00F1': 'n',
2792
+ '\u1E45': 'n',
2793
+ '\u0148': 'n',
2794
+ '\u1E47': 'n',
2795
+ '\u0146': 'n',
2796
+ '\u1E4B': 'n',
2797
+ '\u1E49': 'n',
2798
+ '\u019E': 'n',
2799
+ '\u0272': 'n',
2800
+ '\u0149': 'n',
2801
+ '\uA791': 'n',
2802
+ '\uA7A5': 'n',
2803
+ '\u01CC': 'nj',
2804
+ '\u24DE': 'o',
2805
+ '\uFF4F': 'o',
2806
+ '\u00F2': 'o',
2807
+ '\u00F3': 'o',
2808
+ '\u00F4': 'o',
2809
+ '\u1ED3': 'o',
2810
+ '\u1ED1': 'o',
2811
+ '\u1ED7': 'o',
2812
+ '\u1ED5': 'o',
2813
+ '\u00F5': 'o',
2814
+ '\u1E4D': 'o',
2815
+ '\u022D': 'o',
2816
+ '\u1E4F': 'o',
2817
+ '\u014D': 'o',
2818
+ '\u1E51': 'o',
2819
+ '\u1E53': 'o',
2820
+ '\u014F': 'o',
2821
+ '\u022F': 'o',
2822
+ '\u0231': 'o',
2823
+ '\u00F6': 'o',
2824
+ '\u022B': 'o',
2825
+ '\u1ECF': 'o',
2826
+ '\u0151': 'o',
2827
+ '\u01D2': 'o',
2828
+ '\u020D': 'o',
2829
+ '\u020F': 'o',
2830
+ '\u01A1': 'o',
2831
+ '\u1EDD': 'o',
2832
+ '\u1EDB': 'o',
2833
+ '\u1EE1': 'o',
2834
+ '\u1EDF': 'o',
2835
+ '\u1EE3': 'o',
2836
+ '\u1ECD': 'o',
2837
+ '\u1ED9': 'o',
2838
+ '\u01EB': 'o',
2839
+ '\u01ED': 'o',
2840
+ '\u00F8': 'o',
2841
+ '\u01FF': 'o',
2842
+ '\u0254': 'o',
2843
+ '\uA74B': 'o',
2844
+ '\uA74D': 'o',
2845
+ '\u0275': 'o',
2846
+ '\u01A3': 'oi',
2847
+ '\u0223': 'ou',
2848
+ '\uA74F': 'oo',
2849
+ '\u24DF': 'p',
2850
+ '\uFF50': 'p',
2851
+ '\u1E55': 'p',
2852
+ '\u1E57': 'p',
2853
+ '\u01A5': 'p',
2854
+ '\u1D7D': 'p',
2855
+ '\uA751': 'p',
2856
+ '\uA753': 'p',
2857
+ '\uA755': 'p',
2858
+ '\u24E0': 'q',
2859
+ '\uFF51': 'q',
2860
+ '\u024B': 'q',
2861
+ '\uA757': 'q',
2862
+ '\uA759': 'q',
2863
+ '\u24E1': 'r',
2864
+ '\uFF52': 'r',
2865
+ '\u0155': 'r',
2866
+ '\u1E59': 'r',
2867
+ '\u0159': 'r',
2868
+ '\u0211': 'r',
2869
+ '\u0213': 'r',
2870
+ '\u1E5B': 'r',
2871
+ '\u1E5D': 'r',
2872
+ '\u0157': 'r',
2873
+ '\u1E5F': 'r',
2874
+ '\u024D': 'r',
2875
+ '\u027D': 'r',
2876
+ '\uA75B': 'r',
2877
+ '\uA7A7': 'r',
2878
+ '\uA783': 'r',
2879
+ '\u24E2': 's',
2880
+ '\uFF53': 's',
2881
+ '\u00DF': 's',
2882
+ '\u015B': 's',
2883
+ '\u1E65': 's',
2884
+ '\u015D': 's',
2885
+ '\u1E61': 's',
2886
+ '\u0161': 's',
2887
+ '\u1E67': 's',
2888
+ '\u1E63': 's',
2889
+ '\u1E69': 's',
2890
+ '\u0219': 's',
2891
+ '\u015F': 's',
2892
+ '\u023F': 's',
2893
+ '\uA7A9': 's',
2894
+ '\uA785': 's',
2895
+ '\u1E9B': 's',
2896
+ '\u24E3': 't',
2897
+ '\uFF54': 't',
2898
+ '\u1E6B': 't',
2899
+ '\u1E97': 't',
2900
+ '\u0165': 't',
2901
+ '\u1E6D': 't',
2902
+ '\u021B': 't',
2903
+ '\u0163': 't',
2904
+ '\u1E71': 't',
2905
+ '\u1E6F': 't',
2906
+ '\u0167': 't',
2907
+ '\u01AD': 't',
2908
+ '\u0288': 't',
2909
+ '\u2C66': 't',
2910
+ '\uA787': 't',
2911
+ '\uA729': 'tz',
2912
+ '\u24E4': 'u',
2913
+ '\uFF55': 'u',
2914
+ '\u00F9': 'u',
2915
+ '\u00FA': 'u',
2916
+ '\u00FB': 'u',
2917
+ '\u0169': 'u',
2918
+ '\u1E79': 'u',
2919
+ '\u016B': 'u',
2920
+ '\u1E7B': 'u',
2921
+ '\u016D': 'u',
2922
+ '\u00FC': 'u',
2923
+ '\u01DC': 'u',
2924
+ '\u01D8': 'u',
2925
+ '\u01D6': 'u',
2926
+ '\u01DA': 'u',
2927
+ '\u1EE7': 'u',
2928
+ '\u016F': 'u',
2929
+ '\u0171': 'u',
2930
+ '\u01D4': 'u',
2931
+ '\u0215': 'u',
2932
+ '\u0217': 'u',
2933
+ '\u01B0': 'u',
2934
+ '\u1EEB': 'u',
2935
+ '\u1EE9': 'u',
2936
+ '\u1EEF': 'u',
2937
+ '\u1EED': 'u',
2938
+ '\u1EF1': 'u',
2939
+ '\u1EE5': 'u',
2940
+ '\u1E73': 'u',
2941
+ '\u0173': 'u',
2942
+ '\u1E77': 'u',
2943
+ '\u1E75': 'u',
2944
+ '\u0289': 'u',
2945
+ '\u24E5': 'v',
2946
+ '\uFF56': 'v',
2947
+ '\u1E7D': 'v',
2948
+ '\u1E7F': 'v',
2949
+ '\u028B': 'v',
2950
+ '\uA75F': 'v',
2951
+ '\u028C': 'v',
2952
+ '\uA761': 'vy',
2953
+ '\u24E6': 'w',
2954
+ '\uFF57': 'w',
2955
+ '\u1E81': 'w',
2956
+ '\u1E83': 'w',
2957
+ '\u0175': 'w',
2958
+ '\u1E87': 'w',
2959
+ '\u1E85': 'w',
2960
+ '\u1E98': 'w',
2961
+ '\u1E89': 'w',
2962
+ '\u2C73': 'w',
2963
+ '\u24E7': 'x',
2964
+ '\uFF58': 'x',
2965
+ '\u1E8B': 'x',
2966
+ '\u1E8D': 'x',
2967
+ '\u24E8': 'y',
2968
+ '\uFF59': 'y',
2969
+ '\u1EF3': 'y',
2970
+ '\u00FD': 'y',
2971
+ '\u0177': 'y',
2972
+ '\u1EF9': 'y',
2973
+ '\u0233': 'y',
2974
+ '\u1E8F': 'y',
2975
+ '\u00FF': 'y',
2976
+ '\u1EF7': 'y',
2977
+ '\u1E99': 'y',
2978
+ '\u1EF5': 'y',
2979
+ '\u01B4': 'y',
2980
+ '\u024F': 'y',
2981
+ '\u1EFF': 'y',
2982
+ '\u24E9': 'z',
2983
+ '\uFF5A': 'z',
2984
+ '\u017A': 'z',
2985
+ '\u1E91': 'z',
2986
+ '\u017C': 'z',
2987
+ '\u017E': 'z',
2988
+ '\u1E93': 'z',
2989
+ '\u1E95': 'z',
2990
+ '\u01B6': 'z',
2991
+ '\u0225': 'z',
2992
+ '\u0240': 'z',
2993
+ '\u2C6C': 'z',
2994
+ '\uA763': 'z',
2995
+ '\u0386': '\u0391',
2996
+ '\u0388': '\u0395',
2997
+ '\u0389': '\u0397',
2998
+ '\u038A': '\u0399',
2999
+ '\u03AA': '\u0399',
3000
+ '\u038C': '\u039F',
3001
+ '\u038E': '\u03A5',
3002
+ '\u03AB': '\u03A5',
3003
+ '\u038F': '\u03A9',
3004
+ '\u03AC': '\u03B1',
3005
+ '\u03AD': '\u03B5',
3006
+ '\u03AE': '\u03B7',
3007
+ '\u03AF': '\u03B9',
3008
+ '\u03CA': '\u03B9',
3009
+ '\u0390': '\u03B9',
3010
+ '\u03CC': '\u03BF',
3011
+ '\u03CD': '\u03C5',
3012
+ '\u03CB': '\u03C5',
3013
+ '\u03B0': '\u03C5',
3014
+ '\u03C9': '\u03C9',
3015
+ '\u03C2': '\u03C3'
3016
+ };
3017
+
3018
+ return diacritics;
3019
+ });
3020
+
3021
+ S2.define('select2/data/base',[
3022
+ '../utils'
3023
+ ], function (Utils) {
3024
+ function BaseAdapter ($element, options) {
3025
+ BaseAdapter.__super__.constructor.call(this);
3026
+ }
3027
+
3028
+ Utils.Extend(BaseAdapter, Utils.Observable);
3029
+
3030
+ BaseAdapter.prototype.current = function (callback) {
3031
+ throw new Error('The `current` method must be defined in child classes.');
3032
+ };
3033
+
3034
+ BaseAdapter.prototype.query = function (params, callback) {
3035
+ throw new Error('The `query` method must be defined in child classes.');
3036
+ };
3037
+
3038
+ BaseAdapter.prototype.bind = function (container, $container) {
3039
+ // Can be implemented in subclasses
3040
+ };
3041
+
3042
+ BaseAdapter.prototype.destroy = function () {
3043
+ // Can be implemented in subclasses
3044
+ };
3045
+
3046
+ BaseAdapter.prototype.generateResultId = function (container, data) {
3047
+ var id = container.id + '-result-';
3048
+
3049
+ id += Utils.generateChars(4);
3050
+
3051
+ if (data.id != null) {
3052
+ id += '-' + data.id.toString();
3053
+ } else {
3054
+ id += '-' + Utils.generateChars(4);
3055
+ }
3056
+ return id;
3057
+ };
3058
+
3059
+ return BaseAdapter;
3060
+ });
3061
+
3062
+ S2.define('select2/data/select',[
3063
+ './base',
3064
+ '../utils',
3065
+ 'jquery'
3066
+ ], function (BaseAdapter, Utils, $) {
3067
+ function SelectAdapter ($element, options) {
3068
+ this.$element = $element;
3069
+ this.options = options;
3070
+
3071
+ SelectAdapter.__super__.constructor.call(this);
3072
+ }
3073
+
3074
+ Utils.Extend(SelectAdapter, BaseAdapter);
3075
+
3076
+ SelectAdapter.prototype.current = function (callback) {
3077
+ var data = [];
3078
+ var self = this;
3079
+
3080
+ this.$element.find(':selected').each(function () {
3081
+ var $option = $(this);
3082
+
3083
+ var option = self.item($option);
3084
+
3085
+ data.push(option);
3086
+ });
3087
+
3088
+ callback(data);
3089
+ };
3090
+
3091
+ SelectAdapter.prototype.select = function (data) {
3092
+ var self = this;
3093
+
3094
+ data.selected = true;
3095
+
3096
+ // If data.element is a DOM node, use it instead
3097
+ if ($(data.element).is('option')) {
3098
+ data.element.selected = true;
3099
+
3100
+ this.$element.trigger('change');
3101
+
3102
+ return;
3103
+ }
3104
+
3105
+ if (this.$element.prop('multiple')) {
3106
+ this.current(function (currentData) {
3107
+ var val = [];
3108
+
3109
+ data = [data];
3110
+ data.push.apply(data, currentData);
3111
+
3112
+ for (var d = 0; d < data.length; d++) {
3113
+ var id = data[d].id;
3114
+
3115
+ if ($.inArray(id, val) === -1) {
3116
+ val.push(id);
3117
+ }
3118
+ }
3119
+
3120
+ self.$element.val(val);
3121
+ self.$element.trigger('change');
3122
+ });
3123
+ } else {
3124
+ var val = data.id;
3125
+
3126
+ this.$element.val(val);
3127
+ this.$element.trigger('change');
3128
+ }
3129
+ };
3130
+
3131
+ SelectAdapter.prototype.unselect = function (data) {
3132
+ var self = this;
3133
+
3134
+ if (!this.$element.prop('multiple')) {
3135
+ return;
3136
+ }
3137
+
3138
+ data.selected = false;
3139
+
3140
+ if ($(data.element).is('option')) {
3141
+ data.element.selected = false;
3142
+
3143
+ this.$element.trigger('change');
3144
+
3145
+ return;
3146
+ }
3147
+
3148
+ this.current(function (currentData) {
3149
+ var val = [];
3150
+
3151
+ for (var d = 0; d < currentData.length; d++) {
3152
+ var id = currentData[d].id;
3153
+
3154
+ if (id !== data.id && $.inArray(id, val) === -1) {
3155
+ val.push(id);
3156
+ }
3157
+ }
3158
+
3159
+ self.$element.val(val);
3160
+
3161
+ self.$element.trigger('change');
3162
+ });
3163
+ };
3164
+
3165
+ SelectAdapter.prototype.bind = function (container, $container) {
3166
+ var self = this;
3167
+
3168
+ this.container = container;
3169
+
3170
+ container.on('select', function (params) {
3171
+ self.select(params.data);
3172
+ });
3173
+
3174
+ container.on('unselect', function (params) {
3175
+ self.unselect(params.data);
3176
+ });
3177
+ };
3178
+
3179
+ SelectAdapter.prototype.destroy = function () {
3180
+ // Remove anything added to child elements
3181
+ this.$element.find('*').each(function () {
3182
+ // Remove any custom data set by Select2
3183
+ $.removeData(this, 'data');
3184
+ });
3185
+ };
3186
+
3187
+ SelectAdapter.prototype.query = function (params, callback) {
3188
+ var data = [];
3189
+ var self = this;
3190
+
3191
+ var $options = this.$element.children();
3192
+
3193
+ $options.each(function () {
3194
+ var $option = $(this);
3195
+
3196
+ if (!$option.is('option') && !$option.is('optgroup')) {
3197
+ return;
3198
+ }
3199
+
3200
+ var option = self.item($option);
3201
+
3202
+ var matches = self.matches(params, option);
3203
+
3204
+ if (matches !== null) {
3205
+ data.push(matches);
3206
+ }
3207
+ });
3208
+
3209
+ callback({
3210
+ results: data
3211
+ });
3212
+ };
3213
+
3214
+ SelectAdapter.prototype.addOptions = function ($options) {
3215
+ Utils.appendMany(this.$element, $options);
3216
+ };
3217
+
3218
+ SelectAdapter.prototype.option = function (data) {
3219
+ var option;
3220
+
3221
+ if (data.children) {
3222
+ option = document.createElement('optgroup');
3223
+ option.label = data.text;
3224
+ } else {
3225
+ option = document.createElement('option');
3226
+
3227
+ if (option.textContent !== undefined) {
3228
+ option.textContent = data.text;
3229
+ } else {
3230
+ option.innerText = data.text;
3231
+ }
3232
+ }
3233
+
3234
+ if (data.id !== undefined) {
3235
+ option.value = data.id;
3236
+ }
3237
+
3238
+ if (data.disabled) {
3239
+ option.disabled = true;
3240
+ }
3241
+
3242
+ if (data.selected) {
3243
+ option.selected = true;
3244
+ }
3245
+
3246
+ if (data.title) {
3247
+ option.title = data.title;
3248
+ }
3249
+
3250
+ var $option = $(option);
3251
+
3252
+ var normalizedData = this._normalizeItem(data);
3253
+ normalizedData.element = option;
3254
+
3255
+ // Override the option's data with the combined data
3256
+ $.data(option, 'data', normalizedData);
3257
+
3258
+ return $option;
3259
+ };
3260
+
3261
+ SelectAdapter.prototype.item = function ($option) {
3262
+ var data = {};
3263
+
3264
+ data = $.data($option[0], 'data');
3265
+
3266
+ if (data != null) {
3267
+ return data;
3268
+ }
3269
+
3270
+ if ($option.is('option')) {
3271
+ data = {
3272
+ id: $option.val(),
3273
+ text: $option.text(),
3274
+ disabled: $option.prop('disabled'),
3275
+ selected: $option.prop('selected'),
3276
+ title: $option.prop('title')
3277
+ };
3278
+ } else if ($option.is('optgroup')) {
3279
+ data = {
3280
+ text: $option.prop('label'),
3281
+ children: [],
3282
+ title: $option.prop('title')
3283
+ };
3284
+
3285
+ var $children = $option.children('option');
3286
+ var children = [];
3287
+
3288
+ for (var c = 0; c < $children.length; c++) {
3289
+ var $child = $($children[c]);
3290
+
3291
+ var child = this.item($child);
3292
+
3293
+ children.push(child);
3294
+ }
3295
+
3296
+ data.children = children;
3297
+ }
3298
+
3299
+ data = this._normalizeItem(data);
3300
+ data.element = $option[0];
3301
+
3302
+ $.data($option[0], 'data', data);
3303
+
3304
+ return data;
3305
+ };
3306
+
3307
+ SelectAdapter.prototype._normalizeItem = function (item) {
3308
+ if (!$.isPlainObject(item)) {
3309
+ item = {
3310
+ id: item,
3311
+ text: item
3312
+ };
3313
+ }
3314
+
3315
+ item = $.extend({}, {
3316
+ text: ''
3317
+ }, item);
3318
+
3319
+ var defaults = {
3320
+ selected: false,
3321
+ disabled: false
3322
+ };
3323
+
3324
+ if (item.id != null) {
3325
+ item.id = item.id.toString();
3326
+ }
3327
+
3328
+ if (item.text != null) {
3329
+ item.text = item.text.toString();
3330
+ }
3331
+
3332
+ if (item._resultId == null && item.id && this.container != null) {
3333
+ item._resultId = this.generateResultId(this.container, item);
3334
+ }
3335
+
3336
+ return $.extend({}, defaults, item);
3337
+ };
3338
+
3339
+ SelectAdapter.prototype.matches = function (params, data) {
3340
+ var matcher = this.options.get('matcher');
3341
+
3342
+ return matcher(params, data);
3343
+ };
3344
+
3345
+ return SelectAdapter;
3346
+ });
3347
+
3348
+ S2.define('select2/data/array',[
3349
+ './select',
3350
+ '../utils',
3351
+ 'jquery'
3352
+ ], function (SelectAdapter, Utils, $) {
3353
+ function ArrayAdapter ($element, options) {
3354
+ var data = options.get('data') || [];
3355
+
3356
+ ArrayAdapter.__super__.constructor.call(this, $element, options);
3357
+
3358
+ this.addOptions(this.convertToOptions(data));
3359
+ }
3360
+
3361
+ Utils.Extend(ArrayAdapter, SelectAdapter);
3362
+
3363
+ ArrayAdapter.prototype.select = function (data) {
3364
+ var $option = this.$element.find('option').filter(function (i, elm) {
3365
+ return elm.value == data.id.toString();
3366
+ });
3367
+
3368
+ if ($option.length === 0) {
3369
+ $option = this.option(data);
3370
+
3371
+ this.addOptions($option);
3372
+ }
3373
+
3374
+ ArrayAdapter.__super__.select.call(this, data);
3375
+ };
3376
+
3377
+ ArrayAdapter.prototype.convertToOptions = function (data) {
3378
+ var self = this;
3379
+
3380
+ var $existing = this.$element.find('option');
3381
+ var existingIds = $existing.map(function () {
3382
+ return self.item($(this)).id;
3383
+ }).get();
3384
+
3385
+ var $options = [];
3386
+
3387
+ // Filter out all items except for the one passed in the argument
3388
+ function onlyItem (item) {
3389
+ return function () {
3390
+ return $(this).val() == item.id;
3391
+ };
3392
+ }
3393
+
3394
+ for (var d = 0; d < data.length; d++) {
3395
+ var item = this._normalizeItem(data[d]);
3396
+
3397
+ // Skip items which were pre-loaded, only merge the data
3398
+ if ($.inArray(item.id, existingIds) >= 0) {
3399
+ var $existingOption = $existing.filter(onlyItem(item));
3400
+
3401
+ var existingData = this.item($existingOption);
3402
+ var newData = $.extend(true, {}, item, existingData);
3403
+
3404
+ var $newOption = this.option(newData);
3405
+
3406
+ $existingOption.replaceWith($newOption);
3407
+
3408
+ continue;
3409
+ }
3410
+
3411
+ var $option = this.option(item);
3412
+
3413
+ if (item.children) {
3414
+ var $children = this.convertToOptions(item.children);
3415
+
3416
+ Utils.appendMany($option, $children);
3417
+ }
3418
+
3419
+ $options.push($option);
3420
+ }
3421
+
3422
+ return $options;
3423
+ };
3424
+
3425
+ return ArrayAdapter;
3426
+ });
3427
+
3428
+ S2.define('select2/data/ajax',[
3429
+ './array',
3430
+ '../utils',
3431
+ 'jquery'
3432
+ ], function (ArrayAdapter, Utils, $) {
3433
+ function AjaxAdapter ($element, options) {
3434
+ this.ajaxOptions = this._applyDefaults(options.get('ajax'));
3435
+
3436
+ if (this.ajaxOptions.processResults != null) {
3437
+ this.processResults = this.ajaxOptions.processResults;
3438
+ }
3439
+
3440
+ AjaxAdapter.__super__.constructor.call(this, $element, options);
3441
+ }
3442
+
3443
+ Utils.Extend(AjaxAdapter, ArrayAdapter);
3444
+
3445
+ AjaxAdapter.prototype._applyDefaults = function (options) {
3446
+ var defaults = {
3447
+ data: function (params) {
3448
+ return $.extend({}, params, {
3449
+ q: params.term
3450
+ });
3451
+ },
3452
+ transport: function (params, success, failure) {
3453
+ var $request = $.ajax(params);
3454
+
3455
+ $request.then(success);
3456
+ $request.fail(failure);
3457
+
3458
+ return $request;
3459
+ }
3460
+ };
3461
+
3462
+ return $.extend({}, defaults, options, true);
3463
+ };
3464
+
3465
+ AjaxAdapter.prototype.processResults = function (results) {
3466
+ return results;
3467
+ };
3468
+
3469
+ AjaxAdapter.prototype.query = function (params, callback) {
3470
+ var matches = [];
3471
+ var self = this;
3472
+
3473
+ if (this._request != null) {
3474
+ // JSONP requests cannot always be aborted
3475
+ if ($.isFunction(this._request.abort)) {
3476
+ this._request.abort();
3477
+ }
3478
+
3479
+ this._request = null;
3480
+ }
3481
+
3482
+ var options = $.extend({
3483
+ type: 'GET'
3484
+ }, this.ajaxOptions);
3485
+
3486
+ if (typeof options.url === 'function') {
3487
+ options.url = options.url.call(this.$element, params);
3488
+ }
3489
+
3490
+ if (typeof options.data === 'function') {
3491
+ options.data = options.data.call(this.$element, params);
3492
+ }
3493
+
3494
+ function request () {
3495
+ var $request = options.transport(options, function (data) {
3496
+ var results = self.processResults(data, params);
3497
+
3498
+ if (self.options.get('debug') && window.console && console.error) {
3499
+ // Check to make sure that the response included a `results` key.
3500
+ if (!results || !results.results || !$.isArray(results.results)) {
3501
+ console.error(
3502
+ 'Select2: The AJAX results did not return an array in the ' +
3503
+ '`results` key of the response.'
3504
+ );
3505
+ }
3506
+ }
3507
+
3508
+ callback(results);
3509
+ }, function () {
3510
+ // Attempt to detect if a request was aborted
3511
+ // Only works if the transport exposes a status property
3512
+ if ($request.status && $request.status === '0') {
3513
+ return;
3514
+ }
3515
+
3516
+ self.trigger('results:message', {
3517
+ message: 'errorLoading'
3518
+ });
3519
+ });
3520
+
3521
+ self._request = $request;
3522
+ }
3523
+
3524
+ if (this.ajaxOptions.delay && params.term != null) {
3525
+ if (this._queryTimeout) {
3526
+ window.clearTimeout(this._queryTimeout);
3527
+ }
3528
+
3529
+ this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
3530
+ } else {
3531
+ request();
3532
+ }
3533
+ };
3534
+
3535
+ return AjaxAdapter;
3536
+ });
3537
+
3538
+ S2.define('select2/data/tags',[
3539
+ 'jquery'
3540
+ ], function ($) {
3541
+ function Tags (decorated, $element, options) {
3542
+ var tags = options.get('tags');
3543
+
3544
+ var createTag = options.get('createTag');
3545
+
3546
+ if (createTag !== undefined) {
3547
+ this.createTag = createTag;
3548
+ }
3549
+
3550
+ var insertTag = options.get('insertTag');
3551
+
3552
+ if (insertTag !== undefined) {
3553
+ this.insertTag = insertTag;
3554
+ }
3555
+
3556
+ decorated.call(this, $element, options);
3557
+
3558
+ if ($.isArray(tags)) {
3559
+ for (var t = 0; t < tags.length; t++) {
3560
+ var tag = tags[t];
3561
+ var item = this._normalizeItem(tag);
3562
+
3563
+ var $option = this.option(item);
3564
+
3565
+ this.$element.append($option);
3566
+ }
3567
+ }
3568
+ }
3569
+
3570
+ Tags.prototype.query = function (decorated, params, callback) {
3571
+ var self = this;
3572
+
3573
+ this._removeOldTags();
3574
+
3575
+ if (params.term == null || params.page != null) {
3576
+ decorated.call(this, params, callback);
3577
+ return;
3578
+ }
3579
+
3580
+ function wrapper (obj, child) {
3581
+ var data = obj.results;
3582
+
3583
+ for (var i = 0; i < data.length; i++) {
3584
+ var option = data[i];
3585
+
3586
+ var checkChildren = (
3587
+ option.children != null &&
3588
+ !wrapper({
3589
+ results: option.children
3590
+ }, true)
3591
+ );
3592
+
3593
+ var optionText = (option.text || '').toUpperCase();
3594
+ var paramsTerm = (params.term || '').toUpperCase();
3595
+
3596
+ var checkText = optionText === paramsTerm;
3597
+
3598
+ if (checkText || checkChildren) {
3599
+ if (child) {
3600
+ return false;
3601
+ }
3602
+
3603
+ obj.data = data;
3604
+ callback(obj);
3605
+
3606
+ return;
3607
+ }
3608
+ }
3609
+
3610
+ if (child) {
3611
+ return true;
3612
+ }
3613
+
3614
+ var tag = self.createTag(params);
3615
+
3616
+ if (tag != null) {
3617
+ var $option = self.option(tag);
3618
+ $option.attr('data-select2-tag', true);
3619
+
3620
+ self.addOptions([$option]);
3621
+
3622
+ self.insertTag(data, tag);
3623
+ }
3624
+
3625
+ obj.results = data;
3626
+
3627
+ callback(obj);
3628
+ }
3629
+
3630
+ decorated.call(this, params, wrapper);
3631
+ };
3632
+
3633
+ Tags.prototype.createTag = function (decorated, params) {
3634
+ var term = $.trim(params.term);
3635
+
3636
+ if (term === '') {
3637
+ return null;
3638
+ }
3639
+
3640
+ return {
3641
+ id: term,
3642
+ text: term
3643
+ };
3644
+ };
3645
+
3646
+ Tags.prototype.insertTag = function (_, data, tag) {
3647
+ data.unshift(tag);
3648
+ };
3649
+
3650
+ Tags.prototype._removeOldTags = function (_) {
3651
+ var tag = this._lastTag;
3652
+
3653
+ var $options = this.$element.find('option[data-select2-tag]');
3654
+
3655
+ $options.each(function () {
3656
+ if (this.selected) {
3657
+ return;
3658
+ }
3659
+
3660
+ $(this).remove();
3661
+ });
3662
+ };
3663
+
3664
+ return Tags;
3665
+ });
3666
+
3667
+ S2.define('select2/data/tokenizer',[
3668
+ 'jquery'
3669
+ ], function ($) {
3670
+ function Tokenizer (decorated, $element, options) {
3671
+ var tokenizer = options.get('tokenizer');
3672
+
3673
+ if (tokenizer !== undefined) {
3674
+ this.tokenizer = tokenizer;
3675
+ }
3676
+
3677
+ decorated.call(this, $element, options);
3678
+ }
3679
+
3680
+ Tokenizer.prototype.bind = function (decorated, container, $container) {
3681
+ decorated.call(this, container, $container);
3682
+
3683
+ this.$search = container.dropdown.$search || container.selection.$search ||
3684
+ $container.find('.select2-search__field');
3685
+ };
3686
+
3687
+ Tokenizer.prototype.query = function (decorated, params, callback) {
3688
+ var self = this;
3689
+
3690
+ function createAndSelect (data) {
3691
+ // Normalize the data object so we can use it for checks
3692
+ var item = self._normalizeItem(data);
3693
+
3694
+ // Check if the data object already exists as a tag
3695
+ // Select it if it doesn't
3696
+ var $existingOptions = self.$element.find('option').filter(function () {
3697
+ return $(this).val() === item.id;
3698
+ });
3699
+
3700
+ // If an existing option wasn't found for it, create the option
3701
+ if (!$existingOptions.length) {
3702
+ var $option = self.option(item);
3703
+ $option.attr('data-select2-tag', true);
3704
+
3705
+ self._removeOldTags();
3706
+ self.addOptions([$option]);
3707
+ }
3708
+
3709
+ // Select the item, now that we know there is an option for it
3710
+ select(item);
3711
+ }
3712
+
3713
+ function select (data) {
3714
+ self.trigger('select', {
3715
+ data: data
3716
+ });
3717
+ }
3718
+
3719
+ params.term = params.term || '';
3720
+
3721
+ var tokenData = this.tokenizer(params, this.options, createAndSelect);
3722
+
3723
+ if (tokenData.term !== params.term) {
3724
+ // Replace the search term if we have the search box
3725
+ if (this.$search.length) {
3726
+ this.$search.val(tokenData.term);
3727
+ this.$search.focus();
3728
+ }
3729
+
3730
+ params.term = tokenData.term;
3731
+ }
3732
+
3733
+ decorated.call(this, params, callback);
3734
+ };
3735
+
3736
+ Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
3737
+ var separators = options.get('tokenSeparators') || [];
3738
+ var term = params.term;
3739
+ var i = 0;
3740
+
3741
+ var createTag = this.createTag || function (params) {
3742
+ return {
3743
+ id: params.term,
3744
+ text: params.term
3745
+ };
3746
+ };
3747
+
3748
+ while (i < term.length) {
3749
+ var termChar = term[i];
3750
+
3751
+ if ($.inArray(termChar, separators) === -1) {
3752
+ i++;
3753
+
3754
+ continue;
3755
+ }
3756
+
3757
+ var part = term.substr(0, i);
3758
+ var partParams = $.extend({}, params, {
3759
+ term: part
3760
+ });
3761
+
3762
+ var data = createTag(partParams);
3763
+
3764
+ if (data == null) {
3765
+ i++;
3766
+ continue;
3767
+ }
3768
+
3769
+ callback(data);
3770
+
3771
+ // Reset the term to not include the tokenized portion
3772
+ term = term.substr(i + 1) || '';
3773
+ i = 0;
3774
+ }
3775
+
3776
+ return {
3777
+ term: term
3778
+ };
3779
+ };
3780
+
3781
+ return Tokenizer;
3782
+ });
3783
+
3784
+ S2.define('select2/data/minimumInputLength',[
3785
+
3786
+ ], function () {
3787
+ function MinimumInputLength (decorated, $e, options) {
3788
+ this.minimumInputLength = options.get('minimumInputLength');
3789
+
3790
+ decorated.call(this, $e, options);
3791
+ }
3792
+
3793
+ MinimumInputLength.prototype.query = function (decorated, params, callback) {
3794
+ params.term = params.term || '';
3795
+
3796
+ if (params.term.length < this.minimumInputLength) {
3797
+ this.trigger('results:message', {
3798
+ message: 'inputTooShort',
3799
+ args: {
3800
+ minimum: this.minimumInputLength,
3801
+ input: params.term,
3802
+ params: params
3803
+ }
3804
+ });
3805
+
3806
+ return;
3807
+ }
3808
+
3809
+ decorated.call(this, params, callback);
3810
+ };
3811
+
3812
+ return MinimumInputLength;
3813
+ });
3814
+
3815
+ S2.define('select2/data/maximumInputLength',[
3816
+
3817
+ ], function () {
3818
+ function MaximumInputLength (decorated, $e, options) {
3819
+ this.maximumInputLength = options.get('maximumInputLength');
3820
+
3821
+ decorated.call(this, $e, options);
3822
+ }
3823
+
3824
+ MaximumInputLength.prototype.query = function (decorated, params, callback) {
3825
+ params.term = params.term || '';
3826
+
3827
+ if (this.maximumInputLength > 0 &&
3828
+ params.term.length > this.maximumInputLength) {
3829
+ this.trigger('results:message', {
3830
+ message: 'inputTooLong',
3831
+ args: {
3832
+ maximum: this.maximumInputLength,
3833
+ input: params.term,
3834
+ params: params
3835
+ }
3836
+ });
3837
+
3838
+ return;
3839
+ }
3840
+
3841
+ decorated.call(this, params, callback);
3842
+ };
3843
+
3844
+ return MaximumInputLength;
3845
+ });
3846
+
3847
+ S2.define('select2/data/maximumSelectionLength',[
3848
+
3849
+ ], function (){
3850
+ function MaximumSelectionLength (decorated, $e, options) {
3851
+ this.maximumSelectionLength = options.get('maximumSelectionLength');
3852
+
3853
+ decorated.call(this, $e, options);
3854
+ }
3855
+
3856
+ MaximumSelectionLength.prototype.query =
3857
+ function (decorated, params, callback) {
3858
+ var self = this;
3859
+
3860
+ this.current(function (currentData) {
3861
+ var count = currentData != null ? currentData.length : 0;
3862
+ if (self.maximumSelectionLength > 0 &&
3863
+ count >= self.maximumSelectionLength) {
3864
+ self.trigger('results:message', {
3865
+ message: 'maximumSelected',
3866
+ args: {
3867
+ maximum: self.maximumSelectionLength
3868
+ }
3869
+ });
3870
+ return;
3871
+ }
3872
+ decorated.call(self, params, callback);
3873
+ });
3874
+ };
3875
+
3876
+ return MaximumSelectionLength;
3877
+ });
3878
+
3879
+ S2.define('select2/dropdown',[
3880
+ 'jquery',
3881
+ './utils'
3882
+ ], function ($, Utils) {
3883
+ function Dropdown ($element, options) {
3884
+ this.$element = $element;
3885
+ this.options = options;
3886
+
3887
+ Dropdown.__super__.constructor.call(this);
3888
+ }
3889
+
3890
+ Utils.Extend(Dropdown, Utils.Observable);
3891
+
3892
+ Dropdown.prototype.render = function () {
3893
+ var $dropdown = $(
3894
+ '<span class="select2-dropdown">' +
3895
+ '<span class="select2-results"></span>' +
3896
+ '</span>'
3897
+ );
3898
+
3899
+ $dropdown.attr('dir', this.options.get('dir'));
3900
+
3901
+ this.$dropdown = $dropdown;
3902
+
3903
+ return $dropdown;
3904
+ };
3905
+
3906
+ Dropdown.prototype.bind = function () {
3907
+ // Should be implemented in subclasses
3908
+ };
3909
+
3910
+ Dropdown.prototype.position = function ($dropdown, $container) {
3911
+ // Should be implmented in subclasses
3912
+ };
3913
+
3914
+ Dropdown.prototype.destroy = function () {
3915
+ // Remove the dropdown from the DOM
3916
+ this.$dropdown.remove();
3917
+ };
3918
+
3919
+ return Dropdown;
3920
+ });
3921
+
3922
+ S2.define('select2/dropdown/search',[
3923
+ 'jquery',
3924
+ '../utils'
3925
+ ], function ($, Utils) {
3926
+ function Search () { }
3927
+
3928
+ Search.prototype.render = function (decorated) {
3929
+ var $rendered = decorated.call(this);
3930
+
3931
+ var $search = $(
3932
+ '<span class="select2-search select2-search--dropdown">' +
3933
+ '<input class="select2-search__field" type="search" tabindex="-1"' +
3934
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
3935
+ ' spellcheck="false" role="textbox" />' +
3936
+ '</span>'
3937
+ );
3938
+
3939
+ this.$searchContainer = $search;
3940
+ this.$search = $search.find('input');
3941
+
3942
+ $rendered.prepend($search);
3943
+
3944
+ return $rendered;
3945
+ };
3946
+
3947
+ Search.prototype.bind = function (decorated, container, $container) {
3948
+ var self = this;
3949
+
3950
+ decorated.call(this, container, $container);
3951
+
3952
+ this.$search.on('keydown', function (evt) {
3953
+ self.trigger('keypress', evt);
3954
+
3955
+ self._keyUpPrevented = evt.isDefaultPrevented();
3956
+ });
3957
+
3958
+ // Workaround for browsers which do not support the `input` event
3959
+ // This will prevent double-triggering of events for browsers which support
3960
+ // both the `keyup` and `input` events.
3961
+ this.$search.on('input', function (evt) {
3962
+ // Unbind the duplicated `keyup` event
3963
+ $(this).off('keyup');
3964
+ });
3965
+
3966
+ this.$search.on('keyup input', function (evt) {
3967
+ self.handleSearch(evt);
3968
+ });
3969
+
3970
+ container.on('open', function () {
3971
+ self.$search.attr('tabindex', 0);
3972
+
3973
+ self.$search.focus();
3974
+
3975
+ window.setTimeout(function () {
3976
+ self.$search.focus();
3977
+ }, 0);
3978
+ });
3979
+
3980
+ container.on('close', function () {
3981
+ self.$search.attr('tabindex', -1);
3982
+
3983
+ self.$search.val('');
3984
+ });
3985
+
3986
+ container.on('focus', function () {
3987
+ if (!container.isOpen()) {
3988
+ self.$search.focus();
3989
+ }
3990
+ });
3991
+
3992
+ container.on('results:all', function (params) {
3993
+ if (params.query.term == null || params.query.term === '') {
3994
+ var showSearch = self.showSearch(params);
3995
+
3996
+ if (showSearch) {
3997
+ self.$searchContainer.removeClass('select2-search--hide');
3998
+ } else {
3999
+ self.$searchContainer.addClass('select2-search--hide');
4000
+ }
4001
+ }
4002
+ });
4003
+ };
4004
+
4005
+ Search.prototype.handleSearch = function (evt) {
4006
+ if (!this._keyUpPrevented) {
4007
+ var input = this.$search.val();
4008
+
4009
+ this.trigger('query', {
4010
+ term: input
4011
+ });
4012
+ }
4013
+
4014
+ this._keyUpPrevented = false;
4015
+ };
4016
+
4017
+ Search.prototype.showSearch = function (_, params) {
4018
+ return true;
4019
+ };
4020
+
4021
+ return Search;
4022
+ });
4023
+
4024
+ S2.define('select2/dropdown/hidePlaceholder',[
4025
+
4026
+ ], function () {
4027
+ function HidePlaceholder (decorated, $element, options, dataAdapter) {
4028
+ this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
4029
+
4030
+ decorated.call(this, $element, options, dataAdapter);
4031
+ }
4032
+
4033
+ HidePlaceholder.prototype.append = function (decorated, data) {
4034
+ data.results = this.removePlaceholder(data.results);
4035
+
4036
+ decorated.call(this, data);
4037
+ };
4038
+
4039
+ HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
4040
+ if (typeof placeholder === 'string') {
4041
+ placeholder = {
4042
+ id: '',
4043
+ text: placeholder
4044
+ };
4045
+ }
4046
+
4047
+ return placeholder;
4048
+ };
4049
+
4050
+ HidePlaceholder.prototype.removePlaceholder = function (_, data) {
4051
+ var modifiedData = data.slice(0);
4052
+
4053
+ for (var d = data.length - 1; d >= 0; d--) {
4054
+ var item = data[d];
4055
+
4056
+ if (this.placeholder.id === item.id) {
4057
+ modifiedData.splice(d, 1);
4058
+ }
4059
+ }
4060
+
4061
+ return modifiedData;
4062
+ };
4063
+
4064
+ return HidePlaceholder;
4065
+ });
4066
+
4067
+ S2.define('select2/dropdown/infiniteScroll',[
4068
+ 'jquery'
4069
+ ], function ($) {
4070
+ function InfiniteScroll (decorated, $element, options, dataAdapter) {
4071
+ this.lastParams = {};
4072
+
4073
+ decorated.call(this, $element, options, dataAdapter);
4074
+
4075
+ this.$loadingMore = this.createLoadingMore();
4076
+ this.loading = false;
4077
+ }
4078
+
4079
+ InfiniteScroll.prototype.append = function (decorated, data) {
4080
+ this.$loadingMore.remove();
4081
+ this.loading = false;
4082
+
4083
+ decorated.call(this, data);
4084
+
4085
+ if (this.showLoadingMore(data)) {
4086
+ this.$results.append(this.$loadingMore);
4087
+ }
4088
+ };
4089
+
4090
+ InfiniteScroll.prototype.bind = function (decorated, container, $container) {
4091
+ var self = this;
4092
+
4093
+ decorated.call(this, container, $container);
4094
+
4095
+ container.on('query', function (params) {
4096
+ self.lastParams = params;
4097
+ self.loading = true;
4098
+ });
4099
+
4100
+ container.on('query:append', function (params) {
4101
+ self.lastParams = params;
4102
+ self.loading = true;
4103
+ });
4104
+
4105
+ this.$results.on('scroll', function () {
4106
+ var isLoadMoreVisible = $.contains(
4107
+ document.documentElement,
4108
+ self.$loadingMore[0]
4109
+ );
4110
+
4111
+ if (self.loading || !isLoadMoreVisible) {
4112
+ return;
4113
+ }
4114
+
4115
+ var currentOffset = self.$results.offset().top +
4116
+ self.$results.outerHeight(false);
4117
+ var loadingMoreOffset = self.$loadingMore.offset().top +
4118
+ self.$loadingMore.outerHeight(false);
4119
+
4120
+ if (currentOffset + 50 >= loadingMoreOffset) {
4121
+ self.loadMore();
4122
+ }
4123
+ });
4124
+ };
4125
+
4126
+ InfiniteScroll.prototype.loadMore = function () {
4127
+ this.loading = true;
4128
+
4129
+ var params = $.extend({}, {page: 1}, this.lastParams);
4130
+
4131
+ params.page++;
4132
+
4133
+ this.trigger('query:append', params);
4134
+ };
4135
+
4136
+ InfiniteScroll.prototype.showLoadingMore = function (_, data) {
4137
+ return data.pagination && data.pagination.more;
4138
+ };
4139
+
4140
+ InfiniteScroll.prototype.createLoadingMore = function () {
4141
+ var $option = $(
4142
+ '<li ' +
4143
+ 'class="select2-results__option select2-results__option--load-more"' +
4144
+ 'role="treeitem" aria-disabled="true"></li>'
4145
+ );
4146
+
4147
+ var message = this.options.get('translations').get('loadingMore');
4148
+
4149
+ $option.html(message(this.lastParams));
4150
+
4151
+ return $option;
4152
+ };
4153
+
4154
+ return InfiniteScroll;
4155
+ });
4156
+
4157
+ S2.define('select2/dropdown/attachBody',[
4158
+ 'jquery',
4159
+ '../utils'
4160
+ ], function ($, Utils) {
4161
+ function AttachBody (decorated, $element, options) {
4162
+ this.$dropdownParent = options.get('dropdownParent') || $(document.body);
4163
+
4164
+ decorated.call(this, $element, options);
4165
+ }
4166
+
4167
+ AttachBody.prototype.bind = function (decorated, container, $container) {
4168
+ var self = this;
4169
+
4170
+ var setupResultsEvents = false;
4171
+
4172
+ decorated.call(this, container, $container);
4173
+
4174
+ container.on('open', function () {
4175
+ self._showDropdown();
4176
+ self._attachPositioningHandler(container);
4177
+
4178
+ if (!setupResultsEvents) {
4179
+ setupResultsEvents = true;
4180
+
4181
+ container.on('results:all', function () {
4182
+ self._positionDropdown();
4183
+ self._resizeDropdown();
4184
+ });
4185
+
4186
+ container.on('results:append', function () {
4187
+ self._positionDropdown();
4188
+ self._resizeDropdown();
4189
+ });
4190
+ }
4191
+ });
4192
+
4193
+ container.on('close', function () {
4194
+ self._hideDropdown();
4195
+ self._detachPositioningHandler(container);
4196
+ });
4197
+
4198
+ this.$dropdownContainer.on('mousedown', function (evt) {
4199
+ evt.stopPropagation();
4200
+ });
4201
+ };
4202
+
4203
+ AttachBody.prototype.destroy = function (decorated) {
4204
+ decorated.call(this);
4205
+
4206
+ this.$dropdownContainer.remove();
4207
+ };
4208
+
4209
+ AttachBody.prototype.position = function (decorated, $dropdown, $container) {
4210
+ // Clone all of the container classes
4211
+ $dropdown.attr('class', $container.attr('class'));
4212
+
4213
+ $dropdown.removeClass('select2');
4214
+ $dropdown.addClass('select2-container--open');
4215
+
4216
+ $dropdown.css({
4217
+ position: 'absolute',
4218
+ top: -999999
4219
+ });
4220
+
4221
+ this.$container = $container;
4222
+ };
4223
+
4224
+ AttachBody.prototype.render = function (decorated) {
4225
+ var $container = $('<span></span>');
4226
+
4227
+ var $dropdown = decorated.call(this);
4228
+ $container.append($dropdown);
4229
+
4230
+ this.$dropdownContainer = $container;
4231
+
4232
+ return $container;
4233
+ };
4234
+
4235
+ AttachBody.prototype._hideDropdown = function (decorated) {
4236
+ this.$dropdownContainer.detach();
4237
+ };
4238
+
4239
+ AttachBody.prototype._attachPositioningHandler =
4240
+ function (decorated, container) {
4241
+ var self = this;
4242
+
4243
+ var scrollEvent = 'scroll.select2.' + container.id;
4244
+ var resizeEvent = 'resize.select2.' + container.id;
4245
+ var orientationEvent = 'orientationchange.select2.' + container.id;
4246
+
4247
+ var $watchers = this.$container.parents().filter(Utils.hasScroll);
4248
+ $watchers.each(function () {
4249
+ $(this).data('select2-scroll-position', {
4250
+ x: $(this).scrollLeft(),
4251
+ y: $(this).scrollTop()
4252
+ });
4253
+ });
4254
+
4255
+ $watchers.on(scrollEvent, function (ev) {
4256
+ var position = $(this).data('select2-scroll-position');
4257
+ $(this).scrollTop(position.y);
4258
+ });
4259
+
4260
+ $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
4261
+ function (e) {
4262
+ self._positionDropdown();
4263
+ self._resizeDropdown();
4264
+ });
4265
+ };
4266
+
4267
+ AttachBody.prototype._detachPositioningHandler =
4268
+ function (decorated, container) {
4269
+ var scrollEvent = 'scroll.select2.' + container.id;
4270
+ var resizeEvent = 'resize.select2.' + container.id;
4271
+ var orientationEvent = 'orientationchange.select2.' + container.id;
4272
+
4273
+ var $watchers = this.$container.parents().filter(Utils.hasScroll);
4274
+ $watchers.off(scrollEvent);
4275
+
4276
+ $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
4277
+ };
4278
+
4279
+ AttachBody.prototype._positionDropdown = function () {
4280
+ var $window = $(window);
4281
+
4282
+ var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
4283
+ var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
4284
+
4285
+ var newDirection = null;
4286
+
4287
+ var offset = this.$container.offset();
4288
+
4289
+ offset.bottom = offset.top + this.$container.outerHeight(false);
4290
+
4291
+ var container = {
4292
+ height: this.$container.outerHeight(false)
4293
+ };
4294
+
4295
+ container.top = offset.top;
4296
+ container.bottom = offset.top + container.height;
4297
+
4298
+ var dropdown = {
4299
+ height: this.$dropdown.outerHeight(false)
4300
+ };
4301
+
4302
+ var viewport = {
4303
+ top: $window.scrollTop(),
4304
+ bottom: $window.scrollTop() + $window.height()
4305
+ };
4306
+
4307
+ var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
4308
+ var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
4309
+
4310
+ var css = {
4311
+ left: offset.left,
4312
+ top: container.bottom
4313
+ };
4314
+
4315
+ // Determine what the parent element is to use for calciulating the offset
4316
+ var $offsetParent = this.$dropdownParent;
4317
+
4318
+ // For statically positoned elements, we need to get the element
4319
+ // that is determining the offset
4320
+ if ($offsetParent.css('position') === 'static') {
4321
+ $offsetParent = $offsetParent.offsetParent();
4322
+ }
4323
+
4324
+ var parentOffset = $offsetParent.offset();
4325
+
4326
+ css.top -= parentOffset.top;
4327
+ css.left -= parentOffset.left;
4328
+
4329
+ if (!isCurrentlyAbove && !isCurrentlyBelow) {
4330
+ newDirection = 'below';
4331
+ }
4332
+
4333
+ if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
4334
+ newDirection = 'above';
4335
+ } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
4336
+ newDirection = 'below';
4337
+ }
4338
+
4339
+ if (newDirection == 'above' ||
4340
+ (isCurrentlyAbove && newDirection !== 'below')) {
4341
+ css.top = container.top - parentOffset.top - dropdown.height;
4342
+ }
4343
+
4344
+ if (newDirection != null) {
4345
+ this.$dropdown
4346
+ .removeClass('select2-dropdown--below select2-dropdown--above')
4347
+ .addClass('select2-dropdown--' + newDirection);
4348
+ this.$container
4349
+ .removeClass('select2-container--below select2-container--above')
4350
+ .addClass('select2-container--' + newDirection);
4351
+ }
4352
+
4353
+ this.$dropdownContainer.css(css);
4354
+ };
4355
+
4356
+ AttachBody.prototype._resizeDropdown = function () {
4357
+ var css = {
4358
+ width: this.$container.outerWidth(false) + 'px'
4359
+ };
4360
+
4361
+ if (this.options.get('dropdownAutoWidth')) {
4362
+ css.minWidth = css.width;
4363
+ css.position = 'relative';
4364
+ css.width = 'auto';
4365
+ }
4366
+
4367
+ this.$dropdown.css(css);
4368
+ };
4369
+
4370
+ AttachBody.prototype._showDropdown = function (decorated) {
4371
+ this.$dropdownContainer.appendTo(this.$dropdownParent);
4372
+
4373
+ this._positionDropdown();
4374
+ this._resizeDropdown();
4375
+ };
4376
+
4377
+ return AttachBody;
4378
+ });
4379
+
4380
+ S2.define('select2/dropdown/minimumResultsForSearch',[
4381
+
4382
+ ], function () {
4383
+ function countResults (data) {
4384
+ var count = 0;
4385
+
4386
+ for (var d = 0; d < data.length; d++) {
4387
+ var item = data[d];
4388
+
4389
+ if (item.children) {
4390
+ count += countResults(item.children);
4391
+ } else {
4392
+ count++;
4393
+ }
4394
+ }
4395
+
4396
+ return count;
4397
+ }
4398
+
4399
+ function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
4400
+ this.minimumResultsForSearch = options.get('minimumResultsForSearch');
4401
+
4402
+ if (this.minimumResultsForSearch < 0) {
4403
+ this.minimumResultsForSearch = Infinity;
4404
+ }
4405
+
4406
+ decorated.call(this, $element, options, dataAdapter);
4407
+ }
4408
+
4409
+ MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
4410
+ if (countResults(params.data.results) < this.minimumResultsForSearch) {
4411
+ return false;
4412
+ }
4413
+
4414
+ return decorated.call(this, params);
4415
+ };
4416
+
4417
+ return MinimumResultsForSearch;
4418
+ });
4419
+
4420
+ S2.define('select2/dropdown/selectOnClose',[
4421
+
4422
+ ], function () {
4423
+ function SelectOnClose () { }
4424
+
4425
+ SelectOnClose.prototype.bind = function (decorated, container, $container) {
4426
+ var self = this;
4427
+
4428
+ decorated.call(this, container, $container);
4429
+
4430
+ container.on('close', function (params) {
4431
+ self._handleSelectOnClose(params);
4432
+ });
4433
+ };
4434
+
4435
+ SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
4436
+ if (params && params.originalSelect2Event != null) {
4437
+ var event = params.originalSelect2Event;
4438
+
4439
+ // Don't select an item if the close event was triggered from a select or
4440
+ // unselect event
4441
+ if (event._type === 'select' || event._type === 'unselect') {
4442
+ return;
4443
+ }
4444
+ }
4445
+
4446
+ var $highlightedResults = this.getHighlightedResults();
4447
+
4448
+ // Only select highlighted results
4449
+ if ($highlightedResults.length < 1) {
4450
+ return;
4451
+ }
4452
+
4453
+ var data = $highlightedResults.data('data');
4454
+
4455
+ // Don't re-select already selected resulte
4456
+ if (
4457
+ (data.element != null && data.element.selected) ||
4458
+ (data.element == null && data.selected)
4459
+ ) {
4460
+ return;
4461
+ }
4462
+
4463
+ this.trigger('select', {
4464
+ data: data
4465
+ });
4466
+ };
4467
+
4468
+ return SelectOnClose;
4469
+ });
4470
+
4471
+ S2.define('select2/dropdown/closeOnSelect',[
4472
+
4473
+ ], function () {
4474
+ function CloseOnSelect () { }
4475
+
4476
+ CloseOnSelect.prototype.bind = function (decorated, container, $container) {
4477
+ var self = this;
4478
+
4479
+ decorated.call(this, container, $container);
4480
+
4481
+ container.on('select', function (evt) {
4482
+ self._selectTriggered(evt);
4483
+ });
4484
+
4485
+ container.on('unselect', function (evt) {
4486
+ self._selectTriggered(evt);
4487
+ });
4488
+ };
4489
+
4490
+ CloseOnSelect.prototype._selectTriggered = function (_, evt) {
4491
+ var originalEvent = evt.originalEvent;
4492
+
4493
+ // Don't close if the control key is being held
4494
+ if (originalEvent && originalEvent.ctrlKey) {
4495
+ return;
4496
+ }
4497
+
4498
+ this.trigger('close', {
4499
+ originalEvent: originalEvent,
4500
+ originalSelect2Event: evt
4501
+ });
4502
+ };
4503
+
4504
+ return CloseOnSelect;
4505
+ });
4506
+
4507
+ S2.define('select2/i18n/en',[],function () {
4508
+ // English
4509
+ return {
4510
+ errorLoading: function () {
4511
+ return 'The results could not be loaded.';
4512
+ },
4513
+ inputTooLong: function (args) {
4514
+ var overChars = args.input.length - args.maximum;
4515
+
4516
+ var message = 'Please delete ' + overChars + ' character';
4517
+
4518
+ if (overChars != 1) {
4519
+ message += 's';
4520
+ }
4521
+
4522
+ return message;
4523
+ },
4524
+ inputTooShort: function (args) {
4525
+ var remainingChars = args.minimum - args.input.length;
4526
+
4527
+ var message = 'Please enter ' + remainingChars + ' or more characters';
4528
+
4529
+ return message;
4530
+ },
4531
+ loadingMore: function () {
4532
+ return 'Loading more results…';
4533
+ },
4534
+ maximumSelected: function (args) {
4535
+ var message = 'You can only select ' + args.maximum + ' item';
4536
+
4537
+ if (args.maximum != 1) {
4538
+ message += 's';
4539
+ }
4540
+
4541
+ return message;
4542
+ },
4543
+ noResults: function () {
4544
+ return 'No results found';
4545
+ },
4546
+ searching: function () {
4547
+ return 'Searching…';
4548
+ }
4549
+ };
4550
+ });
4551
+
4552
+ S2.define('select2/defaults',[
4553
+ 'jquery',
4554
+ 'require',
4555
+
4556
+ './results',
4557
+
4558
+ './selection/single',
4559
+ './selection/multiple',
4560
+ './selection/placeholder',
4561
+ './selection/allowClear',
4562
+ './selection/search',
4563
+ './selection/eventRelay',
4564
+
4565
+ './utils',
4566
+ './translation',
4567
+ './diacritics',
4568
+
4569
+ './data/select',
4570
+ './data/array',
4571
+ './data/ajax',
4572
+ './data/tags',
4573
+ './data/tokenizer',
4574
+ './data/minimumInputLength',
4575
+ './data/maximumInputLength',
4576
+ './data/maximumSelectionLength',
4577
+
4578
+ './dropdown',
4579
+ './dropdown/search',
4580
+ './dropdown/hidePlaceholder',
4581
+ './dropdown/infiniteScroll',
4582
+ './dropdown/attachBody',
4583
+ './dropdown/minimumResultsForSearch',
4584
+ './dropdown/selectOnClose',
4585
+ './dropdown/closeOnSelect',
4586
+
4587
+ './i18n/en'
4588
+ ], function ($, require,
4589
+
4590
+ ResultsList,
4591
+
4592
+ SingleSelection, MultipleSelection, Placeholder, AllowClear,
4593
+ SelectionSearch, EventRelay,
4594
+
4595
+ Utils, Translation, DIACRITICS,
4596
+
4597
+ SelectData, ArrayData, AjaxData, Tags, Tokenizer,
4598
+ MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
4599
+
4600
+ Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
4601
+ AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
4602
+
4603
+ EnglishTranslation) {
4604
+ function Defaults () {
4605
+ this.reset();
4606
+ }
4607
+
4608
+ Defaults.prototype.apply = function (options) {
4609
+ options = $.extend(true, {}, this.defaults, options);
4610
+
4611
+ if (options.dataAdapter == null) {
4612
+ if (options.ajax != null) {
4613
+ options.dataAdapter = AjaxData;
4614
+ } else if (options.data != null) {
4615
+ options.dataAdapter = ArrayData;
4616
+ } else {
4617
+ options.dataAdapter = SelectData;
4618
+ }
4619
+
4620
+ if (options.minimumInputLength > 0) {
4621
+ options.dataAdapter = Utils.Decorate(
4622
+ options.dataAdapter,
4623
+ MinimumInputLength
4624
+ );
4625
+ }
4626
+
4627
+ if (options.maximumInputLength > 0) {
4628
+ options.dataAdapter = Utils.Decorate(
4629
+ options.dataAdapter,
4630
+ MaximumInputLength
4631
+ );
4632
+ }
4633
+
4634
+ if (options.maximumSelectionLength > 0) {
4635
+ options.dataAdapter = Utils.Decorate(
4636
+ options.dataAdapter,
4637
+ MaximumSelectionLength
4638
+ );
4639
+ }
4640
+
4641
+ if (options.tags) {
4642
+ options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
4643
+ }
4644
+
4645
+ if (options.tokenSeparators != null || options.tokenizer != null) {
4646
+ options.dataAdapter = Utils.Decorate(
4647
+ options.dataAdapter,
4648
+ Tokenizer
4649
+ );
4650
+ }
4651
+
4652
+ if (options.query != null) {
4653
+ var Query = require(options.amdBase + 'compat/query');
4654
+
4655
+ options.dataAdapter = Utils.Decorate(
4656
+ options.dataAdapter,
4657
+ Query
4658
+ );
4659
+ }
4660
+
4661
+ if (options.initSelection != null) {
4662
+ var InitSelection = require(options.amdBase + 'compat/initSelection');
4663
+
4664
+ options.dataAdapter = Utils.Decorate(
4665
+ options.dataAdapter,
4666
+ InitSelection
4667
+ );
4668
+ }
4669
+ }
4670
+
4671
+ if (options.resultsAdapter == null) {
4672
+ options.resultsAdapter = ResultsList;
4673
+
4674
+ if (options.ajax != null) {
4675
+ options.resultsAdapter = Utils.Decorate(
4676
+ options.resultsAdapter,
4677
+ InfiniteScroll
4678
+ );
4679
+ }
4680
+
4681
+ if (options.placeholder != null) {
4682
+ options.resultsAdapter = Utils.Decorate(
4683
+ options.resultsAdapter,
4684
+ HidePlaceholder
4685
+ );
4686
+ }
4687
+
4688
+ if (options.selectOnClose) {
4689
+ options.resultsAdapter = Utils.Decorate(
4690
+ options.resultsAdapter,
4691
+ SelectOnClose
4692
+ );
4693
+ }
4694
+ }
4695
+
4696
+ if (options.dropdownAdapter == null) {
4697
+ if (options.multiple) {
4698
+ options.dropdownAdapter = Dropdown;
4699
+ } else {
4700
+ var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
4701
+
4702
+ options.dropdownAdapter = SearchableDropdown;
4703
+ }
4704
+
4705
+ if (options.minimumResultsForSearch !== 0) {
4706
+ options.dropdownAdapter = Utils.Decorate(
4707
+ options.dropdownAdapter,
4708
+ MinimumResultsForSearch
4709
+ );
4710
+ }
4711
+
4712
+ if (options.closeOnSelect) {
4713
+ options.dropdownAdapter = Utils.Decorate(
4714
+ options.dropdownAdapter,
4715
+ CloseOnSelect
4716
+ );
4717
+ }
4718
+
4719
+ if (
4720
+ options.dropdownCssClass != null ||
4721
+ options.dropdownCss != null ||
4722
+ options.adaptDropdownCssClass != null
4723
+ ) {
4724
+ var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');
4725
+
4726
+ options.dropdownAdapter = Utils.Decorate(
4727
+ options.dropdownAdapter,
4728
+ DropdownCSS
4729
+ );
4730
+ }
4731
+
4732
+ options.dropdownAdapter = Utils.Decorate(
4733
+ options.dropdownAdapter,
4734
+ AttachBody
4735
+ );
4736
+ }
4737
+
4738
+ if (options.selectionAdapter == null) {
4739
+ if (options.multiple) {
4740
+ options.selectionAdapter = MultipleSelection;
4741
+ } else {
4742
+ options.selectionAdapter = SingleSelection;
4743
+ }
4744
+
4745
+ // Add the placeholder mixin if a placeholder was specified
4746
+ if (options.placeholder != null) {
4747
+ options.selectionAdapter = Utils.Decorate(
4748
+ options.selectionAdapter,
4749
+ Placeholder
4750
+ );
4751
+ }
4752
+
4753
+ if (options.allowClear) {
4754
+ options.selectionAdapter = Utils.Decorate(
4755
+ options.selectionAdapter,
4756
+ AllowClear
4757
+ );
4758
+ }
4759
+
4760
+ if (options.multiple) {
4761
+ options.selectionAdapter = Utils.Decorate(
4762
+ options.selectionAdapter,
4763
+ SelectionSearch
4764
+ );
4765
+ }
4766
+
4767
+ if (
4768
+ options.containerCssClass != null ||
4769
+ options.containerCss != null ||
4770
+ options.adaptContainerCssClass != null
4771
+ ) {
4772
+ var ContainerCSS = require(options.amdBase + 'compat/containerCss');
4773
+
4774
+ options.selectionAdapter = Utils.Decorate(
4775
+ options.selectionAdapter,
4776
+ ContainerCSS
4777
+ );
4778
+ }
4779
+
4780
+ options.selectionAdapter = Utils.Decorate(
4781
+ options.selectionAdapter,
4782
+ EventRelay
4783
+ );
4784
+ }
4785
+
4786
+ if (typeof options.language === 'string') {
4787
+ // Check if the language is specified with a region
4788
+ if (options.language.indexOf('-') > 0) {
4789
+ // Extract the region information if it is included
4790
+ var languageParts = options.language.split('-');
4791
+ var baseLanguage = languageParts[0];
4792
+
4793
+ options.language = [options.language, baseLanguage];
4794
+ } else {
4795
+ options.language = [options.language];
4796
+ }
4797
+ }
4798
+
4799
+ if ($.isArray(options.language)) {
4800
+ var languages = new Translation();
4801
+ options.language.push('en');
4802
+
4803
+ var languageNames = options.language;
4804
+
4805
+ for (var l = 0; l < languageNames.length; l++) {
4806
+ var name = languageNames[l];
4807
+ var language = {};
4808
+
4809
+ try {
4810
+ // Try to load it with the original name
4811
+ language = Translation.loadPath(name);
4812
+ } catch (e) {
4813
+ try {
4814
+ // If we couldn't load it, check if it wasn't the full path
4815
+ name = this.defaults.amdLanguageBase + name;
4816
+ language = Translation.loadPath(name);
4817
+ } catch (ex) {
4818
+ // The translation could not be loaded at all. Sometimes this is
4819
+ // because of a configuration problem, other times this can be
4820
+ // because of how Select2 helps load all possible translation files.
4821
+ if (options.debug && window.console && console.warn) {
4822
+ console.warn(
4823
+ 'Select2: The language file for "' + name + '" could not be ' +
4824
+ 'automatically loaded. A fallback will be used instead.'
4825
+ );
4826
+ }
4827
+
4828
+ continue;
4829
+ }
4830
+ }
4831
+
4832
+ languages.extend(language);
4833
+ }
4834
+
4835
+ options.translations = languages;
4836
+ } else {
4837
+ var baseTranslation = Translation.loadPath(
4838
+ this.defaults.amdLanguageBase + 'en'
4839
+ );
4840
+ var customTranslation = new Translation(options.language);
4841
+
4842
+ customTranslation.extend(baseTranslation);
4843
+
4844
+ options.translations = customTranslation;
4845
+ }
4846
+
4847
+ return options;
4848
+ };
4849
+
4850
+ Defaults.prototype.reset = function () {
4851
+ function stripDiacritics (text) {
4852
+ // Used 'uni range + named function' from http://jsperf.com/diacritics/18
4853
+ function match(a) {
4854
+ return DIACRITICS[a] || a;
4855
+ }
4856
+
4857
+ return text.replace(/[^\u0000-\u007E]/g, match);
4858
+ }
4859
+
4860
+ function matcher (params, data) {
4861
+ // Always return the object if there is nothing to compare
4862
+ if ($.trim(params.term) === '') {
4863
+ return data;
4864
+ }
4865
+
4866
+ // Do a recursive check for options with children
4867
+ if (data.children && data.children.length > 0) {
4868
+ // Clone the data object if there are children
4869
+ // This is required as we modify the object to remove any non-matches
4870
+ var match = $.extend(true, {}, data);
4871
+
4872
+ // Check each child of the option
4873
+ for (var c = data.children.length - 1; c >= 0; c--) {
4874
+ var child = data.children[c];
4875
+
4876
+ var matches = matcher(params, child);
4877
+
4878
+ // If there wasn't a match, remove the object in the array
4879
+ if (matches == null) {
4880
+ match.children.splice(c, 1);
4881
+ }
4882
+ }
4883
+
4884
+ // If any children matched, return the new object
4885
+ if (match.children.length > 0) {
4886
+ return match;
4887
+ }
4888
+
4889
+ // If there were no matching children, check just the plain object
4890
+ return matcher(params, match);
4891
+ }
4892
+
4893
+ var original = stripDiacritics(data.text).toUpperCase();
4894
+ var term = stripDiacritics(params.term).toUpperCase();
4895
+
4896
+ // Check if the text contains the term
4897
+ if (original.indexOf(term) > -1) {
4898
+ return data;
4899
+ }
4900
+
4901
+ // If it doesn't contain the term, don't return anything
4902
+ return null;
4903
+ }
4904
+
4905
+ this.defaults = {
4906
+ amdBase: './',
4907
+ amdLanguageBase: './i18n/',
4908
+ closeOnSelect: true,
4909
+ debug: false,
4910
+ dropdownAutoWidth: false,
4911
+ escapeMarkup: Utils.escapeMarkup,
4912
+ language: EnglishTranslation,
4913
+ matcher: matcher,
4914
+ minimumInputLength: 0,
4915
+ maximumInputLength: 0,
4916
+ maximumSelectionLength: 0,
4917
+ minimumResultsForSearch: 0,
4918
+ selectOnClose: false,
4919
+ sorter: function (data) {
4920
+ return data;
4921
+ },
4922
+ templateResult: function (result) {
4923
+ return result.text;
4924
+ },
4925
+ templateSelection: function (selection) {
4926
+ return selection.text;
4927
+ },
4928
+ theme: 'default',
4929
+ width: 'resolve'
4930
+ };
4931
+ };
4932
+
4933
+ Defaults.prototype.set = function (key, value) {
4934
+ var camelKey = $.camelCase(key);
4935
+
4936
+ var data = {};
4937
+ data[camelKey] = value;
4938
+
4939
+ var convertedData = Utils._convertData(data);
4940
+
4941
+ $.extend(this.defaults, convertedData);
4942
+ };
4943
+
4944
+ var defaults = new Defaults();
4945
+
4946
+ return defaults;
4947
+ });
4948
+
4949
+ S2.define('select2/options',[
4950
+ 'require',
4951
+ 'jquery',
4952
+ './defaults',
4953
+ './utils'
4954
+ ], function (require, $, Defaults, Utils) {
4955
+ function Options (options, $element) {
4956
+ this.options = options;
4957
+
4958
+ if ($element != null) {
4959
+ this.fromElement($element);
4960
+ }
4961
+
4962
+ this.options = Defaults.apply(this.options);
4963
+
4964
+ if ($element && $element.is('input')) {
4965
+ var InputCompat = require(this.get('amdBase') + 'compat/inputData');
4966
+
4967
+ this.options.dataAdapter = Utils.Decorate(
4968
+ this.options.dataAdapter,
4969
+ InputCompat
4970
+ );
4971
+ }
4972
+ }
4973
+
4974
+ Options.prototype.fromElement = function ($e) {
4975
+ var excludedData = ['select2'];
4976
+
4977
+ if (this.options.multiple == null) {
4978
+ this.options.multiple = $e.prop('multiple');
4979
+ }
4980
+
4981
+ if (this.options.disabled == null) {
4982
+ this.options.disabled = $e.prop('disabled');
4983
+ }
4984
+
4985
+ if (this.options.language == null) {
4986
+ if ($e.prop('lang')) {
4987
+ this.options.language = $e.prop('lang').toLowerCase();
4988
+ } else if ($e.closest('[lang]').prop('lang')) {
4989
+ this.options.language = $e.closest('[lang]').prop('lang');
4990
+ }
4991
+ }
4992
+
4993
+ if (this.options.dir == null) {
4994
+ if ($e.prop('dir')) {
4995
+ this.options.dir = $e.prop('dir');
4996
+ } else if ($e.closest('[dir]').prop('dir')) {
4997
+ this.options.dir = $e.closest('[dir]').prop('dir');
4998
+ } else {
4999
+ this.options.dir = 'ltr';
5000
+ }
5001
+ }
5002
+
5003
+ $e.prop('disabled', this.options.disabled);
5004
+ $e.prop('multiple', this.options.multiple);
5005
+
5006
+ if ($e.data('select2Tags')) {
5007
+ if (this.options.debug && window.console && console.warn) {
5008
+ console.warn(
5009
+ 'Select2: The `data-select2-tags` attribute has been changed to ' +
5010
+ 'use the `data-data` and `data-tags="true"` attributes and will be ' +
5011
+ 'removed in future versions of Select2.'
5012
+ );
5013
+ }
5014
+
5015
+ $e.data('data', $e.data('select2Tags'));
5016
+ $e.data('tags', true);
5017
+ }
5018
+
5019
+ if ($e.data('ajaxUrl')) {
5020
+ if (this.options.debug && window.console && console.warn) {
5021
+ console.warn(
5022
+ 'Select2: The `data-ajax-url` attribute has been changed to ' +
5023
+ '`data-ajax--url` and support for the old attribute will be removed' +
5024
+ ' in future versions of Select2.'
5025
+ );
5026
+ }
5027
+
5028
+ $e.attr('ajax--url', $e.data('ajaxUrl'));
5029
+ $e.data('ajax--url', $e.data('ajaxUrl'));
5030
+ }
5031
+
5032
+ var dataset = {};
5033
+
5034
+ // Prefer the element's `dataset` attribute if it exists
5035
+ // jQuery 1.x does not correctly handle data attributes with multiple dashes
5036
+ if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
5037
+ dataset = $.extend(true, {}, $e[0].dataset, $e.data());
5038
+ } else {
5039
+ dataset = $e.data();
5040
+ }
5041
+
5042
+ var data = $.extend(true, {}, dataset);
5043
+
5044
+ data = Utils._convertData(data);
5045
+
5046
+ for (var key in data) {
5047
+ if ($.inArray(key, excludedData) > -1) {
5048
+ continue;
5049
+ }
5050
+
5051
+ if ($.isPlainObject(this.options[key])) {
5052
+ $.extend(this.options[key], data[key]);
5053
+ } else {
5054
+ this.options[key] = data[key];
5055
+ }
5056
+ }
5057
+
5058
+ return this;
5059
+ };
5060
+
5061
+ Options.prototype.get = function (key) {
5062
+ return this.options[key];
5063
+ };
5064
+
5065
+ Options.prototype.set = function (key, val) {
5066
+ this.options[key] = val;
5067
+ };
5068
+
5069
+ return Options;
5070
+ });
5071
+
5072
+ S2.define('select2/core',[
5073
+ 'jquery',
5074
+ './options',
5075
+ './utils',
5076
+ './keys'
5077
+ ], function ($, Options, Utils, KEYS) {
5078
+ var Select2 = function ($element, options) {
5079
+ if ($element.data('select2') != null) {
5080
+ $element.data('select2').destroy();
5081
+ }
5082
+
5083
+ this.$element = $element;
5084
+
5085
+ this.id = this._generateId($element);
5086
+
5087
+ options = options || {};
5088
+
5089
+ this.options = new Options(options, $element);
5090
+
5091
+ Select2.__super__.constructor.call(this);
5092
+
5093
+ // Set up the tabindex
5094
+
5095
+ var tabindex = $element.attr('tabindex') || 0;
5096
+ $element.data('old-tabindex', tabindex);
5097
+ $element.attr('tabindex', '-1');
5098
+
5099
+ // Set up containers and adapters
5100
+
5101
+ var DataAdapter = this.options.get('dataAdapter');
5102
+ this.dataAdapter = new DataAdapter($element, this.options);
5103
+
5104
+ var $container = this.render();
5105
+
5106
+ this._placeContainer($container);
5107
+
5108
+ var SelectionAdapter = this.options.get('selectionAdapter');
5109
+ this.selection = new SelectionAdapter($element, this.options);
5110
+ this.$selection = this.selection.render();
5111
+
5112
+ this.selection.position(this.$selection, $container);
5113
+
5114
+ var DropdownAdapter = this.options.get('dropdownAdapter');
5115
+ this.dropdown = new DropdownAdapter($element, this.options);
5116
+ this.$dropdown = this.dropdown.render();
5117
+
5118
+ this.dropdown.position(this.$dropdown, $container);
5119
+
5120
+ var ResultsAdapter = this.options.get('resultsAdapter');
5121
+ this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
5122
+ this.$results = this.results.render();
5123
+
5124
+ this.results.position(this.$results, this.$dropdown);
5125
+
5126
+ // Bind events
5127
+
5128
+ var self = this;
5129
+
5130
+ // Bind the container to all of the adapters
5131
+ this._bindAdapters();
5132
+
5133
+ // Register any DOM event handlers
5134
+ this._registerDomEvents();
5135
+
5136
+ // Register any internal event handlers
5137
+ this._registerDataEvents();
5138
+ this._registerSelectionEvents();
5139
+ this._registerDropdownEvents();
5140
+ this._registerResultsEvents();
5141
+ this._registerEvents();
5142
+
5143
+ // Set the initial state
5144
+ this.dataAdapter.current(function (initialData) {
5145
+ self.trigger('selection:update', {
5146
+ data: initialData
5147
+ });
5148
+ });
5149
+
5150
+ // Hide the original select
5151
+ $element.addClass('select2-hidden-accessible');
5152
+ $element.attr('aria-hidden', 'true');
5153
+
5154
+ // Synchronize any monitored attributes
5155
+ this._syncAttributes();
5156
+
5157
+ $element.data('select2', this);
5158
+ };
5159
+
5160
+ Utils.Extend(Select2, Utils.Observable);
5161
+
5162
+ Select2.prototype._generateId = function ($element) {
5163
+ var id = '';
5164
+
5165
+ if ($element.attr('id') != null) {
5166
+ id = $element.attr('id');
5167
+ } else if ($element.attr('name') != null) {
5168
+ id = $element.attr('name') + '-' + Utils.generateChars(2);
5169
+ } else {
5170
+ id = Utils.generateChars(4);
5171
+ }
5172
+
5173
+ id = id.replace(/(:|\.|\[|\]|,)/g, '');
5174
+ id = 'select2-' + id;
5175
+
5176
+ return id;
5177
+ };
5178
+
5179
+ Select2.prototype._placeContainer = function ($container) {
5180
+ $container.insertAfter(this.$element);
5181
+
5182
+ var width = this._resolveWidth(this.$element, this.options.get('width'));
5183
+
5184
+ if (width != null) {
5185
+ $container.css('width', width);
5186
+ }
5187
+ };
5188
+
5189
+ Select2.prototype._resolveWidth = function ($element, method) {
5190
+ var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
5191
+
5192
+ if (method == 'resolve') {
5193
+ var styleWidth = this._resolveWidth($element, 'style');
5194
+
5195
+ if (styleWidth != null) {
5196
+ return styleWidth;
5197
+ }
5198
+
5199
+ return this._resolveWidth($element, 'element');
5200
+ }
5201
+
5202
+ if (method == 'element') {
5203
+ var elementWidth = $element.outerWidth(false);
5204
+
5205
+ if (elementWidth <= 0) {
5206
+ return 'auto';
5207
+ }
5208
+
5209
+ return elementWidth + 'px';
5210
+ }
5211
+
5212
+ if (method == 'style') {
5213
+ var style = $element.attr('style');
5214
+
5215
+ if (typeof(style) !== 'string') {
5216
+ return null;
5217
+ }
5218
+
5219
+ var attrs = style.split(';');
5220
+
5221
+ for (var i = 0, l = attrs.length; i < l; i = i + 1) {
5222
+ var attr = attrs[i].replace(/\s/g, '');
5223
+ var matches = attr.match(WIDTH);
5224
+
5225
+ if (matches !== null && matches.length >= 1) {
5226
+ return matches[1];
5227
+ }
5228
+ }
5229
+
5230
+ return null;
5231
+ }
5232
+
5233
+ return method;
5234
+ };
5235
+
5236
+ Select2.prototype._bindAdapters = function () {
5237
+ this.dataAdapter.bind(this, this.$container);
5238
+ this.selection.bind(this, this.$container);
5239
+
5240
+ this.dropdown.bind(this, this.$container);
5241
+ this.results.bind(this, this.$container);
5242
+ };
5243
+
5244
+ Select2.prototype._registerDomEvents = function () {
5245
+ var self = this;
5246
+
5247
+ this.$element.on('change.select2', function () {
5248
+ self.dataAdapter.current(function (data) {
5249
+ self.trigger('selection:update', {
5250
+ data: data
5251
+ });
5252
+ });
5253
+ });
5254
+
5255
+ this.$element.on('focus.select2', function (evt) {
5256
+ self.trigger('focus', evt);
5257
+ });
5258
+
5259
+ this._syncA = Utils.bind(this._syncAttributes, this);
5260
+ this._syncS = Utils.bind(this._syncSubtree, this);
5261
+
5262
+ if (this.$element[0].attachEvent) {
5263
+ this.$element[0].attachEvent('onpropertychange', this._syncA);
5264
+ }
5265
+
5266
+ var observer = window.MutationObserver ||
5267
+ window.WebKitMutationObserver ||
5268
+ window.MozMutationObserver
5269
+ ;
5270
+
5271
+ if (observer != null) {
5272
+ this._observer = new observer(function (mutations) {
5273
+ $.each(mutations, self._syncA);
5274
+ $.each(mutations, self._syncS);
5275
+ });
5276
+ this._observer.observe(this.$element[0], {
5277
+ attributes: true,
5278
+ childList: true,
5279
+ subtree: false
5280
+ });
5281
+ } else if (this.$element[0].addEventListener) {
5282
+ this.$element[0].addEventListener(
5283
+ 'DOMAttrModified',
5284
+ self._syncA,
5285
+ false
5286
+ );
5287
+ this.$element[0].addEventListener(
5288
+ 'DOMNodeInserted',
5289
+ self._syncS,
5290
+ false
5291
+ );
5292
+ this.$element[0].addEventListener(
5293
+ 'DOMNodeRemoved',
5294
+ self._syncS,
5295
+ false
5296
+ );
5297
+ }
5298
+ };
5299
+
5300
+ Select2.prototype._registerDataEvents = function () {
5301
+ var self = this;
5302
+
5303
+ this.dataAdapter.on('*', function (name, params) {
5304
+ self.trigger(name, params);
5305
+ });
5306
+ };
5307
+
5308
+ Select2.prototype._registerSelectionEvents = function () {
5309
+ var self = this;
5310
+ var nonRelayEvents = ['toggle', 'focus'];
5311
+
5312
+ this.selection.on('toggle', function () {
5313
+ self.toggleDropdown();
5314
+ });
5315
+
5316
+ this.selection.on('focus', function (params) {
5317
+ self.focus(params);
5318
+ });
5319
+
5320
+ this.selection.on('*', function (name, params) {
5321
+ if ($.inArray(name, nonRelayEvents) !== -1) {
5322
+ return;
5323
+ }
5324
+
5325
+ self.trigger(name, params);
5326
+ });
5327
+ };
5328
+
5329
+ Select2.prototype._registerDropdownEvents = function () {
5330
+ var self = this;
5331
+
5332
+ this.dropdown.on('*', function (name, params) {
5333
+ self.trigger(name, params);
5334
+ });
5335
+ };
5336
+
5337
+ Select2.prototype._registerResultsEvents = function () {
5338
+ var self = this;
5339
+
5340
+ this.results.on('*', function (name, params) {
5341
+ self.trigger(name, params);
5342
+ });
5343
+ };
5344
+
5345
+ Select2.prototype._registerEvents = function () {
5346
+ var self = this;
5347
+
5348
+ this.on('open', function () {
5349
+ self.$container.addClass('select2-container--open');
5350
+ });
5351
+
5352
+ this.on('close', function () {
5353
+ self.$container.removeClass('select2-container--open');
5354
+ });
5355
+
5356
+ this.on('enable', function () {
5357
+ self.$container.removeClass('select2-container--disabled');
5358
+ });
5359
+
5360
+ this.on('disable', function () {
5361
+ self.$container.addClass('select2-container--disabled');
5362
+ });
5363
+
5364
+ this.on('blur', function () {
5365
+ self.$container.removeClass('select2-container--focus');
5366
+ });
5367
+
5368
+ this.on('query', function (params) {
5369
+ if (!self.isOpen()) {
5370
+ self.trigger('open', {});
5371
+ }
5372
+
5373
+ this.dataAdapter.query(params, function (data) {
5374
+ self.trigger('results:all', {
5375
+ data: data,
5376
+ query: params
5377
+ });
5378
+ });
5379
+ });
5380
+
5381
+ this.on('query:append', function (params) {
5382
+ this.dataAdapter.query(params, function (data) {
5383
+ self.trigger('results:append', {
5384
+ data: data,
5385
+ query: params
5386
+ });
5387
+ });
5388
+ });
5389
+
5390
+ this.on('keypress', function (evt) {
5391
+ var key = evt.which;
5392
+
5393
+ if (self.isOpen()) {
5394
+ if (key === KEYS.ESC || key === KEYS.TAB ||
5395
+ (key === KEYS.UP && evt.altKey)) {
5396
+ self.close();
5397
+
5398
+ evt.preventDefault();
5399
+ } else if (key === KEYS.ENTER) {
5400
+ self.trigger('results:select', {});
5401
+
5402
+ evt.preventDefault();
5403
+ } else if ((key === KEYS.SPACE && evt.ctrlKey)) {
5404
+ self.trigger('results:toggle', {});
5405
+
5406
+ evt.preventDefault();
5407
+ } else if (key === KEYS.UP) {
5408
+ self.trigger('results:previous', {});
5409
+
5410
+ evt.preventDefault();
5411
+ } else if (key === KEYS.DOWN) {
5412
+ self.trigger('results:next', {});
5413
+
5414
+ evt.preventDefault();
5415
+ }
5416
+ } else {
5417
+ if (key === KEYS.ENTER || key === KEYS.SPACE ||
5418
+ (key === KEYS.DOWN && evt.altKey)) {
5419
+ self.open();
5420
+
5421
+ evt.preventDefault();
5422
+ }
5423
+ }
5424
+ });
5425
+ };
5426
+
5427
+ Select2.prototype._syncAttributes = function () {
5428
+ this.options.set('disabled', this.$element.prop('disabled'));
5429
+
5430
+ if (this.options.get('disabled')) {
5431
+ if (this.isOpen()) {
5432
+ this.close();
5433
+ }
5434
+
5435
+ this.trigger('disable', {});
5436
+ } else {
5437
+ this.trigger('enable', {});
5438
+ }
5439
+ };
5440
+
5441
+ Select2.prototype._syncSubtree = function (evt, mutations) {
5442
+ var changed = false;
5443
+ var self = this;
5444
+
5445
+ // Ignore any mutation events raised for elements that aren't options or
5446
+ // optgroups. This handles the case when the select element is destroyed
5447
+ if (
5448
+ evt && evt.target && (
5449
+ evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'
5450
+ )
5451
+ ) {
5452
+ return;
5453
+ }
5454
+
5455
+ if (!mutations) {
5456
+ // If mutation events aren't supported, then we can only assume that the
5457
+ // change affected the selections
5458
+ changed = true;
5459
+ } else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
5460
+ for (var n = 0; n < mutations.addedNodes.length; n++) {
5461
+ var node = mutations.addedNodes[n];
5462
+
5463
+ if (node.selected) {
5464
+ changed = true;
5465
+ }
5466
+ }
5467
+ } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
5468
+ changed = true;
5469
+ }
5470
+
5471
+ // Only re-pull the data if we think there is a change
5472
+ if (changed) {
5473
+ this.dataAdapter.current(function (currentData) {
5474
+ self.trigger('selection:update', {
5475
+ data: currentData
5476
+ });
5477
+ });
5478
+ }
5479
+ };
5480
+
5481
+ /**
5482
+ * Override the trigger method to automatically trigger pre-events when
5483
+ * there are events that can be prevented.
5484
+ */
5485
+ Select2.prototype.trigger = function (name, args) {
5486
+ var actualTrigger = Select2.__super__.trigger;
5487
+ var preTriggerMap = {
5488
+ 'open': 'opening',
5489
+ 'close': 'closing',
5490
+ 'select': 'selecting',
5491
+ 'unselect': 'unselecting'
5492
+ };
5493
+
5494
+ if (args === undefined) {
5495
+ args = {};
5496
+ }
5497
+
5498
+ if (name in preTriggerMap) {
5499
+ var preTriggerName = preTriggerMap[name];
5500
+ var preTriggerArgs = {
5501
+ prevented: false,
5502
+ name: name,
5503
+ args: args
5504
+ };
5505
+
5506
+ actualTrigger.call(this, preTriggerName, preTriggerArgs);
5507
+
5508
+ if (preTriggerArgs.prevented) {
5509
+ args.prevented = true;
5510
+
5511
+ return;
5512
+ }
5513
+ }
5514
+
5515
+ actualTrigger.call(this, name, args);
5516
+ };
5517
+
5518
+ Select2.prototype.toggleDropdown = function () {
5519
+ if (this.options.get('disabled')) {
5520
+ return;
5521
+ }
5522
+
5523
+ if (this.isOpen()) {
5524
+ this.close();
5525
+ } else {
5526
+ this.open();
5527
+ }
5528
+ };
5529
+
5530
+ Select2.prototype.open = function () {
5531
+ if (this.isOpen()) {
5532
+ return;
5533
+ }
5534
+
5535
+ this.trigger('query', {});
5536
+ };
5537
+
5538
+ Select2.prototype.close = function () {
5539
+ if (!this.isOpen()) {
5540
+ return;
5541
+ }
5542
+
5543
+ this.trigger('close', {});
5544
+ };
5545
+
5546
+ Select2.prototype.isOpen = function () {
5547
+ return this.$container.hasClass('select2-container--open');
5548
+ };
5549
+
5550
+ Select2.prototype.hasFocus = function () {
5551
+ return this.$container.hasClass('select2-container--focus');
5552
+ };
5553
+
5554
+ Select2.prototype.focus = function (data) {
5555
+ // No need to re-trigger focus events if we are already focused
5556
+ if (this.hasFocus()) {
5557
+ return;
5558
+ }
5559
+
5560
+ this.$container.addClass('select2-container--focus');
5561
+ this.trigger('focus', {});
5562
+ };
5563
+
5564
+ Select2.prototype.enable = function (args) {
5565
+ if (this.options.get('debug') && window.console && console.warn) {
5566
+ console.warn(
5567
+ 'Select2: The `select2("enable")` method has been deprecated and will' +
5568
+ ' be removed in later Select2 versions. Use $element.prop("disabled")' +
5569
+ ' instead.'
5570
+ );
5571
+ }
5572
+
5573
+ if (args == null || args.length === 0) {
5574
+ args = [true];
5575
+ }
5576
+
5577
+ var disabled = !args[0];
5578
+
5579
+ this.$element.prop('disabled', disabled);
5580
+ };
5581
+
5582
+ Select2.prototype.data = function () {
5583
+ if (this.options.get('debug') &&
5584
+ arguments.length > 0 && window.console && console.warn) {
5585
+ console.warn(
5586
+ 'Select2: Data can no longer be set using `select2("data")`. You ' +
5587
+ 'should consider setting the value instead using `$element.val()`.'
5588
+ );
5589
+ }
5590
+
5591
+ var data = [];
5592
+
5593
+ this.dataAdapter.current(function (currentData) {
5594
+ data = currentData;
5595
+ });
5596
+
5597
+ return data;
5598
+ };
5599
+
5600
+ Select2.prototype.val = function (args) {
5601
+ if (this.options.get('debug') && window.console && console.warn) {
5602
+ console.warn(
5603
+ 'Select2: The `select2("val")` method has been deprecated and will be' +
5604
+ ' removed in later Select2 versions. Use $element.val() instead.'
5605
+ );
5606
+ }
5607
+
5608
+ if (args == null || args.length === 0) {
5609
+ return this.$element.val();
5610
+ }
5611
+
5612
+ var newVal = args[0];
5613
+
5614
+ if ($.isArray(newVal)) {
5615
+ newVal = $.map(newVal, function (obj) {
5616
+ return obj.toString();
5617
+ });
5618
+ }
5619
+
5620
+ this.$element.val(newVal).trigger('change');
5621
+ };
5622
+
5623
+ Select2.prototype.destroy = function () {
5624
+ this.$container.remove();
5625
+
5626
+ if (this.$element[0].detachEvent) {
5627
+ this.$element[0].detachEvent('onpropertychange', this._syncA);
5628
+ }
5629
+
5630
+ if (this._observer != null) {
5631
+ this._observer.disconnect();
5632
+ this._observer = null;
5633
+ } else if (this.$element[0].removeEventListener) {
5634
+ this.$element[0]
5635
+ .removeEventListener('DOMAttrModified', this._syncA, false);
5636
+ this.$element[0]
5637
+ .removeEventListener('DOMNodeInserted', this._syncS, false);
5638
+ this.$element[0]
5639
+ .removeEventListener('DOMNodeRemoved', this._syncS, false);
5640
+ }
5641
+
5642
+ this._syncA = null;
5643
+ this._syncS = null;
5644
+
5645
+ this.$element.off('.select2');
5646
+ this.$element.attr('tabindex', this.$element.data('old-tabindex'));
5647
+
5648
+ this.$element.removeClass('select2-hidden-accessible');
5649
+ this.$element.attr('aria-hidden', 'false');
5650
+ this.$element.removeData('select2');
5651
+
5652
+ this.dataAdapter.destroy();
5653
+ this.selection.destroy();
5654
+ this.dropdown.destroy();
5655
+ this.results.destroy();
5656
+
5657
+ this.dataAdapter = null;
5658
+ this.selection = null;
5659
+ this.dropdown = null;
5660
+ this.results = null;
5661
+ };
5662
+
5663
+ Select2.prototype.render = function () {
5664
+ var $container = $(
5665
+ '<span class="select2 select2-container">' +
5666
+ '<span class="selection"></span>' +
5667
+ '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
5668
+ '</span>'
5669
+ );
5670
+
5671
+ $container.attr('dir', this.options.get('dir'));
5672
+
5673
+ this.$container = $container;
5674
+
5675
+ this.$container.addClass('select2-container--' + this.options.get('theme'));
5676
+
5677
+ $container.data('element', this.$element);
5678
+
5679
+ return $container;
5680
+ };
5681
+
5682
+ return Select2;
5683
+ });
5684
+
5685
+ S2.define('jquery-mousewheel',[
5686
+ 'jquery'
5687
+ ], function ($) {
5688
+ // Used to shim jQuery.mousewheel for non-full builds.
5689
+ return $;
5690
+ });
5691
+
5692
+ S2.define('jquery.select2',[
5693
+ 'jquery',
5694
+ 'jquery-mousewheel',
5695
+
5696
+ './select2/core',
5697
+ './select2/defaults'
5698
+ ], function ($, _, Select2, Defaults) {
5699
+ if ($.fn.select2 == null) {
5700
+ // All methods that should return the element
5701
+ var thisMethods = ['open', 'close', 'destroy'];
5702
+
5703
+ $.fn.select2 = function (options) {
5704
+ options = options || {};
5705
+
5706
+ if (typeof options === 'object') {
5707
+ this.each(function () {
5708
+ var instanceOptions = $.extend(true, {}, options);
5709
+
5710
+ var instance = new Select2($(this), instanceOptions);
5711
+ });
5712
+
5713
+ return this;
5714
+ } else if (typeof options === 'string') {
5715
+ var ret;
5716
+ var args = Array.prototype.slice.call(arguments, 1);
5717
+
5718
+ this.each(function () {
5719
+ var instance = $(this).data('select2');
5720
+
5721
+ if (instance == null && window.console && console.error) {
5722
+ console.error(
5723
+ 'The select2(\'' + options + '\') method was called on an ' +
5724
+ 'element that is not using Select2.'
5725
+ );
5726
+ }
5727
+
5728
+ ret = instance[options].apply(instance, args);
5729
+ });
5730
+
5731
+ // Check if we should be returning `this`
5732
+ if ($.inArray(options, thisMethods) > -1) {
5733
+ return this;
5734
+ }
5735
+
5736
+ return ret;
5737
+ } else {
5738
+ throw new Error('Invalid arguments for Select2: ' + options);
5739
+ }
5740
+ };
5741
+ }
5742
+
5743
+ if ($.fn.select2.defaults == null) {
5744
+ $.fn.select2.defaults = Defaults;
5745
+ }
5746
+
5747
+ return Select2;
5748
+ });
5749
+
5750
+ // Return the AMD loader configuration so it can be used outside of this file
5751
+ return {
5752
+ define: S2.define,
5753
+ require: S2.require
5754
+ };
5755
+ }());
5756
+
5757
+ // Autoload the jQuery bindings
5758
+ // We know that all of the modules exist above this, so we're safe
5759
+ var select2 = S2.require('jquery.select2');
5760
+
5761
+ // Hold the AMD module references on the jQuery function that was just loaded
5762
+ // This allows Select2 to use the internal loader outside of this file, such
5763
+ // as in the language files.
5764
+ jQuery.fn.select2.amd = S2;
5765
+
5766
+ // Return the Select2 instance for anyone who is importing it.
5767
+ return select2;
5768
+ }));
inc/lib/target-rule/target-rule.css ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Select2 */
2
+ .post-type-astra_adv_header span.select2.select2-container.select2-container--default,
3
+ .post-type-astra-advanced-hook span.select2.select2-container.select2-container--default {
4
+ margin-top: 0;
5
+ }
6
+
7
+ .post-type-astra_adv_header li.select2-results__option.select2-results__message,
8
+ .post-type-astra-advanced-hook li.select2-results__option.select2-results__message {
9
+ background: #ecebeb;
10
+ margin-bottom: 0;
11
+ }
12
+ .ast-target-rule-wrapper .select2-container {
13
+ display: inline-block;
14
+ position: relative;
15
+ vertical-align: middle;
16
+ width: 100% !important;
17
+ }
18
+
19
+ .ast-target-rule-wrapper .select2-container--default.select2-container--focus .select2-selection--multiple,
20
+ .ast-target-rule-wrapper .select2-container--default .select2-selection--multiple {
21
+ border: 1px solid #ddd;
22
+ margin-top: 10px;
23
+ }
24
+
25
+ .ast-target-rule-wrapper .select2-container .select2-search--inline,
26
+ .ast-target-rule-wrapper .select2-container--default .select2-search--inline .select2-search__field {
27
+ width: 100% !important;
28
+ }
29
+
30
+ /* Target Rule field */
31
+ .astra-target-rule-condition,
32
+ .astra-user-role-condition {
33
+ position: relative;
34
+ margin-top: 10px;
35
+ }
36
+
37
+ .target_rule-specific-page-wrap {
38
+ position: relative;
39
+ padding: 0 30px 0 0;
40
+ }
41
+
42
+ .user_role-add-rule-wrap,
43
+ .target_rule-add-rule-wrap,
44
+ .target_rule-add-exclusion-rule,
45
+ .user_role-add-rule-wrap {
46
+ margin-top: 15px;
47
+ }
48
+
49
+ .ast-target-rule-display-on,
50
+ .ast-target-rule-exclude-on {
51
+ margin-bottom: 10px;
52
+ }
53
+
54
+ .target_rule-condition-delete,
55
+ .user_role-condition-delete {
56
+ position: absolute;
57
+ color: #999;
58
+ right: 0px;
59
+ top: 0px;
60
+ font-size: 18px;
61
+ line-height: 18px;
62
+ width: 18px;
63
+ height: 18px;
64
+ display: inline-block;
65
+ cursor: pointer;
66
+ top: 50%;
67
+ transform: translateY(-50%);
68
+ }
69
+
70
+ .target_rule-condition-delete:hover {
71
+ color: #d54e21;
72
+ }
73
+
74
+ .target_rule-add-rule-wrap {
75
+ display: inline-block;
76
+ }
77
+
78
+ .target_rule-add-exclusion-rule {
79
+ display: inline-block;
80
+ margin-left: 10px;
81
+ }
82
+
83
+ .configure-content [data-element="exclude_from"],
84
+ .configure-content [data-element="exclusive_on"] {
85
+ padding-bottom: 0;
86
+ }
87
+
88
+ .configure-content .ast-allow-specific-posts input,
89
+ .configure-content .ast-post-types {
90
+ margin-right: 3px;
91
+ }
92
+
93
+ .hide-on-devices input[type=checkbox] {
94
+ margin-right: 5px;
95
+ }
96
+
97
+ .search-panel.search-close-icon {
98
+ pointer-events: auto;
99
+ cursor: pointer;
100
+ }
101
+
102
+ .ast-hidden {
103
+ display: none !important;
104
+ }
inc/lib/target-rule/target-rule.js ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ;(function ( $, window, undefined ) {
2
+
3
+ var init_target_rule_select2 = function( selector ) {
4
+
5
+ $(selector).astselect2({
6
+
7
+ placeholder: astRules.search,
8
+
9
+ ajax: {
10
+ url: ajaxurl,
11
+ dataType: 'json',
12
+ method: 'post',
13
+ delay: 250,
14
+ data: function (params) {
15
+ return {
16
+ q: params.term, // search term
17
+ page: params.page,
18
+ action: 'astra_get_posts_by_query'
19
+ };
20
+ },
21
+ processResults: function (data) {
22
+ // console.log(data);
23
+ // console.log("inside");
24
+ // parse the results into the format expected by Select2.
25
+ // since we are using custom formatting functions we do not need to
26
+ // alter the remote JSON data
27
+
28
+ return {
29
+ results: data
30
+ };
31
+ },
32
+ cache: true
33
+ },
34
+ minimumInputLength: 2,
35
+ language: astRules.ast_lang
36
+ });
37
+ };
38
+
39
+ var update_target_rule_input = function(wrapper) {
40
+ var rule_input = wrapper.find('.ast-target_rule-input');
41
+ var old_value = rule_input.val();
42
+ var new_value = [];
43
+
44
+ wrapper.find('.astra-target-rule-condition').each(function(i) {
45
+
46
+ var $this = $(this);
47
+ var temp_obj = {};
48
+ var rule_condition = $this.find('select.target_rule-condition');
49
+ var specific_page = $this.find('select.target_rule-specific-page');
50
+
51
+ var rule_condition_val = rule_condition.val();
52
+ var specific_page_val = specific_page.val();
53
+
54
+ if ( '' != rule_condition_val ) {
55
+
56
+ temp_obj = {
57
+ type : rule_condition_val,
58
+ specific: specific_page_val
59
+ }
60
+
61
+ new_value.push( temp_obj );
62
+ };
63
+ })
64
+
65
+
66
+ var rules_string = JSON.stringify( new_value );
67
+ rule_input.val( rules_string );
68
+ };
69
+
70
+ var update_close_button = function(wrapper) {
71
+
72
+ type = wrapper.closest('.ast-target-rule-wrapper').attr('data-type');
73
+ rules = wrapper.find('.astra-target-rule-condition');
74
+ show_close = false;
75
+
76
+ if ( 'display' == type ) {
77
+ if ( rules.length > 1 ) {
78
+ show_close = true;
79
+ }
80
+ }else{
81
+ show_close = true;
82
+ }
83
+
84
+ rules.each(function() {
85
+ if ( show_close ) {
86
+ jQuery(this).find('.target_rule-condition-delete').removeClass('ast-hidden');
87
+ }else{
88
+ jQuery(this).find('.target_rule-condition-delete').addClass('ast-hidden');
89
+ }
90
+ });
91
+ };
92
+
93
+ var update_exclusion_button = function( force_show, force_hide ) {
94
+ var display_on = $('.ast-target-rule-display-on-wrap');
95
+ var exclude_on = $('.ast-target-rule-exclude-on-wrap');
96
+
97
+ var exclude_field_wrap = exclude_on.closest('tr');
98
+ var add_exclude_block = display_on.find('.target_rule-add-exclusion-rule');
99
+ var exclude_conditions = exclude_on.find('.astra-target-rule-condition');
100
+
101
+ if ( true == force_hide ) {
102
+ exclude_field_wrap.addClass( 'ast-hidden' );
103
+ add_exclude_block.removeClass( 'ast-hidden' );
104
+ }else if( true == force_show ){
105
+ exclude_field_wrap.removeClass( 'ast-hidden' );
106
+ add_exclude_block.addClass( 'ast-hidden' );
107
+ }else{
108
+
109
+ if ( 1 == exclude_conditions.length && '' == $(exclude_conditions[0]).find('select.target_rule-condition').val() ) {
110
+ exclude_field_wrap.addClass( 'ast-hidden' );
111
+ add_exclude_block.removeClass( 'ast-hidden' );
112
+ }else{
113
+ exclude_field_wrap.removeClass( 'ast-hidden' );
114
+ add_exclude_block.addClass( 'ast-hidden' );
115
+ }
116
+ }
117
+
118
+ };
119
+
120
+ $(document).ready(function($) {
121
+
122
+ jQuery( '.astra-target-rule-condition' ).each( function() {
123
+ var $this = $( this ),
124
+ condition = $this.find('select.target_rule-condition'),
125
+ condition_val = condition.val(),
126
+ specific_page = $this.next( '.target_rule-specific-page-wrap' );
127
+
128
+ if( 'specifics' == condition_val ) {
129
+ specific_page.slideDown( 300 );
130
+ }
131
+ } );
132
+
133
+
134
+ jQuery('select.target-rule-select2').each(function(index, el) {
135
+ init_target_rule_select2( el );
136
+ });
137
+
138
+ jQuery('.ast-target-rule-selector-wrapper').each(function() {
139
+ update_close_button( jQuery(this) );
140
+ })
141
+
142
+ /* Show hide exclusion button */
143
+ update_exclusion_button();
144
+
145
+ jQuery( document ).on( 'change', '.astra-target-rule-condition select.target_rule-condition' , function( e ) {
146
+
147
+ var $this = jQuery(this),
148
+ this_val = $this.val(),
149
+ field_wrap = $this.closest('.ast-target-rule-wrapper');
150
+
151
+ if( 'specifics' == this_val ) {
152
+ $this.closest( '.astra-target-rule-condition' ).next( '.target_rule-specific-page-wrap' ).slideDown( 300 );
153
+ } else {
154
+ $this.closest( '.astra-target-rule-condition' ).next( '.target_rule-specific-page-wrap' ).slideUp( 300 );
155
+ }
156
+
157
+ update_target_rule_input( field_wrap );
158
+ } );
159
+
160
+ jQuery( '.ast-target-rule-selector-wrapper' ).on( 'change', '.target-rule-select2', function(e) {
161
+ var $this = jQuery( this ),
162
+ field_wrap = $this.closest('.ast-target-rule-wrapper');
163
+
164
+ update_target_rule_input( field_wrap );
165
+ });
166
+
167
+ jQuery( '.ast-target-rule-selector-wrapper' ).on( 'click', '.target_rule-add-rule-wrap a', function(e) {
168
+ e.preventDefault();
169
+ e.stopPropagation();
170
+ var $this = jQuery( this ),
171
+ id = $this.attr( 'data-rule-id' ),
172
+ new_id = parseInt(id) + 1,
173
+ type = $this.attr( 'data-rule-type' ),
174
+ rule_wrap = $this.closest('.ast-target-rule-selector-wrapper').find('.target_rule-builder-wrap'),
175
+ template = wp.template( 'astra-target-rule-' + type + '-condition' ),
176
+ field_wrap = $this.closest('.ast-target-rule-wrapper');
177
+
178
+ rule_wrap.append( template( { id : new_id, type : type } ) );
179
+
180
+ init_target_rule_select2( '.ast-target-rule-'+type+'-on .target-rule-select2' );
181
+
182
+ $this.attr( 'data-rule-id', new_id );
183
+
184
+ update_close_button( field_wrap );
185
+ });
186
+
187
+ jQuery( '.ast-target-rule-selector-wrapper' ).on( 'click', '.target_rule-condition-delete', function(e) {
188
+ var $this = jQuery( this ),
189
+ rule_condition = $this.closest('.astra-target-rule-condition'),
190
+ field_wrap = $this.closest('.ast-target-rule-wrapper');
191
+ cnt = 0,
192
+ data_type = field_wrap.attr( 'data-type' ),
193
+ optionVal = $this.siblings('.target_rule-condition-wrap').children('.target_rule-condition').val();
194
+
195
+ if ( 'exclude' == data_type ) {
196
+
197
+ if ( 1 === field_wrap.find('.target_rule-condition').length ) {
198
+
199
+ field_wrap.find('.target_rule-condition').val('');
200
+ field_wrap.find('.target_rule-specific-page').val('');
201
+ field_wrap.find('.target_rule-condition').trigger('change');
202
+ update_exclusion_button( false, true );
203
+
204
+ }else{
205
+ $this.parent('.astra-target-rule-condition').next('.target_rule-specific-page-wrap').remove();
206
+ rule_condition.remove();
207
+ }
208
+
209
+ } else {
210
+
211
+ $this.parent('.astra-target-rule-condition').next('.target_rule-specific-page-wrap').remove();
212
+ rule_condition.remove();
213
+ }
214
+
215
+ field_wrap.find('.astra-target-rule-condition').each(function(i) {
216
+ var condition = jQuery( this ),
217
+ old_rule_id = condition.attr('data-rule'),
218
+ select_location = condition.find('.target_rule-condition'),
219
+ select_specific = condition.find('.target_rule-specific-page'),
220
+ location_name = select_location.attr( 'name' );
221
+
222
+ condition.attr( 'data-rule', i );
223
+
224
+ select_location.attr( 'name', location_name.replace('['+old_rule_id+']', '['+i+']') );
225
+
226
+ condition.removeClass('ast-target-rule-'+old_rule_id).addClass('ast-target-rule-'+i);
227
+
228
+ cnt = i;
229
+ });
230
+
231
+ field_wrap.find('.target_rule-add-rule-wrap a').attr( 'data-rule-id', cnt )
232
+
233
+ update_close_button( field_wrap );
234
+ update_target_rule_input( field_wrap );
235
+ });
236
+
237
+ jQuery( '.ast-target-rule-selector-wrapper' ).on( 'click', '.target_rule-add-exclusion-rule a', function(e) {
238
+ e.preventDefault();
239
+ e.stopPropagation();
240
+ update_exclusion_button( true );
241
+ });
242
+
243
+ });
244
+
245
+ }(jQuery, window));
inc/lib/target-rule/user-role.js ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ;(function ( $, window, undefined ) {
2
+
3
+ var user_role_update_close_button = function(wrapper) {
4
+
5
+ type = wrapper.closest('.ast-user-role-wrapper').attr('data-type');
6
+ rules = wrapper.find('.astra-user-role-condition');
7
+ show_close = false;
8
+
9
+ if ( rules.length > 1 ) {
10
+ show_close = true;
11
+ }
12
+
13
+ rules.each(function() {
14
+ if ( show_close ) {
15
+ jQuery(this).find('.user_role-condition-delete').removeClass('ast-hidden');
16
+ }else{
17
+ jQuery(this).find('.user_role-condition-delete').addClass('ast-hidden');
18
+ }
19
+ });
20
+ };
21
+
22
+ $(document).ready(function($) {
23
+
24
+ jQuery('.ast-user-role-selector-wrapper').each(function() {
25
+ user_role_update_close_button( jQuery(this) );
26
+ })
27
+
28
+ jQuery( '.ast-user-role-selector-wrapper' ).on( 'click', '.user_role-add-rule-wrap a', function(e) {
29
+ e.preventDefault();
30
+ e.stopPropagation();
31
+ var $this = jQuery( this ),
32
+ id = $this.attr( 'data-rule-id' ),
33
+ new_id = parseInt(id) + 1,
34
+ rule_wrap = $this.closest('.ast-user-role-selector-wrapper').find('.user_role-builder-wrap'),
35
+ template = wp.template( 'astra-user-role-condition' ),
36
+ field_wrap = $this.closest('.ast-user-role-wrapper');
37
+
38
+ rule_wrap.append( template( { id : new_id } ) );
39
+
40
+ $this.attr( 'data-rule-id', new_id );
41
+
42
+ user_role_update_close_button( field_wrap );
43
+ });
44
+
45
+ jQuery( '.ast-user-role-selector-wrapper' ).on( 'click', '.user_role-condition-delete', function(e) {
46
+ var $this = jQuery( this ),
47
+ rule_condition = $this.closest('.astra-user-role-condition'),
48
+ field_wrap = $this.closest('.ast-user-role-wrapper');
49
+ cnt = 0,
50
+ data_type = field_wrap.attr( 'data-type' ),
51
+ optionVal = $this.siblings('.user_role-condition-wrap').children('.user_role-condition').val();
52
+
53
+ rule_condition.remove();
54
+
55
+ field_wrap.find('.astra-user-role-condition').each(function(i) {
56
+ var condition = jQuery( this ),
57
+ old_rule_id = condition.attr('data-rule'),
58
+ select_location = condition.find('.user_role-condition'),
59
+ location_name = select_location.attr( 'name' );
60
+
61
+ condition.attr( 'data-rule', i );
62
+
63
+ select_location.attr( 'name', location_name.replace('['+old_rule_id+']', '['+i+']') );
64
+
65
+ condition.removeClass('ast-user-role-'+old_rule_id).addClass('ast-user-role-'+i);
66
+
67
+ cnt = i;
68
+ });
69
+
70
+ field_wrap.find('.user_role-add-rule-wrap a').attr( 'data-rule-id', cnt )
71
+
72
+ user_role_update_close_button( field_wrap );
73
+ });
74
+ });
75
+ }(jQuery, window));
inc/widgets-manager/class-widgets-loader.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Widgets loader for Header Footer Elementor.
4
+ *
5
+ * @package HFE
6
+ * @author HFE
7
+ * @copyright Copyright (c) 2018, HFE
8
+ * @link http://brainstormforce.com/
9
+ * @since HFE 1.2.0
10
+ */
11
+
12
+ namespace HFE\WidgetsManager;
13
+
14
+ use Elementor\Plugin;
15
+
16
+ defined( 'ABSPATH' ) or exit;
17
+
18
+ /**
19
+ * Set up Widgets Loader class
20
+ */
21
+ class Widgets_Loader {
22
+
23
+ /**
24
+ * Instance of Widgets_Loader.
25
+ *
26
+ * @since 1.2.0
27
+ * @var null
28
+ */
29
+ private static $_instance = null;
30
+
31
+ /**
32
+ * Get instance of Widgets_Loader
33
+ *
34
+ * @since 1.2.0
35
+ * @return Widgets_Loader
36
+ */
37
+ public static function instance() {
38
+ if ( ! isset( self::$_instance ) ) {
39
+ self::$_instance = new self();
40
+ }
41
+
42
+ return self::$_instance;
43
+ }
44
+
45
+ /**
46
+ * Setup actions and filters.
47
+ *
48
+ * @since 1.2.0
49
+ */
50
+ private function __construct() {
51
+ // Register widgets.
52
+ add_action( 'elementor/widgets/widgets_registered', [ $this, 'register_widgets' ] );
53
+
54
+ // Add svg support.
55
+ add_filter( 'upload_mimes', [ $this, 'hfe_svg_mime_types' ] );
56
+ }
57
+
58
+
59
+ /**
60
+ * Include Widgets files
61
+ *
62
+ * Load widgets files
63
+ *
64
+ * @since 1.2.0
65
+ * @access public
66
+ */
67
+ public function include_widgets_files() {
68
+ require_once HFE_DIR . '/inc/widgets-manager/widgets/class-retina.php';
69
+ require_once HFE_DIR . '/inc/widgets-manager/widgets/class-copyright.php';
70
+ require_once HFE_DIR . '/inc/widgets-manager/widgets/class-copyright-shortcode.php';
71
+ }
72
+
73
+ /**
74
+ * Provide the SVG support for Retina Logo widget.
75
+ *
76
+ * @param array $mimes which return mime type.
77
+ *
78
+ * @since 1.2.0
79
+ * @return $mimes.
80
+ */
81
+ public function hfe_svg_mime_types( $mimes ) {
82
+
83
+ // New allowed mime types.
84
+ $mimes['svg'] = 'image/svg+xml';
85
+ return $mimes;
86
+ }
87
+
88
+ /**
89
+ * Register Widgets
90
+ *
91
+ * Register new Elementor widgets.
92
+ *
93
+ * @since 1.2.0
94
+ * @access public
95
+ */
96
+ public function register_widgets() {
97
+
98
+ // Its is now safe to include Widgets files.
99
+ $this->include_widgets_files();
100
+ // Register Widgets.
101
+ Plugin::instance()->widgets_manager->register_widget_type( new Widgets\Retina() );
102
+ Plugin::instance()->widgets_manager->register_widget_type( new Widgets\Copyright() );
103
+ }
104
+
105
+ }
106
+
107
+ /**
108
+ * Initiate the class.
109
+ */
110
+ Widgets_Loader::instance();
inc/widgets-manager/widgets/class-copyright-shortcode.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Calling copyright shortcode.
4
+ *
5
+ * @package Copyright
6
+ * @author Brainstorm Force
7
+ */
8
+
9
+ namespace HFE\WidgetsManager\Widgets;
10
+
11
+ /**
12
+ * Exit if accessed directly.
13
+ */
14
+ if ( ! defined( 'ABSPATH' ) ) {
15
+ exit();
16
+ }
17
+
18
+ /**
19
+ * Helper class for the Copyright.
20
+ *
21
+ * @since 1.2.0
22
+ */
23
+ class Copyright_Shortcode {
24
+
25
+ /**
26
+ * Constructor.
27
+ */
28
+ public function __construct() {
29
+
30
+ add_shortcode( 'hfe_current_year', [ $this, 'display_current_year' ] );
31
+ add_shortcode( 'hfe_site_title', [ $this, 'display_site_title' ] );
32
+ }
33
+
34
+ /**
35
+ * Get the hfe_current_year Details.
36
+ *
37
+ * @return array $hfe_current_year Get Current Year Details.
38
+ */
39
+ public function display_current_year() {
40
+
41
+ $hfe_current_year = gmdate( 'Y' );
42
+ $hfe_current_year = do_shortcode( shortcode_unautop( $hfe_current_year ) );
43
+ if ( ! empty( $hfe_current_year ) ) {
44
+ return $hfe_current_year;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Get site title of Site.
50
+ *
51
+ * @return string.
52
+ */
53
+ public function display_site_title() {
54
+
55
+ $hfe_site_title = get_bloginfo( 'name' );
56
+
57
+ if ( ! empty( $hfe_site_title ) ) {
58
+ return $hfe_site_title;
59
+ }
60
+ }
61
+
62
+ }
63
+
64
+ new Copyright_Shortcode();
inc/widgets-manager/widgets/class-copyright.php ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Elementor Classes.
4
+ *
5
+ * @package Header Footer Elementor
6
+ */
7
+
8
+ namespace HFE\WidgetsManager\Widgets;
9
+
10
+ use Elementor\Controls_Manager;
11
+ use Elementor\Utils;
12
+ use Elementor\Group_Control_Typography;
13
+ use Elementor\Scheme_Typography;
14
+ use Elementor\Scheme_Color;
15
+ use Elementor\Widget_Base;
16
+
17
+
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit; // Exit if accessed directly.
20
+ }
21
+
22
+ /**
23
+ * Elementor Copyright
24
+ *
25
+ * Elementor widget for copyright.
26
+ *
27
+ * @since 1.2.0
28
+ */
29
+ class Copyright extends Widget_Base {
30
+
31
+ /**
32
+ * Retrieve the widget name.
33
+ *
34
+ * @since 1.2.0
35
+ *
36
+ * @access public
37
+ *
38
+ * @return string Widget name.
39
+ */
40
+ public function get_name() {
41
+ return 'copyright';
42
+ }
43
+ /**
44
+ * Retrieve the widget title.
45
+ *
46
+ * @since 1.2.0
47
+ *
48
+ * @access public
49
+ *
50
+ * @return string Widget title.
51
+ */
52
+ public function get_title() {
53
+ return __( 'Copyright', 'header-footer-elementor' );
54
+ }
55
+ /**
56
+ * Retrieve the widget icon.
57
+ *
58
+ * @since 1.2.0
59
+ *
60
+ * @access public
61
+ *
62
+ * @return string Widget icon.
63
+ */
64
+ public function get_icon() {
65
+ return 'fa fa-copyright';
66
+ }
67
+ /**
68
+ * Retrieve the list of categories the widget belongs to.
69
+ *
70
+ * Used to determine where to display the widget in the editor.
71
+ *
72
+ * Note that currently Elementor supports only one category.
73
+ * When multiple categories passed, Elementor uses the first one.
74
+ *
75
+ * @since 1.2.0
76
+ *
77
+ * @access public
78
+ *
79
+ * @return array Widget categories.
80
+ */
81
+ public function get_categories() {
82
+ return [ 'HFE' ];
83
+ }
84
+ /**
85
+ * Register Copyright controls.
86
+ *
87
+ * @since 1.2.0
88
+ * @access protected
89
+ */
90
+ protected function _register_controls() { //phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
91
+ $this->register_content_copy_right_controls();
92
+ }
93
+ /**
94
+ * Register Copyright General Controls.
95
+ *
96
+ * @since 1.2.0
97
+ * @access protected
98
+ */
99
+ protected function register_content_copy_right_controls() {
100
+ $this->start_controls_section(
101
+ 'section_title',
102
+ [
103
+ 'label' => __( 'Copyright', 'header-footer-elementor' ),
104
+ ]
105
+ );
106
+
107
+ $this->add_control(
108
+ 'shortcode',
109
+ [
110
+ 'label' => __( 'Copyright Text', 'header-footer-elementor' ),
111
+ 'type' => Controls_Manager::TEXTAREA,
112
+ 'dynamic' => [
113
+ 'active' => true,
114
+ ],
115
+ 'default' => __( 'Copyright © [hfe_current_year] [hfe_site_title] | Powered by [hfe_site_title]', 'header-footer-elementor' ),
116
+ ]
117
+ );
118
+
119
+ $this->add_control(
120
+ 'link',
121
+ [
122
+ 'label' => __( 'Link', 'header-footer-elementor' ),
123
+ 'type' => Controls_Manager::URL,
124
+ 'placeholder' => __( 'https://your-link.com', 'header-footer-elementor' ),
125
+ ]
126
+ );
127
+
128
+ $this->add_responsive_control(
129
+ 'align',
130
+ [
131
+ 'label' => __( 'Alignment', 'header-footer-elementor' ),
132
+ 'type' => Controls_Manager::CHOOSE,
133
+ 'options' => [
134
+ 'left' => [
135
+ 'title' => __( 'Left', 'header-footer-elementor' ),
136
+ 'icon' => 'fa fa-align-left',
137
+ ],
138
+ 'center' => [
139
+ 'title' => __( 'Center', 'header-footer-elementor' ),
140
+ 'icon' => 'fa fa-align-center',
141
+ ],
142
+ 'right' => [
143
+ 'title' => __( 'Right', 'header-footer-elementor' ),
144
+ 'icon' => 'fa fa-align-right',
145
+ ],
146
+ ],
147
+ 'selectors' => [
148
+ '{{WRAPPER}} .hfe-copyright-wrapper' => 'text-align: {{VALUE}};',
149
+ ],
150
+ ]
151
+ );
152
+
153
+ $this->add_control(
154
+ 'title_color',
155
+ [
156
+ 'label' => __( 'Text Color', 'header-footer-elementor' ),
157
+ 'type' => Controls_Manager::COLOR,
158
+ 'scheme' => [
159
+ 'type' => Scheme_Color::get_type(),
160
+ 'value' => Scheme_Color::COLOR_3,
161
+ ],
162
+ 'selectors' => [
163
+ // Stronger selector to avoid section style from overwriting.
164
+ '{{WRAPPER}} .hfe-copyright-wrapper a, {{WRAPPER}} .hfe-copyright-wrapper' => 'color: {{VALUE}};',
165
+ ],
166
+ ]
167
+ );
168
+
169
+ $this->add_group_control(
170
+ Group_Control_Typography::get_type(),
171
+ [
172
+ 'name' => 'caption_typography',
173
+ 'selector' => '{{WRAPPER}} .hfe-copyright-wrapper, {{WRAPPER}} .hfe-copyright-wrapper a',
174
+ 'scheme' => Scheme_Typography::TYPOGRAPHY_3,
175
+ ]
176
+ );
177
+
178
+ }
179
+
180
+ /**
181
+ * Render Copyright output on the frontend.
182
+ *
183
+ * Written in PHP and used to generate the final HTML.
184
+ *
185
+ * @since 1.2.0
186
+ * @access protected
187
+ */
188
+ protected function render() {
189
+ $settings = $this->get_settings_for_display();
190
+ $link = isset( $settings['link']['url'] ) ? $settings['link']['url'] : '';
191
+
192
+ $copy_right_shortcode = do_shortcode( shortcode_unautop( $settings['shortcode'] ) ); ?>
193
+ <div class="hfe-copyright-wrapper">
194
+ <?php if ( ! empty( $link ) ) { ?>
195
+ <a href="<?php echo esc_url( $link ); ?>">
196
+ <span><?php echo esc_attr( $copy_right_shortcode ); ?></span>
197
+ </a>
198
+ <?php } else { ?>
199
+ <span><?php echo esc_attr( $copy_right_shortcode ); ?></span>
200
+ <?php } ?>
201
+ </div>
202
+ <?php
203
+ }
204
+
205
+ /**
206
+ * Render shortcode widget as plain content.
207
+ *
208
+ * Override the default behavior by printing the shortcode instead of rendering it.
209
+ *
210
+ * @since 1.2.0
211
+ * @access public
212
+ */
213
+ public function render_plain_content() {
214
+ // In plain mode, render without shortcode.
215
+ echo esc_attr( $this->get_settings( 'shortcode' ) );
216
+ }
217
+
218
+ /**
219
+ * Render shortcode widget output in the editor.
220
+ *
221
+ * Written as a Backbone JavaScript template and used to generate the live preview.
222
+ *
223
+ * @since 1.2.0
224
+ * @access protected
225
+ */
226
+ protected function _content_template() {} //phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
227
+ }
inc/widgets-manager/widgets/class-retina.php ADDED
@@ -0,0 +1,842 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Elementor Classes.
4
+ *
5
+ * @package header-footer-elementor
6
+ */
7
+
8
+ namespace HFE\WidgetsManager\Widgets;
9
+
10
+ use Elementor\Controls_Manager;
11
+ use Elementor\Control_Media;
12
+ use Elementor\Utils;
13
+ use Elementor\Group_Control_Border;
14
+ use Elementor\Group_Control_Typography;
15
+ use Elementor\Group_Control_Box_Shadow;
16
+ use Elementor\Scheme_Typography;
17
+ use Elementor\Scheme_Color;
18
+ use Elementor\Group_Control_Image_Size;
19
+ use Elementor\Repeater;
20
+ use Elementor\Group_Control_Css_Filter;
21
+ use Elementor\Group_Control_Text_Shadow;
22
+ use Elementor\Plugin;
23
+ use Elementor\Widget_Base;
24
+
25
+ if ( ! defined( 'ABSPATH' ) ) {
26
+ exit; // Exit if accessed directly.
27
+ }
28
+
29
+ /**
30
+ * HFE Retina widget
31
+ *
32
+ * HFE widget for Retina Image.
33
+ *
34
+ * @since 1.2.0
35
+ */
36
+ class Retina extends Widget_Base {
37
+
38
+ /**
39
+ * Retrieve the widget name.
40
+ *
41
+ * @since 1.2.0
42
+ *
43
+ * @access public
44
+ *
45
+ * @return string Widget name.
46
+ */
47
+ public function get_name() {
48
+ return 'retina';
49
+ }
50
+
51
+ /**
52
+ * Retrieve the widget title.
53
+ *
54
+ * @since 1.2.0
55
+ *
56
+ * @access public
57
+ *
58
+ * @return string Widget title.
59
+ */
60
+ public function get_title() {
61
+ return __( 'Retina Image', 'header-footer-elementor' );
62
+ }
63
+
64
+ /**
65
+ * Retrieve the widget icon.
66
+ *
67
+ * @since 1.2.0
68
+ *
69
+ * @access public
70
+ *
71
+ * @return string Widget icon.
72
+ */
73
+ public function get_icon() {
74
+ return 'fas fa-search';
75
+ }
76
+
77
+ /**
78
+ * Retrieve the list of categories the widget belongs to.
79
+ *
80
+ * Used to determine where to display the widget in the editor.
81
+ *
82
+ * Note that currently Elementor supports only one category.
83
+ * When multiple categories passed, Elementor uses the first one.
84
+ *
85
+ * @since 1.2.0
86
+ *
87
+ * @access public
88
+ *
89
+ * @return array Widget categories.
90
+ */
91
+ public function get_categories() {
92
+ return [ 'HFE' ];
93
+ }
94
+
95
+ /**
96
+ * Register Retina Logo controls.
97
+ *
98
+ * @since 1.2.0
99
+ * @access protected
100
+ */
101
+ protected function _register_controls() {
102
+ $this->register_content_retina_image_controls();
103
+ $this->register_retina_image_styling_controls();
104
+ $this->register_retina_caption_styling_controls();
105
+ $this->register_helpful_information();
106
+ }
107
+
108
+ /**
109
+ * Register Retina Logo General Controls.
110
+ *
111
+ * @since 1.2.0
112
+ * @access protected
113
+ */
114
+ protected function register_content_retina_image_controls() {
115
+ $this->start_controls_section(
116
+ 'section_retina_image',
117
+ [
118
+ 'label' => __( 'Retina Image', 'header-footer-elementor' ),
119
+ ]
120
+ );
121
+ $this->add_control(
122
+ 'retina_image',
123
+ [
124
+ 'label' => __( 'Choose Default Image', 'header-footer-elementor' ),
125
+ 'type' => Controls_Manager::MEDIA,
126
+ 'dynamic' => [
127
+ 'active' => true,
128
+ ],
129
+ 'default' => [
130
+ 'url' => Utils::get_placeholder_image_src(),
131
+ ],
132
+ ]
133
+ );
134
+ $this->add_control(
135
+ 'real_retina',
136
+ [
137
+ 'label' => __( 'Choose Retina Image', 'header-footer-elementor' ),
138
+ 'type' => Controls_Manager::MEDIA,
139
+ 'dynamic' => [
140
+ 'active' => true,
141
+ ],
142
+ 'default' => [
143
+ 'url' => Utils::get_placeholder_image_src(),
144
+ ],
145
+ ]
146
+ );
147
+ $this->add_group_control(
148
+ Group_Control_Image_Size::get_type(),
149
+ [
150
+ 'name' => 'retina_image',
151
+ 'label' => __( 'Image Size', 'header-footer-elementor' ),
152
+ 'default' => 'medium',
153
+ ]
154
+ );
155
+ $this->add_responsive_control(
156
+ 'align',
157
+ [
158
+ 'label' => __( 'Alignment', 'header-footer-elementor' ),
159
+ 'type' => Controls_Manager::CHOOSE,
160
+ 'options' => [
161
+ 'left' => [
162
+ 'title' => __( 'Left', 'header-footer-elementor' ),
163
+ 'icon' => 'fa fa-align-left',
164
+ ],
165
+ 'center' => [
166
+ 'title' => __( 'Center', 'header-footer-elementor' ),
167
+ 'icon' => 'fa fa-align-center',
168
+ ],
169
+ 'right' => [
170
+ 'title' => __( 'Right', 'header-footer-elementor' ),
171
+ 'icon' => 'fa fa-align-right',
172
+ ],
173
+ ],
174
+ 'default' => 'center',
175
+ 'selectors' => [
176
+ '{{WRAPPER}} .hfe-retina-image-container, {{WRAPPER}} .hfe-caption-width' => 'text-align: {{VALUE}};',
177
+ ],
178
+ ]
179
+ );
180
+
181
+ $this->add_control(
182
+ 'caption_source',
183
+ [
184
+ 'label' => __( 'Caption', 'header-footer-elementor' ),
185
+ 'type' => Controls_Manager::SELECT,
186
+ 'options' => [
187
+ 'none' => __( 'None', 'header-footer-elementor' ),
188
+ 'custom' => __( 'Custom Caption', 'header-footer-elementor' ),
189
+ ],
190
+ 'default' => 'none',
191
+ ]
192
+ );
193
+
194
+ $this->add_control(
195
+ 'caption',
196
+ [
197
+ 'label' => __( 'Custom Caption', 'header-footer-elementor' ),
198
+ 'type' => Controls_Manager::TEXT,
199
+ 'default' => '',
200
+ 'placeholder' => __( 'Enter your image caption', 'header-footer-elementor' ),
201
+ 'condition' => [
202
+ 'caption_source' => 'custom',
203
+ ],
204
+ 'dynamic' => [
205
+ 'active' => true,
206
+ ],
207
+ 'label_block' => true,
208
+ ]
209
+ );
210
+
211
+ $this->add_control(
212
+ 'link_to',
213
+ [
214
+ 'label' => __( 'Link', 'header-footer-elementor' ),
215
+ 'type' => Controls_Manager::SELECT,
216
+ 'default' => 'none',
217
+ 'options' => [
218
+ 'none' => __( 'None', 'header-footer-elementor' ),
219
+ 'custom' => __( 'Custom URL', 'header-footer-elementor' ),
220
+ ],
221
+ ]
222
+ );
223
+
224
+ $this->add_control(
225
+ 'link',
226
+ [
227
+ 'label' => __( 'Link', 'header-footer-elementor' ),
228
+ 'type' => Controls_Manager::URL,
229
+ 'dynamic' => [
230
+ 'active' => true,
231
+ ],
232
+ 'placeholder' => __( 'https://your-link.com', 'header-footer-elementor' ),
233
+ 'condition' => [
234
+ 'link_to' => 'custom',
235
+ ],
236
+ 'show_label' => false,
237
+ ]
238
+ );
239
+ $this->end_controls_section();
240
+ }
241
+ /**
242
+ * Register Retina Image Style Controls.
243
+ *
244
+ * @since 1.2.0
245
+ * @access protected
246
+ */
247
+ protected function register_retina_image_styling_controls() {
248
+ $this->start_controls_section(
249
+ 'section_style_retina_image',
250
+ [
251
+ 'label' => __( 'Retina Image', 'header-footer-elementor' ),
252
+ 'tab' => Controls_Manager::TAB_STYLE,
253
+ ]
254
+ );
255
+
256
+ $this->add_responsive_control(
257
+ 'width',
258
+ [
259
+ 'label' => __( 'Width', 'header-footer-elementor' ),
260
+ 'type' => Controls_Manager::SLIDER,
261
+ 'default' => [
262
+ 'unit' => '%',
263
+ ],
264
+ 'tablet_default' => [
265
+ 'unit' => '%',
266
+ ],
267
+ 'mobile_default' => [
268
+ 'unit' => '%',
269
+ ],
270
+ 'size_units' => [ '%', 'px', 'vw' ],
271
+ 'range' => [
272
+ '%' => [
273
+ 'min' => 1,
274
+ 'max' => 100,
275
+ ],
276
+ 'px' => [
277
+ 'min' => 1,
278
+ 'max' => 1000,
279
+ ],
280
+ 'vw' => [
281
+ 'min' => 1,
282
+ 'max' => 100,
283
+ ],
284
+ ],
285
+ 'selectors' => [
286
+ '{{WRAPPER}} .hfe-retina-image img' => 'width: {{SIZE}}{{UNIT}};',
287
+ '{{WRAPPER}} .hfe-retina-image .wp-caption .widget-image-caption' => 'width: {{SIZE}}{{UNIT}}; display: inline-block;',
288
+ ],
289
+ ]
290
+ );
291
+
292
+ $this->add_responsive_control(
293
+ 'space',
294
+ [
295
+ 'label' => __( 'Max Width', 'header-footer-elementor' ) . ' (%)',
296
+ 'type' => Controls_Manager::SLIDER,
297
+ 'default' => [
298
+ 'unit' => '%',
299
+ ],
300
+ 'tablet_default' => [
301
+ 'unit' => '%',
302
+ ],
303
+ 'mobile_default' => [
304
+ 'unit' => '%',
305
+ ],
306
+ 'size_units' => [ '%' ],
307
+ 'range' => [
308
+ '%' => [
309
+ 'min' => 1,
310
+ 'max' => 100,
311
+ ],
312
+ ],
313
+ 'selectors' => [
314
+ '{{WRAPPER}} .hfe-retina-image img' => 'max-width: {{SIZE}}{{UNIT}};',
315
+ '{{WRAPPER}} .wp-caption-text' => 'max-width: {{SIZE}}{{UNIT}}; display: inline-block; width: 100%;',
316
+ ],
317
+ ]
318
+ );
319
+
320
+ $this->add_control(
321
+ 'separator_panel_style',
322
+ [
323
+ 'type' => Controls_Manager::DIVIDER,
324
+ 'style' => 'thick',
325
+ ]
326
+ );
327
+
328
+ $this->add_control(
329
+ 'retina_image_border',
330
+ [
331
+ 'label' => __( 'Border Style', 'header-footer-elementor' ),
332
+ 'type' => Controls_Manager::SELECT,
333
+ 'default' => 'none',
334
+ 'label_block' => false,
335
+ 'options' => [
336
+ 'none' => __( 'None', 'header-footer-elementor' ),
337
+ 'solid' => __( 'Solid', 'header-footer-elementor' ),
338
+ 'double' => __( 'Double', 'header-footer-elementor' ),
339
+ 'dotted' => __( 'Dotted', 'header-footer-elementor' ),
340
+ 'dashed' => __( 'Dashed', 'header-footer-elementor' ),
341
+ ],
342
+ 'selectors' => [
343
+ '{{WRAPPER}} .hfe-retina-image-container .hfe-retina-img' => 'border-style: {{VALUE}};',
344
+ ],
345
+ ]
346
+ );
347
+ $this->add_control(
348
+ 'retina_image_border_size',
349
+ [
350
+ 'label' => __( 'Border Width', 'header-footer-elementor' ),
351
+ 'type' => Controls_Manager::DIMENSIONS,
352
+ 'size_units' => [ 'px' ],
353
+ 'default' => [
354
+ 'top' => '1',
355
+ 'bottom' => '1',
356
+ 'left' => '1',
357
+ 'right' => '1',
358
+ 'unit' => 'px',
359
+ ],
360
+ 'condition' => [
361
+ 'retina_image_border!' => 'none',
362
+ ],
363
+ 'selectors' => [
364
+ '{{WRAPPER}} .hfe-retina-image-container .hfe-retina-img' => 'border-width: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
365
+ ],
366
+ ]
367
+ );
368
+
369
+ $this->add_control(
370
+ 'retina_image_border_color',
371
+ [
372
+ 'label' => __( 'Border Color', 'header-footer-elementor' ),
373
+ 'type' => Controls_Manager::COLOR,
374
+ 'scheme' => [
375
+ 'type' => Scheme_Color::get_type(),
376
+ 'value' => Scheme_Color::COLOR_1,
377
+ ],
378
+ 'condition' => [
379
+ 'retina_image_border!' => 'none',
380
+ ],
381
+ 'default' => '',
382
+ 'selectors' => [
383
+ '{{WRAPPER}} .hfe-retina-image-container .hfe-retina-img' => 'border-color: {{VALUE}};',
384
+ ],
385
+ ]
386
+ );
387
+
388
+ $this->add_responsive_control(
389
+ 'image_border_radius',
390
+ [
391
+ 'label' => __( 'Border Radius', 'header-footer-elementor' ),
392
+ 'type' => Controls_Manager::DIMENSIONS,
393
+ 'size_units' => [ 'px', '%' ],
394
+ 'selectors' => [
395
+ '{{WRAPPER}} .hfe-retina-image img' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
396
+ ],
397
+ ]
398
+ );
399
+
400
+ $this->add_group_control(
401
+ Group_Control_Box_Shadow::get_type(),
402
+ [
403
+ 'name' => 'image_box_shadow',
404
+ 'exclude' => [
405
+ 'box_shadow_position',
406
+ ],
407
+ 'selector' => '{{WRAPPER}} .hfe-retina-image img',
408
+ ]
409
+ );
410
+
411
+ $this->start_controls_tabs( 'image_effects' );
412
+
413
+ $this->start_controls_tab(
414
+ 'normal',
415
+ [
416
+ 'label' => __( 'Normal', 'header-footer-elementor' ),
417
+ ]
418
+ );
419
+
420
+ $this->add_control(
421
+ 'opacity',
422
+ [
423
+ 'label' => __( 'Opacity', 'header-footer-elementor' ),
424
+ 'type' => Controls_Manager::SLIDER,
425
+ 'range' => [
426
+ 'px' => [
427
+ 'max' => 1,
428
+ 'min' => 0.10,
429
+ 'step' => 0.01,
430
+ ],
431
+ ],
432
+ 'selectors' => [
433
+ '{{WRAPPER}} .hfe-retina-image img' => 'opacity: {{SIZE}};',
434
+ ],
435
+ ]
436
+ );
437
+
438
+ $this->add_group_control(
439
+ Group_Control_Css_Filter::get_type(),
440
+ [
441
+ 'name' => 'css_filters',
442
+ 'selector' => '{{WRAPPER}} .hfe-retina-image img',
443
+ ]
444
+ );
445
+
446
+ $this->end_controls_tab();
447
+
448
+ $this->start_controls_tab(
449
+ 'hover',
450
+ [
451
+ 'label' => __( 'Hover', 'header-footer-elementor' ),
452
+ ]
453
+ );
454
+ $this->add_control(
455
+ 'opacity_hover',
456
+ [
457
+ 'label' => __( 'Opacity', 'header-footer-elementor' ),
458
+ 'type' => Controls_Manager::SLIDER,
459
+ 'range' => [
460
+ 'px' => [
461
+ 'max' => 1,
462
+ 'min' => 0.10,
463
+ 'step' => 0.01,
464
+ ],
465
+ ],
466
+ 'selectors' => [
467
+ '{{WRAPPER}} .hfe-retina-image:hover img' => 'opacity: {{SIZE}};',
468
+ ],
469
+ ]
470
+ );
471
+
472
+ $this->add_group_control(
473
+ Group_Control_Css_Filter::get_type(),
474
+ [
475
+ 'name' => 'css_filters_hover',
476
+ 'selector' => '{{WRAPPER}} .hfe-retina-image:hover img',
477
+ ]
478
+ );
479
+
480
+ $this->add_control(
481
+ 'hover_animation',
482
+ [
483
+ 'label' => __( 'Hover Animation', 'header-footer-elementor' ),
484
+ 'type' => Controls_Manager::HOVER_ANIMATION,
485
+ ]
486
+ );
487
+ $this->add_control(
488
+ 'background_hover_transition',
489
+ [
490
+ 'label' => __( 'Transition Duration', 'header-footer-elementor' ),
491
+ 'type' => Controls_Manager::SLIDER,
492
+ 'range' => [
493
+ 'px' => [
494
+ 'max' => 3,
495
+ 'step' => 0.1,
496
+ ],
497
+ ],
498
+ 'selectors' => [
499
+ '{{WRAPPER}} .hfe-retina-image img' => 'transition-duration: {{SIZE}}s',
500
+ ],
501
+ ]
502
+ );
503
+
504
+ $this->end_controls_tab();
505
+
506
+ $this->end_controls_tabs();
507
+
508
+ $this->end_controls_section();
509
+ }
510
+ /**
511
+ * Register Caption style Controls.
512
+ *
513
+ * @since 1.2.0
514
+ * @access protected
515
+ */
516
+ protected function register_retina_caption_styling_controls() {
517
+ $this->start_controls_section(
518
+ 'section_style_caption',
519
+ [
520
+ 'label' => __( 'Caption', 'header-footer-elementor' ),
521
+ 'tab' => Controls_Manager::TAB_STYLE,
522
+ 'condition' => [
523
+ 'caption_source!' => 'none',
524
+ ],
525
+ ]
526
+ );
527
+
528
+ $this->add_control(
529
+ 'text_color',
530
+ [
531
+ 'label' => __( 'Text Color', 'header-footer-elementor' ),
532
+ 'type' => Controls_Manager::COLOR,
533
+ 'default' => '',
534
+ 'selectors' => [
535
+ '{{WRAPPER}} .widget-image-caption' => 'color: {{VALUE}};',
536
+ ],
537
+ 'scheme' => [
538
+ 'type' => Scheme_Color::get_type(),
539
+ 'value' => Scheme_Color::COLOR_3,
540
+ ],
541
+ ]
542
+ );
543
+
544
+ $this->add_control(
545
+ 'caption_background_color',
546
+ [
547
+ 'label' => __( 'Background Color', 'header-footer-elementor' ),
548
+ 'type' => Controls_Manager::COLOR,
549
+ 'selectors' => [
550
+ '{{WRAPPER}} .widget-image-caption' => 'background-color: {{VALUE}};',
551
+ ],
552
+ ]
553
+ );
554
+
555
+ $this->add_group_control(
556
+ Group_Control_Typography::get_type(),
557
+ [
558
+ 'name' => 'caption_typography',
559
+ 'selector' => '{{WRAPPER}} .widget-image-caption',
560
+ 'scheme' => Scheme_Typography::TYPOGRAPHY_3,
561
+ ]
562
+ );
563
+
564
+ $this->add_group_control(
565
+ Group_Control_Text_Shadow::get_type(),
566
+ [
567
+ 'name' => 'caption_text_shadow',
568
+ 'selector' => '{{WRAPPER}} .widget-image-caption',
569
+ ]
570
+ );
571
+
572
+ $this->add_responsive_control(
573
+ 'caption_padding',
574
+ [
575
+ 'label' => __( 'Padding', 'header-footer-elementor' ),
576
+ 'type' => Controls_Manager::DIMENSIONS,
577
+ 'size_units' => [ 'px', 'em', '%' ],
578
+ 'selectors' => [
579
+ '{{WRAPPER}} .widget-image-caption' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
580
+ ],
581
+ ]
582
+ );
583
+ $this->add_responsive_control(
584
+ 'caption_space',
585
+ [
586
+ 'label' => __( 'Caption Top Spacing', 'header-footer-elementor' ),
587
+ 'type' => Controls_Manager::SLIDER,
588
+ 'range' => [
589
+ 'px' => [
590
+ 'min' => 0,
591
+ 'max' => 100,
592
+ ],
593
+ ],
594
+ 'default' => [
595
+ 'size' => 0,
596
+ 'unit' => 'px',
597
+ ],
598
+ 'selectors' => [
599
+ '{{WRAPPER}} .widget-image-caption' => 'margin-top: {{SIZE}}{{UNIT}}; margin-bottom: 0px;',
600
+ ],
601
+ ]
602
+ );
603
+
604
+ $this->end_controls_section();
605
+ }
606
+
607
+ /**
608
+ * Helpful Information.
609
+ *
610
+ * @since 1.2.0
611
+ * @access protected
612
+ */
613
+ protected function register_helpful_information() {
614
+ $this->start_controls_section(
615
+ 'section_helpful_info',
616
+ [
617
+ 'label' => __( 'Helpful Information', 'header-footer-elementor' ),
618
+ ]
619
+ );
620
+
621
+ $this->add_control(
622
+ 'help_doc_1',
623
+ [
624
+ 'type' => Controls_Manager::RAW_HTML,
625
+ /* translators: %1$s doc link */
626
+ 'raw' => sprintf( __( '%1$s Getting started article » %2$s', 'header-footer-elementor' ), '<a href="https://uaelementor.com/docs/introducing-retina-image-widget/" target="_blank" rel="noopener">', '</a>' ),
627
+ 'content_classes' => 'hfe-editor-doc',
628
+ ]
629
+ );
630
+
631
+ $this->end_controls_section();
632
+ }
633
+
634
+ /**
635
+ * Check if the current widget has caption
636
+ *
637
+ * @access private
638
+ * @since 1.2.0
639
+ *
640
+ * @param array $settings returns settings.
641
+ *
642
+ * @return boolean
643
+ */
644
+ private function has_caption( $settings ) {
645
+ return ( ! empty( $settings['caption_source'] ) && 'none' !== $settings['caption_source'] );
646
+ }
647
+
648
+ /**
649
+ * Get the caption for current widget.
650
+ *
651
+ * @access private
652
+ * @since 1.2.0
653
+ * @param array $settings returns the caption.
654
+ *
655
+ * @return string
656
+ */
657
+ private function get_caption( $settings ) {
658
+ $caption = '';
659
+ if ( 'custom' === $settings['caption_source'] ) {
660
+ $caption = ! empty( $settings['caption'] ) ? $settings['caption'] : '';
661
+ }
662
+ return $caption;
663
+ }
664
+
665
+ /**
666
+ * Render Retina Image output on the frontend.
667
+ *
668
+ * Written in PHP and used to generate the final HTML.
669
+ *
670
+ * @since 1.2.0
671
+ * @access protected
672
+ */
673
+ protected function render() {
674
+ $settings = $this->get_settings_for_display();
675
+
676
+ if ( empty( $settings['retina_image']['url'] ) ) {
677
+ return;
678
+ }
679
+
680
+ $has_caption = $this->has_caption( $settings );
681
+
682
+ $this->add_render_attribute( 'wrapper', 'class', 'hfe-retina-image' );
683
+ $link = $this->get_link_url( $settings );
684
+
685
+ if ( $link ) {
686
+ $this->add_render_attribute(
687
+ 'link',
688
+ [
689
+ 'href' => $link['url'],
690
+ ]
691
+ );
692
+
693
+ if ( Plugin::$instance->editor->is_edit_mode() ) {
694
+ $this->add_render_attribute(
695
+ 'link',
696
+ [
697
+ 'class' => 'elementor-clickable',
698
+ ]
699
+ );
700
+ }
701
+
702
+ if ( ! empty( $link['is_external'] ) ) {
703
+ $this->add_render_attribute( 'link', 'target', '_blank' );
704
+ }
705
+
706
+ if ( ! empty( $link['nofollow'] ) ) {
707
+ $this->add_render_attribute( 'link', 'rel', 'nofollow' );
708
+ }
709
+ }
710
+
711
+ ?>
712
+ <div <?php echo $this->get_render_attribute_string( 'wrapper' ); ?>>
713
+ <?php if ( $has_caption ) : ?>
714
+ <figure class="wp-caption">
715
+ <?php endif; ?>
716
+ <?php if ( $link ) : ?>
717
+ <a <?php echo $this->get_render_attribute_string( 'link' ); ?>>
718
+ <?php endif; ?>
719
+ <?php
720
+ $size = $settings[ 'retina_image' . '_size' ];
721
+ $demo = '';
722
+
723
+ if ( 'custom' !== $size ) {
724
+ $image_size = $size;
725
+ } else {
726
+ require_once ELEMENTOR_PATH . 'includes/libraries/bfi-thumb/bfi-thumb.php';
727
+
728
+ $image_dimension = $settings[ 'retina_image' . '_custom_dimension' ];
729
+
730
+ $image_size = [
731
+ // Defaults sizes.
732
+ 0 => null, // Width.
733
+ 1 => null, // Height.
734
+
735
+ 'bfi_thumb' => true,
736
+ 'crop' => true,
737
+ ];
738
+
739
+ $has_custom_size = false;
740
+ if ( ! empty( $image_dimension['width'] ) ) {
741
+ $has_custom_size = true;
742
+ $image_size[0] = $image_dimension['width'];
743
+ }
744
+
745
+ if ( ! empty( $image_dimension['height'] ) ) {
746
+ $has_custom_size = true;
747
+ $image_size[1] = $image_dimension['height'];
748
+ }
749
+
750
+ if ( ! $has_custom_size ) {
751
+ $image_size = 'full';
752
+ }
753
+ }
754
+ $retina_image_url = $settings['real_retina']['url'];
755
+
756
+ $image_url = $settings['retina_image']['url'];
757
+
758
+ $image_data = wp_get_attachment_image_src( $settings['retina_image']['id'], $image_size, true );
759
+
760
+ $retina_data = wp_get_attachment_image_src( $settings['real_retina']['id'], $image_size, true );
761
+
762
+ $retina_image_class = 'elementor-animation-';
763
+
764
+ if ( ! empty( $settings['hover_animation'] ) ) {
765
+ $demo = $settings['hover_animation'];
766
+ }
767
+ if ( ! empty( $image_data ) ) {
768
+ $image_url = $image_data[0];
769
+ }
770
+ if ( ! empty( $retina_data ) ) {
771
+ $retina_image_url = $retina_data[0];
772
+ }
773
+ $class_animation = $retina_image_class . $demo;
774
+
775
+ $image_unset = site_url() . '/wp-includes/images/media/default.png';
776
+ $placeholder_img_url = Utils::get_placeholder_image_src();
777
+
778
+ if ( $image_unset === $retina_image_url ) {
779
+ if ( $image_unset !== $image_url ) {
780
+ $retina_image_url = $image_url;
781
+ } else {
782
+ $retina_image_url = $placeholder_img_url;
783
+ }
784
+ }
785
+
786
+ if ( $image_unset === $image_url ) {
787
+ $image_url = $placeholder_img_url;
788
+ }
789
+
790
+ if ( strpos( $_SERVER['HTTP_USER_AGENT'], 'Chrome' ) !== false ) {
791
+ $date = new \DateTime();
792
+ $timestam = $date->getTimestamp();
793
+ $image_url = $image_url . '?' . $timestam;
794
+ $retina_image_url = $retina_image_url . '?' . $timestam;
795
+ }
796
+
797
+ ?>
798
+ <div class="hfe-retina-image-set">
799
+ <div class="hfe-retina-image-container">
800
+ <img class="hfe-retina-img <?php echo $class_animation; ?>" src="<?php echo $image_url; ?>" srcset="<?php echo $image_url . ' 1x' . ',' . $retina_image_url . ' 2x'; ?>"/>
801
+ </div>
802
+ </div>
803
+ <?php if ( $link ) : ?>
804
+ </a>
805
+ <?php endif; ?>
806
+ <?php
807
+ if ( $has_caption ) :
808
+ $caption_text = $this->get_caption( $settings );
809
+ ?>
810
+ <?php if ( ! empty( $caption_text ) ) : ?>
811
+ <div class="hfe-caption-width">
812
+ <figcaption class="widget-image-caption wp-caption-text"><?php echo $caption_text; ?></figcaption>
813
+ </div>
814
+ <?php endif; ?>
815
+ </figure>
816
+ <?php endif; ?>
817
+ </div>
818
+ <?php
819
+ }
820
+
821
+ /**
822
+ * Retrieve Retina image widget link URL.
823
+ *
824
+ * @since 1.2.0
825
+ * @access private
826
+ *
827
+ * @param array $settings returns settings.
828
+ * @return array|string|false An array/string containing the link URL, or false if no link.
829
+ */
830
+ private function get_link_url( $settings ) {
831
+ if ( 'none' === $settings['link_to'] ) {
832
+ return false;
833
+ }
834
+
835
+ if ( 'custom' === $settings['link_to'] ) {
836
+ if ( empty( $settings['link']['url'] ) ) {
837
+ return false;
838
+ }
839
+ return $settings['link'];
840
+ }
841
+ }
842
+ }
inc/widgets-manager/widgets/index.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php
2
+ /**
3
+ * Silence is golden.
languages/header-footer-elementor.pot CHANGED
@@ -1,11 +1,11 @@
1
  # Copyright (C) 2019 Brainstorm Force, Nikhil Chavan
2
- # This file is distributed under the same license as the Header, Footer & Blocks for Elementor package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Header, Footer & Blocks for Elementor 1.1.2\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/header-footer-elementor\n"
8
- "POT-Creation-Date: 2019-01-16 07:15:45+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
@@ -23,121 +23,195 @@ msgstr ""
23
  "X-Poedit-SearchPath-0: .\n"
24
  "X-Poedit-Bookmarks: \n"
25
  "X-Textdomain-Support: yes\n"
26
- "X-Generator: grunt-wp-i18n1.0.2\n"
27
 
28
- #: admin/class-hfe-admin.php:61 admin/class-hfe-admin.php:63
29
  msgid "Header Footers Template"
30
  msgstr ""
31
 
32
- #: admin/class-hfe-admin.php:62 admin/class-hfe-admin.php:64
33
  msgid "Elementor Header Footer"
34
  msgstr ""
35
 
36
- #: admin/class-hfe-admin.php:65
37
  msgid "Add New"
38
  msgstr ""
39
 
40
- #: admin/class-hfe-admin.php:66
41
  msgid "Add New Header Footer"
42
  msgstr ""
43
 
44
- #: admin/class-hfe-admin.php:67
45
  msgid "New Header Footers Template"
46
  msgstr ""
47
 
48
- #: admin/class-hfe-admin.php:68
49
  msgid "Edit Header Footers Template"
50
  msgstr ""
51
 
52
- #: admin/class-hfe-admin.php:69
53
  msgid "View Header Footers Template"
54
  msgstr ""
55
 
56
- #: admin/class-hfe-admin.php:70
57
  msgid "All Elementor Header Footers"
58
  msgstr ""
59
 
60
- #: admin/class-hfe-admin.php:71
61
  msgid "Search Header Footers Templates"
62
  msgstr ""
63
 
64
- #: admin/class-hfe-admin.php:72
65
  msgid "Parent Header Footers Templates:"
66
  msgstr ""
67
 
68
- #: admin/class-hfe-admin.php:73
69
  msgid "No Header Footers Templates found."
70
  msgstr ""
71
 
72
- #: admin/class-hfe-admin.php:74
73
  msgid "No Header Footers Templates found in Trash."
74
  msgstr ""
75
 
76
- #: admin/class-hfe-admin.php:104 admin/class-hfe-admin.php:105
77
  msgid "Header Footer Builder"
78
  msgstr ""
79
 
80
- #: admin/class-hfe-admin.php:117
81
  msgid "Elementor Header Footer options"
82
  msgstr ""
83
 
84
- #: admin/class-hfe-admin.php:145
85
  msgid "Type of Template"
86
  msgstr ""
87
 
88
- #: admin/class-hfe-admin.php:149
89
  msgid "Select Option"
90
  msgstr ""
91
 
92
- #: admin/class-hfe-admin.php:150
93
  msgid "Header"
94
  msgstr ""
95
 
96
- #: admin/class-hfe-admin.php:152
97
  msgid "Before Footer"
98
  msgstr ""
99
 
100
- #: admin/class-hfe-admin.php:154
101
  msgid "Footer"
102
  msgstr ""
103
 
104
- #: admin/class-hfe-admin.php:155
105
  msgid "Custom Block"
106
  msgstr ""
107
 
108
- #: admin/class-hfe-admin.php:161 admin/class-hfe-admin.php:321
109
  msgid "Shortcode"
110
  msgstr ""
111
 
112
- #: admin/class-hfe-admin.php:162
113
  msgid ""
114
  "Copy this shortcode and paste it into your post, page, or text widget "
115
  "content."
116
  msgstr ""
117
 
118
- #: admin/class-hfe-admin.php:174
119
  msgid "Enable Layout for Elementor Canvas Template?"
120
  msgstr ""
121
 
122
- #: admin/class-hfe-admin.php:176
123
  msgid ""
124
  "Enabling this option will display this layout on pages using Elementor "
125
  "Canvas Template."
126
  msgstr ""
127
 
128
- #: admin/class-hfe-admin.php:248
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  #. Translators: Post title, Template Location
130
  msgid "Template %1$s is already assigned to the location %2$s"
131
  msgstr ""
132
 
133
- #: inc/class-header-footer-elementor.php:101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  #. Translators: URL to install or activate Elementor plugin.
135
  msgid ""
136
  "The <strong>Header Footer Elementor</strong> plugin requires <strong><a "
137
  "href=\"%s\">Elementor</strong></a> plugin installed & activated."
138
  msgstr ""
139
 
140
- #: inc/class-header-footer-elementor.php:219
141
  msgid ""
142
  "Hey, your current theme is not supported by Header Footer Elementor, click "
143
  "<a "
@@ -145,8 +219,384 @@ msgid ""
145
  "are-supported-by-this-plugin\">here</a> to check out the supported themes."
146
  msgstr ""
147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  #. Plugin Name of the plugin/theme
149
- msgid "Header, Footer & Blocks for Elementor"
150
  msgstr ""
151
 
152
  #. Plugin URI of the plugin/theme
1
  # Copyright (C) 2019 Brainstorm Force, Nikhil Chavan
2
+ # This file is distributed under the same license as the Elementor - Header, Footer & Blocks package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Elementor - Header, Footer & Blocks 1.2.0-beta.1\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/header-footer-elementor\n"
8
+ "POT-Creation-Date: 2019-12-09 06:37:46+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
23
  "X-Poedit-SearchPath-0: .\n"
24
  "X-Poedit-Bookmarks: \n"
25
  "X-Textdomain-Support: yes\n"
26
+ "X-Generator: grunt-wp-i18n 1.0.3\n"
27
 
28
+ #: admin/class-hfe-admin.php:60 admin/class-hfe-admin.php:62
29
  msgid "Header Footers Template"
30
  msgstr ""
31
 
32
+ #: admin/class-hfe-admin.php:61 admin/class-hfe-admin.php:63
33
  msgid "Elementor Header Footer"
34
  msgstr ""
35
 
36
+ #: admin/class-hfe-admin.php:64
37
  msgid "Add New"
38
  msgstr ""
39
 
40
+ #: admin/class-hfe-admin.php:65
41
  msgid "Add New Header Footer"
42
  msgstr ""
43
 
44
+ #: admin/class-hfe-admin.php:66
45
  msgid "New Header Footers Template"
46
  msgstr ""
47
 
48
+ #: admin/class-hfe-admin.php:67
49
  msgid "Edit Header Footers Template"
50
  msgstr ""
51
 
52
+ #: admin/class-hfe-admin.php:68
53
  msgid "View Header Footers Template"
54
  msgstr ""
55
 
56
+ #: admin/class-hfe-admin.php:69
57
  msgid "All Elementor Header Footers"
58
  msgstr ""
59
 
60
+ #: admin/class-hfe-admin.php:70
61
  msgid "Search Header Footers Templates"
62
  msgstr ""
63
 
64
+ #: admin/class-hfe-admin.php:71
65
  msgid "Parent Header Footers Templates:"
66
  msgstr ""
67
 
68
+ #: admin/class-hfe-admin.php:72
69
  msgid "No Header Footers Templates found."
70
  msgstr ""
71
 
72
+ #: admin/class-hfe-admin.php:73
73
  msgid "No Header Footers Templates found in Trash."
74
  msgstr ""
75
 
76
+ #: admin/class-hfe-admin.php:102 admin/class-hfe-admin.php:103
77
  msgid "Header Footer Builder"
78
  msgstr ""
79
 
80
+ #: admin/class-hfe-admin.php:115
81
  msgid "Elementor Header Footer options"
82
  msgstr ""
83
 
84
+ #: admin/class-hfe-admin.php:143
85
  msgid "Type of Template"
86
  msgstr ""
87
 
88
+ #: admin/class-hfe-admin.php:147
89
  msgid "Select Option"
90
  msgstr ""
91
 
92
+ #: admin/class-hfe-admin.php:148
93
  msgid "Header"
94
  msgstr ""
95
 
96
+ #: admin/class-hfe-admin.php:149
97
  msgid "Before Footer"
98
  msgstr ""
99
 
100
+ #: admin/class-hfe-admin.php:150
101
  msgid "Footer"
102
  msgstr ""
103
 
104
+ #: admin/class-hfe-admin.php:151
105
  msgid "Custom Block"
106
  msgstr ""
107
 
108
+ #: admin/class-hfe-admin.php:159 admin/class-hfe-admin.php:404
109
  msgid "Shortcode"
110
  msgstr ""
111
 
112
+ #: admin/class-hfe-admin.php:160
113
  msgid ""
114
  "Copy this shortcode and paste it into your post, page, or text widget "
115
  "content."
116
  msgstr ""
117
 
118
+ #: admin/class-hfe-admin.php:172
119
  msgid "Enable Layout for Elementor Canvas Template?"
120
  msgstr ""
121
 
122
+ #: admin/class-hfe-admin.php:174
123
  msgid ""
124
  "Enabling this option will display this layout on pages using Elementor "
125
  "Canvas Template."
126
  msgstr ""
127
 
128
+ #: admin/class-hfe-admin.php:200
129
+ msgid "Display On"
130
+ msgstr ""
131
+
132
+ #: admin/class-hfe-admin.php:202
133
+ msgid "Add locations for where this template should appear."
134
+ msgstr ""
135
+
136
+ #: admin/class-hfe-admin.php:209
137
+ msgid "Display Rules"
138
+ msgstr ""
139
+
140
+ #: admin/class-hfe-admin.php:213
141
+ msgid "Add Display Rule"
142
+ msgstr ""
143
+
144
+ #: admin/class-hfe-admin.php:222
145
+ msgid "Do Not Display On"
146
+ msgstr ""
147
+
148
+ #: admin/class-hfe-admin.php:224
149
+ msgid "This Advanced Header will not appear at these locations."
150
+ msgstr ""
151
+
152
+ #: admin/class-hfe-admin.php:231
153
+ msgid "Exclude On"
154
+ msgstr ""
155
+
156
+ #: admin/class-hfe-admin.php:234
157
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:840
158
+ msgid "Add Exclusion Rule"
159
+ msgstr ""
160
+
161
+ #: admin/class-hfe-admin.php:244
162
+ msgid "User Roles"
163
+ msgstr ""
164
+
165
+ #: admin/class-hfe-admin.php:245
166
+ msgid "Targer header based on user role."
167
+ msgstr ""
168
+
169
+ #: admin/class-hfe-admin.php:252
170
+ msgid "Users"
171
+ msgstr ""
172
+
173
+ #: admin/class-hfe-admin.php:255
174
+ msgid "Add User Rule"
175
+ msgstr ""
176
+
177
+ #: admin/class-hfe-admin.php:335
178
  #. Translators: Post title, Template Location
179
  msgid "Template %1$s is already assigned to the location %2$s"
180
  msgstr ""
181
 
182
+ #: inc/class-header-footer-elementor.php:142
183
+ msgid ""
184
+ "Hello! Seems like you have used Elementor - Header, Footer & Blocks to "
185
+ "build this website — Thanks a ton!"
186
+ msgstr ""
187
+
188
+ #: inc/class-header-footer-elementor.php:143
189
+ msgid ""
190
+ "Could you please do us a BIG favor and give it a 5-star rating on "
191
+ "WordPress? This would boost our motivation and help other users make a "
192
+ "comfortable decision while choosing the Elementor - Header, Footer & Blocks."
193
+ msgstr ""
194
+
195
+ #: inc/class-header-footer-elementor.php:145
196
+ msgid "Ok, you deserve it"
197
+ msgstr ""
198
+
199
+ #: inc/class-header-footer-elementor.php:147
200
+ msgid "Nope, maybe later"
201
+ msgstr ""
202
+
203
+ #: inc/class-header-footer-elementor.php:148
204
+ msgid "I already did"
205
+ msgstr ""
206
+
207
+ #: inc/class-header-footer-elementor.php:181
208
  #. Translators: URL to install or activate Elementor plugin.
209
  msgid ""
210
  "The <strong>Header Footer Elementor</strong> plugin requires <strong><a "
211
  "href=\"%s\">Elementor</strong></a> plugin installed & activated."
212
  msgstr ""
213
 
214
+ #: inc/class-header-footer-elementor.php:313
215
  msgid ""
216
  "Hey, your current theme is not supported by Header Footer Elementor, click "
217
  "<a "
219
  "are-supported-by-this-plugin\">here</a> to check out the supported themes."
220
  msgstr ""
221
 
222
+ #: inc/lib/notices/class-astra-notices.php:120
223
+ msgid "WordPress Nonce not validated."
224
+ msgstr ""
225
+
226
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:127
227
+ msgid "404 Page"
228
+ msgstr ""
229
+
230
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:128
231
+ msgid "Search Page"
232
+ msgstr ""
233
+
234
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:129
235
+ msgid "Blog / Posts Page"
236
+ msgstr ""
237
+
238
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:130
239
+ msgid "Front Page"
240
+ msgstr ""
241
+
242
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:131
243
+ msgid "Date Archive"
244
+ msgstr ""
245
+
246
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:132
247
+ msgid "Author Archive"
248
+ msgstr ""
249
+
250
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:136
251
+ msgid "WooCommerce Shop Page"
252
+ msgstr ""
253
+
254
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:141
255
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:213
256
+ msgid "Basic"
257
+ msgstr ""
258
+
259
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:143
260
+ msgid "Entire Website"
261
+ msgstr ""
262
+
263
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:144
264
+ msgid "All Singulars"
265
+ msgstr ""
266
+
267
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:145
268
+ msgid "All Archives"
269
+ msgstr ""
270
+
271
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:150
272
+ msgid "Special Pages"
273
+ msgstr ""
274
+
275
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:191
276
+ msgid "Specific Target"
277
+ msgstr ""
278
+
279
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:193
280
+ msgid "Specific Pages / Posts / Taxanomies, etc."
281
+ msgstr ""
282
+
283
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:215
284
+ msgid "All"
285
+ msgstr ""
286
+
287
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:216
288
+ msgid "Logged In"
289
+ msgstr ""
290
+
291
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:217
292
+ msgid "Logged Out"
293
+ msgstr ""
294
+
295
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:222
296
+ msgid "Advanced"
297
+ msgstr ""
298
+
299
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:619
300
+ msgid "Please enter"
301
+ msgstr ""
302
+
303
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:620
304
+ msgid "Please delete"
305
+ msgstr ""
306
+
307
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:621
308
+ msgid "or more characters"
309
+ msgstr ""
310
+
311
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:622
312
+ msgid "character"
313
+ msgstr ""
314
+
315
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:623
316
+ msgid "Loading more results…"
317
+ msgstr ""
318
+
319
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:624
320
+ msgid "You can only select"
321
+ msgstr ""
322
+
323
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:625
324
+ msgid "item"
325
+ msgstr ""
326
+
327
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:626
328
+ msgid "s"
329
+ msgstr ""
330
+
331
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:627
332
+ msgid "No results found"
333
+ msgstr ""
334
+
335
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:628
336
+ msgid "Searching…"
337
+ msgstr ""
338
+
339
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:629
340
+ msgid "The results could not be loaded."
341
+ msgstr ""
342
+
343
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:630
344
+ msgid "Search pages / post / categories"
345
+ msgstr ""
346
+
347
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:648
348
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:1057
349
+ msgid "Add Rule"
350
+ msgstr ""
351
+
352
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:664
353
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:769
354
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:1073
355
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:1103
356
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:1553
357
+ msgid "Select"
358
+ msgstr ""
359
+
360
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:714
361
+ #. translators: %s post label
362
+ msgid "All %s"
363
+ msgstr ""
364
+
365
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:719
366
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:728
367
+ #. translators: %s post label
368
+ #. translators: %s taxonomy label
369
+ msgid "All %s Archive"
370
+ msgstr ""
371
+
372
+ #: inc/lib/target-rule/class-astra-target-rules-fields.php:1494
373
+ #. translators: %s post title.
374
+ msgid "The same display setting is already exist in %s post/s."
375
+ msgstr ""
376
+
377
+ #: inc/widgets-manager/widgets/class-copyright.php:53
378
+ #: inc/widgets-manager/widgets/class-copyright.php:103
379
+ msgid "Copyright"
380
+ msgstr ""
381
+
382
+ #: inc/widgets-manager/widgets/class-copyright.php:110
383
+ msgid "Copyright Text"
384
+ msgstr ""
385
+
386
+ #: inc/widgets-manager/widgets/class-copyright.php:115
387
+ msgid ""
388
+ "Copyright © [hfe_current_year] [hfe_site_title] | Powered by "
389
+ "[hfe_site_title]"
390
+ msgstr ""
391
+
392
+ #: inc/widgets-manager/widgets/class-copyright.php:122
393
+ #: inc/widgets-manager/widgets/class-retina.php:214
394
+ #: inc/widgets-manager/widgets/class-retina.php:227
395
+ msgid "Link"
396
+ msgstr ""
397
+
398
+ #: inc/widgets-manager/widgets/class-copyright.php:124
399
+ #: inc/widgets-manager/widgets/class-retina.php:232
400
+ msgid "https://your-link.com"
401
+ msgstr ""
402
+
403
+ #: inc/widgets-manager/widgets/class-copyright.php:131
404
+ #: inc/widgets-manager/widgets/class-retina.php:158
405
+ msgid "Alignment"
406
+ msgstr ""
407
+
408
+ #: inc/widgets-manager/widgets/class-copyright.php:135
409
+ #: inc/widgets-manager/widgets/class-retina.php:162
410
+ msgid "Left"
411
+ msgstr ""
412
+
413
+ #: inc/widgets-manager/widgets/class-copyright.php:139
414
+ #: inc/widgets-manager/widgets/class-retina.php:166
415
+ msgid "Center"
416
+ msgstr ""
417
+
418
+ #: inc/widgets-manager/widgets/class-copyright.php:143
419
+ #: inc/widgets-manager/widgets/class-retina.php:170
420
+ msgid "Right"
421
+ msgstr ""
422
+
423
+ #: inc/widgets-manager/widgets/class-copyright.php:156
424
+ #: inc/widgets-manager/widgets/class-retina.php:531
425
+ msgid "Text Color"
426
+ msgstr ""
427
+
428
+ #: inc/widgets-manager/widgets/class-retina.php:61
429
+ #: inc/widgets-manager/widgets/class-retina.php:118
430
+ #: inc/widgets-manager/widgets/class-retina.php:251
431
+ msgid "Retina Image"
432
+ msgstr ""
433
+
434
+ #: inc/widgets-manager/widgets/class-retina.php:124
435
+ msgid "Choose Default Image"
436
+ msgstr ""
437
+
438
+ #: inc/widgets-manager/widgets/class-retina.php:137
439
+ msgid "Choose Retina Image"
440
+ msgstr ""
441
+
442
+ #: inc/widgets-manager/widgets/class-retina.php:151
443
+ msgid "Image Size"
444
+ msgstr ""
445
+
446
+ #: inc/widgets-manager/widgets/class-retina.php:184
447
+ #: inc/widgets-manager/widgets/class-retina.php:520
448
+ msgid "Caption"
449
+ msgstr ""
450
+
451
+ #: inc/widgets-manager/widgets/class-retina.php:187
452
+ #: inc/widgets-manager/widgets/class-retina.php:218
453
+ #: inc/widgets-manager/widgets/class-retina.php:336
454
+ msgid "None"
455
+ msgstr ""
456
+
457
+ #: inc/widgets-manager/widgets/class-retina.php:188
458
+ #: inc/widgets-manager/widgets/class-retina.php:197
459
+ msgid "Custom Caption"
460
+ msgstr ""
461
+
462
+ #: inc/widgets-manager/widgets/class-retina.php:200
463
+ msgid "Enter your image caption"
464
+ msgstr ""
465
+
466
+ #: inc/widgets-manager/widgets/class-retina.php:219
467
+ msgid "Custom URL"
468
+ msgstr ""
469
+
470
+ #: inc/widgets-manager/widgets/class-retina.php:259
471
+ msgid "Width"
472
+ msgstr ""
473
+
474
+ #: inc/widgets-manager/widgets/class-retina.php:295
475
+ msgid "Max Width"
476
+ msgstr ""
477
+
478
+ #: inc/widgets-manager/widgets/class-retina.php:331
479
+ msgid "Border Style"
480
+ msgstr ""
481
+
482
+ #: inc/widgets-manager/widgets/class-retina.php:337
483
+ msgid "Solid"
484
+ msgstr ""
485
+
486
+ #: inc/widgets-manager/widgets/class-retina.php:338
487
+ msgid "Double"
488
+ msgstr ""
489
+
490
+ #: inc/widgets-manager/widgets/class-retina.php:339
491
+ msgid "Dotted"
492
+ msgstr ""
493
+
494
+ #: inc/widgets-manager/widgets/class-retina.php:340
495
+ msgid "Dashed"
496
+ msgstr ""
497
+
498
+ #: inc/widgets-manager/widgets/class-retina.php:350
499
+ msgid "Border Width"
500
+ msgstr ""
501
+
502
+ #: inc/widgets-manager/widgets/class-retina.php:372
503
+ msgid "Border Color"
504
+ msgstr ""
505
+
506
+ #: inc/widgets-manager/widgets/class-retina.php:391
507
+ msgid "Border Radius"
508
+ msgstr ""
509
+
510
+ #: inc/widgets-manager/widgets/class-retina.php:416
511
+ msgid "Normal"
512
+ msgstr ""
513
+
514
+ #: inc/widgets-manager/widgets/class-retina.php:423
515
+ #: inc/widgets-manager/widgets/class-retina.php:457
516
+ msgid "Opacity"
517
+ msgstr ""
518
+
519
+ #: inc/widgets-manager/widgets/class-retina.php:451
520
+ msgid "Hover"
521
+ msgstr ""
522
+
523
+ #: inc/widgets-manager/widgets/class-retina.php:483
524
+ msgid "Hover Animation"
525
+ msgstr ""
526
+
527
+ #: inc/widgets-manager/widgets/class-retina.php:490
528
+ msgid "Transition Duration"
529
+ msgstr ""
530
+
531
+ #: inc/widgets-manager/widgets/class-retina.php:547
532
+ msgid "Background Color"
533
+ msgstr ""
534
+
535
+ #: inc/widgets-manager/widgets/class-retina.php:575
536
+ msgid "Padding"
537
+ msgstr ""
538
+
539
+ #: inc/widgets-manager/widgets/class-retina.php:586
540
+ msgid "Caption Top Spacing"
541
+ msgstr ""
542
+
543
+ #: inc/widgets-manager/widgets/class-retina.php:617
544
+ msgid "Helpful Information"
545
+ msgstr ""
546
+
547
+ #: inc/widgets-manager/widgets/class-retina.php:626
548
+ #. translators: %1$s doc link
549
+ msgid "%1$s Getting started article » %2$s"
550
+ msgstr ""
551
+
552
+ #: themes/default/class-hfe-fallback-theme-support.php:66
553
+ msgid "Compatibility Mode"
554
+ msgstr ""
555
+
556
+ #: themes/default/class-hfe-fallback-theme-support.php:79
557
+ msgid ""
558
+ "Header Footer Elementor plugin includes two compatibility modes to try to "
559
+ "support all the themes.<br>Use the method which works best with your "
560
+ "theme.<br><br>It is possible that both these methods will not work with "
561
+ "your theme correctly with your theme, In that case you should contact your "
562
+ "theme author and request them to <a "
563
+ "href=\"https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-"
564
+ "Header-Footer-Elementor-support-for-your-theme\" target=\"_blank\">add "
565
+ "support for this plugin</a>."
566
+ msgstr ""
567
+
568
+ #: themes/default/class-hfe-fallback-theme-support.php:96
569
+ msgid "Method 1"
570
+ msgstr ""
571
+
572
+ #: themes/default/class-hfe-fallback-theme-support.php:97
573
+ msgid ""
574
+ "This replaces the header.php & footer.php template with a custom templates "
575
+ "from the plugin."
576
+ msgstr ""
577
+
578
+ #: themes/default/class-hfe-fallback-theme-support.php:100
579
+ msgid "Method 2"
580
+ msgstr ""
581
+
582
+ #: themes/default/class-hfe-fallback-theme-support.php:140
583
+ #: themes/default/class-hfe-fallback-theme-support.php:141
584
+ #: themes/default/class-hfe-fallback-theme-support.php:169
585
+ #: themes/default/class-hfe-fallback-theme-support.php:210
586
+ msgid "Settings"
587
+ msgstr ""
588
+
589
+ #: themes/default/class-hfe-fallback-theme-support.php:157
590
+ msgid "Elementor - Header, Footer & Blocks "
591
+ msgstr ""
592
+
593
+ #: themes/default/class-hfe-fallback-theme-support.php:165
594
+ #: themes/default/class-hfe-fallback-theme-support.php:206
595
+ msgid "All templates"
596
+ msgstr ""
597
+
598
  #. Plugin Name of the plugin/theme
599
+ msgid "Elementor - Header, Footer & Blocks"
600
  msgstr ""
601
 
602
  #. Plugin URI of the plugin/theme
readme.txt CHANGED
@@ -4,8 +4,8 @@ Tags: elementor, header footer builder, header, footer, page builder, template b
4
  Donate link: https://www.paypal.me/BrainstormForce
5
  Requires at least: 4.4
6
  Requires PHP: 5.4
7
- Tested up to: 5.2
8
- Stable tag: 1.1.4
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -13,7 +13,7 @@ Create Header and Footer for your site using Elementor Page Builder.
13
 
14
  == Description ==
15
 
16
- Have you ever imagined you could create your website’s header and footer with <a href="https://elementor.com/?ref=1352">Elementor</a>?
17
 
18
  The Header Footer Elementor plugin allows you to create a layout with Elementor and set it as a header or footer easily on your website.
19
 
@@ -27,7 +27,7 @@ You can refer to our step-by-step article that will help you <a href="https://ua
27
 
28
  = Features of Header Footer Elementor =
29
 
30
- - Create attractive pages and templates to be used as header or footer.
31
  - Usefully customized header and footer across the website.
32
 
33
  = Themes you can use Header Footer Elementor with =
@@ -41,6 +41,7 @@ The Header Footer Elementor isn’t universally compatible with all WordPress th
41
  5. OceanWP.
42
  6. Genesis.
43
  7. Phlox Theme.
 
44
 
45
  Do not see your theme listed here? Theme authors can add <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">support for Header Footer Elementor through their theme</a> easily.
46
 
@@ -61,7 +62,7 @@ Powering over 400,000+ WordPress websites, Astra is loved for the performance an
61
 
62
  **Deeper Integrations** - Astra works seamlessly with all WooCommerce plugins, LifterLMS, LearnDash, etc. Therefore, you can now build online stores or websites offering online courses with Astra and Elementor!
63
 
64
- **Ready-to-use complete website demos** - Astra offers free ready-made website demos built with Elementor. You can choose any of the Elementor templates <a href="https://wpastra.com/elementor-templates-free-downloads/">Elementor Templates</a>, tweak them as you want and go live in minutes!
65
 
66
  = SUPPORTED & ACTIVELY DEVELOPED =
67
  Need help with something? Have an issue to report? [Get in touch](https://github.com/Nikschavan/header-footer-elementor "Header Footer elementor on GitHub"). with us on GitHub.
@@ -71,28 +72,20 @@ Made with love at <a href="https://www.brainstormforce.com/?utm_source=wp-repo&u
71
  == Installation ==
72
 
73
  1. Go to `Plugins -> Add New` and search for Header Footer Elementor.
74
- 1. Activate the plugin through the 'Plugins' screen in WordPress.
75
- 1. Go to `Appearance -> Header Footer Builder` to build a header or footer layout using elementor.
76
- 1. After the layout is ready assign the layout as header or footer using the option `Select the type of template this is` (<a href="https://cloudup.com/clK2sPg9nXK+">screenshot</a>)
77
 
78
  == Frequently Asked Questions ==
79
 
80
- = Which themes are supported by this plugin? =
81
-
82
- 1. <a href="https://wpastra.com/?utm_source=wp-repo&utm_campaign=header-footer-elementor&utm_medium=description&bsf=162">Astra</a> - The Fastest, Most Lightweight &amp; Customizable WordPress Theme.
83
- 2. GeneratePress Theme.
84
- 3. Genesis Theme (and should work with most of its child themes).
85
- 4. OceanWP Theme.
86
- 5. Beaver Builder theme.
87
-
88
  If you are a theme developer <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">here</a> is a quick tutorial on how you can add support for the Header Footer Elementor from your theme.
89
 
90
  = How does this plugin work =
91
 
92
  1. Go to `Appearance -> Header Footer Builder` to build a header or footer layout using elementor.
93
- 1. After the layout is ready assign the layout as header or footer using the option `Select the type of template this is` (<a href="https://cloudup.com/clK2sPg9nXK+">screenshot</a>)
94
 
95
- = Can you create Mobile Responsive Header/Footer using this plugin? =
96
 
97
  Yes, You can create the mobile responsive layout of your header using the plugin.
98
 
@@ -105,8 +98,8 @@ This same applies when you are creating your Header/Footer using this plugin.
105
 
106
  If you are a theme developer <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">here</a> is a quick tutorial on how you can add support for the Header Footer Elementor from your theme.
107
 
108
- If you are using a pre-made theme, The best approach would be to contact yoru theme developer and provide them link to the <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">Wiki article</a> on how they can add support for the plugin.
109
- If the above is nnot possible, You can also add support for the plugin from your child theme. Just follow <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Add-support-to-Header-Footer-Elementor-from-the-Child-Theme">this article</a>
110
 
111
  == Screenshots ==
112
 
@@ -115,6 +108,14 @@ If the above is nnot possible, You can also add support for the plugin from your
115
 
116
  == Changelog ==
117
 
 
 
 
 
 
 
 
 
118
  = 1.1.4 =
119
  - Fix: Flush permalinks on plugin update to Elementor error when trying to edit the Header/Footer.
120
 
@@ -132,7 +133,7 @@ If the above is nnot possible, You can also add support for the plugin from your
132
 
133
  = 1.1.0 =
134
  - New: Rename plugin to be Header Footer & Blocks builder as now thee blocks templates can be used as shortcodes.
135
- - New: Add templates before the footer for Astra Theme. Options for other themes will be cominng soon.
136
  - New: Use templates (Blocks) anywhere in your content with the help of shortcodes.
137
  - Improvement: Improved the UI of the metabox for Header Footer post type.
138
 
@@ -186,7 +187,7 @@ If the above is nnot possible, You can also add support for the plugin from your
186
 
187
  = 1.0.2 =
188
  - New: Added support for the OceanWP Theme.
189
- - Fix: Load the elementor header assets corectly in header. This fixes header looking different just when loading the page as previously Elementor would load it's CSS in the footer.
190
  - Introduced helper functions for rendering and checking the headers to make it simpler to integrate HFE with more themes.
191
 
192
  = 1.0.1 =
4
  Donate link: https://www.paypal.me/BrainstormForce
5
  Requires at least: 4.4
6
  Requires PHP: 5.4
7
+ Tested up to: 5.3
8
+ Stable tag: 1.2.0
9
  License: GPLv2 or later
10
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
 
13
 
14
  == Description ==
15
 
16
+ Have you ever imagined you could create your website header and footer with <a href="https://elementor.com/?ref=1352">Elementor</a>?
17
 
18
  The Header Footer Elementor plugin allows you to create a layout with Elementor and set it as a header or footer easily on your website.
19
 
27
 
28
  = Features of Header Footer Elementor =
29
 
30
+ - Create attractive pages and templates to be used as a header or footer.
31
  - Usefully customized header and footer across the website.
32
 
33
  = Themes you can use Header Footer Elementor with =
41
  5. OceanWP.
42
  6. Genesis.
43
  7. Phlox Theme.
44
+ 8. Attesa Theme.
45
 
46
  Do not see your theme listed here? Theme authors can add <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">support for Header Footer Elementor through their theme</a> easily.
47
 
62
 
63
  **Deeper Integrations** - Astra works seamlessly with all WooCommerce plugins, LifterLMS, LearnDash, etc. Therefore, you can now build online stores or websites offering online courses with Astra and Elementor!
64
 
65
+ **Ready-to-use complete website demos** - Astra offers free ready-made website demos built with Elementor. You can choose any of the <a href="https://wpastra.com/elementor-templates-free-downloads/">Elementor Templates</a>, tweak them as you want and go live in minutes!
66
 
67
  = SUPPORTED & ACTIVELY DEVELOPED =
68
  Need help with something? Have an issue to report? [Get in touch](https://github.com/Nikschavan/header-footer-elementor "Header Footer elementor on GitHub"). with us on GitHub.
72
  == Installation ==
73
 
74
  1. Go to `Plugins -> Add New` and search for Header Footer Elementor.
75
+ 2. Activate the plugin through the 'Plugins' screen in WordPress.
76
+ 3. Go to `Appearance -> Header Footer Builder` to build a header or footer layout using elementor.
77
+ 4. After the layout is ready assign it as header or footer using the option `Select the type of template this is` (<a href="https://cloudup.com/clK2sPg9nXK+">screenshot</a>)
78
 
79
  == Frequently Asked Questions ==
80
 
 
 
 
 
 
 
 
 
81
  If you are a theme developer <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">here</a> is a quick tutorial on how you can add support for the Header Footer Elementor from your theme.
82
 
83
  = How does this plugin work =
84
 
85
  1. Go to `Appearance -> Header Footer Builder` to build a header or footer layout using elementor.
86
+ 2. After the layout is ready assign the layout as header or footer using the option `Select the type of template this is` (<a href="https://cloudup.com/clK2sPg9nXK+">screenshot</a>)
87
 
88
+ = Can you create a Mobile Responsive Header/Footer using this plugin? =
89
 
90
  Yes, You can create the mobile responsive layout of your header using the plugin.
91
 
98
 
99
  If you are a theme developer <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">here</a> is a quick tutorial on how you can add support for the Header Footer Elementor from your theme.
100
 
101
+ If you are using a pre-made theme, The best approach would be to contact your theme developer and provide them link to the <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">Wiki article</a> on how they can add support for the plugin.
102
+ If the above is not possible, You can also add support for the plugin from your child theme. Just follow <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Add-support-to-Header-Footer-Elementor-from-the-Child-Theme">this article</a>
103
 
104
  == Screenshots ==
105
 
108
 
109
  == Changelog ==
110
 
111
+ = 1.2.0 =
112
+ - New: Support all the themes, Includes two separate fallback methods so that you can create custom headers and footers for any theme.
113
+ - New: Added target rule engine, which allows you to have different headers/footers for different pages.
114
+ - New: Added Retina Image Elementor widget, which can be used as a Site Logo.
115
+ - New: Added Copyright widget and Shortcode for current year & site title.
116
+ - Improvement: Allow before footer to work on Elementor Canvas Template when not using Astra Theme.
117
+ - Improvement: Added support of `Before Footer` action for all the themes.
118
+
119
  = 1.1.4 =
120
  - Fix: Flush permalinks on plugin update to Elementor error when trying to edit the Header/Footer.
121
 
133
 
134
  = 1.1.0 =
135
  - New: Rename plugin to be Header Footer & Blocks builder as now thee blocks templates can be used as shortcodes.
136
+ - New: Add templates before the footer for Astra Theme. Options for other themes will be coming soon.
137
  - New: Use templates (Blocks) anywhere in your content with the help of shortcodes.
138
  - Improvement: Improved the UI of the metabox for Header Footer post type.
139
 
187
 
188
  = 1.0.2 =
189
  - New: Added support for the OceanWP Theme.
190
+ - Fix: Load the elementor header assets correctly in the header. This fixes header looking different just when loading the page as previously Elementor would load its CSS in the footer.
191
  - Introduced helper functions for rendering and checking the headers to make it simpler to integrate HFE with more themes.
192
 
193
  = 1.0.1 =
themes/astra/class-hfe-astra-compat.php CHANGED
@@ -17,28 +17,14 @@ class HFE_Astra_Compat {
17
  */
18
  private static $instance;
19
 
20
- /**
21
- * Instance of Elementor Frontend class.
22
- *
23
- * @var \Elementor\Frontend()
24
- */
25
- private static $elementor_instance;
26
-
27
  /**
28
  * Initiator
29
  */
30
  public static function instance() {
31
-
32
  if ( ! isset( self::$instance ) ) {
33
  self::$instance = new HFE_Astra_Compat();
34
 
35
- add_action( 'wp', array( self::$instance, 'hooks' ) );
36
- }
37
-
38
- if ( defined( 'ELEMENTOR_VERSION' ) && is_callable( 'Elementor\Plugin::instance' ) ) {
39
-
40
- self::$elementor_instance = Elementor\Plugin::instance();
41
-
42
  }
43
 
44
  return self::$instance;
@@ -48,35 +34,18 @@ class HFE_Astra_Compat {
48
  * Run all the Actions / Filters.
49
  */
50
  public function hooks() {
51
-
52
  if ( hfe_header_enabled() ) {
53
- add_action( 'template_redirect', array( $this, 'astra_setup_header' ), 10 );
54
  add_action( 'astra_header', 'hfe_render_header' );
55
  }
56
 
57
  if ( hfe_footer_enabled() ) {
58
- add_action( 'template_redirect', array( $this, 'astra_setup_footer' ), 10 );
59
  add_action( 'astra_footer', 'hfe_render_footer' );
60
  }
61
 
62
- if ( $this->is_before_footer_enabled() ) {
63
-
64
- // Action `elementor/page_templates/canvas/after_content` is introduced in Elementor Version 1.9.0.
65
- if ( version_compare( ELEMENTOR_VERSION, '1.9.0', '>=' ) ) {
66
-
67
- // check if current page template is Elemenntor Canvas.
68
- if ( 'elementor_canvas' == get_page_template_slug() ) {
69
-
70
- $override_cannvas_template = get_post_meta( $this->get_hfe_before_footer_id(), 'display-on-canvas-template', true );
71
-
72
- if ( '1' == $override_cannvas_template ) {
73
- add_action( 'elementor/page_templates/canvas/after_content', array( $this, 'render_before_footer' ), 9 );
74
- }
75
- }
76
- }
77
-
78
- add_action( 'astra_footer_before', array( $this, 'render_before_footer' ) );
79
-
80
  }
81
  }
82
 
@@ -94,70 +63,6 @@ class HFE_Astra_Compat {
94
  remove_action( 'astra_footer', 'astra_footer_markup' );
95
  }
96
 
97
- /**
98
- * Get HFE Before Footer ID
99
- *
100
- * @since 1.0.2
101
- * @return (String|boolean) before gooter id if it is set else returns false.
102
- */
103
- function get_hfe_before_footer_id() {
104
-
105
- $before_footer_id = Header_Footer_Elementor::get_settings( 'type_before_footer', '' );
106
-
107
- if ( '' === $before_footer_id ) {
108
- $before_footer_id = false;
109
- }
110
-
111
- return apply_filters( 'get_hfe_before_footer_id', $before_footer_id );
112
- }
113
-
114
- /**
115
- * Checks if Before Footer is enabled from HFE.
116
- *
117
- * @since 1.0.2
118
- * @return bool True if before footer is enabled. False if before footer is not enabled.
119
- */
120
- function is_before_footer_enabled() {
121
-
122
- $before_footer_id = Header_Footer_Elementor::get_settings( 'type_before_footer', '' );
123
- $status = false;
124
-
125
- if ( '' !== $before_footer_id ) {
126
- $status = true;
127
- }
128
-
129
- return apply_filters( 'hfe_before_footer_enabled', $status );
130
- }
131
-
132
- /**
133
- * Display before footer markup.
134
- *
135
- * @since 1.0.2
136
- */
137
- public function render_before_footer() {
138
-
139
- if ( false == apply_filters( 'enable_hfe_render_before_footer', true ) ) {
140
- return;
141
- }
142
-
143
- ?>
144
- <div class="hfe-before-footer-wrap">
145
- <?php $this->get_before_footer_content(); ?>
146
- </div>
147
- <?php
148
-
149
- }
150
-
151
- /**
152
- * Prints the Before Footer content.
153
- */
154
- public function get_before_footer_content() {
155
-
156
- echo "<div class='footer-width-fixer'>";
157
- echo self::$elementor_instance->frontend->get_builder_content_for_display( $this->get_hfe_before_footer_id() );
158
- echo '</div>';
159
- }
160
-
161
  }
162
 
163
  HFE_Astra_Compat::instance();
17
  */
18
  private static $instance;
19
 
 
 
 
 
 
 
 
20
  /**
21
  * Initiator
22
  */
23
  public static function instance() {
 
24
  if ( ! isset( self::$instance ) ) {
25
  self::$instance = new HFE_Astra_Compat();
26
 
27
+ add_action( 'wp', [ self::$instance, 'hooks' ] );
 
 
 
 
 
 
28
  }
29
 
30
  return self::$instance;
34
  * Run all the Actions / Filters.
35
  */
36
  public function hooks() {
 
37
  if ( hfe_header_enabled() ) {
38
+ add_action( 'template_redirect', [ $this, 'astra_setup_header' ], 10 );
39
  add_action( 'astra_header', 'hfe_render_header' );
40
  }
41
 
42
  if ( hfe_footer_enabled() ) {
43
+ add_action( 'template_redirect', [ $this, 'astra_setup_footer' ], 10 );
44
  add_action( 'astra_footer', 'hfe_render_footer' );
45
  }
46
 
47
+ if ( hfe_is_before_footer_enabled() ) {
48
+ add_action( 'astra_footer_before', 'hfe_render_before_footer' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
  }
51
 
63
  remove_action( 'astra_footer', 'astra_footer_markup' );
64
  }
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
 
68
  HFE_Astra_Compat::instance();
themes/bb-theme/class-hfe-bb-theme-compat.php CHANGED
@@ -23,11 +23,10 @@ class HFE_BB_Theme_Compat {
23
  * Initiator
24
  */
25
  public static function instance() {
26
-
27
  if ( ! isset( self::$instance ) ) {
28
  self::$instance = new HFE_BB_Theme_Compat();
29
 
30
- add_action( 'wp', array( self::$instance, 'hooks' ) );
31
  }
32
 
33
  return self::$instance;
@@ -37,24 +36,25 @@ class HFE_BB_Theme_Compat {
37
  * Run all the Actions / Filters.
38
  */
39
  public function hooks() {
40
-
41
  if ( hfe_header_enabled() ) {
42
  add_filter( 'fl_header_enabled', '__return_false' );
43
- add_action( 'fl_before_header', array( $this, 'get_header_content' ) );
 
 
 
 
44
  }
45
 
46
  if ( hfe_footer_enabled() ) {
47
  add_filter( 'fl_footer_enabled', '__return_false' );
48
- add_action( 'fl_after_content', array( $this, 'get_footer_content' ) );
49
  }
50
-
51
  }
52
 
53
  /**
54
  * Display header markup for beaver builder theme.
55
  */
56
  public function get_header_content() {
57
-
58
  $header_layout = FLTheme::get_setting( 'fl-header-layout' );
59
 
60
  if ( 'none' == $header_layout || is_page_template( 'tpl-no-header-footer.php' ) ) {
@@ -75,7 +75,6 @@ class HFE_BB_Theme_Compat {
75
  * Display footer markup for beaver builder theme.
76
  */
77
  public function get_footer_content() {
78
-
79
  if ( is_page_template( 'tpl-no-header-footer.php' ) ) {
80
  return;
81
  }
23
  * Initiator
24
  */
25
  public static function instance() {
 
26
  if ( ! isset( self::$instance ) ) {
27
  self::$instance = new HFE_BB_Theme_Compat();
28
 
29
+ add_action( 'wp', [ self::$instance, 'hooks' ] );
30
  }
31
 
32
  return self::$instance;
36
  * Run all the Actions / Filters.
37
  */
38
  public function hooks() {
 
39
  if ( hfe_header_enabled() ) {
40
  add_filter( 'fl_header_enabled', '__return_false' );
41
+ add_action( 'fl_before_header', [ $this, 'get_header_content' ] );
42
+ }
43
+
44
+ if ( hfe_is_before_footer_enabled() ) {
45
+ add_action( 'fl_after_content', [ 'Header_Footer_Elementor', 'get_before_footer_content' ], 10 );
46
  }
47
 
48
  if ( hfe_footer_enabled() ) {
49
  add_filter( 'fl_footer_enabled', '__return_false' );
50
+ add_action( 'fl_after_content', [ $this, 'get_footer_content' ] );
51
  }
 
52
  }
53
 
54
  /**
55
  * Display header markup for beaver builder theme.
56
  */
57
  public function get_header_content() {
 
58
  $header_layout = FLTheme::get_setting( 'fl-header-layout' );
59
 
60
  if ( 'none' == $header_layout || is_page_template( 'tpl-no-header-footer.php' ) ) {
75
  * Display footer markup for beaver builder theme.
76
  */
77
  public function get_footer_content() {
 
78
  if ( is_page_template( 'tpl-no-header-footer.php' ) ) {
79
  return;
80
  }
themes/default/class-global-theme-compatibility.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Support all themes.
4
+ *
5
+ * @package header-footer-elementor
6
+ */
7
+
8
+ namespace HFE\Themes;
9
+
10
+ /**
11
+ * Global theme compatibility.
12
+ */
13
+ class Global_Theme_Compatibility {
14
+
15
+ /**
16
+ * Initiator
17
+ */
18
+ public function __construct() {
19
+ add_action( 'wp', [ $this, 'hooks' ] );
20
+ }
21
+
22
+ /**
23
+ * Run all the Actions / Filters.
24
+ */
25
+ public function hooks() {
26
+ if ( hfe_header_enabled() ) {
27
+ // Replace header.php.
28
+ add_action( 'get_header', [ $this, 'option_override_header' ] );
29
+
30
+ add_action( 'wp_body_open', [ 'Header_Footer_Elementor', 'get_header_content' ] );
31
+ add_action( 'hfe_fallback_header', [ 'Header_Footer_Elementor', 'get_header_content' ] );
32
+ }
33
+
34
+ if ( hfe_is_before_footer_enabled() ) {
35
+ add_action( 'wp_footer', [ 'Header_Footer_Elementor', 'get_before_footer_content' ], 20 );
36
+ }
37
+
38
+ if ( hfe_footer_enabled() ) {
39
+ add_action( 'wp_footer', [ 'Header_Footer_Elementor', 'get_footer_content' ], 50 );
40
+ }
41
+
42
+ if ( hfe_header_enabled() || hfe_footer_enabled() ) {
43
+ add_action( 'wp_enqueue_scripts', [ $this, 'force_fullwidth' ] );
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Force full width CSS for the header.
49
+ *
50
+ * @since 1.2.0
51
+ * @return void
52
+ */
53
+ public function force_fullwidth() {
54
+ $css = '
55
+ .force-stretched-header {
56
+ width: 100vw;
57
+ position: relative;
58
+ margin-left: -50vw;
59
+ left: 50%;
60
+ }';
61
+
62
+ if ( true === hfe_header_enabled() ) {
63
+ $css .= 'header#masthead {
64
+ display: none;
65
+ }';
66
+ }
67
+
68
+ if ( true === hfe_footer_enabled() ) {
69
+ $css .= 'footer#colophon {
70
+ display: none;
71
+ }';
72
+ }
73
+
74
+ wp_add_inline_style( 'hfe-style', $css );
75
+ }
76
+
77
+ /**
78
+ * Function overriding the header in the wp_body_open way.
79
+ *
80
+ * @since 1.2.0
81
+ *
82
+ * @return void
83
+ */
84
+ public function option_override_header() {
85
+ $templates = [];
86
+ $templates[] = 'header.php';
87
+ locate_template( $templates, true );
88
+
89
+ if ( ! did_action( 'wp_body_open' ) ) {
90
+ echo '<div class="force-stretched-header">';
91
+ do_action( 'hfe_fallback_header' );
92
+ echo '</div>';
93
+ }
94
+ }
95
+ }
96
+ new Global_Theme_Compatibility();
themes/default/class-hfe-default-compat.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HFE_Default_Compat setup
4
+ *
5
+ * @package header-footer-elementor
6
+ */
7
+
8
+ namespace HFE\Themes;
9
+
10
+ /**
11
+ * Astra theme compatibility.
12
+ */
13
+ class HFE_Default_Compat {
14
+
15
+ /**
16
+ * Initiator
17
+ */
18
+ public function __construct() {
19
+ add_action( 'wp', [ $this, 'hooks' ] );
20
+ }
21
+
22
+ /**
23
+ * Run all the Actions / Filters.
24
+ */
25
+ public function hooks() {
26
+ if ( hfe_header_enabled() ) {
27
+ // Replace header.php template.
28
+ add_action( 'get_header', [ $this, 'override_header' ] );
29
+
30
+ // Display HFE's header in the replaced header.
31
+ add_action( 'hfe_header', 'hfe_render_header' );
32
+ }
33
+
34
+ if ( hfe_footer_enabled() || hfe_is_before_footer_enabled() ) {
35
+ // Replace footer.php template.
36
+ add_action( 'get_footer', [ $this, 'override_footer' ] );
37
+ }
38
+
39
+ if ( hfe_footer_enabled() ) {
40
+ // Display HFE's footer in the replaced header.
41
+ add_action( 'hfe_footer', 'hfe_render_footer' );
42
+ }
43
+
44
+ if ( hfe_is_before_footer_enabled() ) {
45
+ add_action( 'hfe_footer_before', [ 'Header_Footer_Elementor', 'get_before_footer_content' ] );
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Function for overriding the header in the elmentor way.
51
+ *
52
+ * @since 1.2.0
53
+ *
54
+ * @return void
55
+ */
56
+ public function override_header() {
57
+ require HFE_DIR . 'themes/default/hfe-header.php';
58
+ $templates = [];
59
+ $templates[] = 'header.php';
60
+ // Avoid running wp_head hooks again.
61
+ remove_all_actions( 'wp_head' );
62
+ ob_start();
63
+ locate_template( $templates, true );
64
+ ob_get_clean();
65
+ }
66
+
67
+ /**
68
+ * Function for overriding the footer in the elmentor way.
69
+ *
70
+ * @since 1.2.0
71
+ *
72
+ * @return void
73
+ */
74
+ public function override_footer() {
75
+ require HFE_DIR . 'themes/default/hfe-footer.php';
76
+ $templates = [];
77
+ $templates[] = 'footer.php';
78
+ // Avoid running wp_footer hooks again.
79
+ remove_all_actions( 'wp_footer' );
80
+ ob_start();
81
+ locate_template( $templates, true );
82
+ ob_get_clean();
83
+ }
84
+
85
+ }
86
+
87
+ new HFE_Default_Compat();
themes/default/class-hfe-fallback-theme-support.php ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HFE Fallback Theme Support.
4
+ *
5
+ * Add theme compatibility for all the WordPress themes.
6
+ *
7
+ * @since 1.2.0
8
+ * @package hfe
9
+ */
10
+
11
+ namespace HFE\Themes;
12
+
13
+ /**
14
+ * Class HFE Theme Fallback support.
15
+ *
16
+ * @since 1.2.0
17
+ */
18
+ class HFE_Fallback_Theme_Support {
19
+
20
+ /**
21
+ * Constructor.
22
+ *
23
+ * @since 1.2.0
24
+ */
25
+ public function __construct() {
26
+ $this->setup_fallback_support();
27
+ add_action( 'admin_menu', [ $this, 'hfe_register_settings_page' ] );
28
+ add_action( 'admin_init', [ $this, 'hfe_admin_init' ] );
29
+ add_action( 'admin_head', [ $this, 'hfe_global_css' ] );
30
+ add_filter( 'views_edit-elementor-hf', [ $this, 'hfe_settings' ], 10, 1 );
31
+ }
32
+
33
+ /**
34
+ * Adds CSS to Hide the extra submenu added for the settings tab.
35
+ *
36
+ * @since 1.2.0
37
+ * @return void
38
+ */
39
+ public function hfe_global_css() {
40
+ wp_enqueue_style( 'hfe-admin-style', HFE_URL . 'admin/assets/css/ehf-admin.css', [], HFE_VER );
41
+ }
42
+
43
+ /**
44
+ * Adds a tab in plugin submenu page.
45
+ *
46
+ * @since 1.2.0
47
+ * @param string $views to add tab to current post type view.
48
+ *
49
+ * @return mixed
50
+ */
51
+ public function hfe_settings( $views ) {
52
+ $this->hfe_tabs();
53
+ return $views;
54
+ }
55
+
56
+
57
+ /**
58
+ * Function for registering the settings api.
59
+ *
60
+ * @since 1.2.0
61
+ * @return void
62
+ */
63
+ public function hfe_admin_init() {
64
+ register_setting( 'hfe-plugin-options', 'hfe_compatibility_option' );
65
+ add_settings_section( 'hfe-options', __( 'Add Theme Support', 'header-footer-elementor' ), [ $this, 'hfe_compatibility_callback' ], 'Settings' );
66
+ add_settings_field( 'hfe-way', 'Select Method to Add Theme Support', [ $this, 'hfe_compatibility_option_callback' ], 'Settings', 'hfe-options' );
67
+ }
68
+
69
+ /**
70
+ * Call back function for the ssettings api function add_settings_section
71
+ *
72
+ * This function can be used to add description of the settings sections
73
+ *
74
+ * @since 1.2.0
75
+ * @return void
76
+ */
77
+ public function hfe_compatibility_callback() {
78
+ _e( 'The Elementor - Header, Footer & Blocks plugin is compatible with themes listed <a href="https://github.com/Nikschavan/header-footer-elementor#themes-you-can-use-header-footer-elementor-with"> here</a>.<br><br> In case your current theme is not in the list, you can choose one of the following methods to add theme support.', 'header-footer-elementor' );
79
+ }
80
+
81
+ /**
82
+ * Call back function for the ssettings api function add_settings_field
83
+ *
84
+ * This function will contain the markup for the input feilds that we can add.
85
+ *
86
+ * @since 1.2.0
87
+ * @return void
88
+ */
89
+ public function hfe_compatibility_option_callback() {
90
+ $hfe_radio_button = get_option( 'hfe_compatibility_option', '1' );
91
+ wp_enqueue_style( 'hfe-admin-style', HFE_URL . 'admin/assets/css/ehf-admin.css', [], HFE_VER );
92
+ ?>
93
+
94
+ <label>
95
+ <input type="radio" name="hfe_compatibility_option" value= 1 <?php checked( $hfe_radio_button, 1 ); ?> > <div class="hfe_radio_options"><?php esc_html_e( ' Method 1 (Recommended)', 'header-footer-elementor' ); ?></div>
96
+ <p class="description"><?php esc_html_e( 'This method replaces your theme\'s header (header.php) & footer (footer.php) template with plugin\'s custom templates.', 'header-footer-elementor' ); ?></p><br>
97
+ </label>
98
+ <label>
99
+ <input type="radio" name="hfe_compatibility_option" value= 2 <?php checked( $hfe_radio_button, 2 ); ?> > <div class="hfe_radio_options"><?php esc_html_e( 'Method 2', 'header-footer-elementor' ); ?></div>
100
+ <p class="description">
101
+ <?php
102
+ echo sprintf(
103
+ esc_html( "This method hides your theme's header & footer template with CSS and displays custom templates from the plugin.", 'header-footer-elementor' ),
104
+ '<br>'
105
+ );
106
+ ?>
107
+ </p><br>
108
+ </label>
109
+ <p class="description">
110
+ <?php
111
+ echo sprintf(
112
+ _e( 'Sometimes above methods might not work well with your theme, in this case, contact your theme author and request them to add support for the <a href="https://github.com/Nikschavan/header-footer-elementor/wiki/Adding-Header-Footer-Elementor-support-for-your-theme">plugin.</>', 'header-footer-elementor' ),
113
+ '<br>'
114
+ );
115
+ ?>
116
+ </p>
117
+
118
+ <?php
119
+ }
120
+
121
+ /**
122
+ * Setup Theme Support.
123
+ *
124
+ * @since 1.2.0
125
+ * @return void
126
+ */
127
+ public function setup_fallback_support() {
128
+ $hfe_compatibility_option = get_option( 'hfe_compatibility_option', '1' );
129
+
130
+ if ( '1' === $hfe_compatibility_option ) {
131
+ require HFE_DIR . 'themes/default/class-hfe-default-compat.php';
132
+ } elseif ( '2' === $hfe_compatibility_option ) {
133
+ require HFE_DIR . 'themes/default/class-global-theme-compatibility.php';
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Show a settings page incase of unsupported theme.
139
+ *
140
+ * @since 1.2.0
141
+ *
142
+ * @return void
143
+ */
144
+ public function hfe_register_settings_page() {
145
+ add_submenu_page(
146
+ 'themes.php',
147
+ __( 'Settings', 'header-footer-elementor' ),
148
+ __( 'Settings', 'header-footer-elementor' ),
149
+ 'manage_options',
150
+ 'hfe-settings',
151
+ [ $this, 'hfe_settings_page' ]
152
+ );
153
+ }
154
+
155
+ /**
156
+ * Settings page.
157
+ *
158
+ * Call back function for add submenu page function.
159
+ *
160
+ * @since 1.2.0
161
+ */
162
+ public function hfe_settings_page() {
163
+ echo '<h1 class="hfe-heading-inline">';
164
+ esc_attr_e( 'Elementor - Header, Footer & Blocks ', 'header-footer-elementor' );
165
+ echo '</h1>';
166
+
167
+ ?>
168
+ <h2 class="nav-tab-wrapper">
169
+ <?php
170
+ $tabs = [
171
+ 'hfe_templates' => [
172
+ 'name' => __( 'All templates', 'header-footer-elementor' ),
173
+ 'url' => admin_url( 'edit.php?post_type=elementor-hf' ),
174
+ ],
175
+ 'hfe_settings' => [
176
+ 'name' => __( 'Theme Support', 'header-footer-elementor' ),
177
+ 'url' => admin_url( 'themes.php?page=hfe-settings' ),
178
+ ],
179
+ ];
180
+ $active_tab = 'hfe-settings' == isset( $_GET['page'] ) && $_GET['page'] ? 'hfe_settings' : 'hfe_templates';
181
+ foreach ( $tabs as $tab_id => $tab ) {
182
+ $active = $active_tab == $tab_id ? ' nav-tab-active' : '';
183
+ echo '<a href="' . esc_url( $tab['url'] ) . '" class="nav-tab' . $active . '">';
184
+ echo esc_html( $tab['name'] );
185
+ echo '</a>';
186
+ }
187
+ ?>
188
+ </h2>
189
+ <br />
190
+ <?php
191
+ $hfe_radio_button = get_option( 'hfe_compatibility_option', '1' );
192
+ ?>
193
+ <form action="options.php" method="post">
194
+ <?php settings_fields( 'hfe-plugin-options' ); ?>
195
+ <?php do_settings_sections( 'Settings' ); ?>
196
+ <?php submit_button(); ?>
197
+ </form></div>
198
+ <?php
199
+ }
200
+
201
+ /**
202
+ * Function for adding tabs
203
+ *
204
+ * @since 1.2.0
205
+ * @return void
206
+ */
207
+ public function hfe_tabs() {
208
+ ?>
209
+ <h2 class="nav-tab-wrapper">
210
+ <?php
211
+ $tabs = [
212
+ 'hfe_templates' => [
213
+ 'name' => __( 'All templates', 'header-footer-elementor' ),
214
+ 'url' => admin_url( 'edit.php?post_type=elementor-hf' ),
215
+ ],
216
+ 'hfe_settings' => [
217
+ 'name' => __( 'Theme Support', 'header-footer-elementor' ),
218
+ 'url' => admin_url( 'themes.php?page=hfe-settings' ),
219
+ ],
220
+ ];
221
+ $active_tab = 'hfe-settings' == isset( $_GET['page'] ) && $_GET['page'] ? 'hfe_settings' : 'hfe_templates';
222
+ foreach ( $tabs as $tab_id => $tab ) {
223
+ $active = $active_tab == $tab_id ? ' nav-tab-active' : '';
224
+
225
+ echo '<a href="' . esc_url( $tab['url'] ) . '" class="nav-tab' . esc_attr( $active ) . '">';
226
+ echo esc_html( $tab['name'] );
227
+ echo '</a>';
228
+ }
229
+
230
+ ?>
231
+ </h2>
232
+ <br />
233
+ <?php
234
+ }
235
+
236
+ }
237
+
238
+ new HFE_Fallback_Theme_Support();
themes/default/hfe-footer.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Footer file in case of the elementor way
4
+ *
5
+ * @package header-footer-elementor
6
+ * @since 1.2.0
7
+ */
8
+
9
+ ?>
10
+
11
+ <?php do_action( 'hfe_footer_before' ); ?>
12
+ <?php do_action( 'hfe_footer' ); ?>
13
+ <?php wp_footer(); ?>
14
+ </body>
15
+ </html>
themes/default/hfe-header.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Header file in case of the elementor way
4
+ *
5
+ * @package header-footer-elementor
6
+ * @since 1.2.0
7
+ */
8
+
9
+ ?><!DOCTYPE html>
10
+ <html <?php language_attributes(); ?>>
11
+ <head>
12
+ <meta charset="<?php bloginfo( 'charset' ); ?>" />
13
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
14
+ <link rel="profile" href="http://gmpg.org/xfn/11" />
15
+ <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>" />
16
+ <?php wp_head(); ?>
17
+ </head>
18
+
19
+ <body <?php body_class(); ?>>
20
+ <?php do_action( 'wp_body_open' ); ?>
21
+ <div id="page" class="hfeed site">
22
+
23
+ <?php do_action( 'hfe_header' ); ?>
themes/generatepress/class-hfe-generatepress-compat.php CHANGED
@@ -23,11 +23,10 @@ class HFE_GeneratePress_Compat {
23
  * Initiator
24
  */
25
  public static function instance() {
26
-
27
  if ( ! isset( self::$instance ) ) {
28
  self::$instance = new HFE_GeneratePress_Compat();
29
 
30
- add_action( 'wp', array( self::$instance, 'hooks' ) );
31
  }
32
 
33
  return self::$instance;
@@ -37,17 +36,19 @@ class HFE_GeneratePress_Compat {
37
  * Run all the Actions / Filters.
38
  */
39
  public function hooks() {
40
-
41
  if ( hfe_header_enabled() ) {
42
- add_action( 'template_redirect', array( $this, 'generatepress_setup_header' ) );
43
  add_action( 'generate_header', 'hfe_render_header' );
44
  }
45
 
 
 
 
 
46
  if ( hfe_footer_enabled() ) {
47
- add_action( 'template_redirect', array( $this, 'generatepress_setup_footer' ) );
48
  add_action( 'generate_footer', 'hfe_render_footer' );
49
  }
50
-
51
  }
52
 
53
  /**
23
  * Initiator
24
  */
25
  public static function instance() {
 
26
  if ( ! isset( self::$instance ) ) {
27
  self::$instance = new HFE_GeneratePress_Compat();
28
 
29
+ add_action( 'wp', [ self::$instance, 'hooks' ] );
30
  }
31
 
32
  return self::$instance;
36
  * Run all the Actions / Filters.
37
  */
38
  public function hooks() {
 
39
  if ( hfe_header_enabled() ) {
40
+ add_action( 'template_redirect', [ $this, 'generatepress_setup_header' ] );
41
  add_action( 'generate_header', 'hfe_render_header' );
42
  }
43
 
44
+ if ( hfe_is_before_footer_enabled() ) {
45
+ add_action( 'generate_footer', [ 'Header_Footer_Elementor', 'get_before_footer_content' ], 5 );
46
+ }
47
+
48
  if ( hfe_footer_enabled() ) {
49
+ add_action( 'template_redirect', [ $this, 'generatepress_setup_footer' ] );
50
  add_action( 'generate_footer', 'hfe_render_footer' );
51
  }
 
52
  }
53
 
54
  /**
themes/genesis/class-hfe-genesis-compat.php CHANGED
@@ -21,11 +21,10 @@ class HFE_Genesis_Compat {
21
  * Initiator
22
  */
23
  public static function instance() {
24
-
25
  if ( ! isset( self::$instance ) ) {
26
  self::$instance = new HFE_Genesis_Compat();
27
 
28
- add_action( 'wp', array( self::$instance, 'hooks' ) );
29
  }
30
 
31
  return self::$instance;
@@ -35,106 +34,96 @@ class HFE_Genesis_Compat {
35
  * Run all the Actions / Filters.
36
  */
37
  public function hooks() {
38
-
39
  if ( hfe_header_enabled() ) {
40
- add_action( 'template_redirect', array( $this, 'genesis_setup_header' ) );
41
- add_action( 'genesis_header', array( $this, 'genesis_header_markup_open' ), 16 );
42
- add_action( 'genesis_header', array( $this, 'genesis_header_markup_close' ), 25 );
43
- add_action( 'genesis_header', array( 'Header_Footer_Elementor', 'get_header_content' ), 16 );
44
  }
45
 
46
- if ( hfe_footer_enabled() ) {
47
- add_action( 'template_redirect', array( $this, 'genesis_setup_footer' ) );
48
- add_action( 'genesis_footer', array( $this, 'genesis_footer_markup_open' ), 16 );
49
- add_action( 'genesis_footer', array( $this, 'genesis_footer_markup_close' ), 25 );
50
- add_action( 'genesis_footer', array( 'Header_Footer_Elementor', 'get_footer_content' ), 16 );
51
  }
52
 
 
 
 
 
 
 
53
  }
54
 
55
  /**
56
  * Disable header from the theme.
57
  */
58
  public function genesis_setup_header() {
59
-
60
  for ( $priority = 0; $priority < 16; $priority ++ ) {
61
  remove_all_actions( 'genesis_header', $priority );
62
  }
63
-
64
  }
65
 
66
  /**
67
  * Disable footer from the theme.
68
  */
69
  public function genesis_setup_footer() {
70
-
71
  for ( $priority = 0; $priority < 16; $priority ++ ) {
72
  remove_all_actions( 'genesis_footer', $priority );
73
  }
74
-
75
  }
76
 
77
  /**
78
  * Open markup for header.
79
  */
80
  public function genesis_header_markup_open() {
81
-
82
  genesis_markup(
83
- array(
84
  'html5' => '<header %s>',
85
  'xhtml' => '<div id="header">',
86
  'context' => 'site-header',
87
- )
88
  );
89
 
90
  genesis_structural_wrap( 'header' );
91
-
92
  }
93
 
94
  /**
95
  * Close MArkup for header.
96
  */
97
  public function genesis_header_markup_close() {
98
-
99
  genesis_structural_wrap( 'header', 'close' );
100
  genesis_markup(
101
- array(
102
  'html5' => '</header>',
103
  'xhtml' => '</div>',
104
- )
105
  );
106
-
107
  }
108
 
109
  /**
110
  * Open markup for footer.
111
  */
112
  public function genesis_footer_markup_open() {
113
-
114
  genesis_markup(
115
- array(
116
  'html5' => '<footer %s>',
117
  'xhtml' => '<div id="footer" class="footer">',
118
  'context' => 'site-footer',
119
- )
120
  );
121
  genesis_structural_wrap( 'footer', 'open' );
122
-
123
  }
124
 
125
  /**
126
  * Close markup for footer.
127
  */
128
  public function genesis_footer_markup_close() {
129
-
130
  genesis_structural_wrap( 'footer', 'close' );
131
  genesis_markup(
132
- array(
133
  'html5' => '</footer>',
134
  'xhtml' => '</div>',
135
- )
136
  );
137
-
138
  }
139
 
140
 
21
  * Initiator
22
  */
23
  public static function instance() {
 
24
  if ( ! isset( self::$instance ) ) {
25
  self::$instance = new HFE_Genesis_Compat();
26
 
27
+ add_action( 'wp', [ self::$instance, 'hooks' ] );
28
  }
29
 
30
  return self::$instance;
34
  * Run all the Actions / Filters.
35
  */
36
  public function hooks() {
 
37
  if ( hfe_header_enabled() ) {
38
+ add_action( 'template_redirect', [ $this, 'genesis_setup_header' ] );
39
+ add_action( 'genesis_header', [ $this, 'genesis_header_markup_open' ], 16 );
40
+ add_action( 'genesis_header', [ $this, 'genesis_header_markup_close' ], 25 );
41
+ add_action( 'genesis_header', [ 'Header_Footer_Elementor', 'get_header_content' ], 16 );
42
  }
43
 
44
+ if ( hfe_is_before_footer_enabled() ) {
45
+ add_action( 'genesis_footer', [ 'Header_Footer_Elementor', 'get_before_footer_content' ], 16 );
 
 
 
46
  }
47
 
48
+ if ( hfe_footer_enabled() ) {
49
+ add_action( 'template_redirect', [ $this, 'genesis_setup_footer' ] );
50
+ add_action( 'genesis_footer', [ $this, 'genesis_footer_markup_open' ], 16 );
51
+ add_action( 'genesis_footer', [ $this, 'genesis_footer_markup_close' ], 25 );
52
+ add_action( 'genesis_footer', [ 'Header_Footer_Elementor', 'get_footer_content' ], 16 );
53
+ }
54
  }
55
 
56
  /**
57
  * Disable header from the theme.
58
  */
59
  public function genesis_setup_header() {
 
60
  for ( $priority = 0; $priority < 16; $priority ++ ) {
61
  remove_all_actions( 'genesis_header', $priority );
62
  }
 
63
  }
64
 
65
  /**
66
  * Disable footer from the theme.
67
  */
68
  public function genesis_setup_footer() {
 
69
  for ( $priority = 0; $priority < 16; $priority ++ ) {
70
  remove_all_actions( 'genesis_footer', $priority );
71
  }
 
72
  }
73
 
74
  /**
75
  * Open markup for header.
76
  */
77
  public function genesis_header_markup_open() {
 
78
  genesis_markup(
79
+ [
80
  'html5' => '<header %s>',
81
  'xhtml' => '<div id="header">',
82
  'context' => 'site-header',
83
+ ]
84
  );
85
 
86
  genesis_structural_wrap( 'header' );
 
87
  }
88
 
89
  /**
90
  * Close MArkup for header.
91
  */
92
  public function genesis_header_markup_close() {
 
93
  genesis_structural_wrap( 'header', 'close' );
94
  genesis_markup(
95
+ [
96
  'html5' => '</header>',
97
  'xhtml' => '</div>',
98
+ ]
99
  );
 
100
  }
101
 
102
  /**
103
  * Open markup for footer.
104
  */
105
  public function genesis_footer_markup_open() {
 
106
  genesis_markup(
107
+ [
108
  'html5' => '<footer %s>',
109
  'xhtml' => '<div id="footer" class="footer">',
110
  'context' => 'site-footer',
111
+ ]
112
  );
113
  genesis_structural_wrap( 'footer', 'open' );
 
114
  }
115
 
116
  /**
117
  * Close markup for footer.
118
  */
119
  public function genesis_footer_markup_close() {
 
120
  genesis_structural_wrap( 'footer', 'close' );
121
  genesis_markup(
122
+ [
123
  'html5' => '</footer>',
124
  'xhtml' => '</div>',
125
+ ]
126
  );
 
127
  }
128
 
129
 
themes/oceanwp/class-hfe-oceanwp-compat.php CHANGED
@@ -21,11 +21,10 @@ class HFE_OceanWP_Compat {
21
  * Initiator
22
  */
23
  public static function instance() {
24
-
25
  if ( ! isset( self::$instance ) ) {
26
  self::$instance = new HFE_OceanWP_Compat();
27
 
28
- add_action( 'wp', array( self::$instance, 'hooks' ) );
29
  }
30
 
31
  return self::$instance;
@@ -35,17 +34,19 @@ class HFE_OceanWP_Compat {
35
  * Run all the Actions / Filters.
36
  */
37
  public function hooks() {
38
-
39
  if ( hfe_header_enabled() ) {
40
- add_action( 'template_redirect', array( $this, 'setup_header' ), 10 );
41
  add_action( 'ocean_header', 'hfe_render_header' );
42
  }
43
 
 
 
 
 
44
  if ( hfe_footer_enabled() ) {
45
- add_action( 'template_redirect', array( $this, 'setup_footer' ), 10 );
46
  add_action( 'ocean_footer', 'hfe_render_footer' );
47
  }
48
-
49
  }
50
 
51
  /**
21
  * Initiator
22
  */
23
  public static function instance() {
 
24
  if ( ! isset( self::$instance ) ) {
25
  self::$instance = new HFE_OceanWP_Compat();
26
 
27
+ add_action( 'wp', [ self::$instance, 'hooks' ] );
28
  }
29
 
30
  return self::$instance;
34
  * Run all the Actions / Filters.
35
  */
36
  public function hooks() {
 
37
  if ( hfe_header_enabled() ) {
38
+ add_action( 'template_redirect', [ $this, 'setup_header' ], 10 );
39
  add_action( 'ocean_header', 'hfe_render_header' );
40
  }
41
 
42
+ if ( hfe_is_before_footer_enabled() ) {
43
+ add_action( 'ocean_footer', [ 'Header_Footer_Elementor', 'get_before_footer_content' ], 5 );
44
+ }
45
+
46
  if ( hfe_footer_enabled() ) {
47
+ add_action( 'template_redirect', [ $this, 'setup_footer' ], 10 );
48
  add_action( 'ocean_footer', 'hfe_render_footer' );
49
  }
 
50
  }
51
 
52
  /**
themes/storefront/class-hfe-storefront-compat.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * HFE_Storefront_Compat setup
4
+ *
5
+ * @package header-footer-elementor
6
+ */
7
+
8
+ /**
9
+ * Astra theme compatibility.
10
+ */
11
+ class HFE_Storefront_Compat {
12
+
13
+ /**
14
+ * Instance of HFE_Storefront_Compat.
15
+ *
16
+ * @var HFE_Storefront_Compat
17
+ */
18
+ private static $instance;
19
+
20
+ /**
21
+ * Initiator
22
+ */
23
+ public static function instance() {
24
+ if ( ! isset( self::$instance ) ) {
25
+ self::$instance = new HFE_Storefront_Compat();
26
+
27
+ add_action( 'wp', [ self::$instance, 'hooks' ] );
28
+ }
29
+
30
+ return self::$instance;
31
+ }
32
+
33
+ /**
34
+ * Run all the Actions / Filters.
35
+ */
36
+ public function hooks() {
37
+ if ( hfe_header_enabled() ) {
38
+ add_action( 'template_redirect', [ $this, 'setup_header' ], 10 );
39
+ add_action( 'storefront_before_header', 'hfe_render_header', 500 );
40
+ }
41
+
42
+ if ( hfe_footer_enabled() ) {
43
+ add_action( 'template_redirect', [ $this, 'setup_footer' ], 10 );
44
+ add_action( 'storefront_after_footer', 'hfe_render_footer', 500 );
45
+ }
46
+
47
+ if ( hfe_is_before_footer_enabled() ) {
48
+ add_action( 'storefront_before_footer', 'hfe_render_before_footer' );
49
+ }
50
+
51
+ if ( hfe_header_enabled() || hfe_footer_enabled() ) {
52
+ add_action( 'wp_enqueue_scripts', [ $this, 'styles' ] );
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Add inline CSS to hide empty divs for header and footer in storefront
58
+ *
59
+ * @since 1.2.0
60
+ * @return void
61
+ */
62
+ public function styles() {
63
+ $css = '';
64
+
65
+ if ( true === hfe_header_enabled() ) {
66
+ $css .= '.site-header {
67
+ display: none;
68
+ }';
69
+ }
70
+
71
+ if ( true === hfe_footer_enabled() ) {
72
+ $css .= '.site-footer {
73
+ display: none;
74
+ }';
75
+ }
76
+
77
+ wp_add_inline_style( 'hfe-style', $css );
78
+ }
79
+
80
+ /**
81
+ * Disable header from the theme.
82
+ */
83
+ public function setup_header() {
84
+ for ( $priority = 0; $priority < 200; $priority ++ ) {
85
+ remove_all_actions( 'storefront_header', $priority );
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Disable footer from the theme.
91
+ */
92
+ public function setup_footer() {
93
+ for ( $priority = 0; $priority < 200; $priority ++ ) {
94
+ remove_all_actions( 'storefront_footer', $priority );
95
+ }
96
+ }
97
+
98
+ }
99
+
100
+ HFE_Storefront_Compat::instance();