Skip to content

Instantly share code, notes, and snippets.

@serradura
Last active January 31, 2019 13:23
Show Gist options
  • Save serradura/279ddb7f3aa4a68b5aaf882031f7ffdc to your computer and use it in GitHub Desktop.
Save serradura/279ddb7f3aa4a68b5aaf882031f7ffdc to your computer and use it in GitHub Desktop.
jQuery.behavior (Demo: https://jquery-behavior.firebaseapp.com)
<!DOCTYPE html>
<html>
<head>
<title>jQuery.behavior</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<a href="01.html">01</a> | <a href="02.html">02</a> | <a href="03.html">03</a> | <a href="04.html">04</a> | <a href="05.html">05</a>
<hr>
<p>
<button data-behavior="greet">Greet</button>
</p>
<pre class="prettyprint">
&lt;button data-behavior="greet"&gt;Greet&lt;/button&gt;
</pre>
<pre class="prettyprint">
var greet = function() { alert('Hello!') };
$.behavior( 'greet' ).on( 'click', greet );
</pre>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.js"></script>
<script src="./jquery.behavior.js"></script>
<script>
$(function() {
var greet = function() { alert('Hello!') }
$.behavior( 'greet' ).on( 'click', greet );
});
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>jQuery.behavior</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<a href="01.html">01</a> | <a href="02.html">02</a> | <a href="03.html">03</a> | <a href="04.html">04</a> | <a href="05.html">05</a>
<hr>
<p>
<button data-behavior="greet-with-name">Greet with Name</button>
</p>
<pre class="prettyprint">
&lt;button data-behavior="greet-with-name"&gt;Greet with Name&lt;/button&gt;
</pre>
<pre class="prettyprint">
var greetWithName = function( event ) {
alert( 'Hello ' + event.data + '!' )
};
$.behavior( 'greet-with-name' )
.on( 'click', 'Serradura', greetWithName );
</pre>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.js"></script>
<script src="./jquery.behavior.js"></script>
<script>
$(function() {
var greetWithName = function( event ) {
alert( 'Hello ' + event.data + '!' )
};
$.behavior( 'greet-with-name' )
.on( 'click', 'Serradura', greetWithName );
});
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>jQuery.behavior</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<a href="01.html">01</a> | <a href="02.html">02</a> | <a href="03.html">03</a> (<a href="03a.html">a</a>, <a href="03b.html">b</a>) | <a href="04.html">04</a> | <a href="05.html">05</a>
<hr>
<p data-behavior="counter">
<button data-behavior="increment">+</button>
<span data-behavior-target="number">0</span>
<button data-behavior="decrement">-</button>
</p>
<pre class="prettyprint">
&lt;p data-behavior="counter"&gt;
&lt;button data-behavior="increment"&gt;+&lt;/button&gt;
&lt;span data-behavior-target="number"&gt;0&lt;/span&gt;
&lt;button data-behavior="decrement"&gt;-&lt;/button&gt;
&lt;/p&gt;
</pre>
<pre class="prettyprint">
$.behavior( 'counter' ).ifPresent(function( root ) {
var state = 0;
var updateNumber = function(number) {
root.directTarget( 'number' ).text( number );
};
var handleIncrement = function() {
updateNumber( state = state + 1 );
};
var handleDecrement = function() {
updateNumber( state = state - 1 );
};
root.child( 'increment' ).on( 'click', handleIncrement );
root.child( 'decrement' ).on( 'click', handleDecrement );
});
</pre>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.js"></script>
<script src="./jquery.behavior.js"></script>
<script>
$(function() {
$.behavior( 'counter' ).ifPresent(function( root ) {
var state = 0;
var updateNumber = function(number) {
root.directTarget( 'number' ).text( number );
};
var handleIncrement = function() {
updateNumber( state = state + 1 );
};
var handleDecrement = function() {
updateNumber( state = state - 1 );
};
root.child( 'increment' ).on( 'click', handleIncrement );
root.child( 'decrement' ).on( 'click', handleDecrement );
});
});
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>jQuery.behavior</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<a href="01.html">01</a> | <a href="02.html">02</a> | <a href="03.html">03</a> (<a href="03a.html">a</a>, <a href="03b.html">b</a>) | <a href="04.html">04</a> | <a href="05.html">05</a>
<hr>
<p data-behavior="counter">
<button data-behavior="increment">+</button>
<span data-behavior-target="number">0</span>
<button data-behavior="decrement">-</button>
</p>
<p data-behavior="counter">
<button data-behavior="increment">+</button>
<span data-behavior-target="number">0</span>
<button data-behavior="decrement">-</button>
</p>
<p data-behavior="counter">
<button data-behavior="increment">+</button>
<span data-behavior-target="number">0</span>
<button data-behavior="decrement">-</button>
</p>
<pre class="prettyprint">
&lt;p data-behavior="counter"&gt;
&lt;button data-behavior="increment"&gt;+&lt;/button&gt;
&lt;span data-behavior-target="number"&gt;0&lt;/span&gt;
&lt;button data-behavior="decrement"&gt;-&lt;/button&gt;
&lt;/p&gt;
</pre>
<pre class="prettyprint">
$.behavior( 'counter' ).ifPresent(function( root ) {
var state = 0;
var updateNumber = function(number) {
root.directTarget( 'number' ).text( number );
};
var handleIncrement = function() {
updateNumber( state = state + 1 );
};
var handleDecrement = function() {
updateNumber( state = state - 1 );
};
root.child( 'increment' ).on( 'click', handleIncrement );
root.child( 'decrement' ).on( 'click', handleDecrement );
});
</pre>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.js"></script>
<script src="./jquery.behavior.js"></script>
<script>
$(function() {
$.behavior( 'counter' ).ifPresent(function( root ) {
var state = 0;
var updateNumber = function(number) {
root.directTarget( 'number' ).text( number );
};
var handleIncrement = function() {
updateNumber( state = state + 1 );
};
var handleDecrement = function() {
updateNumber( state = state - 1 );
};
root.child( 'increment' ).on( 'click', handleIncrement );
root.child( 'decrement' ).on( 'click', handleDecrement );
});
});
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>jQuery.behavior</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<a href="01.html">01</a> | <a href="02.html">02</a> | <a href="03.html">03</a> (<a href="03a.html">a</a>, <a href="03b.html">b</a>) | <a href="04.html">04</a> | <a href="05.html">05</a>
<hr>
<p data-behavior="counter">
<button data-behavior="increment">+</button>
<span data-behavior-target="number">0</span>
<button data-behavior="decrement">-</button>
</p>
<p data-behavior="counter">
<button data-behavior="increment">+</button>
<span data-behavior-target="number">0</span>
<button data-behavior="decrement">-</button>
</p>
<p data-behavior="counter">
<button data-behavior="increment">+</button>
<span data-behavior-target="number">0</span>
<button data-behavior="decrement">-</button>
</p>
<pre class="prettyprint">
&lt;p data-behavior="counter"&gt;
&lt;button data-behavior="increment"&gt;+&lt;/button&gt;
&lt;span data-behavior-target="number"&gt;0&lt;/span&gt;
&lt;button data-behavior="decrement"&gt;-&lt;/button&gt;
&lt;/p&gt;
</pre>
<pre class="prettyprint">
$.behavior( 'counter' ).ifPresent(function( root, $root ) {
$root.on( 'updateNumber', function(_, number) {
root.target( 'number' ).text( number );
});
var setState = function(value) { this.data( 'state', value ) };
var getState = function() { return this.data( 'state' ) || 0 };
var updateNumberWith = function(value) {
return function() {
var number = getState.call( $root ) + value;
setState.call( $root, number );
$root.trigger( 'updateNumber', number );
};
};
var handleClickAndAdd = function(value) {
return function() {
this.on( 'click', updateNumberWith( value ) );
}
};
root.child( 'increment' ).ifPresent( handleClickAndAdd( 1 ) );
root.child( 'decrement' ).ifPresent( handleClickAndAdd( -1 ) );
});
</pre>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.js"></script>
<script src="./jquery.behavior.js"></script>
<script>
$(function() {
$.behavior( 'counter' ).ifPresent(function( root, $root ) {
$root.on( 'updateNumber', function(_, number) {
root.target( 'number' ).text( number );
});
var setState = function(value) { this.data( 'state', value ) };
var getState = function() { return this.data( 'state' ) || 0 };
var updateNumberWith = function(value) {
return function() {
var number = getState.call( $root ) + value;
setState.call( $root, number );
$root.trigger( 'updateNumber', number );
};
};
var handleClickAndAdd = function(value) {
return function() {
this.on( 'click', updateNumberWith( value ) );
}
};
root.child( 'increment' ).ifPresent( handleClickAndAdd( 1 ) );
root.child( 'decrement' ).ifPresent( handleClickAndAdd( -1 ) );
});
});
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>jQuery.behavior</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
.text-red { color: red; }
.text-blue { color: blue; }
</style>
</head>
<body>
<a href="01.html">01</a> | <a href="02.html">02</a> | <a href="03.html">03</a> | <a href="04.html">04</a> | <a href="05.html">05</a>
<hr>
<div data-behavior="filters">
<p data-behavior="event-toggler">
Filters:
<button data-behavior="enable" class="text-blue" style="display: none;">
Turn on Events
</button>
<button data-behavior="disable" class="text-red">
Turn off Events
</button>
</p>
<p>
<select data-behavior="numbers-filter">
<option value="">Select any number</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
</p>
<p data-behavior="query-filter">
<input type="text" data-behavior-target="query">
<button type="button" data-behavior="submit-query">Search</button>
</p>
</div>
<pre class="prettyprint">
&lt;div data-behavior="filters"&gt;
&lt;p data-behavior="event-toggler"&gt;
Filters:
&lt;button data-behavior="enable" class="text-blue" style="display: none;"&gt;
Turn on Events
&lt;/button&gt;
&lt;button data-behavior="disable" class="text-red"&gt;
Turn off Events
&lt;/button&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;select data-behavior="numbers-filter"&gt;
&lt;option value=""&gt;Select any number&lt;/option&gt;
&lt;option value="1"&gt;1&lt;/option&gt;
&lt;option value="2"&gt;2&lt;/option&gt;
&lt;/select&gt;
&lt;/p&gt;
&lt;p data-behavior="query-filter"&gt;
&lt;input type="text" data-behavior-target="query"&gt;
&lt;button type="button" data-behavior="submit-query"&gt;Search&lt;/button&gt;
&lt;/p&gt;
&lt;/div&gt;
</pre>
<pre class="prettyprint">
var NumbersFilter = function( $root ) {
var find = function( $root ) {
return $.behavior.child( 'numbers-filter' ).of( $root );
};
var mount = function( root ) {
find( $root ).on( 'change', function() {
var value = $( this ).val();
root.trigger( 'alert', [ 'number', value ] );
});
};
var unmount = function() { find( $root ).off( 'change' ); };
return { mount: mount, unmount: unmount };
};
var QueryFilter = function( root ) {
var submitQuery = root.child( 'submit-query' );
var mount = function( filters ) {
submitQuery.on( 'click', function( e ) {
e.preventDefault();
var value = root.target( 'query' ).val();
filters.trigger( 'alert', [ 'query', value ] )
})
};
var unmount = function() { submitQuery.off( 'click' ) };
return { mount: mount, unmount: unmount };
};
var FiltersComponent = (function() {
var filters = $.behavior( 'filters' );
var queryFilter = filters.child( 'query-filter' );
filters.on( 'alert', function( _event, filter, value ) {
var filterLabel = 'Filter: ' + filter;
if ( value ) return alert( filterLabel + ' | value: ' + value );
console.log( filterLabel + ' | There is nothing to alert. :(' );
});
var mountChildrenComponents = function( filters ) {
NumbersFilter( this ).mount( filters );
QueryFilter( queryFilter ).mount( filters );
};
var unmountChildrenComponents = function() {
NumbersFilter( this ).unmount();
QueryFilter( queryFilter ).unmount();
};
var mountEventToggler = function( filters ) {
filters.child( 'event-toggler' ).ifPresent(function( buttons ) {
var disableButton = buttons.child( 'disable' );
var enableButton = buttons.child( 'enable' );
var show = function() { this.show() };
disableButton.on( 'click', function() {
if ( confirm( 'Are you sure?' ) ) {
$( this ).hide();
filters.ifPresent( unmountChildrenComponents );
enableButton.ifPresent( show );
}
});
enableButton.on( 'click', function() {
$( this ).hide();
filters.ifPresent( mountChildrenComponents );
disableButton.ifPresent( show );
});
})
};
return {
mount: function() {
filters.ifPresent( mountChildrenComponents );
filters.ifPresent( mountEventToggler );
}
}
}());
FiltersComponent.mount();
</pre>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.js"></script>
<script src="./jquery.behavior.js"></script>
<script>
$(function() {
var NumbersFilter = function( $root ) {
var find = function( $root ) {
return $.behavior.child( 'numbers-filter' ).of( $root );
};
var mount = function( root ) {
find( $root ).on( 'change', function() {
var value = $( this ).val();
root.trigger( 'alert', [ 'number', value ] );
});
};
var unmount = function() { find( $root ).off( 'change' ); };
return { mount: mount, unmount: unmount };
};
var QueryFilter = function( root ) {
var submitQuery = root.child( 'submit-query' );
var mount = function( filters ) {
submitQuery.on( 'click', function( e ) {
e.preventDefault();
var value = root.target( 'query' ).val();
filters.trigger( 'alert', [ 'query', value ] )
})
};
var unmount = function() { submitQuery.off( 'click' ) };
return { mount: mount, unmount: unmount };
};
var FiltersComponent = (function() {
var filters = $.behavior( 'filters' );
var queryFilter = filters.child( 'query-filter' );
filters.on( 'alert', function( _event, filter, value ) {
var filterLabel = 'Filter: ' + filter;
if ( value ) return alert( filterLabel + ' | value: ' + value );
console.log( filterLabel + ' | There is nothing to alert. :(' );
});
var mountChildrenComponents = function( filters ) {
NumbersFilter( this ).mount( filters );
QueryFilter( queryFilter ).mount( filters );
};
var unmountChildrenComponents = function() {
NumbersFilter( this ).unmount();
QueryFilter( queryFilter ).unmount();
};
var mountEventToggler = function( filters ) {
filters.child( 'event-toggler' ).ifPresent(function( buttons ) {
var disableButton = buttons.child( 'disable' );
var enableButton = buttons.child( 'enable' );
var show = function() { this.show() };
disableButton.on( 'click', function() {
if ( confirm( 'Are you sure?' ) ) {
$( this ).hide();
filters.ifPresent( unmountChildrenComponents );
enableButton.ifPresent( show );
}
});
enableButton.on( 'click', function() {
$( this ).hide();
filters.ifPresent( mountChildrenComponents );
disableButton.ifPresent( show );
});
})
};
return {
mount: function() {
filters.ifPresent( mountChildrenComponents );
filters.ifPresent( mountEventToggler );
}
}
}());
FiltersComponent.mount();
});
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>jQuery.behavior</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body class="index">
<a href="01.html">01</a> | <a href="02.html">02</a> | <a href="03.html">03</a> | <a href="04.html">04</a> | <a href="05.html">05</a>
<hr>
<pre class="prettyprint">
&lt;body class="index"&gt;
&lt;!--...--&gt;
&lt;/body&gt;
</pre>
<pre class="prettyprint">
var MESSAGE = 'Added after document be ready and because \'.index\' selector was found!';
var awaitAndAppendContent = function() {
var $content = $( '&lt;h2&gt;' ).text( MESSAGE );
var appendContent = function() { $( 'body' ).append( $content ) }
setTimeout( appendContent, 700 );
}
$.behavior.to( '.index' ).ifPresent( awaitAndAppendContent );
</pre>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.slim.js"></script>
<script src="./jquery.behavior.js"></script>
<script>
$(function() {
var MESSAGE = 'Added after document be ready and because \'.index\' selector was found!';
var awaitAndAppendContent = function() {
var $content = $( '<h2>' ).text( MESSAGE );
var appendContent = function() { $( 'body' ).append( $content ) }
setTimeout( appendContent, 700 );
}
$.behavior.to( '.index' ).ifPresent( awaitAndAppendContent );
});
</script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</body>
</html>
(function() {
var buildBehaviorEventHandlers = (function($DELEGATOR) {
var EVENT_HANDLERS = ['on', 'one', 'off'];
var argumentsToAttachEventHandler = function( behaviorSelector, _arguments ) {
var event = _arguments[0];
var tail = $.makeArray( _arguments ).slice( 1 );
// Performs a flatMap because of tail data;
return $.map(
[ event, behaviorSelector, tail ], function(arg) { return arg }
);
};
var delegateEventHandling = function( eventHandler, args ) {
$DELEGATOR[ eventHandler ].apply( $DELEGATOR, args );
};
// returns a behavior event handler (on, one, off) function. e.g:
// behavior('foo').on('event', function() {}) will be equivalent to
// $( document ).on( 'event', '[data-bevahior="foo"]', function() {});
var buildEventHandler = function( event, behaviorSelector ) {
return function() {
var args = argumentsToAttachEventHandler( behaviorSelector, arguments );
delegateEventHandling( event, args );
return this;
}
};
return function(behaviorSelector) {
var behaviorEventHandlers = {};
$.each( EVENT_HANDLERS, function( _, name ) {
behaviorEventHandlers[name] = buildEventHandler( name, behaviorSelector )
} );
return behaviorEventHandlers;
};
}( $(document) ));
var buildBehaviorEventTrigger = function ( $el ) {
return {
trigger: function() {
$el.trigger.apply( $el, arguments );
return this;
}
};
};
var buildBehaviorSelector = function(name) {
return '[data-behavior="' + name + '"]';
};
var mapBehaviors = function( key, $el, strategy, dataAttr, dataKey, result ) {
var selectorBase = '[' + dataAttr;
var selector = key ? selectorBase + '="' + key + '"]' : selectorBase + ']';
var rel = $el[strategy](selector).map(function(_, target) {
var data = {}, $this = $( target ), dataVal = $this.data( dataKey );
data[dataVal] = result( $this, dataAttr, dataVal );
return data;
});
var result = $.extend.apply( null, [ {} ].concat( rel.get() ) );
return result && result !== window ? result : {};
};
var mapBehaviorsWith = function( strategy ) {
return function( $el , key ) {
return mapBehaviors(
key, $el, strategy, 'data-behavior', 'behavior',
function( $el, dataAttr, dataVal ) {
return createBehavior( '[' + dataAttr + '="' + dataVal + '"]', $el, true )
}
)
}
};
var mapBehaviorTargetsWith = function( strategy ) {
return function( $el, key ) {
return mapBehaviors(
key, $el, strategy, 'data-behavior-target', 'behaviorTarget',
function( $el ) { return $el }
)
}
};
var fetchBehaviorElements = function( mapper, $el ) {
return function( key ) {
var data = mapper( $el, key );
return key ? data[key] : data;
}
};
var buildBehaviorElementFetchers = function( $el ) {
return {
child: fetchBehaviorElements( mapBehaviorsWith('find'), $el ),
target: fetchBehaviorElements( mapBehaviorTargetsWith('find'), $el ),
directChild: fetchBehaviorElements( mapBehaviorsWith('children'), $el ),
directTarget: fetchBehaviorElements( mapBehaviorTargetsWith('children'), $el ),
children: function() { return this.child() },
targets: function() { return this.target() },
directChildren: function() { return this.directChild() },
directTargets: function() { return this.directTarget() }
}
};
var buildBehavior = function( $el, selector ) {
var eventHandlers = buildBehaviorEventHandlers( selector );
var eventTrigger = buildBehaviorEventTrigger( $el );
var fetchers = buildBehaviorElementFetchers( $el );
var base = {
selector: selector,
isPresent: function() { return $el.length > 0 },
ifPresent: function( fn ) {
if ( this.isPresent() ) {
$el.each(function(index) {
var $matched = $( this );
var newBehavior = buildBehavior( $matched, selector );
var args = [ newBehavior, $matched, index ];
fn.apply( $matched, args);
})
}
}
};
return $.extend( base, fetchers, eventTrigger, eventHandlers );
};
var createBehavior = function(selector, $behavior) {
var $el = $behavior || $( selector );
return buildBehavior( $el, selector );
};
var behaviorNodeFinder = function( nodeFinder ) {
return function( name ) {
var findBehaviorNode = function( el ) {
var $el = $( el );
var selector = buildBehaviorSelector( name );
var $node = nodeFinder.call( $el, selector );
if ( $node.length ) {
var behavior = createBehavior( selector, $node );
return $.extend( behavior, buildBehaviorEventTrigger( $node ) );
}
};
return { of: findBehaviorNode };
}
};
$.behavior = function( name ) {
return createBehavior( buildBehaviorSelector( name ) )
};
$.behavior.to = createBehavior;
$.behavior.child = behaviorNodeFinder( function(selector) {
return this.find(selector)
} );
$.behavior.parent = behaviorNodeFinder( function(selector) {
return this.parents(selector)
} );
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment