Onblur triggering everywhere - javascript

Update
It appears that the input is locked until I input a well formatted email address and then and only then is the element able to be unlock/unfocus. That is just weird, because if I can't focus any other element then how can the unfocus event get trigger when the current element is still focus. Do you suppose it has to do with something on the server side then?
So I have this piece of code that has an input html generated by the server so I can not directly do the onblur=function() in the tag. Instead I use the onclick event of the td to bind an event handler to the input.
<td id="emailInput" class="label" onclick="emailValidation(event);">
#Html.EditorFor(model => Model.EmailAddress, new { Class = "ignore"})
</td>
<td id="emailValidate" style="display: none">
<label>Please enter a valid email address</label>
</td>
in the Javascript file I bind the event handler like so:
function emailValidation(e) {
$(e.target).on("blur", function () {
console.log("what target e is");
console.log(e.target);
var inputVal = $(e.target).val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
$(e.target).focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
});
}
I check the dev console and e.target is the input element I want. What is happening is that the onblur event in being trigger after it has been appended and the input is unfocus even though the input element is no longer focus, and I am just clicking random area in the screen. Am I mis-understanding something? Is there a better definition that I can get than the w3school, the developer.mozilla, and this weird one
EDIT
I was trying to create a JSfiddle (w/o server stuff) to demonstrate and it worked fine so upon closer inspection I see the the input element is not being unfocus. It does not matter where I click the cursor remains in the text area, and no other element can be focus now.
Edit 2
As requested the JSFiddle, but it works here but not on the one with server side stuff

Here is a working fiddle:
http://jsfiddle.net/Mn5E4/1/
$("#emailMe").on("blur", function () {
var inputVal = $(this).val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
$("#emailMe").focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
});
You don't need to bother with using the click event to attach the handler since you know the id of the input you want to bind to.
Edit: Note that this is a fork of your jsFiddle. Based on the code in your question, I would expect the id of the desired input element to be "EmailAddress", in which case you would replace $("#emailMe") with $("#EmailAddress").
Edit2: You can take out any guesswork by doing this:
<td id="emailInput" class="label">
#Html.EditorFor(model => Model.EmailAddress, new { #class = "ignore validateEmail"})
</td>
<td id="emailValidate" style="display: none">
<label>Please enter a valid email address</label>
</td>
<script type='text/javascript'>
$(".validateEmail").on("blur", function () {
var inputVal = $(this).val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
$(".validateEmail").focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
});
</script>
Note that I passed another class into the EditorFor helper and changed how the class attribute was named to use # to escape the lower case name "class".

