Index: components/reorderer/js/GeometricManager.js
===================================================================
--- components/reorderer/js/GeometricManager.js	(revision 10185)
+++ components/reorderer/js/GeometricManager.js	(working copy)
@@ -1,6 +1,7 @@
 /*
 Copyright 2008-2010 University of Cambridge
 Copyright 2008-2010 University of Toronto
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -237,57 +238,14 @@
         }
     }
     
-    fluid.dropManager = function () {
+   
+    
+    fluid.dropManager = function () { 
         var targets = [];
         var cache = {};
-        var that = {};
-        
-        var lastClosest;
-        
-        function cacheKey(element) {
-            return fluid.allocateSimpleId(element);
-        }
-        
-        function sentinelizeElement(targets, sides, cacheelem, fc, disposition, clazz) {
-            var elemCopy = $.extend(true, {}, cacheelem);
-            elemCopy.rect[sides[fc]] = elemCopy.rect[sides[1 - fc]] + (fc? 1: -1);
-            elemCopy.rect[sides[1 - fc]] = (fc? -1 : 1) * SENTINEL_DIMENSION;
-            elemCopy.position = disposition === fluid.position.INSIDE?
-               disposition : (fc? fluid.position.BEFORE : fluid.position.AFTER);
-            elemCopy.clazz = clazz;
-            targets[targets.length] = elemCopy;
-        }
+        var that = {};        
         
-        function splitElement(targets, sides, cacheelem, disposition, clazz1, clazz2) {
-            var elem1 = $.extend(true, {}, cacheelem);
-            var elem2 = $.extend(true, {}, cacheelem);
-            var midpoint = (elem1.rect[sides[0]] + elem1.rect[sides[1]]) / 2;
-            elem1.rect[sides[1]] = midpoint; 
-            elem1.position = fluid.position.BEFORE;
-            
-            elem2.rect[sides[0]] = midpoint; 
-            elem2.position = fluid.position.AFTER;
-            
-            elem1.clazz = clazz1;
-            elem2.clazz = clazz2;
-            targets[targets.length] = elem1;
-            targets[targets.length] = elem2;
-        }
-       
-        // Expand this configuration point if we ever go back to a full "permissions" model
-        function getRelativeClass(thisElements, index, relative, thisclazz, mapper) {
-            index += relative;
-            if (index < 0 && thisclazz === "locked") {
-                return "locked";
-            }
-            if (index >= thisElements.length || mapper === null) {
-                return null;
-            } else {
-                relative = thisElements[index];
-                return mapper(relative) === "locked" && thisclazz === "locked" ? "locked" : null;
-            }
-        }
-        
+        var lastClosest;              
         var lastGeometry;
         var displacementX, displacementY;
         
@@ -307,21 +265,21 @@
                     if (cacheelem.clazz !== "hidden" && mapper) {
                         cacheelem.clazz = mapper(element);
                     }
-                    cache[cacheKey(element)] = cacheelem;
-                    var backClass = getRelativeClass(thisInfo.elements, j, fluid.position.BEFORE, cacheelem.clazz, mapper); 
-                    var frontClass = getRelativeClass(thisInfo.elements, j, fluid.position.AFTER, cacheelem.clazz, mapper); 
+                    cache[fluid.dropManager.cacheKey(element)] = cacheelem;
+                    var backClass = fluid.dropManager.getRelativeClass(thisInfo.elements, j, fluid.position.BEFORE, cacheelem.clazz, mapper); 
+                    var frontClass = fluid.dropManager.getRelativeClass(thisInfo.elements, j, fluid.position.AFTER, cacheelem.clazz, mapper); 
                     if (disposition === fluid.position.INSIDE) {
                         targets[targets.length] = cacheelem;
                     }
                     else {
-                        splitElement(targets, sides, cacheelem, disposition, backClass, frontClass);
+                        fluid.dropManager.splitElement(targets, sides, cacheelem, disposition, backClass, frontClass);
                     }
                     // deal with sentinel blocks by creating near-copies of the end elements
                     if (sentB && geometricInfo.sentinelize) {
-                        sentinelizeElement(targets, sides, cacheelem, 1, disposition, backClass);
+                        fluid.dropManager.sentinelizeElement(targets, sides, cacheelem, 1, disposition, backClass);
                     }
                     if (sentF && geometricInfo.sentinelize) {
-                        sentinelizeElement(targets, sides, cacheelem, 0, disposition, frontClass);
+                        fluid.dropManager.sentinelizeElement(targets, sides, cacheelem, 0, disposition, frontClass);
                     }
                     //fluid.log(dumpelem(cacheelem));
                     return cacheelem;
@@ -431,18 +389,18 @@
             };
         };
         
-        that.shuffleProjectFrom = function (element, direction, includeLocked) {
-            var togo = that.projectFrom(element, direction, includeLocked);
+        that.shuffleProjectFrom = function (element, direction, includeLocked, disableWrap) {
+            var togo = that.projectFrom(element, direction, includeLocked, disableWrap);
             if (togo) {
                 togo.position = fluid.position.REPLACE;
             }
             return togo;
         };
         
-        that.projectFrom = function (element, direction, includeLocked) {
+        that.projectFrom = function (element, direction, includeLocked, disableWrap) {
             that.updateGeometry(lastGeometry);
-            var cacheelem = cache[cacheKey(element)];
-            var projected = fluid.geom.projectFrom(cacheelem.rect, direction, targets, includeLocked);
+            var cacheelem = cache[fluid.dropManager.cacheKey(element)];
+            var projected = fluid.geom.projectFrom(cacheelem.rect, direction, targets, includeLocked, disableWrap);
             if (!projected.cacheelem) {
                 return null;
             }
@@ -452,31 +410,20 @@
                      };
         };
         
-        function getRelativeElement(element, direction, elements) {
-            var folded = fluid.directionSign(direction);
-      
-            var index = $(elements).index(element) + folded;
-            if (index < 0) {
-                index += elements.length;
-            }
-            index %= elements.length;
-            return elements[index];            
-        }
-        
-        that.logicalFrom = function (element, direction, includeLocked) {
+        that.logicalFrom = function (element, direction, includeLocked, disableWrap) {
             var orderables = that.getOwningSpan(element, fluid.position.INTERLEAVED, includeLocked);
-            return {element: getRelativeElement(element, direction, orderables), 
+            return {element: fluid.dropManager.getRelativeElement(element, direction, orderables, disableWrap), 
                 position: fluid.position.REPLACE};
         };
            
-        that.lockedWrapFrom = function (element, direction, includeLocked) {
-            var base = that.logicalFrom(element, direction, includeLocked);
+        that.lockedWrapFrom = function (element, direction, includeLocked, disableWrap) {
+            var base = that.logicalFrom(element, direction, includeLocked, disableWrap);
             var selectables = that.getOwningSpan(element, fluid.position.INTERLEAVED, includeLocked);
-            var allElements = cache[cacheKey(element)].owner.elements;
+            var allElements = cache[fluid.dropManager.cacheKey(element)].owner.elements;
             if (includeLocked || selectables[0] === allElements[0]) {
                 return base;
             }
-            var directElement = getRelativeElement(element, direction, allElements);
+            var directElement = fluid.dropManager.getRelativeElement(element, direction, allElements, disableWrap);
             if (lastGeometry.elementMapper(directElement) === "locked") {
                 base.element = null;
                 base.clazz = "locked";  
@@ -485,7 +432,7 @@
         }; 
         
         that.getOwningSpan = function (element, position, includeLocked) {
-            var owner = cache[cacheKey(element)].owner; 
+            var owner = cache[fluid.dropManager.cacheKey(element)].owner; 
             var elements = position === fluid.position.INSIDE? [owner.parentElement] : owner.elements;
             if (!includeLocked && lastGeometry.elementMapper) {
                 elements = $.makeArray(elements);
@@ -500,14 +447,77 @@
             var sourceElements = that.getOwningSpan(element, null, true);
             var targetElements = that.getOwningSpan(target, position, true);
             fluid.permuteDom(element, target, position, sourceElements, targetElements);
-        };
+        };              
         
         return that;
-    };
+    };    
+   
  
     fluid.dropManager.NO_CHANGE = "no change";
-
-
+    
+    fluid.dropManager.cacheKey = function (element) {
+        return fluid.allocateSimpleId(element);
+    };
+    
+    fluid.dropManager.sentinelizeElement = function (targets, sides, cacheelem, fc, disposition, clazz) {
+        var elemCopy = $.extend(true, {}, cacheelem);
+        elemCopy.rect[sides[fc]] = elemCopy.rect[sides[1 - fc]] + (fc? 1: -1);
+        elemCopy.rect[sides[1 - fc]] = (fc? -1 : 1) * SENTINEL_DIMENSION;
+        elemCopy.position = disposition === fluid.position.INSIDE?
+           disposition : (fc? fluid.position.BEFORE : fluid.position.AFTER);
+        elemCopy.clazz = clazz;
+        targets[targets.length] = elemCopy;
+    };
+    
+    fluid.dropManager.splitElement = function (targets, sides, cacheelem, disposition, clazz1, clazz2) {
+        var elem1 = $.extend(true, {}, cacheelem);
+        var elem2 = $.extend(true, {}, cacheelem);
+        var midpoint = (elem1.rect[sides[0]] + elem1.rect[sides[1]]) / 2;
+        elem1.rect[sides[1]] = midpoint; 
+        elem1.position = fluid.position.BEFORE;
+        
+        elem2.rect[sides[0]] = midpoint; 
+        elem2.position = fluid.position.AFTER;
+        
+        elem1.clazz = clazz1;
+        elem2.clazz = clazz2;
+        targets[targets.length] = elem1;
+        targets[targets.length] = elem2;
+    };
+    
+    // Expand this configuration point if we ever go back to a full "permissions" model
+    fluid.dropManager.getRelativeClass = function (thisElements, index, relative, thisclazz, mapper) {
+        index += relative;
+        if (index < 0 && thisclazz === "locked") {
+            return "locked";
+        }
+        if (index >= thisElements.length || mapper === null) {
+            return null;
+        } else {
+            relative = thisElements[index];
+            return mapper(relative) === "locked" && thisclazz === "locked" ? "locked" : null;
+        }
+    };
+    
+     fluid.dropManager.getRelativeElement = function (element, direction, elements, disableWrap) {
+        var folded = fluid.directionSign(direction);
+  
+        var index = $(elements).index(element) + folded;
+        if (index < 0) {
+            index += elements.length;
+        }
+        
+        // disable wrap
+        if (disableWrap) {                   
+            if (index === elements.length || index === (elements.length + folded)) {
+                return element;
+            }
+        }
+                      
+        index %= elements.length;
+        return elements[index];              
+    };
+    
     fluid.geom = fluid.geom || {};
     
     // These distance algorithms have been taken from
@@ -545,9 +555,10 @@
      * @param {fluid.direction} direction  The direction of motion
      * @param {Array of Rectangle holders} targets An array of objects "cache elements" 
      * for which the member <code>rect</code> is the holder of the rectangle to be tested.
+     * @param disableWrap which is used to enable or disable wrapping of elements
      * @return The cache element which is the most appropriate for the requested motion.
      */
