允许使用javascript + LivePreview换行

时间:2016-05-24 15:49:16

标签: javascript jquery css

我正在两个栏目中创建一个网站,在左边,你可以写,并在右边显示一个特殊的设计。
问题是,我想在右侧允许换行,但它不会显示。我怎么能这样做?
这是我的设计预览。要查看完整图片,请参阅> Fiddle HERE

function wordsinblocks(self) {
      var demo = document.getElementById("demo"),
        initialText = demo.textContent,
        wordTags = initialText.split(" ").map(function(word) {
          return '<span class="word">' + word + '</span>';
        });

      demo.innerHTML = wordTags.join('');
      self.disabled = true;
      fitWords();
      window.addEventListener('resize', fitWords);
    }



    $(function() {
      $('textarea.source').livePreview({
        previewElement: $('p#demo'),
        allowedTags: ['p', 'strong', 'br', 'em', 'strike'],
        interval: 20
      });
    });

    window.onload = wordsinblocks(self);

    function fitWords() {
      var demo = document.getElementById("demo"),
        width = demo.offsetWidth,
        sizes = [7.69230769230769, 23.07692307692307, 46.15384615384614, 100],
        calculated = sizes.map(function(size) {
          return width * size / 100
        }),
        node,
        i,
        nodeWidth,
        match,
        index;


      for (i = 0; i < demo.childNodes.length; i++) {
        node = demo.childNodes[i];
        node.classList.remove('size-1', 'size-2', 'size-3', 'size-4');

        nodeWidth = node.clientWidth;
        match = calculated.filter(function(grid) {
          return grid >= nodeWidth;
        })[0];
        index = calculated.indexOf(match);


        node.classList.add('size-' + (index + 1));
      }
    }

5 个答案:

答案 0 :(得分:5)

只要按下Enter键,就可以插入换行符。一种方法是使用.which.keyCode

$(document).keydown(function(e){
     var event = e.which || e.keyCode;
     if (event == 13){
          //do something like this
          return '<span class="word"><br/>' + word + '</span>';
     }
});

&#34; 13&#34;是Enter的字符代码。我已经在你的代码中对它进行了测试,它运行正常。您只需将它(也可以更改)置于不影响任何功能代码的位置。

第二种方法是准确复制&#34;写&#34;在执行某些操作之前的面板,例如通过将它们封装在不同的高光中来分隔单词等。

[更新#1]

只是用于测试的一段代码。

function wordsinblocks(self) {
      var demo = document.getElementById("demo"),
        initialText = demo.textContent,
        wordTags = initialText.split(" ").map(function(word) {
          return '<span class="word">' + word + '</span>';
        });

      $(document).keydown(function(e){
          var event = e.which || e.keyCode;
          if (event == 13){
              demo.innerHTML = wordTags.join(' <br/> ');
          } else{
              demo.innerHTML = wordTags.join('');
          }
      });

      self.disabled = true;
      fitWords();
      window.addEventListener('resize', fitWords);
}

[更新#2]

function wordsinblocks(self) {
      var demo = document.getElementById("demo"),
        initialText = demo.innerText.replace(/\n\r?/g,"<br/>"),
        wordTags = initialText.split(" ").map(function(word) {
          return '<span class="word">' + word + '</span>';
        });

      demo.innerHTML = wordTags.join('');
      self.disabled = true;
      fitWords();
      window.addEventListener('resize', fitWords);
}

答案 1 :(得分:4)

您需要按new line分割来源(您所写的内容),然后将每一行拆分为space

wordsinblocks 更新为:

function wordsinblocks(self) {
  var demo = document.getElementById("demo"),
    initialText = demo.innerText,
    wordTags = initialText.split(/\n/g).map(function(line) {
      var spanWord = line.split(/\s/g).filter(Boolean).map(function(word){
          return '<span class="word">' + word + '</span>';
      });

      return "<span class='line-break'>" + spanWord.join("") + "</span>";
    });

    demo.innerHTML = wordTags.join('');

    self.disabled = true;
    fitWords();
    window.addEventListener('resize', fitWords);
}

fitWords 更新为

function fitWords() {
  var demo = document.getElementById("demo"),
    width = demo.offsetWidth,
    sizes = [7.69230769230769, 23.07692307692307, 46.15384615384614, 100],
    calculated = sizes.map(function(size) {
      return width * size / 100
    }),
    lineNode,
    node,
    i, k,
    nodeWidth,
    match,
    index;

  for (k = 0; k < demo.childNodes.length; k++) {
    lineNode = demo.childNodes[k];
    for(i = 0; i < lineNode.childNodes.length; i++) {
       node = lineNode.childNodes[i];
       node.classList.remove('size-1', 'size-2', 'size-3', 'size-4');

       nodeWidth = node.clientWidth;
       match = calculated.filter(function(grid) {
          return grid >= nodeWidth;
       })[0];
       index = calculated.indexOf(match);

       node.classList.add('size-' + (index + 1));
    }
  }
}

style

中添加以下css
#demo .line-break:after {
   clear: both;
   display: table;
   content: ""
}

FIDDLE DEMO HERE

希望,它可以帮助你和...如果我错过了什么,请告诉我。

多次换行的更新

textarea.reloadPreview 更新为

textarea.reloadPreview = function() {
    var previewString = this.val().replace(/\n/g,"<br>");
    if (previewString.length > 0) {
       previewString = this.htmlUnencode(previewString);
       previewString = previewString.replace(opts.paraRegExp, "<p>$1</p><p>$2</p>");
       previewString = previewString.replace(opts.lineBreakRegExp, "$1<br />$2");
       previewString = previewString.replace(allowedTagsRegExp, "<$1>");

    }

    try {
       // Workaround for a bug in jquery 1.3.2 which is fixed in 1.4
       preview[0].innerHTML = previewString;
    }
    catch (e) {
      alert("Sorry, but inserting a block element within is not allowed here.");
    }

    preview.updatingPreview = false;
    this.bind('keyup', this.handleKeyUp);
    wordsinblocks(self);
}

worksinblocks 更新为

function wordsinblocks(self) {
  var demo = document.getElementById("demo"),
    initialText = demo.innerText,
    wordTags = initialText.split(/\n/g).map(function(line) {
      var spanWord = line.split(/\s/g).filter(Boolean).map(function(word){
          return '<span class="word">' + word + '</span>';
      });

      var result = spanWord.join("");
      result = result == "" ? "<span class='empty'></span>" : result;

      return "<span class='line-break'>" + result + "</span>";
    });

    demo.innerHTML = wordTags.join('');

    self.disabled = true;
    fitWords();
    window.addEventListener('resize', fitWords);
}

在您的css中添加以下styles

#demo .line-break .empty {
    height: 25px;
    display: block
}

#demo .word {
    float: left;
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    padding: 5px;
    padding-left: 10px;
    padding-right: 10px;
    font-size: 2.9vw;
    height: 25px;
    font-family: "helvetica";
    border: 1px solid black;
}

UPDATED FIDDLE HERE

答案 2 :(得分:3)

你可以用css代替white-space: pre;

p {
  white-space: pre;
 }

答案 3 :(得分:3)

不错的小挑战。 为了达到合适的效果并处理textarea换行符:

  • 确保显示的文字与textarea中的格式相同:行高,宽度,字母间距,大小....
  • <br />替换新行 - &gt; /(?:\r\n|\r|\n)/g
  • 将单个块用于空格 - &gt;将确保显示行开头的双白色空格和空格。

以下是我的方法:Fiddle Demo

$(function(){

		var set = {
    	hookTo : ".leftside textarea",
      dispIn : ".rightside .content",
      newline : "@#@"
    };
		//Focus text area:
    $(set.hookTo).focus();
    $(set.hookTo).keyup(function(){
    		$text = $(this);
        $tar  = $(set.dispIn);
        raw   = $text.val();
        box   = [];
        //Recplace tags:
        raw.replace(/&/g, "&amp;")
           .replace(/>/g, "&gt;")
           .replace(/</g, "&lt;")
           .replace(/"/g, "&quot;");
        //Hadle Line breaks:
        raw = raw.replace(/(?:\r\n|\r|\n)/g, set.newline);
        //Boxes:
        box = raw.split(' ');
        $.each(box, function(i,e){
        	var newlines;
        	if (e === "") {
            box[i] = "<div class='wordbox space'>&nbsp;</div>";
          } else {
          	newlines = e.split(set.newline);
            if (newlines.length > 0) {
            	$.each(newlines,function(index,el) {
              		if (el === "") 
                  	newlines[index] = "<div class='wordbox space'>&nbsp;</div>";
                  else
                    newlines[index] = "<div class='wordbox'>" + el + "</div>" 
                        + "<div class='wordbox space'>&nbsp;</div>";
              });
              box[i] = newlines.join("<br />");
            } else {
            	box[i] = "<div class='wordbox'>" + e + "</div>" 
            					+ "<div class='wordbox space'>&nbsp;</div>";
            }
          }
        });
        $tar.html(box.join(""));
    });
});
body { background-color:white; height:100%; }
.wrapper { width:100%; font-size:0; box-sizing:border-box; }
.leftside,
.rightside { 
  width:50%; 
  display:inline-block; 
  font-size:16px; 
  vertical-align: top; 
  font-family:arial;
}
.rightside .header,
.leftside .header {
  font-size:16px; 
  padding:10px 20px;
  font-weight:bold;
}
.rightside .header { 
  color: black; 
  background-color:orange; 
}
.leftside .header { 
  color: orange; 
  background-color:black; 
}
.rightside .content {
    width:100%; 
    padding:10px 20px;
    box-sizing:border-box;
    font-size:0;
}
.rightside .content .wordbox {
    outline: 1px solid black;
    line-height:16px;
    letter-spacing: 1px;
    font-size:15px;
    display:inline-block;
    margin-bottom: 3px;
}
.rightside .content .wordbox.space {
    outline: 0;
    opacity:0;
}
.wrapper textarea {
 	  width:100%; 
  	box-sizing:border-box;
    border:0;
  	overflow: auto;
    outline: none;
    -webkit-box-shadow: none;
    -moz-box-shadow: none;
    box-shadow: none;
    resize: none;
    padding:10px 20px;
    font-size:15px;
    font-family:arial;
    line-height:16px;
    letter-spacing: 1px;
    min-height:400px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="wrapper">
	<div class="leftside">
        <div class="header">Write</div>
        <textarea placeholder="Type here please"></textarea>
  </div>
  <div class="rightside">
        <div class="header">See</div>
        <div class="content"></div>
  </div>
</div>

答案 4 :(得分:3)

简短的hacky解决方案

wordsinblocks更改为

function wordsinblocks(self) {
  var demo = document.getElementById("demo"),
    initialText = demo.textContent.replace(new RegExp("\n", "g"), '<br>'),
    wordTags = initialText.split(" ").map(function(wordWithLineBreaks) {
      return wordWithLineBreaks.split('<br>').map(function(word, index, arr)    {
          return (word === '' ? '' : '<span class="word">' + word + '</span>') + 
        (index < arr.length - 1 ? '<div class="lb">&nbsp;</div>' : '') ;
      }).join('');
    });

  demo.innerHTML = wordTags.join('');
  self.disabled = true;
  fitWords();
  window.addEventListener('resize', fitWords);
}

for函数内的fitWords循环中,在循环的第一行之后添加:

if (node.tagName.toLowerCase() === 'div') continue;

更改

$(function() {
  $('textarea.source').livePreview({
    previewElement: $('p#demo'),
    allowedTags: ['p', 'strong', 'br', 'em', 'strike'],
    interval: 20
  });
});

$(function() {
  $('textarea.source').livePreview({
    previewElement: $('p#demo'),
    allowedTags: [],
    paraRegExp: new RegExp('something nobody will ever enter'),
    lineBreakRegExp: new RegExp('something nobody will ever enter'),
    interval: 20
  });
});

添加到你的CSS的末尾:

.lb {
  display: block;
  clear: both;
}

有关完整解决方案,请参阅jsfiddle

关于解决方案的一些想法

虽然这个解决方案有效,但远非最佳。

例如,使用livePreview jQuery插件没有多大意义,因为您的代码似乎不需要HTML支持,因为您的代码在{{1}之后使用textContent属性已经完成了有效删除所有HTML的工作。

这也是为什么插入换行符(通过按Enter键添加)在原始代码中不起作用的原因。发生的事情如下:

  • 用户输入一些包含换行符的文字
  • 由于使用livePreview选项,
  • livePreview会将这些换行符替换为<br>
  • lineBreakRegExp属性仅返回文本,这意味着textContent会再次丢失。

实际上,@ Shlomi Hassid提供了一种更好的,完全不完整的方法。不完整,因为缺少盒子的大小。