So I have the following function. What it does is listens for the focus event on all elements. If that element is either in $mobileMenu or $menuItems it permits it otherwise it removes the focus:
var $body = $("body");
var $mobileMenu = $("#mobile-menu");
var $menuItems = $("#main-menu a");
$body.on("focus.spf", "*", function(e){
e.stopPropagation();
$this = $(this);
// Prevent items from recieving focus and switching view
if (!$this.is($mobileMenu) && !$this.is($menuItems)) {
$this.blur();
} else {
console.log(this);
}
})
The issue I have is that this prevents the user from focusing on anything whatsoever if a normally focusable element that is now non-focusable precedes any of my white-listed elements as it just attempts to refocus on the same element over and over again.
Does anyone know how I can tell it to instead skip to the next focusable element?
If you set the tabindex to -1 on the element, it will ignore the tab.
Not sure if this works in all browsers but it works in Google Chrome.
<input type='text' value='regular'/>
<input type='text' tabindex="-1" value='with tabindex set to -1'/>
This works (updated) :
$body.on("focus.spt", "*", function(e){
$this = $(this);
if (!$this.is($mobileMenu) && !$this.is($menuItems)) {
$this.blur();
var next=$this.nextAll().find('a,input');
if (next.length>0) next[0].focus();
} else {
console.log('ok',this);
e.stopPropagation();
}
})
(updated) fiddle -> http://jsfiddle.net/CADjc/
You can see in the console which elements that receives focus (main-menu a and mobile-menu)
Tested on :
<input type="text" tabindex="1" value="test">
<span><input type="text" tabindex="2" value="test"></span>
<div><input type="text" id="mobile-menu" tabindex="3" value="mobile-menu"></div>
<div><span>
<div id="main-menu">
<a tabindex="4">main-menu</a>
<a tabindex="5">main-menu</a>
</div>
</span></div>
<span>
<input type="text" tabindex="6" value="test">
</span>
If you make something disabled, it won't receive focus. For example:
<input type="text" disabled="disabled" />
Do add it programmatically, you could do:
var el = document.getElementById('disableme');
el.setAttribute('disabled', 'disabled');
attr("readonly","readonly"), prevent input focus and value ARE send to the server.
CSS-only solution from one of my past projects
/* Prevents all mouse interactions */
.disabled-div {
opacity: 0.5;
pointer-events: none;
}
/* Prevents all other focus events */
.disabled-div:focus,
.disabled-div:focus-within {
visibility: hidden;
}
<h1>CSS Only Disable with Prevent Focus</h1>
<input placeholder="Normal text field">
<br><br>
<input class="disabled-div" placeholder="Disabled text field">
<br><br>
<input placeholder="Normal text field">
<br><br>
<input class="disabled-div" placeholder="Disabled text field">
<br><br>
Flickers slightly when it receives focus. That is because when it receives focus, visibility is set to 'hidden' and focus is lost and visibility is set back to 'visible' again. This is actually good because the user now has some idea where focus is while going over disabled fields...
Related
There are two fields, subject and description and I want to add text where the cursor is. It means, if cursor is on description, it should add text in description and if cursor is on subject, it should add text on subject field.
one field is #subject
other one is #description
How I can achieve it?
<button type="button" class="btn btn-light mb-1" onclick="insertText('ticket_id')">Ticket ID</button>
function insertText(text)
{
// here will be code
}
inputs
<textarea class="form-control form-control-solid" rows="4" id="description" name="description" placeholder="Description"></textarea>
<input type="text" class="form-control form-control-solid" placeholder="Subject" name="subject" value="" />
There is a document.activeElement property, which contains currently focused element, but this will already be changed when click event occurs, so you'll need to use mousedown event, which happens before the focus changes to the button.
Then, element.selectionStart can be used to determine the cursor location. If you also need to replace selected text in the input you should use this in combination with element.selectionEnd and modify the click handler accordingly.
Here is an example:
ticketIdButton = document.getElementById('ticketIdButton')
ticketIdInput = null
ticketIdInputCursorLocation = 0
// In mousedown event document.activeElement has not changed yet
// which allows to keep track of previously focused input
ticketIdButton.addEventListener('mousedown', function() {
activeElement = document.activeElement
// For simplicity, let's use ticketIdInput class to identify
// the acceptable inputs for ticket id
if (activeElement.classList.contains('ticketIdInput')) {
ticketIdInput = activeElement
ticketIdInputCursorLocation = activeElement.selectionStart
}
else {
ticketIdInput = null
}
})
ticketIdButton.addEventListener('click', function() {
ticketId = '#1234'
if (ticketIdInput !== null) {
ticketIdInput.value = ticketIdInput.value.substring(0, ticketIdInputCursorLocation) + ticketId + ticketIdInput.value.substring(ticketIdInputCursorLocation)
}
})
<textarea id="description" class="ticketIdInput" placeholder="Description"></textarea><br />
<input id="subject" class="ticketIdInput" placeholder="Subject"><br />
<hr>
<button type="button" id="ticketIdButton">Ticket ID</button>
I have a HTML markup which looks like following:
<input type="number" step="0.1" min="0" max="100" value="1" class="form-control breakEvenInput" style="width:150px" /><br />
<button type="submit" class="btn btn-primary saveBreakEven">Save</button>
As you can see the input is of type "number"... What I was thinking (if it's possible) to do here is to disable the end user so that he/she is not able to input anything into the textbox, but rather enable the user just to have that side scrool up/down arrows that he gets when browser renders the HTML input as type of "number".
I've tried to add "disabled" or "readonly" properties to HTML input but that didn't give me the desired result. When I do it like that then the entire textbox is disabled...
I was thinking that this might be done somehow via jQuery? Can someone help me out ?
P.S. So i'd like to disable the input into the textbox via keyboard, but still leave the up/down arrows in textbox for the user to change the value, so that the user can't enter anything they want , let's say 99999999999 number.. ?
One of the things you can do is to prevent the keydown event.
$(function() {
$('input').on('keydown', function(e) {
e.preventDefault();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" step="0.1" min="0" max="100" value="1" class="form-control breakEvenInput" style="width:150px" /><br />
<button type="submit" class="btn btn-primary saveBreakEven">Save</button>
This way you keep the arrows active, but disable keyboard keys.
Inside the event object (e), you can also check what key was pressed (if you want to support backspace or arrows for example).
An issue you will have is different browsers support and render type="number" differently. I would suggest a span element for the number readout (ff you need to have it as an input, I would hide it), and use styled buttons or elements to increase, decrease the number and update the input box. This will give a uniform user experience across browsers.
<!--style these how you want-->
<span id="number">0</span>
<button id="add>Up</button><button id="sub">Down</button>
<script>
var step = 1;
var output = $('#number');
var up = $('#add');
var sub = $('#sub');
up.add(sub).on('click', function() {
var num = output.val();
num += ( $(this).attr('id') == 'add' ) ? step : (-1 * step);
if( isNumValid(num) ) {
output.val(num);
} else { <!-- error reporting here --> }
}
function isNumValid(num) {
<!-- run validations here, integer, float, positive, etc -->
return true/false;
}
</script>
$(function() {
$('input[type=number]').on('keydown', function(e){
e.preventDefault();
});
});
I would like to clear a text box when a radio button above the text box is selected.
I have tried this:
function clearThis(target){
target = document.getElementById(target);
target.value = "";
}
<input type="radio" name="not_req" id="clear_req" value=""
title="Click here to clear the No Auth need flag"><span id="clear" onclick = 'clearThis("claims")' >Clear
The box I would like to clear is
<input type="text" size="5" name="auth_for" id="claims" value="{$prior_auth->get_auth_for()}" title="Set the number of times no auth can be used">
Took most of this from http://jsfiddle.net/BMrUb/ but I can see that the example is clearing the adjacent text box. I would like to clear a text box not adjacent to the radio button.
As Gerald said place your onclick="" in the <input type="radio" ... >, not in the <span>.
The problem is that it's the sibling input element that needs its value clearing, not the span, even though you only want it to clear when people click on the span element. So the example code below does this. You're also best off decoupling your javascript from your HTML by using event listeners (and not using the old-fashioned onclick attribute).
var clearSpanEl = document.getElementById("clear");
clearSpanEl.addEventListener("click", function(e) {
var inputEl = e.target.previousElementSibling;
inputEl.value = "";
}, false);
<input type="text" name="search" id="search" value="I can be cleared" />
<span id="clear">Clear results</span>
I've forked your JSFiddle here, so you can see it working.
This is my code:
Javascript:
$(".test").on("focusout", function (e) {
$("#output").append("Lost focus<br>");
});
HTML:
Inputs inside div:
<div class="test">
<input type="text" />
<input type="text" />
</div><br>
Inputs outside div:<br>
<input type="text" />
<div id="output">
</div>
I want to detect if user leaves "div.test". Unfortunately, "focusout" works also when I move focus to other object inside this div.
Look at this fiddle: http://jsfiddle.net/Piotrek1/wfukje3g/6/
Click on first input and use Tab to switch through textboxes. "
Lost focus" should appear only if user move out from the div, but it happens always. Why is that and how to change it?
The $ operator returns a collection. You have two inputs inside the <div class="test">. So it matches all elements and children with the .test class.
I think what you want two divs with separate input elements and two different classes OR, use an ID on the actual input element so the $ operator only matches the input id you want this event to fire on. http://jsfiddle.net/wfukje3g/7/
$("#test").on("focusout", function (e) {
$("#output").append("Lost focus<br>");
});
<div class="sometest">
<input id="test" type="text" />
<input type="text" />
</div><br>
Inputs outside div:<br>
<input type="text" />
<div id="output">
</div>
I have implemented piece of code to handle div focus out
$(document).ready(function () {
var count = 1;
$("#name").focusout(function (e) {
if($(this).has(e.relatedTarget).length === 0) {
$("#output").append("<label style='width:100%;'>"+ count++ +" Name div focus out </label>");
}
});
});
Inputs inside div:
<div id="name" class="test">
<input type="text" id="firstname"/>
<input type="text" id="lastname"/>
</div>
Inputs outside div:<br>
<input type="text" id="dob"/>
<div id="output" style="width:100%"></div>
In this piece of code I have used relatedTarget.
relatedTarget will provide the next focused element If next element is not the child of this div then it is div focus out.
Try this in your code.
I hope this will be helpful.
Thanks
JSFIDDLE LINK - Sample code
I am implementing progressive UI disclosure pattern in my application. Using which I am disabling the next elements. So based on input of one element the next element is enabled.
But I have a problem is since the next element is disabled, the tab from the current element is taking the focus to the end of document or the tab header when tab out. As the progressive enables the element after the tab out, while this was happening the next element was not enabled so tab was lost outside the document.
So my requirement is to enable tab on the disabled elements and also on mobile/tablet devices the click events should at least be registered on the disabled elements. Please let me know your views on this.
Answer
To answer the question (as we already discussed in the comments), disabled elements can't be focused.
Workaround
For those looking for a workaround that gives a visual indication that an element is "disabled" and also prevents default functionality while still preserving focusability and click events, following is a simplified example where the submit button appears to be disabled and is prevented from "submitting" unless the input contains some text (also restores "disabled" state if input is cleared).
const input = document.querySelector('input');
const button = document.querySelector('button');
input.addEventListener('input', (event) => {
const target = event.currentTarget;
const next = target.nextElementSibling;
if (target.value) {
next.classList.remove('disabled');
} else {
next.classList.add('disabled');
}
});
button.addEventListener('click', (event) => {
const target = event.currentTarget;
if (target.classList.contains('disabled')) {
event.preventDefault();
console.log('not submitted');
} else {
console.log('submitted');
}
});
button {
background-color: #fff;
color: #0d47a1;
border: 2px solid #0d47a1;
}
button.disabled {
background-color: #e0e0e0;
color: #bdbdbd;
border: 2px solid #bdbdbd;
cursor: default;
}
button.disabled:focus {
outline: none;
}
<input type="text">
<button class="disabled">Submit</button>
You could add an event listener to the keydown event and listen for the tab key like in the code snippet,
document.addEventListener("keydown", keyDown);
function keyDown(e) {
switch (e.which) {
case 9:
var focused = $(document.activeElement);
var all_inputs = $("input");
var disabled_inputs = $("input[disabled='disabled']");
var diff = all_inputs.length - disabled_inputs.length;
var index = all_inputs.index(focused);
if (index == diff - 1 && index != -1 && disabled_inputs.length > 0) {
$(disabled_inputs[0]).removeAttr("disabled").focus();
e.preventDefault();
}
break;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input type="text" placeholder="this is not disabled!"> <br>
<input type="password" placeholder="this is not either!"> <br>
<input type="button" value="This is!" disabled="disabled"> <br>
<input type="submit" value="This is too!" disabled="disabled">
This will enable the element as you tab onto it. It doesn't effect normal behavior otherwise. I am assuming you don't want to re-disable the element after the focus leaves.
It is better if we have some part of the code to understand better your problem.
For this:
I am implementing progressive UI disclosure pattern in my application. Using which I am disabling the next elements. So based on input of one element the next element is enabled.
You must first handle an event for the first element and then in the callback function you need to enable/disable the second element, let say:
For enable:
$('#firstElement).on('click', function(){
$('#secondElement').removeAttr('disabled')
})
For disable:
$('#firstElement).on('click', function(){
$('#secondElement').attr('disabled', 'disabled')
})
Hope this could help.
On my idea a input event listener or change event listener for dropdown and input fields work better for your case.
E.g:
$(document).on('input','input',function()
{
$(this).next().prop('disabled',false);
}
or
$(document).on('change','input',function()
{
$(this).next().prop('disabled',false);
}
You can use tabindex attribute in this case. Please refer below code, you need to update tabindex of disabled elements in a way that they get skipped when you press tab.
as per w3schools
The tabindex attribute specifies the tab order of an element (when the
"tab" button is used for navigating).
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input class="input-1" tabindex="1" value="1">
<input class="input-2" tabindex="2" value="2">
<input type="button" onclick="changeTabIndex();" value="change-tab-index">
<input class="input-3" tabindex="3" value="3">
<input class="input-4" tabindex="4" value="4">
<input class="input-5" tabindex="5" value="5">
<script type="text/javascript">
function changeTabIndex() {
$(".input-5").attr("tabindex",4);
$(".input-4").attr("tabindex",5);
}
</script>