【问题标题】:Append/Prepend space on outer tag在外部标签上附加/前置空格
【发布时间】:2020-02-16 13:55:08
【问题描述】:

我想在外部标签上附加/前置一个空格。

我尝试了以下方法:

var $elem = $('<span>', {
  'data-function': "addSynonym",
  'data-options': '[ test1, test2, test3]',
  'html': $('<span>', {
    'text': 'test4',
    'css': {
      backgroundColor: 'yellow'
    }
  })
});

$elem.append("&nbsp;")
$elem.prepend("&nbsp;");

console.log($elem[0]);
console.log($elem[0].innerHTML);
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

如您所见,只有内部标签有空格。

但是,我想将它放在外部标签上。像下面这样:

&nbsp;<span data-function="addSynonym" data-options="[ test1, test2, test3]"><span style="background-color: yellow;">test4</span></span>&nbsp;

有什么建议吗?

感谢您的回复!

【问题讨论】:

  • 我首先要问你为什么要使用不间断空格?在 CSS 中使用 marginpadding 来实现你想要做的任何事情
  • @RoryMcCrossan 感谢您的回复!我正在使用 jquery 创建一个夏季插件(所见即所得编辑器),并且需要外部标签之前的空格。有什么建议如何将空格添加到外部标签?
  • 什么禁止你使用after() and before()

标签: javascript jquery


【解决方案1】:

方法 1:将你的节点包裹到另一个节点,在开始/结束处没有分隔空间

您可以使用另一个span 元素来包装您的文本。这不会影响您文本中的任何内容,也不会影响您之后可能想要使用$elem 的方式。然后使用NO-BREAK SPACE' (U+00A0) 创建一个文本节点,它等效于&amp;nbsp;,并使用它来编译您的最终文本节点。

var colors = ['yellow', 'red', 'lightgreen', 'cyan'];
var currentColor = 0;

// Create a text node using Unicode Character 'NO-BREAK SPACE' (U+00A0)
var $spaceNode = $(document.createTextNode('\u00A0'));

// Wrap the text node to a span with a begin and end sibling of the space text node clone
var $elem = $('<span>').append(
  $spaceNode.clone(),
  $('<span>', {
    'data-function': "addSynonym",
    'data-options': '[test1, test2, test3]',
    'html': $('<span>', {
      'text': 'test4',
      'css': {
        backgroundColor: 'yellow'
      }
    })
  }),
  $spaceNode.clone()
);

function appendText() {
  // Output $elem node outer HTML to a preview element
  $('#elem_html').text($elem[0].outerHTML);
  
  // Clone the $elem so we can use it multiple times
  var $elemClone = $elem.clone();
  
  // Append the cloned $elem to the DOM
  $('#editor').append($elemClone);
  
  // Apply manipulation demo timer
  hookElemChange($elemClone);
}

// Handle add text button click
$('#add_text').on('click', function() {
  appendText();
});

// Handle change $elem color button click
$('#change_text_color').on('click', function() {
  var newColor;
  
  // Generate a random color
  do {
    newColor = Math.floor(Math.random() * Math.floor(colors.length));
  } while(newColor === currentColor);
  
  currentColor = newColor;
  
  // Change the $elem inner span background color to a random color
  $elem.find('span > span').css('background-color', colors[currentColor]);
  // We can also use specific element selector using data-function with "addSynonym" value
  // $elem.find('span[data-function="addSynonym"] > span').css('background-color', colors[currentColor]);
  
  // Append the text to the DOM
  appendText();
});

// A timer for each element that parses and increases the text prepending number
// This is for to demontrate that each node can be manipulated with no restrictions after creating/cloning
function hookElemChange($element) {
  setInterval(function() {
    var $currentElem = $element.find('span[data-function="addSynonym"] > span');

    var text = $currentElem.text();
    var textParts = text.match(/([a-z]+)(\d+)/);

    if (textParts) {
      var num = parseInt(textParts[2]);
      var newText = textParts[1] + ++num;
      
      $currentElem.text(newText);
    }
  }, 1000);
}
#editor {
  border: 1px solid grey;
  height: 100px;
  margin-bottom: 10px;
  overflow-wrap: break-word;
  overflow: auto;
}

#elem_html {
  white-space: normal;
  margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="editor"></div>

<div>
  <button id="add_text">Add text</button>
  <button id="change_text_color">Change color</button>
</div>

<div>
  <pre id="elem_html"></pre>
</div>

如您所见,您可以使用 span 选择器 ($elem.find('span')) 或更具体地使用 data-function 名称 span[data-function="addSynonym"] ($elem.find('span[data-function="addSynonym"]')) 保存和访问每个克隆的 $elem内部元素span &gt; spanspan[data-function="addSynonym"] &gt; span

方法2:将所有内容直接附加到目标节点(空格/$elem/space)

如果您想保留特定的$elem 结构,另一种方法是直接将所有内容附加到目标节点:

var colors = ['yellow', 'red', 'lightgreen', 'cyan'];
var currentColor = 0;

// Create a text node using Unicode Character 'NO-BREAK SPACE' (U+00A0)
var $spaceNode = $(document.createTextNode('\u00A0'));

// Create the node with initial structure
var $elem = $('<span>', {
  'data-function': "addSynonym",
  'data-options': '[test1, test2, test3]',
  'html': $('<span>', {
    'text': 'test4',
    'css': {
      backgroundColor: 'yellow'
    }
  })
});

function appendText() {
  // Clone the $elem so we can use it multiple times
  var $elemClone = $elem.clone();
  
  // Append the cloned $elem to the DOM
  $('#editor').append($spaceNode.clone(), $elemClone, $spaceNode.clone());
  
  // Output #editor node inner HTML to a preview element
  $('#elem_html').text($('#editor')[0].innerHTML);
  
  // Apply manipulation demo timer
  hookElemChange($elemClone);
}

