Creates up-down arrows buttons on chart
当前为
// ==UserScript==
// @name Up-down arrows buttons for the Tradingview Mobile Site chart
// @description Creates up-down arrows buttons on chart
// @author Konf
// @namespace https://greasyfork.org/users/424058
// @icon https://www.google.com/s2/favicons?sz=64&domain=tradingview.com
// @version 1.1.0
// @match https://www.tradingview.com/*
// @require https://cdnjs.cloudflare.com/ajax/libs/arrive/2.4.1/arrive.min.js#sha512-wkU3qYWjenbM+t2cmvw2ADRRh4opbOYBjkhrPGHV7M6dcE/TR0oKpoDkWXfUs3HrulI2JFuTQyqPLRih1V54EQ==
// @run-at document-body
// @grant none
// @noframes
// ==/UserScript==
/* jshint esversion: 8 */
(function() {
'use strict';
const DEBUG_OUTLINE = false; // true adds red outlines to show hitboxes, false hides them
const BUTTONS_WIDTH = '100%'; // set to 100% to adapt dynamically to price column, or use '50px'
const BUTTONS_HEIGHT = '60px'; // can't use percents here
const BUTTONS_BOTTOM_GAP = '40px'; // bottom padding, can't use percents here
const ARROWS_SCALE = 1; // can be fractional values like 1.4, maybe width is not even needed
const ARROWS_WIDTH = '40px'; // can not go well over 100%, use scale instead
const ARROWS_OPACITY = 0.8; // 1 is fully visible and 0 is fully transparent, 0.5 is half
const ARROW_UP_SRC = 'https://img.icons8.com/fluency-systems-filled/2962ff/128/triangle.png';
const ARROW_DOWN_SRC = 'https://img.icons8.com/fluency-systems-filled/2962ff/128/triangle.png';
const ARROW_UP_ROTATE = 0; // clockwise, may take negative values
const ARROW_DOWN_ROTATE = 180;
const Q = {
priceAxis: 'div.price-axis',
};
document.arrive(Q.priceAxis, { existing: true }, (priceAxis) => {
const btnsContainer = document.createElement('div');
const btnUp = document.createElement('button');
const btnDown = document.createElement('button');
btnUp.addEventListener('click', () => pressKey('ArrowUp', 38));
btnDown.addEventListener('click', () => pressKey('ArrowDown', 40));
for (const btn of [btnUp, btnDown]) {
btn.style.width = '100%';
btn.style.height = BUTTONS_HEIGHT;
btn.style.padding = '0';
btn.style.boxSizing = 'border-box';
btn.style.cursor = 'pointer';
btn.style.overflow = 'hidden';
btn.style.background = 'none';
if (DEBUG_OUTLINE) {
btn.style.border = '1px solid red';
} else {
btn.style.border = 'none';
}
const img = document.createElement('img');
img.style.scale = ARROWS_SCALE;
img.style.width = ARROWS_WIDTH;
img.style.opacity = ARROWS_OPACITY;
btn.append(img);
}
btnUp.firstChild.src = ARROW_UP_SRC;
btnDown.firstChild.src = ARROW_DOWN_SRC;
if (ARROW_UP_ROTATE) {
btnUp.firstChild.style.transform = `rotate(${ARROW_UP_ROTATE}deg)`;
}
if (ARROW_DOWN_ROTATE) {
btnDown.firstChild.style.transform = `rotate(${ARROW_DOWN_ROTATE}deg)`;
}
btnsContainer.style.width = BUTTONS_WIDTH;
btnsContainer.style.position = 'absolute';
btnsContainer.style.bottom = BUTTONS_BOTTOM_GAP;
btnsContainer.style.right = '0';
btnsContainer.style.zIndex = '3';
for (const el of [
btnsContainer, btnUp, btnDown, btnUp.firstChild, btnDown.firstChild,
]) {
el.style.userSelect = 'none';
el.setAttribute('draggable', 'false');
el.addEventListener('dragstart', (ev) => {
ev.preventDefault();
ev.stopImmediatePropagation();
});
}
btnsContainer.append(btnUp, btnDown);
priceAxis.parentElement.append(btnsContainer);
});
// utils ----------------------------------------------------------------------
function pressKey(key, code) {
const event = new KeyboardEvent('keydown', {
key,
code,
keyCode: code,
which: code,
bubbles: true,
});
document.body.dispatchEvent(event);
}
// ---------------------------------------------------------------------- utils
}());