I have a JavaScript calculator with a mode button that is supposed to toggle between radian and degree mode via a switch. If the value of the button is either DEG or RAD, clicking on the cosine button will execute either the cos function or the cosDeg function (see below):
$('#button-mode').click(function() {
var type = $(this).val(),
$div = $('#mode');
switch (type) {
case 'DEG':
$div.html('DEG');
$('#button-mode').html('Rad');
$('#button-mode').val('RAD');
break;
case 'RAD':
$div.html('RAD');
$('#button-mode').html('Deg');
$('#button-mode').val('DEG');
break;
}
});
if ($("#button-mode").val() === 'DEG') {
$('#button-cos').click(function() {
if (checkNum(this.form.display.value)) {
cos(this.form);
$('#disp').addClass("result");
}
console.log('cos');
});
}
else if ($("#button-mode").val() === 'RAD') {
$('#button-cos').click(function() {
if (checkNum(this.form.display.value)) {
cosDeg(this.form);
$('#disp').addClass("result");
}
console.log('cosDeg');
});
}
The switch seems to be working fine in that the correct HTML appears in both the button and the #mode div, but clicking on #button-cos in either case executes the cos function. I am at a loss as for why this happens.
Also, and this may be why this is happening, the button is given by:
<button TYPE="button" ID="button-mode" value="DEG">Deg</button>
How can I change my code to get this working properly?
You should only define one handler for your button-cos click event, and determine the correct function to call inside of that function.
$('#button-cos').click(function() {
if (checkNum(this.form.display.value)) {
if($("#button-mode").val() === 'DEG'){
cosDeg(this.form);
} else{
cos(this.form);
}
$('#disp').addClass("result");
}
});
The problem is cause you add new event listeners, but not remove previously added, so both click handlers executes.
You can use document.getElementById('button-cos').onclick=function() {...} instead of $('#button-cos').click(function() {...} it will remove previous handler and add new one.
But also it seems that code does not add events after clicking button-mode.
So, much better is to move if statements (if ($("#button-mode").val() === '...')) inside event handler. In that case you will need to add click handler only once.
Related
I'm working on my very first site and have a problem with click event.
here is my website (it's unfinished): https://pawcio93.github.io/PortfolioSinglePage/
The problem is that #cancel does not work (function run after click, I checked it with alert, but click event does not undo itself at all. I also try to use .on .off method but with same result. If it's making something wrong or I can't use those methods to undo this 'click' function properly? If not, how should I perform that? Thank in advance for reply I will try to figure it out myself, waiting for Yours propositions
var chooseHobby = function() {
$(this).addClass('hobbyOnClick').removeClass('hobby firstInLine hobbyImg');
$('.hobbyImg').hide();
$('.hobby').css('display', 'none');
updateHeight2();
var id = this.id;
if (id == 'sport') {
if (document.getElementById("gym")) {
return;
} else {
$('#sport').append('<img id="runmaggedon" src="img/runmaggedon.jpg" alt="runmaggedon" />');
$('#sport').append('<img id="gym" src="img/gym.jpg" alt="gym" />');
$('#sport').append('<div class="sportText">\n\
<p>Runmaggedon is my hobby for over a year, it is challenging, hard and the people and athmosphere there is just great. For now my best distance is 24 km in mountain terrain, but it was not my last word! </p>\n\
\n\
</div>');
$('#sport').append('<div class="sportText"><p>Working out is something that I'm doing since studies. It is became the part of my daily routine, I love to work with my body and see physical ad power progress. Gym also help with self-discipline and well-being </p></div>');
$('#sport').append('<div id="cancel"><p>CANCEL</p></div>');
}
} else if (id == 'travel') {
alert("travel");
} else if (id == 'objectivism') {
alert("objectivism");
} else if (id == 'engineering') {
alert("engineering");
} else if (id == 'programming') {
alert("programming");
} else if (id == 'economy') {
alert("economy");
}
$("#cancel").bind("click", function() {
alert("function start");
$(".hobby").unbind("click", chooseHobby);
});
};
$(document).ready(function() {
$(".hobby").bind('click', chooseHobby);
});
A click is an event. It happens milliseconds (quite instantly) after a user click.
You can't "undo" it.
To that event, you can register a function to execute. Now to "undo" the changes made by such a function, you have to store the previous relevant states/values. And using another click event, you can give the impression of an undo.
Here is a really simple example which only changes a <h1> text.
// Store initial text.
var previousH1state = $("h1").text();
// Modify
$("#modify").on("click",function(){
$("h1").text("I'm modified!");
});
// Undo
$("#undo").on("click",function(){
$("h1").text(previousH1state); // Notice the stored text is used here.
});
// De-register functions tied to click events from the modify/Undo buttons.
$("#off").on("click",function(){
$("#modify, #undo").off("click");
console.log("Modify and Undo buttons are not working anymore");
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>I'm unchanged.</h1>
<button id="modify">Modify the header above</button>
<button id="undo">Undo the modification</button><br>
<br>
<button id="off">Use .off()</button>
.off() is used to de-register a function from the event on an element. That is something else...
More on events.
I have created a fiddle of my function here( http://jsfiddle.net/rhy5K/10/ ) . Now i want to disable the button click i.e play/pause if the sound is playing like Get ready,5,4,3,2,1 .
I know only how to disable the form submit button , but I am very confused how to disable the click in my case the hyperlinks.
Explanation using code example:
I want to disable this
PLAY
click, while interpreter is executing the below code:
var playGetReady = function (done) {
var ids = ['audiosource', 'a_5', 'a_4', 'a_3', 'a_2', 'a_1'],
playNext = function () {
var id = ids.shift();
document.getElementById(id).play();
if (ids.length) {
setTimeout(playNext, 1000);
} else {
done();
}
};
playNext();
};
Warning: This JS fiddle demo may play sound on load
You may try this (Changes in following function), but not sure if this is you want and maybe there are other ways to do it.
App.prototype.start = function () {
var self = this;
// unbind for a while
self.$button.unbind('click', self.buttonHandler); // <--
var start = function () {
// start countdown
self.intervalHandle = setInterval($.proxy(self.tick, self), 1000);
// bind again
self.$button.click($.proxy(self.buttonHandler, self)); // <--
// change button text to PAUSE
self.$button.text('PAUSE');
};
if (this.newTimer) {
playGetReady(start);
} else {
start();
}
};
DEMO.
In jquery, it can be done easily by cancel default action. Here's the sample.
$("#btn_start").click(function(event){
if(not_active_flag){
// Prevent anchor to active
return false;
}else{
// Anchor active as usual
return true;
}
});
In your case, the link will ultimately call this.buttonHandler, which has the following code:
App.prototype.buttonHandler = function (e) {
e.preventDefault(); // prevent anchor default action
this.toggle(); // toggle play/pause
};
Because buttonHandler is attached before playGetReady is executed, it is not possible to let playGetReady attach a click handler to that anchor element that uses .stopImmediatePropagation() to prevent the other click handler from executing.
In this case #gp.'s solution in the comments is most likely the best solution. In your case you might even be able to use a local variable in your app. If you use a global variable, reference it with window.yourglobalvariable. If you use a local variable, make sure you define it somewhere and reference it with this.yourvariable. Change your buttonHandler to:
App.prototype.buttonHandler = function (e) {
e.preventDefault(); // prevent anchor default action
if( this.soundready )
this.toggle(); // toggle play/pause
};
On the appropiate place make this variable false to prevent the 'button' from working. When the button should work, change the variable to true. I think that should be just before done() in the code you have in your question, but you probably have a better idea in what order the code is executed.
A follow on from this question
Edit
JSFiddle code
As you can see if you run the code the button text does not change, the onclick is overriding the click function. If you remove the form id attribute from the function and the onclick attribute from the html tag the code works as expected (in a real scenario no onclick function implies a submit button rather than a button)
End Edit
I had thought that a typo was responsible for JQuery not firing the click() event when an inline event was specified, however I've run into the issue once more. Here's my code and the offending tag
<input id="submit1" type="button" onclick="this.disabled=true; doSubmit();" value="submit">
<script>myfunction('submit1', 'working', myformID)</script>
var myfunction = function(ID , text , formID) {
if(ID) {
var element = document.getElementById(ID);
if(formID) {
var form = document.getElementById(formID);
}
if (element) {
jQuery(element).click( function() {
if(jQuery(this).attr('disabled')) {
return false;
}
jQuery(this).attr('disabled' , 'disabled');
jQuery(this).attr('value' , processingText);
onclick = (jQuery(this).attr('onclick') || jQuery(this).attr('onClick'));
if(form && !onclick) {
jQuery(form).submit();
}
jQuery(this).click();
});
}
}
};
I'm using javascript to create a function which will disable submit buttons while keeping any onclick attribute working in case of a doSubmit, like in this case. In other cases where the form id is set and there isn't an existing onclick I submit the form. Therefore if there is an issue with the html tag I need a general way to fix it with JS.
Many thanks in advance
Your inline handler disables the button: this.disabled=true;
Then jQuery handler checks if it is disabled and returns if so:
if(jQuery(this).attr('disabled')) {
return false;
}
There is, unfortunately, no way to predict the order of event handlers execution for the same event on the same element.
As a quick fix, I can suggest this:
Demo
jQuery(element).click( function() {
if(jQuery(this).attr('disabled-by-jquery')) {
return false;
}
jQuery(this).attr('disabled' , 'disabled');
jQuery(this).attr('disabled-by-jquery' , 'disabled');
jQuery(this).attr('value' , text);
onclick = (jQuery(this).attr('onclick') || jQuery(this).attr('onClick'));
if(form && !onclick) {
jQuery(form).submit();
}
jQuery(this).click();
});
I want to click a table element and to have it do x the first click and if clicked again perform Y
<td class='p' id='e1' onclick="myFunction2()"><img src='person2.png'/></td>
Thats what I have for my HTML for one click just now, but I wish to change that so that an item can be selected, then if clicked again for a deselect it would then trigger a different function.
I'm going to assume (you didn't say) that you want the function to be called to alternate with every click:
$('#e1').on('click', function() {
// retrieve current state, initially undefined
var state = $(this).data('state');
// toggle the state - first click will make this "true"
state = !state;
// do your stuff
if (state) {
// do this (1st click, 3rd click, etc)
} else {
// do that
}
// put the state back
$(this).data('state', state);
});
This uses jQuery's .data feature to store the button's click state in the button element itself.
Alternatively, you could use an external variable, but you should enclose the callback in a closure (in this case an immediately invoked function expression) to prevent the variable from becoming a global variable:
(function() {
var state;
$('#e1').on('click', function() {
state = !state;
if (state) {
// do this (1st click, 3rd click, etc)
} else {
// do that
}
});
})();
If the .on call and the state variable declaration are inside a jQuery document.ready handler that would have the same effect.
Pretty basic, let me know if this is close to what you want.
http://jsfiddle.net/WNJ75/6/
<div id="e1">Click Me</div>
.
(function() {
var click_track = 1;
$("#e1").click(function() {
if (click_track == 1)
alert("do something");
else if (click_track == 2) {
alert("do something else and reset click");
click_track = 0;
}
click_track++;
});
})();
demo: http://jsfiddle.net/HJwJf/
Link the toggle method with;
$("button").toggle(function(){
$("body").css("background-color","green");},
function(){
$("body").css("background-color","red");},
function(){
$("body").css("background-color","yellow");}
);
You could create a new atribute on the HTML element named, for example, "clickCount", and use it inside your event handler as a counter.
Let's say you have a button like this one:
<button data-click-count='0' onclick="myFunction(this)">My Button</button>
And you have a function like this:
function myFunction(elt) {
// Gets the clicks count
var count = $(elt).data("click-count");
// Adds one to the click counter
$(elt).data("click-count", ++count);
if (count == 1)
doSomething();
else if (count == 2)
doSomethingElse();
}
Every time you click the button, you'll see an alert with the number of clicks you've made.
You can use the same method and apply it to your case.
Using a state variable. The state variable will swap between the values 0 and 1 on each click. Making use of state we can execute the corresponding function in fn array.
<td class='p' id='e1'><img src='person2.png'/></td>
$("td#e1.p").each(function(){
var state = 1, fn = [myFunction1, myFunction2];
$(this).click(function(){
return fn[state = 1 - state].apply(this, arguments);
});
});
Also, it's preferably to use proper event binding than inline JavaScript.
With prototype I'm listening for a click event on several checkboxes. On checkbox click I want to disable all <select> elements. I'm using prototype. So, I have this code:
$$('.silhouette-items input[type="checkbox"]').invoke('observe', 'click', function(event) {
var liItem = this.up('li.item');
if(this.checked) {
alert('checked');
liItem.removeClassName('inactive');
var selectItem = liItem.select('select');
for(i=0;i<selectItem.length;i++) {
selectItem[i].disabled=false;
if (selectItem[i].hasClassName('super-attribute-select')) {
selectItem[i].addClassName('required-entry');
}
}
} else {
alert('unchecked');
liItem.addClassName('inactive');
var selectItem = liItem.select('select');
for(i=0;i<selectItem.length;i++){
selectItem[i].disabled=true;
if (selectItem[i].hasClassName('super-attribute-select')) {
selectItem[i].removeClassName('required-entry');
}
}
}
calculatePrice();
});
When I manually click on the checkbox, everything seems to be fine. All elements are disabled as wanted.
However, I have also this button which on click event it fires one function which fires click event on that checkbox.
In Opera browser it works. In others, not. It's like Opera first (un)check and then executes event. Firefox first fires event, then (un)check element.
I don't know how to fix it.
The HTML:
<ul class="silhouette-items">
<li>
<input type="checkbox" checked="checked" id="include-item-17" class="include-item"/>
<select name="super_attribute[17][147]">(...)</select>
<select name="super_group[17]">(...)</select>
<button type="button" title="button" onclick="addToCart(this, 17)">Add to cart</button>
</li>
<!-- Repeat li few time with another id -->
</ul>
Another JS:
addToCart = function(button, productId) {
inactivateItems(productId);
productAddToCartForm.submit(button);
}
inactivateItems = function(productId) {
$$('.include-item').each(function(element) {
var itemId = element.id.replace(/[a-z-]*/, '');
if (itemId != productId && element.checked) {
simulateClickOnElement(element);
}
if (itemId == productId && !element.checked) {
simulateClickOnElement(element);
}
});
}
simulateClickOnElement = function(linkElement) {
fireEvent(linkElement, 'click');
}
Where fireEvent is a Magento function that triggers an event
Don't bother simulating a onclick if you can get away with not doing so. Having a separate function that can be called from within the event handler and from outside should work in your case.
var handler = function(){
//...
}
var nodeW = $('#node');
handler.call(nodeW);
Of course, this doesn't trigger all onclick handlers there might be but it is simpler so it should work all right. Points to note for when you use .call to call a function:
Whatever you pass as the first parameter is used as the this inside the call. I don't recall exactly what JQuery sets the this too but you should try passing the same thing for consistency.
The other parameters become the actual parameters of the function. In my example I don't pass any since we don't actually use the event object and also since I don't know how to emulate how JQuery creates that object as well.
replacing
fireEvent(linkElement, 'click');
with
linkElement.click();
works in firefox 5 and safari 5.1, so maybe the problem lies in the fireEvent() method.