Files
danbooru/app/javascript/src/javascripts/posts.js.erb
evazion afa4a2c985 js: fixup issues with @rails/ujs.
Fix a couple regressions caused by the migration from jquery-ujs to
@rails/ujs in 9f4ac4c96:

* Add authenticity tokens to all remote forms. By default, Rails doesn't
  doesn't include authenticity tokens in remote forms because it can cause
  problems with fragment caching. This was fine with jquery-ujs because it
  would insert the authenticity token when the remote form was
  submitted, but apparently @rails/ujs doesn't do this. This broke
  certain remote forms nested inside of jquery UI dialogs.

* Fix dialogs to trigger remote form submissions through @rails/ujs
  instead of through jquery. This fixes a problem where remote forms that
  returned a javascript response displayed the response as plaintext
  instead of executing the returned javascript.
2020-01-10 19:16:27 -06:00

632 lines
19 KiB
Plaintext

import CurrentUser from './current_user'
import Utility from './utility'
import Hammer from 'hammerjs'
import Cookie from './cookie'
import Note from './notes'
import Rails from '@rails/ujs'
let Post = {};
Post.pending_update_count = 0;
Post.SWIPE_THRESHOLD = 60;
Post.SWIPE_VELOCITY = 0.6;
Post.MAX_RECOMMENDATIONS = 45; // 3 rows of 9 posts at 1920x1080.
Post.LOW_TAG_COUNT = 10;
Post.HIGH_TAG_COUNT = 20;
Post.initialize_all = function() {
if ($("#c-posts").length) {
this.initialize_shortcuts();
this.initialize_saved_searches();
}
if ($("#c-posts").length && $("#a-index").length) {
this.initialize_excerpt();
this.initialize_gestures();
}
if ($("#c-posts").length && $("#a-show").length) {
this.initialize_links();
this.initialize_post_relationship_previews();
this.initialize_favlist();
this.initialize_post_sections();
this.initialize_post_image_resize_links();
this.initialize_post_image_resize_to_window_link();
this.initialize_recommended();
if (CurrentUser.data("always-resize-images") || (Utility.meta("viewport") && (window.screen.width <= 660))) {
$("#image-resize-to-window-link").click();
}
}
if ($("#c-posts #a-show, #c-uploads #a-new").length) {
this.initialize_edit_dialog();
}
var $fields_multiple = $('[data-autocomplete="tag-edit"]');
$fields_multiple.on("keypress.danbooru", Post.update_tag_count);
$fields_multiple.on("click", Post.update_tag_count);
$(window).on('danbooru:initialize_saved_seraches', () => {
Post.initialize_saved_searches();
});
}
Post.initialize_gestures = function() {
if (CurrentUser.data("disable-mobile-gestures")) {
return;
}
var $body = $("body");
if ($body.data("hammer")) {
return;
}
if (!Utility.test_max_width(660)) {
return;
}
$("#image-container").css({overflow: "visible"});
var hasPrev = $(".paginator a[rel~=prev]").length;
var hasNext = $(".paginator a[rel~=next]").length;
var hammer = new Hammer($body[0], {touchAction: 'pan-y', recognizers: [[Hammer.Swipe, { threshold: Post.SWIPE_THRESHOLD, velocity: Post.SWIPE_VELOCITY, direction: Hammer.DIRECTION_HORIZONTAL }]], inputClass: Hammer.TouchInput});
$body.data("hammer", hammer);
if (hasPrev) {
hammer.on("swiperight", async function(e) {
$("body").css({"transition-timing-function": "ease", "transition-duration": "0.2s", "opacity": "0", "transform": "translateX(150%)"});
await Utility.delay(200);
Post.swipe_prev(e);
});
}
if (hasNext) {
hammer.on("swipeleft", async function(e) {
$("body").css({"transition-timing-function": "ease", "transition-duration": "0.2s", "opacity": "0", "transform": "translateX(-150%)"});
await Utility.delay(200);
Post.swipe_next(e);
});
}
}
Post.initialize_edit_dialog = function() {
$("#open-edit-dialog").show().on("click.danbooru", function(e) {
Post.open_edit_dialog();
e.preventDefault();
});
}
Post.open_edit_dialog = function() {
if ($("#edit-dialog").length === 1) {
return;
}
$(document).trigger("danbooru:open-post-edit-dialog");
$("#edit").show();
$("#comments").hide();
$("#post-sections li").removeClass("active");
$("#post-edit-link").parent("li").addClass("active");
var $tag_string = $("#post_tag_string,#upload_tag_string");
$("div.input").has($tag_string).prevAll().hide();
$("#open-edit-dialog").hide();
var dialog = $("<div/>").attr("id", "edit-dialog");
$("#form").appendTo(dialog);
dialog.dialog({
title: "Edit tags",
width: $(window).width() * 0.6,
position: {
my: "right",
at: "right-20",
of: window
},
drag: function(e, ui) {
if (CurrentUser.data("enable-auto-complete")) {
$tag_string.data("uiAutocomplete").close();
}
},
close: Post.close_edit_dialog
});
dialog.dialog("widget").draggable("option", "containment", "none");
var pin_button = $("<button/>").button({icons: {primary: "ui-icon-pin-w"}, label: "pin", text: false});
pin_button.css({width: "20px", height: "20px", position: "absolute", right: "28.4px"});
dialog.parent().children(".ui-dialog-titlebar").append(pin_button);
pin_button.on("click.danbooru", function(e) {
var dialog_widget = $('.ui-dialog:has(#edit-dialog)');
var pos = dialog_widget.offset();
if (dialog_widget.css("position") === "absolute") {
pos.left -= $(window).scrollLeft();
pos.top -= $(window).scrollTop();
dialog_widget.offset(pos).css({ position: "fixed" });
dialog.dialog("option", "resize", function() { dialog_widget.css({ position: "fixed" }); });
pin_button.button("option", "icons", {primary: "ui-icon-pin-s"});
} else {
pos.left += $(window).scrollLeft();
pos.top += $(window).scrollTop();
dialog_widget.offset(pos).css({ position: "absolute" });
dialog.dialog("option", "resize", function() { /* do nothing */ });
pin_button.button("option", "icons", {primary: "ui-icon-pin-w"});
}
});
dialog.parent().mouseout(function(e) {
dialog.parent().css({"opacity": 0.6, "transition": "opacity .4s ease"});
}).mouseover(function(e) {
dialog.parent().css({"opacity": 1, "transition": "opacity .2s ease"});
});
$tag_string.css({"resize": "none", "width": "100%"});
$tag_string.focus().selectEnd().height($tag_string[0].scrollHeight);
}
Post.close_edit_dialog = function(e, ui) {
$("#form").appendTo($("#c-posts #edit,#c-uploads #a-new"));
$("#edit-dialog").remove();
var $tag_string = $("#post_tag_string,#upload_tag_string");
$("div.input").has($tag_string).prevAll().show();
$("#open-edit-dialog").show();
$tag_string.css({"resize": "", "width": ""});
$(document).trigger("danbooru:close-post-edit-dialog");
}
Post.swipe_prev = function(e) {
if ($(".paginator a[rel~=prev]").length) {
location.href = $("a[rel~=prev]").attr("href");
}
e.preventDefault();
}
Post.nav_prev = function(e) {
var href = "";
if ($("#search-seq-nav").length) {
href = $("#search-seq-nav a[rel~=prev]").attr("href");
if (href) {
location.href = href;
}
} else if ($(".paginator a[rel~=prev]").length) {
location.href = $("a[rel~=prev]").attr("href");
} else {
href = $("#pool-nav li.pool-selected-true a[rel~=prev], #favgroup-nav a.active[rel~=prev]").attr("href");
if (href) {
location.href = href;
}
}
e.preventDefault();
}
Post.nav_next = function(e) {
var href = "";
if ($("#search-seq-nav").length) {
href = $("#search-seq-nav a[rel~=next]").attr("href");
location.href = href;
} else if ($(".paginator a[rel~=next]").length) {
location.href = $(".paginator a[rel~=next]").attr("href");
} else {
href = $("#pool-nav li.pool-selected-true a[rel~=next], #favgroup-nav a.active[rel~=next]").attr("href");
if (href) {
location.href = href;
}
}
e.preventDefault();
}
Post.swipe_next = function(e) {
if ($(".paginator a[rel~=next ]").length) {
location.href = $(".paginator a[rel~=next]").attr("href");
}
e.preventDefault();
}
Post.initialize_shortcuts = function() {
if ($("#a-show").length) {
Utility.keydown("a", "prev_page", Post.nav_prev);
Utility.keydown("d", "next_page", Post.nav_next);
}
}
Post.initialize_links = function() {
$("#copy-notes").on("click.danbooru", function(e) {
var current_post_id = $("meta[name=post-id]").attr("content");
var other_post_id = parseInt(prompt("Enter the ID of the post to copy all notes to:"), 10);
if (other_post_id !== null) {
$.ajax("/posts/" + current_post_id + "/copy_notes", {
type: "PUT",
data: {
other_post_id: other_post_id
},
success: function(data) {
Utility.notice("Successfully copied notes to <a href='" + other_post_id + "'>post #" + other_post_id + "</a>");
},
error: function(data) {
if (data.status === 404) {
Utility.error("Error: Invalid destination post");
} else if (data.responseJSON && data.responseJSON.reason) {
Utility.error("Error: " + data.responseJSON.reason);
} else {
Utility.error("There was an error copying notes to <a href='" + other_post_id + "'>post #" + other_post_id + "</a>");
}
}
});
}
e.preventDefault();
});
}
Post.initialize_post_relationship_previews = function() {
var current_post_id = $("meta[name=post-id]").attr("content");
$("[id=post_" + current_post_id + "]").addClass("current-post");
if (Cookie.get("show-relationship-previews") === "0") {
this.toggle_relationship_preview($("#has-children-relationship-preview"), $("#has-children-relationship-preview-link"));
this.toggle_relationship_preview($("#has-parent-relationship-preview"), $("#has-parent-relationship-preview-link"));
}
$("#has-children-relationship-preview-link").on("click.danbooru", function(e) {
Post.toggle_relationship_preview($("#has-children-relationship-preview"), $(this));
e.preventDefault();
});
$("#has-parent-relationship-preview-link").on("click.danbooru", function(e) {
Post.toggle_relationship_preview($("#has-parent-relationship-preview"), $(this));
e.preventDefault();
});
}
Post.toggle_relationship_preview = function(preview, preview_link) {
preview.toggle();
if (preview.is(":visible")) {
preview_link.html("&laquo; hide");
Cookie.put("show-relationship-previews", "1");
} else {
preview_link.html("show &raquo;");
Cookie.put("show-relationship-previews", "0");
}
}
Post.initialize_favlist = function() {
$("#show-favlist-link, #hide-favlist-link").on("click.danbooru", function(e) {
$("#favlist, #show-favlist-link, #hide-favlist-link").toggle();
e.preventDefault();
});
}
Post.expand_image = function(e) {
if (Utility.test_max_width(660)) {
// just do the default behavior
return;
}
var $link = $(e.target);
var $image = $("#image");
var $notice = $("#image-resize-notice");
$image.attr("src", $link.attr("href"));
$image.css("filter", "blur(8px)");
$image.width($image.data("original-width"));
$image.height($image.data("original-height"));
$image.on("load.danbooru", function() {
$image.css("animation", "sharpen 0.5s forwards");
$notice.hide();
});
$notice.children().eq(0).hide();
$notice.children().eq(1).show(); // Loading message
Note.Box.scale_all();
$image.data("scale-factor", 1);
e.preventDefault();
}
Post.initialize_post_image_resize_links = function() {
$("#image-resize-link").on("click.danbooru", Post.expand_image);
if ($("#image-resize-notice").length) {
Utility.keydown("v", "resize", function(e) {
if ($("#image-resize-notice").is(":visible")) {
$("#image-resize-link").click();
} else {
var $image = $("#image");
var $notice = $("#image-resize-notice");
$image.attr("src", $("#image-container").data("large-file-url"));
$image.css("filter", "blur(8px)");
$image.width($image.data("large-width"));
$image.height($image.data("large-height"));
$notice.children().eq(0).show();
$notice.children().eq(1).hide(); // Loading message
$image.on("load.danbooru", function() {
$image.css("animation", "sharpen 0.5s forwards");
$notice.show();
});
Note.Box.scale_all();
$image.data("scale-factor", 1);
e.preventDefault();
}
});
}
}
Post.resize_image_to_window = function($img) {
var sidebar_width = 0;
var client_width = 0;
if (($img.data("scale-factor") === 1) || ($img.data("scale-factor") === undefined)) {
if ($(window).width() > 660) {
sidebar_width = $("#sidebar").width() || 0;
client_width = $(window).width() - sidebar_width - 75;
} else {
client_width = $(window).width() - 2;
}
if ($img.width() > client_width) {
var isVideo = $img.prop("tagName") === "VIDEO";
var width = isVideo ? $img.prop("width") : $img.data("original-width");
var height = isVideo ? $img.prop("height") : $img.data("original-height");
var ratio = client_width / width;
$img.data("scale-factor", ratio);
$img.css("width", width * ratio);
$img.css("height", height * ratio);
Post.resize_ugoira_controls();
}
} else {
$img.data("scale-factor", 1);
$img.width($img.data("original-width"));
$img.height($img.data("original-height"));
Post.resize_ugoira_controls();
}
Note.Box.scale_all();
}
Post.initialize_post_image_resize_to_window_link = function() {
$("#image-resize-to-window-link").on("click.danbooru", function(e) {
Post.resize_image_to_window($("#image"));
e.preventDefault();
});
}
Post.initialize_excerpt = function() {
$("#excerpt").hide();
$("#show-posts-link").on("click.danbooru", function(e) {
$("#show-posts-link").parent("li").addClass("active");
$("#show-excerpt-link").parent("li").removeClass("active");
$("#posts").show();
$("#excerpt").hide();
e.preventDefault();
});
$("#show-excerpt-link").on("click.danbooru", function(e) {
if ($(this).parent("li").hasClass("active")) {
return;
}
$("#show-posts-link").parent("li").removeClass("active");
$("#show-excerpt-link").parent("li").addClass("active");
$("#posts").hide();
$("#excerpt").show();
e.preventDefault();
});
if (!$(".post-preview").length && /Nobody here but us chickens/.test($("#posts").html())) {
$("#show-excerpt-link").click();
}
}
Post.initialize_post_sections = function() {
$("#post-sections li a,#side-edit-link").on("click.danbooru", function(e) {
if (e.target.hash === "#comments") {
$("#comments").show();
$("#edit").hide();
$("#recommended").hide();
} else if (e.target.hash === "#edit") {
$("#edit").show();
$("#comments").hide();
$("#post_tag_string").focus().selectEnd().height($("#post_tag_string")[0].scrollHeight);
$("#recommended").hide();
$(document).trigger("danbooru:open-post-edit-tab");
Post.update_tag_count({target: $("#post_tag_string")});
} else if (e.target.hash === "#recommended") {
$("#comments").hide();
$("#edit").hide();
$("#recommended").show();
$.get("/recommended_posts.js", { search: { post_id: Utility.meta("post-id") }, limit: Post.MAX_RECOMMENDATIONS });
} else {
$("#edit").hide();
$("#comments").hide();
$("#recommended").hide();
}
$("#post-sections li").removeClass("active");
$(e.target).parent("li").addClass("active");
e.preventDefault();
});
}
Post.resize_ugoira_controls = function() {
var $img = $("#image");
var width = Math.max($img.width(), 350);
$("#ugoira-control-panel").css("width", width);
$("#seek-slider").css("width", width - 81);
}
Post.notice_update = function(x) {
if (x === "inc") {
Post.pending_update_count += 1;
Utility.notice("Updating posts (" + Post.pending_update_count + " pending)...", true);
} else {
Post.pending_update_count -= 1;
if (Post.pending_update_count < 1) {
Utility.notice("Posts updated");
} else {
Utility.notice("Updating posts (" + Post.pending_update_count + " pending)...", true);
}
}
}
Post.update_data = function(data) {
var $post = $("#post_" + data.id);
$post.attr("data-tags", data.tag_string);
$post.data("rating", data.rating);
$post.removeClass("post-status-has-parent post-status-has-children");
if (data.parent_id) {
$post.addClass("post-status-has-parent");
}
if (data.has_visible_children) {
$post.addClass("post-status-has-children");
}
}
Post.vote = function(score, id) {
Utility.notice("Voting...");
$.post("/posts/" + id + "/votes.js", {
score: score
});
}
Post.tag = function(post_id, tags) {
const tag_string = (Array.isArray(tags) ? tags.join(" ") : String(tags));
Post.update(post_id, { "post[old_tag_string]": "", "post[tag_string]": tag_string });
}
Post.update = function(post_id, params) {
Post.notice_update("inc");
$.ajax({
type: "PUT",
url: "/posts/" + post_id + ".json",
data: params,
success: function(data) {
Post.notice_update("dec");
Post.update_data(data);
},
error: function(data) {
Post.notice_update("dec");
Utility.error(`There was an error updating <a href="/posts/${post_id}">post #${post_id}</a>`);
}
});
}
Post.ban = function(post_id) {
$.ajax({
type: "POST",
url: "/moderator/post/posts/" + post_id + "/ban.js",
data: {
commit: "Ban"
},
success: function(data) {
$("#post_" + post_id).remove();
},
error: function(data) {
Utility.error(`There was an error updating <a href="/posts/${post_id}">post #${post_id}</a>`);
}
});
}
Post.approve = function(post_id) {
$.post(
"/moderator/post/approval.json",
{"post_id": post_id}
).fail(function(data) {
var message = $.map(data.responseJSON.errors, function(msg, attr) { return msg; }).join("; ");
Utility.error("Error: " + message);
}).done(function(data) {
var $post = $("#post_" + post_id);
if ($post.length) {
$post.data("flags", $post.data("flags").replace(/pending/, ""));
$post.removeClass("post-status-pending");
Utility.notice("Approved post #" + post_id);
}
});
}
Post.initialize_saved_searches = function() {
$("#save-search-dialog").dialog({
width: 700,
modal: true,
autoOpen: false,
buttons: {
"Submit": function() {
let form = $("#save-search-dialog form").get(0);
Rails.fire(form, "submit");
$(this).dialog("close");
},
"Cancel": function() {
$(this).dialog("close");
}
}
});
$("#save-search").on("click.danbooru", function(e) {
$("#save-search-dialog #saved_search_query").val($("#tags").val());
if (CurrentUser.data("disable-categorized-saved-searches") === false) {
$("#save-search-dialog").dialog("open");
} else {
$.post(
"/saved_searches.js",
{
"saved_search": {
"query": $("#tags").val()
}
}
);
}
e.preventDefault();
});
}
Post.initialize_recommended = function() {
$(document).on("click.danbooru", ".post-preview .more-recommended-posts", async function (event) {
event.preventDefault();
let post_id = $(this).parents(".post-preview").data("id");
$("#recommended").addClass("loading-recommended-posts");
await $.get("/recommended_posts.js", { search: { post_id: post_id }, limit: Post.MAX_RECOMMENDATIONS });
$("#recommended").removeClass("loading-recommended-posts");
});
};
Post.update_tag_count = function(event) {
let string = "0 tags";
let count = 0;
if (event) {
let tags = [...new Set($(event.target).val().match(/\S+/g))];
if (tags) {
count = tags.length;
string = (count === 1) ? (count + " tag") : (count + " tags")
}
}
$("#tags-container .count").html(string);
let klass = "";
if (count < Post.LOW_TAG_COUNT) {
klass = "frown";
} else if (count >= Post.LOW_TAG_COUNT && count < Post.HIGH_TAG_COUNT) {
klass = "meh";
} else {
klass = "smile";
}
$("#tags-container .options #face").removeClass().addClass(`far fa-${klass}`);
}
$(document).ready(function() {
Post.initialize_all();
});
export default Post