jonas.hjalmarsson

Outline decoration of active button in Blocks

I wanted an outline look of the selected button in the interface in Pixilab Blocks. The outline css property doesn’t work with border-radius in Safari, so I made another solution that works with Blocks automatic scaling and centering of texts. And looks good in Safari on iPad!

I’ve create some settings for you to tweak it to fit various purposes. Variables for outline size, spacing, border radius and the colors are available. Check the comments in code below of what is done.

Inactive button with the outline-button class

ads

Inactive button with the outline-button class

 

:root {
    --outline-button--text-color: white;
    --outline-button--color: pink;
    --outline-button--spacing: 8px;
    --outline-button--spacing-color: white;
    --outline-button--outline-size: 3px;
    --outline-button--border-radius: 1000px;
}

/* set the main element of the button */
.outline-button.Button-ctl,
.outline-button.Button-ctl.active {
    /* set the transparent border to get the same size when the button is inactive */
    border: var(--outline-button--outline-size) solid transparent; 

    /* set the radius of the button */
    border-radius: var(--outline-button--border-radius);
}

/* set the button color when the button is active */
.outline-button.Button-ctl.active {
    /* set the outline color when the button is active */
    border-color: var(--outline-button--color);
}

/* set the actual button div */
.outline-button.Button-ctl>div,
.outline-button.Button-ctl.active>div {
    /* the inner div border is used as the spacing around the button */
    border: var(--outline-button--spacing) solid var(--outline-button--spacing-color);

    /* the button color, same as outline, can be changed to other color if you want */
    background-color: var(--outline-button--color);

    /* the radius of the button is needed here as-well */
    border-radius: var(--outline-button--border-radius);
}

/* set the text color of the button */
.outline-button.Button-ctl>ctl-title,
.outline-button.Button-ctl.active>ctl-title {
    color: var(--outline-button--text-color);
}

For the Blocks scaling calculations of the text placement we have to do some work arounds with using the actual button div border color as spacing, and use the outer wrapper element border as the outline border.

The sizes needs to be set according to your environment to fit the scaling of the actual Spots that will use this feature.

Simple Expand for WordPress

This plugin makes it easy to get an expandable text, or a read more functionality inside a post or page.

Expandable textThis is a small sample for how Simple Expand works.
Expandable text containing images

The inside text can also contain html, as

  • titles,
  • bold styles
  • and other html tags

that can be used in a normal post. It also work with Gutenberg.

Install the plugin, search for Simple Expand or download it here.

Use like this

[expand title='Expandable text']
   This is a small sample for how Simple Expand works.
[/expand]

The title is the text that always is show and the text wrapped inside the tags is shown when the title is pressed.

WP-rocket aggressive purge

In some cases WP-rocket cache plugin empties all cached files although all you do is update a post or product. Or for me when a customer does a purchase that changes the stock value for a WooCommerce product. What I can see, this doesn’t happen for me when updating a product from within WP. So it’s not consistent.

I found this is caused in rocket_get_purge_urls in inc/common/purge.php. When checking for previous and next posts to clear it sometimes finds the front page and adds that url to $purge_urls. This doesn’t only clear the cache for the actual front page, but all the cached files in that directory, i.e. the complete site!

I’ve sent this bug to the WP-rocket team, hopefully they can find a way to fix it.

But until then one way to work around this is to add a filter that always ignores the home page url. This filter doesn’t affect the domain_clean, so no worries when updating WP options or theme settings that should empty all cache.

function disable_cache_clearing_files( $urls ){
  // urls to exclude
  $exclude_urls = [ get_site_url(), get_site_url() . "/" ]; //, $_SERVER['SERVER_NAME'] ];

  // get all urls except excluded urls
  $urls = array_diff( $urls, $exclude_urls);
  
  return $urls;
}
add_filter( 'rocket_post_purge_urls', 'disable_cache_clearing_files');

The issue is also explained here:

https://github.com/wp-media/wp-rocket/issues/3246

https://github.com/wp-media/wp-rocket/issues/2549

https://docs.wp-rocket.me/article/1491-using-wp-rocket-on-your-woocommerce-site#cache-purging

https://docs.wp-rocket.me/article/1640-cache-is-incomplete-cleared-too-frequently-or-randomly

https://docs.wp-rocket.me/article/78-how-often-is-the-cache-updated#full-cache-deletion

https://docs.wp-rocket.me/article/137-disable-all-automatic-cache-clearing

Cleanup session in WooCommerce

There are some pretty simple ways to clear a session with WooCommerce that can be used with code when you need a user to get a brand new session with nothing old getting in the way. Can be used if you by code set a country or currency that’s not the WooCommerce default for example.

