123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- {-# LANGUAGE QuasiQuotes #-}
- {-# LANGUAGE TypeFamilies #-}
- {-# LANGUAGE FlexibleContexts #-}
- {-# LANGUAGE OverloadedStrings #-}
- -- | Some fields spiced up with jQuery UI.
- module Yesod.Form.Jquery
- ( YesodJquery (..)
- , jqueryDayField
- , jqueryDatePickerDayField
- , jqueryAutocompleteField
- , jqueryAutocompleteField'
- , googleHostedJqueryUiCss
- , JqueryDaySettings (..)
- , Default (..)
- ) where
- import Yesod.Core
- import Yesod.Form
- import Data.Time (Day)
- import Data.Default
- import Text.Hamlet (shamlet)
- import Text.Julius (julius, rawJS)
- import Data.Text (Text, pack, unpack)
- import Data.Monoid (mconcat)
- -- | Gets the Google hosted jQuery UI 1.8 CSS file with the given theme.
- googleHostedJqueryUiCss :: Text -> Text
- googleHostedJqueryUiCss theme = mconcat
- [ "//ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/"
- , theme
- , "/jquery-ui.css"
- ]
- class YesodJquery a where
- -- | The jQuery Javascript file. Note that in upgrades to this library, the
- -- version of jQuery referenced, or where it is downloaded from, may be
- -- changed without warning. If you are relying on a specific version of
- -- jQuery, you should give an explicit URL instead of relying on the
- -- default value.
- --
- -- Currently, the default value is jQuery 1.7 from Google\'s CDN.
- urlJqueryJs :: a -> Either (Route a) Text
- urlJqueryJs _ = Right "//ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"
- -- | The jQuery UI 1.8 Javascript file.
- urlJqueryUiJs :: a -> Either (Route a) Text
- urlJqueryUiJs _ = Right "//ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js"
- -- | The jQuery UI 1.8 CSS file; defaults to cupertino theme.
- urlJqueryUiCss :: a -> Either (Route a) Text
- urlJqueryUiCss _ = Right $ googleHostedJqueryUiCss "cupertino"
- -- | jQuery UI time picker add-on.
- urlJqueryUiDateTimePicker :: a -> Either (Route a) Text
- urlJqueryUiDateTimePicker _ = Right "http://github.com/gregwebs/jquery.ui.datetimepicker/raw/master/jquery.ui.datetimepicker.js"
- jqueryDayField :: (RenderMessage site FormMessage, YesodJquery site) => JqueryDaySettings -> Field (HandlerT site IO) Day
- jqueryDayField = flip jqueryDayField' "date"
- -- | Use jQuery's datepicker as the underlying implementation.
- --
- -- Since 1.4.3
- jqueryDatePickerDayField :: (RenderMessage site FormMessage, YesodJquery site) => JqueryDaySettings -> Field (HandlerT site IO) Day
- jqueryDatePickerDayField = flip jqueryDayField' "text"
- jqueryDayField' :: (RenderMessage site FormMessage, YesodJquery site) => JqueryDaySettings -> Text -> Field (HandlerT site IO) Day
- jqueryDayField' jds inputType = Field
- { fieldParse = parseHelper $ maybe
- (Left MsgInvalidDay)
- Right
- . readMay
- . unpack
- , fieldView = \theId name attrs val isReq -> do
- toWidget [shamlet|
- $newline never
- <input id="#{theId}" name="#{name}" *{attrs} type="#{inputType}" :isReq:required="" value="#{showVal val}">
- |]
- addScript' urlJqueryJs
- addScript' urlJqueryUiJs
- addStylesheet' urlJqueryUiCss
- toWidget [julius|
- $(function(){
- var i = document.getElementById("#{rawJS theId}");
- if (i.type != "date") {
- $(i).datepicker({
- dateFormat:'yy-mm-dd',
- changeMonth:#{jsBool $ jdsChangeMonth jds},
- changeYear:#{jsBool $ jdsChangeYear jds},
- numberOfMonths:#{rawJS $ mos $ jdsNumberOfMonths jds},
- yearRange:#{toJSON $ jdsYearRange jds}
- });
- }
- });
- |]
- , fieldEnctype = UrlEncoded
- }
- where
- showVal = either id (pack . show)
- jsBool True = toJSON True
- jsBool False = toJSON False
- mos (Left i) = show i
- mos (Right (x, y)) = concat
- [ "["
- , show x
- , ","
- , show y
- , "]"
- ]
- jqueryAutocompleteField :: (RenderMessage site FormMessage, YesodJquery site)
- => Route site -> Field (HandlerT site IO) Text
- jqueryAutocompleteField = jqueryAutocompleteField' 2
- jqueryAutocompleteField' :: (RenderMessage site FormMessage, YesodJquery site)
- => Int -- ^ autocomplete minimum length
- -> Route site
- -> Field (HandlerT site IO) Text
- jqueryAutocompleteField' minLen src = Field
- { fieldParse = parseHelper $ Right
- , fieldView = \theId name attrs val isReq -> do
- toWidget [shamlet|
- $newline never
- <input id="#{theId}" name="#{name}" *{attrs} type="text" :isReq:required="" value="#{either id id val}" .autocomplete>
- |]
- addScript' urlJqueryJs
- addScript' urlJqueryUiJs
- addStylesheet' urlJqueryUiCss
- toWidget [julius|
- $(function(){$("##{rawJS theId}").autocomplete({source:"@{src}",minLength:#{toJSON minLen}})});
- |]
- , fieldEnctype = UrlEncoded
- }
- addScript' :: (HandlerSite m ~ site, MonadWidget m) => (site -> Either (Route site) Text) -> m ()
- addScript' f = do
- y <- getYesod
- addScriptEither $ f y
- addStylesheet' :: (MonadWidget m, HandlerSite m ~ site)
- => (site -> Either (Route site) Text)
- -> m ()
- addStylesheet' f = do
- y <- getYesod
- addStylesheetEither $ f y
- readMay :: Read a => String -> Maybe a
- readMay s = case reads s of
- (x, _):_ -> Just x
- [] -> Nothing
- data JqueryDaySettings = JqueryDaySettings
- { jdsChangeMonth :: Bool
- , jdsChangeYear :: Bool
- , jdsYearRange :: String
- , jdsNumberOfMonths :: Either Int (Int, Int)
- }
- instance Default JqueryDaySettings where
- def = JqueryDaySettings
- { jdsChangeMonth = False
- , jdsChangeYear = False
- , jdsYearRange = "c-10:c+10"
- , jdsNumberOfMonths = Left 1
- }
|