diff --git a/static/abaev-html.css b/static/abaev-html.css
index 3de1717..59721b0 100644
--- a/static/abaev-html.css
+++ b/static/abaev-html.css
@@ -89,7 +89,11 @@ body>header>nav,
body>footer>nav {
margin: auto;
--pico-primary: #8D0B02 !important;
+ --pico-primary-background: #8D0B02 !important;
+ --pico-primary-border: #8D0B02 !important;
--pico-primary-hover: #cd5c5c !important;
+ --pico-primary-hover-background: #cd5c5c !important;
+ --pico-primary-hover-border: #cd5c5c !important;
}
body>header>nav {
border-bottom-width: thin;
@@ -305,6 +309,21 @@ legend {}
form {}
+header form {
+ margin-bottom: 0 !important;
+}
+
+header form button {
+ padding-left: 1em !important;
+ padding-right: 1em !important;
+ padding-top: 0 !important;
+ padding-bottom: 0 !important;
+}
+
+header form select {
+ max-width:35%;
+}
+
label {}
::placeholder {}
diff --git a/static/abaev-index.js b/static/abaev-index.js
index 3fcb9a7..03b7e5e 100644
--- a/static/abaev-index.js
+++ b/static/abaev-index.js
@@ -45,7 +45,7 @@ $( document ).ready(function() {
if(glosses.length > 0) {
entrystring = `${glosses.join('; ')}: `
}
- opt = $(``);
$select_entry.append(opt)
})
@@ -57,7 +57,8 @@ $( document ).ready(function() {
$('#abv-select-entry').on("dblclick", function() {
let $selected = $(this).children('option:selected');
- let $entry = $selected.attr('value');
- window.location.replace('./dict/' + $entry);
+ let entry = $selected.attr('value');
+ let path = $selected.attr('data-abv-xpath');
+ window.location.replace('./dict/' + entry + `?entry=${entry}&xpath=${path}`);
});
});
diff --git a/xq/abv-mod.xqm b/xq/abv-mod.xqm
index 21b1f9e..e38ce14 100644
--- a/xq/abv-mod.xqm
+++ b/xq/abv-mod.xqm
@@ -267,4 +267,40 @@ declare function abv-m:langname-by-id($id as xs:string, $lang as xs:string) {
declare function abv-m:entry-form-by-id($id as xs:string) {
doc(`abaevdict_index/lookup.xml`)/tei:table[1]/tei:entry[@xml:id=$id]/text()
-};
\ No newline at end of file
+};
+
+declare function abv-m:mark-element($doc as document-node(), $path as xs:string) {
+ let $doc-tr := $doc transform with {
+ for $n in xquery:eval($path, {'': .})
+ return replace node $n
+ with {$n}
+ }
+ return $doc-tr
+};
+
+(: Function to search, used in API and elsewhere :)
+declare function abv-m:search($db-lang as xs:string,
+ $type as xs:string,
+ $query as xs:string) {
+ let $pexpr := string-join(
+ ('declare namespace tei = "http://www.tei-c.org/ns/1.0";',
+ switch($type)
+ case "full" return "//text()"
+ case "form" return "/tei:entry[1]/tei:form/tei:orth"
+ case "sense" return "/tei:entry[1]/tei:sense"
+ case "example" return "/tei:entry[1]//tei:cit[@type='example']/tei:quote"
+ case "translation" return "/tei:entry[1]//tei:cit[@type='translation']"
+ case "mentioned" return "/tei:entry[1]//tei:mentioned/(tei:m|tei:w|tei:phr|tei:s)"
+ case "gloss" return "tei:entry[1]//tei:gloss"
+ case "etym" return "tei:entry[1]/tei:etym[1]//text()"
+ default return "//text()")
+ )
+ return array{for $doc in collection(`abaevdict_{$db-lang}/xml`)
+ let $hits := for $node in xquery:eval($pexpr, {'': $doc})
+ where $node contains text {$query}
+ return path($node)
+ where count($hits) > 0
+ order by abv-m:sortKey($doc/tei:entry[1]/tei:form[1]/tei:orth[1])
+ return {'entry_id': string($doc/tei:entry[1]/@xml:id),
+ 'path': array:build($hits)}}
+ };
\ No newline at end of file
diff --git a/xq/restx_api.xq b/xq/restx_api.xq
index 90cc9d5..5f75851 100644
--- a/xq/restx_api.xq
+++ b/xq/restx_api.xq
@@ -85,7 +85,7 @@ declare function api:word-info-long($n as node()) {
'refs': array:build(./ref,
fn {
map:merge((
- map:entry('node-id', string(./@node-id)),
+ map:entry('path', string(./@path)),
if(./gloss) then
{'glosses': array:build(distinct-values(./gloss/@text), string#1)}
else ()
@@ -168,7 +168,7 @@ declare %rest:path("{$db-lang}/api/languages/{$lang}/words/{$word-id}")
)
};
-(: Entry info (only form for now) :)
+(: Entry info :)
declare %rest:path("{$db-lang}/api/entries")
%rest:GET
function api:entries($db-lang as xs:string) {
@@ -187,4 +187,15 @@ declare %rest:path("{$db-lang}/api/entries/{$entry-id}")
$db-lang)
};
+(: Search API :)
+declare %rest:path("{$db-lang}/api/search")
+ %rest:query-param("type","{$type}",'full')
+ %rest:query-param("query","{$query}")
+ %rest:GET
+ function api:search($db-lang as xs:string,
+ $type as xs:string,
+ $query as xs:string) {
+ abv-m:search($db-lang,$type,$query)
+ };
+
0
\ No newline at end of file
diff --git a/xq/restx_dict_cached.xq b/xq/restx_dict_cached.xq
index e0723b8..9166f15 100644
--- a/xq/restx_dict_cached.xq
+++ b/xq/restx_dict_cached.xq
@@ -4,6 +4,7 @@ declare namespace tei = "http://www.tei-c.org/ns/1.0";
import module namespace abv-m = 'http://ossetic-studies.org/ns/abaevdict-mod' at './abv-mod.xqm';
+
(: =========================================================== :)
(: ================== GLOBAL VARIABLES ======================= :)
(: =========================================================== :)
@@ -49,7 +50,7 @@ declare function page:header($lang as xs:string, $href-other as xs:string) {
{
switch($lang)
case 'ru' return 'ИЭСОЯ В. И. Абаева'
- default return 'Abaevdict'
+ default return `Abaevdict`
} β
{
(element {if ($lang = 'ru') then 'mark' else 'a'}{
@@ -68,6 +69,59 @@ declare function page:header($lang as xs:string, $href-other as xs:string) {
+ -
+
+
- {
switch($lang)
case 'ru' return 'Главная'
@@ -96,6 +150,62 @@ declare function page:invert-lang($lang as xs:string) as xs:string {
if($lang = 'en') then 'ru' else 'en'
};
+(: =============================================================== :)
+(: ======================= SEARCH ENTRYPOINT ===================== :)
+(: =============================================================== :)
+
+declare %rest:path("/search/{$path=.+}")
+ %rest:GET
+ function page:search-default($path as xs:string) {
+ web:forward(`/en/search/{$path}`)
+ };
+
+declare %rest:path("{$lang}/search/new")
+ %rest:query-param("searchType", "{$searchType}", 'full')
+ %rest:query-param("searchQuery", "{$searchQuery}")
+ %output:method("html")
+ %output:html-version('5')
+ function page:search($lang, $searchType, $searchQuery) {
+ let $r1 := session:set('searchType', $searchType)
+ let $r2 := session:set('searchQuery', $searchQuery)
+ let $r3 := session:set('searchN', 1)
+ let $sd := abv-m:search($lang,$searchType,$searchQuery)
+ let $r4 := session:set('searchData',
+ $sd)
+ return page:by-id($lang, $sd(1)('entry_id'), string-join($sd(1)('path')?*,"|"))
+ };
+
+declare %rest:path("{$lang}/search/next")
+ %output:method("html")
+ %output:html-version('5')
+ function page:search-next($lang) {
+ let $n := session:get('searchN')+1
+ let $r1 := session:set('searchN', $n)
+ let $sd := session:get('searchData')
+ return page:by-id($lang, $sd($n)('entry_id'), string-join($sd($n)('path')?*,"|"))
+ };
+
+declare %rest:path("{$lang}/search/prev")
+ %output:method("html")
+ %output:html-version('5')
+ function page:search-prev($lang) {
+ let $n := session:get('searchN')-1
+ let $r1 := session:set('searchN', $n)
+ let $sd := session:get('searchData')
+ return page:by-id($lang, $sd($n)('entry_id'), string-join($sd($n)('path')?*,"|"))
+ };
+
+declare %rest:path("{$lang}/search/clear")
+ %output:method("html")
+ %output:html-version('5')
+ function page:clearSearch($lang) {
+ let $r1 := session:delete('searchType')
+ let $r2 := session:delete('searchQuery')
+ let $r3 := session:delete('searchN')
+ let $r4 := session:delete('searchData')
+ return web:redirect('../dict')
+ };
+
(: =============================================================== :)
(: ======================= HOMEPAGE ============================== :)
(: =============================================================== :)
@@ -328,9 +438,11 @@ declare %rest:path("dict")
(: The main dictionary view :)
declare %rest:path("{$lang}/dict")
%rest:query-param("page","{$p}", 1)
+ %rest:query-param("xpath","{$xpath}", '')
+ %rest:query-param("entry","{$entry}", '')
%output:method("html")
%output:html-version('5')
- function page:dict($lang, $p) {
+ function page:dict($lang, $p, $xpath, $entry) {
{page:head('HEDO – Dictionary',
(