From 529f792d338c75910079903e143d4dd21bd806c3 Mon Sep 17 00:00:00 2001 From: pho Date: Tue, 5 Feb 2008 16:25:10 +0900 Subject: [PATCH] improvements related to page search darcs-hash:20080205072510-62b54-41b33e3b33ec668e02676c8bece17aab0aefc476.gz --- Rakka.cabal | 1 + Rakka/Resource/Search.hs | 142 +++++++++++++++++++++++++++- Rakka/Storage/Impl.hs | 4 +- Rakka/Storage/Types.hs | 3 +- defaultPages/StyleSheet/Default.xml | 26 +++++ js/Makefile | 1 + js/base.js | 1 + js/login.js | 6 +- js/search.js | 37 +++++--- js/uri.js | 25 +++++ 10 files changed, 227 insertions(+), 19 deletions(-) create mode 100644 js/uri.js diff --git a/Rakka.cabal b/Rakka.cabal index 7425209..d9f9b0a 100644 --- a/Rakka.cabal +++ b/Rakka.cabal @@ -38,6 +38,7 @@ Extra-Source-Files: js/login.js js/screen.js js/search.js + js/uri.js Flag build-test-suite Description: Build the test suite. diff --git a/Rakka/Resource/Search.hs b/Rakka/Resource/Search.hs index 8271640..a7e7628 100644 --- a/Rakka/Resource/Search.hs +++ b/Rakka/Resource/Search.hs @@ -3,17 +3,28 @@ module Rakka.Resource.Search ) where +import qualified Codec.Binary.UTF8.String as UTF8 import Control.Arrow import Control.Arrow.ArrowIO +import Control.Arrow.ArrowIf import Control.Arrow.ArrowList +import Control.Arrow.ArrowTree import Control.Monad.Trans import Data.Maybe import Network.HTTP.Lucu +import Network.URI hiding (query, fragment) import Rakka.Environment +import Rakka.Page import Rakka.Resource import Rakka.Storage +import Rakka.SystemConfig +import Rakka.Utils +import Rakka.Wiki.Engine +import System.FilePath import Text.HyperEstraier +import Text.XML.HXT.Arrow.Namespace import Text.XML.HXT.Arrow.XmlArrow +import Text.XML.HXT.Arrow.XmlNodeSet import Text.XML.HXT.DOM.TypeDefs @@ -47,7 +58,7 @@ handleSearch :: Environment -> Resource () handleSearch env = do params <- getQueryForm - let query = fromMaybe "" $ lookup "q" params + let query = UTF8.decodeString $ fromMaybe "" $ lookup "q" params from = read $ fromMaybe "0" $ lookup "from" params to = read $ fromMaybe "20" $ lookup "to" params @@ -91,6 +102,7 @@ handleSearch env mkSnippetTree :: ArrowXml a => a SnippetFragment XmlTree mkSnippetTree = proc fragment -> case fragment of + Boundary -> eelem "boundary" NormalText t -> txt t HighlightedWord w -> eelem "hit" += txt w -<< () @@ -99,4 +111,130 @@ handleSearch env searchResultToXHTML :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a XmlTree XmlTree searchResultToXHTML env = proc tree - -> this -< tree + -> do SiteName siteName <- getSysConfA (envSysConf env) -< () + BaseURI baseURI <- getSysConfA (envSysConf env) -< () + StyleSheet styleSheet <- getSysConfA (envSysConf env) -< () + GlobalLock isGLocked <- getSysConfA (envSysConf env) -< () + + let cssHref = [uriToString id (mkObjectURI baseURI styleSheet) ""] + scriptSrc = [uriToString id (baseURI { uriPath = uriPath baseURI "js" }) ""] + + pageTitle <- listA (readSubPage env) -< (Nothing, Nothing, "PageTitle") + leftSideBar <- listA (readSubPage env) -< (Nothing, Nothing, "SideBar/Left") + rightSideBar <- listA (readSubPage env) -< (Nothing, Nothing, "SideBar/Right") + + ( eelem "/" + += ( eelem "html" + += sattr "xmlns" "http://www.w3.org/1999/xhtml" + += ( eelem "head" + += ( eelem "title" + += txt siteName + += txt " - " + += getXPathTreesInDoc "/searchResult/@query/text()" + ) + += ( constL cssHref + >>> + eelem "link" + += sattr "rel" "stylesheet" + += sattr "type" "text/css" + += attr "href" (arr id >>> mkText) + ) + += ( constL scriptSrc + >>> + eelem "script" + += sattr "type" "text/javascript" + += attr "src" (arr id >>> mkText) + ) + += ( eelem "script" + += sattr "type" "text/javascript" + += txt ("Rakka.baseURI=\"" ++ uriToString id baseURI "" ++ "\";") + += txt ("Rakka.isGlobalLocked=" ++ trueOrFalse isGLocked ++ ";") + += txt "Rakka.isSpecialPage=true;" + ) + ) + += ( eelem "body" + += ( eelem "div" + += sattr "class" "header" + ) + += ( eelem "div" + += sattr "class" "center" + += ( eelem "div" + += sattr "class" "title" + += constL pageTitle + ) + += ( eelem "div" + += sattr "class" "body" + += ( eelem "h1" + += txt "Search Result" + ) + += ( eelem "div" + += sattr "class" "searchStat" + += txt "Search result for " + += ( eelem "span" + += sattr "class" "queryString" + += getXPathTreesInDoc "/searchResult/@query/text()" + ) + += txt ": found " + += getXPathTreesInDoc "/searchResult/@total/text()" + += txt " pages." + ) + += ( getXPathTreesInDoc "/searchResult/page" + >>> + eelem "div" + += sattr "class" "searchResult" + += ( eelem "a" + += attr "href" ( getAttrValue "name" + >>> + arr (\ x -> uriToString id (mkPageURI baseURI x) "") + >>> + mkText + ) + += (getAttrValue "name" >>> mkText) + ) + += ( eelem "p" + += ( getChildren + >>> + choiceA [ isText :-> this + , hasName "boundary" :-> txt " ... " + , hasName "hit" :-> ( eelem "span" + += sattr "class" "highlighted" + += getChildren + ) + ] + ) + ) + ) + ) + ) + += ( eelem "div" + += sattr "class" "footer" + ) + += ( eelem "div" + += sattr "class" "left sideBar" + += ( eelem "div" + += sattr "class" "content" + += constL leftSideBar + ) + ) + += ( eelem "div" + += sattr "class" "right sideBar" + += ( eelem "div" + += sattr "class" "content" + += constL rightSideBar + ) + ) + ) + >>> + uniqueNamespacesFromDeclAndQNames + ) ) -<< tree + + +readSubPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) => + Environment + -> a (Maybe PageName, Maybe XmlTree, PageName) XmlTree +readSubPage env + = proc (mainPageName, mainPage, subPageName) -> + do subPage <- getPageA (envStorage env) >>> arr fromJust >>> xmlizePage -< (subPageName, Nothing) + subXHTML <- makeSubXHTML (envStorage env) (envSysConf env) (envInterpTable env) + -< (mainPageName, mainPage, subPage) + returnA -< subXHTML diff --git a/Rakka/Storage/Impl.hs b/Rakka/Storage/Impl.hs index c763a30..200423f 100644 --- a/Rakka/Storage/Impl.hs +++ b/Rakka/Storage/Impl.hs @@ -17,6 +17,7 @@ import Data.Maybe import Data.Set (Set) import qualified Data.Set as S import Network.HTTP.Lucu +import Network.HTTP.Lucu.Utils import Network.URI import Prelude hiding (words) import Rakka.Attachment @@ -198,7 +199,7 @@ searchIndex index cond snippet <- unsafeInterleaveIO $ do doc <- getDocument index docId [NoAttributes, NoKeywords] sn <- makeSnippet doc words 300 80 80 - return (map toFragment sn) + return (trim (== Boundary) $ map toFragment sn) return SearchResult { srPageName = decodePageName $ uriPath uri , srPageRev = rev @@ -206,6 +207,7 @@ searchIndex index cond } toFragment :: Either String (String, String) -> SnippetFragment + toFragment (Left "") = Boundary toFragment (Left t) = NormalText t toFragment (Right (w, _)) = HighlightedWord w diff --git a/Rakka/Storage/Types.hs b/Rakka/Storage/Types.hs index 2944f28..c83e53e 100644 --- a/Rakka/Storage/Types.hs +++ b/Rakka/Storage/Types.hs @@ -36,6 +36,7 @@ data SearchResult data SnippetFragment - = NormalText !String + = Boundary + | NormalText !String | HighlightedWord !String deriving (Show, Eq) \ No newline at end of file diff --git a/defaultPages/StyleSheet/Default.xml b/defaultPages/StyleSheet/Default.xml index 7a5a6ab..74a17db 100644 --- a/defaultPages/StyleSheet/Default.xml +++ b/defaultPages/StyleSheet/Default.xml @@ -200,6 +200,14 @@ table.pageEditor { margin: 0 2px; } +.searchStat { + margin-bottom: 1.5em; +} + +.searchResult { + margin-bottom: 1.5em; +} + /* color and text *************************************************************/ * { font-family: sans-serif; @@ -395,6 +403,24 @@ input[type="button"][disabled]:active { background-color: white; } +.searchStat { + color: #888888; + font-size: 90%; +} + +.searchResult a { + font-size: 120%; +} +.searchResult { + border-style: dotted; + border-width: 1px 0 0 0; + border-color: #aaaaaa; +} + +.highlighted { + background-color: #ffefd5; +} + /* float **********************************************************************/ h1, h2, h3, h4, h5, h6 { clear: both; diff --git a/js/Makefile b/js/Makefile index 7063803..637f7d1 100644 --- a/js/Makefile +++ b/js/Makefile @@ -12,6 +12,7 @@ SOURCES = \ redirection.js \ screen.js \ search.js \ + uri.js \ $(NULL) COMPRESS = java -jar $(COMPRESSOR) --type js --charset UTF-8 diff --git a/js/base.js b/js/base.js index f2aa402..a3dc7be 100644 --- a/js/base.js +++ b/js/base.js @@ -4,3 +4,4 @@ var Rakka = {}; Rakka.baseURI = null; Rakka.isLocked = false; Rakka.isGlobalLocked = false; +Rakka.isSpecialPage = false; \ No newline at end of file diff --git a/js/login.js b/js/login.js index 48a19b6..291fa29 100644 --- a/js/login.js +++ b/js/login.js @@ -115,7 +115,9 @@ $("input.newButton").attr({disabled: ""}); - $("input.editButton").attr({disabled: ""}); + $("input.editButton").attr({ + disabled: (Rakka.isSpecialPage ? "disabled" : "") + }); } else { /* ログインしてゐない */ @@ -129,7 +131,7 @@ }); $("input.editButton").attr({ - disabled: (Rakka.isLocked || Rakka.isGlobalLocked ? "disabled" : "") + disabled: (Rakka.isLocked || Rakka.isGlobalLocked || Rakka.isSpecialPage ? "disabled" : "") }); } }; diff --git a/js/search.js b/js/search.js index c1a90f8..3367804 100644 --- a/js/search.js +++ b/js/search.js @@ -1,23 +1,34 @@ (function () { $(document).ready(function () { - $("input.searchField") - .val("Search") - .removeClass("activeField") - .addClass("inactiveField") - .focus(function () { - if ($(this).attr("class").indexOf("inactiveField")) { - $(this) - .val("") - .removeClass("inactiveField") - .addClass("activeField"); - } - }) - .keypress(function (e) { + var $fld = $("input.searchField") + + $fld.keypress(function (e) { if (e.which == 10 || e.which == 13) { window.location = Rakka.baseURI + "search.html?q=" + encodeURI($(this).val()); } }); + + /* 檢索 query が指定されてゐれば、それが最初から入力されてゐる + * 状態にする。 + */ + var form = Rakka.getQueryForm(); + if (form["q"] == null) { + $fld.val("Search") + .removeClass("activeField") + .addClass("inactiveField") + .focus(function () { + if ($(this).attr("class").indexOf("inactiveField")) { + $(this) + .val("") + .removeClass("inactiveField") + .addClass("activeField"); + } + }); + } + else { + $fld.val(form["q"]); + } }); })(); \ No newline at end of file diff --git a/js/uri.js b/js/uri.js new file mode 100644 index 0000000..abe7df4 --- /dev/null +++ b/js/uri.js @@ -0,0 +1,25 @@ +(function () { + + Rakka.getQueryForm = function () { + var m = window.location.search.match(/^\?(.+)$/); + if (m) { + var ret = {}; + + $.each(m[1].split(/[&;]/), function () { + var m = this.match(/^(.*?)=(.*)$/); + if (m) { + var key = decodeURI(m[1]); + var val = decodeURI(m[2]); + + ret[key] = val; + } + }); + + return ret; + } + else { + return {}; + } + }; + +})(); \ No newline at end of file -- 2.40.0