Please try this aproach:
<td id="emailInput" class="label" onclick="emailValidation(event);">
#Html.EditorFor(model => Model.EmailAddress, new { Class = "ignore"})
</td>
$("#emailInput").on('focusin', "input", function (e) {
var inputobj = $(this);
var inputVal = inputobj.val();
var re = /[A-z0-9]*[\.?[\w+]+[A-z0-9]+#[A-z0-9][\.?[\w+]+\.[A-z][A-z][A-z]/;
if (!re.test(inputVal)) {
inputobj.focus();
$("#emailValidate").css("display", "inline-block");
} else {
$("#emailValidate").css("display", "none");
}
})
Note: Not tested

You should use $(this)
var inputVal = $(this).val();

Related

DOM equivalent to jQuery `.detach()`?

I’m trying to remove an input field by clicking an “X button”. After it is removed it will not post its value when the form is submitted. A “+ button” appears that allows the user to add said input again. The input has an onclick event that opens a calendar and after reattaching, the calendar does not open on click anymore. I can’t use jQuery.
adderBtn.onclick = function (e) {
var elem = that.hiddenElems.shift();
that.collectionItemContainer.append(elem);
}
removerBtn.onclick = function (e) {
collectionItemElem.remove();
that.hiddenElems.push(collectionItemElem);
}
The question is how do I remove and reattach DOM nodes without losing the Events.
When you remove an element, as long as you keep a reference to it, you can put it back. So:
var input = /*...code to get the input element*/;
input.parentNode.removeChild(input); // Or on modern browsers: `input.remove();`
later if you want to put it back
someParentElement.appendChild(input);
Unlike jQuery, the DOM doesn't distinguish between "remove" and "detach" — the DOM operation is always the equivalent of "detach," meaning if you add the element back, it still has its handlers:
Live Example:
var input = document.querySelector("input[type=text]");
input.addEventListener("input", function() {
console.log("input event: " + this.value);
});
input.focus();
var parent = input.parentNode;
document.querySelector("input[type=button]").addEventListener("click", function() {
if (input.parentNode) {
// Remove it
parent.removeChild(input);
} else {
// Put it back
parent.appendChild(input);
}
});
<form>
<div>
Type in the input to see events from it
</div>
<label>
Input:
<input type="text">
</label>
<div>
<input type="button" value="Toggle Field">
</div>
</form>
If you remove the element without keeping any reference to it, it is eligible for garbage collection, as are any handlers attached to it (provided nothing else refers to them, and ignoring some historic IE bugs in that regard...).
To detach an element in function form:
function detatch(elem) {
return elem.parentElement.removeChild(elem);
}
This will return the 'detached' element

e.preventDefault() behvaing differently

I have a very simple jQuery UI spinner as follows:
<input value="2" class="form-control ui-spinner-input" id="spinner" aria-valuemin="2" aria-valuemax="24" aria-valuenow="2" autocomplete="off" role="spinbutton" type="text">
Using jQuery I set the above text box readonly true/false. The readonly and value is set based on the checkbox a user selects and that function looks like
function checkBoxes() {
var $targetCheckBoxes = $("#BoxFailure,#InstallationFailure");
$targetCheckBoxes.change(function () {
var isChecked = this.checked;
var currentElement = this;
var $radioButton = $('.usage-failure-type-radio');
$targetCheckBoxes.filter(function () {
return this.id !== currentElement.id;
}).prop('disabled', isChecked);
$('#spinner').val(isChecked ? this.value : '').prop('readonly', isChecked);
$radioButton.first().prop('checked', isChecked);
$radioButton.not(':checked').toggle(!isChecked).parent('label').toggle(!isChecked);
$('.usage-before-failure > div > span.ui-spinner > a').toggle(!isChecked);
});
}
Now what I'm trying to achieve is when the #spinner input is readonly and if the user presses the back space I want to prevent the default behaviour e.g. do navigate away from the page. For this I thought I'd do the following:
$('.prevent-default').keydown(function (e) {
e.preventDefault();
});
Which works fine if the input has the class prevent-default on page load. However, if I add it in my checkBoxes function in the following line
$('#spinner').val(isChecked ? this.value : '').prop('readonly', isChecked).toggleClass('prevent-default')
Then I press the backspace it ignores e.prevenDefault();
But if I do
$('#spinner').val(isChecked ? this.value : '').prop('readonly', isChecked).keydown(function (e) { e.preventDefault(); });
Then it works absolutely fine.
Can someone tell me why this is happening please.
The reason I want to use a separate function with a class name is because I have various inputs which get set to read only based on different check/radio values.
Can someone tell me why this is happening please
This is because of the DOM parser and the timing when JavaScript is executed.
If you already have an element with a class prevent-default in your DOM before JS is executed, then the JavaScript will recognise and handle it correctly. If you instead add the class afterwards with JS, then you have to re-initialise the keydown-event again to make it work.
To re-initialise you will need something like this:
function checkBoxes() {
var $targetCheckBoxes = $("#BoxFailure,#InstallationFailure");
$targetCheckBoxes.change(function () {
...
$('#spinner').val(isChecked ? this.value : '').prop('readonly', isChecked).toggleClass('prevent-default');
// assign new keydown events
handleKeyDown();
...
});
}
function handleKeyDown() {
// release all keydown events
$('#spinner').off( "keydown", "**" );
$('.prevent-default').keydown(function (e) {
e.preventDefault();
// do more stuff...
});
}

Disable a particular span using jQuery

I am creating a calendar event app where you can save people's birthday dates and edit people's names or dates whenever you want.
To display stored events I am using a forEach loop in JSP. I have a span named ld-option-okay-edit in each div. You can edit previous data after you click on that span and save your data.
But before clicking on the save button I am checking whether any field in a particular div is empty or not, using a jQuery hover function.
If any field is empty then I am disabling the span element so that it can't forward request to the servlet, but the problem is I am not able to disable it.
??????
THE PROBLEM
???????
My question is how can I disable a span through jQuery, or how can I prevent the onclick event of a span using jQuery?
Here is my code:
<c:forEach items="${relativeUser}" var="user">
<div class="elementsdiv">
<form action="<c:url value=" ******">" method="post">
<div class="cld-option-okay" >
<span class="glyphicon glyphicon-ok cld-option-okay-edit" name="cld-option-okay-edit" ></span>
</div>
<div class="cld-option-name" >
<input class="cld-name-input" value="${user.name}" placeholder="Name of the person" type="text" name="name">
</div>
</form>
</div>
</c:forEach>
What I have tried until now in jQuery is:
$(".elementsdiv").each(function (i, data) {
$($(data).find('.cld-option-okay')).hover(function (e) {
e.preventDefault();
if ($($(data).find('input[name="name"]')).val() === "") {
$($(data).find('span[name="cld-option-okay-edit"]')).addClass('disabled');//in this line i am getting trouble
}
}
});
For that line I even tried:
1)$($(data).find('span[name="cld-option-okay-edit"]')).attr("disabled","true");//with single quote also
2)$($(data).find('span[name="cld-option-okay-edit"]')).attr("disabled","disabled");//with single quote also
3).prop("disabled", true );
4).attr('disabled', '');
5).attr("disabled", "disabled");
6).off( "click", "**" );
7).unbind( "click", handler );
but when I apply:
`$($(data).find('span[name="cld-option-okay-edit"]')).hide()`;//it is applying
**********************
`$($(data).find('span[name="cld-option-okay-edit"]'))`till here code is working fine my problem is in applying disable.
previously i applied disable like below
$('.cld-option-okay-edit').addClass('disabled');
but it disables okay span in all divs
*************************
For enable or disable a span, you could do it like this:
var isEmpty = false;
$('#myDiv > input').keyup(function(){
isEmpty = false;
$('#myDiv > input').each(function(i,obj){
if(this.value == ""){
isEmpty = true;
return false;
}
});
// Styles for the span.
if( ! isEmpty){
$('#myDiv > span').removeClass('disabled');
} else {
$('#myDiv > span').addClass('disabled');
}
});
$('#myDiv > span').click(function(){
if(isEmpty){
alert("disabled");
} else {
alert("enabled");
}
});
I think this is what your code should look like based on what you have written, but I am not sure it is actually what you want to happen. If you want to disable it, you need to use prop()
$(".elementsdiv").each(function() {
var elem = $(this);
elem.find('.cld-option-okay').hover(function(e) {
if (elem.find('input[name="name"]').val() === "") {
elem.find('span[name="cld-option-okay-edit"]').addClass('disabled'); /*.prop("disabled",true); */
}
});
});

