zwilias / elm-reorderable / Reorderable

Reorderable is useful for structures where you want to allow a user to reorder things, while still wanting to make effective use of Html.Keyed. The idea is to have a datastructure that (internally) keeps the association between some an incremental key and data (like an Array), but retains that association while shuffling data around.

Basics


type Reorderable a

empty : Reorderable a

Does what one would expect it to do: create an empty Reorderable. Note that checking equality against empty is not a good way to check if there are 0 values. Pushing and subsequently dropping entries will increment the internal key.

toList empty
--> []

fromList []
--> empty

isEmpty : Reorderable a -> Basics.Bool

Checks if a reorderable contains zero entries.

isEmpty empty
--> True


singleton "hi"
    |> isEmpty
--> False


fromList [ "hello", "world" ]
    |> drop 0
    |> drop 0
    |> isEmpty
--> True

fromList [ "hello", "world" ]
    |> drop 0
    |> drop 0
    |> (==) empty
--> False

length : Reorderable a -> Basics.Int

Determine the length of a Reorderable.

empty
    |> length
--> 0

singleton "hi"
    |> length
--> 1

fromList [ "hello", "world" ]
    |> length
--> 2

singleton : a -> Reorderable a

Create a reorderable from a single piece of data.

singleton "hi"
    |> toList
--> [ "hi" ]

push : a -> Reorderable a -> Reorderable a

Pushes a piece of data onto the end of a Reorderable.

empty
    |> push "hello"
    |> push "world"
    |> toList
--> [ "hello", "world" ]

get : Basics.Int -> Reorderable a -> Maybe a

Try to get the item at a specified index.

fromList [ "a", "b", "c" ]
    |> get 1
--> Just "b"

set : Basics.Int -> a -> Reorderable a -> Reorderable a

Set the value at a specified index (maintaining the key). Basically shorthand for update index (always val) reorderable.

If the specified index does not exist, this does nothing.

update : Basics.Int -> (a -> a) -> Reorderable a -> Reorderable a

Run an update-function on a specified item.

fromList [ "UPPER", "lower", "UPPER"]
    |> update 1 String.toUpper
    |> toKeyedList
--> [ ( "0", "UPPER" )
--> , ( "1", "LOWER" )
--> , ( "2", "UPPER" )
--> ]

Manipulation

swap : Basics.Int -> Basics.Int -> Reorderable a -> Reorderable a

Swaps two entries, unless either of the indices is out of bounds.

fromList [ "a", "d", "c", "b" ]
    |> swap 1 3
    |> toKeyedList
--> [ ( "0", "a" )
--> , ( "3", "b" )
--> , ( "2", "c" )
--> , ( "1", "d" )
--> ]


fromList [ "hi", "there" ]
    |> swap 0 2
    |> toList
--> [ "hi", "there" ]

moveUp : Basics.Int -> Reorderable a -> Reorderable a

Convenience function to move an item "up", i.e. "back".

fromList [ "a", "c", "b" ]
    |> moveUp 2
    |> toKeyedList
--> [ ( "0", "a" )
--> , ( "2", "b" )
--> , ( "1", "c" )
--> ]

moveDown : Basics.Int -> Reorderable a -> Reorderable a

Convenience function to move an item "down", i.e. "forward".

fromList [ "a", "c", "b" ]
    |> moveDown 1
    |> toKeyedList
--> [ ( "0", "a" )
--> , ( "2", "b" )
--> , ( "1", "c" )
--> ]

move : Basics.Int -> Basics.Int -> Reorderable a -> Reorderable a

Move an item from one location to another location.

fromList [ "b", "c", "a" ]
    |> move 2 0
    |> toList
--> [ "a", "b", "c" ]

fromList [ "a", "c", "b"]
    |> move 2 1
    |> toList
--> [ "a", "b", "c" ]

insertAt : Basics.Int -> a -> Reorderable a -> Reorderable a

Inserts a piece of data into a specifc position of the Reorderable.

letters : Reorderable String
letters =
    fromList [ "a", "b", "c", "d" ]


letters
    |> insertAt 0 "foo"
    |> toList
--> [ "foo", "a", "b", "c", "d" ]


letters
    |> insertAt 4 "foo"
    |> toList
--> [ "a", "b", "c", "d", "foo" ]


letters
    |> insertAt 2 "foo"
    |> toKeyedList
--> [ ( "0", "a" )
--> , ( "1", "b" )
--> , ( "4", "foo" )
--> , ( "2", "c" )
--> , ( "3", "d" )
--> ]

insertAfter : Basics.Int -> a -> Reorderable a -> Reorderable a

Convenience function to insert something after a specified index.

fromList [ "a", "c" ]
    |> insertAfter 0 "b"
    |> toList
--> [ "a", "b", "c" ]


fromList [ "a", "b" ]
    |> insertAfter 1 "c"
    |> toList
--> [ "a", "b", "c" ]

drop : Basics.Int -> Reorderable a -> Reorderable a

Drops the entry at a certain index.

fromList [ "a", "removeMe", "b" ]
    |> drop 1
    |> toKeyedList
--> [ ( "0", "a" ), ( "2", "b" ) ]

reverse : Reorderable a -> Reorderable a

Reverse the order of the entries.

fromList [ "first", "second", "third" ]
    |> reverse
    |> toKeyedList
--> [ ( "2", "third" )
--> , ( "1", "second" )
--> , ( "0", "first" )
--> ]

List-y stuff

fromList : List a -> Reorderable a

Initialize a Reorderable a from a List a. Useful for initializing data and decoding with Json.Decode.map Reorderable.fromList.

toList : Reorderable a -> List a

Convert a Reorderable a to a plain old List a.

fromList [ "a", "b", "c" ]
    |> toList
--> [ "a", "b", "c" ]

toKeyedList : Reorderable a -> List ( String, a )

Convert a Reorderable a to a List (String, a), useful for eventually rendering a Html.Keyed node.

fromList [ "a", "b", "c" ]
    |> toKeyedList
--> [ ( "0", "a" )
--> , ( "1", "b" )
--> , ( "2", "c" )
--> ]

This retains the key during swap/insertAt/drop/move*/.. operations, so that your Html.Keyed node can work correctly.

Transformation

map : (a -> b) -> Reorderable a -> Reorderable b

Transform the values in a reorderable

indexedMap : (Basics.Int -> a -> b) -> Reorderable a -> Reorderable b

Transform the values in a reorderable with their index