journalduhacker/app/assets/javascripts/application.js.erb
joshua stein 9535b05490 remove story downvoting, add story hiding
stories should either be reported for spam (coming later), upvoted,
or left alone rather than being downvoted for being uninteresting.
since users don't like leaving uninteresting things alone, they can
now hide stories from their view without affecting the story's
score.

hiding is implemented as a Vote with its vote set to 0 and the
reason set to "H"

add a /hidden url which shows all of a user's hidden stories

while i'm here, simplify Vote guts and add some tests to make sure
all the flip-flopping stuff works right
2014-03-03 17:20:21 -06:00

363 lines
10 KiB
Plaintext

//= require jquery
//= require jquery_ujs
//= require_tree .
"use strict";
var _Lobsters = Class.extend({
curUser: null,
commentDownvoteReasons: { <%= Vote::COMMENT_REASONS.map{|k,v|
"#{k.inspect}: #{v.inspect}" }.join(", ") %> },
upvoteStory: function(voterEl) {
Lobsters.vote("story", voterEl, 1);
},
hideStory: function(hiderEl) {
if (!Lobsters.curUser)
return Lobsters.bounceToLogin();
var li = $(hiderEl).closest(".story, .comment");
var act;
if (li.hasClass("hidden")) {
act = "unhide";
li.removeClass("hidden");
hiderEl.innerHTML = "hide";
} else {
act = "hide";
li.addClass("hidden");
hiderEl.innerHTML = "unhide";
}
$.post("/stories/" + li.attr("data-shortid") + "/" + act);
},
upvoteComment: function(voterEl) {
Lobsters.vote("comment", voterEl, 1);
},
downvoteComment: function(voterEl) {
var li = $(voterEl).closest(".story, .comment");
if (li.hasClass("downvoted")) {
/* already upvoted, neutralize */
Lobsters.vote("comment", voterEl, -1, null);
return;
}
if ($("#downvote_why"))
$("#downvote_why").remove();
if ($("#downvote_why_shadow"))
$("#downvote_why_shadow").remove();
var sh = $("<div id=\"downvote_why_shadow\"></div>");
$(voterEl).after(sh);
sh.click(function() {
$("#downvote_why_shadow").remove();
$("#downvote_why").remove();
});
var d = $("<div id=\"downvote_why\"></div>");
$.each(Lobsters.commentDownvoteReasons, function(k, v) {
var a = $("<a href=\"#\"" + (k == "" ? " class=\"cancelreason\"" : "") +
">" + v + "</a>");
a.click(function() {
$("#downvote_why").remove();
$("#downvote_why_shadow").remove();
if (k != "")
Lobsters.vote("comment", voterEl, -1, k);
return false;
});
d.append(a);
});
$(voterEl).after(d);
d.position({
my: "left top",
at: "left bottom",
offset: "-2 -2",
of: $(voterEl),
collision: "none",
});
},
vote: function(thingType, voterEl, point, reason) {
if (!Lobsters.curUser)
return Lobsters.bounceToLogin();
var li = $(voterEl).closest(".story, .comment");
var scoreDiv = li.find("div.score").get(0);
var score = parseInt(scoreDiv.innerHTML);
var action = "";
if (li.hasClass("upvoted") && point > 0) {
/* already upvoted, neutralize */
li.removeClass("upvoted");
score--;
action = "unvote";
}
else if (li.hasClass("downvoted") && point < 0) {
/* already downvoted, neutralize */
li.removeClass("downvoted");
score++;
action = "unvote";
}
else if (point > 0) {
if (li.hasClass("downvoted"))
/* flip flop */
score++;
li.removeClass("downvoted").addClass("upvoted");
score++;
action = "upvote";
}
else if (point < 0) {
if (li.hasClass("upvoted"))
/* flip flop */
score--;
li.removeClass("upvoted").addClass("downvoted");
score--;
action = "downvote";
}
scoreDiv.innerHTML = score;
if (action == "upvote" || action == "unvote")
li.find(".reason").html("");
else if (action == "downvote" && thingType == "comment")
li.find(".reason").html("(" +
Lobsters.commentDownvoteReasons[reason].toLowerCase() + ")");
$.post("/" + (thingType == "story" ? "stories" : thingType + "s") + "/" +
li.attr("data-shortid") + "/" +
action, { reason: reason });
},
postComment: function(form) {
$.post($(form).attr("action"), $(form).serializeArray(), function(data) {
$(form).closest('.comment').replaceWith($.parseHTML(data));
});
},
previewComment: function(form) {
var params = $(form).serializeArray();
params.push({"name": "preview", "value": "true"});
$.post($(form).attr("action"), params, function(data) {
$(form).closest('.comment').replaceWith($.parseHTML(data));
});
},
previewStory: function(form) {
$("#inside").load("/stories/preview", $(form).serializeArray());
},
moderateStory: function(link) {
var reason = prompt("Moderation reason:");
if (reason == null || reason == "")
return false;
var link = $(link);
/* $.rails.handleMethod() */
var href = $.rails.href(link),
method = link.data('method'),
target = link.attr('target'),
csrf_token = $("meta[name=csrf-token]").attr("content"),
csrf_param = $("meta[name=csrf-param]").attr("content"),
form = $("<form method=\"post\" action=\"" + href + "\"></form>"),
metadata_input = "<input name=\"_method\" value=\"" + method +
"\" type=\"hidden\" />";
if (csrf_param !== undefined && csrf_token !== undefined)
metadata_input += "<input name=\"" + csrf_param + "\" value=\"" +
csrf_token + "\" type=\"hidden\" />";
if (target)
form.attr("target", target);
var r = $("<input type=\"hidden\" name=\"reason\" />");
r.val(reason);
form.append(r);
form.hide().append(metadata_input).appendTo('body');
form.submit();
return false;
},
fetchURLTitle: function(button, url_field, title_field) {
if (url_field.val() == "")
return;
var old_value = button.val();
button.prop("disabled", true);
button.val("Fetching...");
$.post("/stories/fetch_url_title", {
fetch_url: url_field.val(),
})
.success(function(data) {
if (data && data.title)
title_field.val(data.title.substr(0, title_field.maxLength));
button.val(old_value);
button.prop("disabled", false);
})
.error(function() {
button.val(old_value);
button.prop("disabled", false);
});
},
bounceToLogin: function() {
document.location = "/login?return=" +
encodeURIComponent(document.location);
return false;
},
});
var Lobsters = new _Lobsters();
$(document).ready(function() {
$(".comment a.downvoter").click(function() {
Lobsters.downvoteComment(this);
return false;
});
$(".comment a.upvoter").click(function() {
Lobsters.upvoteComment(this);
return false;
});
$("li.story a.upvoter").click(function() {
Lobsters.upvoteStory(this);
return false;
});
$("li.story a.hider").click(function() {
Lobsters.hideStory(this);
return false;
});
$("li.story a.mod_story_link").click(function() {
return Lobsters.moderateStory(this);
}),
$(document).on("click", "a.comment_replier", function() {
if (!Lobsters.curUser) {
Lobsters.bounceToLogin();
return false;
}
var comment = $(this).closest(".comment");
var replies = comment.nextAll(".comments").first();
$.get("/comments/" + comment.attr("data-shortid") + "/reply",
function(data) {
var reply = $($.parseHTML(data));
replies.prepend(reply);
reply.find("textarea").focus();
});
return false;
});
$(document).on("click", "button.comment-cancel", function() {
$(this).closest(".comment").remove();
});
$(document).on("click", "a.comment_editor", function() {
var comment = $(this).closest(".comment");
$.get("/comments/" + comment.attr("data-shortid") + "/edit",
function(data) {
comment.replaceWith($.parseHTML(data));
});
});
$(document).on("click", "a.comment_deletor", function() {
if (confirm("Are you sure you want to delete this comment?")) {
var li = $(this).closest(".comment");
$.post("/comments/" + $(li).attr("data-shortid") + "/delete",
function(d) {
$(li).replaceWith(d);
});
}
});
$(document).on("click", "a.comment_undeletor", function() {
if (confirm("Are you sure you want to undelete this comment?")) {
var li = $(this).closest(".comment");
$.post("/comments/" + $(li).attr("data-shortid") + "/undelete",
function(d) {
$(li).replaceWith(d);
});
}
});
$("#story_tags_a").select2({
formatSelection: function(what) {
return what.id;
},
matcher: function(term, text) {
return text.toUpperCase().indexOf(term.toUpperCase()) == 0;
}
});
$(document).on("click", "div.markdown_help_toggler .markdown_help_label",
function() {
$(this).parents("div.markdown_help_toggler").first().
children(".markdown_help").toggle();
});
$(document).on("click", "button.comment-post", function() {
Lobsters.postComment($(this).parents("form").first());
});
$(document).on("click", "button.comment-preview", function() {
Lobsters.previewComment($(this).parents("form").first());
});
$(document).on("click", "button.story-preview", function() {
Lobsters.previewStory($(this).parents("form").first());
});
$(document).on("blur", "#story_url", function() {
/* if the url looks like a pdf, assign the pdf tag */
if ($("#story_url").val().match(/\.pdf$/i)) {
var ta = $("#story_tags_a").data("select2");
if (ta.getVal().indexOf("pdf") < 0)
ta.addSelectedChoice({ id: "pdf" });
}
/* if the url looks like a video site url, assign the video tag */
else if ($("#story_url").val().match(/[\/\.]((youtube|vimeo)\.com|youtu\.be)\//i)) {
var ta = $("#story_tags_a").data("select2");
if (ta.getVal().indexOf("video") < 0)
ta.addSelectedChoice({ id: "video" });
}
/* if the url looks like a slide sharing site url, assign the slides tag */
else if ($("#story_url").val().match(/[\/\.](slideshare\.net)\//i)) {
var ta = $("#story_tags_a").data("select2");
if (ta.getVal().indexOf("slides") < 0)
ta.addSelectedChoice({ id: "slides" });
}
});
$(document).on("blur", "#story_title", function() {
var m;
if (m = $("#story_title").val().match(/^(show|ask) lobste\.?rs:? (.+)$/i)) {
var ta = $("#story_tags_a").data("select2");
if (ta.getVal().indexOf(m[1].toLowerCase()) < 0)
ta.addSelectedChoice({ id: m[1].toLowerCase() });
$("#story_title").val(m[2]);
}
});
$(document).on("click", "#story_guidelines_toggler", function() {
$("#story_guidelines").toggle();
return false;
});
});