Toggle state of textbox with javascript using a button - javascript

I have a form as follows:
<form>
<label for="input">Input:</label>
<input type="text" id="input" maxlength="3"></input>
<button type="button" id="lock" onMouseDown="toggleInput()"></button>
</form>
And javascript code:
function toggleInput(){
if ($("#input").disabled){
$("#input").disabled = false;
}
else {
$("#input").disabled = true;
};
}
What I basically want to do is to check what state (enabled/disabled) the textbox is in, and then toggle the state accordingly. I don't know if the javascript portion even uses the correct syntax to check if the textbox is disabled, but it's what I could think of.
Thanks in advance!
EDIT: Reason as to why I've chosen to use onmousedown instead of onclick to execute the event with the button:
I have chosen to use onmousedown instead of onclick as it makes the app I'm building feel less clunky due to the presence of this feature with onclick: When you click on a button and then drag the cursor away from the button while holding the mouse button down, and subsequently lift your finger off the mouse button when the cursor is in an area away from the button on the webpage, the event will not be executed. Hence, I've chosen to use onmousedown as this is overcome.

Use .prop(), Get the value of a property for the first element in the set of matched elements or set one or more properties for every matched element
$("#input").prop('disabled',!$("#input").prop('disabled'))
DEMO
I am not sure why you are using onMouseDown. Use click instead
$("#lock").on("click", function() {
$("#input").prop('disabled',!$("#input").prop('disabled'))
});
DEMO with click

