cssyphus
cssyphus

Reputation: 40106

jquery loop through elements by incrementing ID

I have about a dozen events to check and all selectors are similarly (iteratively) named. How could I shorten this routine?

$(document).ready(function() {
    $(document).on('click','#del_od1', function() {
        $('#change_od1').val('YES');
        $('#span_od1').html('(Deleted)');
        $('#status_od1').val('DELETED');
    });
    $(document).on('click','#del_od2', function() {
        $('#change_od2').val('YES');
        $('#span_od2').html('(Deleted)');
        $('#status_od2').val('DELETED');
    });
    $(document).on('click','#del_od3', function() {
        $('#change_od3').val('YES');
        $('#span_od3').html('(Deleted)');
        $('#status_od3').val('DELETED');
    });
});

This question is poorly named. Could someone also suggest a more precise title and I'll change it to that before accepting the answer.


EDIT:

An entire table structure is echoed out in response to an ajax call. The top of the table is like this:

$r = '
    <table id="DocTable">
        <tr>
            <th width="170">Document Title</th>
            <th width="170">MetShare FN</th>
            <th width="50">Action</th>
            <th width="50">Delete</th>
        </tr>';

Followed by a couple of irrelevant rows containing information as requested in the call. Then this is appended to the previous bit, and the whole thing echoed out as echo $r;.

$rest_docs =  $aProj['all_project_docs'];
$ocnt = 0;
if ($rest_docs !== ''){
    $ocnt = $ocnt + 1;
    $aRest_docs = explode('?',$rest_docs);
    foreach($aRest_docs as $doc){
        $aDoc_parts = explode('|',$doc);

        $r = $r . '
        <tr>
            <td>'.$aDoc_parts[0].'</td>
            <td>
                <span id="span_od' . $ocnt . '">
                    <a href="'.$aDoc_parts[1].'" target="blank">
                    '. $aDoc_parts[1] .'
                    </a>
                </span>
                <input type="hidden" id="status_od' . $ocnt . '" name="status_od' . $ocnt . '">
            </td>
            <td>
                <a id="change_od' . $ocnt . '" class="normal" href="#">change</a>
                <input type="file" id="if_od' . $ocnt . '" name="if_od' . $ocnt . '" style="display:none">
                <input type="text" style="display:none">
            </td>
            <td>
                <a href="#" id="del_od' . $ocnt . '">delete</a>
            </td>
        </tr>';
    }
}

echo $r;

Upvotes: 1

Views: 6854

Answers (4)

Roko C. Buljan
Roko C. Buljan

Reputation: 206679

jsBin (just for example) demo

a common thing to all this names...

   del_od1
change_od1
  span_od1
status_od1

is:      1      :)   (a number, and so for all other elements)

...so we need to grab it! look:

$(document).ready(function() {
    $(document).on('click','[id^=del_od]', function() {//^="starts with selector"

        var num = this.id.split('od')[1];  // returns our number from the id!
        // from now on we can use our var "num" :

        $('#change_od'+ num).val ('YES');
        $('#span_od'  + num).html('(Deleted)');
        $('#status_od'+ num).val ('DELETED');
    });
});

Upvotes: 3

Jashwant
Jashwant

Reputation: 29025

In jQuery, you can avoid closure and use event.data instead. This looks cleaner to me.

jQuery(document).ready(function($) { 
    for(var i = 1; i < 10; ++i) {
        $(document).on('click','#del_od' + i,{'index': i},function(e) {
            var index = e.data.index;
            $('#change_od' + index).val('YES');
            $('#span_od' + index).html('(Deleted)');
            $('#status_od' + index).val('DELETED'); 
        })
    }
});

Demo

Reference

Upvotes: 1

jfriend00
jfriend00

Reputation: 708146

You can serve them all with one event handler by parsing the id suffix out of the id:

$(document).ready(function() {
    $(document).on('click','[id^="del_"]', function() {
        var suffix = this.id.replace(/^.*?_/, "");
        $('#change_' + suffix).val('YES');
        $('#span_' + suffix).html('(Deleted)');
        $('#status_' + suffix).val('DELETED');
    });
});

This can also be solved by using the HTML relationship of the delete button to the affected items.

If you could modify the HTML to use classes for the various targets, then it could be done like this without any ids, by just using the relationship of the pressed button to the desired target:

    <tr>
        <td>'.$aDoc_parts[0].'</td>
        <td>
            <span id="span_od'  . $ocnt . '" class="spanTarget">
                <a href="'.$aDoc_parts[1].'" target="blank">
                '. $aDoc_parts[1] .'
                </a>
            </span>
            <input type="hidden" id="status_od' . $ocnt . '" class="statusTarget" name="status_od' . $ocnt . '">
        </td>
        <td>
            <a id="change_od' . $ocnt . '" class="changeTarget normal" href="#">change</a>
            <input type="file" id="if_od' . $ocnt . '" name="if_od' . $ocnt . '" style="display:none">
            <input type="text" style="display:none">
        </td>
        <td>
            <a href="#" id="del_od' class="deleteButton" . $ocnt . '">delete</a>
        </td>
    </tr>';

And, this would be the script based only on position and classes (no ids):

$(document).ready(function() {
    $(document).on('click', '.deleteButton', function() {
        var parent = $(this).closest("tr");
        parent.find('.changeTarget').val('YES');
        parent.find('.spanTarget').html('(Deleted)');
        parent.find('.statusTarget').val('DELETED');
    });
});

This gets the row that the delete button that was clicked was in and then finds the change, span and status objects that are in the same row and operates on them. No ids are used at all. This uses the position of the clicked on button to find the objects that it operates on.

Upvotes: 0

Jon
Jon

Reputation: 437874

The obvious way is

$(document).ready(function() {
    for(var i = 1; i < 10; ++i) {
        $(document).on('click','#del_od' + i, (function(index) {
            return function() {
                $('#change_od' + index).val('YES');
                $('#span_od' + index).html('(Deleted)');
                $('#status_od' + index).val('DELETED');
            };
        })(i));
    }
});

However, it is extremely likely that you could achieve the same effect without this brutish coding style by utilizing classes instead of ids and leveraging the information you have about the structure of the document. Can you give an example of that?

Upvotes: 2

Related Questions