- // ==UserScript==
- // @name ImageFAQs
- // @namespace FightingGames@gfaqs
- // @include http://www.gamefaqs.com
- // @include http://www.gamefaqs.com*
- // @description Converts plain-text image and webm URLs into their embedded form
- // @version 1.03
- // @grant GM_addStyle
- // @grant GM_getResourceText
- // @grant GM_log
- // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js
- // @require https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js
- // @resource jqueryuibaseCSS https://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery.ui.base.css
- // @resource jqueryuithemeCSS https://code.jquery.com/ui/1.11.4/themes/cupertino/jquery-ui.css
- // ==/UserScript==
-
- /*
- The MIT License (MIT)
-
- This greasemonkey script for GameFAQs converts image and webm
- links into their embedded form. It can be considered as a spiritual successor
- to text-to-image for GameFAQs. Many of its features are inspired from appchan x
- by zixaphir at http://zixaphir.github.io/appchan-x/.
-
- Copyright (c) 2015 FightingGames@gamefaqs <adrenalinebionicarm@gmail.com>
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-
- */
-
-
-
- GM_addStyle (GM_getResourceText("jqueryuibaseCSS"));
- GM_addStyle (GM_getResourceText("jqueryuithemeCSS"));
- this.$ = this.jQuery = jQuery.noConflict(true);
-
-
-
-
-
-
-
- /*this top portion of the script handles the settings box and local storage*/
-
- var thumbnailImgWidth = 150;
- var thumbnailImgHeight = 150;
- var settingsJSON = localStorage.getItem("imagefaqs");
- var settings; /*key-value array of JSON*/
- var sessionSpoilersHotkey;
-
- /*if imageFAQs was freshly installed*/
- if (settingsJSON == null)
- {
- settings = {
- enable_imagefaqs: true,
- enable_sigs: false,
- thumbnailWidth: thumbnailImgWidth,
- thumbnailHeight: thumbnailImgHeight,
- imgContainerBackgroundColor: "#DFE6F7",
- isSpoilersMode: false,
- spoilersHotkey: {115: 115}, /*F4*/
- blacklistStr: ""
- };
-
- localStorage.setItem("imagefaqs", JSON.stringify(settings)); /*save default settings*/
- }
- else
- {
- settings = jQuery.parseJSON(settingsJSON);
- }
-
-
-
-
-
-
- function keyCodeToString(keyCode)
- {
- keyCode = parseInt(keyCode);
-
- if (keyCode == 16)
- {
- return "shift";
- }
- else if (keyCode == 17)
- {
- return "ctrl";
- }
- else if (keyCode == 18)
- {
- return "alt";
- }
- else if (keyCode >= 112 && keyCode <= 123) /*F keys*/
- {
- return "F" + (keyCode - 111);
- }
- else
- {
- return String.fromCharCode(keyCode);
- }
- }
-
-
- function keyCodeKVArrayToString(array)
- {
- var string = "";
-
- for (var key in array)
- {
- string += keyCodeToString(key) + " ";
- }
-
- return string;
- }
-
-
- function cloneKVArray(KVArray)
- {
- var newKVArray = {};
-
- for (var key in KVArray)
- {
- newKVArray[key] = KVArray[key];
- }
-
- return newKVArray;
- }
-
-
-
- sessionSpoilersHotkey = cloneKVArray(settings.spoilersHotkey);
-
-
-
-
- /*event where user opens up settings menu*/
- $("body").on("click", "#imagefaqs_settings_but", function(event) {
-
- var popupBox = $("#imagefaqs_settings_popup");
- event.preventDefault();
-
- if (popupBox.length == 0)
- {
- $("body").append(
- "<div id='imagefaqs_settings_popup' title='ImageFAQs Settings. Version "+ GM_info.script.version+"'>" +
- "Update history: <a target='_blank' href='http://fightinggames.bitbucket.org/imagefaqs/'>http://fightinggames.bitbucket.org/imagefaqs/</a>." +
- "<br/>" +
- "Feedback and bug reporting: <a target='_blank' href='http://www.gamefaqs.com/boards/565885-blood-money'>http://www.gamefaqs.com/boards/565885-blood-money</a>." +
- "<br/><br/>" +
- "<label><input id='enableImagefaqs_checkbox' type='checkbox'>Enable ImageFAQs</label>" +
- "<br/>" +
- "<label><input id='enable_sigs_checkbox' type='checkbox'>Enable embedding in signatures</label>" +
- "<br/><br/>" +
- "<label><input id='thumbnailImgWidth_text' type='text'>Thumbnail max-width (150 default)</label>" +
- "<br/>" +
- "<label><input id='thumbnailImgHeight_text' type='text'>Thumbnail max-height (150 default)</label>" +
- "<br/><br/>" +
- "<label><input id='imgContainerBackgroundColor_text' type='text'>Image container background color (#DFE6F7 default)</label>" +
- "<br/><br/>" +
- "<label>Newline separated list of blacklisted image URLs</label>" +
- "<br/>" +
- "<textarea id='blacklist_text'></textarea>" +
- "<br/><br/>" +
- "<span>Tip: You can blacklist an entire domain (e.g. pbsrc.com)</span>" +
- "<br/><br/>" +
- "<label><input id='spoilersHotkey_text' type='text'>Toggle spoilers hotkey (F4 default)</label>" +
- "<br/><br/>" +
- "<span>Tip: At any time, you can toggle spoilers mode. This can be done before or after<br/> entering a topic.</span>" +
- "<br/><br/>" +
- "<button id='saveImagefaqsSettingsBut' type='button'>Save</button> " +
- "<button id='cancelImagefaqsSettingsBut' type='button'>Cancel</button> " +
- "<br/><br/>" +
- "<span id='responseSpan'> </span>" + /*for reporting success or failure*/
- "</div>"
- );
-
- popupBox = $("#imagefaqs_settings_popup");
- }
-
- popupBox.find("#enableImagefaqs_checkbox").prop("checked", settings.enable_imagefaqs);
- popupBox.find("#enable_sigs_checkbox").prop("checked", settings.enable_sigs);
- popupBox.find("#thumbnailImgWidth_text").val(settings.thumbnailWidth);
- popupBox.find("#thumbnailImgHeight_text").val(settings.thumbnailHeight);
- popupBox.find("#imgContainerBackgroundColor_text").val(settings.imgContainerBackgroundColor);
- popupBox.find("#spoilersHotkey_text").val( keyCodeKVArrayToString(settings.spoilersHotkey) );
- popupBox.find("#blacklist_text").val( settings.blacklistStr );
- $("#imagefaqs_settings_popup").children("#responseSpan").html(" ");
-
- $("#imagefaqs_settings_popup").dialog({
- width:'auto'
- });
- });
-
-
-
-
-
- $("body").on("click", "#saveImagefaqsSettingsBut", function(event) {
-
- event.preventDefault();
-
- var settingsPopup = $("#imagefaqs_settings_popup");
-
- /*if valid thumbnail dimensions*/
- if (
- !isNaN($("#thumbnailImgWidth_text").val()) && $("#thumbnailImgWidth_text").val() >= 1 &&
- !isNaN($("#thumbnailImgHeight_text").val()) && $("#thumbnailImgHeight_text").val() >= 1)
- {
- settings.thumbnailWidth = $("#thumbnailImgWidth_text").val();
- settings.thumbnailHeight = $("#thumbnailImgHeight_text").val();
- }
- else
- {
- reportResponseMsgInImagefaqsSettingsPopupBox("Error: Invalid thumbnail dimensions. Use natural numbers only.", settingsPopup);
- return;
- }
-
- /*if valid image container background color*/
- if (settingsPopup.find("#imgContainerBackgroundColor_text").val().search(/^#[a-zA-Z0-9]{6}$/i) >= 0)
- {
- settings.imgContainerBackgroundColor = settingsPopup.find("#imgContainerBackgroundColor_text").val();
- }
- else
- {
- reportResponseMsgInImagefaqsSettingsPopupBox("Error: Invalid image container background color.", settingsPopup);
- return;
- }
-
- settings.enable_imagefaqs = settingsPopup.find("#enableImagefaqs_checkbox").prop("checked");
- settings.enable_sigs = settingsPopup.find("#enable_sigs_checkbox").prop("checked");
- settings.spoilersHotkey = cloneKVArray(sessionSpoilersHotkey);
- settings.blacklistStr = settingsPopup.find("#blacklist_text").val();
-
- localStorage.setItem("imagefaqs", JSON.stringify(settings));
-
- reportResponseMsgInImagefaqsSettingsPopupBox("Settings saved. Please refresh page for changes to take effect.", settingsPopup);
- });
-
-
-
- /*
- @param msg :: message string to show to the user
- @param box :: $("#imagefaqs_settings_popup")
- */
- function reportResponseMsgInImagefaqsSettingsPopupBox(msg, box)
- {
- var msgBox = box.children("#responseSpan");
-
- msgBox.html(msg);
- msgBox.effect("highlight");
- }
-
-
-
- $("body").on("click", "#cancelImagefaqsSettingsBut", function(event) {
-
- event.preventDefault();
- $("#imagefaqs_settings_popup").dialog("close");
- });
-
-
-
-
-
-
- /*begin main scripting*/
- (function(){
-
- var enable_imagefaqs = settings.enable_imagefaqs;
- var isSpoilersMode = settings.isSpoilersMode;
- var thumbnailImgWidth = settings.thumbnailWidth;
- var thumbnailImgHeight = settings.thumbnailHeight;
- var blacklist = settings.blacklistStr.split("\n"); /*array of URLs to block*/
- var currentURL;
- var pageType; /* "topic" or "postPreview" or "other" */
- var allowImgInSig = settings.enable_sigs;
- var isFloatingImgExist = false;
- var floatingImgWidth;
- var floatingImgRightOffset = 50;
- var floatingImgBorder = 10;
- var currentHoveredThumbnail = null;
- var imgAnchorTags = [];
-
-
-
-
-
- var heldDownKeys = {};
- $("body").on("keydown", "#imagefaqs_settings_popup #spoilersHotkey_text", function(event){
-
- heldDownKeys[event.which] = event.which;
- sessionSpoilersHotkey = cloneKVArray(heldDownKeys);
-
- $(this).val(
- keyCodeKVArrayToString(sessionSpoilersHotkey)
- );
-
- return false;
- });
-
-
- $("body").on("keyup", "#imagefaqs_settings_popup #spoilersHotkey_text", function(event){
- delete heldDownKeys[event.which];
- return false;
- });
-
- $("body").on("keypress", "#imagefaqs_settings_popup #spoilersHotkey_text", function(event){
- event.preventDefault();
- });
-
-
-
-
-
-
-
- $("body").keydown(function(event){
-
- var desiredAction;
- heldDownKeys[event.which] = event.which;
-
- /*are every spoilers hotkey pressed?*/
- for (var key in settings.spoilersHotkey)
- {
- if (settings.spoilersHotkey[key] != heldDownKeys[key])
- {
- return;
- }
- }
- desiredAction = "toggleSpoilersMode";
-
- if (desiredAction == "toggleSpoilersMode")
- {
- event.preventDefault();
-
- isSpoilersMode = !isSpoilersMode;
-
- if (isSpoilersMode)
- {
- if (pageType != "other")
- {
- /*for every embedded image*/
- $(".embeddedImg").each(function(index, element) {
-
- /*if image is in thumbnail mode, add spoilers class*/
- if ($(this).hasClass("thumbnailImg"))
- {
- $(this).addClass("thumbnailImg_spoilersExt");
- $(this).parent().addClass("embeddedImgAnchor_spoilersExt");
- }
- });
- }
-
- showNotification("ImageFAQs: Spoilers mode is now on.");
- }
- else
- {
- if (pageType != "other")
- {
- /*for every embedded image*/
- $(".embeddedImg").each(function(index, element) {
-
- /*if image is in thumbnail mode, remove spoilers class*/
- if ($(this).hasClass("thumbnailImg"))
- {
- $(this).removeClass("thumbnailImg_spoilersExt");
- $(this).parent().removeClass("embeddedImgAnchor_spoilersExt");
- }
- });
- }
-
- showNotification("ImageFAQs: Spoilers mode is now off.");
- }
-
- settings.isSpoilersMode = isSpoilersMode;
- localStorage.setItem("imagefaqs", JSON.stringify(settings));
- }
- });
-
-
-
-
- $("body").keyup(function(event){
- delete heldDownKeys[event.which];
- });
-
-
-
-
-
-
-
- /*
- Display a notification on the bottom-right of the browser. Notification will
- disappear in a few seconds.
-
- @param msg :: string message to display
- */
- function showNotification(msg)
- {
- var notificationBox = $("#imagefaqs_notificationBox");
- notificationBox.remove();
-
- $("body").append(
- "<div id='imagefaqs_notificationBox'>" +
- "<span style='color: black'>" +
- msg +
- "</span>" +
- "</div>"
- );
-
- notificationBox = $("#imagefaqs_notificationBox");
-
- notificationBox.css({
- "background-color": "white",
- "position": "absolute",
- "top": ($(window).scrollTop() + $(window).height() - notificationBox.height())+"px",
- "left": ($(window).scrollLeft() + $(window).width() - notificationBox.find("span").width())+"px"
- });
-
- notificationBox.effect("highlight").delay(1000).fadeOut(500);
- }
-
-
-
-
- if (enable_imagefaqs == false)
- {
- return;
- }
-
-
-
- if (blacklist.length == 1 && blacklist[0] == "")
- {
- blacklist = [];
- }
- else
- {
- /*trim white space*/
- for (var i = 0; i < blacklist.length; i++)
- {
- blacklist[i].trim();
- }
- }
-
-
-
-
-
-
-
- function isURLmatchBlacklistedURL(url, blacklistedURL)
- {
- blacklistedURL = blacklistedURL.trim();
-
- /*escape everything*/
- var blacklistedURLregex =
- new RegExp( blacklistedURL.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") );
-
- if (blacklistedURLregex.exec(url) != null)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
-
- /*
- Is the url string in the blacklist?
-
- @url :: string of the url to check
- @blacklist :: array of blacklisted urls
-
- Returns true or false
- */
- function isURLinBlacklist(url, blacklist)
- {
- for (var i = 0; i < blacklist.length; i++)
- {
- if (isURLmatchBlacklistedURL(url, blacklist[i]))
- {
- return true;
- }
- }
-
- return false;
- }
-
-
-
-
-
-
-
-
- currentURL = window.location.href;
- pageType = currentURL.search(/.*gamefaqs\.com\/boards\/.*\/.*/i);
- if (currentURL.search(/.*gamefaqs\.com\/boards\/.*\/.*/i) >= 0)
- {
- pageType = "topic";
- }
- else if (currentURL.search(/.*gamefaqs\.com\/boards\/post/i) >= 0)
- {
- pageType = "postPreview";
- }
- else if (currentURL.search(/.*gamefaqs\.com\/user/i) >= 0)
- {
- /*add settings link*/
- $(".systems").append("<li><a id='imagefaqs_settings_but' href='#'>ImageFAQs Options</a> - Change thumbnail size, enable signature embedding, and more.</li>");
- }
- else
- {
- pageType = "other";
- }
-
-
-
-
- if (pageType == "other")
- {
- return;
- }
-
-
-
-
-
-
-
- GM_addStyle ("\
- .embeddedImgContainer {\
- background: "+settings.imgContainerBackgroundColor+";\
- }\
- .embeddedImgAnchor {\
- display: inline-block;\
- }\
- .embeddedImgAnchor_placeholderHeight {\
- height: "+thumbnailImgHeight+"px;\
- }\
- .embeddedImgAnchor_spoilersExt {\
- background: black;\
- }\
- .thumbnailImg {\
- display: inline-block; /*prevents parent anchor from stretching horizontally*/\
- vertical-align: bottom;\ /*eliminates small gap between bottom of image and parent div*/\
- }\
- .thumbnailImg_spoilersExt {\
- opacity: 0.0;\
- }\
- .expandedImg {\
- display: inline-block;\
- vertical-align: bottom;\
- }\
- ");
-
- $("body").css("position", "relative");
-
- if (pageType == "topic")
- {
- /*get all user posts*/
- var posts = $(".msg_body");
- }
- else if (pageType == "postPreview")
- {
- var posts = $("div.body td:eq(1)");
- }
-
- /*for each user post*/
- posts.each(function(index, element) {
-
- var postHtml;
- var unanchoredImgURLMatches;
- var sigStrIdx;
- var anchorTags;
-
- postHtml = $(this).html();
-
- /*if in post preview mode, need to manually parse through the preview message body and
- replace every plain-text image URL in its anchor form*/
- if (pageType == "postPreview")
- {
- postHtml = postHtml.replace(/https?:\/\/[a-zA-Z0-9\[\]\-\.\_\~\:\/\?\#\[\]\%\@\!\$\&\'\(\)\*\+\,\;\=]*?\.(?:png|jpg|gif|jpeg|webm|gifv)[a-zA-Z0-9\[\]\-\.\_\~\:\/\?\#\[\]\%\@\!\$\&\'\(\)\*\+\,\;\=]*/ig, "<a href='$&'>$&</a>");
-
- $(this).html(postHtml);
- }
-
- /*get index of sig separator*/
- sigStrIdx = postHtml.indexOf("<br>---<br>");
-
- /*get all anchor tags*/
- anchorTags = $(this).find("a");
-
- /*filter in anchor tags that refer to images*/
- anchorTags.each(function(index, element) {
-
- var anchorURL = $(this).attr("href");
- var anchorTagStrIdx = postHtml.indexOf(anchorURL);
-
- if (anchorURL.search(/https?:\/\/[a-zA-Z0-9\[\]\-\.\_\~\:\/\?\#\[\]\%\@\!\$\&\'\(\)\*\+\,\;\=]*?\.(?:png|jpg|gif|jpeg|webm|gifv)/i) >= 0)
- {
- /*if sig exists, anchor is part of sig, and sig shouldn't embedded images*/
- if (sigStrIdx != -1 && anchorTagStrIdx > sigStrIdx && !allowImgInSig)
- {
- return;
- }
-
- imgAnchorTags.push($(this));
- }
- });
- });
-
-
-
- /*for each valid image URL anchor tag, replace with template div for embedded image*/
- for (var imgAnchor of imgAnchorTags)
- {
- var imgURL = imgAnchor.html();
- var imgSize;
- var imgInfoEleStr;
- var postID;
- var isBlacklisted = isURLinBlacklist(imgURL, blacklist);
-
- if (pageType == "topic")
- {
- postID = imgAnchor.parent().attr("name");
- }
- else /*if in post preview mode, need to provide missing message ID*/
- {
- imgAnchor.parent().attr("name", 0);
- postID = 0;
- }
-
- imgInfoEleStr =
- "<span style='margin-right: 5px'>" +
- "<a href="+imgURL+">"+imgURL+"</a>" +
- "</span>";
-
- imgGoogleReverse =
- "<a target='_blank' title='Reverse image search on general images' style='margin-right: 5px' href='https://www.google.com/searchbyimage?image_url="+imgURL+"'>" +
- "google" +
- "</a>";
-
- imgIQDBreverse =
- "<a target='_blank' title='Reverse image search on weeb images' style='margin-right: 5px' href='http://iqdb.org/?url="+imgURL+"'>" +
- "iqdb" +
- "</a>";
-
- if (isBlacklisted)
- {
- imgBlacklistToggle =
- "<a class='imgBlacklistToggle' href='#' title='Whitelist image' style='margin-right: 5px'>whitelist</a>";
- }
- else
- {
- imgBlacklistToggle =
- "<a class='imgBlacklistToggle' href='#' title='Blacklist image' style='margin-right: 5px'>blacklist</a>";
- }
-
- imgCloseAll =
- "<a class='imgCloseAll' href='#' title='Close all images in page' style='margin-right: 5px'><<</a>";
-
- imgClosePost =
- "<a class='imgClosePost' href='#' data-postID='"+postID+"' title='Close all images in post' style='margin-right: 5px'><</a>";
-
- imgExpandPost =
- "<a class='imgExpandPost' href='#' data-postID='"+postID+"' title='Expand all images in post' style='margin-right: 5px'>></a>";
-
- imgExpandAll =
- "<a class='imgExpandAll' href='#' title='Expand all images in page' style='margin-right: 5px'>>></a>";
-
- imgAnchor.replaceWith(
- "<div class='embeddedImgContainer'>" +
- imgInfoEleStr +
- imgGoogleReverse +
- imgIQDBreverse +
- imgBlacklistToggle +
- imgCloseAll +
- imgClosePost +
- imgExpandPost +
- imgExpandAll +
- "<br/>" +
- "<a class='embeddedImgAnchor embeddedImgAnchor_placeholderHeight' href='" + imgURL + "' data-backup-href='" + imgURL + "'>" +
- "</a>" +
- "</div>"
- );
-
- if (isBlacklisted)
- {
- var embeddedImgAnchor = $(".embeddedImgAnchor[href='"+imgURL+"']");
-
- embeddedImgAnchor.hide();
- embeddedImgAnchor.addClass("blacklisted");
- }
- }
-
-
- /*for each template div, insert an embedded image*/
- $(".embeddedImgContainer").each(function(index, element) {
-
- var curEmbeddedImgContainer = $(this);
- var curEmbeddedImgAnchor = $(this).find(".embeddedImgAnchor");
- var imgURL = curEmbeddedImgAnchor.attr("href");
- var imgType; /*e.g. "jpg"*/
- var image = new Image();
- var embeddedImgSpoilersClass;
-
- if (isSpoilersMode)
- {
- embeddedImgSpoilersClass = "thumbnailImg_spoilersExt";
- curEmbeddedImgAnchor.addClass("embeddedImgAnchor_spoilersExt");
- }
- else
- {
- embeddedImgSpoilersClass = "";
- }
-
- var postID = curEmbeddedImgContainer.parent().attr("name");
-
- imageType = imgURL.split(".").pop();
-
- /*if not a webm video (i.e. image)*/
- if (imageType.search(/(webm|gifv)/i) == -1)
- {
- /*on event that image cannot be loaded, post the error*/
- image.onerror = function() {
- curEmbeddedImgAnchor.html("Image cannot be loaded.");
- };
-
- /*on event that image loaded successfully in memory*/
- $(image).load(function() {
- /*write down image's natural dimensions*/
- curEmbeddedImgContainer.find("span").append(
- " (" + image.naturalWidth + "x" + image.naturalHeight + ")"
- );
- curEmbeddedImgAnchor.removeClass("embeddedImgAnchor_placeholderHeight");
- });
-
- image.src = imgURL;
-
- $(image).addClass("embeddedImg thumbnailImg "+embeddedImgSpoilersClass+"");
- $(image).attr("data-postID", postID);
- $(image).attr("alt", "");
- $(image).css("max-width", thumbnailImgWidth + "px");
- $(image).css("max-height", thumbnailImgHeight + "px");
-
- curEmbeddedImgAnchor.html(image);
- }
- else /*if image is actually a webm file*/
- {
- if (imageType == "gifv")
- {
- imgURL = imgURL.replace("gifv", "webm");
- }
-
- htmlVideoSrcTag =
- "<video id='embeddedImg_"+index+"' data-postID='"+postID+"' " +
- "class='embeddedImg webmExt thumbnailImg "+embeddedImgSpoilersClass+"' " +
- "style='max-width: "+thumbnailImgWidth+"px; max-height: "+thumbnailImgHeight+"px;'>" +
- "<source src='" + imgURL + "' type='video/webm'>" +
- "</video>";
-
- curEmbeddedImgAnchor.html(
- htmlVideoSrcTag
- );
-
- curEmbeddedImgAnchor.removeClass("embeddedImgAnchor_placeholderHeight");
-
- /*when video's metadata has been loaded, record its natural width and resolution*/
- $("#embeddedImg_"+index+"")[0].onloadedmetadata = function() {
-
- var video = this;
-
- $(video).parent().parent().find("span").append(
- " (" + video.videoWidth + "x" + video.videoHeight + ")"
- );
- };
- }
- });
-
-
- /*
- Get the natural width of an embedded image.
-
- @image :: jQuery object with the class "embeddedImg"
- */
- function getNatWidthOfEmbeddedImg(image)
- {
- if (image.hasClass("webmExt"))
- {
- return image[0].videoWidth;
- }
- else
- {
- return image[0].naturalWidth;
- }
- }
-
-
-
- /*
- Get the natural width of an embedded image.
-
- @image :: jQuery object with the class "embeddedImg"
- */
- function getNatHeightOfEmbeddedImg(image)
- {
- if (image.hasClass("webmExt"))
- {
- return image[0].videoHeight;
- }
- else
- {
- return image[0].naturalHeight;
- }
- }
-
-
-
- /*if cursor is hovering inside a thumbnail image, display expanded image as floating div*/
- $(document).on("mousemove", function(event) {
-
- var floatingImgLeft;
- var floatingImgTop;
- var floatingImgWidth;
- var floatingImgHeight;
- var floatingImgStyleStr;
-
- /*if user is hovering over thumbnail, prepare floating image size and position*/
- if (currentHoveredThumbnail != null)
- {
- floatingImgWidth = parseInt(getNatWidthOfEmbeddedImg(currentHoveredThumbnail));
-
- floatingImgLeft = event.pageX + floatingImgRightOffset;
-
- /*if right of image exceeds beyond right of window, restrict max width*/
- if (floatingImgLeft + floatingImgWidth > $(window).scrollLeft() + $(window).width() - floatingImgBorder)
- {
- floatingImgWidth = $(window).scrollLeft() + $(window).width() - floatingImgBorder - floatingImgLeft;
- }
-
- floatingImgHeight = Math.round(getNatHeightOfEmbeddedImg(currentHoveredThumbnail) * (floatingImgWidth / getNatWidthOfEmbeddedImg(currentHoveredThumbnail)));
-
- floatingImgTop = event.pageY - (floatingImgHeight / 2);
-
- /*if bottom of image exceeds beyond the window, shift top upwards*/
- if (floatingImgTop + floatingImgHeight > $(window).scrollTop() + $(window).height() - floatingImgBorder)
- {
- floatingImgTop = $(window).scrollTop() + $(window).height() - floatingImgBorder - floatingImgHeight;
- }
-
- /*if top of image expands beyond top of window, lower top of image*/
- if (floatingImgTop < $(window).scrollTop() + floatingImgBorder)
- {
- floatingImgTop = $(window).scrollTop() + floatingImgBorder;
- }
-
- /*if bottom of image exceeds beyond the window, restrict max height*/
- if (floatingImgTop + floatingImgHeight > $(window).scrollTop() + $(window).height() - floatingImgBorder)
- {
- floatingImgHeight = $(window).scrollTop() + $(window).height() - floatingImgBorder - floatingImgTop;
- }
-
- /*if floating image doesn't exist, create it*/
- if (!isFloatingImgExist)
- {
- floatingImgStyleStr =
- "position: absolute;" +
- "left: " + floatingImgLeft + "px;" +
- "top: " + floatingImgTop + "px;" +
- "max-width: " + floatingImgWidth + "px;" +
- "max-height: " + floatingImgHeight + "px;" +
- "z-index: 100;";
-
- /*if webm video*/
- if (currentHoveredThumbnail.hasClass("webmExt"))
- {
- floatingImgSrc =
- "<video id='floatingImg' style='" + floatingImgStyleStr + "'>" +
- "<source src='" + currentHoveredThumbnail.children("source").attr("src") + "' type='video/webm'>" +
- "</video>";
- }
- else
- {
- floatingImgSrc =
- "<img id='floatingImg' style='" + floatingImgStyleStr + "' src='" + currentHoveredThumbnail.attr("src") + "'>";
- }
-
- isFloatingImgExist = true;
-
- /*create the floating image*/
- $("body").append(
- floatingImgSrc
- );
-
- /*if webm video*/
- if (currentHoveredThumbnail.hasClass("webmExt"))
- {
- var video = $("#floatingImg");
-
- video.attr("loop", "");
- video[0].play();
- }
- }
- else /*if floating image already exists, update its size and position*/
- {
- $("#floatingImg").css({
- "left": floatingImgLeft + "px",
- "top": floatingImgTop + "px",
- "max-width": floatingImgWidth + "px",
- "max-height": floatingImgHeight + "px",
- });
- }
- }
- /*if user is not hovering over thumbnail and floating image still exists*/
- else if (currentHoveredThumbnail == null && isFloatingImgExist)
- {
- $("#floatingImg").remove();
- isFloatingImgExist = false;
- }
- });
-
-
-
- /*if mouse hovers inside the image, change cursor to pointer*/
- $(document).on("mouseover", ".embeddedImg", function(event){
- $("html").css("cursor", "pointer");
-
- if (! $(this).hasClass("expandedImg"))
- {
- currentHoveredThumbnail = $(event.target);
- }
- });
-
- /*if mouse hovers outside the image, restore cursor to default graphic*/
- $(document).on("mouseout", ".embeddedImg", function(){
- $("html").css("cursor", "default");
-
- currentHoveredThumbnail = null;
- });
-
-
-
- /*if clicked on the image URL anchor that's surrounding the embedded image, prevent default
- behaviour of anchor, unless it's a middle click*/
- $("body").on("click", ".embeddedImgAnchor", function(event){
-
- /*left-click*/
- if (event.which == 1)
- {
-
- }
- else
- {
- $(this).attr("href", $(this).attr("data-backup-href"));
- }
- });
-
- $("body").on("mousedown", ".embeddedImgAnchor", function(event){
-
- /*left-click*/
- if (event.which == 1)
- {
- event.preventDefault();
- }
- else
- {
- $(this).attr("href", $(this).attr("data-backup-href"));
- }
- });
-
-
- /*toggle image size on left-click*/
- $("body").on("click", ".embeddedImg", function(event){
-
- /*left-click*/
- if (event.which == 1)
- {
- var mouseRelativeY = event.pageY - $(this).offset().top;
-
- /*if expanded webm file, don't shrink to thumbnail if clicked on its controls*/
- if ($(this).hasClass("webmExt") && $(this).hasClass("expandedImg") &&
- (mouseRelativeY > ($(this).height() - 28)))
- {
- $(this).parent().attr("href", "javascript:void(0);");
- }
- else
- {
- toggleEmbeddedImgSize($(this));
- $(window).scrollTop( $(this).parent().parent().offset().top );
-
- return false;
- }
- }
- });
-
-
-
- function toggleEmbeddedImgSize(embeddedImg)
- {
- if (isSpoilersMode)
- {
- /*if going to be expanded*/
- if (embeddedImg.hasClass("thumbnailImg"))
- {
- embeddedImg.removeClass("thumbnailImg_spoilersExt");
- embeddedImg.parent().removeClass("embeddedImgAnchor_spoilersExt");
- }
- else /*if going to be in thumbnail mode*/
- {
- embeddedImg.addClass("thumbnailImg_spoilersExt");
- embeddedImg.parent().addClass("embeddedImgAnchor_spoilersExt");
- }
- }
-
- embeddedImg.toggleClass("thumbnailImg expandedImg");
-
- /*if expanded*/
- if (embeddedImg.hasClass("expandedImg"))
- {
- currentHoveredThumbnail = null;
- $("#floatingImg").remove();
- isFloatingImgExist = false;
-
- embeddedImg.css("max-width", getOptimalExpandedImgMaxWidth(embeddedImg));
- embeddedImg.css("max-height", "");
-
- /*if webm file, start playing it*/
- if (embeddedImg.hasClass("webmExt"))
- {
- embeddedImg[0].play();
- embeddedImg.attr("controls", "");
- }
- }
- else /*if shrinking image back to thumbnail*/
- {
- embeddedImg.css("max-width", thumbnailImgWidth + "px");
- embeddedImg.css("max-height", thumbnailImgHeight + "px");
-
- /*if webm file, stop playing it*/
- if (embeddedImg.hasClass("webmExt"))
- {
- embeddedImg[0].pause();
- embeddedImg.removeAttr("controls");
- }
- }
- }
-
-
-
- /*
- Get the optimal max-width for an expanded image.
-
- The width will either be the length between the left of the thumbnail and the
- right of the image container, or the length between the left of the thumbnail
- and right of the window size.
-
- @param thumbnailImg :: jQuery object of the image to be expanded. It has the
- class "thumbnailImg"
-
- The returned width will be the smaller of the two.
- */
- function getOptimalExpandedImgMaxWidth(thumbnailImg)
- {
- var toContainerWidth;
- var toWindowWidth;
-
- toContainerWidth =
- thumbnailImg.parent().parent().width();
-
- toWindowWidth =
- $(window).width() - thumbnailImg.offset().left;
-
- if (toContainerWidth > toWindowWidth)
- {
- return toWindowWidth;
- }
- else
- {
- return toContainerWidth;
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
- $("body").on("click", ".imgCloseAll", function(event) {
-
- event.preventDefault();
-
- /*for every expanded embedded image*/
- $(".embeddedImg.expandedImg").each(function(index, element) {
-
- toggleEmbeddedImgSize($(this));
- });
-
- $(window).scrollTop( $(this).parent().offset().top );
- });
-
-
- $("body").on("click", ".imgClosePost", function(event) {
-
- var postID = $(this).attr("data-postID");
-
- event.preventDefault();
-
- /*for every expanded embedded image with same post ID*/
- $(".embeddedImg[data-postID="+postID+"].expandedImg").each(function(index, element) {
-
- toggleEmbeddedImgSize($(this));
- });
-
- $(window).scrollTop( $(this).parent().offset().top );
- });
-
-
- $("body").on("click", ".imgExpandPost", function(event) {
-
- var postID = $(this).attr("data-postID");
-
- event.preventDefault();
-
- /*for every embedded image with same post ID*/
- $(".embeddedImg[data-postID='"+postID+"']").each(function(index, element) {
-
- /*if image already expanded*/
- if ($(this).hasClass("expandedImg"))
- {
- /*update its max-width*/
- $(this).css("max-width", getOptimalExpandedImgMaxWidth($(this)))
- }
- else
- {
- toggleEmbeddedImgSize($(this));
- }
- });
-
- $(window).scrollTop( $(this).parent().offset().top );
- });
-
-
-
- $("body").on("click", ".imgExpandAll", function(event) {
-
- event.preventDefault();
-
- /*for every embedded image*/
- $(".embeddedImg").each(function(index, element) {
-
- /*if image already expanded*/
- if ($(this).hasClass("expandedImg"))
- {
- /*update its max-width*/
- $(this).css("max-width", getOptimalExpandedImgMaxWidth($(this)))
- }
- else
- {
- toggleEmbeddedImgSize($(this));
- }
- });
-
- $(window).scrollTop( $(this).parent().offset().top );
- });
-
-
-
-
-
-
-
-
-
-
- $("body").on("click", ".imgBlacklistToggle", function(event) {
-
- event.preventDefault();
-
- var url = $(this).siblings(".embeddedImgAnchor").attr("href");
- url.trim();
-
- /*if image isn't blacklisted (but going to blacklist)*/
- if (! $(this).siblings(".embeddedImgAnchor").hasClass("blacklisted"))
- {
- blacklist.push(url);
-
- /*for every embedded image anchor*/
- $(".embeddedImgAnchor").each(function(index, element) {
-
- /*if has URL that was just blacklisted, hide it*/
- if (isURLmatchBlacklistedURL(url, $(this).attr("href")))
- {
- $(this).siblings(".imgBlacklistToggle").html("whitelist");
- $(this).siblings(".imgBlacklistToggle").attr("title", "Whitelist image");
- $(this).addClass("blacklisted");
- $(this).hide();
- }
- });
- }
- else /*if image is blacklisted (but going to whitelist)*/
- {
- /*remove url from blacklist*/
- var urlIdx = blacklist.indexOf(url);
- if (urlIdx > -1)
- {
- blacklist.splice(urlIdx, 1);
- }
-
- /*for every embedded image anchor*/
- $(".embeddedImgAnchor").each(function(index, element) {
-
- /*if has URL that was just whitelisted, show it*/
- if ($(this).attr("href") == url)
- {
- $(this).siblings(".imgBlacklistToggle").html("blacklist");
- $(this).siblings(".imgBlacklistToggle").attr("title", "Blacklist image");
- $(this).removeClass("blacklisted");
- $(this).show();
- }
- });
- }
-
- settings.blacklistStr = blacklist.join("\n");
- localStorage.setItem("imagefaqs", JSON.stringify(settings));
- });
-
-
-
- })(); /*end of greasemonkey script*/