Samuel Fullman
Samuel Fullman

Reputation: 1312

understanding the object passed in two contexts

I don't know if you've ever felt like you've dived off the stupid tree and hit every branch on the way down, but JavaScript has that effect on me, an experienced PHP programmer but just doesn't get JS sometimes.

so I wrote this function using jQuery.extend({ .. }) as follows:

loadSection: function(obj){
    if(typeof obj=='undefined')obj=event.target; //but this doesn't work
    if(typeof obj=='string')obj=document.getElementById(obj);
    var params=null;
    var instr={};
    var k=0;
    while(true){
    ..etc..

I want to be able to call it two ways:

$.loadSection($('#employee-data-173'));
//or $loadSection('employee-data-173') for convenience

or:

$('#employee-data-173').loadSection();

Clearly (to you anyway!) I'm not grasping the concept of what's being passed in the second case. And that's not even getting into a case like this:

$('.someElement').click(loadSection);

Upvotes: 0

Views: 48

Answers (1)

Martin Ernst
Martin Ernst

Reputation: 3289

You want to use the same function in three totally different usecases. In each case different arguments are automatically passed to the function. So first declare and prepare it to handle all possible types of arguments:

function loadSection(index, obj, args) {
    var element, params = null;
    if (obj && obj.nodeType) { // for usecase 2
        element = obj; if (typeof args == 'object') params = args;
    } else {
        if (typeof obj == 'object') params = obj;
        if (typeof index == 'string') { // usecase 1 with selector-string
            element = document.getElementById(index);
        else if (index.jquery) { // usecase 1 with jQuery object
            if (index.length == 1) element = index[0]; // if only one element inside jQuery
            // if more than one element there call this function recursively on each
            else index.each(loadSection);
        }
        else if (index.target) element = index.target; // for usecase 3
     }

    /* your stuff */
}

In your usecase 1 you have to add the function to the global jQuery object and call it by $.loadSection(argument), where argument may be a id-selector-string or an jQuery-object $("selector"). There are two ways with identic result:

$.loadSection = loadSection;
$.extend({loadSection: loadSection});

In usecase 2 you want to call the function as a method of a jQuery object. Therefore you have to add it to the jQuery.prototype like so:

$.fn.loadSection = function( args ) { // $.fn is synonym for jQuery.prototype
    return this.each(loadSection, args);
};

If you call now $("selector").loadSection() the function is executed once for each element matched by "selector". Arguments index and obj are automatically passed to loadSection.

In usecase 3 the function is used as callback-function for an event. Since its prepared for this case, the event object is automatically passed to it. So just do:

$('.someElement').click(loadSection);

You can use all cases mixed in the same piece of code.

EDIT "What shall/can the function return?"

It may return whatever you want to. Only the behaviour depends on usecase.

In usecase 1 you can do: var result = $.loadSection("selector") and result gets the returned value.

In usecase 2 there is an iteration over all elements in the jQuery object. The return value of loadSection is simply ignored except you explicitely return false. Then iteration stops. So if you do if (index == 2) return false; the function is executed maximum 3 times even when you have 7 elements inside jQuery object. The function as a whole always returns the jQuery object, so you can do chaining:

$("selector").loadSection().css({color: 'blue'}).animate(...). ...

In usecase 3 the function is only executed but the return value gets never recognized anywhere, so you can't catch it.

EDIT 2 "How to pass additional params to the function?"

1) Now loadSection is prepared to take additional args (see above). 2) The setup of $.fn.loadSection is modified to take args (see above). 3) args must be an object or array eg {prop: 'color', id: 23} (otherwise it's ignored) but may be omitted.

In usecase 1 pass args as second argument

var result = $.loadSection("selector", args); // you find args inside in ""var params"

In usecase 2 args is the one and only possible argument. jQuery now makes an iteration inside an iteration: the function is called on each element once for each item in args! The inner iteration is stoppable by return false, but the iteration over all elements no longer.

$("selector").loadSection({prop: 'color', id: 23}) // if $() contains 3 elems, function run six times

In usecase 3 its impossible to pass args since you only point to the function by its name.

Upvotes: 1

Related Questions