1

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>

3 Answers 3

5
$(this).parent()
       .parent()
       .find('input[type=text]')
       .attr('readonly', 'readonly');
Sign up to request clarification or add additional context in comments.

1 Comment

You should be using prop() for boolean properties such as readonly, not attr().
1

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().

5 Comments

when I use '.prop('readonly', true);', it doesn't work, however using '.attr('readonly', 'readonly');' does work...I'm using jquery 1.10.2
@999cm999 you're over 10 versions behind. You should probably look into upgrading.
@999cm999 i misread that - you are only a few versions behind (2.0.3 is latest). the prop() call is working in the fiddle i linked you even if i switch the version to 1.10.2, are there any console errors on your page?
no console errors, but I notice that when clicked, and using .prop('readonly', true); -- it changes the HTML to this: readonly=""
@999cm999 this might be worth a read: difference between attributes and properties
1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.