Automatically toggle between spans

49
May 23, 2019, at 08:30 AM

I can't find any answers that allow for sentence here followed by end word

The idea is that I'll have a list of items in a spans and then toggle between them, so the beginning of the sentence is the same and only the end changes. Ideally there would be some sort of animation but even just the functionality would be appreciated.

<p class="itemlist">We sell 
    <span class="items"> 
      <span>Bread</span> 
      <span>Milk</span> 
      <span>Fish</span> 
      <span>Eggs</span> 
      <span>Cheese</span> 
    </span> 
  </p>

Ideally I'd like it to show one item at a time. The end result would look like the GIF below but the text should remain in the same place.

Gif of intention.

Any prompts/answers would be greatly appreciated. I'm tearing my hair out for two hours over this.

Thanks in advance.

Answer 1

Here is an example using setInterval

let i=0; 
const items = Array.from(document.querySelectorAll('.items span')); 
 
const showNewItem = (index) => { 
  items.forEach(i => i.style.display = 'none'); 
   
  items[index].style.display = 'inline'; 
} 
 
// Initial call 
showNewItem(i++); 
 
setInterval(() => { 
  showNewItem(i++); 
  if(i > items.length-1) i = 0; 
},1000);
<p class="itemlist">We sell 
    <span class="items"> 
      <span>Bread</span> 
      <span>Milk</span> 
      <span>Fish</span> 
      <span>Eggs</span> 
      <span>Cheese</span> 
    </span> 
  </p>

Answer 2

var itemArray = ['Bread', 'Milk', 'Fish', 'Eggs', 'Cheese']; 
var animationInterval; 
 
function getRandomInt(max) { 
  return Math.floor(Math.random() * Math.floor(max)); 
} 
 
function setItemName(_name) { 
  var itemList = document.getElementsByClassName('items')[0]; 
  itemList.textContent = _name; 
} 
 
function startAnimation() { 
  animationInterval = setInterval(function(){ 
    var randomNumber = getRandomInt(itemArray.length); 
    setItemName(itemArray[randomNumber]); 
  }, 1000) 
} 
 
function endAnimation() { 
  clearInterval(animationInterval); 
} 
 
setItemName(itemArray[0]);
<p class="itemlist">We sell 
    <span class="items"></span> 
 </p> 
   
<button onclick="startAnimation();"> Start </button> 
<button onclick="endAnimation();"> End </button>

Answer 3

You can add a delay. here is a sample code for that

<!DOCTYPE html> 
<html> 
<body> 
 
 
  
 
 <p class="itemlist">We sell 
    <span class="items"> 
      <span id="demo"> Bread</span> 
       
    </span> 
  </p> 
 
<script> 
  
  
 
var delayInMilliseconds1 = 1000;  
var delayInMilliseconds2 = 2000;  
var delayInMilliseconds3 = 3000;  
 
setTimeout(function() { 
    document.getElementById("demo").innerHTML = "Milk"; 
}, delayInMilliseconds1); 
 
setTimeout(function() { 
    document.getElementById("demo").innerHTML = "Fish"; 
}, delayInMilliseconds2); 
 
setTimeout(function() { 
    document.getElementById("demo").innerHTML = "Eggs"; 
}, delayInMilliseconds3); 
 
</script> 
 
</body> 
</html>

Answer 4

Set an item to start on using a class like "first"

Using jQuery, grab the items list, and set an interval to go through. Then fadeout the current active and fadein the next one.

Find the next element either just by grabbing the next sibling, or grabbing the first child of the items list if you reach the end.

let itemsList = $(".items").first(); 
 
const changeItem = () => { 
  let current = itemsList.find("span.active"); 
  current.removeClass("active"); 
  current.fadeOut(200, () => { 
    let next; 
    if (current.next().length > 0) next = current.next(); 
    else next = itemsList.children().first(); 
    next.addClass("active"); 
    next.fadeIn(200); 
  }); 
} 
 
setInterval(changeItem, 2000);
.items span { 
  color: red; 
  display: none; 
} 
 
