1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
------------------------------------------------------------------------------
-- | This library provides functions to categorize a list of entities
--   into a HTML page with an index access (e.g., "A-Z") to these entities.
------------------------------------------------------------------------------

module HTML.CategorizedList
  ( list2CategorizedHtml, categorizeByItemKey, stringList2ItemList )
 where

import Data.Char
import Data.List

import HTML.Base
import Network.URL ( string2urlencoded )

-- | General categorization of a list of entries.
--
-- The item will occur in every category for which the boolean function
-- categoryFun yields True.
list2CategorizedHtml :: (HTML h, Show b) =>
     [(a,[h])]        -- ^ the list of key-item pairs which are supposed to be
                      --   categorized with respect to key
  -> [(b,String)]     -- ^ list of key-category pairs to which the items can be
                      --   sorted in
  -> (a -> b -> Bool) -- ^ uses the keys of the items and the keys of the
                      --   categories to distribute the items among
                      --   the categories
  -> [h]              -- ^ HTML containing inner links between the categories
list2CategorizedHtml itemL categoryL categoryFun =
   categories2LinkList categoryL :
   map (\ (categoryKey,categoryString) ->
          anchor (string2urlencoded (show categoryKey))
                 (h2 [htxt categoryString] :
                  concatMap (\ (_,item)->item++[breakline])
                            (filter (\ (itemKey,_) ->
                                            categoryFun itemKey categoryKey)
                                     itemL)
                     ++ [categories2LinkList categoryL])
         )
        categoryL

-- the navigation list
categories2LinkList :: (HTML h, Show a) => [(a,String)] -> h
categories2LinkList categoryL =
  par
  [center
    (concatMap (\ (categoryKey,categoryString) ->
                     [href ('#':(string2urlencoded (show categoryKey)))
                           [htxt categoryString], nbsp])
               categoryL)]

-- | Categorizes a list of entries with respect to the initial keys.
--
-- The categories are named as all initial characters of the keys of the items.
categorizeByItemKey :: HTML h =>
     [(String,[h])] -- ^ the list of key-item pairs which are supposed to be
                    --   categorized with respect to key
  -> [h]            -- ^ HTML containing inner links between the categories
categorizeByItemKey itemL =
   list2CategorizedHtml
       itemL
       (map (\c -> (toUpper c,[toUpper c])) (listHeads (map fst itemL)))
       categorizeStringHead

-- | Converts a string list into an key-item list.
--   The strings are used as keys and for the simple text layout.
stringList2ItemList :: HTML h => [String] -> [(String,[h])]
stringList2ItemList = map (\str -> (str,[htxt str]))

-- yields every listHead only once
listHeads :: [String] -> [Char]
listHeads =
  nubBy isUpperEqual . foldr (\xs ys -> if xs==[] then ys else head xs:ys) []

-- categoryFun for categorizeByItemKey
categorizeStringHead :: String -> Char -> Bool
categorizeStringHead [] _ = False
categorizeStringHead (c:_) c' = isUpperEqual c c'

isUpperEqual :: Char -> Char -> Bool
isUpperEqual c c' = toUpper c == toUpper c'


-- just for testing ----------------------------------------

main :: IO HtmlPage
main = return $ page "CatTest"
                     (categorizeByItemKey (stringList2ItemList testList))

testList :: [String]
testList = ["bbcd",
            "acde",
            "ab",
            "cde",
            "b",
            "xt",
            "gbbcd",
            "uacde",
            "Oab",
            "Qcde",
            "Tb",
            "mxt",
            "mxtr"]

-- To test, export `main` and run:
-- > cypm exec curry2cgi -o ~/public_html/cgi-bin/cat.cgi HTML.CategorizedList