1/* 2 * jquery-gpopover 3 * http://github.com/markembling/jquery-gpopover 4 * 5 * A simple jQuery plugin for creating popover elements similar to Google's 6 * new 'apps' launcher/switcher. 7 * 8 * Copyright (c) 2013 Mark Embling (markembling.info) 9 * Licensed under the BSD (3 clause) license. 10 */ 11 12;(function($){ 13 14 var GPopover = function(element, options) { 15 this.options = null; 16 this.$trigger = null; 17 this.$popover = null; 18 19 this.init(element, options); 20 } 21 22 GPopover.prototype.init = function(element, options) { 23 var that = this; 24 25 this.options = $.extend({}, $.fn.gpopover.defaults, options); 26 27 this.$trigger = $(element); 28 this.$popover = $('#' + this.$trigger.data('popover')); 29 30 this._addArrowElements(); 31 32 if (this.options.preventHide) { 33 this._preventHideClickPropagation(); 34 } 35 36 this.$trigger.click(function(e){ 37 if (! that.$popover.is(":visible")) { 38 // Trigger a click on the parent element (that can bubble up) 39 $(this).parent().click(); 40 41 that.show(); 42 43 e.stopPropagation(); 44 } 45 46 e.preventDefault(); 47 }); 48 } 49 50 GPopover.prototype.show = function() { 51 var that = this; 52 53 // Set width before showing 54 this.$popover.width(this.options.width); 55 56 // Show the popover 57 this.$popover.fadeIn(this.options.fadeInDuration); 58 59 // Set up hiding 60 $(document).one('click.popoverHide', function() { 61 // _hidePopover($popover, settings); 62 that.hide(); 63 }); 64 65 // Sort out the position (must be done after showing) 66 var triggerPos = this.$trigger.offset(); 67 this.$popover.offset({ 68 left: (triggerPos.left + (this.$trigger.outerWidth() / 2)) - (this.$popover.outerWidth() / 2), 69 top: triggerPos.top + this.$trigger.outerHeight() + 10 70 // the final 10 above allows room for the arrow above it 71 }); 72 73 // Check and reposition if out of the viewport 74 var positionXCorrection = this._repositionForViewportSides(); 75 76 // Set the position of the arrow elements 77 this._setArrowPosition(positionXCorrection); 78 79 // Call the callback 80 this.options.onShow.call(this.$trigger, this.$popover); 81 } 82 83 GPopover.prototype.hide = function() { 84 // Hide the popover 85 this.$popover.fadeOut(this.options.fadeOutDuration); 86 87 // Call the callback 88 this.options.onHide.call(this.$trigger, this.$popover); 89 } 90 91 GPopover.prototype._addArrowElements = function() { 92 this.$arrow = $('<div class="gpopover-arrow"></div>'); 93 this.$arrowShadow = $('<div class="gpopover-arrow-shadow"></div>'); 94 95 this.$popover.append(this.$arrow); 96 this.$popover.append(this.$arrowShadow); 97 } 98 99 GPopover.prototype._preventHideClickPropagation = function() { 100 /* Prevent clicks within the popover from being propagated 101 to the document (and thus stop the popover from being 102 hidden) */ 103 this.$popover.click(function(e) { e.stopPropagation(); }); 104 } 105 106 GPopover.prototype._repositionForViewportSides = function() { 107 var popoverOffsetLeft = this.$popover.offset().left, 108 positionXCorrection = 0, 109 $window = $(window); 110 111 // Right edge 112 if (popoverOffsetLeft + this.$popover.outerWidth() + this.options.viewportSideMargin > $window.width()) { 113 var rightEdgeCorrection = -((popoverOffsetLeft + this.$popover.outerWidth() + this.options.viewportSideMargin) - $window.width()); 114 popoverOffsetLeft = popoverOffsetLeft + rightEdgeCorrection 115 116 positionXCorrection = rightEdgeCorrection; 117 } 118 119 // Left edge 120 if (popoverOffsetLeft < this.options.viewportSideMargin) { 121 var leftEdgeCorrection = this.options.viewportSideMargin - popoverOffsetLeft; 122 popoverOffsetLeft = popoverOffsetLeft + leftEdgeCorrection 123 124 positionXCorrection += leftEdgeCorrection; 125 } 126 127 // Reposition the popover element if necessary 128 if (positionXCorrection !== 0) { 129 this.$popover.offset({ left: popoverOffsetLeft }); 130 } 131 132 return positionXCorrection; 133 } 134 135 GPopover.prototype._setArrowPosition = function(positionXCorrection) { 136 var leftPosition = (this.$popover.outerWidth() / 2) - (this.$arrow.outerWidth() / 2) - positionXCorrection; 137 138 this.$arrow.css({ top: -7, left: leftPosition }); 139 this.$arrowShadow.css({ top: -8, left: leftPosition }); 140 } 141 142 $.fn.gpopover = function(option) { 143 return this.each(function(){ 144 var $this = $(this), 145 data = $this.data('gpopover'), 146 options = (typeof option == 'object' && option); 147 148 // Initialise if not already done 149 if (!data) { 150 data = new GPopover(this, options); 151 $this.data('gpopover', data); 152 } 153 154 // If the option parameter was a string, trigger the named function 155 if (typeof option == 'string') data[option](); 156 }); 157 158 }; 159 160 // Default settings 161 $.fn.gpopover.defaults = {
162 width: 250, // Width of the popover 163 fadeInDuration: 65, // Duration of popover fade-in animation 164 fadeOutDuration: 65, // Duration of popover fade-out animation 165 viewportSideMargin: 10, // Space to leave the side if out the viewport 166 preventHide: false, // Prevent hide when clicking within popover 167 168 onShow: function() {}, // Called upon showing the popover 169 onHide: function() {} // Called upon hiding the popover 170 }; 171 172})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.