I've looked on the forum and my question is a duplicate of Button click event not firing in jQuery, except my code already matches the given answer.
I've stripped this down for you guys anyway, and can confirm that links with a class of disabled do not fire, so this proves the document ready and Jquery library are correct.
Javascript
$(document).ready(function () {
// Prevents links from firing
$('a.disabled').click(function (e) {
e.preventDefault();
});
// Handles search
$("#btnTreeSearch").click(function () {
alert("click search fool!");
});
});
Html
<input type="submit" value="btnTreeSearch" />
Any clues?
You need to assign id to input to use id selector
Live Demo
Html
<input type="submit" id="btnTreeSearch" value="btnTreeSearch" />
Javascript
$("#btnTreeSearch").click(function () {
alert("click search!");
});
Change value="btnTreeSearch" to id="btnTreeSearch".
Related
I have a dead simple search form:
<div>
<input id="searchArea" type="text" value="" placeholder="Enter your search terms">
<button id="searchButton">Search</button>
</div>
and a snippet of Javascript controlling it:
function searchFunction() {
console.log("This is a POST request being send to the server");
}
$("#searchButton").on("click", function(e) {
e.preventDefault();
searchFunction();
})
$("#searchArea").on("change", function(e) {
e.preventDefault();
searchFunction();
});
The problem is that click and change overlap in functionality and so I get the following:
When I type something in the text box and then click elsewhere in the screen, searchFunction is fired properly but if "elsewhere" becomes the search button, then searchFunction double fires.
My question is this: Once inside the click handler, is there any way to cancel the change handler from firing as well which would otherwise cause searchFunction to double fire?
Mind that searchArea and searchButton don't have a parent-child relationship which means conventional methods like preventDefault and stopPropagation won't work.
You can see it in action in this fiddle.
What I want to achieve is to track form submits.
But because of the many variations that we use for the submit button I want to change my current code:
$(document).on('click','input[type="submit"], button[type="submit"]',function(){
to something that is universal. And I believe the best approach is the $("form")-annotation.
The problem is that for example if a form has an ajax script on it, it gets blocked by my additional script code.
Basically what I want to achieve is to have both worlds.
So the first one is what the website currently has (not every websites though):
$("form").submit(function () {
// ....do something, maybe ajax submit of the form.....
});
and my additional that I want to add without editing any current scripts already found in the website:
$("form").submit(function () {
$.getJSON("....");
});
The solution for me should be that the second script (the additional) will not interfere with any other form scripts.
AN IDEA
To add a class by using jQuery addClass to the forms of current page.
What is a solution for this?
I created a little Snippet to demonstrate the issue:
$(document).ready(function() {
// Registering form-submission as the first would be a possibility
$('form').on('submit', function(e) {
console.log(e.target);
console.info('My first callback is executing');
// Do some stuff here, but don't mess with the event-object
// (like preventing default or stopping the event-chain)
});
// Then afterwards everything else that *might* catch the event
$('form').on('submit', function(e) {
console.log(e.target);
console.info('My second callback is executing');
// Usually some Ajax-Handler-Callback, that handles sending the form,
// will preventDefault() and stopImmediatePropagation() - that is why
// your general first listener must be registered before any of these callbacks
console.warn('Second callback stops the event from bubbling/propagating');
e.stopImmediatePropagation();
e.preventDefault();
});
// This will never happen
$('form').on('submit', function(e) {
console.log(e.target);
console.info('My third callback will never execute');
});
// Using a delegated event-listener with `useCapture` lets this execute first
document.addEventListener('submit', function(e) {
console.info('Capturing the event natively');
}, true);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>My Website with a multi-handled form</h1>
<form class="" action="" method="post">
<input type="text" name="test" value="">
<button type="submit" name="button">Send</button>
</form>
Output of the Snippet, when submitting the form:
Capturing the event natively
<form class action method="post">…</form>
My first callback is executing
<form class action method="post">…</form>
My second callback is executing
Second callback stops the event from bubbling/propagating
What did just happened?
By pressing the submit-button, our form emits the submit-event. The Browser starts with the event-propagation in a specified event-order. There are two phases of event-propagation: event-capturing and event-bubbling.
Now our first called event-listener is the one with the useCapture-directive.
This is during the capture-phase of the event-propagation.
Explanation for useCapture taken from MDN:
capture: A Boolean that indicates that events of this type will be
dispatched to the registered listener before being dispatched to any
EventTarget beneath it in the DOM tree.
When done, the Browser starts with the bubbling-phase of the event-propagation.
This is where all $('element').on() and element.addEventListener() (without the useCapture option) registered listeners are called in their appearing order.
During this phase our second listener is not only preventing default (not submitting the form the standard-way), but also stopping the event-propagation by calling e.stopImmediatePropagation().
After that the event-chain/event-propagation stops immediately.
That is why our third listener will never execute.
On a side note: When using jQuery and exiting an event-callback with
return false, jQuery will execute e.preventDefault() and
e.stopPropagation() automatically.
See: http://api.jquery.com/on/
Conclusion
You basically have two possibilities for your scenario:
Register your default general event-listener before anything else (first event-registration in Snippet).
Register an event-listener during the capture-phase, to capture the event and handle things before the other listeners from the bubbling-phase get called (last event-registration in Snippet).
With both methods you should be able to do your stuff without interfering with other event-listeners.
Use this:
$(document).on("submit", "form", function (e){
Complete example:
<form id="form1"><input type="text" /><input type="submit" /></form>
<form id="form2"><input type="text" /><input type="submit" /></form>
Js:
$(document).on("submit", "form", function (e) {
var oForm = $(this);
var formId = oForm.attr("id");
var firstValue = oForm.find("input").first().val();
alert("Form '" + formId + " is being submitted, value of first input is: " + firstValue);
return false;
})
[JS fiddle]: http://jsfiddle.net/pZ3Jn/
What I want to achieve is to track form submits.
Why not just use $(document).on('submit', 'form', function(){});?
It will be triggered on every form submit, no matter how it is being submitted.
$(document).ready(function() {
// Some already existing event handler
$('#bir').on('submit', function(e) {
console.log($(this).attr('id'));
e.preventDefault();
});
// Your universal form event handler
$(document).on('submit', 'form', function(e) {
console.log('Additional functionality for: ' + $(this).attr('id'));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="bir">
<input type="submit" />
</form>
<form id="ikki">
<input type="submit" />
</form>
I've ran into this issue a few times before and my solution was to capture all form nodes and associate them with a special action . This may not be practical but is a possible solution for you also .
Example
//Getting all form elements
var formNodes = document.getElementsByTagName('form');
//loop through nodelist and add submit event and special class to each.
for(var i = 0; i < formNodes.length; i++){
formNodes[i].addEventListener('submit' , registerAction)
formNodes[i].className += "form-" + i;
}
/*This function captures the submitted form and determines
the action to carry out based off class name .
e.preventDefault will stop page from reloading in case of
making ajax requests.
*/
function registerAction(e){
e.preventDefault();
var formTarget = $(e.target).attr('class');
switch(formTarget){
case "form-0" :
// Do something ...
break;
case "form-1" :
// Do something else...
break;
default:
break;
}
return false;
}
Keep in mind that the logic inside registerAction can be alter to fit your needs
in this situation I used "case statement" because I feel it makes the most sense .
This is not perfect but I hope it gives you an idea..
The problem is that for example if a form has an ajax script on it, it
gets blocked by my additional script code.
No, it doesn't. You can bind many handlers on one element.
For rare cases, see the other suggestions, but If I got you right, your basic assumption was that binding a handler on an element cancel the previous one. Well, it doesn't.
It seems disabled button "onclick" function is still fired when triggering it programmaticaly, eg:
<div>
<input type="button" onclick="save()" id="saveButton" value="save" disabled="disabled" />
<input type="button" onclick="byPassDisabled()" value="bypass disabled button"/>
<div id="counter">0</div>
function save(){
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
function byPassDisabled(){
$('#saveButton').click();
}
see http://jsfiddle.net/WzEvs/363/
In my situation, keyboards shortcuts are bound to functions triggering the ".click()" on buttons. I'll find it very annoying to have to disable the shorcuts or check if the button is disabled myself. I'd prefer a general solution fixing this problem.
But why? This behavior doesn't seem fair to me.
Any workaround?
The attribute only disables user interaction, the button is still usable programmatically.
So yeah, you gotta check
function byPassDisabled(){
$('#saveButton:enabled').click();
}
Alternatively don't use inline handlers.
$(document).on('click', '#saveButton:enabled', function(){
// ...
});
For future use...the OP code works because jQuery will still call it's own handlers even if the DOM element is disabled. If one were to use vanilla javascript, the disabled attribute would be honored.
const element = document.getElementById('saveButton');
element.click() //this would not work
You can programmatically trigger click on a disabled button.
There are ways to find if the event is a click on button by user or it has been trigger programmatically. http://jsfiddle.net/WzEvs/373/
$(function () {
$("#saveButton").on('click', function (e) {
if (!e.isTrigger) {
var count = parseInt($('#counter').html());
$('#counter').html(++count);
}
});
$("#bypassButton").on('click', function (e) {
$("#saveButton").click();
});
});
e.isTrigger is true if you call the click() programmatically. Basically you are triggering the click event manually in code.
You can trigger click still although made it disable .As Spokey said it just shows the user-interaction(the usability still persists that can be turned on programmatically) .
off or unbind the click will solve this issue.
Thanks
I want to replace a button with an input field, where the user enters something and presses the enter button. After that, the button from the beginning should appear again. My script works so far but I can't repeat this once it finished.
Update: The button should also appear again, if the input field is shown but the user don't want to enter anything and clicks somewhere else.
The code:
<button id="createButton">Create item</button>
/*
jquery stuff
*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('#createButton').click(function( event ) {
$(this).replaceWith('<input type="text" id="buttonInput" placeholder="e.g. books, movies" autofocus>');
});
$(this).on('keypress', function (event) {
if(event.which == '13'){ // If enter button is pressed
alert('You entered something');
$('#buttonInput').replaceWith('<button id="createButton">Create item</button>');
}
});
});
</script>
Update 2: I updated the code with hide() and show() to get the same result. But how can I let the input disappear, if the user clicks somewhere inside the body, without redundancy?
The new code:
<button id="createButton">Create item</button>
<input type="text" id="input" placeholder="e.g. books, movies" autofocus>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
$('#input').hide();
$(document).on('click', '#createButton', function (event) {
$(this).hide();
$('#input').show().focus();
});
$('#input').on('keypress', function (event) {
if (event.which == '13') { // if enter button is pressed
$(this).hide().val('');
$('#createButton').show();
}
});
});
</script>
As the other answers say, you're replacing the element (createButton), which means the click handler is no longer bound.
You can either re-bind, or bind to the parent element, with the #createButton selector using on.
$(document).on('click','#createButton', function( event ) {
...
});
Don't actually use document - use whatever the parent element is, which doesn't get replace (a div, perhaps?)
Replacing DOM elements is a bad approach though -- you'd be better off leaving the elements on the page, and using show and hide.
http://jsfiddle.net/v03j8bns/
Updated Answer
Here's a fiddle showing the show/hide/ approach. To handle:
The button should also appear again, if the input field is shown but the user don't want to enter anything and clicks somewhere else.
When the button is clicked, I call focus() on the textbox. I've also hooked up a blur() event handler, so if the user clicks/tabs out, then it'll hide the textbox and show the button.
You have to bind the click event to newly created button again:
$(document).ready(function () {
$('#createButton').click(function (event) {
$(this).replaceWith('<input type="text" id="buttonInput" placeholder="e.g. books, movies" autofocus>');
});
$(this).on('keypress', function (event) {
if (event.which == '13') { // If enter button pressed
//Disable textbox to prevent multiple submit
alert('You entered something');
$('#buttonInput').replaceWith('<button id="createButton">Create item</button>');
}
$('#createButton').bind('click', function (event) {
$(this).replaceWith('<input type="text" id="buttonInput" placeholder="e.g. books, movies" autofocus>');
});
});
});
You have this issue because you replace DOM elements. It means that your new element button no longer has click handler.
I would recommend you to use something like show/hide or use jQuery delegate on/bind for handling click.
When you're changing DOM on the fly and want to automatically assign listeners to elements that may or may not exist at certain points of time, you need to use delegated event listeners.
$(document).on('click', '#createButton', function () { ... });
$(document).on('click', '#buttonInput', function () { ... });
These handlers will work however you scramble the DOM.
I'm trying to display error alert messages using bootstrap alerts. If a user submits the form with some fields empty, an error should be displayed. However when i click submit nothing is displayed.
JS
<script type="text/javascript">
$(document).ready(function () {
$('form[name="register"]').on("submit", function (e) {
var email = $(this).find('input[name="email"]');
if ($.trim(email.val()) === "") {
e.preventDefault();
$("#errorAlert").slideDown(400);
} else {
$("#errorAlert").slideUp(400, function () {
email.val("");
});
}
});
$(".alert").find(".close").on("click", function (e) {
e.stopPropagation();
e.preventDefault();
$(this).closest(".alert").slideUp(400);
});
});
</script>
HTML
<div class="alert hide" id="errorAlert">
<a class="close">×</a>
Oops!!. You may have left some fields empty. Please fill them out.
</div>
<form name="register" action="" method="post">
<input type="text" name="email" />
<input type="submit" class="btn" value="Submit" />
</form>
When i remove the "hide" class from the div above, the alert message comes up even before the form is submitted. If i then close the alert and submit the form, the alert isn't displayed. How do i get it working. Thanks in advance
on your $("#errorAlert").slideDown(400), add .removeClass('hide')
that would be $("#errorAlert").hide().slideDown(400).removeClass('hide').
I'm suspecting hide class has display:none!important. so we have to remove the class.
DEMO fiddle
Demo
jquery
$(document).ready(function () {
// Run this code only when the DOM (all elements) are ready
$('form[name="register"]').on("submit", function (e) {
// Find all <form>s with the name "register", and bind a "submit" event handler
// Find the <input /> element with the name "username"
var email = $(this).find('input[name="email"]');
if ($.trim(email.val()) === "") {
// If its value is empty
e.preventDefault(); // Stop the form from submitting
$("#errorAlert").slideDown(400); // Show the Alert
} else {
e.preventDefault(); // Not needed, just for demonstration
$("#errorAlert").slideUp(400, function () { // Hide the Alert (if visible)
alert("Would be submitting form"); // Not needed, just for demonstration
username.val(""); // Not needed, just for demonstration
});
}
});
$(".alert").find(".close").on("click", function (e) {
// Find all elements with the "alert" class, get all descendant elements with the class "close", and bind a "click" event handler
e.stopPropagation(); // Don't allow the click to bubble up the DOM
e.preventDefault(); // Don't let any default functionality occur (in case it's a link)
$(this).closest(".alert").slideUp(400); // Hide this specific Alert
});
});
The problem's pretty simple. .hide is not a good idea to use here because it contains display: none with !important following it, so even when you are trying to display the alert, this property overrides it.
You could create a simple css:
.hid{
display:none;
}
Add the hid as class to the alert box instead of hide.
DEMO
You could simply delete the hide class and add style="display:none;" to the $('#errorAlert') element. This way, the element will not appear on page load, and jQuery will manipulate the display property when using slide* functions. (it would never delete/add Bootstrap's hide class.)
See fiddle: http://jsfiddle.net/X2B9h/
UPDATED: http://jsfiddle.net/crw4K/
EDIT: Changing my answer because I haven't had my coffee yet.
Okay, so my changes to your code:
I removed the class 'hide' from the alert div, and added an inline style tag with 'display:none;'
Also, I removed the initial
$(".alert").find(".close")...
and changed it to just
$(".close").on("click"...
EDIT: I think I have found your problem. The .hide class in bootstrap is:
display:none !important;
which means it takes top priority over every other css for the element. Meaning that when you do slide down, the display:none !important is still taking priority.
You could either remove the class entirely, and add your own inline style tag (as I have in my answer) or you could remove the class with jquery.