//= require jquery //= require jquery_ujs //= require_tree . "use strict"; var _Lobsters = Class.extend({ curUser: null, storyFlagReasons: { <%= Vote::STORY_REASONS.map{|k,v| "#{k.inspect}: #{v.inspect}" }.join(", ") %> }, commentDownvoteReasons: { <%= Vote::COMMENT_REASONS.map{|k,v| "#{k.inspect}: #{v.inspect}" }.join(", ") %> }, upvoteStory: function(voterEl) { Lobsters.vote("story", voterEl, 1); }, flagStory: function(voterEl) { Lobsters._showDownvoteWhyAt("story", voterEl, function(k) { Lobsters.vote("story", voterEl, -1, k); }); }, hideStory: function(hiderEl) { if (!Lobsters.curUser) return Lobsters.bounceToLogin(); var li = $(hiderEl).closest(".story, .comment"); var act; if (li.hasClass("hidden")) { act = "révéler"; li.removeClass("hidden"); hiderEl.innerHTML = "cacher"; } else { act = "cacher"; li.addClass("hidden"); hiderEl.innerHTML = "révéler"; } $.post("/stories/" + li.attr("data-shortid") + "/" + act); }, upvoteComment: function(voterEl) { Lobsters.vote("comment", voterEl, 1); }, downvoteComment: function(voterEl) { Lobsters._showDownvoteWhyAt("comment", voterEl, function(k) { Lobsters.vote("comment", voterEl, -1, k); }); }, _showDownvoteWhyAt: function(thingType, voterEl, onChooseWhy) { if (!Lobsters.curUser) return Lobsters.bounceToLogin(); var li = $(voterEl).closest(".story, .comment"); if (li.hasClass("downvoted")) { /* already upvoted, neutralize */ Lobsters.vote(thingType, voterEl, -1, null); return; } if ($("#downvote_why")) $("#downvote_why").remove(); if ($("#downvote_why_shadow")) $("#downvote_why_shadow").remove(); var sh = $("
"); $(voterEl).after(sh); sh.click(function() { $("#downvote_why_shadow").remove(); $("#downvote_why").remove(); }); var d = $("
"); var reasons; if (thingType == "comment") reasons = Lobsters.commentDownvoteReasons; else reasons = Lobsters.storyFlagReasons; $.each(reasons, function(k, v) { var a = $("" + v + ""); a.click(function() { $("#downvote_why").remove(); $("#downvote_why_shadow").remove(); if (k != "") onChooseWhy(k); return false; }); d.append(a); }); $(voterEl).after(d); d.position({ my: "left top", at: "left bottom", offset: "-2 -2", of: $(voterEl), collision: "none", }); /* XXX: why is this needed? */ if (thingType == "story") d.css("left", $(voterEl).position().left); }, 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 = 0; var showScore = true; if (scoreDiv.innerHTML == "-") showScore = false; else 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"; } if (showScore) scoreDiv.innerHTML = score; if (action == "upvote" || action == "unvote") { li.find(".reason").html(""); if (action == "unvote" && thingType == "story" && point < 0) li.find(".flagger").text("flag"); } else if (action == "downvote" && thingType == "comment") li.find(".reason").html("| " + Lobsters.commentDownvoteReasons[reason].toLowerCase()); else if (action == "downvote" && thingType == "story") li.find(".flagger").text("unflag"); $.post("/" + (thingType == "story" ? "stories" : thingType + "s") + "/" + li.attr("data-shortid") + "/" + action, { reason: reason }); }, postComment: function(form) { $.post($(form).attr("action"), $(form).serializeArray(), function(data) { if ($(form).find('#parent_comment_short_id').length) { $(form).closest('.comment').replaceWith($.parseHTML(data)); } else { $(form).parent(".comment").replaceWith($.parseHTML(data)); } }); }, previewComment: function(form) { var params = $(form).serializeArray(); params.push({"name": "preview", "value": "true"}); $.post($(form).attr("action"), params, function(data) { var da = $.parseHTML(data); var ta = $(da).find("textarea"); $(form).closest(".comment").replaceWith(da); autosize(ta); }); }, previewStory: function(form) { $("#inside").load("/stories/preview", $(form).serializeArray(), function() { Lobsters.runSelect2(); }); }, runSelect2: function() { $("#story_tags_a").select2({ formatSelection: function(what) { return what.id; }, matcher: function(term, text) { return text.toUpperCase().indexOf(term.toUpperCase()) >= 0; }, sortResults: function(results, container, query) { if (query.term) { var tmatches = []; var dmatches = []; /* prefer tag matches first, then description matches */ for (var x in results) { var r = results[x]; if (r.id.toUpperCase().indexOf(query.term.toUpperCase()) == 0) tmatches.push(r); else dmatches.push(r); } tmatches = tmatches.sort(function(a, b) { return a.text.localeCompare(b.text); }); dmatches = dmatches.sort(function(a, b) { return a.text.localeCompare(b.text); }); return tmatches.concat(dmatches); } return results; } }); }, moderateStory: function(link) { var reason = prompt("Raison de la modération :"); 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 = $("
"), metadata_input = ""; if (csrf_param !== undefined && csrf_token !== undefined) metadata_input += ""; if (target) form.attr("target", target); var r = $(""); 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_attributes", { fetch_url: url_field.val(), }) .success(function(data) { if (data) { if (data.title) title_field.val(data.title.substr(0, title_field.maxLength)); if (data.url) url_field.val(data.url); } 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.flagger").click(function() { Lobsters.flagStory(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); }), $(".toggle_dragons").click(function(a) { var c = $(".dragon_threads").first(); if (c) { if (c.hasClass("hidden")) c.removeClass("hidden"); else c.addClass("hidden"); } }), $(document).on("click", "a.comment_replier", function() { if (!Lobsters.curUser) { Lobsters.bounceToLogin(); return false; } var comment = $(this).closest(".comment"); if ($("#reply_form_" + comment.attr("id")).length > 0) return false; var sel = ""; if (window.getSelection) sel = window.getSelection().toString(); else if (document.selection && document.selection.type != "Control") sel = document.selection.createRange().text; if (sel != "") { var t = ""; $.each(sel.split("\n"), function(k, v) { t += (t == "" ? "" : "\n") + "> " + v; }); sel = t; if (sel != "") sel += "\n\n"; } var replies = comment.nextAll(".comments").first(); $.get("/comments/" + comment.attr("data-shortid") + "/reply", function(data) { var reply = $($.parseHTML(data)); reply.attr("id", "reply_form_" + comment.attr("id")); replies.prepend(reply); var ta = reply.find("textarea"); ta.focus().text(sel); autosize(ta); }); return false; }); $(document).on("click", "button.comment-cancel", function() { var comment = $(this).closest(".comment"); var comment_id = comment.attr("data-shortid"); if (comment_id != null && comment_id !== '') { $.get("/comments/" + comment_id, function(data) { comment.replaceWith($.parseHTML(data)); }); } else { 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("Êtes-vous sûr de vouloir supprimer ce commentaires ?")) { 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("Êtes-vous sûr de vouloir restaurer ce commentaire ?")) { var li = $(this).closest(".comment"); $.post("/comments/" + $(li).attr("data-shortid") + "/undelete", function(d) { $(li).replaceWith(d); }); } }); $(document).on("click", "a.comment_dragon", function() { if (confirm("Êtes-vous sûr de vouloir marquer ce fil de discussion ?")) { var li = $(this).closest(".comment"); $.post("/comments/" + $(li).attr("data-shortid") + "/dragon", function(d) { window.location.reload(); }); } }); $(document).on("click", "a.comment_undragon", function() { if (confirm("Êtes-vous sûr de vouloir supprimer la marque de ce fil de discussion ?")) { var li = $(this).closest(".comment"); $.post("/comments/" + $(li).attr("data-shortid") + "/undragon", function(d) { window.location.reload(); }); } }); $(document).on("click", "a.comment_moderator", function() { var reason = prompt("Raison de la modération :"); if (reason == null || reason == "") return false; var li = $(this).closest(".comment"); $.post("/comments/" + $(li).attr("data-shortid") + "/delete", { reason: reason }, function(d) { $(li).replaceWith(d); }); }); Lobsters.runSelect2(); $(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() { var url_tags = { "\.pdf$": "pdf", "[\/\.]((youtube|vimeo)\.com|youtu\.be|twitch.tv)\/": "video", "[\/\.](slideshare\.net|speakerdeck\.com)\/": "slides", "[\/\.](soundcloud\.com)\/": "audio", }; for (var u in url_tags) { var tag = url_tags[u]; if ($("#story_url").val().match(new RegExp(u, "i"))) { var ta = $("#story_tags_a").data("select2"); if (ta.getVal().indexOf(tag) < 0) ta.addSelectedChoice({ id: tag }); } } }); $(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; }); $('textarea#comment').keydown(function (e) { if ((e.metaKey || e.ctrlKey) && e.keyCode == 13) { $("button.comment-post").click(); } }); });