I have got this html:
<a style="display:block; padding:100%; text-decoration: none;" href="http://google.com " class="Jasmin" id="target_site_to_visit">
<span data-app-id="88" class="btn" id="visit_site" style="right:22px; top:65px; padding:5px;z-index: -99999;">VISIT SITE</span>
</a>
and this jquery:
(function($){
$('#target_site_to_visit').live('click',function(event){
event.preventDefault();
var appName=$('#target_site_to_visit').attr('class');
$.post('db/update_site_viewed.php',{ name:appName }, function(data){
throw new Error("AppName: "+appName);
},'html').error(function(data){
throw new Error("Error: "+data.responseText);
});
document.location.href=$('#target_site_to_visit').attr('href');
}); })(jQuery);
A problem exists, whenever the button is clicked.. the post method is executed which puts the data into the database. But that only happens when the last line in jquery doesnt exist: document.location.href.. the redirection effects the post somehow..and doesnt probably doesnt give the post method to execute..resulting in no record being inserted to the db (or in other post method doesnt execute).. is it possible that that is the cause..cause the redirection does effect the execution of the post method
This will solve your problem
<script type="text/javascript">
$('#target_site_to_visit').live("click",function(event){
event.preventDefault();
var appName=$('#target_site_to_visit').attr('class');
$.post('db/update_site_viewed.php',{ name:appName }, function(data){
// console.log("AppName: "+appName);
},'html').error(function(data){
// console.log("Error: "+data.responseText);
});
// document.location.href=$('#target_site_to_visit').attr('href');
});
But use .on() instead of .live().LIke
<script type="text/javascript">
$(document).on("click",'#target_site_to_visit',function(event){
event.preventDefault();
var appName=$('#target_site_to_visit').attr('class');
$.post('db/update_site_viewed.php',{ name:appName }, function(data){
// console.log("AppName: "+appName);
},'html').error(function(data){
// console.log("Error: "+data.responseText);
});
// document.location.href=$('#target_site_to_visit').attr('href');
});
</script>
You need to pass the event to listen for (in this case click) to the live method.
$("#somediv").live("click", function () {
console.log("you clicked it");
});
Also, as the other answerer said, you should use on as opposed to live, here is an article that explains why: http://bitovi.com/blog/2011/04/why-you-should-never-use-jquery-live.html
You don't appear to have specified the type of event. It should be 'click', and if my extremely limited knowledge of jQuery syntax is correct, it should be the first parameter before your callback.
To be on the safe side, I like to have any link that is intended to be handled by JavaScript have href="javascript:void(null);". That way, even if the event handler fails to cancel the event, nothing will happen anyway. It's also less confusing for the users to see a JavaScript link in their status bar when you hover over it, than a link to Google.
Related
For a web based project, I am using jQuery. In one part of the code, there is data that gets dynamically added to the screen on the client side based on the activity of other users connected to the server. I want to write a code that will allow me to execute a function when a client clicks on the data.
To elaborate a little bit, there is a list which shows which members are online. When a new client connects, his name is added to the list and all other users can see on their screen that he is online. When another user clicks on his name, he sends a message request.
This is the relevant jQuery code:
$('#inc').append("<br><i onclick='accept()'>"+data.plr+"<i><br>")
And the accept function is defined under this block which is within another function, so like
function a(){
$('#inc')....
}
function accept(){
//...
}
However, when the code runs I get an error which says accept() is not defined
How do I solve this problem?
Maybe you can do it in that way...
$('#inc').append("<br><i>"+data.plr+"<i><br>")
$('#inc i:last-child').click(accept);
I did a small CodePen to let you see the code in action
https://codesandbox.io/embed/frosty-jang-fvk3j
I've always done it this way. I find this easier.
$('#inc').append("<br><i class="child">"+data.plr+"<i><br>")
$('.child').on("click",function(){
//your code here
});
You can do it with this way as well :
jQuery(function(){
click_link = $('<a class="" href="#">Click here</a>');
click_link .bind("click", function(){
alert('DO something');
});
$('.your_dom').append(click_link );
});
Write it using jQuery methods:
var $i = $('<i>').text(data.plr).click(function(event) {
//handle here onClick event
}); //or if you have the function already declared just write .click(accept);
$('#inc').append('<br />', $i, '<br />');
https://api.jquery.com/click/
My question is in two parts. One overall question and one relating to it with explicit code.
The general question:
Is Javascript read into the memory on load, and by this "installed", or is it read each time I do something? How are handlers installed? Once I .click() on an element, is then the handler in memory, including the function inside it? I once had trouble with a .mouseleave(), every time I left the element, the function was installed again and it was absolute chaos...how does this work with .click() then? Is the function then every time read again or does it stay in memory? The solution to the .mouseleave() was: here.
The specific question:
I just found out, that a .click() function I use here runs on first click once, on the second click twice, etc. ? You can see it, when you open the link, open the console and click on an image. Click on it to close it again, then click on ANY(!!) image and it loads as described. Weird, huh? Also it logs in the console the boolean for .data("installed") as true, although the switch to true comes only later in code?
Hope you can help me.
jQuery code:
$('.pfiles').data("installed", false);
if (!$('.pfiles').data("installed")) {
$('.pfiles img').click(function() {
var scroll = $('body').scrollTop(),
imgThis = $(this).attr('src'),
txtThis = $(this).attr('src').split('/')[2].split('.')[0] + ".txt",
$this = $(this),
bigImgH = $(this).height(),
bigImgW = $(this).width();
$('.progress').show();
console.log($('.pfiles').data("installed"));
$('.pfiles').fadeOut(200, function() {
$('.big').fadeIn(400);
$('.frame').height($('.big').height());
});
$.ajax({
type: 'GET',
url: imgThis,
dataType: 'HTML',
success: function(data) {
$('.big').empty().append("<img src='" + imgThis + "'/>");
if (bigImgW / bigImgH <= 1.3529411176) {
$('.big img').css({'height': '100%'});
} else {
$('.big img').css('width', '100%');
}
$('body').scrollTop(0);
$('.big img').click(function(){
$('.big').fadeOut(400, function() {
$('.pfiles').fadeIn(400);
$('body').scrollTop(scroll);
$('.big').empty();
$('.frame').height($('.incontent').height());
});
});
// progress();
}
});
});
$('.pfiles').data("installed", true);
}
"HTML" code
<?php
//Profile catch
$path = 'img/profile';
$profiles = scandir($path);
natsort($profiles);
$profiles = array_reverse($profiles);
$profiles = array_diff($profiles, array('.', '..', '.DS_Store', 'txt'));
?>
<div class="incontent" style="background:white">
<div class="progress">
<div class="bardiv">
<div class="bar"></div>
<p class="bartext text"></p>
</div>
</div>
<div class="big"></div>
<div class="pfiles">
<?php
foreach ($profiles as $pfiles) {
echo '<img onclick="" src="img/profile/'.$pfiles.'">';
}
?>
</div>
I already tried the same trick with the .data(), but it keeps console.logging on every click (even true!) and it is to no avail to the multiple XHR load... (On the server it is without the .data() switch!)
Javascript code in your page is parsed and run at the time the page loads and remains in memory in the browser while the page is active. As the user interacts with the page, any event handlers that your code might have installed are then called upon demand as those events happen.
Once you install a .click() handler, it remains in place for the lifetime of that DOM element or until you remove the click handler. Until you remove it, the click handler will get called every time the item is clicked on.
You should ONLY install a .click() handler for a given function one time. If you install it multiple times, it will be called multiple times when the item is clicked. If your click handler is being called more and more times each time you click it, then your code is apparently installing another click handler each time you click on it and you would need to modify your code not to do that.
To help more specifically, we'd need to know which click handler you're having an issue with and probably need to see some of the relevant HTML.
You can simplify your event handling code by having only one constant event handler for the .big img rather than constantly creating a new one. You can do that with delegated event handling like this:
$(".big").on("click", "img", function() {
$(".big").fadeOut(400, function() {
$('.pfiles').fadeIn(400);
$('body').scrollTop(scroll);
$('.big').empty();
$('.frame').height($('.incontent').height());
});
});
Put this code before any of the code you have in your question so it is initialized once and only once.
Here's a potential problem. At the very beginning of your block of code, you have this:
$('.pfiles').data("installed", false);
if (!$('.pfiles').data("installed")) {
That means that you will ALWAYS execute the if block, even if you previously set the data to true. You can just remove the first line because the default value for $('.pfiles').data("installed") will be falsey. You don't need to initialize it. Then, when this is called subsequent times, it will respect the fact that you've set it to true later in your code.
I have a basic form popup that will display when the button buy now of the main product is clicked with this code: onclick="productAddToCartForm.submit(this)"
and i have related products too in the same page with this main product with exactly the same button, and i want this pop up to be displayed also when it's clicked, and i tried to add onclick="productAddToCartForm.submit(this)" to it too but if i push it the pop up WILL work but will add to the CART both products.
how can i do this?
the code looks like this:
<div style="display: none;" id="ajax-popup">
<span class="button b-close"><span>X</span></span>
<h2 id="ajax-popup-message"></h2>
<div id="ajax-popup-content"></div>
</div>
<script type="text/javascript">
//<![CDATA[
var productAddToCartForm = new VarienForm('product_addtocart_form');
productAddToCartForm.submit = function(button, url) {
if (this.validator.validate()) {
var form = this.form;
var oldUrl = form.action;
if (url) {
form.action = url;
}
var e = null;
// Start of our new ajax code
if (!url) {
url = jQuery('#product_addtocart_form').attr('action');
}
url = url.replace("checkout/cart","ajax/index"); // New Code
var data = jQuery('#product_addtocart_form').serialize();
data += '&isAjax=1';
jQuery('#ajax_loader').show();
try {
jQuery.ajax( {
url : url,
dataType : 'json',
type : 'post',
data : data,
success : function(data) {
jQuery('#ajax_loader').hide();
//alert(data.status + ": " + data.message);
jQuery('#ajax-popup-message').addClass(data.status);
if(jQuery('#ajax-popup')){
jQuery('#ajax-popup-message').html(data.message);
}
if(jQuery('#ajax-popup')){
jQuery('#ajax-popup-content').html(data.sidebar);
}
if(jQuery('.header .links')){
jQuery('.header .links').replaceWith(data.toplink);
}
jQuery('#ajax-popup').bPopup();
}
});
} catch (e) {
}
// End of our new ajax code
this.form.action = oldUrl;
if (e) {
throw e;
}
}
}.bind(productAddToCartForm);
productAddToCartForm.submitLight = function(button, url){
if(this.validator) {
var nv = Validation.methods;
delete Validation.methods['required-entry'];
delete Validation.methods['validate-one-required'];
delete Validation.methods['validate-one-required-by-name'];
// Remove custom datetime validators
for (var methodName in Validation.methods) {
if (methodName.match(/^validate-datetime-.*/i)) {
delete Validation.methods[methodName];
}
}
if (this.validator.validate()) {
if (url) {
this.form.action = url;
}
this.form.submit();
}
Object.extend(Validation.methods, nv);
}
}.bind(productAddToCartForm);
//]]>
</script>
HTML looks like this:
<div class="main">
<div class="first">
<div class="add-to-cart">
<img onclick="productAddToCartForm.submit(this)" title="Add to Cart" src="../images/add-to-cart.png">
</div></div>
//STUFF
<div class="second">
<button onclick="window.location='URL'; productAddToCartForm.submit(this)" class="form-button add-to-cart" type="button"></button></div>
</div>
The root of your issue is, from what I can see from your example, that you are calling the form submission function twice. It appears that the second onclick had debug code with the window.location left in it when you pasted it here, of which is, what I can only determine from your description, the popup window markup that causes an endless loop of submitting items to the cart.
Firstly you're using jQuery to make programming with Javascript easier, get rid of the onclick= DHTML events in your html and use jQuery.
then add
jQuery(document).ready(function(){
jQuery('.add-to-cart').click(function(e){
e.preventDefault();
productAddToCartForm.submit(this);
});
});
Secondly there's no reason to wrap jQuery.ajax in a try catch, it has it's own error processing functionality. Unless you believe something would be wrong with jQuery's ajax function. Otherwise if you are trying to catch errors within the success method, you need to place the code inside the success method.
Think of ajax as a completely separate browser being opened up the instant it is executed.
Here's an example of what I am referring to: http://jsfiddle.net/73gpC/1/
Here's an example of an error method:
jQuery.ajax({
error: function(jqXHR, text, errorThrown){
if(errorThrown){
alert('Error: ' + errorThrown);
}
}
});
Next you have already declared the form with var form = this.form;, why search the DOM for it again?
jQuery('#product_addtocart_form').serialize();
should be form.serialize();
Every time you execute jQuery('selector'), jQuery "searches" for the element within the DOM.
While it sounds okay at first, as you begin dealing with more complex applications it is extremely slow to do things this way while the user interacts with your application.
It is much faster to use the declared variable instead since you already found it. With that said always favor ID's over class names as they are much faster to find but require valid HTML (ID's are unique and can not be reused).
From the look of it <button onclick="window.location='URL'; productAddToCartForm.submit(this)" is just completely broken and you are expecting it do something it simply won't because window.location='URL' is going to redirect the users browser to 'URL' when they click it and productAddToCartForm.submit(this) will never execute.
Example: http://jsfiddle.net/CZqDL/
No alert box will be displayed on click, indicating the function never fired.
I am all for helping someone learn how to figure out an issue if I am able, but this is really beyond your experience level with Javascript or jQuery in general.
I suggest getting a jQuery programming book or hiring a developer to program it correctly.
Especially seeing as how VarienForm is a part of Magento, which should be listed in your tags, which is an eCommerce application.
If you're just learning I suggest reaching out on the jQuery or Magento forums on how to use the applications or possibly for training.
Otherwise you will lose customers, get incorrect orders, or possibly be sued or arrested (depending on if you are processing credit cards) should your form mess up due to poor programming practices.
There are many websites where you can hire a freelancer to do just what you need for very low costs and avoid the hassles.
After the request, the new elements created are not recognized by the event handlers in my jQuery code.
Is there a way to reload the file to re-register these events?
I'm assuming that you mean that events you've registered for elements that have been replaced by with the results of your ajax requests aren't firing?
Use .live() (see http://api.jquery.com/live/) to register the events against elements that the match the selector (including the new DOM elements created from the results of the ajax), rather than the results of the selector when the event handlers were first, which will be destroyed when they are replaced.
e.g.
replace
$('div.someClass').click(function(e){
//do stuff
});
with
$('div.someClass').live('click', function(e){
//do stuff
});
Important:
While I've recommended using .live() this is for clarity as its syntax is similar to .bind(), you should use .on() if possible. See links in #jbabey's comment for important information.
This question was about binding event handler on DOM element created after the loading of the page. For instance, if after a request ajax you create a new <div> bloc and want to catch the onClick event.
//This will work for element that are present at the page loading
$('div.someClass').click(function(e){
//do stuff
});
// This will work for dynamically created element but is deprecated since jquery 1.7
$('div.someClass').live('click', function(e){
//do stuff
});
// This will work for dynamically created element
$('body').on('click', 'div.someClass', function(e){
//do stuff
});
You would find the documentation here: http://api.jquery.com/on/
This codes works perfect for me..
$("head script").each(function(){
var oldScript = this.getAttribute("src");
$(this).remove();
var newScript;
newScript = document.createElement('script');
newScript.type = 'text/javascript';
newScript.src = oldScript;
document.getElementsByTagName("head")[0].appendChild(newScript);
});
It removes the old script tag and make a new one with the same src (reloading it).
To increase the website performance and reduce the total file’s size return, you may consider to load JavaSript (.js) file when it’s required. In jQuery, you can use the $.getScript function to load a JavaScript file at runtime or on demand.
For example,
$("#load").click(function(){
$.getScript('helloworld.js', function() {
$("#content").html('Javascript is loaded successful!');
});
});
when a button with an Id of “load” is clicked, it will load the “helloworld.js” JavaScript file dynamically.
Try it yourself
In this example, when you clicked on the load button, it will load the “js-example/helloworld.js” at runtime, which contains a “sayhello()” function.
<html>
<head>
<script type="text/javascript" src="jquery-1.4.2.min.js"></script>
</head>
<body>
<h1>Load Javascript dynamically with jQuery</h1>
<div id="content"></div>
<br/>
<button id="load">Load JavaScript</button>
<button id="sayHello">Say Hello</button>
<script type="text/javascript">
$("#load").click(function(){
$.getScript('js-example/helloworld.js', function() {
$("#content").html('
Javascript is loaded successful! sayHello() function is loaded!
');
});
});
$("#sayHello").click(function(){
sayHello();
});
</script>
</body>
</html>
In your request callback, call a function that acts on your newly appended or created blocks.
$.ajax({
success: function(data) {
$('body').append(data);
//do your javascript here to act on new blocks
}
});
simple way to solve this problem
$(document).ready(function(){
$('body').on('click','.someClass',function(){
//do your javascript here..
});
});
You can also attach the click handlers to the body so that they never get destroyed in the first place.
$('body').on('click', 'a', function(event) {
event.preventDefault();
event.stopPropagation();
// some stuff
})
var scripts = document.getElementsByTagName("script");
for (var i=0;i<scripts.length;i++) {
if (scripts[i].src)
if(scripts[i].src.indexOf('nameofyourfile') > -1 )
var yourfile = scripts[i].src;
}
jQuery.get(yourfile, function(data){
if(data){
try {
eval(data);
} catch (e) {
alert(e.message);
}
}
});
You can try loadscript plugin for loading the javascript file.
forexample
$("#load").click(function(){
$.loadScript('path/example.js');
});
or
$.ajax({
success: function(data) {
$.loadScript('path/example.js');
}
});
http://marcbuils.github.io/jquery.loadscript/
What do you mean not recognized by jQuery?
jQuery walks the DOM each time you make a request, so they should be visible. Attached events however will NOT be.
What isn't visible exactly?
P.S.: Reloading JavaScript is possible, but highly discouraged!
I have lots of jquery functions in my script but a particular one is not working, this is my function
$('#delete').click(function() {
var id = $(this).val();
$.ajax({
type: 'post',
url: 'update.php',
data: 'action=delete&id=' + id ,
success: function(response) {
$('#response').fadeOut('500').empty().fadeIn('500').append(response);
$(this).parent('tr').slideUp('500').empty();
}
});
});
a similar function like this is working
<!-- WORKING FUNCTION -->
$('#UpdateAll').click(function() {
$.ajax({
type: 'post',
url: 'update.php',
data: 'action=updateAll',
success: function(response) {
$('#response').fadeOut('500').empty().fadeIn('500').append(response);
$('#table').slideUp('1000').load('data.php #table', function() {
$(this).hide().appendTo('#divContainer').slideDown('1000');
});
}
});
});
I checked with firebug, the console doesnt show any errors, i checked html source the values are loading correct, i checked my php file 5times it is correct can't figure out the problem. Please Help.
I struggled with the EXACT SAME PROBLEM for 6hr straight! the solution was to use jquery 'live'.
And that is it.
$('#submit').live('click',function(){
...code...
});
With the first one, I'd put a quick and nasty alert() within the click anonymous function, to ensure that it is being fired. Eliminate reasons why it may not be working. Also, try using Live HTTP headers or Firebug's console to see if the AJAX request is being sent.
If the click is not being fired, see if you have the selector correct. I often do this (quite nasty)
var testSelector = 'p:first ul li:last';
$(testSelector).css( { border: '1px solid red' } );
It won't always be visible, but if you see style="border: 1px solid red"` in the generated markup, you know your selector is on the ball.
Perhaps you have another click that is overwriting it? Try using
$('#delete').bind('click', function() {
// do it
});
I just had the same problem with a quick example I was working on. The solution was to put the click inside $(document).ready. I was trying to use my element before it was actually ready to be used.
It's basic JavaScript to wait until the DOM is ready before you try to use an element, but... for whatever reason I forgot to do that, so maybe the same happened to you.
$(document).on('click', '#selector', function(){
// do something
});
jQuery 1.7+ has depreciated .live() and now uses .on() instead :)
I don't know if this applies in your context, but if you have parts of the page that are getting loaded by AJAX then you'll need to bind the click handlers after that content is loaded, meaning a $(document).ready isn't going to work. I've run into this problem a number of times, where certain events will fire fine until parts of the page are reloaded, then all the sudden the events seem to stop firing.
Just use your .click with $(document).ready(function(){ ... }); because you are trying to apply the click event on a non-existent element.
1) just before the last }); you should add return false;
2) Are you sure that #delete exists? Also, are you sure is UNIQUE?
This is a long shot, but it's good to be aware of.
http://code.google.com/p/fbug/issues/detail?id=1948
May not be an issue if you're not on Firefox 3.5.
Instead of id=delete i changed it to class=delete in html and in js ('.delete') and it is working fine now but when again tried with id it doesnt work.
Thank You all for Help, i dont have any problem whether it is id or class just the function works now.
There is few things you can do:
like Elmo Gallen and Shooz Eh suggested, put your code in $(document).ready(function(){...});
code your $('#delete').click(function(){...}); event handling AFTER your <button> tag,
use $('#submit').live('click',function(){...}); like Parikshit Tiwari suggested.
Everyone of these should work ok.
EDIT: oops, didn't see that this was asked '09 :D
I think you must use .on() function for dynamically code run in jQuery like this:
$(document).on("click","#delete",function(){ });