I want to get the data in a within the description inside the product items. I'm trying to do this with jquery.
$(".dl-view-item").click(function() {
var sku = $(this).find(".product.description").find.data("sku");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dl-view-item">
<div class="product">
<div class="description" data-sku="sample-data">
</div>
</div>
</div>
I want to get the data in data-sku
You could try this.
$(".dl-view-item").click(function() {
var sku = $(this).find(".product.description");
console.log(sku)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dl-view-item">
<div class="product">
<div class="description" data-sku="sample-data">
Lorem ipsum
</div>
</div>
</div>
this will work for you.
$(document).ready(function(){
$(".dl-view-item").click(function () {
var sku = $(this).find("div.description").data("sku");
$(this).find("div.description").text(sku);
});
});
You are missing a space between your selector classes.
.product.description
Alternatively, instead of simply supplying a space here, you could use a child combinator since the description is an immediate child of the the product container. If this is not the case, you can remove the > in the selector.
.product > .description
$('.dl-view-item').click(function() {
var sku = $(this).find('.product > .description').data('sku');
console.log(sku);
});
.dl-view-item {
display: block;
width: 32px;
height: 32px;
background: red;
border-radius: 50%;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dl-view-item">
<div class="product">
<div class="description" data-sku="sample-data">
</div>
</div>
</div>
By the way, you can do this without jQuery.
document.querySelectorAll('.dl-view-item').forEach(el => {
el.addEventListener('click', (e) => {
let sku = e.target.querySelector('.product > .description').dataset.sku;
console.log(sku);
})
});
.dl-view-item {
display: block;
width: 32px;
height: 32px;
background: red;
border-radius: 50%;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dl-view-item">
<div class="product">
<div class="description" data-sku="sample-data">
</div>
</div>
</div>
$(".dl-view-item").click(function () {
var sku = $(".dl-view-item").find("div.description").attr("data-sku");
console.log(sku);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dl-view-item"> Click Me!
<div class="product">
<div class="description" data-sku="sample-data">
</div>
</div>
</div>
Related
For a comment list I use the event delegation pattern after a recommendation from Stackoverflow colleagues (mplungjan, Michel). It works well and I am very enthusiastic about this pattern. But as I already suspected, there will be problems if the bound element (button) contains two child elements (span, span).
Since I want to get the CommentID from the target in the parent element of the child element, it only works in the cases when you click exactly between the spans inside the button. Actually a case for currentTarget but that doesn't work in this case because the tapped element is the whole comment list.
Question: What do I have to do to fix it?
const commentList = document.querySelector('.comment-list');
commentList.addEventListener('click', (ev) => {
console.log('1. clicked');
const getObjectId = () => {
return ev.target.parentNode.parentNode.getAttribute('data-comment-id');
}
if (! getObjectId()) return false;
if (ev.target.classList.contains('delete')) {
console.log('2. Delete action');
console.log('3. for relatedID', getObjectId());
}
if (ev.target.classList.contains('edit')) {
console.log('2. Edit action');
console.log('3. for relatedID', getObjectId());
}
if (ev.target.classList.contains('flag')) {
console.log('2. Flag action');
console.log('3. for relatedID', getObjectId());
}
});
.controller {
display: flex;
gap:20px;
}
.comment {
margin-bottom: 20px;
background: gray;
}
.controller button > span {
background: orange;
}
.controller button span:first-child {
margin-right: 10px;
}
<div class="comment-list">
<div class="comment">
<div class="content">lorem 1. Dont work! Nested button.</div>
<div class="controller" data-comment-id="1">
<div class="delete">
<button class="delete"><span>delete</span><span>ICON</span></button>
</div>
<div class="edit">
<button class="edit"><span>edit</span><span>ICON</span></button>
</div>
<div class="flag">
<button class="flag"><span>flag</span><span>ICON</span></button>
</div>
</div>
</div>
<div class="comment">
<div class="content">lorem 2. Work! </div>
<div class="controller" data-comment-id="2">
<div class="delete"><button class="delete">delete</button></div>
<div class="edit"><button class="edit">edit</button></div>
<div class="flag"><button class="flag">flag</button></div>
</div>
</div>
<div class="comment">
<div class="content">lorem 3. Work! </div>
<div class="controller" data-comment-id="3">
<div class="delete"><button class="delete">delete</button></div>
<div class="edit"><button class="edit">edit</button></div>
<div class="flag"><button class="flag">flag</button></div>
</div>
</div>
</div>
The problem is that you're using .parentNode.parentNode to get to the element with data-comment-id, but the number of parents changes when the target is nested inside additional <span> elements.
Don't hard-code the nesting levels, use .closest() to find the containing controller node.
const getObjectId = () => {
return ev.target.closest('.controller').getAttribute('data-comment-id');
}
Building on my last comment in the other question
const tgtButtonWhenSpansInsideButton = e.target.closest("button")
Cache the objects
the closest method will get the button itself even if no children
Make sure you get the class from the containing element of what you want to call a button
const commentList = document.querySelector('.comment-list');
const getObjectId = (tgt) => tgt.closest('.controller').dataset.commentId;
commentList.addEventListener('click', (ev) => {
const tgt = ev.target.closest("button")
const objectId = getObjectId(tgt);
if (!objectId) return;
console.log(objectId,"clicked")
if (tgt.classList.contains('delete')) {
console.log('2. Delete action');
console.log('3. for relatedID', objectId);
}
if (tgt.classList.contains('edit')) {
console.log('2. Edit action');
console.log('3. for relatedID', objectId);
}
if (tgt.classList.contains('flag')) {
console.log('2. Flag action');
console.log('3. for relatedID', objectId);
}
});
.controller {
display: flex;
gap: 20px;
}
.comment {
margin-bottom: 20px;
background: gray;
}
.controller button>span {
background: orange;
}
.controller button span:first-child {
margin-right: 10px;
}
<div class="comment-list">
<div class="comment">
<div class="content">lorem 1. Dont work! Nested button.</div>
<div class="controller" data-comment-id="1">
<div class="delete">
<button class="delete"><span>delete</span><span>ICON</span></button>
</div>
<div class="edit">
<button class="edit"><span>edit</span><span>ICON</span></button>
</div>
<div class="flag">
<button class="flag"><span>flag</span><span>ICON</span></button>
</div>
</div>
</div>
<div class="comment">
<div class="content">lorem 2. Work! </div>
<div class="controller" data-comment-id="2">
<div class="delete"><button class="delete">delete</button></div>
<div class="edit"><button class="edit">edit</button></div>
<div class="flag"><button class="flag">flag</button></div>
</div>
</div>
<div class="comment">
<div class="content">lorem 3. Work! </div>
<div class="controller" data-comment-id="3">
<div class="delete"><button class="delete">delete</button></div>
<div class="edit"><button class="edit">edit</button></div>
<div class="flag"><button class="flag">flag</button></div>
</div>
</div>
</div>
In this case I would "traverse" the DOM up if it wasn't a button that was clicked, something like this
const commentList = document.querySelector('.comment-list');
commentList.addEventListener('click', (ev) => {
console.log('1. clicked', ev.target.tagName);
let target = ev.target
if (target.tagName === "SPAN") {
target = target.parentElement
}
const commentId = target.parentElement.parentElement.getAttribute('data-comment-id');
if (!commentId) return false;
if (target.classList.contains('delete')) {
console.log('2. Delete action');
console.log('3. for relatedID', commentId);
}
if (target.classList.contains('edit')) {
console.log('2. Edit action');
console.log('3. for relatedID', commentId);
}
if (target.classList.contains('flag')) {
console.log('2. Flag action');
console.log('3. for relatedID', commentId);
}
});
.controller {
display: flex;
gap:20px;
}
.comment {
margin-bottom: 20px;
background: gray;
}
.controller button > span {
background: orange;
}
.controller button span:first-child {
margin-right: 10px;
}
<div class="comment-list">
<div class="comment">
<div class="content">lorem 1. Dont work! Nested button.</div>
<div class="controller" data-comment-id="1">
<div class="delete">
<button class="delete"><span>delete</span><span>ICON</span></button>
</div>
<div class="edit">
<button class="edit"><span>edit</span><span>ICON</span></button>
</div>
<div class="flag">
<button class="flag"><span>flag</span><span>ICON</span></button>
</div>
</div>
</div>
<div class="comment">
<div class="content">lorem 2. Work! </div>
<div class="controller" data-comment-id="2">
<div class="delete"><button class="delete">delete</button></div>
<div class="edit"><button class="edit">edit</button></div>
<div class="flag"><button class="flag">flag</button></div>
</div>
</div>
<div class="comment">
<div class="content">lorem 3. Work! </div>
<div class="controller" data-comment-id="3">
<div class="delete"><button class="delete">delete</button></div>
<div class="edit"><button class="edit">edit</button></div>
<div class="flag"><button class="flag">flag</button></div>
</div>
</div>
</div>
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>
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>
This should be a straightforward problem but I haven't found the solution anywhere on the list.js documentation. How do I go about preventing the list from auto searching as I type in the search field and instead add a search button instead?
var options = {
valueNames: ['material', 'type', 'thickness', 'height', 'category']
};
var featureList = new List('piece-search', options);
.item {
margin: 0.5em;
padding: 0.5em;
width: 150px;
height: 150px;
float: left;
background: #229B55;
color: #F4F4F4;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.15);
}
.item p {
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/list.js/1.1.1/list.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="page">
<div id="main">
<div class="c1">
<div id="piece-search">
<ul class="sort-by">
<li>
<input class="search" placeholder="Search pieces">
</li>
</ul>
<ul class="list">
<li class="item">
<p class="sorting-info hide-this">
<p class="material">plastic</p>
<p class="type">pipe</p>
<p class="thickness">3mm</p>
<p class="height">15inch+</p>
<p class="category">artsy</p>
</li>
<li class="item">
<p class="sorting-info hide-this">
<p class="material">glass</p>
<p class="type">pipe</p>
<p class="thickness">5mm</p>
<p class="height">14inch-</p>
<p class="category">scientific</p>
</li>
</ul>
</div>
</div>
</div>
</div>
The default class for search is "search" according to the documentation. So, you need to remove/change the classname from text input box in order to prevent auto search onkeyup.
I added a button for search that will call the function search() where you will get the search text value and search manually.
To search manually, read the documentation provided here.
JS function that will trigger on button click:
function search() {
var searchText = document.getElementById("searchText").value;
//console.log(searchText);
var options = {
valueNames: ['material', 'type', 'thickness', 'height', 'category']
};
var featureList = new List('piece-search', options);
// Search manually
featureList.search(searchText);
// Search manually on specific columns
//listObj.search(searchText, [ 'material' ]);
}
function search() {
var searchText = document.getElementById("searchText").value;
//console.log(searchText);
var options = {
valueNames: ['material', 'type', 'thickness', 'height', 'category']
};
var featureList = new List('piece-search', options);
// Search manually
featureList.search(searchText);
// Search manually on specific columns
//listObj.search(searchText, [ 'material' ]);
}
.item {
margin: 0.5em;
padding: 0.5em;
width: 150px;
height: 150px;
float: left;
background: #229B55;
color: #F4F4F4;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.15);
}
.item p {
margin: 0;
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/list.js/1.1.1/list.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="page">
<div id="main">
<div class="c1">
<div id="piece-search">
<ul class="sort-by">
<li>
<input id="searchText" placeholder="Type text to search">
</li>
<li>
<input type="button" class="searchButton" value="Search pieces" onclick="search()">
</li>
</ul>
<ul class="list">
<li class="item">
<p class="sorting-info hide-this">
<p class="material">plastic</p>
<p class="type">pipe</p>
<p class="thickness">3mm</p>
<p class="height">15inch+</p>
<p class="category">artsy</p>
</li>
<li class="item">
<p class="sorting-info hide-this">
<p class="material">glass</p>
<p class="type">pipe</p>
<p class="thickness">5mm</p>
<p class="height">14inch-</p>
<p class="category">scientific</p>
</li>
</ul>
</div>
</div>
</div>
</div>
I basically want to create a product listing page using jquery, just like this page: https://losangeles.sharegrid.com/browse/
Here is my code:
$(function(){
$('.link').click(function(){
$(this).next('ul').toggle();
var id = $(this).attr("rel");
$('#'+id).show();
});
});
.container {
width: 100%;
height: auto;
}
.eighty-percent {
width: 80%;
margin: 0 auto;
}
.categories {
width: 20%;
float: left;
ul {
li {
ul {
display: none;
}
}
}
}
.products-list {
width: 80%;
float: right;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="eighty-percent">
<div class="categories left">
<ul>
<li>
<a href="#" class="link" id="main-category" rel="main1">
main-category-one
</a>
<ul>
<li>sub-cat-one</li>
<li>sub-cat-one</li>
<li>sub-cat-one</li>
<li>sub-cat-one</li>
</ul>
</li>
</ul>
</div>
<div class="products right">
<div class="products-list" id="main1">
<h1>main category one</h1>
</div>
<div class="products-list" id="main-sub1">
<h1>sub category one</h1>
</div>
<div class="products-list" id="main-sub2">
<h1>sub category one</h1>
</div>
<div class="products-list" id="main-sub3">
<h1>sub category one</h1>
</div>
<div class="products-list" id="main-sub4">
<h1>sub category one</h1>
</div>
</div>
</div>
</div>
Now the problem I am having is as you can see, I cannot make the div that is currently opened make hidden when I click on the other sub category links. I hope my snippet will make clear what I am trying to achieve
All changes and details are commented within the source.
FIDDLE
SNIPPET
$(function() {
$('.link').click(function(event) {
/*
Added to prevent <a>nchor links
from jumping. Note the `event`
parameter above as well.
*/
event.preventDefault();
$(this).next('ul').toggle();
var id = $(this).attr("rel");
/*
Added a class (i.e. `sub`), to
each #main-sub* so all of them will
be targeted to hide by the .hide()
method.
*/
$('.sub').hide();
$('#' + id).show();
});
});
.container {
width: 100%;
height: auto;
}
/*
Added to prevent the right
column from wrapping under
the left column.
*/
.subList {
height: 100vw;
display: none;
}
.categories {
width: 50%;
float: left;
}
.products-list {
width: 50%;
float: right;
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<!--Removed .eighty-percent because it
hindered layout in demo only,
adding it or removing it shouln't
affect functionality in your production version.-->
<div class="categories left">
<ul>
<li>
main-category-one
<!--Added a class (i.e. subList)
in order to style it easier,
see CSS for why styling was needed -->
<ul class="subList">
<!--Changed each <a>nchor id as a
unique one. You should never have more
than one of the same id on a page.-->
<li>sub-cat-one
</li>
<li>sub-cat-two
</li>
<li>sub-cat-three
</li>
<li>sub-cat-four
</li>
</ul>
</li>
</ul>
</div>
<div class="products right">
<div class="products-list" id="main1">
<h1>main category one</h1>
</div>
<div class="products-list sub" id="main-sub1">
<h2>sub category one</h2>
</div>
<div class="products-list sub" id="main-sub2">
<h2>sub category two</h2>
</div>
<div class="products-list sub" id="main-sub3">
<h2>sub category three</h2>
</div>
<div class="products-list sub" id="main-sub4">
<h2>sub category four</h2>
</div>
</div>
</div>
As far as I understood, you want to hide the main div when another was clicked.
This would achieve it:
$(function() {
$('.link').click(function() {
$(this).next('ul').toggle();
var id = $(this).attr("rel");
$('div[id^="main"]').hide(); // added line
$('#' + id).show();
});
});