Javascript executing but not keeping value on Woocommerce checkout page - javascript

I'm using this in functions.php to execute on Woocommerce checkout page.
I see display: none is being applied but only for couple of miliseconds.
Any idea how to keep the styling on elements?
// add script to checkout page
add_action( 'wp_footer', 'add_javascript_function', 9999 );
function add_javascript_function() {
global $wp;
if ( is_checkout() && empty( $wp->query_vars['order-pay'] ) && ! isset( $wp->query_vars['order-received'] ) ) {
echo '<script>
window.addEventListener("DOMContentLoaded", () => {
let myDivs = document.getElementsByClassName("products");
for(let i = 2; i < myDivs.length; i++) {
myDivs[i].style.display="none"; }
});
</script>';
}
}
Also would like to add a button to toggle the items being hidden by this function. But this issue is driving me crazy.
Thanks in advance.

Using JS to set the initial visibility of your HTML elements won't work because after your function has run update_checkout is triggered which refreshes the order review part of the checkout. That is why you see your styles only being applied briefly.
You should use CSS to set the visibility of your products, then use JS to overrule those styles when clicking on a button, toggling between hidden and visible.
The woocommerce_review_order_after_cart_contents hook gives you a nice place to add a button for this. You can also add your CSS and JS there so everything is wrapped up in one neat little function. Like this:
add_action ('woocommerce_review_order_after_cart_contents', function() {
?>
<style>
.woocommerce-checkout-review-order-table .cart_item:nth-child(n+3) {
display: none;
}
</style>
<script>
jQuery( function( $ ) {
$( '#product-toggle' ).on( 'click', 'span.button', function() {
if ( $( this ).data( 'show' ) === true ) {
$( '.woocommerce-checkout-review-order-table .cart_item').show();
$( this ).text( 'Show less products' ).data( 'show', false );
} else {
$( '.woocommerce-checkout-review-order-table .cart_item').slice(2).hide();
$( this ).text( 'Show all products' ).data( 'show', true );
}
} );
} );
</script>
<?php
echo '<tr id="product-toggle"><td colspan="2"><span class="button" data-show="true">Show all products</span></td></tr>';
}, 10 );

Related

Conditionally add class to element based on other element status/class

I'm trying to hide an image after I scroll down my page. When scrolling my header gets a class fl-theme-builder-header-scrolled. My image div has a class hiding-image and I want to add a class image-off when the fl-theme-builder-header-scrolled class shows up in the header.
This is what I have:
$(document).ready(function() {
if($( 'header' ).hasClass( 'fl-theme-builder-header-scrolled' )) {
$( '.hiding-image' ).toggleClass( 'image-off' );
}
});
but this doesn't work. Any advice? Thx.
Your code only runs once after the document ready, as soon as the page loads. So if the header doesn't have the fl-theme-builder-header-scrolled class and only gets added later, your code will not run again.
You need a a mutation Observer.
Check this thread: Event trigger on a class change
Alternatively you can do as #Brewal is saying, putting the code evaluation on the scroll event. Although be careful so you don't run the code every time the scroll event is triggered since it can slow your website performance, specially on mobile devices.
Try something like this.
$(window).scroll(function() {
if($( 'header' ).hasClass( 'fl-theme-builder-header-scrolled' )) {
$( '.hiding-image' ).toggleClass( 'image-off' );
}
});
As pointed out in the comments, I think the best approach would be to find where the fl-theme-builder-header-scrolled class is already being controlled.
However, If you really would want to put the logic in a separate area, you can do it like this:
$(document).ready(function () {
$(window).scroll(function () { //attach to window scroll event
if ($('header').hasClass('fl-theme-builder-header-scrolled') && !$('.hiding-image').hasClass('image-off')) {
$('.hiding-image').addClass('image-off'); //add class only if it does not already exist;
} else {
if ($('.hiding-image').hasClass('image-off')) {
$('.hiding-image').removeClass('image-off'); //remove class
}
}
});
});
Check condition like this:
`$(window).scroll(function() {
if($( 'header' ).hasClass( 'fl-theme-builder-header-scrolled' ))
{
$( '.hiding-image' ).addClass( 'image-off' );
}
else
{
$( '.hiding-image' ).removeClass( 'image-off' );
}
});`
I finally managed to make it work doing this:
(function($){
$(function(){
var headerThemer = $( '.fl-builder-content[data-type=header]' ).eq(0);
$(window).on( 'scroll.fl-theme-builder-header-scrolled', function(){
if ( headerThemer.hasClass('fl-theme-builder-header-scrolled') ) {
$('.hiding-image').hide();
}
else {
$('.hiding-image').show();
}
});
})
})(jQuery);

