web-dev-qa-db-fra.com

Utilisez l'onglet pour mettre en retrait dans textarea

J'ai un simple texte HTML de mon côté. À l'heure actuelle, si vous cliquez sur l'onglet, le champ suivant apparaît. Je voudrais faire le retrait du bouton de tabulation de quelques espaces à la place. Comment puis-je faire ceci? Merci.

121
user780483

Emprunter fortement d’autres réponses pour des questions similaires (posté ci-dessous) ...

$(document).delegate('#textbox', 'keydown', function(e) {
  var keyCode = e.keyCode || e.which;

  if (keyCode == 9) {
    e.preventDefault();
    var start = this.selectionStart;
    var end = this.selectionEnd;

    // set textarea value to: text before caret + tab + text after caret
    $(this).val($(this).val().substring(0, start)
                + "\t"
                + $(this).val().substring(end));

    // put caret at right position again
    this.selectionStart =
    this.selectionEnd = start + 1;
  }
});

jQuery: comment capturer la touche TAB dans une zone de texte

Comment gérer <tab> dans textarea?

http://jsfiddle.net/jz6J5/

109
kasdega
var textareas = document.getElementsByTagName('textarea');
var count = textareas.length;
for(var i=0;i<count;i++){
    textareas[i].onkeydown = function(e){
        if(e.keyCode==9 || e.which==9){
            e.preventDefault();
            var s = this.selectionStart;
            this.value = this.value.substring(0,this.selectionStart) + "\t" + this.value.substring(this.selectionEnd);
            this.selectionEnd = s+1; 
        }
    }
}

Cette solution ne nécessite pas jQuery et activera la fonctionnalité de tabulation sur tous les espaces de texte d'une page.

45
user1949974

Comme d'autres l'ont écrit, vous pouvez utiliser JavaScript pour capturer l'événement, empêcher l'action par défaut (afin que le curseur ne se décale pas) et insérer un caractère de tabulation.

Mais , la désactivation du comportement par défaut rend impossible le déplacement du focus hors de la zone de texte sans utiliser la souris. Les utilisateurs aveugles interagissent avec des pages Web à l'aide du clavier et rien d'autre - ils ne peuvent pas voir le pointeur de la souris pour faire quoi que ce soit d'utile avec, alors c'est un clavier ou rien. La touche de tabulation est le principal moyen de naviguer dans le document, en particulier les formulaires. Remplacer le comportement par défaut de la touche de tabulation empêchera les utilisateurs non-voyants de déplacer le focus sur l'élément de formulaire suivant.

Donc, si vous écrivez un site Web pour un large public, je vous déconseille de le faire sans une raison convaincante, et de fournir une sorte de solution de rechange aux utilisateurs aveugles qui ne les piège pas textarea.

34
Will Martin

Pour ce que cela vaut, voici mon oneliner, pour ce dont vous avez tous parlé dans ce fil de discussion:

<textarea onkeydown="if(event.keyCode===9){var v=this.value,s=this.selectionStart,e=this.selectionEnd;this.value=v.substring(0, s)+'\t'+v.substring(e);this.selectionStart=this.selectionEnd=s+1;return false;}">
</textarea>

Testez dans les dernières éditions de Chrome, Firefox, Internet Explorer et Edge.

28
elgholm

Je n'allais nulle part rapidement en essayant d'utiliser la réponse de @ kasdega dans un environnement AngularJS, rien de ce que j'ai essayé ne semblait capable de faire agir Angular sur le changement. Donc, au cas où cela pourrait être utile aux passants, voici une réécriture du code de @ kasdega, à la AngularJS, qui a fonctionné pour moi:

app.directive('ngAllowTab', function () {
    return function (scope, element, attrs) {
        element.bind('keydown', function (event) {
            if (event.which == 9) {
                event.preventDefault();
                var start = this.selectionStart;
                var end = this.selectionEnd;
                element.val(element.val().substring(0, start) 
                    + '\t' + element.val().substring(end));
                this.selectionStart = this.selectionEnd = start + 1;
                element.triggerHandler('change');
            }
        });
    };
});

