Sorin Coza http://localhost/sorincoza.com/blog-wp Just another web blog. Tue, 30 Aug 2016 10:46:43 +0000 en-US hourly 1 https://wordpress.org/?v=4.4.4 PayPal setup with WooCommerce http://localhost/sorincoza.com/blog-wp/paypal-setup-with-woocommerce/ Tue, 30 Aug 2016 10:40:30 +0000 http://localhost/sorincoza.com/blog-wp/?p=100 I find PayPal to be very difficult to use in general. Even for everyday stuff. But this is especially true when you’re a developer and need to test things. Their developer website is sooo confusing…

So recently I needed to setup PayPal with WooCommerce on WordPress, and it was a nightmare, which is why I need to document the process here for you (the reader) and me (the frustrated developer).

First, let’s set up a sandbox account for testing.

Go to developer.paypal.com and create a test account. You’ll probably need to login with your “real” PayPal account the first time, but then you’ll only need to use the sandbox account and password (this is yet another confusing thing).

Then, let’s change the settings

Then you’ll need to set up some options for payments. You’ll never find the page that WooCommerce is reffering to, because PayPal is very confusing, so here is the direct link for both when you will set this up live and when in sandbox mode:

]]>
Create a “long-press” click event http://localhost/sorincoza.com/blog-wp/create-a-long-press-click-event/ Sun, 20 Mar 2016 15:54:29 +0000 http://localhost/sorincoza.com/blog-wp/?p=90 I needed an event for a “long press” with the mouse, or a “long touch” event on the mobile devices. This one does the following:

  • depends on jQuery
  • prevents the “click” event from firing, in case the “longpress” event occurs
  • “longpress” does not fire if the mouse leaves the element during pressing
  • the following examples attaches to all elements specified by the selector
(function( selector ){
	var $ = ( typeof jQuery !== 'undefined' )  ?  jQuery  :  false;
	if( !$ ) return;


	var isLongClick = false,
		isMouseIn = false,
		pressTimer,
		pressDelay = 1000; // ms

	$(selector)
		.on( 'mousedown touchstart', function(e){
			var $this = $(this);

			pressTimer = window.setTimeout(function() {
				if( typeof e.button !== 'undefined'  &&  e.button !== 0 ) return;  // prevent trigger on right-click
				if( isMouseIn ){  
					isLongClick = true;
					$this.trigger( 'longpress' );
					e.preventDefault();
					e.stopPropagation();
					e.stopImmediatePropagation();
				}
			}, pressDelay);

		} )
		.on( 'mouseup touchend', function(e){
			clearTimeout(pressTimer);
		} )
		.on( 'click', function(e){
			if( isLongClick ){
				isLongClick = false; // reset this flag (it has done its part)
				e.preventDefault();
				e.stopPropagation();
    			e.stopImmediatePropagation();
    			return false;
			}
		} )
		.on( 'mouseover touchstart', function(e){
			isMouseIn = true;
		} )
		.on( 'mouseout touchleave touchcancel', function(e){
			isMouseIn = false;
		} )
	;
})( '.btn' );
]]>
Improve Big Query Performance in WP http://localhost/sorincoza.com/blog-wp/improve-big-query-performance-in-wp/ Sat, 13 Feb 2016 09:53:09 +0000 http://localhost/sorincoza.com/blog-wp/?p=83 I was working on a site that had some custom posts and a lot of terms associated with that custom post type. After a while, we noticed that the search function is getting slower and slower, as the custom posts piled up. Sometimes, the time if took for the search to complete was more than a minute. Other times, it just gave back an error. So I knew I had do do something about this.

The thing is, when you have custom post types in WordPress, you’ll probably need at some point to make a custom query to the database. This can be quite easily done using the built-in class WP_Query, which can do just about anything you can think of. The problems start to appear when you have a relatively large database, and you do a big query on it.

What happens is that WP_Query returns an object that contains all the information about all the custom posts that you are querying. And trust me, every post contains a lot of information. So where is all this data stored after the query? In the RAM of course!

Our search function was doing just this: using WP_Query to get all the posts at once, then looping through them. When I did some tests to find out the memory usage of every search operation, I discovered that it uses quite a lot of RAM, and the amount increases with the search complexity and the number of results. The usage was often exceeding the allocated amount of 128 MB of memory per request.

The solution was to add an argument that limits the amount of data that is being stored in our query object, named fields.

// setup our args:
$args = array(
    'fields' => 'ids',
    // ... [other arguments that you need]
);

// get the query object that contains ids of posts:
$query = new WP_Query( $args );

// get only ids from object to loop them:
$ids = $query->posts;

// slightly rewrite the loop:
foreach( $ids as $id ){
    $post = get_post( $id );
    // ... [now do the other stuff with the $post]
}

The result

The result was amazing: memory usage improved 7 times, and execution time was 3 times faster for the usual searches, on average. The search function never crashed again, even though the posts kept multiplying, and continue to do so up until this day. And everyone lived happily ever after. The end.

]]>
How to add custom shortcodes in CF7 http://localhost/sorincoza.com/blog-wp/how-to-add-custom-shortcodes-in-cf7/ Wed, 16 Dec 2015 17:59:22 +0000 http://sorincoza.com/blog/?p=57 Sometimes, the types of fields that are available by default in Contact Form 7 are just not enough. And sometimes, you want to just be able to use a shortcode when you define the form . For such situation, we can use the wpcf7_add_shortcode() function, combined with the wpcf7_init hook.

Documentation

The wpcf7_add_shortcode() function takes 3 arguments:

  • $shortcode, which is our shortcode name, exactly as in WordPress;
  • $callback, which is a function that will be called when the shortcode is encountered, exactly as in WordPress;
  • $has_name_part, which is boolean and false by default, but if it is set to true, then the shortcode can be used with a name, for example: '[my_shortcode field-name]', just how you would use a usual CF7 field: '[text* your-name]'

Find all details on the Contact Form 7 site’s documentation page: Adding a custom form-tag.

Example

add_action( 'wpcf7_init', 'create_my_custom_cf7_shortcodes' );

function create_my_custom_cf7_shortcodes(){
    wpcf7_add_shortcode( 'lots_of_checkboxes', 'render_checkboxes' );
}

function render_checkboxes(){
    // Construct checkboxes HTML here...
    return $html;
}

Now we can use this when we are defining the form fields: [lots_of_checkboxes], which will output whatever the render_checkboxes() function decides.

]]>
Useful hooks in CF7 http://localhost/sorincoza.com/blog-wp/useful-hooks-in-cf7/ Wed, 16 Dec 2015 17:25:27 +0000 http://sorincoza.com/blog/?p=50 Contact form 7 has a few hooks that you can use to customize your forms. Here is a list of those hooks that I think are the most helpful.

wpcf7_init

This is great if you want to add custom shortcodes to be handled by Contact Form 7. The shortcodes can be used in your Dashboard when you define the form fields. More details here: How to add custom shortcodes in CF7.

wpcf7_before_send_mail

This is fired just before the mail is sent. By this time, all validations have passed.

wpcf7_mail_sent

This is fired after the mail was sent. By this time, the $_POST is empty. Check this post for details on how to manipulate posted data in this hook: How to correctly get posted data in CF7.

wpcf7_validate_{$field_type}

This is a filter that helps us to validate fields using our own custom rules. Read this post for more information on how to do that: How to validate a field in CF7.

]]>
How to correctly get posted data in CF7 http://localhost/sorincoza.com/blog-wp/how-to-correctly-get-posted-data-in-cf7/ Wed, 16 Dec 2015 17:08:44 +0000 http://sorincoza.com/blog/?p=46 In Contact Form 7, if you hook into wpcf7_mail_sent, then  the $_POST variable is empty, so you cannot use it to do stuff with it. You are too late. However, there is a way to get around this: you have to use Contact Form 7 built-in functions to get the posted data.

$submission = WPCF7_Submission::get_instance();
if ( $submission ) {
    $form_data = $submission->get_posted_data();

    // now $form_data contains the form values,
    // so you can do, for example $form_data['email'], instead of $_POST['email']

}else{
    // we got nothing; something went wrong
}

That’s it.

]]>
How to validate a field in CF7 http://localhost/sorincoza.com/blog-wp/how-to-validate-a-field-in-cf7/ Wed, 16 Dec 2015 16:46:56 +0000 http://sorincoza.com/blog/?p=36 What we need:

  • a filter 'wpcf7_validate_{$field_type}', which will filter the fields by type;
  • a function, which takes 2 arguments from Contact Form 7:
    • $result, which can be validated or invalidated before it is returned;
    • $tag, which helps us to identify the field by its name.

The {$field_type} is the exact field type that you have defined in your form, for example: text, text*, textarea, textarea*, email, etc.... The asterisk is used to indicate a required field, and yes, it has to be specified in the hook ( text is different from text* ).

Example

// hook our function:
add_filter( 'wpcf7_validate_text*', 'validate_phone', 20, 2 );

