Monday, 26 March 2012

Exam Prepration jQuery Tool

I do love 'er-indoors but she's not the most patient of people. Sure, she manages to actively listen for a while but ask her to do something that doesn't interest her and the result is obvious boredom. Which is a shame as I needed her help to revise for my DEV 401 exam.

I asked if I could borrow her for an hour or two on Saturday and Sunday. "Sure", says she in a nice surrendered wife type of way. My idea was to go through possible questions and give answers and ask her to say if I'd got it right or wrong. She agreed and we sat down but the delay of a few micro-seconds before I got a reply when I asked her a question was doing my nut in. I looked down to see her farming Smurfs or something. I really couldn't face putting her, or myself, through it all again the next day.

jQuery to the rescue!

I copied the questions I had into an array of JSON objects with the questions, the possible answers and the solution. This worked a treat as I could swap over questions easily enough and re-task it for other purposes.

I thought about trying to pluginify it but I don't really think it needs it as it takes a set of questions, answers and solutions and spits back a set of divs into the container of your choice. Props to David for the compare function.

(function(){
    prepareExam("chap1.json", "body");
    $("select#paper").on("change", function(){
        $val = $(this).val();
        $("div.question").empty().remove();
        $("div.score").empty().remove();
        prepareExam($val, "body");                    });
})();
jQuery.fn.compare = function(t) {
    if (this.length != t.length) {         return false;     }
    var a = this.sort(),
        b = t.sort();
    for (var i = 0; t[i]; i++) {
        if (a[i] !== b[i]) {             return false;
        }
    }
    return true;
};
function prepareExam(paper, target) {
    $.getJSON(paper, function(exam) {
        $.each(exam.exam, function(i, question){
            var d = $("<div></div>").addClass("question").appendTo(target);
            var q = $("<p></p>").html(i+1+". "+question.question).appendTo(d);
            var f = $("<fieldset></fieldset>").appendTo(d);
            $.each(question.answers, function(letter, possible){
                var labelID = letter+(i+1);
                $("<input></input>", {"type":"checkbox", "name":i+1,"value":letter, "id":labelID}).appendTo(f);
                $("<label></label>", {"for":labelID}).text(letter+". "+possible).appendTo(f);
                f.append('<br />');
            });
            d.data({"answer":question.solution});
            var c = $("<span></span>").addClass("check").text("Submit").button().appendTo(f).on("click", function(){
                var $parent = $(this).parent().parent();
                var allVals = [];
                $.each($parent.find("input:checked"), function(x, y){
                    allVals.push($(y).attr("value"));
                })
                if($(allVals).compare($parent.data("answer"))){
                    $parent.css("background-color","#ccffcc");
                    $parent.find("span.check").remove();
                    $parent.data({"success":true});
                }else{
                    $parent.css("background-color","#ffcccc");
                    $parent.find("span.check").remove();
                    $parent.data({"success":false});
                }
            });
            var leg = (question.solution.length !== 1) ? "answers" : "answer";
            $("<legend></legend>").text("Please choose "+question.solution.length+" "+leg+":").prependTo(f);
        });
        var s = $("<div></div>").addClass("score").appendTo(target);
        $("<p></p>").text("Ready to calculate your final score?").appendTo(s);
        $("<span></span>").addClass("final").text("Check").button().appendTo(s).on("click", function(){
            var total = 0, correct = 0;
            $.each($("div.question"), function(i, div){
                total++;
                if($(div).data("success")){
                    correct++;
                }
            });
            var l = $("<p></p>").text("Total Score = "+(((correct/total)*100).toFixed(2))+"%").appendTo($("div.score"));
            if(((correct/total)*100).toFixed(2) >= 68){
                l.css("color","green")
            }else{
                l.css("color","red")
            }
            $("span.final").remove();
        });
    });
};

As you can probably tell I used a lot of different sets of questions and I added them to a select input so I could load up a set of new questions when I'd done a paper and scored myself.

The format of the JSON should be:

