Carol.Kar
Carol.Kar

Reputation: 5355

Append/Prepend space on outer tag

I would like to append/prepend a space on the outer tags.

I tried the following:

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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

As you can see only the inner tag has the spaces.

However, I would like to have it on the outer tag. Like the following:

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

Any suggestions how to do this?

I appreciate your replies!

Upvotes: 4

Views: 619

Answers (6)

Jin Thakur
Jin Thakur

Reputation: 2773

There are many ways to append space on outside of element. but unless you wrap it inside another span it will not work.

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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 0

Amin Taghikhani
Amin Taghikhani

Reputation: 762

Maybe this can help you.

If you can add pseudo ::after ::before to your style.

<!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>

If you want pure Javascript solution I think you must add space to your element container.

Kind Regards

Amin

Upvotes: 0

Andrew
Andrew

Reputation: 446

Given that nodes are not aware of what's going on around them, this is a perfect scenario for 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;'

Upvotes: 2

Christos Lytras
Christos Lytras

Reputation: 37318

Method 1: Wrap your node to another node with a no break space at start/end

You can use another span element to wrap your text. That won't affect anything in your text neither in the way you may want to use $elem afterwards. Then create a text node using NO-BREAK SPACE' (U+00A0) which is equivalent to &nbsp; and use it to compile your final text node.

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>

As you can see, you can save and access each cloned $elem afterwards with both span selector ($elem.find('span')) or even more specific using data-function name span[data-function="addSynonym"] ($elem.find('span[data-function="addSynonym"]')) and for the inner element span > span or span[data-function="addSynonym"] > span.

Method 2: Append everything directly to the target node (space/$elem/space)

Another way is to directly append everything to the target node if you want to keep that specific $elem structure:

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>

Using this way, you'll have to access inner span using just span ($elem.find('span')) selector.

Upvotes: 6

Lewis
Lewis

Reputation: 4595

I would just reference the vanilla outerHTML manually.

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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Upvotes: 0

Miaplacidus
Miaplacidus

Reputation: 545

In jQuery, insertBefore/before and insertAfter/after are the methods used to insert elements before or after the target element.

&nbsp; is not element, though, so you have to create a text node:

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

See example:

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

Upvotes: -1

Related Questions