您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds QoL improvements to Bandcamp.
当前为
// ==UserScript== // @name Bandcamp Tools // @namespace http://violentmonkey.net/ // @version 1.0 // @description Adds QoL improvements to Bandcamp. // @author InariOkami // @match *://*.bandcamp.com/* // @grant none // @icon https://cdn-icons-png.flaticon.com/512/21/21496.png // ==/UserScript== (function() { 'use strict'; var app = { id: "bcp-sp" }; app.debug = false; var cls = { price: app.id + '-price', handled: app.id + '-handled' }; var selectors = { product: 'li[data-trackid]:not(.' + cls.handled + ')' }; function findOne(selector, context, dontYell) { context = context || document; var item = context.querySelector(selector); if (item && app.debug) { console.log(app.id, ': found element matching "' + selector + '"'); } else if (!item && !dontYell) { console.warn(app.id, ': found no element for selector "' + selector + '"'); } return item; } function findFirst(selector, context) { return findAll(selector, context)[0]; } function findAll(selector, context, dontYell) { if (!selector || !selector.length || selector.length === 1) { console.error(app.id, ': incorrect selector : ', selector); } context = context || document; var items = Array.prototype.slice.call(context.querySelectorAll(selector)); if (items.length && app.debug) { console.log(app.id, ': found', items.length, 'elements matching "' + selector + '"'); } else if (!items.length && !dontYell) { console.warn(app.id, ': found no elements for selector "' + selector + '"'); } return items; } function debounce(func, wait, immediate) { var timeout; return function () { var context = this; var args = arguments; var later = function later() { timeout = null; if (!immediate) { func.apply(context, args); } }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) { func.apply(context, args); } }; } function cleanPrevious() { findAll('[class^="' + cls.price + '"]', document, true).forEach(function (node) { return node.remove(); }); } function displayPrice(product, price) { var tag = document.createElement('div'); tag.innerHTML = price.value + ' <small>' + price.currency + '</small>'; tag.style = 'position: absolute; top: 0; right: 0; background-color: green; color: white;'; tag.classList.add(cls.price, 'col-edit-box'); product.appendChild(tag); if (price.value > 2) { product.style.filter = 'grayscale(1) opacity(.5)'; } product.classList.add(cls.handled); } function displayPrices() { findAll(selectors.product, document, true).forEach(function (product) { var trackid = parseInt(product.getAttribute('data-trackid')); if (trackid) { if (app.debug) { console.log(app.id, ': adding price for', trackid); } if (!app.tracks.hasOwnProperty(trackid)) { throw new Error('failed at gettting track price'); } var price = app.tracks[trackid]; displayPrice(product, price); } }); } function setTracksFromList(list) { if (!app.tracks) { app.tracks = {}; } var added = 0; list.map(function (track) { var trackid = track.track_id; if (!app.tracks.hasOwnProperty(trackid)) { app.tracks[trackid] = { value: Math.round(track.price), currency: track.currency }; added++; } }); console.log(app.id, ': added', added, 'tracks to local db :D'); } function getDataFromApi() { fetch('https://bandcamp.com/api/fancollection/1/wishlist_items', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ fan_id: app.userid, older_than_token: app.token }) }).then(function (json) { return json.json(); }).then(function (data) { app.token = data.last_token; setTracksFromList(data.track_list); if (data.more_available) { getDataFromApi(); } }); } function getDataFromPage() { var dataEl = findOne('#pagedata'); var data = JSON.parse(dataEl.getAttribute('data-blob')); setTracksFromList(data.track_list); app.token = data.wishlist_data.last_token; app.userid = data.fan_data.fan_id; } function process() { displayPrices(); } function init() { console.log(app.id, ': init !'); cleanPrevious(); getDataFromPage(); getDataFromApi(); process(); } init(); var processDebounced = debounce(process, 500); document.addEventListener('scroll', processDebounced); })(); (function() { 'use strict'; var table = $('#track_table tbody tr') , tdata = table ? table.each(function(){}) : [] , adata = window.TralbumData || false; if (table.length > 1 && adata) { for(var i = 0; adata.trackinfo[i]; i++) { var p = $($('tr td .dl_link')[i]), link = document.createElement("a"), track = adata.trackinfo[i]; link.href = track.file["mp3-128"]; link.title = link.download = track.track_num + " - " + track.title + ".mp3"; link.alt = 'If left clicking opens song, right click to download.'; link.innerHTML = 'Download!'; p.html(link); } } else { $('.inline_player').append('<br /><strong><a href="#" class="font-size: 18px;" onclick="location.href=TralbumData.trackinfo[0].file["mp3-128"]">Download Now! (128kb MP3)</a></strong><br />'); } alert("jestem"); })(); (function() { 'use strict'; const DBG = false; let log = function(s) { return (DBG && console.log(s)); }, qS = function(el, scope) { scope = (typeof scope === 'object') ? scope : document; return scope.querySelector(el) || false; }, qSall = function(els, scope) { scope = (typeof scope === 'object') ? scope : document; return scope.querySelectorAll(els) || false; }, hidden, visibilityChange, state, tabFocused = function(evt) { log("tab has focus!"); if (document !== evt.target) { log("warning, document not equal to document. it is "); log(evt.target); // should be document } if (evt.target.body !== document.activeElement) { log("warning, document.activeElement not equal to document.body. it is "); log(evt.target.body); // should be document.body } }, elmTarget = qS("#trackInfoInner > div.inline_player > table > tbody > tr:nth-child(1) > td.play_cell > a > div"); if (!elmTarget) { log('main play button not found, exiting'); return; } if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support hidden = "hidden"; visibilityChange = "visibilitychange"; state = "visibilityState"; } else if (typeof document.mozHidden !== "undefined") { hidden = "mozHidden"; visibilityChange = "mozvisibilitychange"; state = "mozVisibilityState"; } else if (typeof document.msHidden !== "undefined") { hidden = "msHidden"; visibilityChange = "msvisibilitychange"; state = "msVisibilityState"; } else if (typeof document.webkitHidden !== "undefined") { hidden = "webkitHidden"; visibilityChange = "webkitvisibilitychange"; state = "webkitVisibilityState"; } if ('undefined' === typeof hidden) { log('document.hidden not found, exiting'); return; } document.addEventListener(visibilityChange, function(e) { return (false === document[hidden]) && tabFocused(e); }); window.addEventListener('keydown', function(e) { log("in keydown"); if(e.key === " " && e.target === document.body) { log("keydown ok"); e.preventDefault(); } }); qS('body').addEventListener("keyup", function(e) { log("in keyup"); if (e.key === " " && e.target === document.body) { e.preventDefault(); elmTarget.focus(); elmTarget.click(); elmTarget.blur(); log("keyup ok"); } }); })(); var gen = document.querySelector("meta[name=generator]"); if(!gen || gen.content != "Bandcamp") { return; } var style = document.createElement("style"); style.textContent = ".volumeControl{align-items:center;display:flex;height:52px;margin-top:1em}.volumeControl .thumb{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.volumeControl>.speaker{background:#fff;border:1px solid #d9d9d9;border-radius:2px;color:#000;cursor:pointer;font-size:32px;height:54px;line-height:54px;position:relative;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:54px}.volumeControl>.speaker>svg{margin:11px}"; document.head.appendChild(style); var dragWidth = 226; var dragging = false; var dragPos = 0; var percentage = parseFloat(localStorage.getItem("volume")) || 0.5; var speaker, volumeInner, audio, volume; function onLoad() { audio = document.getElementsByTagName("audio")[0]; updateVolume(); var container = document.createElement("div"); container.classList.add("volumeControl"); speaker = document.createElement("i"); speaker.classList.add("speaker"); speaker.addEventListener("click", function () { audio.muted = !audio.muted; updateHtml(); }); container.appendChild(speaker); var volume = document.createElement("div"); volume.classList.add("progbar"); container.appendChild(volume); var fill = document.createElement("div"); fill.classList.add("progbar_empty"); fill.style.width = "248px"; volume.appendChild(fill); volumeInner = document.createElement("div"); volumeInner.classList.add("thumb"); volumeInner.addEventListener("mousedown", function (e) { dragging = true; dragPos = e.offsetX; }); fill.appendChild(volumeInner); document.querySelector(".inline_player").appendChild(container); updateHtml(); document.addEventListener("mouseup", function () { if (dragging) { localStorage.setItem("volume", percentage); dragging = false; } }); document.addEventListener("mousemove", function (e) { if (dragging) { var pos = volume.getBoundingClientRect(); audio.muted = false; percentage = clamp(((e.pageX - pos.left) - dragPos) / dragWidth, 0, 1); updateVolume(); updateHtml(); } }); } if (document.readyState == 'complete') { onLoad(); } else { window.addEventListener("load", onLoad); } function updateVolume() { audio.volume = (Math.exp(percentage) - 1) / (Math.E - 1); } function updateHtml() { // svgs from https://www.material.io/resources/icons if (audio.muted) { speaker.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 24 24" width="32"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'; volumeInner.style.left = "0%"; } else { if (percentage <= 0) { speaker.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 24 24" width="32"><path d="M7 9v6h4l5 5V4l-5 5H7z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'; } else if (percentage < 0.5) { speaker.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 24 24" width="32"><path d="M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'; } else { speaker.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="32" viewBox="0 0 24 24" width="32"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/><path d="M0 0h24v24H0z" fill="none"/></svg>'; } volumeInner.style.left = dragWidth * percentage + 'px'; } } function clamp(num, min, max) { return num <= min ? min : num >= max ? max : num; }