|
|
/**
|
|
|
* 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'); |