r2860 - positionTo: Added support for positioning against the document, window and events.

r2860 - positionTo: Added support for positioning against the document, window and events.


Author: scott.gonzalez
Date: Thu Jul 2 06:35:46 2009
New Revision: 2860
Modified:
branches/dev/positionTo/tests/unit/positionTo/positionTo.html
branches/dev/positionTo/tests/unit/positionTo/positionTo_core.js
branches/dev/positionTo/ui/ui.positionTo.js
Log:
positionTo: Added support for positioning against the document, window and
events.
Modified: branches/dev/positionTo/tests/unit/positionTo/positionTo.html
==============================================================================
--- branches/dev/positionTo/tests/unit/positionTo/positionTo.html    (original)
+++ branches/dev/positionTo/tests/unit/positionTo/positionTo.html    Thu Jul
2 06:35:46 2009
@@ -25,6 +25,8 @@
    <div id="elx" style="position: absolute; width: 10px; height: 10px;
background-color: red"></div>
    <div id="parentx" style="position: absolute; width: 20px; height: 20px;
top: 40px; left: 40px; background-color: green"></div>
</div>
+
+<div style="height: 5000px; width: 5000px;"></div>
</body>
</html>
Modified: branches/dev/positionTo/tests/unit/positionTo/positionTo_core.js
==============================================================================
--- branches/dev/positionTo/tests/unit/positionTo/positionTo_core.js    
(original)
+++ branches/dev/positionTo/tests/unit/positionTo/positionTo_core.js    Thu
Jul 2 06:35:46 2009
@@ -84,6 +84,83 @@
    });
});
+test('of', function() {
+    $('#elx').positionTo({
+        my: 'left top',
+        at: 'left top',
+        of: '#parentx'
+    });
+    same($('#elx').offset(), { top: 40, left: 40 }, 'selector');
+    
+    $('#elx').positionTo({
+        my: 'left top',
+        at: 'left bottom',
+        of: $('#parentx')
+    });
+    same($('#elx').offset(), { top: 60, left: 40 }, 'jQuery object');
+    
+    $('#elx').positionTo({
+        my: 'left top',
+        at: 'left top',
+        of: $('#parentx')[0]
+    });
+    same($('#elx').offset(), { top: 40, left: 40 }, 'DOM element');
+    
+    $('#elx').positionTo({
+        my: 'right bottom',
+        at: 'right bottom',
+        of: document
+    });
+    same($('#elx').offset(), {
+        top: $(document).height() - 10,
+        left: $(document).width() - 10
+    }, 'document');
+    
+    $('#elx').positionTo({
+        my: 'right bottom',
+        at: 'right bottom',
+        of: window
+    });
+    same($('#elx').offset(), {
+        top: $(window).height() - 10,
+        left: $(window).width() - 10
+    }, 'window');
+    
+    $(window).scrollTop(500).scrollLeft(200);
+    $('#elx').positionTo({
+        my: 'right bottom',
+        at: 'right bottom',
+        of: window
+    });
+    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').positionTo({
+        my: 'left top',
+        at: 'left top',
+        of: event
+    });
+    same($('#elx').offset(), {
+        top: 300,
+        left: 200
+    }, 'event - left top, left top');
+    
+    event = $.extend($.Event('someEvent'), { pageX: 400, pageY: 600 });
+    $('#elx').positionTo({
+        my: 'left top',
+        at: 'right bottom',
+        of: event
+    });
+    same($('#elx').offset(), {
+        top: 600,
+        left: 400
+    }, 'event - left top, right bottom');
+});
+
test('offset', function() {
    $('#elx').positionTo({
        my: 'left top',
Modified: branches/dev/positionTo/ui/ui.positionTo.js
==============================================================================
--- branches/dev/positionTo/ui/ui.positionTo.js    (original)
+++ branches/dev/positionTo/ui/ui.positionTo.js    Thu Jul 2 06:35:46 2009
@@ -21,12 +21,30 @@
    }, options);
    var target = $(options.of),
-        targetWidth = target.outerWidth(),
-        targetHeight = target.outerHeight(),
-
        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 or
middle
    $.each(['my', 'at'], function() {
        var pos = options[this].split(' ');
        pos = pos.length == 1
@@ -91,6 +109,9 @@
        // TODO: collision option
        (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
        (options.by ? options.by.call(this, position) : elem.offset(position));
    });
};