-    fluid.geom.projectFrom = function (baserect, direction, targets, forSelection) {
+    fluid.geom.projectFrom = function (baserect, direction, targets, forSelection, disableWrap) {
         var axis = fluid.directionAxis(direction);
         var frontSide = fluid.rectSides[direction];
         var backSide = fluid.rectSides[axis * 15 + 5 - direction];
@@ -597,8 +608,13 @@
             }
             //fluid.log("Element " + i + " " + dumpelem(elem) + " mindist " + collect.mindist);
         }
-        var wrap = !collect.minelem || backcollect.mindist < collect.mindist;
-        var mincollect = wrap? backcollect: collect;
+        var wrap = !collect.minelem || backcollect.mindist < collect.mindist ;
+        
+        // disable wrap
+        wrap = wrap && !disableWrap;       
+                
+        var mincollect = wrap? backcollect: collect;        
+        
         var togo = {
             wrapped: wrap,
             cacheelem: mincollect.minelem
Index: components/reorderer/js/ModuleLayout.js
===================================================================
--- components/reorderer/js/ModuleLayout.js	(revision 10185)
+++ components/reorderer/js/ModuleLayout.js	(working copy)
@@ -1,6 +1,7 @@
 /*
 Copyright 2008-2009 University of Cambridge
 Copyright 2008-2009 University of Toronto
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -169,7 +170,7 @@
         that.getRelativePosition  = 
            fluid.reorderer.relativeInfoGetter(options.orientation, 
                  fluid.reorderer.WRAP_LOCKED_STRATEGY, fluid.reorderer.GEOMETRIC_STRATEGY, 
-                 dropManager, dom);
+                 dropManager, dom, options.disableWrap);
                  
         that.getGeometricInfo = function () {
         	var extents = [];
Index: components/reorderer/js/Reorderer.js
===================================================================
--- components/reorderer/js/Reorderer.js	(revision 10185)
+++ components/reorderer/js/Reorderer.js	(working copy)
@@ -1,6 +1,7 @@
 /*
 Copyright 2007-2009 University of Toronto
 Copyright 2007-2010 University of Cambridge
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -121,9 +122,9 @@
         }
         var thatReorderer = fluid.initView("fluid.reorderer", container, options);
         options = thatReorderer.options;
-        
-        var dropManager = fluid.dropManager();
-        
+                
+        var dropManager = fluid.dropManager();   
+                
         thatReorderer.layoutHandler = fluid.initSubcomponent(thatReorderer,
             "layoutHandler", [thatReorderer.container, options, dropManager, thatReorderer.dom]);
         
@@ -176,7 +177,7 @@
                 var isMovement = keyset.modifier(evt);
                 
                 var dirnum = fluid.keycodeDirection[keydir];
-                var relativeItem = thatReorderer.layoutHandler.getRelativePosition(item, dirnum, !isMovement);
+                var relativeItem = thatReorderer.layoutHandler.getRelativePosition(item, dirnum, !isMovement);  
                 if (!relativeItem) {
                     continue;
                 }
@@ -569,11 +570,11 @@
     fluid.reorderer.WRAP_LOCKED_STRATEGY       = "lockedWrapFrom";
     fluid.reorderer.NO_STRATEGY = null;
     
-    fluid.reorderer.relativeInfoGetter = function (orientation, coStrategy, contraStrategy, dropManager, dom) {
+    fluid.reorderer.relativeInfoGetter = function (orientation, coStrategy, contraStrategy, dropManager, dom, disableWrap) {
         return function (item, direction, forSelection) {
             var dirorient = fluid.directionOrientation(direction);
             var strategy = dirorient === orientation? coStrategy: contraStrategy;
-            return strategy !== null? dropManager[strategy](item, direction, forSelection) : null;
+            return strategy !== null? dropManager[strategy](item, direction, forSelection, disableWrap) : null;
         };
     };
     
@@ -613,7 +614,11 @@
             keysets: "replace",
             "selectors.selectables": "selectors.movables",
             "selectors.dropTargets": "selectors.movables"
-        }
+        },
+        
+        // The user option to enable or disable wrapping of elements within the container
+        disableWrap: false        
+        
     });
 
 
@@ -649,7 +654,7 @@
 
         that.getRelativePosition = 
           fluid.reorderer.relativeInfoGetter(options.orientation, 
-                fluid.reorderer.LOGICAL_STRATEGY, null, dropManager, dom);
+                fluid.reorderer.LOGICAL_STRATEGY, null, dropManager, dom, options.disableWrap);
         
         that.getGeometricInfo = geometricInfoGetter(options.orientation, options.sentinelize, dom);
         
@@ -675,8 +680,8 @@
 
         that.getRelativePosition = 
            fluid.reorderer.relativeInfoGetter(options.orientation, 
-                 fluid.reorderer.LOGICAL_STRATEGY, fluid.reorderer.SHUFFLE_GEOMETRIC_STRATEGY, 
-                 dropManager, dom);
+                 options.disableWrap ? fluid.reorderer.SHUFFLE_GEOMETRIC_STRATEGY : fluid.reorderer.LOGICAL_STRATEGY, fluid.reorderer.SHUFFLE_GEOMETRIC_STRATEGY, 
+                 dropManager, dom, options.disableWrap);
         
         that.getGeometricInfo = geometricInfoGetter(options.orientation, options.sentinelize, dom);
         
Index: demos/reorderer/gridReorderer/js/gridReorderer.js
===================================================================
--- demos/reorderer/gridReorderer/js/gridReorderer.js	(revision 10185)
+++ demos/reorderer/gridReorderer/js/gridReorderer.js	(working copy)
@@ -19,6 +19,7 @@
     return fluid.reorderGrid('.myGrid', {
         selectors: {
             movables: 'p'
-        }
+        },
+        disableWrap: true
     });
 };
Index: demos/reorderer/imageReorderer/js/imageReorderer.js
===================================================================
--- demos/reorderer/imageReorderer/js/imageReorderer.js	(revision 10185)
+++ demos/reorderer/imageReorderer/js/imageReorderer.js	(working copy)
@@ -22,7 +22,8 @@
         var reorderer = fluid.reorderImages(".flc-imageReorderer", {
             selectors: {
                 movables: ".flc-imageReorderer-item"
-            }
+            },
+            disableWrap: true
         });  
     };
 })(jQuery, fluid);
\ No newline at end of file
Index: demos/reorderer/layoutReorderer/js/layoutReorderer.js
===================================================================
--- demos/reorderer/layoutReorderer/js/layoutReorderer.js	(revision 10185)
+++ demos/reorderer/layoutReorderer/js/layoutReorderer.js	(working copy)
@@ -22,7 +22,8 @@
                 modules: "> div > div",
                 lockedModules: ".locked",
                 dropWarning: ".flc-reorderer-dropWarning"
-            }
+            },
+            disableWrap: true
         });
     };
 })(jQuery, fluid);
Index: demos/reorderer/listReorderer/js/listReorderer.js
===================================================================
--- demos/reorderer/listReorderer/js/listReorderer.js	(revision 10185)
+++ demos/reorderer/listReorderer/js/listReorderer.js	(working copy)
@@ -24,14 +24,15 @@
                 movables: ".movable"
             },
             styles: {
-				defaultStyle: "demo-reorderer-movable-default",
-				selected: "demo-reorderer-movable-selected",
-				dragging: "demo-reorderer-movable-dragging",
-				mouseDrag: "demo-reorderer-movable-mousedrag",
-				hover: "demo-reorderer-movable-hover",
-				dropMarker: "demo-reorderer-dropMarker",
-				avatar: "demo-reorderer-avatar"
-            }
+                defaultStyle: "demo-reorderer-movable-default",
+                selected: "demo-reorderer-movable-selected",
+                dragging: "demo-reorderer-movable-dragging",
+                mouseDrag: "demo-reorderer-movable-mousedrag",
+                hover: "demo-reorderer-movable-hover",
+                dropMarker: "demo-reorderer-dropMarker",
+                avatar: "demo-reorderer-avatar"
+            },
+            disableWrap: true
         });
     };
 })(jQuery, fluid);
\ No newline at end of file
Index: tests/component-tests/reorderer/html/GeometricManager-test.html
===================================================================
--- tests/component-tests/reorderer/html/GeometricManager-test.html	(revision 10185)
+++ tests/component-tests/reorderer/html/GeometricManager-test.html	(working copy)
@@ -20,6 +20,7 @@
     <script type="text/javascript" src="../../../test-core/jqUnit/js/jqUnit.js"></script>
 
     <!--  These are tests that have been written using this page as data -->
+    <script type="text/javascript" src="../js/ReordererTestUtils.js"></script>
     <script type="text/javascript" src="../js/GeometricManagerTests.js"></script>
 
   </head>
Index: tests/component-tests/reorderer/js/GeometricManagerTests.js
===================================================================
--- tests/component-tests/reorderer/js/GeometricManagerTests.js	(revision 10185)
+++ tests/component-tests/reorderer/js/GeometricManagerTests.js	(working copy)
@@ -1,5 +1,6 @@
 /*
 Copyright 2008-2009 University of Cambridge
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -8,17 +9,14 @@
 You may obtain a copy of the ECL 2.0 License and BSD License at
 https://source.fluidproject.org/svn/LICENSE.txt
 */
-
-/*global jQuery*/
-/*global fluid*/
-/*global jqUnit*/
+/*global document, expect, jQuery, fluid, jqUnit*/
 
 
 (function ($) {
     $(document).ready(function () {
-    	     
+         
         var GeometricManagerTests = new jqUnit.TestCase("GeometricManagerTests");
-    	
+        
         function assertOrder(message, parentId, required) {
             var all = $("#" + parentId + " div");
             var str = "";
@@ -31,8 +29,6 @@
         }
 
         GeometricManagerTests.test("Original order", function() {
-            var orders = $("#permuteTest .orderable");
-          
             expect(2);
             assertOrder("Original order", "permuteTest",  "0123A4567B8");
             assertOrder("Original order", "permuteTest2", "abCc");
@@ -59,9 +55,8 @@
                 assertOrder(name, "permuteTest", expected1);
                 assertOrder(name, "permuteTest2", expected2);
             });            
-        }
-        
-
+        }        
+       
         // Original order:                                                   "0123A4567B8"
         selfPermuteTest("REPLACE right rend",  2, 8, fluid.position.REPLACE, "0134A5678B2");
         selfPermuteTest("REPLACE right",       2, 6, fluid.position.REPLACE, "0134A5627B8");
@@ -135,40 +130,14 @@
           
         });
         
-      GeometricManagerTests.test("projectFrom", function() {
-          // column 1, 3x3 squares spaced by 1, middle skew 1 to the right
-          var rects = [
-              {left: 1, top: 1, right: 4, bottom: 4},
-              {left: 2, top: 5, right: 5, bottom: 8},
-              {left: 1, top: 9, right: 4, bottom: 12},
-          // column 2, same dimensions but offset down by 1
-              {left: 6, top: 2, right: 9, bottom: 5},
-              {left: 6, top: 6, right: 9, bottom: 9}];
-          
-          var elems = fluid.transform(rects, function(rect, i) {
-             return {rect: rect, index: i}
-          });
-          
-          function assertProject(name, fromIndex, direction, toIndex, wrapped) {
-              var proj = fluid.geom.projectFrom(rects[fromIndex], fluid.direction[direction], elems);
-              jqUnit.assertEquals(name + " index", toIndex, proj.cacheelem.index);
-              jqUnit.assertEquals(name + " wrapped", wrapped, proj.wrapped);
-          }
+      GeometricManagerTests.test("projectFrom", function() {          
           expect(24);  
-          assertProject("Right0", 0, "RIGHT", 3, false);
-          assertProject("Left3",  3, "LEFT",  0, false);
-          assertProject("Right3", 3, "RIGHT", 0, true);
-          assertProject("Left0",  0, "LEFT",  3, true);
-          assertProject("Down0",  0, "DOWN",  1, false);
-          assertProject("Up1",    1, "UP",    0, false);
-          
-          assertProject("Up0",    0, "UP",    2, true);
-          assertProject("Down2",  2, "DOWN",  0, true);
-          assertProject("Right2", 2, "RIGHT", 4, false);
-          assertProject("Left4",  4, "LEFT",  1, false);
-          assertProject("Left1",  1, "LEFT",  4, true);
-          assertProject("Right4", 4, "RIGHT", 1, true);
-          
+          fluid.testUtils.reorderer.stepProjectFrom(false);
+      });
+            
+      GeometricManagerTests.test("projectFrom with disabled wrap", function() {          
+          expect(24);  
+          fluid.testUtils.reorderer.stepProjectFrom(true);
       });
     });
 })(jQuery);
