Handler to let the user reorder the items in a list

Hi fellow AppleScripters,

Last week I wrote a small script for our DTP department to let them reorder the pages of a produced PDF file. In this process I developed a general handler, which lets users reorder items of a list using the «choose from list» dialog. Might be of some use for others too :slight_smile:

Happy Scripting!


property mytitle : "Reorder sample"

on run
	set entries to {"Page 1", "Page 2", "Page 3", "Page 4", "Page 5", "Page 6", "Page 7", "Page 8", "Page 9", "Page 10"}
	set reorderedentries to my getreorderedentries(entries)
	if entries is missing value then
		return
	else
		return reorderedentries
	end if
	
	-- more code goes here
end run

-- I am returning a list of items reordered by the user
on getreorderedentries(entries)
	-- we are adding unique ids to the entries so we can identify them
	set tmpentries to my addids(entries)
	set tmpentries to {"↑↑ Move up", "↓↓ Move down", "﹉﹉﹉﹉﹉﹉﹉"} & tmpentries
	choose from list tmpentries with prompt "Please reorder the entries below:" with title mytitle with multiple selections allowed and empty selection allowed
	set chosenentries to result
	if chosenentries is not false then
		set chosenentries to chosenentries as list
		-- nothing was selected by the user -> we are finished
		if chosenentries is {} then
			return (my removeids(items 4 through -1 of tmpentries))
			-- only 1 menu item/entry was selected -> we display the main menu again
		else if length of chosenentries is 1 then
			my getreorderedentries(my removeids(items 4 through -1 of tmpentries))
			-- at least 2 menu items/entries were selected
		else
			-- both reorder commands were selected  -> we display the main menu again
			if chosenentries contains "↑↑ Move up" and chosenentries contains "↓↓ Move down" then
				my getreorderedentries(my removeids(items 4 through -1 of tmpentries))
				-- no reorder commands were selected  -> we display the main menu again
			else if chosenentries does not contain "↑↑ Move up" and chosenentries does not contain "↓↓ Move down" then
				my getreorderedentries(my removeids(items 4 through -1 of tmpentries))
			else
				-- move up or down?
				if chosenentries contains "↑↑ Move up" then
					set reorderdirection to "up"
					set chosenentries to (items 2 through -1 of chosenentries)
				else if chosenentries contains "↓↓ Move down" then
					set reorderdirection to "down"
					set chosenentries to reverse of (items 2 through -1 of chosenentries)
				end if
				-- reordering the items according to the user's choice
				set tmpentries to (items 4 through -1 of tmpentries)
				set counttmpentries to length of tmpentries
				repeat with chosenentry in chosenentries
					repeat with i from counttmpentries to 1 by -1
						set tmpentry to item i of tmpentries
						if (tmpentry as text) is equal to (chosenentry as text) then
							if reorderdirection is "up" then
								set neighborindex to (i - 1)
								if neighborindex is 0 then
									set tmpentries to (items 2 through -1 of tmpentries) & {chosenentry as text}
									exit repeat
								end if
							else if reorderdirection is "down" then
								set neighborindex to (i + 1)
								if neighborindex is (counttmpentries + 1) then
									set tmpentries to {chosenentry as text} & (items 1 through -2 of tmpentries)
									exit repeat
								end if
							end if
							set neighborentry to item neighborindex of tmpentries
							set item i of tmpentries to neighborentry
							set item neighborindex of tmpentries to (chosenentry as text)
							exit repeat
						end if
					end repeat
				end repeat
				-- we display the main menu with the reordered items
				my getreorderedentries(my removeids(tmpentries))
			end if
		end if
	else
		-- the user canceled the dialog
		return missing value
	end if
end getreorderedentries

-- I am adding ids to the entries
on addids(entries)
	set countentries to length of entries
	set countstrentries to length of (countentries as text)
	set tmpentries to {}
	repeat with i from 1 to countentries
		set entry to item i of entries
		set countstridx to (length of (i as text))
		set stridx to i
		repeat (countstrentries - countstridx) times
			set stridx to "0" & stridx
		end repeat
		set tmpentry to "[" & stridx & "] " & entry
		set tmpentries to tmpentries & tmpentry
	end repeat
	return tmpentries
end addids

-- I am removing ids from the entries
on removeids(entries)
	set tmpentries to {}
	repeat with entry in entries
		set bracketoffset to offset of "]" in entry
		set entry to (characters (bracketoffset + 2) through -1 of entry) as text
		set tmpentries to tmpentries & entry
	end repeat
	return tmpentries
end removeids