Skip to content

Instantly share code, notes, and snippets.

@ncherro
Last active December 22, 2015 16:18
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 ncherro/6498150 to your computer and use it in GitHub Desktop.
Save ncherro/6498150 to your computer and use it in GitHub Desktop.
jquery toggler plugin
/*!
* jQuery toggler plugin
* Original other: @ncherro
* Licensed under the MIT License
*/
;(function ($, window, document, undefined) {
var plugin_name = 'toggler',
defaults = {
on_class: 'on',
toggle_on_click: true,
show_on_mouseover: true,
hide_on_mouseout: true,
delay: 50, // how long should we wait before checking the hover count (in ms)
hide_others: true, // hide other instances when this instance displays
after_init: null, // callback
on_show: null, // callback
on_hide: null // callback
},
instances = [];
function Plugin(el, opts) {
this.id = instances.length; // unique identifier
this.el = el;
this.settings = $.extend({}, defaults, opts);
this._defaults = defaults;
this._name = plugin_name;
this.init();
};
Plugin.prototype = {
locked: false,
hover_count: 0,
init: function() {
this.$el = $(this.el);
this.$toggled = $(this.$el.data('toggle'));
if (this.$toggled.length == 0) return;
// quick reference to both elements
this.$all = this.$el.add(this.$toggled);
if (this.settings.toggle_on_click) {
// toggle on click
this.$el.click($.proxy(this.toggle, this));
}
if (this.settings.show_on_mouseover) {
// show on mouseover
this.$all.mouseenter($.proxy(this.over, this));
}
if (this.settings.hide_on_mouseout) {
// hide on mouseout
this.$all.mouseleave($.proxy(this.out, this));
}
if (typeof this.settings.after_init === 'function') {
this.settings.after_init.call(this);
}
},
toggle: function(e) {
if (e) e.preventDefault();
this.$all.toggleClass(this.settings.on_class);
if (this.$el.hasClass(this.settings.on_class)) {
if (this.settings.hide_others) {
this.hideOthers();
}
if (typeof this.settings.on_show === 'function') {
this.settings.on_show.call(this);
}
}
},
checkHoverCount: function() {
if (this.hover_count <= 0) {
if (typeof this.settings.on_hide === 'function' && this.$el.hasClass(this.settings.on_class)) {
this.settings.on_hide.call(this);
}
this.$all.removeClass(this.settings.on_class);
this.hover_count = 0; // probably not necessary
}
},
hideOthers: function() {
for (var i=0, len=instances.length; i<len; i++) {
if (instances[i].id != this.id) {
// force hide
instances[i].hover_count = 0;
instances[i].locked = false;
instances[i].out();
}
}
},
over: function(e) {
if (this.settings.hide_others) this.hideOthers();
if (this.locked) return;
this.hover_count ++;
this.$all.addClass(this.settings.on_class);
if (typeof this.settings.on_show === 'function') {
this.settings.on_show.call(this);
}
},
out: function(e) {
if (this.locked) return;
this.hover_count --;
// check in X ms (allows mouse to go from one element to the other)
setTimeout($.proxy(this.checkHoverCount, this), this.settings.delay);
}
};
$.fn[plugin_name] = function(options) {
var instance;
return this.each(function() {
if (!$.data(this, "plugin_" + plugin_name)) {
instance = new Plugin(this, options);
instances.push(instance);
$.data(this, "plugin_" + plugin_name, instance);
}
});
}
}(jQuery, window, document));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment