Sleazy Fork is available in English.

Danbooru Ajax Interface

New interface to search images on Booru-style sites.

14.07.2015 itibariyledir. En son verisyonu görün.

  1. // ==UserScript==
  2. // @name Danbooru Ajax Interface
  3. // @namespace http://danbooru.donmai.us
  4. // @description New interface to search images on Booru-style sites.
  5.  
  6. // @include http://danbooru.donmai.us/
  7. // @include http://danbooru.donmai.us/#*
  8. // @include http://www.donmai.us/
  9. // @include http://www.donmai.us/#*
  10. // @include http://donmai.us/
  11. // @include http://donmai.us/#*
  12.  
  13. // @include http://gelbooru.com/
  14. // @include http://gelbooru.com/#*
  15. // @include http://www.gelbooru.com/
  16. // @include http://www.gelbooru.com/#*
  17.  
  18. // @include http://konachan.com/
  19. // @include http://konachan.com/#*
  20. // @include http://konachan.net/
  21. // @include http://konachan.net/#*
  22.  
  23. // @include https://yande.re/post
  24. // @include https://yande.re/post#*
  25.  
  26. // @version 0.3
  27. // @grant GM_addStyle
  28. // @grant GM_getValue
  29. // @grant GM_setValue
  30. // @grant GM_xmlhttpRequest
  31. // ==/UserScript==
  32.  
  33. // CONSTANTS
  34. const ratio = ((1 + Math.sqrt(5)) / 2);
  35. const d = document;
  36.  
  37. // NEW SITES CAN BE ADDED NOW
  38. var sites = [
  39. {
  40. name : "Danbooru", // Site name
  41. site : "donmai\.us", // Regular expression check on current url
  42. post : "/post/index.xml", // Relative url to xml post API
  43. note : "/note_versions.xml", // Relative url to xml note API
  44. list : "/posts/", // Relative url to post listing
  45. page : "/posts/", // Relative url to post page
  46. query : function(tags, images, page, postid) { // Query passed to API
  47. login = btoa(/user_name=(.*?)(;|$)/.test(d.cookie) ? (d.cookie.match("user_name=(.*?)(;|$)")[1]) : "");
  48. passhash = btoa(/password_hash=(.*?)(;|$)/.test(d.cookie) ? (d.cookie.match("password_hash=(.*?)(;|$)")[1]) : "");
  49. apiquery = "?login=" + atob(login) + "&passhash=" + atob(passhash);
  50. apiquery += tags ? "&tags=" + tags : "";
  51. apiquery += images ? "&limit=" + images : "";
  52. apiquery += page ? "&page=" + page : "";
  53. apiquery += postid ? "&search[post_id]=" + postid : "";
  54. return (apiquery);
  55. }
  56. },
  57. {
  58. name : "Gelbooru",
  59. site : "(www\.)?gelbooru\.",
  60. post : "/index.php?page=dapi&s=post&q=index",
  61. note : "/index.php?page=dapi&s=note&q=index&post_id=",
  62. list : "/index.php?page=post&s=list",
  63. page : "/index.php?page=post&s=view&id=",
  64. query : function(tags, images, page, postid) {
  65. return (postid ? postid : "&tags=" + tags + "&limit=" + images + "&pid=" + (page - 1));
  66. }
  67. },
  68. {
  69. name : "Konachan",
  70. site : "konachan\.",
  71. post : "/post.xml",
  72. note : "/note.xml?post_id=",
  73. list : "/post/",
  74. page : "/post/show/",
  75. query : function(tags, images, page, postid) {
  76. return (postid ? postid : "?tags=" + tags + "&limit=" + images + "&page=" + page);
  77. }
  78. },
  79. {
  80. name : "Yande.re",
  81. site : "yande\.re",
  82. post : "/post.xml",
  83. note : "/note.xml?post_id=",
  84. list : "/post/",
  85. page : "/post/show/",
  86. query : function(tags, images, page, postid) {
  87. return (postid ? postid : "?tags=" + tags + "&limit=" + images + "&page=" + page);
  88. }
  89. }
  90. ];
  91.  
  92. var booru;
  93. for(var i = 0; i < sites.length; i++)
  94. if(new RegExp(sites[i].site).test(window.location.hostname))
  95. booru = sites[i];
  96.  
  97. var alltags = GM_getValue("tags", setDefaults("alltags", sites.length));
  98. var allpage = GM_getValue("page", setDefaults("allpage", sites.length));
  99. var allimages = GM_getValue("images", setDefaults("allimages", sites.length));
  100. var allcolumns = GM_getValue("columns", setDefaults("allcolumns", sites.length));
  101. var allrating = GM_getValue("rating", setDefaults("allrating", sites.length));
  102.  
  103. // PAGE CLEANING
  104. while(d.documentElement.firstChild)
  105. d.documentElement.removeChild(d.documentElement.firstChild);
  106.  
  107. d.documentElement.appendChild(d.createElement("HEAD"));
  108. d.documentElement.appendChild(d.createElement("BODY"));
  109. d.documentElement.firstChild.appendChild(title = d.createElement("TITLE"));
  110. title.appendChild(d.createTextNode(booru.name));
  111.  
  112. GM_addStyle("* { transition: all 2s ease-in-out 0s; } a { text-decoration: none; color: #0000EE; } img { border: 0px; } .thumb { border: 1px solid WhiteSmoke; text-align: center; vertical-align: middle; min-width: 150px; min-height: 150px; padding: 1px; line-height: 10px; }");
  113.  
  114. // SCRIPT STARTS HERE
  115. var tags = getValue("alltags", alltags);
  116. var page = getValue("allpage", allpage);
  117. var images = getValue("allimages", allimages);
  118. var columns = getValue("allcolumns", allcolumns);
  119. var rating = getValue("allrating", allrating);
  120.  
  121. var searchTable, searchTr, searchTd, searchForm, aLink, aTags, aReply, aTableBar, aLeftBar, aCenterBar, aRightBar, aTable, aTr1, aTd1, aTd2, aPage, aTd3, aRS, aRQ, aRE, aFIT, aSD, aTr2, aTd4, aTd5, aImages, aTr3, aTd6, aTd7, aColumns, aPrev, aSearch, aNext, aTagsDisplay, imagesLayer, overlay, display, displayDiv, sampleRate = 1;
  122.  
  123. d.body.appendChild(searchTable = d.createElement("TABLE"));
  124. searchTable.appendChild(searchTr = d.createElement("TR"));
  125. searchTr.setAttribute("style", "vertical-align: top;");
  126. searchTr.appendChild(searchTd = d.createElement("TD"));
  127. searchTd.setAttribute("style", "text-align: center;");
  128.  
  129. searchForm = d.createElement("FORM");
  130. searchForm.addEventListener("submit", function(event) {
  131. tags = aTags.value;
  132. page = Math.max(1, parseInt(aPage.value, 10));
  133. images = Math.max(1, Math.min(parseInt(aImages.value, 10), 100));
  134. columns = Math.max(1, parseInt(aColumns.value, 10));
  135. rating = (aRS.checked ? "s" : "") + (aRQ.checked ? "q" : "") + (aRE.checked ? "e" : "") + (aFIT.checked ? "f" : "");
  136.  
  137. allimages = setValue("images", allimages, images);
  138. allcolumns = setValue("columns", allcolumns, columns);
  139. allrating = setValue("rating", allrating, rating);
  140.  
  141. search(tags, page);
  142. event.preventDefault();
  143. }, false);
  144.  
  145. searchForm.appendChild(aLink = d.createElement("A"));
  146. aLink.setAttribute("href", booru.list);
  147. aLink.appendChild(d.createTextNode(booru.name));
  148.  
  149. searchForm.appendChild(d.createElement("BR"));
  150.  
  151. searchForm.appendChild(aTags = d.createElement("INPUT"));
  152. aTags.setAttribute("type", "text");
  153. aTags.setAttribute("cols", 25);
  154. aTags.setAttribute("value", tags);
  155. aTags.setAttribute("tabindex", "1");
  156. aTags.addEventListener("change", function(event) {
  157. aPage.value = 1;
  158. }, false);
  159.  
  160. searchForm.appendChild(d.createElement("P"));
  161.  
  162. searchForm.appendChild(aReply = d.createElement("SPAN"));
  163. aReply.appendChild(d.createTextNode("Nobody here but us chickens!"));
  164.  
  165. searchForm.appendChild(d.createElement("P"));
  166.  
  167. // Slider
  168. aTableBar = d.createElement("TABLE");
  169. aTableBar.appendChild(d.createElement("TR"));
  170. aTableBar.setAttribute("style", "border: 1px solid Black; border-collapse: collapse; width: 100%;");
  171. aLeftBar = d.createElement("TD");
  172. aLeftBar.setAttribute("style", "padding: 0px;");
  173. aTableBar.firstChild.appendChild(aLeftBar);
  174. aCenterBar = d.createElement("TD");
  175. aCenterBar.setAttribute("style", "border: 1px solid Black; padding: 0px; padding-top: 3px; background-color: WhiteSmoke; width: 25%; min-width: 1px");
  176. aTableBar.firstChild.appendChild(aCenterBar);
  177. aRightBar = d.createElement("TD");
  178. aRightBar.setAttribute("style", "padding: 0px; width: 100%;");
  179. aTableBar.firstChild.appendChild(aRightBar);
  180. searchForm.appendChild(aTableBar);
  181.  
  182. aTable = d.createElement("TABLE");
  183. aTr1 = d.createElement("TR");
  184. aTd1 = d.createElement("TD");
  185. aTd1.appendChild(d.createTextNode("Page:"));
  186. aTr1.appendChild(aTd1);
  187.  
  188. aTd2 = d.createElement("TD");
  189. aPage = d.createElement("INPUT");
  190. aPage.setAttribute("type", "text");
  191. aPage.setAttribute("size", "1");
  192. aPage.setAttribute("value", page);
  193. aPage.setAttribute("tabindex", "2");
  194. aTd2.appendChild(aPage);
  195. aTr1.appendChild(aTd2);
  196.  
  197. aTd3 = d.createElement("TD");
  198. aTd3.setAttribute("rowspan", "3");
  199. aTd3.setAttribute("align", "left");
  200.  
  201. aRS = d.createElement("INPUT");
  202. aRS.setAttribute("type", "checkbox");
  203. if(/s/.test(rating)) aRS.setAttribute("checked", "checked");
  204. aTd3.appendChild(aRS);
  205. aTd3.appendChild(d.createTextNode("Safe"));
  206. aTd3.appendChild(d.createElement("BR"));
  207.  
  208. aRQ = d.createElement("INPUT");
  209. aRQ.setAttribute("type", "checkbox");
  210. if(/q/.test(rating)) aRQ.setAttribute("checked", "checked");
  211. aTd3.appendChild(aRQ);
  212. aTd3.appendChild(d.createTextNode("Questionable"));
  213. aTd3.appendChild(d.createElement("BR"));
  214.  
  215. aRE = d.createElement("INPUT");
  216. aRE.setAttribute("type", "checkbox");
  217. if(/e/.test(rating)) aRE.setAttribute("checked", "checked");
  218. aTd3.appendChild(aRE);
  219. aTd3.appendChild(d.createTextNode("Explicit"));
  220. aTd3.appendChild(d.createElement("BR"));
  221.  
  222. aFIT = d.createElement("INPUT");
  223. aFIT.setAttribute("type", "checkbox");
  224. if(/f/.test(rating)) aFIT.setAttribute("checked", "checked");
  225. aTd3.appendChild(aFIT);
  226. aTd3.appendChild(d.createTextNode("Fit width"));
  227. aTd3.appendChild(d.createElement("BR"));
  228.  
  229. aSD = d.createElement("INPUT");
  230. aSD.setAttribute("type", "checkbox");
  231.  
  232. aTr1.appendChild(aTd3);
  233. aTable.appendChild(aTr1);
  234.  
  235. aTr2 = d.createElement("TR");
  236. aTd4 = d.createElement("TD");
  237. aTd4.appendChild(d.createTextNode("Images:"));
  238. aTr2.appendChild(aTd4);
  239.  
  240. aTd5 = d.createElement("TD");
  241. aImages = d.createElement("INPUT");
  242. aImages.setAttribute("type", "text");
  243. aImages.setAttribute("size", "1");
  244. aImages.setAttribute("value", images);
  245. aImages.setAttribute("tabindex", "3");
  246. aTd5.appendChild(aImages);
  247. aTr2.appendChild(aTd5);
  248. aTable.appendChild(aTr2);
  249.  
  250. aTr3 = d.createElement("TR");
  251. aTd6 = d.createElement("TD");
  252. aTd6.appendChild(d.createTextNode("Columns:"));
  253. aTr3.appendChild(aTd6);
  254.  
  255. aTd7 = d.createElement("TD");
  256. aColumns = d.createElement("INPUT");
  257. aColumns.setAttribute("type", "text");
  258. aColumns.setAttribute("size", "1");
  259. aColumns.setAttribute("value", columns);
  260. aColumns.setAttribute("tabindex", "4");
  261. aTd7.appendChild(aColumns);
  262. aTr3.appendChild(aTd7);
  263. aTable.appendChild(aTr3);
  264. searchForm.appendChild(aTable);
  265.  
  266. searchForm.appendChild(d.createElement("HR"));
  267.  
  268. searchForm.appendChild(aPrev = d.createElement("INPUT"));
  269. aPrev.setAttribute("type", "button");
  270. aPrev.setAttribute("value", "<");
  271. aPrev.setAttribute("disabled", "disabled");
  272. aPrev.addEventListener("click", function(event) {
  273. search(tags, --page);
  274. }, false);
  275.  
  276. searchForm.appendChild(aSearch = d.createElement("INPUT"));
  277. aSearch.setAttribute("type", "submit");
  278. aSearch.setAttribute("value", "Search");
  279.  
  280. searchForm.appendChild(aNext = d.createElement("INPUT"));
  281. aNext.setAttribute("type", "button");
  282. aNext.setAttribute("value", ">");
  283. aNext.setAttribute("disabled", "disabled");
  284. aNext.addEventListener("click", function(event) {
  285. search(tags, ++page);
  286. }, false);
  287.  
  288. searchForm.appendChild(d.createElement("HR"));
  289.  
  290. searchForm.appendChild(aTagsDisplay = d.createElement("DIV"));
  291. aTagsDisplay.setAttribute("style", "overflow-x: hidden;");
  292.  
  293. searchTd.appendChild(searchForm);
  294. searchTr.appendChild(imagesLayer = d.createElement("TD"));
  295.  
  296. searchTd.style.setProperty("min-width", (searchTd.getBoundingClientRect().right - searchTd.getBoundingClientRect().left) + "px", "important");
  297. searchTd.style.setProperty("max-width", (searchTd.getBoundingClientRect().right - searchTd.getBoundingClientRect().left) + "px", "important");
  298.  
  299. // "Lightbox"
  300. overlay = d.createElement("DIV");
  301. overlay.setAttribute("style", "opacity: 0.75; display: none; background-color: Black; width: 100%; height: 100%; position: fixed; top: 0px; left: 0px");
  302. display = d.createElement("TABLE");
  303. display.setAttribute("style", "display: none; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; text-align: center; vertical-align: middle");
  304. displayDiv = d.createElement("DIV");
  305. displayDiv.setAttribute("id", "displayDiv");
  306. displayDiv.setAttribute("style", "background-color: White; display: inline-block; padding: 10px; min-width: 200px; min-height: 200px; border-radius: 10px");
  307.  
  308. display.appendChild(d.createElement("TR"));
  309. display.firstChild.appendChild(d.createElement("TD"));
  310. display.firstChild.firstChild.appendChild(displayDiv);
  311.  
  312. d.body.insertBefore(display, d.body.firstChild);
  313. d.body.insertBefore(overlay, d.body.firstChild);
  314.  
  315. if(!window.location.origin)
  316. window.location.origin = (window.location.protocol + "//" + window.location.host);
  317.  
  318. if(window.location.hash)
  319. search(window.location.hash.split("#")[1], 1);
  320.  
  321. var requestPost, requestNote, requestCount;
  322.  
  323. function search(newtags, newpage) {
  324. /*
  325. if(requestPost)
  326. requestPost.abort();
  327. if(requestNote)
  328. requestNote.abort();
  329. if(requestCount)
  330. requestCount.abort();
  331. */
  332. aTags.value = tags = newtags;
  333. aPage.value = page = newpage;
  334. aImages.value = images;
  335.  
  336. alltags = setValue("tags", alltags, tags);
  337. allpage = setValue("page", allpage, page);
  338.  
  339. aPrev.disabled = (newpage < 2);
  340. aRS.checked = /s/.test(rating);
  341. aRQ.checked = /q/.test(rating);
  342. aRE.checked = /e/.test(rating);
  343. // aFIT.checked = /f/.test(rating);
  344.  
  345. if(/^sf?$/.test(rating))
  346. newtags += " rating:safe";
  347. if(/^qf?$/.test(rating))
  348. newtags += " rating:questionable";
  349. if(/^ef?$/.test(rating))
  350. newtags += " rating:explicit";
  351. if(/^qef?$/.test(rating))
  352. newtags += " -rating:safe";
  353. if(/^sef?$/.test(rating))
  354. newtags += " -rating:questionable";
  355. if(/^sqf?$/.test(rating))
  356. newtags += " -rating:explicit";
  357.  
  358. if(imagesLayer.hasChildNodes())
  359. imagesLayer.removeChild(imagesLayer.firstChild);
  360.  
  361. imagesLayer.appendChild(d.createTextNode("Loading..."));
  362. requestPost = GM_xmlhttpRequest({
  363. method : "GET",
  364. url : window.location.origin + booru.post + booru.query(encodeURIComponent(newtags), images, page),
  365. headers: { "Accept" : "application/xml" },
  366. overrideMimeType : "application/xml; charset=utf-8",
  367. onload : function(response) {
  368. getContent(new DOMParser().parseFromString(response.responseText, "application/xml"), newtags);
  369. }
  370. });
  371. }
  372.  
  373. function showContent(xmldoc) {
  374. if(imagesLayer.hasChildNodes())
  375. imagesLayer.removeChild(imagesLayer.firstChild);
  376.  
  377. aReply.textContent = "Nobody here but us chickens!";
  378.  
  379. var posts = xmldoc.evaluate("posts", xmldoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  380. if(!posts) {
  381. reason = xmldoc.evaluate("response/@reason", xmldoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  382. if(reason)
  383. imagesLayer.textContent = reason.nodeValue;
  384. else
  385. imagesLayer.textContent = "Something broke.";
  386. return;
  387. }
  388. var post = xmldoc.evaluate("posts/post", xmldoc, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  389. if((parseInt(posts.getAttribute("offset"), 10) + 1) > posts.getAttribute("count")) {
  390. search(tags, Math.ceil(parseInt(posts.getAttribute("count"), 10) / images));
  391. return;
  392. }
  393. aReply.textContent = "Found " + posts.getAttribute("count") + ", showing " + (parseInt(posts.getAttribute("offset"), 10) + 1) + "-" + (Math.min(posts.getAttribute("count"), parseInt(posts.getAttribute("offset"), 10) + images));
  394. aLeftBar.style.setProperty("width", (posts.getAttribute("offset") / posts.getAttribute("count") * 100) + "%");
  395. aCenterBar.style.setProperty("width", (images / posts.getAttribute("count") * 100) + "%");
  396.  
  397. aNext.disabled = (page >= Math.ceil(posts.getAttribute("count") / images));
  398.  
  399. imagesLayer.appendChild(table = d.createElement("TABLE"));
  400. table.setAttribute("style", "border-collapse: collapse;");
  401.  
  402. for(var i = 0; i < Math.ceil(images / columns); i++) {
  403. table.appendChild(tr = d.createElement("TR"));
  404. for(var j = 0; j < Math.min(columns, images); j++) {
  405. tr.appendChild(td = d.createElement("TD"));
  406. data = post.snapshotItem(i * Math.min(columns, images) + j);
  407. if(data) {
  408. if(/true/.test(data.getAttribute("has_notes")))
  409. td.style.setProperty("background-color", "LightYellow", "");
  410. if(/deleted/.test(data.getAttribute("status")))
  411. td.style.setProperty("background-color", "MistyRose", "");
  412.  
  413. var image = d.createElement("IMG");
  414. image.setAttribute("width", (data.getAttribute("preview_width") || ""));
  415. image.setAttribute("height", (data.getAttribute("preview_height") || ""));
  416. image.setAttribute("src", data.getAttribute("preview_url"));
  417. image.setAttribute("id", data.getAttribute("id"));
  418. image.setAttribute("alt", data.getAttribute("tags").trim());
  419. image.setAttribute("title", data.getAttribute("tags").trim() + " rating:" + data.getAttribute("rating").replace(/e$/, "Explicit").replace(/s$/, "Safe").replace(/q$/, "Questionable") + " score:" + data.getAttribute("score"));
  420. image.setAttribute("fullsize", data.getAttribute("file_url"));
  421. image.setAttribute("fullwidth", data.getAttribute("width"));
  422. image.setAttribute("fullheight", data.getAttribute("height"));
  423. image.setAttribute("notes", data.getAttribute("has_notes"));
  424. image.setAttribute("md5", data.getAttribute("md5"));
  425.  
  426. // Show tags on sidebar
  427. image.addEventListener("click", function(event) {
  428. if(aTagsDisplay.hasChildNodes())
  429. aTagsDisplay.removeChild(aTagsDisplay.firstChild);
  430. aTagsDisplay.appendChild(d.createElement("DIV"));
  431.  
  432. var tagnames = this.getAttribute("alt").split(" ");
  433. for(var t = 0; t < tagnames.length; t++) {
  434. var taglink = d.createElement("A");
  435. taglink.appendChild(d.createTextNode(tagnames[t]));
  436. taglink.setAttribute("href", "#" + tagnames[t]);
  437. taglink.addEventListener("click", function(event) {
  438. aTags.value = this.textContent;
  439. aPage.value = 1;
  440. aSearch.click();
  441. event.preventDefault();
  442. }, false);
  443. aTagsDisplay.firstChild.appendChild(taglink);
  444. aTagsDisplay.firstChild.appendChild(document.createElement("BR"));
  445. }
  446.  
  447. // CTRL + click to show only the tags
  448. if(event.ctrlKey) return;
  449.  
  450. // "Lightbox" by VIPPER ("How do I jQuery?")
  451. while(displayDiv.hasChildNodes())
  452. displayDiv.removeChild(displayDiv.firstChild);
  453.  
  454. overlay.addEventListener("click", function(event) {
  455. if(event.target.id) return;
  456. overlay.style.setProperty("display", "none", "");
  457. display.style.setProperty("display", "none", "");
  458. }, false);
  459.  
  460. display.addEventListener("click", function(event) {
  461. if(event.target.id) return;
  462. overlay.style.setProperty("display", "none", "");
  463. display.style.setProperty("display", "none", "");
  464. }, false);
  465.  
  466. display.addEventListener("dblclick", function(event) {
  467. overlay.style.setProperty("display", "none", "");
  468. display.style.setProperty("display", "none", "");
  469. }, false);
  470.  
  471. if(/\.swf$/.test(this.getAttribute("fullsize"))) {
  472. fullsize = d.createElement("EMBED");
  473. } else {
  474. fullsize = d.createElement("IMG");
  475. fullsize.addEventListener("click", function(event) {
  476. noteDivs = d.evaluate("//DIV[starts-with(@id, 'note')]", d, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  477. for(var n = 0, note = null; note = noteDivs.snapshotItem(n++); n) {
  478. if(window.getComputedStyle(note, null).getPropertyValue("visibility") == "visible")
  479. note.style.setProperty("visibility", "hidden", "");
  480. else
  481. note.style.setProperty("visibility", "visible", "");
  482. }
  483. }, false);
  484. }
  485. fullsize.setAttribute("src", this.getAttribute("fullsize"));
  486. sampleRate = 1;
  487. fullsize.setAttribute("width", this.getAttribute("fullwidth"));
  488. fullsize.setAttribute("height", this.getAttribute("fullheight"));
  489. var clientwidth = Math.min(d.documentElement.clientWidth, d.body.clientWidth) - 30;
  490. if(aFIT.checked && this.getAttribute("fullwidth") > clientwidth) {
  491. sampleRate = clientwidth / this.getAttribute("fullwidth");
  492. fullsize.setAttribute("width", clientwidth + "px");
  493. fullsize.setAttribute("height", Math.floor(this.getAttribute("fullheight") * clientwidth / this.getAttribute("fullwidth")) + "px");
  494. }
  495. fullsize.setAttribute("id", this.getAttribute("id"));
  496. fullsize.setAttribute("notes", this.getAttribute("notes"));
  497. fullsize.setAttribute("md5", this.getAttribute("md5"));
  498.  
  499. if(fullsize.getAttribute("notes") == "true") {
  500. requestNote = GM_xmlhttpRequest({
  501. method : "GET",
  502. url : window.location.origin + booru.note + booru.query(null, 10000, null, fullsize.getAttribute("id")),
  503. headers: { "Accept" : "application/xml" },
  504. overrideMimeType : "application/xml; charset=utf-8",
  505. onload : function(response) {
  506. getNotes(new DOMParser().parseFromString(response.responseText, "application/xml"), response.finalUrl);
  507. }
  508. });
  509. }
  510.  
  511. var pagelink = d.createElement("A");
  512. pagelink.setAttribute("href", booru.page + fullsize.getAttribute("id"));
  513. pagelink.appendChild(d.createTextNode(fullsize.getAttribute("id")));
  514.  
  515. displayDiv.appendChild(fullsize);
  516. displayDiv.appendChild(d.createElement("BR"));
  517. displayDiv.appendChild(pagelink);
  518.  
  519. overlay.style.setProperty("display", "", "");
  520. display.style.setProperty("display", "", "");
  521. }, false);
  522.  
  523. var link = d.createElement("A");
  524. link.setAttribute("href", data.getAttribute("file_url"));
  525. link.setAttribute("alt", data.getAttribute("id"));
  526. link.appendChild(image);
  527. link.addEventListener("click", function(event) {
  528. event.preventDefault();
  529. }, false);
  530. td.setAttribute("class", "thumb");
  531. td.appendChild(link);
  532. }
  533. }
  534. }
  535. }
  536.  
  537. function getContent(xmldoc, newtags) {
  538. if(booru.name == "Danbooru") { // Inject the count where it should be by default...
  539. requestCount = GM_xmlhttpRequest({
  540. method : "GET",
  541. url : window.location.origin + "/counts/posts.xml" + booru.query(encodeURIComponent(newtags)),
  542. headers: { "Accept" : "application/xml" },
  543. overrideMimeType : "application/xml; charset=utf-8",
  544. onload : function(response) {
  545. newxmldoc = new DOMParser().parseFromString(response.responseText, "application/xml");
  546. posts = xmldoc.evaluate("posts", xmldoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  547. count = newxmldoc.evaluate("counts/posts", newxmldoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  548. if(posts) {
  549. posts.setAttribute("count", count ? count.textContent.trim() : "0");
  550. posts.setAttribute("offset", (page - 1) * images);
  551. }
  552. showContent(xmldoc);
  553. }
  554. });
  555. } else {
  556. showContent(xmldoc);
  557. }
  558. }
  559.  
  560. function showNotes(note, id) {
  561. var offsetx = fullsize.getBoundingClientRect().left + (d.documentElement.scrollLeft || d.body.scrollLeft);
  562. var offsety = fullsize.getBoundingClientRect().top + (d.documentElement.scrollTop || d.body.scrollTop);
  563. var vp_bottom = Math.max(window.innerHeight, displayDiv.getBoundingClientRect().bottom - displayDiv.getBoundingClientRect().top);
  564.  
  565. for(var i = 0, ndata = null; ndata = note.snapshotItem(i++); i) {
  566. if(id.match(/[0-9]+$/)[0] != fullsize.getAttribute("id")) continue;
  567. if(d.getElementById("note" + ndata.getAttribute("id"))) continue;
  568.  
  569. var ntop = (parseInt(ndata.getAttribute("y"), 10) + offsety) * sampleRate;
  570. var nleft = (parseInt(ndata.getAttribute("x"), 10) + offsetx) * sampleRate;
  571.  
  572. var noteDiv = d.createElement("DIV");
  573. noteDiv.setAttribute("id", "note" + ndata.getAttribute("id"));
  574. noteDiv.setAttribute("class", "trans");
  575. noteDiv.setAttribute("style", "opacity: 0.4; border: 1px solid Black; background-color: LightYellow; position: absolute;");
  576. noteDiv.style.setProperty("top", ntop + "px", "");
  577. noteDiv.style.setProperty("left", nleft + "px", "");
  578. noteDiv.style.setProperty("width", ndata.getAttribute("width") * sampleRate + "px", "");
  579. noteDiv.style.setProperty("height", ndata.getAttribute("height") * sampleRate + "px", "");
  580. noteDiv.addEventListener("mouseover", function(event) {
  581. d.getElementById("body" + this.getAttribute("id")).style.setProperty("display", "", "");
  582. }, false);
  583. noteDiv.addEventListener("mouseout", function(event) {
  584. d.getElementById("body" + this.getAttribute("id")).style.setProperty("display", "none", "");
  585. }, false);
  586. displayDiv.appendChild(noteDiv);
  587.  
  588. var noteBody = d.createElement("DIV");
  589. noteBody.innerHTML = ndata.getAttribute("body");
  590. noteBody.setAttribute("id", "bodynote" + ndata.getAttribute("id"));
  591. noteBody.setAttribute("class", "trans");
  592. noteBody.setAttribute("style", "border: 1px solid Black; background-color: LightYellow; position: absolute; color: Black; text-align: left; padding: 4px; z-index: 1" + i + ";");
  593. noteBody.addEventListener("mouseover", function(event) {
  594. this.style.setProperty("display", "", "");
  595. }, false);
  596. noteBody.addEventListener("mouseout", function(event) {
  597. this.style.setProperty("display", "none", "");
  598. }, false);
  599. displayDiv.appendChild(noteBody);
  600.  
  601. // this sucks, find another method!
  602. var w = parseInt(ndata.getAttribute("width"), 10) * sampleRate;
  603. var h = parseInt(ndata.getAttribute("height"), 10) * sampleRate;
  604. if(w < h) { w ^= h; h ^= w; w ^= h; } // FUCK YEAH XOR SWAP
  605. while(w / h > ratio) {
  606. w -= ratio;
  607. h += ratio;
  608. }
  609.  
  610. noteBody.style.setProperty("min-width", "-moz-min-content", "");
  611. noteBody.style.setProperty("max-width", w + "px", "");
  612.  
  613. ntop = ntop + 5 + (parseInt(ndata.getAttribute("height"), 10) * sampleRate);
  614. nheight = noteBody.getBoundingClientRect().bottom - noteBody.getBoundingClientRect().top;
  615. if(ntop + nheight > vp_bottom)
  616. noteBody.style.setProperty("top", vp_bottom - nheight + "px", "");
  617. else
  618. noteBody.style.setProperty("top", ntop + "px", "");
  619.  
  620. noteBody.style.setProperty("left", nleft + "px", "");
  621. noteBody.style.setProperty("display", "none", "");
  622. }
  623. }
  624.  
  625. function getNotes(xmldoc, id) {
  626. if(booru.name == "Danbooru") { // fix for not working http://danbooru.donmai.us/notes.xml?search[post_id]=
  627. var notesxml = xmldoc.evaluate("note-versions/note-version/note-id", xmldoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
  628. var allnotes = new Array(notesxml.snapshotLength);
  629. for(var i = 0, ndata = null; ndata = notesxml.snapshotItem(i++); i)
  630. allnotes[i] = ndata.textContent;
  631.  
  632. // remove duplicates
  633. var temp = {};
  634. for(var i = 0; i < allnotes.length - 1; i++)
  635. temp[allnotes[i + 1]] = true;
  636. var notes = [];
  637. for(var i in temp)
  638. notes.push(i);
  639.  
  640. for(var i = 0; i < notes.length; i++) {
  641. requestNote = GM_xmlhttpRequest({
  642. method : "GET",
  643. url : window.location.origin + "/notes/" + notes[i] + ".xml" + booru.query(),
  644. headers: { "Accept" : "application/xml" },
  645. overrideMimeType : "application/xml; charset=utf-8",
  646. onload : function(response) {
  647. var xmldoc = new DOMParser().parseFromString(response.responseText, "application/xml");
  648. var note = xmldoc.evaluate("note", xmldoc, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  649. while(note.firstChild) {
  650. if(note.firstChild.nodeName != "#text")
  651. note.setAttribute(note.firstChild.nodeName, note.firstChild.textContent);
  652. note.removeChild(note.firstChild);
  653. }
  654. showNotes(xmldoc.evaluate("note[@is-active = 'true']", xmldoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null), id);
  655. }
  656. });
  657. }
  658. } else {
  659. showNotes(xmldoc.evaluate("notes/note[@is_active = 'true']", xmldoc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null), id);
  660. }
  661. }
  662.  
  663. function getValue(name, values) {
  664. for(var i = 0; i < sites.length; i++)
  665. if(new RegExp(sites[i].site).test(window.location.hostname)) {
  666. if(eval(values)[i] != "" && !eval(values)[i]) {
  667. values = setValue(name.replace(/all/, ""), values, setDefaults(name, 1));
  668. }
  669. return eval(values)[i];
  670. }
  671. }
  672.  
  673. function setValue(name, values, newvalue) {
  674. for(var i = 0; i < sites.length; i++)
  675. if(new RegExp(sites[i].site).test(window.location.hostname)) {
  676. oldvalue = eval(values);
  677. oldvalue[i] = (newvalue == "" ? "" : newvalue || oldvalue[i]);
  678. GM_setValue(name, JSON.stringify(oldvalue));
  679. return(JSON.stringify(oldvalue));
  680. }
  681. }
  682.  
  683. function setDefaults(name, all) {
  684. var def, string = "[";
  685. for(var i = 0; i < all; i++) {
  686. if(name == "alltags")
  687. def = "\"\"";
  688. if(name == "allpage")
  689. def = "1";
  690. if(name == "allimages")
  691. def = "20";
  692. if(name == "allcolumns")
  693. def = "5";
  694. if(name == "allrating")
  695. def = "\"s\"";
  696. string += (def) + (i < sites.length - 1 ? ", " : "]");
  697. }
  698. return (all > 1 ? string : eval(def));
  699. }