diff --git a/Makefile b/Makefile index 3c6fb5c..45797f2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: init: - (cd isso/js && ender build jeesh reqwest) + (cd isso/js && ender build jeesh) js: cat isso/js/ender.js isso/js/isso.js > _.js diff --git a/isso/__init__.py b/isso/__init__.py index 1dafd73..ba64e07 100644 --- a/isso/__init__.py +++ b/isso/__init__.py @@ -26,10 +26,10 @@ import sys; reload(sys) sys.setdefaultencoding('utf-8') # we only support UTF-8 and python 2.X :-) import io +import os import json import traceback -from os.path import dirname from optparse import OptionParser, make_option, SUPPRESS_HELP from itsdangerous import URLSafeTimedSerializer @@ -117,9 +117,13 @@ class Isso(object): if code == 404: try: - code, body, headers = wsgi.sendfile(environ['PATH_INFO'], dirname(__file__)) + code, body, headers = wsgi.sendfile(environ['PATH_INFO'], os.getcwd()) except (IOError, OSError): - pass + try: + path = environ['PATH_INFO'].rstrip('/') + '/index.html' + code, body, headers = wsgi.sendfile(path, os.getcwd()) + except (IOError, OSError): + pass if request == 'HEAD': body = '' diff --git a/isso/js/isso.js b/isso/js/isso.js index cfea3ae..d0e9bdb 100644 --- a/isso/js/isso.js +++ b/isso/js/isso.js @@ -12,20 +12,21 @@ /* utility functions -- JS Y U SO STUPID? * - * read(cookie): return `cookie` string if set - * zfill(argument, i): zero fill `argument` with `i` zeros + * read(cookie): return `cookie` string if set + * format(date): human-readable date formatting + * brew(array): similar to DOMinate essentials */ - // var prefix = "/comments"; - var prefix = ""; +// var prefix = "/comments"; +var prefix = ""; -function read(cookie){ - return(document.cookie.match('(^|; )' + cookie + '=([^;]*)') || 0)[2] +function read(cookie) { + return (document.cookie.match('(^|; )' + cookie + '=([^;]*)') || 0)[2] }; -function format(date){ +function format(date) { /*! * JavaScript Pretty Date * Copyright (c) 2011 John Resig (ejohn.org) @@ -34,20 +35,49 @@ function format(date){ var diff = (((new Date()).getTime() - date.getTime()) / 1000), day_diff = Math.floor(diff / 86400); - if ( isNaN(day_diff) || day_diff < 0 || day_diff >= 31 ) + if (isNaN(day_diff) || day_diff < 0 || day_diff >= 31) return; return day_diff == 0 && ( diff < 60 && "just now" || diff < 120 && "1 minute ago" || - diff < 3600 && Math.floor( diff / 60 ) + " minutes ago" || + diff < 3600 && Math.floor(diff / 60) + " minutes ago" || diff < 7200 && "1 hour ago" || - diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") || + diff < 86400 && Math.floor(diff / 3600) + " hours ago") || day_diff == 1 && "Yesterday" || day_diff < 7 && day_diff + " days ago" || - day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago"; + day_diff < 31 && Math.ceil(day_diff / 7) + " weeks ago"; } + +function brew(arr) { + /* + * Element creation utility. Similar to DOMinate, but with a slightly different syntax: + * brew([TAG, {any: attribute, ...}, 'Hello World', ' Foo Bar', ['TAG', 'Hello World'], ...]) + * --> Hello World Foo BarHello World + */ + + var rv = document.createElement(arr[0]); + + for (var i = 1; i < arr.length; i++) { + + if (arr[i] instanceof Array) { + rv.appendChild(brew(arr[i])); + } else if (typeof(arr[i]) == "string") { + rv.appendChild(document.createTextNode(arr[i])); + } else { + attrs = arr[i] || {}; + for (var k in attrs) { + if (!attrs.hasOwnProperty(k)) continue; + rv.setAttribute(k, attrs[k]); + } + } + }; + + return rv; +} + + /* * isso specific helpers to create, modify, delete and receive comments */ @@ -91,24 +121,21 @@ function form(id, appendfunc, eventfunc) { :param eventfunc: function, when the user submits the form */ - var formid = 'issoform' + (id ? ('_' + id) : ''), form = - '
' + - '
' + - ' ' + - '
' + - '
' + - ' ' + - '
' + - '
' + - '' + - '
' + - '
' + - ' ' + - '
' + - '
' + - '' + - '
' + - '
' + var formid = 'issoform' + (id ? ('_' + id) : ''), form = brew([ + 'div', {'class': 'issoform', 'id': formid}, + ['div', + ['input', {'type': 'text', 'name': 'author', 'id': 'author', 'value': '', 'placeholder': "Name"}]], + ['div', + ['input', {'type': 'email', 'name': 'email', 'id': 'email', 'value': '', 'placeholder': "Email"}]], + ['div', + ['input', {'type': 'email', 'name': 'email', 'id': 'email', 'value': '', 'placeholder': "Email"}]], + ['div', + ['input', {'type': 'url', 'name': 'website', 'id': 'website', 'value': '', 'placeholder': "website URL"}]], + ['div', + ['textarea', {'rows': '10', 'name': 'text', 'id': 'comment', 'placeholder': "Comment"}]], + ['div', + ['input', {'type': 'submit', 'value': 'Add Comment'}]], + ]); appendfunc(form); $('#' + formid + ' ' + 'input[type="submit"]').on('click', eventfunc); @@ -130,19 +157,16 @@ function insert(post) { $('#isso_' + post['parent']).append(''); $(post['parent'] ? '#isso_' + post['parent'] + ' > ul:last-child' : '#isso_thread > ul') - .append( - '
' + - '
' + - '
' + - ' ' + - '
' - ); + .append(brew([ + 'article', {'class': 'isso', 'id': 'isso_' + post['id']}, + ['header'], ['div'], ['footer'] + ])); var node = $('#isso_' + post['id']), author = post['author'] || 'Anonymous'; if (post['website']) - author = '' + author + ''; + author = brew(['a', {'href': post['website'], 'rel': 'nofollow'}]); // deleted if (post['mode'] == 4) { @@ -154,28 +178,22 @@ function insert(post) { $('header', node).append('' + author + ''); if (post['mode'] == 2 ) - $('helpers', node).append('Kommentar muss noch freigeschaltet werden'); + $('header', node).append(brew(['span', {'class': 'note'}, 'Kommentar muss noch freigeschaltet werden'])); $('div', node).html(post['text']); - $('footer', node).append( - 'Antworten' + - '#' + post['id'] + '' + - '' - ) - - // pending notification - if (post['mode'] == 2 ) { - $('#isso_' + post['id'] + ' header') - .append('Kommentar muss noch freigeschaltet werden'); - } + $('footer', node).append(brew([ + 'a', {'href': '#'}, 'Antworten', + ])).append(brew([ + 'a', {'href': '#isso_' + post['id']}, '#' + post['id'], + ])).append(brew([ + 'time', {'datetime': date.getUTCFullYear() + '-' + date.getUTCMonth() + '-' + date.getUTCDate()}, format(date) + ])); if (read(path + '-' + post['id'])) { $('#isso_' + post['id'] + '> footer > a:first-child') - .after('Löschen') - .after('Bearbeiten'); + .after(brew(['a', {'class': 'delete', 'href': '#'}, 'Löschen'])) + .after(brew(['a', {'class': 'edit', 'href': '#'}, 'Bearbeiten'])); // DELETE $('#isso_' + post['id'] + ' > footer .delete').on('click', function(event) { @@ -289,7 +307,6 @@ function initialize(thread) { function fetch(thread) { - console.log(window.location.pathname); $.ajax('GET', prefix + '/1.0/' + encodeURIComponent(window.location.pathname), {}, {'Content-Type': 'application/json'}).then(function(status, rv) {