skribe
skribe

Reputation: 3615

Type error: "Not a function" using "this" keyword in a function

I have created the following function.

function showAllSelectOpts(select)
{
  selectLength = select.children().length;
  select.attr('size',selectLength);
  select.css('height','auto');
  select.focusout(function(){
      select.attr('size','1');
  });
}

When it is called directly on a select element like this showAllSelectOpts(mySelect); it works fine, but when called within another function, as below using the keyword "this", it returns the error. Type error: select.children not a function

$('select').on('focus',function(){
  showAllSelectOpts(this);
})  

Is this a scope issue or what, and how can I resolve it?

Upvotes: 1

Views: 96

Answers (5)

Thielicious
Thielicious

Reputation: 4452

These previous answers fix it. I'd just add here to create it as an extension since $(this) refers to a prototype of one method call.

$.fn.showAllSelectOpts=function() {
    $(this).on('focus',()=>{
        $(this)
            .css('height','auto')
            .attr('size',$(this).children().length)
            .focusout(()=>{
                $(this).attr('size','1');
            });
    });
};
$('select').showAllSelectOpts(); 

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1075537

In an event handler, this is a reference to the DOM element, not a jQuery object. But your showAllSelectOpts expects its argument to be a jQuery object.

Either change the call to wrap the DOM element with $():

showAllSelectOpts($(this));

...or update showAllSelectOpts to do so itself:

function showAllSelectOpts(select)
{
  select = $(select);                      // ***
  selectLength = select.children().length;
  select.attr('size',selectLength);
  select.css('height','auto');
  select.focusout(function(){
      select.attr('size','1');
  });
}

Side note: As A.Wolff points out, your function attaches a new focusout handler to the select every time it's called. You only want one.

I'd remove that part of the handler entirely, and replace it with a single focusout:

function showAllSelectOpts(select)
{
  var selectLength = select.children().length;
  select.attr('size',selectLength);
  select.css('height','auto');
}
$('select')
  .on('focus',function(){
    showAllSelectOpts($(this));
  })
  .on('focusout', function(){
    $(this).attr('size', '1');
  });

Also note that I added a var for selectLength in showAllSelectOpts (although actually, you could just remove the variable entirely); without one, the code is falling prey to The Horror of Implicit Globals (that's a post on my anemic little blog). Be sure to declare your variables.

Upvotes: 4

Ahsan
Ahsan

Reputation: 4154

Try this:

var myselect  = $('select');

$('select').on('focus',function(){
  showAllSelectOpts(myselect);
})  

A better way could be:

$('select').on('focus',function(event){
  showAllSelectOpts($(event.target));
})  

Why your code not working?

$('select').on('focus',function(){
  //Here `this` is bound with the dom html element, not the $('select') object.
  showAllSelectOpts(this);
})  

Upvotes: 0

synthet1c
synthet1c

Reputation: 6282

jQuery event listener callbacks set this as the HTMLElement that the event was fired on.

In your callback you are expecting a jQuery object, but you have the HTMLElement.

You can pass the HTMLElement to a jQuery constructor and pass it into the showAllSelectOpts function

$('select').on('focus',function(){
  showAllSelectOpts($(this));
}) 

Upvotes: 1

Rehban Khatri
Rehban Khatri

Reputation: 954

Try this one -

$('select').on('focus',function()    { 
showAllSelectOpts($(this)); }) 

Upvotes: 0

Related Questions