To do it with jQuery try this:
$("#input").prop("disabled", function(i, v) { return !v; });
Your existing code doesn't work because DOM elements have a .disabled property, but jQuery objects do not.
I'm not sure why you're using onmousedown instead of onclick for the button, but either way if you're going to use jQuery I'd recommend removing the inline event attribute in favour of binding the handler with jQuery:
$("#lock").on("click", function() {
$("#input").prop("disabled", function(i, v) { return !v; });
});
(You'd need to include that code either in a script block at the end of the body or in a document ready handler.)
Demo: http://jsfiddle.net/a7f8v/

You should append the event handler with jQuery instead of an onMouseDown event. The syntax could look like this:
<label for="input">Input:</label>
<input type="text" id="input" maxlength="3"></input>
<button type="button" id="lock"></button>
JavaScript:
$(document).ready(function() {
$("#lock").click(function() {
var input = $("#input");
input.prop('disabled',!input.is(':disabled'))
});
});
Example

Related

Why is jQuery select event listener triggering multiple times?

Please run this sample in Google Chrome browser.
Stack Snippet
$(function() {
$(":input").select(function() {
$("div").text("Something was selected").show().fadeOut(1000);
alert("Selected");
});
$("button").click(function() {
$(":input").select();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text">
<div></div>
Here why jQuery select event listener is triggering multiple times? Does anyone know the reason behind this? And is there any workaround solution for this without using timeout?
The $(":input") selector is selecting the button too, so it causes recursion. Either use just $("input"), or $(":input:not(button)").
I noticed when the three events are fired, the first doesn't have originalEvent property, so we definitely can dismiss it, and the second two has very similar (however not identical) timestamp. You can store the last timestamp in some variable and in event listener compare it with the event's timestamp. If the rounded values of these two are the same, you can dismiss this event.
$(function() {
var lastTimeStamp;
$("input").select(function(event) {
if (!event.originalEvent ||
lastTimeStamp === Math.round(event.timeStamp)) return;
lastTimeStamp = Math.round(event.timeStamp);
$("div").text("Something was selected").show().fadeOut(1000);
alert("Selected");
});
$("button").click(function() {
$("input").select();
});
});
See updated JS Fiddle.
It appears the issue is a combination of:
the :input selector gets the input and the button, hence multiple events triggered.
even when using just input as the selector there is some odd event propagation being triggered on related elements which is raising the select event handler multiple times.
To avoid both of the above, use input as the selector and also use preventDefault() in the event handler. stopPropagation() may also be required, depending on your HTML stucture.
$(function() {
$('input').select(function(e) {
// e.stopPropagation(); // optional
e.preventDefault();
$('#message').text("Something was selected").show().fadeOut(1000);
console.log('Selected');
});
$('button').click(function() {
$('input').select();
});
});
Working example
UPDATE: We were all fooled. The select() function needs a prevent default.
Rory McCrossan figured it out. Well done mate.
Incidentally, I'm not sure what the benefit of select() actually is! Something like focus() or on('focus',) might make more sense. Not Sure what the context is however. The below still follows:
Why waste time using generalised tag/type selectors which may change? Use an ID, and pick out only the one you want.
If you want to detect multiple, use a class. If you want to use multiple, but figure out which one you clicked, use a class and an ID. Bind with the class, and identify using $this.attr('id').
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<button>Click To Select</button>
<input type="text" value="Some text" id="pick-me">
<div></div>
$(function() {
$("#pick-me").select(function(event) {
event.preventDefault();
$("div").text("Something was selected").show().fadeOut(1000);
alert("Selected");
});
$("button").click(function() {
$("#pick-me").select();
});
});

how to fire event on label text change

I'm trying to fire a function when the label text changes. This is my code
$("#frameItemCode").change(function (e) {
alert("Changed");
});
#frameItemCode is my label id, but the event isn't firing. I have tried examples given before but they hasn't helped me.This is my html
<div class="input-group">
<span class="input-group-addon" #*style="width: 120px;"*#>Item Group</span>
<label class="input-group-addon" #*style="width: 120px;"*# id="frameGroupCode"></label>
<input class="form-control" type="text" id="frameGroupName" style="">
</div>
Take a look at the documentation for the change event. It only fires for specific types of elements:
The change event is fired for <input>, <select>, and <textarea> elements when a change to the element's value is committed by the user...
You won't be able to use the change event for an element that is not one of the previously mentioned types.
If you have some other way of knowing that editing has finished of a specific element, you'll have to fire your own event - possibly using the blur event on the element that was used to change the value. The blur event is triggered when the selected element looses focus such as when a user clicks (or tabs) out of an input element.
For label .change() will not work, So you can try something like this by using trigger() which call our custom event, here fnLabelChanged is my custom event
.change() event worked for <input> , <textarea> ,<select> .i.e
$("button").on('click',function(){
$("#frameGroupCode").text("Hello").trigger("fnLabelChanged");
});
$("#frameGroupCode").on('fnLabelChanged', function(){
console.log('changed');
})
Working Demo
You can get the current text of the label and check if the value is different on keyup or when pressing a button. The change event doesn't work for non form elements.
If you use, $("#frameItemCode").text('abc') to change the lable (as you commented), just call the alert("changed") after that. No need to define an event listener..
$("#frameItemCode").text('abc');
alert("changed");
If the label changes in several ways, define a timeInterval to check if the label has changed,
function inspectLabel(callback){
var label = $("#frameItemCode").text();
setInterval(function(){
var newlabel = $("#frameItemCode").text();
if (newlabel != label){
callback();
label = newlabel;
}
}, 100);
}
inspectLabel(function(){
alert('changed');
});
Depending on which browsers you need to support, you can use MutationObserver:
var observer = new MutationObserver(
function (mutations) {
alert('Label was changed!');
}
);
observer.observe(document.querySelector('#frameGroupCode'), { childList: true });
Example jsFiddle
I don't think label has change() event associated with it, if you want to achive it, then it can be done through JQuery or JS. Because changing label text dynamically is done through Jquery or JS.
Instead, you can create a function and call it when the label is being changed from your function where the lable text change takes place.

Can't detect changed id

When I change the id of a button I cannot find the new id with on.("click"). The function console.log() does detect that it's changed but I cannot detect it with the on() function.
HTML:
<form id="formName" action="" method="post">
<input type="submit" id="submitBtn" value="Submit" />
</form>
<button id="change">Change</button>
JS:
$("#change").on("click", function(){
$("#submitBtn").attr("id", "NewBtn");
});
$("#formName").submit(function(e){
e.preventDefault();
});
$("#NewBtn").on("click", function(){
alert("Hello");
});
So I need it to alert "Hello" after I have clicked on change. It does change the id I checked that with inspect element.
Fiddle: http://jsfiddle.net/WvbXX/
Change
$("#NewBtn").on("click", function(){
to
$(document).on("click", "#NewBtn", function(){
The reason for this is that you're wanting to use the delegate form of .on(). This call is a little different in that it takes a "string" as the second parameter. That string is the selector for your "dynamic" element while the main selector need either be a parent container (not created dynamically) or the document itself.
jsFiddle
you are setting onclick event for newBtn on load of page for the first time but unfortunately newBtn not available that time. hence after changing the id it will not trigger onclick function for newBtn.
you can do one thing to make it work, set onclick event for newBtn inside the same function where you are changing the id like below.
$("#change").on("click", function(){
$("#submitBtn").attr("id", "NewBtn");
// set on click event for new button
$("#NewBtn").on("click", function(){
alert("Hello");
});
});
.attr() function does not have a callback and thus it cannot be checked unless you setup an interval using setInterval but the function itself executes pretty soon so you are not going to need it.
For solving the problem in hand event delegation proposed by tymeJV is the right way to do it.

Prevent icon inside disabled button from triggering click?

Trying to figure out proper way to make a click event not fire on the icon of a disabled link. The problem is when you click the Icon, it triggers the click event. I need the selector to include child objects(I think) so that clicking them triggers the event whenever the link is enabled, but it needs to exclude the children when the parent is disabled.
Links get disabled attribute set dynamically AFTER page load. That's why I'm using .on
Demo here:(New link, forgot to set link to disabled)
http://jsfiddle.net/f5Ytj/9/
<div class="container">
<div class="hero-unit">
<h1>Bootstrap jsFiddle Skeleton</h1>
<p>Fork this fiddle to test your Bootstrap stuff.</p>
<p>
<a class="btn" disabled>
<i class="icon-file"></i>
Test
</a>
</p>
</div>
</diV>​
$('.btn').on('click', ':not([disabled])', function () { alert("test"); });​
Update:
I feel like I'm not using .on right, because it doesn't take the $('.btn') into account, only searching child events. So I find myself doing things like $('someParentElement').on or $('body').on, one being more difficult to maintain because it assumes the elements appear in a certain context(someone moves the link and now the javascript breaks) and the second method I think is inefficient.
Here is a second example that works properly in both enabled/disabled scenarios, but I feel like having to first select the parent element is really bad, because the event will break if someone rearranges the page layout:
http://jsfiddle.net/f5Ytj/32/
Don't use event delegation if you only want to listen for clicks on the .btn element itself:
$('.btn').on('click', function() {
if (!this.hasAttribute("disabled"))
alert("test");
});​
If you'd use event delegation, the button would need to be the matching element:
$(someParent).on('click', '.btn:not([disabled])', function(e) {
alert('test!!');
});​
Demo
Or use a true button, which can really be disabled:
<button class="btn" [disabled]><span class="file-icon" /> Test</button>
Demo, disabled.
Here, no click event will fire at all when disabled, because it's a proper form element instead of a simple anchor. Just use
$('.btn').on('click', function() {
if (!this.disabled) // check actually not needed
this.diabled = true;
var that = this;
// async action:
setTimeout(function() {
that.disabled = false;
}, 1000);
});​
.on('click', ':not([disabled])'
^ This means that, since the icon is a child of the button ".btn", and it is not disabled, the function will execute.
Either disable the icon, also, or apply the event listener only to the <a> tag that is your button, or use e.stopPropagation();
I would suggest using e.stopPropagation();, this should prevent the icon from responding to the click.
That doesn't seem to work for me ^
Disabling the icon, however, does.
I would prefer to add the event using delegation here as you are trying to base the event based on the attributes of the element.
You can add a check condition to see if you want to run the code or not.
$('.container').on('click', '.btn', function() {
if( $(this).attr('disabled') !== 'disabled'){
alert('test!!');
}
});​
Check Fiddle
You're not using the selector properly.
$('.btn').not('[disabled]').on('click', function () {
alert("test");
});​
See it live here.
Edit:
$('.container').on('click', '.btn:not([disabled])', function () {
alert("test");
});​
I think what you need is:
e.stopPropagation();
See: http://api.jquery.com/event.stopPropagation/
Basically something like the following should work
$('.icon-file').on('click', function(event){event.stopPropagation();});
You may want to add some logic to only stop bubbling the event when the button ist disabled.
Update:
not sure, but this selector should work:
$('.btn:disabled .icon-file')

When a 'blur' event occurs, how can I find out which element focus went *to*?

Suppose I attach an blur function to an HTML input box like this:
<input id="myInput" onblur="function() { ... }"></input>
Is there a way to get the ID of the element which caused the blur event to fire (the element which was clicked) inside the function? How?
For example, suppose I have a span like this:
<span id="mySpan">Hello World</span>
If I click the span right after the input element has focus, the input element will lose its focus. How does the function know that it was mySpan that was clicked?
PS: If the onclick event of the span would occur before the onblur event of the input element my problem would be solved, because I could set some status value indicating a specific element had been clicked.
PPS: The background of this problem is that I want to trigger an AJAX autocompleter control externally (from a clickable element) to show its suggestions, without the suggestions disappearing immediately because of the blur event on the input element. So I want to check in the blur function if one specific element has been clicked, and if so, ignore the blur event.
2015 answer: according to UI Events, you can use the relatedTarget property of the event:
Used to identify a secondary EventTarget related to a Focus
event, depending on the type of event.
For blur events,
relatedTarget: event target receiving focus.
Example:
function blurListener(event) {
event.target.className = 'blurred';
if(event.relatedTarget)
event.relatedTarget.className = 'focused';
}
[].forEach.call(document.querySelectorAll('input'), function(el) {
el.addEventListener('blur', blurListener, false);
});
.blurred { background: orange }
.focused { background: lime }
<p>Blurred elements will become orange.</p>
<p>Focused elements should become lime.</p>
<input /><input /><input />
Note Firefox won't support relatedTarget until version 48 (bug 962251, MDN).
Hmm... In Firefox, you can use explicitOriginalTarget to pull the element that was clicked on. I expected toElement to do the same for IE, but it does not appear to work... However, you can pull the newly-focused element from the document:
function showBlur(ev)
{
var target = ev.explicitOriginalTarget||document.activeElement;
document.getElementById("focused").value =
target ? target.id||target.tagName||target : '';
}
...
<button id="btn1" onblur="showBlur(event)">Button 1</button>
<button id="btn2" onblur="showBlur(event)">Button 2</button>
<button id="btn3" onblur="showBlur(event)">Button 3</button>
<input id="focused" type="text" disabled="disabled" />
Caveat: This technique does not work for focus changes caused by tabbing through fields with the keyboard, and does not work at all in Chrome or Safari. The big problem with using activeElement (except in IE) is that it is not consistently updated until after the blur event has been processed, and may have no valid value at all during processing! This can be mitigated with a variation on the technique Michiel ended up using:
function showBlur(ev)
{
// Use timeout to delay examination of activeElement until after blur/focus
// events have been processed.
setTimeout(function()
{
var target = document.activeElement;
document.getElementById("focused").value =
target ? target.id||target.tagName||target : '';
}, 1);
}
This should work in most modern browsers (tested in Chrome, IE, and Firefox), with the caveat that Chrome does not set focus on buttons that are clicked (vs. tabbed to).
I solved it eventually with a timeout on the onblur event (thanks to the advice of a friend who is not StackOverflow):
<input id="myInput" onblur="setTimeout(function() {alert(clickSrc);},200);"></input>
<span onclick="clickSrc='mySpan';" id="mySpan">Hello World</span>
Works both in FF and IE.
It's possible to use mousedown event of document instead of blur:
$(document).mousedown(function(){
if ($(event.target).attr("id") == "mySpan") {
// some process
}
});
The instance of type FocusEvent has the relatedTarget property, however, up to version 47 of the FF, specifically, this attribute returns null, from 48 it already works.
You can see more here.
Works in Google Chrome v66.x, Mozilla v59.x and Microsoft Edge... Solution with jQuery.
I test in Internet Explorer 9 and not supported.
$("#YourElement").blur(function(e){
var InputTarget = $(e.relatedTarget).attr("id"); // GET ID Element
console.log(InputTarget);
if(target == "YourId") { // If you want validate or make a action to specfic element
... // your code
}
});
Comment your test in others internet explorer versions.
I am also trying to make Autocompleter ignore blurring if a specific element clicked and have a working solution, but for only Firefox due to explicitOriginalTarget
Autocompleter.Base.prototype.onBlur = Autocompleter.Base.prototype.onBlur.wrap(
function(origfunc, ev) {
if ($(this.options.ignoreBlurEventElement)) {
var newTargetElement = (ev.explicitOriginalTarget.nodeType == 3 ? ev.explicitOriginalTarget.parentNode : ev.explicitOriginalTarget);
if (!newTargetElement.descendantOf($(this.options.ignoreBlurEventElement))) {
return origfunc(ev);
}
}
}
);
This code wraps default onBlur method of Autocompleter and checks if ignoreBlurEventElement parameters is set. if it is set, it checks everytime to see if clicked element is ignoreBlurEventElement or not. If it is, Autocompleter does not cal onBlur, else it calls onBlur. The only problem with this is that it only works in Firefox because explicitOriginalTarget property is Mozilla specific . Now I am trying to find a different way than using explicitOriginalTarget. The solution you have mentioned requires you to add onclick behaviour manually to the element. If I can't manage to solve explicitOriginalTarget issue, I guess I will follow your solution.
Can you reverse what you're checking and when? That is if you remeber what was blurred last:
<input id="myInput" onblur="lastBlurred=this;"></input>
and then in the onClick for your span, call function() with both objects:
<span id="mySpan" onClick="function(lastBlurred, this);">Hello World</span>
Your function could then decide whether or not to trigger the Ajax.AutoCompleter control. The function has the clicked object and the blurred object. The onBlur has already happened so it won't make the suggestions disappear.
Use something like this:
var myVar = null;
And then inside your function:
myVar = fldID;
And then:
setTimeout(setFocus,1000)
And then:
function setFocus(){ document.getElementById(fldID).focus(); }
Final code:
<html>
<head>
<script type="text/javascript">
function somefunction(){
var myVar = null;
myVar = document.getElementById('myInput');
if(myVar.value=='')
setTimeout(setFocusOnJobTitle,1000);
else
myVar.value='Success';
}
function setFocusOnJobTitle(){
document.getElementById('myInput').focus();
}
</script>
</head>
<body>
<label id="jobTitleId" for="myInput">Job Title</label>
<input id="myInput" onblur="somefunction();"></input>
</body>
</html>
i think it's not possibe,
with IE you can try to use window.event.toElement, but it dosn't work with firefox!
You can fix IE with :
event.currentTarget.firstChild.ownerDocument.activeElement
It looks like "explicitOriginalTarget" for FF.
Antoine And J
As noted in this answer, you can check the value of document.activeElement. document is a global variable, so you don't have to do any magic to use it in your onBlur handler:
function myOnBlur(e) {
if(document.activeElement ===
document.getElementById('elementToCheckForFocus')) {
// Focus went where we expected!
// ...
}
}
document.activeElement could be a parent node (for example body node because it is in a temporary phase switching from a target to another), so it is not usable for your scope
ev.explicitOriginalTarget is not always valued
So the best way is to use onclick on body event for understanding indirectly your node(event.target) is on blur
Edit:
A hacky way to do it would be to create a variable that keeps track of focus for every element you care about. So, if you care that 'myInput' lost focus, set a variable to it on focus.
<script type="text/javascript">
var lastFocusedElement;
</script>
<input id="myInput" onFocus="lastFocusedElement=this;" />
Original Answer:
You can pass 'this' to the function.
<input id="myInput" onblur="function(this){
var theId = this.id; // will be 'myInput'
}" />
I suggest using global variables blurfrom and blurto. Then, configure all elements you care about to assign their position in the DOM to the variable blurfrom when they lose focus. Additionally, configure them so that gaining focus sets the variable blurto to their position in the DOM. Then, you could use another function altogether to analyze the blurfrom and blurto data.
keep in mind, that the solution with explicitOriginalTarget does not work for text-input-to-text-input jumps.
try to replace buttons with the following text-inputs and you will see the difference:
<input id="btn1" onblur="showBlur(event)" value="text1">
<input id="btn2" onblur="showBlur(event)" value="text2">
<input id="btn3" onblur="showBlur(event)" value="text3">
I've been playing with this same feature and found out that FF, IE, Chrome and Opera have the ability to provide the source element of an event. I haven't tested Safari but my guess is it might have something similar.
$('#Form').keyup(function (e) {
var ctrl = null;
if (e.originalEvent.explicitOriginalTarget) { // FF
ctrl = e.originalEvent.explicitOriginalTarget;
}
else if (e.originalEvent.srcElement) { // IE, Chrome and Opera
ctrl = e.originalEvent.srcElement;
}
//...
});
I do not like using timeout when coding javascript so I would do it the opposite way of Michiel Borkent. (Did not try the code behind but you should get the idea).
<input id="myInput" onblur="blured = this.id;"></input>
<span onfocus = "sortOfCallback(this.id)" id="mySpan">Hello World</span>
In the head something like that
<head>
<script type="text/javascript">
function sortOfCallback(id){
bluredElement = document.getElementById(blured);
// Do whatever you want on the blured element with the id of the focus element
}
</script>
</head>
I wrote an alternative solution how to make any element focusable and "blurable".
It's based on making an element as contentEditable and hiding visually it and disabling edit mode itself:
el.addEventListener("keydown", function(e) {
e.preventDefault();
e.stopPropagation();
});
el.addEventListener("blur", cbBlur);
el.contentEditable = true;
DEMO
Note: Tested in Chrome, Firefox, and Safari (OS X). Not sure about IE.
Related: I was searching for a solution for VueJs, so for those who interested/curious how to implement such functionality using Vue Focusable directive, please take a look.
I see only hacks in the answers, but there's actually a builtin solution very easy to use :
Basically you can capture the focus element like this:
const focusedElement = document.activeElement
https://developer.mozilla.org/en-US/docs/Web/API/DocumentOrShadowRoot/activeElement
This way:
<script type="text/javascript">
function yourFunction(element) {
alert(element);
}
</script>
<input id="myinput" onblur="yourFunction(this)">
Or if you attach the listener via JavaScript (jQuery in this example):
var input = $('#myinput').blur(function() {
alert(this);
});
Edit: sorry. I misread the question.
I think its easily possible via jquery by passing the reference of the field causing the onblur event in "this".
For e.g.
<input type="text" id="text1" onblur="showMessageOnOnblur(this)">
function showMessageOnOnblur(field){
alert($(field).attr("id"));
}
Thanks
Monika
You could make it like this:
<script type="text/javascript">
function myFunction(thisElement)
{
document.getElementByName(thisElement)[0];
}
</script>
<input type="text" name="txtInput1" onBlur="myFunction(this.name)"/>

Categories

Resources