Link to home
Start Free TrialLog in
Avatar of sharingsunshine
sharingsunshineFlag for United States of America

asked on

Need Jquery Fixed To Post Shipping Message

This is a screenshot of my site that isn't live yet.  Because it isn't live, I will need your IP number to be whitelisted before you can access the site.  Just pm me your ip number if you are interested.  Because the site isn't live and I pay by the hour it isn't on all the time.  So, if you can let me know when you can look at  it I will make sure the site is turned on.

https://gyazo.com/a01ccbb27bf6eb9a73e2127d01e505fb

This is my jquery that isn't producing the result it is supposed to produce.

<?php
/**
 * The template for displaying the footer.
 *
 * @package flatsome
 */

global $flatsome_opt;
?>

</main><!-- #main -->

<footer id="footer" class="footer-wrapper">

        <?php do_action('flatsome_footer'); ?>

</footer><!-- .footer-wrapper -->

</div><!-- #wrapper -->

<?php wp_footer(); ?>

<script>
jQuery(document).ready(function(){
        jQuery(document).on('click','#shipping_method_0_132643',function(){
                if(hasPobox()){
                        showPoError();
                }
        });

        jQuery(document).on('blur','#shipping_address_1',function(){
                if(hasPobox() && jQuery('#shipping_method_0_132643').is(':checked')){
                        showPoError();
                }else{
                        hidePoError();
                }
        });
 jQuery(document).on('blur','#shipping_address_2',function(){
                if(hasPobox() && jQuery('#shipping_method_0_132643').is(':checked')){
                        showPoError();
                }else{
                        hidePoError();
                }
        });

        function showPoError(){
                var msg ='<div class="pobox-error woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout"><ul class="woocommerce-error message-wrapper" role="alert"><li><div class="messa$
                if(!jQuery('.pobox-error').length){
                        jQuery('#place_order').after(msg);
                }
        }

        function hidePoError(){
                jQuery('.pobox-error').remove();
        }

        function hasPobox(){
                var res = false;
            var pat1 = /^(([pP]{1}(.*?)(\s+)?[oO]{1}(.*?))+?(\s+)?([0-9]+))+?/i;
            var pat2 = /^([bB][oO]?[xX]?)(\s+)?([0-9]+)+?/i;
            var ad1 = jQuery('#shipping_address_1').val();
            var ad2 = jQuery('#shipping_address_2').val();
                if(pat1.test(ad1) || pat2.test(ad1) || pat1.test(ad2) || pat2.test(ad2)){
                res = true;
            }
            return res;
 }
});
</script>

Open in new window


It seems the onclick isn't picking up the UPS shipment method.  If it is working correctly it is supposed to show a message if either shipping address is going to a PO Box.  Currently, it isn't showing any message if the address is going to a PO Box.  UPS won't ship to a PO Box so that's the reason for the message.

Please help me to get this to produce the message once UPS is clicked for any order going to a PO Box.

Thanks,
Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

You can probably debug this yourself quite easily.

Open up your site and view the console (press F12). Go to the Debugger tab (if you're in Firefox) and stick a breakpoint on the if(hasPobox()){ line. Then if it fires, you can step through your code. If it doesn't fire, then double check that you do actually have an element with an ID of shipping_method_0_132643 and the it is clickable. Make sure you have the jQuery library included.

Asking people to send you their IP address is likely to severly limit the help you can get here.
The problem is your regex.

Here is what I would do
function hasPobox(){
  var ad1 = jQuery('#shipping_address_1').val();
  ad1 = ad1.replace(/[^A-Z]/gi,'').substr(0,5).toLowerCase();

  var ad2 = jQuery('#shipping_address_2').val();
  ad2 = ad2.replace(/[^A-Z]/gi,'').substr(0,5).toLowerCase();

  return (ad1=='pobox' || ad2 == 'pobox');
}

Open in new window

In this method we
a) Strip out all non-alpha characters (spaces, '.' etc)
b) we take the first 5 characters
c) we lower case the string

I prefer this method as we are approaching the problem from the perspective of lets first remove all variation from the string (spaces, capital letters, period / no period etc) - what we are left with should be pobox if a pobox was entered. It is a trivial test then to see if a PO Box was entered - irrespective of the variation.
Avatar of sharingsunshine

ASKER

I tried your code but the message still doesn't show.  I like your approach, though.  It will be much cleaner.  

