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, result){
// Default result to an empty jQuery object if not provided
result = typeof result !== 'undefined' ?
result :
new jQuery();
// Iterate through all children, except those match Mask
this.children().each(function(){
thisObject = jQuery( this );
if( thisObject.is( Selector ) )
result.push( this );
// Recursively seek children without Mask
if( !thisObject.is( Mask ) )
thisObject.findExclude( Selector, Mask, result );
});
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
{
...