mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-22 11:37:56 -04:00
Merge pull request #138 from kiwix/split--contentManagerHtml
Split contentmanager.html
This commit is contained in:
commit
9a3a554e6f
@ -2,5 +2,7 @@
|
|||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file>js/vue.js</file>
|
<file>js/vue.js</file>
|
||||||
<file>texts/_contentManager.html</file>
|
<file>texts/_contentManager.html</file>
|
||||||
|
<file>css/_contentManager.css</file>
|
||||||
|
<file>js/_contentManager.js</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
149
resources/css/_contentManager.css
Normal file
149
resources/css/_contentManager.css
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
html, body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#app {
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
*:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
#searchInput {
|
||||||
|
background-image: url('qrc:///icons/search.svg');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: left top;
|
||||||
|
background-size: 40px 40px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
padding-left: 45px;
|
||||||
|
height: 40px;
|
||||||
|
width: 90%;
|
||||||
|
border: 1px solid #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bookTable {
|
||||||
|
position: relative;
|
||||||
|
height: calc(100% - 42px); /* 42px = 40px(height of #searchInput) + 2px(border) */
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bookList {
|
||||||
|
height: calc(100% - 19px - 20px); /*19px the header size, 20px the header margin-top */
|
||||||
|
overflow-y:scroll;
|
||||||
|
overflow-x:hidden;
|
||||||
|
position: relative;
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.tablerow,
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
color: #555;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.tablecell{
|
||||||
|
flex-basis:20%;
|
||||||
|
}
|
||||||
|
.cell0 {
|
||||||
|
flex-basis: 60px;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.tablerow > .cell1 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.cell0 > img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
.cell1,
|
||||||
|
.cell2,
|
||||||
|
.cell3,
|
||||||
|
.cell4,
|
||||||
|
.cell5 {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
summary::-webkit-details-marker {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
summary {
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
.book {
|
||||||
|
border-top: 1px solid #EEE;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background: transparent;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
.tablerow button {
|
||||||
|
color: blue;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 0px;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.tablerow button:hover {
|
||||||
|
color: white;
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
details:hover {
|
||||||
|
background-color: #d9e9ff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
/* width: 120px; */
|
||||||
|
box-shadow: 0 4px 5px 3px rgba(0, 0, 0, 0.2);
|
||||||
|
position: fixed;
|
||||||
|
display: none;
|
||||||
|
z-index: 99999999999999;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-options {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0 0 0 0;
|
||||||
|
margin: 2px 0px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-option {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 10px 40px 10px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-option:hover {
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
.loader {
|
||||||
|
margin: 0 auto;
|
||||||
|
border: 16px solid #f3f3f3; /* Light grey */
|
||||||
|
border-top: 16px solid #3498db; /* Blue */
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.do-not-display {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
173
resources/js/_contentManager.js
Normal file
173
resources/js/_contentManager.js
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
function niceBytes(x){
|
||||||
|
var unitIndex = 0;
|
||||||
|
var n = parseInt(x, 10) || 0;
|
||||||
|
while(n >= 1024 && ++unitIndex)
|
||||||
|
n = n/1024;
|
||||||
|
return(n.toFixed(n >= 10 || unitIndex < 1 ? 0 : 2) + ' ' + units[unitIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDict(keys, values) {
|
||||||
|
var d = {}
|
||||||
|
for(var i=0; i<keys.length; i++) {
|
||||||
|
d[keys[i]] = values[i];
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
const BOOK_KEYS = ["id", "name", "path", "url", "size", "description", "title", "tags", "date", "faviconUrl", "faviconMimeType", "downloadId"];
|
||||||
|
function addBook(values) {
|
||||||
|
var b = createDict(BOOK_KEYS, values);
|
||||||
|
if (b.downloadId && !downloadUpdaters.hasOwnProperty(b.id)) {
|
||||||
|
downloadUpdaters[b.id] = setInterval(function() { getDownloadInfo(b.id); }, 1000);
|
||||||
|
}
|
||||||
|
app.books.push(b);
|
||||||
|
}
|
||||||
|
function onBooksChanged () {
|
||||||
|
app.books = [];
|
||||||
|
for(var i=0; i<contentManager.bookIds.length; i++) {
|
||||||
|
var id = contentManager.bookIds[i];
|
||||||
|
contentManager.getBookInfos(id, BOOK_KEYS, addBook);
|
||||||
|
}
|
||||||
|
app.displayedBooksNb = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadUpdaters = {}
|
||||||
|
const DOWNLOAD_KEYS = ["id", "status", "followedBy", "path", "totalLength", "completedLength", "downloadSpeed", "verifiedLength"];
|
||||||
|
function getDownloadInfo(id) {
|
||||||
|
contentManager.updateDownloadInfos(id, DOWNLOAD_KEYS, function(values) {
|
||||||
|
if (values.length == 0) {
|
||||||
|
clearInterval(downloadUpdaters[id]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d = createDict(DOWNLOAD_KEYS, values);
|
||||||
|
if (d.status == "completed") {
|
||||||
|
clearInterval(downloadUpdaters[id]);
|
||||||
|
Vue.delete(app.downloads, id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Vue.set(app.downloads, id, createDict(DOWNLOAD_KEYS, values));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayLoadIcon(display) {
|
||||||
|
if (display) {
|
||||||
|
document.getElementById("load-icon").classList.remove("do-not-display")
|
||||||
|
document.getElementById("bookList").classList.add("do-not-display");
|
||||||
|
} else {
|
||||||
|
document.getElementById("load-icon").classList.add("do-not-display");
|
||||||
|
document.getElementById("bookList").classList.remove("do-not-display")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
new QWebChannel(qt.webChannelTransport, function(channel) {
|
||||||
|
contentManager = channel.objects.contentManager;
|
||||||
|
app = new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data: {
|
||||||
|
contentManager: contentManager,
|
||||||
|
displayedBooksNb: 20,
|
||||||
|
books: [],
|
||||||
|
downloads: {}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openBook : function(book) {
|
||||||
|
contentManager.openBook(book.id, function() {});
|
||||||
|
},
|
||||||
|
downloadBook : function(book) {
|
||||||
|
contentManager.downloadBook(book.id, function(did) {
|
||||||
|
if (did.length == 0)
|
||||||
|
return;
|
||||||
|
book.downloadId = did;
|
||||||
|
downloadUpdaters[book.id] = setInterval(function() { getDownloadInfo(book.id); }, 1000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
eraseBook : function(book) {
|
||||||
|
contentManager.eraseBook(book.id);
|
||||||
|
},
|
||||||
|
pauseBook : function(book) {
|
||||||
|
contentManager.pauseBook(book.id);
|
||||||
|
},
|
||||||
|
resumeBook : function(book) {
|
||||||
|
contentManager.resumeBook(book.id);
|
||||||
|
},
|
||||||
|
cancelBook : function(book) {
|
||||||
|
contentManager.cancelBook(book.id);
|
||||||
|
clearInterval(downloadUpdaters[book.id]);
|
||||||
|
Vue.delete(app.downloads, book.id);
|
||||||
|
},
|
||||||
|
displayedBooks : function(books, nb) {
|
||||||
|
var a = books.slice(0, nb);
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
getBookFromMousePosition : function() {
|
||||||
|
var elements = document.elementsFromPoint(mouseX, mouseY);
|
||||||
|
var bookId = null;
|
||||||
|
for(var i = 0; i < elements.length; i++) {
|
||||||
|
if (elements[i].localName == "summary" && elements[i].classList.contains("book-summary")) {
|
||||||
|
bookId = elements[i].id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var book = null;
|
||||||
|
for(var i = 0; i < app.books.length; i++) {
|
||||||
|
if (app.books[i]["id"] == bookId) {
|
||||||
|
book = app.books[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return book;
|
||||||
|
},
|
||||||
|
niceBytes : niceBytes
|
||||||
|
}
|
||||||
|
});
|
||||||
|
contentManager.booksChanged.connect(onBooksChanged);
|
||||||
|
contentManager.pendingRequest.connect(displayLoadIcon);
|
||||||
|
onBooksChanged();
|
||||||
|
displayLoadIcon(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
futurCall = null;
|
||||||
|
function setSearch(value) {
|
||||||
|
clearTimeout(futurCall);
|
||||||
|
futurCall = setTimeout(function(){contentManager.setSearch(value)}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
function scrolled(e) {
|
||||||
|
if (e.offsetHeight + e.scrollTop >= e.scrollHeight) {
|
||||||
|
app.displayedBooksNb = Math.min(app.displayedBooksNb+20, app.books.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("click", e => {
|
||||||
|
if (menuVisible)
|
||||||
|
displayMenu(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
var mouseX, mouseY = 0;
|
||||||
|
window.addEventListener("contextmenu", e => {
|
||||||
|
e.preventDefault();
|
||||||
|
mouseX = e.pageX;
|
||||||
|
mouseY = e.pageY;
|
||||||
|
setContextMenuPosition();
|
||||||
|
var book = app.getBookFromMousePosition();
|
||||||
|
displayMenu(book);
|
||||||
|
});
|
||||||
|
|
||||||
|
var menuVisible = false;
|
||||||
|
function displayMenu(book) {
|
||||||
|
var menu = document.getElementById("menu");
|
||||||
|
menu.style.display = (book) ? "block" : "none";
|
||||||
|
menuVisible = (book) ? true : false;
|
||||||
|
if (!book)
|
||||||
|
return;
|
||||||
|
var localElement = document.getElementsByClassName("local-option")[0];
|
||||||
|
localElement.style.display = (book.path) ? "block" : "none";
|
||||||
|
};
|
||||||
|
|
||||||
|
function setContextMenuPosition() {
|
||||||
|
var menu = document.getElementById("menu");
|
||||||
|
menu.style.left = `${mouseX}px`;
|
||||||
|
menu.style.top = `${mouseY}px`;
|
||||||
|
};
|
@ -3,334 +3,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<script src="qrc:///js/vue.js"></script>
|
<script src="qrc:///js/vue.js"></script>
|
||||||
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||||
<script type="text/javascript">
|
<script src="qrc:///js/_contentManager.js"></script>
|
||||||
const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
<link rel="stylesheet" type="text/css" href="qrc:///css/_contentManager.css"/>
|
||||||
function niceBytes(x){
|
|
||||||
var unitIndex = 0;
|
|
||||||
var n = parseInt(x, 10) || 0;
|
|
||||||
while(n >= 1024 && ++unitIndex)
|
|
||||||
n = n/1024;
|
|
||||||
return(n.toFixed(n >= 10 || unitIndex < 1 ? 0 : 2) + ' ' + units[unitIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDict(keys, values) {
|
|
||||||
var d = {}
|
|
||||||
for(var i=0; i<keys.length; i++) {
|
|
||||||
d[keys[i]] = values[i];
|
|
||||||
}
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
const BOOK_KEYS = ["id", "name", "path", "url", "size", "description", "title", "tags", "date", "faviconUrl", "faviconMimeType", "downloadId"];
|
|
||||||
function addBook(values) {
|
|
||||||
var b = createDict(BOOK_KEYS, values);
|
|
||||||
if (b.downloadId && !downloadUpdaters.hasOwnProperty(b.id)) {
|
|
||||||
downloadUpdaters[b.id] = setInterval(function() { getDownloadInfo(b.id); }, 1000);
|
|
||||||
}
|
|
||||||
app.books.push(b);
|
|
||||||
}
|
|
||||||
function onBooksChanged () {
|
|
||||||
app.books = [];
|
|
||||||
for(var i=0; i<contentManager.bookIds.length; i++) {
|
|
||||||
var id = contentManager.bookIds[i];
|
|
||||||
contentManager.getBookInfos(id, BOOK_KEYS, addBook);
|
|
||||||
}
|
|
||||||
app.displayedBooksNb = 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadUpdaters = {}
|
|
||||||
const DOWNLOAD_KEYS = ["id", "status", "followedBy", "path", "totalLength", "completedLength", "downloadSpeed", "verifiedLength"];
|
|
||||||
function getDownloadInfo(id) {
|
|
||||||
contentManager.updateDownloadInfos(id, DOWNLOAD_KEYS, function(values) {
|
|
||||||
if (values.length == 0) {
|
|
||||||
clearInterval(downloadUpdaters[id]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
d = createDict(DOWNLOAD_KEYS, values);
|
|
||||||
if (d.status == "completed") {
|
|
||||||
clearInterval(downloadUpdaters[id]);
|
|
||||||
Vue.delete(app.downloads, id);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Vue.set(app.downloads, id, createDict(DOWNLOAD_KEYS, values));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function displayLoadIcon(display) {
|
|
||||||
if (display) {
|
|
||||||
document.getElementById("load-icon").classList.remove("do-not-display")
|
|
||||||
document.getElementById("bookList").classList.add("do-not-display");
|
|
||||||
} else {
|
|
||||||
document.getElementById("load-icon").classList.add("do-not-display");
|
|
||||||
document.getElementById("bookList").classList.remove("do-not-display")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
new QWebChannel(qt.webChannelTransport, function(channel) {
|
|
||||||
contentManager = channel.objects.contentManager;
|
|
||||||
app = new Vue({
|
|
||||||
el: "#app",
|
|
||||||
data: {
|
|
||||||
contentManager: contentManager,
|
|
||||||
displayedBooksNb: 20,
|
|
||||||
books: [],
|
|
||||||
downloads: {}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
openBook : function(book) {
|
|
||||||
contentManager.openBook(book.id, function() {});
|
|
||||||
},
|
|
||||||
downloadBook : function(book) {
|
|
||||||
contentManager.downloadBook(book.id, function(did) {
|
|
||||||
if (did.length == 0)
|
|
||||||
return;
|
|
||||||
book.downloadId = did;
|
|
||||||
downloadUpdaters[book.id] = setInterval(function() { getDownloadInfo(book.id); }, 1000);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
eraseBook : function(book) {
|
|
||||||
contentManager.eraseBook(book.id);
|
|
||||||
},
|
|
||||||
pauseBook : function(book) {
|
|
||||||
contentManager.pauseBook(book.id);
|
|
||||||
},
|
|
||||||
resumeBook : function(book) {
|
|
||||||
contentManager.resumeBook(book.id);
|
|
||||||
},
|
|
||||||
cancelBook : function(book) {
|
|
||||||
contentManager.cancelBook(book.id);
|
|
||||||
clearInterval(downloadUpdaters[book.id]);
|
|
||||||
Vue.delete(app.downloads, book.id);
|
|
||||||
},
|
|
||||||
displayedBooks : function(books, nb) {
|
|
||||||
var a = books.slice(0, nb);
|
|
||||||
return a;
|
|
||||||
},
|
|
||||||
getBookFromMousePosition : function() {
|
|
||||||
var elements = document.elementsFromPoint(mouseX, mouseY);
|
|
||||||
var bookId = null;
|
|
||||||
for(var i = 0; i < elements.length; i++) {
|
|
||||||
if (elements[i].localName == "summary" && elements[i].classList.contains("book-summary")) {
|
|
||||||
bookId = elements[i].id;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var book = null;
|
|
||||||
for(var i = 0; i < app.books.length; i++) {
|
|
||||||
if (app.books[i]["id"] == bookId) {
|
|
||||||
book = app.books[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return book;
|
|
||||||
},
|
|
||||||
niceBytes : niceBytes
|
|
||||||
}
|
|
||||||
});
|
|
||||||
contentManager.booksChanged.connect(onBooksChanged);
|
|
||||||
contentManager.pendingRequest.connect(displayLoadIcon);
|
|
||||||
onBooksChanged();
|
|
||||||
displayLoadIcon(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
futurCall = null;
|
|
||||||
function setSearch(value) {
|
|
||||||
clearTimeout(futurCall);
|
|
||||||
futurCall = setTimeout(function(){contentManager.setSearch(value)}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
function scrolled(e) {
|
|
||||||
if (e.offsetHeight + e.scrollTop >= e.scrollHeight) {
|
|
||||||
app.displayedBooksNb = Math.min(app.displayedBooksNb+20, app.books.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener("click", e => {
|
|
||||||
if (menuVisible)
|
|
||||||
displayMenu(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
var mouseX, mouseY = 0;
|
|
||||||
window.addEventListener("contextmenu", e => {
|
|
||||||
e.preventDefault();
|
|
||||||
mouseX = e.pageX;
|
|
||||||
mouseY = e.pageY;
|
|
||||||
setContextMenuPosition();
|
|
||||||
var book = app.getBookFromMousePosition();
|
|
||||||
displayMenu(book);
|
|
||||||
});
|
|
||||||
|
|
||||||
var menuVisible = false;
|
|
||||||
function displayMenu(book) {
|
|
||||||
var menu = document.getElementById("menu");
|
|
||||||
menu.style.display = (book) ? "block" : "none";
|
|
||||||
menuVisible = (book) ? true : false;
|
|
||||||
if (!book)
|
|
||||||
return;
|
|
||||||
var localElement = document.getElementsByClassName("local-option")[0];
|
|
||||||
localElement.style.display = (book.path) ? "block" : "none";
|
|
||||||
};
|
|
||||||
|
|
||||||
function setContextMenuPosition() {
|
|
||||||
var menu = document.getElementById("menu");
|
|
||||||
menu.style.left = `${mouseX}px`;
|
|
||||||
menu.style.top = `${mouseY}px`;
|
|
||||||
};
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
html, body {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
#app {
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
*:focus {
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
#searchInput {
|
|
||||||
background-image: url('qrc:///icons/search.svg');
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: left top;
|
|
||||||
background-size: 40px 40px;
|
|
||||||
padding: 0px;
|
|
||||||
margin: 0px;
|
|
||||||
padding-left: 45px;
|
|
||||||
height: 40px;
|
|
||||||
width: 90%;
|
|
||||||
border: 1px solid #EEE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bookTable {
|
|
||||||
position: relative;
|
|
||||||
height: calc(100% - 42px); /* 42px = 40px(height of #searchInput) + 2px(border) */
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#bookList {
|
|
||||||
height: calc(100% - 19px - 20px); /*19px the header size, 20px the header margin-top */
|
|
||||||
overflow-y:scroll;
|
|
||||||
overflow-x:hidden;
|
|
||||||
position: relative;
|
|
||||||
width: 100%
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablerow,
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.header {
|
|
||||||
color: #555;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
.tablecell{
|
|
||||||
flex-basis:20%;
|
|
||||||
}
|
|
||||||
.cell0 {
|
|
||||||
flex-basis: 60px;
|
|
||||||
flex-grow: 0;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
.tablerow > .cell1 {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.cell0 > img {
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
}
|
|
||||||
.cell1,
|
|
||||||
.cell2,
|
|
||||||
.cell3,
|
|
||||||
.cell4,
|
|
||||||
.cell5 {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
summary::-webkit-details-marker {
|
|
||||||
display: none
|
|
||||||
}
|
|
||||||
summary {
|
|
||||||
height: 64px;
|
|
||||||
}
|
|
||||||
.book {
|
|
||||||
border-top: 1px solid #EEE;
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
background: transparent;
|
|
||||||
border: 0px;
|
|
||||||
}
|
|
||||||
.tablerow button {
|
|
||||||
color: blue;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 14px;
|
|
||||||
border: 0px;
|
|
||||||
background: transparent;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
.tablerow button:hover {
|
|
||||||
color: white;
|
|
||||||
background: blue;
|
|
||||||
}
|
|
||||||
details:hover {
|
|
||||||
background-color: #d9e9ff;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu {
|
|
||||||
/* width: 120px; */
|
|
||||||
box-shadow: 0 4px 5px 3px rgba(0, 0, 0, 0.2);
|
|
||||||
position: fixed;
|
|
||||||
display: none;
|
|
||||||
z-index: 99999999999999;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-options {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0 0 0 0;
|
|
||||||
margin: 2px 0px 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-option {
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 14px;
|
|
||||||
padding: 10px 40px 10px 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-option:hover {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
.loader {
|
|
||||||
margin: 0 auto;
|
|
||||||
border: 16px solid #f3f3f3; /* Light grey */
|
|
||||||
border-top: 16px solid #3498db; /* Blue */
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 120px;
|
|
||||||
height: 120px;
|
|
||||||
animation: spin 2s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.do-not-display {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
0% { transform: rotate(0deg); }
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body onload="init()">
|
<body onload="init()">
|
||||||
<div id="app">
|
<div id="app">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user