问题
I am trying to apply changes to the DOM when a <tr>
is clicked. When clicked, it should add data-state=enabled
and data-display=expanded
to the clicked <tr>
while applying data-state=disabled
and data-display=collapsed
to every other <tr>
.
So it should look like highlighting the clicked row while disabling the other rows.
Then, when a row is highlighted, and a user clicks elsewhere, it should reset to default, i.e. data-state=enabled
and data-display=collapsed
for all <tr>
's
Currently, I have it working so that when a <tr>
is clicked, that row is highlighted and all others disabled. However, the script is missing the reset to default because if another <tr>
is clicked, it immediately highlights that one and disables the rest.
I would like to do this in vanilla javascript but I am also open to using jQuery if it is substantially easier and won't affect performance noticably.
Here is the JSbin with working code to see where it's at: https://jsbin.com/kirati/
And the code so far:
<table class="table">
<thead>
<tr>
<th class="sort-key asc"><a href="#">Pet Name </a></th>
<th><a href="#">Owner (Last, First)</a></th>
<th><a href="#">Species</a></th>
<th><a href="#">Breed</a></th>
<th><a href="#">ID</a></th>
</tr>
</thead>
<tbody>
<tr>
<td>
Fluffy
<div class="table-row__expanded-content">
<data-key>Sex: </data-key> <data-value>Male</data-value><br />
<data-key>DOB: </data-key> <data-value>12/08/2010</data-value> <br />
<data-key>Weight: </data-key> <data-value>20 lbs</data-value> <br />
<data-key>Location: </data-key> <data-value>Kennel 2B</data-value> <br />
<data-key>Temperament: </data-key> <data-value>Aggresive</data-value> <br />
<data-key>Allergies: </data-key> <data-value>Sulfa, Penicillin, Peanuts</data-value>
</div>
</td>
<td>Anderson, James</td>
<td>Dog</td>
<td>Bulldog-Shitzu</td>
<td>ABCDE1234567</td>
</tr>
<tr>
<td>Feather</td>
<td>Michelle Charlotte, <br /> Angel Vanessa</td>
<td>Cat</td>
<td>American Bobtail</td>
<td>FGHIJ1234567</td>
</tr>
<tr>
<td>Fluffer-Nutter</td>
<td>Rakerstraw, Rickey</td>
<td>Dog</td>
<td>American Eskimo</td>
<td>KLMNO1234567</td>
</tr>
<tr>
<td>Farley</td>
<td>Cunningham, Stephanie</td>
<td>Dog</td>
<td>Pomeranian</td>
<td>PQRST1234567</td>
</tr>
<tr>
<td>Fuzzy</td>
<td>Venice, Harding</td>
<td>Cat</td>
<td>Burmese</td>
<td>UVWXY1234567</td>
</tr>
<tr class="alphabet-label">
<td>G</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>Goldie</td>
<td>Cherilyn, Mitchener</td>
<td>Dog</td>
<td>Chihuahua-Maltese</td>
<td>ZABCD1234567</td>
</tr>
</tbody>
</table>
And the Javascript
window.onload = function () {
var tablerow = document.body.getElementsByTagName('tr');
console.log(tablerow);
// Convert the HTMLCollection into a true javascript Array, so we can do "stuff" with it
var tablerowArr = Array.prototype.slice.call(tablerow);
console.log(tablerowArr);
// Do stuff
tablerowArr.forEach(function (value, i) {
console.log(i, value);
tablerow[i].onclick = function (e) {
//console.log("clicked!");
var newArr = tablerowArr.slice(i, i + 1);
//console.log(tablerow);
console.log(i);
//console.log(tablerowArr);
console.log('newArr', newArr);
tablerowArr.forEach(function (value, i) {
// first reset all instances of data-XXX
tablerowArr[i].setAttribute('data-display', "collapsed");
// tablerowArr[i].setAttribute('data-state', "enabled");
// Set the <tr> data-display attribute to expanded/collapsed on click
newArr[0].setAttribute('data-display', tablerowArr[i].getAttribute('data-display') === "collapsed" ? "expanded" : "collapsed");
//tablerowArr[i].setAttribute('data-display', tablerowArr[i].getAttribute('data-display') === "collapsed" ? "expanded" : "collapsed");
// Set the <tr> data-state attribute to enabled/disabled on click
newArr[0].setAttribute('data-state', newArr[0].getAttribute('data-state') === "disabled" ? "enabled" : "enabled");
tablerowArr[i].setAttribute('data-state', newArr[0].getAttribute('data-state') === "enabled" ? "disabled" : "enabled");
});
e.preventDefault();
};
});
};
回答1:
Here is a pure javascript example in the below jsfiddle:
http://jsfiddle.net/pya9jzxm/14
var tbody = document.querySelector('tbody');
var trs = tbody.querySelectorAll('tr');
var tr, index = 0, length = trs.length;
for (; index < length; index++) {
tr = trs[index];
tr.setAttribute('data-state', 'enabled');
tr.setAttribute('data-display', 'collapsed');
tr.addEventListener('click',
function () {
if (this.classList.contains('alphabet-label')) {
return;
}
var trIndex = 0, trLength = trs.length, hasExpanded = false;
var state = 'disabled';
if (tbody.querySelectorAll('[data-display="expanded"]').length > 0) {
hasExpanded = true;
state = 'enabled';
}
for (; trIndex < trLength; trIndex++) {
trs[trIndex].setAttribute('data-state', state);
trs[trIndex].setAttribute('data-display', 'collapsed');
}
if (!hasExpanded) {
this.setAttribute('data-state', 'enabled');
this.setAttribute('data-display', 'expanded');
}
}
);
}
};
回答2:
in jQuery:
$(function() {
$('html').click(function() {
/* return to default state */
$('.table tbody tr').data('state', 'enabled').data('display', 'expanded');
});
$('.table tbody tr').on('click', function(e) {
/* stop the html click event */
e.stopPropagation();
/* set attributes for all rows */
$('.table tbody tr').data('state', 'disabled').data('display', 'collapsed');
/* set attributes for the clicked row */
$(this).data('state', 'enabled').data('display', 'expanded');
});
});
I've commented the function, to clarify how it works.
回答3:
Which is very simular to @LinkinTED
Please inspect the html before you say this does not work.. I've tested it myself.
May i suggest that you instead modify the class... to change the effects.
$(function() {
var $row = $('.table tbody tr');
$('html').click(function() {
$row.attr('state', 'enabled').attr('display', 'expanded');
});
$row.on('click', function(e) {
e.stopPropagation();
$row
.attr('state', 'disabled')
.attr('display', 'collapsed');
//console.log(e);
$(this)
.attr('state', 'enabled')
.attr('display', 'expanded');
});
});
回答4:
Using vanilla JS and event delegation. DEMO
var tablerow = document.body.getElementsByTagName('tr');
// Convert the HTMLCollection into a true javascript Array, so we can do "stuff" with it
var tablerowArr = Array.prototype.slice.call(tablerow);
// store the highlighted row
var highlighted;
// extracted function to enable/disable rows
var enable = function(row){
row.setAttribute('data-display', "expanded");
row.setAttribute('data-state', "enabled");
}
var disable = function( row ){
row.setAttribute('data-display', "collapsed");
row.setAttribute('data-state', "disabled");
}
// on click anywhere
document.body.addEventListener('click', function(e){
var target = e.target;
// check if event target or any of its parents is a TR
while( target.parentNode && target.nodeName.toLowerCase() != 'tr' ){
target = target.parentNode;
}
// if s row was higlighted disable all rows
if( highlighted ){
tablerowArr.forEach( disable );
// and remove the reference to highlighted
highlighted = null;
}
// no row is highlighted
else {
tablerowArr.forEach( function(row){
// if the event target is a row, highlight it
if(row == target) {
enable( row );
// and store it as the currently highlighted
highlighted = row;
}
// if it's not the event target then disable
else {
disable( row );
}
});
}
});
来源:https://stackoverflow.com/questions/33128718/change-data-attribute-on-click-of-html-elements