Home › Forums › JavaScript › Why is 'this' not the jQuery selector?
- This topic is empty.
-
AuthorPosts
-
June 10, 2015 at 5:57 am #203539ShikkedielParticipant
Working on this page scrolling plugin that pretty straightforward :
$(document).ready(function() { $(this).impulse(); })
That’ll create a full page effect…
It can also be used on descendant elements :$(document).ready(function() { $('#element').impulse(); })
Scrolling only some segment of the page…
One of the options is to set the amount to be scrolled – here’s is where something I don’t get comes in. This works :$(document).ready(function() { $('#element').impulse(range: $('#element').height()); })
And I would have expected for this to get the same result :
$(document).ready(function() { $('#element').impulse(range: $(this).height()); })
But it doesn’t. Instead
$(this)
seems to refer to whatever object the wrapping function is, so in this case it would return the height of the document. And with this you get the screen height :$(window).on('load', function() { $('#element').impulse(range: $(this).height()); });
Anyone have a clue why it might be ‘skipping’ the direct object the method was applied to? Not getting this one at all.
Some examples can be found here (starting to get quite nifty for the rest, still working on the documentation) :
June 10, 2015 at 11:52 am #203550ShikkedielParticipantAll I could find on it, which doesn’t really provide a good explanation…
http://stackoverflow.com/questions/3453589/this-in-plugin-options
June 10, 2015 at 6:51 pm #203559AlenParticipantTry
$(document).ready(function() { var $document = $(this); $('#element').impulse(range: $document.height()); });
June 11, 2015 at 12:07 am #203562Ilan FirsovParticipantNot really sure I understand what you are trying to do, but try
$(document).ready(function() { var $element = $('#element'); $element.impulse(range: $element.height()); });
or
$(document).ready(function() { (function(){ this.impulse(range: this.height()); }).call($('#element')); });
June 11, 2015 at 4:39 am #203580ShikkedielParticipantThanks for the replies, guys.
Alen, the odd thing is that the
range
property takes on the height ofdocument
even if you pass$(this).height()
to it. So instead ofthis
referring to the element that was selected with the method, it skips that level and automatically refers to whatever function the plugin was wrapped in.If you use
this.height()
inside the plugin itself, you get the height of the selected element like one would expect…Ilan, that does indeed work – I added something similar to the first snippet to the examples on the documentation page I’m writing about it. But it seems strange and unnatural that you can’t just use
$(this)
in the ‘usual’ way. Not seeing the inner logic of that (yet anyway)…June 11, 2015 at 2:07 pm #203616AnonymousInactiveBut it seems strange and unnatural that you can’t just use $(this) in the ‘usual’ way. Not seeing the inner logic of that (yet anyway)…
I’m not a javascript guru, so I may have this way off, but as far as I can tell from the documentation,
this
within an event handler refers to the element from which it fired. In the context of:$(document).ready(function() { $('#element').impulse(range: $(this).height()); })
That would be
document
, no?I’m not sure exactly what you mean by “in the usual way” but I’m pretty sure @ilanf is using it in the usual way.
June 11, 2015 at 3:19 pm #203617ShikkedielParticipantThanks for the brainstorm. The event would be mousewheeling though, done in the context of
$('#element')
and it’s shouldn’t be bubbling up (because ofstopPropagation()
being used inside the plugin).It’s not the biggest deal getting it to work but I’m just never satisfied until I understand why something is happening…
Function scope is a tricky one and I’m obviously not yet fully getting it.:-D
What I meant with ‘the usual way’ is that for example with
.animate
you can refer to the selected element from within some options :$('#element').animate({scrollTop: somewhere}, { start: function() {$(this).dosomething()}, ... });
If
dosomething()
is getting the height for example, it will be that of#element
… but it does have a function wrapped around it so that may be of influence. I’m sure I’ll figure it out at some point by means of experiment. Most tutorials on jQuery plugins don’t dig too deep unfortunately.June 11, 2015 at 6:06 pm #203629ShikkedielParticipantCheers, that seems helpful from the start already (although the beginning is something I should ‘know’, it’s still enlightening to read back when explained well). I’ll have a good read-through, much like this page deserves :
June 12, 2015 at 6:14 am #203640AnonymousInactiveWhat I meant with ‘the usual way’ is that for example with .animate you can refer to the selected element from within some options
Not really. There’s a difference between your two examples. In your
impulse
example, you usethis
in the current context to define a variable. In theanimate
example you write a function that includesthis
. In the function context,this
will mean whatever it ought to mean at the point at which the function is called.June 12, 2015 at 6:55 am #203642ShikkedielParticipantSeems to work when you set a variable/property directly as well though (duration would be the only option that doesn’t involve a function) :
$('#element').animate({scrollTop: somewhere}, { duration: $(this).height(), ... });
B-/
Thanks for thinking along in any case…
June 12, 2015 at 11:51 am #203667AnonymousInactiveThanks for thinking along in any case…
That’s fine. It’s a slightly quirky topic, so kinda interesting.
Does it not matter that in the final example you are within an object context (ie.
{variable: this}
) whereas in your first example you are not (ie.variable: this
)?June 12, 2015 at 12:49 pm #203672ShikkedielParticipantGood one, those are actually typos I hadn’t noticed in the first post.
They should also be wrapped in an object extension :$(document).ready(function() { $('#element').impulse({range: $('#element').height()}); });
Sorry for the blooper (nice catch, must have been mystifying the issue).
:-S
I do believe your post is the crux of it though, I was thinking I was extending the jQuery object with these additional properties but somehow that must not be the case – when approaching it from the ‘outside’. Inside the plugin the selected element(s) will refer to
this
. The general way to do this :$.fn.impulse = function(options) { var set = $.extend({ range: 135 }, options); ... };
If I do
range: this
and logset.range
it’ll show an object with the elements that were selected with$(' ... ')
…Currently reading up on this, pretty interesting :
June 12, 2015 at 2:37 pm #203677ShikkedielParticipantHow can I forget to add the pen where the issue could be replicated rather easily…
http://codepen.io/Shikkediel/pen/GJRbOV
Somehow embedding doesn’t quite work with an external script. :-(
June 14, 2015 at 12:00 pm #203727ShikkedielParticipantHaven’t completely figured it out yet but I did discover something. When adding another option (a function this time) and logging ‘this’ through the method, it seems to refer to the var
set
itself :$.fn.impulse = function(options) { var set = $.extend({ test: function() {} }, options); set.test(); ... };
$('element').impulse({ test: function() {console.log(this)} });
So that object (
set
) will extend to the selected elements from the ‘inner’ perspective of the plugin but it is not owned by them when applying the method. Sinceset
isn’t a DOM element, getting the height obviously doesn’t lead anywhere…Comparing it to
.animate()
doesn’t seem fair. After looking at the jQuery source, any variables/properties are undergoing more operations so it’s not as straightforward as this issue.June 17, 2015 at 10:10 am #203928ShikkedielParticipantThinking about it some more, it might be what jQuery is essentially about. Allowing access to the global object inside a plugin but keeping the variables private…
-
AuthorPosts
- The forum ‘JavaScript’ is closed to new topics and replies.