2013-03-17 4 views
2

아래 예제는 nicEditor를 textarea에 바인딩하는 스냅 숏을 정의합니다. 다음 질문은 아래 예와 관련이있을뿐만 아니라 다른 유사 사례와 관련이있을 수 있습니다.nicEditor 스냅 릿을 만드는 방법은 무엇입니까? (몇 가지 질문들)

  1. 초보자는 다음 지침 (명확하게 설명하는 방법)을 따를 수 있습니까?
  2. 예제를 사용하여 단계를 줄이거 나 간단하게 만드는 방법은 무엇입니까? (아래 내용과 거의 같은 내용입니까?)
  3. 이것은 해석 된 스플 라이스를 사용했습니다. 가능한 경우 스냅 릿이 컴파일 된 스플 라이스를 제공해야합니까?
  4. 아마도 스냅 릿은 일반적인 상황에 대해 기본 처리기 또는 몇 개의 처리기를 제공 할 수 있습니다. 그리고 핸들러는 아래의 "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 단계가 생략됩니다. 다음으로, 스냅 릿은 자체 라우트를 정의 할 수 있습니다. addRoutes 함수를 호출하여 이니셜 라이저에서이를 수행 할 수 있습니다. 이렇게하면 8 단계가 생략됩니다. 스냅 릿은 자체 파일 시스템 리소스를 제공하여이를 사용하는 모든 프로젝트에 복사합니다. 이 기능을 사용하여 10 단계를 생략하고 기본 구성 파일을 제공 할 수 있습니다. 이를 수행하는 방법에 대한 자세한 내용은 스냅 숏 자습서 끝 부분의 filesystem data and automatic installation 섹션을 참조하십시오.

현재, snaplet-postgresql-simple은 아마도 스냅 릿이 제공해야하는 대부분의 기능을 사용하는 방법에 대한 해킹에 대한 가장 좋은 예일 것입니다. 이것을 다른 사람들이 사용할 수있는 견고한 범용 스냅 숏으로 만들고 싶다면 반드시 인터프리터와 컴파일 된 스플 라이스를 모두 포함해야합니다. 필자는 최근 컴파일 된 또는 해석 된 스플 라이스 모드에서 자동으로 작동하는 일반 스냅 릿을 작성하기 쉽게 만드는 스냅 패키지에 new functions을 추가했습니다. 이 코드는 아직 해커가 아니지만 곧 공개 할 예정입니다.

나는 또한 another snaplet에서 작업하여 snaplet API의 대부분의 기능을 훨씬 더 광범위하게 사용하고 있습니다. snaplet-postgresql-simple과 달리이 스냅 릿은 템플릿과 스플 라이스를 정의합니다. 아직 개발 중이지만 이미 대부분의 기능을 보여줍니다. 남은 작품은 대부분 폴란드어와 견고 함이 될 것입니다.

+0

다시 한번 감사드립니다. 나는 파일 시스템 데이터 섹션을 여러 번 읽어야했고, 캐벌과 함께 힘든 시간을 보냈다. 이제 설치하는 것처럼 보이고 다른 라이브러리와 마찬가지로 사용할 수 있습니다. – Gspia

+0

그리고 계속해서, 다음 질문은 청소를 한 후에이 패키지로 무엇을 할 것인지입니다. (이것은 github에 넣어야할까요?) 또 다른 질문은 이제 주소 끝에/-char가 필요하다는 것입니다. 이것은/-char를 끝내지 않고 주소를 받아들이는 방법? – Gspia

+1

다른 사람들이 이로부터 혜택을 볼 수 있다고 생각한다면 일반적인 접근 방법은 그것을 github과 hackage에 두는 것입니다. 나는 더 많은 정보없이 두 번째 질문에 대답 할 수 없다. – mightybyte