The most brutal (and sometimes most officiant way) is to destroy the session completely.

WC()->session->destroy_session()

https://woocommerce.github.io/code-reference/classes/WC-Session-Handler.html#method_destroy_session

This line cleans the session and clears the cookies for you and should be called early in WordPress since it tampers with cookies and session variables. For example:

// clear WC session if argument do_cleanup is true is passed
add_action( 'wp_loaded', 'my_cleanup_session');
function my_cleanup_session() {
  if ($_REQUEST['do_cleanup'] == 'true') {
    // cleanup old session
    WC()->session->destroy_session();
    // force redirect (needed in some cases) 
    //wp_safe_redirect( '/' );
  }
}

There are other alternatives as well if you don’t need to completely destroy the session. You could try one of these instead:

// clears session, but keeps cookies
WC()->session->cleanup_session()

// clear specific users session
WC()->session->delete_session($customer_id)

// forgets the session without destroying it
WC()->session->forget_session()

Check for more details in the code reference.

Check if one variation is enabled or disabled in WooCommerce

One of my clients had the need to sometime disable one variation of many, but to avoid deleting and adding again they use en little checkbox Enable in the variation setting. Really simple!

But not equally simple to find out how to check that status in code it turned out. But after digging in the WooCommerce source I found out it uses the actual status of the “product”, i.e. every variation is kind of a product, but with a parent and some other stuff. So this is how you check that Enable checkbox:

$variation = wc_get_product($variation_id);
if ($variation->get_status( 'edit' ) == 'publish') {
  // do something if enabled
}
if ($variation->get_status( 'edit' ) == 'private') {
  // do something if NOT enabled
}       

So as you can see, the code is REALLY simple, a smart way of the WooCommerce team to reuse already built functionality. But it took a little while to find after googling for attributes, properties, meta-data and other stuff. Not so much on the web on this topic.

Use of attachment_url_to_postid in WordPress

I did some image lookup via ajax from the Elementor Image Gallery, a place where I only had the image-url to get a meta data field attached to the image. To find the image id I instead used the WordPress helper function attachment_url_to_postid, that made the lookup for me.

But I found that sometimes the lookup didn’t work for some reason. After some digging I found that WordPress adds the ending ‘-scaled’ to the image, which makes the lookup function not finding the image since it’s not the original name.

// get the image url via ajax in some way, sanitize url as simple security check
$image_url = sanitize_text_field( $_REQUEST['image_url'] ); 

// get only the image file name, to avoid looking for cdn-url for example
$image_url = end(explode('/', $image_url));

// If the filename is an auto-generated thumbnail, remove the sizes and get the URL of the original image
$image_url_org = preg_replace( '/-\d+x\d+(?=\.(webp|jpg|jpeg|png|gif)$)/i', '', $image_url );

// do the same thing but add '-scaled' to the name if the first lookup fails
$image_url_scaled = preg_replace( '/-\d+x\d+(?=\.(webp|jpg|jpeg|png|gif)$)/i', '-scaled', $image_url );

// do the magic, find the actual image id, to be used to find meta data on for example
$image_id = attachment_url_to_postid($image_url_org);

// if the original name fails, try with the '-scaled' name added to it.
if ($image_id == 0) { // try to find image with scale ending if not found with original name
	$image_id = attachment_url_to_postid($image_url_scaled);
}

// hopefully now you got the id to return or do whatever you need with it.
return $image_id;

WooCommerce – really slow wc_get_product_class

In my investigation and work to make WooCommerce perform a little bit better i found this little surprise! The little helper wc_get_product_class to print correct class names in the wrapper element in html for me took over 100ms per product. With over 100 products it’s really bad! I have quite complex products with many variations. But REALLY slowing down.

So this little code is now removed from my code.

wc_get_product_class('my-product', $product)

Yes, for me this was a good solution. I just added “product” as class instead. And saved 100ms per product! Good enough for my purpose, but it might not be sufficient for everyone.

If you don’t overwrite the product with a template, here is one way that might help you override this:

add_filter( 'woocommerce_attribute_taxonomies', 'remove_slowdowns_caused_by_taxonomies', 10, 1); function remove_slowdowns_caused_by_taxonomies($attribute_taxonomies){ return array('product'); }

Or read more here for more solutions:

https://github.com/woocommerce/woocommerce/issues/20262

WooCommerce – find default variation performance

My shop page was very slow when I had over 100 products, REALLY slow. So I had to investigate what happened. So here are some points.

Find default variation

One thing I did for every product was to find the default variation to show correct image, and the code I used was this. My products have 15 variations, and this was really bad for performance.

$default_attributes = $product->get_default_attributes();
$available_variations = $product->get_available_variations();