{
    "exam": [
        {
            "question": "Jack and Jill went up the hill to fetch?",
            "answers": {
                "a": "A pail of water",
                "b": "Porridge",
                "c": "Vinegar"
            },
            "solution": [
                "a"
            ]
        },
        {
            "question": "What did the old woman who lived in a shoe do to her children?",
            "answers": {
                "a": "She gave them some broth without any bread.",
                "b": "She starved them.",
                "c": "She sent them to sweep chimneys.",
                "d": "She whipped them all soundly and put them to bed."
            },
            "solution": [
                "a",
                "d"
            ]
        }
    ]
}

Have fun!

I think it's lovely so by all means take it, use it and let me know if you improve it, let me see where you use it too ehh?

This is now on github.

Tuesday, 20 March 2012

Arsing data object

I don't know how many times I've had to re-research this so this is the last time as I'm going to document it!

I really like jQuery UI modal dialogs but I always have trouble getting them to do the proper thing when they've closed! Poor Alex is forever reminding me after I've spent 20 fruitless minutes looking so I'll save his sanity by noting that you can pass data to some (maybe all) UI elements.

The use case was simply that some cells within a table had to be populated with user content, it needn't be saved to the server or anything, just needed to be displayed.

It's basically done like this:

$('.editableContent').on("click", function(event) {
    $("#dialog-form").find("textarea").val($(this).text());
    $("#dialog-form").data('bob', $(this)).dialog("open");
});

Here we're adding the existing content to the textarea in the first line of the function and then adding the calling object to the data of the dialog and calling it bob (hey, it's short enough ehh?)

Then, in the dialog code:

$("#dialog-form").dialog({
    autoOpen: false,
    height: 300,
    width: 350,
    modal: true,
    buttons: {
        "Add Content": function() {
            $(this).data('bob').text($(this).find("textarea").val());
            $(this).dialog("close");
        },
        Cancel: function() {
            $(this).dialog("close");
        }
    },
    close: function() {
    }
});

The important bit here is the line:

$(this).data('bob').text($(this).find("textarea").val());

Which calls the bob bit of the data object (giving us a reference to the original td) and populating it with the content of the text area. Bloody brilliant, now I shouldn't forget it!

Saturday, 14 January 2012

More Curry

Cracking evening last night with a lovely couple of pints after work with cracking people and then out for a curry at the Bengal Diner, again with cracking old friends and perhaps a little too much wine. The food was brilliant and they don't have a licence so you get to take your own plonk, this effectively means that the wine is brilliant and the bill is small. Eventually got to bed a little after midnight. Up at silly o'clock for pee, paracetamol and lots of water then back to bed where my sleep got disturbed every single time I farted by 'er indoors complaining in some volume about the gaseous eruption transferring its way from my shapely arse onto her belly (Hey, you sleep in a small bed when you're as big as we are and you have to spoon, besides, it was that cold last night that if we hadn't we'd have frozen).

Thing is I woke about 09:45 hrs and thought I'd try something:

"It's cold out there, I'd like you to get up and put the fire on and tell me when it's warm enough for me to get out of bed. Perhaps while you're up you could put the kettle on and get breakfast started?"

Strange thing is that she did... and I've still got my testicles where they should be as well... and now she's tidying the boat - I wonder what she's setting me up for?

Wednesday, 11 January 2012

King Prawn Curry, Egg-Fried Rice And A Portion Of Chips, Please.

So the first time I ever had a Chinese takeaway, I'm pretty sure it was in Birkenhead, I had the above. Pretty much every time I've had one since I've had the same. Generally speaking if I have an Indian takeaway I'll have King Prawn Korma, Egg-Fried Rice and a Garlic Narn. I'll start with putting the Narn bread on the plate and then put the rice and curry on the Narn. That way the Narn soaks up everything and I'm left with a clean plate after eating the Narn after the curry. The Chinese just gets mixed all up in a big bowl and eaten as quick as.

What's this got to do with anything, I hear you ask in between shaking your head in wonderment, not a great deal except to illustrate that I, like a true Yorkshireman, know what I like and like what I know.

