如何在 Textarea 元素中显示数组

Posted

技术标签:

【中文标题】如何在 Textarea 元素中显示数组【英文标题】:How to display the arrays in a Textarea element 【发布时间】:2020-04-07 16:55:43 【问题描述】:

我想在textarea中显示非常硬的数组和硬数组。现在,它显示在 textarea 下,因为我不知道如何在 textarea 中显示它。用户通过用户输入的难句和非常难句给出输入和服务器响应。难句有黄色背景,非常难句有红色背景。目前,只有黄色和红色背景的难句和非常难的句子分别显示在 textarea 下方而不是全部内容,但我认为这不直观,因为用户必须再次在 textarea 中搜索句子作为句子的确切位置。所以我希望整个事情都显示在 textarea 本身中,用黄色和红色背景突出显示的难句和非常难句。

现在我的代码看起来像这样:

state=
    hardArray: [],
    vhardArray: []


  performHard = async () => 
    const  enteredText  = this.state;
    const body =  text: enteredText ;
    const stringifiedBody = JSON.stringify(body);
    const options = 
      method: "POST",
      headers: 
        "Content-Type": "application/json",
        Accept: "application/json"
      ,
      body: stringifiedBody
    ;
    const url = "api/same";

    try 
      const response = await fetch(url, options);
      const result = await response.json();
      this.setState(prevState => (
        hardArray: [...prevState.hardArray, ...result.hard]
      ));
     catch (error) 
      console.error("error");
    
  ;
  performVHard = async () => 
    const  enteredText  = this.state;
    const body =  text: enteredText ;
    const stringifiedBody = JSON.stringify(body);
    const options = 
      method: "POST",
      headers: 
        "Content-Type": "application/json",
        Accept: "application/json"
      ,
      body: stringifiedBody
    ;
    const url ="api/same";
    try 
      const response = await fetch(url, options);
      const result = await response.json();
      this.setState(prevState => (
        vhardArray: [...prevState.vhardArray, ...result.very_hard]
      ));
     catch (error) 
      console.error("error");
    
  ;
  performAnalysis = () => 
    this.performHard();
    this.performVHard();
  ;

  <textarea
    name="enteredText"       
    className="textareaclass"
    placeholder="Enter your text here"
    onChange=this.handleChange
    value=enteredText
    ></textarea>
  <Button 
   className="rectangle-3" 
   onClick=this.performAnalysis>Analyse
   </Button>
  <div>
   this.state.hardArray.map((word, i) => (
     <span className="hardColor">word</span>
   ))
   this.state.vhardArray.map((word, i) => (
     <span className="vhardColor">word</span>
   ))
  </div>

编辑:这就是我从服务器接收响应的方式


  "hard": [
    "It's the possibility of having a dream come true that makes life interesting",
    "I cannot fix on the hour, or the spot, or the look or the words, which laid the foundation.",
  ]
 "very_hard": [
    “He stepped down, trying not to look long at her, as if she were the sun, yet he saw her, like the sun, even 
     without looking.”
  ]

我想在用户编写内容的同一文本区域中显示所有文本,而不是在浏览器中的其他任何地方显示,因为这会使所有内容看起来很丑。

【问题讨论】:

这能回答你的问题吗? How can I pretty-print JSON using javascript? 不,它没有@NVRM。我认为它没有回答我将如何将它们注入文本区域。 根据这个post 和这个post,我认为你不能用普通的textarea 做到这一点。您可能想查看CodeMirror 如何实现他们的彩色编辑器。 如果我想再显示一个框(不是 textarea),但整个文本分别用黄色和红色突出显示,非硬或非非常硬,只需一个简单的白色背景? 【参考方案1】:

它没有颜色,但在这段代码中你可以设置这样的标签(hard:veryhard :)

    state = 
    value: "",
    hard: [],
    veryHard: []
  ;

  handleChange = ( target ) => 
    const  value, name  = target;
    console.log(value, name);
    this.setState( value );
  ;

  performAnalysis = () => 
    let hard = [
     //this state ,get from performHard function (you should set state it )
      "It's the possibility of having a dream come true that makes life interesting",
      "I cannot fix on the hour, or the spot, or the look or the words, which laid the foundation."
    ];
    let veryHard = [
      //this state ,get from performVHard function (you should set state it )
      "“He stepped down, trying not to look long at her, as if she were the sun, yet he saw her, like the sun, even without looking.“"
    ];
    this.setState( hard, veryHard );

    // you shoud setState like this in these 2 function
    // this.performHard();
    // this.performVHard();
  ;
  render() 
    return (
      <div className="App">
        <header className="App-header">
          <textarea
            value=
              this.state.value.length
                ? this.state.value
                : " Hard : " +
                  " " +
                  this.state.hard +
                  " " +
                  "very Hard : " +
                  this.state.veryHard
            
            onChange=this.handleChange
          />
          <button onClick=this.performAnalysis>analise</button>
        </header>
      </div>
    );
  

