Bug Tracker

Opened 9 years ago

Closed 9 years ago

Last modified 8 years ago

#7348 closed enhancement (wontfix)

Current "set" of Matched Elements: jQuery.self or jQuery.last

Reported by: anonymous Owned by:
Priority: low Milestone:
Component: core Version:
Keywords: Cc:
Blocked by: Blocking:

Description

I am constantly finding myself wanting to reference the current set of elements inside a chain of commands. Let me explain with a couple of examples:

var r = $('#test');
var g = r.find('span[data-Name=Name]');
g.css('width', g.width() + 10);
var i = r.find('input[name=Date]');
i.attr('data-OldValue', i.val()).val('now');

As you can see, both g and i needed to reference themselves within the methods executed against them. There's no way for me to turn this into a chain of commands using the end() method because of this. I think jQuery needs a variable that holds the current set of elements (e.g. $.$, $._, $.self, $.last, ...); the above code then could be written like so:

$('#test').find('span[data-Name=Name]')
   .css('width', $.$.width() + 10)
.end().find('input[name=Date]')
   .attr('data-OldValue', $.$.val()).val('now')
.end();

It's more for convenience than reducing code length, however, if you keep this reference name small (such as $.$ or $._), it would be both a convenience and reduce the overall code length slightly. It just seems like this would be a great compliment to the end() method.

I apologize ahead of time if there's already a feature for this or someone knows of a way to do it without breaking a chain.

Change History (6)

comment:1 Changed 9 years ago by Rick Waldron

Component: unfiledcore
Milestone: 1.5
Priority: undecidedlow

Pardon me if I've misunderstood, but are looking for this: http://api.jquery.com/andself/

comment:2 Changed 9 years ago by anonymous

What I am trying to get at is a way to reference the current object so that one doesn't have to break a chain in the case that a property of the current object is needed inside of the chain. Here's one more simple example that hopefully conveys what I mean.

<script>
$(function () {
$('body').find('input[name=abc]')
   .val($._.val() + ' World!')
.end().find('input[name=123]')
   .val($._.val() + 'bar')
.end();
})();
</script>
<body>
<input name="abc" value="Hello" />
<input name="123" value="foo" />
</body>

After this document loads, the first INPUT element should say "Hello World!" and the second should say "foobar" because $._ always references the last jQuery set (which would be whatever elements were found with the find() method).

Now that I have reiterated this again, I do realize that the above example could be rewritten with the each() method, like so...

<script>
$(function () {
$('body').find('input[name=abc]')
   .each(function () {$(this).val($(this).val() + ' World!');})
.end().find('input[name=123]')
   .each(function () {$(this).val($(this).val() + ' bar!');})
.end();
})();
</script>
<body>
<input name="abc" value="Hello" />
<input name="123" value="foo" />
</body>

As you can probably see, this way has a little more code to it, but it allows me to create one chain of commands in the current context without having to break it up into variables like so...

<script>
$(function () {
var a = $('input[name=abc]');
a.val(a.val() + ' World!');
a = $('input[name=123]');
a.val(a.val() + ' bar!');

// or even more lenghty...
$('input[name=abc]').val($('input[name=abc]') + ' World'!');
$('input[name=123]').val($('input[name=123]') + ' bar!');

})();
</script>
<body>
<input name="abc" value="Hello" />
<input name="123" value="foo" />
</body>

By having a variable that always contains the last set of elements of whatever method is called, you are able to keep one chain that is also a little condensed as far as code. This is kind of similar to how RegExp is handled in JavaScript; RegExp.lastMatch always contains the last match, so jQuery.last or jQuery._ would always contain the last set of elements matched.

Again, this is just for convenience. I don't think it's going to be a feature used by many.

Thank you for the time, rwaldron.

comment:3 Changed 9 years ago by snover

Resolution: wontfix
Status: newclosed

Most of the code you’ve written for this example wouldn’t work properly anyway unless your selectors only ever match a single object. Use .each, and don’t be afraid to break chains when you need references.

comment:4 Changed 9 years ago by tjm

Hi, sorry to bring up a fairly old ticket but I have also found a need for this recently and have come up with the following simple plugin to allow it. I post it here hopefully to help anyone else that has the same need but also to get confirmation (or not as they case may be) that this method won't break anything else in jQuery. I'm not sure if the use of '$.$' is the best choice but that can easily be modified. Heres what I've got:

(function($) {
    'use strict';
 
    var 
    oldfninit = $.fn.init;
    
    ($.fn.init = function() {

        oldfninit.apply($.$=this,arguments);
        return $.$;

    }).prototype = oldfninit.prototype;

}(jQuery));

comment:5 in reply to:  4 Changed 9 years ago by tjm

Just to note, the return in my previous example is redundant but i also think the content of the new $.fn.init, should read,

    return $.$ = oldfninit.apply(this,arguments);

since the original does not just modify this but may return another object. In the case that no element has explicitly been selected, for example, the previous code was returning the wrong object.

I'm still not sure if this won't break other things though!

comment:6 Changed 8 years ago by leorou@…

If you want to maintain chain-ability and to reference an object in it you can do something like this and then use the variable in the following chain:

$(selector).toVariable('theObject').html(theObject.attr('title'));

Otherwise, without the plugin:

var theObject = $(selector);
theObject.html(theObject.attr('title'));

Here is the plugin:

(function( $ ){

  $.fn.toVariable = function( variableName ) {  
	
	window[variableName] = this;
	
	return $(this);

  };
})( jQuery );
Note: See TracTickets for help on using tickets.