I often need to customize existing software and plugins. Recently had to apply flashy UI for one of the most popular WordPress quiz plugins – WatuPRO.
Instead of selecting radio buttons and checkboxes and radio buttons, the user had to be able to click on rectangles and get a correct / incorrect checkmark right away.
And this has to happen without touching the original plugin code! How? Read on.
But first see how the modified quiz looks here.
How Do You Customize Something Without Touching Its Code?
A well structured HTML code (fortunately this is the case with WatuPRO) is easy to be modified by applying Javascript and CSS to it. This Jjavascript and CSS code can reside in completely different file and just be included on the page. In our WordPress example this happens by adding another plugin.
The CSS (Turn Radio Buttons and Checkboxes Into Clickable Rectangles)
The CSS code of this project isn’t anything that special. We just need to hide the radio and checkbox buttons in the div:
.watupro-question-choice input[type="radio"].answer { display: none !important; padding: 5px; } .watupro-question-choice input[type="checkbox"].answer { display: none !important; }
In this case the wrapper div has class “watupro-question-choice”. You’ll need to change the class if you are working on a different project. If there is no class at all, and you can’t change the source code, you can change the behavior on the whole page (without class), but I don’t recommend it.
Making the visible rectangles is trivial and you can have your own ideas:
div.watupro-question-choice { display: block; cursor: pointer; padding: 5px; margin: 5px; background-color: '.get_option('wtpsd_default_color').'; }
We also have to add some classes for pressed div, and correct / incorrect answer:
.wtpsd-checked { background-color: '.get_option('wtpsd_checked_color').' !important; } .wtpsd-correct { background-image:url(correct.png); background-repeat: no-repeat; background-position: 90% 50%;; } .wtpsd-wrong { background-image:url(wrong.png'); background-repeat: no-repeat; background-position: 90% 50%;; }
That’s it. Just some nice styling. But how to we make this actually work?
Making Things Work (The JavaScript)
There are three things we need to make happen here:
- Make clicking on a rectangle change its color and actually check the hidden radio button or checkbox
- Get the response from the server so we can apply the wtpsd-correct or wtpsd-wrong class
- If the question contains set of radio buttons, disallow further changes (because the user saw the answer). If it’s a set of checkboxes, disallow de-selecting the current answer (because they already know if it’s correct or not).
Here’s how to do it (please read the comments inside the code):
// first, wrap in document.loaded handler: jQuery(function() { // attach click event on all wrapping divs. If you don't have such, use whatever parent element there is jQuery('.watupro-question-choice').click(function() { var inputs = jQuery(this).find('input').css('class', 'answer'); // we are finding all the radio buttons or checkboxes in the question here parent = jQuery(this).parent(); var divs = jQuery(parent).find('.watupro-question-choice'); // find all other divs, wrapping radio buttons / checkboxes in this question var currentInput = inputs[0]; // this is the current radio button or checkbox if(currentInput.type == 'radio') { // need to see if there is any checked, if there is, it can't be changed var anyChecked = false; jQuery(divs).each(function(i){ if(jQuery(divs[i]).hasClass('wtpsd-checked')) anyChecked = true; }); if(anyChecked) return false; // go throguh all divs to uncheck them jQuery(divs).each(function(i){ jQuery(divs[i]).removeClass('wtpsd-checked'); }); currentInput.checked = true; // check the current radio jQuery(this).addClass('wtpsd-checked'); wtpsdDisplayResult(currentInput); // call the ajax function to get the result } else { // handling checkboxes // unchecking cannot be done if result is displayed if(currentInput.checked) return false; currentInput.checked = !currentInput.checked; // check the checkbox // apply or remove the class if(currentInput.checked) jQuery(this).addClass('wtpsd-checked'); else jQuery(this).removeClass('wtpsd-checked'); wtpsdDisplayResult(currentInput); // call the ajax function to get the result } }); // now apply the checked class to all divs that contain checked checkbox or radio button jQuery('.watupro-question-choice > input:checked').each(function(){ var parent = jQuery(this).parent(); jQuery(parent).addClass('wtpsd-checked'); }); });
The main thing here is to use the jQuery find() function to catch the radio button or checkbox contained in the div which the user has clicked. Find also the div’s parent so you can find the other divs of the same class.
The rest is just checking / unchecking and setting CSS classes.
Finally we only have to send Ajax request to some server-side script which will verify the answer, figure if it’s correct or not, and return 1 or 0 (we’ll leave the server-side work for you):
function wtpsdDisplayResult(input) { if(!input.checked) return false; // get value and answer ID var val = input.value; var answerID = input.id.split('-')[2]; var parent = jQuery(input).parent(); var data = {'answer_id': answerID, 'value' : val}; jQuery.post('server-url.php', data, function(msg){ if(msg == '1') jQuery(parent).addClass('wtpsd-correct'); else jQuery(parent).addClass('wtpsd-wrong'); }); }
Share Your Thoughts