packages feed

digestive-functors-heist 0.7.0.0 → 0.8.0.0

raw patch · 3 files changed

+116/−116 lines, 3 filesdep ~heistPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: heist

API changes (from Hackage documentation)

- Text.Digestive.Heist: digestiveSplices :: MonadIO m => View Text -> [(Text, Splice m)]
+ Text.Digestive.Heist: digestiveSplices :: MonadIO m => View Text -> Splices (Splice m)
- Text.Digestive.Heist.Compiled: dfChildErrorList :: Monad m => Promise (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: dfChildErrorList :: Monad m => RuntimeSplice m (View Text) -> Splice m
- Text.Digestive.Heist.Compiled: dfErrorList :: Monad m => Promise (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: dfErrorList :: Monad m => RuntimeSplice m (View Text) -> Splice m
- Text.Digestive.Heist.Compiled: dfIfChildErrors :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfIfChildErrors :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfInput :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInput :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputCheckbox :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputCheckbox :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputHidden :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputHidden :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputList :: Monad m => Promise (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputList :: Monad m => RuntimeSplice m (View Text) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputPassword :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputPassword :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputRadio :: Monad m => Promise (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputRadio :: Monad m => RuntimeSplice m (View Text) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputSelect :: Monad m => Promise (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputSelect :: Monad m => RuntimeSplice m (View Text) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputSelectGroup :: Monad m => Promise (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputSelectGroup :: Monad m => RuntimeSplice m (View Text) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputText :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputText :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfInputTextArea :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfInputTextArea :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfLabel :: Monad m => Promise (View v) -> Splice m
+ Text.Digestive.Heist.Compiled: dfLabel :: Monad m => RuntimeSplice m (View v) -> Splice m
- Text.Digestive.Heist.Compiled: dfSubView :: Monad m => Promise (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: dfSubView :: Monad m => RuntimeSplice m (View Text) -> Splice m
- Text.Digestive.Heist.Compiled: digestiveSplices :: Monad m => Promise (View Text) -> [(Text, Splice m)]
+ Text.Digestive.Heist.Compiled: digestiveSplices :: Monad m => RuntimeSplice m (View Text) -> Splices (Splice m)
- Text.Digestive.Heist.Compiled: formSplice :: Monad m => [(Text, Splice m)] -> [(Text, AttrSplice m)] -> RuntimeSplice m (View Text) -> Splice m
+ Text.Digestive.Heist.Compiled: formSplice :: Monad m => Splices (Splice m) -> Splices (AttrSplice m) -> RuntimeSplice m (View Text) -> Splice m

Files

digestive-functors-heist.cabal view
@@ -1,5 +1,5 @@ Name:          digestive-functors-heist-Version:       0.7.0.0+Version:       0.8.0.0 Synopsis:      Heist frontend for the digestive-functors library Description:   Heist frontend for the digestive-functors library Homepage:      http://github.com/jaspervdj/digestive-functors@@ -22,7 +22,7 @@     base               >= 4      && < 5,     blaze-builder      >= 0.3    && < 0.4,     digestive-functors >= 0.6.1  && < 0.7,-    heist              >= 0.11.1 && < 0.13,+    heist              >= 0.13   && < 0.14,     mtl                >= 2      && < 2.2,     text               >= 0.11   && < 0.12,     xmlhtml            >= 0.1    && < 0.3
src/Text/Digestive/Heist.hs view
@@ -76,27 +76,27 @@   ---------------------------------------------------------------------------------digestiveSplices :: MonadIO m => View Text -> [(Text, Splice m)]-digestiveSplices view =-    [ ("dfInput",            dfInput view)-    , ("dfInputList",        dfInputList view)-    , ("dfInputText",        dfInputText view)-    , ("dfInputTextArea",    dfInputTextArea view)-    , ("dfInputPassword",    dfInputPassword view)-    , ("dfInputHidden",      dfInputHidden view)-    , ("dfInputSelect",      dfInputSelect view)-    , ("dfInputSelectGroup", dfInputSelectGroup view)-    , ("dfInputRadio",       dfInputRadio view)-    , ("dfInputCheckbox",    dfInputCheckbox view)-    , ("dfInputFile",        dfInputFile view)-    , ("dfInputSubmit",      dfInputSubmit view)-    , ("dfLabel",            dfLabel view)-    , ("dfForm",             dfForm view)-    , ("dfErrorList",        dfErrorList view)-    , ("dfChildErrorList",   dfChildErrorList view)-    , ("dfSubView",          dfSubView view)-    , ("dfIfChildErrors",    dfIfChildErrors view)-    ]+digestiveSplices :: MonadIO m => View Text -> Splices (Splice m)+digestiveSplices view = do+    "dfInput"            ## dfInput view+    "dfInputList"        ## dfInputList view+    "dfInputText"        ## dfInputText view+    "dfInputTextArea"    ## dfInputTextArea view+    "dfInputPassword"    ## dfInputPassword view+    "dfInputHidden"      ## dfInputHidden view+    "dfInputSelect"      ## dfInputSelect view+    "dfInputSelectGroup" ## dfInputSelectGroup view+    "dfInputRadio"       ## dfInputRadio view+    "dfInputCheckbox"    ## dfInputCheckbox view+    "dfInputFile"        ## dfInputFile view+    "dfInputSubmit"      ## dfInputSubmit view+    "dfLabel"            ## dfLabel view+    "dfForm"             ## dfForm view+    "dfErrorList"        ## dfErrorList view+    "dfChildErrorList"   ## dfChildErrorList view+    "dfSubView"          ## dfSubView view+    "dfIfChildErrors"    ## dfIfChildErrors view+       --------------------------------------------------------------------------------@@ -469,16 +469,16 @@             , ("style", "display: none;")             ]         items = listSubViews ref view-        f attrs v = localHS (bindAttributeSplices [("itemAttrs", attrs v)] .+        f attrs v = localHS (bindAttributeSplices ("itemAttrs" ## attrs v) .                        bindDigestiveSplices v) runChildren         dfListItem = do             template <- f templateAttrs (makeListSubView ref (-1) view)             res <- mapSplices (f itemAttrs) items             return $ template ++ res-        attrSplices = [ ("addControl", addControl)-                      , ("removeControl", removeControl)-                      ]-    nodes <- localHS (bindSplices [("dfListItem", dfListItem)] .+        attrSplices = do+            "addControl"    ## addControl+            "removeControl" ## removeControl+    nodes <- localHS (bindSplices ("dfListItem" ## dfListItem) .                       bindAttributeSplices attrSplices) runChildren     let indices = [X.Element "input"                     [ ("type", "hidden")
src/Text/Digestive/Heist/Compiled.hs view
@@ -59,12 +59,13 @@ import           Data.Function         (on) import           Data.List             (unionBy) import           Data.Maybe            (fromMaybe)-import           Data.Monoid           ((<>), mempty)+import           Data.Monoid           ((<>), mempty, mappend) import           Data.Text             (Text) import qualified Data.Text             as T import           Data.Text.Encoding import           Heist import           Heist.Compiled+import           Heist.Compiled.LowLevel import qualified Text.XmlHtml          as X  @@ -77,27 +78,28 @@ -- | List of splices defined for forms.  For most uses the formSplice function -- will be fine and you won't need to use this directly.  But this is -- available if you need more customization.-digestiveSplices :: (Monad m) => Promise (View Text) -> [(Text, Splice m)]-digestiveSplices vp =-    [ ("dfInput",            dfInput vp)-    , ("dfInputText",        dfInputText vp)-    , ("dfInputTextArea",    dfInputTextArea vp)-    , ("dfInputPassword",    dfInputPassword vp)-    , ("dfInputHidden",      dfInputHidden vp)-    , ("dfInputSelect",      dfInputSelect vp)-    , ("dfInputSelectGroup", dfInputSelectGroup vp)-    , ("dfInputRadio",       dfInputRadio vp)-    , ("dfInputCheckbox",    dfInputCheckbox vp)-    , ("dfInputFile",        dfInputFile vp)-    , ("dfInputSubmit",      dfInputSubmit)-    , ("dfLabel",            dfLabel vp)-    , ("dfErrorList",        dfErrorList vp)-    , ("dfChildErrorList",   dfChildErrorList vp)-    , ("dfSubView",          dfSubView vp)-    , ("dfIfChildErrors",    dfIfChildErrors vp)-    , ("dfInputList",        dfInputList vp)-    , ("dfEncType",          dfEncType vp)-    ]+digestiveSplices :: (Monad m)+                 => RuntimeSplice m (View Text)+                 -> Splices (Splice m)+digestiveSplices vp = do+    "dfInput"            ## dfInput vp+    "dfInputText"        ## dfInputText vp+    "dfInputTextArea"    ## dfInputTextArea vp+    "dfInputPassword"    ## dfInputPassword vp+    "dfInputHidden"      ## dfInputHidden vp+    "dfInputSelect"      ## dfInputSelect vp+    "dfInputSelectGroup" ## dfInputSelectGroup vp+    "dfInputRadio"       ## dfInputRadio vp+    "dfInputCheckbox"    ## dfInputCheckbox vp+    "dfInputFile"        ## dfInputFile vp+    "dfInputSubmit"      ## dfInputSubmit+    "dfLabel"            ## dfLabel vp+    "dfErrorList"        ## dfErrorList vp+    "dfChildErrorList"   ## dfChildErrorList vp+    "dfSubView"          ## dfSubView vp+    "dfIfChildErrors"    ## dfIfChildErrors vp+    "dfInputList"        ## dfInputList vp+    "dfEncType"          ## dfEncType vp   ------------------------------------------------------------------------------@@ -105,13 +107,13 @@ -- gets the form's view and this function returns a splice that creates a form -- tag.  In your HeistConfig you might have a compiled splice like this: ----- `("customerForm", formSplice (liftM fst $ runForm "customer" custForm))`+-- > ("customerForm" ## formSplice (liftM fst $ runForm "customer" custForm)) -- -- Then you can use the customerForm tag just like you would use the dfForm -- tag in interpreted templates anywhere you want to have a customer form. formSplice :: Monad m-           => [(Text, Splice m)]-           -> [(Text, AttrSplice m)]+           => Splices (Splice m)+           -> Splices (AttrSplice m)            -> RuntimeSplice m (View Text)            -> Splice m formSplice ss as getView = do@@ -124,8 +126,7 @@                     ])                  (X.childNodes node)         action = runNode tree-    defer (\vp -> withLocalSplices (digestiveSplices vp ++ ss) as action)-          getView+    withLocalSplices (digestiveSplices getView `mappend` ss) as action   --------------------------------------------------------------------------------@@ -148,30 +149,30 @@   dfEncType :: (Monad m)-          => Promise (View v)+          => RuntimeSplice m (View v)           -> Splice m-dfEncType p = do+dfEncType getView = do     return $ yieldRuntime $ do-        view <- getPromise p+        view <- getView         return $ fromByteString $ encodeUtf8 $ T.pack (show $ viewEncType view)   dfMaster :: Monad m          => (Text -> [(Text, Text)] -> View v -> RuntimeSplice m Builder)-         -> Promise (View v) -> Splice m-dfMaster f p = do+         -> RuntimeSplice m (View v) -> Splice m+dfMaster f getView = do     node <- getParamNode     let (ref, attrs) = getRefAttributes node Nothing     runAttrs <- runAttributesRaw attrs     return $ yieldRuntime $ do-        view <- getPromise p+        view <- getView         attrs' <- runAttrs         f ref attrs' view   dfTag :: (Monad m)       => (Text -> [(Text, Text)] -> Text -> [X.Node])-      -> Promise (View v)+      -> RuntimeSplice m (View v)       -> Splice m dfTag f = dfMaster $ \ref attrs view -> do     let ref' = absoluteRef ref view@@ -183,7 +184,7 @@  dfInputGeneric :: Monad m                => [(Text, Text)]-               -> Promise (View v)+               -> RuntimeSplice m (View v)                -> Splice m dfInputGeneric as = dfTag $ \ref attrs value ->     makeElement "input" [] $ addAttrs attrs $@@ -211,13 +212,13 @@ -- -- > <dfLabel ref="user.married">Married: </dfLabel> -- > <dfInputCheckbox ref="user.married" />-dfLabel :: Monad m => Promise (View v) -> Splice m-dfLabel p = do+dfLabel :: Monad m => RuntimeSplice m (View v) -> Splice m+dfLabel getView = do     node <- getParamNode     let (ref, attrs) = getRefAttributes node Nothing     runAttrs <- runAttributesRaw attrs     return $ yieldRuntime $ do-        view <- getPromise p+        view <- getView         attrs' <- runAttrs         let ref'  = absoluteRef ref view             e = makeElement "label" (X.childNodes node) $ addAttrs attrs'@@ -229,7 +230,7 @@ -- | Generate an input field with a supplied type. Example: -- -- > <dfInput type="date" ref="date" />-dfInput :: Monad m => Promise (View v) -> Splice m+dfInput :: Monad m => RuntimeSplice m (View v) -> Splice m dfInput = dfInputGeneric []  @@ -237,7 +238,7 @@ -- | Generate a text input field. Example: -- -- > <dfInputText ref="user.name" />-dfInputText :: Monad m => Promise (View v) -> Splice m+dfInputText :: Monad m => RuntimeSplice m (View v) -> Splice m dfInputText = dfInputGeneric [("type", "text")]  @@ -245,7 +246,7 @@ -- | Generate a text area. Example: -- -- > <dfInputTextArea ref="user.about" />-dfInputTextArea :: Monad m => Promise (View v) -> Splice m+dfInputTextArea :: Monad m => RuntimeSplice m (View v) -> Splice m dfInputTextArea = dfTag $ \ref attrs value ->     makeElement "textarea" [X.TextNode value] $ addAttrs attrs         [("id", ref), ("name", ref)]@@ -255,7 +256,7 @@ -- | Generate a password field. Example: -- -- > <dfInputPassword ref="user.password" />-dfInputPassword :: Monad m => Promise (View v) -> Splice m+dfInputPassword :: Monad m => RuntimeSplice m (View v) -> Splice m dfInputPassword = dfInputGeneric [("type", "password")]  @@ -263,7 +264,7 @@ -- | Generate a hidden input field. Example: -- -- > <dfInputHidden ref="user.forgery" />-dfInputHidden :: Monad m => Promise (View v) -> Splice m+dfInputHidden :: Monad m => RuntimeSplice m (View v) -> Splice m dfInputHidden = dfInputGeneric [("type", "hidden")]  @@ -272,7 +273,7 @@ -- -- > <dfInputCheckbox ref="user.married" /> dfInputCheckbox :: Monad m-                => Promise (View v)+                => RuntimeSplice m (View v)                 -> Splice m dfInputCheckbox = dfMaster $ \ref attrs view -> do     let ref'  = absoluteRef ref view@@ -288,7 +289,7 @@ -- | Generate a file upload element. Example: -- -- > <dfInputFile ref="user.avatar" />-dfInputFile :: Monad m => Promise (View v) -> Splice m+dfInputFile :: Monad m => RuntimeSplice m (View v) -> Splice m dfInputFile = dfMaster $ \ref attrs view -> do     let ref'  = absoluteRef ref view         value = maybe "" T.pack $ fieldInputFile ref view@@ -302,7 +303,7 @@ -- | Generate a select button (also known as a combo box). Example: -- -- > <dfInputSelect ref="user.sex" />-dfInputSelect :: Monad m => Promise (View Text) -> Splice m+dfInputSelect :: Monad m => RuntimeSplice m (View Text) -> Splice m dfInputSelect = dfMaster $ \ref attrs view -> do     let ref'     = absoluteRef ref view         choices  = fieldInputChoice ref view@@ -322,7 +323,7 @@ -- | Generate a select button (also known as a combo box). Example: -- -- > <dfInputSelectGroup ref="user.sex" />-dfInputSelectGroup :: Monad m => Promise (View Text) -> Splice m+dfInputSelectGroup :: Monad m => RuntimeSplice m (View Text) -> Splice m dfInputSelectGroup = dfMaster $ \ref attrs view -> do     let ref'     = absoluteRef ref view         choices  = fieldInputChoiceGroup ref view@@ -344,7 +345,7 @@ -- | Generate a number of radio buttons. Example: -- -- > <dfInputRadio ref="user.sex" />-dfInputRadio :: Monad m => Promise (View Text) -> Splice m+dfInputRadio :: Monad m => RuntimeSplice m (View Text) -> Splice m dfInputRadio = dfMaster $ \ref attrs view -> do     let ref'     = absoluteRef ref view         choices  = fieldInputChoice ref view@@ -368,11 +369,11 @@ -- -- > <dfErrorList ref="user.name" /> -- > <dfInputText ref="user.name" />-dfErrorList :: Monad m => Promise (View Text) -> Splice m-dfErrorList p = do+dfErrorList :: Monad m => RuntimeSplice m (View Text) -> Splice m+dfErrorList getView = do     node <- getParamNode     return $ yieldRuntime $ do-        view <- getPromise p+        view <- getView         let (ref, attrs) = getRefAttributes node Nothing             nodes = errorList (errors ref view) attrs         return $ X.renderHtmlFragment X.UTF8 nodes@@ -391,11 +392,11 @@ -- Which is more conveniently written as: -- -- > <dfChildErrorList />-dfChildErrorList :: Monad m => Promise (View Text) -> Splice m-dfChildErrorList p = do+dfChildErrorList :: Monad m => RuntimeSplice m (View Text) -> Splice m+dfChildErrorList getView = do     node <- getParamNode     return $ yieldRuntime $ do-        view <- getPromise p+        view <- getView         let (ref, attrs) = getRefAttributes node (Just "")             nodes = errorList (childErrors ref view) attrs         return $ X.renderHtmlFragment X.UTF8 nodes@@ -410,11 +411,11 @@ -- > </dfIfChildErrors> -- -- The @ref@ attribute can be omitted if you want to check the entire form.-dfIfChildErrors :: (Monad m) => Promise (View v) -> Splice m-dfIfChildErrors p = do+dfIfChildErrors :: (Monad m) => RuntimeSplice m (View v) -> Splice m+dfIfChildErrors getView = do     node <- getParamNode     return $ yieldRuntime $ do-        view <- getPromise p+        view <- getView         let (ref, _) = getRefAttributes node Nothing         if null (childErrors ref view)           then return mempty@@ -445,34 +446,34 @@ -- > </dfSubView> -- > -- > <dfInputTextArea ref="comment.body" />-dfSubView :: Monad m => Promise (View Text) -> Splice m-dfSubView p = do+dfSubView :: Monad m => RuntimeSplice m (View Text) -> Splice m+dfSubView getView = do     node <- getParamNode     p2 <- newEmptyPromise     let action = yieldRuntimeEffect $ do-            view <- getPromise p+            view <- getView             let (ref, _) = getRefAttributes node Nothing                 view' = subView ref view             putPromise p2 view'-    res <- withLocalSplices (digestiveSplices p2) [] $+    res <- withLocalSplices (digestiveSplices (getPromise p2)) noSplices $              runNodeList $ X.childNodes node     return $ action <> res  -dfSingleListItem :: Monad m+dfSingleListItem :: Monad n                  => X.Node-                 -> (Promise (View Text) -> AttrSplice m)-                 -> Promise (View Text)-                 -> HeistT m IO (RuntimeSplice m Builder)+                 -> (RuntimeSplice n (View Text) -> AttrSplice n)+                 -> RuntimeSplice n (View Text)+                 -> Splice n dfSingleListItem node attrs viewPromise = do     p2 <- newEmptyPromise     let action = yieldRuntimeEffect $ do-            view <- getPromise viewPromise+            view <- viewPromise             putPromise p2 view-    res <- withLocalSplices (digestiveSplices p2)-                            [("itemAttrs", attrs viewPromise)]+    res <- withLocalSplices (digestiveSplices (getPromise p2))+                            ("itemAttrs" ## attrs viewPromise)                             (runNodeList $ X.childNodes node)-    return $ codeGen $ action <> res+    return $ action <> res   --------------------------------------------------------------------------------@@ -496,22 +497,22 @@ --     an onclick attribute that calls a javascript function addInputListItem. --   removeControl - Use this attribute on the control for removing individual --     items.  It adds an onclick attribute that calls removeInputListItem.-dfInputList :: Monad m => Promise (View Text) -> Splice m-dfInputList p = do+dfInputList :: Monad m => RuntimeSplice m (View Text) -> Splice m+dfInputList getView = do     node <- getParamNode     itemsPromise <- newEmptyPromise     refPromise <- newEmptyPromise     indicesPromise <- newEmptyPromise     templateViewPromise <- newEmptyPromise-    let itemAttrs viewPromise _ = do-            view <- getPromise viewPromise+    let itemAttrs gv _ = do+            view <- gv             listRef <- getPromise refPromise             return               [ ("id", T.concat [listRef, ".", last $ "0" : viewContext view])               , ("class", T.append listRef ".inputListItem")               ]-        templateAttrs viewPromise _ = do-            view <- getPromise viewPromise+        templateAttrs gv _ = do+            view <- gv             listRef <- getPromise refPromise             return               [ ("id", T.concat [listRef, ".", last $ "-1" : viewContext view])@@ -520,11 +521,10 @@               ]         dfListItem = do             n <- getParamNode-            template <- dfSingleListItem n templateAttrs-                                         templateViewPromise-            body <- mapPromises (dfSingleListItem n itemAttrs) $-                                getPromise itemsPromise-            return $ yieldRuntime template <> body+            template <- dfSingleListItem n templateAttrs (getPromise templateViewPromise)+            body <- deferMany (dfSingleListItem n itemAttrs) $+                              getPromise itemsPromise+            return $ template <> body     let listAttrs =             [ ("id", "${dfListRef}")             , ("class", "inputList")@@ -545,17 +545,17 @@             return [ ("onclick", T.concat [ "removeInputListItem(this, '"                                           , listRef                                           , "'); return false;"] ) ]-        attrSplices = [ ("addControl", addControl)-                      , ("removeControl", removeControl)-                      ]-        splices = [ ("dfListRef", return $ yieldRuntimeText $ getPromise refPromise)-                  , ("dfIndicesList", return $ yieldRuntimeText $ getPromise indicesPromise)-                  , ("dfListItem", dfListItem)-                  ]+        attrSplices = do+            "addControl"    ## addControl+            "removeControl" ## removeControl+        splices = do+            "dfListRef"     ## return $ yieldRuntimeText $ getPromise refPromise+            "dfIndicesList" ## return $ yieldRuntimeText $ getPromise indicesPromise+            "dfListItem"    ## dfListItem      -- The runtime action that gets the right data and puts it in promises.     let action = yieldRuntimeEffect $ do-          view <- getPromise p+          view <- getView           let (ref, _) = getRefAttributes node Nothing               listRef  = absoluteRef ref view               items = listSubViews ref view