[fix] slick-router
This commit is contained in:
parent
0659567f36
commit
dcd18dd3d5
18 changed files with 618 additions and 28 deletions
63
src/lib/bookpages.xqm
Normal file
63
src/lib/bookpages.xqm
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
xquery version '3.1';
|
||||
(:~ describe book page numbers as sequence of ranges, similar to PDF pagelabels
|
||||
@author quodatum
|
||||
:)
|
||||
module namespace bookpages = 'urn:bookpages';
|
||||
|
||||
(:~ Invisible-xml grammar to parse custom pagelabel representation :)
|
||||
declare variable $bookpages:grammar:="
|
||||
book: pagecount,'#',range,(-',', range)*.
|
||||
pagecount:['0'-'9']+.
|
||||
range: s,from?,s,type,s,prefix?,s,offset?.
|
||||
@from: ['0'-'9']+. { pageIndex }
|
||||
@type: ['C'|'D'|'R'|'r'|'A'|'a'|'w'].
|
||||
@prefix: -':',~[',']+.
|
||||
@offset: -'@',['0'-'9']+.
|
||||
|
||||
-s: ([Zs]; #9; #a; #d)*. {Optional whitespace}
|
||||
";
|
||||
|
||||
(:~
|
||||
page number range in given style
|
||||
:)
|
||||
declare function bookpages:span($type as xs:string,$length as xs:integer,$first as xs:integer)
|
||||
as xs:string*{
|
||||
let $r:=$first to $first+$length
|
||||
return switch ($type)
|
||||
case "D" return $r!format-integer(.,"1")
|
||||
case "r" return $r!format-integer(.,"i")
|
||||
case "R" return $r!format-integer(.,"I")
|
||||
case "C" return "Cover"
|
||||
default return $r!format-integer(.,$type)
|
||||
};
|
||||
|
||||
(:~ pagelabels from text:)
|
||||
declare function bookpages:expand($pages as xs:string)
|
||||
as xs:string*{
|
||||
let $x:=bookpages:parse($pages)
|
||||
let $last:=head($x)=>xs:integer()
|
||||
return hof:until(
|
||||
function($m){ empty($m?ranges) or count($m?result)eq $last },
|
||||
function($m){
|
||||
let $range:=head($m?ranges)=>trace("SS")
|
||||
let $start:=if($range/@offset)then xs:integer($range/@offset) else 1
|
||||
let $end:=($m?ranges[2]/xs:integer(@from)-1) otherwise $last
|
||||
let $length:=$end -count($m?result)-1
|
||||
let $span:=bookpages:span($range/@type,$length,$start)
|
||||
let $span:=if($range/@prefix)then $span!concat($range/@prefix,.) else $span
|
||||
return map {
|
||||
'ranges': tail($m?ranges),
|
||||
'result': ($m?result, $span)
|
||||
}},
|
||||
|
||||
(: initial input = grammar ranges :)
|
||||
map { 'ranges': tail($x) , 'result': () }
|
||||
)?result
|
||||
};
|
||||
|
||||
(:~ parse pagenumber description to xml :)
|
||||
declare function bookpages:parse($pages as xs:string)
|
||||
as element(range)*{
|
||||
invisible-xml($bookpages:grammar)($pages)/*
|
||||
};
|
||||
|
||||
|
|
@ -2,12 +2,12 @@ xquery version '3.1';
|
|||
(:~
|
||||
pdfbox 3.0 https://pdfbox.apache.org/ BaseX 10.7+ interface library,
|
||||
requires pdfbox jar on classpath
|
||||
3.02 required tested with pdfbox-app-3.0.2-20240121.184204-66.jar
|
||||
3.02+ required tested with pdfbox-app-3.0.2.jar
|
||||
@see https://repository.apache.org/content/groups/snapshots/org/apache/pdfbox/pdfbox-app/3.0.2-SNAPSHOT/
|
||||
@javadoc https://javadoc.io/static/org.apache.pdfbox/pdfbox/3.0.0/
|
||||
|
||||
:)
|
||||
module namespace pdfbox="urn:expkg-zone58:pdfbox:3";
|
||||
module namespace pdfbox="urn:expkg-zone58:pdfbox3";
|
||||
|
||||
declare namespace Loader ="java:org.apache.pdfbox.Loader";
|
||||
declare namespace PDFTextStripper = "java:org.apache.pdfbox.text.PDFTextStripper";
|
||||
|
|
@ -96,7 +96,7 @@ as map(*)*{
|
|||
};
|
||||
|
||||
(: return bookmark info for children of $outlineItem as seq of maps :)
|
||||
declare function pdfbox:outline($doc,$outlineItem )
|
||||
declare function pdfbox:outline($doc as item(),$outlineItem as item()?)
|
||||
as map(*)*
|
||||
{
|
||||
let $find:=hof:until(
|
||||
|
|
@ -143,7 +143,7 @@ as map(*)
|
|||
}
|
||||
};
|
||||
|
||||
declare function pdfbox:outx($page,$document)
|
||||
declare function pdfbox:outx($page ,$document)
|
||||
{
|
||||
let $currentPage := PDOutlineItem:findDestinationPage($page,$document)
|
||||
let $pageNumber := pdfbox:pageIndex($currentPage,$document)
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
xquery version '3.1';
|
||||
(:~ look for pagenos in pdf text
|
||||
pagenos:page-report($doc )=>pagenos:inverted-map()
|
||||
pdfscrape:page-report($doc )=>pdfscrape:inverted-map()
|
||||
:)
|
||||
module namespace pagenos = 'urn:pageno';
|
||||
import module namespace pdfbox="urn:expkg-zone58:pdfbox:3" at "pdfbox3.xqm";
|
||||
module namespace pdfscrape = 'urn:pdfscrape';
|
||||
import module namespace pdfbox="urn:expkg-zone58:pdfbox3" at "pdfbox3.xqm";
|
||||
|
||||
(: look for possible page number in first/last line of page text
|
||||
@todo last line and roman
|
||||
1=Number system ( D=decimal, R=Roman)
|
||||
2=Side L=left,R=right
|
||||
:)
|
||||
declare variable $pagenos:pats:=map{
|
||||
declare variable $pdfscrape:pats:=map{
|
||||
"DL": "^([1-9][0-9]*).*",
|
||||
"DR": ".*[^0-9]([1-9][0-9]*)$",
|
||||
"RL": "^([ivxlc]+).*",
|
||||
|
|
@ -18,47 +18,56 @@ declare variable $pagenos:pats:=map{
|
|||
};
|
||||
|
||||
(: page-reports for all pages :)
|
||||
declare function pagenos:page-report($doc as item())
|
||||
declare function pdfscrape:page-report($doc as item())
|
||||
as element(page)*{
|
||||
let $count:=pdfbox:page-count($doc)=>trace("Pages: ")
|
||||
return (0 to $count -1)!pagenos:page-report($doc,.)
|
||||
return (1 to $count )!pdfscrape:page-report($doc,.)
|
||||
};
|
||||
|
||||
(: page-report for given page :)
|
||||
declare function pagenos:page-report($doc as item(), $page as xs:integer)
|
||||
declare function pdfscrape:page-report($doc as item(), $page as xs:integer)
|
||||
as element(page){
|
||||
let $txt:=pdfbox:getText($doc,$page)
|
||||
let $line1:=substring-before($txt,file:line-separator())
|
||||
let $fn:=function($acc,$this){ $acc otherwise pagenos:line-report($this,$line1)}
|
||||
let $found:=map:keys($pagenos:pats)=>fold-left( (),$fn)
|
||||
let $fn:=function($acc,$this){ $acc otherwise pdfscrape:line-report($this,$line1)}
|
||||
let $found:=map:keys($pdfscrape:pats)=>fold-left( (),$fn)
|
||||
|
||||
return <page index="{ $page }">{ $found, $line1 }</page>
|
||||
};
|
||||
|
||||
(: empty or attributes created by matching $style with $line1 :)
|
||||
declare function pagenos:line-report($style as xs:string, $line1 as xs:string)
|
||||
declare function pdfscrape:line-report($style as xs:string, $line1 as xs:string)
|
||||
as attribute(*)*{
|
||||
if(matches($line1,$pagenos:pats?($style)))
|
||||
if(matches($line1,$pdfscrape:pats?($style)))
|
||||
then (
|
||||
attribute {"style"} { substring($style,1,1) } ,(: 1st key:)
|
||||
attribute {"LR"} { substring($style,2,1) } ,(: 2nd key:)
|
||||
attribute {"number"} { replace($line1,$pagenos:pats?($style),"$1") }
|
||||
attribute {"number"} { replace($line1,$pdfscrape:pats?($style),"$1") }
|
||||
)
|
||||
};
|
||||
|
||||
(:~ keys are parsed pageno values are pageindices where found:)
|
||||
declare function pagenos:inverted-map($pages as element(page)*)
|
||||
declare function pdfscrape:inverted-map($pages as element(page)*)
|
||||
as map(*) {
|
||||
$pages[@number]!map:entry(string(@number),string(@index))
|
||||
=>map:merge(map{"duplicates":"combine"})
|
||||
};
|
||||
(:~ %match
|
||||
$l page labels
|
||||
:)
|
||||
declare function pdfscrape:score($l as xs:string*,$report as element(page)*)
|
||||
{
|
||||
let $s:=$report!(if(@number)then string(@number) else "")
|
||||
let $match:= for-each-pair($l,$s,function($l,$s){if($s eq "")then 0 else if ($s eq $l)then 1 else -1})
|
||||
return round(sum($match) div count($l) *100,0)
|
||||
};
|
||||
|
||||
(:~ convert roman to integer, zero if invalid
|
||||
@see https://joewiz.org/2021/05/30/converting-roman-numerals-with-xquery-xslt/
|
||||
:)
|
||||
declare function pagenos:decode-roman-numeral($roman-numeral as xs:string)
|
||||
declare function pdfscrape:decode-roman-numeral($roman-numeral as xs:string)
|
||||
as xs:integer{
|
||||
$roman-numeral => upper-case() => pagenos:characters()
|
||||
$roman-numeral => upper-case() => characters()
|
||||
=> for-each(map { "M": 1000, "D": 500, "C": 100, "L": 50, "X": 10, "V": 5, "I": 1 })
|
||||
=> fold-right([0,0], function($number,$accumulator) {
|
||||
if ($number lt $accumulator?2)
|
||||
|
|
@ -67,8 +76,3 @@ as xs:integer{
|
|||
=> array:head()
|
||||
};
|
||||
|
||||
(:~ xpath 4:)
|
||||
declare function pagenos:characters($value as xs:string?)
|
||||
as xs:string*{
|
||||
fn:string-to-codepoints($value) ! fn:codepoints-to-string(.)
|
||||
};
|
||||
26
src/scratch/abc.xq
Normal file
26
src/scratch/abc.xq
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
(: test use of pageIndex :)
|
||||
import module namespace pdfbox="urn:expkg-zone58:pdfbox:3" at "../src/lib/pdfbox3.xqm";
|
||||
import module namespace pagenos = 'urn:pageno' at "../src/lib/pageno.xqm";
|
||||
declare variable $base:=file:base-dir();
|
||||
declare function local:go($doc,$pdf as element(pdf)){
|
||||
let $range:=$pdf/@pages/tokenize(.,"–")
|
||||
let $start:=$range[1]
|
||||
let $end:=if(count($range) eq 1) then $range[1] else $range[2]
|
||||
|
||||
return ``[ `{$start}` ;;; `{ $end }` ]``
|
||||
};
|
||||
let $src:="257107---Book_File-Web_PDF_9798400691218_486731.pdf"=>file:resolve-path($base)
|
||||
let $doc:=pdfbox:open($src)
|
||||
let $labels:= pdfbox:getPageLabels($doc)
|
||||
let $pdfs:=doc("pdfs\chunks-docbook.xml")/chunks/pdf
|
||||
for $pdf in $pdfs
|
||||
let $range:=$pdf/@pages/tokenize(.,"–")
|
||||
let $start:=$range[1]
|
||||
let $end:=if(count($range) eq 1) then $range[1] else $range[2]
|
||||
let $startIndex:=index-of($labels,$start)
|
||||
let $endIndex:=index-of($labels,$end)
|
||||
return if(exists($startIndex) and exists($endIndex))
|
||||
then $pdf/@pages || " " || $startIndex || ":" || $endIndex
|
||||
(: pdfbox:extract($doc,$startIndex,$endIndex,file:resolve-path($pdf/@fileref,$base)) :)
|
||||
else $pdf/@pages
|
||||
|
||||
20
src/scratch/nos.xq
Normal file
20
src/scratch/nos.xq
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
(:~ describe book page numbering :)
|
||||
|
||||
import module namespace pdfbox="urn:expkg-zone58:pdfbox3" at "../lib/pdfbox3.xqm";
|
||||
import module namespace bookpages="urn:bookpages" at "../lib/bookpages.xqm";
|
||||
import module namespace pdfscrape="urn:pdfscrape" at "../lib/pdfscrape.xqm";
|
||||
|
||||
declare variable $base:="C:\Users\mrwhe\Desktop\1e\";
|
||||
declare variable $tests:=map{
|
||||
"simple":"20#C,R,7D",
|
||||
"set\2-6-2\A5267C": "1037#C,r,28D,520r:V2,526D@493",
|
||||
"gpg-book\2-3\A3581C-TRD": "848#C,r:Vol1:,28D,400r:Vol2:,438D@401"
|
||||
};
|
||||
let $pdf:=pdfbox:open("C:\Users\mrwhe\Desktop\1e\set\2-6-2\A5267C\257273---Book_File-Web_PDF_9798400612572_486638.pdf")
|
||||
let $l:=pdfbox:getPageLabels($pdf)
|
||||
|
||||
let $index:=bookpages:expand($tests?"set\2-6-2\A5267C")
|
||||
return pdfscrape:score($l,pdfscrape:page-report($pdf))
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
(: PDFBOX experiments
|
||||
:)
|
||||
|
||||
import module namespace pdfbox="urn:expkg-zone58:pdfbox:3" at "../lib/pdfbox3.xqm";
|
||||
import module namespace pdfbox="urn:expkg-zone58:pdfbox3" at "../lib/pdfbox3.xqm";
|
||||
|
||||
|
||||
declare variable $samples:= map{
|
||||
|
|
|
|||
87
src/webapp/pdf/app.xqm
Normal file
87
src/webapp/pdf/app.xqm
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
(:~
|
||||
: Common RESTXQ access points.
|
||||
:
|
||||
: @author Christian Grün, BaseX Team 2005-23, BSD License
|
||||
:)
|
||||
module namespace pdf = 'pdf/common';
|
||||
|
||||
|
||||
|
||||
(:~
|
||||
: Redirects to the start page.
|
||||
: @return redirection
|
||||
:)
|
||||
declare
|
||||
%rest:path('/pdf')
|
||||
function pdf:home() as element() {
|
||||
web:forward('/pdf/static/index.html')
|
||||
};
|
||||
declare
|
||||
%rest:path('/pdf/{$file=.+}')
|
||||
function pdf:spa($file)as element(){
|
||||
pdf:home()
|
||||
};
|
||||
(:~ list slugs :)
|
||||
declare
|
||||
%rest:path('/pdf/api/sources')
|
||||
%output:method("json")
|
||||
%output:json("format=xquery")
|
||||
function pdf:apt()
|
||||
{
|
||||
let $base:="C:/Users/mrwhe/git/expkg-zone58/pdfbox/data/"
|
||||
let $d:="1e/"
|
||||
let $f:=file:list($base || $d,true(),"*.pdf")[not(contains(.,"\outputs\"))]
|
||||
return map{
|
||||
"count": count($f),
|
||||
"items": array{$f!map{"id":position(),"name":.}}
|
||||
}
|
||||
};
|
||||
|
||||
(:~
|
||||
: Returns a file.
|
||||
: @param $file file or unknown path
|
||||
: @return rest binary data
|
||||
:)
|
||||
declare
|
||||
%rest:path('/pdf/static/{$file=.+}')
|
||||
%output:method('basex')
|
||||
%perm:allow('public')
|
||||
function pdf:file(
|
||||
$file as xs:string
|
||||
) as item()+ {
|
||||
let $path := file:base-dir() || "static/" || $file
|
||||
return if(file:exists($path))
|
||||
then (
|
||||
web:response-header(
|
||||
map { 'media-type': web:content-type($path) },
|
||||
map { 'Cache-Control': 'max-age=3600,public', 'Content-Length': file:size($path) }
|
||||
),
|
||||
file:read-binary($path)
|
||||
)else
|
||||
web:forward("/pdf/api/404")
|
||||
|
||||
};
|
||||
|
||||
(:~
|
||||
: Shows a 'page not found' error.
|
||||
: @param $path path to unknown page
|
||||
: @return page
|
||||
:)
|
||||
declare
|
||||
%rest:path('/pdf/api/404')
|
||||
%output:method('html')
|
||||
function pdf:unknown(
|
||||
$path as xs:string
|
||||
) as element(*) {
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<h2>Page not found:</h2>
|
||||
<ul>
|
||||
<li>Page: dba/{ $path }</li>
|
||||
<li>Method: { request:method() }</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
};
|
||||
15
src/webapp/pdf/readme.md
Normal file
15
src/webapp/pdf/readme.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Uses
|
||||
* https://www.npmjs.com/package/slick-router
|
||||
<style>table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}</style>
|
||||
<table >
|
||||
<caption>Sample table</caption>
|
||||
<tr>
|
||||
<td>Foo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
</tr>
|
||||
</table>
|
||||
53
src/webapp/pdf/static/animations.css
Normal file
53
src/webapp/pdf/static/animations.css
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/* extracted from https://vuejs.org/v2/guide/transitions.html */
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.5s;
|
||||
}
|
||||
|
||||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Enter and leave animations can use different */
|
||||
/* durations and timing functions. */
|
||||
.slide-fade-enter-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.slide-fade-leave-active {
|
||||
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
|
||||
}
|
||||
|
||||
.slide-fade-enter, .slide-fade-leave-to {
|
||||
transform: translateX(1000px);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.bounce-enter {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.bounce-enter-active {
|
||||
animation: bounce-in 0.8s;
|
||||
}
|
||||
|
||||
.bounce-leave-active {
|
||||
animation: bounce-in 0.8s reverse;
|
||||
}
|
||||
|
||||
@keyframes bounce-in {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
80% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
router-outlet > * {
|
||||
display: block;
|
||||
}
|
||||
139
src/webapp/pdf/static/components.js
Normal file
139
src/webapp/pdf/static/components.js
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
import { withRouterLinks } from 'https://unpkg.com/slick-router@2.5.0/middlewares/router-links.js'
|
||||
|
||||
class ApplicationView extends withRouterLinks(HTMLElement) {
|
||||
constructor() {
|
||||
super()
|
||||
this.addEventListener('change', e => {
|
||||
if (e.target.matches('#animation-type')) {
|
||||
const animation = e.target.value
|
||||
if (animation) {
|
||||
this.outlet.setAttribute('animation', e.target.value)
|
||||
} else {
|
||||
this.outlet.removeAttribute('animation')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
this.innerHTML = `
|
||||
<div class='App'>
|
||||
<div class='App-header'>
|
||||
<h1>Application</h1>
|
||||
<ul class='Nav' routerlinks>
|
||||
<li class='Nav-item'><a route="home" >Home</a></li>
|
||||
<li class='Nav-item'><a route="messages">Messages</a></li>
|
||||
<li class='Nav-item'><a route="profile.index" param-user="scrobblemuch">Profile</a></li>
|
||||
<li class='Nav-item'><a route="settings" >Settings</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
<router-outlet animation="fade"></router-outlet>
|
||||
|
||||
<div class="App-footer">
|
||||
<div>
|
||||
Animation
|
||||
<select id="animation-type">
|
||||
<option value="">None</option>
|
||||
<option value="fade" selected>Fade</option>
|
||||
<option value="slide-fade">Slide Fade</option>
|
||||
<option value="bounce">Bounce</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`
|
||||
this.outlet = this.querySelector('router-outlet')
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('application-view', ApplicationView)
|
||||
|
||||
class HomeView extends withRouterLinks(HTMLElement) {
|
||||
connectedCallback() {
|
||||
super.connectedCallback()
|
||||
this.innerHTML = `
|
||||
<div class='Home' routerlinks>
|
||||
<h2>Tweets</h2>
|
||||
<div class='Tweet'>
|
||||
<div class='Tweet-author'>
|
||||
<a route="profile.index" param-user="dan_abramov">Dan Abramov @dan_abramov</a>
|
||||
</div>
|
||||
<div class='Tweet-time'>12m12 minutes ago</div>
|
||||
<div class='Tweet-content'>Another use case for \`this.context\` I think might be valid: forms. They're too painful right now.</div>
|
||||
</div>
|
||||
<div class='Tweet'>
|
||||
<div class='Tweet-author'>
|
||||
<a route="profile.index" param-user="afanasjevas">Eduardas Afanasjevas @afanasjevas</a>
|
||||
</div>
|
||||
<div class='Tweet-time'>12m12 minutes ago</div>
|
||||
<div class='Tweet-content'>I just published “What will Datasmoothie bring to the analytics startup landscape?” https://medium.com/@afanasjevas/what-will-datasmoothie-bring-to-the-analytics-startup-landscape-f7dab70d75c3?source=tw-81c4e81fe6f8-1427630532296</div>
|
||||
</div>
|
||||
<div class='Tweet'>
|
||||
<div class='Tweet-author'>
|
||||
<a route="profile.index" param-user="LNUGorg">LNUG @LNUGorg</a>
|
||||
</div>
|
||||
<div class='Tweet-time'>52m52 minutes ago</div>
|
||||
<div class='Tweet-content'> new talks uploaded on our YouTube page - check them out http://bit.ly/1yoXSAO</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('home-view', HomeView)
|
||||
|
||||
class MessagesView extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<div class='Messages'>
|
||||
<h2>Messages</h2>
|
||||
<p>You have no direct messages</p>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
customElements.define('messages-view', MessagesView)
|
||||
|
||||
class SettingsView extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<div class='Messages'>
|
||||
<h2>Sett</h2>
|
||||
<p>You have no direct messages</p>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
customElements.define('settings-view', SettingsView)
|
||||
|
||||
class ProfileView extends HTMLElement {
|
||||
static get outlet() {
|
||||
return '.Container'
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<div class='Profile'>
|
||||
<div class='Container'></div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('profile-view', ProfileView)
|
||||
|
||||
class ProfileIndexView extends HTMLElement {
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<div class='ProfileIndex'>
|
||||
<h2>${this.$route.params.user} profile</h2>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('profile-index-view', ProfileIndexView)
|
||||
BIN
src/webapp/pdf/static/favicon.png
Normal file
BIN
src/webapp/pdf/static/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
18
src/webapp/pdf/static/index.html
Normal file
18
src/webapp/pdf/static/index.html
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<base href="/pdf/static/"/>
|
||||
<title>PDFS453 </title>
|
||||
|
||||
<link rel="icon" href="favicon.png">
|
||||
<script type="module" src="index.js"></script>
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
<link rel="stylesheet" href="animations.css" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
41
src/webapp/pdf/static/index.js
Normal file
41
src/webapp/pdf/static/index.js
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { Router } from 'https://unpkg.com/slick-router@2.5.0/slick-router.js?module'
|
||||
import { wc } from 'https://unpkg.com/slick-router@2.5.0/middlewares/wc.js'
|
||||
import { events } from 'https://unpkg.com/slick-router@2.5.0/middlewares/events.js'
|
||||
import { routerLinks } from 'https://unpkg.com/slick-router@2.5.0/middlewares/router-links.js'
|
||||
import { AnimatedOutlet } from 'https://unpkg.com/slick-router@2.5.0/components/animated-outlet.js'
|
||||
|
||||
import './components.js'
|
||||
|
||||
customElements.define('router-outlet', AnimatedOutlet)
|
||||
|
||||
// create the router
|
||||
const router = new Router({
|
||||
pushState: true,
|
||||
|
||||
log: true
|
||||
})
|
||||
|
||||
// provide your route map
|
||||
// in this particular case we configure components by its tag name
|
||||
|
||||
router.map(route => {
|
||||
route('application', { path: '/pdf/', component: 'application-view' }, () => {
|
||||
route('home', { path: '', component: 'home-view' })
|
||||
route('messages', { component: 'messages-view' })
|
||||
route('status', { path: ':user/status/:id' })
|
||||
route('profile', { path: 'profile/:user', component: 'profile-view' }, () => {
|
||||
route('profile.index', { path: '', component: 'profile-index-view' })
|
||||
route('profile.lists')
|
||||
route('profile.edit')
|
||||
})
|
||||
route('settings',{path: 'settings',component:'settings-view'})
|
||||
})
|
||||
})
|
||||
|
||||
// install middleware that will handle transitions
|
||||
router.use(wc)
|
||||
router.use(routerLinks)
|
||||
router.use(events)
|
||||
|
||||
// start listening to browser's location bar changes
|
||||
router.listen()
|
||||
75
src/webapp/pdf/static/styles.css
Normal file
75
src/webapp/pdf/static/styles.css
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');
|
||||
|
||||
body,
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
}
|
||||
|
||||
.App {
|
||||
width: 800px;
|
||||
margin: 0 auto 20px auto;
|
||||
}
|
||||
|
||||
.App-header {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.App-header .active {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.App-footer {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
padding-bottom: 20px;
|
||||
text-align: center;
|
||||
background-color: bisque;
|
||||
}
|
||||
|
||||
.App h1 {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.Nav {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.Nav-item {
|
||||
list-style: none;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.Nav-item a {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.Tweet {
|
||||
border: 1px solid #eee;
|
||||
border-radius: 3px;
|
||||
padding: 10px;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.Tweet:last-child {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.Tweet-author {
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.Tweet-time {
|
||||
color: #888;
|
||||
display: inline-block;
|
||||
margin-left: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
router-outlet > * {
|
||||
display: block;
|
||||
}
|
||||
47
src/webapp/pdf/static/summary-display.js
Normal file
47
src/webapp/pdf/static/summary-display.js
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
customElements.define('summary-display',
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const template = document.getElementById('summary-display-template');
|
||||
const templateContent = template.content;
|
||||
|
||||
const shadowRoot = this.attachShadow({mode: 'open'});
|
||||
shadowRoot.appendChild(templateContent.cloneNode(true));
|
||||
|
||||
const items = Array.from(this.querySelectorAll('li'));
|
||||
const descriptions = Array.from(this.querySelectorAll('p'));
|
||||
|
||||
items.forEach(item => {
|
||||
handleClick(item);
|
||||
});
|
||||
|
||||
function handleClick(item) {
|
||||
item.addEventListener('click', function() {
|
||||
items.forEach(item => {
|
||||
item.style.backgroundColor = 'white';
|
||||
});
|
||||
|
||||
descriptions.forEach(description => {
|
||||
updateDisplay(description, item);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateDisplay(description, item) {
|
||||
description.removeAttribute('slot');
|
||||
|
||||
if(description.getAttribute('data-name') === item.textContent) {
|
||||
description.setAttribute('slot', 'choice');
|
||||
item.style.backgroundColor = '#bad0e4';
|
||||
}
|
||||
}
|
||||
|
||||
const slots = this.shadowRoot.querySelectorAll('slot');
|
||||
slots[1].addEventListener('slotchange', function(e) {
|
||||
const nodes = slots[1].assignedNodes();
|
||||
console.log(`Element in Slot "${slots[1].name}" changed to "${nodes[0].outerHTML}".`);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue