Reputation: 40106
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
Reputation: 206679
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
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');
})
}
});
Upvotes: 1
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
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