jQuery show div with same number suffix as first child of element - javascript

First off I'd like to apologise for asking about something so specific but it's been wracking my brain all day and I'm out of ideas.
I'm using jquery to show and hide elements based on their number suffix ie:
<span></span> will target ->
<div class="content" id="cont-1">This is content</div> and it's working perfectly. I'd like to target another element based on the suffix of another element but I'm failing to. Here's the code:
HTML:
<script src="http://code.jquery.com/jquery.js"></script>
1
2
3
<div class="content" id="cont-1"><p>This is content</p></div>
<div class="content" id="cont-2"><p>This is content</p></div>
<div class="content" id="cont-3">
<div class="child" id="child-11"><p>This is the first child</p></div>
<div class="child" id="child-12"><p>This is the second child</p></div>
</div>
<div class="external" id="external-11"><p>I am the first external</p></div>
<div class="external" id="external-12"><p>I am the second external</p></div>
JAVASCRIPT:
var $ = jQuery;
$(document).ready(function(){
$('.content .child:nth-child(1)').addClass('active');
});
function showCont(num){
$('.content').fadeOut(300);
if( $('#cont-'+num).css('display')=='none' ){
$('#cont-'+num).fadeIn();
}else{
$('#cont-'+num).fadeOut();
}
}
CSS:
.content{
background:green;
color:white;
padding:5px;
}
.external{
background:blue;
color:white;
padding:5px;
}
.content, .external, .child{
display:none;
}
.active{
display:block;
}
CodePen: http://codepen.io/anon/pen/uFpzE
What I'm trying to achieve is this:
If you click on #tab-3 the .external div that corresponds with the first child of #cont-3 should show.
I've tried this:
var $ = jQuery;
$(document).ready(function(){
$('.content .child:nth-child(1)').addClass('active');
var random = $('#cont'+num + '.child:first-child').attr('id').replace(/child-/, '');
});
function showCont(num){
$('.content').fadeOut(300);
if( $('#cont-'+num).css('display')=='none'){
$('#cont-'+num).fadeIn();
$('#external'+random).fadeIn({'duration':600,'queue':false});
}else{
$('#cont-'+num).fadeOut();
}
}
...and it isn't working. Where am I going wrong?

I'm not 100% sure what you're trying to accomplish with the code in the document.ready part, but the showCont function does what you requested.
$(document).ready(function(){
$('.content .child:nth-child(1)').addClass('active');
});
function showCont(num)
{
$('.content').fadeOut(300);
$('.external').fadeOut(300);
if( $('#cont-'+num).css('display')=='none' )
{
$('#cont-'+num).fadeIn();
// get the child element's id
var targetID = $("#cont-"+num).children().first().attr('id');
if(targetID)
{
// construct the id of the external element
$('#external-'+targetID.substring(targetID.indexOf('-')+1))
.fadeIn({'duration':600,'queue':false});
}
}
else
{
$('#cont-'+num).fadeOut();
}
}
DEMO

The variable random is not defined in your JS file, and there are some typos regarding the selector elements (e.g. it should be $('#external-'+random) instead of $('#external'+random)). Base on your code, I came up with the following for your reference:
DEMO
var $ = jQuery;
$(document).ready(function(){
$('.content .child:nth-child(1)').addClass('active');
});
function showCont(num){
$('.content').fadeOut(300);
if( $('#cont-'+num).css('display')=='none' )
{
$('#cont-'+num).fadeIn();
var random = $('#cont-'+num + ' div:first-child').attr('id').substring(6);
$('#external-'+random).fadeIn({'duration':600,'queue':false});
}
else
{
$('#cont-'+num).fadeOut();
var random = $('#cont-'+num + ' div:first-child').attr('id').substring(6);
$('#external-'+random).fadeOut({'duration':600,'queue':false});
}
}

