英文:
Resize `textarea` in other directions
问题
我创建了一个textarea
并调整其大小,以仅显示文本Title 1: value 1;
。然后,我选择了textarea中的所有文本并将该文本拖出来。我注意到在拖动时文本的预览与调整textarea大小后可见的文本部分相同。换句话说,在拖动文本时,Chrome浏览器不显示整个文本,而只显示在textarea中可见的部分。
我想在textarea中仅显示文本value 1;
。问题是调整textarea大小的按钮位于该元素的右下角。我想象如果该按钮也位于textarea的左上角,它仍然需要隐藏左侧的文本。
我还没有找到解决这个问题的方法。我也不知道是否有其他HTML元素可以替代textarea以仅显示我需要的文本。
英文:
I created a textarea
and resized it to show just the text Title 1: value 1;
. Then I selected all the text in the textarea and dragged that text out of it. I noticed that the preview of the text while dragging is identical to the part of the text visible after resizing the textarea. In other words, when dragging the text out, the Chrome browser does not show the whole text, but only the part that is visible in the textarea.
I want to make visible in the textarea only the text value 1;
. The problem is that the button that resizes the textarea is located at the bottom right of this element. I imagine that if that button was also on the top left of the textarea it would still need to hide the text to the left.
I haven't found a way to resolve this. I also don't know if another html element can replace the textarea to show only the text I need.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
document.querySelector('textarea').select()
<!-- language: lang-css -->
textarea {
width: 145px;
height: 15px;
}
<!-- language: lang-html -->
<textarea>Title 1: value 1; Title 2: value 2;</textarea>
<!-- end snippet -->
答案1
得分: 2
以下是您要翻译的内容:
"After some thought, this might be a solution for you (your last comment also taken into account). UPDATE: Fore more flexibility a more appropriate solution has been appended at the end.
The key was to use the text-indent property on
// required vars
let el, visibleText, visibleTextLength;
// get specific textarea
el = document.querySelector( 'textarea' );
// extract desired text that remains visible
visibleText = el.value.split( '; ' )[0].split( ': ')[1];
// get text length of extracted text
visibleTextLength = visibleText.length;
// add the cols attribute to the textarea
el.setAttribute( 'cols', visibleTextLength );
// selects all the text in the textarea
el.select();
textarea {
width: auto;
max-width: 100px;
height: 15px;
font-size: 14px;
text-indent: -70px;
white-space: nowrap;
overflow: hidden;
resize: none;
}
UPDATE: A MORE APPROPRIATE SOLUTION
Due to the text-indent dilemma I revised and improved my solution again to get more flexibility. So what changes have been made?
First,
If you don't use the script's styling options and create your own CSS rule for
- padding - setting left and right to 0 is recommended
- height - can be customized according to your needs
- max-width - set it to none if width is not an issue
- line-height - set to 1 should be fine for general use
- font-family - a monoytpe font is highly recommended
- font-size - can be customized according to your needs
Further, as already mentioned, text-ident no longer has to be adjusted manually when the length of the "before-text" changes, where "before-text" is the text before the visible text. The issue was solved by inserting a temporary at the end of the page and placing the "before-text" there. The width can now be derived from this and used for the text-intend. The element is removed from the flow and the visibility is set to hidden so as not to break the design. Once width has been calculated, is automatically removed again.
/* Options */
const TxtArea = {
// textarea element ID (string)
elID: 'demo-area',
// text block separator (string)
txtSep: '; ',
// sub text separator (string)
subSep: ': ',
// cut separator from visible text (bool)
cutSep: false,
// invoke event handler only once (bool)
evOnce: true,
// event handler trigger (string)
trigger: 'DOMContentLoaded',
// textarea styling (object)
// set
styles: {
'padding': '0', // (string)
'height': '15px', // (string)
'max-width': '100px', // (string)
'font-family': 'monospace', // (string)
'font-size': '14px', // (string)
'line-height': '1' // (string)
}
};
/* Script */
TxtArea.init = document.addEventListener( TxtArea.trigger, ( event ) => ( ( opts ) => {
let el,
elStyle,
tempElm,
txtSep = '',
subSep = '',
fullText = '',
firstText = '',
beforeText = '',
visibleText = '',
beforeTextLength = 0,
visibleTextLength = 0,
tempElmIdentifier = 'temp-12345678';
// get specific textarea
el = document.getElementById( opts.elID );
// check if it's a textarea
if ( el.tagName.toLowerCase() !== 'textarea' ) {
console.log( '[ ERROR ] : Custom ID is not assigned to a textarea.' );
return false;
}
// get textarea CSS properties
elStyle = window.getComputedStyle( el, null );
// set required properties
el.style.width = 'auto';
el.style.whiteSpace = 'nowrap';
el.style.overflow = 'hidden';
el.style.resize = 'none';
// set custom properties
for ( let property in opts.styles ) {
if ( opts.styles.hasOwnProperty( property ) && opts.styles[property] !== false ) {
el.style[property] = opts.styles[property];
} else {
el.style[property] = elStyle.getPropertyValue( property );
}
}
// trim separators
txtSep = opts.txtSep.replace( /^\s+|\s+$/g, '' );
subSep = opts.subSep.replace( /^\s+|\s+$/g, '' );
// get text from textarea
fullText = el.value;
// extract first text block
firstText = fullText.split( txtSep )[0];
// extract text before visible text
beforeText = firstText.split( subSep )[0];
// extract visible text
visibleText = firstText.split( subSep )[1];
// get text length of extracted text
visibleTextLength = visibleText.length;
// cut separator from visible text
if ( opts.cutSep === true ) {
visibleTextLength--;
}
// create a temporary element to detect beforeText length
document.body.appendChild(
Object.assign(
document.createElement( 'span' ), {
id: tempElmIdentifier,
style: 'position: absolute; visibility: hidden; width: auto; height: auto; white-space: nowrap;',
innerHTML: beforeText + opts.subSep.replace( / /g, ' ' )
}
)
);
// get temporary element
tempElm = document.getElementById( tempElmIdentifier );
// assign additional properties
tempElm.style.zIndex = -9999;
英文:
After some thought, this might be a solution for you (your last comment also taken into account). UPDATE: Fore more flexibility a more appropriate solution has been appended at the end.
The key was to use the text-indent
property on <textarea>
and give it a negative value. A few lines of JavaScript are also required (it's self-explanatory since commented). However, it should be mentioned that width
of <textarea>
varies as it adapts to the visible text. In order to be able to control this behavior at least somewhat, I've set a max-width
for <textarea>
. Furthermore, the value for the text-ident
has to be adjusted every time the text before the visible text changes.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
// required vars
let el, visibleText, visibleTextLength;
// get specific textarea
el = document.querySelector( 'textarea' );
// extract desired text that remains visible
visibleText = el.value.split( ';' )[0].split( ':' )[1];
// get text length of extracted text
visibleTextLength = visibleText.length;
// add the cols attribute to the textarea
el.setAttribute( 'cols', visibleTextLength );
// selects all the text in the textarea
el.select();
<!-- language: lang-css -->
textarea {
width: auto;
max-width: 100px;
height: 15px;
font-size: 14px;
text-indent: -70px;
white-space: nowrap;
overflow: hidden;
resize: none;
}
<!-- language: lang-html -->
<textarea>Title 1: value 1; Title 2: value 2;</textarea>
<!-- end snippet -->
UPDATE: A MORE APPROPRIATE SOLUTION
Due to the text-indent
dilemma I revised and improved my solution again to get more flexibility. So what changes have been made?
First, <textarea>
must now have an ID
assigned to make things work. If the ID
is assigned to an element other than a <textarea>
, the script exits. Also, an additional CSS part is no longer required to set mandatory style properties. The styling can be handled via script options, but doesn't have to, the old way still works and even has to be used if you want more styling for <textarea>
. Things like font-color
, background-color
, border
and the like were not taken into account.
If you don't use the script's styling options and create your own CSS rule for <textarea>
instead, it MUST contain and have set the following properties to achieve the desired result:
padding
- settingleft
andright
to0
is recommendedheight
- can be customized according to your needsmax-width
- set it tonone
ifwidth
is not an issueline-height
- set to1
should be fine for general usefont-family
- a monoytpe font is highly recommendedfont-size
- can be customized according to your needs
Further, as already mentioned, text-ident
no longer has to be adjusted manually when the length of the "before-text" changes, where "before-text" is the text before the visible text. The issue was solved by inserting a temporary <span>
at the end of the page and placing the "before-text" there. The width
can now be derived from this and used for the text-intend
. The <span>
element is removed from the flow and the visibility
is set to hidden
so as not to break the design. Once width
has been calculated, <span>
is automatically removed again.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
/* Options */
const TxtArea = {
// textarea element ID (string)
elID: 'demo-area',
// text block separator (string)
txtSep: '; ',
// sub text separator (string)
subSep: ': ',
// cut separator from visible text (bool)
cutSep: false,
// invoke event handler only once (bool)
evOnce: true,
// event handler trigger (string)
trigger: 'DOMContentLoaded',
// textarea styling (object)
// set <prop>: false to use CSS value
styles: {
'padding': '0', // (string)
'height': '15px', // (string)
'max-width': '100px', // (string)
'font-family': 'monospace', // (string)
'font-size': '14px', // (string)
'line-height': '1' // (string)
}
};
/* Script */
TxtArea.init = document.addEventListener( TxtArea.trigger, ( event ) => ( ( opts ) => {
let el,
elStyle,
tempElm,
txtSep = '',
subSep = '',
fullText = '',
firstText = '',
beforeText = '',
visibleText = '',
beforeTextLength = 0,
visibleTextLength = 0,
tempElmIdentifier = 'temp-12345678';
// get specific textarea
el = document.getElementById( opts.elID );
// check if it's a textarea
if ( el.tagName.toLowerCase() !== 'textarea' ) {
console.log( '[ ERROR ] : Custom ID is not assigned to a textarea.' );
return false;
}
// get textarea CSS properties
elStyle = window.getComputedStyle( el, null );
// set required properties
el.style.width = 'auto';
el.style.whiteSpace = 'nowrap';
el.style.overflow = 'hidden';
el.style.resize = 'none';
// set custom properties
for ( let property in opts.styles ) {
if ( opts.styles.hasOwnProperty( property ) && opts.styles[property] !== false ) {
el.style[property] = opts.styles[property];
} else {
el.style[property] = elStyle.getPropertyValue( property );
}
}
// trim separators
txtSep = opts.txtSep.replace( /^\s+|\s+$/g, '' );
subSep = opts.subSep.replace( /^\s+|\s+$/g, '' );
// get text from textarea
fullText = el.value;
// extract first text block
firstText = fullText.split( txtSep )[0];
// extract text before visible text
beforeText = firstText.split( subSep )[0];
// extract visible text
visibleText = firstText.split( subSep )[1];
// get text length of extracted text
visibleTextLength = visibleText.length;
// cut separator from visible text
if ( opts.cutSep === true ) {
visibleTextLength--;
}
// create a temporary element to detect beforeText length
document.body.appendChild(
Object.assign(
document.createElement( 'span' ), {
id: tempElmIdentifier,
style: 'position: absolute; visibility: hidden; width: auto; height: auto; white-space: nowrap;',
innerHTML: beforeText + opts.subSep.replace( / /g, '&nbsp;' )
}
)
);
// get temporary element
tempElm = document.getElementById( tempElmIdentifier );
// assign additional properties
tempElm.style.zIndex = -9999;
tempElm.style.left = 0;
tempElm.style.top = 0;
// apply required styles from the textarea to the created element
tempElm.style.fontFamily = elStyle.getPropertyValue( 'font-family' );
tempElm.style.fontSize = parseFloat( elStyle.getPropertyValue( 'font-size' ) ) + 'px';
// get beforeText length
beforeTextLength = tempElm.clientWidth;
// remove temporary element
tempElm.remove();
// adjust textarea's text-indent
el.style.textIndent = '-' + beforeTextLength + 'px';
// add cols attribute to the textarea
el.setAttribute( 'cols', visibleTextLength );
// select all text within textarea
el.select();
} ) ( TxtArea ), { once: TxtArea.evOnce } );
<!-- language: lang-css -->
textarea {
/* additional styling goes here */
}
<!-- language: lang-html -->
<textarea id="demo-area">Titel 1: value 1; Title 2: value 2;</textarea>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论