span.first { 
  display: inline-block; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
<p class="itemlist">We sell 
    <span class="items"> 
      <span class="active first">Bread</span> 
      <span>Milk</span> 
      <span>Fish</span> 
      <span>Eggs</span> 
      <span>Cheese</span> 
    </span> 
  </p>

Answer 5

How about decoupling data from HTML? and use setInterval then

const itemList = ['Bread', 'Milk', 'Fish'] 
const prefix = "We Sell" 
 
const placeholder = document.getElementById('placeholder'); 
let index = 0; 
 
setInterval(() => { 
  index = index >= itemList.length ? 0 : index; 
 
  placeholder.innerHTML = `${prefix} <span style='color: red'> ${itemList[index]} </span>`; 
 
  index++; 
}, 1000)
<div id="placeholder" />

Answer 6

yes setInterval is the key [edit] text is now centered

const All_span = document.querySelectorAll('p.itemlist span.items span'); 
var NoSpan = 0; 
 
setInterval(() => { 
    All_span[NoSpan++].style.display = 'none'; 
    NoSpan %= All_span.length; 
    All_span[NoSpan].style.display = 'inline'; 
}, 900);
p.itemlist { 
	font: 2em Verdana, Geneva, Arial, Helvetica, sans-serif; 
	display: block; 
	width: 8em; 
	text-align: center; 
} 
p.itemlist span.items span { 
	display: none; 
	color:crimson; 
} 
p.itemlist span.items span:first-child { 
    display: inline; 
}
<p class="itemlist">We sell 
	<span class="items"> 
		<span>Bread</span> 
		<span>Milk</span> 
		<span>Fish</span> 
		<span>Eggs</span> 
		<span>Cheese</span> 
	</span> 
</p>

Answer 7

For info, you could also use CSS variable and CSS animation

span { 
  display: inline-block; 
  vertical-align: top; 
} 
 
.items span { 
  position: absolute;/* instead display */ 
  animation: var(--delay, 0) 10s hidsh linear infinite; 
} 
 
@keyframes hidsh { 
  0%, 
  80% { 
    color: transparent; 
  } 
  80.1%, 
  100% { 
    color: initial 
  }
<p class="itemlist">We sell 
  <span class="items"> 
      <span style='--delay:-2s' >Bread </span> 
  <span style='--delay:-4s'>Milk  </span> 
  <span style='--delay:-6s'>Fish  </span> 
  <span style='--delay:-8s'>Eggs  </span> 
  <span style='--delay:-10s'>Cheese</span> 
  </span> 
</p>
You may also declare the custom properties in the style sheet if you do not want to touch the HTML

.items span              {--delay:-2s } 
.items span:nth-child(2) {--delay:-4s } 
.items span:nth-child(3) {--delay:-6s } 
.items span:nth-child(4) {--delay:-8s } 
.items span:nth-child(5) {--delay:-10s} 
span { 
  display: inline-block; 
  vertical-align: top; 
} 
 
.items span { 
  position: absolute;/* instead display*/ 
  animation: var(--delay, 0) 10s hidsh linear infinite; 
} 
 
@keyframes hidsh { 
  0%, 
  80% { 
    color: transparent;/* instead visibility or opacity */ 
  } 
  80.1%, 
  100% { 
    color: initial 
  }
<p class="itemlist">We sell 
  <span class="items"> 
   <span>Bread </span> 
   <span>Milk  </span> 
   <span>Fish  </span> 
   <span>Eggs  </span> 
   <span>Cheese</span> 
  </span> 
</p>

READ ALSO
Angular re-fetch data after parameter change GET request

Angular re-fetch data after parameter change GET request

How to re-fetch data after parameter change from: oglas/1 to oglas/2 by click, so when put URL and than click ENTER everything works, but when click on oglas/2 button when oglas/1 is rendered URL changes to oglas/2 but data is from oglas/1?

50
Two Colum website with opposite scrolling effect [on hold]

Two Colum website with opposite scrolling effect [on hold]

How does one go about creating a website with two columns with one column moving up and the other one moving down at the same time? Example: wwwritevac

55
How do I configure to print for a thermal paper printer with react-to-print?

How do I configure to print for a thermal paper printer with react-to-print?

I'm working in a React page, and I'm using react-to-print for printingBut now I need to print in a thermal paper printer

25