Commit dbacd5e0 authored by Michael Murtaugh's avatar Michael Murtaugh
Browse files

separated cc from widget code

parent b4f9e9d7
/*
Goal: preserve the basic operation of CC, in a lumino/widget independent way
NB: hash vs. fragment
hash includes the leading hash tag, e.g. valid hash values are '', or '#foo'
while fragment never includes the hash, e.g. fragment is '', or 'foo'
*/
import { parseFragment } from './url.js';
import * as reflinks from './reflinks.js';
export default class CCManager {
construct(urlbar, frame, editor) {
this.urlbar = urlbar;
this.frame = frame;
this.editor = editor;
}
handleLink(href, target) {
// HANDLE HREF + TARGET
// console.log('cc.handleLink', href, target);
if (this.frame) {
this.frame.src = href;
}
}
pasteLink() {
let href = this.urlbar.url;
const hash = this.urlbar.fragment;
// console.log('pasteLink', href, hash);
if (this.editor) {
const ev = this.editor.getValue();
const thereflinks = reflinks.extractReflinkDefinitions(ev);
if (hash) {
href = parseFragment(href).base + hash;
}
const compactHref = reflinks.compactRefLink(href, thereflinks);
if (compactHref !== href) {
this.editor.replaceSelection(`[${compactHref}]`);
} else {
this.editor.replaceSelection(`<${href}>`);
}
}
}
setActiveEditor(editor) {
if (editor !== this.editor) {
// console.log("setActiveEditor", editor);
this.editor = editor;
}
}
// maybe this needs to become onFrameHashChange ... add frame
frameHashchange(frame, baseurl, fragment) {
this.urlbar.url = baseurl;
this.urlbar.fragment = fragment || '';
}
frameLoad(frame, url) {
const { base, fragment } = parseFragment(url);
this.urlbar.url = base;
if (fragment) {
this.urlbar.fragment = `#${fragment}`;
}
}
}
......@@ -11,34 +11,18 @@ import URLBar from './urlbar.js';
import EditorWidget from './editor.js';
import FrameWidget from './framewidget.js';
import Sniffer from './sniffer.js';
import CCManager from './cc.js';
// import { ListingWidget } from './listing.js';
import * as reflinks from './reflinks.js';
// import * as reflinks from './reflinks.js';
// import * as ticdb from './ticdb.js';
// const VIDEO_URL = 'http://vandal.ist/thesituationisttimes/video/2017-12-14/MVI_0033.web.mp4';
/* eslint no-unused-vars: ["error", { "args": "none" }] */
const cc = {};
window.cc = cc;
cc.version = '0.0.1dev-2021-02-11-2021';
const commands = new CommandRegistry();
let urlbar;
function parseFragment(url) {
// console.log("parseFragment", url);
const ret = {};
if (url.indexOf('#') >= 0) {
const p = url.split('#', 2);
[ret.base, ret.fragment] = p;
// ret.fragment = p[1];
} else {
ret.base = url;
ret.fragment = '';
}
return ret;
}
window.cclab_version = '0.0.1dev-2021-02-11-2021';
/*
cc.handleLink = function handleLink(href, target) {
// HANDLE HREF + TARGET
// console.log('cc.handleLink', href, target);
......@@ -75,34 +59,27 @@ cc.setActiveEditor = (editor) => {
// maybe this needs to become onFrameHashChange ... add frame
// and also onFrameLoad ...
cc.hashchange = (baseurl, fragment) => {
function ccHashChange (baseurl, fragment) {
urlbar.url = baseurl;
urlbar.fragment = fragment || '';
};
cc.hashchange = ccHashChange;
function ccOnLoad (url) {
}
cc.load = ccOnLoad;
*/
function main() {
// const dialog = document.getElementById('dialog');
let dock;
// function dialogIsOpen() {
// return dialog.style.display !== 'none';
// }
// function closeDialog() {
// dialog.style.display = 'none';
// openfile.style.display = 'none';
// openfileFileinput.value = null;
// }
// function showOpenfile() {
// dialog.style.display = 'flex';
// openfile.style.display = 'block';
// openfileFileinput.focus();
// }
// openfileCancel.addEventListener('click', (e) => {
// closeDialog();
// });
const cc = new CCManager();
window.cc = cc;
const commands = new CommandRegistry();
const dock = new DockPanel();
dock.id = 'dock';
commands.addCommand('annotation:new', {
label: 'New',
......@@ -111,7 +88,7 @@ function main() {
execute: () => {
// console.log('Import...');
// showOpenfile();
const editor = new EditorWidget();
const editor = new EditorWidget('', cc);
dock.addWidget(editor);
},
});
......@@ -242,8 +219,9 @@ function main() {
bar.addMenu(mediamenu);
bar.id = 'menuBar';
urlbar = new URLBar();
const urlbar = new URLBar();
urlbar.id = 'urlbar';
cc.urlbar = urlbar;
document.addEventListener('keydown', (event) => {
// console.log("keydown", event);
......@@ -257,15 +235,13 @@ function main() {
// let listing = new ListingWidget('Listing');
// window._tic.listing = listing;
dock = new DockPanel();
// dock.addWidget(editor2, { ref: editor1 });
dock.id = 'dock';
const frame = new FrameWidget(null, cc); // VIDEO_URL
cc.frame = frame;
dock.addWidget(frame);
const editor = new EditorWidget();
const editor = new EditorWidget('', cc);
dock.addWidget(editor, { mode: 'split-right' }); // { mode: 'split-right' }
editor.setValue('<http://localhost:8000/>\n\n<http://vandal.ist/thesituationisttimes/video/2017-12-14/MVI_0033.web.mp4>\n\n<https://www.youtube.com/watch?v=162VzSzzoPs>\n\n');
......
......@@ -60,11 +60,13 @@ export default class EditorWidget extends Widget {
return node;
}
constructor(name) {
constructor(name, cc) {
super({ node: EditorWidget.createNode() });
// let editor_div = this.node.getElementsByTagName('div')[0];
this.cm = CodeMirror(this.editorDiv, CM_OPTS);
this.cc = cc;
const nop = function nop(cm) {};
// block shift-ctrl-up to prevent shift-up + cc keys
this.cm.setOption('extraKeys', {
......@@ -112,14 +114,14 @@ export default class EditorWidget extends Widget {
// console.log("editor.onAfterAttach", this, "hidden", this.isHidden);
if (!this.isHidden) {
// initial state is this
window.cc.setActiveEditor(this);
this.cc.setActiveEditor(this);
}
// this.cm.refresh();
}
onAfterShow() {
// console.log("editor.onAfterShow", this, this.isHidden);
window.cc.setActiveEditor(this);
this.cc.setActiveEditor(this);
// this.cm.refresh();
}
......@@ -166,7 +168,7 @@ export default class EditorWidget extends Widget {
}
}
if (href) {
window.cc.handleLink(href, target);
this.cc.handleLink(href, target);
}
}
}
......@@ -3,6 +3,7 @@ import * as timecode from './timecode.js';
import MediaFrame from './mediaframe.js';
import PlyrFrame from './plyrframe.js';
import IFrame from './iframe.js';
import { parseFragment } from './url.js';
const VIEWERS = [MediaFrame, PlyrFrame, IFrame];
......@@ -23,25 +24,6 @@ TODO implement generic jumpback/forward based on form of fragment
/* eslint no-unused-vars: ["error", { "args": "none" }] */
// function stripFragment(url) {
// const p = url.indexOf('#');
// if (p >= 0) { return url.substring(0, p); }
// return url;
// }
function parseFragment(url) {
// console.log("parseFragment", url);
const ret = {};
if (url.indexOf('#') >= 0) {
const p = url.split('#', 2);
[ret.base, ret.fragment] = p;
} else {
ret.base = url;
ret.fragment = '';
}
return ret;
}
function parseTime(h) {
const m = h.match('t=([^&,]*)');
// console.log("parseTime", h, m);
......@@ -73,7 +55,7 @@ export default class Frame {
if (VIEWERS[i].sniff(url)) {
if (this.frame) {
this.frame.dispose();
this.elt.innerHTML = "";
this.elt.innerHTML = '';
}
this.frame = new VIEWERS[i](this, url, fragment);
break;
......@@ -119,11 +101,11 @@ export default class Frame {
}
hashchange(f, fragment) {
this.cc.hashchange(f.url, fragment);
this.cc.frameHashchange(f, f.url, fragment);
}
load(f, url) {
this.cc.load(f.url, fragment);
this.cc.frameLoad(f, url);
}
toggle() {
......
// import * as timecode from './timecode.js';
import { parseFragment } from './url.js';
// function stripFragment(url) {
// const p = url.indexOf('#');
......@@ -17,29 +18,47 @@ export default class IFrame {
this.frame = frame;
this.iframe = document.createElement('iframe');
this.frame.elt.appendChild(this.iframe);
this.iframe.addEventListener('hashchange', this.hashupdate.bind(this));
// this.iframe.addEventListener('hashchange', this.hashchange.bind(this));
this.iframe.addEventListener('load', this.load.bind(this));
this.iframe.src = this.url + (this.fragment || '');
// console.log('iframe constructor', this.url, fragment);
this.iframe.src = this.url + (fragment ? `#${fragment}` : '');
}
hashupdate() {
hashchange() {
// console.log('iframe hashchange', this);
this.frame.hashchange(this, this.iframe.contentWindow.location.hash);
}
load() {
console.log('iframe load', this.iframe.contentWindow.location);
// this.frame.load(this, new_url, new_hash);
const newURL = this.iframe.contentWindow.location.toString();
const { base } = parseFragment(newURL);
this.url = base;
this.frame.load(this, newURL);
this.iframe.contentWindow.addEventListener('hashchange', this.hashchange.bind(this));
this.iframe.contentDocument.addEventListener('click', this.clickhander.bind(this));
// console.log('iframe load', this.iframe.contentWindow.location);
}
set fragment(f) {
// console.log("iframe set fragment", f);
this.frame.contentWindow.location.hash = f;
this.iframe.contentWindow.location.hash = f;
// when set on a click, this happens, but no hashchange event naturally occurs..
this.frame.hashchange(this, f);
}
get fragment() {
return this.iframe.contentWindow.location.hash;
}
clickhander(event) {
const t = event.target;
const tid = t.getAttribute('id');
// console.log("iframe click", t, tid);
if (tid) {
this.frame.hashchange(this, `#${tid}`);
}
}
dispose() {
this.iframe.remove();
}
......
export function stripFragment(url) {
const p = url.indexOf('#');
if (p >= 0) { return url.substring(0, p); }
return url;
}
export function parseFragment(url) {
// console.log("parseFragment", url);
const ret = {};
if (url.indexOf('#') >= 0) {
const p = url.split('#', 2);
[ret.base, ret.fragment] = p;
// ret.fragment = p[1];
} else {
ret.base = url;
ret.fragment = '';
}
return ret;
}
......@@ -277,6 +277,11 @@ async def websocket_handler(request):
print('Websocket connection closed')
return ws
async def lab_index_handler (request):
htdocs = request.app['htdocs']
return web.FileResponse(os.path.join(htdocs, "index.html"))
def main ():
ap = argparse.ArgumentParser("make & serve")
ap.add_argument("--makefile", "-f", default="Makefile")
......@@ -285,9 +290,14 @@ def main ():
ap.add_argument("--port", type=int, default=8000)
ap.add_argument("--editor", default=None)
ap.add_argument("--static", nargs=2, default=None, action="append")
ap.add_argument("--debug", action="store_true", default=False)
ap.add_argument("--version", action="store_true", default=False)
args = ap.parse_args()
print ("Makeserver Version 3.1.0")
version = '3.1.0-dev-2021-02-14'
print (f"Makeserver {version}")
if args.version:
sys.exit(0)
if sys.platform == 'win32':
# Folowing: https://docs.python.org/3/library/asyncio-subprocess.html
......@@ -306,9 +316,12 @@ def main ():
data = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data")
htdocs = os.path.join(data, "htdocs")
app['htdocs'] = htdocs
laburl = "__lab__"
print (f"Adding static route {laburl}/ -> {htdocs}")
app.router.add_static(f"/{laburl}", htdocs, show_index=True)
# add /__lab__/ => index.html
app.router.add_route("GET", f"/{laburl}/", lab_index_handler)
app.router.add_static(f"/{laburl}", htdocs, show_index=args.debug)
if args.static:
for name, path in args.static:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment