diff --git a/better-better-booru.user.js b/better-better-booru.user.js index faa7aa1..3f6dace 100644 --- a/better-better-booru.user.js +++ b/better-better-booru.user.js @@ -3,7 +3,7 @@ // @namespace https://greasyfork.org/scripts/3575-better-better-booru // @author otani, modified by Jawertae, A Pseudonymous Coder & Moebius Strip. // @description Several changes to make Danbooru much better. -// @version 8.2.1 +// @version 8.2.2 // @updateURL https://greasyfork.org/scripts/3575-better-better-booru/code/better_better_booru.meta.js // @downloadURL https://greasyfork.org/scripts/3575-better-better-booru/code/better_better_booru.user.js // @match *://*.donmai.us/* @@ -293,6 +293,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. /* Global Variables */ var bbb = { // Container for script info. + autocomplete: {}, blacklist: { entries: [], match_list: {}, @@ -357,7 +358,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. swapped: false // Whether the post content has been changed between the original and sample versions. }, options: { // Setting options and data. - bbb_version: "8.2.1", + bbb_version: "8.2.2", add_popular_link: newOption("checkbox", false, "Add Popular Link", "Add a link to the popular listing to the \"posts\" submenu"), add_random_post_link: newOption("checkbox", false, "Add Random Link", "Add a link to a random post to the post sidebar options menu."), alternate_image_swap: newOption("checkbox", false, "Alternate Image Swap", "Switch between the sample and original image by clicking the image. NoteNotes can be toggled by using the link in the sidebar options section."), @@ -641,8 +642,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. endlessInit(); - bbbAutocompleteInit(); - delayMe(formatThumbnails); // Delayed to allow Danbooru to run first. delayMe(blacklistInit); // Delayed to allow Danbooru to run first. @@ -926,8 +925,8 @@ function bbbScript() { // Wrapper for injecting the script into the document. // Prep the "toggle notes" link. The "toggle notes" link is added here just for consistency's sake. noteToggleLinkInit(); - if (postInfo.pixiv_ugoira_frame_data.data) // Set up the post. - ugoiraInit(); + if (postInfo.pixiv_ugoira_frame_data.data && Danbooru.Ugoira && Danbooru.Ugoira.create_player) // Set up the post. + Danbooru.Ugoira.create_player(postInfo.pixiv_ugoira_frame_data.content_type, postInfo.pixiv_ugoira_frame_data.data, postInfo.file_url); } } else if (!postInfo.image_height) // Create manual download. @@ -1012,6 +1011,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. var artistTags = postInfo.tag_string_artist.split(" "); var copyrightTags = postInfo.tag_string_copyright.split(" "); var characterTags = postInfo.tag_string_character.split(" "); + var metaTags = postInfo.tag_string_meta.split(" "); var limit = (thumbnail_count ? "&limit=" + thumbnail_count : ""); var j, jl, tag; // Loop variables. @@ -1035,6 +1035,11 @@ function bbbScript() { // Wrapper for injecting the script into the document. tagLinks = tagLinks.replace(tag.bbbSpacePad(), ' ' + tag.replace(/_/g, " ") + ' '); } + for (j = 0, jl = metaTags.length; j < jl; j++) { + tag = metaTags[j]; + tagLinks = tagLinks.replace(tag.bbbSpacePad(), ' ' + tag.replace(/_/g, " ") + ' '); + } + // Create the new post. var childSpan = document.createElement("span"); @@ -1471,6 +1476,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. tag_string_character: scrapePostTags("character", target), tag_string_copyright: scrapePostTags("copyright", target), tag_string_general: scrapePostTags("general", target), + tag_string_meta: scrapePostTags("meta", target), pool_string: imgContainer.getAttribute("data-pools") || "", uploader_name: imgContainer.getAttribute("data-uploader") || "", uploader_id: Number(imgContainer.getAttribute("data-uploader-id")) || 0, @@ -1516,6 +1522,8 @@ function bbbScript() { // Wrapper for injecting the script into the document. categoryClass = "category-1"; else if (category === "general") categoryClass = "category-0"; + else if (category === "meta") + categoryClass = "category-5"; var categoryTags = tagList.getElementsByClassName(categoryClass); var categoryString = ""; @@ -2050,7 +2058,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. helpPage.className = "bbb-page"; scrollDiv.appendChild(helpPage); - helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
Wildcards can be used with any of the above methods:
Multiple match rules can be specified by using commas or separate lines when possible:
Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
The following metatags are supported:
The id, score, favcount, width, and height metatags can also use number ranges for matching:'); + helpPage.bbbTextSection('Thumbnail Matching Rules', 'For creating thumbnail matching rules, please consult the following examples:
Wildcards can be used with any of the above methods:
Multiple match rules can be specified by using commas or separate lines when possible:
Tags can be nested/grouped together by using parentheses that only have spaces or commas next to them:
The following metatags are supported:
The id, score, favcount, width, and height metatags can also use number ranges for matching:'); helpPage.bbbTextSection('Hotkeys', 'Posts
Note: Numbers refer to the main typing keypad and not the numeric keypad.

