I'm still pretty new to JQuery and JavaScript as a whole, so bear with me. I tried searching the web for an answer to my question and experimented a little bit, but I'm coming up dry. Anyway, is there a way to store multiple CSS classes in an array with JavaScript?
I'm writing some simple JQuery for a friend's portfolio website such as this:
$('.item.two').click(function(){
$('.content.item, .current.item').show();
$('.content.item, .content.item, .content.item, .current.item, .current.item, .current.item').hide();
$('.item.one, .item.three, .item.four').fadeTo(0, 0.5);
$('.item.two').fadeTo(0, 1.0);
});
All this is doing is hiding certain elements and only showing them when their corresponding icon is clicked on. This is also turning the opacity from 50% off the main class to 100% when clicked on.
There's nothing wrong with the code itself, it serves its intended purpose. But is there a way to clean this code up a bit by just holding those classes into a reusable array? I feel like it should be possible, but I'm not sure how.
Thanks!
EDIT: Sorry, I wasn't clear that I'm actually using 4 different classes to hide or show. So instead of the previous bit it's actually
$('.item.two').click(function(){
// this is the content i want to show on click
$('.content.itemTwo').show();
// this is the content that i want to hide/remain hiding on click
$('.content.itemOne, .content.itemThree, .content.itemFour').hide();
// these are icons representing the content
$('.item.one, .item.three, .item.four').fadeTo(0, 0.5);
$('.item.two').fadeTo(0, 1.0);
});
Also, here is my HTML some of you are requesting. Like I said, what I'm trying to make happen, happens. I just feel like there's a better way of making it happen.
<!-- these are icons representing the written content-->
<div class="item one">
<div class="fs1" aria-hidden="true" data-icon=""></div>
</div>
<div class="item two">
<div class="fs1" aria-hidden="true" data-icon=""></div>
</div>
<div class="item three">
<div class="fs1" aria-hidden="true" data-icon=""></div>
</div>
<div class="item four">
<div class="fs1" aria-hidden="true" data-icon=""></div>
</div>
<!-- this is the written content to be shown upon clicking corresponding icon -->
<div class="content itemOne">
<h3>itemOne</h3>
<p>....</p>
</div>
<div class="content itemTwo">
<h3>itemTwo</h3>
<p>...</p>
<div class="content itemThree">
<h3>itemThree</h3>
<p>...</p>
</div>
<div class="content itemFour">
<h3>itemFour</h3>
<p>....</p>
</div>
Looking at it now, I probably don't need the extra selectors on the .content or .item.
If I correctly understood , you are trying to change the element that is clicked.
$('.item.two').click(function(){
// there is no reason to show and then hide all
$('.content.item, .current.item').hide();
$('.item').not(this).fadeTo(0, 0.5);
$(this).fadeTo(0, 1.0);
});
check if this works for you
Edit another approch could be using index suffix in classes in loop
eg
you could use class1, class2, class3 instead.
$('.item.two').click(function(){
// this is the content i want to show on click
$('.content.itemTwo').show();
// this is the content that i want to hide/remain hiding on click
$('.content.itemOne, .content.itemThree, .content.itemFour').hide();
// these are icons representing the content
$('.item.one, .item.three, .item.four').fadeTo(0, 0.5);
$('.item.two').fadeTo(0, 1.0);
});
to
for(var i=1;i<=4;i++){
$('.item.'+i).click(function(){
// this is the content i want to show on click
$('.content.class'+i).show();
// this is the content that i want to hide/remain hiding on click
$('.content class').hide();
// these are icons representing the content
$('.item').not(this).fadeTo(0, 0.5);
$(this).fadeTo(0, 1.0);
});
}
Hope you can get approch from it
Use the push method like
var arrayClass = [];
$('.item.two').click(function() {
arrayClass.push($(this));
});
alert(arrayClass);
You mean you are trying to select a list of items using jQuery because you have been using a lot of clases? You can do this by using jquery index, with eq and the this selector.
Here is a full description on how to use the index feature to make your code shorter
http://api.jquery.com/index/
You do not have to repeat same class over and over and do not need to store classes in array.
Change
$('.content.item, .content.item, .content.item, .current.item, .current.item, .current.item').hide();
To
$('.content.item').hide();
You can store classes in string instead of array in this case $('.item.one, .item.three, .item.four')
classesSet = ".item.one, .item.three, .item.four";
$(strClassesSet).fadeTo(0, 0.5);
Related
I'm trying to hide a slick slider section if it has no slides. I've tried tons of different options, like trying to use PHP and CSS, but I feel I'm closest to getting it to work with jQuery.
The HTML output structure is:
<div class="container-flex type-testimonials-container">
<div class="container">
<div class="container type-testimonials slick-initialized slick-slider">
<div class="slick-list draggable">
<div class="slick-track">
<div class="slick-slide">
SINGLE SLIDE CONTENT
</div>
<div class="slick-slide">
SINGLE SLIDE CONTENT
</div>
<div class="slick-slide">
SINGLE SLIDE CONTENT
</div>
</div>
</div>
</div>
</div>
</div>
So, I'm thinking I can use jQuery to hide the containing div (.type-testimonials-container) if the single slide div (.slick-slide) doesn't exists.
I have tried the following:
if(jQuery(".slick-slide").html().length)
{
jQuery(".type-testimonials-container").hide();
}
As well as lots of variations of that... I think it might be because the two divs aren't on the same level and one contains the other, but trying to find a parent/child way of doing is proving difficult... I'm not sure which way to go...
Any help would be massively appreciated!
EDIT*
I've also tried checking the parent and child relationship and trying to wait until the DOM has loaded, like this:
document.addEventListener("DOMContentLoaded", function(event) {
var parentDiv = document.getElementsByClassName("slick-track");
var childDiv = document.getElementsByClassName("slick-slide");
if (parentDiv.contains(childDiv))
{
alert("div DOES exist");
}
else{
alert("div DOES NOT exist");
}
});
But this just shows me the DOES NOT exist alert even though it does exist - Will this search the whole of the DOM for it? or do I need to provide the exact path of the div from body or something?
Why not just query for the length of the HTML collection of .slick-slide? JQ will still return an object if the target element doesn't exist, and the object will have a property length. Something like
if(jQuery(".slick-slide").length === 0) {
jQuery(".type-testimonials-container").hide();
}
I managed to do it this way:
jQuery(document).ready(function() {
if(jQuery('.slick-slide').length){
jQuery('.type-testimonials-container').show();
}
else
{
jQuery('.type-testimonials-container').hide();
}
});
I'm building a modular building program and have a side panel where the user can add the code of a module in order to make it appear in the list.
The list is simply span tags with text in. Since they are already in a set order in the HTML, they appear in that default order when they are made visible, rather than appearing at the bottom of the list each time a new one is made visible.
My workaround is to make all of the spans positioned absolute and use some jQuery/JS to do some calculations and move the latest visible-made span to the bottom.
This code works in moving the input field and button to the bottom of the list:
var searchModule = 0;
$("#add_module_button").click(function(){
searchModule = "#" + document.getElementById("add_module_input").value;
$(searchModule).css('display', 'block');
visibleModules = $('.side_module:visible').length * 50 + "px";
$('#add_a_module').css('top', visibleModules);
});
Is there a better solution out there for re-arranging HTML elements without essentially faking it with absolute positioning?
If I get you right it's actually quite easy. Make use of jQuery.append(). If you use jQuery.append() to append an item to the same container it's already contained in, the item is actually removed from its current location and appended at the end. As far as I read your question that's what you want. The example below shows the basic idea ...
$('#container').append($('#three').css('display', 'block'));
$('#container').append($('#one').css('display', 'block'));
$('#container').append($('#five').css('display', 'block'));
.item{
display: none
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="item" id="one">One</div>
<div class="item" id="two">Two</div>
<div class="item" id="three">Three</div>
<div class="item" id="four">Four</div>
<div class="item" id="five">Five</div>
</div>
So, I have a requirement for dynamically generated content blocks on a page. These blocks have a thumbnail and when it is clicked, it should open a modal, and display an unique overlay window, as well as as the unique associated video.
I am trying to write some generic JavaScript that will traverse the DOM tree properly, so that when any particular thumbnail is clicked, a modal, the associated overlay, and the associated video will open.
Here is an example of what I have now (there are many of these, dynamically added):
<div class="block">
<div class="thumbnail">
//Thumbnail image
</div>
<p>Video Description</p>
<div class="window hide">
<div class="video hide">
//Video content
</div>
</div>
</div>
<div id="modal" class="hide"></div>
and after attempting to do a bunch of different things, I ended up trying to do something like this for the JavaScript, which doesn't work:
$(".thumbnail").on("click",function(){
$("#modal").removeClass("hide").addClass("show");
$(this).closest(".window").removeClass("hide").addClass("show");
$(this).closest(".video").removeClass("hide").addClass("show");
});
CSS is very basic:
.hide { display: none; }
.show { display: block; }
Trying to make the click function generic as possible so it would work on any .thumbnail that was clicked. I've also interchanged find(".window") and children(".window") but nothing happens. Any ideas on what I'm doing wrong? Thanks!
Depending on what you actually want your classes to be, I'd use this code:
$(".thumbnail").on("click", function () {
var $block = $(this).closest(".block");
$block.find(".window, .video").add("#modal").removeClass("hide").addClass("show");
});
DEMO: http://jsfiddle.net/gLMSF/ (using different, yet similar code)
It actually finds the right elements, based on the clicked .thumbnail. It finds its containing .block element, then looks at its descendants to find the .window and .video elements.
If you actually want to include . in your attributes, you need to escape them for jQuery selection.
As for styling, you should probably just have the styling be display: block; by default, and then toggle the hide class. It's less work, and makes more sense logically.
You have a huge issue with your class names in HTML:
<div class=".block">
it should be
<div class="block">
Your modal is the only one that has the class properly named. Your DOM traversals will not work because they are looking for "block" but it's called ".block"
So fix it all to this and you should find more success:
<div class="block">
<div class="thumbnail">
//Thumbnail image
</div>
<p>Video Description</p>
<div class="window hide">
<div class="video hide">
//Video content
</div>
</div>
</div>
<div id="modal" class="hide"></div>
Your code won't work because your selectors have periods (.) in your classes if that's actually what you want, you should try it like this:
$(".\\.thumbnail").on("click",function(){
$("#modal").removeClass("hide").addClass("show");
$(this).closest("\\.window").removeClass("hide").addClass("show");
$(this).closest("\\.video").removeClass("hide").addClass("show");
});
Otherwise just try removing the periods from the classes...
Also, you're using .closest() incorrectly, as it looks up through ancestors in the DOM tree...
You should change your code to:
$(".\\.thumbnail").on("click",function(){
$(this).next("\\.window").children(".video")
.addBack().add("#modal").removeClass("hide").addClass("show");
});
I'm using the following HTML structure:
<div id="clock">5:30 AM
<div id="day">Wednesday
</div>
<div id="date">14 December
</div>
</div>
I update the contents of these elements using Javascript. For "day" and "date" I use $("#day").text(day) and $("#date").text(date). Because "clock" is a parent element I had to use $("#clock").prepend(clock) to succesfully add the text.
The problem with the latter function, is that new text is prepended every time the clock is refreshed, i.e. it builds up a list of clock times. For the first two functions the text is just replaced, like it should. Is there a way to make this happen for the "clock" function as well?
EDIT: Sorry, should have been a bit more clear about the clock. Have edited the code, so you understand. BTW, the reason the clock is parent element is that could make the other two elements depend on the clock's position and styling.
I also created a jsFiddle: https://jsfiddle.net/daanodinot/NZtFA/
I left the list building thing (annoyingly) in!
BTW, I'm not too sure if function(); setInterval('function()', 1000) is the best way to refresh, so if you something better I'd be happy to know :)
What you need to do is change the structure of your html to this.
<div id="wrapper">
<div id="clock"></div>
<div id="day"></div>
<div id="date"></div>
</div>
Then for the javascript
$('#clock').text('12:45');
$('#day').text('Wednesday');
$('#date').text('12/14/2011');
This way you can just change/refresh the text of clock instead of prepending values to it.
Another approach, with your current html, which i do not recommend.
<div id="clock">
<div id="day">
</div>
<div id="date">
</div>
</div>
The js
$('#clock').contents().get(0).nodeValue = '12:45';
$('#day').text('Wednesday');
$('#date').text('12/14/2011');
If you have HTML
<div id="clock">
<div id="day"></div>
<div id="date"></div>
</div>
Then you don't have to modify #clock at all. By doing $("#day").text(day) and $("#date").text(date) content of those divs is changed and you don't have to touch #clock.
But in case you want to replace a content of a element then use .html(newContent). See documentation.
You should first add a new element with prepend and then replace it's content, now you just constantly keep prepending new elements instead of working on the same element again.
What do you mean by
Because "clock" is a parent element I had to use
$("#clock").prepend(clock) to succesfully add the text.
?
It seems redundant. Since $('#day') and $('#date') uniquely address your targeted elements.
My tip:
Do not use clock. $("#day").text(day) and $("#date").text(date) already update the numbers inside your #clock element.
Hy,
my consideration for your problem is, IF you choose to manipulate the Content of the #clock div you could simply do this:
var newContent="";//in here comes whatever you want to add to your clock div
$('#clock').html($('#clock').html()+newContent);
That's the way I use it most of the time but you could also do this:
var curContent=$('#clock').html();
curContent+="<>put in your code to add</>";
$('#clock').html(curContent);
This is I guess a bit slower than the first one, but it works.
I'm tinkering a bit with jquery to show a hidden div when a link is clicked. This should be fairly simple, but there's a flaw to it in this case. I have the following markup:
<div class="first-row">
<div class="week">
<p>Uge 2</p>
<p>(08-01-11)</p>
</div>
<div class="destination">
<p>Les Menuires</p>
<p>(Frankrig)</p>
</div>
<div class="days">4</div>
<div class="transport">Bil</div>
<div class="lift-card">3 dage</div>
<div class="accommodation">
<p><a class="show-info" href="#">Hotel Christelles (halvpension)</a></p>
<p>4-pers. værelse m. bad/toilet</p>
</div>
<div class="order">
<p>2149,-</p>
<p class="old-price">2249,-</p>
</div>
<div class="hotel-info">
<!-- The div I want to display on click -->
</div>
</div>
When I click the "show-info" link I want the "hotel-info" div to display.
My backend devs don't want me to use ids (don't ask me why..) and the above markup is used over and over again to display data. Therefore I need to be able to access the "hotel-info" div in the "first-row" div where the link is clicked.
I've tried to do something like:
$(document).ready(function() {
$('.show-info').click(function() {
var parentElement = $(this).parent().parent();
var lastElementOfParent = parentElement.find(".show-hotel");
lastElementOfParent.show();
});
});
But without a result :-/ Is this possible at all?
Any help is greatly appreciated!
Thanks a lot in advance!
Try this:
$('.show-info').click(function() {
$(this).closest('.accommodation').siblings('.hotel-info').show();
});
Even better imo, as it would be independent from where the link is in a row, if every "row div" has the same class (I assume only the first one has class first-row), you can do:
$(this).closest('.row-class').find('.hotel-info').show();
Reference: .closest, .siblings
Explanation why your code does not work:
$(this).parent().parent();
gives you the div with class .accommodation and this one has no descendant with class .hotel-info.
It is not a good idea to use this kind of traversal for more than one level anyway. If the structure is changed a bit, your code will break. Always try to use methods that won't break on structure changes.
You're right in not using an ID element to find the DIV you want :)
Use closest and nextAll
Live demo here : http://jsfiddle.net/jomanlk/xTWzn/
$('.show-info').click(function(){
$(this).closest('.accommodation').nextAll('.hotel-info').toggle();
});