【问题标题】:Dynamically expand <input> element with text使用文本动态扩展 <input> 元素
【发布时间】:2016-04-20 08:19:39
【问题描述】:

我觉得这应该很容易。我已经搜索/尝试了至少一个星期,但仍然无济于事。

我想要一个带有占位符文本的 &lt;input&gt; 元素。我希望元素仅与占位符文本一样宽。当您单击&lt;input&gt; 时,我希望宽度保持不变。在您键入时,如果您的输入文本超出了原始占位符文本的宽度(因此也超出了 &lt;input&gt; 元素本身),我希望 &lt;input&gt; 扩展以容纳文本。

有什么想法吗?

【问题讨论】:

标签: javascript html css


【解决方案1】:

这是一个考虑不同字体大小、不同字符宽度等的工作解决方案的尝试(在原版javascript):

function reviewWidth(startWidth) {

/* Grab various elements */
var hiddenSpan = document.getElementsByClassName('hidden')[0];
var inputValue = document.getElementsByTagName('input')[0].value;

/* Update text content of hiddenSpan */
hiddenSpan.innerHTML = inputValue;

/* Update <input> width */
var hiddenSpanStyles = getComputedStyle(hiddenSpan);
var newWidth = parseInt(hiddenSpanStyles.getPropertyValue('width'));

if (newWidth > startWidth) {
    input.style.width = newWidth + 'px';
}

else {
    input.style.width = startWidth + 'px';	
}

}

/* Grab various elements */
var body = document.getElementsByTagName('body')[0];
var input = document.getElementsByTagName('input')[0];
var placeholder = input.getAttribute('placeholder');

/* Create hiddenSpan */
var hiddenSpan = document.createElement('span');
var placeholderText = document.createTextNode(placeholder);
hiddenSpan.appendChild(placeholderText);

/* Style hiddenSpan */
var inputStyles = getComputedStyle(input);
hiddenSpan.style.fontFamily = inputStyles.getPropertyValue('font-family');
hiddenSpan.style.fontSize = inputStyles.getPropertyValue('font-size');
hiddenSpan.style.borderLeftWidth = inputStyles.getPropertyValue('border-left-width');
hiddenSpan.style.paddingLeft = inputStyles.getPropertyValue('padding-left');
hiddenSpan.style.paddingRight = inputStyles.getPropertyValue('padding-right');
hiddenSpan.style.borderRightWidth = inputStyles.getPropertyValue('border-right-width');
hiddenSpan.style.display = 'inline-block';
hiddenSpan.style.opacity = '0';
hiddenSpan.classList.add('hidden');

/* Add hiddenSpan to document body */
body.appendChild(hiddenSpan);

/* Initialise <input> width */
var hiddenSpanStyles = getComputedStyle(hiddenSpan);
var startWidth = parseInt(hiddenSpanStyles.getPropertyValue('width'));
input.style.width = startWidth + 'px';

/* Run reviewWidth() function once */
if (input.value != '') {
    reviewWidth(startWidth);
}


/* Add Event Listener to <input> to trigger reviewWidth() function */
input.addEventListener('input',function(){reviewWidth(startWidth);},false);
input {
font-family: arial, sans-serif;
font-size: 0.8em;
padding: 2px;
}
&lt;input type="text" placeholder="Example Placeholder" /&gt;

【讨论】:

  • border-width 怎么样?虽然你还没有设置一个,但我很确定这会影响input 元素相对于span 的宽度。另外,我认为你可以听keydown,所以响应速度没有延迟。
  • 您对border-width 的看法是正确的——感谢@Patrick。实际上应该是border-left-width + padding-left + padding-right + border-right-width。我将更新上面的帖子以反映这些改进。另一方面,它必须是keyup,而不是keydownkeypress,否则inputValue 会短1 个字符。
  • 哦,那就试试input,而不是keydown
  • 太棒了!我什至不知道input 事件。非常感谢您的宝贵补充。如果这个答案有任何积分,我可以给你一半吗?
  • 运行 Chrome 版本 47.0.2526.111,而且不太对。
【解决方案2】:

我对@Rounin 的回答添加了一些小的改进,以进行我自己的尝试:

  • 解析 HTML 中的连续空格会压缩为一个空格,除非它们是不间断的,因此我将 映射到 &amp;nbsp。此外,我将&amp;lt; 映射到&amp;lt; 以转义HTML。我没有使用textContent 而不是innerHTML 的原因是因为无法将不间断空格注入textContent
  • 隐藏的 span 在不需要时不再是 DOM 的一部分,因此当它太宽时不会触发父元素滚动。
  • width 的像素值实际上是浮点数,而不是整数,因此使用 parseFloat 代替 parseInt 会使 &lt;input/&gt; 的宽度更精确。
  • 我精简了一些代码以减少冗长,同时努力保持可读性。

/* Set up */
var regExp = /[ <]/g;

function replacer(c) {
  return {
    ' ': '&nbsp;',
    '<': '&lt;'
  }[c];
}

/* Grab various elements */
var body = document.querySelector('body');
var input = document.querySelector('input');
var placeholder = input.getAttribute('placeholder');

/* Create hiddenSpan */
var hiddenSpan = document.createElement('span');
hiddenSpan.innerHTML = placeholder.replace(regExp, replacer);

/* Style hiddenSpan */
var inputStyles = getComputedStyle(input);

['font', 'padding', 'border', 'display'].forEach(function(prop) {
  hiddenSpan.style[prop] = inputStyles.getPropertyValue(prop);
});

hiddenSpan.style.visibility = 'hidden';
hiddenSpan.style.pointerEvents = 'none';

var hiddenSpanStyles = getComputedStyle(hiddenSpan);

/* Initialise <input> width */
body.appendChild(hiddenSpan);

var startWidth = parseFloat(hiddenSpanStyles.getPropertyValue('width'));

body.removeChild(hiddenSpan);

function reviewWidth() {
  var inputValue = input.value;

  /* Update text content of hiddenSpan */
  hiddenSpan.innerHTML = inputValue.replace(regExp, replacer);

  body.appendChild(hiddenSpan);

  /* Update <input> width */
  var newWidth = parseFloat(hiddenSpanStyles.getPropertyValue('width'));

  body.removeChild(hiddenSpan);

  if (newWidth > startWidth) {
    input.style.width = newWidth + 'px';
  } else {
    input.style.width = startWidth + 'px';
  }
}

reviewWidth();

/* Add Event Listener to <input> to trigger reviewWidth() function */
input.addEventListener('input', reviewWidth, false);
input {
  font-family: arial, sans-serif;
  font-size: 0.8em;
  padding: 2px;
}
&lt;input type="text" placeholder="Example Placeholder" /&gt;

如果您对改进此答案有任何问题或建议,请随时离开 cmets。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-23
    • 1970-01-01
    • 1970-01-01
    • 2018-05-12
    • 1970-01-01
    相关资源
    最近更新 更多