diff --git a/modules/app.xqm b/modules/app.xqm
index 9fc20f485..862ecadde 100644
--- a/modules/app.xqm
+++ b/modules/app.xqm
@@ -28,6 +28,7 @@ import module namespace gl="http://xquery.weber-gesamtausgabe.de/modules/gl" at
import module namespace er="http://xquery.weber-gesamtausgabe.de/modules/external-requests" at "external-requests.xqm";
import module namespace dev-app="http://xquery.weber-gesamtausgabe.de/modules/dev/dev-app" at "dev/dev-app.xqm";
import module namespace functx="http://www.functx.com";
+import module namespace kwic="http://exist-db.org/xquery/kwic";
import module namespace templates="http://exist-db.org/xquery/templates";
import module namespace str="http://xquery.weber-gesamtausgabe.de/modules/str" at "xmldb:exist:///db/apps/WeGA-WebApp-lib/xquery/str.xqm";
import module namespace app-shared="http://xquery.weber-gesamtausgabe.de/modules/app-shared" at "xmldb:exist:///db/apps/WeGA-WebApp-lib/xquery/app-shared.xqm";
@@ -899,7 +900,8 @@ declare
declare
%templates:default("lang", "en")
function app:print-wega-bio($node as node(), $model as map(*), $lang as xs:string) as element(div)* {
- let $bio := wega-util:transform($model('doc')//(tei:note[@type='bioSummary'] | tei:event[tei:head] | tei:note[parent::tei:org]), doc(concat($config:xsl-collection-path, '/persons.xsl')), config:get-xsl-params(()))
+ let $query-result:= app:inject-query($model?doc/*)
+ let $bio := wega-util:transform($query-result//(tei:note[@type='bioSummary'] | tei:event[tei:head] | tei:note[parent::tei:org]), doc(concat($config:xsl-collection-path, '/persons.xsl')), config:get-xsl-params(()))
return
if(some $i in $bio satisfies $i instance of element()) then $bio
else
@@ -1251,11 +1253,11 @@ declare
default return doc(concat($config:xsl-collection-path, '/var.xsl'))
let $textRoot :=
switch($docType)
- case 'diaries' return $doc/tei:ab
- case 'works' return $doc/mei:mei
- case 'var' case 'addenda' return $doc//tei:text/tei:body/(tei:div[@xml:lang=$lang] | tei:divGen | tei:div[not(@xml:lang)])
- case 'thematicCommentaries' return $doc//tei:text/(tei:body | tei:back)
- default return $doc//tei:text/tei:body
+ case 'diaries' return $doc/tei:ab ! app:inject-query(.)
+ case 'works' return $doc/mei:mei ! app:inject-query(.)
+ case 'var' case 'addenda' return ($doc//tei:text/tei:body ! app:inject-query(.))/(tei:div[@xml:lang=$lang] | tei:divGen | tei:div[not(@xml:lang)])
+ case 'thematicCommentaries' return $doc//tei:text/tei:body ! app:inject-query(.) | $doc//tei:text/tei:back
+ default return $doc//tei:text/tei:body ! app:inject-query(.)
let $body :=
if(functx:all-whitespace({$textRoot}))
then
@@ -1289,6 +1291,27 @@ declare
}
};
+(:~
+ : Search and highlight query strings in a document
+ : Helper function for app:prepare-text()
+ :
+ : @param $input must be node() that is indexed by Lucene
+ : @return if a hit was found in $input, an expanded copy of the $input with exist:match elements wrapping the hits.
+ : If no hit was found, the initial $input is returned
+ :)
+declare %private function app:inject-query($input as node()) {
+ let $q := request:get-parameter('q', '')
+ return
+ if($q) then
+ let $sanitized-query-string := wega-util:strip-diacritics(str:normalize-space(str:sanitize(string-join($q, ' '))))
+ let $query := search:create-lucene-query-element($sanitized-query-string)
+ let $result := ft:query($input, $query)
+ return
+ if($result) then $result ! kwic:expand(.)
+ else $input
+ else $input
+};
+
declare
%templates:wrap
function app:series($node as node(), $model as map(*)) as xs:string {
@@ -1695,7 +1718,7 @@ declare
return
element {name($node)} {
$node/@*[not(name(.) = 'href')],
- if($node[self::xhtml:a]) then attribute href {app:createUrlForDoc($model('doc'), $lang)}
+ if($node[self::xhtml:a]) then attribute href {app:createUrlForDoc($model('doc'), $lang) || (if(map:contains($model, 'query-string-org')) then ('?q=' || $model?query-string-org) else ())}
else (),
if($title instance of xs:string or $title instance of text() or count($title) gt 1) then $title
else $title/node()
diff --git a/modules/search.xqm b/modules/search.xqm
index becec6332..7ece00e77 100644
--- a/modules/search.xqm
+++ b/modules/search.xqm
@@ -17,6 +17,8 @@ import module namespace str="http://xquery.weber-gesamtausgabe.de/modules/str" a
import module namespace wdt="http://xquery.weber-gesamtausgabe.de/modules/wdt" at "wdt.xqm";
import module namespace lang="http://xquery.weber-gesamtausgabe.de/modules/lang" at "lang.xqm";
import module namespace wega-util="http://xquery.weber-gesamtausgabe.de/modules/wega-util" at "wega-util.xqm";
+import module namespace controller="http://xquery.weber-gesamtausgabe.de/modules/controller" at "controller.xqm";
+import module namespace app="http://xquery.weber-gesamtausgabe.de/modules/app" at "app.xqm";
import module namespace functx="http://www.functx.com";
declare variable $search:ERROR := QName("http://xquery.weber-gesamtausgabe.de/modules/search", "Error");
@@ -46,7 +48,7 @@ declare
return
switch($docType)
(: search page :)
- case 'search' return search:search(map:merge(($model, $filters, map:entry('docID', 'indices'))))
+ case 'search' return search:search-session(map:merge(($model, $filters, map:entry('docID', 'indices'))), search:search#1)
(: controller sends docType=persons which needs to be turned into "personsPlus" here :)
case 'persons' return search:list(map:merge(($filters, map:put($model, 'docType', 'personsPlus'))))
(: various list views :)
@@ -160,7 +162,7 @@ declare
: Search results and other goodies for the *search* page
~:)
declare %private function search:search($model as map(*)) as map(*) {
- let $updatedModel := search:prepare-search-string($model)
+ let $updatedModel := $model
let $docTypes :=
if($updatedModel?query-docTypes = 'all') then ($search:wega-docTypes, 'var', 'addenda') (: silently add 'var' (= special pages, e.g. "Impressum/About" or "Sonderband/Special Volume") to the list of docTypes :)
else $search:wega-docTypes[.=$updatedModel?query-docTypes]
@@ -176,6 +178,10 @@ declare %private function search:search($model as map(*)) as map(*) {
let $fulltext-search :=
if($updatedModel('query-string')) then search:merge-hits($docTypes ! search:fulltext($filtered-results, $updatedModel('query-string'), $updatedModel?filters, .))
else $filtered-results
+ let $store-session :=
+ if(count($fulltext-search) gt 0)
+ then session:set-attribute('wegasearch', map:merge(($updatedModel, map:entry('search-results', $fulltext-search))))
+ else ()
return
map:merge(($updatedModel, map:entry('search-results', $fulltext-search)))
};
@@ -235,7 +241,7 @@ declare %private function search:fulltext($items as item()*, $searchString as xs
(:~
: Parse the query string and create an XML query element for the lucene search
~:)
-declare %private function search:create-lucene-query-element($searchString as xs:string) as element(query) {
+declare function search:create-lucene-query-element($searchString as xs:string) as element(query) {
let $groups := analyze-string($searchString, '(-?"(.+?)")')/* (: split into fn:match – for expressions in parentheses – and fn:non-match elements :)
let $queryElement := function($elementName as xs:string, $token as item()) as element() {
element {$elementName} {
@@ -432,3 +438,49 @@ declare %private function search:prepare-search-string($model as map()) as map(*
}
))
};
+
+(:~
+ : Cache search results in browser session
+ :
+ : @param $model the current model map of the templating module
+ : @param $callback a callback function to actually do the search if the session is empty
+ : @return a map object {'filters': {}, 'search-results': {}, 'query-string-org': '', 'query-docTypes': ('') }
+~:)
+declare %private function search:search-session($model as map(), $callback as function() as map(*)) as map(*) {
+ let $updatedModel := search:prepare-search-string($model)
+ let $session-exists :=
+ try {
+ count(session:get-attribute('wegasearch')?search-results) gt 0
+ and session:get-attribute('wegasearch')?query-string-org = $updatedModel?query-string-org
+ and functx:sequence-deep-equal(session:get-attribute('wegasearch')?filters?*, $updatedModel?filters?*)
+ and functx:sequence-deep-equal(session:get-attribute('wegasearch')?query-docTypes, $updatedModel?query-docTypes)
+ }
+ catch * {false()}
+ return
+ if($session-exists)
+ then session:get-attribute('wegasearch')
+ else $callback($updatedModel)
+};
+
+declare
+ %templates:wrap
+ function search:get-session-for-singleview($node as node(), $model as map(*)) as map()? {
+ let $wegasearch := session:get-attribute('wegasearch')
+ let $index-of-current-doc := functx:index-of-node($wegasearch?search-results?doc, $model?doc)
+ let $page := ceiling($index-of-current-doc div config:entries-per-page())
+ let $url := controller:resolve-link('$link/search', $model) || '?q=' || $wegasearch?query-string-org || '&d=' || string-join($wegasearch?query-docTypes, '&d=') || '&page=' || $page
+ let $search-prev-item-url :=
+ if($index-of-current-doc gt 1) then app:createUrlForDoc($wegasearch?search-results[$index-of-current-doc - 1]?doc, $model?lang) || '?q=' || $wegasearch?query-string-org
+ else '#'
+ let $search-next-item-url :=
+ if($index-of-current-doc lt count($wegasearch?search-results)) then app:createUrlForDoc($wegasearch?search-results[$index-of-current-doc + 1]?doc, $model?lang) || '?q=' || $wegasearch?query-string-org
+ else '#'
+ return
+ map:merge((
+ $wegasearch,
+ map:entry('index-of-current-doc', $index-of-current-doc),
+ map:entry('search-backlink', $url),
+ map:entry('search-prev-item-url', $search-prev-item-url),
+ map:entry('search-next-item-url', $search-next-item-url)
+ ))
+};
diff --git a/resources/sass/pages/_search.scss b/resources/sass/pages/_search.scss
index 46cb779c1..83dff0e76 100644
--- a/resources/sass/pages/_search.scss
+++ b/resources/sass/pages/_search.scss
@@ -35,7 +35,7 @@
}
}
-*[class*="hi-"], *[class*="hi-"] *, .kwic .hi {
+*[class*="hi-"], *[class*="hi-"] *, .hi {
color: #ffffff !important;
background-color: $primary !important;
}
diff --git a/templates/document.html b/templates/document.html
index d7f8fd638..37e96f225 100644
--- a/templates/document.html
+++ b/templates/document.html
@@ -11,28 +11,43 @@
CARL MARIA VON WEBER AN
-
-
-
- -
- Home
-
- -
- Carl Maria von Weber
-
- -
- Korrespondenz
-
- -
- A040080
- in Bearbeitung
-
-
-
+
diff --git a/templates/person.html b/templates/person.html
index 0053ea53e..c514214df 100644
--- a/templates/person.html
+++ b/templates/person.html
@@ -10,16 +10,31 @@
Weber, Carl Maria von
-
-
-
- - Home
- - Carl Maria von Weber
-
-
+
+
+
+
+ - Home
+ - Carl Maria von Weber
+
+
+
+
+ back
+
-
- back
+
+
diff --git a/templates/var.html b/templates/var.html
index 79b139dd2..797f3e450 100644
--- a/templates/var.html
+++ b/templates/var.html
@@ -11,31 +11,46 @@
CARL MARIA VON WEBER AN
-
-
-
-
-
- - Home
- - Carl Maria von Weber
- - Werke
- - A020040 in Bearbeitung
-
+
diff --git a/xsl/common_main.xsl b/xsl/common_main.xsl
index 73ce6a59e..9b6a343b5 100644
--- a/xsl/common_main.xsl
+++ b/xsl/common_main.xsl
@@ -8,7 +8,9 @@
xmlns:functx="http://www.functx.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:teix="http://www.tei-c.org/ns/Examples"
- xmlns:mei="http://www.music-encoding.org/ns/mei" version="2.0">
+ xmlns:mei="http://www.music-encoding.org/ns/mei"
+ xmlns:exist="http://exist.sourceforge.net/NS/exist"
+ version="2.0">
@@ -825,4 +827,15 @@
+
+
+
+
+
+
+ hi
+
+
+
+