jQuery Mutltiple delegation on container - javascript

I have a buttons which should be handlad by ajax and they should be delegated on its container:
jQuery('#container').on('click', 'a', function() {
if(jQuery(this).hasClass('myButton1') {
//handle
return false;
} else if(jQuery(this).hasClass('myButton2') {
//handle
return false;
}
})
so I thought about improving this:
jQuery('#container').on('click', 'a.sharedClass', function() {
if(jQuery(this).hasClass('myButton1') {
//handle
return false;
} else if(jQuery(this).hasClass('myButton2') {
//handle
return false;
}
})
what do you think, will it improve my code IF:
I have many buttons: its a news stream and every news node have its own buttons like delete, favorite, spam, open media lightbox, vote, view votes and etc..
there are other anchors which are not handled by ajax.

This is an interesting question and how I usually approach this is by using the HTML5 data attribute. I'd use a data attribute like so data-actionFn = 'delete'.
HTML
The two below trigger ajax calls onclick
<a href="#" data-actionFn='delete' class='js-ajax'> delete </a>
<a href="#" data-actionFn='vote' class='js-ajax'> vote </a>
....
This does not trigger an ajax call
do something
JAVASCRIPT
jQuery('#container').on('click', 'a.js-ajax', function (e) {
e.preventDefault();
var actionFn = $(this).data('actionFn'); // grab function name
if (window[actionFn]) {
window[actionFn]();
} else {
// throw Error here
}
});
function detele(){
// put code here
}
function favorite(){
// put code here
}
function spam(){
// put code here
}
function open(){
// put code here
}
function media(){
// put code here
}
function lightbox(){
// put code here
}
function vote(){
// put code here
}
function view(){
// put code here
}
NB:
This is just to give you an idea of how you could implement it.

Related

Between two event listeners: How do I pass my function without using trigger()?

Please check out my diagram, and the pseudo-code below. I'm trying to figure out how to pass a function between two event listeners.
Basically, I want to execute some code if "Availability" is less than 0, OR when a user clicks "confirm" in a bootstrap dialog. If the Availability is greater than 0, you'll get the special bootstrap dialog.
I'm trying to avoid writing the same code twice. I'm also trying to avoid using trigger $("#btnConfirm").trigger("click", fn1); --- my assumption is that there is a sexier way, like a callback, or something...
So.... how do I get the code I want to execute into the other 'button click' event listener --OR-- how do I return "btnConfirm" back to the event listener that called the dialog?
$("#Select").on("change", function(e) {
fn1 = function() {
//stuff I want to do
};
//a check that must be passed
currAvail = $("#Availability").val();
if (currAvail > 0) {
//show a message, "Are you sure you want to make the thing?"
//if YES, execute fn1()
//fn1() needs to be available to btnConfirm click listener
// use trigger("click", fn1) ????
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
//Ok, well, they said YES...
//so I need to execute fn1();
});
Since the requirement is to call fn1() in both cases, you can separate the logic out into a method and call when it is needed
function fn1() {
//code to execute on no goes here
}
$("#Select").on("change", function(e) {
let currAvail = $("#Availability").val();
if (currAvail > 0) {
//show modal window
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
fn1()
});
Why not just move the function definition to outside the change callback?
$("#Select").on("change", function(e) {
//a check that must be passed
currAvail = $("#Availability").val();
if (currAvail > 0) {
//show a message, "Are you sure you want to make the thing?"
//if YES, execute fn1()
//fn1() needs to be available to btnConfirm click listener
// use trigger("click", fn1) ????
} else {
//execute the code
fn1();
};
});
$("#btnConfirm").on("click", function(e, param1) {
//Ok, well, they said YES...
//so I need to execute fn1();
});
// Function move to here.
function fn1() {
//stuff I want to do
};

One button submits AJAX, another button queries result of that AJAX

This question is part of me trying to learn promises and deferreds. Suppose you have a button that submits a POST:
$("#submit").click( function() {
$.post({...})
})
My understanding is that AJAX is itself a promise (which makes obvious sense), so what I'd like to do is, when user clicks #check, it returns the output of the AJAX once it is complete (assuming that #check can and will always be clicked only after #submit has been clicked).
I thought this was simple enough, so my initial code was:
$("#check").click(function() {
$.when($.post({...})).done( function(data) {
console.log("data")
})
})
But I realize that in this implementation, the AJAX wouldn't start POSTing until #check is clicked. There's no need for any #submit button and having the AJAX .post in #submit is redundant.
Is there a way to achieve what I'm doing using promises/deferreds?
Just store the promise returned by post.
var myPromise = null;
$("#submit").click( function() {
myPromise = $.post({...});
});
$("#check").click(function() {
if (myPromise) {
myPromise.then( function(data) {
console.log("data");
});
}
});
The other changes I made are using then() instead of done() (a single function to accept success, failure or progress) and I added statement-ending semicolons (because automatic semicolon insertion kills puppies).
And once you're done studying promises, move on swiftly to observables. With JavaScript the fun never stops.
Based on a comment on the question:
i want to submit something via AJAX, but then i want to use the result of that AJAX ONLY LATER when button check is clicked.
You may be overcomplicating this. You don't really need to dissect the AJAX request/promise/etc. between these two buttons. Simply make the request in the first button and store the result, then use the result in the second button. Something as simple as this:
// disable the check button until there is a result to check
$('#check').prop('disabled', true);
var ajaxResult;
$("#submit").click( function() {
$.post({...})
.done(function (result) {
// any other logic you want to put here, then...
ajaxResult = result;
$('#check').prop('disabled', false);
});
})
$('#check').click(function() {
// the result is in ajaxResult, use it as needed here
});
Basically the "check" button doesn't have anything to do with AJAX. It's just performing an action on data which exists in memory. That button is simply enabled when that data is successfully fetched.
You could create a Promise when the #submit button is pressed, and then use that to establish a handler for the #check button.
$("#submit").click(function() {
var requestPromise = $.post( "xxx", function(response) {
// do something here
})
.fail(function() {
alert( "error" );
})
$("#check").click(function() {
requestPromise.done(function(response) {
// do something meaningful with response here, or other logic
});
// disable #check button and remove click handler here
}
// enable #check button here
})
EDIT - as requested by OP
Here's the version using a compliant Promise:
$("#submit").click(function() {
var requestPromise = new Promise(function(resolve, reject) {
$.post( "xxx", function(response) {
// do something here
resolve(response);
})
.fail(function(response) {
alert( "error" );
reject(response);
});
});
$("#check").click(function() {
requestPromise.then(function(response) {
// do something meaningful with response here, or other logic
});
// disable #check button and remove click handler here
}
// enable #check button here
})

Handling multithreadiing issue in javascript/jquery?

$(".getDetails").click(function() {
// some stuff like fetching response from server
})
when user clicks getDetails button on UI multiple times within fraction of second , jquery generates two calls for click function and my logic fails.
I think solution to this will be to disable the button on first click itself(so that use can't click multiple times). Once i get the response or just before returning
from click method i make it enable. Is there any better solution ?
If no, how can i make button disable as soon as user click button first time. I think it needs to be done before calling click method or some where in html element ?
Java provides synchronized keyword so that only one thread enters at time inside method , i am not sure is similar thing exist in javascript or not ?
Assuming the click handler executes an AJAX request you can set the button as disabled before making the request, then enable it again once the request completes. Try this:
$(".getDetails").click(function(){}
var $btn = $(this).prop('disabled', true);
$.ajax({
url: '/foo'
success: function() {
console.log('It worked!');
},
error: function() {
console.log('It failed!');
},
complete: function() {
$btn.prop('disabled', false);
}
});
});
you can try unbinding click event and after ajax call again bind click to that class
$(".getDetails").click(function(){}
$(".getDetails").unbind('click');
// some stuff like fetching response from server
)
You can use simple flag to prevent firing your logic multiple times:
var flag = true
$(".getDetails").click(function() {
if (flag) {
flag = false;
//your logic...
//when your code ends (in after-AJAX callback for example)
flag = true;
}
});
$(".getDetails").click(function(e){
var $target = $(e.currentTarget);
// assuming the click listener is on the button
$target.prop('disabled',true);
// request, stuff...and when done:
$target.prop('disabled',false);
})
try Prevent Default and return false to avoid any other event propagation
This is solution is like semaphore or monitor
var progress = false;
$(".getDetails").on('click', function(e) {
if(!progress){
progress = true;
// some stuff like fetching response from server
//also after sucessfull fetch make true to false again
}else{
console.log('something in progress');
}
e.preventDefault();
return false;
})
This should make sure that your button will not fire the async request twice, until you have a response.
function doAjaxReq() {
/*
Add your ajax operation here
as a return value of doAjaxReq
like so:
return $.ajax({
url: '/foo',
type: 'POST',
data: data
})
Since i can't use ajax here let's smilulate
it useing a promise.
*/
promise = new Promise(function(res, rej) {
setTimeout(function(){
res({foo: "bar"});
}, 1000)
})
return promise;
}
/*
Inside here you add the click handlder
only once use `elem.one('click'...`
*/
function addClickHandler(elem) {
elem.one('click', function() {
// do your ajax request and when its
// done run `addClickHanlder` again
// i'm using `.then` because of the promise,
// you should be using `.done`.
doAjaxReq().then(function(data) {
console.log(data);
addClickHandler(elem);
});
})
}
addClickHandler($(".getDetails"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="getDetails">Get Details</button>

Toggle window.location in jQuery/javascript

What I am trying to achieve is that whenever you click an image, it changes the window.location url, toggling it between '#' and '#footer'. Right now, all I have is this:
<script>
function clickarrow(){
var rd=Math.floor(Math.random()*11)
if (rd > 5){
window.location="#footer";
}
else{
window.location="#";
}
}
</script>
As you can see, this makes a 50:50 chance of either change being made. It works as a temparary fix, but sometimes you have to click up to 6 times for it to take effect.
Is there a way of doing this that properly toggles the window.location?
I am using jQuery 1.9.
If you're trying to reliably toggle the hash, rather than using a random chance, try something like this:
function clickarrow(){
var showFooter = true;
return function () {
if (showFooter) {
window.location.hash = "footer";
} else {
window.location.hash = "";
}
showFooter = !showFooter;
}
}
jQuery(function () {
jQuery('#myToggleLink').click(clickarrow());
});
Note: Normally when binding events, a function reference must be passed in. Here, I'm invoking clickarrow() since it returns a function by design. The returned function encapsulates the toggle variable via closure.
you can use data attribute to tell what is next step:
$('#arrow').click(function() {
if ($(this).data('footer'))
{
window.location="#footer";
$(this).data('footer', 'false');
alert('b');
}
else
{
window.location="#";
$(this).data('footer', 'true');
alert('a');
}
});

Using Jquery calling different functions with a singe link

I would like to use single a href link to call different functions .
On first click it should call first_function() and on second click it should call second_function. Like toggling between two functions using same link. Suggest the best way to be done.
Jquery Code :
$(function() {
var IntervalId;
function first_function() {
//code goes here
};
function second_function(){
//code goes here
}
$("#link2").click((function(){
second_function();
}));
$("#link1").click((function(){
first_function();
}));
});
Html Code :
Call function2
Call function1
"Like toggling between two functions using same link."
$("#link1").toggle(
function first_function() {
// Code goes here
},
function second_function(){
// Code goes here
}
);
From the jQuery docs on toggle(fn1, fn2, [fn3, [fn4, [...]]]):
Toggle among two or more function calls every other click.
Javascript:
$(document).ready(function() {
function first_function() {
// Code goes here
};
function second_function(){
// Code goes here
}
$("#link").toggle(first_function, second_function);
});
HTML:
<!-- I'm pretty sure that <a> isn't the right tag for this. -->
<button id="link">Toggle between the two functions.</button>
the easiest way would be
var performFirstAction = true;
$(function() {
function first_function() {
// Code goes here
}
function second_function(){
// Code goes here
}
$("#link1").click(function(){
if(performFirstAction) {
first_function(); performFirstAction = false; }
else {
second_function(); performFirstAction = true; }
});
});
or using toggle as Tomalak mention and well,
$(function() {
function first_function() {
// Code goes here
}
function second_function(){
// Code goes here
}
$("#link1").toggle(
first_function,
second_function
);
});

Categories

Resources