您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Panorama helper for d3.ru
// ==UserScript== // @name Panorama Helper d3.ru // @namespace d3.ru // @version 1.007 // @description Panorama helper for d3.ru // @author Anton aka RichDad // @match https://*.d3.ru/* // @match https://d3.ru/edit/* // @run-at document-start // ==/UserScript== (function () { 'use strict'; const PANORAMA_PROTOCOL = 'panorama://'; const TYPE_POST = 'post'; const TYPE_COMMENT = 'comment'; const PANORAMA_BUTTON_CLASS = 'panorama-helper-button0'; const PANORAMA_SHOWCASE_CLASS = 'panorama-helper-showcase0'; const IFRAME_SRC = 'https://cdn.pannellum.org/2.5/pannellum.htm#panorama=${img}&${params}'; // noinspection JSUnresolvedVariable,JSUnresolvedFunction let version = (typeof GM_info == 'function' ? GM_info().script.version : (typeof GM_info == 'object' ? GM_info.script.version : '?')); // noinspection JSUnusedGlobalSymbols let Helper = { log: function (...args) { if (console) console.log(...args); }, debug: function (...args) { if (console) console.debug(...args); }, error: function (...args) { if (console) { const stack = (new Error).stack.split("\n"); let caller_line = stack.length > 3 ? stack[3] : stack.pop(); let index = caller_line.indexOf("at "); let clean = caller_line.slice(index + 3, caller_line.length); console.log('[' + clean + ']', ...args); } }, arraysIntersect: function (haystack, arr) { return arr.some(function (v) { return haystack.indexOf(v) >= 0; }); } }; let PanoramaHelper = { isDeveloperMode: true, hasClass: function (element, className) { if (element && element.className) { let classes = element.className.split(' '); return classes.indexOf(className) > -1; } return false; }, hasParentWithAnyClassOf: function (element, classname_arr) { if (!element) return false; if (element.className) { let classes = element.className.split(' '); if (Helper.arraysIntersect(classes, classname_arr)) { return true; } } return element.parentNode && PanoramaHelper.hasParentWithAnyClassOf(element.parentNode, classname_arr); }, getParentWithClass: function (element, classname) { if (!element) return null; if (element.className) { let classes = element.className.split(' '); if (classes.indexOf(classname) >= 0) { return element; } } return element.parentNode ? PanoramaHelper.getParentWithClass(element.parentNode, classname) : null; }, paramsToUri: function (params) { let paramParts = []; for (let paramName in params) { if (params.hasOwnProperty(paramName)) { paramParts.push(paramName + '=' + params[paramName]); } } return paramParts.join('&'); }, prepareIframe: function (params) { let iframe = document.createElement('iframe'); iframe.setAttribute('width', params.w); iframe.setAttribute('height', params.h); iframe.setAttribute('style', 'border-style:none;'); iframe.setAttribute('allowfullscreen', ''); let src = IFRAME_SRC.replace(/\${params}/, PanoramaHelper.paramsToUri({ haov: params.haov, vaov: params.vaov, autoLoad: params.autoLoad, vOffset: params.vOffset })).replace(/\${img}/, params.img); iframe.setAttribute('src', src); return iframe; }, parsePanoramaHref: function (href) { let result = { autoLoad: 'true', vOffset: 0 }; if (href.indexOf(PANORAMA_PROTOCOL) === 0) { href = href.substr(PANORAMA_PROTOCOL.length); href = href.toLocaleLowerCase(); href = href.replace(/%20/g, '+'); const parts = href.replace(/[+.,\/#!$%^&*;:{}=\-_`~()]/g, " ").split(/\s+/); // parse TYPE if (parts.length) { if (parts[0] === 'post') { result.type = TYPE_POST; parts.shift(); } else if (parts[0] === 'comment') { result.type = TYPE_COMMENT; parts.shift(); } else { result.type = TYPE_COMMENT; } // parse HAOV if (parts.length) { let haov = parseInt(parts.shift()); if (!isNaN(haov) && haov > 0) { result.haov = haov; // parse VAOV if (parts.length) { let vaov = parseInt(parts.shift()); if (!isNaN(vaov) && vaov > 0) { result.vaov = vaov; // parse vOffset if (parts.length) { let vOffset = parseInt(parts.shift()); if (!isNaN(vOffset)) { result.vOffset = vOffset; } } } } } } } } return result; }, addDimensions: function (link, params) { let result = Object.assign(Object.create(null), params); params.w = 800; params.h = 600; if (params.type === TYPE_POST) { // TODO } else if (params.type === TYPE_COMMENT) { // TODO } return result; }, addPostSelector: function (link, params) { let result = Object.assign(Object.create(null), params); if (PanoramaHelper.hasParentWithAnyClassOf(link, ['b-post__body', 'post_body', 'b-post-cut__post-cut'])) { result.type = TYPE_POST; } return result; }, getPreviousComment: function (link) { let parent = link; while (parent.parentElement) { parent = parent.parentElement; if (PanoramaHelper.hasClass(parent, 'b-comment') && !PanoramaHelper.hasClass(parent, 'b-comment_mode_root')) { return parent; } } return null; }, addImage: function (link, params) { let result = Object.assign(Object.create(null), params); result.img = '?'; if (params.type === TYPE_POST) { // SEARCH UP let post = PanoramaHelper.getParentWithClass(link, 'b-post__body'); if (post) { let post_image = post.querySelector('img[src]'); if (post_image) { result.img = post_image.getAttribute('src'); } } else { let post_small = PanoramaHelper.getParentWithClass(link, 'b-post-cut'); if (post_small) { let post_small_image = post_small.querySelector('img[src]'); if (post_small_image) { result.img = post_small_image.getAttribute('src'); } } else { let post_feed = PanoramaHelper.getParentWithClass(link, 'post_body'); if (post_feed) { let post_feed_image = post_feed.querySelector('img[src]'); if (post_feed_image) { result.img = post_feed_image.getAttribute('src'); } } else { // SEARCH DOWN let post_image = document.querySelector('.b-post__body img[src]'); if (post_image) { result.img = post_image.getAttribute('src'); } } } } } else if (params.type === TYPE_COMMENT) { let comment_image = link.parentElement.querySelector('img'); if (comment_image) { result.img = comment_image.getAttribute('src'); } else { let previous_comment = PanoramaHelper.getPreviousComment(link); while (previous_comment) { let comment_image = previous_comment.parentElement.querySelector('img'); if (comment_image) { result.img = comment_image.getAttribute('src'); break; } previous_comment = PanoramaHelper.getPreviousComment(previous_comment); } } } return result; }, convertLinkToButton: function (link) { let linkHref = link.getAttribute('href'); let params = PanoramaHelper.parsePanoramaHref(linkHref); params = PanoramaHelper.addPostSelector(link, params); params = PanoramaHelper.addDimensions(link, params); params = PanoramaHelper.addImage(link, params); let div = document.createElement('div'); let button = document.createElement('button'); button.innerText = 'Panorama (' + params.type.toUpperCase() + ' ' + params.haov + '/' + params.vaov + (params.vOffset ? '/' + params.vOffset : '') + ')'; button.onclick = function () { let buttonDiv = this.parentElement; let w = buttonDiv.offsetWidth; let h = Math.floor(w * 3 / 4); params.w = w; params.h = h; let iframe = PanoramaHelper.prepareIframe(params); buttonDiv.removeChild(this); buttonDiv.appendChild(iframe); }; div.appendChild(button); return div; }, appendLinkToButton: function (link) { let div = PanoramaHelper.convertLinkToButton(link); let linkParent = link.parentElement; linkParent.removeChild(link); linkParent.appendChild(div); }, checkNewComment: function (commentBody, text) { if (!commentBody) return; let showcase = commentBody.querySelector('div.' + PANORAMA_SHOWCASE_CLASS); if (showcase) { showcase.parentElement.removeChild(showcase); } showcase = document.createElement('div'); showcase.className = PANORAMA_SHOWCASE_CLASS; let textAppended = false; let textLines = text.split("\n"); for (let textLine of textLines) { let line = textLine.trim(); if (line.indexOf(PANORAMA_PROTOCOL) === 0) { if (!textAppended) { showcase.innerText = 'Panorama example:'; textAppended = true; } let a = document.createElement('a'); a.href = line; showcase.append(a); } } commentBody.append(showcase); }, hasPanoramaLinks: function (element) { if (element) { let text = element.innerText; let textLines = text.split("\n"); for (let textLine of textLines) { let line = textLine.trim(); if (line.indexOf(PANORAMA_PROTOCOL) === 0) { return true; } } } return false; }, developerMode: function () { let commentButtons = document.querySelectorAll("span.b-comment__save-button"); for (let commentButtonContatiner of commentButtons) { if (commentButtonContatiner.offsetParent !== null) { // it is visible let commentBody = PanoramaHelper.getParentWithClass(commentButtonContatiner, 'b-comment__body'); let wysiwygEditor = commentBody.querySelector('div[contenteditable=true][id^=b-wysiwyg-editor-]'); if (!PanoramaHelper.hasPanoramaLinks(wysiwygEditor)) continue; let panoramaButton = commentButtonContatiner.querySelector('div.' + PANORAMA_BUTTON_CLASS); if (!panoramaButton) { let buttonDiv = document.createElement('div'); buttonDiv.className = "b-button b-button_size_s b-button_mode_default b-button_color_yellow b-button_icon_false b-button_empty_false b-button_disabled_false " + PANORAMA_BUTTON_CLASS; buttonDiv.innerText = "Panorama example" buttonDiv.onclick = () => { if (commentBody) { if (wysiwygEditor) { let text = wysiwygEditor.innerText; PanoramaHelper.checkNewComment(commentBody, text); } else { Helper.debug('wysiwygEditor?') } } else { Helper.debug('commentBody?') } }; commentButtonContatiner.append(" "); commentButtonContatiner.append(buttonDiv); } } } }, makeButtons: function () { let panoramaLinks = document.querySelectorAll("div:not(.b-wysiwyg__editor) > a[href^='" + PANORAMA_PROTOCOL + "']"); if (panoramaLinks && panoramaLinks.length) { for (let i = 0; i < panoramaLinks.length; i++) { PanoramaHelper.appendLinkToButton(panoramaLinks[i]); } } if (PanoramaHelper.isDeveloperMode) { PanoramaHelper.developerMode(); } }, init: function () { PanoramaHelper.makeButtons(); setInterval(PanoramaHelper.makeButtons, 1000); Helper.log('[Panorama Helper] Started v.' + version); } }; PanoramaHelper.init(); // noinspection JSUnresolvedVariable if (typeof unsafeWindow !== 'undefined') { // noinspection JSUnresolvedVariable unsafeWindow.PanoramaHelper = PanoramaHelper; } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址