Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@bhalash
Last active May 15, 2016 22:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bhalash/61c8a90cd4b88f978051233c6a260c93 to your computer and use it in GitHub Desktop.
Save bhalash/61c8a90cd4b88f978051233c6a260c93 to your computer and use it in GitHub Desktop.
jQuery-based data binding directives
(function($, document, window) {
/**
* Event subscribe/unsubscribe.
*
* @link https://davidwalsh.name/pubsub-javascript
* @link https://gist.github.com/cowboy/661855
*/
$.observer = $({});
/**
* Break up arguments object into useful data.
*
* For each action fragment (see below), broadcast an action with that
* fragment's data:
*
* @param {object} args - Arguments object.
* @returns {array} actions - Mapped actions array.
*
*/
$.observer.triggers = function(args) {
var args = Array.prototype.slice.apply(args),
triggers = args[0].split(':'),
data = {};
data = $.observer.triggers.data(triggers, args);
triggers = $.observer.triggers.arr(triggers, args, data);
return triggers;
}
/**
* Construct data object for event.
*
* This hold information about the complete action (action, method and
* target).
*
* fullAction is so because a full action has three parameters.
*
* @param {array} triggers - Split array of action fragments.
* @param {array} args - Superset args object.
* @returns {object} triggers
*/
$.observer.triggers.data = function(triggers, args) {
var target = null,
fullAction = 3;
if (triggers.length === fullAction) {
target = triggers[2];
} else if (typeof(args[1]) === 'string') {
target = args[1];
}
return {
action: triggers[0],
method: triggers[1],
target: target
};
}
/**
* Construct complete trigger stack for action.
*
* 'modal:show:lightbox' =
* 'modal'
* 'modal:show'
* 'modal:show:lightbox'
*
* The last line is dense: jQuery's trigger takes an optional array of
* parameters to apply. The first array element is the trigger action
* detailed above. The second array element contains the data object
* followed by all of the other arguments passed to the trigger.
*
* return [event, [data, arg1, arg2, arg3]]
*
* $.observer.trigger(event, [data, arg1, arg2, arg3])
*
* @link https://api.jquery.com/trigger/
* @param {array} triggers - Split array of action fragments.
* @param {array} args - Superset args object.
* @param {object} data - Constructed action data object.
* @returns {array} triggers
*
*/
$.observer.triggers.arr = function(triggers, args, data) {
var trigger = '';
// See explanation above.
data = [data].concat(args.slice(1));
return triggers.map(function(fragment, index) {
if (index) {
trigger = trigger.concat(':');
}
trigger = trigger.concat(fragment);
return [trigger, data];
});
}
/**
* Subscribe and unsubscribe actions.
*
* @link https://gist.github.com/cowboy/661855
* @param {string} name
* @param {string} action
*/
$.each({ on: 'subscribe', off: 'unsubscribe' }, function(name, action) {
$[action] = function() {
$.observer[name].apply($.observer, arguments);
}
});
/**
* Broadcast action.
*
* More complex than the subscribe and unsubscribe, because it splits up the
* triggering event into individual fragments to trigger individually:
*
* 'modal:show:lightbox' =
* 'modal'
* 'modal:show'
* 'modal:show:lightbox'
*/
$.broadcast = function() {
$.observer.triggers(arguments).forEach(function(action) {
$.observer.trigger.apply($.observer, action);
});
}
/**
* Click directive.
*
* Just an example, because that's all I need right now.
*
* @param {object} event - DOM event.
* @param {bool} false - Prevent normal click action from occurring.
*/
$(document).on('click tap', '[data-click]', function(event) {
$.broadcast($(event.currentTarget).data('click'), event.currentTarget);
return false;
});
})(jQuery, document, window);
<img
data-click="modal:show:lightbox"
src="https://ix.bhalash.com/13544806616/m/1_1600.jpg"
srcset="https://ix.bhalash.com/13544806616/m/1_1600.jpg 1600w,
https://ix.bhalash.com/13544806616/m/1_1280.jpg 1280w,
https://ix.bhalash.com/13544806616/m/1_1024.jpg 1024w,
https://ix.bhalash.com/13544806616/m/1_768.jpg 768w,
https://ix.bhalash.com/13544806616/m/1_640.jpg 640w,
https://ix.bhalash.com/13544806616/m/1_480.jpg 480w"
sizes="(min-width: 480) 100%"
alt="Friend and I">
(function($, document, window) {
/**
* Broadcast to hide all modals when <Esc> is depressed.
*
* @param {object} event - DOM event.
*/
$(document).on('keydown', function(event) {
switch (event.keyCode) {
case 27: $.broadcast('modal:hide'); break;
}
});
/**
* Show specified modal.
*
* Show modal if data is set.
*
* @param {object} event - DOM event.
* @param {object} data - Binding event data.
*/
$.subscribe('modal:show', function(event, data) {
if (data.target) {
$.broadcast('modal:hide');
$('[data-modal="' + data.target + '"]').removeClass('hidden').show();
}
});
/**
* Hide specified/all modals.
*
* If there is no data set, hide all modals.
*
* @param {object} event - DOM event.
* @param {object} data - Binding event data.
*/
$.subscribe('modal:hide', function(event, data) {
var modal = '[data-modal]';
if (data.target) {
modal = '[data-modal="' + data.target + '"]';
}
$(modal).hide();
});
/**
* Set lightbox image when the modal is shown.
*
* @param {object} event - DOM event.
* @param {object} data - Binding event data.
* @param {object} element - Event triggering element.
*/
$.subscribe('modal:show:lightbox', function(event, data, element) {
data = {
src: $(element).data('src') || $(element).attr('src'),
alt: $(element).data('alt') || $(element).attr('alt')
};
$('.lightbox__image').attr(data);
});
/**
* Focus the modal search input after it is displayed.
*/
$.subscribe('modal:show:search', function() {
$('.modal-search__input').focus();
});
})(jQuery, document, window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment