英文:
Issue with focusing on input with Javascript
问题
我有一个按钮,当它获得焦点时,会使包含输入框的 div 变为可见:
<button class="edit-path-btn " style="float:right" onfocus='makeFocus()'>click to show</button>
<div class="edit-path-container ">
    <input id="in" type="text" value="test">
</div>
在这里,您可以单击输入框并编辑文本,如果单击其他地方,容器将按预期消失。我已经添加了一些 JavaScript 代码,以便将焦点设置到输入框,以便用户可以立即开始输入,但容器永远不会变得可见。有没有办法修复这个问题?
英文:
I have a button that when it has focus will make a div containing an input become visible:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function makeFocus() {
	//document.getElementById('in').focus();
}
<!-- language: lang-css -->
.edit-path-container {
	display: none;
	height: 100%;
}
.edit-path-btn:focus + .edit-path-container {
	display: block;
}
.edit-path-container:focus-within, .edit-path-container:active {
	display: block !important;
}
<!-- language: lang-html -->
<button class="edit-path-btn " style="float:right" onfocus='makeFocus()'>click to show</button>
<div class="edit-path-container ">
	<input id="in" type="text" value="test">
</div>
<!-- end snippet -->
Here you can click in the input and edit the text, if you click away the container will disappear as intended.
I have added some JavaScript to give the input focus so the user can start typing straight away but the container never becomes visible. Is there a way to fix this?
答案1
得分: 1
我认为你可以这样做:
function switchFocus() {
  const input = document.getElementById('in');
  input.parentElement.classList.toggle('invisible');
  if (!input.parentElement.classList.contains('invisible')) {
    input.focus();
  }
}
.invisible {
    display: none;
}
<button class="edit-path-btn " style="float:right" onclick='switchFocus()'>click to show</button>
<div id="in-container" class="edit-path-container invisible">
    <input id="in" type="text" value="test" onblur="switchFocus()">
</div>
英文:
I think you can do like that :
<!-- begin snippet: js hide: false console: true babel: null -->
<!-- language: lang-js -->
function switchFocus() {
  const input = document.getElementById('in');
  input.parentElement.classList.toggle('invisible');
  if (!input.parentElement.classList.contains('invisible')) {
    input.focus();
  }
}
<!-- language: lang-css -->
.invisible {
    display: none;
}
<!-- language: lang-html -->
<button class="edit-path-btn " style="float:right" onclick='switchFocus()'>click to show</button>
<div id="in-container" class="edit-path-container invisible">
    <input id="in" type="text" value="test" onblur="switchFocus()">
</div>
<!-- end snippet -->
答案2
得分: 1
代码部分不要翻译。
英文:
The problem with how it works is the blur event fires before the focus happens so the element hides as you try to focus it.
Only way I can see to get around it with how your HTML code is written is to add a temp class that makes it visible and you can then remove that temp class after you focus it or use all JavaScript.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function makeFocus() {
  var inp = document.getElementById('in');
  inp.classList.add('active');
  inp.focus();
  inp.classList.remove('active');
}
<!-- language: lang-css -->
.edit-path-container {
  display: none;
  height: 100%;
}
.edit-path-btn:focus+.edit-path-container {
  display: block;
}
.edit-path-container:focus-within,
.edit-path-container:active,
.edit-path-container:has(.active) {
  display: block !important;
}
<!-- language: lang-html -->
<button class="edit-path-btn " style="float:right" onfocus='makeFocus()'>click to show</button>
<div class="edit-path-container ">
	<input id="in" type="text" value="test">
</div>
<!-- end snippet -->
答案3
得分: 1
简化了基本的 CSS,但后来又添加了一些内容以解决页面上放置 float 时的问题。
更改摘要:
- 在元素上使用事件
 - 从 HTML 中移除事件附加并将其放入代码中
 - 为了清晰起见,使用自定义事件
 - 文本字段的失焦/模糊将使用 
'blur'事件隐藏它 - 关键部分:使用元素上的属性作为切换机制显示/隐藏其容器包装器
 - 也可以为 "custom" 效果添加多个值。例如,添加一个新值以同时显示它并显示相关内容,例如在失焦时显示相邻的兄弟元素;诸如此类。参考链接:https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
 - 大量过多的控制台日志以展示何时/何处发生的情况
 
