You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
8.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* Popovers
* @param {type} $
* @param {type} window
* @param {type} document
* @param {type} name
* @param {type} undefined
* @returns {undefined}
*/
(function($, window, document, name) {
var CLASS_POPOVER = $.className('popover');
var CLASS_POPOVER_ARROW = $.className('popover-arrow');
var CLASS_ACTION_POPOVER = $.className('popover-action');
var CLASS_BACKDROP = $.className('backdrop');
var CLASS_BAR_POPOVER = $.className('bar-popover');
var CLASS_BAR_BACKDROP = $.className('bar-backdrop');
var CLASS_ACTION_BACKDROP = $.className('backdrop-action');
var CLASS_ACTIVE = $.className('active');
var CLASS_BOTTOM = $.className('bottom');
var handle = function(event, target) {
if (target.tagName === 'A' && target.hash) {
$.targets._popover = document.getElementById(target.hash.replace('#', ''));
if ($.targets._popover && $.targets._popover.classList.contains(CLASS_POPOVER)) {
return target;
} else {
$.targets._popover = null;
}
}
return false;
};
$.registerTarget({
name: name,
index: 60,
handle: handle,
target: false,
isReset: false,
isContinue: true
});
var onPopoverShown = function(e) {
this.removeEventListener('webkitTransitionEnd', onPopoverShown);
this.addEventListener($.EVENT_MOVE, $.preventDefault);
$.trigger(this, 'shown', this);
}
var onPopoverHidden = function(e) {
setStyle(this, 'none');
this.removeEventListener('webkitTransitionEnd', onPopoverHidden);
this.removeEventListener($.EVENT_MOVE, $.preventDefault);
$.trigger(this, 'hidden', this);
};
var backdrop = (function() {
var element = document.createElement('div');
element.classList.add(CLASS_BACKDROP);
element.addEventListener($.EVENT_MOVE, $.preventDefault);
element.addEventListener('tap', function(e) {
var popover = $.targets._popover;
if (popover) {
popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
popover.classList.remove(CLASS_ACTIVE);
removeBackdrop(popover);
}
});
return element;
}());
var removeBackdropTimer;
var removeBackdrop = function(popover) {
backdrop.setAttribute('style', 'opacity:0');
$.targets.popover = $.targets._popover = null; //reset
removeBackdropTimer = $.later(function() {
if (!popover.classList.contains(CLASS_ACTIVE) && backdrop.parentNode && backdrop.parentNode === document.body) {
document.body.removeChild(backdrop);
}
}, 350);
};
window.addEventListener('tap', function(e) {
if (!$.targets.popover) {
return;
}
var toggle = false;
var target = e.target;
for (; target && target !== document; target = target.parentNode) {
if (target === $.targets.popover) {
toggle = true;
}
}
if (toggle) {
e.detail.gesture.preventDefault(); //fixed hashchange
togglePopover($.targets._popover, $.targets.popover);
}
});
var togglePopover = function(popover, anchor, state) {
if ((state === 'show' && popover.classList.contains(CLASS_ACTIVE)) || (state === 'hide' && !popover.classList.contains(CLASS_ACTIVE))) {
return;
}
removeBackdropTimer && removeBackdropTimer.cancel(); //取消remove的timer
//remove一遍以免来回快速切换导致webkitTransitionEnd不触发无法remove
popover.removeEventListener('webkitTransitionEnd', onPopoverShown);
popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
backdrop.classList.remove(CLASS_BAR_BACKDROP);
backdrop.classList.remove(CLASS_ACTION_BACKDROP);
var _popover = document.querySelector($.classSelector('.popover.active'));
if (_popover) {
// _popover.setAttribute('style', '');
_popover.addEventListener('webkitTransitionEnd', onPopoverHidden);
_popover.classList.remove(CLASS_ACTIVE);
// _popover.removeEventListener('webkitTransitionEnd', onPopoverHidden);
//同一个弹出则直接返回解决同一个popover的toggle
if (popover === _popover) {
removeBackdrop(_popover);
return;
}
}
var isActionSheet = false;
if (popover.classList.contains(CLASS_BAR_POPOVER) || popover.classList.contains(CLASS_ACTION_POPOVER)) { //navBar
if (popover.classList.contains(CLASS_ACTION_POPOVER)) { //action sheet popover
isActionSheet = true;
backdrop.classList.add(CLASS_ACTION_BACKDROP);
} else { //bar popover
backdrop.classList.add(CLASS_BAR_BACKDROP);
// if (anchor) {
// if (anchor.parentNode) {
// var offsetWidth = anchor.offsetWidth;
// var offsetLeft = anchor.offsetLeft;
// var innerWidth = window.innerWidth;
// popover.style.left = (Math.min(Math.max(offsetLeft, defaultPadding), innerWidth - offsetWidth - defaultPadding)) + "px";
// } else {
// //TODO anchor is position:{left,top,bottom,right}
// }
// }
}
}
setStyle(popover, 'block'); //actionsheet transform
popover.offsetHeight;
popover.classList.add(CLASS_ACTIVE);
backdrop.setAttribute('style', '');
document.body.appendChild(backdrop);
calPosition(popover, anchor, isActionSheet); //position
backdrop.classList.add(CLASS_ACTIVE);
popover.addEventListener('webkitTransitionEnd', onPopoverShown);
};
var setStyle = function(popover, display, top, left) {
var style = popover.style;
if (typeof display !== 'undefined')
style.display = display;
if (typeof top !== 'undefined')
style.top = top + 'px';
if (typeof left !== 'undefined')
style.left = left + 'px';
};
var calPosition = function(popover, anchor, isActionSheet) {
if (!popover || !anchor) {
return;
}
if (isActionSheet) { //actionsheet
setStyle(popover, 'block')
return;
}
var wWidth = window.innerWidth;
var wHeight = window.innerHeight;
var pWidth = popover.offsetWidth;
var pHeight = popover.offsetHeight;
var aWidth = anchor.offsetWidth;
var aHeight = anchor.offsetHeight;
var offset = $.offset(anchor);
var arrow = popover.querySelector('.' + CLASS_POPOVER_ARROW);
if (!arrow) {
arrow = document.createElement('div');
arrow.className = CLASS_POPOVER_ARROW;
popover.appendChild(arrow);
}
var arrowSize = arrow && arrow.offsetWidth / 2 || 0;
var pTop = 0;
var pLeft = 0;
var diff = 0;
var arrowLeft = 0;
var defaultPadding = popover.classList.contains(CLASS_ACTION_POPOVER) ? 0 : 5;
var position = 'top';
if ((pHeight + arrowSize) < (offset.top - window.pageYOffset)) { //top
pTop = offset.top - pHeight - arrowSize;
} else if ((pHeight + arrowSize) < (wHeight - (offset.top - window.pageYOffset) - aHeight)) { //bottom
position = 'bottom';
pTop = offset.top + aHeight + arrowSize;
} else { //middle
position = 'middle';
pTop = Math.max((wHeight - pHeight) / 2 + window.pageYOffset, 0);
pLeft = Math.max((wWidth - pWidth) / 2 + window.pageXOffset, 0);
}
if (position === 'top' || position === 'bottom') {
pLeft = aWidth / 2 + offset.left - pWidth / 2;
diff = pLeft;
if (pLeft < defaultPadding) pLeft = defaultPadding;
if (pLeft + pWidth > wWidth) pLeft = wWidth - pWidth - defaultPadding;
if (arrow) {
if (position === 'top') {
arrow.classList.add(CLASS_BOTTOM);
} else {
arrow.classList.remove(CLASS_BOTTOM);
}
diff = diff - pLeft;
arrowLeft = (pWidth / 2 - arrowSize / 2 + diff);
arrowLeft = Math.max(Math.min(arrowLeft, pWidth - arrowSize * 2 - 6), 6);
arrow.setAttribute('style', 'left:' + arrowLeft + 'px');
}
} else if (position === 'middle') {
arrow.setAttribute('style', 'display:none');
}
setStyle(popover, 'block', pTop, pLeft);
};
$.createMask = function(callback) {
var element = document.createElement('div');
element.classList.add(CLASS_BACKDROP);
element.addEventListener($.EVENT_MOVE, $.preventDefault);
element.addEventListener('tap', function() {
mask.close();
});
var mask = [element];
mask._show = false;
mask.show = function() {
mask._show = true;
element.setAttribute('style', 'opacity:1');
document.body.appendChild(element);
return mask;
};
mask._remove = function() {
if (mask._show) {
mask._show = false;
element.setAttribute('style', 'opacity:0');
$.later(function() {
var body = document.body;
element.parentNode === body && body.removeChild(element);
}, 350);
}
return mask;
};
mask.close = function() {
if (callback) {
if (callback() !== false) {
mask._remove();
}
} else {
mask._remove();
}
};
return mask;
};
$.fn.popover = function() {
var args = arguments;
this.each(function() {
$.targets._popover = this;
if (args[0] === 'show' || args[0] === 'hide' || args[0] === 'toggle') {
togglePopover(this, args[1], args[0]);
}
});
};
})(mui, window, document, 'popover');