Weird problem with JavaScript/jQuery which get fixed using alert() - javascript

Here's my code:
$('ul.container_12 li ul li div ul li.icon_export').click(function (e) {
e.preventDefault();
var anchorHrefValue2 = $('a', this).attr('href');
var mycat2 = $(this).parents('li.current').attr('class').split(' ')[0];
window.location = anchorHrefValue2+"?active="+mycat2;
});
When I click menu in Firefox seems like variable anchorHrefValue2 is undefined, if I add alert('somthing'); between lines 3 and 4 anchorHrefValue2 returns the right value and mycat2 returns the value menu! Which I don't know where the hell it comes from.
both variables has been set correctly but not together.
Both return the right value using alert(); but seems to be undefined calling in the line: window.location=...;.
If anyone has experienced anything close to this, please share. I've tested this in different browsers with JavaScript enabled.
By the way, I have another function like this for parent menus with the same goal which works just fine(only selectors are different with the first one):
$('ul.container_12 li ul li').click(function (e) {
e.preventDefault();
var anchorHrefValue = $('a', this).attr('href');
var mycat = $(this).parent().parent().attr('class').split(' ')[0];
window.location = anchorHrefValue+"?active="+mycat;
});

When I had a similar weird bug that went away when I added an alert box, it turned out that the same event (a div losing focus) was triggering two different javascripts. (I guess adding the alert gave one script a chance to complete before the other was triggered). So asynchronous behaviour as CamelCamelCamel said above, but you can get (unwanted) asynchronous behaviour even if there is no server-side code. Hope that helps someone out.

ul.container_12 li ul li div ul li.icon_export
This is a very long and very specific selector, if you change your HTML code only a little, this selector will break. Try simplifying it. To me it seems that .container_12 .icon_export would work as well.

Related

Why does jQuery.remove() remove mousedown listener from other div element?

I'm working on a HTML5 friendly drag and drop system and I've encountered another mystery that seems to make no sense...
The system is working in Edge - it's when I'm emulating IE8 that I encounter this latest problem.
I have a set of '.draggable' divs that get the following listener attached:
$(document).ready(function() {
$('#reset-button').click(resetDraggables);
if (!dragAndDropSupported()) {
var $draggables = $('.draggable');
$draggables.each( function (index) {
$(this).mousedown( jQueryStartDrag );
});
}
}
The draggables can be sent back to their original locations by hitting a 'reset' button. That all works fine.
The problem is - any divs that get sent back to their origins are no longer draggable. Even if I re-attach the listener in the reset function, it does not fire. Once again, this issue is only happening when I'm emulating IE8 and I don't remove the listener anywhere in my code.
function resetDraggables() {
if ( !$('#reset-button').hasClass('inactive') ) {
var $dropTargets = $('.drop-target');
$dropTargets.each(function (index) {
var draggableId = $(this).attr('data-contains');
var $originDraggable = $('#' + draggableId);
if ($originDraggable.attr('id')!=undefined) {
var $droppedDraggable = $(this).find('.draggable');
$droppedDraggable.remove();
$originDraggable.removeClass('inactive').addClass('draggable').attr('draggable', 'true').css('filter', 'alpha(opacity=100)').hide().fadeIn('fast');
$('#' + draggableId).mousedown( jQueryStartDrag );
$(this).removeClass('occupied').attr('data-contains', '');
$('#reset-button').addClass('inactive');
}
});
}
}
I've realised it's the $droppedDraggable.remove() line that's causing the problem. I'm not sure why a line to remove ONE object would remove the listener from another. The $droppedDraggable object was cloned from the other; Is that causing the issue?
Any ideas what might be going on?
OK, so I replaced the jQuery remove() lines with...
var droppedDraggable = document.getElementById('dropped-' + draggableId);
droppedDraggable.outerHTML = "";
...and that has done the trick. I'm guessing there must have been some hidden association made between the objects when one was cloned from the other and remove()ing one removed the mousedown listener from the other.
If anyone has a better theory, feel free to let me know, but this seems to have solved the problem.
Edit
I've just realised the above fixed the problem in IE8, but not in 9. Great! If anyone has any pointers on how NOT to include a bunch of browser-specific work arounds in my code, I'd be very keen to hear them. Thanks.

Problems with jQuery Hide/Show

I'm having a few problems with a hide/show function in jQuery that I can't seem to figure out. I have a if/else statement which is checking against a data attribute in my HTML, it's then hiding/showing the element based on the results of it. I've been able to log the entire function and it's triggering the correct statements when they are supposed to, but the problem I'm having is getting the content to reappear again after it was hidden. It hides properly, but never comes back. Here is the code:
var bar = $("#alert");
if (!supressed) {
bar.animate({height:0});
bar.parent().animate({height:0}, function() {
$(this).hide()
});
}
if (supressed) {
console.log("Supressing");
bar.replaceWith(newBar);
bar.parent().animate({height: "45px"}, function() {
$(this).show()
});
bar.animate({height: "45px"});
}
The problem is occuring where the console.log("Supressing"); statement is. It logs it to the console so I know it's working, but for some reason the bar is not appearing at all.
If I do an inspect element I can still see that the parent of #alert still has style="height: 0px; display: none;" on it.
Where am I going wrong?
The problem is you're using the replaceWith function (first line after the else statement). Then you call bar.parent() after the element has been removed from the DOM.
Maybe you meant to say
newBar.parent().animate({height: "45px"}, function() {
$(this).show()
});

Is there an alternative to indexOf for jQuery?

I'm in the process of refining a translation script, and the script itself actually works fine (on most computers). We've found that the script does not work correctly on computers where the native language is not English.
The script is as follows:
$('.translation-links a').click(function(e) {
e.preventDefault();
var lang = $(this).data('lang');
$('#google_translate_element select option').each(function(){
if($(this).text().indexOf(lang) != -1) {
$(this).parent().val($(this).val());
var container = document.getElementById('google_translate_element');
var select = container.getElementsByTagName('select')[0];
triggerHtmlEvent(select, 'change');
}
});
});
The .translation-links a would be something like:
<li><span class="south-africa"></span>Afrikaans</li>
The line with the problem is
if($(this).text().indexOf(lang) != -1) {
We've narrowed it to that line through troubleshooting, but we're wondering if there is another way to write it to possibly prevent the issue. Maybe an alternative to indexOf? We're not sure exactly why the native language matters, so if somebody has some insight into that as well we'd appreciate it!
It seems that you should be looking for a match between the clicked elements' data-lang string and an option's value, both of which should be immune to translation.
If so, then it should be as simple as :
$('.translation-links a').on('click', function(e) {
e.preventDefault();
$('#google_translate_element select').eq(0).val($(this).data('lang')).trigger('change');
});

jQuery slideToggle for multiple divs

What I am trying to do is have four links that each will display and hide a certain div when clicked. I am using slideToggle and I was able to get it to work with really sloppy and repetitive code. A friend of mine gave me a script he used and I tried it out and finally was able to get something to happen. However, all it does is hide the div and wont redisplay. Also it hides all the divs instead of just the specific one. Here is a jsfiddle I made. Hopefully you guys can understand what I am trying to do and help! Thanks alot.
Here is the script I'm using.
$(document).ready(function () {
$(".click_me").on('click', function () {
var $faq = $(this).next(".hide_div");
$faq.slideToggle();
$(".hide_div").not($faq).slideUp();
});
});
http://jsfiddle.net/uo15brz1/
Here's a link to a fiddle. http://jsfiddle.net/uo15brz1/7/
I changed your markup a little, adding id attributes to your divs. The jquery, gets the name attribute from the link that's clicked, adds a # to the front, hides the visible div, then toggles the respective div. I also added e.preventDefault to stop the browser from navigating due to the hash change. As an aside, javascript don't require the $ prefix.
$(document).ready(function () {
$(".click_me").on('click', function (e) {
e.preventDefault();
var name = $(this).attr('name');
var target = $("#" + name);
if(target.is(':visible')){
return false; //ignore the click if div is visible
}
target.insertBefore('.hide_div:eq(0)'); //put this item above other .hide_div elments, makes the animation prettier imo
$('.hide_div').slideUp(); //hide all divs on link click
target.slideDown(); // show the clicked one
});
});
Welcome to Stack Overflow!
Here's a fiddle:
http://jsfiddle.net/uo15brz1/2/
Basically, you need a way to point to the relevant content <div> based on the link that's clicked. It would be tricky to do that in a robust way with your current markup, so I've edited it. The examples in the jquery documentation are pretty good. Spend some time studying them, they are a great way to start out.

for loop vs forEach in JavaScript -- example from book

I am currently learning JavaScript using O'Reilly's "Learning Web Application Development". In the example, we are constructing a website using HTML and CSS, which includes 3 tabs which should be able to be selected and become the "active" tab. The books claims that the following two ways of writing the tab code are equivalent:
1)
var main = function() {
"use strict";
var tabNumber;
for (tabNumber=1;tabNumber<=3;tabNumber++) {
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$(tabSelector).on("click",function() {
$(".tabs span").removeClass("active");
$(tabSelector).addClass("active");
$("main .content").empty();
return false;
});
}
}
$(document).ready(main);
2)
var main = function() {
"use strict";
$(".tabs a span").toArray().forEach(function(element) {
$(element).on("click", function() {
console.print("this element: " + element);
$(".tabs span").removeClass("active");
$(element).addClass("active");
$("main .content").empty();
return false;
});
});
}
$(document).ready(main);
However, they do not output the same result. The version using forEach works correctly, so that when I click one of the tabs the attention moves to that tab and it becomes highlighted. However, in the version using a for loop, whenever I click any tab, the attention always moves to the last tab. To confirm what is happening, I printed out the name of the element inside the event listener with both methods, using 3 tabs total. And using the for loop, no matter which tab I click I am getting a response of
"this element: .tabs a:nth-child(3) span"
Could someone please help me explain why this is happening? Why is the output different using for or forEach? And why, using for, is it always passing the last element of tabs to the event listener?
Looks like there's a problem here:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$tabSelector.on("click",function(){
You've created a variable that doesn't have the $ at the beginning, then attached the event to a variable (not sure what it would refer to) with a $ at the beginning.
It should be changed to this, I believe:
$(tabSelector).on("click",function(){
In the for loop solution, you are setting tabSelector multiple times like so:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
This selector is, in the end, going to be set to the last tabNumber, which is always going to be called when you make a reference to it:
$(tabSelector).addClass("active");
To avoid that, replace it by this, which will be different for each of them:
$(this).addClass("active");
JS Fiddle Demo

Categories