.attr('href') returning undefined - javascript

I am using a simple JQuery solution to get the href from a link and apply it to a click event. This works in Webkit and Gecko browsers, however Internet Explorer (7 & 8) keeps displaying the href location as undefined. Anyone got a fix for this? Can help me solve this? Much appreciated if so.
$('table tr').click(
function () {
var element = $(this).attr("class");
var hrefLocation = $('#'+ element +' .deal-holder a').attr('href');
alert(hrefLocation)
window.location.href = hrefLocation;
return false;
}
);
HTML is simple:
<tr class="QRG">
<td class="blue">QRG</td>
<td>Company Sale</td>
<td>Technology</td>
</tr>
<div class="deal" id="QRG">
<p><span class="js">Overview</span><span class="no-js">Enham</span></p>
<div class="deal-holder">
<div class="image-holder">
<img src="../assets/images/enham.gif" alt="" height="70" width="150" />
</div>
<p>Enham is a charity established in 1918, which delivers a wide range of essential services that provide choice and empowerment to disabled people to make their own decisions about their lives. Enham is a charity established in 1918, which delivers a wide range of essential services that provide choice and empowerment to disabled people to make their own decisions about their lives</p>
<a class="moreInfo" href="individual.html">More Information</a>
</div>
</div>

Nothing jumps out at me at being wrong.
First make sure your using the latest version of jQuery as that can sometimes help.
I change your code so the link within the tr has the click event:
$('table tr a').click(function (e) {
var element = $(this).closest('tr').attr("class"),
hrefLocation = $('#'+ element +' .deal-holder a').attr('href');
alert(hrefLocation)
window.location.href = hrefLocation;
e.preventDefault();
});
I did a demo here and it works in IE 7,8 and 9. Hope this helps.

Without knowing the rest of your html code is difficult to know exactly what's your problem, the behaviour depends greatly on how your html is structured... But doing a quick test here it works: Example, just uses the $(this) pointer to get the child link.

You may need to select the first element in the group of hyperlinks.
$('table tr').click(
function () {
var element = $(this).attr("class");
var hrefLocation = $('#'+ element +' .deal-holder a').eq(0).attr('href');
alert(hrefLocation)
window.location.href = hrefLocation;
return false;
}
);

Try wrapping it in the ready function.
IE could be trying to add the event to the object, before it's in the DOM:
$(document).ready(function(){
$('table tr').click(
function () {
var element = $(this).attr("class");
var hrefLocation = $('#'+ element +' .deal-holder a').attr('href');
alert(hrefLocation);
window.location.href = hrefLocation;
return false;
});
});

Related

Efficient jQuery/JS - avoiding copy-paste the same code again & again

I need to write an efficient code in order to keep it simple & code file small, also I want to use the knowledge I hopefully get from here in future codes.
UPDATE: Just to be clear - my example is fixed "buttons" on browser window side & if you click on one of them, it takes you to div with same ID (look at code below).
IMAGE:
MY CODE EXAMPLE:
//Smooth Scroll Menu Links
jQuery('.div1').on('click', function(e) {
e.preventDefault();
jQuery('html,body').animate({scrollTop:jQuery(this.hash).offset().top-100}, 800);
});
//I have to copy-paste it 1000 times & only change the ".div1" to something else
//Note that I need a solution with different class names, not "div1", "div2" etc but e.g "location", "potato", "car" etc.
How to make this code working without writing same lines for every single div?
There got to be a way to get class from item you click & then scroll to item with same name ID, right? Or any other way to keep codes shorter in that kind of situations - otherwise it's just copy-paste-huge-file fest.
You can give each button a class so you can catch them all, than go to the element you want to scroll to by looking at the attribute of the clicked button :)
HTML
<div class="buttons" data-scroll="div1">div1</div>
<div class="buttons" data-scroll="div2">div2</div>
<div class="buttons" data-scroll="div3">div3</div>
<div class="content" id="div1">some content</div>
<div class="content" id="div2">some content</div>
<div class="content" id="div3">some content</div>
JS
$('.buttons').on('click', function(e) {
e.preventDefault();
var scrollTarget = $(this).data("scroll");
scrollme(scrollTarget);
function scrollme(target) {
$('html,body').animate({scrollTop:$("#"+target).offset().top}, 800);
}
});
example: http://jsfiddle.net/7gd66kr1/1/
try this i hope will work with you :
jQuery('div').on('click', function(e) {
e.preventDefault();
jQuery('html,body').animate({scrollTop:jQuery(this.hash).offset().top-100}, 800);
});
note that : this function will aplay on all divs in page
I think there are more than an unique solution. If you don't want to modify your HTML, then you need a condition to determine if the clicked element is an "active" one:
jQuery('div').on('click', function(e) {
var id = $(this).attr('class');
var scrollto = $('#' + id);
if(scrollto.length > 0) {
e.preventDefault();
jQuery('html,body').animate({scrollTop:scrollto.offset().top-100}, 800);
}
});
If you "can" modify your HTML, it's wise to add some attribute to the "active" elements (the ones that are buttons), so you know they scroll the page, or put them inside a container. The attribute you add may be a class or any other valid attribute (I recommend "rel", but might be "data" as spotted by #Iliya Reyzis , who selects by class and scrolls to "data") and select them by it:
<div class="div1" rel="mybutton">div1</div>
jQuery("[rel='mybutton']").on('click', function(e) {
var id = $(this).attr('class');
var scrollto = $('#' + id);
e.preventDefault();
jQuery('html,body').animate({scrollTop:scrollto.offset().top-100}, 800);
});
Hope it helps!!

Append a div outside of the input parent

Im fairly new to javascript and I just can't figure this out despite my attempt in researching. How do I track the change of a input within a div and trigger an append to an outside div? My code goes as follow:
Append h3 with "Pending" once ".image-value" input has a change in value
<!-- APPEND <h3> -->
<h3>Best Overall Costume<div class="pending">Pending</div></h3>
<div>
<div class="select-form">
<img src="images/vote.jpg" data-value="image_value">
<img src="images/vote.jpg" data-value="image_value2">
<img src="images/vote.jpg" data-value="image_value3">
<img src="images/vote.jpg" data-value="image_value4">
<img src="images/vote.jpg" data-value="image_value5">
<!-- Track the change of this input -->
<input type="hidden" class="image-value" name="selected_image" value="">
</div>
</div>
I tried this:
function changeStatus(statusValue) {
$("input",".select-form").val(statusValue).trigger("change");
}
$("input",".select-form").change(function(){
if (!$(this).val()){
$("<div class='pending'>Pending</div>").appendTo($("h3").prev($(this)));
}
});
But that didn't seem to work. Any ideas?
place an empty div where you want your new div and give it an id i.e(<div id='myDiv'><div>) and then append what you want like this.
$( "#myDiv" ).append( "<div class='pending'>Pending</div>" );
You can also check Append Explained
for more explanations.
Thanks.
I've done a couple things here... First, I'm not sure why you had it all in a named function. When you're using event listeners that often isn't necessary.
Then, I don't know what the val check was for, so I reversed it.
Finally, I'm using one(), which only runs once. This case seemed to call for that.
$('.select-form').one('change', 'input', function () {
if ( $(this).val() ) { alert('asdgf');
$("<div class='pending'>Pending</div>")
.appendTo($(this).parent().prev('h3'));
}
});
Fiddle
try this:
$("input",".select-form").on("change", function(){
var $this = $(this);
if (!$this.val()){
var elem = $('<h3>Best Overall Costume<div class="pending">Pending</div></h3>');
$this.parent().parent().before(elem);
}
});
you can also place a check, that if the pending div is already added, not to add it again.
Of course this solution assumes that there are no other nested divs between the target div(before which you want to append) and the input control

multiple classes and id's in jquery not working in safari

The below code is working in firefox and chrome but not in safari. Can anybody tell me if this is the correct way to add multiple classes and id's in jquery?
jquery
$(document).ready(function () {
$('.imgLink, .imgLink1, .imgLink2, .imgLink3, .imgLink4, .imgLink5, .imgLink6,
.imgLink7, .imgLink8, .imgLink9').click(function () {
var imgPath = $(this).attr('href');
$('#theImage, #theImage1, #theImage2, #theImage3, #theImage4, #theImage5, #theImage6,
#theImage7, #theImage8, #theImage9').attr('src', imgPath);
return false;
});
});
html for .imgLink
<a class="imgLink1" href="http://www.customtie.com/images/press/printwear-11-2013.jpg">Printwear Nov 2013</a>
hmtl for #theImage
<img id="theImage" src="http://www.customtie.com/images/press/counselor-2-2014.jpg" alt="" width="auto" height="auto">
Ugh... Classes are not meant to be used that way. Rather:
FOO
BAR
<img id="theImage1" src="images/default.jpg" alt="">
<img id="theImage2" src="images/default.jpg" alt="">
$(function () { // DOM ready shorthand
$('.imgLink').click(function ( e ) {
e.preventDefault();
var imgPath = $(this).attr('href');
var targetID = $(this).data('targetid');
$('#theImage'+ targetID).attr('src', imgPath);
});
});
|→ jsBin demo
So basically you add the same class to all your clickables, and a data-* attribute with the number of the image ID suffix you want to target.
There's also other nice ways (even simpler) to achieve the same, but without seeing some HTML it's blind guessing.
I would first agree with m90's suggestion that you want to just add a single class to all these elements and select off that.
But I would presume that the issue is the carriage return halfway through your string. If you want to start a new line, you have to end the first one and then concatenate them together like this:
$('.imgLink, .imgLink1, .imgLink2, .imgLink3, .imgLink4, .imgLink5, .imgLink6,'+
'.imgLink7, .imgLink8, .imgLink9').click(function () {
var imgPath = $(this).attr('href');
$('#theImage, #theImage1, #theImage2, #theImage3, #theImage4, #theImage5, #theImage6, ' +
'#theImage7, #theImage8, #theImage9').attr('src', imgPath);
return false;
});

jQuery toggle() text in separate element

I am having some trouble getting a toggle function to work and need someone to help explain it to me.
My HTML (simplified):
<div id="filter_names"></div>
<div class="item">Option 1</div>
<div class="item">Option 2</div>
<div class="item">Option 3</div>
<div class="item">Option 4</div>
My jQuery (simplified)
$(".item").click(function(){
var tagname = $(this).html();
$('#filter_names').append(' > '+tagname);
$(".loading").show();
});
As you can see I am appending clicked items' value to the div at the top. This works fine, but i need it to be removed when i click it again.
I am pretty sure it needs a toggle() function but so far my attempts have been pretty fruitless.
Some guidance would be greatly appreciated.
EDIT: You can see what i want to achieve in this JSfiddle. It's working exactly how i want it to by appending a value to the end (like a breadcrumb link), but is not being removed when i click it again.
You need to look at the #filter_names contents and check if the clicked tag's value is already included, then remove it if it is, or add it otherwise:
if (filternames.indexOf(tagname) === -1) {
$('#filter_names').append(' > '+tagname);
} else {
$('#filter_names').text(filternames.replace(' > '+tagname, ''));
}
Working fiddle: http://jsfiddle.net/passcod/Kz3vx/
Note that you might get weird results if one tag's value is contained in another's.
<script type="text/javascript">
$(function(){
$(".item").click(function(){
var $this=$(this);
var tagname = ' > ' +$this.html();
//if has item-check class remove tag from filter_names
if($this.hasClass("item-click")){
var h=$("#filter_names").text();
$("#filter_names").text(h.replace(tagname, '' ));
}
else{
$('#filter_names').append(tagname);
}
$(this).toggleClass("item-click").toggleClass("item");
});
});
</script>
try this one...
$(this).toggleClass("item-click item");
this will add these classes alternatively when you click on div. or if you just want to remove this class on second click then you should write this in your click handler.
if( $(this).hasClass("item-click")){
$(this).removeClass("item-click");
}
EDITED -----
to remove appended html you can try this...
if($(this).hasClass("item-click")){
$("#filter_names").text("");
}
else{
$('#filter_names').append(tagname);
}
it's working HERE
hope this helps you!!
I like passcod's solution - here's an alternative that wraps the elements in divs and puts them in alphabetical order.
JSFiddle here. The sort function is from http://www.wrichards.com/blog/2009/02/jquery-sorting-elements/.
$(".item").click(function(){
var tagname = $(this).html();
var target = $('#filter_names').find('div:contains("> ' + tagname + '")');
if (target.is('*')) {
target.remove();
}
else $('#filter_names').append('<div class="appended"> > '+ tagname +'<div>');
function sortAlpha(a,b) {
return a.innerHTML > b.innerHTML ? 1 : -1;
}
$('#filter_names div').sort(sortAlpha).appendTo('#filter_names');
});

