kevinmkr kevinmkr - 10 days ago 4
jQuery Question

Accessing public/private methods of a jQuery widget from within an .each() method inside that widget

I'm trying to extend the Tabs widget in jQuery so that it automatically adds certain html to a tab upon either the creation of a new tab (triggered by user) or on page load (for any pre-existing tabs). I was able to get all of this to work external to the widget by using the regular tabs widget and a bunch of custom javascript functions. However, to make it more modular, I want those functions to be member functions of my extended widget.

Widget:

$.widget( "custom.extendedTabs", $.ui.tabs, {
,_addOptions: function($el) {
//add a "close" button and an "options" button on each tab on mouseover
}
,_create: function() {
this.element.find("li").each(function(i,el){
this._addOptions($(this));
});
return this._super();
}
,addTab: function() {
//handle tab creation
........
this._addOptions(<newlyCreatedliElement>);
}
});


Instantiation:

$(".tabs").each(function(){
$(this).extendedTabs();
});


Sample:

<div id="tabs1" class="tabs">
<ul>
<li><a href="#tabs-1">Nunc tincidunt</a></li>
<li><a href="#tabs-2">Proin dolor</a></li>
</ul>
<div id="tabs-1">
<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus.</p>
</div>
<div id="tabs-2">
<p>Morbi tincidunt, dui sit amet facilisis feugiat, odio metus.</p>
</div>
</div>

<div id="tabs2" class="tabs">
<ul>
<li><a href="#tabs-3">Nunc tincidunt</a></li>
</ul>
<div id="tabs-3">
<p>Proin elit arcu, rutrum commodo, vehicula tempus, commodo a, risus.</p>
</div>
</div>


The Problem:

Based on testing I have no problem calling
this._addOptions()
directly from
_create()
. However, I do not have the same success when calling it from the
.each()
inside of
_create()
. When attempting to do so, I receive
this.addOptions is not a function
as an error.

I know that the
this
inside of the
.each()
represents the iterated instance element, itself, and not the parent widget that called it. But I thought there might be some way to reference the object that called the
.each()
.

UPDATE:

I was successfully able to replace the
.each()
with the following:

for (var el in this.element.find("li").toArray()) {
this._addOptions($(this.element.find("li").toArray()[el]));
}


It feels clunky, however, so I would still appreciate some insight from somebody who may have a cleaner method.

Answer

I've considered an alternate solution -- one that retains the jQuery .each():

,_create: function() {
    var self=this;
    this.element.find("li").each(function(i,el){
        self._addOptions($(this));
    });
    return this._super();
}
Comments