<-- begin snippet: js hide: false console: true babel: false -->
<-- language: lang-js -->
let editPathButton = document.querySelector('.edit-path-btn');
let textInputFoFocus = document.querySelector('.text-input-for-focus');
const focusEvent = new Event("focus");
const makeVisibleEvent = new Event("makevisible");
editPathButton.addEventListener('click', makeFocus, false);
function makeFocus(event) {
  console.log("here");
  textInputFoFocus.dispatchEvent(makeVisibleEvent);
}
textInputFoFocus.addEventListener("blur", (event) => {
  console.log("here in blur");
  event.target.dataset.showonfocus = "hide";
});
textInputFoFocus.addEventListener("makevisible", event => {
  console.log("here in custom");
  event.target.dataset.showonfocus = "show";
  event.target.focus()
  console.log(event.target.outerHTML);
});
textInputFoFocus.addEventListener("focus", (event) => {
  console.log("here in focus; start typing");
});
<-- language: lang-css -->
body {
  font-size: 16px;
  margin: 0;
  padding: 0;
  box-sizing: border;
}
.container-wrapper {
  display: grid;
  grid-template: columns: 1fr auto;
  justify-content: space-between;
  height: 3rem;
  padding: 1rem;
}
.edit-path-btn {
  grid-column: 2;
  grid-row: 1;
  height: 1.5rem;
}
.edit-path-container {
  grid-column: 1;
  grid-row: 1;
  display: none;
  height: 100%;
}
.edit-path-container:has(> .text-input-for-focus[data-showonfocus="show"]) {
  display: block;
}
<-- language: lang-html -->
<div class="container-wrapper">
  <button class="edit-path-btn">Click to show and focus text edit</button>
  <div class="edit-path-container">
    <label for="in">Edit Me:</label>
    <input class="text-input-for-focus" id="in" type="text" value="test" data-showonfocus="hide">
  </div>
</div>
<-- end snippet -->
英文:
Basic CSS I simplified but then added some more to remove the problematic float when placed on a page.
Change summary:
- Used events on the elements
 - Removed event attachment from HTML and put it in code
 - Used a custom event just for clarity
 - Focus out/blur on the text fields will hide it using the 
'blur'event - Key part Used an attribute on the element to show/hide its container wrapper as a toggle mechanism
 - Can also have multiple values for "custom" effects. For example add a new value to both show it and show a related for example to show an adjacent sibling when the blur happens; things like that. ref: https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator
 - Lots of excess console logs to show what happens when/where
 
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let editPathButton = document.querySelector('.edit-path-btn');
let textInputFoFocus = document.querySelector('.text-input-for-focus');
const focusEvent = new Event("focus");
const makeVisibleEvent = new Event("makevisible");
editPathButton.addEventListener('click', makeFocus, false);
function makeFocus(event) {
  console.log("here");
  textInputFoFocus.dispatchEvent(makeVisibleEvent);
}
textInputFoFocus.addEventListener("blur", (event) => {
  console.log("here in blur");
  event.target.dataset.showonfocus = "hide";
});
textInputFoFocus.addEventListener("makevisible", event => {
  console.log("here in custom");
  event.target.dataset.showonfocus = "show";
  event.target.focus()
  console.log(event.target.outerHTML);
});
textInputFoFocus.addEventListener("focus", (event) => {
  console.log("here in focus; start typing");
});
<!-- language: lang-css -->
body {
  font-size: 16px;
  margin: 0;
  padding: 0;
  box-sizing: border;
}
.container-wrapper {
  display: grid;
  grid-template: columns: 1fr auto;
  justify-content: space-between;
  height: 3rem;
  padding: 1rem;
}
.edit-path-btn {
  grid-column: 2;
  grid-row: 1;
  height: 1.5rem;
}
.edit-path-container {
  grid-column: 1;
  grid-row: 1;
  display: none;
  height: 100%;
}
.edit-path-container:has(> .text-input-for-focus[data-showonfocus="show"]) {
  display: block;
}
<!-- language: lang-html -->
<div class="container-wrapper">
  <button class="edit-path-btn">Click to show and focus text edit</button>
  <div class="edit-path-container">
    <label for="in">Edit Me:</label>
    <input class="text-input-for-focus" id="in" type="text" value="test" data-showonfocus="hide">
  </div>
</div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论