亮点:辅助弹出层弹出和隐藏 Demo测试页面: http://steper.oschina.io/yx-js-toolkit/popupDismiss/jsPlugin/index.html popupDismissEverywhere.js /** * Javascript plugin: Popup with dismiss v3.0 * */(function () {var bodyElement =
Demo测试页面: http://steper.oschina.io/yx-js-toolkit/popupDismiss/jsPlugin/index.htmlpopupDismissEverywhere.js
/**
* Javascript plugin: Popup with dismiss v3.0
*
*/
(function () {
var bodyElement = null;
var method = {
isTap: undefined,
popupEvent: function (event) {
var popupTrigger = event.target;
if (popupTrigger.getAttribute('data-toggle') !== 'popupDismissEveryWhere')
{
popupTrigger = method.findAncestor(popupTrigger, '[data-toggle="popupDismissEveryWhere"]');
}
var eventData = {
type: event.type,
namespace: popupTrigger.getAttribute('data-target'),
popupTrigger: popupTrigger,
popupTarget: document.querySelector(popupTrigger.getAttribute('data-target')),
toggledClass: popupTrigger.getAttribute('data-toggle-class') || null, // Recommend: 'open'
popupHandler: popupTrigger.getAttribute('data-popup-handler') || null,
dismissHandler: popupTrigger.getAttribute('data-dismiss-handler') || null
};
if (eventData.popupTarget.getAttribute('data-isPopup') !== 'true')
{
method.monitorTap();
if (eventData.toggledClass)
{
method.addClass(eventData.popupTrigger, eventData.toggledClass);
method.addClass(eventData.popupTarget, eventData.toggledClass);
}
eventData.popupTarget.setAttribute('data-isPopup', 'true');
bodyElement.on(eventData.type + "." + eventData.namespace, function (newEvent) {
if (event === newEvent)
{
return;
}
var newEventData = {
type: eventData.type,
namespace: eventData.namespace,
dismissTrigger: newEvent.target,
popupTrigger: eventData.popupTrigger,
popupTarget: eventData.popupTarget,
toggledClass: eventData.toggledClass,
dismissHandler: eventData.dismissHandler
};
newEvent.stopPropagation();
method.popupDismiss(newEventData, true);
});
eventData.popupHandler !== null && window[eventData.popupHandler](eventData.popupTarget);
method.setBodyCursorInIOS("pointer");
}
else
{
eventData.dismissTrigger = popupTrigger;
method.popupDismiss(eventData);
}
},
popupDismiss: function (eventData, isTrigger) {
if (method.isTap === false)
return;
if (!isTrigger ||
(!method.hasCloset(eventData.dismissTrigger, eventData.popupTrigger)
&& method.isDismissTrigger(eventData.dismissTrigger, eventData.popupTarget)
&& eventData.popupTarget.getAttribute('data-isPopup') === 'true'
)
)
{
if (eventData.toggledClass)
{
method.removeClass(eventData.popupTrigger, eventData.toggledClass);
method.removeClass(eventData.popupTarget, eventData.toggledClass);
}
eventData.popupTarget.setAttribute('data-isPopup', 'false');
bodyElement.off(eventData.type + "." + eventData.namespace, function () {
method.popupDismiss(eventData, true);
});
eventData.dismissHandler !== null && window[eventData.dismissHandler](eventData.popupTarget);
method.setBodyCursorInIOS("default");
}
},
monitorTap: function () {
method.isTap = undefined;
var start = {}, end = {};
document.body.addEventListener('mousedown', mouseDown);
document.body.addEventListener('mouseup', mouseUp);
function mouseDown(event)
{
method.isTap = false;
start.x = event.pageX;
start.y = event.pageY;
}
function mouseUp(event)
{
end.x = event.pageX;
end.y = event.pageY;
if (Math.abs(end.x - start.x) < 5 && Math.abs(end.y - start.y) < 5)
{
method.isTap = true;
document.body.removeEventListener('mousedown', mouseDown);
document.body.removeEventListener('mouseup', mouseUp);
}
}
},
// Default: all be dismiss trigger(return true);
// Check click point ($child) has '[data-popup-dismiss="false"]'('[data-popup-dismiss="true"]') or not;
isDismissTrigger: function (child, parent) {
if (method.hasCloset(child, parent))
{
var parentDismissTrue = method.findAncestor(child, '[data-popup-dismiss="true"]'),
parentDismissFalse = method.findAncestor(child, '[data-popup-dismiss="false"]');
if (child.getAttribute('data-popup-dismiss') === 'false')
{
return false;
}
else if (child.getAttribute('data-popup-dismiss') === 'true')
{
return true;
}
else if (parentDismissFalse)
{
return parentDismissTrue ? method.hasCloset(parentDismissTrue, parentDismissFalse) : false;
}
}
return true;
},
// Fix issue : In iOS device, the dismiss function could not be triggered;
setBodyCursorInIOS: function (val) {
if (/iPhone|iPad|iPod/i.test(navigator.userAgent))
{
var body = document.querySelector('body'),
popupCount = parseInt(body.getAttribute('popup-count') || '0', 10);
if (val === 'pointer')
{
++popupCount === 1 && (body.style.cursor = val);
}
else if (val === 'default')
{
--popupCount && (body.style.cursor = val);
}
body.setAttribute('popup-count', popupCount.toString());
}
},
findAncestor: function (el, sel) {
while ((el = el.parentElement) && !((el.matches || el.matchesSelector).call(el, sel))) ;
return el;
},
hasCloset: function (el, parentElement) {
if (el === parentElement)
{
return true;
}
// If no parentSelector defined will bubble up all the way to *document*
if (parentElement === undefined)
{
parentElement = document;
}
var parents = [];
var p = el.parentNode;
while (p !== parentElement && p.parentNode)
{
var o = p;
parents.push(o);
p = o.parentNode;
}
return p === parentElement;
},
on: function (elSelector, eventName, selector, fn) {
var element = document.querySelector(elSelector);
element.addEventListener(eventName, function (event) {
var possibleTargets = element.querySelectorAll(selector);
var target = event.target;
for (var i = 0, l = possibleTargets.length; i < l; i++)
{
var el = target;
var p = possibleTargets[i];
while (el && el !== element)
{
if (el === p)
{
return fn.call(p, event);
}
el = el.parentNode;
}
}
});
},
addClass: function (el, className) {
if (el.classList)
el.classList.add(className);
else
el.className += ' ' + className;
},
removeClass: function (el, className) {
if (el.classList)
el.classList.remove(className);
else
el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' ');
},
//Extend on/off methods
extendOnOff: function (el) {
var events = {
on: function (event, callback, opts) {
if (!this.namespaces) // save the namespaces on the DOM element itself
this.namespaces = {};
this.namespaces[event] = callback;
var options = opts || false;
this.addEventListener(event.split('.')[0], callback, options);
return this;
},
off: function (event) {
this.removeEventListener(event.split('.')[0], this.namespaces[event]);
delete this.namespaces[event];
return this;
}
};
// Extend the DOM with these above custom methods
el.on = Element.prototype.on = events.on;
el.off = Element.prototype.off = events.off;
return el;
}
};
bodyElement = method.extendOnOff(document.querySelector('body'));
this.PopupDismissEverywhere = function (elements) {
if (elements)
{
if (elements.jquery)
{
elements = elements.length > 1 ? elements.get() : elements[0];
}
if (NodeList.prototype.isPrototypeOf(elements) || Array.isArray(elements))
{
for (var i = 0, l = elements.length; i < l; i++)
{
elements[i].addEventListener("click", method.popupEvent);
}
}
else if (elements.nodeType)
{
elements.addEventListener("click", method.popupEvent);
}
}
else
{
method.on('body', 'click', '[data-toggle="popupDismissEveryWhere"]', method.popupEvent);
}
};
})();
