Reputation:
When the user clicks on either .class
or #id
, some changes are made to the css of both divs and the value of #id
increases by 1. However, when the user clicks on either one of the divs, the changes should only be made once - if the user clicks again, nothing will happen unless the page is refreshed.
$('.class, #id').one('click', function(e) {
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff',
});
$("#id").html(function(i, val) { return val*1+1 });
});
Above shows the code that I am using. As you can see, I have used .one
to make sure that the code is only performed once. This works, but the problem is that the user can click on .class
and then click on #div
which means that the code can be performed twice.
How would I edit this so that the code can only be performed once - clicking on one div means the other div can not be clicked on.
Upvotes: 1
Views: 399
Reputation: 43728
I think you could use one with event delegation instead. That way you have a single handler for all targets and jQuery will automatically remove it once invoked.
$(document).one('click', '#first,#second', alert.bind(null, 'clicked'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="first">first</button>
<button id="second">second</button>
With your code it would be:
$(document).one('click', '.class, #id', function(e) {
//handle click
});
Here's another example showing how you could manually remove the handler after invocation in a safe way (without affecting other handlers) using a named function expression:
$('#first, #second').click(function someClickHandler(e) {
alert('clicked!');
$('#first, #second').off('click', someClickHandler);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="first">First</button>
<button id="second">Second</button>
Upvotes: 1
Reputation: 7008
You are setting two listeners, in fact. One on the .class
and another on the #id
.
This means you'll need to store a state variable and check it before performing any action.
var isClickable = true;
$('.class, #id').one('click', function(e) {
if(isClickable){
isClickable = false;
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff',
});
$("#id").html(function(i, val) { return val*1+1 });
}
});
This is a better option than adding a state attribute to the actual DOM element.
Upvotes: 0
Reputation: 708136
You can set a data attribute on both objects and only increment the counter if that is not set:
$('.class, #id').one('click', function(e) {
if (!$(this).data("valueSet")) {
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
}).data("valueSet", true);
$("#id").html(function(i, val) { return val*1+1 });
}
});
Or, if you know there are no other jQuery click handlers that you want to retain, you can unbind all jQuery click handlers from both objects:
$('.class, #id').one('click', function(e) {
$('.class, #id').off("click").css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
})
$("#id").html(function(i, val) { return val*1+1 });
});
Or, you can unbind just this specific event handler by putting the event handler in a named function:
function oneClick(e) {
$('.class, #id').off("click", oneClick).css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
})
$("#id").html(function(i, val) { return val*1+1 });
}
$('.class, #id').one('click', oneClick);
A little more generic scheme would create a custom function that will only ever perform its action once:
function oneAction(fn) {
var calledYet = false;
return function() {
if (!calledYet) {
calledYet = true;
return fn.apply(this, arguments);
}
}
}
Then, you can use this:
$('.class, #id').one('click', oneAction(function(e) {
// this will only ever be executed once
$('.class, #id').css({
'background-color' : 'rgb(232,69,73)',
'color' : '#fff'
})
$("#id").html(function(i, val) { return val*1+1 });
}));
Upvotes: 2