// define the function:
function validate_phone( $result, $tag ){

    // check if this is our phone field, and return the $result unchanged if it isn't:
    $tag = new WPCF7_Shortcode( $tag );
    if ( $tag->name !== 'phone' ){ return $result; }

    // if we got this far, then this is our phone input - we check to see if it is valid
    // assuming we have a function somewhere named "is_valid_phone"
    if( ! is_valid_phone('phone') ){
        $result->invalidate( $tag, 'This phone number is not valid! Please try again.' );
    }

    // finally, return the result:
    return $result;
}
]]>
Do you really need jQuery? http://localhost/sorincoza.com/blog-wp/do-you-really-need-jquery/ Sat, 12 Sep 2015 16:49:46 +0000 http://sorincoza.com/blog/?p=5 jQuery has become so popular that it is often confused with JavaScript itself. Many times when searching for a JavaScript answer on the internet, you bump into a jQuery solution, which fails to mention that it is jQuery. It is just assumed that everyone in the Universe is using jQuery!

So there is no wonder that so many sites use it. But the problem is when it is used for just a couple of simple operations (like hiding an element, or changing some of its style). The whole thing may go down something like this: the developer (or site owner) needs to toggle the visibility of an element. He/she searches online for an answer. The answer appears to be simple:

$( '#myButtonID' ).on( 'click', function(){
    $( '#myElementID' ).toggle();
});

So simple, right? It just so happens that jQuery has exactly the function that is needed. But now jQuery has to be included into the page, so this has to be included before the other script:

<script src="/path/to/jquery.min.js"></script>

And the above script has to be loaded first, and is no negligible size: the latest version is more than 80KB. But size is not the biggest issue here. The biggest issue is that it is 80KB of JavaScript code, which has to be parsed, and nothing else can execute until the jQuery file parsing is done. It is said to be a blocking resource, because it blocks everything else while it is loading.

These things add up and can noticeably increase the site loading time. This is bad, because everybody knows by now that the bounce rate of any website increases as the loading time increases. So, is it worth losing visitors just to get a HTML element to toggle? I would say no. That’s why I want to mention some ideas to these simple tasks:

1. Use document.getElementById() whenever you can

This JavaScript function is the mother of all. It is fast and works in most browsers, even ancient ones like Internet Explorer 5.5. So, instead of jQuery statement $( '#myID' ), use the pure JavaScript version of it: document.getElementById( 'myID' ). Read some documentation on Mozilla website: MDN.

2. When the above is not possible, use document.querySelector()

This is a general purpose function, that lets you select elements exactly like you do in jQuery when the selector is more complicated than just an ID. The function will return the first element that matches your selector. So, for example, something like $( '#myID .myClass' ) can be easily replaced by document.querySelector( '#myID .myClass' ).

This function works in Internet Explorer 8 and up. Documentation here.

3. Use the good old onclick, and his friends

OK, I know this should not be encouraged, since modern browsers have addEventListener() now, but that is not supported by some Internet Explorer versions, which are still in use among web-surfers. So if you don’t want (or don’t know how) to work around this issue, then the best thing is to just use onclick. It is guaranteed to work in all browsers, because even new browsers have to provide backward compatibility for this feature – they can’t just throw it away, since many websites still use it.

So, instead of writing $( element ).on( 'click', callbackFunction ), you can very safely use element.onclick = callbackFunction

Putting it all together

So now that we have replacements for jQuery functions, let’s try to “translate” the example from the beginning of the article. To do this, we have to emulate the .toggle() function. We can do it in pure JavaScript, but it is a bit more complicated than the second option – which is to use a CSS class to hide the element. Sure, this means you’ll have to write a few lines of CSS code, but the advantage is that it will be faster, and you can do more stuff with your element – like making it disappear in a cloud of smoke (which is not easy to do with jQuery!).

I always prefer the CSS way in such situations. After all, it was built to style DOM elements, whereas JavaScript and jQuery are not so efficient at this kind of tasks. So what we will do is add a class named hidden to our element whenever we want to hide it. Here it goes:

// get the element to be hidden and store it in this variable:
var myElement = document.getElementById( 'myElementID' );

document.getElementById( 'myButtonID' ).onclick = function(){
    
    // check if the element is hidden, and act accordingly:
    if ( myElement.className.indexOf( 'hidden' ) > -1 ){
        myElement.className = myElement.className.replace( ' hidden', '' );  // remove "hidden"
    }else{
        myElement.className += ' hidden';  // add "hidden"
    }
};

That wasn’t so bad, was it? And the best thing is that you can put anything you want in that hidden class!

]]>