xbase-2.x-dev/js/libraries/jquery.clicktoggle/jquery.clicktoggle.js
js/libraries/jquery.clicktoggle/jquery.clicktoggle.js
;(function($, window, document, undefined) {
'use strict';
var pluginName = 'clickToggle';
var defaults = {
target: {
'this': 'is-open',
},
event: 'click',
autoClose: false,
autoCloseIgnore: [],
closeElement: null,
condition: null,
openCallback: null,
preOpenCallback: null,
firstOpenCallback: null,
closeCallback: null,
};
function Plugin (element, options) {
this.element = element;
this.settings = $.extend({}, defaults, options);
this._defaults = defaults;
this.init();
}
$.extend(Plugin.prototype, {
/**
* Plugin init.
*/
init: function () {
var pluginInstance = this;
var $clickedElement = $(pluginInstance.element);
$clickedElement.on(pluginInstance.settings.event + '.clickToggle', function (event) {
if (pluginInstance.settings.condition && pluginInstance.settings.condition($clickedElement) === false) {
return;
}
event.preventDefault();
var isOpen = pluginInstance.isOpen();
if (!isOpen) {
pluginInstance.open();
}
else {
pluginInstance.close();
}
// Auto close by click outside
if (pluginInstance.settings.autoClose && !isOpen) {
$(document).on('click.clickToggle', function (event) {
var $eventTarget = $(event.target);
if ($eventTarget.closest($clickedElement).length) {
if (!pluginInstance.isOpen()) {
$(this).off(event);
}
}
else if (
pluginInstance.settings.autoCloseIgnore &&
!pluginInstance.elementIsContainedInElements($eventTarget, pluginInstance.settings.autoCloseIgnore, $clickedElement)
) {
pluginInstance.close();
}
});
}
});
if (pluginInstance.settings.closeElement) {
$(pluginInstance.settings.closeElement).on('click.clickToggle', function () {
$clickedElement.trigger('click');
});
}
},
/**
* Destroy plugin instance.
*/
destroy: function () {
var pluginInstance = this;
var $clickedElement = $(pluginInstance.element);
$clickedElement.off(pluginInstance.settings.event + '.clickToggle');
if (pluginInstance.settings.closeElement) {
$(pluginInstance.settings.closeElement).off('click.clickToggle');
}
$clickedElement.data(pluginName + 'Plugin', null);
},
/**
* "Open" handler.
*/
open: function () {
var pluginInstance = this;
var $clickedElement = $(pluginInstance.element);
if (pluginInstance.isOpen()) {
return;
}
$clickedElement.trigger('clickToggleBeforeOpen', [pluginInstance.settings]);
if (pluginInstance.settings.preOpenCallback) {
pluginInstance.settings.preOpenCallback($clickedElement, pluginInstance.settings);
}
// Add classes
$.each(pluginInstance.settings.target, function (key, value) {
var target = pluginInstance.getTarget(key, value, $clickedElement);
if (target.element.length) {
target.element.addClass(target.className);
}
});
// Run callbacks
if (pluginInstance.settings.firstOpenCallback && !$clickedElement.data('was-clicked')) {
pluginInstance.settings.firstOpenCallback($clickedElement, pluginInstance.settings);
$clickedElement.data('was-clicked', true);
}
if (pluginInstance.settings.openCallback) {
pluginInstance.settings.openCallback($clickedElement, pluginInstance.settings);
}
$clickedElement.trigger('clickToggleOpen', [pluginInstance.settings]);
},
/**
* "Close" handler.
*/
close: function () {
var pluginInstance = this;
var $clickedElement = $(pluginInstance.element);
if (!pluginInstance.isOpen()) {
return;
}
$clickedElement.trigger('clickToggleBeforeClose', [pluginInstance.settings]);
// Remove classes
$.each(pluginInstance.settings.target, function (key, value) {
var target = pluginInstance.getTarget(key, value, $clickedElement);
if (target.element.length) {
target.element.removeClass(target.className);
}
});
// Run callbacks
if (pluginInstance.settings.closeCallback) {
pluginInstance.settings.closeCallback($clickedElement, pluginInstance.settings);
}
$clickedElement.trigger('clickToggleClose', [pluginInstance.settings]);
},
/**
* Return element by selector, or pseudo-selector, or function.
*/
getElement: function (element, context) {
var $context = $(context);
var $element;
if (element instanceof jQuery) {
$element = element;
}
else if (element == 'this') {
$element = $context;
}
else if (element == 'parent') {
$element = $context.parent();
}
else if (element == 'next') {
$element = $context.next();
}
else if ($.isFunction(element)) {
$element = element($context, this.settings);
}
else {
$element = $(element);
}
return $element;
},
/**
* Return true if element is open.
*/
isOpen: function () {
var $clickedElement = $(this.element);
var firstTargetKey = Object.keys(this.settings.target)[0];
var firstTarget = this.getTarget(firstTargetKey, this.settings.target[firstTargetKey], $clickedElement);
return firstTarget.element.hasClass(firstTarget.className);
},
/**
* Return target element and class.
*/
getTarget: function (key, value, context) {
return {
element: (typeof value == 'object') ? this.getElement(value.element, context) : this.getElement(key, context),
className: (typeof value == 'object') ? value.className : value,
};
},
/**
* Return true if checkedElement contained in any element from elementsArray.
*/
elementIsContainedInElements: function (checkedElement, elementsArray, elementsArrayContext) {
var pluginInstance = this;
var $checkedElement = $(checkedElement);
var contained = false;
elementsArray = Array.isArray(elementsArray) ? elementsArray : [elementsArray];
$.each(elementsArray, function (index, elementFromArray) {
var $elementFromArray = pluginInstance.getElement(elementFromArray, elementsArrayContext);
if ($checkedElement.closest($elementFromArray).length > 0) {
contained = true;
}
});
return contained;
},
});
$.fn[pluginName] = function (options) {
if (typeof(options) != 'object') {
options = {target: {}};
options.target[arguments[0]] = arguments[1];
}
return this.each(function () {
if (!$.data(this, pluginName + 'Plugin')) {
$.data(this, pluginName + 'Plugin', new Plugin(this, options));
}
});
};
})(jQuery, window, document);
