introduce namespaces for JS and trying to escape the pyramid of doom
This commit is contained in:
parent
525a2828c5
commit
261f2fe18e
2
Makefile
2
Makefile
@ -9,6 +9,6 @@ init:
|
||||
rm -rf $(ISSO)/promise.js
|
||||
|
||||
js:
|
||||
cat $(ISSO)/ender.js $(ISSO)/isso.js $(ISSO)/utils.js > $(ISSO)/_.js
|
||||
cat $(ISSO)/ender.js $(ISSO)/isso.js $(ISSO)/utils.js $(ISSO)/client.js > $(ISSO)/_.js
|
||||
yuicompressor --type js --charset utf-8 $(ISSO)/_.js -o $(ISSO)/embed.js
|
||||
rm $(ISSO)/_.js
|
||||
|
216
isso/js/client.js
Normal file
216
isso/js/client.js
Normal file
@ -0,0 +1,216 @@
|
||||
/* Copyright 2012, Martin Zimmermann <info@posativ.org>. All rights reserved.
|
||||
* License: BSD Style, 2 clauses. See isso/__init__.py.
|
||||
*/
|
||||
|
||||
var isso = isso || {};
|
||||
|
||||
|
||||
function form(id, defaults, func) {
|
||||
/*
|
||||
Returns HTML for form and registers submit call.
|
||||
|
||||
Synopsis: `isso_N` is the comment with the id N. `issoform` is a new
|
||||
form to write an answer to the article or answer to a comment using
|
||||
`issoform_N` where N is the id to respond to.
|
||||
|
||||
:param id: comment id
|
||||
:param returnfunc: function, that takes one argument (the HTML to display the form)
|
||||
:param func: function, when the user submits the form
|
||||
*/
|
||||
|
||||
var rv = $(brew([
|
||||
'div', {'class': 'issoform', 'id': 'issoform' + (id ? ('_' + id) : '')},
|
||||
['div',
|
||||
['input', {'type': 'text', 'name': 'author', 'id': 'author', 'value': defaults.author || "", 'placeholder': "Name"}]],
|
||||
['div',
|
||||
['input', {'type': 'email', 'name': 'email', 'id': 'email', 'value': defaults.email || "", 'placeholder': "Email"}]],
|
||||
['div',
|
||||
['input', {'type': 'url', 'name': 'website', 'id': 'website', 'value': defaults.website || "", 'placeholder': "Website"}]],
|
||||
['div',
|
||||
['textarea', defaults.text || "", {'rows': '10', 'name': 'text', 'id': 'comment', 'placeholder': "Comment"}]],
|
||||
['div',
|
||||
['input', {'type': 'submit', 'value': 'Add Comment'}]],
|
||||
]));
|
||||
|
||||
$('input[type="submit"]', rv).on('click', function(event) {
|
||||
func(rv, id);
|
||||
event.stop();
|
||||
});
|
||||
return rv;
|
||||
};
|
||||
|
||||
|
||||
function extract(form, parent) {
|
||||
return {
|
||||
text: $('textarea[id="comment"]', form).val() || null,
|
||||
author: $('input[id="author"]', form).val() || null,
|
||||
email: $('input[id="email"]', form).val() || null,
|
||||
website: $('input[id="website"]', form).val() || null,
|
||||
parent: parent
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function edit() {
|
||||
|
||||
};
|
||||
|
||||
|
||||
function commit(form, parent) {
|
||||
isso.create(extract(form, parent), function(status, rv) {
|
||||
if (status == 201 || status == 202) {
|
||||
insert(JSON.parse(rv));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var insert = function insert(post) {
|
||||
/*
|
||||
Insert a comment into #isso_thread.
|
||||
|
||||
:param post: JSON from API call
|
||||
*/
|
||||
|
||||
var path = encodeURIComponent(window.location.pathname),
|
||||
date = new Date(parseInt(post['created']) * 1000);
|
||||
|
||||
// create <ul /> for parent, if used
|
||||
if (post['parent'])
|
||||
$('#isso_' + post['parent']).append('<ul></ul>');
|
||||
|
||||
$(post['parent'] ? '#isso_' + post['parent'] + ' > ul:last-child' : '#isso_thread > ul')
|
||||
.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 = brew(['a', {'href': post['website'], 'rel': 'nofollow'}]);
|
||||
|
||||
// deleted
|
||||
if (post['mode'] == 4) {
|
||||
node.addClass('deleted');
|
||||
$('header', node).append('Kommentar entfernt')
|
||||
$('div', node).append('<p> </p>')
|
||||
return;
|
||||
}
|
||||
|
||||
$('header', node).append('<span class="author">' + author + '</span>');
|
||||
if (post['mode'] == 2 )
|
||||
$('header', node).append(brew(['span', {'class': 'note'}, 'Kommentar muss noch freigeschaltet werden']));
|
||||
|
||||
$('div', node).html(post['text']);
|
||||
|
||||
$('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(brew(['a', {'class': 'delete', 'href': '#'}, 'Löschen']))
|
||||
.after(brew(['a', {'class': 'edit', 'href': '#'}, 'Bearbeiten']));
|
||||
|
||||
// DELETE
|
||||
$('#isso_' + post['id'] + ' > footer .delete').on('click', function(event) {
|
||||
isso.remove(post['id'], function(status, rv) {
|
||||
// XXX comment might not actually deleted
|
||||
$('#isso_' + post['id']).remove();
|
||||
});
|
||||
event.stop();
|
||||
});
|
||||
|
||||
// EDIT
|
||||
$('#isso_' + post['id'] + ' > footer .edit').on('click', function(event) {
|
||||
|
||||
if ($('#issoform_' + post['id']).length == 0) { // HTML form not shown
|
||||
isso.plain(post['id'], function(status, rv) {
|
||||
if (status != 200) return alert('Mööp');
|
||||
var rv = form(post['id'], JSON.parse(rv), function(form, id) {
|
||||
isso.modify(id, extract(form, post['parent']), function(status, rv) {
|
||||
if (status != 200) return alert('Mööp');
|
||||
|
||||
$('#issoform_' + post['id']).remove();
|
||||
$('#isso_' + post['id']).remove();
|
||||
insert(JSON.parse(rv));
|
||||
});
|
||||
});
|
||||
|
||||
$('#isso_' + post['id']).after(rv);
|
||||
$('input[type="submit"]', rv)[0].value = 'Bestätigen.';
|
||||
});
|
||||
} else {
|
||||
$('#issoform_' + post['id']).remove();
|
||||
};
|
||||
event.stop();
|
||||
});
|
||||
};
|
||||
|
||||
// ability to answer directly to a comment
|
||||
$('footer > a:first-child', '#isso_' + post['id']).on('click', function(event) {
|
||||
|
||||
if ($('#issoform_' + post['id']).length == 0) { // HTML form not shown
|
||||
$('#isso_' + post['id']).after(form(post['id'], {}, function(form, id) {
|
||||
commit(form, id);
|
||||
// XXX: animation (aka user feedback)
|
||||
$('#issoform_' + post['id']).remove();
|
||||
}));
|
||||
} else {
|
||||
$('#issoform_' + post['id']).remove();
|
||||
};
|
||||
event.stop();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* initialize form and fetch recent comments
|
||||
*/
|
||||
|
||||
function initialize(thread) {
|
||||
var html;
|
||||
|
||||
thread.append('<ul id="comments"></ul>');
|
||||
$('head').append('<link rel="stylesheet" href="/static/style.css" />');
|
||||
|
||||
html = form(null, {}, commit);
|
||||
thread.append(html);
|
||||
};
|
||||
|
||||
|
||||
function fetch(thread) {
|
||||
$.ajax('GET', isso.prefix + '/1.0/' + encodeURIComponent(window.location.pathname),
|
||||
{}, {'Content-Type': 'application/json'}).then(function(status, rv) {
|
||||
|
||||
if (status != 200) {
|
||||
return
|
||||
};
|
||||
|
||||
rv = JSON.parse(rv);
|
||||
for (var item in rv) {
|
||||
insert(rv[item]);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$.domReady(function() {
|
||||
|
||||
// initialize comment form and css
|
||||
initialize($('#isso_thread'));
|
||||
|
||||
// fetch comments for path
|
||||
fetch($('#isso_thread'));
|
||||
|
||||
// REMOVE ME
|
||||
$('input[id="author"]').val("Peter");
|
||||
$('textarea[id="comment"]').val("Lorem ipsum ...");
|
||||
|
||||
});
|
249
isso/js/isso.js
249
isso/js/isso.js
@ -9,12 +9,18 @@
|
||||
* with `isso`.
|
||||
*/
|
||||
|
||||
// var prefix = "/comments";
|
||||
var prefix = "";
|
||||
// Uhm. Namespaces are one honking great idea, aren't they?
|
||||
var isso = isso || {},
|
||||
prefix = "",
|
||||
path = encodeURIComponent(window.location.pathname);
|
||||
|
||||
// XXX
|
||||
isso.prefix = prefix;
|
||||
isso.path = path;
|
||||
|
||||
|
||||
/*
|
||||
* isso specific helpers to create, modify, delete and receive comments
|
||||
* isso specific helpers to create, modify, remove and receive comments
|
||||
*/
|
||||
|
||||
function verify(data) {
|
||||
@ -22,251 +28,32 @@ function verify(data) {
|
||||
};
|
||||
|
||||
|
||||
function create(data, func) {
|
||||
isso.create = function(data, func) {
|
||||
|
||||
if (!verify(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax('POST', prefix + '/1.0/' + encodeURIComponent(window.location.pathname) + '/new',
|
||||
$.ajax('POST', prefix + '/1.0/' + path + '/new',
|
||||
JSON.stringify(data), {'Content-Type': 'application/json'}).then(func);
|
||||
};
|
||||
|
||||
|
||||
function modify(id, data, func) {
|
||||
isso.modify = function(id, data, func) {
|
||||
if (!verify(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax('PUT', prefix + '/1.0/' + encodeURIComponent(window.location.pathname) + '/' + id,
|
||||
$.ajax('PUT', prefix + '/1.0/' + path + '/' + id,
|
||||
JSON.stringify(data), {'Content-Type': 'application/json'}).then(func)
|
||||
};
|
||||
|
||||
|
||||
function form(id, appendfunc, eventfunc) {
|
||||
/*
|
||||
Returns HTML for form and registers submit call.
|
||||
|
||||
Synopsis: `isso_N` is the comment with the id N. `issoform` is a new
|
||||
form to write an answer to the article or answer to a comment using
|
||||
`issoform_N` where N is the id to respond to.
|
||||
|
||||
:param id: comment id
|
||||
:param returnfunc: function, that takes one argument (the HTML to display the form)
|
||||
:param eventfunc: function, when the user submits the 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);
|
||||
};
|
||||
|
||||
|
||||
function insert(post) {
|
||||
/*
|
||||
Insert a comment into #isso_thread.
|
||||
|
||||
:param post: JSON from API call
|
||||
*/
|
||||
|
||||
var path = encodeURIComponent(window.location.pathname),
|
||||
date = new Date(parseInt(post['created']) * 1000);
|
||||
|
||||
// create <ul /> for parent, if used
|
||||
if (post['parent'])
|
||||
$('#isso_' + post['parent']).append('<ul></ul>');
|
||||
|
||||
$(post['parent'] ? '#isso_' + post['parent'] + ' > ul:last-child' : '#isso_thread > ul')
|
||||
.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 = brew(['a', {'href': post['website'], 'rel': 'nofollow'}]);
|
||||
|
||||
// deleted
|
||||
if (post['mode'] == 4) {
|
||||
node.addClass('deleted');
|
||||
$('header', node).append('Kommentar entfernt')
|
||||
$('div', node).append('<p> </p>')
|
||||
return;
|
||||
}
|
||||
|
||||
$('header', node).append('<span class="author">' + author + '</span>');
|
||||
if (post['mode'] == 2 )
|
||||
$('header', node).append(brew(['span', {'class': 'note'}, 'Kommentar muss noch freigeschaltet werden']));
|
||||
|
||||
$('div', node).html(post['text']);
|
||||
|
||||
$('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(brew(['a', {'class': 'delete', 'href': '#'}, 'Löschen']))
|
||||
.after(brew(['a', {'class': 'edit', 'href': '#'}, 'Bearbeiten']));
|
||||
|
||||
// DELETE
|
||||
$('#isso_' + post['id'] + ' > footer .delete').on('click', function(event) {
|
||||
$.ajax('DELETE', prefix + '/1.0/' + path + '/' + post['id'])
|
||||
.then(function(status, rv) {
|
||||
// XXX comment might not actually deleted
|
||||
$('#isso_' + post['id']).remove();
|
||||
});
|
||||
event.stop();
|
||||
});
|
||||
|
||||
// EDIT
|
||||
$('#isso_' + post['id'] + ' > footer .edit').on('click', function(event) {
|
||||
|
||||
if ($('#issoform_' + post['id']).length == 0) {
|
||||
|
||||
$.ajax('GET', prefix + '/1.0/' + path + '/' + post['id'], {'plain': '1'})
|
||||
.then(function(status, rv) {
|
||||
rv = JSON.parse(rv);
|
||||
form(post['id'],
|
||||
function(html) {
|
||||
$('#isso_' + post['id']).after(html);
|
||||
|
||||
var node = $("#issoform_" + post['id']);
|
||||
$('textarea[id="comment"]', node).val(rv['text']);
|
||||
$('input[id="author"]', node).val(rv['author']);
|
||||
$('input[id="email"]', node).val(rv['email']);
|
||||
$('input[id="website"]', node).val(rv['website']);
|
||||
$('input[name="submit"]', node).val('Bestätigen.')
|
||||
},
|
||||
function(event) {
|
||||
var node = $("#issoform_" + post['id']);
|
||||
modify(post['id'], {
|
||||
text: $('textarea[id="comment"]', node).val() || null,
|
||||
author: $('input[id="author"]', node).val() || null,
|
||||
email: $('input[id="email"]', node).val() || null,
|
||||
website: $('input[id="website"]', node).val() || null,
|
||||
parent: post['parent']
|
||||
}, function(status, rv) {
|
||||
$('#isso_' + post['id'] + ' div').html(JSON.parse(rv)['text']);
|
||||
$('#issoform_' + post['id']).remove();
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$('#issoform_' + post['id']).remove();
|
||||
};
|
||||
event.stop();
|
||||
});
|
||||
};
|
||||
|
||||
// ability to answer directly to a comment
|
||||
$('footer > a:first-child', '#isso_' + post['id']).on('click', function(event) {
|
||||
|
||||
if ($('#issoform_' + post['id']).length == 0) {
|
||||
form(post['id'],
|
||||
function(html) {
|
||||
$('#isso_' + post['id']).after(html)
|
||||
},
|
||||
function(event) {
|
||||
create({
|
||||
text: $('textarea[id="comment"]').val() || null,
|
||||
author: $('input[id="author"]').val() || null,
|
||||
email: $('input[id="email"]').val() || null,
|
||||
website: $('input[id="website"]').val() || null,
|
||||
parent: post['id']
|
||||
}, function(status, rv) {
|
||||
$('#issoform_' + post['id']).remove();
|
||||
if (status == 201 || status == 202) {
|
||||
insert(JSON.parse(rv));
|
||||
} else {
|
||||
alert("Mööp.");
|
||||
};
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$('#issoform_' + post['id']).remove();
|
||||
};
|
||||
event.stop();
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* initialize form and fetch recent comments
|
||||
*/
|
||||
|
||||
function initialize(thread) {
|
||||
|
||||
// that with an unordered list
|
||||
thread.append('<ul id="comments"></ul>');
|
||||
|
||||
// load our css
|
||||
$('head').append('<link rel="stylesheet" href="/static/style.css" />');
|
||||
|
||||
// append form
|
||||
form(null, function(html) { thread.append(html) }, function(event) {
|
||||
create({
|
||||
text: $('textarea[id="comment"]').val() || null,
|
||||
author: $('input[id="author"]').val() || null,
|
||||
email: $('input[id="email"]').val() || null,
|
||||
website: $('input[id="website"]').val() || null,
|
||||
parent: null
|
||||
}, function(status, rv) {
|
||||
if (status == 201 || status == 202) {
|
||||
insert(JSON.parse(rv));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function fetch(thread) {
|
||||
$.ajax('GET', prefix + '/1.0/' + encodeURIComponent(window.location.pathname),
|
||||
{}, {'Content-Type': 'application/json'}).then(function(status, rv) {
|
||||
|
||||
if (status != 200) {
|
||||
return
|
||||
};
|
||||
|
||||
rv = JSON.parse(rv);
|
||||
for (var item in rv) {
|
||||
insert(rv[item]);
|
||||
};
|
||||
});
|
||||
isso.plain = function(id, func) {
|
||||
$.ajax('GET', prefix + '/1.0/' + path + '/' + id, {'plain': '1'}).then(func);
|
||||
}
|
||||
|
||||
|
||||
$.domReady(function() {
|
||||
|
||||
// initialize comment form and css
|
||||
initialize($('#isso_thread'));
|
||||
|
||||
// fetch comments for path
|
||||
fetch($('#isso_thread'));
|
||||
|
||||
// REMOVE ME
|
||||
$('input[id="author"]').val("Peter");
|
||||
$('textarea[id="comment"]').val("Lorem ipsum ...");
|
||||
|
||||
});
|
||||
isso.remove = function(id, func) {
|
||||
$.ajax('DELETE', prefix + '/1.0/' + path + '/' + id).then(func);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
<script type="text/javascript" src="/js/ender.js"></script>
|
||||
<script type="text/javascript" src="/js/isso.js"></script>
|
||||
<script type="text/javascript" src="/js/utils.js"></script>
|
||||
<script type="text/javascript" src="/js/client.js"></script>
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0 auto;
|
||||
|
Loading…
Reference in New Issue
Block a user