js: reorganize Javascript file structure.
Move Javascript files from app/components/**/*.js back to app/javascript/src/javascripts/*.js. This way Javascript files are in one place, which simplifies import paths and makes it easier to see all Javascript at once.
This commit is contained in:
@@ -29,26 +29,25 @@ require("@fortawesome/fontawesome-free/css/regular.css");
|
||||
|
||||
importAll(require.context('../src/javascripts', true, /\.js(\.erb)?$/));
|
||||
importAll(require.context('../src/styles', true, /\.s?css(?:\.erb)?$/));
|
||||
importAll(require.context('../../components', true, /\.js(\.erb)?$/));
|
||||
importAll(require.context('../../components', true, /\.s?css(?:\.erb)?$/));
|
||||
|
||||
import Autocomplete from "../src/javascripts/autocomplete.js";
|
||||
import Blacklist from "../src/javascripts/blacklists.js";
|
||||
import CommentComponent from "../../components/comment_component/comment_component.js";
|
||||
import CommentVotesTooltipComponent from "../../components/comment_votes_tooltip_component/comment_votes_tooltip_component.js";
|
||||
import CommentComponent from "../src/javascripts/comment_component.js";
|
||||
import CommentVotesTooltipComponent from "../src/javascripts/comment_votes_tooltip_component.js";
|
||||
import CurrentUser from "../src/javascripts/current_user.js";
|
||||
import Dtext from "../src/javascripts/dtext.js";
|
||||
import FavoritesTooltipComponent from "../../components/favorites_tooltip_component/favorites_tooltip_component.js";
|
||||
import FileUploadComponent from "../../components/file_upload_component/file_upload_component.js";
|
||||
import ForumPostComponent from "../../components/forum_post_component/forum_post_component.js";
|
||||
import FavoritesTooltipComponent from "../src/javascripts/favorites_tooltip_component.js";
|
||||
import FileUploadComponent from "../src/javascripts/file_upload_component.js";
|
||||
import ForumPostComponent from "../src/javascripts/forum_post_component.js";
|
||||
import IqdbQuery from "../src/javascripts/iqdb_queries.js";
|
||||
import Note from "../src/javascripts/notes.js";
|
||||
import MediaAssetComponent from "../../components/media_asset_component/media_asset_component.js";
|
||||
import PopupMenuComponent from "../../components/popup_menu_component/popup_menu_component.js";
|
||||
import MediaAssetComponent from "../src/javascripts/media_asset_component.js";
|
||||
import PopupMenuComponent from "../src/javascripts/popup_menu_component.js";
|
||||
import Post from "../src/javascripts/posts.js";
|
||||
import PostModeMenu from "../src/javascripts/post_mode_menu.js";
|
||||
import PostTooltip from "../src/javascripts/post_tooltips.js";
|
||||
import PostVotesTooltipComponent from "../../components/post_votes_tooltip_component/post_votes_tooltip_component.js";
|
||||
import PostVotesTooltipComponent from "../src/javascripts/post_votes_tooltip_component.js";
|
||||
import RelatedTag from "../src/javascripts/related_tag.js";
|
||||
import Shortcuts from "../src/javascripts/shortcuts.js";
|
||||
import TagCounter from "../src/javascripts/tag_counter.js";
|
||||
|
||||
52
app/javascript/src/javascripts/comment_component.js
Normal file
52
app/javascript/src/javascripts/comment_component.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import Utility from "./utility";
|
||||
|
||||
class CommentComponent {
|
||||
static initialize() {
|
||||
if ($("#c-posts #a-show, #c-comments").length) {
|
||||
$(document).on("click.danbooru.comment", ".edit_comment_link", CommentComponent.showEditForm);
|
||||
$(document).on("click.danbooru.comment", ".expand-comment-response", CommentComponent.showNewCommentForm);
|
||||
$(document).on("click.danbooru.comment", ".unhide-comment-link", CommentComponent.unhideComment);
|
||||
$(document).on("click.danbooru.comment", ".comment-copy-id", CommentComponent.copyID);
|
||||
$(document).on("click.danbooru.comment", ".comment-copy-link", CommentComponent.copyLink);
|
||||
}
|
||||
}
|
||||
|
||||
static showNewCommentForm(e) {
|
||||
$(e.target).hide();
|
||||
var $form = $(e.target).closest("div.new-comment").find("form");
|
||||
$form.show();
|
||||
$form[0].scrollIntoView(false);
|
||||
$form.find("textarea").selectEnd();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static showEditForm(e) {
|
||||
$(this).closest(".comment").find(".edit_comment").show();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static unhideComment(e) {
|
||||
let $comment = $(this).closest(".comment");
|
||||
$comment.find(".unhide-comment-link").hide();
|
||||
$comment.find(".body").show();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static async copyID(e) {
|
||||
let id = $(this).closest(".comment").data("id");
|
||||
let link = `comment #${id}`;
|
||||
Utility.copyToClipboard(link);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static async copyLink(e) {
|
||||
let id = $(this).closest(".comment").data("id");
|
||||
let link = `${window.location.origin}/comments/${id}`;
|
||||
Utility.copyToClipboard(link);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(CommentComponent.initialize);
|
||||
|
||||
export default CommentComponent;
|
||||
@@ -0,0 +1,65 @@
|
||||
import Utility from "./utility";
|
||||
import { delegate, hideAll } from 'tippy.js';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
|
||||
class CommentVotesTooltipComponent {
|
||||
// Trigger on the comment score link; see CommentComponent.
|
||||
static TARGET_SELECTOR = "span.comment-score";
|
||||
static SHOW_DELAY = 125;
|
||||
static HIDE_DELAY = 125;
|
||||
static DURATION = 250;
|
||||
static instance = null;
|
||||
|
||||
static initialize() {
|
||||
if ($(CommentVotesTooltipComponent.TARGET_SELECTOR).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CommentVotesTooltipComponent.instance = delegate("body", {
|
||||
allowHTML: true,
|
||||
appendTo: document.querySelector("#comment-votes-tooltips"),
|
||||
delay: [CommentVotesTooltipComponent.SHOW_DELAY, CommentVotesTooltipComponent.HIDE_DELAY],
|
||||
duration: CommentVotesTooltipComponent.DURATION,
|
||||
interactive: true,
|
||||
maxWidth: "none",
|
||||
target: CommentVotesTooltipComponent.TARGET_SELECTOR,
|
||||
theme: "common-tooltip",
|
||||
touch: false,
|
||||
|
||||
onShow: CommentVotesTooltipComponent.onShow,
|
||||
onHide: CommentVotesTooltipComponent.onHide,
|
||||
});
|
||||
}
|
||||
|
||||
static async onShow(instance) {
|
||||
let $target = $(instance.reference);
|
||||
let $tooltip = $(instance.popper);
|
||||
let commentId = $target.parents("[data-id]").data("id");
|
||||
|
||||
hideAll({ exclude: instance });
|
||||
|
||||
try {
|
||||
$tooltip.addClass("tooltip-loading");
|
||||
|
||||
instance._request = $.get(`/comments/${commentId}/votes`, { variant: "tooltip" });
|
||||
let html = await instance._request;
|
||||
instance.setContent(html);
|
||||
|
||||
$tooltip.removeClass("tooltip-loading");
|
||||
} catch (error) {
|
||||
if (error.status !== 0 && error.statusText !== "abort") {
|
||||
Utility.error(`Error displaying votes for comment #${commentId} (error: ${error.status} ${error.statusText})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async onHide(instance) {
|
||||
if (instance._request?.state() === "pending") {
|
||||
instance._request.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(CommentVotesTooltipComponent.initialize);
|
||||
|
||||
export default CommentVotesTooltipComponent;
|
||||
@@ -0,0 +1,65 @@
|
||||
import Utility from "./utility";
|
||||
import { delegate, hideAll } from 'tippy.js';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
|
||||
class FavoritesTooltipComponent {
|
||||
// Trigger on the post favcount link.
|
||||
static TARGET_SELECTOR = "span.post-favcount a";
|
||||
static SHOW_DELAY = 125;
|
||||
static HIDE_DELAY = 125;
|
||||
static DURATION = 250;
|
||||
static instance = null;
|
||||
|
||||
static initialize() {
|
||||
if ($(FavoritesTooltipComponent.TARGET_SELECTOR).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
FavoritesTooltipComponent.instance = delegate("body", {
|
||||
allowHTML: true,
|
||||
appendTo: document.querySelector("#post-favorites-tooltips"),
|
||||
delay: [FavoritesTooltipComponent.SHOW_DELAY, FavoritesTooltipComponent.HIDE_DELAY],
|
||||
duration: FavoritesTooltipComponent.DURATION,
|
||||
interactive: true,
|
||||
maxWidth: "none",
|
||||
target: FavoritesTooltipComponent.TARGET_SELECTOR,
|
||||
theme: "common-tooltip",
|
||||
touch: false,
|
||||
|
||||
onShow: FavoritesTooltipComponent.onShow,
|
||||
onHide: FavoritesTooltipComponent.onHide,
|
||||
});
|
||||
}
|
||||
|
||||
static async onShow(instance) {
|
||||
let $target = $(instance.reference);
|
||||
let $tooltip = $(instance.popper);
|
||||
let postId = $target.parents("[data-id]").data("id");
|
||||
|
||||
hideAll({ exclude: instance });
|
||||
|
||||
try {
|
||||
$tooltip.addClass("tooltip-loading");
|
||||
|
||||
instance._request = $.get(`/posts/${postId}/favorites?variant=tooltip`);
|
||||
let html = await instance._request;
|
||||
instance.setContent(html);
|
||||
|
||||
$tooltip.removeClass("tooltip-loading");
|
||||
} catch (error) {
|
||||
if (error.status !== 0 && error.statusText !== "abort") {
|
||||
Utility.error(`Error displaying favorites for post #${postId} (error: ${error.status} ${error.statusText})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async onHide(instance) {
|
||||
if (instance._request?.state() === "pending") {
|
||||
instance._request.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(FavoritesTooltipComponent.initialize);
|
||||
|
||||
export default FavoritesTooltipComponent;
|
||||
163
app/javascript/src/javascripts/file_upload_component.js
Normal file
163
app/javascript/src/javascripts/file_upload_component.js
Normal file
@@ -0,0 +1,163 @@
|
||||
import Dropzone from 'dropzone';
|
||||
import Utility from "./utility";
|
||||
import capitalize from "lodash/capitalize";
|
||||
|
||||
export default class FileUploadComponent {
|
||||
static initialize() {
|
||||
$(".file-upload-component").toArray().forEach(element => {
|
||||
new FileUploadComponent($(element));
|
||||
});
|
||||
}
|
||||
|
||||
constructor($component) {
|
||||
this.$component = $component;
|
||||
this.$component.on("ajax:success", e => this.onSubmit(e));
|
||||
this.$component.on("ajax:error", e => this.onError(e));
|
||||
this.$dropTarget.on("paste.danbooru", e => this.onPaste(e));
|
||||
this.dropzone = this.initializeDropzone();
|
||||
|
||||
// If the source field is pre-filled, then immediately submit the upload.
|
||||
if (/^https?:\/\//.test(this.$sourceField.val())) {
|
||||
this.$component.find("input[type='submit']").click();
|
||||
}
|
||||
}
|
||||
|
||||
initializeDropzone() {
|
||||
if (!window.FileReader) {
|
||||
this.$dropzone.addClass("hidden");
|
||||
this.$component.find("input[type='file']").removeClass("hidden");
|
||||
return null;
|
||||
}
|
||||
|
||||
let dropzone = new Dropzone(this.$dropTarget.get(0), {
|
||||
url: "/uploads.json",
|
||||
paramName: "upload[file]",
|
||||
clickable: this.$dropzone.get(0),
|
||||
previewsContainer: this.$dropzone.get(0),
|
||||
thumbnailHeight: null,
|
||||
thumbnailWidth: null,
|
||||
addRemoveLinks: false,
|
||||
maxFiles: 1,
|
||||
maxFilesize: this.maxFileSize,
|
||||
maxThumbnailFilesize: this.maxFileSize,
|
||||
timeout: 0,
|
||||
acceptedFiles: "image/jpeg,image/png,image/gif,video/mp4,video/webm",
|
||||
previewTemplate: this.$component.find(".dropzone-preview-template").html(),
|
||||
});
|
||||
|
||||
dropzone.on("complete", file => {
|
||||
this.$dropzone.find(".dz-progress").hide();
|
||||
});
|
||||
|
||||
dropzone.on("addedfile", file => {
|
||||
this.$dropzone.removeClass("error");
|
||||
this.$dropzone.find(".dropzone-hint").hide();
|
||||
|
||||
// Remove all files except the file just added.
|
||||
dropzone.files.forEach(f => {
|
||||
if (f !== file) {
|
||||
dropzone.removeFile(f);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
dropzone.on("success", file => {
|
||||
this.$dropzone.addClass("success");
|
||||
let upload = JSON.parse(file.xhr.response)
|
||||
this.pollStatus(upload);
|
||||
});
|
||||
|
||||
dropzone.on("error", (file, msg) => {
|
||||
this.$dropzone.addClass("error");
|
||||
});
|
||||
|
||||
return dropzone;
|
||||
}
|
||||
|
||||
onPaste(e) {
|
||||
let url = e.originalEvent.clipboardData.getData("text");
|
||||
this.$component.find("input[name='upload[source]']:not([disabled])").val(url);
|
||||
|
||||
if (/^https?:\/\//.test(url)) {
|
||||
this.$component.find("input[type='submit']:not([disabled])").click();
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
onSubmit(e) {
|
||||
let upload = e.originalEvent.detail[0];
|
||||
this.pollStatus(upload);
|
||||
}
|
||||
|
||||
// Called after the upload is submitted via AJAX. Polls the upload until it
|
||||
// is complete, then redirects to the upload page.
|
||||
async pollStatus(upload) {
|
||||
this.$component.find("progress").removeClass("hidden");
|
||||
this.$component.find("input").attr("disabled", "disabled");
|
||||
|
||||
while (upload.status === "pending" || upload.status === "processing") {
|
||||
await Utility.delay(500);
|
||||
upload = await $.get(`/uploads/${upload.id}.json`);
|
||||
}
|
||||
|
||||
if (upload.status === "completed") {
|
||||
let params = new URLSearchParams(window.location.search);
|
||||
let isBookmarklet = params.has("url");
|
||||
params.delete("url");
|
||||
params.delete("ref");
|
||||
|
||||
let url = new URL(`/uploads/${upload.id}`, window.location.origin);
|
||||
url.search = params.toString();
|
||||
|
||||
if (isBookmarklet) {
|
||||
window.location.replace(url);
|
||||
} else {
|
||||
window.location.assign(url);
|
||||
}
|
||||
} else if (upload.status === "error") {
|
||||
this.$dropzone.removeClass("success");
|
||||
this.$component.find("progress").addClass("hidden");
|
||||
this.$component.find("input").removeAttr("disabled");
|
||||
|
||||
Utility.error(`Upload failed: ${upload.error}.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Called when creating the upload failed because of a validation error (normally, because the source URL was not a real URL).
|
||||
async onError(e) {
|
||||
let errors = e.originalEvent.detail[0].errors;
|
||||
let message = Object.keys(errors).map(attribute => {
|
||||
return errors[attribute].map(error => {
|
||||
if (attribute === "base") {
|
||||
return `${error}`;
|
||||
} else {
|
||||
return `${capitalize(attribute)} ${error}`;
|
||||
}
|
||||
});
|
||||
}).join("; ");
|
||||
|
||||
Utility.error(message);
|
||||
}
|
||||
|
||||
get $dropzone() {
|
||||
return this.$component.find(".dropzone-container");
|
||||
}
|
||||
|
||||
get $sourceField() {
|
||||
return this.$component.find("input[name='upload[source]']");
|
||||
}
|
||||
|
||||
get maxFileSize() {
|
||||
return Number(this.$component.attr("data-max-file-size")) / (1024 * 1024);
|
||||
}
|
||||
|
||||
// The element to listen for drag and drop events and paste events. By default,
|
||||
// it's the `.file-upload-component` element. If `data-drop-target` is the `body`
|
||||
// element, then you can drop images or paste URLs anywhere on the page.
|
||||
get $dropTarget() {
|
||||
return $(this.$component.attr("data-drop-target") || this.$component);
|
||||
}
|
||||
}
|
||||
|
||||
$(FileUploadComponent.initialize);
|
||||
48
app/javascript/src/javascripts/forum_post_component.js
Normal file
48
app/javascript/src/javascripts/forum_post_component.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import Utility from "./utility";
|
||||
|
||||
class ForumPostComponent {
|
||||
static initialize() {
|
||||
if ($("#c-forum-topics #a-show, #c-forum-posts #a-show").length) {
|
||||
$(document).on("click.danbooru.forum_post", ".edit_forum_post_link", ForumPostComponent.showEditPostForm);
|
||||
$(document).on("click.danbooru.forum_post", ".edit_forum_topic_link", ForumPostComponent.showEditTopicForm);
|
||||
$(document).on("click.danbooru.forum_post", "#new-response-link", ForumPostComponent.showNewForumPostForm);
|
||||
$(document).on("click.danbooru.forum_post", ".forum-post-copy-id", ForumPostComponent.copyID);
|
||||
$(document).on("click.danbooru.forum_post", ".forum-post-copy-link", ForumPostComponent.copyLink);
|
||||
}
|
||||
}
|
||||
|
||||
static showNewForumPostForm(e) {
|
||||
$("#topic-response").show();
|
||||
$("#forum_post_body").get(0).scrollIntoView(false);
|
||||
$("#forum_post_body").selectEnd();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static showEditPostForm(e) {
|
||||
$(this).closest(".forum-post").find(".edit_forum_post").show();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static showEditTopicForm(e) {
|
||||
$(this).closest(".forum-post").find(".edit_forum_topic").show();
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static async copyID(e) {
|
||||
let id = $(this).closest(".forum-post").data("id");
|
||||
let link = `forum #${id}`;
|
||||
Utility.copyToClipboard(link);
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
static async copyLink(e) {
|
||||
let id = $(this).closest(".forum-post").data("id");
|
||||
let link = `${window.location.origin}/forum_posts/${id}`;
|
||||
Utility.copyToClipboard(link);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(ForumPostComponent.initialize);
|
||||
|
||||
export default ForumPostComponent;
|
||||
56
app/javascript/src/javascripts/media_asset_component.js
Normal file
56
app/javascript/src/javascripts/media_asset_component.js
Normal file
@@ -0,0 +1,56 @@
|
||||
export default class MediaAssetComponent {
|
||||
static initialize() {
|
||||
$(".media-asset-component").toArray().forEach(element => {
|
||||
new MediaAssetComponent(element);
|
||||
});
|
||||
}
|
||||
|
||||
constructor(element) {
|
||||
this.$component = $(element);
|
||||
|
||||
if (this.$image.length) {
|
||||
this.$image.on("click.danbooru", e => this.toggleFit());
|
||||
new ResizeObserver(() => this.updateZoom()).observe(this.$image.get(0));
|
||||
this.updateZoom();
|
||||
}
|
||||
}
|
||||
|
||||
toggleFit() {
|
||||
this.$component.toggleClass("fit-screen");
|
||||
this.updateZoom();
|
||||
}
|
||||
|
||||
updateZoom() {
|
||||
this.$image.removeClass("cursor-zoom-in cursor-zoom-out");
|
||||
this.$zoomLevel.addClass("hidden").text(`${Math.round(100 * this.zoomLevel)}%`);
|
||||
|
||||
if (this.isDownscaled) {
|
||||
this.$image.addClass("cursor-zoom-out");
|
||||
this.$zoomLevel.removeClass("hidden");
|
||||
} else if (this.isTooBig) {
|
||||
this.$image.addClass("cursor-zoom-in");
|
||||
}
|
||||
}
|
||||
|
||||
get zoomLevel() {
|
||||
return this.$image.width() / Number(this.$image.attr("width"));
|
||||
}
|
||||
|
||||
get isDownscaled() {
|
||||
return this.$image.width() < Number(this.$image.attr("width"));
|
||||
}
|
||||
|
||||
get isTooBig() {
|
||||
return this.$image.width() > this.$component.width();
|
||||
}
|
||||
|
||||
get $image() {
|
||||
return this.$component.find(".media-asset-image");
|
||||
}
|
||||
|
||||
get $zoomLevel() {
|
||||
return this.$component.find(".media-asset-zoom-level");
|
||||
}
|
||||
}
|
||||
|
||||
$(MediaAssetComponent.initialize);
|
||||
36
app/javascript/src/javascripts/popup_menu_component.js
Normal file
36
app/javascript/src/javascripts/popup_menu_component.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { delegate } from 'tippy.js';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
|
||||
class PopupMenuComponent {
|
||||
static initialize() {
|
||||
delegate("body", {
|
||||
allowHTML: true,
|
||||
interactive: true,
|
||||
theme: "common-tooltip",
|
||||
target: "a.popup-menu-button",
|
||||
placement: "bottom-start",
|
||||
trigger: "click",
|
||||
touch: "hold",
|
||||
animation: null,
|
||||
content: PopupMenuComponent.content,
|
||||
});
|
||||
|
||||
$(document).on("click.danbooru", ".popup-menu-content", PopupMenuComponent.onMenuItemClicked);
|
||||
}
|
||||
|
||||
static content(element) {
|
||||
let $content = $(element).parents(".popup-menu").find(".popup-menu-content");
|
||||
$content.show();
|
||||
return $content.get(0);
|
||||
}
|
||||
|
||||
// Hides the menu when a menu item is clicked.
|
||||
static onMenuItemClicked(event) {
|
||||
let tippy = $(event.target).parents("[data-tippy-root]").get(0)._tippy;
|
||||
tippy.hide();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(PopupMenuComponent.initialize);
|
||||
|
||||
export default PopupMenuComponent;
|
||||
@@ -0,0 +1,65 @@
|
||||
import Utility from "./utility";
|
||||
import { delegate, hideAll } from 'tippy.js';
|
||||
import 'tippy.js/dist/tippy.css';
|
||||
|
||||
class PostVotesTooltipComponent {
|
||||
// Trigger on the post score link; see PostVotesComponent.
|
||||
static TARGET_SELECTOR = "span.post-votes span.post-score a";
|
||||
static SHOW_DELAY = 125;
|
||||
static HIDE_DELAY = 125;
|
||||
static DURATION = 250;
|
||||
static instance = null;
|
||||
|
||||
static initialize() {
|
||||
if ($(PostVotesTooltipComponent.TARGET_SELECTOR).length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
PostVotesTooltipComponent.instance = delegate("body", {
|
||||
allowHTML: true,
|
||||
appendTo: document.querySelector("#post-votes-tooltips"),
|
||||
delay: [PostVotesTooltipComponent.SHOW_DELAY, PostVotesTooltipComponent.HIDE_DELAY],
|
||||
duration: PostVotesTooltipComponent.DURATION,
|
||||
interactive: true,
|
||||
maxWidth: "none",
|
||||
target: PostVotesTooltipComponent.TARGET_SELECTOR,
|
||||
theme: "common-tooltip",
|
||||
touch: false,
|
||||
|
||||
onShow: PostVotesTooltipComponent.onShow,
|
||||
onHide: PostVotesTooltipComponent.onHide,
|
||||
});
|
||||
}
|
||||
|
||||
static async onShow(instance) {
|
||||
let $target = $(instance.reference);
|
||||
let $tooltip = $(instance.popper);
|
||||
let postId = $target.parents("[data-id]").data("id");
|
||||
|
||||
hideAll({ exclude: instance });
|
||||
|
||||
try {
|
||||
$tooltip.addClass("tooltip-loading");
|
||||
|
||||
instance._request = $.get(`/post_votes?search[post_id]=${postId}`, { variant: "tooltip" });
|
||||
let html = await instance._request;
|
||||
instance.setContent(html);
|
||||
|
||||
$tooltip.removeClass("tooltip-loading");
|
||||
} catch (error) {
|
||||
if (error.status !== 0 && error.statusText !== "abort") {
|
||||
Utility.error(`Error displaying votes for post #${postId} (error: ${error.status} ${error.statusText})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async onHide(instance) {
|
||||
if (instance._request?.state() === "pending") {
|
||||
instance._request.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(PostVotesTooltipComponent.initialize);
|
||||
|
||||
export default PostVotesTooltipComponent;
|
||||
@@ -1,4 +1,4 @@
|
||||
import SourceDataComponent from '../../../components/source_data_component/source_data_component.js';
|
||||
import SourceDataComponent from "./source_data_component.js";
|
||||
import Utility from './utility';
|
||||
|
||||
let RelatedTag = {};
|
||||
|
||||
22
app/javascript/src/javascripts/source_data_component.js
Normal file
22
app/javascript/src/javascripts/source_data_component.js
Normal file
@@ -0,0 +1,22 @@
|
||||
class SourceDataComponent {
|
||||
static initialize() {
|
||||
$(document).on("click.danbooru", ".source-data-fetch", SourceDataComponent.fetchData);
|
||||
}
|
||||
|
||||
static async fetchData(e) {
|
||||
let url = $("#post_source").val();
|
||||
let ref = $("#post_referer_url").val();
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if (/^https?:\/\//.test(url)) {
|
||||
$(".source-data").addClass("loading");
|
||||
await $.get("/source.js", { url: url, ref: ref });
|
||||
$(".source-data").removeClass("loading");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(SourceDataComponent.initialize);
|
||||
|
||||
export default SourceDataComponent;
|
||||
Reference in New Issue
Block a user