I am still getting to grips with jQuery and wondered if anyone had a suggestion for this?
Basically on click I want to show the div with the matching class, so if you click the btn with class '.project1' then it should show the content div with the same class of '.project1'.
I'm just stuck on how it would find this so any suggestions would be awesome :)
Thanks in advance.
Snippet:
$('div[class*="project"]').click(function (e) {
$(this).closest('.content').show();
});
.content {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>
CodePen: https://codepen.io/nickelse/pen/mYrOdz?editors=1111
One option is to use data() to store arbitrary data associated with the matched elements or return the value at the named data store for the first element in the set of matched elements.
$('div[class*="project"]').click(function (e) {
var project = $(this).data("project"); //Get the data-project of the clicked element
$(".content.project" + project).toggle(); //Toggle the element with content and project class
});
.content {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn" data-project="1">BTN 1</div> <!-- Add data-project on HTML-->
<div class="project2 btn" data-project="2">BTN 2</div>
<div class="project3 btn" data-project="3">BTN 3</div>
<div class="project4 btn" data-project="4">BTN 4</div>
<div class="project1 content" data-project="1">CONTENT 1</div>
<div class="project2 content" data-project="2">CONTENT 2</div>
<div class="project3 content" data-project="3">CONTENT 3</div>
<div class="project4 content" data-project="4">CONTENT 4</div>
You need to find the project number you clicked on.
You can do that by filtering the classes of the button you clicked on and extracting the number :
+[...this.classList].find(c => c.startsWith('project')).replace('project', '');
Then all you have to do is toggle the targeted project content :
$('.content.project'+project).toggle();
Here's a working example:
$('div[class^="project"]').on('click', function(){
const project = +[...this.classList].find(c => c.startsWith('project')).replace('project', '');
$('.content.project'+project).toggle();
});
.content {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>
Toggling based on class matching is one of the harder thing to do in JQuery, however to achieve what you require you could do the following:
/* When a btn is clicked */
$('.btn').click(function(e) {
/* Extract the classes of this button element */
const classes = $(this).attr('class');
/* Parse the project class part of the classes string */
const projectClass = classes.match(/project\d+/)[0];
/* Construct a matcher for the projects corresponding
content and "toggle" the content's visiblity */
$('.content.' + projectClass).toggle();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>
You can try to use regex to the class started with "project" and then show or hide it
$('.btn').click(function (e) {
var classArray = $(this).attr("class"),
re = /^project[0-9]+/ ,
className = re.exec(classArray)[0];
$('.content.'+ className).toggle();
});
$('.btn').click(function (e) {
var classArray = $(this).attr("class"),
re = /^project[0-9]+/ ,
className = re.exec(classArray)[0];
$('.content.'+ className).toggle();
});
.content {
display: none
}
.btn {
cursor:pointer
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="project1 btn">BTN 1</div>
<div class="project2 btn">BTN 2</div>
<div class="project3 btn">BTN 3</div>
<div class="project4 btn">BTN 4</div>
<div class="project1 content">CONTENT 1</div>
<div class="project2 content">CONTENT 2</div>
<div class="project3 content">CONTENT 3</div>
<div class="project4 content">CONTENT 4</div>
Related
I'm trying to add a class to the first div if the attribute is equal value.
What I have:
<div class="list">
<div class="list__item" title="attr1">value 1</div>
<div class="list__item" title="attr1">value 2</div>
<div class="list__item" title="attr2">value 3</div>
<div class="list__item" title="attr2">value 4</div>
<div class="list__item" title="attr2">value 5</div>
<div class="list__item" title="attr2">value 6</div>
<div class="list__item" title="attr2">value 7</div>
</div>
What I'm trying to achieve is:
What I have:
<div class="list">
<div class="list__item" title="attr1" class="active">value 1</div>
<div class="list__item" title="attr1">value 2</div>
<div class="list__item" title="attr1">value 3</div>
<div class="list__item" title="attr2" class="active">value 3</div>
<div class="list__item" title="attr2">value 4</div>
<div class="list__item" title="attr2">value 5</div>
<div class="list__item" title="attr2">value 6</div>
</div>
My code:
const tags = ['attr1', 'attr2']
const collection = document.getElementByClassName("list__item")
// convert colelction into array
const arr = [...collection]
arr.forEach(el => {
this.tags.forEach(tag => {
if(tag == el.attributes.attr1.value) {
document.querySelector(".list__item").classList.add('active')
}
})
})
What I'm getting is:
<div class="list">
<div class="list__item" title="attr1" class="active">value 1</div>
<div class="list__item" title="attr1">value 2</div>
<div class="list__item" title="attr1">value 3</div>
<div class="list__item" title="attr2">value 3</div>
<div class="list__item" title="attr2">value 4</div>
<div class="list__item" title="attr2">value 5</div>
<div class="list__item" title="attr2">value 6</div>
</div>
The problem is that for the first iteration it's not adding the class to the first div with attr2
You should iterate over the tags. For each tag, you search for elements that have title equal to the tag. When you find the first one, you stop that specific tag and proceed to the next one.
Notice I use for in the inner loop, not forEach. This is because of the return, which stops the processing of the tag.
const tags = ['attr1', 'attr2']
const collection = document.getElementsByClassName("list__item")
// convert colelction into array
const arr = [...collection]
tags.forEach(tag => {
for(const el of arr) {
if (tag === el.getAttribute('title')) {
el.classList.add('active')
return;
}
}
})
.active { color: red }
<div class="list">
<div class="list__item" title="attr1">value 1</div>
<div class="list__item" title="attr1">value 2</div>
<div class="list__item" title="attr2">value 3</div>
<div class="list__item" title="attr2">value 4</div>
<div class="list__item" title="attr2">value 5</div>
<div class="list__item" title="attr2">value 6</div>
<div class="list__item" title="attr2">value 7</div>
</div>
const tags = ['attr1', 'attr2']
const collection = document.getElementsByClassName("list__item")
// convert colelction into array
const arr = [...collection]
//document.querySelector will always pick the first instance of a selector, even when 2 or more are present
//so for each tag, we can just find the first element with the title, and set that class
for( let tag of tags){
let node = document.querySelector(`[title="${tag}"]`);
node.classList.add("active");
}
<div class="list">
<div class="list__item" title="attr1">value 1</div>
<div class="list__item" title="attr1">value 2</div>
<div class="list__item" title="attr2">value 3</div>
<div class="list__item" title="attr2">value 4</div>
<div class="list__item" title="attr2">value 5</div>
<div class="list__item" title="attr2">value 6</div>
<div class="list__item" title="attr2">value 7</div>
</div>
I have a simple html and jquery script like below, I am trying to get a comma seperated list of data-item-id so would look like...
1,2,3,4,5
var items = $('.container').children();
console.log(items);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="item" data-item-id="1">Item 1</div>
<div class="item" data-item-id="2">Item 2</div>
<div class="item" data-item-id="3">Item 3</div>
<div class="item" data-item-id="4">Item 4</div>
<div class="item" data-item-id="5">Item 5</div>
</div>
I have grabbed the items but how can I convert this into the comma seperated string?
Map each item to its item-id, then join by commas:
var items = $('.container')
.children()
.map(function() { return $(this).data('item-id') })
.get()
.join(',');
console.log(items);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="item" data-item-id="1">Item 1</div>
<div class="item" data-item-id="2">Item 2</div>
<div class="item" data-item-id="3">Item 3</div>
<div class="item" data-item-id="4">Item 4</div>
<div class="item" data-item-id="5">Item 5</div>
</div>
But there's no need for a big library like jQuery to accomplish something this trivial, if you want:
const items = Array.from(
document.querySelectorAll('.container > .item'),
div => div.dataset.itemId
)
.join(',');
console.log(items);
<div class="container">
<div class="item" data-item-id="1">Item 1</div>
<div class="item" data-item-id="2">Item 2</div>
<div class="item" data-item-id="3">Item 3</div>
<div class="item" data-item-id="4">Item 4</div>
<div class="item" data-item-id="5">Item 5</div>
</div>
Because who wouldn't want to add destructuring as well ..... (Kudos to CertainPerformance)
const items = Array.from(
document.querySelectorAll('.container > .item'),
({ dataset: { itemId: i } }) => i
)
.join(',');
console.log(items);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="item" data-item-id="1">Item 1</div>
<div class="item" data-item-id="2">Item 2</div>
<div class="item" data-item-id="3">Item 3</div>
<div class="item" data-item-id="4">Item 4</div>
<div class="item" data-item-id="5">Item 5</div>
</div>
Another alternative with JQuery could be using .each() to traverse the items while grabbing the data-item-id with .data() and adding it to a string.
$(document).ready(function()
{
var itemList = "";
$('.container .item').each(function()
{
itemList += $(this).data('item-id') + ",";
});
console.log("Ids:", itemList.slice(0,-1));
});
.as-console {background-color:black !important; color:lime;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="item" data-item-id="1">Item 1</div>
<div class="item" data-item-id="2">Item 2</div>
<div class="item" data-item-id="3">Item 3</div>
<div class="item" data-item-id="4">Item 4</div>
<div class="item" data-item-id="5">Item 5</div>
</div>
You can also apply some features of ES5 and ES6 for a shorter solution. And without jQuery.
let itemsIds = [...document.getElementsByClassName("item")]
.map(elem => elem.getAttribute("data-item-id"))
.join(',');
console.log(itemsIds);
<div class="container">
<div class="item" data-item-id="1">Item 1</div>
<div class="item" data-item-id="2">Item 2</div>
<div class="item" data-item-id="3">Item 3</div>
<div class="item" data-item-id="4">Item 4</div>
<div class="item" data-item-id="5">Item 5</div>
</div>
I want to insert html after a particular element but insertAdjacentHTML wont let me add a closing tag first.
If I do
elm.insertAdjacentHTML('afterend', '</div><section class="block">');
the expected result is
<element></element></div><section class="block">
the result it's returning
<element></element><section class="block"></div>
Is there a way around this?
Edit:
Basically what i'm trying to do is loop through each element and split them into two divs
<div class="column">
<div class="block">block 1</div>
<div class="block">block 2</div>
<div class="block">block 3</div>
<div class="block">block 4</div>
<div class="block">block 5</div>
<div class="block">block 6</div>
<div class="block">block 7</div>
<div class="block">block 8</div>
</div>
Expected result
<div class="column">
<div class="block">block 1</div>
<div class="block">block 2</div>
<div class="block">block 3</div>
<div class="block">block 4</div>
</div>
<div class="column">
<div class="block">block 5</div>
<div class="block">block 6</div>
<div class="block">block 7</div>
<div class="block">block 8</div>
</div>
JS
const blocks = document.querySelectorAll(".block");
let half = Math.ceil(blocks.length / 2 - 1);
blocks[half].insertAdjacentHTML('afterend', '</div><div class="column">');
If I get your requirement right, this is what you want to do:
elm.parentNode.insertAdjacentHTML('afterend', '<section class="block"></section>');
If the div is not the direct parent element, you might want to use Element.closest(selector) instead:
elm.closest('div.myDiv').insertAdjacentHTML('afterend', '<section class="block"></section>');
update
You have elaborated on your requirements further, this is how to do it in Javascript:
const blocks = [...document.querySelectorAll('.block')];
const middle = Math.ceil(blocks.length / 2 - 1);
const column = document.querySelector('.column');
const parent = document.querySelector('.parent');
const col1 = document.createElement('div');
col1.className = 'column';
const col2 = document.createElement('div');
col2.className = 'column';
blocks.forEach((block, index) => {
if (index <= middle) {
col1.appendChild(block)
} else {
col2.appendChild(block)
}
})
parent.removeChild(column)
parent.appendChild(col1);
parent.appendChild(col2);
.column+.column {
color: green;
}
<div class="parent">
<div class="column">
<div class="block">block 1</div>
<div class="block">block 2</div>
<div class="block">block 3</div>
<div class="block">block 4</div>
<div class="block">block 5</div>
<div class="block">block 6</div>
<div class="block">block 7</div>
<div class="block">block 8</div>
</div>
</div>
Resulting DOM:
I know this question is kind of weird but i am not able to find out this
For Example : there is some div with ids
HTML
<div id="test1">test 1</div>
<div id="test2">test 2</div>
<div id="test3">test 3</div>
<div id="test4">test 4</div>
<div id="test5">test 5</div>
<div id="test6">test 6</div>
and i want to toggle some specific div
like
test1, test4 and test6
so i have to do like this
$('#test1').toggle();
$('#test4').toggle();
$('#test6').toggle();
but i want to know is there any way to do that like
$('#test1', '#test4', '#test6').toggle();
I know it can be done if i just give same class on the div which i want to toggle.
but i want to know this for that reason i asked
Sure you can, simply comma separate your ID selector:
$('#test1, #test4, #test6').toggle();
$("#toggle").on("click", function(){
$('#test1, #test4, #test6').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="toggle">TOGGLE 1, 4, 6</button>
<div id="test1">test 1</div>
<div id="test2">test 2</div>
<div id="test3">test 3</div>
<div id="test4">test 4</div>
<div id="test5">test 5</div>
<div id="test6">test 6</div>
A much reusable code would allow you to toggle any desired elements without copy/pasting your JavaScript functions.
Here's an example where the desired selector to toggle is stored within the data-toggle attribute of the action element:
$("[data-toggle]").on("click", function(){
$(this.dataset.toggle).toggle();
});
.hidden{display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button data-toggle="#test1,#test6">Toggle 1, 6</button>
<button data-toggle="#test3,#test4">Toggle 3, 4</button>
<div id="test1">test 1</div>
<div id="test2">test 2</div>
<div id="test3">test 3</div>
<div id="test4">test 4</div>
<div id="test5">test 5</div>
<div id="test6">test 6</div>
<button data-toggle=".info">Toggle .info</button>
This is some
<span class="info">OLD</span>
<span class="info hidden">NEW!!!</span>
info
I have HTML like this -
<div class="outerDiv" id="od_1">
<label>Div 1</label>
<div class="innerDiv">Inner Div 1</div>
<div class="innerDiv">Inner Div 2</div>
<div class="innerDiv">Inner Div 3</div>
</div>
<div class="outerDiv" id="od_2">
<label>Div 2</label>
<div class="innerDiv">Inner Div 1</div>
<div class="innerDiv">Inner Div 2</div>
<div class="innerDiv">Inner Div 3</div>
</div>
What I want to achieve through jQuery is this -
<div class="outerDiv" id="od_1">
<label>Div 1</label>
<div class="innerDivBox">
<div class="innerDiv">Inner Div 1</div>
<div class="innerDiv">Inner Div 2</div>
<div class="innerDiv">Inner Div 3</div>
</div>
</div>
<div class="outerDiv" id="od_2">
<label>Div 2</label>
<div class="innerDivBox">
<div class="innerDiv">Inner Div 1</div>
<div class="innerDiv">Inner Div 2</div>
<div class="innerDiv">Inner Div 3</div>
</div>
</div>
I started with looping through div with class "outerDiv" -
$('.outerDiv').each(function(i, obj) {
var divId = this.id;
});
But I am not sure how exactly I should proceed from here. Any help would be appreciated. Thanks.
You could use find() and wrapAll() to group the inner divs with a common parent:
$('.outerDiv').each(function(i, obj) {
$(this).find('.innerDiv').wrapAll('<div class="innerDivBox">');
});
jsFiddle here.
Try this:
$('.outerDiv').each(function() {
$(this).append( $('<div class="innerDivBox"></div>').append( $(this).find('.innerDiv') ) );
});