How to detect mouseleave() on two elements at once?

Answer can be in vanilla js or jQuery. I want to hide a div with the id "myDiv" if the user is no longer hovering over a link with the id "myLink" or a span with the id "mySpan". If the user has his mouse over either element "myDiv" will still show, but the second the user is not hover over either of the two (doesn't matter which element the user's mouse leaves first) "myDiv" will disappear from the face of existence.
In other words this is how I detect mouse leave on one element:
$('#someElement').mouseleave(function() {
// do something
});
but how to say (in a way that will actually work):
$('#someElement').mouseleave() || $('#someOtherElement').mouseleave()) {
// do something
});
How to detect this?
Something like this should work:
var count = 0;
$('#myLink, #mySpan').mouseenter(function(){
count++;
$('#myDiv').show();
}).mouseleave(function(){
count--;
if (!count) {
$('#myDiv').hide();
}
});
jsfiddle
You could use a multiple selector:
$("#someElement, #someOtherElement").mouseleave(function() {
// Do something.
});
You can beautifully use setTimeout() to give the mouseleave() function some "tolerance", that means if you leave the divs but re-enter one of them within a given period of time, it does not trigger the hide() function.
Here is the code (added to lonesomeday's answer):
var count = 0;
var tolerance = 500;
$('#d1, #d2').mouseenter(function(){
count++;
$('#d3').show();
}).mouseleave(function(){
count--;
setTimeout(function () {
if (!count) {
$('#d3').hide();
}
}, tolerance);
});
http://jsfiddle.net/pFTfm/195/
I think, it's your solution!!!
$(document).ready(function() {
var someOtherElement = "";
$("#someElement").hover(function(){
var someOtherElement = $(this).attr("href");
$(someOtherElement).show();
});
$("#someElement").mouseleave(function(){
var someOtherElement= $(this).attr("href");
$(someOtherElement).mouseenter(function(){
$(someOtherElement).show();
});
$(someOtherElement).mouseleave(function(){
$(someOtherElement).hide();
});
});
});
----
html
----
<div id="someElement">
<ul>
<li>element1</li>
<li>element2</li>
</ul>
</div>
<div id="tab1" style="display: none"> TAB1 </div>
<div id="tab2" style="display: none"> TAB1 </div>
While the answer from lonesomeday is perfectly valid I changed my html to have both elements in one container. I originally wanted to avoid this hence I had to do more refactoring for my clients in other html templates, but I think it will pay out on the long term.
<div id="my-container">
<div class="elem1">Foo</div>
<div class="elem2">Bar</div>
</div>
$('#my-container').mouseleave(function() { console.log("left"); });

Categories

Resources