12

私はこれを概念化することすら難しいと感じています。簡単な方法は、大きなtextarea要素が画面の大部分を占め、その下に小さなテキストinput要素があることです。プレーヤーはコマンドを入力し、出力はに表示されますtextarea

問題は、入力を完全に統合したいということです。DOS画面について考えてみてください。ブラケットプロンプトがあり>、その後にコマンドを入力します。Enterキーを押すと、その下に出力が表示さ>れ、次のコマンドのプロンプトが表示されます。入力は、視覚的には出力から分離されていません。私が達成したいことの例はここで見ることができます:http ://www.youtube.com/watch?v = UC_FrikiZdE (マウスを使用してコマンドを選択する代わりに、コマンドを入力することができます)。

HTMLでそれを行うにはどうすればよいですか(入力/出力の処理にJavaScript / jQueryを使用)?おそらくすべてが編集可能なもので行われていると思いtextareaますが、Backspaceボタンは>プロンプト以降から何も消去できず、入力されたテキストのみを消去できます。

これを行う最も簡単な方法は何ですか?オンラインでデモやチュートリアルを見つけることができませんでした。誰かが私が見逃したかもしれないものを私に指摘できますか?ありがとう。

4

2 に答える 2

14

あなたはグーグルを通してオンラインで見つけられるこれらのJavaScriptターミナルをチェックすることができます:

また、私のフランス人の友人の何人かはこれに取り組んでいます:

于 2012-10-16T00:18:29.733 に答える
4

ライブラリを使用する代わりに自分でソリューションを構築したい場合は、contenteditable要素とその後に偽の正方形のカレットを使用できます。カレットが別の位置に移動すると、その偽のカレットは非表示になり、代わりに実際の垂直線が表示されます。

ただし、オーバータイプモードが無効になっている場合でも、このコードを微調整して常に1文字を選択し、カレットが常に1文字幅の正方形になるようにすることができます。

コマンドを表示しているだけですが、コマンドを別の方法で処理するのは簡単です。

const history = document.getElementById('history');
const input = document.getElementById('input');
const cursor = document.getElementById('cursor');

function focusAndMoveCursorToTheEnd(e) {  
  input.focus();
  
  const range = document.createRange();
  const selection = window.getSelection();
  const { childNodes } = input;
  const lastChildNode = childNodes && childNodes.length - 1;
  
  range.selectNodeContents(lastChildNode === -1 ? input : childNodes[lastChildNode]);
  range.collapse(false);

  selection.removeAllRanges();
  selection.addRange(range);
}

function handleCommand(command) {
  const line = document.createElement('DIV');
  
  line.textContent = `> ${ command }`;
  
  history.appendChild(line);
}

// Every time the selection changes, add or remove the .noCursor
// class to show or hide, respectively, the bug square cursor.
// Note this function could also be used to enforce showing always
// a big square cursor by always selecting 1 chracter from the current
// cursor position, unless it's already at the end, in which case the
// #cursor element should be displayed instead.
document.addEventListener('selectionchange', () => {
  if (document.activeElement.id !== 'input') return;
  
  const range = window.getSelection().getRangeAt(0);
  const start = range.startOffset;
  const end = range.endOffset;
  const length = input.textContent.length;
  
  if (end < length) {
    input.classList.add('noCaret');
  } else {
    input.classList.remove('noCaret');
  }
});

input.addEventListener('input', () => {    
  // If we paste HTML, format it as plain text and break it up
  // input individual lines/commands:
  if (input.childElementCount > 0) {
    const lines = input.innerText.replace(/\n$/, '').split('\n');
    const lastLine = lines[lines.length - 1];
    
    for (let i = 0; i <= lines.length - 2; ++i) {
      handleCommand(lines[i]);
    }
  
    input.textContent = lastLine;
    
    focusAndMoveCursorToTheEnd();
  }
  
  // If we delete everything, display the square caret again:
  if (input.innerText.length === 0) {
    input.classList.remove('noCaret');  
  }  
});

document.addEventListener('keydown', (e) => {   
  // If some key is pressed outside the input, focus it and move the cursor
  // to the end:
  if (e.target !== input) focusAndMoveCursorToTheEnd();
});

input.addEventListener('keydown', (e) => {    
  if (e.key === 'Enter') {
    e.preventDefault();
        
    handleCommand(input.textContent);    
    input.textContent = '';
    focusAndMoveCursorToTheEnd();
  }
});

// Set the focus to the input so that you can start typing straigh away:
input.focus();
body {
  background: #000;
  color: #0F0;
  font-family: monospace;
  height: 100vh;
  box-sizing: border-box;
  overflow-x: hidden;
  overflow-y: scroll;
  word-break: break-all;
  margin: 0;
  padding: 16px;
}

#input {
  display: inline;
  outline: none;
  visibility: visible;
}

/*
  If you press the Insert key, the vertical line caret will automatically
  be replaced by a one-character selection.
*/
#input::selection {
  color: #000;
  background: #0F0;
}

#input:empty::before {
  content: ' ';
}

@keyframes blink {
  to {
    visibility: hidden;
  }
}

#input:focus + #caret {
  animation: blink 1s steps(5, start) infinite;
}

#input.noCaret + #caret {
  visibility: hidden;
}

#caret {
  border: 0;
  padding: 0;
  outline: none;
  background-color: #0F0;
  display: inline-block;
  font-family: monospace;
}
<div id="history"></div>

> 

<div id="input" contenteditable="true"></div><button id="caret" for="input">&nbsp;</button>

このソリューションは、キーボードイベント( / / )ではなく、主にイベントinputとイベントに依存していることに注意してください。通常、テキスト入力やカーソルの処理にこれらを使用することはお勧めできません。入力の値は、テキストを貼り付けたりドロップしたりすることで更新することもでき、矢印、削除、エスケープ、次のようなショートカットなど、多くのエッジケースがあります。すべてを選択し、コピーして貼り付けます...したがって、処理する必要のあるすべてのキーの完全なリストを考え出すことは、おそらく最善のアプローチではありません。selectionchangekeydownkeypresskeyup

さらに、ほとんどのキーが同じ値を出力するモバイルでは機能しe.key = 'Unidentified'ませe.which== 229e.keyCode = 229

代わりに、通常は、などの他のイベントに依存し、次のような非常に特定のキーを処理するためにinput使用することをお勧めします。KeyboardEvents↵</kbd> in this case.

e.key、などのKeyboardEventのプロパティ値を確認する必要がある場合e.codee.whichまたはhttps://keyjs.deve.keyCodeを使用できます。これらの種類のクロスブラウザの非互換性に関する情報をすぐに追加します!

Key.js \JavaScriptKeyboardEventのキーコードとキー識別子

免責事項:私は著者です。

于 2020-10-05T23:05:45.667 に答える