I think you've got random in the wrong function. The #cont and #external selectors are also missing a trailing dash:
$(document).ready(function(){
$('.content .child:nth-child(1)').addClass('active');
});
function showCont(num){
var random = $('#cont-'+num + '.child:first-child').attr('id').replace(/child-/, '');
$('.content').fadeOut(300);
if( $('#cont-'+num).css('display')=='none'){
$('#cont-'+num).fadeIn();
$('#external-'+random).fadeIn({'duration':600,'queue':false});
}else{
$('#cont-'+num).fadeOut();
}
}
This should be closer to what you're after (untested though).
Once you've got it working, you could look at simplifying it by using data-id="num" attributes on your HTML elements and accessing the id values with .data('id') in your js, then binding the tab buttons from within your DOM ready fn. It would look closer to this:
$(function() {
$('.tab').click(function (e) {
var num = $(this).data('id'),
$child = $('.child[data-id="' + num + '"]')
;
// ...
})
})

I think this changes to your function showCont(num) would do:
$('.content').fadeOut(300);
if( $('#cont-'+num).css('display')=='none' )
{
$('#cont-'+num).fadeIn();
var value= $('#cont-'+num+' div' ).first().attr("id").slice(-2);
$('#external-'+value).fadeIn();
}
else
{
$('#cont-'+num).fadeOut();
$('.external').fadeOut();
}

Related

Hide div if URL hash begins with word in Javascript