This is except when other people are involved: The Chinese was on a recommendation from the lass I was then courting as I didn't know what to order (I'm sure that there were Chinese takeaways in Huddersfield but there weren't any in the villages where I grew up - and even if there were there'd be no chance of having one, not when there was food to be cooked at home!). I'm not sure where the Indian came from but I'm nigh on positive it was either down to a lass or something I'd read or heard on the wireless.

You'll perhaps be shocked to hear that I have no firm favourites in restaurants or takeaways of other nationalities, except that I do have a penchant for anchovies on my pizzas.

I guess the reason I'm thinking about this just now is that within the 30 seconds prior to putting finger to screen I caught sight of a jar of silver-skin pickled onions that 'er indoors bought for #3 son and a packet of Marmite chocolate.

The onions were bought because #3 really likes pickled onions but really, really likes silver-skin pickled onions - preferably the cheaper the better. I'm pretty sure that that's down to him having eczema, I'm not sure what it is about kids in my family with eczema and pickled onions but there seems to be a distinct correlation between the diagnosis of one and the almost pathological desire for the other... The thing is that the jar is a fancy one, with onions pickled in balsamic vinegar bought in a sale, the thing also is the #3 is not in the least bit keen. Not cheap enough I guess?

I love Marmite and I love chocolate and when 'er indoors said that she'd heard of chocolate with Marmite I was more than keen to try some. Now I wish I hadn't as, while the idea is pretty good, the reality is not so much, not to my mind anyway!

Wednesday, 7 December 2011

Rummaging and Pilfering

I've written about Travelodge before, in the previous context I was doing some training for work in London and didn't want to cost them too much money so chose Travelodge. This time I was also conscious of money - not because we're cheap but because I'm almost a stereotypical Yorkshireman - again I'm doing some training for work so Travelodge it was. After all, not all Travelodges can be as utterly crap as the one in London I stayed in last time can they?

You know where this is going don't you?

I'm in the process of giving up smoking but in the meantime I'm reducing my consumption by the use of e-fags from Totally Wicked and as a result the paraphernalia involved gets quite bulky, what with charging equipment for USB, mains and 12V, spare-parts and various e-liquids. So I keep it all in a lovely hessian bag, which I guess is a re-purposed hand-bag curtesy of 'er-indoors.

Thing is that each and every evening I've come back to rest my head after it being crammed full of SalesForce Developer Stuff and the bags been interfered with.

The first time I guessed it might have been knocked over but this evening a zip was left open and the nice needle I use to fill up the e-liquid container was missing... I can only guess why they want a blunt hyperdermic needle!

Needless to say I'll definitely not be going for the cheapest option next time, a little bit of privacy isn't too much to ask for is it? Thankfully I'm with Jeff Jarvis in regards to privacy these days and so live my life in the full expectation that it's lived fully in public... bloody boring too!

Humph!

Wednesday, 23 November 2011

No wikipedia allowed!

Got this wrong and it cost us the wipe out round last night in the pub quiz at The Green Dragon.

If you know without checking wikipedia then I'll be blown!

Who counts the journalist Sheena McDonald and Princess Margarita of Romania amongst his ex-girlfriends?

Hint: It's not Russell Brand (which is who I thought it was, sorry chaps!).

Thursday, 10 November 2011

Walter Zorn's ToolTip

Well blow me!

Walter Zorn's tooltip is and was the bees knees in terms of tool tips and I used it extensively when I was doing my dissertation to provide context sensitive help to users. I tried to use it again recently but couldn't find his site despite it coming near the top of searches for tooltips. Then this morning I was looking for a similar thing to use at work but hopefully based on jQuery and I cam across this site (Walter Zorn’s ToolTip with a JQuery Twist).

I found a reference to him being dead on and then found this on his site:

Walter Zorn, the author of this homepage, died in 2009.
We, his familiy and friends decided to make this page available as a static page again for the friends of his homepages.
Please, be aware, that we didn’t create this homepage or any of its content, and therefore we are not able to give technical support.
Walter made the source codes publicly available under the LGPL license, so we expect that any usage of his programs will be in accordance to this license. Walter Zorns copyright notice must be untouched at all times, and must not be removed.

What a bugger! I had a brief emial conversation with him about his tooltip and he struck me as a really nice bloke, R.I.P. Mr Zorn!