WooCommerce global.js doesn't work after update cart - javascript

I write personnal javascript in global.js, and it work until I click on the WooCommerce button update_cart.
After my function doesn't work.
The function is for update notification display :
$('#nb_article').change(function() {
if ($('#nb_article').text() = 0) {
$('#nb_article').css("display", "none");
} else {
$('#nb_article').css("display", "block");
}
});
and it's in balise jQuery(document).ready(function($) {}.
Do you know what can I do ?

The update cart action is triggered on woocommerce/assets/js/frontend/cart.js, look for update_cart: function() {
It makes a ajax call to the url of form and then update the .woocommerce div with the html returned by ajax call. So, it doesn't work maybe because $('#nb_article') is inside .woocommerce and the plugin will replace all html, losing the events. You should reapply the event handler after update.
Or in alternative, you can apply the event by delegation, in this way:
$('.woocommerce').on( 'change', '#nb_article', function() {
var $nb_article = $(this);
if ( $nb_article.text() == 0) {
$nb_article.css("display", "none");
} else {
$nb_article.css("display", "block");
}
});

There are two issues:
inside event function, you have to use $(this) so you can refer to element that triggers the event
in the if statement you have to use the compare operator == instead of =
So the final results should be:
$('#nb_article').change(function() {
var $nb_article = $(this);
if ( $nb_article.text() == 0) {
$nb_article.css("display", "none");
} else {
$nb_article.css("display", "block");
}
});
They are surely issues, but I don't know if there is something other related to other code of your project.
I hope it helps

Related

Checking Id of clicked element

I have several images with the same class and would like to set up a click function that changes the text in some elements based on which image is clicked.
My if statement is not working, I'm not entirely sure why because I've used this method before, or so I thought.
$('.gallery_image').click(function(e) {
var t = $(this);
if(t.id == 'csf') {
console.log('It works!');
}
});
JSFIDDLE
Use t.attr('id') instead of t.id
More about .attr()
An alternate solution is using classes instead of id's. Call the click function on the class they share then use a second class to distinguish them with the hasClass function:
<div id="csf" class="gallery_image csf">csf</div>
<div id="csi" class="gallery_image csi">csi</div>
$('.gallery_image').click(function(e) {
var t = $(this);
if(t.hasClass('csf')) {
alert("It works!");
}
else if(t.hasClass('csi')) {
alert("So does this!");
}
});

Jquery - wrapping a bind function to THIS elements

I have multiple tables on a page (there will be over 100) and I want to use one function for all of them. When the user selects "Custom" in the drop-down menu, additional questions apply TO ALL OF THEM. How do I wrap my function in a THIS statement to have it only added to that individual table. I apologize in advance for my description of the issue.
$(document).ready(function(){
$('td.additional_content').css('visibility', 'hidden');
$('#srds_mapping').bind('change', function (e) {
if( $('#srds_mapping').val() == 'Custom') {
$('td.additional_content').css('visibility', 'visible');
$('td.additional_content .custom').show();
} else {
$('td.additional_content').css('visibility', 'hidden');
$('td.additional_content .custom').hide();
}
}).trigger('change');
});
It is better explained by looking at it
http://jsfiddle.net/2Q7J7/2/
this is the targetted element inside the event handler:
$('#srds_mapping').bind('change', function (e) {
if( $(this).val() == 'Custom') { // traverse to find the target input element
Note that you should not use more than one ID on the page. Use classes or other selectors instead, f.ex:
$('select').bind('change', function (e) {
if( $(this).val() == 'Custom') {
jQuery .each() function would be a good option:
Assuming $('#srds_mapping') is your table. Firstly, instead of id you could add a class to the tables. For example <table id="srds_mapping" class="srds_mapping"></table>. After that is in place you could do something like this.
$('.srds_mapping').each(function(){
$(this).bind('change', function (e) {
// other function stuff
}).trigger('change');
});
Also, this thread may be worth a read, or something to think about.

Intercept clicks, make some calls then resume what the click should have done before

Good day all, I have this task to do:
there are many, many many webpages, with any kind of element inside, should be inputs, buttons, links, checkboxes and so on, some time there should be a javascript that could handle the element behaviour, sometimes it is a simple ... link.
i have made a little javascript that intercepts all the clicks on clickable elements:
$( document ).ready(function() {
$('input[type=button], input[type=submit], input[type=checkbox], button, a').bind('click', function(evt, check) {
if (typeof check == 'undefined'){
evt.preventDefault();
console.log("id:"+ evt.target.id+", class:"+evt.target.class+", name:"+evt.target.name);
console.log (check);
$(evt.target).trigger('click', 'check');
}
});
});
the logic is: when something is cllicked, I intercept it, preventDefault it, make my track calls and then resme the click by trigger an event with an additional parameter that will not trigger the track call again.
but this is not working so good. submit clicks seams to work, but for example clicking on a checkbox will check it, but then it cannot be unchecked, links are simply ignored, I track them (in console.log() ) but then the page stay there, nothing happens.
maybe I have guessed it in the wrong way... maybe i should make my track calls and then bind a return true with something like (//...track call...//).done(return true); or something...
anyone has some suggestions?
If you really wanted to wait with the click event until you finished with your tracking call, you could probably do something like this. Here's an example for a link, but should be the same for other elements. The click event in this example fires after 2seconds, but in your case link.click() would be in the done() method of the ajax object.
google
var handled = {};
$("#myl").on('click', function(e) {
var link = $(this)[0];
if(!handled[link['id']]) {
handled[link['id']] = true;
e.preventDefault();
e.stopPropagation();
//simulate async ajax call
window.setTimeout(function() {link.click();}, 2000);
} else {
//reset
handled[link['id']] = false;
}
});
EDIT
So, for your example, this would look something like this
var handled = {};
$( document ).ready(function() {
$('input[type=button], input[type=submit], input[type=checkbox], button, a').bind('click', function(evt) {
if(!handled[evt.target.id]) {
handled[evt.target.id] = true;
evt.preventDefault();
evt.stopPropagation();
$.ajax({
url: 'your URL',
data: {"id" : evt.target.id, "class": evt.target.class, "name": evt.target.name},
done: function() {
evt.target.click();
}
});
} else {
handled[evt.target.id] = false;
}
});

how to apply function to each checkbox on page?

I am trying to apply a function to every checkbox on a page that shows/hides <div class="selectlist"> depending on if the checkbox is checked, this function makes all the <div class="selectlist"> on the page toggle
$("input[type=checkbox]").live('change', function() {
if ($(this).is(':checked') == false) {
$('#selectlist').hide();
} else {
$('#selectlist').show();
}
});
I tried the jquery each function like this but that doesnt seem to work
$.each($("input[type=checkbox]").live('change', function() {
if ($(this).is(':checked') == false) {
$('#selectlist').hide();
} else {
$('#selectlist').show();
}
}));
I know its possible to this by using a class instead of input[type=checkbox] but I want to avoid doing that
How can I make jquery change the behavior of the checkbox the user clicks?
If you're trying to bind an event handler to all elements verifying input[type=checkbox], simply do
$(document).on('change', "input[type=checkbox]", function() {
if (!this.checked) {
$('#selectlist').hide();
} else {
$('#selectlist').show();
}
});
No need to use each there : most jQuery functions work if the jQuery set contains more than one element.
Note that I use on there instead of live : after having been deprecated for a long time, live has been removed from recent versions of jQuery.
EDIT : discussion in comments below lead to this code :
$(document).on('change', "input[type=checkbox]", function() {
$(this).next().toggle(this.checked);
});
$(document).on('change', 'input[type=checkbox]', function() {
$('#selectlist').toggle(this.checked);
});
ID's are uniqe, and there is no "all the <div id="selectlist"> on the page toggle", there can be only one? Use a class instead, and show us what the markup looks like !

jQuery .load() How to prevent double loading from double clicking

I am using jQuery load() function to load some pages into container. Here is the code:
$('div.next a').live('click',function() {
$('.content').load('page/3/ #info','',function(){
//do something
});
return false;
});
Everything works just fine but the problem is when I quickly double click the div.next link, from console I see that it loads the page twice because I did a quick double click. I could even make it 3 clicks and it will load it 3 times and show in console smth like that:
GET http://site/page/3/ 200 OK 270ms
GET http://site/page/3/ 200 OK 260ms
My question is how to prevent such double clicking and not to let load the target page more then once no matter how many times it was clicked.
Thank you.
Whatever happened to good ol' JavaScript? Why are you all trying to figure it out with pure jQuery?
var hasBeenClicked = false;
$('div.next a').live('click',function() {
if(!hasBeenClicked){
hasBeenClicked = true;
$('.content').load('page/3/ #info','',function(){
//do something
//If you want it clickable AFTER it loads just uncomment the next line
//hasBeenClicked = false;
});
}
return false;
});
As a side note, never never never use .live(). Use .delegate instead like:
var hasBeenClicked = false;
$('div.next').delegate('a','click',function() {
if(!hasBeenClicked){
hasBeenClicked = true;
$('.content').load('page/3/ #info','',function(){
//do something
//If you want it clickable AFTER it loads just uncomment the next line
//hasBeenClicked = false;
});
}
return false;
});
Why? Paul Irish explains: http://paulirish.com/2010/on-jquery-live/
To answer your comment...
This could happen if you have your delegate function nested inside your AJAX call (.load(), .get(), etc). The div.next has to be on the page for this to work. If div.next isn't on the page, and this isn't nested, just do this:
$('#wrapper').delegate('div.next a','click',function() {
http://api.jquery.com/delegate/
Delegate needs the selector to be the parent of the dynamically added element. Then, the first parameter of delegate (div.next a in the last example) is the element to look for within the selected element (#wrapper). The wrapper could also be body if it's not wrapped in any element.
You could try using the jquery one method:
$("a.button").one("click", function() {
$('.content').load('page/3/ #info','',function(){
//do something
});
});
You could unbind the click event with die():
$(this).die('click').click(function() { return False; });
Or you could give the element a .clicked class once it is clicked:
$(this).addClass('clicked');
And check if that class exists when performing your logic:
$('div.next a').live('click',function() {
if (!$(this).is('.clicked')) {
$(this).addClass('clicked');
$('.content').load('page/3/ #info','',function(){
//do something
});
}
return false;
});
Store whether you're waiting for the load in a variable.
(function() {
var waitingToLoad = false;
$('div.next a').live('click',function() {
if (!waitingToLoad) {
waitingToLoad = true;
$('.content').load('page/3/ #info','',function(){
waitingToLoad = false;
//do something
});
}
return false;
});
})()

Categories

Resources