et:

<textarea ng-model="mytext" ng-allow-tab></textarea>
9
stovroz

Script d'indentation sur plusieurs lignes basé sur la solution @kasdega.

$('textarea').on('keydown', function (e) {
    var keyCode = e.keyCode || e.which;

    if (keyCode === 9) {
        e.preventDefault();
        var start = this.selectionStart;
        var end = this.selectionEnd;
        var val = this.value;
        var selected = val.substring(start, end);
        var re = /^/gm;
        var count = selected.match(re).length;


        this.value = val.substring(0, start) + selected.replace(re, '\t') + val.substring(end);
        this.selectionStart = start;
        this.selectionEnd = end + count;
    }
});
6
Martin

Vous devez écrire le code JS pour attraper la touche TAB et insérer un tas d'espaces. Quelque chose de semblable à ce que JSFiddle fait.

Vérifiez jquery violon :

HTML:

<textarea id="mybox">this is a test</textarea>

JavaScript:

$('#mybox').live('keydown', function(e) { 
  var keyCode = e.keyCode || e.which; 

  if (keyCode == 9) { 
    e.preventDefault(); 
    alert('tab pressed');
  } 
});
​
6
Aziz Shaikh

Cette solution permet de tabuler toute une sélection, comme votre éditeur de code typique, et de supprimer cette sélection Cependant, je n'ai pas trouvé comment implémenter shift-tab quand il n'y a pas de sélection.

$('#txtInput').on('keydown', function(ev) {
    var keyCode = ev.keyCode || ev.which;

    if (keyCode == 9) {
        ev.preventDefault();
        var start = this.selectionStart;
        var end = this.selectionEnd;
        var val = this.value;
        var selected = val.substring(start, end);
        var re, count;

        if(ev.shiftKey) {
            re = /^\t/gm;
            count = -selected.match(re).length;
            this.value = val.substring(0, start) + selected.replace(re, '') + val.substring(end);
            // todo: add support for shift-tabbing without a selection
        } else {
            re = /^/gm;
            count = selected.match(re).length;
            this.value = val.substring(0, start) + selected.replace(re, '\t') + val.substring(end);
        }

        if(start === end) {
            this.selectionStart = end + count;
        } else {
            this.selectionStart = start;
        }

        this.selectionEnd = end + count;
    }
});
#txtInput {
  font-family: monospace;
  width: 100%;
  box-sizing: border-box;
  height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


<textarea id="txtInput">
$(document).ready(function(){
	$("#msgid").html("This is Hello World by JQuery");
});
</textarea>

6
mpen

De manière moderne, les deux sont simples et ne perdent pas la possibilité d'annuler (Ctrl + Z) des dernières modifications.

$('#your-textarea').keydown(function (e) {
    var keyCode = e.keyCode || e.which;

    if (keyCode === $.ui.keyCode.TAB) {
        e.preventDefault();

        const TAB_SIZE = 4;

        // The one-liner that does the magic
        document.execCommand('insertText', false, ' '.repeat(TAB_SIZE));
    }
});

En savoir plus sur execCommand:

5
jom

Basé sur tout ce que les gens avaient à dire ici sur les réponses, c'est juste une combinaison de keydown (not keyup) + preventDefault () + insérez un caractère de tabulation dans le curseur. Quelque chose comme:

var keyCode = e.keyCode || e.which;
if (keyCode == 9) {
   e.preventDefault();
   insertAtCaret('txt', '\t')
}

La réponse précédente avait un jsfiddle qui fonctionnait, mais elle utilisait une alerte () lors du raccourci clavier. Si vous supprimez cette alerte, cela ne fonctionnera pas. Je viens d’ajouter une fonction pour insérer un onglet à la position actuelle du curseur dans la zone de texte.

Voici un exemple de travail pour le même: http://jsfiddle.net/nsHGZ/

3
walmik

Je vois que ce sujet n'est pas résolu. J'ai codé ceci et cela fonctionne très bien… .. Il insère une tabulation à l'index du curseur. Sans utiliser jquery

