Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save xlplugins/0bbc0c9a17353670df58b96d0abb60fe to your computer and use it in GitHub Desktop.

Select an option

Save xlplugins/0bbc0c9a17353670df58b96d0abb60fe to your computer and use it in GitHub Desktop.
showing choose plan inside the plan selector
<?php
/**
* Plugin Name: Sublium Choose Plan Label (test)
* Description: Shows "Choose Plan" in the Sublium plan-selector trigger box and, when the Subscription option is active but no plan has been picked, blocks add-to-cart and shows a "Please select a subscription plan." message instead of silently disabling the button.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
add_action(
'wp_footer',
function () {
// Scope to the single product page only — not cart, checkout, or the
// FunnelKit slide cart, which also render Sublium's plan dropdown but
// should keep showing the real selected plan there.
if ( ! is_product() ) {
return;
}
$label = __( 'Choose Plan', 'sublium-subscriptions-for-woocommerce' );
$message = __( 'Please select a subscription plan.', 'sublium-subscriptions-for-woocommerce' );
?>
<script>
( function ( $ ) {
var subliumPlanUserSelected = false;
// Scope everything to the main product-page widget only. The
// FunnelKit slide cart can be opened while still on the product page
// (same URL, no navigation) and renders its own instance of the same
// .sublium-selected-option/.sublium-dropdown-options markup for the
// cart line item — that instance must keep showing the real plan.
var subliumWidgetSelector = '.sublium-front-widget-container';
var subliumMessageText = '<?php echo esc_js( $message ); ?>';
var subliumMessageClass = 'sublium-plan-required-message';
function subliumSubscriptionIsActive( $widget ) {
// The "Subscription" radio has id="sublium-plan-type-{type}"; a
// separate "One Time Purchase" radio (id="one-time") can also
// exist on products where it's enabled. Only treat a plan as
// required when a subscription-type option is the one currently
// checked — one-time purchase needs no plan selection at all.
var $checked = $widget.closest( 'form.cart' ).find( 'input[name="sublium-purchase-option"]:checked' );
return $checked.length > 0 && $checked.attr( 'id' ).indexOf( 'sublium-plan-type-' ) === 0;
}
// Create the inline validation message once and place it on its OWN
// full-width line immediately AFTER the .sublium-front-widget-container
// box closes — directly under the Subscribe / Choose Plan area, which
// is where the choice is actually made. It is inserted as a SIBLING of
// the widget (not inside it), so Sublium re-rendering the widget's
// internals never wipes the message. Inline styles keep it visible
// regardless of theme CSS, on mobile and desktop.
function subliumGetMessage( $widget ) {
// Deduped globally: the message lives outside the widget, so a
// widget-scoped lookup would miss it and stack duplicates per click.
var $msg = $( '.' + subliumMessageClass );
if ( ! $msg.length ) {
$msg = $( '<div></div>' )
.addClass( subliumMessageClass )
.attr( 'role', 'alert' )
.text( subliumMessageText )
.css( {
display: 'none',
color: '#d63638',
fontSize: '14px',
fontWeight: '600',
margin: '12px 0 0',
width: '100%',
flexBasis: '100%',
clear: 'both'
} );
$widget.after( $msg );
}
return $msg;
}
function subliumHideMessage() {
$( '.' + subliumMessageClass ).css( 'display', 'none' );
}
// Does the current state require a plan the customer has not chosen yet?
function subliumNeedsPlan( $widget ) {
return $widget.length > 0 && subliumSubscriptionIsActive( $widget ) && ! subliumPlanUserSelected;
}
function subliumApplyChoosePlanText() {
var $widget = $( subliumWidgetSelector );
if ( ! $widget.length ) {
return;
}
if ( subliumPlanUserSelected ) {
subliumHideMessage();
return;
}
// Show "Choose Plan" and hide the stale billing summary while no
// plan is chosen, regardless of which radio (One Time /
// Subscription) is currently active — a customer switching to
// Subscription later should see the placeholder immediately.
$widget.find( '.sublium-selected-option .sublium-selected-text' ).each( function () {
if ( $( this ).text() !== '<?php echo esc_js( $label ); ?>' ) {
$( this ).text( '<?php echo esc_js( $label ); ?>' );
}
} );
$widget.find( '.sublium-front-description' ).css( 'display', 'none' );
}
// Block the add and show the message. Shared by the click and submit
// interceptors so both the button and a plain form submit are covered.
function subliumBlockAndWarn( e, $widget ) {
e.preventDefault();
e.stopImmediatePropagation();
subliumGetMessage( $widget ).css( 'display', 'block' );
// Bring the plan dropdown into view so what to do is obvious on
// mobile too.
if ( $widget[0] && $widget[0].scrollIntoView ) {
$widget[0].scrollIntoView( { behavior: 'smooth', block: 'center' } );
}
}
// Native capture-phase listeners run BEFORE Sublium's / WooCommerce's
// own handlers, so we can stop the add cleanly. We intercept both the
// button click and the form submit, because the button is a submit
// control and a keyboard Enter can submit the form without a click.
document.addEventListener(
'click',
function ( e ) {
var button = e.target.closest( 'form.cart .single_add_to_cart_button' );
if ( ! button ) {
return;
}
var $widget = $( subliumWidgetSelector );
if ( subliumNeedsPlan( $widget ) ) {
subliumBlockAndWarn( e, $widget );
}
},
true
);
document.addEventListener(
'submit',
function ( e ) {
var form = e.target;
if ( ! form.matches || ! form.matches( 'form.cart' ) ) {
return;
}
var $widget = $( subliumWidgetSelector );
if ( subliumNeedsPlan( $widget ) ) {
subliumBlockAndWarn( e, $widget );
}
},
true
);
// isTrusted is a native, un-fakeable browser flag: true only for real
// user-initiated events, always false for script-dispatched ones.
// Sublium's own click handling stops native propagation and
// re-dispatches via jQuery's .trigger('click') afterward, which strips
// isTrusted by the time a jQuery delegated listener sees it — so this
// uses a native, capture-phase listener instead.
document.addEventListener(
'click',
function ( e ) {
if ( ! e.isTrusted ) {
return;
}
if ( ! e.target.closest( subliumWidgetSelector + ' .sublium-dropdown-options li' ) ) {
return;
}
// The customer picked a plan: clear the warning and unlock the add.
subliumPlanUserSelected = true;
subliumHideMessage();
subliumApplyChoosePlanText();
},
true
);
// Re-evaluate when switching between Subscription / One Time Purchase.
// Switching AWAY from Subscription resets the "user picked a plan"
// flag, so returning to Subscription later always requires a fresh
// explicit choice instead of silently carrying over a prior pick.
$( document ).on( 'change', 'input[name="sublium-purchase-option"]', function () {
var $widget = $( subliumWidgetSelector );
if ( $widget.length && ! subliumSubscriptionIsActive( $widget ) ) {
subliumPlanUserSelected = false;
}
subliumHideMessage();
subliumApplyChoosePlanText();
} );
// Race-proof against Sublium's own render timing: react to DOM
// mutations directly instead of relying on the sublium_plans_rendered
// event firing after this script attaches its listener.
var subliumObserver = new MutationObserver( subliumApplyChoosePlanText );
function subliumStartObserving() {
subliumObserver.observe( document.body, { childList: true, subtree: true, characterData: true } );
subliumApplyChoosePlanText();
}
if ( document.readyState === 'loading' ) {
document.addEventListener( 'DOMContentLoaded', subliumStartObserving );
} else {
subliumStartObserving();
}
} )( jQuery );
</script>
<?php
},
20
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment