JavaScript: How stop a function which is started with $(function(){}) - javascript

I created a function and then called this function when the page loads, also I need call same the function, but without it existing twice. I want it to just stop from $(function(){}) and call again when an element is clicked on.
function myfunction(){
console.log('message');
}
$(function(){
myFunction();
$('#id').click(function(){
...some code here ...
myFunction();
});
})
When page is loaded the console gives me: "message" - it's ok, but when click on #id then I get this message twice, if again then 3 times;
Here my code
function select_cta(){
$('.cta-id').click(function(){
console.log('-');
$('.cta-id').removeClass('active');
$(this).addClass('active');
var cta_arr = parseInt($(this).attr('id').replace('cta-button-', ''))-1;
$('.cta-image').fadeOut(300).removeClass('active');
$('#'+$(this).attr('id').replace('cta-button', 'cta-image')).fadeIn(300).addClass('active');
if(cta_data[cta_arr]){
$('.cta-actions #cta_id').val(cta_data[cta_arr].id);
}
else{
$('.cta-actions #cta_id').val('');
};
if(cta_data[cta_arr]){
$('.cta-actions #cta_link').val(cta_data[cta_arr].link);
}
else{
$('.cta-actions #cta_link').val('');
};
});
}
$(function(){
select_cta();
$('.add-new-cta').click(function(){
var new_tab = parseInt($(this).prev().attr('id').replace('cta-button-',''))+1;
$(this).before('<div id="cta-button-'+new_tab+'" class="cta-btn cta-id empty" style="display:none;"><span>'+new_tab+'</span><span class="onair">ON</span></div>');
$('#cta-button-'+new_tab).fadeIn(300);
$('.cta-images').append('<div id="cta-image-'+new_tab+'" class="cta-image " style="display:none"><img src="/assets/images/page/placeholder_cta.gif"></div>');
select_cta();
})
});

Your problem that every call to select_cta adds another handler to each of the elements. They all would be executed when the click event fires. Two solutions:
Unbind the event handlers from all elements before you re-add them. To do so, begin the function select_cta with $('.cta-id').off("click").on("click", function(){…
Better: use event delegation:
jQuery(function($){
function getIdNumber($el) {
return parseInt($el.prop('id').replace(/\D/g, ''), 10);
}
var $active = $('.cta-id.active'),
$activeImg = $('.cta-image.active')
$(document).on("click", '.cta-id', function(e) {
$active.removeClass('active');
$active = $(this).addClass('active');
var num = getIdNumber($active);
$activeImg.fadeOut(300).removeClass('active');
$activeImg = $('#cta-image'+num).fadeIn(300).addClass('active');
var cta_arr = num - 1;
if(cta_arr in cta_data) {
$('#cta_id').val(cta_data[cta_arr].id);
$('#cta_link').val(cta_data[cta_arr].link);
} else {
$('#cta_id').val('');
$('#cta_link').val('');
}
});
$('.add-new-cta').click(function(e) {
var $this = $(this),
new_tab = getIdNumber($this.prev())+1,
new_button = $('<div id="cta-button-'+new_tab+'" class="cta-btn cta-id empty" style="display:none;"><span>'+new_tab+'</span><span class="onair">ON</span></div>');
$this.before(new_button);
new_button.fadeIn(300);
$('.cta-images').append('<div id="cta-image-'+new_tab+'" class="cta-image " style="display:none"><img src="/assets/images/page/placeholder_cta.gif"></div>');
})
});

Related

dynamic attachment of event handler not working

I was just trying a small experiment in js. It's something like this; I have a ul and below that about 5 li, now I attach an event handler for click on the 1st li , using a selector like below:
var elem = $('ul li:nth-child('+ i +')');
Now I add the function funk, like so:
var funk = function() {
return i < 5 ? i++ : i = 0 ;
}
Now what I want to happen is once the first li is clicked, I want the event handler to be attached to the next li, and when I click on the li, the click event should be attached to the li after that and so on ...
Now I have written the following code so far:
var i = 0;
$('document').ready(function(){
str = funk();
console.log(str);
var elem = $('ul li:nth-child('+ i +')');
elem.on('click' , function(){
console.log('logged');
funk();
});
});
var funk = function() {
return i < 5 ? i++ : i = 0 ;
}
Now there are some obvious errors in the code that I am not able to iron out, for some reason the funk() function itself does't function as the I is never incremented.
Can somebody help me attach a dynamic event handler?
FIDDLE HERE
Ae-x.
Your code is correct, the problem is with declaration. Move func definition before it gets called.
The problem is with func function. It is a variable, so it gets declared initially and set to undefined, then all lines will gets executed but func is undefined so it will throw error.
I have created a recursive solution for same. This adds handlers for next list items only on click
$(document).ready(function() {
var i = 1;
addEventHandlerForNextItem(i);
function addEventHandlerForNextItem(num) {
var elem = $('ul li:nth-child(' + num + ')');
elem.on('click', function() {
console.log('element:' + elem[0].textContent);
alert('element:' + elem[0].textContent);
i = i + 1;
addEventHandlerForNextItem(i);
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
not the prittest, but heres how i managed to attached the event handler dynamically ::
var i = 1;
var funk = function() {
return i < 5 ? ++i : i = 1 ;
}
changeHanderler = function(){
str = funk();
console.log(str);
var elem = $('ul li:nth-child('+ i +')');
elem.on('click.ga' , function(){
console.log('logged');
elem.off('click.ga');
changeHanderler();
});
}
$('document').ready(function(){
elem = $('ul li:nth-child('+ i +')');
elem.on('click.ga' , function(){
changeHanderler();
console.log('logged');
elem.off('click.ga');
});
});
not pritty but effective , also excessive usage of on() and off() jquery functions , maybe should have gone for the one() function.

Call one event on a set of matches

I do what something like:
$('div > img').onAll('load', function() { alert('Loaded!') })
Which would alert "Loaded!" only once
I don't want this:
$('div > img').on('load', function() { alert('Loaded!'); });
because this would call the event after every single image has been loaded
Is there any ready function in jQuery that calls an event on a set of matches? Or do I have to write a custom function for it?
Create your own method
$.fn.onAll = function(ev, callback) {
var xhr = [];
this.each(function() {
var def = new $.Deferred();
var ele = document.createElement(this.tagName.toLowerCase());
ele['on'+ev] = function() {
def.resolve();
}
ele.src = this.src;
xhr.push(def);
});
$.when.apply($, xhr).then(callback);
return this;
}
to be used as
$('div > img').onAll('load', function() { alert('Loaded!'); });
FIDDLE
Try this
var $images = $("div > img")
, imageCount = $images.length
, counter = 0;
// one instead of on, because it need only fire once per image
$images.one("load",function(){
// increment counter everytime an image finishes loading
counter++;
if (counter == imageCount) {
// do stuff when all have loaded
alert('Loaded!');
}
}).each(function () {
if (this.complete) {
// manually trigger load event in
// event of a cache pull
$(this).trigger("load");
}
});
try something like this
$('body').on('load','div > img',function() { alert('Loaded!') });
Happy Coding :)

Javascript function only works after page refresh

I have a forum that has a "subscribe" and "unsubscribe" button. When you hit it once, it changes but then doesn't switch back again until the page is refreshed.
http://jsfiddle.net/7QPyL/
Here's my code:
$(document).ready(function () {
// Subscribe to topic subscribedtotopic
$(".notsubscribedtotopic").click(function () {
var topicid = $(this).attr('rel');
$(this).slideUp('fast');
$(this).html('Unsubscribe From Topic');
$(this).removeClass('notsubscribedtotopic').addClass('subscribedtotopic');
$(this).slideDown();
$.get("/base/Solution/SubScribeToTopic/" + topicid + ".aspx",
function (data) {
var result = $('value', data).text();
});
return false;
});
// UnSubscribe to topic subscribedtotopic
$(".subscribedtotopic").click(function () {
var topicid = $(this).attr('rel');
$(this).slideUp('fast');
$(this).html('Subscribe To Topic');
$(this).removeClass('subscribedtotopic').addClass('notsubscribedtotopic');
$(this).slideDown();
$.get("/base/Solution/UnSubScribeToTopic/" + topicid + ".aspx",
function (data) {
var result = $('value', data).text();
});
return false;
});
});
It does not work because the class is not there when you add the event handler, so it can not find the element.
$(".notsubscribedtotopic") and $(".subscribedtotopic") do not magically select new elements as they are added to the page.
You should write one function and just toggle the state.
$(".subscribe").click(function () {
var link = $(this);
var isSubscribbed = link.hasClass("subscribedtotopic");
link.toggleClass("subscribedtotopic notsubscribedtotopic");
...
});
I would set up your code to be something like this:
$(document).ready(function () {
// Subscribe to topic subscribedtotopic
function subscribetotopic() {
var topicid = $(this).attr('rel');
$(this).slideUp('fast');
$(this).html('Unsubscribe From Topic');
$(this).removeClass('notsubscribedtotopic').addClass('subscribedtotopic');
$(this).slideDown();
$.get("/base/Solution/SubScribeToTopic/" + topicid + ".aspx",
function (data) {
var result = $('value', data).text();
});
return false;
}
// UnSubscribe to topic subscribedtotopic
function unsubscribetotopic() {
var topicid = $(this).attr('rel');
$(this).slideUp('fast');
$(this).html('Subscribe To Topic');
$(this).removeClass('subscribedtotopic').addClass('notsubscribedtotopic');
$(this).slideDown();
$.get("/base/Solution/UnSubScribeToTopic/" + topicid + ".aspx",
function (data) {
var result = $('value', data).text();
});
return false;
}
});
And then make a simple onclick call in your HTML element, like so:
<button onclick="subscribetotopic()">Subscribe</button>
If you'd prefer to keep your code the way it is, then clarify which element you want to have active.
Example (simply set a div w/ id mymainelement and button w/ id subscribebutton):
$(#mymainelement .subscribebutton).click(function() { ... });
If you'd prefer to toggle the button instead of having two separate elements, check out #epsacarello's answer.

jQuery Function - return a value with two clicks

I want to carry a value inside a JavaScript function but use jQuery to detect the click or hover state.
function foo(bar){
var choc=bar;
}
When I click foo() I want it detect the first click and the second so I can do an image swap.
Example:
function foo(bar) {
var choc=id;
$(id).click(function () {
alert('first click');
}, function () {
alert('second click');
});
}
I can only return first click. This is what I am trying to do:
An example which will not work
open <img id="5" class="swap5" src="down.png" />
<div id="box5">press the up button to close me</div>
jQuery
$(document).ready(function() {
$(".open").click(function(event){
var id = event.target.id;
$('#box' + id).slideToggle();
$(".swap"+id).attr("src", "up.png");
}, function () {
var id = event.target.id;
$('#box' + id).slideToggle();
$(".swap"+id).attr("src", "down.png");
});
});
Use .toggle instead of .click.
$(document).ready(function() {
$(".open").toggle(function(event){
event.preventDefault();
var id = event.target.id;
$('#box' + id).slideToggle();
$(".swap"+id).attr("src", "up.png");
}, function (event) {
event.preventDefault();
var id = event.target.id;
$('#box' + id).slideToggle();
$(".swap"+id).attr("src", "down.png");
});
});
Also lose the href="javascript:open(5);" in the <a> tag. Use href="#" instead.
This is a pretty hacky solution, but here is my take at it.
Declare a counter variable that is initialized at 0.
On click increment it and do a check to see if it is 2 to perform your action.
var counter = 0;
function foo(bar) {
var choc=id;
$(id).click(function () {
if(counter == 2) {
//Perform action
counter = 0; //reset counter
} else {
counter++; //Increment counter
}
});
}
Did you try using the double click event handler? Check out a description by going to: http://api.jquery.com/dblclick/
It's pretty well documented so you should find it straight forward to implement

reinitiate jquery plugin after ajax, causes events to fire multiple times

I have a query plugin I'm working on and I certain functions after ajax content has loaded. The problem is that let's say I re-initiate it 15 times, a click event will then fire 15 times when it's only clicked once.
Is there a way so it doesn't keep piling up? I'm calling addToCart onload and also from itemDetail after the ajax return
thanks!
function addToCart()
{
$(options.add_to_cart).click(function ()
{
event.preventDefault();
var id = $(this).attr('id');
store_item_id_val = id.replace('store-item-id-', '');
var quantity = $('.quantity-' + store_item_id_val);
if (quantity.val() < 1)
{
showError('Please enter a quantity of 1 or more.');
$(quantity).val(1);
return this;
}
$.post($(this).attr('href'),
{ store_item_id: store_item_id_val, quantity: quantity.val() },
function (data)
{
var result = jQuery.parseJSON(data);
renderCart(result);
});
});
return this;
}
function itemDetails()
{
$('.item-details').click(function ()
{
event.preventDefault();
var url = $(this).attr('href');
$.getJSON(url, function (result)
{
$('.modal-title').empty().html(result.title);
$('.modal-content').empty().html(result.html);
$('#modal').slideDown(100);
$('.ui-button').button();
addToCart();
$('.modal-close').click(function ()
{
event.preventDefault();
$('#modal').hide();
});
});
});
Based on the code you provided, I would probably say that you have some other code calling itemDetails(). Each time itemDetails() is called, it ADDS another event handler for click to your .item-details. You may want to instead do:
$(document).ready(function()
{
$('.item-details').click(function ()
{
event.preventDefault();
var url = $(this).attr('href');
$.getJSON(url, function (result)
{
$('.modal-title').empty().html(result.title);
$('.modal-content').empty().html(result.html);
$('#modal').slideDown(100);
$('.ui-button').button();
addToCart();
$('.modal-close').click(function ()
{
event.preventDefault();
$('#modal').hide();
});
});
});
});
This would put the event handler on your .item-details classed items, and only fire the events once. If you have dynamic .item-details added and removed you probably should use:
$('.item-details').live('click', function() ...

Categories

Resources