0

我有一个这样的排序集合:

 var sortedCollection = [
     {id: 3,x: 1,y: 1},
     {id: 2,x: 1,y: 2},
     {id: 1,x: 2,y: 1},
     {id: 9,x: 2,y: 2},
     {id: 5,x: 2,y: 3},
     {id: 8,x: 2,y: 4},
     {id: 7,x: 3,y: 1},
     {id: 6,x: 3,y: 2},
     {id: 4,x: 4,y: 1}
 ];

集合首先按 x 排序,然后按 y 作为第二个排序值。

我的集合中的 x 和 y 值代表一个矩阵视图。使用示例模型,它看起来像这样:

[][][][]
[][][]
  []
  []

类似的结构reveal.js 演示文稿使用,如果这更容易理解的话。

可以拖放元素([] 表示一个元素)。如果我将一个元素放到另一个元素上,我会显示一个指示器,拖动元素的放置位置(上方、下方、之前、之后)。需要集合中的数据来处理元素(缩略图)并将其发送回服务器

移动一个项目的功能应该遵循这个逻辑:我选择一个项目,例如{x: 2,y: 2},我想在集合中移动它。第二项是放置此元素的参考,例如{x: 3, y: 2}。应该可以将元素放置在该元素的上方、下方、之前和之后。

这意味着对于我的两个示例值{x: 2,y: 2}{x: 3, y: 2}引用位置 + 以下信息:

  • “以上”表示{x: 2,y: 2}变为{x: 3, y: 2},之后的所有值以及{x: 3, y: 2}具有相同 x 值的重复值迭代 1
  • “低于”表示{x: 2,y: 2}变为{x: 3, y: 3},之后所有具有相同 x 值的值迭代 1

之前和之后操作仅适用于具有 y: 1 的值(示例 {x: 2,y: 2}{x: 3, y: 1}

  • “之前”是指{x: 2,y: 2}变为{x: 3, y: 1}{x: 3, y: 1}变为{x: 4, y: 1}和所有其他 x 值为 3 的对象变为 4 所有元素的 x 值被迭代 1
  • “之后”表示{x: 2,y: 2}变为{x: 4, y: 1}并且{x: 3, y: 1}保持不变,但所有 x 值大于 4 的元素必须迭代 1

我希望我在描述我需要什么时没有犯错。我无法管理它来处理填补空白或处理重复以修复集合中的数字系列的所有情况。任何有关用 JavaScript 编程或简化此逻辑的提示都会有所帮助。

我创建了一个显示主要思想的 JSFiddle,并在我卡住的位置添加了待办事项评论:http: //jsfiddle.net/FrontEnds/69PXk/8/

4

1 回答 1

0

得到了一个似乎有效的解决方案:

var sortedCollection = [
     {id: 3,x: 1,y: 1},
     {id: 2,x: 1,y: 2},
     {id: 1,x: 2,y: 1},
     {id: 9,x: 2,y: 2},
     {id: 5,x: 2,y: 3},
     {id: 8,x: 2,y: 4},
     {id: 7,x: 3,y: 1},
     {id: 6,x: 3,y: 2},
     {id: 4,x: 4,y: 1}
 ];

// example case
var  movedItemIndex = 3 // change this value to which item you want to move
    ,movedItem = sortedCollection[movedItemIndex]
    ,movedItemId = movedItem.id
    ,referenceItemIndex = 6 // change this value to which item reference where you want to move your item
    ,referenceItem = sortedCollection[referenceItemIndex]
    ,referenceItemId = referenceItem.id
    ,relativePlacing = "above"; // second reference indicator one of (above, below, before, after)

sortedCollection = moveSortedCollectionItem( sortedCollection, movedItemIndex, referenceItem.x, referenceItem.y, relativePlacing );
sortedCollection = fixSortCollectionsNumericalXAndYSequence( sortedCollection, movedItemId, referenceItemId );
console.dir( sortedCollection );

function moveSortedCollectionItem( sortedCollection, itemIndex, refPosX, refPosY, relativePlace )
{    
    switch( true )
    {
        case( relativePlace == "above" || relativePlace == "before" ):
            {
                sortedCollection[itemIndex].x = refPosX
                sortedCollection[itemIndex].y = refPosY
                break;
            }

        case( relativePlace == "below" ):
            {
                sortedCollection[itemIndex].x = refPosX
                sortedCollection[itemIndex].y = refPosY + 1
                break;
            }           

        case( relativePlace == "after" ):
            {
                sortedCollection[itemIndex].x = refPosX + 1
                sortedCollection[itemIndex].y = refPosY
                break;
            }
    }

    return sortedCollection;
}

function fixSortCollectionsNumericalXAndYSequence( sortedCollection, movedItemId, referenceItemId )
{    
    // make sure we have the right sort order
    sortedCollection.sort( sortByXAndY );

    // return sortedCollection;

    for( var i = 0, len = sortedCollection.length; i < len; i++ )
    {
        if( i == 0 && (sortedCollection[i].x != 1 || sortedCollection[i].y != 1) )
        {
            // first one must have x: 1 and y; 1 in order to make the whole thing work
            sortedCollection[i].x = 1;
            sortedCollection[i].y = 1;
        }
        else if( typeof sortedCollection[i-1] != 'undefined' /* has previous item */ )
        {
            sortedCollection[i] = _replaceXAndYFromItemWithPreviousItem( sortedCollection[i-1], sortedCollection[i] );
        }
    }

    return sortedCollection;
}

function _replaceXAndYFromItemWithPreviousItem( previousItem, currentItem )
{    
    // case: previous item x and current item x are the same
    if( currentItem.x == previousItem.x )
    {
        // set current item y = previous item y + 1
        currentItem.y = previousItem.y + 1;
    }  
    // case: current item x is not previous item x and not previous item x + 1
    else if( currentItem.x != previousItem.x && currentItem.x != previousItem.x + 1 )
    {
        // set current item x = previous item x + 1; set current item y = 1
        currentItem.x = previousItem.x + 1;                
        currentItem.y = 1;
    }

    return currentItem;
}

function sortByXAndY( model1, model2 )
{
    var  a = parseInt( model1.x )
        ,b = parseInt( model2.x )

    if( a == b )
    {
        var  c = parseInt( model1.y )
            ,d = parseInt( model2.y );

        return c - d;
    }

    return a - b;
}

http://jsfiddle.net/69PXk/17/

于 2013-10-10T13:01:14.417 回答