Index: tests/component-tests/reorderer/js/LayoutReordererTests.js
===================================================================
--- tests/component-tests/reorderer/js/LayoutReordererTests.js	(revision 10185)
+++ tests/component-tests/reorderer/js/LayoutReordererTests.js	(working copy)
@@ -1,6 +1,7 @@
 /*
 Copyright 2008-2009 University of Cambridge
 Copyright 2008-2009 University of Toronto
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -10,10 +11,7 @@
 https://source.fluidproject.org/svn/LICENSE.txt
 */
 
-/*global jQuery*/
-/*global fluid*/
-/*global demo*/
-/*global jqUnit*/
+/*global document, jQuery, fluid, demo, jqUnit*/
 
 (function ($) {
     $(document).ready(function () {
@@ -23,8 +21,8 @@
         
         layoutReordererTests.test("Default selectors", function () {
             var testReorderer = fluid.reorderLayout("#default-selector-test");
-            var item1 = jQuery("#portlet-1");
-            var item2 = jQuery("#portlet-2").focus();
+            var item1 = $("#portlet-1");
+            var item2 = $("#portlet-2").focus();
             
             // Sniff test the reorderer that was created - keyboard selection
             jqUnit.assertTrue("focus on item2", item2.hasClass("fl-reorderer-movable-selected"));
@@ -106,27 +104,34 @@
             reorderer.handleKeyUp(fluid.testUtils.keyEvent("CTRL", portlet8));
             jqUnit.notVisible("After ctrl is released, drop warning should not be visible", "#drop-warning"); 
     
-        });
-    
+        });   
     
-    
-        function expectOrder(message, order) {
-           var items = fluid.transform(jQuery(".portlet"), fluid.getId);
-           var expected = fluid.transform(order, function(item) {return fluid.testUtils.moduleLayout.portletIds[item];});
-           jqUnit.assertDeepEq(message, expected, items);
-        }
-      
+       function expectOrder(message, order) {
+                var items = fluid.transform($(".portlet"), fluid.getId);
+                var expected = fluid.transform(order, function(item) {return fluid.testUtils.moduleLayout.portletIds[item];});
+                jqUnit.assertDeepEq(message, expected, items);
+       }
+             
         var tests = new jqUnit.TestCase("Reorder Layout Tests");
-    
-        tests.test("reorderLayout API", function () {
-          
-            var options = {
+        
+        var assembleOptions = function (isDisableWrap,isLocked) {
+            var obj = {
                 selectors: {
                     columns: "[id^='c']",
-                    modules: ".portlet"
-                }
+                    modules: ".portlet",
+                    lockedModules: isLocked
+                },
+                disableWrap: isDisableWrap,
+                reordererFn: "fluid.reorderLayout",
+                expectOrderFn: expectOrder,
+                key: fluid.testUtils.reorderer.compositeKey                       
             };
             
+            return obj;
+        };       
+        
+        tests.test("reorderLayout API", function () {
+            var options = assembleOptions();
             var lastLayoutModel = null;
             
             var layoutReorderer = fluid.reorderLayout(".reorderer_container", options);
@@ -134,14 +139,13 @@
             // Test for FLUID-3121
             var afterMoveListener = function() {
                 lastLayoutModel = layoutReorderer.layoutHandler.getModel();
-                }
+                };
             layoutReorderer.events.afterMove.addListener(afterMoveListener);
             
             var item2 = fluid.jById(fluid.testUtils.moduleLayout.portletIds[2]).focus();
             var item3 = fluid.jById(fluid.testUtils.moduleLayout.portletIds[3]);
             
-            // Sniff test the reorderer that was created - keyboard selection and movement
-    
+            // Sniff test the reorderer that was created - keyboard selection and movement    
             jqUnit.assertTrue("focus on item2", item2.hasClass("fl-reorderer-movable-selected"));
             jqUnit.assertTrue("focus on item2 - item3 should be default", item3.hasClass("fl-reorderer-movable-default"));
             jqUnit.assertEquals("No move callback", null, lastLayoutModel);
@@ -159,18 +163,18 @@
                 [1, 2, 4, 3, 5, 6, 7, 8, 9]);
         });
     
-        tests.test("reorderLayout with optional styles", function () {
+        tests.test("reorderLayout with optional styles", function () {       
             var options = {
-                selectors: {
-                    columns: "[id^='c']",
-                    modules: ".portlet"            
-                },
-                styles: {
-                    defaultStyle: "myDefault",
-                    selected: "mySelected"
-                }
-            };
-    
+                    selectors: {
+                        columns: "[id^='c']",
+                        modules: ".portlet" 
+                    },
+                    styles: {
+                        defaultStyle: "myDefault",
+                        selected: "mySelected"
+                    }
+                };
+                
             var layoutReorderer = fluid.reorderLayout(".reorderer_container", options);
             
             jqUnit.assertEquals("default class is myDefault", "myDefault", layoutReorderer.options.styles.defaultStyle);
@@ -181,14 +185,7 @@
         });
         
         tests.test("reorderLayout with locked portlets", function () {
-            var options = {
-                selectors: {
-                    columns: "[id^='c']",
-                    modules: ".portlet",
-                    lockedModules: ".locked"
-                }
-            };
-
+            var options = assembleOptions(false,".locked");
             var layoutReorderer = fluid.reorderLayout(".reorderer_container", options);
             var item2 = fluid.jById(fluid.testUtils.moduleLayout.portletIds[2]).focus();
             var item3 = fluid.jById(fluid.testUtils.moduleLayout.portletIds[3]);
@@ -217,8 +214,67 @@
             jqUnit.assertTrue("Moved to new column", 
                 fluid.dom.isContainer($("#c5")[0], item3[0]));
                    
+        });        
+       
+        tests.test("reorderLayout, option set disabled wrap, user action ctrl+up", function () {              
+            var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "UP",
+                expectedOrderArrays: [[1, 2, 3, 4, 5, 6, 7, 8, 9]],
+                itemSelector: fluid.jById(fluid.testUtils.moduleLayout.portletIds[1])
+            };
+       
+            fluid.testUtils.reorderer.stepReorderer(".reorderer_container", options);  
+                                    
+        });        
+     
+        tests.test("reorderLayout, option set disabled wrap, user action ctrl+down", function () {  
+             var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "DOWN",
+                expectedOrderArrays: [[1, 2, 3, 4, 5, 6, 7, 8, 9]],
+                itemSelector: fluid.jById(fluid.testUtils.moduleLayout.portletIds[9])
+            };
+       
+            fluid.testUtils.reorderer.stepReorderer(".reorderer_container", options);                      
         });
-    
+        
+        tests.test("reorderLayout with locked portlets, option set disabled wrap, user action ctrl+up", function () {
+            var options = {
+                reordererOptions: assembleOptions(true, ".locked"),
+                direction: "UP",
+                expectedOrderArrays: [[1, 2, 4, 3, 5, 6, 7, 8, 9],[1, 2, 4, 3, 5, 6, 7, 8, 9]],
+                itemSelector: fluid.jById(fluid.testUtils.moduleLayout.portletIds[4])
+            };
+       
+            fluid.testUtils.reorderer.stepReorderer(".reorderer_container", options); 
+            
+            jqUnit.assertValue("gives warning message when trying to move item4 up ", $(".flc-reorderer-dropWarning"));                   
+        });       
+       
+        tests.test("reorderLayout with locked portlets, option set disabled wrap, user action ctrl+right", function () {
+            var options = {
+                reordererOptions: assembleOptions(true, ".locked"),
+                direction: "RIGHT",
+                expectedOrderArrays: [[1, 2, 4, 5, 6, 3, 7, 8, 9], [1, 2, 4, 5, 6, 7, 8, 3, 9], 
+                                      [1, 2, 4, 5, 6, 7, 8, 9, 3], [1, 2, 4, 5, 6, 7, 8, 9, 3]],
+                itemSelector: fluid.jById(fluid.testUtils.moduleLayout.portletIds[3])
+            };
+       
+            fluid.testUtils.reorderer.stepReorderer(".reorderer_container", options); 
+        });        
+        
+        tests.test("reorderLayout with locked portlets, option set disabled wrap, user action ctrl+left", function () { 
+            var options = {
+                reordererOptions: assembleOptions(true, ".locked"),
+                direction: "LEFT",
+                expectedOrderArrays: [[1, 2, 3, 4, 5, 6, 9, 7, 8], [1, 2, 3, 9, 4, 5, 6, 7, 8], 
+                                      [1, 2, 3, 9, 4, 5, 6, 7, 8]],
+                itemSelector: fluid.jById(fluid.testUtils.moduleLayout.portletIds[9])                             
+            };
+       
+            fluid.testUtils.reorderer.stepReorderer(".reorderer_container", options);                       
+        });    
     
     });
 })(jQuery);
