mirror of
https://github.com/hkalexling/Mango.git
synced 2025-08-03 03:15:31 -04:00
Rewrite reader.js with a reusable alpine function
This commit is contained in:
parent
e64908ad06
commit
a68282b4bf
@ -1,293 +1,264 @@
|
|||||||
let lastSavedPage = page;
|
const readerComponent = () => {
|
||||||
let items = [];
|
return {
|
||||||
let longPages = false;
|
loading: true,
|
||||||
|
mode: 'continuous', // Can be 'continuous', 'height' or 'width'
|
||||||
|
msg: 'Loading the web reader. Please wait...',
|
||||||
|
alertClass: 'uk-alert-primary',
|
||||||
|
items: [],
|
||||||
|
curItem: {},
|
||||||
|
flipAnimation: null,
|
||||||
|
longPages: false,
|
||||||
|
lastSavedPage: page,
|
||||||
|
|
||||||
$(() => {
|
/**
|
||||||
getPages();
|
* Initialize the component by fetching the page dimensions
|
||||||
|
*/
|
||||||
|
init(nextTick) {
|
||||||
|
$.get(`${base_url}api/dimensions/${tid}/${eid}`)
|
||||||
|
.then(data => {
|
||||||
|
if (!data.success && data.error)
|
||||||
|
throw new Error(resp.error);
|
||||||
|
const dimensions = data.dimensions;
|
||||||
|
|
||||||
$('#page-select').change(() => {
|
this.items = dimensions.map((d, i) => {
|
||||||
const p = parseInt($('#page-select').val());
|
return {
|
||||||
toPage(p);
|
id: i + 1,
|
||||||
});
|
url: `${base_url}api/page/${tid}/${eid}/${i+1}`,
|
||||||
|
width: d.width,
|
||||||
|
height: d.height
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
$('#mode-select').change(() => {
|
const avgRatio = this.items.reduce((acc, cur) => {
|
||||||
const mode = $('#mode-select').val();
|
return acc + cur.height / cur.width
|
||||||
const curIdx = parseInt($('#page-select').val());
|
}, 0) / this.items.length;
|
||||||
|
|
||||||
updateMode(mode, curIdx);
|
console.log(avgRatio);
|
||||||
});
|
this.longPages = avgRatio > 2;
|
||||||
});
|
this.loading = false;
|
||||||
|
this.mode = localStorage.getItem('mode') || 'continuous';
|
||||||
|
|
||||||
$(window).resize(() => {
|
// Here we save a copy of this.mode, and use the copy as
|
||||||
const mode = getProp('mode');
|
// the model-select value. This is because `updateMode`
|
||||||
if (mode === 'continuous') return;
|
// might change this.mode and make it `height` or `width`,
|
||||||
|
// which are not available in mode-select
|
||||||
|
const mode = this.mode;
|
||||||
|
this.updateMode(this.mode, page, nextTick);
|
||||||
|
$('#mode-select').val(mode);
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
const errMsg = `Failed to get the page dimensions. ${e}`;
|
||||||
|
console.error(e);
|
||||||
|
this.alertClass = 'uk-alert-danger';
|
||||||
|
this.msg = errMsg;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Handles the `change` event for the page selector
|
||||||
|
*/
|
||||||
|
pageChanged() {
|
||||||
|
const p = parseInt($('#page-select').val());
|
||||||
|
this.toPage(p);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Handles the `change` event for the mode selector
|
||||||
|
*
|
||||||
|
* @param {function} nextTick - Alpine $nextTick magic property
|
||||||
|
*/
|
||||||
|
modeChanged(nextTick) {
|
||||||
|
const mode = $('#mode-select').val();
|
||||||
|
const curIdx = parseInt($('#page-select').val());
|
||||||
|
|
||||||
const wideScreen = $(window).width() > $(window).height();
|
this.updateMode(mode, curIdx, nextTick);
|
||||||
const propMode = wideScreen ? 'height' : 'width';
|
},
|
||||||
setProp('mode', propMode);
|
/**
|
||||||
});
|
* Handles the window `resize` event
|
||||||
|
*/
|
||||||
|
resized() {
|
||||||
|
if (this.mode === 'continuous') return;
|
||||||
|
|
||||||
/**
|
const wideScreen = $(window).width() > $(window).height();
|
||||||
* Update the reader mode
|
this.mode = wideScreen ? 'height' : 'width';
|
||||||
*
|
},
|
||||||
* @function updateMode
|
/**
|
||||||
* @param {string} mode - The mode. Can be one of the followings:
|
* Handles the window `keydown` event
|
||||||
* {'continuous', 'paged', 'height', 'width'}
|
*
|
||||||
* @param {number} targetPage - The one-based index of the target page
|
* @param {Event} event - The triggering event
|
||||||
*/
|
*/
|
||||||
const updateMode = (mode, targetPage) => {
|
keyHandler(event) {
|
||||||
localStorage.setItem('mode', mode);
|
if (this.mode === 'continuous') return;
|
||||||
|
|
||||||
// The mode to be put into the `mode` prop. It can't be `screen`
|
if (event.key === 'ArrowLeft' || event.key === 'k')
|
||||||
let propMode = mode;
|
this.flipPage(false);
|
||||||
|
if (event.key === 'ArrowRight' || event.key === 'j')
|
||||||
|
this.flipPage(true);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Flips to the next or the previous page
|
||||||
|
*
|
||||||
|
* @param {bool} isNext - Whether we are going to the next page
|
||||||
|
*/
|
||||||
|
flipPage(isNext) {
|
||||||
|
const idx = parseInt(this.curItem.id);
|
||||||
|
const delta = isNext ? 1 : -1;
|
||||||
|
const newIdx = idx + delta;
|
||||||
|
|
||||||
if (mode === 'paged') {
|
this.toPage(newIdx);
|
||||||
const wideScreen = $(window).width() > $(window).height();
|
|
||||||
propMode = wideScreen ? 'height' : 'width';
|
|
||||||
}
|
|
||||||
|
|
||||||
setProp('mode', propMode);
|
if (isNext)
|
||||||
|
this.flipAnimation = 'right';
|
||||||
|
else
|
||||||
|
this.flipAnimation = 'left';
|
||||||
|
|
||||||
if (mode === 'continuous') {
|
setTimeout(() => {
|
||||||
waitForPage(items.length, () => {
|
this.flipAnimation = null;
|
||||||
setupScroller();
|
}, 500);
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
waitForPage(targetPage, () => {
|
this.replaceHistory(newIdx);
|
||||||
setTimeout(() => {
|
},
|
||||||
toPage(targetPage);
|
/**
|
||||||
}, 100);
|
* Jumps to a specific page
|
||||||
});
|
*
|
||||||
};
|
* @param {number} idx - One-based index of the page
|
||||||
|
*/
|
||||||
/**
|
toPage(idx) {
|
||||||
* Get dimension of the pages in the entry from the API and update the view
|
if (this.mode === 'continuous') {
|
||||||
*/
|
$(`#${idx}`).get(0).scrollIntoView(true);
|
||||||
const getPages = () => {
|
} else {
|
||||||
$.get(`${base_url}api/dimensions/${tid}/${eid}`)
|
if (idx >= 1 && idx <= this.items.length) {
|
||||||
.then(data => {
|
this.curItem = this.items[idx - 1];
|
||||||
if (!data.success && data.error)
|
}
|
||||||
throw new Error(resp.error);
|
|
||||||
const dimensions = data.dimensions;
|
|
||||||
|
|
||||||
items = dimensions.map((d, i) => {
|
|
||||||
return {
|
|
||||||
id: i + 1,
|
|
||||||
url: `${base_url}api/page/${tid}/${eid}/${i+1}`,
|
|
||||||
width: d.width,
|
|
||||||
height: d.height
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const avgRatio = items.reduce((acc, cur) => {
|
|
||||||
return acc + cur.height / cur.width
|
|
||||||
}, 0) / items.length;
|
|
||||||
|
|
||||||
console.log(avgRatio);
|
|
||||||
longPages = avgRatio > 2;
|
|
||||||
|
|
||||||
setProp('items', items);
|
|
||||||
setProp('loading', false);
|
|
||||||
|
|
||||||
const storedMode = localStorage.getItem('mode') || 'continuous';
|
|
||||||
|
|
||||||
setProp('mode', storedMode);
|
|
||||||
updateMode(storedMode, page);
|
|
||||||
$('#mode-select').val(storedMode);
|
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
const errMsg = `Failed to get the page dimensions. ${e}`;
|
|
||||||
console.error(e);
|
|
||||||
setProp('alertClass', 'uk-alert-danger');
|
|
||||||
setProp('msg', errMsg);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Jump to a specific page
|
|
||||||
*
|
|
||||||
* @function toPage
|
|
||||||
* @param {number} idx - One-based index of the page
|
|
||||||
*/
|
|
||||||
const toPage = (idx) => {
|
|
||||||
const mode = getProp('mode');
|
|
||||||
if (mode === 'continuous') {
|
|
||||||
$(`#${idx}`).get(0).scrollIntoView(true);
|
|
||||||
} else {
|
|
||||||
if (idx >= 1 && idx <= items.length) {
|
|
||||||
setProp('curItem', items[idx - 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
replaceHistory(idx);
|
|
||||||
UIkit.modal($('#modal-sections')).hide();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a page exists every 100ms. If so, invoke the callback function.
|
|
||||||
*
|
|
||||||
* @function waitForPage
|
|
||||||
* @param {number} idx - One-based index of the page
|
|
||||||
* @param {function} cb - Callback function
|
|
||||||
*/
|
|
||||||
const waitForPage = (idx, cb) => {
|
|
||||||
if ($(`#${idx}`).length > 0) return cb();
|
|
||||||
setTimeout(() => {
|
|
||||||
waitForPage(idx, cb)
|
|
||||||
}, 100);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the control modal
|
|
||||||
*
|
|
||||||
* @function showControl
|
|
||||||
* @param {string} idx - One-based index of the current page
|
|
||||||
*/
|
|
||||||
const showControl = (idx) => {
|
|
||||||
const pageCount = $('#page-select > option').length;
|
|
||||||
const progressText = `Progress: ${idx}/${pageCount} (${(idx/pageCount * 100).toFixed(1)}%)`;
|
|
||||||
$('#progress-label').text(progressText);
|
|
||||||
$('#page-select').val(idx);
|
|
||||||
UIkit.modal($('#modal-sections')).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirect to a URL
|
|
||||||
*
|
|
||||||
* @function redirect
|
|
||||||
* @param {string} url - The target URL
|
|
||||||
*/
|
|
||||||
const redirect = (url) => {
|
|
||||||
window.location.replace(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace the address bar history and save th ereading progress if necessary
|
|
||||||
*
|
|
||||||
* @function replaceHistory
|
|
||||||
* @param {number} idx - One-based index of the current page
|
|
||||||
*/
|
|
||||||
const replaceHistory = (idx) => {
|
|
||||||
const ary = window.location.pathname.split('/');
|
|
||||||
ary[ary.length - 1] = idx;
|
|
||||||
ary.shift(); // remove leading `/`
|
|
||||||
ary.unshift(window.location.origin);
|
|
||||||
const url = ary.join('/');
|
|
||||||
saveProgress(idx);
|
|
||||||
history.replaceState(null, "", url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set up the scroll handler that calls `replaceHistory` when an image
|
|
||||||
* enters the view port
|
|
||||||
*
|
|
||||||
* @function setupScroller
|
|
||||||
*/
|
|
||||||
const setupScroller = () => {
|
|
||||||
const mode = getProp('mode');
|
|
||||||
if (mode !== 'continuous') return;
|
|
||||||
$('#root img').each((idx, el) => {
|
|
||||||
$(el).on('inview', (event, inView) => {
|
|
||||||
if (inView) {
|
|
||||||
const current = $(event.currentTarget).attr('id');
|
|
||||||
|
|
||||||
setProp('curItem', getProp('items')[current - 1]);
|
|
||||||
replaceHistory(current);
|
|
||||||
}
|
}
|
||||||
});
|
this.replaceHistory(idx);
|
||||||
});
|
UIkit.modal($('#modal-sections')).hide();
|
||||||
};
|
},
|
||||||
|
/**
|
||||||
|
* Replace the address bar history and save the reading progress if necessary
|
||||||
|
*
|
||||||
|
* @param {number} idx - One-based index of the page
|
||||||
|
*/
|
||||||
|
replaceHistory(idx) {
|
||||||
|
const ary = window.location.pathname.split('/');
|
||||||
|
ary[ary.length - 1] = idx;
|
||||||
|
ary.shift(); // remove leading `/`
|
||||||
|
ary.unshift(window.location.origin);
|
||||||
|
const url = ary.join('/');
|
||||||
|
this.saveProgress(idx);
|
||||||
|
history.replaceState(null, "", url);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Updates the backend reading progress if:
|
||||||
|
* 1) the current page is more than five pages away from the last
|
||||||
|
* saved page, or
|
||||||
|
* 2) the average height/width ratio of the pages is over 2, or
|
||||||
|
* 3) the current page is the first page, or
|
||||||
|
* 4) the current page is the last page
|
||||||
|
*
|
||||||
|
* @param {number} idx - One-based index of the page
|
||||||
|
* @param {function} cb - Callback
|
||||||
|
*/
|
||||||
|
saveProgress(idx, cb) {
|
||||||
|
idx = parseInt(idx);
|
||||||
|
if (Math.abs(idx - this.lastSavedPage) >= 5 ||
|
||||||
|
this.longPages ||
|
||||||
|
idx === 1 || idx === this.items.length
|
||||||
|
) {
|
||||||
|
this.lastSavedPage = idx;
|
||||||
|
console.log('saving progress', idx);
|
||||||
|
|
||||||
/**
|
const url = `${base_url}api/progress/${tid}/${idx}?${$.param({eid: eid})}`;
|
||||||
* Update the backend reading progress if:
|
$.ajax({
|
||||||
* 1) the current page is more than five pages away from the last
|
method: 'PUT',
|
||||||
* saved page, or
|
url: url,
|
||||||
* 2) the average height/width ratio of the pages is over 2, or
|
dataType: 'json'
|
||||||
* 3) the current page is the first page, or
|
})
|
||||||
* 4) the current page is the last page
|
.done(data => {
|
||||||
*
|
if (data.error)
|
||||||
* @function saveProgress
|
alert('danger', data.error);
|
||||||
* @param {number} idx - One-based index of the page
|
if (cb) cb();
|
||||||
* @param {function} cb - Callback
|
})
|
||||||
*/
|
.fail((jqXHR, status) => {
|
||||||
const saveProgress = (idx, cb) => {
|
alert('danger', `Error: [${jqXHR.status}] ${jqXHR.statusText}`);
|
||||||
idx = parseInt(idx);
|
});
|
||||||
if (Math.abs(idx - lastSavedPage) >= 5 ||
|
}
|
||||||
longPages ||
|
},
|
||||||
idx === 1 || idx === items.length
|
/**
|
||||||
) {
|
* Updates the reader mode
|
||||||
lastSavedPage = idx;
|
*
|
||||||
console.log('saving progress', idx);
|
* @param {string} mode - Either `continuous` or `paged`
|
||||||
|
* @param {number} targetPage - The one-based index of the target page
|
||||||
|
* @param {function} nextTick - Alpine $nextTick magic property
|
||||||
|
*/
|
||||||
|
updateMode(mode, targetPage, nextTick) {
|
||||||
|
localStorage.setItem('mode', mode);
|
||||||
|
|
||||||
const url = `${base_url}api/progress/${tid}/${idx}?${$.param({eid: eid})}`;
|
// The mode to be put into the `mode` prop. It can't be `screen`
|
||||||
$.ajax({
|
let propMode = mode;
|
||||||
method: 'PUT',
|
|
||||||
url: url,
|
if (mode === 'paged') {
|
||||||
dataType: 'json'
|
const wideScreen = $(window).width() > $(window).height();
|
||||||
})
|
propMode = wideScreen ? 'height' : 'width';
|
||||||
.done(data => {
|
}
|
||||||
if (data.error)
|
|
||||||
alert('danger', data.error);
|
this.mode = propMode;
|
||||||
if (cb) cb();
|
|
||||||
})
|
if (mode === 'continuous') {
|
||||||
.fail((jqXHR, status) => {
|
nextTick(() => {
|
||||||
alert('danger', `Error: [${jqXHR.status}] ${jqXHR.statusText}`);
|
this.setupScroller();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
this.toPage(targetPage);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
/**
|
||||||
|
* Shows the control modal
|
||||||
|
*
|
||||||
|
* @param {Event} event - The triggering event
|
||||||
|
*/
|
||||||
|
showControl(event) {
|
||||||
|
const idx = event.currentTarget.id;
|
||||||
|
const pageCount = this.items.length;
|
||||||
|
const progressText = `Progress: ${idx}/${pageCount} (${(idx/pageCount * 100).toFixed(1)}%)`;
|
||||||
|
$('#progress-label').text(progressText);
|
||||||
|
$('#page-select').val(idx);
|
||||||
|
UIkit.modal($('#modal-sections')).show();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Redirects to a URL
|
||||||
|
*
|
||||||
|
* @param {string} url - The target URL
|
||||||
|
*/
|
||||||
|
redirect(url) {
|
||||||
|
window.location.replace(url);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Set up the scroll handler that calls `replaceHistory` when an image
|
||||||
|
* enters the view port
|
||||||
|
*/
|
||||||
|
setupScroller() {
|
||||||
|
if (this.mode !== 'continuous') return;
|
||||||
|
$('#root img').each((idx, el) => {
|
||||||
|
$(el).on('inview', (event, inView) => {
|
||||||
|
if (inView) {
|
||||||
|
const current = $(event.currentTarget).attr('id');
|
||||||
|
|
||||||
/**
|
this.curItem = this.items[current - 1];
|
||||||
* Mark progress to 100% and redirect to the next entry
|
this.replaceHistory(current);
|
||||||
* Used as the onclick handler for the "Next Entry" button
|
}
|
||||||
*
|
});
|
||||||
* @function nextEntry
|
});
|
||||||
* @param {string} nextUrl - URL of the next entry
|
},
|
||||||
*/
|
/**
|
||||||
const nextEntry = (nextUrl) => {
|
* Marks progress as 100% and jumps to the next entry
|
||||||
saveProgress(items.length, () => {
|
*
|
||||||
redirect(nextUrl);
|
* @param {string} nextUrl - URL of the next entry
|
||||||
});
|
*/
|
||||||
};
|
nextEntry(nextUrl) {
|
||||||
|
this.saveProgress(items.length, () => {
|
||||||
/**
|
this.redirect(nextUrl);
|
||||||
* Show the next or the previous page
|
});
|
||||||
*
|
}
|
||||||
* @function flipPage
|
};
|
||||||
* @param {bool} isNext - Whether we are going to the next page
|
}
|
||||||
*/
|
|
||||||
const flipPage = (isNext) => {
|
|
||||||
const curItem = getProp('curItem');
|
|
||||||
const idx = parseInt(curItem.id);
|
|
||||||
const delta = isNext ? 1 : -1;
|
|
||||||
const newIdx = idx + delta;
|
|
||||||
|
|
||||||
toPage(newIdx);
|
|
||||||
|
|
||||||
if (isNext)
|
|
||||||
setProp('flipAnimation', 'right');
|
|
||||||
else
|
|
||||||
setProp('flipAnimation', 'left');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
setProp('flipAnimation', null);
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
replaceHistory(newIdx);
|
|
||||||
saveProgress(newIdx);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle the global keydown events
|
|
||||||
*
|
|
||||||
* @function keyHandler
|
|
||||||
* @param {event} event - The $event object
|
|
||||||
*/
|
|
||||||
const keyHandler = (event) => {
|
|
||||||
const mode = getProp('mode');
|
|
||||||
if (mode === 'continuous') return;
|
|
||||||
|
|
||||||
if (event.key === 'ArrowLeft' || event.key === 'k')
|
|
||||||
flipPage(false);
|
|
||||||
if (event.key === 'ArrowRight' || event.key === 'j')
|
|
||||||
flipPage(true);
|
|
||||||
};
|
|
||||||
|
@ -4,19 +4,8 @@
|
|||||||
<% page = "Reader" %>
|
<% page = "Reader" %>
|
||||||
<%= render_component "head" %>
|
<%= render_component "head" %>
|
||||||
|
|
||||||
<body style="position:relative;">
|
<body style="position:relative;" x-data="readerComponent()" x-init="init($nextTick)" @resize.window="resized()">
|
||||||
<div class="uk-section uk-section-default uk-section-small reader-bg"
|
<div class="uk-section uk-section-default uk-section-small reader-bg" :style="mode === 'continuous' ? '' : 'padding:0'">
|
||||||
id="root"
|
|
||||||
:style="mode === 'continuous' ? '' : 'padding:0'"
|
|
||||||
x-data="{
|
|
||||||
loading: true,
|
|
||||||
mode: 'continuous', // can be 'continuous', 'height' or 'width'
|
|
||||||
msg: 'Loading the web reader. Please wait...',
|
|
||||||
alertClass: 'uk-alert-primary',
|
|
||||||
items: [],
|
|
||||||
curItem: {},
|
|
||||||
flipAnimation: null
|
|
||||||
}">
|
|
||||||
|
|
||||||
<div @keydown.window.debounce="keyHandler($event)"></div>
|
<div @keydown.window.debounce="keyHandler($event)"></div>
|
||||||
|
|
||||||
@ -40,7 +29,7 @@
|
|||||||
:width="item.width"
|
:width="item.width"
|
||||||
:height="item.height"
|
:height="item.height"
|
||||||
:id="item.id"
|
:id="item.id"
|
||||||
:onclick="`showControl('${item.id}')`"
|
@click="showControl($event)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<%- if next_entry_url -%>
|
<%- if next_entry_url -%>
|
||||||
@ -56,11 +45,11 @@
|
|||||||
'uk-align-center': true,
|
'uk-align-center': true,
|
||||||
'uk-animation-slide-left': flipAnimation === 'left',
|
'uk-animation-slide-left': flipAnimation === 'left',
|
||||||
'uk-animation-slide-right': flipAnimation === 'right'
|
'uk-animation-slide-right': flipAnimation === 'right'
|
||||||
}" :data-src="curItem.url" :width="curItem.width" :height="curItem.height" :id="curItem.id" :onclick="`showControl('${curItem.id}')`" :style="`
|
}" :data-src="curItem.url" :width="curItem.width" :height="curItem.height" :id="curItem.id" @click="showControl($event)" :style="`
|
||||||
width:${mode === 'width' ? '100vw' : 'auto'};
|
width:${mode === 'width' ? '100vw' : 'auto'};
|
||||||
height:${mode === 'height' ? '100vh' : 'auto'};
|
height:${mode === 'height' ? '100vh' : 'auto'};
|
||||||
margin-bottom:0;
|
margin-bottom:0;
|
||||||
`" />
|
`" />
|
||||||
|
|
||||||
<div style="position:absolute;z-index:1; top:0;left:0; width:30%;height:100%;" @click="flipPage(false)"></div>
|
<div style="position:absolute;z-index:1; top:0;left:0; width:30%;height:100%;" @click="flipPage(false)"></div>
|
||||||
<div style="position:absolute;z-index:1; top:0;right:0; width:30%;height:100%;" @click="flipPage(true)"></div>
|
<div style="position:absolute;z-index:1; top:0;right:0; width:30%;height:100%;" @click="flipPage(true)"></div>
|
||||||
@ -83,7 +72,7 @@
|
|||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
<label class="uk-form-label" for="page-select">Jump to page</label>
|
<label class="uk-form-label" for="page-select">Jump to page</label>
|
||||||
<div class="uk-form-controls">
|
<div class="uk-form-controls">
|
||||||
<select id="page-select" class="uk-select">
|
<select id="page-select" class="uk-select" @change="pageChanged()">
|
||||||
<%- (1..entry.pages).each do |p| -%>
|
<%- (1..entry.pages).each do |p| -%>
|
||||||
<option value="<%= p %>"><%= p %></option>
|
<option value="<%= p %>"><%= p %></option>
|
||||||
<%- end -%>
|
<%- end -%>
|
||||||
@ -93,7 +82,7 @@
|
|||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
<label class="uk-form-label" for="mode-select">Mode</label>
|
<label class="uk-form-label" for="mode-select">Mode</label>
|
||||||
<div class="uk-form-controls">
|
<div class="uk-form-controls">
|
||||||
<select id="mode-select" class="uk-select">
|
<select id="mode-select" class="uk-select" @change="modeChanged($nextTick)">
|
||||||
<option value="continuous">Continuous</option>
|
<option value="continuous">Continuous</option>
|
||||||
<option value="paged">Paged</option>
|
<option value="paged">Paged</option>
|
||||||
</select>
|
</select>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user