Copied position plugin from /branches/dev/positionTo r2971.

This commit is contained in:
Scott González 2009-07-24 18:24:13 +00:00
parent bfca009321
commit eff793d014
9 changed files with 900 additions and 0 deletions

124
demos/position/cycler.html Normal file
View File

@ -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>

158
demos/position/default.html Normal file
View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

18
demos/position/index.html Normal file
View File

@ -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>

View File

@ -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>

View File

@ -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);

227
ui/ui.position.js Normal file
View File

@ -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);