From 3f76395928231070118789898fff57d4ab3c5474 Mon Sep 17 00:00:00 2001 From: Meitar Moscovitz Date: Sun, 12 Mar 2017 15:43:23 -0400 Subject: [PATCH] Modify the JavaScript component so it works seamlessly with no-JS WP. With this commit, the JavaScript component now renders itself inside a `FORM` element, rather than outside. This begins addressing the issues listed in #1, and means that both JavaScript and non-JavaScript variations work; the JavaScript now creates inputs as the WordPress back-end expects them. Further, this commit also fixes the error animation, and changes the animation for when the user enters the quiz answers correctly. Previously, this component hid the comment form and revealed it when the quiz was answered, but this required rendering the quiz outside the form. With the above change, the animation has been changed to disabling the comment form's textareas and re-enabling them when the quiz is answered correctly, along with showing a bolded green success message. --- README.md | 65 ++++++++++++++++++++++++++----------------------- nrkbetaquiz.css | 46 +++++++++++++++++----------------- nrkbetaquiz.js | 46 ++++++++++++++++++++-------------- nrkbetaquiz.php | 49 +++++++++++++++++-------------------- 4 files changed, 109 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index ab0911e..a3b91e4 100644 --- a/README.md +++ b/README.md @@ -19,36 +19,41 @@ The plugin is made for Wordpress, but the JavaScript component can easily be imp If you're using a different content management system, you can still use the JavaScript component to enable this functionality on your site. -The component requires a `DIV` right before the container which holds your comment form. The `DIV` has two data-attributes: `data-nrkbetaquiz` and `data-nrkbetaquiz-error`. The `DIV` also needs the class `nrkbetaquiz`. - -`data-nrkbetaquiz-error` is a string with the error message in case the user has answered the quiz wrongfully. -`data-nrkbetaquiz` is an array with the following structure: - - [{ - text: 'Who is the current president of The Unites States?' - answers: ['Barack Obama', 'Donald Trump', 'Steve Bannon'], - correct: 1 - }, { - text: 'What is the radius of Earth?' - answers: ['6 371 kilometers', '371 kilometers', '200 kilometers'], - correct: 0 - }] - +The component requires a `DIV` to be inserted as a direct child of your comment form. The `DIV` has three `data-`attributes: `data-nrkbetaquiz`, `data-nrkbetaquiz-error`, and `data-nrkbetaquiz-correct`. The `DIV` also needs the class `nrkbetaquiz`. + +* `data-nrkbetaquiz-error` is a string with the error message in case the user has answered the quiz wrongfully. +* `data-nrkbetaquiz-correct` is a string with the success message when the user answers the quiz correctly. +* `data-nrkbetaquiz` is a [JSON](http://json.org/) array with the following structure: + + ```json + [{ + "text": "Who is the current president of The Unites States?", + "answers": ["Barack Obama", "Donald Trump", "Steve Bannon"], + "correct": 1 + }, { + "text": "What is the radius of Earth?", + "answers": ["6,371 kilometers", "371 kilometers", "200 kilometers"], + "correct": 0 + }] + ``` Here's a full example of the implementation: - -
-
- -
+```html +
+ +
+
+``` diff --git a/nrkbetaquiz.css b/nrkbetaquiz.css index 253ad93..5af1bea 100644 --- a/nrkbetaquiz.css +++ b/nrkbetaquiz.css @@ -1,27 +1,27 @@ -.nrkbetaquiz, -.nrkbetaquiz + * { - overflow: hidden; - transition: .5s; - height: 0; -} -.nrkbetaquiz { height: auto } -.nrkbetaquiz label { - cursor: pointer; - display: inline-block; - margin: 0 7px 6px 0; - border-radius: 5px; - padding: 10px 15px; - background: #eee; - transition: .2s; +.nrkbetaquiz label.answer { + cursor: pointer; + display: inline-block; + margin: 0 7px 6px 0; + border-radius: 5px; + padding: 10px 15px; + background: #eee; } .nrkbetaquiz label:hover { - background: #ccc; + background: #ccc; +} +.nrkbetaquiz p.correct, +.nrkbetaquiz p.error { + font: inherit; + animation: .5s nrkbetaquiz; +} +.nrkbetaquiz p.correct { + color: green; + font-weight: bold; +} +.nrkbetaquiz p.error { + color: red; } -.nrkbetaquiz h3 { - color: red; - font: inherit; - animation: nrkbetaquiz forward; +@keyframes nrkbetaquiz { + from { transform: scale(0); } + to { transform: scale(1); } } -@keyframes nrkbetaquiz{ - from{transform:scale(0)} -} \ No newline at end of file diff --git a/nrkbetaquiz.js b/nrkbetaquiz.js index 490dbd7..f1fc047 100644 --- a/nrkbetaquiz.js +++ b/nrkbetaquiz.js @@ -6,18 +6,9 @@ document.addEventListener('DOMContentLoaded', function(){ catch(err){return []} }; - var removeQuiz = function(quizNode, formNode){ - quizNode.style.height = quizNode.offsetHeight + 'px'; - formNode.style.height = formNode.scrollHeight + 'px'; - quizNode.style.height = '0px'; - setTimeout(function(){ - quizNode.style.display = 'none'; - formNode.style.height = 'auto'; - }, 500); - }; - var buildAnswer = function(text, name, value){ var label = document.createElement('label'); + label.className = 'answer'; var input = label.appendChild(document.createElement('input')); var title = label.appendChild(document.createTextNode(text)); @@ -28,11 +19,15 @@ document.addEventListener('DOMContentLoaded', function(){ }; var buildQuiz = function(quizNode){ - var formNode = quizNode.nextElementSibling; + var formNode = quizNode.parentNode; var errorText = quizNode.getAttribute('data-' + NRKBCQ + '-error'); + var correctText = quizNode.getAttribute('data-' + NRKBCQ + '-correct'); var questions = parseQuiz(quizNode.getAttribute('data-' + NRKBCQ)); var correctId = NRKBCQ + location.pathname + questions.map(function(q){return q.correct}).join(''); - var errorNode = document.createElement('h3').appendChild(document.createTextNode(errorText)).parentNode; + var errorNode = document.createElement('p').appendChild(document.createTextNode(errorText)).parentNode; + errorNode.className = 'error'; + var correctNode = document.createElement('p').appendChild(document.createTextNode(correctText)).parentNode; + correctNode.className = 'correct'; var container = document.createElement('div'); if(localStorage.getItem(correctId) === correctId){ //Skip quiz if already solved @@ -47,20 +42,35 @@ document.addEventListener('DOMContentLoaded', function(){ .forEach(function(node){node && container.appendChild(node)}); }); + // Disable form textareas until quiz is answered correctly. + var el; + formNode.querySelectorAll( 'textarea' ).forEach( function (el) { + el.setAttribute( 'disabled', 'disabled' ); + }); + quizNode.appendChild(container); quizNode.addEventListener('change', function(){ var checked = questions.map(function(q,i){return container.querySelector('input[name="' + NRKBCQ + i + '"]:checked')}); var correct = questions.every(function(q,i){return checked[i] && Number(checked[i].value) === Number(q.correct)}); var failure = !correct && checked.filter(Boolean).length === questions.length; - if(correct){ - localStorage.setItem(correctId, correctId); - removeQuiz(quizNode, formNode); - }else if(failure){ - container.appendChild(errorNode); + if ( correct ) { + if ( el = quizNode.querySelector('.error') ) { + el.parentNode.removeChild( el ); + } + localStorage.setItem( correctId, correctId ); + container.appendChild( correctNode ); + formNode.querySelectorAll( 'textarea' ).forEach( function (el) { + el.removeAttribute( 'disabled' ); + }); + } else if ( failure ) { + if ( el = quizNode.querySelector('.correct') ) { + el.parentNode.removeChild( el ); + } + container.appendChild( errorNode ); } }); }; [].forEach.call(document.querySelectorAll('.' + NRKBCQ), buildQuiz); -}); \ No newline at end of file +}); diff --git a/nrkbetaquiz.php b/nrkbetaquiz.php index d6b8eb2..da8fcf9 100644 --- a/nrkbetaquiz.php +++ b/nrkbetaquiz.php @@ -25,14 +25,13 @@ wp_enqueue_style( NRKBCQ, plugins_url( 'nrkbetaquiz.css', __FILE__ ) ); }); -add_action( 'comment_form_before', 'nrkbetaquiz_form' ); +add_action( 'comment_form_top', 'nrkbetaquiz_form' ); /** - * Prints the commenting quiz before WordPress's comment form. + * Prints the comment quiz atop WordPress's comment form. * - * @TODO This functionality should be moved into the `nrkbetaquiz_form_top()` - * function, but I don't want to move it quite yet because I'm not yet - * touching any of the JavaScript, and a lot of the code still uses - * DOM hierarchy to function properly. + * This outputs the JavaScript-hooked element and initial greeting. A + * different function, `nrkbetaquiz_form_no_js`, prints the HTML-only + * version of the same quiz and is used when JavaScript is disabled. */ function nrkbetaquiz_form() { global $post; @@ -40,35 +39,31 @@ function nrkbetaquiz_form() { ?>
="" - data--error=""> + data--error="" + data--correct="" + >

-

ID, NRKBCQ ); $answer_hash = hash( 'sha256', serialize( $quiz ) ); ?>