pagination nav refactoring, only miss pages display in text

This commit is contained in:
2020-07-22 13:03:03 +02:00
parent 2c7b8004f5
commit def83059ed
4 changed files with 216 additions and 122 deletions
+8 -7
View File
@@ -472,7 +472,8 @@ section[role="main-content"]{
$w:3em; $w:3em;
width:$w; height:0; width:$w; height:0;
margin-left:calc(100% - (#{$w} * 0.5)); margin-left:calc(100% - (#{$w} * 0.5));
&:before, &:after{ // &:before
&:after{
display: block; display: block;
position: absolute; position: absolute;
font-size: 0.630em; font-size: 0.630em;
@@ -483,13 +484,13 @@ section[role="main-content"]{
color: $bleuroi; color: $bleuroi;
text-indent: $w + 0.5em; text-indent: $w + 0.5em;
} }
&:before{ // &:before{
content:attr(data-num-prev); // content:attr(data-num-prev);
border-bottom: 1px solid $bleuroilight; // border-bottom: 1px solid $bleuroilight;
bottom: 0.1em; // bottom: 0.1em;
} // }
&:after{ &:after{
content:attr(data-num); content:attr(title);
border-top: 1px solid $bleuroilight; border-top: 1px solid $bleuroilight;
top:0.1em; top:0.1em;
} }
+130
View File
@@ -0,0 +1,130 @@
<template>
<div v-if="options.length">
<!-- <select class="" name="page-nav" v-model="page_selected" placeholder="Pages">
<option value="" disabled selected>Pages</option>
<option v-for="(page, index) in pages" :key="index" :value="page">{{ page }}</option>
</select> -->
<v-select
id="page-nav-select"
type="select"
placeholder="Aller à la page ..."
append-to-body
:calculate-position="dropDownMenuPos"
:options="options"
:clearable="false"
:value="page_selected"
:selectable="option => ! option.disabled"
@input="onClickPaginationItem"
>
<template v-slot:option="option">
<span v-for="l in option.level" :key="l" class="op-tab"/>
{{ option.label }}
</template>
</v-select>
</div>
</template>
<script>
import { createPopper } from '@popperjs/core'
export default {
name: 'EdPagination',
props: {
pagination: Array
},
data: () => ({
options: [],
page_selected: ''
}),
created () {
this.parsePagesToOptions(this.pagination)
},
// watch: {
// loadedtextsuuids (n, o) {
// console.log('EdToc watch loadedtxtsuuids', o, n)
// }
// },
methods: {
parsePagesToOptions (p, i = 0, l = 0) {
console.log('EdPagination parsePagesToOptions', p)
for (var j = 0; j < p.length; j++) {
// if it is just a section without page like a volume
if (p[j].text) {
this.options.push({
key: i,
code: p[j].text,
label: p[j].text,
disabled: true,
level: l
})
}
// if it's a real page break
if (p[j].pageBreak) {
this.options.push({
key: i,
code: p[j].pageBreak,
label: p[j].pageNum,
uuid: p[j].uuid,
level: l
})
}
if (p[j].pages && p[j].pages.length) {
this.parsePagesToOptions(p[j].pages, i++, l + 1)
} else {
i++
}
}
},
dropDownMenuPos (dropdownList, component, { width }) {
/**
* We need to explicitly define the dropdown width since
* it is usually inherited from the parent with CSS.
*/
dropdownList.style.width = width
/**
* Here we position the dropdownList relative to the $refs.toggle Element.
*
* The 'offset' modifier aligns the dropdown so that the $refs.toggle and
* the dropdownList overlap by 1 pixel.
*
* The 'toggleClass' modifier adds a 'drop-up' class to the Vue Select
* wrapper so that we can set some styles for when the dropdown is placed
* above.
*/
const popper = createPopper(component.$refs.toggle, dropdownList, {
placement: 'top',
modifiers: [
{
name: 'offset',
options: {
offset: [0, -1]
}
},
{
name: 'toggleClass',
enabled: true,
phase: 'write',
fn ({ state }) {
component.$el.classList.toggle('drop-up', state.placement === 'top')
}
}]
})
/**
* To prevent memory leaks Popper needs to be destroyed.
* If you return function, it will be called just before dropdown is removed from DOM.
*/
return () => popper.destroy()
},
onClickPaginationItem (o) {
this.page_selected = o
this.$emit('onClickPaginationItem', o)
}
}
}
</script>
<style lang="scss" scoped>
</style>
+25 -25
View File
@@ -27,9 +27,9 @@ export default {
this.buildTemplate() this.buildTemplate()
} }
}, },
mounted () { // mounted () {
this.$emit('onNewPageBreaks', this.pages) // this.$emit('onNewPageBreaks', this.pages)
}, // },
methods: { methods: {
buildTemplate () { buildTemplate () {
// console.log('EdText buildTemplate: tei', this.tei) // console.log('EdText buildTemplate: tei', this.tei)
@@ -89,28 +89,28 @@ export default {
}, },
parsePageBreaks () { parsePageBreaks () {
let pbs = this.html.match(/<span role="pageBreak"[^>]+><\/span>/g) let pbs = this.html.match(/<span role="pageBreak"[^>]+><\/span>/g)
// console.log('pagebreaks', pbs) console.log('pagebreaks', pbs)
if (pbs) { // if (pbs) {
let pbparts, newpb, num // let pbparts, newpb, num
for (var i = 0; i < pbs.length; i++) { // for (var i = 0; i < pbs.length; i++) {
pbparts = RegExp(/<span role="pageBreak" data-num="(.+)"><\/span>/).exec(pbs[i], 'g') // pbparts = RegExp(/<span role="pageBreak" data-num="(.+)"><\/span>/).exec(pbs[i], 'g')
if (!pbparts) { // if (!pbparts) {
console.warn(`pageBreak ${i} maformed`, pbs[i]) // console.warn(`pageBreak ${i} maformed`, pbs[i])
} else { // } else {
// console.log('pbparts', pbparts) // // console.log('pbparts', pbparts)
num = pbparts[1] // num = pbparts[1]
this.pages.push(num) // this.pages.push(num)
newpb = `<span` + // newpb = `<span` +
// ` id="page-break-${num}"` + // // ` id="page-break-${num}"` +
` role="pageBreak"` + // ` role="pageBreak"` +
` data-num="${num}"` + // ` data-num="${num}"` +
` data-num-prev="${num - 1}"` + // ` data-num-prev="${num - 1}"` +
` />` // ` />`
// console.log('newpb', newpb) // // console.log('newpb', newpb)
this.html = this.html.replace(pbs[i], newpb) // this.html = this.html.replace(pbs[i], newpb)
} // }
} // }
} // }
}, },
onClickRef (e) { onClickRef (e) {
console.log('onClickRef(e)', e) console.log('onClickRef(e)', e)
+53 -90
View File
@@ -51,7 +51,6 @@
:textid="textid" :textid="textid"
@onHoverLink="onHoverLink" @onHoverLink="onHoverLink"
@onLeaveLink="onLeaveLink" @onLeaveLink="onLeaveLink"
@onNewPageBreaks="onNewPageBreaks"
/> />
<infinite-loading <infinite-loading
:identifier="textid" :identifier="textid"
@@ -61,37 +60,30 @@
</div> </div>
<template #nav> <template #nav>
<EdToc id="toc" :toc="toc" :loadedtextsuuids="textsuuids" @onClickTocItem="onClickTocItem" /> <EdToc
<div v-if="pages.length" id="page-nav"> id="toc"
<!-- <select class="" name="page-nav" v-model="page_selected" placeholder="Pages"> :toc="toc"
<option value="" disabled selected>Pages</option> :loadedtextsuuids="textsuuids"
<option v-for="(page, index) in pages" :key="index" :value="page">{{ page }}</option> @onClickTocItem="onClickTocItem"
</select> --> />
<v-select <EdPagination
id="page-nav-select" v-if="pagination"
type="select" id="page-nav"
placeholder="Aller à la page ..." :pagination="pagination"
append-to-body @onClickPaginationItem="onClickPaginationItem"
:calculate-position="dropDownMenuPos" />
:options="pages"
:clearable="false"
:value="page_selected"
@input="onPageSelected"
/>
</div>
</template> </template>
</MainContentLayout> </MainContentLayout>
</template> </template>
<script> <script>
import { createPopper } from '@popperjs/core'
import { REST } from 'api/rest-axios' import { REST } from 'api/rest-axios'
import { mapState, mapActions } from 'vuex' import { mapState, mapActions } from 'vuex'
import MainContentLayout from '../components/Layouts/MainContentLayout' import MainContentLayout from '../components/Layouts/MainContentLayout'
import EdText from '../components/Content/EdText' import EdText from '../components/Content/EdText'
import EdToc from '../components/Content/EdToc' import EdToc from '../components/Content/EdToc'
import EdPagination from '../components/Content/EdPagination'
export default { export default {
name: 'Edition', name: 'Edition',
@@ -104,7 +96,8 @@ export default {
components: { components: {
MainContentLayout, MainContentLayout,
EdText, EdText,
EdToc EdToc,
EdPagination
}, },
data: () => ({ data: () => ({
toc: null, toc: null,
@@ -126,9 +119,7 @@ export default {
inifinite_load_distance: 10, inifinite_load_distance: 10,
reftoscrollto: null, reftoscrollto: null,
// //
pages: [], pagination: null
pagesOptions: [],
page_selected: ''
}), }),
computed: { computed: {
...mapState({ ...mapState({
@@ -193,10 +184,28 @@ export default {
} }
} else { } else {
console.warn('Bad edition uuid', this.$route.params.id, this.$route) console.warn('Bad edition uuid', this.$route.params.id, this.$route)
this.$router.replace({ // this.$router.replace({
name: 'notfound', // name: 'notfound',
query: { fullpath: this.$route.path } // query: { fullpath: this.$route.path }
}) // })
}
})
.catch((error) => {
console.warn('Issue with text toc', error)
Promise.reject(error)
})
// get the edition's pagination
REST.get(`${window.apipath}/texts/` + this.$route.params.id + `/pagination`, {})
.then(({ data }) => {
console.log('texts/pagination REST: data', data)
if (data.content && data.content !== 'vide') {
this.pagination = data.content
} else {
console.warn('Bad edition uuid', this.$route.params.id, this.$route)
// this.$router.replace({
// name: 'notfound',
// query: { fullpath: this.$route.path }
// })
} }
}) })
.catch((error) => { .catch((error) => {
@@ -336,71 +345,25 @@ export default {
}) })
} }
}, },
onNewPageBreaks (p) { onClickPaginationItem (o) {
// console.log('onNewPageBreaks', p) console.log('onClickPaginationItem', o)
for (var i = 0; i < p.length; i++) { if (this.textsuuids.indexOf(o.uuid) !== -1) {
if (this.pages.indexOf(p[i]) === -1) { // if already loaded, scroll to uuid
this.pages.push(p[i]) this.scrollToPage(o)
} } else {
// if not already loaded, change route
this.$router.push({
name: `editiontext`,
params: {
id: this.editionid,
textid: o.uuid
}
})
} }
// reorder array
this.pages.sort((a, b) => a - b)
// this.pagesOptions = []
// for (var j = 0; j < this.pages.length; j++) {
// this.pagesOptions.push({ code: this.pages[j], label: `page ${this.pages[j]}` })
// }
},
dropDownMenuPos (dropdownList, component, { width }) {
/**
* We need to explicitly define the dropdown width since
* it is usually inherited from the parent with CSS.
*/
dropdownList.style.width = width
/**
* Here we position the dropdownList relative to the $refs.toggle Element.
*
* The 'offset' modifier aligns the dropdown so that the $refs.toggle and
* the dropdownList overlap by 1 pixel.
*
* The 'toggleClass' modifier adds a 'drop-up' class to the Vue Select
* wrapper so that we can set some styles for when the dropdown is placed
* above.
*/
const popper = createPopper(component.$refs.toggle, dropdownList, {
placement: 'top',
modifiers: [
{
name: 'offset',
options: {
offset: [0, -1]
}
},
{
name: 'toggleClass',
enabled: true,
phase: 'write',
fn ({ state }) {
component.$el.classList.toggle('drop-up', state.placement === 'top')
}
}]
})
/**
* To prevent memory leaks Popper needs to be destroyed.
* If you return function, it will be called just before dropdown is removed from DOM.
*/
return () => popper.destroy()
},
onPageSelected (e) {
console.log('onPageSelected', e)
this.page_selected = e
this.scrollToPage(e)
// this.scrollToPage(e.code)
}, },
scrollToPage (p) { scrollToPage (p) {
// console.log('scrollToPage', p) // console.log('scrollToPage', p)
this.reftoscrollto = `span[role="pageBreak"][data-num="${p}"]` this.reftoscrollto = `span[role="pageBreak"][id="${p.code}"]`
} }
} }
} }