Up-down arrows buttons (Mobile)

Creates up-down arrows buttons on chart

  1. // ==UserScript==
  2. // @name Up-down arrows buttons (Mobile)
  3. // @description Creates up-down arrows buttons on chart
  4. // @author Konf
  5. // @namespace https://greasyfork.org/users/424058
  6. // @icon https://www.google.com/s2/favicons?sz=64&domain=tradingview.com
  7. // @version 2.0.1
  8. // @match https://www.tradingview.com/chart/*
  9. // @run-at document-body
  10. // @grant GM_addStyle
  11. // @noframes
  12. // ==/UserScript==
  13.  
  14. /* jshint esversion: 8 */
  15. /* eslint no-multi-spaces: 'off' */
  16.  
  17. (function() {
  18. 'use strict';
  19.  
  20. // The script creates an arrows inside of a buttons. Buttons represent the arrows hitboxes
  21.  
  22. // Set to true to show a red outlines representing buttons hitboxes, or false to hide them
  23. const DEBUG_OUTLINE = false;
  24.  
  25. // For a buttons/arrows sizes use these values:
  26. // '50px' to set 50 pixels or '50vw' to set 50% of view width or '50vh' for a view height.
  27. // Percents are not recommended because they're always based on width of a parent element
  28.  
  29. const X_GAP_SIDE = 'right'; // 'left' or 'right'
  30. const Y_GAP_SIDE = 'bottom'; // 'top' or 'bottom'
  31. const BUTTONS_X_GAP = '0px'; // x gap size
  32. const BUTTONS_Y_GAP = '100px'; // y gap size
  33.  
  34. const BUTTONS_WIDTH = '60px';
  35. const BUTTONS_HEIGHT = '55px';
  36.  
  37. // This is useful when you're editing the arrows size related to the buttons hitboxes.
  38. // Fractional values like 1.4 or 0.7 are allowed too
  39. const ARROWS_SCALE = 0.85;
  40.  
  41. // This is useful when you're editing the arrows position related to the buttons hitboxes.
  42. // Represents individual inner gaps of the buttons. 4 values representing the sides where
  43. // first value is the top gap, and the other three are right, bottom, left sides respectively.
  44. const UP_BUTTON_PADDING = '5px 5px 0px 5px'; // top right bottom left
  45. const DOWN_BUTTON_PADDING = '0px 5px 5px 5px';
  46. const ARROWS_OPACITY = 0.8; // 1 is fully visible, 0.5 is half visible
  47.  
  48. const ARROW_UP_ROTATE = 0; // clockwise, may take negative values
  49. const ARROW_DOWN_ROTATE = 180;
  50.  
  51. const ARROW_UP_SRC = 'https://img.icons8.com/fluency-systems-filled/2962ff/128/triangle.png';
  52. const ARROW_DOWN_SRC = 'https://img.icons8.com/fluency-systems-filled/2962ff/128/triangle.png';
  53.  
  54. const btnsContainer = document.createElement('div');
  55. const btnUp = document.createElement('button');
  56. const btnDown = document.createElement('button');
  57.  
  58. btnsContainer.classList.add('up-down-arrows');
  59.  
  60. GM_addStyle(`
  61. div.up-down-arrows {
  62. position: fixed;
  63. user-select: none;
  64. z-index: 3;
  65. ${X_GAP_SIDE}: ${BUTTONS_X_GAP};
  66. ${Y_GAP_SIDE}: ${BUTTONS_Y_GAP};
  67. }
  68.  
  69. div.up-down-arrows button {
  70. width: ${BUTTONS_WIDTH};
  71. height: ${BUTTONS_HEIGHT};
  72. display: block;
  73. padding: 0;
  74. box-sizing: border-box;
  75. cursor: pointer;
  76. overflow: hidden;
  77. background: none;
  78. border: ${DEBUG_OUTLINE ? '1px solid red' : 'none'};
  79. }
  80.  
  81. div.up-down-arrows img {
  82. scale: ${ARROWS_SCALE};
  83. width: 100%;
  84. opacity: ${ARROWS_OPACITY};
  85. height: -moz-available;
  86. height: -webkit-fill-available;
  87. height: fill-available;
  88. }
  89. `);
  90.  
  91. btnUp.append(document.createElement('img'));
  92. btnUp.addEventListener('click', () => pressKey('ArrowUp', 38));
  93. btnUp.style.padding = UP_BUTTON_PADDING;
  94. btnUp.firstChild.src = ARROW_UP_SRC;
  95.  
  96. if (ARROW_UP_ROTATE) {
  97. btnUp.firstChild.style.transform = `rotate(${ARROW_UP_ROTATE}deg)`;
  98. }
  99.  
  100. btnDown.append(document.createElement('img'));
  101. btnDown.addEventListener('click', () => pressKey('ArrowDown', 40));
  102. btnDown.style.padding = DOWN_BUTTON_PADDING;
  103. btnDown.firstChild.src = ARROW_DOWN_SRC;
  104.  
  105. if (ARROW_DOWN_ROTATE) {
  106. btnDown.firstChild.style.transform = `rotate(${ARROW_DOWN_ROTATE}deg)`;
  107. }
  108.  
  109. for (const el of [
  110. btnsContainer, btnUp, btnDown, btnUp.firstChild, btnDown.firstChild,
  111. ]) {
  112. el.setAttribute('draggable', 'false');
  113. el.addEventListener('dragstart', (ev) => {
  114. ev.preventDefault();
  115. ev.stopImmediatePropagation();
  116. });
  117. }
  118.  
  119. btnsContainer.append(btnUp, btnDown);
  120. document.body.append(btnsContainer);
  121.  
  122. // utils ----------------------------------------------------------------------
  123.  
  124. function pressKey(key, code) {
  125. const event = new KeyboardEvent('keydown', {
  126. key,
  127. code,
  128. keyCode: code,
  129. which: code,
  130. bubbles: true,
  131. });
  132.  
  133. document.body.dispatchEvent(event);
  134. }
  135.  
  136. // ---------------------------------------------------------------------- utils
  137. }());