Categories
Code Snippets WordPress

WooCommerce Shipping Options Based on Weight

WooCommerce shipping options based on weight can be accomplished by creating a callback function for the woocommerce_cart_shipping_packages filter. The filter hook allows you to make a change to the cart package such as conditional shipping options based on shipping class, location, or weight.

To get the weight of all the products in the shopping cart you can use the cart_contents_weight method of the WooCommerce Cart class. The code below will allow only UPS shipping method if the weight is great than 4 pounds. If the weight is below 4 pounds USPS will be the only shipping options. The shipping options can be changed on lines 15 and 30. The weight condition can be changed on line 13.

/** 
 * Shipping based on cart contents weight
 */
add_filter( 'woocommerce_cart_shipping_packages', 'ps_woocommerce_cart_shipping_packages_by_weight' );

function ps_woocommerce_cart_shipping_packages_by_weight( $packages ) {

    $packages = array();
 
  
    $cart_items = WC()->cart->get_cart(); 
   
   if( WC()->cart->cart_contents_weight > 4){
        $packages[] = array(
            'ship_via' => array( 'ups'  ), /*Shipping methods that are available for order over 4 lbs */
            'contents' => $cart_items,
            'contents_cost' => array_sum( wp_list_pluck( $cart_items, 'line_total' ) ),
            'applied_coupons' => WC()->cart->applied_coupons,
            'destination' => array(
                'country' => WC()->customer->get_shipping_country(),
                'state' => WC()->customer->get_shipping_state(),
                'postcode' => WC()->customer->get_shipping_postcode(),
                'city' => WC()->customer->get_shipping_city(),
                'address' => WC()->customer->get_shipping_address(),
                'address_2' => WC()->customer->get_shipping_address_2()
            )
        );
    }else{
       $packages[] = array(
            'ship_via' => array('usps'), /*Shipping methods that are available for order under 4 lbs */
            'contents' => $cart_items,
            'contents_cost' => array_sum( wp_list_pluck( $cart_items, 'line_total' ) ),
            'applied_coupons' => WC()->cart->applied_coupons,
            'destination' => array(
                'country' => WC()->customer->get_shipping_country(),
                'state' => WC()->customer->get_shipping_state(),
                'postcode' => WC()->customer->get_shipping_postcode(),
                'city' => WC()->customer->get_shipping_city(),
                'address' => WC()->customer->get_shipping_address(),
                'address_2' => WC()->customer->get_shipping_address_2()
            )
        ); 
    }
      
    return $packages;
}
Categories
Code Snippets jQuery WordPress

Mobile Friendly Menu

In this tutorial I explain how to create a mobile friendly menu for the iThemes Builder theme. By default the menu will wrap on smaller screens. When the menu wraps it is not very mobile friendly.

The menu wraps on small screens.
The menu wraps on screens.

In your child theme directory create a new file for some jQuery. You can call it what you want but I am going to call it mobile_script.js. The code in this file should not run until the page loads. The script needs to be enqueued in the functions.php file.

Add Mobile Menu Functionality
After the page loads add a class to the menu and to the navigation module. The Menu label is added before the module navigation. If you click on ≡ Menu the menu items are shown or hidden. The sub-menu items are hidden until the parent item is tapped.

jQuery(document).ready(function() {

	jQuery(".builder-module-navigation .menu").addClass("mobile-menu-hidden");
	jQuery(".builder-module-navigation").addClass("mobile");
	
	jQuery(".mobile-menu-hidden").before('<div class="mobile-menu">≡ Menu</div>');
	
	jQuery(".mobile-menu").click(function(){
		jQuery(this).next().slideToggle();
	});


	jQuery(".mobile.builder-module-navigation li:has(ul)").click(function(){
		jQuery(".mobile.builder-module-navigation li ul").hide('fast');
		jQuery("ul",this).toggle();
	});

});

Style The Mobile Menu
After you add the jQuery file ≡ Menu will show above the navigation on a desktop. So in the style.css file it is hidden or told not to display.

.mobile-menu{
display: none;
}

Then the mobile navigation style is added to the main style sheet, responsive style sheet, or mobile style sheet that is available with most Builder child themes.


