1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225 |
- /*
- * webui popover plugin - v1.2.17
- * A lightWeight popover plugin with jquery ,enchance the popover plugin of bootstrap with some awesome new features. It works well with bootstrap ,but bootstrap is not necessary!
- * https://github.com/sandywalker/webui-popover
- *
- * Made by Sandy Duan
- * Under MIT License
- */
- (function(window, document, undefined) {
- 'use strict';
- (function(factory) {
- if (typeof define === 'function' && define.amd) {
- // Register as an anonymous AMD module.
- define(['jquery'], factory);
- } else if (typeof exports === 'object') {
- // Node/CommonJS
- module.exports = factory(require('jquery'));
- } else {
- // Browser globals
- factory(window.jQuery);
- }
- }(function($) {
- // Create the defaults once
- var pluginName = 'webuiPopover';
- var pluginClass = 'webui-popover';
- var pluginType = 'webui.popover';
- var defaults = {
- placement: 'auto',
- container: null,
- width: 'auto',
- height: 'auto',
- trigger: 'click', //hover,click,sticky,manual
- style: '',
- selector: false, // jQuery selector, if a selector is provided, popover objects will be delegated to the specified.
- delay: {
- show: null,
- hide: 300
- },
- async: {
- type: 'GET',
- before: null, //function(that, xhr, settings){}
- success: null, //function(that, xhr){}
- error: null //function(that, xhr, data){}
- },
- cache: true,
- multi: false,
- arrow: true,
- title: '',
- content: '',
- closeable: false,
- padding: true,
- url: '',
- type: 'html',
- direction: '', // ltr,rtl
- animation: null,
- template: '<div class="webui-popover">' +
- '<div class="webui-arrow"></div>' +
- '<div class="webui-popover-inner">' +
- '<a href="#" class="close"></a>' +
- '<h3 class="webui-popover-title"></h3>' +
- '<div class="webui-popover-content"><i class="icon-refresh"></i> <p> </p></div>' +
- '</div>' +
- '</div>',
- backdrop: false,
- dismissible: true,
- onShow: null,
- onHide: null,
- abortXHR: true,
- autoHide: false,
- offsetTop: 0,
- offsetLeft: 0,
- iframeOptions: {
- frameborder: '0',
- allowtransparency: 'true',
- id: '',
- name: '',
- scrolling: '',
- onload: '',
- height: '',
- width: ''
- },
- hideEmpty: false
- };
- var rtlClass = pluginClass + '-rtl';
- var _srcElements = [];
- var backdrop = $('<div class="webui-popover-backdrop"></div>');
- var _globalIdSeed = 0;
- var _isBodyEventHandled = false;
- var _offsetOut = -2000; // the value offset out of the screen
- var $document = $(document);
- var toNumber = function(numeric, fallback) {
- return isNaN(numeric) ? (fallback || 0) : Number(numeric);
- };
- var getPopFromElement = function($element) {
- return $element.data('plugin_' + pluginName);
- };
- var hideAllPop = function() {
- var pop = null;
- for (var i = 0; i < _srcElements.length; i++) {
- pop = getPopFromElement(_srcElements[i]);
- if (pop) {
- pop.hide(true);
- }
- }
- $document.trigger('hiddenAll.' + pluginType);
- };
- var hideOtherPops = function(currentPop) {
- var pop = null;
- for (var i = 0; i < _srcElements.length; i++) {
- pop = getPopFromElement(_srcElements[i]);
- if (pop && pop.id !== currentPop.id) {
- pop.hide(true);
- }
- }
- $document.trigger('hiddenAll.' + pluginType);
- };
- var isMobile = ('ontouchstart' in document.documentElement) && (/Mobi/.test(navigator.userAgent));
- var pointerEventToXY = function(e) {
- var out = {
- x: 0,
- y: 0
- };
- if (e.type === 'touchstart' || e.type === 'touchmove' || e.type === 'touchend' || e.type === 'touchcancel') {
- var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
- out.x = touch.pageX;
- out.y = touch.pageY;
- } else if (e.type === 'mousedown' || e.type === 'mouseup' || e.type === 'click') {
- out.x = e.pageX;
- out.y = e.pageY;
- }
- return out;
- };
- // The actual plugin constructor
- function WebuiPopover(element, options) {
- this.$element = $(element);
- if (options) {
- if ($.type(options.delay) === 'string' || $.type(options.delay) === 'number') {
- options.delay = {
- show: options.delay,
- hide: options.delay
- }; // bc break fix
- }
- }
- this.options = $.extend({}, defaults, options);
- this._defaults = defaults;
- this._name = pluginName;
- this._targetclick = false;
- this.init();
- _srcElements.push(this.$element);
- return this;
- }
- WebuiPopover.prototype = {
- //init webui popover
- init: function() {
- if (this.$element[0] instanceof document.constructor && !this.options.selector) {
- throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!');
- }
- if (this.getTrigger() !== 'manual') {
- //init the event handlers
- if (isMobile) {
- this.$element.off('touchend', this.options.selector).on('touchend', this.options.selector, $.proxy(this.toggle, this));
- } else if (this.getTrigger() === 'click') {
- this.$element.off('click', this.options.selector).on('click', this.options.selector, $.proxy(this.toggle, this));
- } else if (this.getTrigger() === 'hover') {
- this.$element
- .off('mouseenter mouseleave click', this.options.selector)
- .on('mouseenter', this.options.selector, $.proxy(this.mouseenterHandler, this))
- .on('mouseleave', this.options.selector, $.proxy(this.mouseleaveHandler, this));
- }
- }
- this._poped = false;
- this._inited = true;
- this._opened = false;
- this._idSeed = _globalIdSeed;
- this.id = pluginName + this._idSeed;
- // normalize container
- this.options.container = $(this.options.container || document.body).first();
- if (this.options.backdrop) {
- backdrop.appendTo(this.options.container).hide();
- }
- _globalIdSeed++;
- if (this.getTrigger() === 'sticky') {
- this.show();
- }
- if (this.options.selector) {
- this._options = $.extend({}, this.options, {
- selector: ''
- });
- }
- },
- /* api methods and actions */
- destroy: function() {
- var index = -1;
- for (var i = 0; i < _srcElements.length; i++) {
- if (_srcElements[i] === this.$element) {
- index = i;
- break;
- }
- }
- _srcElements.splice(index, 1);
- this.hide();
- this.$element.data('plugin_' + pluginName, null);
- if (this.getTrigger() === 'click') {
- this.$element.off('click');
- } else if (this.getTrigger() === 'hover') {
- this.$element.off('mouseenter mouseleave');
- }
- if (this.$target) {
- this.$target.remove();
- }
- },
- getDelegateOptions: function() {
- var options = {};
- this._options && $.each(this._options, function(key, value) {
- if (defaults[key] !== value) {
- options[key] = value;
- }
- });
- return options;
- },
- /*
- param: force boolean value, if value is true then force hide the popover
- param: event dom event,
- */
- hide: function(force, event) {
- if (!force && this.getTrigger() === 'sticky') {
- return;
- }
- if (!this._opened) {
- return;
- }
- if (event) {
- event.preventDefault();
- event.stopPropagation();
- }
- if (this.xhr && this.options.abortXHR === true) {
- this.xhr.abort();
- this.xhr = null;
- }
- var e = $.Event('hide.' + pluginType);
- this.$element.trigger(e, [this.$target]);
- if (this.$target) {
- this.$target.removeClass('in').addClass(this.getHideAnimation());
- var that = this;
- setTimeout(function() {
- that.$target.hide();
- if (!that.getCache()) {
- that.$target.remove();
- //that.getTriggerElement.removeAttr('data-target');
- }
- }, that.getHideDelay());
- }
- if (this.options.backdrop) {
- backdrop.hide();
- }
- this._opened = false;
- this.$element.trigger('hidden.' + pluginType, [this.$target]);
- if (this.options.onHide) {
- this.options.onHide(this.$target);
- }
- },
- resetAutoHide: function() {
- var that = this;
- var autoHide = that.getAutoHide();
- if (autoHide) {
- if (that.autoHideHandler) {
- clearTimeout(that.autoHideHandler);
- }
- that.autoHideHandler = setTimeout(function() {
- that.hide();
- }, autoHide);
- }
- },
- delegate: function(eventTarget) {
- var self = $(eventTarget).data('plugin_' + pluginName);
- if (!self) {
- self = new WebuiPopover(eventTarget, this.getDelegateOptions());
- $(eventTarget).data('plugin_' + pluginName, self);
- }
- return self;
- },
- toggle: function(e) {
- var self = this;
- if (e) {
- e.preventDefault();
- e.stopPropagation();
- if (this.options.selector) {
- self = this.delegate(e.currentTarget);
- }
- }
- self[self.getTarget().hasClass('in') ? 'hide' : 'show']();
- },
- hideAll: function() {
- hideAllPop();
- },
- hideOthers: function() {
- hideOtherPops(this);
- },
- /*core method ,show popover */
- show: function() {
- if (this._opened) {
- return;
- }
- //removeAllTargets();
- var
- $target = this.getTarget().removeClass().addClass(pluginClass).addClass(this._customTargetClass);
- if (!this.options.multi) {
- this.hideOthers();
- }
- // use cache by default, if not cache setted , reInit the contents
- if (!this.getCache() || !this._poped || this.content === '') {
- this.content = '';
- this.setTitle(this.getTitle());
- if (!this.options.closeable) {
- $target.find('.close').off('click').remove();
- }
- if (!this.isAsync()) {
- this.setContent(this.getContent());
- } else {
- this.setContentASync(this.options.content);
- }
- if (this.canEmptyHide() && this.content === '') {
- return;
- }
- $target.show();
- }
- this.displayContent();
- if (this.options.onShow) {
- this.options.onShow($target);
- }
- this.bindBodyEvents();
- if (this.options.backdrop) {
- backdrop.show();
- }
- this._opened = true;
- this.resetAutoHide();
- },
- displayContent: function() {
- var
- //element postion
- elementPos = this.getElementPosition(),
- //target postion
- $target = this.getTarget().removeClass().addClass(pluginClass).addClass(this._customTargetClass),
- //target content
- $targetContent = this.getContentElement(),
- //target Width
- targetWidth = $target[0].offsetWidth,
- //target Height
- targetHeight = $target[0].offsetHeight,
- //placement
- placement = 'bottom',
- e = $.Event('show.' + pluginType);
- if (this.canEmptyHide()) {
- var content = $targetContent.children().html();
- if (content !== null && content.trim().length === 0) {
- return;
- }
- }
- //if (this.hasContent()){
- this.$element.trigger(e, [$target]);
- //}
- // support width as data attribute
- var optWidth = this.$element.data('width') || this.options.width;
- if (optWidth === '') {
- optWidth = this._defaults.width;
- }
- if (optWidth !== 'auto') {
- $target.width(optWidth);
- }
- // support height as data attribute
- var optHeight = this.$element.data('height') || this.options.height;
- if (optHeight === '') {
- optHeight = this._defaults.height;
- }
- if (optHeight !== 'auto') {
- $targetContent.height(optHeight);
- }
- if (this.options.style) {
- this.$target.addClass(pluginClass + '-' + this.options.style);
- }
- //check rtl
- if (this.options.direction === 'rtl' && !$targetContent.hasClass(rtlClass)) {
- $targetContent.addClass(rtlClass);
- }
- //init the popover and insert into the document body
- if (!this.options.arrow) {
- $target.find('.webui-arrow').remove();
- }
- $target.detach().css({
- top: _offsetOut,
- left: _offsetOut,
- display: 'block'
- });
- if (this.getAnimation()) {
- $target.addClass(this.getAnimation());
- }
- $target.appendTo(this.options.container);
- placement = this.getPlacement(elementPos);
- //This line is just for compatible with knockout custom binding
- this.$element.trigger('added.' + pluginType);
- this.initTargetEvents();
- if (!this.options.padding) {
- if (this.options.height !== 'auto') {
- $targetContent.css('height', $targetContent.outerHeight());
- }
- this.$target.addClass('webui-no-padding');
- }
- // add maxHeight and maxWidth support by limodou@gmail.com 2016/10/1
- if (this.options.maxHeight) {
- $targetContent.css('maxHeight', this.options.maxHeight);
- }
- if (this.options.maxWidth) {
- $targetContent.css('maxWidth', this.options.maxWidth);
- }
- // end
- targetWidth = $target[0].offsetWidth;
- targetHeight = $target[0].offsetHeight;
- var postionInfo = this.getTargetPositin(elementPos, placement, targetWidth, targetHeight);
- this.$target.css(postionInfo.position).addClass(placement).addClass('in');
- if (this.options.type === 'iframe') {
- var $iframe = $target.find('iframe');
- var iframeWidth = $target.width();
- var iframeHeight = $iframe.parent().height();
- if (this.options.iframeOptions.width !== '' && this.options.iframeOptions.width !== 'auto') {
- iframeWidth = this.options.iframeOptions.width;
- }
- if (this.options.iframeOptions.height !== '' && this.options.iframeOptions.height !== 'auto') {
- iframeHeight = this.options.iframeOptions.height;
- }
- $iframe.width(iframeWidth).height(iframeHeight);
- }
- if (!this.options.arrow) {
- this.$target.css({
- 'margin': 0
- });
- }
- if (this.options.arrow) {
- var $arrow = this.$target.find('.webui-arrow');
- $arrow.removeAttr('style');
- //prevent arrow change by content size
- if (placement === 'left' || placement === 'right') {
- $arrow.css({
- top: this.$target.height() / 2
- });
- } else if (placement === 'top' || placement === 'bottom') {
- $arrow.css({
- left: this.$target.width() / 2
- });
- }
- if (postionInfo.arrowOffset) {
- //hide the arrow if offset is negative
- if (postionInfo.arrowOffset.left === -1 || postionInfo.arrowOffset.top === -1) {
- $arrow.hide();
- } else {
- $arrow.css(postionInfo.arrowOffset);
- }
- }
- }
- this._poped = true;
- this.$element.trigger('shown.' + pluginType, [this.$target]);
- },
- isTargetLoaded: function() {
- return this.getTarget().find('i.glyphicon-refresh').length === 0;
- },
- /*getter setters */
- getTriggerElement: function() {
- return this.$element;
- },
- getTarget: function() {
- if (!this.$target) {
- var id = pluginName + this._idSeed;
- this.$target = $(this.options.template)
- .attr('id', id);
- this._customTargetClass = this.$target.attr('class') !== pluginClass ? this.$target.attr('class') : null;
- this.getTriggerElement().attr('data-target', id);
- }
- if (!this.$target.data('trigger-element')) {
- this.$target.data('trigger-element', this.getTriggerElement());
- }
- return this.$target;
- },
- removeTarget: function() {
- this.$target.remove();
- this.$target = null;
- this.$contentElement = null;
- },
- getTitleElement: function() {
- return this.getTarget().find('.' + pluginClass + '-title');
- },
- getContentElement: function() {
- if (!this.$contentElement) {
- this.$contentElement = this.getTarget().find('.' + pluginClass + '-content');
- }
- return this.$contentElement;
- },
- getTitle: function() {
- return this.$element.attr('data-title') || this.options.title || this.$element.attr('title');
- },
- getUrl: function() {
- return this.$element.attr('data-url') || this.options.url;
- },
- getAutoHide: function() {
- return this.$element.attr('data-auto-hide') || this.options.autoHide;
- },
- getOffsetTop: function() {
- return toNumber(this.$element.attr('data-offset-top')) || this.options.offsetTop;
- },
- getOffsetLeft: function() {
- return toNumber(this.$element.attr('data-offset-left')) || this.options.offsetLeft;
- },
- getCache: function() {
- var dataAttr = this.$element.attr('data-cache');
- if (typeof(dataAttr) !== 'undefined') {
- switch (dataAttr.toLowerCase()) {
- case 'true':
- case 'yes':
- case '1':
- return true;
- case 'false':
- case 'no':
- case '0':
- return false;
- }
- }
- return this.options.cache;
- },
- getTrigger: function() {
- return this.$element.attr('data-trigger') || this.options.trigger;
- },
- getDelayShow: function() {
- var dataAttr = this.$element.attr('data-delay-show');
- if (typeof(dataAttr) !== 'undefined') {
- return dataAttr;
- }
- return this.options.delay.show === 0 ? 0 : this.options.delay.show || 100;
- },
- getHideDelay: function() {
- var dataAttr = this.$element.attr('data-delay-hide');
- if (typeof(dataAttr) !== 'undefined') {
- return dataAttr;
- }
- return this.options.delay.hide === 0 ? 0 : this.options.delay.hide || 100;
- },
- getAnimation: function() {
- var dataAttr = this.$element.attr('data-animation');
- return dataAttr || this.options.animation;
- },
- getHideAnimation: function() {
- var ani = this.getAnimation();
- return ani ? ani + '-out' : 'out';
- },
- setTitle: function(title) {
- var $titleEl = this.getTitleElement();
- if (title) {
- //check rtl
- if (this.options.direction === 'rtl' && !$titleEl.hasClass(rtlClass)) {
- $titleEl.addClass(rtlClass);
- }
- $titleEl.html(title);
- } else {
- $titleEl.remove();
- }
- },
- hasContent: function() {
- return this.getContent();
- },
- canEmptyHide: function() {
- return this.options.hideEmpty && this.options.type === 'html';
- },
- getIframe: function() {
- var $iframe = $('<iframe></iframe>').attr('src', this.getUrl());
- var self = this;
- $.each(this._defaults.iframeOptions, function(opt) {
- if (typeof self.options.iframeOptions[opt] !== 'undefined') {
- $iframe.attr(opt, self.options.iframeOptions[opt]);
- }
- });
- return $iframe;
- },
- getContent: function() {
- if (this.getUrl()) {
- switch (this.options.type) {
- case 'iframe':
- this.content = this.getIframe();
- break;
- case 'html':
- try {
- this.content = $(this.getUrl());
- if (!this.content.is(':visible')) {
- this.content.show();
- }
- } catch (error) {
- throw new Error('Unable to get popover content. Invalid selector specified.');
- }
- break;
- }
- } else if (!this.content) {
- var content = '';
- if ($.isFunction(this.options.content)) {
- content = this.options.content.apply(this.$element[0], [this]);
- } else {
- content = this.options.content;
- }
- this.content = this.$element.attr('data-content') || content;
- if (!this.content) {
- var $next = this.$element.next();
- if ($next && $next.hasClass(pluginClass + '-content')) {
- this.content = $next;
- }
- }
- }
- return this.content;
- },
- setContent: function(content) {
- var $target = this.getTarget();
- var $ct = this.getContentElement();
- if (typeof content === 'string') {
- $ct.html(content);
- } else if (content instanceof $) {
- $ct.html('');
- //Don't want to clone too many times.
- if (!this.options.cache) {
- content.clone(true, true).removeClass(pluginClass + '-content').appendTo($ct);
- } else {
- content.removeClass(pluginClass + '-content').appendTo($ct);
- }
- }
- this.$target = $target;
- },
- isAsync: function() {
- return this.options.type === 'async';
- },
- setContentASync: function(content) {
- var that = this;
- if (this.xhr) {
- return;
- }
- this.xhr = $.ajax({
- url: this.getUrl(),
- type: this.options.async.type,
- cache: this.getCache(),
- beforeSend: function(xhr, settings) {
- if (that.options.async.before) {
- that.options.async.before(that, xhr, settings);
- }
- },
- success: function(data) {
- that.bindBodyEvents();
- if (content && $.isFunction(content)) {
- that.content = content.apply(that.$element[0], [data]);
- } else {
- that.content = data;
- }
- that.setContent(that.content);
- var $targetContent = that.getContentElement();
- $targetContent.removeAttr('style');
- that.displayContent();
- if (that.options.async.success) {
- that.options.async.success(that, data);
- }
- },
- complete: function() {
- that.xhr = null;
- },
- error: function(xhr, data) {
- if (that.options.async.error) {
- that.options.async.error(that, xhr, data);
- }
- }
- });
- },
- bindBodyEvents: function() {
- if (_isBodyEventHandled) {
- return;
- }
- if (this.options.dismissible && this.getTrigger() === 'click') {
- if (isMobile) {
- $document.off('touchstart.webui-popover').on('touchstart.webui-popover', $.proxy(this.bodyTouchStartHandler, this));
- } else {
- $document.off('keyup.webui-popover').on('keyup.webui-popover', $.proxy(this.escapeHandler, this));
- $document.off('click.webui-popover').on('click.webui-popover', $.proxy(this.bodyClickHandler, this));
- }
- } else if (this.getTrigger() === 'hover') {
- $document.off('touchend.webui-popover')
- .on('touchend.webui-popover', $.proxy(this.bodyClickHandler, this));
- }
- },
- /* event handlers */
- mouseenterHandler: function(e) {
- var self = this;
- if (e && this.options.selector) {
- self = this.delegate(e.currentTarget);
- }
- if (self._timeout) {
- clearTimeout(self._timeout);
- }
- self._enterTimeout = setTimeout(function() {
- if (!self.getTarget().is(':visible')) {
- self.show();
- }
- }, this.getDelayShow());
- },
- mouseleaveHandler: function() {
- var self = this;
- clearTimeout(self._enterTimeout);
- //key point, set the _timeout then use clearTimeout when mouse leave
- self._timeout = setTimeout(function() {
- self.hide();
- }, this.getHideDelay());
- },
- escapeHandler: function(e) {
- if (e.keyCode === 27) {
- this.hideAll();
- }
- },
- bodyTouchStartHandler: function(e) {
- var self = this;
- var $eventEl = $(e.currentTarget);
- $eventEl.on('touchend', function(e) {
- self.bodyClickHandler(e);
- $eventEl.off('touchend');
- });
- $eventEl.on('touchmove', function() {
- $eventEl.off('touchend');
- });
- },
- bodyClickHandler: function(e) {
- _isBodyEventHandled = true;
- var canHide = true;
- for (var i = 0; i < _srcElements.length; i++) {
- var pop = getPopFromElement(_srcElements[i]);
- if (pop && pop._opened) {
- var offset = pop.getTarget().offset();
- var popX1 = offset.left;
- var popY1 = offset.top;
- var popX2 = offset.left + pop.getTarget().width();
- var popY2 = offset.top + pop.getTarget().height();
- var pt = pointerEventToXY(e);
- var inPop = pt.x >= popX1 && pt.x <= popX2 && pt.y >= popY1 && pt.y <= popY2;
- if (inPop) {
- canHide = false;
- break;
- }
- }
- }
- if (canHide) {
- hideAllPop();
- }
- },
- /*
- targetClickHandler: function() {
- this._targetclick = true;
- },
- */
- //reset and init the target events;
- initTargetEvents: function() {
- if (this.getTrigger() === 'hover') {
- this.$target
- .off('mouseenter mouseleave')
- .on('mouseenter', $.proxy(this.mouseenterHandler, this))
- .on('mouseleave', $.proxy(this.mouseleaveHandler, this));
- }
- this.$target.find('.close').off('click').on('click', $.proxy(this.hide, this, true));
- //this.$target.off('click.webui-popover').on('click.webui-popover', $.proxy(this.targetClickHandler, this));
- },
- /* utils methods */
- //caculate placement of the popover
- getPlacement: function(pos) {
- var
- placement,
- container = this.options.container,
- clientWidth = container.innerWidth(),
- clientHeight = container.innerHeight(),
- scrollTop = container.scrollTop(),
- scrollLeft = container.scrollLeft(),
- pageX = Math.max(0, pos.left - scrollLeft),
- pageY = Math.max(0, pos.top - scrollTop);
- //arrowSize = 20;
- //if placement equals auto,caculate the placement by element information;
- if (typeof(this.options.placement) === 'function') {
- placement = this.options.placement.call(this, this.getTarget()[0], this.$element[0]);
- } else {
- placement = this.$element.data('placement') || this.options.placement;
- }
- var isH = placement === 'horizontal';
- var isV = placement === 'vertical';
- var detect = placement === 'auto' || isH || isV;
- if (detect) {
- if (pageX < clientWidth / 3) {
- if (pageY < clientHeight / 3) {
- placement = isH ? 'right-bottom' : 'bottom-right';
- } else if (pageY < clientHeight * 2 / 3) {
- if (isV) {
- placement = pageY <= clientHeight / 2 ? 'bottom-right' : 'top-right';
- } else {
- placement = 'right';
- }
- } else {
- placement = isH ? 'right-top' : 'top-right';
- }
- //placement= pageY>targetHeight+arrowSize?'top-right':'bottom-right';
- } else if (pageX < clientWidth * 2 / 3) {
- if (pageY < clientHeight / 3) {
- if (isH) {
- placement = pageX <= clientWidth / 2 ? 'right-bottom' : 'left-bottom';
- } else {
- placement = 'bottom';
- }
- } else if (pageY < clientHeight * 2 / 3) {
- if (isH) {
- placement = pageX <= clientWidth / 2 ? 'right' : 'left';
- } else {
- placement = pageY <= clientHeight / 2 ? 'bottom' : 'top';
- }
- } else {
- if (isH) {
- placement = pageX <= clientWidth / 2 ? 'right-top' : 'left-top';
- } else {
- placement = 'top';
- }
- }
- } else {
- //placement = pageY>targetHeight+arrowSize?'top-left':'bottom-left';
- if (pageY < clientHeight / 3) {
- placement = isH ? 'left-bottom' : 'bottom-left';
- } else if (pageY < clientHeight * 2 / 3) {
- if (isV) {
- placement = pageY <= clientHeight / 2 ? 'bottom-left' : 'top-left';
- } else {
- placement = 'left';
- }
- } else {
- placement = isH ? 'left-top' : 'top-left';
- }
- }
- } else if (placement === 'auto-top') {
- if (pageX < clientWidth / 3) {
- placement = 'top-right';
- } else if (pageX < clientWidth * 2 / 3) {
- placement = 'top';
- } else {
- placement = 'top-left';
- }
- } else if (placement === 'auto-bottom') {
- if (pageX < clientWidth / 3) {
- placement = 'bottom-right';
- } else if (pageX < clientWidth * 2 / 3) {
- placement = 'bottom';
- } else {
- placement = 'bottom-left';
- }
- } else if (placement === 'auto-left') {
- if (pageY < clientHeight / 3) {
- placement = 'left-top';
- } else if (pageY < clientHeight * 2 / 3) {
- placement = 'left';
- } else {
- placement = 'left-bottom';
- }
- } else if (placement === 'auto-right') {
- if (pageY < clientHeight / 3) {
- placement = 'right-bottom';
- } else if (pageY < clientHeight * 2 / 3) {
- placement = 'right';
- } else {
- placement = 'right-top';
- }
- }
- return placement;
- },
- getElementPosition: function() {
- // If the container is the body or normal conatiner, just use $element.offset()
- var elRect = this.$element[0].getBoundingClientRect();
- var container = this.options.container;
- var cssPos = container.css('position');
- if (container.is(document.body) || cssPos === 'static') {
- return $.extend({}, this.$element.offset(), {
- width: this.$element[0].offsetWidth || elRect.width,
- height: this.$element[0].offsetHeight || elRect.height
- });
- // Else fixed container need recalculate the position
- } else if (cssPos === 'fixed') {
- var containerRect = container[0].getBoundingClientRect();
- return {
- top: elRect.top - containerRect.top + container.scrollTop(),
- left: elRect.left - containerRect.left + container.scrollLeft(),
- width: elRect.width,
- height: elRect.height
- };
- } else if (cssPos === 'relative') {
- return {
- top: this.$element.offset().top - container.offset().top,
- left: this.$element.offset().left - container.offset().left,
- width: this.$element[0].offsetWidth || elRect.width,
- height: this.$element[0].offsetHeight || elRect.height
- };
- }
- },
- getTargetPositin: function(elementPos, placement, targetWidth, targetHeight) {
- var pos = elementPos,
- container = this.options.container,
- //clientWidth = container.innerWidth(),
- //clientHeight = container.innerHeight(),
- elementW = this.$element.outerWidth(),
- elementH = this.$element.outerHeight(),
- scrollTop = document.documentElement.scrollTop + container.scrollTop(),
- scrollLeft = document.documentElement.scrollLeft + container.scrollLeft(),
- position = {},
- arrowOffset = null,
- arrowSize = this.options.arrow ? 20 : 0,
- padding = 10,
- fixedW = elementW < arrowSize + padding ? arrowSize : 0,
- fixedH = elementH < arrowSize + padding ? arrowSize : 0,
- refix = 0,
- pageH = document.documentElement.clientHeight + scrollTop,
- pageW = document.documentElement.clientWidth + scrollLeft;
- var validLeft = pos.left + pos.width / 2 - fixedW > 0;
- var validRight = pos.left + pos.width / 2 + fixedW < pageW;
- var validTop = pos.top + pos.height / 2 - fixedH > 0;
- var validBottom = pos.top + pos.height / 2 + fixedH < pageH;
- switch (placement) {
- case 'bottom':
- position = {
- top: pos.top + pos.height,
- left: pos.left + pos.width / 2 - targetWidth / 2
- };
- break;
- case 'top':
- position = {
- top: pos.top - targetHeight,
- left: pos.left + pos.width / 2 - targetWidth / 2
- };
- break;
- case 'left':
- position = {
- top: pos.top + pos.height / 2 - targetHeight / 2,
- left: pos.left - targetWidth
- };
- break;
- case 'right':
- position = {
- top: pos.top + pos.height / 2 - targetHeight / 2,
- left: pos.left + pos.width
- };
- break;
- case 'top-right':
- position = {
- top: pos.top - targetHeight,
- left: validLeft ? pos.left - fixedW : padding
- };
- arrowOffset = {
- left: validLeft ? Math.min(elementW, targetWidth) / 2 + fixedW : _offsetOut
- };
- break;
- case 'top-left':
- refix = validRight ? fixedW : -padding;
- position = {
- top: pos.top - targetHeight,
- left: pos.left - targetWidth + pos.width + refix
- };
- arrowOffset = {
- left: validRight ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW : _offsetOut
- };
- break;
- case 'bottom-right':
- position = {
- top: pos.top + pos.height,
- left: validLeft ? pos.left - fixedW : padding
- };
- arrowOffset = {
- left: validLeft ? Math.min(elementW, targetWidth) / 2 + fixedW : _offsetOut
- };
- break;
- case 'bottom-left':
- refix = validRight ? fixedW : -padding;
- position = {
- top: pos.top + pos.height,
- left: pos.left - targetWidth + pos.width + refix
- };
- arrowOffset = {
- left: validRight ? targetWidth - Math.min(elementW, targetWidth) / 2 - fixedW : _offsetOut
- };
- break;
- case 'right-top':
- refix = validBottom ? fixedH : -padding;
- position = {
- top: pos.top - targetHeight + pos.height + refix,
- left: pos.left + pos.width
- };
- arrowOffset = {
- top: validBottom ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH : _offsetOut
- };
- break;
- case 'right-bottom':
- position = {
- top: validTop ? pos.top - fixedH : padding,
- left: pos.left + pos.width
- };
- arrowOffset = {
- top: validTop ? Math.min(elementH, targetHeight) / 2 + fixedH : _offsetOut
- };
- break;
- case 'left-top':
- refix = validBottom ? fixedH : -padding;
- position = {
- top: pos.top - targetHeight + pos.height + refix,
- left: pos.left - targetWidth
- };
- arrowOffset = {
- top: validBottom ? targetHeight - Math.min(elementH, targetHeight) / 2 - fixedH : _offsetOut
- };
- break;
- case 'left-bottom':
- position = {
- top: validTop ? pos.top - fixedH : padding,
- left: pos.left - targetWidth
- };
- arrowOffset = {
- top: validTop ? Math.min(elementH, targetHeight) / 2 + fixedH : _offsetOut
- };
- break;
- }
- position.top += this.getOffsetTop();
- position.left += this.getOffsetLeft();
- return {
- position: position,
- arrowOffset: arrowOffset
- };
- }
- };
- $.fn[pluginName] = function(options, noInit) {
- var results = [];
- var $result = this.each(function() {
- var webuiPopover = $.data(this, 'plugin_' + pluginName);
- if (!webuiPopover) {
- if (!options) {
- webuiPopover = new WebuiPopover(this, null);
- } else if (typeof options === 'string') {
- if (options !== 'destroy') {
- if (!noInit) {
- webuiPopover = new WebuiPopover(this, null);
- results.push(webuiPopover[options]());
- }
- }
- } else if (typeof options === 'object') {
- webuiPopover = new WebuiPopover(this, options);
- }
- $.data(this, 'plugin_' + pluginName, webuiPopover);
- } else {
- if (options === 'destroy') {
- webuiPopover.destroy();
- } else if (typeof options === 'string') {
- results.push(webuiPopover[options]());
- }
- }
- });
- return (results.length) ? results : $result;
- };
- //Global object exposes to window.
- var webuiPopovers = (function() {
- var _hideAll = function() {
- hideAllPop();
- };
- var _create = function(selector, options) {
- options = options || {};
- $(selector).webuiPopover(options);
- };
- var _isCreated = function(selector) {
- var created = true;
- $(selector).each(function(i, item) {
- created = created && $(item).data('plugin_' + pluginName) !== undefined;
- });
- return created;
- };
- var _show = function(selector, options) {
- if (options) {
- $(selector).webuiPopover(options).webuiPopover('show');
- } else {
- $(selector).webuiPopover('show');
- }
- };
- var _hide = function(selector) {
- $(selector).webuiPopover('hide');
- };
- var _setDefaultOptions = function(options) {
- defaults = $.extend({}, defaults, options);
- };
- var _updateContent = function(selector, content) {
- var pop = $(selector).data('plugin_' + pluginName);
- if (pop) {
- var cache = pop.getCache();
- pop.options.cache = false;
- pop.options.content = content;
- if (pop._opened) {
- pop._opened = false;
- pop.show();
- } else {
- if (pop.isAsync()) {
- pop.setContentASync(content);
- } else {
- pop.setContent(content);
- }
- }
- pop.options.cache = cache;
- }
- };
- var _updateContentAsync = function(selector, url) {
- var pop = $(selector).data('plugin_' + pluginName);
- if (pop) {
- var cache = pop.getCache();
- var type = pop.options.type;
- pop.options.cache = false;
- pop.options.url = url;
- if (pop._opened) {
- pop._opened = false;
- pop.show();
- } else {
- pop.options.type = 'async';
- pop.setContentASync(pop.content);
- }
- pop.options.cache = cache;
- pop.options.type = type;
- }
- };
- return {
- show: _show,
- hide: _hide,
- create: _create,
- isCreated: _isCreated,
- hideAll: _hideAll,
- updateContent: _updateContent,
- updateContentAsync: _updateContentAsync,
- setDefaultOptions: _setDefaultOptions
- };
- })();
- window.WebuiPopovers = webuiPopovers;
- }));
- })(window, document);
|