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