function getTargetGrid(item, rootGrid, threshold) {
      var target = null;
      var dragSort = rootGrid._settings.dragSort;
      var bestScore = -1;
      var gridScore;
      var grids;
      var grid;
      var container;
      var containerRect;
      var left;
      var top;
      var right;
      var bottom;
      var i;

      // Get potential target grids.
      if (dragSort === true) {
        gridsArray[0] = rootGrid;
        grids = gridsArray;
      } else if (isFunction(dragSort)) {
        grids = dragSort.call(rootGrid, item);
      }

      // Return immediately if there are no grids.
      if (!grids || !Array.isArray(grids) || !grids.length) {
        return target;
      }

      // Loop through the grids and get the best match.
      for (i = 0; i < grids.length; i++) {
        grid = grids[i];

        // Filter out all destroyed grids.
        if (grid._isDestroyed) continue;

        // Compute the grid's client rect an clamp the initial boundaries to
        // viewport dimensions.
        grid._updateBoundingRect();
        left = Math.max(0, grid._left);
        top = Math.max(0, grid._top);
        right = Math.min(window.innerWidth, grid._right);
        bottom = Math.min(window.innerHeight, grid._bottom);

        // The grid might be inside one or more elements that clip it's visibility
        // (e.g overflow scroll/hidden) so we want to find out the visible portion
        // of the grid in the viewport and use that in our calculations.
        container = grid._element.parentNode;
        while (
          container &&
          container !== document &&
          container !== document.documentElement &&
          container !== document.body
        ) {
          if (container.getRootNode && container instanceof DocumentFragment) {
            container = container.getRootNode().host;
            continue;
          }

          if (getStyle(container, 'overflow') !== 'visible') {
            containerRect = container.getBoundingClientRect();
            left = Math.max(left, containerRect.left);
            top = Math.max(top, containerRect.top);
            right = Math.min(right, containerRect.right);
            bottom = Math.min(bottom, containerRect.bottom);
          }

          if (getStyle(container, 'position') === 'fixed') {
            break;
          }

          container = container.parentNode;
        }

        // No need to go further if target rect does not have visible area.
        if (left >= right || top >= bottom) continue;

        // Check how much dragged element overlaps the container element.
        targetRect.left = left;
        targetRect.top = top;
        targetRect.width = right - left;
        targetRect.height = bottom - top;
        gridScore = getIntersectionScore(itemRect, targetRect);

        // Check if this grid is the best match so far.
        if (gridScore > threshold && gridScore > bestScore) {
          bestScore = gridScore;
          target = grid;
        }
      }

      // Always reset grids array.
      gridsArray.length = 0;

      return target;
    }
Default drag sort predicate.

@public
@static
@param {Item} item
@param {Object} [options]
@param {Number} [options.threshold=50]
@param {String} [options.action='move']
@returns {?Object}
  - Returns `null` if no valid index was found. Otherwise returns drag sort
    command.