1

I have a survey-type form that's being populated from a web database on the client. I can populate the questions fine, but then I try to go through and trigger the click event where there is an existing answer (edit scenario), I'm finding that the new elements are not yet in the DOM so this doesn't work. Here's the code:

$(function() {
    var db = openDatabase(...);
    db.transaction(function(tx) {
        tx.executeSql("select ....", [surveyId], function(tx, results) {
            var items = "", answers = [];
            for (var i = 0; i < results.rows.length; i++) {
               var id = results.rows.item(i).id;
               items += "<div><input type='radio' name='q-" + id + "' id='q-" + id + "-1' /><label for='q-"+id+"-1'>Yes</label><input type='radio' name='q-" + id + "' id='q-" + id + "-2' /><label for='q-"+id+"-2'>No</label></div>";
               if (result.rows.item(i).answer) {
                   answers.push('#q-'+id+'-'+results.rows.item(i).answer);
               }
            }
            $('#questions-div').append(items);
            $.each(answers, function(i, e) { $(e).click(); });
        });
    });
});

Any tips how I can make this work, or better generally?

1
  • @mikerobi, me too, sorry if I came over a bit strong Commented Nov 1, 2010 at 23:33

3 Answers 3

1

I think here:

answers.push('#q-'+id+'-'+result);

You meant to push this:

answers.push('#q-'+id+'-'+result.rows.item[i].answer);

Otherwise you're getting '#q-XX-[object Object]' as a selector, where I think you're after the 1 or 2 version of '#q-XX-1'.

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

13 Comments

@Nick sorry, typo, was tidying up the code to make it "web-friendly"
@Jon - what is .item(i)? That's not an appropriate array accessor, it should be .item[i]...if you don't post your actual code, we can't help you, don't change all the code when it gets posted...you just introduce new irrelevant problems.
@Nick I'm not 100% sure - it appears the result.rows object from a web SQL database query isn't an array. I've been working from html5doctor.com/introducing-web-sql-databases - it uses it, and that part works fine in my code. I just removed stuff that is confidential from the code and I messed that little bit up...
@Nick - This looks like it is for Safari or Mobile Safari. That's how you iterate through a local record set.
...and quoting from that link "The callback receives the transaction object (again) and the results object. The results object contains a rows object, which is array-like but isn’t an array. It has a length, but to get to the individual rows, you need to use results.rows.item(i), where i is the index of the row."
|
1

I suspect this is actually a race condition. My bet is that if you execute your each statement after a tiny delay, things will work as expected. Is so, the reason for this is that you can't be 100% sure when the browser will actually get around to updating the DOM when you programmaticallly insert new elements. I'm not sure what the best solution would be: if you were attaching events, I'd say you should do it at the same time you are building the elements; but if you are triggering the clicks, I'm leaning toward just continually testing for the existance of the elements and then triggering the clicks as soon as you know they are there.

3 Comments

I was trying to do that earlier, but as in the comment stream on Nick's answer, if I alert the length of the selector it's 1, which would be my detecting that they're there...
What happens if you replace the last line with this: setTimeout(function() {$.each(answers, function(i, e) { $(e).click(); }); }, 1000);
it seems to work sometimes which definitely suggests a race condition. I came up with a workaround - see my answer...
0

So I came up with a solution:

I replaced the line items += "<div> ...." with

var item = "<div><input type='radio' name='q-" + id + "' id='q-" + id + "-1' ";
if (results.rows.item(i).answer == 1) item += "checked ";
item += "/><label for='q-"+id+"-1'>Yes</label><input type='radio' name='q-" + id + "' id='q-" + id + "-2' ";
if (results.rows.item(i).answer == 2) item += "checked ";
item += "/><label for='q-"+id+"-2'>No</label></div>";
items += item;

... which means I no longer need the answers array or to trigger click events on the radio buttons.

I was hoping for something a bit neater, but this seems to work OK. Thanks @Nick Craver & @Andrew for helping me arrive at it!

Comments

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.