JSFiddle - React, Tailwind, and code Playground
HTML
<ul class="Interface" data-role="Container">
<li class="title">Some title</li>
<li>
<article>Message content</article>
</li>
<li class="vote controls">
<button class="up" data-role="VoteUp">1</button>
<button class="down" data-role="VoteDown">0</button>
</li>
<li class="social controls">
<button class="up" data-role="ReplyButton">Reply</button>
</li>
<li class=" NESTING HERE ENDS AT LINE_28 ">
<ul class="Interface" data-role="Container">
<li class="title">Re: Some title</li>
<li>
<article>Another Message content</article>
</li>
<li class="vote controls">
<button class="up" data-role="VoteUp"> <i class="fa fa-caret-up"> 1 </i>
</button>
<button class="down" data-role="VoteDown"> <i class="fa fa-caret-down"> 0 </i>
</button>
</li>
<li class="social controls">
<button class="up" data-role="ReplyButton">Reply</button>
</li>
</ul>
</li>
<li class="Interface SomethingElse"> <span> Meaningless Heading </span>
<div data-role="SuperContent">I could put stuff in here and let the controls <span class="controls">Inherit their role <a href="#">Click</a></span>
<div class="controls" data-role="special">
<button data-role="Command">or define them</button>
<button>In different ways</button>
</div>
</div>
</li>
</ul>
<!-- This should work even when '.Interface' is nested in itself: $('.Interface').each( function(){ $(this).findExcept('.controls','.Interface').on('click',func) ); Sometimes not required when .each is unneeded (in normal chaining), still works with chains. -->
JavaScript
// Find-like method which masks any descendant
// branches matching the Mask argument.
$.fn.findExclude = function (Selector, Mask) {
var startTime = new Date();
var result = $([]);
$(this).each(function (Idx, Elem) {
$(Elem).find(Selector).each(function (Idx2, Elem2) {
if ($(Elem2).closest(Mask)[0] == Elem) {
result = result.add(Elem2);
}
});
});
console.log(new Date().getTime() - startTime.getTime());
return result;
}
var Interface = function (Markup) {
$elf = this;
$elf.call = {
init: function (Markup) {
$elf.Interface = Markup;
$elf.Controls = $(Markup).findExclude('.controls', '.Interface');
$elf.Controls.on('click mouseenter mouseleave', this.events);
return $elf;
},
ReplyButton: function () {
console.log('Reply clicked');
},
VoteUp: function () {
console.log('Up vote');
},
VoteDown: function () {
console.log('Down Vote');
},
events: function (e) {
var role = $(e.target).data('role');
if (e.type == 'click') {
CurrentControl = $(e.target).closest('.controls')[0];
if (typeof $(e.target).data('role') !== 'undefined') role = $(e.target).data('role');
else role = $(e.target).closest('[data-role]').data('role');
// Call any defined role action, alternative to switch(role)
if ($.isFunction($elf.call[role])) $elf.call[role](e);
// No function found matching role name
else {
console.log('');
console.log('No ' + e.type + ' handler for "' + role + '" on: ', e.target);
}
} // End click listener
} // End call.events function
} // End $elf.call
return $elf.call.init(Markup);
}; // End Interface...