General'); helpPage.bbbTextSection('Questions, Suggestions, or Bugs?', 'If you have any questions, please use the Greasy Fork feedback forums located here. If you\'d like to report a bug or make a suggestion, please create an issue on GitHub here.'); helpPage.bbbTocSection(); @@ -3408,6 +3416,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. case "8.0.2": case "8.1": case "8.2": + case "8.2.1": break; } @@ -4351,7 +4360,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. function postTagTitles() { // Replace the post title with the full set of tags. if (post_tag_titles && gLoc === "post") - document.title = getMeta("tags").replace(/\s/g, ", ").replace(/_/g, " ") + " - Danbooru"; + document.title = document.bbbInfo("tags").replace(/\s/g, ", ").replace(/_/g, " ") + " - Danbooru"; } function minimizeStatusNotices() { @@ -4605,75 +4614,6 @@ function bbbScript() { // Wrapper for injecting the script into the document. } } - function ugoiraInit() { - // Execute a static copy of Danbooru's embedded JavaScript for setting up the post. - var postInfo = bbb.post.info; - - try { - Danbooru.Ugoira = {}; - - Danbooru.Ugoira.create_player = function() { - var meta_data = { - mime_type: postInfo.pixiv_ugoira_frame_data.content_type, - frames: postInfo.pixiv_ugoira_frame_data.data - }; - var options = { - canvas: document.getElementById("image"), - source: postInfo.file_url, - metadata: meta_data, - chunkSize: 300000, - loop: true, - autoStart: true, - debug: false - }; - - this.player = new ZipImagePlayer(options); - }; - - Danbooru.Ugoira.player = null; - - $(function() { - var player_manually_paused = false; - - Danbooru.Ugoira.create_player(); - $(Danbooru.Ugoira.player).on("loadProgress", function(event, progress) { $("#seek-slider").progressbar("value", Math.floor(progress * 100)); }); - $("#ugoira-play").click(function(event) { - Danbooru.Ugoira.player.play(); - $(this).hide(); - $("#ugoira-pause").show(); - player_manually_paused = false; - event.preventDefault(); - }); - $("#ugoira-pause").click(function(event) { - Danbooru.Ugoira.player.pause(); - $(this).hide(); - $("#ugoira-play").show(); - player_manually_paused = true; - event.preventDefault(); - }); - $("#seek-slider").progressbar({value: 0}); - $("#seek-slider").slider({ - min: 0, - max: Danbooru.Ugoira.player._frameCount-1, - start: function() { Danbooru.Ugoira.player.pause(); }, - slide: function(event, ui) { - Danbooru.Ugoira.player._frame = ui.value; - Danbooru.Ugoira.player._displayFrame(); - }, - stop: function() { - if (!(player_manually_paused)) { - Danbooru.Ugoira.player.play(); - } - } - }); - $(Danbooru.Ugoira.player).on("frame", function(frame, frame_number) { $("#seek-slider").slider("option", "value", frame_number); }); - }); - } - catch (error) { - bbbNotice("Unexpected error creating the ugoira post. (Error: " + error.message + ")", -1); - } - } - function videoVolume() { // Set the volume of video posts to a specified level. var vid = document.getElementById("image"); @@ -6532,31 +6472,31 @@ function bbbScript() { // Wrapper for injecting the script into the document. var urlReg, url, id, artist, title; // If/else variables. if (!!(urlReg = source.match(/^https?:\/\/img\d+\.pixiv\.net\/img\/[^\/]+\/(\d+)/i) || source.match(/^https?:\/\/i\d\.pixiv\.net\/img\d+\/img\/[^\/]+\/(\d+)/i))) - url = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + urlReg[1]; + url = "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/(?:i\d+\.pixiv\.net|i\.pximg\.net)\/img-(?:master|original)\/img\/(?:\d+\/)+(\d+)_p/i) || source.match(/^https?:\/\/(?:i\d+\.pixiv\.net|i\.pximg\.net)\/c\/\d+x\d+\/img-master\/img\/(?:\d+\/)+(\d+)_p/i) || source.match(/^https?:\/\/(?:i\d+\.pixiv\.net|i\.pximg\.net)\/img-zip-ugoira\/img\/(?:\d+\/)+(\d+)_ugoira\d+x\d+\.zip/i))) - url = "http://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + urlReg[1]; + url = "https://www.pixiv.net/member_illust.php?mode=medium&illust_id=" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/lohas\.nicoseiga\.jp\/priv\/(\d+)\?e=\d+&h=[a-f0-9]+/i) || source.match(/^https?:\/\/lohas\.nicoseiga\.jp\/priv\/[a-f0-9]+\/\d+\/(\d+)/i))) - url = "http://seiga.nicovideo.jp/seiga/im" + urlReg[1]; + url = "https://seiga.nicovideo.jp/seiga/im" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/(?:d3j5vwomefv46c|dn3pm25xmtlyu)\.cloudfront\.net\/photos\/large\/(\d+)\./i))) { id = parseInt(urlReg[1]).toString(36); - url = "http://twitpic.com/" + id; + url = "https://twitpic.com/" + id; } else if (!!(urlReg = source.match(/^https?:\/\/(?:(?:fc|th|pre|orig|img|prnt)\d{2}|origin-orig)\.deviantart\.net\/.+\/([a-z0-9_]+)_by_([a-z0-9_]+)-d([a-z0-9]+)\./i))) { title = urlReg[1].replace(/[^A-Za-z0-9]/g, " ").bbbSpaceClean().replace(/[ ]/g, "-"); artist = urlReg[2].replace(/_/g, "-"); id = parseInt(urlReg[3], 36); - url = "http://" + artist + ".deviantart.com/art/" + title + "-" + id; + url = "https://" + artist + ".deviantart.com/art/" + title + "-" + id; } else if (!!(urlReg = source.match(/^https?:\/\/(?:fc|th|pre|orig|img|prnt)\d{2}\.deviantart\.net\/.+\/[a-f0-9]{32}-d([a-z0-9]+)\./i))) { id = parseInt(urlReg[1], 36); - url = "http://deviantart.com/deviation/" + id; + url = "https://deviantart.com/deviation/" + id; } else if (!!(urlReg = source.match(/^http:\/\/www\.karabako\.net\/images(?:ub)?\/karabako_(\d+)(?:_\d+)?\./i))) url = "http://www.karabako.net/post/view/" + urlReg[1]; - else if (!!(urlReg = source.match(/^http:\/\/p\.twpl\.jp\/show\/orig\/([a-z0-9]+)/i))) + else if (!!(urlReg = source.match(/^http:\/\/p\.twpl\.jp\/show\/(?:large|orig)\/([a-z0-9]+)/i))) url = "http://p.twipple.jp/" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/pictures\.hentai-foundry\.com\/\/?[^\/]\/([^\/]+)\/(\d+)/i))) - url = "http://www.hentai-foundry.com/pictures/user/" + urlReg[1] + "/" + urlReg[2]; + url = "https://www.hentai-foundry.com/pictures/user/" + urlReg[1] + "/" + urlReg[2]; else if (!!(urlReg = source.match(/^http:\/\/blog(?:(?:-imgs-)?\d*(?:-origin)?)?\.fc2\.com\/(?:(?:[^\/]\/){3}|(?:[^\/]\/))([^\/]+)\/(?:file\/)?([^\.]+\.[^\?]+)/i))) url = "http://" + urlReg[1] + ".blog.fc2.com/img/" + urlReg[2] + "/"; else if (!!(urlReg = source.match(/^http:\/\/diary(\d?)\.fc2\.com\/user\/([^\/]+)\/img\/(\d+)_(\d+)\/(\d+)\./i))) @@ -6564,13 +6504,13 @@ function bbbScript() { // Wrapper for injecting the script into the document. else if (!!(urlReg = source.match(/^https?:\/\/(?:fbcdn-)?s(?:content|photos)-[^\/]+\.(?:fbcdn|akamaihd)\.net\/hphotos-.+\/\d+_(\d+)_(?:\d+_){1,3}[no]\./i))) url = "https://www.facebook.com/photo.php?fbid=" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/c(?:s|han|[1-4])\.sankakucomplex\.com\/data(?:\/sample)?\/(?:[a-f0-9]{2}\/){2}(?:sample-|preview)?([a-f0-9]{32})/i))) - url = "http://chan.sankakucomplex.com/en/post/show?md5=" + urlReg[1]; + url = "https://chan.sankakucomplex.com/en/post/show?md5=" + urlReg[1]; else if (!!(urlReg = source.match(/^http:\/\/s(?:tatic|[1-4])\.zerochan\.net\/.+(?:\.|\/)(\d+)\.(?:jpe?g?)$/i))) - url = "http://www.zerochan.net/" + urlReg[1] + "#full"; + url = "https://www.zerochan.net/" + urlReg[1] + "#full"; else if (!!(urlReg = source.match(/^http:\/\/static[1-6]?\.minitokyo\.net\/(?:downloads|view)\/(?:\d{2}\/){2}(\d+)/i))) url = "http://gallery.minitokyo.net/download/" + urlReg[1]; - else if (postInfo.md5 && !!(urlReg = source.match(/^https?:\/\/(?:(?:s?img|cdn|www)\d?\.)?gelbooru\.com\/{1,2}(?:images|samples)\/(?:\d+|[a-f0-9]{2}\/[a-f0-9]{2})\/(?:sample_)?(?:[a-f0-9]{32}|[a-f0-9]{40})\./i))) - url = "http://gelbooru.com/index.php?page=post&s=list&md5=" + postInfo.md5; + else if (postInfo.md5 && !!(urlReg = source.match(/^https?:\/\/(?:\w+\.)?gelbooru\.com\/\/?(?:images|samples)\/(?:\d+|[a-f0-9]{2}\/[a-f0-9]{2})\/(?:sample_)?(?:[a-f0-9]{32}|[a-f0-9]{40})\./i))) + url = "https://gelbooru.com/index.php?page=post&s=list&md5=" + postInfo.md5; else if (!!(urlReg = source.match(/^https?:\/\/(?:slot\d*\.)?im(?:g|ages)\d*\.wikia\.(?:nocookie\.net|com)\/(?:_{2}cb\d{14}\/)?([^\/]+)(?:\/[a-z]{2})?\/images\/(?:(?:thumb|archive)?\/)?[a-f0-9]\/[a-f0-9]{2}\/(?:\d{14}(?:!|%21))?([^\/]+)/i))) url = "http://" + urlReg[1] + ".wikia.com/wiki/File:" + urlReg[2]; else if (!!(urlReg = source.match(/^https?:\/\/vignette(?:\d*)\.wikia\.nocookie\.net\/([^\/]+)\/images\/[a-f0-9]\/[a-f0-9]{2}\/([^\/]+)/i))) @@ -6584,21 +6524,21 @@ function bbbScript() { // Wrapper for injecting the script into the document. else if (!!(urlReg = source.match(/^https?:\/\/sozai\.doujinantena\.com\/contents_jpg\/([a-f0-9]{32})\//i))) url = "http://doujinantena.com/page.php?id=" + urlReg[1]; else if (!!(urlReg = source.match(/^http:\/\/rule34-(?:data-\d{3}|images)\.paheal\.net\/(?:_images\/)?([a-f0-9]{32})/i))) - url = "http://rule34.paheal.net/post/list/md5:" + urlReg[1] + "/1"; + url = "https://rule34.paheal.net/post/list/md5:" + urlReg[1] + "/1"; else if (!!(urlReg = source.match(/^http:\/\/shimmie\.katawa-shoujo\.com\/image\/(\d+)/i))) - url = "http://shimmie.katawa-shoujo.com/post/view/" + urlReg[1]; + url = "https://shimmie.katawa-shoujo.com/post/view/" + urlReg[1]; else if (postInfo.md5 && !!(urlReg = source.match(/^http:\/\/(?:(?:(?:img\d?|cdn)\.)?rule34\.xxx|img\.booru\.org\/(?:rule34|r34))(?:\/(?:img\/rule34|r34))?\/{1,2}images\/\d+\/(?:[a-f0-9]{32}|[a-f0-9]{40})\./i))) - url = "http://rule34.xxx/index.php?page=post&s=list&md5=" + postInfo.md5; + url = "https://rule34.xxx/index.php?page=post&s=list&md5=" + postInfo.md5; else if (!!(urlReg = source.match(/^https?:\/\/(?:s3\.amazonaws\.com\/imgly_production|img\.ly\/system\/uploads)\/((?:\d{3}\/){3}|\d+\/)/i))) { id = parseInt((urlReg[1].replace(/[^0-9]/g, '')) || 0).bbbEncode62(); - url = "http://img.ly/" + id; + url = "https://img.ly/" + id; } else if (!!(urlReg = source.match(/^(http:\/\/.+)\/diarypro\/d(?:ata\/upfile\/|iary\.cgi\?mode=image&upfile=)(\d+)/i))) url = urlReg[1] + "/diarypro/diary.cgi?no=" + urlReg[2]; else if (!!(urlReg = source.match(/^http:\/\/i(?:\d)?\.minus\.com\/(?:i|j)([^\.]{12,})/i))) url = "http://minus.com/i/" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/pic0[1-4]\.nijie\.info\/nijie_picture\/(?:diff\/main\/)?\d+_(\d+)_(?:\d{10}|\d+_\d{14})/i))) - url = "http://nijie.info/view.php?id=" + urlReg[1]; + url = "https://nijie.info/view.php?id=" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/(?:ayase\.|yuno\.|files\.)?yande\.re\/(?:sample|image)\/[a-z0-9]{32}\/yande\.re%20([0-9]+)%20/i))) url = "https://yande.re/post/show/" + urlReg[1]; else if (!!(urlReg = source.match(/^https?:\/\/(?:ayase\.|yuno\.|files\.)?yande\.re\/(?:image|jpeg|sample)\/([a-z0-9]{32})(?:\/yande\.re.*|\/?\.(?:jpg|png))$/i))) @@ -6617,6 +6557,10 @@ function bbbScript() { // Wrapper for injecting the script into the document. else url = source; } + else if (!!(urlReg = source.match(/^https?:\/\/\w+\.photozou\.jp\/pub\/\d+\/(\d+)\/photo\/(\d+)_.*$/i))) + url = "https://photozou.jp/photo/show/" + urlReg[1] + "/" + urlReg[2]; + else if (!!(urlReg = source.match(/^https?:\/\/\w+\.?toranoana\.jp\/(?:popup_(?:bl)?img\d*|ec\/img)\/\d{2}\/\d{4}\/\d{2}\/\d{2}\/(\d+)/i))) + url = "https://ec.toranoana.jp/tora_r/ec/item/" + urlReg[1] + "/"; else url = source; @@ -7031,10 +6975,11 @@ function bbbScript() { // Wrapper for injecting the script into the document. var parent = (postInfo.parent_id ? " parent:" + postInfo.parent_id : ""); var child = (postInfo.has_children === true ? " child:true" : ""); var isFav = " isfav:" + postInfo.is_favorited; + var filetype = " filetype:" + postInfo.file_ext; postSearchInfo = { tags: postInfo.tag_string.bbbSpacePad(), - metatags:(rating + status + user + pools + parent + child + isFav + userId + taggerId + source + approverId).bbbSpacePad(), + metatags:(rating + status + user + pools + parent + child + isFav + userId + taggerId + source + approverId + filetype).bbbSpacePad(), score: postInfo.score, favcount: postInfo.fav_count, id: postInfo.id, @@ -7604,10 +7549,11 @@ function bbbScript() { // Wrapper for injecting the script into the document. // Update the mark link if the paginator updates. if (paginator) { paginator.bbbWatchNodes(function() { - var activePage = paginator.getElementsByTagName("span")[0]; + var activePage = paginator.getElementsByClassName("current-page")[0]; + var pageNumber = (activePage ? activePage.textContent.bbbSpaceClean() : "1") || "1"; - if (activePage) - markLink.innerHTML = "Mark pages 1-" + activePage.textContent.bbbSpaceClean() + " viewed"; + if (pageNumber && pageNumber !== "1") + markLink.innerHTML = "Mark pages 1-" + pageNumber + " viewed"; }); } } @@ -10099,7 +10045,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. else { var tagName = tag.split(":", 1)[0].bbbSpaceClean(); - if (tagName === "pool" || tagName === "user" || tagName === "status" || tagName === "rating" || tagName === "parent" || tagName === "child" || tagName === "isfav" || tagName === "userid" || tagName === "taggerid" || tagName === "source" || tagName === "approverid") + if (tagName === "pool" || tagName === "user" || tagName === "status" || tagName === "rating" || tagName === "parent" || tagName === "child" || tagName === "isfav" || tagName === "userid" || tagName === "taggerid" || tagName === "source" || tagName === "approverid" || tagName === "filetype") return true; else return false; @@ -10236,145 +10182,276 @@ function bbbScript() { // Wrapper for injecting the script into the document. } function bbbAutocompleteInit() { - // Add custom tags to Danbooru's autocomplete and fix other issues. - if (!Danbooru.Autocomplete) - return; - + // Set up a modified version of Danbooru's autocomplete. try { - // Add custom metatags. - var groups = []; + var Autocomplete = bbb.autocomplete; + + Autocomplete.AUTOCOMPLETE_VERSION = 1; + Autocomplete.PREFIXES = /^([-~]*)(.*)$/i; + Autocomplete.METATAGS = /^(status|rating|parent|child|user|pool|group|g|isfav|userid|taggerid|approverid|source|id|score|favcount|height|width|filetype):(.*)$/i; + + Autocomplete.initialize_all = function() { + if (Danbooru.Utility.meta("enable-auto-complete") === "true") { + $.widget("ui.autocomplete", $.ui.autocomplete, { + options: {delay: 0, minLength: 1, autoFocus: false, focus: function() { return false; }}, + _create: function() { + this.element.on("keydown.Autocomplete.tab", null, "tab", Autocomplete.on_tab); + this._super(); + }, + _renderItem: Autocomplete.render_item, + }); + } + }; - for (var i = 0, il = tag_groups.length; i < il; i++) - groups.push(tag_groups[i].name); + Autocomplete.normal_source = function(term, resp) { + $.ajax({ + url: "/tags/autocomplete.json", + data: {"search[name_matches]": term, "expiry": 7}, + method: "get", + success: function(data) { + var d = $.map(data, function(tag) { + return {type: "tag", label: tag.name.replace(/_/g, " "), antecedent: tag.antecedent_name, value: tag.name, category: tag.category, post_count: tag.post_count}; + }); - Danbooru.Autocomplete.static_metatags.group = Danbooru.Autocomplete.static_metatags.g = groups; - Danbooru.Autocomplete.static_metatags.parent = ["any", "none"]; - Danbooru.Autocomplete.static_metatags.isfav = ["true", "false"]; - Danbooru.Autocomplete.static_metatags.pool = ["series", "collection", "any", "none", "active", "inactive"]; - Danbooru.Autocomplete.static_metatags.source = ["any", "none"]; - Danbooru.Autocomplete.static_metatags.approverid = ["any", "none"]; + resp(d); + } + }); + }; - // Counter normal autocomplete getting turned back on after submitting an input. - document.body.addEventListener("focus", function(event) { - var target = event.target; + Autocomplete.parse_query = function(text, caret) { + var metatag = ""; + var term = ""; + var before_caret_text = text.substring(0, caret); + var match = before_caret_text.match(/\S+$/g); - if (target.bbbHasClass("ui-autocomplete-input")) - target.setAttribute("autocomplete", "off"); - }, true); - } - catch (error) { - bbbNotice("Unexpected error while trying to initialize autocomplete. (Error: " + error.message + ")", -1); - } + if (match) + term = match[0]; + else + return {}; - } + if (!!(match = term.match(Autocomplete.PREFIXES))) { + metatag = match[1].toLowerCase(); + term = match[2]; + } - function bbbAutocomplete(searchInputs) { - // Use a modified copy of Danbooru's autocomplete. - try { - var $fields_multiple = $(searchInputs); + if (!!(match = term.match(Autocomplete.METATAGS))) { + metatag = match[1].toLowerCase(); + term = match[2]; + } - var prefixes = "-~"; - var metatags = "status|rating|parent|child|user|pool|group|g|isfav|userid|taggerid|approverid|source|id|score|favcount|height|width"; + return {metatag: metatag, term: term}; + }; - $fields_multiple.autocomplete({ - delay: 100, - autoFocus: false, - focus: function() { return false; }, - select: function(event, ui) { - var before_caret_text = this.value.substring(0, this.selectionStart); - var after_caret_text = this.value.substring(this.selectionStart); - var regexp = new RegExp("([" + prefixes + "]*)\\S+$", "g"); + Autocomplete.insert_completion = function(input, completion) { + var before_caret_text = input.value.substring(0, input.selectionStart); + var after_caret_text = input.value.substring(input.selectionStart); - this.value = before_caret_text.replace(regexp, "$1" + ui.item.value + " "); + var prefixes = "-~"; + var regexp = new RegExp("([" + prefixes + "]*)\\S+$", "g"); + before_caret_text = before_caret_text.replace(regexp, "$1") + completion + " "; - var original_start = this.selectionStart; + input.value = before_caret_text + after_caret_text; + input.selectionStart = input.selectionEnd = before_caret_text.length; + }; - this.value += after_caret_text; - this.selectionStart = this.selectionEnd = original_start; + Autocomplete.on_tab = function(event) { + var input = this; + var autocomplete = $(input).autocomplete("instance"); + var $autocomplete_menu = autocomplete.menu.element; - return false; - }, - source: function(req, resp) { - var before_caret_text = req.term.substring(req.term.substring(0, this.element.get(0).selectionStart).lastIndexOf("\n"), this.element.get(0).selectionStart); + if (!$autocomplete_menu.is(":visible")) + return; - if (before_caret_text.match(/ $/)) { - this.close(); - return; - } + if ($autocomplete_menu.has(".ui-state-active").length === 0) { + var $first_item = $autocomplete_menu.find(".ui-menu-item").first(); + var completion = $first_item.data().uiAutocompleteItem.value; - var term = before_caret_text.match(/\S+/g).pop(); - var regexp = new RegExp("^[" + prefixes + "]*(.*)$", "i"); - var match = term.match(regexp); - var metatag; + Autocomplete.insert_completion(input, completion); + autocomplete.close(); + } - if (match) - term = match[1]; + event.preventDefault(); + }; - if (term === "") - return; + Autocomplete.render_item = function(list, item) { + var $link = $(""); + $link.text(item.label); + $link.attr("href", "/posts?tags=" + encodeURIComponent(item.value)); + $link.click(function(e) {e.preventDefault();}); - regexp = new RegExp("^(" + metatags + "):(.*)$", "i"); - match = term.match(regexp); + if (item.antecedent) { + var antecedent = item.antecedent.replace(/_/g, " "); + var arrow = $("").html(" → ").addClass("autocomplete-arrow"); + var antecedent_element = $("").text(antecedent).addClass("autocomplete-antecedent"); - if (match) { - metatag = match[1].toLowerCase(); - term = match[2]; - } + $link.prepend([antecedent_element, arrow]); + } - switch(metatag) { - case "userid": - case "taggerid": - case "id": - case "score": - case "favcount": - case "height": - case "width": - this.close(); - return; - case "status": - case "rating": - case "parent": - case "child": - case "group": - case "g": - case "isfav": - case "pool": - case "source": - case "approverid": - Danbooru.Autocomplete.static_metatag_source(term, resp, metatag); - return; - } + if (item.post_count !== undefined) { + var count = item.post_count; - if (term === "") - return; + if (count >= 1000) + count = Math.floor(count / 1000) + "k"; - switch(metatag) { - case "user": - Danbooru.Autocomplete.user_source(term, resp, metatag); - break; - default: - Danbooru.Autocomplete.normal_source(term, resp); - break; - } + var $post_count = $("").addClass("post-count").css("float", "right").text(count); + + $link.append($post_count); } - }); - $fields_multiple.on("autocompleteselect", function() { Danbooru.autocompleting = true; }); - $fields_multiple.on("autocompleteclose", function() { setTimeout(function() {Danbooru.autocompleting = false;}, 100); }); - $fields_multiple.each(function(i, field) { $(field).data("uiAutocomplete")._renderItem = Danbooru.Autocomplete.render_item; }); + if (item.type === "tag" || item.type === "metatag") + $link.addClass("tag-type-" + item.category); + else if (item.type === "user") { + var level_class = "user-" + item.level.toLowerCase(); + + $link.addClass(level_class); + + if (Danbooru.Utility.meta("style-usernames") === "true") + $link.addClass("with-style"); + } + + var $menu_item = $("
").append($link); + + return $("
  • ").data("item.autocomplete", item).append($menu_item).appendTo(list); + }; + + var groups = []; + + for (var i = 0, il = tag_groups.length; i < il; i++) + groups.push(tag_groups[i].name); + + Autocomplete.static_metatags = { + status: ["any", "deleted", "active", "pending", "flagged", "banned"], + rating: ["safe", "questionable", "explicit"], + child: ["any", "none"], + parent: ["any", "none"], + filetype: ["jpg", "png", "gif", "swf", "zip", "webm", "mp4"], + isfav: ["true", "false"], + pool: ["series", "collection", "any", "none", "active", "inactive"], + source: ["any", "none"], + approverid: ["any", "none"], + group: groups, + g: groups + }; + + Autocomplete.static_metatag_source = function(term, resp, metatag) { + var sub_metatags = this.static_metatags[metatag]; + + var regexp = new RegExp("^" + $.ui.autocomplete.escapeRegex(term), "i"); + var matches = $.grep(sub_metatags, function (sub_metatag) { + return regexp.test(sub_metatag); + }); + + var d = $.map(matches, function(sub_metatag) { + return {type: "metatag", category: 5, label: sub_metatag, value: metatag + ":" + sub_metatag}; + }); + + if (d.length > 10) + d = d.slice(0, 10); + + resp(d); + }; + + Autocomplete.user_source = function(term, resp, metatag) { + $.ajax({ + url: "/users.json", + data: {"search[order]": "post_upload_count", "search[current_user_first]": "true", "search[name_matches]": term + "*", "limit": 10}, + method: "get", + success: function(data) { + var display_name = function(name) {return name.replace(/_/g, " ");}; + + resp($.map(data, function(user) { + return {type: "user", label: display_name(user.name), value: metatag + ":" + user.name, level: user.level_string}; + })); + } + }); + }; - // Make autocomplete fixed like the quick search and menu and allow it to be on top of inputs if there is more space there. - $(searchInputs).autocomplete("widget").css("position", "fixed"); - $(searchInputs).autocomplete("option", "position", {my: "left top", at: "left bottom", collision: "flip"}); + Autocomplete.initialize_all(); } catch (error) { bbbNotice("Unexpected error while trying to initialize autocomplete. (Error: " + error.message + ")", -1); } + + } + + function bbbAutocomplete(searchInputs) { + // Apply a modified copy of Danbooru's autocomplete to inputs after Danbooru has finished. + delayMe(function() { + if (!bbb.autocomplete.AUTOCOMPLETE_VERSION) + bbbAutocompleteInit(); + + try { + var Autocomplete = bbb.autocomplete; + var $fields_multiple = $(searchInputs); + + $fields_multiple.autocomplete({ + search: function() { + if ($(this).data("ui-autocomplete")) + $(this).data("ui-autocomplete").menu.bindings = $(); + }, + select: function(event, ui) { + if (event.key === "Enter") + event.stopImmediatePropagation(); + + Autocomplete.insert_completion(this, ui.item.value); + return false; + }, + source: function(req, resp) { + var query = Autocomplete.parse_query(req.term, this.element.get(0).selectionStart); + var metatag = query.metatag; + var term = query.term; + + if (!metatag && !term) { + this.close(); + return; + } + + switch (metatag) { + case "userid": + case "taggerid": + case "id": + case "score": + case "favcount": + case "height": + case "width": + resp([]); + return; + case "status": + case "rating": + case "parent": + case "child": + case "group": + case "g": + case "isfav": + case "pool": + case "source": + case "filetype": + case "approverid": + Autocomplete.static_metatag_source(term, resp, metatag); + return; + case "user": + Autocomplete.user_source(term, resp, metatag); + break; + default: + Autocomplete.normal_source(term, resp); + break; + } + } + }); + + // Make autocomplete fixed like the quick search and menu and allow it to be on top of inputs if there is more space there. + $(searchInputs).autocomplete("widget").css("position", "fixed"); + $(searchInputs).autocomplete("option", "position", {my: "left top", at: "left bottom", collision: "flip"}); + } + catch (error) { + bbbNotice("Unexpected error while trying to initialize autocomplete. (Error: " + error.message + ")", -1); + } + }); } function menuAutocomplete(searchInputs) { // Use autocomplete on a BBB menu input if allowed by the option. - if (enable_menu_autocomplete && Danbooru.Autocomplete) + if (enable_menu_autocomplete) bbbAutocomplete(searchInputs); } @@ -10382,7 +10459,7 @@ function bbbScript() { // Wrapper for injecting the script into the document. // Use autocomplete on an input outside of the BBB menu if allowed for Danbooru. var allowAutocomplete = (getMeta("enable-auto-complete") === "true"); - if (allowAutocomplete && Danbooru.Autocomplete) + if (allowAutocomplete) bbbAutocomplete(searchInputs); } diff --git a/changelog.md b/changelog.md index 6dbc272..6c2d227 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,13 @@ Changelog ---------- +* Version 8.2.2: + * Added "filetype" to the script metatags. + * Updated to support Danbooru's new orange metatags. + * Updated to support Danbooru's ugoira update. + * Updated to support Danbooru's autocomplete update. + * Updated to support Danbooru's normalized source update. + * Fixed the "post tag titles" option. + * Fixed the mark link for the "track new posts" listing when using endless pages. * Version 8.2.1: * Added "Shift + E" as a hotkey for loading more pages when endless pages pauses. * Added "Control + Left Click" on the quick search icon as a shortcut for negating the current search.