...
 
Commits (3)
......@@ -68,5 +68,20 @@
<ul>
<li>Enable making files in subdirectories that don't (yet) exist. (make_server.py:FileMaker)</li>
</ul>
<h2 id="section">2017</h2>
<p>Request.process res = site.getResourceFor() res.render</p>
<p>NEED FileSaver Resource that gets returned for a file.</p>
<p>TODO</p>
<ul>
<li>Separate editor options / cleanup editor</li>
<li>Use favicon for editor / file type specific ?!</li>
<li>Wrapping options (without having to resize the browser window)</li>
<li>Font + font sizes!</li>
<li>&quot;Sticky&quot; preferences (like theme/fonts/etc)</li>
</ul>
<h2 id="march-2017">March 2017</h2>
<ul>
<li>add ?touch query option + functionality in main code (remove cgi)</li>
</ul>
</body>
</html>
......@@ -75,4 +75,33 @@ In explaining the project yesterday, I naturally described the server as the "ma
TODO: Clean the editor code to not require the (rather) unholy mess of both jquery + d3.
* Enable making files in subdirectories that don't (yet) exist. (make_server.py:FileMaker)
\ No newline at end of file
* Enable making files in subdirectories that don't (yet) exist. (make_server.py:FileMaker)
2017
----------
Request.process
res = site.getResourceFor()
res.render
NEED FileSaver Resource that gets returned for a file.
TODO
* Separate editor options / cleanup editor
* Use favicon for editor / file type specific ?!
* Wrapping options (without having to resize the browser window)
* Font + font sizes!
* "Sticky" preferences (like theme/fonts/etc)
March 2017
-------------
* add ?touch query option + functionality in main code (remove cgi)
* 12 April 2017: Observation: auto "edit" linking functionality would be nice -- but from the index page (ie automagically adding the ?edit, which can then be manually removed) (ie original decision to do this auto editing INSIDE the server was too rigid)
......@@ -152,6 +152,13 @@ function editor (elt, ace) {
startNormalized: t,
start: aa_secondsToTimecode(t)
}, "*");
var tc = aa_secondsToTimecode(t);
console.log("aafragment", tc);
localStorage.setItem("aafragment", JSON.stringify({
time: t,
timecode: tc,
event: "tokenclick"
}));
// var href = current_href.replace(/\.srt$/, '');
// $(editor.elt).trigger("fragmentclick", { href: href+"#t="+aa.secondsToTimecode(t) });
} else {
......@@ -374,15 +381,21 @@ function editor (elt, ace) {
var mode = aceeditor.getSession().getMode().$id,
link,
t;
console.log("paste", window, window.parent);
if (last_fragment && last_fragment.hash.t.length) {
t = last_fragment.hash.t[0];
console.log("paste using localStorage", window, window.parent);
var cchref = localStorage.getItem("cchref"),
ccfragment = localStorage.getItem("ccfragment");
if (cchref) {
if (mode == "ace/mode/srtmd") {
link = aa_secondsToTimecode(t.startNormalized)+" -->\n";
link = ccfragment+" -->\n";
} else if (mode == "ace/mode/markdown") {
link = "["+last_fragment.value+"]("+last_fragment.value+")";
if (ccfragment) {
link = "[#"+ccfragment+"]("+cchref+"#"+ccfragment+")";
} else {
link = "["+cchref+"]("+cchref+")";
}
} else {
link = last_fragment.value;
link = cchref+"#"+ccfragment;
}
aceeditor.insert(link);
}
......@@ -402,6 +415,7 @@ function editor (elt, ace) {
bindKey: {win: 'ctrl-shift-up', mac: 'command-shift-up'},
exec: function () {
window.postMessage({msg: "cc_toggle", origin: window.name}, "*");
localStorage.setItem("cccontrol", JSON.stringify({cmd: "toggle", time: new Date()}));
},
readOnly: true // false if this command should not apply in readOnly mode
});
......@@ -410,6 +424,7 @@ function editor (elt, ace) {
bindKey: {win: 'ctrl-shift-left', mac: 'command-shift-left'},
exec: function () {
window.postMessage({msg: "cc_left", origin: window.name}, "*");
localStorage.setItem("cccontrol", JSON.stringify({cmd: "left", time: new Date()}));
},
readOnly: true // false if this command should not apply in readOnly mode
});
......@@ -418,6 +433,7 @@ function editor (elt, ace) {
bindKey: {win: 'ctrl-shift-right', mac: 'command-shift-right'},
exec: function () {
window.postMessage({msg: "cc_right", origin: window.name}, "*");
localStorage.setItem("cccontrol", JSON.stringify({cmd: "right", time: new Date()}));
},
readOnly: true // false if this command should not apply in readOnly mode
});
......
......@@ -2,6 +2,7 @@
<html>
<head>
<meta charset="utf-8" />
<title>editor</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<style type="text/css" media="screen">
body {
......
<!DOCTYPE>
<html>
<head>
<meta charset="utf-8" />
<title>player</title>
<style>
body {
margin: 0;
}
iframe {
width: 100%;
height: 100%;
border: none;
background: pink;
}
</style>
</head>
<body>
<iframe id="iframe"></iframe>
<script>
/* LIBRARY ROUTINES */
var parseQueryString = function( queryString ) {
var params = {}, queries, temp, i, l;
// Split into key/value pairs
queries = queryString.split("&");
// Convert the array of strings into an object
for ( i = 0, l = queries.length; i < l; i++ ) {
temp = queries[i].split('=');
params[temp[0]] = decodeURIComponent(temp[1]);
}
return params;
};
function aa_secondsToTimecode (ss, style) {
style = timecode_styles[style || 'html5'];
var h = Math.floor(ss/3600),
m,
s,
fract,
ret;
ss -= (h * 3600);
m = Math.floor(ss / 60);
ss -= (m * 60);
s = Math.floor(ss);
fract = style.delimiter + (""+(ss - s)).substr(2, 3);
while (fract.length < 4) { fract += "0"; } // PAD TO ALWAYS BE THREE DIGITS LONG (eg .040)
ret = (h || style.requireHours ? ((((h<10)?"0":"")+h)+":") : '')
ret += (((m<10)?"0":"")+m)+":"+(((s<10)?"0":"")+s)+fract;
return ret;
}
timecode_styles = {
'srt': {
requireHours: true,
delimiter: ','
},
'html5': {
requireHours: false,
delimiter: '.'
}
}
function aa_timecodeToSeconds (tc) {
var tcpat = /^(?:(\d\d):)?(\d\d):(\d\d(?:[\.,](?:\d{1,3}))?)$/,
groups = tcpat.exec(tc);
if (groups != null) {
var h = groups[1] !== undefined ? parseInt(groups[1]) : 0,
m = parseInt(groups[2]),
s = parseFloat(groups[3].replace(/,/, "."));
return (h * 3600) + (m * 60) + s;
}
}
/* */
// window.addEventListener("message", function (e) {
// // console.log("message", e);
// if (e.data.msg == "fragmentclick" && e.data.hash.t[0].startNormalized) {
// audio.currentTime = e.data.hash.t[0].startNormalized;
// } else if (e.data.msg == "cc_toggle") {
// if (audio.paused) {
// audio.play();
// } else {
// audio.pause();
// }
// } else if (e.data.msg == "cc_left") {
// audio.currentTime -= 5;
// } else if (e.data.msg == "cc_right") {
// audio.currentTime += 5;
// }
// }, false);
var iframe = document.getElementById("iframe"),
current_src,
current_hash,
media;
function on_timeupdate () {
localStorage.setItem("ccfragment", "t="+aa_secondsToTimecode(media.currentTime))
}
iframe.addEventListener("load", function () {
console.log("iframe.load");
media = iframe.contentDocument.querySelector("audio,video");
if (media) {
console.log("listening to timeupdate events")
media.addEventListener("timeupdate", on_timeupdate);
}
})
function update_location () {
var vars = parseQueryString(window.location.hash.substring(1));
// console.log("video.html, update_location", vars);
iframe.src = vars.href;
current_src = vars.href;
localStorage.setItem("cchref", vars.href);
localStorage.removeItem("ccfragment");
// audio.play();
}
console.log("listening to storage");
window.addEventListener("storage", function (e) {
console.log("storage", e);
if (e.key == "cccontrol") {
// console.log("e.value", e.newValue);
var d = JSON.parse(e.newValue);
if (d.cmd == "toggle") {
if (media && media.paused) {
media.play();
} else {
media.pause();
}
} else if (d.cmd == "left") {
if (media) {
media.currentTime = media.currentTime - 5;
}
} else if (d.cmd == "right") {
if (media) {
media.currentTime = media.currentTime + 5;
}
}
}
}, false);
window.addEventListener("hashchange", function (e) {
update_location();
// var h = window.location.hash;
// // console.log("hashchange", h);
// if (h !== current_hash) {
// // act on it
// current_hash = h;
// var vars = parseQueryString(h.substring(1));
// if (vars.href !== current_src) {
// audio.src = vars.href;
// current_src = vars.href;
// audio.play();
// }
// if (vars.start) {
// audio.currentTime = aa_timecodeToSeconds(vars.start);
// audio.play();
// }
// }
});
// audio.addEventListener("timeupdate", function () {
// // console.log("timeupdate", this.currentTime);
// var start = audio.currentTime,
// start_tc = aa_secondsToTimecode(start);
// // current_hash = "#href="+current_src+"&t=" + aa_secondsToTimecode(audio.currentTime);
// // window.location.hash = current_hash;
// window.postMessage({
// msg: "fragmentchange",
// href: current_src,
// value: current_src+"#t="+start_tc,
// hash: {
// t: [{
// start: start_tc,
// startNormalized: start,
// unit: "npt",
// value: start_tc,
// end: "",
// endNormalized: ""
// }]
// }
// }, "*");
// });
update_location();
</script>
</body>
</html>
\ No newline at end of file
......@@ -10,16 +10,16 @@
<body>
<h1>Index of {{ request_label }}</h1>
<table>
<tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
<tr><th valign="top">&nbsp;</th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
<tr><th colspan="5"><hr></th></tr>
{% if parent_link %}
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="{{ parent_link }}">Parent Directory</a></td><td>&nbsp;</td><td align="right"> - </td><td>&nbsp;</td></tr>
<tr><td valign="top">&nbsp;</td><td><a href="{{ parent_link }}">Parent Directory</a></td><td>&nbsp;</td><td align="right"> - </td><td>&nbsp;</td></tr>
{% endif %}
{% for item in items %}
{% if item.is_dir %}
<tr class="{{item.classes}}"><td valign="top"><img src="/__makeserver__/icons/directory.symbolic.png" alt="[DIR]"></td><td><a href="{{item.link}}">{{item.label}}</a>{{item.buttons}}</td><td align="right">{% if item.lasmod %}{{item.lastmod | strftime("%Y-%m-%d %H:%M")}}{%else%}&mdash;{%endif%}</td><td align="right"> - </td><td>&nbsp;</td></tr>
{% else %}
<tr class="{{item.classes}}"><td valign="top"><a href="{{item.link}}?edit"><img src="/__makeserver__/icons/{% if item.is_text %}text{%else%}generic{%endif%}.symbolic.png" alt="[ ]" border="0"></a></td><td><a href="{{item.link}}">{{item.label}}</a>{{item.buttons}}</td><td align="right">{% if item.lastmod %}{{item.lastmod | strftime("%Y-%m-%d %H:%M")}}{%else%}&mdash;{%endif%} </td><td align="right">{{item.size|humanize_bytes}}</td><td>&nbsp;</td></tr>
<tr class="{{item.classes}}"><td valign="top"><a href="{{item.link}}?edit"><img src="/__makeserver__/icons/{% if item.is_text %}text{%else%}generic{%endif%}.symbolic.png" alt="[ ]" border="0"></a></td><td><a href="{{item.link}}{% if item.is_text and not (item.ext == "html" or item.ext == "svg")%}?edit{% endif %}">{{item.label}}</a>{{item.buttons}}</td><td align="right">{% if item.lastmod %}{{item.lastmod | strftime("%Y-%m-%d %H:%M")}}{%else%}&mdash;{%endif%} </td><td align="right">{{item.size|humanize_bytes}}</td><td>&nbsp;</td></tr>
{% endif %}
{% endfor %}
</table>
......
......@@ -178,12 +178,6 @@ class FileMaker (Resource):
ext = ext.lstrip('.').lower()
# print ("FILE '{0}'/'{1}'".format(base, ext))
use_editor = "edit" in query
# use_editor = "edit" in query or ((xRequestedWith != "XMLHttpRequest") and \
# "serve" not in query \
# and ext not in TEXT_SERVE_BY_DEFAULT \
# and base != self.index \
# and is_text_file(fpath))
if use_editor:
return EDITOR
else:
......@@ -214,6 +208,7 @@ class FileMaker (Resource):
return super(FileMaker, self).getChildForRequest(request)
def render_POST(self, request):
""" is this code reached ???? """
print ("POST", self.path, request)
# queue make request for self.path, and give request
# return "<html><body>make: {0}</body></html>".format(self.path)
......
......@@ -183,20 +183,8 @@ class MakeDirectoryListing (object):
fsize = 0
buttons = ' '
# file_request_uri = request_uri + urllib.quote(file)
# if makeable or missing or remake:
# note that request_uri DOES get "double encoded" but this seems the most sensible...
# as it will be received then as a URI, rather than already decoded
# makelink = "/cookbook/cgi-bin/make.cgi?" + urllib.urlencode({"pwd": path, "uri": file_request_uri, "return": "1", "force": "1"})
# buttons += '<a href="{0}" class="makebutton make">MAKE</a>'.format(makelink)
# editmakelink = "/cookbook/cgi-bin/maketext.cgi?" + urllib.urlencode({"pwd": path, "uri": file_request_uri})
# buttons += ' <a href="{0}" class="makebutton editmake">EDIT RECIPE</a>'.format(editmakelink)
# if is_text:
# # editlink = "/ace/#href=" + file_request_uri + "&path=" + urllib.quote(fp)
# editlink = "/cookbook/editor.html#href=" + file_request_uri + "&path=" + urllib.quote(fp)
# buttons += ' <a href="{0}" class="makebutton edit">EDIT</a>'.format(editlink)
# touchlink = "/cookbook/cgi-bin/touch.cgi?" + urllib.urlencode({"pwd": path, "uri": file_request_uri, "return": "1"})
# buttons += ' <a href="{0}" class="makebutton edit">TOUCH</a>'.format(touchlink)
_, ext = os.path.splitext(file)
ext = ext[1:].lower()
items.append({
'is_dir': is_dir,
......@@ -207,6 +195,7 @@ class MakeDirectoryListing (object):
'size': fsize,
'buttons': buttons,
'classes': classes,
'ext': ext
})
tvars['items'] = items
......