2013-03-17 60 views
2

下面的示例定义了一个将nicEditor绑定到textarea的snaplet。以下问题不仅与以下示例有关,而且可能与其他一些类似案例有关。如何让nicEditor快捷方式? (几个问题)

  1. 新手是否可以按照以下说明进行操作?(如何澄清)?
  2. 如何让示例使用更少的步骤或更简单? (是否可能与下面的内容大致相同?)
  3. 这使用了解释拼接。如果可能的话,是否应该提供拼接拼接?
  4. snaplet可能会给一个默认处理程序或几个处理程序的典型情况。处理程序可以在下面的“SnapNic.hs”中定义。给用户一些回调机制呢?

-

{-# LANGUAGE TemplateHaskell #-} 
{-# LANGUAGE OverloadedStrings #-} 

------------------------------------------------------------------------------ 
-- | This module defines nicEditor snaplet, just a short example to show, 
-- how snaplets can be defined together with splices. 
-- License: BSD3. 
-- Here are hopefully easy instructions, how to use or try: 
-- 
-- 1. Make a directory, we'll use "netry" below, go there. 
-- Initialize a project, e.g. "snap init default". 
-- 2. Copy this file to netry/src-directory as SnapNic.hs. 
-- 3. Add "import SnapNic" to Site.hs and to Application.hs 
-- 4. Add ", _niced :: Snaplet Nicsnap" to data App in Application.hs 
-- 
-- 5. Add "n <- nestSnaplet "niced" niced nicsnapInit" to 
-- app :: SnapletInit App App in Site.hs. 
-- 6. Add "addNicEditSplices n" to the same function as in step 5. 
-- 7. Change the return-line of the same function as in step 5: 
--  "return $ App h s a n" 
-- that is, add "n" into the end. We need this because of step 4. 
-- 
-- 8. Make route, e.g. ", ("/netext", with auth handleNEtext)" to 
-- routes-function in Site.hs 
-- 
-- 9. And then add handler into Site.hs: 
-- handleNEtext :: Handler App v() 
-- handleNEtext = method GET handleForm <|> method POST handleFormSubmit 
--  where 
--  handleForm = render "textedit" 
--  handleFormSubmit = do 
--  p <- getParam "ots" 
--  writeText "Submitting text from textarea...\n" 
--  writeText (T.pack (show p)) 
-- 
-- 10. Last, add the following 2 templates to "netry/snaplets/heist/templates". 
-- (This could be made simpler, but this works as an example of apply-tag.) 
-- textedit.tpl: 
--  <apply template="base"> 
--   <apply template="_textedit" /> 
--  </apply> 
-- _textedit.tpl: 
--  <h2>Your nic editor</h2> 
--   <form method="post" action="netext"> 
--   <neTA/> 
--   <button name="ne" value="ne" type="Submit">Send text</button> 
--   </form> 
--   <neScript/> 
-- 
-- 11. Compile everything "cabal install -fdevelopment". After that, 
--  if everything compiled, "netry -p 8000", start your browser and go 
--  to "localhost:8000/netext". 
-- 
-- TODO! This could use the config-files at least for some parameters, and more 
-- tags,please. Tags could use some attributes (for example, size parameters 
-- could be given as attributes of tags)... 
-- 
module SnapNic 
    (Nicsnap (..) 
    , nicsnapInit 
    , addNicEditSplices 
) where 

------------------------------------------------------------------------------ 
import   Control.Lens (makeLenses, view, (^.)) 
import qualified Data.Text as T (Text, append, pack) 
import   Data.Maybe  (fromJust, fromMaybe) 
import   Snap.Core  (MonadSnap) 
import   Snap.Snaplet (Snaplet 
           , makeSnaplet 
           , snapletValue 
           , SnapletInit 
           , Initializer 
           ) 
import   Snap.Snaplet.Heist  (HasHeist, addSplices) 
import qualified Text.XmlHtml as X  (Node (Element, TextNode)) 
import qualified Heist.Interpreted as I (Splice) 

------------------------------------------------------------------------------ 
-- | Nicsnap has fields that can be used to set some basic properties. 
-- The editor can have a title and its size can be set. Javascript can be 
-- local or remote. 
data Nicsnap = Nicsnap 
    { _nicsnap :: T.Text  -- title 
    , _areaSize :: (Int,Int) -- rows, cols 
    , _areaRef :: T.Text  -- how to apply nicEditors? 
    -- (This may not be sufficient in order to refer in some other way, TODO!) 
    , _localR :: Maybe T.Text -- local route to nicEdit.js 
    , _webR  :: T.Text  -- route to nicEdit's javascript source. 
    } 

makeLenses ''Nicsnap   -- makes webR and other lenses 


------------------------------------------------------------------------------ 
-- | Configurations are given here. This could use config-files... 
-- What other things to configure? 
-- If you want to make a local copy of the nicEdit, then add a static route 
-- to the "routes"-function. 
nicsnapInit :: SnapletInit b Nicsnap 
nicsnapInit = makeSnaplet "nicsnap" "NicEditor snaplet " Nothing $ do 
    let m = "Nic editor title" 
     aS = (20,80)::(Int,Int) -- rows, cols 
     aR = "nicEditors.allTextAreas" -- TODO! We need to be able to tell, 
     -- which textareas have editors in a page. 
     lR = Nothing 
     -- lR = Just "/nicEdit.js" 
     -- If localR is nothing, then webR is used with the following addr. 
     wR = "http://js.nicedit.com/nicEdit-latest.js" 
    return $ Nicsnap m aS aR lR wR 

------------------------------------------------------------------------------ 

-- | Internal, this makes the script-tag. 
-- Input could be e.g. txt = "/nicEdit.js" 
srcElem :: T.Text -> X.Node 
srcElem txt = X.Element "script" 
    [("src",txt),("type","text/javascript")] [] 

-- | Internal, this makes the script-tag. At the moment this changes all 
-- textareas to niceditors, if the example input below is used. TODO!... 
-- Input could be e.g. txt = "nicEditors.allTextAreas" 
srcOnLoad :: T.Text -> X.Node 
srcOnLoad txt = X.Element "script" [("type","text/javascript")] 
    [X.TextNode (T.append (T.append "bkLib.onDomLoaded(" txt) ");")] 


-- | Internal, used to define "divs", where we give a label and size to 
-- textarea. Also ids and names. 
-- TODO! ids and names could be parameters. 
divLabelTX :: T.Text -> T.Text -> T.Text -> X.Node 
divLabelTX title r c = X.Element "div" [("class", "required")] 
    [ X.Element "label" [("for","ots")] 
     [X.TextNode title] 
    , X.Element "textarea" 
     [("id","ots"), ("name","ots"), ("cols",c), ("rows",r)] 
     [X.TextNode " "] 
    ] 

-- | Internal, this can be used in splice-definition. 
-- TODO! ids and names could be parameters, too. 
nicTextAreaAdd :: MonadSnap m => T.Text -> (Int,Int) -> I.Splice m 
nicTextAreaAdd title (r,c) = return [divLabelTX 
    title 
    (T.pack . show $ r) 
    (T.pack . show $ c)] 

-- | Add script-tags to web page with splice that tell, what javascript 
-- library to use... 
nicEditAdd :: MonadSnap m => T.Text -> T.Text -> I.Splice m 
nicEditAdd src edElems = return (srcElem src : [srcOnLoad edElems]) 

------------------------------------------------------------------------------ 

-- | Get the route to the javascript library that is applied (either local 
-- library or construct a link to a web address). 
nicRoute :: Nicsnap -> T.Text 
nicRoute ns = let mlR = ns ^. localR in fromMaybe (ns ^. webR) mlR 

------------------------------------------------------------------------------ 

-- | neTextAreaTag and neScripTag are used in addSplices to define the tags 
-- to be used in templates. 
-- What other tags could be useful? Maybe a way to add a nicEditor directly 
-- with one or more button bind to it ("send", "clear", etc). TODO! 
neTextAreaTag = "neTA"  :: T.Text 
neScriptTag = "neScript" :: T.Text 

-- | Make the tags to be used in templates. At the moment, only the above 
-- tags are defined. 
addNicEditSplices :: HasHeist b => Snaplet Nicsnap -> Initializer b v() 
addNicEditSplices n = let m = view snapletValue n in addSplices 
    [(neTextAreaTag, nicTextAreaAdd (m ^. nicsnap) (m ^. areaSize)) 
    ,(neScriptTag, nicEditAdd (nicRoute m) (m ^. areaRef)) 
    ] 
------------------------------------------------------------------------------ 

回答

1

我不是一个新手,所以我不能回答你的第一个问题,但我有一些想法和解答一些其他人。首先,如果你真的希望这是一个严重的问题(无论是出于教学目的还是实际使用),你应该把它变成一个小型项目。这将消除您的指示中的第2步。接下来,snaplets可以定义他们自己的路线。您可以通过调用addRoutes函数在初始化程序中执行此操作。这将消除步骤8. Snaplets还可以提供自己的文件系统资源,这些资源将被复制到使用它的任何项目中。您可以使用此功能来消除步骤10,并提供默认配置文件。有关如何执行此操作的更多信息,请参阅snaplet教程末尾的filesystem data and automatic installation部分。

目前,snaplet-postgresql-simple可能是关于如何使用snaplets必须提供的大多数功能的最佳示例。如果你想使它成为其他人使用的真正强大的通用目标,那么你肯定应该包括解释和编译的拼接。我最近在快照包中添加了一些new functions,这使得编写自动工作在编译或解释模式下的通用snaplets变得更加容易。这段代码还没有破解,但我很快就会发布它。

我也一直在研究another snaplet,它更全面地使用了snaplet API的大部分功能。与snaplet-postgresql-simple不同,这个snaplet定义了模板和拼接。它仍在开发中,但已经展示了大部分功能。其余的工作将主要是抛光和坚固。

+0

再次感谢!我不得不多次阅读文件系统数据部分,并与cabal有一些困难。现在它似乎安装,我可以像其他库一样使用。 – Gspia 2013-03-19 21:33:03

+0

接下来的问题是,我做了一些清理工作后,如何处理这个软件包。 (这是否应该放到github?)另一个问题是,现在路由在地址的末尾需要/ -char。如何使这个接受也是一个没有结束/ -char的地址? – Gspia 2013-03-19 21:39:54

+1

如果您认为其他人可以从中受益,那么通常的做法是将其放在github和hackage上。没有更多信息,我无法回答第二个问题。 – mightybyte 2013-03-20 14:19:07