Hide Row when other Toggled - Wordpress Javascript

I am trying to show/hide rows on WpBakery when an image is clicked. When the first image is clicked I would like a row to toggle. When the second image is clicked I would like first row to hide and then the second row to show. I would like to do this with 10 different images. I have adapted the following code which I found online:
add_action( 'wp_footer', function() { ?>
<script>
( function( $ ) {
'use strict';
$( document ).ready( function() {
var $trigger = $( '.open-stan' );
var $hiddenRow = $( '.stan' );
var $trigger1 = $( '.open-test' );
var $hiddenRow1 = $( '.test' );
if ( $hiddenRow.length ) {
$trigger.click( function() {
$hiddenRow.toggle();
$hiddenRow1.hide();
return false;
} );
}
else if ( $hiddenRow1.length ) {
$trigger1.click( function() {
$hiddenRow1.toggle();
$hiddenRow.hide();
return false;
} );
}
} );
} ( jQuery ) );
</script>
To test if it is working hiddenRow1 is shown when I open the page as I have not hidden it using CSS, if you click on the first image (trigger) this hides hiddenRow1 and displays hiddenRow. However when you click on the second image nothing happens.
Any help would be appreciated
Use similar like this...
$(".row_class").click(function(){
$(".row_class").not(this).removeClass('show');
$(this).addClass('show');
});

How can I program a JS button who activate a transition on click and on scroll too?

I have a .js document who allow me to switch between different page into the same html document.
I have a trigger button who activate the transition on click only and i wanted to activate it on scroll too or on scroll only.
I tried to add an onscroll parameter in my function but it doesn't worked. I think it's because I have my different pages who are in width:100% so I don't have any scrollbar...
Here is my HTML structure
<body>
<button id="iterateEffects" class="btn_bot"></button> <!--Trigger btn-->
<div id="pt-main" class="pt-perspective">
<div class="pt-page pt-page-1">First page code inside</div>
<div class="pt-page pt-page-2">Second page code inside</div>
etc...
</div>
</body>
Here is my button function
$iterate = $( '#iterateEffects' ) //my iterateEffects var
function init() {
$pages.each( function() {
var $page = $( this );
$page.data( 'originalClassList', $page.attr( 'class' ) );
} );
$pages.eq( current ).addClass( 'pt-page-current' );
$( '#dl-menu' ).dlmenu( {
animationClasses : { in : 'dl-animate-in-2', out : 'dl-animate-out-2' },
onLinkClick : function( el, ev ) {
ev.preventDefault();
nextPage( el.data( 'animation' ) );
}
} );
$iterate.on( 'click', function() {
animcursor = 3;
nextPage( animcursor );
} ); //Activate the function on click
}
Have you tried this:
$( document ).on( 'scroll', function() {
animcursor = 3;
nextPage( animcursor );
} );
Also make sure that your page is scrollable.

WooCommerce event not triggering when using Select2 instead of actual select

I've built a custom website using Wordpress and WooCommerce and have installed Select2 to generate custom selects which is working fine. The issue I am having is with some of the selects on the WooCommerce pages, specifically those that trigger an event on change.
The custom selects successfully change the option selected, but the issue arises with selects that are meant to trigger an event. For example, the colour variation dropdown on the product page or the 'Sort By' select on the store page.
I've looked through the WooCommerce JS files and discovered some WooCommerce specific events that are triggered when a selection is made using the actual select box but I'm not sure how to implement this when using Select2 instead.
Here is a copy of the WooCommerce JS in relation to the event I'm talking about (in this case the change to the select for product variations):
.on( 'change', '.variations select', function() {
$form.find( 'input[name="variation_id"], input.variation_id' ).val( '' ).change();
$form.find( '.wc-no-matching-variations' ).remove();
if ( $use_ajax ) {
if ( $xhr ) {
$xhr.abort();
}
var all_attributes_chosen = true;
var some_attributes_chosen = false;
var data = {};
$form.find( '.variations select' ).each( function() {
var attribute_name = $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' );
if ( $( this ).val().length === 0 ) {
all_attributes_chosen = false;
} else {
some_attributes_chosen = true;
}
data[ attribute_name ] = $( this ).val();
});
if ( all_attributes_chosen ) {
// Get a matchihng variation via ajax
data.product_id = $product_id;
$xhr = $.ajax( {
url: wc_cart_fragments_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_variation' ),
type: 'POST',
data: data,
success: function( variation ) {
if ( variation ) {
$form.find( 'input[name="variation_id"], input.variation_id' )
.val( variation.variation_id )
.change();
$form.trigger( 'found_variation', [ variation ] );
} else {
$form.trigger( 'reset_data' );
$form.find( '.single_variation_wrap' ).after( '<p class="wc-no-matching-variations woocommerce-info">' + wc_add_to_cart_variation_params.i18n_no_matching_variations_text + '</p>' );
$form.find( '.wc-no-matching-variations' ).slideDown( 200 );
}
}
} );
} else {
$form.trigger( 'reset_data' );
}
if ( some_attributes_chosen ) {
if ( $reset_variations.css( 'visibility' ) === 'hidden' ) {
$reset_variations.css( 'visibility', 'visible' ).hide().fadeIn();
}
} else {
$reset_variations.css( 'visibility', 'hidden' );
}
} else {
$form.trigger( 'woocommerce_variation_select_change' );
$form.trigger( 'check_variations', [ '', false ] );
$( this ).blur();
}
// Custom event for when variation selection has been changed
$form.trigger( 'woocommerce_variation_has_changed' );
} )
And then my own attempt to utilise this event:
$('#pa_colour').select2();
$('#pa_colour').on('change', function(){
var $form = $(this).parents('form');
$form.trigger( 'woocommerce_variation_select_change' );
$form.trigger( 'woocommerce_variation_has_changed' );
});
Unfortunately the site isn't live yet so I can't provide a link but hopefully you get the idea.
If someone can help me here I'd be so appreciative, I'm not exactly sure how Wordpress hooks (if this is what this is) work and I may be just missing something obvious.
Thanks,
Kathryn
This isn't a solution exactly, but I ended up replacing the Select2 plugin with the Selectric plugin and that works perfectly. Oh well! Thanks guys. http://lcdsantos.github.io/jQuery-Selectric/
I came across the same issue and found a solution in the last comment in this thread Select2 not showing selected value
The comment by Matt inspired by Kevin suggested wrapping the select2 call in $(window).bind("load", function() {...}); which worked for me.
Kudos to those guys.

How to add links to tabbing order when they're made visible with CSS?

Links that are subject to display: none aren't in the default tabbing order. However, when they're revealed - e.g. CSS for a drop-down menu reveals a sub-menu when a parent link gains focus - they still aren't in the tabbing order. Presumably JavaScript is required, but simply setting tabindex="0" does nothing.
The problem here is that as soon as you tab off the "Top level page with child" link, the CSS is updated and the parent of the anchor becomes display:none before the anchor can receive focus. You will need to use JavaScript to solve this problem and delay the change in the CSS using a timeout until you can determine whether the loss of focus has resulted in the focus shifting to the child element.
Setting tabindex="0" when the parent is display:none will not help, display:none means that the content might as well not be in the document.
I've come up with a solution that basically works: http://codepen.io/gyrus/pen/waKjKv/ There seem to be some issues in IE, I'm working on that. But the general idea is:
Add a small delay before hiding the drop-down
Set a data attribute to flag whether any links inside the drop-down have focus, and check this before hiding
This is just the jQuery, check the pen for more:
jQuery( document ).ready( function( $ ) {
$( '.nav' ).on( 'mouseenter focusin', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Show sub-menu
el.attr( 'aria-expanded', 'true' )
.find( '.sub-menu-wrapper' ).show();
}).on( 'mouseleave focusout', '.menu-level-0.menu-item-has-children', function( e ) {
var el = $( this );
// Only hide sub-menu after a short delay, so links get a chance to catch focus from tabbing
setTimeout( function() {
var smw = el.find( '.sub-menu-wrapper' );
if ( smw.attr( 'data-has-focus' ) !== 'true' ) {
el.attr( 'aria-expanded', 'false' );
smw.hide();
}
}, 100 );
}).on( 'focusin', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'true' );
}).on( 'focusout', '.sub-menu-wrapper', function( e ) {
var el = $( this );
el.attr( 'data-has-focus', 'false' );
// Hide sub-menu on the way out
el.hide().parents( '.menu-level-0' ).attr( 'aria-expanded', 'false' );
});
});

Categories

Resources