<textarea id="myArea"></textarea>
<script>
document.getElementById("myArea").addEventListener("keydown",function(event){
    if(event.code==="Tab"){
        var cIndex=this.selectionStart;
        this.value=[this.value.slice(0,cIndex),//Slice at cursor index
            "\t",                              //Add Tab
            this.value.slice(cIndex)].join('');//Join with the end
        event.stopPropagation();
        event.preventDefault();                //Don't quit the area
        this.selectionStart=cIndex+1;
        this.selectionEnd=cIndex+1;            //Keep the cursor in the right index
    }
});
</script>
2
Bibimission

Maintenez la touche Alt et appuyez sur 0,9 à partir du pavé numérique. Cela fonctionne dans google-chrome

2
krishna

Voici ma version de ceci, supporte: 

  • tab + shift tab
  • maintient la pile d'annulation pour les insertions de caractères de tabulation simples
  • prend en charge l'indentation/annulation de ligne de bloc, mais supprime la pile d'annulation
  • sélectionne correctement les lignes entières lorsque l'indentation/l'indentation du bloc
  • prend en charge l'indentation automatique en appuyant sur entrée (maintient la pile d'annulation)
  • utilisez la touche Echap pour annuler la prise en charge sur l'onglet/la touche Entrée suivante
  • Fonctionne sur Chrome + Edge, autres non testés.

$(function() { 
	var enabled = true;
	$("textarea.tabSupport").keydown(function(e) {

		// Escape key toggles tab on/off
		if (e.keyCode==27)
		{
			enabled = !enabled;
			return false;
		}

		// Enter Key?
		if (e.keyCode === 13 && enabled)
		{
			// selection?
			if (this.selectionStart == this.selectionEnd)
			{
				// find start of the current line
				var sel = this.selectionStart;
				var text = $(this).val();
				while (sel > 0 && text[sel-1] != '\n')
				sel--;

				var lineStart = sel;
				while (text[sel] == ' ' || text[sel]=='\t')
				sel++;

				if (sel > lineStart)
				{
					// Insert carriage return and indented text
					document.execCommand('insertText', false, "\n" + text.substr(lineStart, sel-lineStart));

					// Scroll caret visible
					this.blur();
					this.focus();
					return false;
				}
			}
		}

		// Tab key?
		if(e.keyCode === 9 && enabled) 
		{
			// selection?
			if (this.selectionStart == this.selectionEnd)
			{
				// These single character operations are undoable
				if (!e.shiftKey)
				{
					document.execCommand('insertText', false, "\t");
				}
				else
				{
					var text = $(this).val();
					if (this.selectionStart > 0 && text[this.selectionStart-1]=='\t')
					{
						document.execCommand('delete');
					}
				}
			}
			else
			{
				// Block indent/unindent trashes undo stack.
				// Select whole lines
				var selStart = this.selectionStart;
				var selEnd = this.selectionEnd;
				var text = $(this).val();
				while (selStart > 0 && text[selStart-1] != '\n')
					selStart--;
				while (selEnd > 0 && text[selEnd-1]!='\n' && selEnd < text.length)
					selEnd++;

				// Get selected text
				var lines = text.substr(selStart, selEnd - selStart).split('\n');

				// Insert tabs
				for (var i=0; i<lines.length; i++)
				{
					// Don't indent last line if cursor at start of line
					if (i==lines.length-1 && lines[i].length==0)
						continue;

					// Tab or Shift+Tab?
					if (e.shiftKey)
					{
						if (lines[i].startsWith('\t'))
							lines[i] = lines[i].substr(1);
						else if (lines[i].startsWith("    "))
							lines[i] = lines[i].substr(4);
					}
					else
						lines[i] = "\t" + lines[i];
				}
				lines = lines.join('\n');

				// Update the text area
				this.value = text.substr(0, selStart) + lines + text.substr(selEnd);
				this.selectionStart = selStart;
				this.selectionEnd = selStart + lines.length; 
			}

			return false;
		}

		enabled = true;
		return true;
	});
});
textarea
{
  width: 100%;
  height: 100px;
  tab-size: 4;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="tabSupport">if (something)
{
	// This textarea has "tabSupport" CSS style
	// Try using tab key
	// Try selecting multiple lines and using tab and shift+tab
	// Try pressing enter at end of this line for auto indent
	// Use Escape key to toggle tab support on/off
	//     eg: press Escape then Tab to go to next field
}
</textarea>
<textarea>This text area doesn't have tabSupport class so disabled here</textarea>

1
Brad Robinson

Les réponses ci-dessus effacent tout l'historique des annulations. Pour ceux qui recherchent une solution qui ne le fait pas, j'ai passé la dernière heure à coder les éléments suivants pour Chrome:

jQuery.fn.enableTabs = function(TAB_TEXT){
    // options
    if(!TAB_TEXT)TAB_TEXT = '\t';
    // text input event for character insertion
    function insertText(el, text){
        var te = document.createEvent('TextEvent');
        te.initTextEvent('textInput', true, true, null, text, 9, "en-US");
        el.dispatchEvent(te);
    }
    // catch tab and filter selection
    jQuery(this).keydown(function(e){
        if((e.which || e.keyCode)!=9)return true;
        e.preventDefault();
        var contents = this.value,
            sel_start = this.selectionStart,
            sel_end = this.selectionEnd,
            sel_contents_before = contents.substring(0, sel_start),
            first_line_start_search = sel_contents_before.lastIndexOf('\n'),
            first_line_start = first_line_start_search==-1 ? 0 : first_line_start_search+1,
            tab_sel_contents = contents.substring(first_line_start, sel_end),
            tab_sel_contents_find = (e.shiftKey?new RegExp('\n'+TAB_TEXT, 'g'):new RegExp('\n', 'g')),
            tab_sel_contents_replace = (e.shiftKey?'\n':'\n'+TAB_TEXT);
            tab_sel_contents_replaced = (('\n'+tab_sel_contents)
                .replace(tab_sel_contents_find, tab_sel_contents_replace))
                .substring(1),
            sel_end_new = first_line_start+tab_sel_contents_replaced.length;
        this.setSelectionRange(first_line_start, sel_end);
        insertText(this, tab_sel_contents_replaced);
        this.setSelectionRange(first_line_start, sel_end_new);
    });
};

En bref, les onglets sont insérés au début des lignes sélectionnées.

JSFiddle: http://jsfiddle.net/iausallc/5Lnabspr/11/

Gist: https://Gist.github.com/iautomation/e53647be326cb7d7112d

Exemple d'utilisation: $('textarea').enableTabs('\t')

Inconvénients: ne fonctionne que sur Chrome tel quel.

1
iautomation

Le moyen le plus simple J'ai trouvé que je faisais cela dans les navigateurs modernes avec JavaScript JavaScript est:

  <textarea name="codebox"></textarea>
  
  <script>
  const codebox = document.querySelector("[name=codebox]")

  codebox.addEventListener("keydown", (e) => {
    let { keyCode } = e;
    let { value, selectionStart, selectionEnd } = codebox;

    if (keyCode === 9) {  // TAB = 9
      e.preventDefault();

      codebox.value = value.slice(0, selectionStart) + "  " + value.slice(selectionEnd);

      codebox.setSelectionRange(selectionStart+2, selectionStart+2)
    }
  });
  </script>

Notez que j'ai utilisé de nombreuses fonctionnalités ES6 dans cet extrait de code par souci de simplicité, vous voudrez probablement l'enregistrer à l'aide de Babel ou de TypeScript avant de le déployer.

0
Telmo Trooper

J'en ai créé un auquel vous pouvez accéder avec n'importe quel élément textarea que vous aimez:

function textControl (element, event)
{
    if(event.keyCode==9 || event.which==9)
    {
        event.preventDefault();
        var s = element.selectionStart;
        element.value = element.value.substring(0,element.selectionStart) + "\t" + element.value.substring(element.selectionEnd);
        element.selectionEnd = s+1; 
    }
}

Et l'élément ressemblerait à ceci:

<textarea onkeydown="textControl(this,event)"></textarea>
0
Hellena Bailey