JQuery function not firing on enter keypress

I have the following jQuery/js controlling a trello style input field. So when you click on the span element, it switches to an input field. Then after you finish editing the element and take focus away from it(blur), it switches back to the span element with the new text. I also having it submitting to an ajax script to submit the new text to my database.
Now this all works flawlessly and I have no problems with what is described above. The problem came when I tried to make the "switch back to the span element" work on "enter" key press.
I have tested the code with an alert so I know the enter key is being detected but I can not get the "editableTextBlurred" function to fire from within the keypress function. Which means that it will not switch back to the span element on enter press.
function divClicked(div) {
div = "#"+div;
var divHtml = $(div).text();
var editableText = $('<input type="text" id="firstname" name="firstname" placeholder="First Name" onChange="profileUpdate(this)">');
editableText.val(divHtml);
$(div).replaceWith(editableText);
editableText.focus();
console.log(editableText);
// setup the blur event for this new textarea
editableText.blur(editableTextBlurred);
$(":input").keypress(function(event) {
if (event.which == '13') {
event.preventDefault();
editableTextBlurred();
}
});
}
function editableTextBlurred() {
var html = $(this).val();
var viewableText = $("<span id='firtname_text' onClick='divClicked(this.id)'></span>");
viewableText.html(html);
$(this).replaceWith(viewableText);
}
<span id='firtname_text' onClick='divClicked(this.id)'>
".ucfirst($fname)."
</span>
Any insight on what I missing or doing wrong will be greatly appreciated,
Thanks!
I suspect it's successfully calling editableTextBlurred, but then that function isn't working. And the reason it's not working is that it expects this to refer to the input element, but the way you're calling it, this will be the global object (in loose mode) or undefined (in strict mode).
To make the this in editableTextBlurred the same as the this in the keypress handler, use .call:
editableTextBlurred.call(this);
Alternately, just pass the element as an argument:
editableTextBlurred(this);
...and then
function editableTextBlurred(input) {
var html = $(input).val();
var viewableText = $("");
viewableText.html(html);
$(input).replaceWith(viewableText);
}
Separately, there's a problem with that onClick code, it will end up with this.id (the actual text) in the onClick attribute. You probably wanted:
var viewableText = $("<span id='firtname_text' onClick='divClicked(\"'" + input.id + "'\")'></span>");
...though I wouldn't use onClick for this at all; use jQuery.
Rather than adding/removing event handlers, this is the kind of situation that cries out for event delegation:
// Delegated handler for converting to inputs
$("#container").on("click", ".click-to-edit", function(e) {
var $div = $(this),
$input = $("<input type=text>");
$div.toggleClass("click-to-edit editing");
$input.val($div.text());
$div.empty().append($input);
setTimeout(function() { // Some browsers want this delay
$input.focus();
}, 50);
});
// Delegated handler for converting back
$("#container").on("keypress", ".editing input", function(event) {
var $input = $(this), $div;
if (event.which == 13) {
event.preventDefault();
$div = $input.closest(".editing");
$div.toggleClass("click-to-edit editing");
$div.empty().text($input.val());
}
});
<div id="container">
<div class="click-to-edit">Testing 1 2 3</div>
<div class="click-to-edit">Testing 4 5 6</div>
<div class="click-to-edit">Testing 7 8 9</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Get a field with jQuery when a button is clicked

