How to properly do JS condition? - javascript

I run this jQuery (1.8.3) code and always get the "in" alerted even when the length is greater than 1.
What I'm doing is dynamically adding elements to a menu and the if is to make sure this element doesn't exist yet.
I tried also == 0 and === 0 but the result is the same...
Here is a JS fiddle: http://jsfiddle.net/mHhwq/4/
$(".sidebarit a.olink").click(function(event){
iframe_url = $(this).attr("href");
sidebar_id = '#' + iframe_url.replace(/[/.]/g, '');
alert('sidebar_id: ' + sidebar_id);
// create the sidebar if it doesn't exist
if ($(sidebar_id).length < 1) {
alert("in");
$("#sidebar_nav ul").append('<li></li>');
$("#sidebar_content").append('<div id="' + sidebar_id + '" style="display:none;"></div></div>');
} else { alert("out"); }
// don't follow the link
event.preventDefault();
});
In FireBug I see the length equals 1 but still enters the block.
What am I doing wrong?
Update:
My mistake was that I added the # at the wrong place...

Try to put alert inside if stmt as alert($(sidebar_id).length).
And you are making a mistake in appending the div to$("#sidebar_content").
Where sidebar_id is something like #test from sidebar_id = '#' + iframe_url.replace(/[/.]/g, ''); and you are appending like <div id= "#test" there, where it should be <div id= "test"(No # symbol is requird for id).
Your code will results like
$("#sidebar_content").append('<div id="#test" style="display:none;"></div></div>');
Change to
$("#sidebar_content").append('<div id="test" style="display:none;"></div></div>');
Then try again.

You must not have more than one element with the same ID. jQuery takes just the first in such a case.
To prove this have such HTML:
<div id="mydiv">hello</div>
<div id="mydiv">world</div>
Then this code:
var myDiv = $("#mydiv");
alert("length: " + myDiv.length + ", contents: " + myDiv.html());​
Test case.
If you have more than one element you need to iterate, use class instead or alternatively make sure to have unique ID for each sidebar and take the one closest to the clicked element.

Related

Javascript append + click remove them