Index: tests/component-tests/reorderer/js/ReorderGridTests.js
===================================================================
--- tests/component-tests/reorderer/js/ReorderGridTests.js	(revision 10185)
+++ tests/component-tests/reorderer/js/ReorderGridTests.js	(working copy)
@@ -1,6 +1,7 @@
 /*
 Copyright 2008-2009 University of Cambridge
 Copyright 2008-2009 University of Toronto
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -9,25 +10,36 @@
 You may obtain a copy of the ECL 2.0 License and BSD License at
 https://source.fluidproject.org/svn/LICENSE.txt
 */
+/*global document, jqUnit, fluid, orderableIds, lightboxRootId, jQuery*/
 
 (function($) {
     $(document).ready(function() {
         var tests = new jqUnit.TestCase("Reorder Grid Tests");
         
         var k = fluid.testUtils.reorderer.bindReorderer(orderableIds);
-    
-        tests.test("reorderGrid API", function() {
-            var options = {
+        
+        var assembleOptions = function (isDisableWrap) {
+            var obj = {
                 selectors: {
                     movables: ".float"
-                }
-            };
+                },
+                disableWrap: isDisableWrap,
+                reordererFn: "fluid.reorderGrid",
+                expectOrderFn: fluid.testUtils.reorderer.assertItemsInOrder,
+                key: fluid.testUtils.reorderer.bindReorderer(orderableIds).compositeKey,
+                thumbArray: "img",
+                prefix: "fluid.img."
+            };            
+            return obj;
+        };    
+        
+        tests.test("reorderGrid API", function() {            
+            var options = assembleOptions(false);
             var containerSelector = "[id='" + lightboxRootId + "']";
             var gridReorderer = fluid.reorderGrid(containerSelector, options);
             var item2 = fluid.jById(orderableIds[1]).focus();
             var item3 = fluid.jById(orderableIds[2]);
             var item5 = fluid.jById(orderableIds[4]);
-            var ctrlDownArrow = fluid.testUtils.ctrlKeyEvent("DOWN");
             
             // Sniff test the reorderer that was created - keyboard selection and movement
     
@@ -43,10 +55,11 @@
             k.compositeKey(gridReorderer, fluid.testUtils.ctrlKeyEvent("DOWN"), 4);
             
             fluid.testUtils.reorderer.assertItemsInOrder("after ctrl-down", [0, 1, 2, 3, 5, 6, 7, 4, 8, 9, 10, 11, 12, 13], 
-                jQuery("img", jQuery(containerSelector)), "fluid.img.");
+                $("img", $(containerSelector)), "fluid.img.");
         
             });
     
+        
         tests.test("reorderGrid with optional styles", function() {
             var options = {
                 selectors: {
@@ -66,6 +79,112 @@
             jqUnit.assertEquals("dragging class is fl-reorderer-movable-dragging", "fl-reorderer-movable-dragging", gridReorderer.options.styles.dragging);
             jqUnit.assertEquals("mouseDrag class is fl-reorderer-movable-dragging", "fl-reorderer-movable-dragging", gridReorderer.options.styles.mouseDrag);
             
-        });    
+        });  
+        
+        tests.test("reorderGrid, option set disabled wrap, user action ctrl+down", function() {        
+            var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "DOWN",
+                expectedOrderArrays: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 9, 13], 
+                                      [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 9, 13]], 
+                itemSelector: fluid.jById(orderableIds[9]),      
+                itemIndex: 9
+            };
+          
+            fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });
+        
+        tests.test("reorderGrid, option set enabled wrap, user action ctrl+down", function() {   
+            var options = {
+                reordererOptions: assembleOptions(false),
+                direction: "DOWN",
+                expectedOrderArrays: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 9, 13],
+                                      [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13]], 
+                itemSelector: fluid.jById(orderableIds[9]),
+                itemIndex: 9
+            };
+             
+             fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });
+      
+        tests.test("reorderGrid, option set disabled wrap, user action ctrl+up", function() {   
+            var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "UP",
+                expectedOrderArrays: [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
+                                      [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]], 
+                itemSelector: fluid.jById(orderableIds[1]),
+                itemIndex: 1
+            };
+            
+            fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });
+        
+        tests.test("reorderGrid, option set enabled wrap, user action ctrl+up", function() {   
+            var options = {
+                reordererOptions: assembleOptions(false),
+                direction: "UP",
+                expectedOrderArrays: [[0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1],
+                                      [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 11, 12, 13],
+                                      [0, 2, 3, 4, 5, 6, 7, 1, 8, 9, 10, 11, 12, 13]], 
+                itemSelector: fluid.jById(orderableIds[1]),
+                itemIndex: 1
+            };
+             
+             fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });
+           
+        tests.test("reorderGrid, option set disabled wrap, user action ctrl+right", function() {    
+            var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "RIGHT",
+                expectedOrderArrays: [[0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
+                                      [0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]], 
+                itemSelector: fluid.jById(orderableIds[1]),
+                itemIndex: 1
+            };
+            
+            fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });
+        
+        tests.test("reorderGrid, option set enabled wrap, user action ctrl+right", function() { 
+            var options = {
+                reordererOptions: assembleOptions(false),
+                direction: "RIGHT",
+                expectedOrderArrays: [[0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
+                                      [0, 2, 3, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]], 
+                itemSelector: fluid.jById(orderableIds[1]),
+                itemIndex: 1
+            };
+         
+            fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });        
+        
+        tests.test("reorderGrid, option set disabled wrap, user action ctrl+left", function() { 
+            var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "LEFT",
+                expectedOrderArrays: [[1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
+                                      [1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]], 
+                itemSelector: fluid.jById(orderableIds[1]),
+                itemIndex: 1       
+            };
+           
+             fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });        
+      
+        tests.test("reorderGrid, option set enabled wrap, user action ctrl+left", function() {
+            var options = {
+                reordererOptions: assembleOptions(false),
+                direction: "LEFT",
+                expectedOrderArrays: [[1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
+                                      [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1]], 
+                itemSelector: fluid.jById(orderableIds[1]),
+                itemIndex: 1
+            };
+             
+            fluid.testUtils.reorderer.stepReorderer("[id='" + lightboxRootId + "']", options);
+        });
+        
     });
 })(jQuery);
Index: tests/component-tests/reorderer/js/ReorderListTests.js
===================================================================
--- tests/component-tests/reorderer/js/ReorderListTests.js	(revision 10185)
+++ tests/component-tests/reorderer/js/ReorderListTests.js	(working copy)
@@ -1,6 +1,7 @@
 /*
 Copyright 2008-2009 University of Cambridge
 Copyright 2008-2009 University of Toronto
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -9,6 +10,7 @@
 You may obtain a copy of the ECL 2.0 License and BSD License at
 https://source.fluidproject.org/svn/LICENSE.txt
 */
+/*global document, jqUnit, setUp, fluid, itemIds, callbackConfirmer, afterMoveCallbackWasCalled, itemIds2, jQuery*/
 
 (function($) {
     $(document).ready(function() {
@@ -16,23 +18,34 @@
     
         function assertItemsInOrder(message, expectOrder) {
             return fluid.testUtils.reorderer.assertItemsInOrder(message, expectOrder, 
-               jQuery("li", jQuery("#list1")), "list1item");
-        }
+               $("li", $("#list1")), "list1item");
+        }        
         
         var k = fluid.testUtils.reorderer.bindReorderer(itemIds);
         
-        tests.test("reorderList API", function() {
-            var options = {
+        var assembleOptions = function (isDisableWrap) {
+            var obj = {
                 selectors: {
                     movables: "li"
                 },
                 listeners: {
                     afterMove: callbackConfirmer
-                }
-            };
+                },
+                disableWrap: isDisableWrap,
+                reordererFn: "fluid.reorderList",
+                expectOrderFn: fluid.testUtils.reorderer.assertItemsInOrder,
+                key: fluid.testUtils.reorderer.bindReorderer(itemIds).compositeKey,
+                thumbArray: "li",
+                prefix: "list1item"
+            };            
+            return obj;
+        };
+        
+        tests.test("reorderList API", function() {
+            var options = assembleOptions(false); 
             var listReorderer = fluid.reorderList("#list1", options);
-            var item2 = jQuery("#list1item2").focus();
-            var item3 = jQuery("#list1item3");
+            var item2 = $("#list1item2").focus();
+            var item3 = $("#list1item3");
             
             // Sniff test the reorderer that was created - keyboard selection and movement
     
@@ -76,11 +89,10 @@
             
         });    
     
-       function assertItemsInOrder2(message, expectOrder) {
+        function assertItemsInOrder2(message, expectOrder) {
             return fluid.testUtils.reorderer.assertItemsInOrder(message, expectOrder, 
-               jQuery("li", jQuery("#list2")), "list2item");
-        }
-    
+               $("li", $("#list2")), "list2item");
+        }    
     
         var k2 = fluid.testUtils.reorderer.bindReorderer(itemIds2);
     
@@ -98,11 +110,10 @@
     
             var listReorderer = fluid.reorderList("#list2", options);
             
-            var item1 = jQuery("#list2item1").focus();
-            var item2 = jQuery("#list2item2");
-            var item3 = jQuery("#list2item3");
-            var item4 = jQuery("#list2item4");
-    
+            var item1 = $("#list2item1").focus();
+            var item2 = $("#list2item2");
+            var item3 = $("#list2item3");
+                
             jqUnit.assertTrue("focus on item1", item1.hasClass("fl-reorderer-movable-selected"));
 
             jqUnit.assertTrue("focus on item1 - item2 should be default", item2.hasClass("fl-reorderer-movable-default"));
@@ -129,5 +140,30 @@
             jqUnit.assertTrue("after ctrl-down on movable, order should change", afterMoveCallbackWasCalled);
     
         });