How could I hide divs that begin with id "news" but also contain a number like "news1" "news2" etc if the URL hash doesnt contain "news".
like hide if someurl.com/#events. but show any "news" div if someurl.com/news1
need in regular JS
thanks,
Try This:-
$(function(){
var url = window.location.hash;
if(url.indexOf('news') > -1){
$("div[id^='news']").hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="news1">News1</div><br>
<div id="news2">news2</div><br>
<div id="news3">news3</div><br>
<div id="event">event</div><br>
Update: (Using Pure JavaScript)
(function() {
var url = window.location.hash;
/* for testing set the hash to 'news' */
url='news';
if(url.indexOf('news') > -1){
var bodyDOM = document.body;
bodyDOM.querySelectorAll("[id^='news']").forEach(function(item, index){
item.style.display='none';
});
}
})();
<div id="news1">News1</div><br>
<div id="news2">news2</div><br>
<div id="news3">news3</div><br>
<div id="event">event</div><br>
The script hasn't been tested. It does these steps:
Looking for the word "#news" in URL. In our case, if there aren't any word.
For each div with the ID "new" or similar
Add a CSS to this div to hide it.
<script type="text/javascript">
$(document).ready(function () {
if(window.location.href.indexOf("#news") < 0) {
$("div[id^='news']").css('display', 'none');
}
});
</script>
If you put a class on all the divs you'd want this apply to, you can do this:
$(document).ready(function() {
$('.CLASSNAME').each(function(i) {
if($(this).val().indexOf('WORD_YOURE_LOOKING_FOR') > -1) {
$(this).css('display', 'none');
}
);
});
Well you can access the hash in a URL like so:
var hash = window.location.hash;
I'm not 100% clear what you want to do at that point. If you wanted to show the news1 div, you'd do this:
if(hash == 'news1') {
$('#news1').show();
}
Try this:
var hash = window.location.hash;
$('[id^="'+hash+'"').hide();

How to show a specific amount of child divs?

I am not sure if this is possible...
If you have f.ex.
<div id="parent">
<div id="child1"></div>
<div id="child2"></div>
<div id="child3"></div>
<div id="child4"></div>
<div id="child5"></div>
<div id="child6"></div>
</div>
How could you, with jquery or javascript (or anything for that matter), just show the first two?
You can use :gt() jQuery selector.
$("#parent>div:gt(1)").hide()
Actually, if you want to show incrementally, it is better to hide everything first and then use :lt() jQuery selector to show.
$("#parent>div").hide();
var n = 2;
$("#parent>div:lt(" + n + ")").show();
el.click(function () {
n += 5;
$("#parent>div:lt(" + n + ")").show();
});
You can do this with CSS:
#parent div:nth-child(n+3) {
display: none;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/%3Anth-child
JsFiddle
Here's a way you could do it in jQuery:
// hide all the children
$("#parent>div").hide();
// unhide the two we care about
$("#child1").show();
$("#child2").show();
If you don't have known IDs for your elements, here's a more general solution:
$("#parent>div~div~div").hide();
You could write jQuery code like so:
var visibleIndexes = [0, 1]
$("#parent").children().each(function(index) {
if(visibleIndexes.indexOf(index) === -1){
$(this).hide();
} else {
$(this).show();
}
});
You can store indexes which you want to show in variable visibleIndexes or any other variable and pass it to this function
A simple iterative approach:
$( document ).ready(function() {
var i = 0;
var somevalue = 3;
$("#parent").children("div").each(
function () {
if(i > somevalue) $(this).hide();
i++;
});
});

jQuery show delete display attr

I'm using jQuery hide and show function but I have a problem with the show one.
My javascript code is:
function toggle_visibility(idContent, idLien, question) {
var c = document.getElementById(idContent);
var l = document.getElementById(idLien);
var q = question;
if(c.style.display == 'block') {
$("#" + idContent).hide("blind") ;
l.innerHTML = '<h4><i class=\"icone-rouge icon-right-open-big\"></i>'+ q +'</h4>' ;
}
else {
$("#" + idContent).show("blind") ;
l.innerHTML = '<h4><i class=\"icone-rouge icon-down-open-big\"></i>'+ q +'</h4>' ;
}
}
The problem is that it doesn't work for the hide part when the div is hidden at the load of the page (with display='none'). I can display the block but then I cannot hide it.
I noticed that when I show a content, jQuery delete the display attr in my html style... Maybe there is a link.
Here a link for example : http://jsfiddle.net/29c4D/2/
Thank you.
DescampsAu, since you are using jQuery I rewrote your code to take full advantage of the powerful library. You can see the example in this fiddle.
Let jQuery do the heavy lifting of checking whether an element is hidden or not by making use of either the .toggle() or .slideToggle() methods.
Remove all of the onClick() code within your spans and use this jQuery instead:
jQuery
$(document).ready( function() {
//After the page has loaded, let jQuery know where all of the spans are.
var toggleThis = $(".toggleMe");
//Whenever you click one of the spans do this function.
toggleThis.click( function() {
//Register the span you clicked and the next div that holds the hidden stuffs.
var el = $(this),
nextDiv = el.next(".toggleMeDiv");
//Check if the span's partner div is hidden or showing by checking its css "display" value.
if(nextDiv.css("display") == "block") {
//Change the text of the span to be its title attribute plus whether its partner is showing or hidden.
el.html(el.attr("title")+" hidden");
} else {
el.text(el.attr("title")+" shown");
}
//Let jQuery toggle the partner's visibility.
nextDiv.slideToggle();
});
});
HTML
<span class="toggleMe" title="Quest 1">Quest 1</span>
<div class="toggleMeDiv">Boubou1</div>
<span class="toggleMe" title="Quest 2">Quest 2</span>
<div class="toggleMeDiv">Boubou2</div>
Making this too hard on yourself.
HTML
<span class="toggle" id="lien1" data-original-text="Quest 1">Quest 1</span>
<div id="content1">Boubou1</div>
<span class="toggle" id="lien2" data-original-text="Quest 1">Quest 2</span>
<div id="content2">Boubou2</div>
JS
$(document).ready( function () {
$('.toggle').on('click', function() {
$(this).next('div').toggle('blind', textToggle); // or slideToggle();
});
function textToggle() {
var $target = $(this).prev('span'); // "this" is the div that was toggled.
var originalText = $target.attr('data-original-text');
if ( $(this).is(':visible') ) {
$target.text( originalText + ' open' );
} else {
$target.text( originalText + ' closed' );
}
}
});
A fiddle: http://jsfiddle.net/29c4D/7/
EDIT to include label + effect.

How to cycle through siblings using jQuery?

I have the folowing code:
html:
<div class="container">
<div class="selected">A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
<button id="next">next!</button>
jQuery:
$("#next").click(function() {
$(".selected").removeClass("selected").next().addClass("selected");
});
What i want is loop through the divs in the container. I can do this to cycle:
$("#next").click(function() {
if ($(".selected").next().length == 0) {
$(".selected").removeClass("selected").siblings(":nth-child(1)").addClass("selected");
}
else {
$(".selected").removeClass("selected").next().addClass("selected");
}
});
But i think there is a simpler way. How can i make it simpler ? (I don't mind if you don't use the next() function).
jsFiddle: http://jsfiddle.net/S28uC/
I 'd prefer siblings.first() instead of siblings(":nth-child(1)"), but in essence you won't be able to wrap around without using some variant of next().length.
Update: If I were writing this from scratch, this is how I 'd do it:
$("#next").click(function() {
var $selected = $(".selected").removeClass("selected");
var divs = $selected.parent().children();
divs.eq((divs.index($selected) + 1) % divs.length).addClass("selected");
});
This approach is motivated by two factors:
When you want to cycle over a collection indefinitely, modulo comes to mind
Getting rid of the if makes for smarter-looking code
When setting the value of divs I preferred $selected.parent().children() over the equivalent $selected.siblings().add($selected) as a matter of taste -- there are practically endless possibilities.
One simple way is this :
$("#container").find("div:eq(0)").addClass("selected");
how about this.
...
var selected = $(".selected").removeClass("selected");
if (jQuery(selected).next().addClass("selected").length == 0
{jQuery(selected).siblings().first().addClass("selected");};
...
In old good AI manner you try to do the deed (addClass), if it worked (length <> 0) nothing more to do, otherwise you try again on the first of the siblings.
You can try this
var cont = $('.container'),
i = 0;
$("#next").on('click', function() {
cont.children().removeClass('selected');
i += 1;
if ( i === document.querySelectorAll('.container div').length ) { i = 0; }
cont.children().eq(i).addClass('selected');
});
var cont = $('.container'),
i = 0;
$("#next").on('click', function() {
cont.children().removeClass('selected');
// increase index for each click
i += 1;
// reset i if it reached to last index
//(hack to force next to go back to first element when we are at the end)
if ( i === document.querySelectorAll('.container div').length ) {
i = 0;
}
cont.children().eq(i).addClass('selected');
});
.selected {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="selected">A</div>
<div>B</div>
<div>C</div>
<div>D</div>
</div>
<button id="next">next!</button>
simply you will increase i for each click and when it reach the end (divs length ) it will be reset.

Jquery Hide Class when no class is present

I have some text below called (16 Courses). I need to hide only this text, but I can't seem to hide it no matter what I try using jquery. Is there any help someone could provide so I can hide on this text?
<div id="programAttributes">
<div class="left" id="credits">
<h3>Credits</h3>
<h3 class="cost">48</h3>
(16 Courses)
</div>
<div class="gutter12 left"> </div>
<div class="left" id="costPer">
<h3>Cost Per Credit</h3>
<h3 class="cost">$300</h3>
</div>
</div>
I thought if I could write something like this that would do the trick, but I am so far unsuccessful.
$("#credits:not([class!=h3])").hide();
Usage
// hides in the whole document
hideText("(16 Courses)");
// only hide inside a specific element
hideText("(16 Courses)", $('#programAttributes'));
// make it visible again
showText("(16 Courses)");
[See it in action]
CSS
.hiddenText { display:none; }
Javascript
// escape by Colin Snover
RegExp.escape = function(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
}
function hideText(term, base) {
base = base || document.body;
var re = new RegExp("(" + RegExp.escape(term) + ")", "gi");
var replacement = "<span class='hiddenText'>" + term + "</span>";
$("*", base).contents().each( function(i, el) {
if (el.nodeType === 3) {
var data = el.data || el.textContent || el.innerText;
if (data = data.replace(re, replacement)) {
var wrapper = $("<span>").html(data);
$(el).before(wrapper.contents()).remove();
}
}
});
}
function showText(term, base) {
var text = document.createTextNode(term);
$('span.hiddenText', base).each(function () {
this.parentNode.replaceChild(text.cloneNode(false), this);
});
}
You can check for and remove textnodes like this:
​$("#credits").contents().filter(function() {
if(this.nodeType == 3)
this.parentNode.removeChild(this);
});​​​​​​
You can test it here, this gets all the nodes (including text nodes) with .contents(), then we loop through, if it's a text node (.nodeType == 3) then we remove it.
Could you wrap it in a separate span, and then do:
$('#credits span').hide();
?
Try wrapping the text in a span as follows:
<div class="left" id="credits">
<h3>Credits</h3>
<h3 class="cost">48</h3>
<span id="toHide">(16 Courses)</span>
</div>
then you can use jquery:
$("#credits > span)").hide();
the hide() function has to be applied to a DOM element.
I would use a label tag around the text so I can handle it with jquery.
It's textnode. Loop thru all parents nodes and if it's type is textnode, hide it. See also this:
How do I select text nodes with jQuery?

Categories

Resources