aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott González <scott.gonzalez@gmail.com>2009-07-24 18:24:13 +0000
committerScott González <scott.gonzalez@gmail.com>2009-07-24 18:24:13 +0000
commiteff793d014dfaeb4e601dbd97cf7b33352b05ce5 (patch)
tree9b3bed79e91895f21b2ccab876a973850544b541
parentbfca009321a9be73c7b4fa042f0cfe5fd39ca8a4 (diff)
downloadjquery-ui-eff793d014dfaeb4e601dbd97cf7b33352b05ce5.tar.gz
jquery-ui-eff793d014dfaeb4e601dbd97cf7b33352b05ce5.zip
Copied position plugin from /branches/dev/positionTo r2971.
-rw-r--r--demos/position/cycler.html124
-rw-r--r--demos/position/default.html158
-rw-r--r--demos/position/images/earth.jpgbin0 -> 35007 bytes
-rw-r--r--demos/position/images/flight.jpgbin0 -> 35234 bytes
-rw-r--r--demos/position/images/rocket.jpgbin0 -> 51070 bytes
-rw-r--r--demos/position/index.html18
-rw-r--r--tests/unit/position/position.html40
-rw-r--r--tests/unit/position/position_core.js333
-rw-r--r--ui/ui.position.js227
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
new file mode 100644
index 000000000..87ea48803
--- /dev/null
+++ b/demos/position/images/earth.jpg
Binary files differ
diff --git a/demos/position/images/flight.jpg b/demos/position/images/flight.jpg
new file mode 100644
index 000000000..9721986c0
--- /dev/null
+++ b/demos/position/images/flight.jpg
Binary files differ
diff --git a/demos/position/images/rocket.jpg b/demos/position/images/rocket.jpg
new file mode 100644
index 000000000..d3bff6123
--- /dev/null
+++ b/demos/position/images/rocket.jpg
Binary files differ
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);