I got a question, what I have already solved, but it's just so annoying.
I have a js code, which is putting down some html code when a button is pushed with "append", and with that code I'm giving an id to an x button, and an id to the container element. I wanted to use these id-s to identify them with a click function, to remove the html code:
var num = 0;
$('.button').click(funcion(){
num++;
var code = '\
<div class="container" id="text' + num + '">\
<div id="x' + num + '">\
x\
</div>\
Some stuff\
</div>\
';
$('.puthere').append(code);
$('#x' + num).click(function(){
$('#text' + num).remove();
});
});
Now the annoying part is the click function on the x. What I would expect is, that this code would work somehow like this:
1st click on the "button" class element should give this code:
$('#x1').click(function(){
$('#text1').remove();
});
after 2nd click I should have this:
$('#x1').click(function(){
$('#text1').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
instead what I'm getting after the 2nd click is this:
$('#x1').click(function(){
$('#text2').remove();
});
$('#x2').click(function(){
$('#text2').remove();
});
so it's always the last element what the x buttons want to remove. My question is, why can my "num" variable stay "1" at the #x1, but not at the #text1?
My solution was to address the parent element instead:
$('#x' + num).click(function(){
$(this).parent('.container').remove();
});
I know, that there is the "live" function too, what I could use, and I wouldn't need to mess with id-s, but that just seems more heavy. Is that correct? Or I'm overcomplicating things too much without making it more efficent?
It's because num is global and you access it after you create second button. To fix this you can wrap your code with anonymouse self executing function:
(function(num) {
$('#x' + num).click(function(){
$('#text' + num).remove();
});
})(num);
or better use only one click
$('.parent').on('click', '.container > div', function() {
$(this).parent().remove();
});

Variable Interpolation in Jquery code inside for loop

I have some code, http://jsfiddle.net/hucw940s/
which has a for loop.
before
<div id="container">
</div>
after
for (i = 1; i < 4; i++){
var showMe = $('<a href=# id="link' + i + '">')
.append('click').click(function(){ alert('You clicked num: ' + i) });
$('#container').append(
$('<div id="div'+i+'">').append('this is div number: ' + i).append(showMe)
);
}
so the links are generated with id=link1, link2, link3 etc, and the divs appended are the same, however the onclick code seems to put the var i in after the event, so on clicking any link they say "you clicked number 4"
How can I make this use the i from the clicked link inside the function that is called on click?
What you are experiencing is the expected behavior based on your code.
However, what you are actually trying to do is pass in event data to your click function. This can be accomplished like this:
for (i = 1; i < 4; i++) {
var showMe = $('<a href=# id="link' + i + '">').append('click')
.click({value: i}, function (e) { alert('You clicked num: ' + e.data.value) });
$('#container').append($('<div id="div' + i + '">').append('this is div number: ' + i).append(showMe));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
</div>
First, you have to assign the event data, so we pass in an object
{value: i} before we pass in the handler function.
Then, in the handler function, we assign the variable e to the
event, so we can access the data attribute.
Finally, you access the value that was passed in by referencing
e.data.value.
You can add as many event data objects as you want and reference them by name this way.
The reason your code is not working as you are expecting is because the variable i is already equal to 3 by the time the click event happens, since the for loop completes before you are able to click any of the links.
Hope this helps give you a better understanding of why your code is behaving the way it is and what you can do to fix it.
Store the id in a data-attribute.
Updated jsFiddle

Two different css classes in the same javascript line

I'm trying to assign these css values (below) for the javascript line in the example below, but don't know a way to target valueB with the .valueB-class.
$(".valueA").html(valueA + " valueB" + ((valueA > 1) ? 's': ''));
.valueA-class { font-size:X }
.valueB-class { font-size:XX }
Here is an example of what I need help with (you may have to click on the input boxes in the results panel to get the calculations to show up - that's what I had to do): http://jsfiddle.net/hughett/g21g8t85/
Welcome to stackoverflow!
Your question seems a bit vague. I assume that this is you want to achieve. In the specific example the value of the class is changed through the use of the jquery attr function. Firstly, the specific div in which our text is placed is retrieved and then the value gets specified. I am attaching a code snippet below.
A general note, using a . in css indicates that you are referring to a class so there is no need to attach a -class in the name.
$( "#myButton" ).on( "click", function() {
var attr = $("#myText").attr('class');
console.log(attr);
if (attr == "valueA") {
$("#myText").attr("class","valueB");
} else {
$("#myText").attr("class","valueA");
}
});
.valueA { font-size:11pt }
.valueB { font-size:25pt }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="myButton" type="button">Change Text size</button>
<div id="myText" class="valueA">sdsa asd aasdaas asdjlasj dasdkas asldjsalj slad TEST</div>
EDIT to include another answer
In order for the text included in a single span to have different font-size you need to separate it somehow. In the specific example, I have added a second span in the respective div and adjusted the cacl_summary method to get the expected result.
The code is available below; I have also updated the jsfiddle here
<div style="background:yellow;"><span class="label">Simple payback</span>
<span class="figure sp"></span> <span class="figure year"></span></div>
function calc_summary(){
if (cspy) {
sp = parseFloat($("input[name=upgrade]").val()) / cspy;
if (sp) {
sp = (sp < 100) ? sp.toString().substring(0, 4) : sp;
$(".sp").html(sp);
$(".year").html(" years" + ((sp > 1) ? 's': ''));
$(".ror").html(parseInt((1/sp) * 100) + '%');
}
}
}

jQuery show, get element by name

I'm creating a news page. I need to find out if there is set an anchor to an article. If not, I just show the latest article. An example URL with anchor is: example.com/news.php#article43
The HTML structure is:
<div>
<a name="article43"></a>
<h2>TITLE</h2>
<div class="news_content"></div>
</div>
And my JS is this:
var anchor = $(location).attr('href').split('#');
if(anchor[1]){
$('a[name=' + anchor[1] + ']').next('.news_content').show();
}else{
$('.news_content').first().show();
}
Something doesn't work.
next will only return the immediate sibling after the element, you probably want nextAll:
$('a[name=' + anchor[1] + ']').nextAll('.news_content').show();
or, if your HTML structure doesn't involve wrapping, ie:
<div>
<a name="article43"></a>
<h2>TITLE</h2>
<div class="news_content"></a>
<a name="article44"></a>
<h2>TITLE</h2>
<div class="news_content"></a>
</div>
You'd want: http://jsfiddle.net/AVg3y/
$('a[name=' + anchor[1] + ']').nextAll('.news_content').first().show();
Also, this is probably just a typo, but your HTML is malformed. It should be:
<div>
<a name="article43"></a>
<h2>TITLE</h2>
<div class="news_content"></div> //<-- oops
</div>
Try this (use siblings instead of next):
var anchor = location.href.split('#');
if(anchor[1]) {
$('a[name=' + anchor[1] + ']').siblings('.news_content').show();
} else {
$('.news_content').first().show();
}
You can get the hash by looking at window.location.hash. Use substring(1), to return everything after the # in the window.location.hash value.
if(window.location.hash) {
$('a[name=' + window.location.hash.substring(1) + ']').next('.news_content').show();
} else {
$('.news_content').first().show();
}
I solved the problem.
First: I ned to use nextAll() as many of you said.
Second: I included a CSS with jQuery (one that's only used when JS is enabled). I had to include this before the $(document).ready function. Else it was setting the news_content elements to display:none
Thanks to all who tried to help me.
All the answers have simlilar variations for hash, but none check to see if the hash has a matching element:
I suggest checking that the element exists as part of condition.
var contentToDisplay=$('.news_content').first();
if(anchor[1]){
var $link= $('a[name="' + anchor[1] + '"]');
contentToDisplay= $link.length ? $link.next().next('.news_content') : contentToDisplay;
}
contentToDisplay.show()

How to select for something that begins with a string but doesn't end with a different string in jQuery?

I am new to jQuery, exploring its syntax a bit.
My page has elements like this:
<area id="SA" ... />
<area id="AF" ... />
<area id="EU" ... />
<area id="NA" ... />
I am trying to show and hide div sections based on click events off the area tags, which have matching ending ID's, coded like this:
<div id="div_SA" ... />
<div id="div_AF" ... />
<div id="div_EU" ... />
<div id="div_NA" ... />
So, to show the exact match, but hide all the div sections which have id's that start with "div_" but don't otherwise match, without hiding every other div on the page, I tried this:
var q = 'div[id="div_' + event.target.id + '"]';
var r = 'div[id^="div_"],div:not[id$=' + event.target.id + '"]';
$(q).show();
$(r).hide();
$(r).hide(); is not working. What am I doing wrong? (I know I could assign CSS classes and get at them with class names, but I'm still curious about how to construct a query that will work this way.)
Make things as easy and simple as possible, since you are new at jQuery, you should get the habit of using on(). Not click(), that is outdated, and simply just refers to the on method.
$('area').on('click', function() {
var id = "#div_" + $(this).attr('id'), // comma allows you to make multiple variables
divs = $('div').hide() // puts all the divs in a variable and automatically hides them all
// filter through all the divs, and selects the one with the id,
// of the area that was clicked, and shows it
divs.filter(id).show();
});​
Hope this could help you for now. If not, please let me know.
Edit: See below for the syntax fix as mentioned in your post,
var q = '#div_' + this.id;
var r = 'div[id^="div_"]:not("#div_' + this.id + '")';
$(r).hide();
$(q).show();
DEMO
Please check the alternate solution below,
For evaluating q, I would simply use
var q = $('#div_' + this.id);
And for r,
var r = $('div[id^="div_"]').not(q);
r.hide();
q.show();
DEMO
The not css pseudo selector uses parenthesis not brackets. Also you have an unmatched quotation mark towards the end before the last bracket.
var r = 'div[id^="div_"],div:not(#' + event.target.id + ')';
Also, your code can be simplified by changing it to:
var q = '#' + event.target.id;
var r = 'div[id^="div_"]:not(#' + event.target.id + ')';
$(q).show();
$(r).hide();
How about this:
$('area').click(function() {
var areaID = $(this).attr('id');
$('div[id^="div_"]').hide();
$('div[id^="div_' + areaID + '"]').show();
});​
//start by selecing all of the DIV elements that have an ID attribute that starts with "div_",
//and hide all of them,
//then filter that list down to only the element(s) that have an ID that ends with the id of the `event.target` element
//and show that/those element(s)
$('div[id^="div_"]').hide().filter('#div_' + event.target.id).show();
Short and simple
// cache divs, no need to search them again
var divs=$('div[id^="div_"]');
$('area').click(function(){
divs.hide().eq( $(this).index() ).show();
});

Categories