簡體   English   中英

如何使此 div scrollTop 值與 textarea 的值匹配?

[英]How to make this div scrollTop value match that of the textarea?

我正在使用 div 來格式化和顯示來自等尺寸文本區域的文本,我需要它們永久同步。 但是,在輸入文本超過文本區域底部后,我無法同步它們各自的 scrollTops。

我的過程與此處描述的過程類似,但我無法讓他的解決方案在我的項目中發揮作用。

這是最少相關代碼的演示和片段:

<section>
  <div class="input-text__container">
    <div id="input-text--mirror" class="input-text"></div>
      <textarea
        id="input-text--original"
        cols="30"
        rows="6"
        autofocus
        class="input-text"
        placeholder="Enter your text here"
        autocomplete="off"
        autocorrect="off"
        spellcheck="false"
      ></textarea>
  </div>
<section>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500&display=swap');

html {
  font-size: 62.5%;
  box-sizing: border-box;
  scroll-behavior: smooth;
}

*,
*::after,
*::before {
  margin: 0;
  padding: 0;
  border: 0;
  box-sizing: inherit;
  vertical-align: baseline;
}

body {
  height: 100vh;
}

section {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding: 1rem;
}

.input-text__container {
  width: 100%;
  position: relative;
  flex: 1;
}

.input-text {
  width: 100%;
  height: 100%;
  position: absolute;
  font-size: 3.2rem;
  overflow-wrap: break-word;
  font-family: "Inter";
}

#input-text--mirror {
  background-color: #e9ecf8;
  color: #0a3871;
  overflow: hidden;
}

#input-text--original {
  background-color: transparent;
  -webkit-text-fill-color: transparent;
  resize: none;
  outline: none;
  -ms-overflow-style: none; /* IE and Edge */
  scrollbar-width: none; /* Firefox */
}

#input-text--original::placeholder {
  color: #e9ecf8;
  -webkit-text-fill-color: #052051;
}

#input-text--original::selection {
  -webkit-text-fill-color: #ffffff;
}

.invalid {
  font-weight: 400;
  color: #ff0000;
}

#input-text--original::-webkit-scrollbar {
  display: none;
}
let invalidInput = false;
const patterns = {
  valid: "a-z ",
  invalid: "[^a-z ]",
  linebreaks: "\r|\r\n|\n",
};
const textIn = document.querySelector("#input-text--original");
const mirror = document.querySelector("#input-text--mirror");

function validateInput(string, className) {
  let anyInvalidChar = false;

  // Generate regular expressions for validation
  const regExpInvalids = new RegExp(patterns.invalid, "g");
  const regExpLinebreaks = new RegExp(patterns.linebreaks);

  // Generate innerHTML for mirror
  const mirrorContent = string.replace(regExpInvalids, (match) => {
    if (regExpLinebreaks.test(match)) {
      return "<br/>";
    } else {
      anyInvalidChar = true;
      return `<span class=${className}>${match}</span>`;
    }
  });
  // Update mirror
  mirror.innerHTML = mirrorContent;

  return anyInvalidChar;
}

textIn.addEventListener("input", (e) => {
  const plain = textIn.value;
  const newInputValidity = validateInput(plain, "invalid");
  mirror.scrollTop = textIn.scrollTop;
});

textIn.addEventListener(
  "scroll",
  () => {
    mirror.scrollTop = textIn.scrollTop;
  },
  { passive: true }
);

在桌面屏幕上鍵入列中的前 8 個自然數應該足以重現該問題。

我檢查的最后一件事,但也許到目前為止最相關的是這個 它似乎在 React 上處理完全相同的問題,但恐怕我不知道如何使該解決方案適應 Vanilla JavaScript,因為我才剛剛開始學習 React。 請注意,我正在嘗試尋找一種不依賴於 jQuery 或 React 等庫的解決方案。

除此之外,我通過替換return "<br/>";嘗試了上述博客中描述的解決方案; return "<br/>&nbsp;"; 在我的validateInput function 中,但這沒有用。 我還在 append 中添加了一個條件,一個空格到plain in const plain = textIn.value; 如果最后一個字符是換行符,但我沒有運氣。

我還在mirror.scrollTop = textIn.scrollTop; 在 textIn 滾動處理程序中跟蹤每個 scrollTop 的值,即使它們不同,鏡像 scrollTop 也沒有更新。 我讀到這可能是因為默認情況下 div 不可滾動,但是將“溢出:滾動”添加到其 styles 也沒有解決問題。

我閱讀了與 scrollTop 相關的其他屬性,如offsetTop 和 pageYOffset ,但它們要么是只讀的,要么沒有為 div 定義。

我也查看了以下帖子/站點,但仍然無法解決此問題。

我不再記得我還審查了什么,但沒有任何效果,我不再知道還能做什么。 感謝您的關注和幫助。

在嘗試復制我在帖子中提到的 React 應用程序的解決方案后,使用 vanilla JavaScript (此處演示) ,我嘗試將其應用於我自己的項目,我所要做的就是向mirror添加一個<br>標簽在我的validateInput function 的末尾。即: mirror.innerHTML = mirrorContent + "<br>"; .

除此之外,不需要在每次觸發 textarea 上的輸入事件時更新鏡像的 scrollTop。 也不是將{ passive: true }參數傳遞給滾動事件。

修改后的代碼在這里:

function validateInput(string, className) {
  let anyInvalidChar = false;

  // Generate regular expressions for validation
  const regExpInvalids = new RegExp(patterns.invalid, "g");
  const regExpLinebreaks = new RegExp(patterns.linebreaks);

  // Generate innerHTML for mirror
  const mirrorContent = string.replace(regExpInvalids, (match) => {
    if (regExpLinebreaks.test(match)) {
      return "<br/>";
    } else {
      anyInvalidChar = true;
      return `<span class=${className}>${match}</span>`;
    }
  });
  // Update mirror
  mirror.innerHTML = mirrorContent + "<br>";

  return anyInvalidChar;
}

textIn.addEventListener("input", (e) => {
  const plain = textIn.value;
  const newInputValidity = validateInput(plain, "invalid");
});

textIn.addEventListener("scroll", () => mirror.scrollTop = textIn.scrollTop);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM