How to check if a button is clicked or not in prototype JavaScript?
$('activateButton').observe('click', function(event) {
alert(hi);
});
The code above is not working.
With this button:
<button id="mybutton">Click Me</button>
Use this:
$('mybutton').observe('click', function () {
alert('Hi');
});
Tested and works, here.
You might want to encase it in a document.observe('dom:loaded', function () { }) thingy, to prevent it executing before your page loads.
Also, just an explanation:
The single dollar sign in Prototype selects an element by its id. The .observe function is very similar to jQuery's .on function, in that it is for binding an event handler to an element.
Also, if you need it to be a permanent 'button already clicked' thingy, try this:
$('mybutton').observe('click', function () {
var clicked = true;
window.clicked = clicked;
});
And then, if you want to test if the button has been clicked, then you can do this:
if (clicked) {
// Button clicked
} else {
// Button not clicked
}
This may help if you are trying to make a form, in which you don't want the user clicking multiple times.
How one may do it in jQuery, just for a reference:
$('#mybutton').on('click', function () {
alert('Hi');
});
Note that, the jQuery code mentioned above could also be shortened to:
$('#mybutton').click(function () {
alert('Hi');
});
jQuery is better in Prototype, in that it combines the usage of Prototype's $ and $$ functions into a single function, $. That is not just able to select elements via their id, but also by other possible css selection methods.
How one may do it with plain JavaScript:
document.getElementById('mybutton').onclick = function () {
alert('Hi');
}
Just for a complete reference, in case you need it.
$('body').delegate('.activateButton', 'click', function(e){
alert('HI');
});
Related
In our application we have more than 100 grids and we need to display help button on Title bar of grid, for that I have created a plugin using
$.jgrid.extend({
EnableHelpButton: function(value) {
var $t = this;
...............;
}
});
Currently, I go to each .html page of grid and need to call the EnableHelpButton as shown in below code.
-----------------Index1.html-------------------------
$("#TestGrid1").bind("jqGridInitGrid", function () {
$(this).EnableHelpButton(true);
});
-----------------Index2.html-------------------------
$("#TestGrid2").bind("jqGridInitGrid", function () {
$(this).EnableHelpButton(true);
});
How I can create a generic way to call this EnableHelpButton on jqGridInitGrid events of each grid. It should write once on single place and it should work for each grid.
You have to have some specific call of your custom function on every page. One way will be to define you plugin so
$.jgrid.extend({
EnableHelpButton: function(value) {
var $t = this;
...............;
},
myInit: function () {
return this.each(function () {
$(this).bind("jqGridInitGrid", function ({
$(this).EnableHelpButton(true);
});
});
}
});
Even in the case you need to include .jqGrid("myInit") call on every page. You can make the call of myInit before the <table> is converted to grid. For example instead of
$("#grid").jqGrid({
... // parameter used to create jqGrid
});
you will be use now
$("#grid").jqGrid("myInit").jqGrid({
... // parameter used to create jqGrid
});
Only if you never use onInitGrid callback in any your grids you can use the callback instead of jqGridInitGrid. In the case you need just define the callback in some JavaScript code which you included in every your page:
$.extend(true, $.jgrid.defaults, {
onInitGrid: function () {
$(this).EnableHelpButton(true);
}
});
In the way you will set default implementation of onInitGrid for every grid.
Thus the definition of common initialization inside of onInitGrid callback produces the shortest implementation, but have restriction that you shouldn't use the callback in no of your grids. Alternatively you defines the method myInit which makes all bindings add you can add .jqGrid("myInit") on every your grids. The last approach will work for every jqGrid.
I have a page that is built around a wrapper with some very defined logic. There is a Save button on the bottom of the wrapped form that looks like this:
<form>
... my page goes here...
<input id="submitBtnSaveId" type="button" onclick="submitPage('save', 'auto', event)" value="Save">
</form>
This cannot change...
Now, I'm writing some javascript into the page that gets loaded in "...my page goes here...". The code loads great and runs as expected. It does some work around the form elements and I've even injected some on-page validation. This is where I'm stuck. I'm trying to "intercept" the onclick and stop the page from calling "submitPage()" if the validation fails. I'm using prototype.js, so I've tried all variations and combinations like this:
document.observe("dom:loaded", function() {
Element.observe('submitBtnSaveId', 'click', function (e) {
console.log('Noticed a submit taking place... please make it stop!');
//validateForm(e);
Event.stop(e);
e.stopPropagation();
e.cancelBubble = true;
console.log(e);
alert('Stop the default submit!');
return false;
}, false);
});
Nothing stops the "submitPage()" from being called! The observe actually works and triggers the console message and shows the alert for a second. Then the "submitPage()" kicks in and everything goes bye-bye. I've removed the onclick attached to the button in Firebug, and my validation and alert all work as intended, so it leads me to think that the propagation isn't really being stopped for the onclick?
What am I missing?
So based on the fact that you can't change the HTML - here's an idea.
leave your current javascript as is to catch the click event - but add this to the dom:loaded event
$('submitBtnSaveId').writeAttribute('onclick',null);
this will remove the onclick attribute so hopefully the event wont be called
so your javascript will look like this
document.observe("dom:loaded", function() {
$('submitBtnSaveId').writeAttribute('onclick',null);
Element.observe('submitBtnSaveId', 'click', function (e) {
console.log('Noticed a submit taking place... please make it stop!');
//validateForm(e);
Event.stop(e);
e.stopPropagation();
e.cancelBubble = true;
console.log(e);
alert('Stop the default submit!');
return false;
submitPage('save', 'auto', e);
//run submitPage() if all is good
}, false);
});
I took the idea presented by Geek Num 88 and extended it to fully meet my need. I didn't know about the ability to overwrite the attribute, which was great! The problem continued to be that I needed to run submitPage() if all is good, and that method's parameters and call could be different per page. That ended up being trickier than just a simple call on success. Here's my final code:
document.observe("dom:loaded", function() {
var allButtons = $$('input[type=button]');
allButtons.each(function (oneButton) {
if (oneButton.value === 'Save') {
var originalSubmit = oneButton.readAttribute('onclick');
var originalMethod = getMethodName(originalSubmit);
var originalParameters = getMethodParameters(originalSubmit);
oneButton.writeAttribute('onclick', null);
Element.observe(oneButton, 'click', function (e) {
if (validateForm(e)) {
return window[originalMethod].apply(this, originalParameters || []);
}
}, false);
}
});
});
function getMethodName(theMethod) {
return theMethod.substring(0, theMethod.indexOf('('))
}
function getMethodParameters(theMethod) {
var parameterCommaDelimited = theMethod.substring(theMethod.indexOf('(') + 1, theMethod.indexOf(')'));
var parameterArray = parameterCommaDelimited.split(",");
var finalParamArray = [];
parameterArray.forEach(function(oneParam) {
finalParamArray.push(oneParam.trim().replace("'","", 'g'));
});
return finalParamArray;
}
I have a button which when clicked the first time it will load another html page.
When it is clicked the second time it will empty a div of the loaded page.
However, for some reason the loaded content keeps reappearing after the second click....
CSS:
#boatdiv {
width: 100%;
}
.clicked {}
HTML
<button id="load"></button>
<div id="boatdiv"></div>
jQuery
$(document).ready(function() {
$.ajaxSetup ({
cache: false
});
var loadURL = "AjaxLoad_injection.html";
$("#load").on("click", function() {
if(!($(this).hasClass("clicked"))){ //checks if button has NOT been clicked
$("#boatdiv").html("<p>loading...</p>").load(loadURL);
}
else {
$("#boatdiv").empty();
}
$("#boatdiv").toggleClass("clicked");
}
);
}); // end ready
What's going on?
You test $(#load) but toggle $("boatdiv").
Try :
$("#load").on("click", function() {
if(!($(this).hasClass("clicked"))){ //checks if button has NOT been clicked
$("#boatdiv").html("<p>loading...</p>").load(loadURL);
}
else {
$("#boatdiv").empty();
}
$(this).toggleClass("clicked");
});
You are toggling class on wrong element. You want it to toggle on the element being clicked. Same as code I gave you in last post.
Simple to walk through it, you are testing this... so need to toglle the class on this
Use
$(this).togglClass('clicked')
Remember that ajax calls are asynchronous. You may be clicking the button a second time before the ajax call has returned.
You could disable the button during the ajax call, like this:
$('#load').on('click', function() {
if (!$(this).hasClass("clicked")) {
$('#load').attr('disabled', true);
$("#boatdiv").html("<p>loading...</p>").load(loadURL, function() {
$('#load').attr('disabled', false);
});
} else {
$('#boatdiv').empty();
}
//$('#boatdiv').toggleClass("clicked");
$('#load').toggleClass("clicked");
});
The button is disabled before the ajax call. A callback function is passed as a second parameter to the "load()" function. It will be called when the ajax call returns. It will re-enable the button.
EDIT: I missed that the wrong element was getting the class toggled, but I still think you want to disable the button during the ajax call or things can get messed up.
I need to avoid the double click submitting behavior. I'm using the client validation with the unobtrusive library. I have the following code for avoiding the double clic:
jQuery.fn.preventDoubleSubmit = function () {
var alreadySubmitted = false;
return jQuery(this).submit(function () {
if (alreadySubmitted)
return false;
else {
alreadySubmitted = true;
}
});
};
jQuery('form').preventDoubleSubmit();
Unfortunately, if my form has some validable fields (for example, a required field), the code above is still being fired, hence, even if I correct any mistakes on the form, I won't be able to submit it again.
How can I fire the double click code after the validation has been succesfully done?
You can also use the JQuery One event.
I have found that I could get past most guards against double-clicks by double-clicking fast. Using the one event is the only true way to make sure the event is only fired once. I don't think this technique will work "out of the box" with an input type=submit tag. Instead, you can simply use an input type=button or JQueryUI's .button().
$("#submitButton").one("click", function(event) {
$('#theForm').submit();
});
If you need to re-wire the event on a validation error (or other circumstance), I recommend that you create a function for the event handler. The function isn't necessary in this example because all the event handler does is submit the form, but in more complicated scenarios you may want to avoid repeating yourself.
function submitClick(event) {
$('#theForm').submit();
}
$("#submitButton").one('click', function(event) {
submitClick(event);
});
// This handler will re-wire the event when the form is invalid.
$('#theForm').submit(function(event) {
if (!$(this).valid()) {
event.preventDefault();
$('#submitButton').one('click', function(event) { submitClick(event); });
}
});
You could obviously add the disabling code here if you wanted to give feedback to the user that the button doesn't work anymore. One great side-effect of using the One event is that you don't actually have to make the button disabled, you can use a style of your own.
function submitClick(event) {
$('#submitButton').addClass('disabledButton');
$('#theForm').submit();
}
$("#submitButton").one('click', function(event) {
submitClick(event);
});
// This handler will re-wire the event when the form is invalid.
$('#theForm').submit(function(event) {
if (!$(this).valid()) {
event.preventDefault();
$('#submitButton').one('click', function(event) { submitClick(event); });
$('#submitButton').removeClass('disabledButton');
}
});
JQuery One Event: http://api.jquery.com/one/
I solved it with the following code:
var tryNumber = 0;
jQuery('input[type=submit]').click(function (event) {
var self = $(this);
if (self.closest('form').valid()) {
if (tryNumber > 0) {
tryNumber++;
alert('Your form has been already submited. wait please');
return false;
}
else {
tryNumber++;
}
};
});
NOTE: You can also replace the:
return false;
line, for:
self.attr('disabled', true);
BUT, if you use the name of your submit buttons on your controller for extra logic, they will be sent as null. (you can use an additional hidden field to charge them before submitting)
that's it, hope it helps
Rodrigo
EDIT: Thanks to these posts:
jquery newbie: combine validate with hidding submit button
Why not just use:
function disableButtons() {
var form = $(this);
var btns = $("input:submit", form);
if (!form.valid()) {
// allow user to correct validation errors and re-submit
btns.removeAttr("disabled");
} else {
btns.attr("disabled", "disabled");
}
}
to disable your buttons and activate it using:
$("form").bind("submit", disableButtons);
Based on Ryan P's popular answer I created the following generic solution that also works with my ajax form.
decorate your custom submit button with the following class:
<button type="button" class="one-click-submit-button">Submit</button>
Add the following to your javascript file:
function OneClickSubmitButton() {
$('.one-click-submit-button').each(function () {
var $theButton = $(this);
var $theForm = $theButton.closest('form');
//hide the button and submit the form
function tieButtonToForm() {
$theButton.one('click', function () {
$theButton.hide();
$theForm.submit();
});
}
tieButtonToForm();
// This handler will re-wire the event when the form is invalid.
$theForm.submit(function (event) {
if (!$(this).valid()) {
$theButton.show();
event.preventDefault();
tieButtonToForm();
}
});
});
}
OneClickSubmitButton();
since this is an ajax form we want to reload the handlers if we fail server validation.
function MyForm_OnSuccess() {
if (true if your form passed validation logic) {
//do something since your form submitted successfully
} else { //validation failed on server
OneClickSubmitButton(); //reinitialize the button logic
}
}
Obviously if you don't have ajax forms you can omit the whole OneClickSubmitButton function business and run $('.one-click-submit-button').each(... directly.
I have a form that uses MVC3 unobtrusive validation, and a viewmodel with a [RemoteAttribute].
It looks to me like the form's submit event only fires after all validation has passed. I'm currently using this, and it seems to work:
<input type="submit" value="Submit the Form"
data-app-disable-on-submit="true" />
$('form').live('submit', function() {
$(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
.attr('disabled', 'disabled');
})
;
I set breakpoints on both the remote attribute validation action method and the HttpPost action method. Clicking the submit button the first time hits the breakpoint on the validation action method. At this point, the button is still enabled. I can click it multiple times, and after resuming the validation method, the HttpPost is hit only once. When the HttpPost is hit, the submit button is disabled.
Update
Right you are Alex. So an updated version of the above would look like this:
$('form').on('submit', function() {
$(this).find('input[type="submit"][data-app-disable-on-submit="true"]')
.attr('disabled', 'disabled');
})
$('form').submit(function () {
$('input[type="submit"]', this).attr('disabled', 'disabled');
});
I use a different approach to this. Not wiring to the click event of the button, but to the submit event of the form. Works like a charm to prevent multiple simultaneous submits of forms.
function initFormsToPreventSimultaneousSubmits(selector) {
if (!selector) {
selector = 'form'; // No selector supplied, apply to all forms on the page
}
// Make sure all forms that conform to selector are marked as not submitting
$(selector).each(function()
{
var $form = $(this);
$form.data('submitting', false);
});
// Attach to submit event of all forms that conform to selector
$(selector).off('submit').on('submit', function (e) {
var $form = $(this);
if (!$form.valid || $form.valid()) { // Make sure to only process when the form is valid or jquery validation is not used
if ($form.data('submitting')) {
// form is already submitting. Classic case of double click on one of the submit buttons of the form. Stop the submit
e.preventDefault();
return false;
} else {
// All ok, mark the form as submitting and let the form perform the submit
$form.data('submitting', true);
return true;
}
}
});
}
On document ready i call initFormsToPreventSimultaneousSubmits() to init all forms on the page.
Only thing to remember is that when u use a ajax form post is to call the initFormsToPreventSimultaneousSubmits('#formId') on the OnComplete event of the AjaxOptions settings. Because otherwise the form will still be marked as submitting when its done. When a 'normal' form post is used this is not an issue.
Extends answers by Alex and Ryan P to accounts for situations where jQuery Validation might be missing and where multiple submit buttons exist in a single form.
oneClickSubmitButton = function () {
$('input[type=submit], button[type=submit], input[type=image]').each(function () {
var $theButton = $(this);
var $theForm = $theButton.closest('form');
//hide the button and submit the form
function tieButtonToForm() {
$theButton.one('click', function () {
$theButton.addClass('ui-state-disabled');
});
}
tieButtonToForm();
$theForm.submit(function (event) {
// Only proceed for the clicked button
if (!$theButton.hasClass("ui-state-disabled"))
return;
// If jQuery Validation is not present or the form is valid, the form is valid
if (!$theForm.valid || $theForm.valid())
return;
// Re-wire the event
$theButton.removeClass('ui-state-disabled');
event.preventDefault();
tieButtonToForm();
});
});
};
I was able to fix a similar issue with a couple of lines of code. I prefer this if you don't want to "alert" to user that they double clicked and just silently ignore the second click.
I just made a global javascript variable that I toggled when my function was executing during a critical section. This kept subsequent function calls from re-executing the same section.
var criticalSection = false;
SomeOnClickEventFired = function () {
if (!criticalSection)
{
criticalSection = true;
//Ajax Time
criticalSection = false;
}
}
Why are none of the live (or dead) events I bind to a dynamic element firing?
(function ($) {
$.fn.myPlugin = function () {
var $filterBox = $("<input type='text'>").live("click", function () {
alert("Clicked");
});
this.before($filterBox); // insert into DOM before current element
return this; // keep chain
};
})(jQuery);
I am calling myPlugin on several <select> elements. I thought it would work without the Live plugin if I bound it before adding the element to the DOM, but not even the live events are firing. Is it because my element has no ID?
Edit:
The following does not work either:
var $filterBox = $("<input type='text'>").bind("click", function () {
alert("Clicked");
});
.live() works off a selector (since it checks the target against the selector at the time the event happens), you can't attach it directly to an element...you should just use .click() in these cases:
(function ($) {
$.fn.myPlugin = function () {
var $filterBox = $("<input type='text'>").click(function () {
alert("Clicked");
});
this.before($filterBox); // insert into DOM before current element
return this; // keep chain
};
})(jQuery);
You can try it out here, or a bit shorter with .insertBefore():
(function ($) {
$.fn.myPlugin = function () {
$("<input type='text'>").click(function () {
alert("Clicked");
}).insertBefore(this);
return this;
};
})(jQuery);
You can test it here.
The live method works with selectors, not detached elements.
You can handle the normal (non-live) click event, and it should work fine.
Why not just bind it? http://jsfiddle.net/9WvpA/
Can it be just because "<input type='text'>" is not a valid HTML? You have not closed your tag. However, I am not sure whether jQuery is unable to close it for you.
Solved by not using global variables that replaced each other, and iterating over each element in question with this.each(...):
(function ($) {
$.fn.myPlugin = function () {
return this.each(function () {
// do stuff
});
};
})(jQuery);