2013-09-05 17:31:18 +00:00
|
|
|
|
/* Isso – Ich schrei sonst!
|
|
|
|
|
*/
|
2014-03-04 14:48:44 +00:00
|
|
|
|
define(["app/text/html", "app/dom", "app/utils", "app/config", "app/api", "app/markup", "app/i18n", "app/lib", "app/globals"],
|
|
|
|
|
function(templates, $, utils, config, api, Mark, i18n, lib, globals) {
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
"use strict";
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
var msgs = i18n[i18n.lang];
|
|
|
|
|
|
|
|
|
|
var Postbox = function(parent) {
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
var el = $.htmlify(Mark.up(templates["postbox"]));
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-10-09 13:33:31 +00:00
|
|
|
|
// add a default identicon to not waste CPU cycles
|
2013-10-29 15:58:38 +00:00
|
|
|
|
$(".avatar > svg", el).replace(lib.identicons.blank(4, 48));
|
2013-10-01 12:42:00 +00:00
|
|
|
|
|
|
|
|
|
// on text area focus, generate identicon from IP address
|
2014-03-27 09:10:28 +00:00
|
|
|
|
$(".textarea-wrapper > .textarea", el).on("focus", function() {
|
2013-10-29 23:24:32 +00:00
|
|
|
|
if ($(".avatar svg", el).getAttribute("className") === "blank") {
|
2013-10-29 15:58:38 +00:00
|
|
|
|
$(".avatar svg", el).replace(
|
2013-11-02 17:41:00 +00:00
|
|
|
|
lib.identicons.generate(lib.pbkdf2(api.remote_addr(), api.salt, 1000, 6), 4, 48));
|
2013-10-01 12:42:00 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2013-11-16 20:41:54 +00:00
|
|
|
|
// update identicon on email input. Listens on keyup, after 200ms the
|
|
|
|
|
// new identicon is generated.
|
2013-10-01 12:42:00 +00:00
|
|
|
|
var active;
|
|
|
|
|
$(".input-wrapper > [type=email]", el).on("keyup", function() {
|
|
|
|
|
if (active) {
|
|
|
|
|
clearTimeout(active);
|
|
|
|
|
}
|
|
|
|
|
active = setTimeout(function() {
|
2013-11-02 17:41:00 +00:00
|
|
|
|
lib.pbkdf2($(".input-wrapper > [type=email]", el).value || api.remote_addr(), api.salt, 1000, 6)
|
2013-10-01 12:42:00 +00:00
|
|
|
|
.then(function(rv) {
|
2013-10-29 15:58:38 +00:00
|
|
|
|
$(".avatar svg", el).replace(lib.identicons.generate(rv, 4, 48));
|
2013-10-01 12:42:00 +00:00
|
|
|
|
});
|
|
|
|
|
}, 200);
|
|
|
|
|
}, false);
|
|
|
|
|
|
|
|
|
|
$(".input-wrapper > [type=email]", el).on("keydown", function() {
|
|
|
|
|
clearTimeout(active);
|
|
|
|
|
}, false);
|
|
|
|
|
|
2013-11-16 20:41:54 +00:00
|
|
|
|
// callback on success (e.g. to toggle the reply button)
|
2013-10-04 15:59:59 +00:00
|
|
|
|
el.onsuccess = function() {};
|
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
el.validate = function() {
|
2014-03-27 09:10:28 +00:00
|
|
|
|
if (utils.text($(".textarea", this).innerHTML).length < 3 ||
|
|
|
|
|
$(".textarea", this).classList.contains("placeholder"))
|
|
|
|
|
{
|
|
|
|
|
$(".textarea", this).focus();
|
2013-10-01 12:42:00 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
|
2013-11-16 20:41:54 +00:00
|
|
|
|
// submit form, initialize optional fields with `null` and reset form.
|
|
|
|
|
// If replied to a comment, remove form completely.
|
2013-10-01 12:42:00 +00:00
|
|
|
|
$("[type=submit]", el).on("click", function() {
|
|
|
|
|
if (! el.validate()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-29 13:07:26 +00:00
|
|
|
|
api.create($("#isso-thread").getAttribute("data-isso-id"), {
|
2013-10-01 12:42:00 +00:00
|
|
|
|
author: $("[name=author]", el).value || null,
|
|
|
|
|
email: $("[name=email]", el).value || null,
|
2014-03-27 09:10:28 +00:00
|
|
|
|
text: utils.text($(".textarea", el).innerHTML),
|
2013-10-01 12:42:00 +00:00
|
|
|
|
parent: parent || null
|
|
|
|
|
}).then(function(comment) {
|
|
|
|
|
$("[name=author]", el).value = "";
|
|
|
|
|
$("[name=email]", el).value = "";
|
2014-03-27 09:10:28 +00:00
|
|
|
|
$(".textarea", el).innerHTML = "";
|
|
|
|
|
$(".textarea", el).blur();
|
2013-10-01 12:42:00 +00:00
|
|
|
|
insert(comment, true);
|
|
|
|
|
|
|
|
|
|
if (parent !== null) {
|
2013-10-04 15:59:59 +00:00
|
|
|
|
el.onsuccess();
|
2013-10-01 12:42:00 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2014-03-27 09:10:28 +00:00
|
|
|
|
lib.editorify($(".textarea", el));
|
2013-10-02 12:26:06 +00:00
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
return el;
|
|
|
|
|
};
|
|
|
|
|
|
2014-04-22 19:45:16 +00:00
|
|
|
|
var insert_loader = function(commentWrapper, lastcreated) {
|
|
|
|
|
var entrypoint;
|
|
|
|
|
if (commentWrapper.id === null) {
|
|
|
|
|
entrypoint = $("#isso-root");
|
|
|
|
|
commentWrapper.name = 'null';
|
|
|
|
|
} else {
|
|
|
|
|
entrypoint = $("#isso-" + commentWrapper.id + " > .text-wrapper > .isso-follow-up");
|
|
|
|
|
commentWrapper.name = commentWrapper.id;
|
|
|
|
|
}
|
|
|
|
|
var el = $.htmlify(Mark.up(templates["comment_loader"], commentWrapper));
|
|
|
|
|
|
|
|
|
|
entrypoint.append(el);
|
|
|
|
|
|
|
|
|
|
$("a.load_hidden", el).toggle("click",
|
|
|
|
|
function() {
|
|
|
|
|
el.remove();
|
2014-05-02 19:45:19 +00:00
|
|
|
|
api.fetch($("#isso-thread").getAttribute("data-isso-id"),
|
2014-05-03 08:48:57 +00:00
|
|
|
|
config["reveal-on-click"], "0",
|
|
|
|
|
commentWrapper.id,
|
|
|
|
|
lastcreated).then(
|
2014-04-22 19:45:16 +00:00
|
|
|
|
function(rv) {
|
2014-05-03 08:48:57 +00:00
|
|
|
|
if (rv.total_replies === 0) {
|
2014-04-22 19:45:16 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lastcreated = 0;
|
|
|
|
|
rv.replies.forEach(function(commentObject) {
|
|
|
|
|
insert(commentObject, false);
|
|
|
|
|
if(commentObject.created > lastcreated) {
|
|
|
|
|
lastcreated = commentObject.created;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(rv.hidden_replies > 0) {
|
|
|
|
|
insert_loader(rv, lastcreated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (window.location.hash.length > 0) {
|
|
|
|
|
$(window.location.hash).scrollIntoView();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
function(err) {
|
|
|
|
|
console.log(err);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
};
|
2013-10-01 12:42:00 +00:00
|
|
|
|
|
2014-04-22 19:45:16 +00:00
|
|
|
|
var insert = function(comment, scrollIntoView) {
|
2013-10-01 12:42:00 +00:00
|
|
|
|
var el = $.htmlify(Mark.up(templates["comment"], comment));
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-11-16 20:41:54 +00:00
|
|
|
|
// update datetime every 60 seconds
|
2013-09-09 11:24:03 +00:00
|
|
|
|
var refresh = function() {
|
2013-11-16 20:41:54 +00:00
|
|
|
|
$(".permalink > date", el).textContent = utils.ago(
|
2014-03-04 14:48:44 +00:00
|
|
|
|
globals.offset.localTime(), new Date(parseInt(comment.created, 10) * 1000));
|
2013-10-01 12:42:00 +00:00
|
|
|
|
setTimeout(refresh, 60*1000);
|
2013-11-16 20:41:54 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// run once to activate
|
|
|
|
|
refresh();
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-10-29 15:58:38 +00:00
|
|
|
|
$("div.avatar > svg", el).replace(lib.identicons.generate(comment.hash, 4, 48));
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
var entrypoint;
|
|
|
|
|
if (comment.parent === null) {
|
|
|
|
|
entrypoint = $("#isso-root");
|
2013-09-05 17:31:18 +00:00
|
|
|
|
} else {
|
2014-04-20 14:30:18 +00:00
|
|
|
|
entrypoint = $("#isso-" + comment.parent + " > .text-wrapper > .isso-follow-up");
|
2013-09-05 17:31:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
entrypoint.append(el);
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-09-08 15:24:54 +00:00
|
|
|
|
if (scrollIntoView) {
|
2013-10-01 12:42:00 +00:00
|
|
|
|
el.scrollIntoView();
|
2013-09-08 15:24:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-19 09:38:16 +00:00
|
|
|
|
var footer = $("#isso-" + comment.id + " > .text-wrapper > .isso-comment-footer"),
|
|
|
|
|
header = $("#isso-" + comment.id + " > .text-wrapper > .isso-comment-header"),
|
|
|
|
|
text = $("#isso-" + comment.id + " > .text-wrapper > .text");
|
2013-10-01 12:42:00 +00:00
|
|
|
|
|
2013-11-16 20:41:54 +00:00
|
|
|
|
var form = null; // XXX: probably a good place for a closure
|
2013-10-03 16:56:36 +00:00
|
|
|
|
$("a.reply", footer).toggle("click",
|
2013-10-04 15:59:59 +00:00
|
|
|
|
function(toggler) {
|
2014-04-20 14:30:18 +00:00
|
|
|
|
form = footer.insertAfter(new Postbox(comment.parent === null ? comment.id : comment.parent));
|
2013-10-04 15:59:59 +00:00
|
|
|
|
form.onsuccess = function() { toggler.next(); };
|
2014-03-27 09:10:28 +00:00
|
|
|
|
$(".textarea", form).focus();
|
2013-10-03 16:56:36 +00:00
|
|
|
|
$("a.reply", footer).textContent = msgs["comment-close"];
|
|
|
|
|
},
|
|
|
|
|
function() {
|
2014-05-03 08:48:57 +00:00
|
|
|
|
form.remove();
|
2013-10-03 16:56:36 +00:00
|
|
|
|
$("a.reply", footer).textContent = msgs["comment-reply"];
|
|
|
|
|
}
|
|
|
|
|
);
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-11-16 20:41:54 +00:00
|
|
|
|
// update vote counter, but hide if votes sum to 0
|
2014-04-22 19:45:16 +00:00
|
|
|
|
var votes = function(value) {
|
2013-10-01 12:42:00 +00:00
|
|
|
|
var span = $("span.votes", footer);
|
2014-03-20 15:04:44 +00:00
|
|
|
|
if (span === null && value !== 0) {
|
2014-01-07 13:29:51 +00:00
|
|
|
|
footer.prepend($.new("span.votes", value));
|
2013-10-01 12:42:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (value === 0) {
|
|
|
|
|
span.remove();
|
|
|
|
|
} else {
|
|
|
|
|
span.textContent = value;
|
|
|
|
|
}
|
2013-09-05 17:31:18 +00:00
|
|
|
|
}
|
2013-10-01 12:42:00 +00:00
|
|
|
|
};
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
$("a.upvote", footer).on("click", function() {
|
|
|
|
|
api.like(comment.id).then(function(rv) {
|
|
|
|
|
votes(rv.likes - rv.dislikes);
|
2013-09-05 17:31:18 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
2013-10-01 12:42:00 +00:00
|
|
|
|
|
|
|
|
|
$("a.downvote", footer).on("click", function() {
|
|
|
|
|
api.dislike(comment.id).then(function(rv) {
|
|
|
|
|
votes(rv.likes - rv.dislikes);
|
|
|
|
|
});
|
2013-09-05 17:31:18 +00:00
|
|
|
|
});
|
|
|
|
|
|
2013-10-03 16:56:36 +00:00
|
|
|
|
$("a.edit", footer).toggle("click",
|
|
|
|
|
function(toggler) {
|
|
|
|
|
var edit = $("a.edit", footer);
|
|
|
|
|
|
|
|
|
|
edit.textContent = msgs["comment-save"];
|
|
|
|
|
edit.insertAfter($.new("a.cancel", msgs["comment-cancel"])).on("click", function() {
|
2014-03-27 09:10:28 +00:00
|
|
|
|
toggler.canceled = true;
|
2013-10-03 16:56:36 +00:00
|
|
|
|
toggler.next();
|
|
|
|
|
});
|
|
|
|
|
|
2014-03-27 09:10:28 +00:00
|
|
|
|
toggler.canceled = false;
|
2013-10-03 16:56:36 +00:00
|
|
|
|
api.view(comment.id, 1).then(function(rv) {
|
2014-03-27 09:10:28 +00:00
|
|
|
|
var textarea = lib.editorify($.new("div.textarea"));
|
|
|
|
|
|
2014-04-09 07:48:15 +00:00
|
|
|
|
textarea.innerHTML = utils.detext(rv.text);
|
2014-03-27 09:10:28 +00:00
|
|
|
|
textarea.focus();
|
|
|
|
|
|
|
|
|
|
text.classList.remove("text");
|
|
|
|
|
text.classList.add("textarea-wrapper");
|
|
|
|
|
|
2013-10-03 16:56:36 +00:00
|
|
|
|
text.textContent = "";
|
|
|
|
|
text.append(textarea);
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
function(toggler) {
|
2014-03-27 09:10:28 +00:00
|
|
|
|
var textarea = $(".textarea", text);
|
|
|
|
|
|
|
|
|
|
if (! toggler.canceled && textarea !== null) {
|
|
|
|
|
if (utils.text(textarea.innerHTML).length < 3) {
|
|
|
|
|
textarea.focus();
|
|
|
|
|
toggler.wait();
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
api.modify(comment.id, {"text": utils.text(textarea.innerHTML)}).then(function(rv) {
|
|
|
|
|
text.innerHTML = rv.text;
|
|
|
|
|
comment.text = rv.text;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
text.innerHTML = comment.text;
|
2013-10-03 16:56:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-27 09:10:28 +00:00
|
|
|
|
text.classList.remove("textarea-wrapper");
|
|
|
|
|
text.classList.add("text");
|
|
|
|
|
|
2013-10-03 16:56:36 +00:00
|
|
|
|
$("a.cancel", footer).remove();
|
|
|
|
|
$("a.edit", footer).textContent = msgs["comment-edit"];
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2013-10-29 17:46:08 +00:00
|
|
|
|
$("a.delete", footer).toggle("click",
|
|
|
|
|
function(toggler) {
|
|
|
|
|
var del = $("a.delete", footer);
|
|
|
|
|
var state = ! toggler.state;
|
|
|
|
|
|
|
|
|
|
del.textContent = msgs["comment-confirm"];
|
|
|
|
|
del.on("mouseout", function() {
|
|
|
|
|
del.textContent = msgs["comment-delete"];
|
|
|
|
|
toggler.state = state;
|
|
|
|
|
del.onmouseout = null;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
function() {
|
|
|
|
|
var del = $("a.delete", footer);
|
2013-10-01 12:42:00 +00:00
|
|
|
|
api.remove(comment.id).then(function(rv) {
|
|
|
|
|
if (rv) {
|
|
|
|
|
el.remove();
|
|
|
|
|
} else {
|
2013-10-03 11:48:38 +00:00
|
|
|
|
$("span.note", header).textContent = msgs["comment-deleted"];
|
|
|
|
|
text.innerHTML = "<p> </p>";
|
2014-03-20 15:04:44 +00:00
|
|
|
|
$("a.edit", footer).remove();
|
|
|
|
|
$("a.delete", footer).remove();
|
2013-10-01 12:42:00 +00:00
|
|
|
|
}
|
2013-10-29 17:46:08 +00:00
|
|
|
|
del.textContent = msgs["comment-delete"];
|
2013-10-01 12:42:00 +00:00
|
|
|
|
});
|
2013-09-09 12:13:34 +00:00
|
|
|
|
}
|
2013-10-29 17:46:08 +00:00
|
|
|
|
);
|
2013-10-04 15:28:26 +00:00
|
|
|
|
|
|
|
|
|
// remove edit and delete buttons when cookie is gone
|
|
|
|
|
var clear = function(button) {
|
2013-11-05 11:20:17 +00:00
|
|
|
|
if (! utils.cookie("isso-" + comment.id)) {
|
2013-11-16 20:42:11 +00:00
|
|
|
|
if ($(button, footer) !== null) {
|
|
|
|
|
$(button, footer).remove();
|
|
|
|
|
}
|
2013-10-04 15:28:26 +00:00
|
|
|
|
} else {
|
|
|
|
|
setTimeout(function() { clear(button); }, 15*1000);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
clear("a.edit");
|
|
|
|
|
clear("a.delete");
|
2013-10-06 17:03:32 +00:00
|
|
|
|
|
|
|
|
|
// show direct reply to own comment when cookie is max aged
|
|
|
|
|
var show = function(el) {
|
2013-11-05 11:20:17 +00:00
|
|
|
|
if (utils.cookie("isso-" + comment.id)) {
|
2013-10-06 17:03:32 +00:00
|
|
|
|
setTimeout(function() { show(el); }, 15*1000);
|
|
|
|
|
} else {
|
|
|
|
|
footer.append(el);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2013-11-16 21:15:31 +00:00
|
|
|
|
if (! config["reply-to-self"] && utils.cookie("isso-" + comment.id)) {
|
2013-10-06 17:03:32 +00:00
|
|
|
|
show($("a.reply", footer).detach());
|
|
|
|
|
}
|
2014-04-22 19:45:16 +00:00
|
|
|
|
|
|
|
|
|
if(comment.hasOwnProperty('replies')) {
|
|
|
|
|
var lastcreated = 0;
|
|
|
|
|
comment.replies.forEach(function(replyObject) {
|
|
|
|
|
insert(replyObject, false);
|
|
|
|
|
if(replyObject.created > lastcreated) {
|
|
|
|
|
lastcreated = replyObject.created;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
if(comment.hidden_replies > 0) {
|
|
|
|
|
insert_loader(comment, lastcreated);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-01 12:42:00 +00:00
|
|
|
|
};
|
2013-09-05 17:31:18 +00:00
|
|
|
|
|
|
|
|
|
return {
|
2013-10-01 12:42:00 +00:00
|
|
|
|
insert: insert,
|
2014-04-22 19:45:16 +00:00
|
|
|
|
insert_loader: insert_loader,
|
2013-10-01 12:42:00 +00:00
|
|
|
|
Postbox: Postbox
|
|
|
|
|
};
|
2013-11-01 14:25:44 +00:00
|
|
|
|
});
|