views:

100

answers:

2

I started with this question: http://stackoverflow.com/questions/1875693/multiple-javascript-gadgets-per-page . After reading up on how to build a jQuery plugin I've modified my OO JavaScript object into a jQuery plugin by wrapping my JS object in

(function {} { /*my object code*/ }(jQuery))

and adding a

function createMyGadget() { return new myObject }

in my object. I can now successfully display two gadgets on one page by doing the following:

<div id="foo"></div>
<div id="bar"></div>

<script language="JavaScript">
    $("#foo").createMyGadget({ title: "My First Gadget"});
    $("#bar").createMyGadget({ title: "My Second Gadget"});
</script>

As part of the createMyGadget() function, I create a new div with a unique ID (gadgetUID), write a bunch of HTML, buttons, imgs, etc. to that div, then append that div to #foo and #bar. That works well.

In my HTML, I have a "Next" button which needs to call the goNext() function which is defined in the JavaScript Object. How do I reference that function in that object? I've tried

onClick='$("#foo").goNext()'

and

onClick='$("#gadgetUID").goNext()'

and every other permutation I could think of. Firebug always responds with an error message "...not a function".

ADDENDUM: Here's my response to johnnyheadphones :

I've been trying to do the same thing from inside of jQuery with the same results, e.g. '...is not a function'. Here's the actual function call:

displayGadget : function() {

    var myString = "\
    <div id=\""+this.gadgetId+"\" >\
        <div id=\"gadget_header\">\
            <h1 id=\"title\">"+this.options.title+"</h1>\
        </div>\
        <div id='loading' style=''><img src='images/loading2.gif' /></div> \
        <div id=\"gadget_body\"></div>\
        <div id=\"gadget_footer\">\
            <div id=\"searchAsset\">\
            </div>\
            <div id=\"pageControls\">\
                <img id=\"goPreviousIcon\" src=\"images/go-previous.png\">\
                <img id=\"goNextIcon\"  src=\"images/go-next.png\">\
                <input type=\"button\" value=\"Next\" />\
            </div>\
        </div> \
    \
    </div>\
    <div id=\"debugInfo\"></div>\
            <script type=\"text/javascript\"> \
            </script>\
    ";

    $("#"+this.gadgetContainerID).html(myString);

    $('input[value="Next"]','#'+this.gadgetContainerID).click(function() {
        $('#'+this.gadgetId).pageData(1);
    });
}

When I reload and click the next button, Firebug says '$('#'+this.gadgetId).pageData(1) is not a function'.

BTW, I initially wanted to do this with the goNextIcon but changed it to a button so I could copy/paste your code.

I'm starting to think I have something else wrong and this is just a weird by-product.

ADDENDUM: I figured out the problem: I'm an idiot (but any of my xGFs could have told you that).

I was calling the pageData() on the element in question. There is no pageData() function on the element; it's on the 'this' object. Onc I pointed to the correct (and only) pageData() object (which is attached to 'this'), it worked as advertised.

Now to go do some code cleanup.

Thanks for all the help!

A: 

Perhaps this is what you're thinking of...

onClick = function() {
    $("#gadgetUID").goNext();
}

This creates a reference to an anonymous function that finds your JQuery object(s) and runs the function you want to run.

MillsJROSS
That, and every permutation I've tried, gives me a syntax error
+1  A: 

if you're writing the onclick handler as part of the HTML that gets appended to the DOM, try something like this:

<input type="button" value="Next" onclick="function() { $('#gadgetUID').goNext(); }" />

Or, you could use jQuery to bind the handler inside plugin code. Without seeing a code sample, it's hard to say exactly what you need. But this is the general idea:

$('input[value="Next"]','#foo').click(function() {
    $('#gadgetUID').goNext();
});

EDIT: It sounds like this is a scoping problem. Calling pageData() in correct scope should fix your problem. Maybe something like this would work:

displayGadget : function() {
    // encapsulate this in a closure, so pageData() is called on the instance
    // of the object, not the DOM element selected by jQuery
    var that = this;

    [... string stuff here. you should replace 'this' with 'that' here as well ...]

    $("#"+that.gadgetContainerID).html(myString);

    $('#goNextIcon','#'+that.gadgetContainerID).click(function() {
        that.pageData(1);
    });
},

// the above code assumes that pageData() is part of the same
// object instance as displayGadget. if not, then you'll have to
// tweak your code to point call pageData in the correct scope
pageData: function( page ) {
    // do stuff here!
}

Note that I changed the jQuery selector back to match your original code (the image tags).

If you're planning on having multiple instances of this HTML on a page, one thing you might want to consider is using classes instead of IDs for the generated DOM elements. Giving the same ID to more than one DOM element is generally a bad thing and can cause you some headaches and bugs further down the road.

Also, you might want to look into DOM node creation instead using innerHTML to generate the controls. It would be easier to keep references to the elements and hook event handlers onto them.

jonnyheadphones
See my response to you in my post.
where is pageData() getting defined? is it a method of the same object that has displayGadget()?if so, then check out the edit to my post.
jonnyheadphones
Yes, pageSata() is defined in the same object (via .prototype) as displayGadget(). I agree it's a scoping problem but all methods are public, so WTF? I don't see anything in your soln that I haven't already tried, but I'll it try again in the morning. Thanks for the reminder to switch from ids to classes. Meant to do that before I started wrestling with the alligators.
so you tried setting 'this' to a variable so it gets captured in a closure? i'm pretty sure that will maintain scope.i don't see anything in your code that creates $('#'+gadgetId) as the instance of the object, so i'm guessing that the getData() method is a public property of another object. have you tried setting a breakpoint in Firebug in the click handler and watching $('#'+gadgetId)? it'll probably show that that jQuery object doesn't have getData();
jonnyheadphones