+        
+        tests.test("reorderList, option set disabled wrap, user action ctrl+down", function() {
+            var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "DOWN",
+                expectedOrderArrays: [[1, 2, 3, 5, 4], [1, 2, 3, 5, 4]],
+                itemSelector: $("#list1item4"),
+                itemIndex: 3
+            };
+        
+            fluid.testUtils.reorderer.stepReorderer("#list1", options);
+        });
+
+        tests.test("reorderList, option set disabled wrap, user action ctrl+up", function() {
+            var options = {
+                reordererOptions: assembleOptions(true),
+                direction: "UP",
+                expectedOrderArrays: [[2, 1, 3, 4, 5],[2, 1, 3, 4, 5]],
+                itemSelector: $("#list1item2"),
+                itemIndex: 1
+            };
+       
+            fluid.testUtils.reorderer.stepReorderer("#list1", options);
+        });        
+        
     });
 })(jQuery);
Index: tests/component-tests/reorderer/js/ReordererTestUtils.js
===================================================================
--- tests/component-tests/reorderer/js/ReordererTestUtils.js	(revision 10185)
+++ tests/component-tests/reorderer/js/ReordererTestUtils.js	(working copy)
@@ -1,5 +1,6 @@
 /*
 Copyright 2008-2009 University of Cambridge
+Copyright 2010 OCAD University
 
 Licensed under the Educational Community License (ECL), Version 2.0 or the New
 BSD license. You may not use this file except in compliance with one these
@@ -9,7 +10,7 @@
 https://source.fluidproject.org/svn/LICENSE.txt
 */
 
