resizeHandle.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. (function() {
  2. const GRADIO_MIN_WIDTH = 320;
  3. const PAD = 16;
  4. const DEBOUNCE_TIME = 100;
  5. const R = {
  6. tracking: false,
  7. parent: null,
  8. parentWidth: null,
  9. leftCol: null,
  10. leftColStartWidth: null,
  11. screenX: null,
  12. };
  13. let resizeTimer;
  14. let parents = [];
  15. function setLeftColGridTemplate(el, width) {
  16. el.style.gridTemplateColumns = `${width}px 16px 1fr`;
  17. }
  18. function displayResizeHandle(parent) {
  19. if (window.innerWidth < GRADIO_MIN_WIDTH * 2 + PAD * 4) {
  20. parent.style.display = 'flex';
  21. parent.resizeHandle.style.display = "none";
  22. return false;
  23. } else {
  24. parent.style.display = 'grid';
  25. parent.resizeHandle.style.display = "block";
  26. return true;
  27. }
  28. }
  29. function afterResize(parent) {
  30. if (displayResizeHandle(parent) && parent.style.gridTemplateColumns != parent.style.originalGridTemplateColumns) {
  31. const oldParentWidth = R.parentWidth;
  32. const newParentWidth = parent.offsetWidth;
  33. const widthL = parseInt(parent.style.gridTemplateColumns.split(' ')[0]);
  34. const ratio = newParentWidth / oldParentWidth;
  35. const newWidthL = Math.max(Math.floor(ratio * widthL), parent.minLeftColWidth);
  36. setLeftColGridTemplate(parent, newWidthL);
  37. R.parentWidth = newParentWidth;
  38. }
  39. }
  40. function setup(parent) {
  41. const leftCol = parent.firstElementChild;
  42. const rightCol = parent.lastElementChild;
  43. parents.push(parent);
  44. parent.style.display = 'grid';
  45. parent.style.gap = '0';
  46. let leftColTemplate = "";
  47. if (parent.children[0].style.flexGrow) {
  48. leftColTemplate = `${parent.children[0].style.flexGrow}fr`;
  49. parent.minLeftColWidth = GRADIO_MIN_WIDTH;
  50. } else {
  51. leftColTemplate = parent.children[0].style.flexBasis;
  52. parent.minLeftColWidth = parent.children[0].style.flexBasis.slice(0, -2);
  53. }
  54. const gridTemplateColumns = `${leftColTemplate} ${PAD}px ${parent.children[1].style.flexGrow}fr`;
  55. parent.style.gridTemplateColumns = gridTemplateColumns;
  56. parent.style.originalGridTemplateColumns = gridTemplateColumns;
  57. const resizeHandle = document.createElement('div');
  58. resizeHandle.classList.add('resize-handle');
  59. parent.insertBefore(resizeHandle, rightCol);
  60. parent.resizeHandle = resizeHandle;
  61. ['mousedown', 'touchstart'].forEach((eventType) => {
  62. resizeHandle.addEventListener(eventType, (evt) => {
  63. if (eventType.startsWith('mouse')) {
  64. if (evt.button !== 0) return;
  65. } else {
  66. if (evt.changedTouches.length !== 1) return;
  67. }
  68. evt.preventDefault();
  69. evt.stopPropagation();
  70. document.body.classList.add('resizing');
  71. R.tracking = true;
  72. R.parent = parent;
  73. R.parentWidth = parent.offsetWidth;
  74. R.leftCol = leftCol;
  75. R.leftColStartWidth = leftCol.offsetWidth;
  76. if (eventType.startsWith('mouse')) {
  77. R.screenX = evt.screenX;
  78. } else {
  79. R.screenX = evt.changedTouches[0].screenX;
  80. }
  81. });
  82. });
  83. resizeHandle.addEventListener('dblclick', (evt) => {
  84. evt.preventDefault();
  85. evt.stopPropagation();
  86. parent.style.gridTemplateColumns = parent.style.originalGridTemplateColumns;
  87. });
  88. afterResize(parent);
  89. }
  90. ['mousemove', 'touchmove'].forEach((eventType) => {
  91. window.addEventListener(eventType, (evt) => {
  92. if (eventType.startsWith('mouse')) {
  93. if (evt.button !== 0) return;
  94. } else {
  95. if (evt.changedTouches.length !== 1) return;
  96. }
  97. if (R.tracking) {
  98. if (eventType.startsWith('mouse')) {
  99. evt.preventDefault();
  100. }
  101. evt.stopPropagation();
  102. let delta = 0;
  103. if (eventType.startsWith('mouse')) {
  104. delta = R.screenX - evt.screenX;
  105. } else {
  106. delta = R.screenX - evt.changedTouches[0].screenX;
  107. }
  108. const leftColWidth = Math.max(Math.min(R.leftColStartWidth - delta, R.parent.offsetWidth - GRADIO_MIN_WIDTH - PAD), R.parent.minLeftColWidth);
  109. setLeftColGridTemplate(R.parent, leftColWidth);
  110. }
  111. });
  112. });
  113. ['mouseup', 'touchend'].forEach((eventType) => {
  114. window.addEventListener(eventType, (evt) => {
  115. if (eventType.startsWith('mouse')) {
  116. if (evt.button !== 0) return;
  117. } else {
  118. if (evt.changedTouches.length !== 1) return;
  119. }
  120. if (R.tracking) {
  121. evt.preventDefault();
  122. evt.stopPropagation();
  123. R.tracking = false;
  124. document.body.classList.remove('resizing');
  125. }
  126. });
  127. });
  128. window.addEventListener('resize', () => {
  129. clearTimeout(resizeTimer);
  130. resizeTimer = setTimeout(function() {
  131. for (const parent of parents) {
  132. afterResize(parent);
  133. }
  134. }, DEBOUNCE_TIME);
  135. });
  136. setupResizeHandle = setup;
  137. })();
  138. onUiLoaded(function() {
  139. for (var elem of gradioApp().querySelectorAll('.resize-handle-row')) {
  140. if (!elem.querySelector('.resize-handle')) {
  141. setupResizeHandle(elem);
  142. }
  143. }
  144. });
  145. function setupExtraNetworksResizeHandle() {
  146. for (var elem of document.body.querySelectorAll('.resize-handle-row')) {
  147. if (!elem.querySelector('.resize-handle') && !elem.children[0].classList.contains("hidden")) {
  148. setupResizeHandle(elem);
  149. }
  150. }
  151. }