Reputation: 7092
this question relates to a another question that I asked previously.
I have a bunch of textbox pairs on my page, each of which have an image associated with them. When clicked, this image should hide itself, and also make the pair of textboxes read-only.
The first part works, it does hide itself. But the second part does not work.
I can't figure out how to 'find' the pair of textboxes that is closest to the image that is being clicked.
Here is my jQuery:
$("body").on('click', '.pageLinks img.save', function () {
$(this).hide();
$(this).prevAll('input').each(function () {
$(this).attr('readonly', 'readonly');
});
Here is my HTML:
<div class="pageLinks">
<div>
<div>
<input type="text" class="firstName">
<input type="text" class="lastName">
</div>
<div>
<img src='/saveLink.png' class='save' />
</div>
</div>
<div>
<div>
<input type="text" class="firstName">
<input type="text" class="lastName">
</div>
<div>
<img src='/saveLink.png' class='save' />
</div>
</div>
<div>
<div>
<input type="text" class="firstName">
<input type="text" class="lastName">
</div>
<div>
<img src='/saveLink.png' class='save' />
</div>
</div>
Upvotes: 1
Views: 98
Reputation: 43745
You could associate the elements with one another when generating them instead. If they are created with js, you could use logic like this:
var frag = document.createDocumentFragment();
for (var i=0; i<10; ++i) {
var input = document.createElement('input');
input.value = "Input "+i;
var p = document.createElement('p');
p.textContent = "Paragraph "+i;
input.dataset.i = i;
p.dataset.i = i;
frag.appendChild(input);
frag.appendChild(p);
}
document.body.appendChild(frag);
In this example, all inputs have a paragraph associated with them that we can easily identify by the data attribute "i". This could just as soon be generated server-side as well.
and you might take advantage of this like so:
$('input').keyup(function() {
var i = this.dataset.i; //get the assigned index "i"
var p = $('p[data-i="'+i+'"]'); //find the associated paragraph with "i"
p.text(this.value);
});
Here's a demo of a simple usage (click here).
Of course, you will want to restrict the selectors here to some class name to isolate your logic (you wouldn't want to select some other paragraph tag that also has data-i
as an attribute, just in case. One nice advantage of this is that you aren't going to mess up your selectors if you change the structure of the html - they are associated by attribute, not by their location in the dom.
AngularJS is an awesome framework that establishes a natural connection between your data and the dom, so you don't even need to worry about selectors like this. You might even want to check that out. I love it.
Upvotes: 1
Reputation: 46647
I would give the containing divs a class that you can select on, and then search downwards from there. This alleviates the need for .parent().parent()
which is much more brittle.
HTML:
<div class="somethingMeaningful">
<div>
<input type="text" class="firstName" />
<input type="text" class="lastName" />
</div>
<div>
<img src='/saveLink.png' class='save' />
</div>
</div>
...
JavaScript:
$('body').on('click', '.save', function () {
$(this)
.hide()
.closest('.somethingMeaningful')
.find('input')
.prop('readonly', true);
});
Working example and documentation for closest().
Upvotes: 1
Reputation: 56688
$(this).parent()
.parent()
.find('input[type=text]')
.attr('readonly', 'readonly');
Upvotes: 5