I did a complete replace of the function was that your intent?
The problem is here
if(hasPobox() && jQuery('#shipping_method_0_132320').is(':checked')){

Open in new window

As I mentioned before that checkbox id does not exist. The actual value on your form is ship-to-different-address-checkbox

So the function hasPobox() is working - just your if statement will never be true because you are trying to check the state of a non-existent checkbox.
I understand but how can I get a correct if statement?
Looking at the source code it shows 132643 or am I missing something.

<tr class="shipping">
	<th>Shipping</th>
	<td data-title="Shipping">
					<ul id="shipping_method">
									<li>
						<input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_132643" value="132643" class="shipping_method"  />
								<label for="shipping_method_0_132643">UPS: <span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">&#36;</span>8.45</span></label>					</li>
									<li>
						<input type="radio" name="shipping_method[0]" data-index="0" id="shipping_method_0_132651" value="132651" class="shipping_method"  checked='checked' />
								<label for="shipping_method_0_132651">Priority Mail: <span class="woocommerce-Price-amount amount"><span class="woocommerce-Price-currencySymbol">&#36;</span>8.45</span></label>					</li>
							</ul>
		
		
			</td>
</tr>

Open in new window



Chris, I tried the debugger but that's the first time I have tried to debug anything with it.
Looks like your ID is correct.

I'm now unsure as to which problem we're trying to resolve here. In your opening question you stated that the onclick wasn't firing, but we're also discussing regex issues and missing IDs. Maybe you have more than one issue here, so it makes sense to work through them one by one.

As for your opening question, the easiest way to figure out whether your onclick is firing is to add in an alert:

jQuery(document).on('click','#shipping_method_0_132643',function(){
    alert("UPS Option Clicked");
    if(hasPobox()){
        showPoError();
    }
});

Open in new window

Now if you get an alert, you know the click is firing, and you can move on to the hasPobox() function. If you don't get an alert, then we'll try and figure out why it's not firing.
i do get the alert
I set an alert if the function hasPobox and it showed it did "have po box" but only if I clicked the UPS option.  It needs to be changed if it is already selected and not clicked because in that scenario the alert never showed.

The reason is the cart sometimes defaults to UPS and so there is no click.  Is that possible?
I understand but how can I get a correct if statement?
Use the correct control id as I have suggested.

You are doing a check where you are saying
If (hasPOBox() && A_Control_which_does_not_exist_is_checked) {
   // do this
   // even if hasPOBox() returns true - this will never fire because you are
   // checking the check state of something that does not exist
}

Open in new window


Looking at the source code it shows 132643 or am I missing something.
That is not what is being rendered on your live site.
I am working off the link from your last question - and when I go there that id does not exist - instead it is set to ship-to-different-address-checkbox
we may have an issue of looking at different items.  Please send me a screenshot of what you are seeing.
Screenshot of Shipping in cart and debug window.
User generated image User generated image
Yes, it appears we aren't in synch.  I am not focused on that selection box but where UPS is listed which in my image is the first circle and the second circle is the code creating it.
89897c0b5c377639626f5ef475f7a85d.jpg
Ok we are on the same page - I see the error message
User generated image
Wow, glad to see that you are seeing it but why can't I?
I can't answer that. (CORRECTION: I can - billing addresses were not linked)
I cleared my cookies - started again.
1. Select product
2. Goto cart
3. Goto checkout
4. Select ship to different address
5. Select US as country
6. Select UPS
7. Enter PO Box 111
8. Message appears

Note: My tests are on SHIPPING address.
If you repeat the above for BILLING it will not work because you are not checking for billing in your jQuery at the bottom - only for shipping.

Here is what I would do - a bit of a rewrite but this should take care of all the options.
jQuery(function() {
  jQuery('#ship-to-different-address-checkbox').change(function() {
	this.checked ? $('.shipping-box').show() : $('.shipping-box').hide();
  });
  // Check for changes on all controls that affect the PO Box check  
  jQuery('#billing_address_1,#billing_address_2,#shipping_address_1,#shipping_address_2,#ship-to-different-address-checkbox,[name="shipping_method[0]"]').change(function() {
    // Only proceed if we UPS is checked
    if ($('#shipping_method_0_132643').is(':checked') ) {
      if ($('#ship-to-different-address-checkbox').is(':checked')) {
        ad1 = jQuery('#shipping_address_1').val();
        ad2 = jQuery('#shipping_address_2').val();
      }
      else {
        ad1 = jQuery('#billing_address_1').val();
        ad2 = jQuery('#billing_address_2').val();
      }
      if (hasPOBox(ad1, ad2)) {
        showPoError();
      }
      else {
        hidePoError();
      }
    }
    // IF UPS not checked then hide the error - we don't care about PO Boxes
    else {
      hidePoError();
    }
  });
  
function showPoError() 
{
  var msg ='<div class="pobox-error woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout"><ul class="woocommerce-error message-wrapper" role="alert"><li><div class="message-container container alert-color medium-text-center"><span class="message-icon icon-close"></span> <strong>UPS can not send to PO Box.</strong></div></li></ul></div>';
  if(!jQuery('.pobox-error').length) {
    jQuery('#place_order').after(msg);
    }
  }

  function hidePoError(){
    jQuery('.pobox-error').remove();
  }

  // This now becomes generic for billing and shipping
  function hasPOBox(ad1, ad2)
  {
    ad1 = ad1.replace(/[^A-Z]/gi,'').substr(0,5).toLowerCase();
    ad2 = ad2.replace(/[^A-Z]/gi,'').substr(0,5).toLowerCase();

    return (ad1=='pobox' || ad2=='pobox');
 }
});

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I still don't have it working on my end.  You have done more than anyone can ask.  I'll just watch after I go live if any addresses are getting through.  My concern is that if someone has a PO Box for billing and the same for shipping will it catch it.  Since I can't see it, I will just have to wait and see.  Nevertheless, it is good to know it is working on the customer end.
Firstly remove lines 3-5 of the script above - that was part of my testing environment. i.e. these lines
  $('#ship-to-different-address-checkbox').change(function() {
	this.checked ? $('.shipping-box').show() : $('.shipping-box').hide();
  });

Open in new window


Then I just saw that the Shipping options (UPS) are dynamically added - which is why I could not find them in the source - but more importantly the binding on the change() event won't work as the latter are statically bound and those options are added after the static binding.

Here is an update that should fix that.
<script>
jQuery(function($) {
  // CHECK FOR UPS OPTION CHANGE
  $('body').on('change', '[name="shipping_method[0]"]', doPOCheck);

  // CHECK FOR ANY CHANGES TO ADDRESS OR SHIPPING CHECKBOX
  $('#billing_address_1,#billing_address_2,#shipping_address_1,#shipping_address_2,#ship-to-different-address-checkbox').change(doPOCheck);

  // THIS IS THE WORKHORSE  
  function doPOCheck ()
  {
    // Only proceed if we UPS is checked
    if ($('#shipping_method_0_132643').is(':checked') ) {

      // IF THE SHIPPING CHECKBOX IS CHECKED WE WANT THE SHIPPING
      // ADDRESSES OTHERWISE THE BILLING ADDRESSES
      if ($('#ship-to-different-address-checkbox').is(':checked')) {
        ad1 = $('#shipping_address_1').val();
        ad2 = $('#shipping_address_2').val();
      }
      else {
        ad1 = $('#billing_address_1').val();
        ad2 = $('#billing_address_2').val();
      }

      // DO THE PO CHECK
      if (hasPOBox(ad1, ad2)) {
        showPoError();
      }
      else {
        hidePoError();
      }
    }
	else {
	  hidePoError();
	}
  }
  
  function showPoError() 
  {
    var msg ='<div class="pobox-error woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout"><ul class="woocommerce-error message-wrapper" role="alert"><li><div class="message-container container alert-color medium-text-center"><span class="message-icon icon-close"></span> <strong>UPS can not send to PO Box.</strong></div></li></ul></div>';
    if(!jQuery('.pobox-error').length) {
      $('#place_order').after(msg);
    }
  }

  function hidePoError(){
    $('.pobox-error').remove();
  }

  // This now becomes generic for billing and shipping
  function hasPOBox(ad1, ad2)
  {
    ad1 = ad1.replace(/[^A-Z]/gi,'').substr(0,5).toLowerCase();
    ad2 = ad2.replace(/[^A-Z]/gi,'').substr(0,5).toLowerCase();

    return (ad1=='pobox' || ad2=='pobox');
 }
});
</script>

Open in new window

I made the changes and thanks for staying with this.  However, I still can't see anything on my end.  I have cleared caches and used different browsers but still no error message.

But because you have seen it I am OK.
I think I see the problem (or at least one of them)
First - please remove the lines as noted above they are not supposed to go in your code.

Second, when you change the UPS setting it does an AJAX request - this wipes out the error message. So if you type in PO Box - then select country then select UPS, the AJAX wipes the message.

Need to get it to do the check only after the AJAX is complete.

Do you control that or is it part of the framework?
it would be part of the framework, which is wordpress because woocommerce is just a plugin for wordpress.  That's why I put the code in the footer hoping the ajax had already completed.
I put the code in the footer hoping the ajax had already completed.
Unformtunately it does not work like that. AJAX runs asynchronously - so the call is initiated and any other code on your page is executed and (usually) finishes long before the ajax completes.

What we need to do here is tap into that AJAX complete and run the verification code after that happens (in addition to where it is happening now).

You will also need to implement checks on the server when the form is submitted - these are client side checks which are for convenience only - server checks are still necessary to santize and validate data.
I think this information is something I don't really know how to proceed with.  If I pose this as another question is that something you would answer?