-/*global jQuery, jqUnit*/
+/*global jQuery, jqUnit, orderableIds, defaultClass, selectedClass, draggingClass*/
 
 var fluid_1_2 = fluid_1_2 || {};
 var fluid = fluid || fluid_1_2;
@@ -103,6 +104,61 @@
                    fluid.byId(ids[targetIndex]));
             }
         };
+    };   
+    
+    // GeometricManagerTest
+    fluid.testUtils.reorderer.stepProjectFrom = function (disabledWrap) {
+        // column 1, 3x3 squares spaced by 1, middle skew 1 to the right
+        var rects = [
+            {left: 1, top: 1, right: 4, bottom: 4},
+            {left: 2, top: 5, right: 5, bottom: 8},
+            {left: 1, top: 9, right: 4, bottom: 12},
+        // column 2, same dimensions but offset down by 1
+            {left: 6, top: 2, right: 9, bottom: 5},
+            {left: 6, top: 6, right: 9, bottom: 9}];
+        
+        var elems = fluid.transform(rects, function(rect, i) {
+           return {rect: rect, index: i};
+        });
+                 
+        function assertProject(name, fromIndex, direction, toIndex, couldWrap) {
+            var proj = fluid.geom.projectFrom(rects[fromIndex], fluid.direction[direction], elems, false, disabledWrap);
+            if(couldWrap && disabledWrap) {
+                jqUnit.assertUndefined(name + " index " + toIndex, proj.cacheelem);
+                jqUnit.assertFalse("no wrapping from index:" + fromIndex + " to index:" + toIndex + " wrapped set to " + couldWrap, proj.wrapped);
+            } else {
+                jqUnit.assertEquals(name + " index", toIndex, proj.cacheelem.index);
+                jqUnit.assertEquals(name + " wrapped", couldWrap, proj.wrapped);
+            }
+        }
+        
+        assertProject("Right0", 0, "RIGHT", 3, false, disabledWrap);
+        assertProject("Left3",  3, "LEFT",  0, false, disabledWrap);
+        assertProject("Right3", 3, "RIGHT", 0, true, disabledWrap);
+        assertProject("Left0",  0, "LEFT",  3, true, disabledWrap);
+        assertProject("Down0",  0, "DOWN",  1, false, disabledWrap);
+        assertProject("Up1",    1, "UP",    0, false, disabledWrap);
+        
+        assertProject("Up0",    0, "UP",    2, true, disabledWrap);
+        assertProject("Down2",  2, "DOWN",  0, true, disabledWrap);
+        assertProject("Right2", 2, "RIGHT", 4, false, disabledWrap);
+        assertProject("Left4",  4, "LEFT",  1, false, disabledWrap);
+        assertProject("Left1",  1, "LEFT",  4, true, disabledWrap);
+        assertProject("Right4", 4, "RIGHT", 1, true, disabledWrap);            
+             
     };
+    
+    // stepReorderTests
+    fluid.testUtils.reorderer.stepReorderer = function (container, options) {    
+        var that = fluid.invokeGlobalFunction(options.reordererOptions.reordererFn, [container, options.reordererOptions]);
+        for (var i = 0; i < options.expectedOrderArrays.length; i++) { 
+            var focusItem = $(options.itemSelector).focus();
+            var expectedOrder = options.expectedOrderArrays[i];
+            jqUnit.assertTrue("focus on item " + focusItem.selector, focusItem.hasClass("fl-reorderer-movable-selected"));   
+            options.reordererOptions.key(that, fluid.testUtils.ctrlKeyEvent(options.direction), options.itemIndex?options.itemIndex:options.itemSelector);                
+            options.reordererOptions.expectOrderFn("after ctrl-" + options.direction.toLowerCase() + " the order is " + expectedOrder, expectedOrder, 
+                    $(options.reordererOptions.thumbArray, that.container), options.reordererOptions.prefix);           
+        }
+    };   
   
 })(jQuery, fluid_1_2);
\ No newline at end of file