// Handle add text button click
$('#add_text').on('click', function() {
  appendText();
});

// Handle change $elem color button click
$('#change_text_color').on('click', function() {
  var newColor;
  
  // Generate a random color
  do {
    newColor = Math.floor(Math.random() * Math.floor(colors.length));
  } while(newColor === currentColor);
  
  currentColor = newColor;
  
  // Change the $elem inner span background color to a random color
  $elem.find('span').css('background-color', colors[currentColor]);
  // We can also use specific element selector using data-function with "addSynonym" value
  // $elem.find('span[data-function="addSynonym"] > span').css('background-color', colors[currentColor]);
  
  // Append the text to the DOM
  appendText();
});

// A timer for each element that parses and increases the text prepending number
// This is for to demontrate that each node can be manipulated with no restrictions after creating/cloning

function hookElemChange($element) {
  setInterval(function() {
    var $currentElem = $element.find('span');

    var text = $currentElem.text();
    var textParts = text.match(/([a-z]+)(\d+)/);

    if (textParts) {
      var num = parseInt(textParts[2]);
      var newText = textParts[1] + ++num;
      $currentElem.text(newText);
    }
  }, 1000);
}
#editor {
  border: 1px solid grey;
  height: 100px;
  margin-bottom: 10px;
  overflow-wrap: break-word;
  overflow: auto;
}

#elem_html {
  white-space: normal;
  margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="editor"></div>

<div>
  <button id="add_text">Add text</button>
  <button id="change_text_color">Change color</button>
</div>

<div><pre id="elem_html"></pre></div>

使用这种方式,您必须仅使用 span ($elem.find('span')) 选择器访问内部跨度。

【讨论】:

    【解决方案2】:

    鉴于节点不知道它们周围发生了什么,这对于DocumentFragments 来说是一个完美的场景。

    let $fragment = $(document.createDocumentFragment());
    let $elem = $('<span>', {
      'data-function': "addSynonym",
      'data-options': '[ test1, test2, test3]',
      'html': $('<span>', {
        'text': 'test4',
        'css': {
          backgroundColor: 'yellow'
        }
      })
    });
    
    $fragment.append('\u00A0', $elem, '\u00A0');
    
    $container.append($fragment);
    // $container => '&nbsp;<span...><span...>test4</span></span>&nbsp;'
    
    $elem.append('!');
    // $container => '&nbsp;<span...><span...>test4</span>!</span>&nbsp;'
    

    【讨论】:

      【解决方案3】:

      我会手动引用原版outerHTML

      var $elem = $('<span>', {
        'data-function': "addSynonym",
        'data-options': '[ test1, test2, test3]',
        'html': $('<span>', {
          'text': 'test4',
          'css': {
            backgroundColor: 'yellow'
          }
        })
      });
      
      $elem.append("&nbsp;");
      $elem.prepend("&nbsp;");
      
      console.log("&nbsp;" + $elem[0].outerHTML + "&nbsp;");
      console.log($elem[0].innerHTML);
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

      【讨论】:

        【解决方案4】:

        也许这对你有帮助。

        如果你可以在你的风格中添加伪::after::before

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Document</title>
            <style>
                .mySpan::before{
                    content: ' ';
                }
                .mySpan::after{
                    content: ' ';
                }
            </style>
        </head>
        <body>
            <div id="target">my text</div>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
            <script>
                var $elem = $('<span>', {
                    'class': 'mySpan',
          'data-function': "addSynonym",
          'data-options': '[ test1, test2, test3]',
          'html': $('<span>', {
            'text': 'test4',
            'css': {
              backgroundColor: 'yellow'
            }
          })
        })
        
        
            $("#target").append($elem)
        
        
            </script>
        </body>
        </html>
        

        如果您想要纯 Javascript 解决方案,我认为您必须为元素容器添加空间。

        亲切的问候

        阿明

        【讨论】:

          【解决方案5】:

          有很多方法可以在元素外部添加空间。但除非你将它包裹在另一个跨度内,否则它将无法工作。

          var $elem = $('<span>', {
            'data-function': "addSynonym",
            'data-options': '[ test1, test2, test3]',
            'html': $('<span>', {
              'text': 'test4',
              'css': {
                backgroundColor: 'yellow'
              }
            })
          });
          
          $elem.append("&nbsp;")
          $elem.prepend("&nbsp;");
          const textNode = '&nbsp;'
          $elem.before(textNode)
          $elem.after(textNode)
          console.log($elem[0]);
          console.log($elem[0].innerHTML);
          var $elemupdated = $('<span>', {
          
            'html': $elem[0].innerHTML
            
          });
          console.log($elemupdated[0].outerHTML);
          &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"&gt;&lt;/script&gt;

          【讨论】:

            【解决方案6】:

            在 jQuery 中,insertBefore/beforeinsertAfter/after 是用于在目标元素之前或之后插入元素的方法。

            &amp;nbsp; 不是元素,所以你必须创建一个文本节点:

            const textNode = '&nbsp;'
            $('.some-element').before(textNode)
            $('.some-element').after(textNode)
            

            参见示例:

            https://jsfiddle.net/yq1jfd5z/1/

            【讨论】:

            • 我不明白为什么这是错误的答案。我想这就是他想要的。
            • 这是我在 Stack Overflow 上的第一个答案,另一位用户为此展开了一场小小的争吵。
            • 我使用了您的解决方案并附加了另一个跨度以显示空间。这是最好的,
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-02-21
            • 1970-01-01
            • 2019-03-29
            • 1970-01-01
            • 1970-01-01
            • 2016-06-23
            • 1970-01-01
            相关资源
            最近更新 更多