これはもっと簡潔にすべきだと思わずにはいられませんが( 3 つ for (...)
のループを使用すると、不必要にコストがかかるように感じます)、1 つのアプローチは次のとおりです。
Object.prototype.classHighlight = function (over, out) {
var that = this.length ? this : [this];
function onOver() {
for (var i = 0, len = that.length; i < len; i++) {
that[i].style.backgroundColor = over;
}
}
function onOut() {
for (var i = 0, len = that.length; i < len; i++) {
that[i].style.backgroundColor = out;
}
}
for (var i = 0, len = that.length; i < len; i++) {
that[i].onmouseover = onOver;
that[i].onmouseout = onOut;
}
};
document.getElementsByClassName('test').classHighlight('#f90', '#fff');
JS フィドルのデモ。
6年後、この質問と回答へのリンクをたどって、上記のアプローチを更新し、スニペットと参照を追加するために編集しています。
更新されたコード:
// extending the Object prototype to allow chaining of this method,
// 'over' : String, the class-name to add when the element(s) of the
// HTMLCollection/NodeList are hovered-over. We also set the default
// value of the 'over' variable in order that a class-name will always
// be present:
Object.prototype.classHighlight = function(over = 'over') {
// taking the 'this' and using the spread operator to expand
// the iterable collection to an Array:
const that = [...this],
// creating a named function to act as the event-handler for
// 'mouseenter' and 'mouseleave':
toggleHighlight = (event) => {
// iterating over the array using Array.prototype.forEach():
that.forEach(
// we're not using 'this' in here, so using an Arrow function
// to use the Element.classList API to toggle the supplied
// class on each element of the collection. If the event-type
// is exactly equal to 'mouseenter' we add the class otherwise
// we remove the class:
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
// iterating over the collection, again using Array.prototype.forEach():
that.forEach(
// and another Arrow function:
(element) => {
// here we bind the toggleHighlight function - created above - as
// the event-handler for both the 'mouseenter' and 'mouseleave'
// events:
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
// here we use document.getElementsByClassName() to retrieve an HTMLCollection
// of elements matching the supplied class-name; and then using chaining - which
// is why we extended the Object prototype - to pass that HTMLCollection to
// the classHighlight() function:
document.getElementsByClassName('test').classHighlight('whenOver');
.whenOver {
background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
この更新されたアプローチは、要素のstyle
属性でインライン スタイルを追加およびクリアするのではなく、クラス名を切り替えているため、セレクターの特異性がスタイルの適用に干渉する可能性があることを意味します。次に例を示します。
// extending the Object prototype to allow chaining of this method,
// 'over' : String, the class-name to add when the element(s) of the
// HTMLCollection/NodeList are hovered-over. We also set the default
// value of the 'over' variable in order that a class-name will always
// be present:
Object.prototype.classHighlight = function(over = 'over') {
// taking the 'this' and using the spread operator to expand
// the iterable collection to an Array:
const that = [...this],
// creating a named function to act as the event-handler for
// 'mouseenter' and 'mouseleave':
toggleHighlight = (event) => {
// iterating over the array using Array.prototype.forEach():
that.forEach(
// we're not using 'this' in here, so using an Arrow function
// to use the Element.classList API to toggle the supplied
// class on each element of the collection. If the event-type
// is exactly equal to 'mouseenter' we add the class otherwise
// we remove the class:
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
// iterating over the collection, again using Array.prototype.forEach():
that.forEach(
// and another Arrow function:
(element) => {
// here we bind the toggleHighlight function - created above - as
// the event-handler for both the 'mouseenter' and 'mouseleave'
// events:
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
// here we use document.getElementsByClassName() to retrieve an HTMLCollection
// of elements matching the supplied class-name; and then using chaining - which
// is why we extended the Object prototype - to pass that HTMLCollection to
// the classHighlight() function:
document.getElementsByClassName('test').classHighlight('whenOver');
li.test {
background-color: fuchsia;
}
.whenOver {
background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
これは、割り当てられたクラス名のセレクターの特異性を高めることで解決できます。
li.test {
background-color: fuchsia;
}
html body .whenOver {
background-color: #f90;
}
Object.prototype.classHighlight = function(over = 'over') {
const that = [...this],
toggleHighlight = (event) => {
that.forEach(
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
that.forEach(
(element) => {
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
document.getElementsByClassName('test').classHighlight('whenOver');
li.test {
background-color: fuchsia;
}
html body .whenOver {
background-color: #f90;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
または、代わりに!important
キーワードを使用して!important
、特定性に関係なくその -化されたプロパティを強制的に適用することもできます (別のルールも使用し!important
、それ自体がより具体的でない限り)。たとえば、次のようになります。
/* Note the ridiculous and overly-specific selector: */
html > body > ul > li.test {
background-color: fuchsia;
}
.whenOver {
/ and here, as the demo shows, !important still
wins: */
background-color: #f90 !important;
}
Object.prototype.classHighlight = function(over = 'over') {
const that = [...this],
toggleHighlight = (event) => {
that.forEach(
(el) => el.classList.toggle(over, event.type === 'mouseenter')
);
};
that.forEach(
(element) => {
element.addEventListener('mouseenter', toggleHighlight);
element.addEventListener('mouseleave', toggleHighlight);
});
};
document.getElementsByClassName('test').classHighlight('whenOver');
html > body > ul > li.test {
background-color: fuchsia;
}
.whenOver {
background-color: #f90 !important;
}
<p class="test">Testing</p>
<div>No classes here</div>
<ul>
<li class="test">Something in a 'test' element</li>
</ul>
ただし、MDN が指摘しているように、 に関しては!important
、可能な限り使用を避けるようにしてください。
ただし、を使用!important
することは悪い習慣であり、スタイルシートの自然な [カスケード] を壊してデバッグをより困難にするため、避ける必要があります。
「例外」!important
MDN .
参考文献: