PluginProbe
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder / 3.6.0
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder v3.6.0
3.6.0 3.5.0 trunk 1.0.10 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.6.1 1.0.7 1.0.8 1.0.9 1.1 1.1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5 1.5.1 All 110 releases
← All changes | freemius/templates/add-ons.php +493 -165 1.13.6.0 View file →
@@ -1,165 +1,493 @@
1 -<?php
2 - /**
3 - * @package Freemius
4 - * @copyright Copyright (c) 2015, Freemius, Inc.
5 - * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
6 - * @since 1.0.3
7 - */
8 -
9 - if ( ! defined( 'ABSPATH' ) ) {
10 - exit;
11 - }
12 -
13 - /**
14 - * @var array $VARS
15 - */
16 - $slug = $VARS['slug'];
17 - /**
18 - * @var Freemius
19 - */
20 - $fs = freemius( $slug );
21 -
22 - $open_addon_slug = fs_request_get( 'slug' );
23 -
24 - $open_addon = false;
25 -
26 - /**
27 - * @var FS_Plugin[]
28 - */
29 - $addons = $fs->get_addons();
30 -
31 - $has_addons = ( is_array( $addons ) && 0 < count( $addons ) );
32 -?>
33 - <div id="fs_addons" class="wrap">
34 - <h2><?php printf( fs_text( 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ?></h2>
35 -
36 - <div id="poststuff">
37 - <?php if ( ! $has_addons ) : ?>
38 - <h3><?php printf(
39 - '%s... %s',
40 - fs_text( 'oops', $slug ),
41 - fs_text( 'add-ons-missing', $slug )
42 - ) ?></h3>
43 - <?php endif ?>
44 - <ul class="fs-cards-list">
45 - <?php if ( $has_addons ) : ?>
46 - <?php foreach ( $addons as $addon ) : ?>
47 - <?php
48 - $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) );
49 -
50 - $price = 0;
51 - $plan = null;
52 - $plans_result = $fs->get_api_site_or_plugin_scope()->get( "/addons/{$addon->id}/plans.json" );
53 - if ( ! isset( $plans_result->error ) ) {
54 - $plans = $plans_result->plans;
55 - if ( is_array( $plans ) && 0 < count( $plans ) ) {
56 - $plan = new FS_Plugin_Plan( $plans[0] );
57 - $pricing_result = $fs->get_api_site_or_plugin_scope()->get( "/addons/{$addon->id}/plans/{$plan->id}/pricing.json" );
58 - if ( ! isset( $pricing_result->error ) ) {
59 - // Update plan's pricing.
60 - $plan->pricing = $pricing_result->pricing;
61 -
62 - if ( is_array( $plan->pricing ) && 0 < count( $plan->pricing ) ) {
63 - $min_price = 999999;
64 - foreach ( $plan->pricing as $pricing ) {
65 - if ( ! is_null( $pricing->annual_price ) && $pricing->annual_price > 0 ) {
66 - $min_price = min( $min_price, $pricing->annual_price );
67 - } else if ( ! is_null( $pricing->monthly_price ) && $pricing->monthly_price > 0 ) {
68 - $min_price = min( $min_price, 12 * $pricing->monthly_price );
69 - }
70 - }
71 -
72 - if ( $min_price < 999999 ) {
73 - $price = $min_price;
74 - }
75 - }
76 - }
77 - }
78 - }
79 - ?>
80 - <li class="fs-card fs-addon" data-slug="<?php echo $addon->slug ?>">
81 - <?php
82 - echo sprintf( '<a href="%s" class="thickbox fs-overlay" aria-label="%s" data-title="%s"></a>',
83 - esc_url( network_admin_url( 'plugin-install.php?tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug .
84 - '&TB_iframe=true&width=600&height=550' ) ),
85 - esc_attr( sprintf( fs_text( 'more-information-about-x', $slug ), $addon->title ) ),
86 - esc_attr( $addon->title )
87 - );
88 - ?>
89 - <?php
90 - if ( is_null( $addon->info ) ) {
91 - $addon->info = new stdClass();
92 - }
93 - if ( ! isset( $addon->info->card_banner_url ) ) {
94 - $addon->info->card_banner_url = '//dashboard.freemius.com/assets/img/marketing/blueprint-300x100.jpg';
95 - }
96 - if ( ! isset( $addon->info->short_description ) ) {
97 - $addon->info->short_description = 'What\'s the one thing your add-on does really, really well?';
98 - }
99 - ?>
100 - <div class="fs-inner">
101 - <ul>
102 - <li class="fs-card-banner"
103 - style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"></li>
104 -<!-- <li class="fs-tag"></li>-->
105 - <li class="fs-title"><?php echo $addon->title ?></li>
106 - <li class="fs-offer">
107 - <span
108 - class="fs-price"><?php echo ( 0 == $price ) ? fs_text( 'free', $slug ) : ('$' . number_format( $price, 2 ) . ($plan->has_trial() ? ' - ' . fs_text('trial', $slug) : '')) ?></span>
109 - </li>
110 - <li class="fs-description"><?php echo ! empty( $addon->info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?></li>
111 - <li class="fs-cta"><a class="button"><?php fs_echo( 'view-details', $slug ) ?></a></li>
112 - </ul>
113 - </div>
114 - </li>
115 - <?php endforeach ?>
116 - <?php endif ?>
117 - </ul>
118 - </div>
119 - </div>
120 - <script type="text/javascript">
121 - (function ($) {
122 - <?php if ( $open_addon ) : ?>
123 -
124 - var interval = setInterval(function () {
125 - // Open add-on information page.
126 - <?php
127 - /**
128 - * @author Vova Feldman
129 - *
130 - * This code does NOT expose an XSS vulnerability because:
131 - * 1. This page only renders for admins, so if an attacker manage to get
132 - * admin access, they can do more harm.
133 - * 2. This code won't be rendered unless $open_addon_slug matches any of
134 - * the plugin's add-ons slugs.
135 - */
136 - ?>
137 - $('.fs-card[data-slug=<?php echo $open_addon_slug ?>] a').click();
138 - if ($('#TB_iframeContent').length > 0) {
139 - clearInterval(interval);
140 - interval = null;
141 - }
142 - }, 200);
143 -
144 - <?php else : ?>
145 -
146 -
147 - $('.fs-card.fs-addon')
148 - .mouseover(function () {
149 - $(this).find('.fs-cta .button').addClass('button-primary');
150 - }).mouseout(function () {
151 - $(this).find('.fs-cta .button').removeClass('button-primary');
152 - });
153 -
154 - <?php endif ?>
155 - })(jQuery);
156 - </script>
157 -<?php
158 - $params = array(
159 - 'page' => 'addons',
160 - 'module_id' => $fs->get_id(),
161 - 'module_slug' => $slug,
162 - 'module_version' => $fs->get_plugin_version(),
163 - );
164 - fs_require_template( 'powered-by.php', $params );
165 -?>
1 +<?php
2 + /**
3 + * @package Freemius
4 + * @copyright Copyright (c) 2015, Freemius, Inc.
5 + * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 + * @since 1.0.3
7 + */
8 +
9 + if ( ! defined( 'ABSPATH' ) ) {
10 + exit;
11 + }
12 +
13 + /**
14 + * @var array $VARS
15 + * @var Freemius
16 + */
17 + $fs = freemius( $VARS['id'] );
18 +
19 + $slug = $fs->get_slug();
20 +
21 + $open_addon_slug = fs_request_get( 'slug' );
22 +
23 + $open_addon = false;
24 +
25 + $is_data_debug_mode = $fs->is_data_debug_mode();
26 + $is_whitelabeled = $fs->is_whitelabeled();
27 +
28 + /**
29 + * @var FS_Plugin[]
30 + */
31 + $addons = $fs->get_addons();
32 +
33 + $has_addons = ( is_array( $addons ) && 0 < count( $addons ) );
34 +
35 + $account_addon_ids = $fs->get_updated_account_addons();
36 +
37 + $download_latest_text = fs_text_x_inline( 'Download Latest', 'as download latest version', 'download-latest', $slug );
38 + $view_details_text = fs_text_inline( 'View details', 'view-details', $slug );
39 +
40 + $has_tabs = $fs->_add_tabs_before_content();
41 +
42 + $fs_blog_id = ( is_multisite() && ! is_network_admin() ) ?
43 + get_current_blog_id() :
44 + 0;
45 +?>
46 + <div id="fs_addons" class="wrap fs-section">
47 + <?php if ( ! $has_tabs ) : ?>
48 + <h2><?php echo esc_html( sprintf( fs_text_inline( 'Add Ons for %s', 'add-ons-for-x', $slug ), $fs->get_plugin_name() ) ) ?></h2>
49 + <?php endif ?>
50 +
51 + <?php $fs->do_action( 'addons/after_title' ) ?>
52 +
53 + <div id="poststuff">
54 + <?php if ( ! $has_addons ) : ?>
55 + <h3><?php echo esc_html( sprintf(
56 + '%s... %s',
57 + fs_text_x_inline( 'Oops', 'exclamation', 'oops', $slug ),
58 + fs_text_inline( 'We couldn\'t load the add-ons list. It\'s probably an issue on our side, please try to come back in few minutes.', 'add-ons-missing', $slug )
59 + ) ) ?></h3>
60 + <?php endif ?>
61 + <ul class="fs-cards-list">
62 + <?php if ( $has_addons ) : ?>
63 + <?php
64 + $plans_and_pricing_by_addon_id = $fs->_get_addons_plans_and_pricing_map_by_id();
65 +
66 + $active_plugins_directories_map = Freemius::get_active_plugins_directories_map( $fs_blog_id );
67 + ?>
68 + <?php
69 + $hide_all_addons_data = false;
70 +
71 + if ( $fs->is_whitelabeled_by_flag() ) {
72 + $hide_all_addons_data = true;
73 +
74 + $addon_ids = $fs->get_updated_account_addons();
75 + $installed_addons = $fs->get_installed_addons();
76 + foreach ( $installed_addons as $fs_addon ) {
77 + $addon_ids[] = $fs_addon->get_id();
78 + }
79 +
80 + if ( ! empty( $addon_ids ) ) {
81 + $addon_ids = array_unique( $addon_ids );
82 + }
83 +
84 + foreach ( $addon_ids as $addon_id ) {
85 + $addon = $fs->get_addon( $addon_id );
86 +
87 + if ( ! is_object( $addon ) ) {
88 + continue;
89 + }
90 +
91 + $addon_storage = FS_Storage::instance( WP_FS__MODULE_TYPE_PLUGIN, $addon->slug );
92 +
93 + if ( ! $addon_storage->is_whitelabeled ) {
94 + $hide_all_addons_data = false;
95 + break;
96 + }
97 +
98 + if ( $is_data_debug_mode ) {
99 + $is_whitelabeled = false;
100 + }
101 + }
102 + }
103 + ?>
104 + <?php foreach ( $addons as $addon ) : ?>
105 + <?php
106 + $basename = $fs->get_addon_basename( $addon->id );
107 +
108 + $is_addon_installed = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $basename ) );
109 +
110 + if ( ! $is_addon_installed && $hide_all_addons_data ) {
111 + continue;
112 + }
113 +
114 + $is_addon_activated = $is_addon_installed ?
115 + $fs->is_addon_activated( $addon->id ) :
116 + false;
117 +
118 + $is_plugin_active = (
119 + $is_addon_activated ||
120 + isset( $active_plugins_directories_map[ dirname( $basename ) ] )
121 + );
122 +
123 + $open_addon = ( $open_addon || ( $open_addon_slug === $addon->slug ) );
124 +
125 + $price = 0;
126 + $has_trial = false;
127 + $has_free_plan = false;
128 + $has_paid_plan = false;
129 +
130 + if ( isset( $plans_and_pricing_by_addon_id[$addon->id] ) ) {
131 + $plans = $plans_and_pricing_by_addon_id[$addon->id];
132 +
133 + if ( is_array( $plans ) && 0 < count( $plans ) ) {
134 + foreach ( $plans as $plan ) {
135 + if ( ! isset( $plan->pricing ) ||
136 + ! is_array( $plan->pricing ) ||
137 + 0 == count( $plan->pricing )
138 + ) {
139 + // No pricing means a free plan.
140 + $has_free_plan = true;
141 + continue;
142 + }
143 +
144 +
145 + $has_paid_plan = true;
146 + $has_trial = $has_trial || ( is_numeric( $plan->trial_period ) && ( $plan->trial_period > 0 ) );
147 +
148 + $min_price = 999999;
149 + foreach ( $plan->pricing as $pricing ) {
150 + $pricing = new FS_Pricing( $pricing );
151 +
152 + if ( ! $pricing->is_usd() ) {
153 + /**
154 + * Skip non-USD pricing.
155 + *
156 + * @author Leo Fajardo (@leorw)
157 + * @since 2.3.1
158 + */
159 + continue;
160 + }
161 +
162 + if ( $pricing->has_annual() ) {
163 + $min_price = min( $min_price, $pricing->annual_price );
164 + } else if ( $pricing->has_monthly() ) {
165 + $min_price = min( $min_price, 12 * $pricing->monthly_price );
166 + }
167 + }
168 +
169 + if ( $min_price < 999999 ) {
170 + $price = $min_price;
171 + }
172 +
173 + }
174 + }
175 +
176 + if ( ! $has_paid_plan && ! $has_free_plan ) {
177 + continue;
178 + }
179 + }
180 + ?>
181 + <li class="fs-card fs-addon" data-slug="<?php echo $addon->slug ?>">
182 + <?php
183 + $view_details_link = sprintf( '<a href="%s" aria-label="%s" data-title="%s"',
184 + esc_url( network_admin_url( 'plugin-install.php?fs_allow_updater_and_dialog=true' . ( ! empty( $fs_blog_id ) ? '&fs_blog_id=' . $fs_blog_id : '' ) . '&tab=plugin-information&parent_plugin_id=' . $fs->get_id() . '&plugin=' . $addon->slug .
185 + '&TB_iframe=true&width=600&height=550' ) ),
186 + esc_attr( sprintf( fs_text_inline( 'More information about %s', 'more-information-about-x', $slug ), $addon->title ) ),
187 + esc_attr( $addon->title )
188 + ) . ' class="thickbox%s">%s</a>';
189 +
190 + echo sprintf(
191 + $view_details_link,
192 + /**
193 + * Additional class.
194 + *
195 + * @author Leo Fajardo (@leorw)
196 + * @since 2.2.4
197 + */
198 + ' fs-overlay',
199 + /**
200 + * Set the view details link text to an empty string since it is an overlay that
201 + * doesn't really need a text and whose purpose is to open the details dialog when
202 + * the card is clicked.
203 + *
204 + * @author Leo Fajardo (@leorw)
205 + * @since 2.2.4
206 + */
207 + ''
208 + );
209 + ?>
210 + <?php
211 + if ( is_null( $addon->info ) ) {
212 + $addon->info = new stdClass();
213 + }
214 + if ( ! isset( $addon->info->card_banner_url ) ) {
215 + $addon->info->card_banner_url = '//dashboard.freemius.com/assets/img/marketing/blueprint-300x100.jpg';
216 + }
217 + if ( ! isset( $addon->info->short_description ) ) {
218 + $addon->info->short_description = 'What\'s the one thing your add-on does really, really well?';
219 + }
220 + ?>
221 + <div class="fs-inner">
222 + <ul>
223 + <li class="fs-card-banner"
224 + style="background-image: url('<?php echo $addon->info->card_banner_url ?>');"><?php
225 + if ( $is_plugin_active || $is_addon_installed ) {
226 + echo sprintf(
227 + '<span class="fs-badge fs-installed-addon-badge">%s</span>',
228 + esc_html( $is_plugin_active ?
229 + fs_text_x_inline( 'Active', 'active add-on', 'active-addon', $slug ) :
230 + fs_text_x_inline( 'Installed', 'installed add-on', 'installed-addon', $slug )
231 + )
232 + );
233 + }
234 + ?></li>
235 + <!-- <li class="fs-tag"></li> -->
236 + <li class="fs-title"><?php echo $addon->title ?></li>
237 + <li class="fs-offer">
238 + <span
239 + class="fs-price"><?php
240 + if ( $is_whitelabeled ) {
241 + echo '&nbsp;';
242 + } else {
243 + $descriptors = array();
244 +
245 + if ($has_free_plan)
246 + $descriptors[] = fs_text_inline( 'Free', 'free', $slug );
247 + if ($has_paid_plan && $price > 0)
248 + $descriptors[] = '$' . number_format( $price, 2 );
249 + if ($has_trial)
250 + $descriptors[] = fs_text_x_inline( 'Trial', 'trial period', 'trial', $slug );
251 +
252 + echo implode(' - ', $descriptors);
253 +
254 + } ?></span>
255 + </li>
256 + <li class="fs-description"><?php echo ! empty( $addon->info->short_description ) ? $addon->info->short_description : 'SHORT DESCRIPTION' ?></li>
257 + <?php
258 + $is_free_only_wp_org_compliant = ( ! $has_paid_plan && $addon->is_wp_org_compliant );
259 +
260 + $is_allowed_to_install = (
261 + $fs->is_allowed_to_install() ||
262 + $is_free_only_wp_org_compliant
263 + );
264 +
265 + $show_premium_activation_or_installation_action = true;
266 +
267 + if ( ! in_array( $addon->id, $account_addon_ids ) ) {
268 + $show_premium_activation_or_installation_action = false;
269 + } else if ( $is_addon_installed ) {
270 + /**
271 + * If any add-on's version (free or premium) is installed, check if the
272 + * premium version can be activated and show the relevant action. Otherwise,
273 + * show the relevant action for the free version.
274 + *
275 + * @author Leo Fajardo (@leorw)
276 + * @since 2.4.5
277 + */
278 + $fs_addon = $is_addon_activated ?
279 + $fs->get_addon_instance( $addon->id ) :
280 + null;
281 +
282 + $premium_plugin_basename = is_object( $fs_addon ) ?
283 + $fs_addon->premium_plugin_basename() :
284 + "{$addon->premium_slug}/{$addon->slug}.php";
285 +
286 + if (
287 + ( $is_addon_activated && $fs_addon->is_premium() ) ||
288 + file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $premium_plugin_basename ) )
289 + ) {
290 + $basename = $premium_plugin_basename;
291 + }
292 +
293 + $show_premium_activation_or_installation_action = (
294 + ( ! $is_addon_activated || ! $fs_addon->is_premium() ) &&
295 + /**
296 + * This check is needed for cases when an active add-on doesn't have an
297 + * associated Freemius instance.
298 + *
299 + * @author Leo Fajardo (@leorw)
300 + * @since 2.4.5
301 + */
302 + ( ! $is_plugin_active )
303 + );
304 + }
305 + ?>
306 + <?php if ( ! $show_premium_activation_or_installation_action ) : ?>
307 + <li class="fs-cta"><a class="button"><?php echo esc_html( $view_details_text ) ?></a></li>
308 + <?php else : ?>
309 + <?php
310 + $latest_download_local_url = $is_free_only_wp_org_compliant ?
311 + null :
312 + $fs->_get_latest_download_local_url( $addon->id );
313 + ?>
314 +
315 + <li class="fs-cta fs-dropdown">
316 + <div class="button-group">
317 + <?php if ( $is_allowed_to_install ) : ?>
318 + <?php
319 + if ( ! $is_addon_installed ) {
320 + echo sprintf(
321 + '<a class="button button-primary" href="%s">%s</a>',
322 + wp_nonce_url( self_admin_url( 'update.php?' . ( ( $has_paid_plan || ! $addon->is_wp_org_compliant ) ? 'fs_allow_updater_and_dialog=true&' : '' ) . 'action=install-plugin&plugin=' . $addon->slug ), 'install-plugin_' . $addon->slug ),
323 + fs_esc_html_inline( 'Install Now', 'install-now', $slug )
324 + );
325 + } else {
326 + echo sprintf(
327 + '<a class="button button-primary edit" href="%s" title="%s" target="_parent">%s</a>',
328 + wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . $basename, 'activate-plugin_' . $basename ),
329 + fs_esc_attr_inline( 'Activate this add-on', 'activate-this-addon', $addon->slug ),
330 + fs_text_inline( 'Activate', 'activate', $addon->slug )
331 + );
332 + }
333 + ?>
334 + <?php else : ?>
335 + <a target="_blank" rel="noopener" class="button button-primary" href="<?php echo $latest_download_local_url ?>"><?php echo esc_html( $download_latest_text ) ?></a>
336 + <?php endif ?>
337 + <div class="button button-primary fs-dropdown-arrow-button"><span class="fs-dropdown-arrow"></span><ul class="fs-dropdown-list" style="display: none">
338 + <?php if ( $is_allowed_to_install && ! empty( $latest_download_local_url ) ) : ?>
339 + <li><a target="_blank" rel="noopener" href="<?php echo $latest_download_local_url ?>"><?php echo esc_html( $download_latest_text ) ?></a></li>
340 + <?php endif ?>
341 + <li><?php
342 + echo sprintf(
343 + $view_details_link,
344 + /**
345 + * No additional class.
346 + *
347 + * @author Leo Fajardo (@leorw)
348 + * @since 2.2.4
349 + */
350 + '',
351 + /**
352 + * Set the view details link text to a non-empty string since it is an
353 + * item in the dropdown list and the text should be visible.
354 + *
355 + * @author Leo Fajardo (@leorw)
356 + * @since 2.2.4
357 + */
358 + esc_html( $view_details_text )
359 + );
360 + ?></li>
361 + </ul></div>
362 + </div>
363 + </li>
364 + <?php endif ?>
365 + </ul>
366 + </div>
367 + </li>
368 + <?php endforeach ?>
369 + <?php endif ?>
370 + </ul>
371 + </div>
372 +
373 + <?php $fs->do_action( 'addons/after_addons' ) ?>
374 + </div>
375 + <script type="text/javascript">
376 + (function( $, undef ) {
377 + <?php if ( $open_addon ) : ?>
378 +
379 + var interval = setInterval(function () {
380 + // Open add-on information page.
381 + <?php
382 + /**
383 + * @author Vova Feldman
384 + *
385 + * This code does NOT expose an XSS vulnerability because:
386 + * 1. This page only renders for admins, so if an attacker manage to get
387 + * admin access, they can do more harm.
388 + * 2. This code won't be rendered unless $open_addon_slug matches any of
389 + * the plugin's add-ons slugs.
390 + */
391 + ?>
392 + $('.fs-card[data-slug=<?php echo $open_addon_slug ?>] a').click();
393 + if ($('#TB_iframeContent').length > 0) {
394 + clearInterval(interval);
395 + interval = null;
396 + }
397 + }, 200);
398 +
399 + <?php else : ?>
400 +
401 + $( '.fs-card.fs-addon' )
402 + .mouseover(function() {
403 + var $this = $( this );
404 +
405 + $this.find( '.fs-cta .button' ).addClass( 'button-primary' );
406 +
407 + if ( 0 === $this.find( '.fs-dropdown-arrow-button.active' ).length ) {
408 + /**
409 + * When hovering over a card, close the dropdown on any other card.
410 + *
411 + * @author Leo Fajardo (@leorw)
412 + * @since 2.2.4
413 + */
414 + toggleDropdown();
415 + }
416 + }).mouseout(function( evt ) {
417 + var $relatedTarget = $( evt.relatedTarget );
418 +
419 + if ( 0 !== $relatedTarget.parents( '.fs-addon' ).length ) {
420 + return true;
421 + }
422 +
423 + var $this = $( this );
424 +
425 + /**
426 + * Set the color of the "View details" button to "secondary".
427 + *
428 + * @author Leo Fajardo (@leorw)
429 + * @since 2.2.4
430 + */
431 + $this.find( '.fs-cta .button' ).filter(function() {
432 + /**
433 + * Keep the "primary" color of the dropdown arrow button, "Install Now" button, and
434 + * "Download Latest" button.
435 +
436 + * @author Leo Fajardo (@leorw)
437 + * @since 2.2.4
438 + */
439 + return $( this ).parent().is( ':not(.button-group)' );
440 + }).removeClass('button-primary');
441 +
442 + toggleDropdown( $this.find( '.fs-dropdown' ), false );
443 + }).find( 'a.thickbox, .button:not(.fs-dropdown-arrow-button)' ).click(function() {
444 + toggleDropdown();
445 + });
446 +
447 + <?php endif ?>
448 +
449 + var $dropdowns = $( '.fs-dropdown' );
450 + if ( 0 !== $dropdowns.length ) {
451 + $dropdowns.find( '.fs-dropdown-arrow-button' ).click(function() {
452 + var $this = $( this ),
453 + $dropdown = $this.parents( '.fs-dropdown' );
454 +
455 + toggleDropdown( $dropdown, ! $dropdown.hasClass( 'active' ) );
456 + });
457 + }
458 +
459 + /**
460 + * Returns the default state of the dropdown arrow button and hides the dropdown list.
461 + *
462 + * @author Leo Fajardo (@leorw)
463 + * @since 2.2.4
464 + *
465 + * @param {(Object|undefined)} [$dropdown]
466 + * @param {(Boolean|undefined)} [state]
467 + */
468 + function toggleDropdown( $dropdown, state ) {
469 + if ( undef === $dropdown ) {
470 + var $activeDropdown = $dropdowns.find( '.active' );
471 + if ( 0 !== $activeDropdown.length ) {
472 + $dropdown = $activeDropdown;
473 + }
474 + }
475 +
476 + if ( undef === $dropdown ) {
477 + return;
478 + }
479 +
480 + if ( undef === state ) {
481 + state = false;
482 + }
483 +
484 + $dropdown.toggleClass( 'active', state );
485 + $dropdown.find( '.fs-dropdown-list' ).toggle( state );
486 + $dropdown.find( '.fs-dropdown-arrow-button' ).toggleClass( 'active', state );
487 + }
488 + })( jQuery );
489 + </script>
490 +<?php
491 + if ( $has_tabs ) {
492 + $fs->_add_tabs_after_content();
493 + }