@media screen and (max-width:767px) { 
/*********************************************
	Mobile Menu
*********************************************/
.mobile-menu {
  color: #4b9eec;
  width: auto;
  font-weight: 700;
  font-size: 1.5rem;
  cursor: pointer;
  display: block;
  padding: .65em 0;
  -webkit-font-smoothing: antialiased;
  -webkit-appearance: none;
  -webkit-transition: all .2s ease-in;
  -moz-transition: all .2s ease-in;
  -o-transition: all .2s ease-in;
  -ms-transition: all .2s ease-in;
  transition: all .2s ease-in;
  text-align: center;
}

.mobile.builder-module-navigation .mobile-menu-hidden {
	display: none;
	margin-bottom: 1em;
}

.mobile .builder-module-navigation-menu-wrapper {
	display: block;
}
.builder-module-navigation-background-wrapper {
	padding: 0;
}
.builder-module-outer-wrapper .mobile.builder-module-navigation {
	padding: 0;
}
.mobile.builder-module-navigation {
	display: block;
	line-height: 1;
	width: 100%;
}
.mobile.builder-module-navigation ul.menu {
	border-bottom: 0;
}
.mobile.builder-module-navigation ul.menu:after {
	visibility: hidden;
	display: block;
	font-size: 0;
	content: " ";
	clear: both;
	height: 0;
}
.mobile.builder-module-navigation ul {
	display: block;
	float: none;
	width: 100%;
	margin: 0;
	padding: 0;
}
.mobile.builder-module-navigation ul * {
	margin: 0;
}
.mobile.builder-module-navigation li {
	padding: 0;
	display: block;
	width: 100%;
	background-color: rgba(255, 255, 255,.8);
}

.mobile.builder-module-navigation li a,
.mobile.builder-module-navigation .current_page_item li a,
.mobile.builder-module-navigation .current-cat li a,
.mobile.builder-module-navigation .current-menu-item li a {
	color: #333333;
	font-size: 1em;
	font-weight: 600;
	text-decoration: none;
	padding: .5em 1em;
	border: 0;
	border-bottom: 1px solid #C9C9C9;
	margin: 0;
	-webkit-font-smoothing: antialiased;
}
.mobile.builder-module-navigation .current_page_item > a,
.mobile.builder-module-navigation .current-cat > a,
.mobile.builder-module-navigation .current-menu-item > a {
	color: #252525;
	background: #F5F5F5;
}
.mobile.builder-module-navigation li a:hover,
.mobile.builder-module-navigation .current_page_item li a:hover,
.mobile.builder-module-navigation .current-cat li a li a:hover,
.mobile.builder-module-navigation .current-menu-item li a:hover {
	color: #252525;
	background: #F5F5F5;
}
/* Second Level */
.mobile.builder-module-navigation li ul {
	background: #FFFFFF;
	border: 0;
	width: 100%;
	left: 0;
	position: relative;
	display: none; 
}

.mobile.builder-module-navigation li li {
	border: 0;
	width: 100%;
}
.mobile.builder-module-navigation li li a,
.mobile.builder-module-navigation .current_page_item li a,
.mobile.builder-module-navigation .current-cat li a,
.mobile.builder-module-navigation .current-menu-item li a {
	float: none;
	font-size: 1em;
	line-height: 1;
	margin: 0;
	padding-left: 2em;
}
.mobile.builder-module-navigation li li a:hover,
.mobile.builder-module-navigation li li a.sfhover {

}
.mobile.builder-module-navigation li ul ul {
	margin: 0;
}
.mobile.builder-module-navigation li:hover ul,
.mobile.builder-module-navigation li li:hover ul,
.mobile.builder-module-navigation li li li:hover ul,
.mobile.builder-module-navigation li li li li:hover ul,
.mobile.builder-module-navigation li li li li li:hover ul,
.mobile.builder-module-navigation li.sfhover ul,
.mobile.builder-module-navigation li li.sfhover ul,
.mobile.builder-module-navigation li li li.sfhover ul,
.mobile.builder-module-navigation li li li li.sfhover ul,
.mobile.builder-module-navigation li li li li li.sfhover ul {
	left: 0;
}

.builder-module-navigation .builder-module-sidebar-outer-wrapper {
  display: none;
}
}

Final Result

Example Mobile Friendly Menu

Categories
Code Snippets jQuery

Replace Smart Quotes With Straight Quotes

I created a web app that uses ckEditor as the rich text editor. It works perfectly except when you copy and paste text that includes smart quotes and other special symbols. CkEditor converts the smart quotes to HTML entities, which would be fine in a normal situation. The Html entities caused a problem when it was time to write the iTunes XML feed. So what I ended up doing is replacing all the html entities with the correct character as soon as I got the content from ckEditor. The code I used to replace smart quotes with straight quotes is below.

function cleanstring(dirty){
	var smartchr = [ "’","‘","“","”","–","—","…", " ", '„', '‚' , '«','»', '‹', '›'];
	var correctchr = ["'", "'", '"', '"', '-', '-', '...', '', '"', "'", '"', '"', "'", "'"];

	var thestring = dirty;
	var regex; 
  	for (var i = 0; i < smartchr.length; i++) {
    	regex = new RegExp(smartchr[i], "g");
    	thestring = thestring.replace(regex, correctchr[i]);
	}	


	return thestring;
}