它并不完全是你想要的,但你可以从这段代码中获得帮助

【讨论】:

【参考方案2】:

你只能给 textarea 一个背景颜色,但你可以让它透明并在它后面放一些东西来添加一些颜色,是的,这完全是 hack,你需要摆弄尺寸和空白行将文本向下移动一点 - 我将把这个练习留给你。

这也没有显示如何将您的值放入textarea,但这可能是简单的 JavaScript/react 代码。

我用一些函数对此进行了更改,以说明您可以在哪里简单地添加/删除 textarea 中的空白行以匹配背景颜色的高度 - 当它溢出大小时可能必须调整该背景以匹配,或者您可以调整背景以使其颜色更小。

我会让你决定哪个是更好的选择,我使用 "|""||" 作为行/节分隔符,因为一旦它在 textarea 中并进行了编辑,你将需要类似的东西。

我现在有时间来加强这一点,但应该为这种没有明确标准解决方案的边缘情况提供一个起点。

.message 
  width: 300px;
  height: 150px;
  display: block;
  position: absolute;


textarea.format-custom,
.custom-underlay,
.underlay 
  margin: 0;
  box-sizing: border-box;
  vertical-align: top;
  display: block;
  position: absolute;
  border: lime solid 1px;


textarea.format-custom 
  width: 100%;
  height: 100%;
  background: transparent;
  resize: none;
  display: block;


.underlay 
  width: 100%;
  height: 100%;
  background: transparent;
  display: block;
  z-index: -1;


.custom-underlay 
  width: 100%;
  height: 50%;
  margin: 0;
  box-sizing: border-box;
  vertical-align: top;


.custom-underlay.top 
  background-color: #FFDDDD;
  top: 0;
  left: 0;


.custom-underlay.bottom 
  background-color: #DDDDFF;
  top: 50%;
  left: 0;
<div class="message">
  <label for="msg">Your message:</label>
  <textarea id="msg" name="user_message" class="format-custom">howdy, I am here
  
  
  
  
bottom of here</textarea>
  <div class="underlay">
    <div class="custom-underlay top"></div>
    <div class="custom-underlay bottom"></div>
  </div>
</div>

问题的替代想法,将文本放在 div 的后面:

'use strict';
// borrowed code from https://***.com/a/17590149/125981
// makeClass - By Hubert Kauker (MIT Licensed)
// original by John Resig (MIT Licensed).
var makeClass = (function(Void) 
  return function() 
    var constructor = function() 
      var init = constructor.prototype.init,
        hasInitMethod = (typeof init == "function"),
        instance;
      if (this instanceof constructor) 
        if (hasInitMethod) init.apply(this, arguments);
       else 
        Void.prototype = constructor.prototype;
        instance = new Void();
        if (hasInitMethod) init.apply(instance, arguments);
        return instance;
      
    ;
    return constructor;
  ;
)(function() );

//make a class MyApp using above
var MyApp = makeClass();

// create MyApp functional part using the init:
MyApp.prototype.init = function(myItem, showmeClass = "showme", separator = "|", groupSeparator = "||") 
  let eventChangeName = "change";
  let textElement = document.getElementById(myItem);
  let showme = textElement.closest(".container").getElementsByClassName(showmeClass)[0];
  let lineSep = "|\n";
  let myData = 
    hard: [],
    very_hard: []
  ;
  this.sentData = 
    hard: [],
    very_hard: []
  ;

  //so we can tell the lines
  function getStyle(elId, styleProp) 
    var x = document.getElementById(elId);
    let y = ;
    if (x.currentStyle) 
      y = x.currentStyle[styleProp];
     else if (window.getComputedStyle) 
      y = document.defaultView.getComputedStyle(x, null).getPropertyValue(styleProp);
    
    return y;
  

  function getTextareaThings(myTextarea) 
    let taComputedStyles = window.getComputedStyle(myTextarea);
    return 
      height: myTextarea.style.height,
      rows: myTextarea.rows,
      clientHeight: myTextarea.clientHeight,
      lineHeight: taComputedStyles.getPropertyValue('line-height'),
      font: taComputedStyles.getPropertyValue('font-size')
    ;
  

  function getLinesInString(myString) 
    /* new line things: /r old Mac, /cr/lf some, /n some
     all the "new line": regex: /\r\n|\n|\r/gm
     above reduced regex: g and m are for global and multiline flags */
    let nl = /[\r\n]+/gm;
    let lines = [];
    lines = myString.split(nl);
    return lines;
  

  function splitGroupString(myString, separator) 
    let strings = [];
    strings = myString.split(separator);
    return strings;
  

  function getGroupsInString(myString) 
    return splitGroupString(myString, groupSeparator);
  

  function getGroupItemsInString(myString) 
    return splitGroupString(myString, separator);
  

  function getCurrentValue() 
    return textElement.value;
  

  function addNewLines(text, count) 
    let newLine = "\n";
    return text + newLine.repeat(count);
  
  // make stuff obvious
  function onFocusTextareaValue(event) 
    showForDebug(event);
  

  function onChangeTextareaValue(event) 
    if (event.type == eventChangeName) 
      event.stopPropagation();
      event.stopImmediatePropagation();
    
    showForDebug(event);
  

  function showForDebug(event) 
    let what = "Event: " + event.type;
    let b = "<br />";
    let tat = getTextareaThings(event.target);
    let v = getCurrentValue().replace(what, "");
    showme.innerhtml = what + b + ": lines:" + getLinesInString(v).length + b + v;
  

  function getStringLineCount(arr) 
    arr.length;
  

  function getGroupItems() 
    let groups = getGroupsInString(getCurrentValue());
    let groupItems = 
      count: groups.length, // how many groups, two in the definition (top/bottom)
      groups: []
    ;
    groups.forEach(function(group, index, groupsArr) 
      let items = getGroupItemsInString(group);
      // determine how to define "group name", I use a string and the index here
      let gname = "group" + index;
      let g = 
        itemCount: items.length // number in this group
      ;
      g[gname] = 
        items: []
      ;
      items.forEach(function(item, itemindex, itemsArr) 
        let itemName = "item" + itemindex;
        let itemobj = ;
        itemobj[itemName] = 
          items: item
        ;
        g[gname].items.push(itemobj);
      );
      groupItems.groups.push(g);
    );
    return groupItems;
  
  // setup events
  textElement.addEventListener(eventChangeName, onChangeTextareaValue, false);
  textElement.addEventListener("focus", onFocusTextareaValue, false);
  this.getGeometry = function() 
    let geometry = ;
    let element = textElement;
    let rect = element.getBoundingClientRect();
    geometry.top = rect.top;
    geometry.right = rect.right;
    geometry.bottom = rect.bottom;
    geometry.left = rect.left;
    geometry.offsetHeight = element.offsetHeight;
    geometry.rows = element.rows;
    geometry.clientHeight = element.clientHeight;
    geometry.fontSize = this.getStyleProperty("font-size");
    geometry.lineCount = this.getLines().length;
    geometry.lineHeight = this.getLineHeight();
    geometry.height = geometry.bottom - geometry.top;
    geometry.width = geometry.right - geometry.left;
    console.log("Geometry:",geometry);
  ;
  
  this.getMetrics = function() 
    let fSize = this.getStyleProperty("font-size");
    let lineCount = this.getLines().length;
    let lineHeight = this.getLineHeight();
    let yh = lineHeight / lineCount;

    let yfhPixel = parseInt(fSize, 10);
    let yLineY = yh * yfhPixel;
    console.log("LH:", lineHeight, "font:", fSize, "Lines:", lineCount, "lineHeight:", lineHeight, "yh:", yh, "yfPixel:", yfhPixel, "yLineY:", yLineY);
  ;

  this.getStyleProperty = function(propertyName) 
    return getStyle(textElement.id, propertyName)
  ;

  // public functions and objects
  this.getLines = function() 
    return getLinesInString(getCurrentValue());
  ;
  this.getGroups = function() 
    return getGroupsInString(getCurrentValue());
  ;
  this.setText = function(content) 
    if (!content) 
      content = this.sentData;
    

    let hard = content.hard.join(lineSep);
    let veryHard = content.very_hard.join(lineSep);
    this.textElement.value = hard.concat("|" + lineSep, veryHard);
  ;
  this.getLineHeight = function(element) 
    if (!element) 
      element = textElement;
    
    let temp = document.createElement(element.nodeName);
    temp.setAttribute("style", "margin:0px;padding:0px;font-family:" + element.style.fontFamily + ";font-size:" + element.style.fontSize);
    temp.innerHTML = "test";
    temp = element.parentNode.appendChild(temp);
    let lineHeight = temp.clientHeight;
    temp.parentNode.removeChild(temp);
    return lineHeight;
  ;

  this.getGroupItems = function() 
    return getGroupItems();
  ;
  this.textElement = textElement;
  this.showme = showme;
;
let sentData = 
  hard: [
    "It's the possibility of having a dream come true that makes life interesting",
    "I cannot fix on the hour, or the spot, or the look or the words, which laid the foundation."
  ],
  very_hard: ["He stepped down, trying not to look long at her, as if she were the sun, yet he saw her, like the sun, even without looking."]
;

// create instances and use our app, pass the id
var containerApp = MyApp("textThing"); //default last three parameters

containerApp.sentData = sentData;
containerApp.setText();
let groups = containerApp.getGroups();
let groupItems = containerApp.getGroupItems();
containerApp.getMetrics();
containerApp.getGeometry();


// create instances and use our app, pass the id
var containerApp2 = MyApp("msgTwo", "showme", "|", "||");

//console.log("Second One Lines:", containerApp2.getLines().length);
//containerApp2.getMetrics();
//containerApp2.getGeometry();
.page-container 
  display: flex;
  /* center and stack the containers*/
  justify-content: center;
  flex-direction: column;
  align-items: center;
  font-size: 62.5%;


.container 
  border: solid 1px black;


.container-block 
  border: 2px dashed #AAAAAA;


.container-items 
  width: 500px;
  position: relative;


.container-items .format-custom,
.container-items label 
  width: 100%;


.container-items .format-custom 
  height: 10em


.message-hr 
  border: 1px solid blue;
  background-color: blue;
  height: 0.05em;
  width: 450px;
  align-items: center;
  margin: 0.5em;


.showme 
  border: dotted 2px dodgerblue;
  background-color: #EEEEEE;
  padding: 1em;


textarea.format-custom,
.custom-underlay,
.underlay 
  margin: 0;
  box-sizing: border-box;
  vertical-align: top;
  display: block;
  border: lime solid 1px;


textarea.format-custom 
  width: 100%;
  height: 3em;
  background: transparent;
  resize: none;
  border: red solid 1px;
  padding: 0.5em;


.underlay 
  border: 1px solid #fff;
  width: 100%;
  height: 100%;
  background: transparent;
  top: 1em;
  left: 0;
  display: block;
  z-index: -1;
  position: absolute;


.custom-underlay 
  width: 100%;
  height: 50%;
  margin: 0;
  box-sizing: border-box;
  vertical-align: top;
  position: absolute;


.custom-underlay.top 
  background-color: #FFFF00;
  top: 0;
  left: 0;


.custom-underlay.bottom 
  background-color: #FFAAAA;
  top: 50%;
  left: 0;
<div class="page-container">
  <div class="container">
    <div class="container-block">
      <div class="container-items">
        <label for="textThing">Your message:</label>
        <textarea id="textThing" name="textThing" class="format-custom">howdy, I am here|another one | cheese burgers
fries and a drink   
|| 
bottom of here| bottom second</textarea>
        <div class="underlay">
          <div class="custom-underlay top"></div>
          <div class="custom-underlay bottom"></div>
        </div>
      </div>
    </div>
    <div class="showme">xxxone</div>
  </div>
  <div class="container">
    <div class="container-block">
      <div class="message-hr container-items">
        &nbsp;</div>
    </div>
  </div>
  <div class="container">
    <div class="container-block">
      <div class="container-items">
        <label for="msgTwo">Second message:</label>
        <textarea id="msgTwo" name="msgTwo" class="format-custom">Not the same|Nxxt one 
  
  
  
  
  
  
  
 || 
bottom of next</textarea>
        <div class="underlay">
          <div class="custom-underlay top"></div>
          <div class="custom-underlay bottom"></div>
        </div>
      </div>
    </div>
    <div class="showme">xxxtwo</div>
  </div>
</div>

【讨论】:

我相信这是不可能的难句之后的句子。一开始可以是任何东西,也可能先是非常难,然后是难句,这取决于用户输入的内容。所以我认为 textarea 根本不起作用。如果我想将所有内容保存在一个 div 块容器中,并显示用户输入的所有带有难句和非常难句的文本显示其相应的颜色,而其余的则为白色背景怎么办? 好吧,您可以简单地将文本放在 textarea 后面的适当 div 中,然后将 textarea 文本擦除,当他们再次聚焦时,将其反转,将文本放回。这样 textarea 仍然为焦点而曝光,但显示是分开的(比如在焦点之外)

以上是关于如何在 Textarea 元素中显示数组的主要内容,如果未能解决你的问题,请参考以下文章

正确显示textarea中输入的回车和空格

如何在 php 代码中的 textarea 元素中添加新行?

如何使用用户提供的信息更新在 textArea 中输出的现有数组?

如何在文本区域的末尾设置光标?

如何在 Facebook 状态更新框 (textarea) 中突出显示好友姓名?

如何在 HTML textarea 元素中强制单行?