web: cleanup, enable jquery, use auto-completing combo fields on add form

This commit is contained in:
Simon Michael 2010-08-10 00:13:47 +00:00
parent f3ffef2d8a
commit 8c8395778c
4 changed files with 415 additions and 234 deletions

View File

@ -12,6 +12,7 @@ import System.FilePath ((</>), takeFileName)
import System.IO.Storage (withStore, putValue, getValue)
import Text.ParserCombinators.Parsec (parse)
import Yesod
import Yesod.Helpers.Static
import Hledger.Cli.Commands.Add (journalAddTransaction)
import Hledger.Cli.Commands.Balance
@ -28,36 +29,43 @@ import Paths_hledger_make (getDataFileName)
#else
import Paths_hledger (getDataFileName)
#endif
-- import Hledger.Cli.Commands.Web.Templates
defhost = "localhost"
defport = 5000
defbaseurl = printf "http://%s:%d" defhost defport :: String
defhost = "localhost"
defport = 5000
browserstartdelay = 100000 -- microseconds
hledgerurl = "http://hledger.org"
manualurl = hledgerurl++"/MANUAL.html"
hledgerorgurl = "http://hledger.org"
manualurl = hledgerorgurl++"/MANUAL.html"
data HledgerWebApp = HledgerWebApp {
appRoot :: String
,appWebdir :: FilePath
,appDir :: FilePath
,appOpts :: [Opt]
,appArgs :: [String]
,appJournal :: Journal
,appStatic :: Static
}
mkYesod "HledgerWebApp" [$parseRoutes|
/ IndexPage GET
/style.css StyleCss GET
/journalonly JournalOnlyPage GET POST
/registeronly RegisterOnlyPage GET
/accounts AccountsPage GET
/journal AccountsJournalPage GET POST
/register AccountsRegisterPage GET POST
/static StaticR Static appStatic
/ IndexR GET
/journalonly JournalOnlyR GET POST
/registeronly RegisterOnlyR GET
/accounts AccountsOnlyR GET
/journal JournalR GET POST
/register RegisterR GET POST
|]
style_css = StaticRoute ["style.css"]
hledger_js = StaticRoute ["hledger.js"]
jquery_js = StaticRoute ["jquery.js"]
dhtmlxcommon_js = StaticRoute ["dhtmlxcommon.js"]
dhtmlxcombo_js = StaticRoute ["dhtmlxcombo.js"]
instance Yesod HledgerWebApp where approot = appRoot
defaultpage = AccountsJournalPage
defaultroute = JournalR
-- | A bundle of useful data passed to templates.
data TemplateData = TD {
@ -71,7 +79,7 @@ data TemplateData = TD {
}
mktd = TD {
here = IndexPage
here = IndexR
,title = "hledger"
,msg = Nothing
,a = ""
@ -83,8 +91,9 @@ mktd = TD {
-- | The web command.
web :: [Opt] -> [String] -> Journal -> IO ()
web opts args j = do
let baseurl = fromMaybe defbaseurl $ baseUrlFromOpts opts
port = fromMaybe defport $ portFromOpts opts
let host = defhost
port = fromMaybe defport $ portFromOpts opts
baseurl = fromMaybe (printf "http://%s:%d" host port) $ baseUrlFromOpts opts
unless (Debug `elem` opts) $ forkIO (browser baseurl) >> return ()
server baseurl port opts args j
@ -98,10 +107,11 @@ browser baseurl = do
server :: String -> Int -> [Opt] -> [String] -> Journal -> IO ()
server baseurl port opts args j = do
printf "starting web server on port %d with base url %s\n" port baseurl
fp <- getDataFileName "web"
dir <- getDataFileName "web"
let app = HledgerWebApp{
appRoot=baseurl
,appWebdir=fp
,appDir=dir
,appStatic=fileLookupDir (dir </> "static") $ typeByExt -- ++[("hamlet","text/plain")]
,appOpts=opts
,appArgs=args
,appJournal=j
@ -156,22 +166,14 @@ getHandlerParameters = do
----------------------------------------------------------------------
-- handlers & templates
getStyleCss :: Handler HledgerWebApp ()
getStyleCss = do
app <- getYesod
let dir = appWebdir app
sendFile "text/css" $ dir </> "style.css"
----------------------------------------------------------------------
getIndexPage :: Handler HledgerWebApp ()
getIndexPage = redirect RedirectTemporary defaultpage
getIndexR :: Handler HledgerWebApp ()
getIndexR = redirect RedirectTemporary defaultroute
----------------------------------------------------------------------
-- | A combined accounts and journal view.
getAccountsJournalPage :: Handler HledgerWebApp RepHtml
getAccountsJournalPage = do
getJournalR :: Handler HledgerWebApp RepHtml
getJournalR = do
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
today <- liftIO getCurrentDay
-- app <- getYesod
@ -183,11 +185,10 @@ getAccountsJournalPage = do
td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
editform' = editform td $ jtext j
hamletToRepHtml $ pageLayout td [$hamlet|
^scripts^
%div.ledger
%div.accounts!style=float:left; ^br^
^navlinks.td^
^addform^
^addform.td^
^editform'^
^importform^
%div#transactions.journal
@ -195,14 +196,14 @@ getAccountsJournalPage = do
^jr^
|]
postAccountsJournalPage :: Handler HledgerWebApp RepPlain
postAccountsJournalPage = postJournalOnlyPage
postJournalR :: Handler HledgerWebApp RepPlain
postJournalR = postJournalOnlyR
----------------------------------------------------------------------
-- | A combined accounts and register view.
getAccountsRegisterPage :: Handler HledgerWebApp RepHtml
getAccountsRegisterPage = do
getRegisterR :: Handler HledgerWebApp RepHtml
getRegisterR = do
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
today <- liftIO getCurrentDay
-- app <- getYesod
@ -215,11 +216,10 @@ getAccountsRegisterPage = do
td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
editform' = editform td $ jtext j
hamletToRepHtml $ pageLayout td [$hamlet|
^scripts^
%div.ledger
%div.accounts!style=float:left; ^br^
^navlinks.td^
^addform^
^addform.td^
^editform'^
^importform^
%div#transactions.register
@ -227,14 +227,14 @@ getAccountsRegisterPage = do
^rr^
|]
postAccountsRegisterPage :: Handler HledgerWebApp RepPlain
postAccountsRegisterPage = postJournalOnlyPage
postRegisterR :: Handler HledgerWebApp RepPlain
postRegisterR = postJournalOnlyR
----------------------------------------------------------------------
-- | A simple accounts and balances view like hledger balance.
getAccountsPage :: Handler HledgerWebApp RepHtml
getAccountsPage = do
getAccountsOnlyR :: Handler HledgerWebApp RepHtml
getAccountsOnlyR = do
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
today <- liftIO getCurrentDay
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
@ -308,8 +308,8 @@ isAccountRegex s = take 1 s == "^" && (take 5 $ reverse s) == ")$|:("
----------------------------------------------------------------------
-- | A basic journal view, like hledger print, with editing.
getJournalOnlyPage :: Handler HledgerWebApp RepHtml
getJournalOnlyPage = do
getJournalOnlyR :: Handler HledgerWebApp RepHtml
getJournalOnlyR = do
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
today <- liftIO getCurrentDay
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
@ -317,12 +317,11 @@ getJournalOnlyPage = do
txns = journalReportAsHtml opts td $ journalReport opts fspec j
hamletToRepHtml $ pageLayout td [$hamlet|
%div.journal
^scripts^
%div.nav2
%a#addformlink!href!onclick="return addformToggle()" add one transaction
\ | $
%a#editformlink!href!onclick="return editformToggle()" edit the whole journal
^addform^
^addform.td^
^editform'^
#transactions ^txns^
|]
@ -346,9 +345,25 @@ journalReportAsHtml _ td items = [$hamlet|
evenodd = if even n then "even" else "odd"
txn = trimnl $ showTransaction t where trimnl = reverse . dropWhile (=='\n') . reverse
addform :: Hamlet HledgerWebAppRoute
addform = [$hamlet|
%form#addform!method=POST!style=display:none;
addform :: TemplateData -> Hamlet HledgerWebAppRoute
addform td = [$hamlet|
%script!type=text/javascript
$$(document).ready(function() {
/* dhtmlxcombo setup */
window.dhx_globalImgPath="../static/images/";
var desccombo = new dhtmlXCombo("description");
var acct1combo = new dhtmlXCombo("account1");
var acct2combo = new dhtmlXCombo("account2");
desccombo.enableFilteringMode(true);
acct1combo.enableFilteringMode(true);
acct2combo.enableFilteringMode(true);
desccombo.setSize(300);
acct1combo.setSize(300);
acct2combo.setSize(300);
/* desccombo.enableOptionAutoHeight(true, 20); */
/* desccombo.setOptionHeight(200); */
});
%form#addform!method=POST!style=display:none;
%table.form
%tr
%td!colspan=4
@ -361,7 +376,10 @@ addform = [$hamlet|
%td!style=padding-left:1em;
Description:
%td
%input.textinput!size=35!name=description!value=$desc$
%select!id=description!name=description
%option
$forall descriptions d
%option!value=$d$ $d$
%tr.helprow
%td
%td
@ -369,8 +387,7 @@ addform = [$hamlet|
%td
%td
.help $deschelp$
^transactionfields1^
^transactionfields2^
^postingsfields.td^
%tr#addbuttonrow
%td!colspan=4
%input!type=hidden!name=action!value=add
@ -378,20 +395,29 @@ addform = [$hamlet|
|]
where
-- datehelplink = helplink "dates" "..."
datehelp = "eg: 7/20, 2010/1/1, "
datehelp = "eg: 2010/7/20"
deschelp = "eg: supermarket (optional)"
date = "today"
desc = ""
transactionfields1 = transactionfields 1
transactionfields2 = transactionfields 2
descriptions = sort $ nub $ map tdescription $ jtxns $ j td
transactionfields :: Int -> Hamlet HledgerWebAppRoute
transactionfields n = [$hamlet|
postingsfields :: TemplateData -> Hamlet HledgerWebAppRoute
postingsfields td = [$hamlet|
^p1^
^p2^
|]
where
p1 = postingfields td 1
p2 = postingfields td 2
postingfields :: TemplateData -> Int -> Hamlet HledgerWebAppRoute
postingfields td n = [$hamlet|
%tr#postingrow
%td!align=right
$label$:
%td!align=right $acctlabel$:
%td
%input.textinput!size=35!name=$acctvar$!value=$acct$
%select!id=$acctvar$!name=$acctvar$
%option
$forall acctnames a
%option!value=$a$ $a$
^amtfield^
%tr.helprow
%td
@ -402,24 +428,26 @@ transactionfields n = [$hamlet|
.help $amthelp$
|]
where
label | n == 1 = "To account"
| otherwise = "From account"
accthelp | n == 1 = "eg: expenses:food"
| otherwise = "eg: assets:bank:checking"
amtfield | n == 1 = [$hamlet|
numbered = (++ show n)
acctvar = numbered "account"
amtvar = numbered "amount"
acctnames = sort $ journalAccountNamesUsed $ j td
(acctlabel, accthelp, amtfield, amthelp)
| n == 1 = ("To account"
,"eg: expenses:food"
,[$hamlet|
%td!style=padding-left:1em;
Amount:
%td
%input.textinput!size=15!name=$amtvar$!value=$amt$
%input.textinput!size=15!name=$amtvar$!value=""
|]
| otherwise = nulltemplate
amthelp | n == 1 = "eg: 5, $6, €7.01"
| otherwise = ""
acct = ""
amt = ""
numbered = (++ show n)
acctvar = numbered "accountname"
amtvar = numbered "amount"
,"eg: $6"
)
| otherwise = ("From account"
,"eg: assets:bank:checking"
,nulltemplate
,""
)
editform :: TemplateData -> String -> Hamlet HledgerWebAppRoute
editform _ content = [$hamlet|
@ -455,142 +483,8 @@ importform = [$hamlet|
%a!href!onclick="return importformToggle()" cancel
|]
scripts = [$hamlet|
<script type="text/javascript">
function filterformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (f.style.display == 'none') {
flink.style['font-weight'] = 'bold';
f.style.display = 'block';
} else {
flink.style['font-weight'] = 'normal';
f.style.display = 'none';
}
return false;
}
function addformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (a.style.display == 'none') {
alink.style['font-weight'] = 'bold';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
jlink.style['font-weight'] = 'normal';
rlink.style['font-weight'] = 'normal';
a.style.display = 'block';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'none';
} else {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'block';
}
return false;
}
function editformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (e.style.display == 'none') {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'bold';
ilink.style['font-weight'] = 'normal';
jlink.style['font-weight'] = 'normal';
rlink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'block';
i.style.display = 'none';
t.style.display = 'none';
} else {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'block';
}
return false;
}
function importformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (i.style.display == 'none') {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'bold';
jlink.style['font-weight'] = 'normal';
rlink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'block';
t.style.display = 'none';
} else {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'block';
}
return false;
}
</script>
|]
postJournalOnlyPage :: Handler HledgerWebApp RepPlain
postJournalOnlyPage = do
postJournalOnlyR :: Handler HledgerWebApp RepPlain
postJournalOnlyR = do
action <- runFormPost' $ maybeStringInput "action"
case action of Just "edit" -> postEditForm
Just "import" -> postImportForm
@ -606,9 +500,9 @@ postAddForm = do
$ (,,,,,)
<$> maybeStringInput "date"
<*> maybeStringInput "description"
<*> maybeStringInput "accountname1"
<*> maybeStringInput "account1"
<*> maybeStringInput "amount1"
<*> maybeStringInput "accountname2"
<*> maybeStringInput "account2"
<*> maybeStringInput "amount2"
-- supply defaults and parse date and amounts, or get errors.
let dateE = maybe (Left "date required") (either (\e -> Left $ showDateParseError e) Right . fixSmartDateStrEither today) dateM
@ -643,14 +537,14 @@ postAddForm = do
Left errs -> do
-- save current form values in session
setMessage $ string $ intercalate "; " errs
redirect RedirectTemporary AccountsRegisterPage
redirect RedirectTemporary RegisterR
Right t -> do
let t' = txnTieKnot t -- XXX move into balanceTransaction
j <- liftIO $ fromJust `fmap` getValue "hledger" "journal"
liftIO $ journalAddTransaction j opts t'
setMessage $ string $ printf "Added transaction:\n%s" (show t')
redirect RedirectTemporary AccountsRegisterPage
redirect RedirectTemporary RegisterR
-- | Handle a journal edit form post.
postEditForm :: Handler HledgerWebApp RepPlain
@ -663,7 +557,7 @@ postEditForm = do
Left errs -> do
-- XXX should save current form values in session
setMessage $ string errs
redirect RedirectTemporary AccountsJournalPage
redirect RedirectTemporary JournalR
Right t' -> do
-- try to avoid unnecessary backups or saving invalid data
@ -677,24 +571,24 @@ postEditForm = do
if not changed
then do
setMessage $ string $ "No change"
redirect RedirectTemporary AccountsJournalPage
redirect RedirectTemporary JournalR
else do
jE <- liftIO $ journalFromPathAndString Nothing f tnew
either
(\e -> do
setMessage $ string e
redirect RedirectTemporary AccountsJournalPage)
redirect RedirectTemporary JournalR)
(const $ do
liftIO $ writeFileWithBackup f tnew
setMessage $ string $ printf "Saved journal %s\n" (show f)
redirect RedirectTemporary AccountsJournalPage)
redirect RedirectTemporary JournalR)
jE
-- | Handle an import page post.
postImportForm :: Handler HledgerWebApp RepPlain
postImportForm = do
setMessage $ string $ "can't handle file upload yet"
redirect RedirectTemporary AccountsJournalPage
redirect RedirectTemporary JournalR
-- -- get form input values, or basic validation errors. E means an Either value.
-- fileM <- runFormPost' $ maybeFileInput "file"
-- let fileE = maybe (Left "No file provided") Right fileM
@ -702,17 +596,17 @@ postImportForm = do
-- case fileE of
-- Left errs -> do
-- setMessage $ string errs
-- redirect RedirectTemporary AccountsJournalPage
-- redirect RedirectTemporary JournalR
-- Right s -> do
-- setMessage $ string $ s
-- redirect RedirectTemporary AccountsJournalPage
-- redirect RedirectTemporary JournalR
----------------------------------------------------------------------
-- | A simple postings view like hledger register.
getRegisterOnlyPage :: Handler HledgerWebApp RepHtml
getRegisterOnlyPage = do
getRegisterOnlyR :: Handler HledgerWebApp RepHtml
getRegisterOnlyR = do
(a, p, opts, fspec, j, msg, here) <- getHandlerParameters
today <- liftIO getCurrentDay
let td = mktd{here=here, title="hledger", msg=msg, a=a, p=p, j=j, today=today}
@ -753,8 +647,8 @@ mixedAmountAsHtml b = preEscapedString $ addclass $ intercalate "<br>" $ lines $
----------------------------------------------------------------------
-- | A standalone journal edit form page.
getEditPage :: Handler HledgerWebApp RepHtml
getEditPage = do
getEditR :: Handler HledgerWebApp RepHtml
getEditR = do
(a, p, _, _, _, msg, here) <- getHandlerParameters
today <- liftIO getCurrentDay
-- reload journal's text without parsing, if changed -- XXX are we doing this right ?
@ -774,7 +668,11 @@ pageLayout td@TD{title=title, msg=msg} content = [$hamlet|
%head
%title $title$
%meta!http-equiv=Content-Type!content=$metacontent$
%link!rel=stylesheet!type=text/css!href=@StyleCss@!media=all
%script!type=text/javascript!src=@StaticR.jquery_js@
%script!type=text/javascript!src=@StaticR.dhtmlxcommon_js@
%script!type=text/javascript!src=@StaticR.dhtmlxcombo_js@
%script!type=text/javascript!src=@StaticR.hledger_js@
%link!rel=stylesheet!type=text/css!media=all!href=@StaticR.style_css@
%body
^navbar.td^
#messages $m$
@ -787,7 +685,7 @@ pageLayout td@TD{title=title, msg=msg} content = [$hamlet|
navbar :: TemplateData -> Hamlet HledgerWebAppRoute
navbar TD{p=p,j=j,today=today} = [$hamlet|
#navbar
%a.topleftlink!href=$hledgerurl$
%a.topleftlink!href=$hledgerorgurl$
hledger
<br />
$version$
@ -817,8 +715,8 @@ navlinks td = [$hamlet|
|]
-- \ | $
where
accountsjournallink = navlink td "journal" AccountsJournalPage
accountsregisterlink = navlink td "register" AccountsRegisterPage
accountsjournallink = navlink td "journal" JournalR
accountsregisterlink = navlink td "register" RegisterR
navlink :: TemplateData -> String -> HledgerWebAppRoute -> Hamlet HledgerWebAppRoute
navlink TD{here=here,a=a,p=p} s dest = [$hamlet|%a#$s$link.$style$!href=@?u@ $s$|]

135
data/web/static/hledger.js Normal file
View File

@ -0,0 +1,135 @@
/* hledger web ui javascripts */
/* depends on jquery, other support libs, and additional js inserted inline */
$(document).ready(function() {
});
function filterformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (f.style.display == 'none') {
flink.style['font-weight'] = 'bold';
f.style.display = 'block';
} else {
flink.style['font-weight'] = 'normal';
f.style.display = 'none';
}
return false;
}
function addformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (a.style.display == 'none') {
alink.style['font-weight'] = 'bold';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
jlink.style['font-weight'] = 'normal';
rlink.style['font-weight'] = 'normal';
a.style.display = 'block';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'none';
} else {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'block';
}
return false;
}
function editformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (e.style.display == 'none') {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'bold';
ilink.style['font-weight'] = 'normal';
jlink.style['font-weight'] = 'normal';
rlink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'block';
i.style.display = 'none';
t.style.display = 'none';
} else {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'block';
}
return false;
}
function importformToggle() {
var a = document.getElementById('addform');
var e = document.getElementById('editform');
var f = document.getElementById('filterform');
var i = document.getElementById('importform');
var t = document.getElementById('transactions');
var alink = document.getElementById('addformlink');
var elink = document.getElementById('editformlink');
var flink = document.getElementById('filterformlink');
var ilink = document.getElementById('importformlink');
var jlink = document.getElementById('journallink');
var rlink = document.getElementById('registerlink');
if (i.style.display == 'none') {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'bold';
jlink.style['font-weight'] = 'normal';
rlink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'block';
t.style.display = 'none';
} else {
alink.style['font-weight'] = 'normal';
elink.style['font-weight'] = 'normal';
ilink.style['font-weight'] = 'normal';
a.style.display = 'none';
e.style.display = 'none';
i.style.display = 'none';
t.style.display = 'block';
}
return false;
}

View File

@ -4,7 +4,7 @@
/* overspecified for cross-browser robustness */
body { font-family:helvetica,arial,"sans serif"; }
pre { font-family:courier,"courier new",monospace; }
#addform input.textinput { font-family:courier,"courier new",monospace; font-size:small; }
input.textinput, .dhx_combo_input, .dhx_combo_list { font-size:small; }
#editform textarea { font-family:courier,"courier new",monospace; font-size:small; }
.nav2 { font-size:small; }
#filterform { font-size:small; }
@ -75,9 +75,152 @@ table.registerreport { border-spacing:0; }
.firstposting td { }
.registerreport .odd { background-color:#f0f0f0; }
#addform input.textinput { background-color:#eee; padding:4px; }
#addform input.textinput, #addform .dhx_combo_input, .dhx_combo_list { background-color:#eee; padding:4px; }
#addform table { }
#addform #addbuttonrow { text-align:right; }
/* #editform { width:95%; } */
#editform textarea { width:100%; background-color:#eee; padding:4px; }
#filterform table { border-spacing:0; padding-left:1em; }
/*------------------------------------------------------------------------------------------*/
.dhx_combo_input{
/* color:#333333; */
/* font-family: Arial; */
/* font-size: 9pt; */
/* border:0px; */
/* padding:2px 2px 2px 2px; */
/* position:absolute; */
/* top:0px; */
}
/* table {border:thin solid red} */
/* div {border:thin solid yellow} */
.dhx_combo_box{
position:relative;
display:inline-block;
/* text-align:left; */
/* height:20px; */
/* _height:22px; */
/* overflow:hidden; */
/* background-color: white; */
}
.dhx_combo_list{
position:absolute;
z-index:230;
overflow-y:auto;
overflow-x:hidden;
white-space:nowrap;
border:1px solid black;
height:50%;
/* background-color: white; */
}
.dhx_combo_list div{
cursor:default;
padding:2px 2px 2px 2px;
}
.dhx_selected_option{
background-color:navy;
color:white;
}
.dhx_combo_img{
/* display:none; */
width:18px;
height:20px;
position:absolute;
top:12px;
right:-10px;
}
.dhx_combo_option_img{
position:relative;
top:1px;
margin:0px;
margin-left:2px;
left:0px;
width:18px; height:18px;
}
/* .combo_dhx_sel{ */
/* .dhx_selected_option{ */
/* background-image: url("../static/images/bg_selection.gif") !important; */
/* background-position: bottom; */
/* background-repeat: repeat-x; */
/* color:black; */
/* } */
/* .dhx_combo_img_rtl{ */
/* position:absolute; */
/* top:0px; */
/* left:1px; */
/* width:17px; */
/* height:20px; */
/* } */
/* .dhx_combo_option_img_rtl{ */
/* float:right; */
/* margin-right :0px; */
/* width:18px; height:18px; */
/* } */
/* .dhx_combo_list_rtl{ */
/* direction: rtl; */
/* unicode-bidi : bidi-override; */
/* position:absolute; */
/* z-index:230; */
/* overflow-y:auto; */
/* overflow-x:hidden; */
/* border:1px solid black; */
/* height:100px; */
/* /\* font-family: Arial; *\/ */
/* font-size: 9pt; */
/* background-color: white; */
/* } */
/* .dhx_combo_list_rtl div{ */
/* direction: rtl; */
/* unicode-bidi : bidi-override; */
/* padding:2px 2px 2px 2px; */
/* } */
/* .dhx_combo_list_rtl div div{ */
/* float :right !important; */
/* cursor:default; */
/* } */
/* .dhx_combo_list_rtl div img{ */
/* float :right !important; */
/* } */
/* .dhx_combo_list_rtl div input{ */
/* float :right !important; */
/* } */
/* .dhx_combo_box.dhx_skyblue{ */
/* border:1px solid #a4bed4; */
/* } */
/* .dhx_combo_box.dhx_skyblue .dhx_combo_input { */
/* font-family:Tahoma; */
/* font-size: 11px; */
/* padding:3px; */
/* } */
/* .dhx_combo_list.dhx_skyblue_list{ */
/* background-color: #eaf2fb; */
/* border:1px solid #a4bed4; */
/* font-family:Tahoma; */
/* font-size: 11px; */
/* } */
/* .dhx_combo_list.dhx_skyblue_list div{ */
/* cursor:default; */
/* padding:3px 4px; */
/* } */
/* .dhx_combo_list_rtl.dhx_skyblue_list{ */
/* background-color: #eaf2fb; */
/* border:1px solid #a4bed4; */
/* font-family:Tahoma; */
/* font-size: 11px; */
/* } */

View File

@ -23,7 +23,12 @@ cabal-version: >= 1.2
build-type: Custom
data-dir: data
data-files:
web/style.css
web/static/style.css
web/static/hledger.js
web/static/jquery.js
web/static/dhtmlxcommon.js
web/static/dhtmlxcombo.js
web/static/images/combo_select.gif
extra-tmp-files:
extra-source-files:
README.rst