foreach($available_variations as $variation_values ) {
  $found_variations = 0;
  foreach($default_attributes as $key => $default_attribute_value ) {
                
    if ($variation_values['attributes']['attribute_'.$key] == $default_attribute_value) {
      $found_variations++;
    }
  }
  // return variation_id if found all of the default variations 
  if (count($default_attributes) == $found_variations) {
    return $variation_values['variation_id'];
  }
}

Instead i found the neat little function find_matching_product_variation, so instead of the nested foreach loops, I use the Data_Store_CPT to do the same.

$default_attributes = $product->get_default_attributes();
$attributes = [];
foreach ($default_attributes as $key => $value) {
  $attributes['attribute_'.$key] = $value;
}
return (new \WC_Product_Data_Store_CPT())->find_matching_product_variation(
        new \WC_Product($product->get_id()),
        $attributes
);

The same procedure that on my machine in the first foreach loops took 70-90 ms now take around 2 ms instead!

WooCommerce zero trimming decimal

I found this little neat thing when messing around with decimals in WooCommerce.

// Trim only when decimal is zero in price
add_filter( 'woocommerce_price_trim_zeros', '__return_true' );

Nice of them to provide this little filter! But even better if it was a setting in wp-admin, but until that is added, this is a quite simple solution. Just put the above code in your functions.php.

If you can’t access your functions.php or don’t know howto do it, there is of course a plugin for that. It’s made by Therichpost, and it only does exactly the above small filter snippet above. So really simple and not bloated with other crap 😉

CSV and HTML search filter for WordPress

This is one of my WordPress plugins, made to add a simple ajax-search in html or in uploaded CSV-file.

The plugin has two shortcodes.

[csvsearch src='/path/file.csv']
[filtersearch search_element='table']

[csvsearch]

[csvsearch] is performing a search in an uploaded (or otherwise accessible) CSV-file. Use the format to set the output. use {0}, {1} etc for different columns in the file and {b}{/b}, {i}{/i} etc for simple formatting. Here is a sample with all arguments to use.

[csvsearch 

// url to uploaded file
src='URL' 

// charset of file
charset='iso-8859-1' 

// format the output
format='{b}{0}{/b}, {1}, {2}{br/}'

// format the output with link
format="{a href='{0}'}{1}{/a}"

// format the output with image
format="{img src='{0}' /}"

// search label
searchtext='search' 

// format for output when instant search
instantformat='{0}' 

// instant search enabled or not
instantsearch='false' 

// data ID format, i.e. what to put in data-id of the listed element.
dataidformat="{0}" 

// change the item separator depending on type of csv file used
csv_separator=';'

// change the nothing found message
nothing_found_message='Nothing found when searching for: '

// If true, the shortcode will only find exact matches, case sensitive. Default false.
exact_match='false'

// Add text where search-result will be placed. Default none.
placeholder_text='Place some default text before searching.'

// If you only want to search in one specific column you can specify this. If you only want to search in the first column you enter 0 here. Remove this argument or add -1 to search in all columns.
only_search_in_column='2'
]

[filtersearch]

[filtersearch] does a filter inside current html page. Specify which element you want to search within. You cah use either element type, .class_name of #id. See sample below for more arguments that can be used.

[filtersearch 

// what DOM element to search in, use element type, .class_name or #id
search_element='' 

// show table header or not when filtering
show_header_in_table='false'

// filter heading 
text='Page filter'

// class to style clear icon
clear_icon_class='delete-icon'

// clear filter text
clear_text='Clear' 

// enable or disable to set focus in filter input element on page load
set_focus_on_load='true'
]

Live samples using the plugin

Use this [filtersearch] shortcode

[filtersearch search_element='#name_table' text='Filter name in table' show_header_in_table=true clear_text='Clear filter' set_focus_on_load=false]

which enables this filter

Filter name in tableclear filter

on this table (with id name_table)

First nameLast name
EmilySmith
EdithJohnson
JohnWilliams
SophiaBrown
RobertJones
PaulaGarcia
JamieMiller
RobertDavis
MartinaRodriguez
PabloMartinez

Use this [csvsearch] shortcode

[csvsearch src='/wp-content/uploads/2021/09/sample.csv' searchtext='Search in file' format='{b}{0} {1}{/b} {2} - {3}{br/}' nothing_found_message='No hits for: ']

to show this search

for a search in this csv-sample-file. Try searching for a name (I’m using the same sampel names as in the table above) or a favorite color (pink, blue, red, …) or lucky number (3, 6, 7, …) to see the results.

Download

Download the plugin from wordpress.org.

Feel free to donate if you find the plugin useful 🙂