diff options
author | Scott González <scott.gonzalez@gmail.com> | 2009-07-24 18:24:13 +0000 |
---|---|---|
committer | Scott González <scott.gonzalez@gmail.com> | 2009-07-24 18:24:13 +0000 |
commit | eff793d014dfaeb4e601dbd97cf7b33352b05ce5 (patch) | |
tree | 9b3bed79e91895f21b2ccab876a973850544b541 | |
parent | bfca009321a9be73c7b4fa042f0cfe5fd39ca8a4 (diff) | |
download | jquery-ui-eff793d014dfaeb4e601dbd97cf7b33352b05ce5.tar.gz jquery-ui-eff793d014dfaeb4e601dbd97cf7b33352b05ce5.zip |
Copied position plugin from /branches/dev/positionTo r2971.
-rw-r--r-- | demos/position/cycler.html | 124 | ||||
-rw-r--r-- | demos/position/default.html | 158 | ||||
-rw-r--r-- | demos/position/images/earth.jpg | bin | 0 -> 35007 bytes | |||
-rw-r--r-- | demos/position/images/flight.jpg | bin | 0 -> 35234 bytes | |||
-rw-r--r-- | demos/position/images/rocket.jpg | bin | 0 -> 51070 bytes | |||
-rw-r--r-- | demos/position/index.html | 18 | ||||
-rw-r--r-- | tests/unit/position/position.html | 40 | ||||
-rw-r--r-- | tests/unit/position/position_core.js | 333 | ||||
-rw-r--r-- | ui/ui.position.js | 227 |
9 files changed, 900 insertions, 0 deletions
diff --git a/demos/position/cycler.html b/demos/position/cycler.html new file mode 100644 index 000000000..9bf90d9cc --- /dev/null +++ b/demos/position/cycler.html @@ -0,0 +1,124 @@ +<!doctype html> +<html lang="en"> +<head> + <title>jQuery UI Position - Default functionality</title> + <link type="text/css" href="../../themes/base/ui.all.css" rel="stylesheet" /> + <script type="text/javascript" src="../../jquery-1.3.2.js"></script> + <script type="text/javascript" src="../../ui/ui.core.js"></script> + <script type="text/javascript" src="../../ui/ui.draggable.js"></script> + <script type="text/javascript" src="../../ui/ui.position.js"></script> + <link type="text/css" href="../demos.css" rel="stylesheet" /> + + <style type="text/css"> + html, body { + margin: 0; + padding: 0 + } + </style> + + <script type="text/javascript"> + $(function() { + + $.fn.position2 = function(options) { + return this.position($.extend({ + of: window, + by: function(to) { + $(this).css({ + top: to.top, + left: to.left + }) + }, + collision: "none" + }, options)); + } + + $.fn.left = function(by) { + return this.position2({ + my: "right middle", + at: "left middle", + offset: "25 0", + by: by + }); + } + $.fn.right = function(by) { + return this.position2({ + my: "left middle", + at: "right middle", + offset: "-25 0", + by: by + }); + } + $.fn.center = function(by) { + return this.position2({ + my: "center middle", + at: "center middle", + by: by + }); + }; + + $("img:eq(0)").left(); + $("img:eq(1)").center(); + $("img:eq(2)").right(); + + $("body").css({ + overflow: "hidden" + }) + $(".demo").css({ + position: "relative", + }); + $(".demo img").css({ + position: "absolute", + }); + + function animate(to) { + $(this).animate(to); + } + function next() { + $("img:eq(2)").center(animate); + $("img:eq(1)").left(animate) + $("img:eq(0)").right().appendTo(".demo"); + } + function previous() { + $("img:eq(0)").center(animate); + $("img:eq(1)").right(animate); + $("img:eq(2)").left().prependTo(".demo"); + } + $("#previous").click(previous); + $("#next").click(next); + + $(".demo img").click(function() { + $(".demo img").index(this) == 0 ? previous() : next(); + }); + + $(window).resize(function() { + $("img:eq(0)").left(animate); + $("img:eq(1)").center(animate); + $("img:eq(2)").right(animate); + }) + }); + </script> + +</head> +<body> + +<div class="demo"> + + <img src="images/earth.jpg" /> + <img src="images/flight.jpg" /> + <img src="images/rocket.jpg" /> + + <a id="previous" href="#">Previous</a> + <a id="next" href="#">Next</a> +</div> + +<div class="demo-description"> + +<p>A prototype for the <a href="http://wiki.jqueryui.com/Photoviewer">Photoviewer</a> using Position to place images at the center, left and right and cycle them. +<br/>Use the links at the top to cycle, or click on the images on the left and right. +<br/>Note how the images are repositioned when resizing the window. +<br/>Warning: Doesn't currently work inside the demo viewer; open in a new window instead!</p> + +</div><!-- End demo-description --> + +</body> +</html> diff --git a/demos/position/default.html b/demos/position/default.html new file mode 100644 index 000000000..ff378cd0e --- /dev/null +++ b/demos/position/default.html @@ -0,0 +1,158 @@ +<!doctype html> +<html lang="en"> +<head> + <title>jQuery UI Position - Default functionality</title> + <link type="text/css" href="../../themes/base/ui.all.css" rel="stylesheet" /> + <script type="text/javascript" src="../../jquery-1.3.2.js"></script> + <script type="text/javascript" src="../../ui/ui.core.js"></script> + <script type="text/javascript" src="../../ui/ui.draggable.js"></script> + <script type="text/javascript" src="../../ui/ui.position.js"></script> + <link type="text/css" href="../demos.css" rel="stylesheet" /> + + <style type="text/css"> + div#parent + { + width: 60%; + margin: 10px auto; + padding: 5px; + + border: 1px solid #777; + background-color: #fbca93; + text-align: center; + } + + div.positionable + { + width: 75px; + height: 75px; + display: block; + position: fixed; + right: 0; + bottom: 0; + + background-color: #bcd5e6; + text-align: center; + } + + select, input + { + margin-left: 15px; + } + </style> + + <script type="text/javascript"> + $(function() { + + function position(by) { + $('.positionable').position({ + of: $('#parent'), + my: $('#my_horizontal').val() + ' ' + $('#my_vertical').val(), + at: $('#at_horizontal').val() + ' '+ $('#at_vertical').val(), + offset: $('#offset').val(), + by: by, + collision: $("#collision_horizontal").val() + ' ' + $("#collision_vertical").val() + }); + } + + $('.positionable').css("opacity", 0.5); + + $(':input').bind('click keyup change', position); + + $("#parent").draggable({ + drag: position + }); + + $('.positionable').draggable({ + drag: function(event, ui) { + // reset offset before calculating it + $("#offset").val("0"); + position(function(result) { + $("#offset").val("" + (ui.offset.left - result.left) + " " + (ui.offset.top - result.top)); + position(); + }); + } + }); + + position(); + }); + </script> + +</head> +<body> + +<div class="demo"> + +<div id="parent"> + <p> + This is the position parent element. + </p> +</div> + +<div class="positionable"> + <p> + to position + </p> +</div> + +<div class="positionable" style="width:120px; height: 40px;"> + <p> + to position 2 + </p> +</div> + +<div style="padding: 20px; margin-top: 75px;"> + position... + <div style="padding-bottom: 20px;"> + <b>my:</b> + <select id="my_horizontal"> + <option value="left">left</option> + <option value="center">center</option> + <option value="right">right</option> + </select> + <select id="my_vertical"> + <option value="top">top</option> + <option value="middle">center</option> + <option value="bottom">bottom</option> + </select> + </div> + <div style="padding-bottom: 20px;"> + <b>at:</b> + <select id="at_horizontal"> + <option value="left">left</option> + <option value="center">center</option> + <option value="right">right</option> + </select> + <select id="at_vertical"> + <option value="top">top</option> + <option value="middle">center</option> + <option value="bottom">bottom</option> + </select> + </div> + <div style="padding-bottom: 20px;"> + <b>offset:</b> + <input id="offset" type="text" size="15"/> + </div> + <div style="padding-bottom: 20px;"> + <b>collision:</b> + <select id="collision_horizontal"> + <option value="flip">flip</option> + <option value="fit">fit</option> + <option value="none">none</option> + </select> + <select id="collision_vertical"> + <option value="flip">flip</option> + <option value="fit">fit</option> + <option value="none">none</option> + </select> + </div> +</div> + +<div class="demo-description"> + +<p>Use the form controls to configure the positioning, or drag the positioned element to modify its offset. +<br/>Drag around the parent element to see collision detection in action.</p> + +</div><!-- End demo-description --> + +</body> +</html> diff --git a/demos/position/images/earth.jpg b/demos/position/images/earth.jpg Binary files differnew file mode 100644 index 000000000..87ea48803 --- /dev/null +++ b/demos/position/images/earth.jpg diff --git a/demos/position/images/flight.jpg b/demos/position/images/flight.jpg Binary files differnew file mode 100644 index 000000000..9721986c0 --- /dev/null +++ b/demos/position/images/flight.jpg diff --git a/demos/position/images/rocket.jpg b/demos/position/images/rocket.jpg Binary files differnew file mode 100644 index 000000000..d3bff6123 --- /dev/null +++ b/demos/position/images/rocket.jpg diff --git a/demos/position/index.html b/demos/position/index.html new file mode 100644 index 000000000..1d7ae3255 --- /dev/null +++ b/demos/position/index.html @@ -0,0 +1,18 @@ +<!doctype html> +<html lang="en"> +<head> + <title>jQuery UI Position Demo</title> + <link type="text/css" href="../demos.css" rel="stylesheet" /> +</head> +<body> + +<div class="demos-nav"> + <h4>Examples</h4> + <ul> + <li class="demo-config-on"><a href="default.html">Default functionality</a></li> + <li><a href="cycler.html">Cycling images</a></li> + </ul> +</div> + +</body> +</html> diff --git a/tests/unit/position/position.html b/tests/unit/position/position.html new file mode 100644 index 000000000..6d9a00008 --- /dev/null +++ b/tests/unit/position/position.html @@ -0,0 +1,40 @@ +<!doctype html>
+<html lang="en">
+<head>
+ <title>jQuery UI Position Test Suite</title>
+
+ <script type="text/javascript" src="../../../jquery-1.3.2.js"></script>
+ <script type="text/javascript" src="../../../ui/ui.core.js"></script>
+ <script type="text/javascript" src="../../../ui/ui.position.js"></script>
+
+ <link type="text/css" href="../testsuite.css" rel="stylesheet" />
+ <script type="text/javascript" src="../testsuite.js"></script>
+ <script type="text/javascript" src="../../../external/testrunner-r6343.js"></script>
+
+ <script type="text/javascript" src="position_core.js"></script>
+</head>
+<body>
+
+<div id="main" style="top: 0; left: 0;">
+ <div id="el1" style="position: absolute; width: 6px; height: 6px;"></div>
+ <div id="el2" style="position: absolute; width: 6px; height: 6px;"></div>
+ <div id="parent" style="position: absolute; width: 6px; height: 6px; top: 4px; left: 4px;"></div>
+</div>
+
+<div style="position: absolute; top: 0px; left: 0px">
+ <div id="elx" style="position: absolute; width: 10px; height: 10px;"></div>
+ <div id="parentx" style="position: absolute; width: 20px; height: 20px; top: 40px; left: 40px;"></div>
+</div> + +<div style="position: absolute; top: 200px; left: 100px;"> + <div id="el-offset-100-200" style="position: absolute; width: 10px; height: 10px;"></div> + <div style="position: absolute; top: 100px; left: 50px;"> + <div id="el-two-offset-150-300" style="position: absolute; width: 10px; height: 10px;"></div> + <div id="el-fixed" style="position: fixed; top: 200px; left: 200px;"></div> + </div> +</div>
+ +<div style="position: absolute; height: 5000px; width: 5000px;"></div> +
+</body>
+</html>
diff --git a/tests/unit/position/position_core.js b/tests/unit/position/position_core.js new file mode 100644 index 000000000..f05a2e804 --- /dev/null +++ b/tests/unit/position/position_core.js @@ -0,0 +1,333 @@ +/*
+ * position_core.js
+ */
+(function($) {
+
+test('my, at, of', function() {
+ $('#elx').position({
+ my: 'left top',
+ at: 'left top',
+ of: '#parentx',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 40, left: 40 }, 'left top, left top');
+
+ $('#elx').position({
+ my: 'left top',
+ at: 'left bottom',
+ of: '#parentx',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 60, left: 40 }, 'left top, left bottom');
+
+ $('#elx').position({
+ my: 'left',
+ at: 'bottom',
+ of: '#parentx',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 55, left: 50 }, 'left, bottom');
+
+ $('#elx').position({
+ my: 'left foo',
+ at: 'bar baz',
+ of: '#parentx',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 45, left: 50 }, 'left foo, bar baz');
+});
+
+test('multiple elements', function() {
+ var elements = $('#el1, #el2');
+ var result = elements.position({
+ my: 'left top',
+ at: 'left bottom',
+ of: '#parent',
+ collision: 'none'
+ });
+
+ same(result, elements);
+ var expected = {top: 10, left: 4};
+ elements.each(function() {
+ same($(this).offset(), expected);
+ });
+});
+
+test('positions', function() {
+ var definitions = [];
+ var offsets = {
+ left: 0,
+ center: 3,
+ right: 6,
+ top: 0,
+ center: 3,
+ bottom: 6
+ };
+ var start = { left: 4, top: 4 };
+ $.each([0, 1], function(my) {
+ $.each(["top", "center", "bottom"], function(vindex, vertical) {
+ $.each(["left", "center", "right"], function(hindex, horizontal) {
+ definitions.push({
+ my: my ? horizontal + " " + vertical : 'left top',
+ at: !my ? horizontal + " " + vertical : 'left top',
+ result: {
+ top: my ? start.top - offsets[vertical] : start.top + offsets[vertical],
+ left: my ? start.left - offsets[horizontal] : start.left + offsets[horizontal]
+ }
+ });
+ });
+ });
+ });
+ var el = $("#el1");
+ $.each(definitions, function(index, definition) {
+ el.position({
+ my: definition.my,
+ at: definition.at,
+ of: '#parent',
+ collision: 'none'
+ });
+ same(el.offset(), definition.result, "Position via " + jsDump.parse({my:definition.my, at:definition.at}));
+ });
+});
+
+test('of', function() {
+ $('#elx').position({
+ my: 'left top',
+ at: 'left top',
+ of: '#parentx',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 40, left: 40 }, 'selector');
+
+ $('#elx').position({
+ my: 'left top',
+ at: 'left bottom',
+ of: $('#parentx'),
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 60, left: 40 }, 'jQuery object');
+
+ $('#elx').position({
+ my: 'left top',
+ at: 'left top',
+ of: $('#parentx')[0],
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 40, left: 40 }, 'DOM element');
+
+ $('#elx').position({
+ my: 'right bottom',
+ at: 'right bottom',
+ of: document,
+ collision: 'none'
+ });
+ same($('#elx').offset(), {
+ top: $(document).height() - 10,
+ left: $(document).width() - 10
+ }, 'document');
+
+ $('#elx').position({
+ my: 'right bottom',
+ at: 'right bottom',
+ of: window,
+ collision: 'none'
+ });
+ same($('#elx').offset(), {
+ top: $(window).height() - 10,
+ left: $(window).width() - 10
+ }, 'window');
+
+ $(window).scrollTop(500).scrollLeft(200);
+ $('#elx').position({
+ my: 'right bottom',
+ at: 'right bottom',
+ of: window,
+ collision: 'none'
+ });
+ same($('#elx').offset(), {
+ top: $(window).height() + 500 - 10,
+ left: $(window).width() + 200 - 10
+ }, 'window, scrolled');
+ $(window).scrollTop(0).scrollLeft(0);
+
+ var event = $.extend($.Event('someEvent'), { pageX: 200, pageY: 300 });
+ $('#elx').position({
+ my: 'left top',
+ at: 'left top',
+ of: event,
+ collision: 'none'
+ });
+ same($('#elx').offset(), {
+ top: 300,
+ left: 200
+ }, 'event - left top, left top');
+
+ event = $.extend($.Event('someEvent'), { pageX: 400, pageY: 600 });
+ $('#elx').position({
+ my: 'left top',
+ at: 'right bottom',
+ of: event,
+ collision: 'none'
+ });
+ same($('#elx').offset(), {
+ top: 600,
+ left: 400
+ }, 'event - left top, right bottom');
+});
+
+test('offset', function() {
+ $('#elx').position({
+ my: 'left top',
+ at: 'left bottom',
+ of: '#parentx',
+ offset: '10',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 70, left: 50 }, 'single value');
+
+ $('#elx').position({
+ my: 'left top',
+ at: 'left bottom',
+ of: '#parentx',
+ offset: '5 -3',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 57, left: 45 }, 'two values');
+
+ $('#elx').position({
+ my: 'left top',
+ at: 'left bottom',
+ of: '#parentx',
+ offset: '5px -3px',
+ collision: 'none'
+ });
+ same($('#elx').offset(), { top: 57, left: 45 }, 'with units');
+});
+
+test('by', function() {
+ expect(6);
+
+ var count = 0,
+ elems = $('#el1, #el2'),
+ expectedPosition = { top: 40, left: 40 },
+ originalPosition = elems.position({
+ my: 'right bottom',
+ at: 'rigt bottom',
+ of: '#parentx',
+ collision: 'none'
+ }).offset();
+
+ elems.position({
+ my: 'left top',
+ at: 'left top',
+ of: '#parentx',
+ by: function(position) {
+ same(this, elems[count], 'correct context for call #' + count);
+ same(position, expectedPosition, 'correct position for call #' + count);
+ count++;
+ }
+ });
+
+ elems.each(function() {
+ same($(this).offset(), originalPosition, 'elements not moved');
+ });
+});
+
+function collisionTest(config, result, msg) {
+ var elem = $("#elx").position($.extend({
+ my: "left top",
+ at: "right bottom",
+ of: window
+ }, config));
+ same(elem.offset(), result, msg);
+}
+
+function collisionTest2(config, result, msg) {
+ collisionTest($.extend({
+ my: "right bottom",
+ at: "left top"
+ }, config), result, msg);
+}
+
+test("collision: fit, no offset", function() {
+ collisionTest({
+ collision: "fit"
+ }, { top: $(window).height() - 10, left: $(window).width() - 10 }, "right bottom");
+
+ collisionTest2({
+ collision: "fit"
+ }, { top: 0, left: 0 }, "left top");
+});
+
+test("collision: fit, with offset", function() {
+ collisionTest({
+ collision: "fit",
+ offset: "2 3"
+ }, { top: $(window).height() - 10, left: $(window).width() - 10 }, "right bottom");
+
+ collisionTest2({
+ collision: "fit",
+ offset: "2 3"
+ }, { top: 0, left: 0 }, "left top, positive offset");
+
+ collisionTest2({
+ collision: "fit",
+ offset: "-2 -3"
+ }, { top: 0, left: 0 }, "left top, negative offset");
+});
+
+test("collision: flip, no offset", function() {
+ collisionTest({
+ collision: "flip"
+ }, { top: -10, left: -10 }, "left top");
+
+ collisionTest2({
+ collision: "flip"
+ }, { top: $(window).height(), left: $(window).width() }, "right bottom");
+});
+
+test("collision: flip, with offset", function() {
+ collisionTest({
+ collision: "flip",
+ offset: "2 3"
+ }, { top: -13, left: -12 }, "left top, with offset added");
+
+ collisionTest2({
+ collision: "flip",
+ offset: "2 3"
+ }, { top: $(window).height() - 3, left: $(window).width() - 2 }, "bottom, positive offset");
+
+ collisionTest2({
+ collision: "flip",
+ offset: "-2 -3"
+ }, { top: $(window).height() + 3, left: $(window).width() + 2 }, "right bottom, negative offset");
+});
+
+test("collision: none, no offset", function() {
+ collisionTest({
+ collision: "none"
+ }, { top: $(window).height(), left: $(window).width() }, "left top");
+
+ collisionTest2({
+ collision: "none"
+ }, { top: -10, left: -10 }, "moved to the right bottom");
+});
+
+test("collision: none, with offset", function() {
+ collisionTest({
+ collision: "none",
+ offset: "2 3"
+ }, { top: $(window).height() + 3, left: $(window).width() + 2 }, "right bottom, with offset added");
+
+ collisionTest2({
+ collision: "none",
+ offset: "2 3"
+ }, { top: -7, left: -8 }, "left top, positive offset");
+
+ collisionTest2({
+ collision: "none",
+ offset: "-2 -3"
+ }, { top: -13, left: -12 }, "left top, negative offset");
+});
+
+})(jQuery);
diff --git a/ui/ui.position.js b/ui/ui.position.js new file mode 100644 index 000000000..b77e96e60 --- /dev/null +++ b/ui/ui.position.js @@ -0,0 +1,227 @@ +/*
+ * jQuery UI Position @VERSION
+ *
+ * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ * TODO: create document page for position and add link here
+ */
+(function($) {
+
+var horizontalPositions = /left|center|right/,
+ horizontalDefault = 'center',
+ verticalPositions = /top|center|bottom/,
+ verticalDefault = 'center',
+ _position = $.fn.position;
+
+$.fn.position = function(options) {
+ if (!options || !options.of) {
+ return _position.apply(this, arguments);
+ }
+
+ options = $.extend({
+ stackFix: true
+ }, options);
+
+ var target = $(options.of),
+ collision = (options.collision || 'flip').split(' '),
+ offset = options.offset ? options.offset.split(' ') : [0, 0],
+ targetWidth,
+ targetHeight,
+ basePosition;
+
+ if (options.of == document) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: 0, left: 0 };
+ } else if (options.of == window) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
+ } else if (options.of.preventDefault) {
+ targetWidth = targetHeight = 0;
+ basePosition = { top: options.of.pageY, left: options.of.pageX };
+ } else {
+ targetWidth = target.outerWidth();
+ targetHeight = target.outerHeight();
+ basePosition = target.offset();
+ }
+
+ // force my and at to have valid horizontal and veritcal positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each(['my', 'at'], function() {
+ var pos = options[this].split(' ');
+ pos = pos.length == 1
+ ? horizontalPositions.test(pos[0])
+ ? pos.concat([verticalDefault])
+ : verticalPositions.test(pos[0])
+ ? [horizontalDefault].concat(pos)
+ : [horizontalDefault, verticalDefault]
+ : pos;
+ pos[0] = horizontalPositions.test(pos[0]) ? pos[0] : horizontalDefault;
+ pos[1] = verticalPositions.test(pos[1]) ? pos[1] : verticalDefault;
+ options[this] = pos;
+ });
+
+ // normalize collision option
+ if (collision.length == 1) {
+ collision[1] = collision[0];
+ }
+
+ // normalize offset option
+ offset[0] = parseInt(offset[0], 10) || 0;
+ if (offset.length == 1) {
+ offset[1] = offset[0];
+ }
+ offset[1] = parseInt(offset[1], 10) || 0;
+
+ switch (options.at[0]) {
+ case 'right':
+ basePosition.left += targetWidth;
+ break;
+ case horizontalDefault:
+ basePosition.left += targetWidth / 2;
+ break;
+ }
+
+ switch (options.at[1]) {
+ case 'bottom':
+ basePosition.top += targetHeight;
+ break;
+ case verticalDefault:
+ basePosition.top += targetHeight / 2;
+ break;
+ }
+
+ basePosition.left += offset[0];
+ basePosition.top += offset[1];
+
+ return this.each(function() {
+ var elem = $(this),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ position = $.extend({}, basePosition),
+ over,
+ myOffset,
+ atOffset;
+
+ switch (options.my[0]) {
+ case 'right':
+ position.left -= elemWidth;
+ break;
+ case horizontalDefault:
+ position.left -= elemWidth / 2;
+ break;
+ }
+
+ switch (options.my[1]) {
+ case 'bottom':
+ position.top -= elemHeight;
+ break;
+ case verticalDefault:
+ position.top -= elemHeight / 2;
+ break;
+ }
+
+ $.each(['left', 'top'], function(i, dir) {
+ ($.ui.position[collision[i]] &&
+ $.ui.position[collision[i]][dir](position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ offset: offset,
+ my: options.my,
+ at: options.at
+ }));
+ });
+
+ (options.stackfix && $.fn.stackfix && elem.stackfix());
+ // the by function is passed the offset values, not the position values
+ // we'll need the logic from the .offset() setter to be accessible for
+ // us to calculate the position values to make the by option more useful
+ ($.isFunction(options.by) ? options.by.call(this, position) : elem.offset(position));
+ });
+};
+
+$.ui.position = {
+ fit: {
+ left: function(position, data) {
+ var over = position.left + data.elemWidth - $(window).width() - $(window).scrollLeft();
+ position.left = over > 0 ? position.left - over : Math.max(0, position.left);
+ },
+ top: function(position, data) {
+ var over = position.top + data.elemHeight - $(window).height() - $(window).scrollTop();
+ position.top = over > 0 ? position.top - over : Math.max(0, position.top);
+ }
+ },
+
+ flip: {
+ left: function(position, data) {
+ if (data.at[0] == 'center')
+ return;
+ var over = position.left + data.elemWidth - $(window).width() - $(window).scrollLeft(),
+ myOffset = data.my[0] == 'left' ? -data.elemWidth : data.my[0] == 'right' ? data.elemWidth : 0,
+ offset = -2 * data.offset[0];
+ position.left += position.left < 0 ? myOffset + data.targetWidth + offset : over > 0 ? myOffset - data.targetWidth + offset : 0;
+ },
+ top: function(position, data) {
+ if (data.at[1] == 'center')
+ return;
+ var over = position.top + data.elemHeight - $(window).height() - $(window).scrollTop(),
+ myOffset = data.my[1] == 'top' ? -data.elemHeight : data.my[1] == 'bottom' ? data.elemHeight : 0,
+ atOffset = data.at[1] == 'top' ? data.targetHeight : -data.targetHeight,
+ offset = -2 * data.offset[1];
+ position.top += position.top < 0 ? myOffset + data.targetHeight + offset : over > 0 ? myOffset + atOffset + offset : 0;
+ }
+ }
+};
+
+
+// the following functionality is planned for jQuery 1.4
+// based on http://plugins.jquery.com/files/offset.js.txt
+$.fn.extend({
+ _offset: $.fn.offset,
+ offset: function(newOffset) {
+ return !newOffset ? this._offset() : this.each(function() {
+ var elem = $(this),
+ // we need to convert static positioning to relative positioning
+ isRelative = /relative|static/.test(elem.css('position')),
+ hide = elem.css('display') == 'none';
+
+ (isRelative && elem.css('position', 'relative'));
+ (hide && elem.show());
+
+ var offset = elem.offset(),
+ delta = {
+ left : parseInt(elem.css('left'), 10),
+ top: parseInt(elem.css('top'), 10)
+ };
+
+ // in case of 'auto'
+ delta.left = !isNaN(delta.left)
+ ? delta.left
+ : isRelative
+ ? 0
+ : this.offsetLeft;
+ delta.top = !isNaN(delta.top)
+ ? delta.top
+ : isRelative
+ ? 0
+ : this.offsetTop;
+
+ // allow setting only left or only top
+ if (newOffset.left || newOffset.left === 0) {
+ elem.css('left', newOffset.left - offset.left + delta.left);
+ }
+ if (newOffset.top || newOffset.top === 0) {
+ elem.css('top', newOffset.top - offset.top + delta.top);
+ }
+
+ (hide && elem.hide());
+ });
+ }
+});
+
+})(jQuery);
|