178 lines
6.1 KiB
JavaScript
178 lines
6.1 KiB
JavaScript
window.EditorMovie = (function () {
|
|
'use strict';
|
|
|
|
var STORAGE_KEY = 'omdb-api-key';
|
|
|
|
var BEGIN = '<!-- BEGIN MOVIE -->';
|
|
var END = '<!-- END MOVIE -->';
|
|
|
|
function firstHeading(text) {
|
|
var m = text.match(/^#{1,6}\s+(.+?)\s*$/m);
|
|
return m ? m[1].trim() : '';
|
|
}
|
|
|
|
function parseTitleYear(raw) {
|
|
var m = raw.match(/^(.+?)\s*\((\d{4})\)\s*$/);
|
|
return m ? { title: m[1].trim(), year: m[2] } : { title: raw.trim(), year: null };
|
|
}
|
|
|
|
function safe(v) { return (!v || v === 'N/A') ? '' : String(v); }
|
|
|
|
function esc(s) {
|
|
return String(s)
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"');
|
|
}
|
|
|
|
function buildBlock(m) {
|
|
var out = [BEGIN, '<aside class="movie-info">'];
|
|
if (m.Poster && m.Poster !== 'N/A') {
|
|
out.push('<img class="movie-poster" src="' + esc(m.Poster) +
|
|
'" alt="' + esc(safe(m.Title)) + ' poster">');
|
|
}
|
|
out.push('<table>');
|
|
[
|
|
['Title', m.Title],
|
|
['Year', m.Year],
|
|
['Runtime', m.Runtime],
|
|
['Genre', m.Genre],
|
|
['Director', m.Director],
|
|
['Cast', m.Actors],
|
|
['Plot', m.Plot],
|
|
].forEach(function (r) {
|
|
out.push('<tr><th>' + r[0] + '</th><td>' + esc(safe(r[1])) + '</td></tr>');
|
|
});
|
|
out.push('</table>', '</aside>', END);
|
|
return out.join('\n');
|
|
}
|
|
|
|
// ctx is the CM adapter from main.js: { getValue(), replace(start,end,text) }.
|
|
function insertOrReplace(ctx, markup) {
|
|
var t = ctx.getValue() || '';
|
|
var b = t.indexOf(BEGIN);
|
|
var e = t.indexOf(END);
|
|
if (b !== -1 && e !== -1 && e > b) {
|
|
ctx.replace(b, e + END.length, markup);
|
|
} else {
|
|
var h = t.match(/^#{1,6}\s+.+?\s*$/m);
|
|
if (h) {
|
|
var idx = t.indexOf(h[0]) + h[0].length;
|
|
ctx.replace(idx, idx, '\n\n' + markup);
|
|
} else {
|
|
ctx.replace(0, 0, t ? markup + '\n\n' : markup);
|
|
}
|
|
}
|
|
}
|
|
|
|
function fetchMovie(key, title, year) {
|
|
var url = 'https://www.omdbapi.com/?apikey=' + encodeURIComponent(key) +
|
|
'&type=movie&t=' + encodeURIComponent(title);
|
|
if (year) url += '&y=' + encodeURIComponent(year);
|
|
return fetch(url).then(function (r) { return r.json(); });
|
|
}
|
|
|
|
function showMessage(title, msg) {
|
|
openModal({ title: title, body: msg, confirm: { label: 'OK' } });
|
|
}
|
|
|
|
function promptForKey(rejected, onSaved) {
|
|
var body = document.createDocumentFragment();
|
|
|
|
if (rejected) {
|
|
var notice = document.createElement('p');
|
|
notice.textContent = 'The previously stored key was rejected by OMDb.';
|
|
body.appendChild(notice);
|
|
}
|
|
|
|
var info = document.createElement('p');
|
|
info.appendChild(document.createTextNode('Enter your OMDb API key. Get one at '));
|
|
var link = document.createElement('a');
|
|
link.href = 'https://www.omdbapi.com/apikey.aspx';
|
|
link.target = '_blank';
|
|
link.rel = 'noopener';
|
|
link.textContent = 'omdbapi.com/apikey.aspx';
|
|
info.appendChild(link);
|
|
info.appendChild(document.createTextNode('.'));
|
|
body.appendChild(info);
|
|
|
|
var input = document.createElement('input');
|
|
input.type = 'text';
|
|
input.className = 'input';
|
|
input.placeholder = 'OMDb API key';
|
|
body.appendChild(input);
|
|
|
|
openModal({
|
|
title: 'OMDb API key required',
|
|
body: body,
|
|
confirm: {
|
|
label: 'SAVE',
|
|
onConfirm: function () {
|
|
var key = input.value.trim();
|
|
if (!key) return;
|
|
localStorage.setItem(STORAGE_KEY, key);
|
|
closeModal();
|
|
onSaved(key);
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function importWithKey(ctx, key, initialTitle) {
|
|
var input = document.createElement('input');
|
|
input.type = 'text';
|
|
input.className = 'input';
|
|
input.placeholder = 'Title, optionally with (YYYY)';
|
|
input.value = initialTitle;
|
|
|
|
openModal({
|
|
title: 'Import movie',
|
|
body: input,
|
|
confirm: {
|
|
label: 'IMPORT',
|
|
onConfirm: function () {
|
|
var raw = input.value.trim();
|
|
if (!raw) return;
|
|
var parsed = parseTitleYear(raw);
|
|
closeModal();
|
|
fetchMovie(key, parsed.title, parsed.year)
|
|
.then(function (data) {
|
|
if (data && data.Response === 'False' &&
|
|
data.Error === 'Invalid API key!') {
|
|
localStorage.removeItem(STORAGE_KEY);
|
|
promptForKey(true, function (newKey) {
|
|
importWithKey(ctx, newKey, raw);
|
|
});
|
|
return;
|
|
}
|
|
if (!data || data.Response === 'False') {
|
|
showMessage('Not found',
|
|
(data && data.Error) || 'Movie not found.');
|
|
return;
|
|
}
|
|
insertOrReplace(ctx, buildBlock(data));
|
|
})
|
|
.catch(function () {
|
|
showMessage('Import failed', 'OMDb lookup failed.');
|
|
});
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function run(ctx) {
|
|
var initialTitle = firstHeading(ctx.getValue() || '');
|
|
var key = localStorage.getItem(STORAGE_KEY);
|
|
if (!key) {
|
|
promptForKey(false, function (newKey) {
|
|
importWithKey(ctx, newKey, initialTitle);
|
|
});
|
|
return;
|
|
}
|
|
importWithKey(ctx, key, initialTitle);
|
|
}
|
|
|
|
return { run: run };
|
|
})();
|