Initial commit.
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
node_modules/
|
||||
.vscode/
|
||||
*.sqllite
|
||||
testStuff/
|
||||
chache.bin
|
||||
key.cfg
|
334
index.js
Normal file
334
index.js
Normal file
@ -0,0 +1,334 @@
|
||||
const express = require("express");
|
||||
const Eta = require("eta");
|
||||
const fs = require("fs");
|
||||
const request = require("request");
|
||||
const imdb = require("imdb-api");
|
||||
const sqlite3 = require("sqlite3");
|
||||
const requestSync = require("sync-request");
|
||||
var Config = require('config-js');
|
||||
const app = express();
|
||||
const port = 4000;
|
||||
|
||||
const initalTableSQL =
|
||||
"CREATE TABLE `movieInfo` ( \
|
||||
`id` INT NOT NULL, \
|
||||
`movieID` VARCHAR(128), \
|
||||
`movieTitel` VARCHAR(255), \
|
||||
`place` INT zerofill, \
|
||||
`type` INT zerofill, \
|
||||
`posterUrl` VARCHAR(255) \
|
||||
);";
|
||||
|
||||
const initalTableSQL2 =
|
||||
"CREATE TABLE `apiChache` ( \
|
||||
`imdbID` VARCHAR(128), \
|
||||
`url` VARCHAR(255) \
|
||||
);";
|
||||
|
||||
var responseBuffer = { allBufferd: [] };
|
||||
|
||||
responseBuffer = JSON.parse(fs.readFileSync("chache.bin", "utf8"));
|
||||
|
||||
var db = new sqlite3.Database("database.sqllite");
|
||||
if (!fs.existsSync("database.sqllite")) {
|
||||
console.log("Creating table.");
|
||||
db.serialize(() => {
|
||||
db.run(initalTableSQL);
|
||||
//db.run(initalTableSQL2);
|
||||
});
|
||||
}
|
||||
db.close();
|
||||
var db = new sqlite3.Database("database.sqllite");
|
||||
|
||||
var config = new Config('key.cfg');
|
||||
|
||||
|
||||
async function doesMovieExistInDatabase(imdbID) {
|
||||
console.warn(imdbID);
|
||||
db.all(
|
||||
"SELECT * FROM movieInfo WHERE movieID='" + imdbID + "'",
|
||||
function (err, rows) {
|
||||
console.log("!!!" + rows);
|
||||
if (rows == undefined) {
|
||||
console.log(false);
|
||||
return false;
|
||||
} else {
|
||||
console.log(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getBufferdResponse(type, imdbID) {
|
||||
// Cover image
|
||||
if (type == 1) {
|
||||
db.all(
|
||||
"SELECT * FROM apiChache WHERE imdbID=" + imdbID,
|
||||
function (err, rows) {
|
||||
// Okay, there is no result, lets ask the real api
|
||||
if (rows == undefined) {
|
||||
console.log("No chache");
|
||||
var res = requestSync(
|
||||
"GET",
|
||||
"https://imdb-api.com/en/API/Posters//" + imdbID,
|
||||
{}
|
||||
);
|
||||
const jsonParsed = JSON.parse(res.body);
|
||||
// Well frick, api limit reached
|
||||
if (jsonParsed.errorMessage.includes("Maximum usage")) {
|
||||
console.warn("API limit reached!");
|
||||
|
||||
return "https://tse2.mm.bing.net/th?id=OIP.SW4X5yWbxOMofUFxMwSTbAHaJQ&pid=Api"; // Return "No cover image"
|
||||
console.log("unreachable");
|
||||
} else {
|
||||
// Cool, we got an response
|
||||
posterUrl =
|
||||
"https://tse2.mm.bing.net/th?id=OIP.SW4X5yWbxOMofUFxMwSTbAHaJQ&pid=Api"; // Just a fallback
|
||||
if (jsonParsed.posters[0] != undefined) {
|
||||
posterUrl = jsonParsed.posters[0].link;
|
||||
// Lets save the response
|
||||
db.run(
|
||||
"INSERT INTO apiChache(imdbID, url) VALUES(?, ?)",
|
||||
[imdbID, posterUrl],
|
||||
(err) => {
|
||||
if (err) {
|
||||
return console.log(err.message);
|
||||
}
|
||||
console.log("Saved url to chache");
|
||||
}
|
||||
);
|
||||
}
|
||||
// Return the url
|
||||
return posterUrl;
|
||||
}
|
||||
} else {
|
||||
// There is a result, lets return the result
|
||||
return rows[0].url;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
app.use(express.static("static"));
|
||||
|
||||
app.get("/", function (req, res) {
|
||||
// https://imdb-api.com/de/API/Posters//[ID HERE]
|
||||
var buildString = "";
|
||||
db.serialize(function () {
|
||||
db.all("SELECT * FROM movieInfo ORDER BY movieTitel ASC;", function (err, rows) {
|
||||
/* rows.forEach((row) => {
|
||||
console.log(row.id + ": " + row.movieTitel);
|
||||
//var posterLink = getBufferdResponse(1, row.movieID);
|
||||
posterLink = row.posterUrl;
|
||||
console.log(posterLink);
|
||||
|
||||
/*var res = requestSync(
|
||||
"GET",
|
||||
"https://imdb-api.com/en/API/Posters//" + row.movieID,
|
||||
{}
|
||||
);
|
||||
const jsonParsed = JSON.parse(res.body);
|
||||
console.log(jsonParsed);
|
||||
posterLink = "";
|
||||
if (jsonParsed.posters[0] == undefined) {
|
||||
posterLink =
|
||||
"https://tse2.mm.bing.net/th?id=OIP.SW4X5yWbxOMofUFxMwSTbAHaJQ&pid=Api";
|
||||
} else {
|
||||
posterLink = jsonParsed.posters[0].link;
|
||||
}*/
|
||||
/*buildString +=
|
||||
"<a href='/showDetails?id=" +
|
||||
row.id +
|
||||
"'><div style='width: 150px; float: left; padding: 5px;'><img src='" +
|
||||
posterLink +
|
||||
'\' style="width: 100%;"><br><center><b>' +
|
||||
row.movieTitel +
|
||||
"</b></center></div></a>";
|
||||
|
||||
});*/
|
||||
|
||||
console.log(rows)
|
||||
const data = fs.readFileSync("template/bookshelf.html", "utf8");
|
||||
res.send(Eta.render(data, {jsonRespo: JSON.stringify(rows)}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/add", function (req, res) {
|
||||
const data = fs.readFileSync("template/add.html", "utf8");
|
||||
res.send(Eta.render(data, { isDisplay: false }));
|
||||
});
|
||||
|
||||
app.get("/delete", function (req, res) {
|
||||
db.run(`DELETE FROM movieInfo WHERE id=?`, req.query["id"], function (err) {
|
||||
if (err) {
|
||||
return console.error(err.message);
|
||||
}
|
||||
console.log(`Row(s) deleted ${this.changes}`);
|
||||
res.send("Done.");
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/returnSaveResult", function (req, res) {
|
||||
const data = fs.readFileSync("template/addToShelf.html", "utf8");
|
||||
responseJson = responseBuffer[req.query["reponseID"]];
|
||||
console.log(responseBuffer);
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
id: responseJson.id,
|
||||
cover: responseJson.coverImage,
|
||||
titleByAPI: responseJson.titleByAPI,
|
||||
ean: responseJson.ean,
|
||||
isDisplay: true,
|
||||
responseID: req.query["reponseID"],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
app.get("/showDetails", function (req, res) {
|
||||
const data = fs.readFileSync("template/movieDetails.html", "utf8");
|
||||
console.log( req.query["id"])
|
||||
db.serialize(function () {
|
||||
db.all(
|
||||
"SELECT * FROM movieInfo WHERE movieID='" + req.query["id"] + "'",
|
||||
function (err, rows) {
|
||||
//+ req.params["id"]
|
||||
row = rows[0];
|
||||
console.log(row);
|
||||
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
internalID: row.id,
|
||||
id: row.movieID,
|
||||
cover: row.posterUrl,
|
||||
titleByAPI: row.movieTitel,
|
||||
})
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
/*responseJson = responseBuffer[req.query["reponseID"]];
|
||||
console.log(responseBuffer);
|
||||
res.send(
|
||||
Eta.render(data, {
|
||||
id: responseJson.id,
|
||||
cover: responseJson.coverImage,
|
||||
titleByAPI: responseJson.titleByAPI,
|
||||
ean: responseJson.ean,
|
||||
isDisplay: true,
|
||||
responseID: req.query["reponseID"]
|
||||
})
|
||||
);*/
|
||||
});
|
||||
|
||||
app.get("/apiCallBack", function (req, res) {
|
||||
//console.log(req.query);
|
||||
if (!responseBuffer.allBufferd.includes(req.query["ean"])) {
|
||||
request(
|
||||
"http://localhost:9999/?ean=" + req.query["ean"],
|
||||
function (error, response, body) {
|
||||
if (response.statusCode != 200) {
|
||||
console.log("OH NO");
|
||||
res.send({ state: "ERR_EAN_CONV_NO_200" });
|
||||
} else {
|
||||
var reqString =
|
||||
"https://imdb-api.com/en/API/SearchTitle/" + config.get('keys.imdb') + "/" +
|
||||
response.body;
|
||||
request(reqString, function (error, response2, body) {
|
||||
jsonBody = JSON.parse(response2.body);
|
||||
console.log(response.body);
|
||||
if (jsonBody.errorMessage.includes("Maximum usage")) {
|
||||
res.send({ state: "ERR_IMDB_LIMIT_REACHED" });
|
||||
} else {
|
||||
jsonBody = jsonBody.results[0];
|
||||
//const data = fs.readFileSync("template/addToShelf.html.html", "utf8");
|
||||
timest = new Date().valueOf();
|
||||
responseJson = {
|
||||
state: "OK",
|
||||
id: jsonBody.id,
|
||||
coverImage: jsonBody.image,
|
||||
titleByAPI: response.body,
|
||||
ean: req.query["ean"],
|
||||
reponseID: req.query["ean"],
|
||||
};
|
||||
responseBuffer[req.query["ean"]] = responseJson;
|
||||
responseBuffer.allBufferd.push(req.query["ean"]);
|
||||
|
||||
// ToDo: Rewrite chache (and all pages!!!) to use ean instead of timeid
|
||||
|
||||
|
||||
try {
|
||||
fs.writeFileSync("chache.bin", JSON.stringify(responseBuffer));
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
res.send(responseJson);
|
||||
/* res.send(
|
||||
Eta.render(data, {
|
||||
id: jsonBody.id,
|
||||
cover: jsonBody.image,
|
||||
titleByAPI: response.body,
|
||||
ean: req.query["ean"],
|
||||
isDisplay: true,
|
||||
})
|
||||
);*/
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
console.log("Using chache");
|
||||
responseJson = responseBuffer[req.query["ean"]];
|
||||
res.send(responseJson);
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/save", function (req, res) {
|
||||
responseJson = responseBuffer[req.query["reponseID"]];
|
||||
|
||||
db.all(
|
||||
"SELECT * FROM movieInfo WHERE movieID='" + responseJson.id + "'",
|
||||
function (err, rows) {
|
||||
console.log(rows);
|
||||
if (rows == undefined || rows.length == 0) {
|
||||
db.run(
|
||||
"INSERT INTO movieInfo(id, movieID, movieTitel, place, type, posterUrl) VALUES(?, ?, ?, ?, ?, ?)",
|
||||
[
|
||||
new Date().valueOf(),
|
||||
responseJson.id,
|
||||
responseJson.titleByAPI,
|
||||
0,
|
||||
0,
|
||||
responseJson.coverImage,
|
||||
],
|
||||
(err) => {
|
||||
if (err) {
|
||||
return console.log(err.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
res.send({ status: "OK" });
|
||||
} else {
|
||||
res.send({ status: "ERR_ALREADY_EXIST" });
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
//var res = request('POST', 'https://ssl.ofdb.de/view.php?page=suchergebnis', {
|
||||
// json: {'SText': '4030521376748', 'Kat':'EAN'},
|
||||
//});
|
||||
|
||||
//var temp2 = String(res.getBody('utf8'))
|
||||
//temp = //temp.replace("<script>", "").replace("<html>", "").replace("\n", "").replace("\r", "").replace("\t", "")
|
||||
//htmlBlock = htmlParser.parse(temp)
|
||||
//temp2 = temp2.split(/\r?\n/)
|
||||
//temp = temp.split('img src="https://ssl.ofdb.de/images/shim.gif" width="1" height="10" border="0" alt=""></td>')[0]
|
||||
//console.log(temp2.find(checkForString))
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Movie DB app listening at http://localhost:${port}`);
|
||||
});
|
1795
package-lock.json
generated
Normal file
1795
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
package.json
Normal file
32
package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "openmoviedb",
|
||||
"version": "1.0.0",
|
||||
"description": "An openmoviedb where you can save which movies you own.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "openmoviedb"
|
||||
},
|
||||
"keywords": [
|
||||
"movie",
|
||||
"imdb"
|
||||
],
|
||||
"author": "TheGreydiamond",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"config-js": "^1.1.14",
|
||||
"eta": "^1.12.1",
|
||||
"express": "^4.17.1",
|
||||
"form-data": "^4.0.0",
|
||||
"imdb-api": "^4.4.1",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-html-parser": "^3.1.2",
|
||||
"quagga": "^0.12.1",
|
||||
"request": "^2.88.2",
|
||||
"sqlite3": "^5.0.2",
|
||||
"sync-request": "^6.1.0"
|
||||
}
|
||||
}
|
56
python/eanConverter.py
Normal file
56
python/eanConverter.py
Normal file
@ -0,0 +1,56 @@
|
||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||
import time
|
||||
import requests
|
||||
|
||||
hostName = "localhost"
|
||||
serverPort = 9999
|
||||
|
||||
class MyServer(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
|
||||
print(self.path)
|
||||
if(self.path.startswith("/?ean=")):
|
||||
print("EAN request")
|
||||
|
||||
eanCode = self.path.split("=")[1]
|
||||
print(eanCode)
|
||||
url = 'https://ssl.ofdb.de/view.php?page=suchergebnis'
|
||||
myobj = {'SText': eanCode, 'Kat':'EAN'} #'4030521376748'
|
||||
|
||||
x = requests.post(url, data = myobj)
|
||||
tme = x.text
|
||||
try:
|
||||
tme = tme.split('<div data-nx-container="inread"><!-- INREAD --></div>')[1]
|
||||
tme = tme.split('img src="https://ssl.ofdb.de/images/shim.gif" width="1" height="10" border="0" alt=""></td>')[0]
|
||||
tme = tme.split(',SHADOW,true)"><b>')[1]
|
||||
tme = tme.split('</b></a><br>')[0]
|
||||
tme = tme[:len(tme)-7]
|
||||
except IndexError:
|
||||
self.send_response(500)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes("Invalid EAN", "utf-8"))
|
||||
else:
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
self.wfile.write(bytes(tme, "utf-8"))
|
||||
else:
|
||||
self.send_response(404)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
webServer = HTTPServer((hostName, serverPort), MyServer)
|
||||
print("Server started http://%s:%s" % (hostName, serverPort))
|
||||
|
||||
try:
|
||||
webServer.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
webServer.server_close()
|
||||
print("Server stopped.")
|
427
static/css/normalize.css
vendored
Normal file
427
static/css/normalize.css
vendored
Normal file
@ -0,0 +1,427 @@
|
||||
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||
* and Firefox.
|
||||
* Correct `block` display not defined for `main` in IE 11.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9/10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow not hidden in IE 9/10/11.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contain overflow in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address odd `em`-unit font size rendering in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||
* styling of `select`, unless a `border` property is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct color not being inherited.
|
||||
* Known issue: affects color of disabled elements.
|
||||
* 2. Correct font properties not being inherited.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||
* Correct `select` style inheritance in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's recommended that you don't attempt to style these elements.
|
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||
*
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||
* `font-size` values of the `input`, it causes the cursor style of the
|
||||
* decrement button to change from `default` to `text`.
|
||||
*/
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
|
||||
* (include `-moz` to future-proof).
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||
* padding (and `textfield` appearance).
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't inherit the `font-weight` (applied by a rule above).
|
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
487
static/css/skeleton.css
vendored
Normal file
487
static/css/skeleton.css
vendored
Normal file
@ -0,0 +1,487 @@
|
||||
/*
|
||||
* Skeleton V2.0.4
|
||||
* Copyright 2014, Dave Gamache
|
||||
* www.getskeleton.com
|
||||
* Free to use under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* 12/29/2014
|
||||
*/
|
||||
|
||||
|
||||
/* Table of contents
|
||||
––––––––––––––––––––––––––––––––––––––––––––––––––
|
||||
- Grid
|
||||
- Base Styles
|
||||
- Typography
|
||||
- Links
|
||||
- Buttons
|
||||
- Forms
|
||||
- Lists
|
||||
- Code
|
||||
- Tables
|
||||
- Spacing
|
||||
- Utilities
|
||||
- Clearing
|
||||
- Media Queries
|
||||
*/
|
||||
|
||||
|
||||
/* Grid
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
.container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
box-sizing: border-box; }
|
||||
.column,
|
||||
.columns {
|
||||
width: 100%;
|
||||
float: left;
|
||||
box-sizing: border-box; }
|
||||
|
||||
/* For devices larger than 400px */
|
||||
@media (min-width: 400px) {
|
||||
.container {
|
||||
width: 85%;
|
||||
padding: 0; }
|
||||
}
|
||||
|
||||
/* For devices larger than 550px */
|
||||
@media (min-width: 550px) {
|
||||
.container {
|
||||
width: 80%; }
|
||||
.column,
|
||||
.columns {
|
||||
margin-left: 4%; }
|
||||
.column:first-child,
|
||||
.columns:first-child {
|
||||
margin-left: 0; }
|
||||
|
||||
.one.column,
|
||||
.one.columns { width: 4.66666666667%; }
|
||||
.two.columns { width: 13.3333333333%; }
|
||||
.three.columns { width: 22%; }
|
||||
.four.columns { width: 30.6666666667%; }
|
||||
.five.columns { width: 39.3333333333%; }
|
||||
.six.columns { width: 48%; }
|
||||
.seven.columns { width: 56.6666666667%; }
|
||||
.eight.columns { width: 65.3333333333%; }
|
||||
.nine.columns { width: 74.0%; }
|
||||
.ten.columns { width: 82.6666666667%; }
|
||||
.eleven.columns { width: 91.3333333333%; }
|
||||
.twelve.columns { width: 100%; margin-left: 0; }
|
||||
|
||||
.one-third.column { width: 30.6666666667%; }
|
||||
.two-thirds.column { width: 65.3333333333%; }
|
||||
|
||||
.one-half.column { width: 48%; }
|
||||
|
||||
/* Offsets */
|
||||
.offset-by-one.column,
|
||||
.offset-by-one.columns { margin-left: 8.66666666667%; }
|
||||
.offset-by-two.column,
|
||||
.offset-by-two.columns { margin-left: 17.3333333333%; }
|
||||
.offset-by-three.column,
|
||||
.offset-by-three.columns { margin-left: 26%; }
|
||||
.offset-by-four.column,
|
||||
.offset-by-four.columns { margin-left: 34.6666666667%; }
|
||||
.offset-by-five.column,
|
||||
.offset-by-five.columns { margin-left: 43.3333333333%; }
|
||||
.offset-by-six.column,
|
||||
.offset-by-six.columns { margin-left: 52%; }
|
||||
.offset-by-seven.column,
|
||||
.offset-by-seven.columns { margin-left: 60.6666666667%; }
|
||||
.offset-by-eight.column,
|
||||
.offset-by-eight.columns { margin-left: 69.3333333333%; }
|
||||
.offset-by-nine.column,
|
||||
.offset-by-nine.columns { margin-left: 78.0%; }
|
||||
.offset-by-ten.column,
|
||||
.offset-by-ten.columns { margin-left: 86.6666666667%; }
|
||||
.offset-by-eleven.column,
|
||||
.offset-by-eleven.columns { margin-left: 95.3333333333%; }
|
||||
|
||||
.offset-by-one-third.column,
|
||||
.offset-by-one-third.columns { margin-left: 34.6666666667%; }
|
||||
.offset-by-two-thirds.column,
|
||||
.offset-by-two-thirds.columns { margin-left: 69.3333333333%; }
|
||||
|
||||
.offset-by-one-half.column,
|
||||
.offset-by-one-half.columns { margin-left: 52%; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Base Styles
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
/* NOTE
|
||||
html is set to 62.5% so that all the REM measurements throughout Skeleton
|
||||
are based on 10px sizing. So basically 1.5rem = 15px :) */
|
||||
html {
|
||||
font-size: 62.5%; }
|
||||
body {
|
||||
font-size: 1.5em; /* currently ems cause chrome bug misinterpreting rems on body element */
|
||||
line-height: 1.6;
|
||||
font-weight: 400;
|
||||
font-family: "Raleway", "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
color: #222; }
|
||||
|
||||
|
||||
/* Typography
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 2rem;
|
||||
font-weight: 300; }
|
||||
h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
|
||||
h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
|
||||
h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
|
||||
h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
|
||||
h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
|
||||
h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
|
||||
|
||||
/* Larger than phablet */
|
||||
@media (min-width: 550px) {
|
||||
h1 { font-size: 5.0rem; }
|
||||
h2 { font-size: 4.2rem; }
|
||||
h3 { font-size: 3.6rem; }
|
||||
h4 { font-size: 3.0rem; }
|
||||
h5 { font-size: 2.4rem; }
|
||||
h6 { font-size: 1.5rem; }
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0; }
|
||||
|
||||
|
||||
/* Links
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
a {
|
||||
color: #1EAEDB; }
|
||||
a:hover {
|
||||
color: #0FA0CE; }
|
||||
|
||||
|
||||
/* Buttons
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"] {
|
||||
display: inline-block;
|
||||
height: 38px;
|
||||
padding: 0 30px;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 38px;
|
||||
letter-spacing: .1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #bbb;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box; }
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover,
|
||||
.button:focus,
|
||||
button:focus,
|
||||
input[type="submit"]:focus,
|
||||
input[type="reset"]:focus,
|
||||
input[type="button"]:focus {
|
||||
color: #333;
|
||||
border-color: #888;
|
||||
outline: 0; }
|
||||
.button.button-primary,
|
||||
button.button-primary,
|
||||
input[type="submit"].button-primary,
|
||||
input[type="reset"].button-primary,
|
||||
input[type="button"].button-primary {
|
||||
color: #FFF;
|
||||
background-color: #33C3F0;
|
||||
border-color: #33C3F0; }
|
||||
.button.button-primary:hover,
|
||||
button.button-primary:hover,
|
||||
input[type="submit"].button-primary:hover,
|
||||
input[type="reset"].button-primary:hover,
|
||||
input[type="button"].button-primary:hover,
|
||||
.button.button-primary:focus,
|
||||
button.button-primary:focus,
|
||||
input[type="submit"].button-primary:focus,
|
||||
input[type="reset"].button-primary:focus,
|
||||
input[type="button"].button-primary:focus {
|
||||
color: #FFF;
|
||||
background-color: #1EAEDB;
|
||||
border-color: #1EAEDB; }
|
||||
|
||||
|
||||
/* Forms
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="text"],
|
||||
input[type="tel"],
|
||||
input[type="url"],
|
||||
input[type="password"],
|
||||
textarea,
|
||||
select {
|
||||
height: 38px;
|
||||
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
|
||||
background-color: #fff;
|
||||
border: 1px solid #D1D1D1;
|
||||
border-radius: 4px;
|
||||
box-shadow: none;
|
||||
box-sizing: border-box; }
|
||||
/* Removes awkward default styles on some inputs for iOS */
|
||||
input[type="email"],
|
||||
input[type="number"],
|
||||
input[type="search"],
|
||||
input[type="text"],
|
||||
input[type="tel"],
|
||||
input[type="url"],
|
||||
input[type="password"],
|
||||
textarea {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none; }
|
||||
textarea {
|
||||
min-height: 65px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px; }
|
||||
input[type="email"]:focus,
|
||||
input[type="number"]:focus,
|
||||
input[type="search"]:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="tel"]:focus,
|
||||
input[type="url"]:focus,
|
||||
input[type="password"]:focus,
|
||||
textarea:focus,
|
||||
select:focus {
|
||||
border: 1px solid #33C3F0;
|
||||
outline: 0; }
|
||||
label,
|
||||
legend {
|
||||
display: block;
|
||||
margin-bottom: .5rem;
|
||||
font-weight: 600; }
|
||||
fieldset {
|
||||
padding: 0;
|
||||
border-width: 0; }
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
display: inline; }
|
||||
label > .label-body {
|
||||
display: inline-block;
|
||||
margin-left: .5rem;
|
||||
font-weight: normal; }
|
||||
|
||||
|
||||
/* Lists
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
ul {
|
||||
list-style: circle inside; }
|
||||
ol {
|
||||
list-style: decimal inside; }
|
||||
ol, ul {
|
||||
padding-left: 0;
|
||||
margin-top: 0; }
|
||||
ul ul,
|
||||
ul ol,
|
||||
ol ol,
|
||||
ol ul {
|
||||
margin: 1.5rem 0 1.5rem 3rem;
|
||||
font-size: 90%; }
|
||||
li {
|
||||
margin-bottom: 1rem; }
|
||||
|
||||
|
||||
/* Code
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
code {
|
||||
padding: .2rem .5rem;
|
||||
margin: 0 .2rem;
|
||||
font-size: 90%;
|
||||
white-space: nowrap;
|
||||
background: #F1F1F1;
|
||||
border: 1px solid #E1E1E1;
|
||||
border-radius: 4px; }
|
||||
pre > code {
|
||||
display: block;
|
||||
padding: 1rem 1.5rem;
|
||||
white-space: pre; }
|
||||
|
||||
|
||||
/* Tables
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
th,
|
||||
td {
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #E1E1E1; }
|
||||
th:first-child,
|
||||
td:first-child {
|
||||
padding-left: 0; }
|
||||
th:last-child,
|
||||
td:last-child {
|
||||
padding-right: 0; }
|
||||
|
||||
|
||||
/* Spacing
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
button,
|
||||
.button {
|
||||
margin-bottom: 1rem; }
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
fieldset {
|
||||
margin-bottom: 1.5rem; }
|
||||
pre,
|
||||
blockquote,
|
||||
dl,
|
||||
figure,
|
||||
table,
|
||||
p,
|
||||
ul,
|
||||
ol,
|
||||
form {
|
||||
margin-bottom: 2.5rem; }
|
||||
|
||||
|
||||
/* Utilities
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
.u-full-width {
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.u-max-full-width {
|
||||
max-width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.u-pull-right {
|
||||
float: right; }
|
||||
.u-pull-left {
|
||||
float: left; }
|
||||
|
||||
|
||||
/* Misc
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
hr {
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 3.5rem;
|
||||
border-width: 0;
|
||||
border-top: 1px solid #E1E1E1; }
|
||||
|
||||
|
||||
/* Clearing
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
|
||||
/* Self Clearing Goodness */
|
||||
.container:after,
|
||||
.row:after,
|
||||
.u-cf {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both; }
|
||||
|
||||
|
||||
/* Media Queries
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– */
|
||||
/*
|
||||
Note: The best way to structure the use of media queries is to create the queries
|
||||
near the relevant code. For example, if you wanted to change the styles for buttons
|
||||
on small devices, paste the mobile query code up in the buttons section and style it
|
||||
there.
|
||||
*/
|
||||
|
||||
|
||||
/* Larger than mobile */
|
||||
@media (min-width: 400px) {}
|
||||
|
||||
/* Larger than phablet (also point when grid becomes active) */
|
||||
@media (min-width: 550px) {}
|
||||
|
||||
/* Larger than tablet */
|
||||
@media (min-width: 750px) {}
|
||||
|
||||
/* Larger than desktop */
|
||||
@media (min-width: 1000px) {}
|
||||
|
||||
/* Larger than Desktop HD */
|
||||
@media (min-width: 1200px) {}
|
||||
|
||||
|
||||
.lds-grid {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
.lds-grid div {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: #dfc;
|
||||
animation: lds-grid 1.2s linear infinite;
|
||||
}
|
||||
.lds-grid div:nth-child(1) {
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
.lds-grid div:nth-child(2) {
|
||||
top: 8px;
|
||||
left: 32px;
|
||||
animation-delay: -0.4s;
|
||||
}
|
||||
.lds-grid div:nth-child(3) {
|
||||
top: 8px;
|
||||
left: 56px;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
.lds-grid div:nth-child(4) {
|
||||
top: 32px;
|
||||
left: 8px;
|
||||
animation-delay: -0.4s;
|
||||
}
|
||||
.lds-grid div:nth-child(5) {
|
||||
top: 32px;
|
||||
left: 32px;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
.lds-grid div:nth-child(6) {
|
||||
top: 32px;
|
||||
left: 56px;
|
||||
animation-delay: -1.2s;
|
||||
}
|
||||
.lds-grid div:nth-child(7) {
|
||||
top: 56px;
|
||||
left: 8px;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
.lds-grid div:nth-child(8) {
|
||||
top: 56px;
|
||||
left: 32px;
|
||||
animation-delay: -1.2s;
|
||||
}
|
||||
.lds-grid div:nth-child(9) {
|
||||
top: 56px;
|
||||
left: 56px;
|
||||
animation-delay: -1.6s;
|
||||
}
|
||||
@keyframes lds-grid {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
BIN
static/images/favicon.png
Normal file
BIN
static/images/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
5
static/jquery-1.11.3.min.js
vendored
Normal file
5
static/jquery-1.11.3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
static/test.html
Normal file
18
static/test.html
Normal file
@ -0,0 +1,18 @@
|
||||
<h1>Testpage</h1>
|
||||
<div style="width: 150px; float: left; padding: 5px;">
|
||||
<img src="https://imdb-api.com/images/original/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_Ratio0.6800_AL_.jpg" style="width: 100%;">
|
||||
<br>
|
||||
<center><b>Txt</b></center>
|
||||
</div>
|
||||
|
||||
<div style="width: 150px; float: left; padding: 5px;">
|
||||
<img src="https://imdb-api.com/images/original/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_Ratio0.6800_AL_.jpg" style="width: 100%;">
|
||||
<br>
|
||||
<center><b>Txt 2</b></center>
|
||||
</div>
|
||||
|
||||
<div style="width: 150px; float: left; padding: 5px;">
|
||||
<img src="https://imdb-api.com/images/original/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_Ratio0.6800_AL_.jpg" style="width: 100%;">
|
||||
<br>
|
||||
<center><b>Txt 3</b></center>
|
||||
</div>
|
206
static/video.js
Normal file
206
static/video.js
Normal file
@ -0,0 +1,206 @@
|
||||
var videoElement = document.querySelector('video');
|
||||
var canvas = document.getElementById('pcCanvas');
|
||||
var mobileCanvas = document.getElementById('mobileCanvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
var mobileCtx = mobileCanvas.getContext('2d');
|
||||
var videoSelect = document.querySelector('select#videoSource');
|
||||
var videoOption = document.getElementById('videoOption');
|
||||
var buttonGo = document.getElementById('go');
|
||||
var barcode_result = document.getElementById('dbr');
|
||||
|
||||
var isPaused = false;
|
||||
var videoWidth = 640,
|
||||
videoHeight = 480;
|
||||
var mobileVideoWidth = 240,
|
||||
mobileVideoHeight = 320;
|
||||
var isPC = true;
|
||||
|
||||
var ZXing = null;
|
||||
var decodePtr = null;
|
||||
|
||||
var tick = function () {
|
||||
if (window.ZXing) {
|
||||
ZXing = ZXing();
|
||||
decodePtr = ZXing.Runtime.addFunction(decodeCallback);
|
||||
} else {
|
||||
setTimeout(tick, 10);
|
||||
}
|
||||
};
|
||||
tick();
|
||||
|
||||
var decodeCallback = function (ptr, len, resultIndex, resultCount) {
|
||||
var result = new Uint8Array(ZXing.HEAPU8.buffer, ptr, len);
|
||||
console.log(String.fromCharCode.apply(null, result));
|
||||
barcode_result.textContent = String.fromCharCode.apply(null, result);
|
||||
buttonGo.disabled = false;
|
||||
if (isPC) {
|
||||
canvas.style.display = 'block';
|
||||
} else {
|
||||
mobileCanvas.style.display = 'block';
|
||||
}
|
||||
};
|
||||
|
||||
// check devices
|
||||
function browserRedirect() {
|
||||
var deviceType;
|
||||
var sUserAgent = navigator.userAgent.toLowerCase();
|
||||
var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
|
||||
var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
|
||||
var bIsMidp = sUserAgent.match(/midp/i) == "midp";
|
||||
var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
|
||||
var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
|
||||
var bIsAndroid = sUserAgent.match(/android/i) == "android";
|
||||
var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
|
||||
var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
|
||||
if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
|
||||
deviceType = 'phone';
|
||||
} else {
|
||||
deviceType = 'pc';
|
||||
}
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
if (browserRedirect() == 'pc') {
|
||||
isPC = true;
|
||||
} else {
|
||||
isPC = false;
|
||||
}
|
||||
|
||||
// stackoverflow: http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata/5100158
|
||||
function dataURItoBlob(dataURI) {
|
||||
// convert base64/URLEncoded data component to raw binary data held in a string
|
||||
var byteString;
|
||||
if (dataURI.split(',')[0].indexOf('base64') >= 0)
|
||||
byteString = atob(dataURI.split(',')[1]);
|
||||
else
|
||||
byteString = unescape(dataURI.split(',')[1]);
|
||||
|
||||
// separate out the mime component
|
||||
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
|
||||
|
||||
// write the bytes of the string to a typed array
|
||||
var ia = new Uint8Array(byteString.length);
|
||||
for (var i = 0; i < byteString.length; i++) {
|
||||
ia[i] = byteString.charCodeAt(i);
|
||||
}
|
||||
|
||||
return new Blob([ia], {
|
||||
type: mimeString
|
||||
});
|
||||
}
|
||||
|
||||
// add button event
|
||||
buttonGo.onclick = function () {
|
||||
if (isPC) {
|
||||
canvas.style.display = 'none';
|
||||
} else {
|
||||
mobileCanvas.style.display = 'none';
|
||||
}
|
||||
|
||||
isPaused = false;
|
||||
scanBarcode();
|
||||
buttonGo.disabled = true;
|
||||
};
|
||||
|
||||
// scan barcode
|
||||
function scanBarcode() {
|
||||
barcode_result.textContent = "";
|
||||
|
||||
if (ZXing == null) {
|
||||
buttonGo.disabled = false;
|
||||
alert("Barcode Reader is not ready!");
|
||||
return;
|
||||
}
|
||||
|
||||
var data = null,
|
||||
context = null,
|
||||
width = 0,
|
||||
height = 0,
|
||||
dbrCanvas = null;
|
||||
|
||||
if (isPC) {
|
||||
context = ctx;
|
||||
width = videoWidth;
|
||||
height = videoHeight;
|
||||
dbrCanvas = canvas;
|
||||
} else {
|
||||
context = mobileCtx;
|
||||
width = mobileVideoWidth;
|
||||
height = mobileVideoHeight;
|
||||
dbrCanvas = mobileCanvas;
|
||||
}
|
||||
|
||||
context.drawImage(videoElement, 0, 0, width, height);
|
||||
|
||||
var vid = document.getElementById("video");
|
||||
console.log("video width: " + vid.videoWidth + ", height: " + vid.videoHeight);
|
||||
var barcodeCanvas = document.createElement("canvas");
|
||||
barcodeCanvas.width = vid.videoWidth;
|
||||
barcodeCanvas.height = vid.videoHeight;
|
||||
var barcodeContext = barcodeCanvas.getContext('2d');
|
||||
var imageWidth = vid.videoWidth, imageHeight = vid.videoHeight;
|
||||
barcodeContext.drawImage(videoElement, 0, 0, imageWidth, imageHeight);
|
||||
// read barcode
|
||||
var imageData = barcodeContext.getImageData(0, 0, imageWidth, imageHeight);
|
||||
var idd = imageData.data;
|
||||
var image = ZXing._resize(imageWidth, imageHeight);
|
||||
console.time("decode barcode");
|
||||
for (var i = 0, j = 0; i < idd.length; i += 4, j++) {
|
||||
ZXing.HEAPU8[image + j] = idd[i];
|
||||
}
|
||||
var err = ZXing._decode_any(decodePtr);
|
||||
console.timeEnd('decode barcode');
|
||||
console.log("error code", err);
|
||||
if (err == -2) {
|
||||
setTimeout(scanBarcode, 30);
|
||||
}
|
||||
}
|
||||
// https://github.com/samdutton/simpl/tree/gh-pages/getusermedia/sources
|
||||
var videoSelect = document.querySelector('select#videoSource');
|
||||
|
||||
navigator.mediaDevices.enumerateDevices()
|
||||
.then(gotDevices).then(getStream).catch(handleError);
|
||||
|
||||
videoSelect.onchange = getStream;
|
||||
|
||||
function gotDevices(deviceInfos) {
|
||||
for (var i = deviceInfos.length - 1; i >= 0; --i) {
|
||||
var deviceInfo = deviceInfos[i];
|
||||
var option = document.createElement('option');
|
||||
option.value = deviceInfo.deviceId;
|
||||
if (deviceInfo.kind === 'videoinput') {
|
||||
option.text = deviceInfo.label || 'camera ' +
|
||||
(videoSelect.length + 1);
|
||||
videoSelect.appendChild(option);
|
||||
} else {455
|
||||
console.log('Found one other kind of source/device: ', deviceInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getStream() {
|
||||
buttonGo.disabled = false;
|
||||
if (window.stream) {
|
||||
window.stream.getTracks().forEach(function(track) {
|
||||
track.stop();
|
||||
});
|
||||
}
|
||||
|
||||
var constraints = {
|
||||
video: {
|
||||
deviceId: {exact: videoSelect.value}
|
||||
}
|
||||
};
|
||||
|
||||
navigator.mediaDevices.getUserMedia(constraints).
|
||||
then(gotStream).catch(handleError);
|
||||
}
|
||||
|
||||
function gotStream(stream) {
|
||||
window.stream = stream; // make stream available to console
|
||||
videoElement.srcObject = stream;
|
||||
}
|
||||
|
||||
function handleError(error) {
|
||||
console.log('Error: ', error);
|
||||
}
|
36
static/zxing.js
Normal file
36
static/zxing.js
Normal file
File diff suppressed because one or more lines are too long
211
template/add.html
Normal file
211
template/add.html
Normal file
@ -0,0 +1,211 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Basic Page Needs
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta charset="utf-8" />
|
||||
<title>OpenMovieDB - Bookshelf</title>
|
||||
<meta name="description" content="OpenMovieDB - Bookshelf" />
|
||||
<meta name="author" content="TheGreydiamond" />
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- FONT
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link
|
||||
href="//fonts.googleapis.com/css?family=Raleway:400,300,600"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
<!-- CSS
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="stylesheet" href="css/normalize.css" />
|
||||
<link rel="stylesheet" href="css/skeleton.css" />
|
||||
<style>
|
||||
|
||||
/* In order to place the tracking correctly */
|
||||
canvas.drawing, canvas.drawingBuffer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<!-- Favicon
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="icon" type="image/png" href="images/favicon.png" />
|
||||
<script src="https://kit.fontawesome.com/d7b80a780b.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.rawgit.com/serratus/quaggaJS/0420d5e0/dist/quagga.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="one-half column" style="margin-top: 15%" id="mainCont">
|
||||
<h4>OpenMovieDB - Add a new movie</h4>
|
||||
<!-- Div to show the scanner -->
|
||||
<% if(it.isDisplay == true) { %>
|
||||
<%= it.titleByAPI %><br>
|
||||
<%= it.id %><br>
|
||||
<img src="<%= it.cover %>" alt="Cover image" style="height: 200px;"></img><br>
|
||||
<button onclick="saveToLibary()"> Add to libary</button>
|
||||
<% } else{ %>
|
||||
<div id="scanner-container"></div>
|
||||
<input type="button" id="btn" value="Start/Stop the scanner" />
|
||||
<div id="currentEAN">EAN: Waiting for valid EAN...</div>
|
||||
<button onclick="sendEanConvRequest()" disabled id="searchBtn"> <i class="fas fa-search"></i>Search</button>
|
||||
<button onclick="window.location.href = '/'"><i class="fas fa-home"></i> Back to home</button>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Include the image-diff library -->
|
||||
|
||||
<script>
|
||||
setTimeout(function(){
|
||||
document.getElementById("btn").style.backgroundColor = "rgba(255, 0, 0, 0.5)";
|
||||
document.getElementById("searchBtn").style.backgroundColor = "rgba(10, 10, 10, 0.5);"
|
||||
}, 20)
|
||||
|
||||
var _scannerIsRunning = false;
|
||||
|
||||
function startScanner() {
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
name: "Live",
|
||||
type: "LiveStream",
|
||||
target: document.querySelector('#scanner-container'),
|
||||
constraints: {
|
||||
width: 480,
|
||||
height: 320,
|
||||
facingMode: "environment"
|
||||
},
|
||||
},
|
||||
decoder: {
|
||||
readers: [
|
||||
"code_128_reader",
|
||||
"ean_reader",
|
||||
"ean_8_reader",
|
||||
"code_39_reader",
|
||||
"code_39_vin_reader",
|
||||
"codabar_reader",
|
||||
"upc_reader",
|
||||
"upc_e_reader",
|
||||
"i2of5_reader"
|
||||
],
|
||||
debug: {
|
||||
showCanvas: false,
|
||||
showPatches: false,
|
||||
showFoundPatches: false,
|
||||
showSkeleton: false,
|
||||
showLabels: false,
|
||||
showPatchLabels: false,
|
||||
showRemainingPatchLabels: false,
|
||||
boxFromPatches: {
|
||||
showTransformed: false,
|
||||
showTransformedBox: false,
|
||||
showBB: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return
|
||||
}
|
||||
|
||||
console.log("Initialization finished. Ready to start");
|
||||
Quagga.start();
|
||||
|
||||
// Set flag to is running
|
||||
_scannerIsRunning = true;
|
||||
});
|
||||
|
||||
/*Quagga.onProcessed(function (result) {
|
||||
//var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||
//drawingCanvas = Quagga.canvas.dom.overlay;
|
||||
|
||||
/*if (result) {
|
||||
if (result.boxes) {
|
||||
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||
result.boxes.filter(function (box) {
|
||||
return box !== result.box;
|
||||
}).forEach(function (box) {
|
||||
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
|
||||
});
|
||||
}
|
||||
|
||||
if (result.box) {
|
||||
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
|
||||
}
|
||||
|
||||
if (result.codeResult && result.codeResult.code) {
|
||||
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
|
||||
}
|
||||
}
|
||||
});*/
|
||||
|
||||
|
||||
Quagga.onDetected(function (result) {
|
||||
console.log("Barcode detected and processed : [" + result.codeResult.code + "]", result);
|
||||
if(String(result.codeResult.code).length == 13){
|
||||
document.getElementById("currentEAN").innerHTML = "EAN: " + result.codeResult.code
|
||||
console.log(result.codeResult.code)
|
||||
document.getElementById("searchBtn").style.backgroundColor = "color: #555;"
|
||||
document.getElementById("searchBtn").disabled = false;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Start/stop scanner
|
||||
document.getElementById("btn").addEventListener("click", function () {
|
||||
if (_scannerIsRunning) {
|
||||
document.getElementById("btn").style.backgroundColor = "rgba(255, 0, 0, 0.5)";
|
||||
Quagga.stop();
|
||||
} else {
|
||||
document.getElementById("btn").style.backgroundColor = "rgba(0, 255, 0, 0.5)";
|
||||
startScanner();
|
||||
}
|
||||
}, false);
|
||||
|
||||
function sendEanConvRequest(){
|
||||
curEan = document.getElementById("currentEAN").innerHTML
|
||||
curEan = curEan.replace("EAN: ", "")
|
||||
document.getElementById("mainCont").innerHTML = "<h4>OpenMovieDB - Add a new movie</h4><center><div class=\"lds-grid\"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div><br><i>Searching database...</i></center>";
|
||||
if(curEan[0] == "0"){
|
||||
curEan = curEan.substring(1);
|
||||
}
|
||||
url = "/apiCallBack?ean=" + curEan;
|
||||
//window.open(url)
|
||||
$.get(url,function(data,status) {
|
||||
var respon = JSON.parse(data)
|
||||
if(respon.state == "OK"){
|
||||
url = "/returnSaveResult?reponseID=" + respon.reponseID;
|
||||
window.location.href = url
|
||||
}else{
|
||||
// alert("An error with the api occured.")
|
||||
document.getElementById("mainCont").innerHTML = "<h4>OpenMovieDB - Add a new movie</h4><center><i style='color: #cc0000; font-size: 100px;' class=\"fas fa-exclamation-circle\"></i><br>Ohno, the API returned an error. Errorcode: <br> <code>" + respon.state + "</code><br><br><button onclick=\"window.location.href = '/'\"><i class=\"fas fa-home\"></i> Back to home</button></center>"
|
||||
}
|
||||
console.log(data);
|
||||
},'html');
|
||||
//alert(curEan)
|
||||
}
|
||||
|
||||
function saveToLibary(){
|
||||
url = "/save?ean=<%= it.ean %>";
|
||||
|
||||
$.get(url,function(data,status) { console.log(data); console.log(status) },'html');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
133
template/addToShelf.html
Normal file
133
template/addToShelf.html
Normal file
@ -0,0 +1,133 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Basic Page Needs
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta charset="utf-8" />
|
||||
<title>OpenMovieDB - Bookshelf</title>
|
||||
<meta name="description" content="OpenMovieDB - Bookshelf" />
|
||||
<meta name="author" content="TheGreydiamond" />
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- FONT
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link
|
||||
href="//fonts.googleapis.com/css?family=Raleway:400,300,600"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
<!-- CSS
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="stylesheet" href="css/normalize.css" />
|
||||
<link rel="stylesheet" href="css/skeleton.css" />
|
||||
<style>
|
||||
#overlay {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
#overlay2 {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#text{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
font-size: 50px;
|
||||
color: white;
|
||||
transform: translate(-50%,-50%);
|
||||
-ms-transform: translate(-50%,-50%);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Favicon
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="icon" type="image/png" href="images/favicon.png" />
|
||||
<script src="https://kit.fontawesome.com/d7b80a780b.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.rawgit.com/serratus/quaggaJS/0420d5e0/dist/quagga.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body>
|
||||
<div id="overlay" onclick="off()">
|
||||
<div id="text"><svg class='checkmark' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 52 52'><circle class='checkmark__circle ' cx='26' cy='26' r='25' fill='none'/><path class='checkmark__check' fill='none' d='M14.1 27.2l7.1 7.2 16.7-16.8'/></svg><style>.checkmark__circle { stroke-dasharray: 166; stroke-dashoffset: 166; stroke-width: 2; stroke-miterlimit: 10; stroke: #7ac142; fill: none; animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;}.checkmark { width: 56px; height: 56px; border-radius: 50%; display: block; stroke-width: 2; stroke: #fff; stroke-miterlimit: 10; margin: 10% auto; box-shadow: inset 0px 0px 0px #7ac142; animation: fill .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both;}.checkmark__check { transform-origin: 50% 50%; stroke-dasharray: 48; stroke-dashoffset: 48; animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;}@keyframes stroke { 100% { stroke-dashoffset: 0; }}@keyframes scale { 0%, 100% { transform: none; } 50% { transform: scale3d(1.1, 1.1, 1); }}@keyframes fill { 100% { box-shadow: inset 0px 0px 0px 30px #7ac142; }}</style></div>
|
||||
</div>
|
||||
<div id="overlay2" onclick="off()">
|
||||
<div id="text"><h1>!</h1><red>This movie already exists in the DB.</red></div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="one-half column" style="margin-top: 15%" id="mainCont">
|
||||
<h4>OpenMovieDB - Add a new movie</h4>
|
||||
<div style="width: 300px;">
|
||||
<img src="<%= it.cover %>" alt="Cover image" style="width: 100%;"></img><br>
|
||||
<center><%= it.titleByAPI %><br><i><%= it.id %></i></center>
|
||||
</div>
|
||||
<button onclick="saveToLibary()" class="button-primary" id="addToBtn"> Add to libary</button>
|
||||
<button onclick="window.location.href = '/'"><i class="fas fa-home"></i> Back to home</button>
|
||||
<button
|
||||
|
||||
onclick="window.location.href = '/add'"
|
||||
>
|
||||
<i class="fas fa-plus"></i> Add new movie</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Include the image-diff library -->
|
||||
|
||||
<script>
|
||||
function on() {
|
||||
document.getElementById("overlay").style.display = "block";
|
||||
}
|
||||
function on2() {
|
||||
document.getElementById("overlay2").style.display = "block";
|
||||
}
|
||||
|
||||
function off() {
|
||||
document.getElementById("overlay").style.display = "none";
|
||||
document.getElementById("overlay2").style.display = "none";
|
||||
}
|
||||
|
||||
function saveToLibary(){
|
||||
url = "/save?reponseID=<%= it.ean %>";
|
||||
document.getElementById("addToBtn").remove();
|
||||
$.get(url,function(data,status) {
|
||||
console.log(JSON.parse(data))
|
||||
if(JSON.parse(data).status == "OK"){
|
||||
on();
|
||||
}else{
|
||||
console.log("exist")
|
||||
on2()
|
||||
}
|
||||
},'html');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
90
template/bookshelf.html
Normal file
90
template/bookshelf.html
Normal file
@ -0,0 +1,90 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Basic Page Needs
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta charset="utf-8" />
|
||||
<title>OpenMovieDB - Bookshelf</title>
|
||||
<meta name="description" content="OpenMovieDB - Bookshelf" />
|
||||
<meta name="author" content="TheGreydiamond" />
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- FONT
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link
|
||||
href="//fonts.googleapis.com/css?family=Raleway:400,300,600"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
<!-- CSS
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="stylesheet" href="css/normalize.css" />
|
||||
<link rel="stylesheet" href="css/skeleton.css" />
|
||||
|
||||
<!-- Favicon
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="icon" type="image/png" href="images/favicon.png" />
|
||||
<script
|
||||
src="https://kit.fontawesome.com/d7b80a780b.js"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Primary Page Layout
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<div class="eleven column" style="margin-top: 15%">
|
||||
<h4>OpenMovieDB - Bookshelf</h4>
|
||||
<div style="float: right; top: -20px;">
|
||||
<input class="u-full-width" type="text" placeholder="Search" id="search">
|
||||
</div>
|
||||
<button
|
||||
class="button-primary"
|
||||
onclick="window.location.href = '/add'"
|
||||
>
|
||||
<i class="fas fa-plus"></i> Add new movie</button
|
||||
><br />
|
||||
<div id="listOfMovies"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
ser = document.getElementById("search");
|
||||
ser.addEventListener("input", updateValue);
|
||||
json = <%~ it.jsonRespo %>;
|
||||
function updateValue(e) {
|
||||
console.log(e.target.value)
|
||||
outList = [];
|
||||
i = 0;
|
||||
elem = document.getElementById("listOfMovies");
|
||||
elem.innerHTML = ""
|
||||
while(i < json.length){
|
||||
currenElm = json[i]
|
||||
if(currenElm.movieTitel.toLowerCase().replace("(", "").replace(")", "").includes(e.target.value.toLowerCase())){
|
||||
console.log(currenElm.movieID)
|
||||
elem.innerHTML += "<a href='/showDetails?id=" + currenElm.movieID + "'><div style='width: 150px; float: left; padding: 5px;'><img src='" + currenElm.posterUrl + '\' style="width: 100%;"><br><center><b>' + currenElm.movieTitel + "</b></center></div></a>"
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
}
|
||||
i = 0;
|
||||
elem = document.getElementById("listOfMovies")
|
||||
while(i < json.length){
|
||||
currenElm = json[i]
|
||||
elem.innerHTML += "<a href='/showDetails?id=" + currenElm.movieID + "'><div style='width: 150px; float: left; padding: 5px;'><img src='" + currenElm.posterUrl + '\' style="width: 100%;"><br><center><b>' + currenElm.movieTitel + "</b></center></div></a>"
|
||||
i++;
|
||||
}
|
||||
|
||||
</script>
|
||||
<!-- End Document
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
</body>
|
||||
</html>
|
138
template/index.html
Normal file
138
template/index.html
Normal file
@ -0,0 +1,138 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<script src="https://cdn.rawgit.com/serratus/quaggaJS/0420d5e0/dist/quagga.min.js"></script>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
/* In order to place the tracking correctly */
|
||||
canvas.drawing, canvas.drawingBuffer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<%= it.titleByAPI %><br>
|
||||
<%= it.id %><br>
|
||||
<img src="<%= it.cover %>" alt="Cover image" style="height: 200px;"></img>
|
||||
<!-- Div to show the scanner -->
|
||||
<div id="scanner-container"></div>
|
||||
<input type="button" id="btn" value="Start/Stop the scanner" />
|
||||
<div id="currentEAN">Waiting for proper EAN..</div>
|
||||
<button onclick="sendEanConvRequest()"> Search</button>
|
||||
|
||||
<!-- Include the image-diff library -->
|
||||
|
||||
<script>
|
||||
var _scannerIsRunning = false;
|
||||
|
||||
function startScanner() {
|
||||
Quagga.init({
|
||||
inputStream: {
|
||||
name: "Live",
|
||||
type: "LiveStream",
|
||||
target: document.querySelector('#scanner-container'),
|
||||
constraints: {
|
||||
width: 480,
|
||||
height: 320,
|
||||
facingMode: "environment"
|
||||
},
|
||||
},
|
||||
decoder: {
|
||||
readers: [
|
||||
"code_128_reader",
|
||||
"ean_reader",
|
||||
"ean_8_reader",
|
||||
"code_39_reader",
|
||||
"code_39_vin_reader",
|
||||
"codabar_reader",
|
||||
"upc_reader",
|
||||
"upc_e_reader",
|
||||
"i2of5_reader"
|
||||
],
|
||||
debug: {
|
||||
showCanvas: true,
|
||||
showPatches: true,
|
||||
showFoundPatches: true,
|
||||
showSkeleton: true,
|
||||
showLabels: true,
|
||||
showPatchLabels: true,
|
||||
showRemainingPatchLabels: true,
|
||||
boxFromPatches: {
|
||||
showTransformed: true,
|
||||
showTransformedBox: true,
|
||||
showBB: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}, function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return
|
||||
}
|
||||
|
||||
console.log("Initialization finished. Ready to start");
|
||||
Quagga.start();
|
||||
|
||||
// Set flag to is running
|
||||
_scannerIsRunning = true;
|
||||
});
|
||||
|
||||
Quagga.onProcessed(function (result) {
|
||||
var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||
drawingCanvas = Quagga.canvas.dom.overlay;
|
||||
|
||||
if (result) {
|
||||
if (result.boxes) {
|
||||
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||
result.boxes.filter(function (box) {
|
||||
return box !== result.box;
|
||||
}).forEach(function (box) {
|
||||
Quagga.ImageDebug.drawPath(box, { x: 0, y: 1 }, drawingCtx, { color: "green", lineWidth: 2 });
|
||||
});
|
||||
}
|
||||
|
||||
if (result.box) {
|
||||
Quagga.ImageDebug.drawPath(result.box, { x: 0, y: 1 }, drawingCtx, { color: "#00F", lineWidth: 2 });
|
||||
}
|
||||
|
||||
if (result.codeResult && result.codeResult.code) {
|
||||
Quagga.ImageDebug.drawPath(result.line, { x: 'x', y: 'y' }, drawingCtx, { color: 'red', lineWidth: 3 });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Quagga.onDetected(function (result) {
|
||||
console.log("Barcode detected and processed : [" + result.codeResult.code + "]", result);
|
||||
if(String(result.codeResult.code).length == 13){
|
||||
document.getElementById("currentEAN").innerHTML = result.codeResult.code
|
||||
console.log(result.codeResult.code)
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Start/stop scanner
|
||||
document.getElementById("btn").addEventListener("click", function () {
|
||||
if (_scannerIsRunning) {
|
||||
Quagga.stop();
|
||||
} else {
|
||||
startScanner();
|
||||
}
|
||||
}, false);
|
||||
|
||||
function sendEanConvRequest(){
|
||||
url = "/apiCallBack?ean=" + document.getElementById("currentEAN").innerHTML;
|
||||
window.open(url)
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
126
template/movieDetails.html
Normal file
126
template/movieDetails.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Basic Page Needs
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta charset="utf-8" />
|
||||
<title>OpenMovieDB - Bookshelf</title>
|
||||
<meta name="description" content="OpenMovieDB - Bookshelf" />
|
||||
<meta name="author" content="TheGreydiamond" />
|
||||
|
||||
<!-- Mobile Specific Metas
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- FONT
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link
|
||||
href="//fonts.googleapis.com/css?family=Raleway:400,300,600"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
/>
|
||||
|
||||
<!-- CSS
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="stylesheet" href="css/normalize.css" />
|
||||
<link rel="stylesheet" href="css/skeleton.css" />
|
||||
<style>
|
||||
#overlay {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#overlay2 {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
z-index: 2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#text{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
font-size: 50px;
|
||||
color: white;
|
||||
transform: translate(-50%,-50%);
|
||||
-ms-transform: translate(-50%,-50%);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Favicon
|
||||
–––––––––––––––––––––––––––––––––––––––––––––––––– -->
|
||||
<link rel="icon" type="image/png" href="images/favicon.png" />
|
||||
<script src="https://kit.fontawesome.com/d7b80a780b.js" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.rawgit.com/serratus/quaggaJS/0420d5e0/dist/quagga.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<body>
|
||||
<div id="overlay" onclick="off()">
|
||||
<div id="text"><svg class='checkmark' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 52 52'><circle class='checkmark__circle ' cx='26' cy='26' r='25' fill='none'/><path class='checkmark__check' fill='none' d='M14.1 27.2l7.1 7.2 16.7-16.8'/></svg><style>.checkmark__circle { stroke-dasharray: 166; stroke-dashoffset: 166; stroke-width: 2; stroke-miterlimit: 10; stroke: #7ac142; fill: none; animation: stroke 0.6s cubic-bezier(0.65, 0, 0.45, 1) forwards;}.checkmark { width: 56px; height: 56px; border-radius: 50%; display: block; stroke-width: 2; stroke: #fff; stroke-miterlimit: 10; margin: 10% auto; box-shadow: inset 0px 0px 0px #7ac142; animation: fill .4s ease-in-out .4s forwards, scale .3s ease-in-out .9s both;}.checkmark__check { transform-origin: 50% 50%; stroke-dasharray: 48; stroke-dashoffset: 48; animation: stroke 0.3s cubic-bezier(0.65, 0, 0.45, 1) 0.8s forwards;}@keyframes stroke { 100% { stroke-dashoffset: 0; }}@keyframes scale { 0%, 100% { transform: none; } 50% { transform: scale3d(1.1, 1.1, 1); }}@keyframes fill { 100% { box-shadow: inset 0px 0px 0px 30px #7ac142; }}</style></div>
|
||||
</div>
|
||||
|
||||
<div id="overlay2" onclick="off()">
|
||||
<div id="text">Do you really want to remove this movie?<br>
|
||||
<button onclick="sureDelete()" style="background-color: rgba(174, 255, 128, 0.699)"><i class="fas fa-trash"></i> Yes</button>
|
||||
<button onclick="off()" style="background-color: rgba(255, 95, 95, 0.719)"><i class="fas fa-times"></i> No</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="one-half column" style="margin-top: 10%" id="mainCont">
|
||||
<h4>OpenMovieDB - Moviedetails</h4>
|
||||
<div style="width: 300px;">
|
||||
<img src="<%= it.cover %>" alt="Cover image" style="width: 100%;"></img><br>
|
||||
<center><%= it.titleByAPI %><br><i><%= it.id %></i></center>
|
||||
</div>
|
||||
<button onclick="handelDelete()" id="delBtn"><i class="fas fa-trash"></i> Delete</button>
|
||||
<button onclick="window.location.href = '/'"><i class="fas fa-home"></i> Back to home</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function on() {
|
||||
document.getElementById("overlay").style.display = "block";
|
||||
}
|
||||
|
||||
function off() {
|
||||
document.getElementById("overlay").style.display = "none";
|
||||
document.getElementById("overlay2").style.display = "none";
|
||||
}
|
||||
|
||||
function sureDelete(){
|
||||
console.log("Deleting movie")
|
||||
url = "/delete?id=<%= it.internalID %>";
|
||||
document.getElementById("delBtn").remove();
|
||||
$.get(url,function(data,status) { console.log(data); console.log(status); on(); setTimeout(function(){window.location.href = '/';}, 1000); },'html');
|
||||
}
|
||||
|
||||
function handelDelete(){
|
||||
document.getElementById("overlay2").style.display = "block";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
26
testEANconver.js
Normal file
26
testEANconver.js
Normal file
@ -0,0 +1,26 @@
|
||||
|
||||
|
||||
|
||||
|
||||
/*const FormData = require('form-data');
|
||||
const http = require('http');
|
||||
|
||||
const form = new FormData();
|
||||
form.append('SText', '4010884546217');
|
||||
form.append('Kat', 'EAN');
|
||||
const uploadResponse = fetch("https://ssl.ofdb.de/view.php?page=suchergebnis", {method: 'POST', body: form });
|
||||
|
||||
setTimeout(() => {
|
||||
console.log(uploadResponse)
|
||||
}, 500);
|
||||
*/
|
||||
|
||||
const { URLSearchParams } = require('url');
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.append('SText', '4010884546217');
|
||||
params.append('Kat', 'EAN');
|
||||
|
||||
fetch('https://ssl.ofdb.de/view.php?page=suchergebnis', { method: 'POST', body: params })
|
||||
.then(res => console.log(res.statusCode))
|
Reference in New Issue
Block a user