Adding a Div around the contents of 2 matched elements - javascript

I am trying to add a div with class name 'wrapped' around 2 divs with innerHTML 'one' and 'two'
<div class='blk'>one</div>
<div class='blk'>two</div>
Here I am trying to use the first and second 'clearfix' class element and use it as a selector to wrap the contents between them with a div. What I understand from the below code is wrapAll will wrap only the matched elements. I am trying to figure out what functionality in jquery will help me to wrap one and two with a parent div.
var arr = $('.clearfix');
$(arr[0], arr[1]).wrapAll('<div class="wrapped"/>');
.wrapped {
background-color: 'red';
}
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='clearfix'></div>
<div class='blk'>one</div>
<div class='blk'>two</div>
<div class='clearfix'></div>
<div class='blk'>3</div>
<div class='blk'>4</div>
<div class='clearfix'></div>
</div>
My expected output is :
<div>
<div class='clearfix'></div>
<div class='wrapped'>
<div class='blk'>one</div>
<div class='blk'>two</div>
</div>
<div class='clearfix'></div>
<div class='blk'>3</div>
<div class='blk'>4</div>
<div class='clearfix'></div>
</div>

If I understand the question correctly, you're wanting to wrap a div (with class wrapped) around the two elements (with class blk) that contain the text content; "one" and "two".
One way to achieve this would be via the :eq selector - this allows you to isolate specific elements for the .blk class selector (ie the first and second), and than apply wrapping to those only:
/* Select the first and second elements that match the .blk selector
and apply wrapped div to those only */
$('.blk:eq(0), .blk:eq(1)').wrapAll('<div class="wrapped"/>');
.wrapped{
background-color: red; /* Fixed syntax error here too :) */
}
.hidden{
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='clearfix'></div>
<div class='blk'>one</div>
<div class='blk'>two</div>
<div class='clearfix'></div>
<div class='blk'>3</div>
<div class='blk'>4</div>
<div class='clearfix'></div>
</div>

You can try with .filter()
var arr = $('.blk');
arr.filter((i, el) => i < 2).wrapAll(`<div class="wrapped"></div>`);
.wrapped{
background-color: red;
}
.hidden{
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='clearfix'></div>
<div class='blk'>one</div>
<div class='blk'>two</div>
<div class='clearfix'></div>
<div class='blk'>3</div>
<div class='blk'>4</div>
</div>

var clearfixParent = $('.clearfix').parent();
var wrappedEle = 0;
$(clearfixParent).find( 'div' ).each(function(){
if( $(this).hasClass( 'clearfix' ) ) {
wrappedEle += 1;
$(this).after('<div class="wrapped"/>');
} else {
$(this).appendTo( '.wrapped:eq(' + ( wrappedEle - 1 ) + ')' );
}
});
.wrapped {
background-color: 'red';
}
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='clearfix'></div>
<div class='blk'>one</div>
<div class='blk'>two</div>
<div class='clearfix'></div>
<div class='blk'>3</div>
<div class='blk'>4</div>
<div class='clearfix'></div>
</div>

You don't need jQuery for this, you can use the DOM API.
const appendSelectedSiblings = selector => target => {
while (target.nextElementSibling && target.nextElementSibling.matches(selector))
target.appendChild(target.nextElementSibling)
}
document.querySelectorAll('.clearfix').forEach(appendSelectedSiblings('.blk'))
.clearfix > .blk { background: green };
<div id="root">
<div class='clearfix'></div>
<div class='blk'>one</div>
<div class='blk'>two</div>
<div class='clearfix'></div>
<div class='blk'>3</div>
<div class='blk'>4</div>
<div class='clearfix'></div>
</div>

From what I understood with the markup you included, you want to enclose/group all the divs with class BLKs that are beside each other.
I made a snippet that will be able to do this dynamically, without specifying the index of your wrap all.
Feel free to update if you could make the code more efficient.
var divs = $(".scan").find("div");
var toEnclose = [];
var continueEnclose;
var latestArray = [];
divs.each(function(i) {
if ($(this).hasClass("clearfix")) {
if (latestArray.length != 0) {
toEnclose.push(latestArray);
latestArray = [];
}
}
if ($(this).hasClass("blk")) {
latestArray.push(i);
}
});
if (latestArray.length != 0) {
toEnclose.push(latestArray);
latestArray = [];
}
var enclose;
var mix = [];
$.each(toEnclose, function(i, k) {
$.each($(this), function(i2, k2) {
if (i != 0) {
k2 += i;
}
mix.push(".scan div:eq(" + k2 + ")");
});
enclose = mix.join(",");
// console.log(enclose);
$(enclose).wrapAll($("<div class='wrapped'></div>"));
mix = [];
});
.wrapped {
background-color: red;
margin-bottom: 5px;
}
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="scan">
<div class='clearfix'></div>
<div class='blk'>one</div>
<div class='blk'>two</div>
<div class='clearfix'></div>
<div class='blk'>3</div>
<div class='blk'>4</div>
<div class='clearfix'></div>
<div class='blk'>5</div>
<div class='blk'>6</div>
<div class='blk'>7</div>
</div>

Related

Change the Page layout when a button is clicked

I want to change the layout of a page that has 3 columns:
<div>
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
... to 4 columns when a button is clicked:
<div>
<div class="container">
<div class="row" >
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
<div class="col-md-3"></div>
</div>
</div>
</div>
I have no clue on how to do this.
There are many ways you can add another div. Here is my approach :
function appendDiv(){
let row = document.getElementsByClassName('row');
// change className for all the col-md-4 div
document.querySelectorAll('.col-md-4').forEach(function(item) {
item.className = 'col-md-3';
})
//create new div;
let col = document.createElement('div');
// add classname to div
col.className = "col-md-3"
row[0].appendChild(col)
}
.col-md-4{
border : 1px solid blue;
height : 20px;
}
.col-md-3{
border : 1px solid green;
height : 20px;
}
<div>
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
<button onClick='appendDiv()'>click</button>
</div>
</div>
There's a few ways this could be done depending on your data, however, here's one angle.
If you have both your 4 column & 3 column versions of the data loaded on the page (but one hidden with css). You could run something like this.
HTML
<div id="colsThree" class="displayArea show">
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
<div id="colsFour" class="displayArea">
<div class="container">
<div class="row" >
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
<button id="changeColumns">Click Me To Change Columns</button>
Javascript
const buttonEl = document.querySelector("#changeColumns");
buttonEl.addEventListener('click', () => {
const outputEls = document.querySelectorAll('.displayArea')
outputEls.forEach((outputEl) => {
outputEl.toggle("show")
})
});
CSS
.displayArea {
display: none;
}
.displayArea.show {
display: block;
}
Use forEach and appendChild method.
const btn = document.querySelector('#btn')
btn.onclick = function() {
const targetClasses = document.querySelectorAll('.col-md-4')
targetClasses.forEach((tag, idx) => {
tag.className = 'col-md-3'
const lastIdx = targetClasses.length - 1
if (idx === lastIdx) {
const tag = document.createElement('div')
, row = document.querySelector('.row')
tag.className = 'col-md-3'
tag.innerText = '4'
row.appendChild(tag)
}
})
console.log(targetClasses)
return
}
<div>
<button id="btn">Click me</button>
<div class="container">
<div class="row" >
<div class="col-md-4">1</div>
<div class="col-md-4">2</div>
<div class="col-md-4">3</div>
</div>
</div>
</div>
If you're only using vanilla HTML, CSS, and JavaScript, then one of the ways to achieve this is by adding a click listener to the button beforehand. FYI: for brevity's sake, I'll call the div element with row class as parent. When user clicks the button, then it should
remove col-md-4 class and add col-md-3 class to all the children elements of parent.
add a new div element with col-md-3 class into parent.
Here's a link to the codepen for your reference.
const button = document.querySelector('button');
const rowDiv = document.querySelector('.row');
button.addEventListener('click', (e) => {
Array.from(rowDiv.children).forEach(childDiv => {
childDiv.classList.remove('col-md-4');
childDiv.classList.add('col-md-3');
});
const newDiv = document.createElement('div');
newDiv.classList.add('col-md-3');
rowDiv.appendChild(newDiv);
// I disabled the button to prevent the user
// from clicking it the second time.
e.target.disabled = true;
});
.button-parent {
margin: 15px 0;
}
.row {
height: 100vh;
}
.row > div:nth-child(1) {
background: red;
}
.row > div:nth-child(2) {
background: blue;
}
.row > div:nth-child(3) {
background: yellow;
}
.row > div:nth-child(4) {
background: green;
}
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
<div>
<div class="container">
<div class="button-parent">
<button class="btn btn-primary">Add div</button>
</div>
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4"></div>
<div class="col-md-4"></div>
</div>
</div>
</div>
</body>

Get next element with class (that's not a child or sibling)

With the press of a button, I want to toggle the class .active on the next div.bottom. These are basically accordions, but with a different structure.
Using nextElementSibling I guess won't work here to select the target element. How would one select such an element, that's neither a child nor a sibling (in plain JS)?
<div class="wrapper">
<div class="top">
<div class="inner">
<div><button></button></div>
</div>
</div>
<div class="bottom"></div>
</div>
<div class="wrapper">
<div class="top">
<div class="inner">
<div><button></button></div>
</div>
</div>
<div class="bottom"></div>
</div>
I'd do it by using closest to go up to the container .wrapper element, then querySelector to find the bottom element:
function onClick(event) {
const wrapper = event.target.closest(".wrapper");
const bottom = wrapper && wrapper.querySelector(".bottom");
if (bottom) {
bottom.classList.toggle("active");
}
}
Live Example:
// I've added event delegation here
document.body.addEventListener("click", function onClick(event) {
const button = event.target.closest(".inner button");
const wrapper = button && button.closest(".wrapper");
const bottom = wrapper && wrapper.querySelector(".bottom");
if (bottom) {
bottom.classList.toggle("active");
}
});
.active {
color: blue;
border: 1px solid black;
}
<div class="wrapper">
<div class="top">
<div class="inner">
<div><button>Button A</button></div>
</div>
</div>
<div class="bottom">Bottom A</div>
</div>
<div class="wrapper">
<div class="top">
<div class="inner">
<div><button>Button B</button></div>
</div>
</div>
<div class="bottom">Bottom B</div>
</div>
Or the same thing using optional chaining (relatively new):
function onClick(event) {
const wrapper = event.target.closest(".wrapper");
const bottom = wrapper?.querySelector(".bottom");
bottom?.classList.toggle("active");
}
Live Example:
// I've added event delegation here
document.body.addEventListener("click", function onClick(event) {
const button = event.target.closest(".inner button");
const wrapper = button?.closest(".wrapper");
const bottom = wrapper?.querySelector(".bottom");
bottom?.classList.toggle("active");
});
.active {
color: blue;
border: 1px solid black;
}
<div class="wrapper">
<div class="top">
<div class="inner">
<div><button>Button A</button></div>
</div>
</div>
<div class="bottom">Bottom A</div>
</div>
<div class="wrapper">
<div class="top">
<div class="inner">
<div><button>Button B</button></div>
</div>
</div>
<div class="bottom">Bottom B</div>
</div>
By using closest() you can traverse the DOM upwards. With this it's easy to just get the relevant .bottom and toggle the active class on this element.
document.querySelectorAll('button').forEach(button => {
button.addEventListener('click', (e) => {
e.currentTarget.closest('.wrapper').querySelector('.bottom').classList.toggle('active');
});
});
.bottom {
display: none
}
.bottom.active {
display: block
}
<div class="wrapper">
<div class="top">
<div class="inner">
<button type="button">Toggle</button>
</div>
</div>
<div class="bottom">Hidden content</div>
</div>
<div class="wrapper">
<div class="top">
<div class="inner">
<button type="button">Toggle 2</button>
</div>
</div>
<div class="bottom">Hidden content 2</div>
</div>

jquery hiding an array of id

I am trying to build a bookmarklet that will hide all data-agentid selectors that have a data-color selector = 30. so I have a list on the website that look something like this
<div class="sch" data-agent-id=1></div>
<div data-agentid="1" data-color="30">
<div data-agentid="1" data-color="20">
...
<div class="sch" data-agent-id=2></div>
<div data-agentid="2" data-color="10">
<div data-agentid="2" data-color="20">
...
...
edited
There is a lot more code but I figure this is the important part.
I am thinking I can just build an array of ids where their color is 30 and then hide all of the ids in the array. My code is below but I don't think it is even building the array at this point.
(function() {
var arr = $('*[data-color="30"]').map(function() {
return $(this).data("data-agentid");
}).get().join();
$('*[data-agent-id=arr]').hide();
})();
Seems like you would just do this directly:
$('[data-color="30"]').hide()
Edit: Now that you've clarified what you're trying to do, it'll be more performant to select the elements once and iterate over them calling hide on the matching ones:
const agentsToHide =
Array.from(document.querySelectorAll('[data-color="30"'))
.reduce((agents, el) => {
const agentId = el.getAttribute("data-agentid")
if (!agents.includes(agentId)) agents.push(agentId)
return agents
}, [])
.forEach(agentId => {
document.querySelectorAll(`[data-agent-id="${agentId}"]`)
.forEach(el => {
el.style.display = "none"
})
})
<div class="sch" data-agent-id=1>Agent 1</div>
<div data-agentid="1" data-color="30">30</div>
<div data-agentid="1" data-color="30">30</div>
<div data-agentid="1" data-color="20">20</div>
<div class="sch" data-agent-id=2>Agent 2</div>
<div data-agentid="2" data-color="10">10</div>
<div data-agentid="2" data-color="20">20</div>
There is no selector that works off an array. So you would need to make a comma separated value
var selector = $('[data-color="30"]').map(function() {
return '[data-agent-id="' + $(this).data("agentid") + '"]';
}).get().join(',');
$(selector).hide();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-agentid="1" data-color="30"></div>
<div data-agentid="2" data-color="20"></div>
<div data-agentid="3" data-color="30"></div>
<div data-agent-id="1">1-1</div>
<div data-agent-id="2">2-1</div>
<div data-agent-id="3">3-1</div>
<div data-agent-id="1">1-2</div>
<div data-agent-id="2">2-2</div>
<div data-agent-id="3">3-2</div>
<div data-agent-id="1">1-3</div>
<div data-agent-id="2">2-3</div>
<div data-agent-id="3">3-3</div>
Other option is to use filter()
var ids = $('[data-color="30"]').map(function() {
return $(this).data('agentid');
}).get();
$('[data-agent-id]')
.filter(function () {
return ids.includes($(this).data('agent-id'));
})
.hide();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-agentid="1" data-color="30"></div>
<div data-agentid="2" data-color="20"></div>
<div data-agentid="3" data-color="30"></div>
<div data-agent-id="1">1-1</div>
<div data-agent-id="2">2-1</div>
<div data-agent-id="3">3-1</div>
<div data-agent-id="1">1-2</div>
<div data-agent-id="2">2-2</div>
<div data-agent-id="3">3-2</div>
<div data-agent-id="1">1-3</div>
<div data-agent-id="2">2-3</div>
<div data-agent-id="3">3-3</div>
Or just select in a loop
$('[data-color="30"]').each(function() {
var id = $(this).data('agentid');
$('[data-agent-id="' + id + '"]').hide();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-agentid="1" data-color="30"></div>
<div data-agentid="2" data-color="20"></div>
<div data-agentid="3" data-color="30"></div>
<div data-agent-id="1">1-1</div>
<div data-agent-id="2">2-1</div>
<div data-agent-id="3">3-1</div>
<div data-agent-id="1">1-2</div>
<div data-agent-id="2">2-2</div>
<div data-agent-id="3">3-2</div>
<div data-agent-id="1">1-3</div>
<div data-agent-id="2">2-3</div>
<div data-agent-id="3">3-3</div>
Plain and simple in vanilla javascript:
document.querySelectorAll('[data-color="30"]').forEach(function(item) {
item.style.display = "none";
});
<div data-agentid="1" data-color="30">Test30</div>
<div data-agentid="2" data-color="20">Test20</div>
<div data-agentid="1" data-color="30">Test30</div>
<div data-agentid="2" data-color="20">Test20</div>
<div data-agentid="1" data-color="30">Test30</div>
<div data-agentid="2" data-color="20">Test20</div>
<div data-agentid="1" data-color="30">Test30</div>

Save original data filter, unfiltered and unsorted

I'm trying to save original data state to "all" filter. The content gets sorted and filtered by data attribute "data-filter". So my output will be the original state unfiltered and unsorted. Note: the divs content that have the same "data-id" will be displayed only once.
So my desired output on "all" filter and when I first run the code will be:
content first
content second
content third
content fourth
Also for
- filter “one" the output will always be "content first",
- filter “two” the ouput will be "content second” "content third”
…and so on
function removeDuplicates() {
var content = $('.content');
contentIds = content.map(function() {
return $(this).data("id");
}).toArray();
var newSetContentIds = [...new Set(contentIds)];
listedContent = $(newSetContentIds).map(function() {
return $("[data-id=" + this + "]").first()[0];
});
listedContent.addClass('listed');
}
$('.filter').click(function() {
var filterId = $(this).attr('data-filter');
$('.content').hide();
$('.content[data-filter=' + filterId + ']').addClass('active').show();
removeDuplicates();
});
.filter-container {
display: flex;
}
.filter-container div {
margin: 10px;
cursor: pointer;
}
.listed {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-container">
<div class="filter" data-filter="all">
all
</div>
<div class="filter" data-filter="1">
one
</div>
<div class="filter" data-filter="2">
two
</div>
<div class="filter" data-filter="3">
three
</div>
</div>
<div class="content-container">
<div class="content" data-filter="1" data-id="20">
content first
</div>
<div class="content" data-filter="2" data-id="15">
content second
</div>
<div class="content" data-filter="2" data-id="17">
content third
</div>
<div class="content" data-filter="2" data-id="17">
content third
</div>
<div class="content" data-filter="3" data-id="16">
content fourth
</div>
<div class="content" data-filter="1" data-id="20">
content first
</div>
</div>
Your removeDuplicates function is not working. Also, it hinted that you want to run this function only the first time you press any of the filters.
Instead of using show() and hide() that apply inline display messing up with the .listed class, you can use another class .hidden to show or hide the divs.
Finally, it was no clear if you want to sort once or every time when the chosen filter is not "all". Anyway, as mentioned, you can use flex property for the container and order property for the divs. It is inside removeDuplicates considering you want to sort divs once for all after the first click.
function removeDuplicates() {
$(".filter").off("click", removeDuplicates);
var content = $('.content');
contentIds = content.map(function() {
$(this).css('order', $(this).data("filter"));
return $(this).data("id");
}).toArray();
var newContentIds = contentIds.filter((a, i, aa) => aa.indexOf(a) === i && aa.lastIndexOf(a) !== i);
listedContent = $(newContentIds).map(function() {
return $("[data-id=" + this + "]")[0];
});
listedContent.addClass('listed');
}
$(".filter").on("click", removeDuplicates);
$('.filter').click(function() {
var filterId = $(this).attr('data-filter');
if (filterId == "all") {
$('.content').removeClass('hidden');
return;
}
$('.content').addClass('hidden');
$('.content[data-filter=' + filterId + ']').addClass('active').removeClass('hidden');
});
.filter-container {
display: flex;
}
.filter-container div {
margin: 10px;
cursor: pointer;
}
.hidden {
display: none;
}
.content.listed {
display: none;
}
.content-container {
display: flex;
flex-direction: column;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-container">
<div class="filter" data-filter="all">
all
</div>
<div class="filter" data-filter="1">
one
</div>
<div class="filter" data-filter="2">
two
</div>
<div class="filter" data-filter="3">
three
</div>
</div>
<div class="content-container">
<div class="content" data-filter="1" data-id="20">
content first
</div>
<div class="content" data-filter="2" data-id="15">
content second
</div>
<div class="content" data-filter="2" data-id="17">
content third
</div>
<div class="content" data-filter="2" data-id="17">
content third
</div>
<div class="content" data-filter="3" data-id="16">
content fourth
</div>
<div class="content" data-filter="1" data-id="20">
content first
</div>
</div>

Change text in multiple divs with same class onclick [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have a list of football matches and would like to replace all scores with "?-?" when pressing a button and toggle back to show the score when pressing again.
div {
display: table;
}
div div {
display: table-row;
}
div div div {
display: table-cell;
}
.score {
color: blue;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Hide scores!</button>
<br> <br>
<div class="table">
<div class="match">
<div class="team1">Manchester United</div>
<div class="score">1-1</div>
<div class="team2">Liverpool</div>
</div>
<div class="match">
<div class="team1">Juventus</div>
<div class="score">2-0</div>
<div class="team2">Inter Milan</div>
</div>
<div class="match">
<div class="team1">Real Madrid</div>
<div class="score">1-4</div>
<div class="team2">Barcelona</div>
</div>
<div class="match">
<div class="team1">Dortmund</div>
<div class="score">3-0</div>
<div class="team2">Bayern Munich</div>
</div>
<div class="match">
<div class="team1">PSG</div>
<div class="score">0-1</div>
<div class="team2">Marseille</div>
</div>
</div>
I have experimented with getElementById and innerHTML, but due to the large number of matches I would prefer to use getElementsByClassName instead. I've seen people recommending querySelectorAll() for this, but I can't get the scripts to work.
An alternative would be to run a script replacing all numbers with a question mark inside divs with the same class.
Please help me out by using this fiddle
Here's a solution that uses querySelector only to select the button and the .table element to toggle a class.
The rest is all CSS, so no looping is needed.
Note that this exchanges your .score text content for a data-score attribute.
document.querySelector("button")
.addEventListener("click", function() {
document.querySelector("div.table").classList.toggle("hide-score");
});
.table .score:after {
content: attr(data-score);
}
.table.hide-score .score:after {
content: "?-?";
}
<button>Hide scores!</button>
<br>
<br>
<div class="table">
<div class="match">
<div class="team1">Manchester United</div>
<div class="score" data-score="1-1"></div>
<div class="team2">Liverpool</div>
</div>
<div class="match">
<div class="team1">Juventus</div>
<div class="score" data-score="2-0"></div>
<div class="team2">Inter Milan</div>
</div>
<div class="match">
<div class="team1">Real Madrid</div>
<div class="score" data-score="1-4"></div>
<div class="team2">Barcelona</div>
</div>
<div class="match">
<div class="team1">Dortmund</div>
<div class="score" data-score="3-0"></div>
<div class="team2">Bayern Munich</div>
</div>
<div class="match">
<div class="team1">PSG</div>
<div class="score" data-score="0-1"></div>
<div class="team2">Marseille</div>
</div>
</div>
To support older browsers, you could instead keep the score as text content, but put it in a span with another <span>?-?</span> next to it, and then configure the CSS to hide the :first-child and show the rest as needed.
If you don't want to change your html code
$.each($('.score'), function(key, score) {
var score_text = $(score).text();
$(score).data('score', score_text)
})
$('button').click(function() {
if ($(this).data('hiding-score')) {
$(this).data('hiding-score', false);
$.each($('.score'), function () {
$(this).text($(this).data('score'));
});
} else {
$(this).data('hiding-score', true);
$('.score').text('?-?');
}
})
div { display:table; }
div div { display:table-row; }
div div div { display:table-cell; }
.score { color:blue; padding:10px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Hide scores!</button>
<br>
<br>
<div class="table">
<div class="match">
<div class="team1">Manchester United</div>
<div class="score">1-1</div>
<div class="team2">Liverpool</div>
</div>
<div class="match">
<div class="team1">Juventus</div>
<div class="score">2-0</div>
<div class="team2">Inter Milan</div>
</div>
<div class="match">
<div class="team1">Real Madrid</div>
<div class="score">1-4</div>
<div class="team2">Barcelona</div>
</div>
<div class="match">
<div class="team1">Dortmund</div>
<div class="score">3-0</div>
<div class="team2">Bayern Munich</div>
</div>
<div class="match">
<div class="team1">PSG</div>
<div class="score">0-1</div>
<div class="team2">Marseille</div>
</div>
</div>
Here is a fiddle with plain old Javascript.
But I have to admit, #SkinnyPete's way is way better and easier to understand ! You shouls use it if you're only to hide the score. This is the best way to go.
// Mandatory JS code
const score = document.getElementsByClassName('score')
const button = document.getElementById("hide")
const initialState = []
for(let i = 0; i < score.length; i++){
initialState.push({initial : score[i].innerHTML})
}
button.addEventListener('click', (e) => {
const dynamicScore = document.getElementsByClassName('score')
for(let i = 0; i < dynamicScore.length; i++){
if(dynamicScore[i].innerText === initialState[i].initial){
dynamicScore[i].innerHTML = "?-?"
}else{
dynamicScore[i].innerHTML = initialState[i].initial
}
}
})
i added an id "hide" to your button this works fine
The solution I would recommend is that you make use of data attributes on the divs to store the scores. i.e. <div class="score" data-for="1" data-against="1">1-1</div>. Then it's easier to toggle the values. Since you're using jQuery,
// Set the values to ?-?
$('.match .score').html('?-?');
// set the actual scores
$('.match .score').each(function(){
$(this).html($(this).data('for') + '-' + $(this).data('against'));
});
My solution:
I would use the temporary storage. U can set the values for each element with the data()-Method
//STORE DATA IN TEMP STORAGE
$( ".score" ).each(function( index ) {
$(this).data("score-temp", $(this).text());
});
On Click-Event I would add a class "hide-score" to distinguish between both states. And if hide-score is already set, than you reset the values from the temporary storage
$("button").click(function() {
if ($(".table").hasClass( "hide-score" )) {
$(".table").removeClass("hide-score");
//set VALUE FROM TEMP STORAGE
$( ".score" ).each(function( index ) {
var score_temp = $(this).data("score-temp" );
$(this).text(score_temp);
});
}
else {
$( ".score" ).text("?-?");
$(".table").addClass("hide-score");
}
});

Categories

Resources