Toggle <span> text which contains inner HTML element

Viewed 284

On the button click, I want to toggle its text from 'View More' to 'View Less'. However, the span element contains another element inside of it (Font Awesome icon). When I toggle text of a span element, the element inside of it disappears. You can see it in the snippet below.

I also tried this solution:

$('.button span').text(($('.button span').text()=='View More<i class="fas fa-angle-down"></i>') ? 'View Less<i class="fas fa-angle-up"></i>' : 'View More<i class="fas fa-angle-down"></i>');

But it inserts the i element as a span text, instead as an element.

NOTE: I can't keep the i element outside of the span element because I have certain animations in CSS.

$('.button').click(function() {
    $('.button i').toggleClass('fa-angle-up fa-angle-down');
    $('.button span').text(($('.button span').text()=='View More') ? 'View Less' : 'View More');
});
.button {
  width: 250px;
  padding: 12px 0;
  text-transform: uppercase;
  cursor: pointer;
}

.button i {
  margin-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>

<button type="button" name="button" value="" class="button">
  <span>View More<i class="fas fa-angle-down"></i></span>
</button>

6 Answers

$('.button').click(function() {
    $('.button span').html(($('.button span').text()=='View More') ? 'View Less<i class="fas fa-angle-up">' : 'View More<i class="fas fa-angle-down">');
});
.button {
  width: 250px;
  padding: 12px 0;
  text-transform: uppercase;
  cursor: pointer;
}

.button i {
  margin-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>

<button type="button" name="button" value="" class="button">
  <span>View More<i class="fas fa-angle-down"></i></span>
</button>

This can be fixed using the html() function of JQuery. That will have the same functionality as the text() function, but adds the option to set html elements.

This link provides you with the JQuery documentation.

what about to wrap the text which you want to change into an own span with an id? then you could change the text without touching the fontawesome icon

I would simply add a data attribute to the texts and toggle only that portion instead of trying to complicate things, like this:

$('.button').click(function() {
    $('.button i').toggleClass('fa-angle-up fa-angle-down');
   
    const currentText = $('[data-view-more]').text();
    const updatedText = currentText === 'View More' ? 'View Less' : 'View More';
    $('[data-view-more]').text(updatedText);
});
.button {
  width: 250px;
  padding: 12px 0;
  text-transform: uppercase;
  cursor: pointer;
}

.button i {
  margin-left: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>

<button type="button" name="button" value="" class="button">
  <span>
    <span data-view-more>View More</span>
    <i class="fas fa-angle-down"></i>
  </span>
</button>

As you can see I now target data-view-more text when toggling the text and then I target the icon to toggle that.

Just for fun and for the idea: no jquery, use event delegation and a data-attribute to toggle text and icon

document.addEventListener("click", handle);

function handle(evt) {
  const bttn = evt.target.closest("[data-view]");
  return bttn 
    ? toggleBttn(bttn, bttn.dataset.view === "more")
    : true;
}

function toggleBttn(bttn, isClosed) {
  let classes = ["fa-angle-down", "fa-angle-up"];
  classes = isClosed ? classes : classes.reverse();
  bttn.querySelector("i").classList.replace(...classes);
  bttn.dataset.view = isClosed ? "less" : "more";
}
.button {
  width: 250px;
  padding: 12px 0;
  text-transform: uppercase;
  cursor: pointer;
}

[data-view]:before {
  content: 'view 'attr(data-view);
  margin-right: 10px;
}
<script src="https://kit.fontawesome.com/a671c6b423.js" crossorigin="anonymous"></script>

<button type="button" data-view="more" class="button">
  <i class="fas fa-angle-down"></i>
</button>

When you keep the icon out of the span, it works like you expect it:

<button type="button" name="button" value="" class="button">
    <span>View More></span>
    <i class="fas fa-angle-down"></i
</button>
Related