Guest User

Untitled

a guest
Feb 25th, 2021
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.67 KB | None | 0 0
  1. <script type="text/javascript">
  2. const map = (typeof Map === "function") ? new Map() : (function() {
  3. const keys = [];
  4. const values = [];
  5. return {
  6. has(key) {
  7. return keys.indexOf(key) > -1;
  8. },
  9. get(key) {
  10. return values[keys.indexOf(key)];
  11. },
  12. set(key, value) {
  13. if (keys.indexOf(key) === -1) {
  14. keys.push(key);
  15. values.push(value);
  16. }
  17. },
  18. delete(key) {
  19. const index = keys.indexOf(key);
  20. if (index > -1) {
  21. keys.splice(index, 1);
  22. values.splice(index, 1);
  23. }
  24. },
  25. }
  26. })();
  27. let createEvent = (name) => new Event(name, {
  28. bubbles: true
  29. });
  30. try {
  31. new Event('test');
  32. } catch (e) {
  33. // IE does not support `new Event()`
  34. createEvent = (name) => {
  35. const evt = document.createEvent('Event');
  36. evt.initEvent(name, true, false);
  37. return evt;
  38. };
  39. }
  40.  
  41. function assign(ta) {
  42. if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || map.has(ta)) return;
  43. let heightOffset = null;
  44. let clientWidth = null;
  45. let cachedHeight = null;
  46.  
  47. function init() {
  48. const style = window.getComputedStyle(ta, null);
  49. if (style.resize === 'vertical') {
  50. ta.style.resize = 'none';
  51. } else if (style.resize === 'both') {
  52. ta.style.resize = 'horizontal';
  53. }
  54. if (style.boxSizing === 'content-box') {
  55. heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
  56. } else {
  57. heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
  58. }
  59. // Fix when a textarea is not on document body and heightOffset is Not a Number
  60. if (isNaN(heightOffset)) {
  61. heightOffset = 0;
  62. }
  63. update();
  64. }
  65.  
  66. function changeOverflow(value) {
  67. {
  68. // Chrome/Safari-specific fix:
  69. // When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
  70. // made available by removing the scrollbar. The following forces the necessary text reflow.
  71. const width = ta.style.width;
  72. ta.style.width = '0px';
  73. // Force reflow:
  74. /* jshint ignore:start */
  75. ta.offsetWidth;
  76. /* jshint ignore:end */
  77. ta.style.width = width;
  78. }
  79. ta.style.overflowY = value;
  80. }
  81.  
  82. function getParentOverflows(el) {
  83. const arr = [];
  84. while (el && el.parentNode && el.parentNode instanceof Element) {
  85. if (el.parentNode.scrollTop) {
  86. arr.push({
  87. node: el.parentNode,
  88. scrollTop: el.parentNode.scrollTop,
  89. })
  90. }
  91. el = el.parentNode;
  92. }
  93. return arr;
  94. }
  95.  
  96. function resize() {
  97. if (ta.scrollHeight === 0) {
  98. // If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
  99. return;
  100. }
  101. const overflows = getParentOverflows(ta);
  102. const docTop = document.documentElement && document.documentElement.scrollTop; // Needed for Mobile IE (ticket #240)
  103. ta.style.height = '';
  104. ta.style.height = (ta.scrollHeight + heightOffset) + 'px';
  105. // used to check if an update is actually necessary on window.resize
  106. clientWidth = ta.clientWidth;
  107. // prevents scroll-position jumping
  108. overflows.forEach(el => {
  109. el.node.scrollTop = el.scrollTop
  110. });
  111. if (docTop) {
  112. document.documentElement.scrollTop = docTop;
  113. }
  114. }
  115.  
  116. function update() {
  117. resize();
  118. const styleHeight = Math.round(parseFloat(ta.style.height));
  119. const computed = window.getComputedStyle(ta, null);
  120. // Using offsetHeight as a replacement for computed.height in IE, because IE does not account use of border-box
  121. var actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(computed.height)) : ta.offsetHeight;
  122. // The actual height not matching the style height (set via the resize method) indicates that
  123. // the max-height has been exceeded, in which case the overflow should be allowed.
  124. if (actualHeight < styleHeight) {
  125. if (computed.overflowY === 'hidden') {
  126. changeOverflow('scroll');
  127. resize();
  128. actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
  129. }
  130. } else {
  131. // Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
  132. if (computed.overflowY !== 'hidden') {
  133. changeOverflow('hidden');
  134. resize();
  135. actualHeight = computed.boxSizing === 'content-box' ? Math.round(parseFloat(window.getComputedStyle(ta, null).height)) : ta.offsetHeight;
  136. }
  137. }
  138. if (cachedHeight !== actualHeight) {
  139. cachedHeight = actualHeight;
  140. const evt = createEvent('autosize:resized');
  141. try {
  142. ta.dispatchEvent(evt);
  143. } catch (err) {
  144. // Firefox will throw an error on dispatchEvent for a detached element
  145. // https://bugzilla.mozilla.org/show_bug.cgi?id=889376
  146. }
  147. }
  148. }
  149. const pageResize = () => {
  150. if (ta.clientWidth !== clientWidth) {
  151. update();
  152. }
  153. };
  154. const destroy = (style => {
  155. window.removeEventListener('resize', pageResize, false);
  156. ta.removeEventListener('input', update, false);
  157. ta.removeEventListener('keyup', update, false);
  158. ta.removeEventListener('autosize:destroy', destroy, false);
  159. ta.removeEventListener('autosize:update', update, false);
  160. Object.keys(style).forEach(key => {
  161. ta.style[key] = style[key];
  162. });
  163. map.delete(ta);
  164. }).bind(ta, {
  165. height: ta.style.height,
  166. resize: ta.style.resize,
  167. overflowY: ta.style.overflowY,
  168. overflowX: ta.style.overflowX,
  169. wordWrap: ta.style.wordWrap,
  170. });
  171. ta.addEventListener('autosize:destroy', destroy, false);
  172. // IE9 does not fire onpropertychange or oninput for deletions,
  173. // so binding to onkeyup to catch most of those events.
  174. // There is no way that I know of to detect something like 'cut' in IE9.
  175. if ('onpropertychange' in ta && 'oninput' in ta) {
  176. ta.addEventListener('keyup', update, false);
  177. }
  178. window.addEventListener('resize', pageResize, false);
  179. ta.addEventListener('input', update, false);
  180. ta.addEventListener('autosize:update', update, false);
  181. ta.style.overflowX = 'hidden';
  182. ta.style.wordWrap = 'break-word';
  183. map.set(ta, {
  184. destroy,
  185. update,
  186. });
  187. init();
  188. }
  189.  
  190. function destroy(ta) {
  191. const methods = map.get(ta);
  192. if (methods) {
  193. methods.destroy();
  194. }
  195. }
  196.  
  197. function update(ta) {
  198. const methods = map.get(ta);
  199. if (methods) {
  200. methods.update();
  201. }
  202. }
  203. let autosize = null;
  204. // Do nothing in Node.js environment and IE8 (or lower)
  205. if (typeof window === 'undefined' || typeof window.getComputedStyle !== 'function') {
  206. autosize = el => el;
  207. autosize.destroy = el => el;
  208. autosize.update = el => el;
  209. } else {
  210. autosize = (el, options) => {
  211. if (el) {
  212. Array.prototype.forEach.call(el.length ? el : [el], x => assign(x, options));
  213. }
  214. return el;
  215. };
  216. autosize.destroy = el => {
  217. if (el) {
  218. Array.prototype.forEach.call(el.length ? el : [el], destroy);
  219. }
  220. return el;
  221. };
  222. autosize.update = el => {
  223. if (el) {
  224. Array.prototype.forEach.call(el.length ? el : [el], update);
  225. }
  226. return el;
  227. };
  228. }
  229. export default autosize;
  230. autosize(document.querySelector('textarea'));
  231. </script>
Advertisement
Add Comment
Please, Sign In to add comment