123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /*
- * positionBy 1.0.7 (2008-01-29)
- *
- * Copyright (c) 2006,2007 Jonathan Sharp (http://jdsharp.us)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
- *
- * http://jdsharp.us/
- *
- * Built upon jQuery 1.2.2 (http://jquery.com)
- * This also requires the jQuery dimensions plugin
- *
- *
- * @@ Modified by dflaven for handling the positioning of the iTop popup menus @@
- *
- */
- (function($){
- /**
- * This function centers an absolutely positioned element
- */
- /*
- $.fn.positionCenter = function(offsetLeft, offsetTop) {
- var offsetLeft = offsetLeft || 1;
- var offsetTop = offsetTop || 1;
- var ww = $(window).width();
- var wh = $(window).height();
- var sl = $(window).scrollLeft();
- var st = $(window).scrollTop();
- return this.each(function() {
- var $t = $(this);
-
- // If we are not visible we have to display our element (with a negative position offscreen)
- var left = Math.round( ( ww - $t.outerWidth() ) / 2 );
- if ( left < 0 ) {
- left = 0;
- } else {
- left *= offsetLeft;
- }
- left += sl;
- var top = Math.round( ( wh - $t.outerHeight() ) / 2 );
- if ( top < 0 ) {
- top = 0;
- } else {
- top *= offsetTop;
- }
- top += st;
- $(this).parents().each(function() {
- var $this = $(this);
- if ( $this.css('position') != 'static' ) {
- var o = $this.offset();
- left += -o.left;
- top += -o.top;
- return false;
- }
- });
- $t.css({left: left, top: top});
- });
- };
- */
-
- // Our range object is used in calculating positions
- var Range = function(x1, y1, x2, y2) {
- this.x1 = x1; this.x2 = x2;
- this.y1 = y1; this.y2 = y2;
- };
- Range.prototype.contains = function(range) {
- return (this.x1 <= range.x1 && range.x2 <= this.x2)
- &&
- (this.y1 <= range.y1 && range.y2 <= this.y2);
- };
- Range.prototype.transform = function(x, y) {
- return new Range(this.x1 + x, this.y1 + y, this.x2 + x, this.y2 + y);
- };
- $.fn.positionBy = function(args) {
- var date1 = new Date();
- if ( this.length == 0 ) {
- return this;
- }
-
- var args = $.extend({ // The target element to position us relative to
- target: null,
- // The target's corner, possible values 0-3
- targetPos: null,
- // The element's corner, possible values 0-3
- elementPos: null,
-
- // A raw x,y coordinate
- x: null,
- y: null,
- // Pass in an array of positions that are valid 0-15
- positions: null,
- // Add the final position class to the element (eg. positionBy0 through positionBy3, positionBy15)
- addClass: false,
-
- // Force our element to be at the location we specified (don't try to auto position it)
- force: false,
-
- // The element that we will make sure our element doesn't go outside of
- container: window,
- // Should the element be hidden after positioning?
- hideAfterPosition: false
- }, args);
- if ( args.x != null ) {
- var tLeft = args.x;
- var tTop = args.y;
- var tWidth = 0;
- var tHeight = 0;
-
- // Position in relation to an element
- } else {
- var $target = $( $( args.target )[0] );
- var tWidth = $target.outerWidth();
- var tHeight = $target.outerHeight();
- var tOffset = $target.offset();
- var tLeft = tOffset.left;
- var tTop = tOffset.top;
- }
- // Our target right, bottom coord
- var tRight = tLeft + tWidth;
- var tBottom = tTop + tHeight;
- return this.each(function() {
- var $element = $( this );
- // Position our element in the top left so we can grab its width without triggering scrollbars
- if ( !$element.is(':visible') ) {
- $element.css({ left: -3000,
- top: -3000
- })
- .show();
- }
- var eWidth = $element.outerWidth();
- var eHeight = $element.outerHeight();
-
- // Holds x1,y1,x2,y2 coordinates for a position in relation to our target element
- var position = [];
- // Holds a list of alternate positions to try if this one is not in the browser viewport
- var next = [];
-
- // Our Positions via ASCII ART
- /*
- 8 9 10 11
- +------------+
- 7 | 15 12 | 0
- | |
- 6 | 14 13 | 1
- +------------+
- 5 4 3 2
-
- */
- position[0] = new Range(tRight, tTop, tRight + eWidth, tTop + eHeight);
- next[0] = [1,7,4];
-
- position[1] = new Range(tRight, tBottom - eHeight, tRight + eWidth, tBottom);
- next[1] = [0,6,4];
-
- position[2] = new Range(tRight, tBottom, tRight + eWidth, tBottom + eHeight);
- next[2] = [1,3,10];
-
- position[3] = new Range(tRight - eWidth, tBottom, tRight, tBottom + eHeight);
- next[3] = [1,6,10];
-
- position[4] = new Range(tLeft, tBottom, tLeft + eWidth, tBottom + eHeight);
- next[4] = [1,6,9];
-
- position[5] = new Range(tLeft - eWidth, tBottom, tLeft, tBottom + eHeight);
- next[5] = [6,4,9];
-
- position[6] = new Range(tLeft - eWidth, tBottom - eHeight, tLeft, tBottom);
- next[6] = [7,1,4];
-
- position[7] = new Range(tLeft - eWidth, tTop, tLeft, tTop + eHeight);
- next[7] = [6,0,4];
-
- position[8] = new Range(tLeft - eWidth, tTop - eHeight, tLeft, tTop);
- next[8] = [7,9,4];
-
- position[9] = new Range(tLeft, tTop - eHeight, tLeft + eWidth, tTop);
- next[9] = [0,7,4];
-
- position[10]= new Range(tRight - eWidth, tTop - eHeight, tRight, tTop);
- next[10] = [0,7,3];
-
- position[11]= new Range(tRight, tTop - eHeight, tRight + eWidth, tTop);
- next[11] = [0,10,3];
-
- position[12]= new Range(tRight - eWidth, tTop, tRight, tTop + eHeight);
- next[12] = [13,7,10];
-
- position[13]= new Range(tRight - eWidth, tBottom - eHeight, tRight, tBottom);
- next[13] = [12,6,3];
-
- position[14]= new Range(tLeft, tBottom - eHeight, tLeft + eWidth, tBottom);
- next[14] = [15,1,4];
-
- position[15]= new Range(tLeft, tTop, tLeft + eWidth, tTop + eHeight);
- next[15] = [14,0,9];
-
- // @@ Added by dflaven
- position[16]= new Range(tRight - eWidth, tBottom, tRight, tBottom + eHeight);
- next[16] = [3,10];
- // @@End of modification
-
- if ( args.positions !== null ) {
- var pos = args.positions[0];
- } else if ( args.targetPos != null && args.elementPos != null ) {
- var pos = [];
- pos[0] = [];
- pos[0][0] = 15;
- pos[0][1] = 7;
- pos[0][2] = 8;
- pos[0][3] = 9;
- pos[1] = [];
- pos[1][0] = 0;
- pos[1][1] = 12;
- pos[1][2] = 10;
- pos[1][3] = 11;
- pos[2] = [];
- pos[2][0] = 2;
- pos[2][1] = 3;
- pos[2][2] = 13;
- pos[2][3] = 1;
- pos[3] = [];
- pos[3][0] = 4;
- pos[3][1] = 5;
- pos[3][2] = 6;
- pos[3][3] = 14;
- // @@ Added by dflaven
- pos[4] = [];
- pos[4][0] = 16;
- pos[4][1] = 16;
- pos[4][2] = 16;
- pos[4][3] = 16;
- // @@ End of modification
- var pos = pos[args.targetPos][args.elementPos];
- }
- var ePos = position[pos];
- var fPos = pos;
- if ( !args.force ) {
- // TODO: Do the args.container
- // window width & scroll offset
- $window = $( window );
- var sx = $window.scrollLeft();
- var sy = $window.scrollTop();
-
- // TODO: Look at innerWidth & innerHeight
- var container = new Range( sx, sy, sx + $window.width(), sy + $window.height() );
-
- // If we are outside of our viewport, see if we are outside vertically or horizontally and push onto the stack
- var stack;
- if ( args.positions ) {
- stack = args.positions;
- } else {
- stack = [pos];
- }
- var test = []; // Keeps track of our positions we already tried
-
- while ( stack.length > 0 ) {
- var p = stack.shift();
- if ( test[p] ) {
- continue;
- }
- test[p] = true;
-
- // If our current position is not within the viewport (eg. window)
- // add the next suggested position
- if ( !container.contains(position[p]) ) {
- if ( args.positions === null ) {
- stack = jQuery.merge( stack, next[p] );
- }
- } else {
- ePos = position[p];
- break;
- }
- }
- }
- // + TODO: Determine if we are going to use absolute left, top, bottom, right
- // positions relative to our target
-
- // Take into account any absolute or fixed positioning
- // to 'normalize' our coordinates
- $element.parents().each(function() {
- var $this = $(this);
- if ( $this.css('position') != 'static' ) {
- var abs = $this.offset();
- ePos = ePos.transform( -abs.left, -abs.top );
- return false;
- }
- });
-
- // Finally position our element
- var css = { left: ePos.x1, top: ePos.y1 };
- if ( args.hideAfterPosition ) {
- css['display'] = 'none';
- }
- $element.css( css );
- if ( args.addClass ) {
- $element.removeClass( 'positionBy0 positionBy1 positionBy2 positionBy3 positionBy4 positionBy5 '
- + 'positionBy6 positionBy7 positionBy8 positionBy9 positionBy10 positionBy11 '
- + 'positionBy12 positionBy13 positionBy14 positionBy15')
- .addClass('positionBy' + p);
- }
- });
- };
- })(jQuery);
|