2

I have a list of multiple choice questions:

<div class="question active">
    <p>The first counting tool was the _____.</p>
    <button class="btn-a">A) Stepped Reckoned</button>
    <button class="btn-b">B) Abacus</button>
    <button class="btn-c">C) Aba Zaba</button>
    <button class="btn-d">D) Punch Card</button>
</div>
<div class="question">
    <p>Who founded IBM and was responsible for tabulating the US Census with a punch card tabulator in only six weeks?</p>
    <button class="btn-a">A) Jacquard</button>
    <button class="btn-b">B) Hollerith</button>
    <button class="btn-c">C) Mark I</button>
    <button class="btn-d">D) Babbage</button>
</div>

How can I trigger each of these buttons to submit with the corresponding letter on the keyboard?

The keyboard should only work with the .active question.


Bonus:

Is it possible to allow two keys to trigger the question? For example, since ABCD are spaced around the keyboard it may also be helpful to allow QWER or JKL; to correspond to ABCD to make it easy for one hand keyboard entry.

4
  • 1
    You should close the quotes on your class attributes Commented Jul 23, 2013 at 15:36
  • 1
    And how about something like: jsfiddle.net/6RRMJ Commented Jul 23, 2013 at 15:39
  • @Ian, you should submit that as an answer. Very well done. I think I'll run with that, then add the active class to the next question on key entry (and remove from current question). Commented Jul 23, 2013 at 15:46
  • 1
    Thanks :) I just added an answer (I updated the fiddle quite a bit too). I hope it helps! Commented Jul 23, 2013 at 16:29

1 Answer 1

1

Using the keyup event, you can listen for the user releasing a key. You can then translate it to a letter (or an arrow key, in my example), and access the appropriate question/button. You can try something like this:

$(document).ready(function () {
    var $questions = $("div.question"),
        $activeQuestion = function () {
            return $questions.filter(".active");
        },
        $prevQuestion = function (setActive) {
            var $prev;
            $prev = $activeQuestion().prevAll(".question").first();
            if ($prev.length === 0) {
                $prev = $questions.last();
            }
            return $prev;
        },
        $nextQuestion = function () {
            var $next;
            $next = $activeQuestion().nextAll(".question").first();
            if ($next.length === 0) {
                $next = $questions.first();
            }
            return $next;
        };

    $(document).on("keyup", function (e) {
        var key, character, $active, $next, $prev;
        key = e.which;
        switch (key) {
            case 37:
            case 38:
                $prev = $prevQuestion();
                $questions.removeClass("active");
                $prev.addClass("active");
                break;
            case 39:
            case 40:
                $next = $nextQuestion();
                $questions.removeClass("active");
                $next.addClass("active");
                break;
            default:
                character = String.fromCharCode(key).toLowerCase();
                $active = $activeQuestion();
                $active.find("button").removeClass("selected").filter(".btn-" + character).addClass("selected");
                break;
        }
    });
});

DEMO: http://jsfiddle.net/wdXkB/1/

I took it a little far, but I added the ability to use arrow keys to move to the next question (down and right arrows) or previous question (up and left arrows).

Sign up to request clarification or add additional context in comments.

2 Comments

This is looking great! One question on the "extra credit"... I can get next question working with down or right arrow, but not previous. Could it be that my keyboard isn't mapped the same as yours? UPDATE: Strange, the keycodes map fine at unixpapa.com/js/testkey.html but still don't trigger for up or left on your fiddle. Will update when finished debugging.
@Ryan Thank you :) And sorry about that, typo on my part; I can't believe I didn't see that before. I think it's because I went back and renamed things and forgot to re-test one last time. I had return prev;, but it should've been return $prev;. I updated my code and fiddle. It seems to be working now :) Let me know if you need more help with it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.