I have a table full of appointments. Every appointment has two buttons. One for canceling the event, one for accepting it.
I am struggling to get the appointmentId in the jQuery function when I click on a button. Can you please give me a hint how to do this? The appointmentId is in the table as a hidden input field.
// my html code
<tr>
<td align="left">
<input type="hidden" name="appointmentId" value="234">
John Smith - 14.03.2013 at 9 o'clock
</td>
<td align="right">
<input type="button" id="acceptEvent" class="acceptEvent" value="Accept">
<input type="button" id="cancelEvent" class="cancelEvent" value="Cancel">
</td>
</tr>
// my jQuery code
$("body").delegate('.acceptEvent', 'click', function() {
console.log('accept event clicked');
// get the appointmentId here
});
$("body").delegate('.cancelEvent', 'click', function() {
console.log('cancel event clicked');
// get the appointmentId here
});
Use closest to grab the parent tr element, then select your hidden field.
The reason that this is the correct answer is because it takes the context of the click event with $(this). Then it travels up the DOM tree to your root table row element and selects the child by name. This ensures that you are always in the correct row.
EDIT: I know you already selected an answer, but this was really bothering me that it wasn't working properly. I had to walk down twice using .children() to get it to work though you could also use .find('input[name="appointmentId"]'). Even though you've already selected your answer, I hope this will help you.
$('.acceptEvent').click(function() {
var myVal = $(this).closest('tr').children().children().val();
});
$('.cancelEvent').click(function() {
var myVal = $(this).closest('tr').children().children().val();
});
In the click function, you have access to the button that was clicked with this so you can do:
$("body").on('click', '.cancelEvent', function() {
var input = $(this).closest('tr').find('input[name="appointmentId"]').val();
});
Assuming you have no other IDs or classes to key off of, you can use jQuery's Attribute Equals Selector in reference to the clicked button's parent tr element:
$('.acceptEvent').click(function() {
// get the appointmentId here
var appointmentId = $(this).closest('tr').find('input[name="appointmentId"]').val();
});
I'll do it like that :
$("body").on('.acceptEvent', 'click', function() {
var id = $('input[name="appointmentId"]').val();
//Or search in the parent <tr>
var id = $(this).parent().find('input[name="appointmentId"]').val();
console.log('accept event clicked');
console.log('Id is ' + id);
});

Categories

Resources