Monthly Archives: June 2013

PHP Autoresponder Basic and PRO Upgrade

There has been a new release to the PHP autoresponder app.
(Please note this is not the WordPress plugin “Broadfast for WordPress”. That one will be upgraded soon)

Besides some bug fixes there are two most important changes:

1. You can now control the contents of subscribe/unsubscribe notification emails (both Basic and PRO)
2. There are much better link tracking stats for trackable links (Pro only)

Upgrading is free for customers who bought less than one year ago, and costs 40% of the full price for customers who bought before that.

Conditionally Load Scripts and CSS in WordPress Plugins That Use Shortcodes

The official way of loading javascript and CSS files in WordPress is by loading your scripts on wp_enqueue_scripts hook. The problem with this approach is that every single plugin you use will be adding its own scripts and CSS even if its used just once in a single post or page. This approach can quickly overload your blog with CSS files and scripts which you don’t use on most pages.

This is especially true for plugins that use shortcodes.

There is an easy way to solve this!

Due to the holes in the official WordPress documentation most developers are not using it.
Others has to develop smart but no longer necessary hacks like this here. The problem with the proposed solution on that page are at least three:

  • Unnecessary complexity in the code
  • Consuming extra server cycles
  • It will sometimes load your scripts when you don’t need them. For example in my theme the solution was still loading the scripts everywhere because of the loop of “Recent posts” in the sidebar.

So, this is far from perfect. Here is the simplest solution:

Call wp_enqueue_script inside the shortcode functions

It’s really that simple and we are starting to use this approach in our WatuPRO. WordPress handles  this from version 3.3 so you need to use the old “load everywhere” solution for older versions.

Here is a code example of this technique from WatuPRO:

[sourcecode language=’php’]
// this is in our init function. If version is 3.3 or lower we just use the official way
$version = get_bloginfo(“version”);
if($version <= 3.3) add_action("wp_enqueue_scripts", "watupro_vc_scripts"); // then in our shortcode handlers we simply call watupro_vc_scripts directly: function watupro_shortcode($attr) { watupro_vc_scripts(); // ..... } [/sourcecode] Inside watupro_vs_scripts() there are all the wp_register_script and wp_enqueue_script calls. This seems to work fine on all versions. If you have any comments, please let me know.

Dynamically Add Input Form Fields With jQuery

And how to deal with the data on the server-side (PHP)

A very frequent requirement from customers is to have input fields dynamically added to a form while typing in it. This should happen without refreshing the page because the user shouldn't be submitting the form before all their information is completed. Here below is a simple example of such interface:
Item quantity: Item name:

Click on the "Add Row" button and you'll see it in action. Ever wondered how to do something like this? Let me show you.

Download Working Example Here!
(some fixed to the code are added inside)

The HTML

The HTML code for this is actually quite simple. It's just a form with onclick action at the "Add row" button:
<form method="post">
<div id="itemRows">

Item quantity: <input type="text" name="add_qty" size="4" /> Item name: <input type="text" name="add_name" /> <input onclick="addRow(this.form);" type="button" value="Add row" />

</div>
</form>

The JavaScript (jQuery)

If you had to do this with basic Javascript, it would require lots of typing. But the jQuery's html() method takes all the browser-related hassle out of you, so you can just construct your HTML code and append it when the button is clicked:
var rowNum = 0;
function addRow(frm) {
rowNum ++;
var row = '<p id="rowNum'+rowNum+'">Item quantity: <input type="text" name="qty[]" size="4" value="'+frm.add_qty.value+'"> Item name: <input type="text" name="name[]" value="'+frm.add_name.value+'"> <input type="button" value="Remove" onclick="removeRow('+rowNum+');"></p>';
jQuery('#itemRows').append(row);
frm.add_qty.value = '';
frm.add_name.value = '';
}
This function simply constructs HTML code for a new row while filling the form field values from the data supplied by the form. Then it appends the code to the wrapper DIV element and cleanups the values in the original form. Cleaning up the values is good user experience practice in such cases. Otherwise the user will be confused whether the first row will be stored to the database or not. The added rows don't have another "add row" button. Instead of this they have "remove" button in case the user has added too many rows and wants to delete some of them. Here is the removeRow() function:
function removeRow(rnum) {
jQuery('#rowNum'+rnum).remove();
}
Now you can see why we needed to count the rows and to use that rowNum global variable. We needed unique ID on each row so it can be removed.

The Back-End (PHP) - Inserting the records

At the server-side there is a straighforward and a tricky part. I'll show you the easy one first - inserting the data. Let's assume we have a MySQL database and a very simple table called products with fields id, qty and name. So when processing the POST data we'll do something like this:
foreach($_POST['qty'] as $cnt => $qty) {
$sql = "INSERT INTO products (qty, name) VALUES ('$qty', '".$_POST['name'][$cnt]."');";
// run the query - with mysqli_query or whatever database wrapper you are using
// ...
}
(Please note there is no security filtering done in the query above) In case you don't understand, here's the explanation: as the field names had [], in PHP this will send $_POST array with the name of the field and the values from all form fields with this name. So we are iterating through the $_POST array 'qty' while taking the current index in $cnt. Then we use the same $cnt to match the same row value in $_POST['name']. And that's it, the data is inserted.

The Back-End (PHP) - Updating the records

This is where the things become tricky. We have several goals:
  • To let the user see and edit already inserted data
  • To let the user add new data
  • To let the user remove data
This means we have to construct some more HTML and basically break it in two parts - editing existing data and adding new data. The HTML/jQuery code for adding new data will be exactly the same as above. So let's see what can we do with the existing data:
// let's assume you have the product data from the DB in variable called $products
foreach($products as $product):?>
<p id="oldRow<?=$product['id']?>">Item quantity: <input type="text" name="qty<?=$product['id']?>" size="4" value="<?=$product['qty']?>" /> Item name: <input type="text" name="name<?=$product['id']?>" value="<?=$product['name']?>" /> <input type="checkbox" name="delete_ids[]" value="<?=$product['id']?>"> Mark to delete</p>
<?php endforeach;?>
What's going on here? We are iterating through the existing DB records and displaying similar forms for them letting the user edit the data. We also add a checkbox that allows them to mark a product for deletion. All the changes will be stored after the form is submitted. Like this:
// first delete the records marked for deletion. Why? Because we don't want to process them in the code below
if(is_array($_POST['delete_ids']) and !empty($_POST['delete_ids'])) {
// you can optimize below into a single query, but let's keep it simple and clear for now:
foreach($_POST['delete_ids'] as $id) {
$sql = "DELETE FROM products WHERE id=$id";
// run the query - not shown
}
}

// now, to edit the existing data, we have to select all the records in a variable.
$sql="SELECT * FROM products ORDER BY id";
$products = .... // run your DB wrapper methods here to fill $products

// now edit them
foreach($products as $product) {
// remember how we constructed the field names above? This was with the idea to access the values easy now
$sql = "UPDATE products SET qty='".$_POST['qty'.$product['id']]."', name='".$_POST['name'.$product['id']]."'
WHERE id='$product[id]'";
// run the query
}
// (feel free to optimize this so query is executed only when a product is actually changed)
And after the above is done, don't forget to also add the new products with the same code as in "Inserting the records" section. That's it. Was it clear and easy?

A Few Interesting Scripts

Browsing Codecanyon I've found several ready scripts that do something like what I have described above. Have a look at them and decide yourself if some of them can do the work for you: