У меня есть текстовое поле и кнопка. При нажатии кнопки текст вставляется в текстовое поле.
Есть ли способ разрешить пользователю нажимать Ctrl/Cmd+z, чтобы отменить вставку текста и вернуть текстовую область в ее предыдущее состояние?
У меня есть текстовое поле и кнопка. При нажатии кнопки текст вставляется в текстовое поле.
Есть ли способ разрешить пользователю нажимать Ctrl/Cmd+z, чтобы отменить вставку текста и вернуть текстовую область в ее предыдущее состояние?
Я думаю, что самый простой способ использовать стек отмены браузера вместо захвата событий.
Для этого нужно использовать разные коды для разных браузеров. К счастью, из всех основных браузеров только у Firefox есть другой подход.
// http://stackoverflow.com/a/9851769/529024
// Opera 8.0+
var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
// Firefox 1.0+
var isFirefox = typeof InstallTrigger !== 'undefined';
// Safari 3.0+ "[object HTMLElementConstructor]"
var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0 || (function(p) {
return p.toString() === "[object SafariRemoteNotification]";
})(!window['safari'] || safari.pushNotification);
// Internet Explorer 6-11
var isIE = /*@cc_on!@*/ false || !!document.documentMode;
// Edge 20+
var isEdge = !isIE && !!window.StyleMedia;
// Chrome 1+
var isChrome = !!window.chrome && !!window.chrome.webstore;
var position = 0;
// text to anser
var text = 'Inserted Text';
// Just for fun :)
if (isFirefox)
text = " __ Firefox __ ";
else if (isIE)
text = " __ IE __ ";
else if (isEdge)
text = " __ Edge __ ";
else if (isSafari)
text = " __ Safari __ ";
else if (isOpera)
text = " __ Opera __ ";
else if (isChrome)
text = " __ Chrome __ ";
/* Adding text on click based on browser */
jQuery(".addText").on("click", function() {
if (isFirefox) {
// Firefox
var val = jQuery(".textArea").val();
var firstText = val.substring(0, position);
var secondText = val.substring(position);
jQuery(".textArea").val(firstText + text + secondText);
} else {
jQuery(".textArea").focus();
var val = jQuery(".textArea").val();
jQuery(".textArea")[0].selectionStart = position;
jQuery(".textArea")[0].selectionEnd = position;
document.execCommand('insertText', false, text);
}
});
jQuery(".textArea").on("focusout", function(e) {
position = jQuery(this)[0].selectionStart;
});
textarea {
padding: 10px;
font-family: Calibri;
font-size: 18px;
line-height: 1.1;
resize: none;
}
.addText {
padding: 5px 15px;
transition: all 0.5s;
border: 1px solid black;
border-radius: 2px;
background-color: #169c16;
width: 70px;
margin: 10px 0;
color: white;
cursor: pointer;
}
.addText:hover {
background-color: #2776b9;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea name='textArea' class='textArea' rows="7" cols="50">Suspendisse convallis, metus at laoreet congue, sapien dui ornare magna, a porttitor felis purus a ipsum. Morbi vulputate erat rhoncus, luctus neque ut, lacinia orci. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis
egestas. Fusce aliquam, nulla nec fringilla ultrices, ipsum lectus maximus nisl, ut laoreet purus lectus eget nisl. Duis blandit cursus nulla. Vestibulum consectetur, nunc non viverra condimentum, neque neque tincidunt diam, nec vestibulum neque nisi
ac sem. Integer aliquam a leo id laoreet. Mauris ultrices mauris lorem, eu hendrerit odio volutpat ut. Nam eget hendrerit metus.</textarea>
<div class='addText'>
Add Text
</div>
Проверено на:
Вам нужно вставить текст особым образом, чтобы пользователь мог использовать обычное поведение отмены/возврата.
var textEvent = document.createEvent('TextEvent');
textEvent.initTextEvent('textInput', true, true, null, "new text");
document.getElementById("your-textarea").dispatchEvent(textEvent);
textbox.setSelectionRange(0, textbox.value.length);
- person SeBsZ; 08.09.2016
Сохраните исходное значение textarea
в его data
:
var $textarea = $('textarea');
$('button').on('click', function () {
var val = $textarea.val();
$textarea.data('old-val', val).val(val + ' some text');
});
Если вам нужен массив данных (как предложил @ahren), используйте это:
var $textarea = $('textarea');
$('button').on('click', function () {
var val = $textarea.val();
if ( ! $textarea.data('old-val')) {
$textarea.data('old-val', []);
}
$textarea.data('old-val').push(val);
$textarea.val(val + ' some text');
});
$("#target").keypress(function(event) {
if ( event.which == 'Z' && first press == 'Cmd' && second press == 'Ctrl') {//check for key press
event.preventDefault();
text.value = defaultValueForTextField
}
});
Это должно быть то, что вы ищете. Первое и второе нажатие нужно будет сохранить, так как вы хотите комбо-прессы. Однако вам действительно нужно будет сохранить текстовое значение по умолчанию.
Даже если этот вопрос год назад, я тоже хочу поделиться своим способом.
Вы можете сделать это следующим образом:
$(function () {
// Check to see if an array is not already defined.
if (!$('#t').data('old-val')) {
// If the check returns True we proceed to create an array in old-val.
$('#t').data('old-val', []);
}
// Get the current content value.
inputValue = $('#t').val();
// Push it to the old-val array.
$('#t').data('old-val').push(inputValue);
// We start with a current array position of 0.
curArrPos = 0;
$('#c').click(function () {
// Append a string to the #t.
$('#t').val(' ==this is the 2nd appended text==');
// Save the current content value.
inputValue = $('#t').val();
// Push it to the array.
$('#t').data('old-val').push(inputValue);
// Increment current array position.
++curArrPos;
});
$('#b').click(function () {
// Append a string to the #t.
$('#t').val(' ==this is the 1st appended text==');
// Save the current content value.
inputValue = $('#t').val();
// Push it to the array.
$('#t').data('old-val').push(inputValue);
// Increment current array position.
++curArrPos;
});
$('#undo').click(function () {
// First check that the old-val array length is greater than 1 (It's the initial position. No need undoing to a blank state) and current array position greater than 0 (for the same reason).
if ($('#t').data('old-val').length > 1 && curArrPos > 0) {
// Set current #t value to the one in the current array position, minus one.
// Minus one gets you to the previous array position (ex. current=5; previous= current - 1 = 4).
$('#t').val($('#t').data('old-val')[curArrPos - 1]);
// Decrease current array position, because we effectively shifted back by 1 position.
--curArrPos;
}
});
$('#redo').click(function () {
if (currentArrayPos < $('#c').data('old-val').length - 1) {
$('#t').val($('#t').data('old-val')[curArrPos + 1]);
// Increase current array position, because we effectively shifted forward by 1 position.
++curArrPos;
}
});
});
Вот скрипт, если вы хотите поэкспериментировать с ним http://jsfiddle.net/45Jwz/1/
Я написал такой код для лучшего понимания, но вы, конечно, должны писать код лучше и менее многословно, чем этот.
Конкретные библиотеки и технологии сильно зависят от вашего стека.
Есть 2 основных способа, о которых я могу думать мгновенно.
Во-первых: сохраните предыдущее состояние в вашем контроллере. Подключитесь к ярлыку и замените содержимое на предыдущее состояние. Если внесены другие изменения, удалите крючок. Более или менее ваш подход 2013 года
Это быстрый способ, и он не очень хорошо работает, если вам нужен стек с более чем одной историей редактирования.
Второе: следите за текстовым вводом и периодически сохраняйте состояние в стеке. Подключиться к ярлыку. (Возьмите на себя весь процесс). Это более чистый способ, потому что ваша модификация концептуально такая же, как и пользовательские модификации.
Это может быть довольно просто с архитектурой redux/flux http://redux.js.org/docs/recipes/ImplementingUndoHistory.html
Для захвата cmd/ctrl+z вы можете заглянуть в https://github.com/madrobby/keymaster.
Если вы немного подробнее расскажете о своем стеке/требованиях, я был бы рад расширить этот ответ.
Вот мысль:
Если мы сможем генерировать события keyborad так же, как если бы пользователь печатал в текстовом поле, тогда браузер автоматически сможет обрабатывать событие Undo. Поэтому вместо того, чтобы просто добавлять/изменять значение textarea, мы должны попытаться имитировать события клавиатуры для текста, который мы хотим вставить.
Согласно документации в MDN (ссылки приведены ниже), мы можем использовать объект KeyboardEvent
для генерации таких событий, как:
var e1 = new KeyboardEvent(<type>, <details>);
var b1 = <textbox>.dispatchEvent(e1);
Где:
<type>
представляет тип события, например keydown
, keypress
или keyup
<details>
представляет объект, имеющий сведения о событии, такие как key
, code
<textbox>
представляет целевое текстовое поле, в котором мы хотим инициировать событиеВот JSFiddle, где я пытался смоделировать события keydown
, keypress
и keyup
для каждого символ в заданной строке. Хотя он запускает соответствующие обработчики событий, символы почему-то не отображаются/не добавляются в текстовое поле.
Что я заметил, так это то, что есть некоторые различия в объекте события, сгенерированном, когда я набираю a
в стихах текстового поля, когда я имитирую 3 события для a
, используя свой код. Различия (при тестировании в Firefox 50.1.0):
explicitOriginalTarget
отличается от originalTarget
, когда я имитирую события; и когда я набираю текстовое поле, оба имеют одинаковое значениеrangeParent
и rangeOffset
значения равны null
/0
, когда я печатаю текстовое поле; и когда я моделирую события, они имеют некоторые значенияisTrusted
равно true
, когда я набираю текстовое поле; и когда я моделирую события, это false
(для любого события, сгенерированного с использованием скрипта, оно будет иметь false
)МДН ссылки:
Самый простой способ выглядит так:
В настоящее время:
$('#idOfTextarea').val($('#idOfTextarea').attr('prevContents'));
. Процедура отмены также очищает «грязный» атрибут, поэтому отмена не вызывается дважды.Вы можете хотеть или нет также перехватывать onChange в текстовой области. Если onChange срабатывает, а грязный не установлен, это начальный щелчок кнопки, и его можно игнорировать. В противном случае это может указывать на то, что пользователь добавил некоторые собственные изменения в текст, по которому щелкнул мышью. В этом случае вы можете отключить отмену, чтобы сохранить эти изменения, или запросить подтверждение у пользователя.
Вы можете сделать так,
HTML
<div id="text-content">
<textarea rows="10" cols="50"></textarea>
<input type="button" name="Insert" value="Insert" />
</div>
JQuery
var oldText = [],ctrl=false;
$(function(){
$("input[name=Insert]").click(function(){
var text = oldText.length+1;
oldText.push(text);
var textAreaText = $('textarea').val();
textAreaText +=text;
$('textarea').val(textAreaText);
$("input[name=insertText]").val('');
});
$('textarea').keydown(function(e){
if(e.which == 17){ ctrl = true;}
});
$('textarea').keyup(function(e){
var c = e.which;
if(c == 17){ ctrl = false;}
if(ctrl==true && c==90 ){
oldText.pop();
var text = '';
$.each(oldText,function(i,ele){
text += ele;
});
$('textarea').val(text);
}
})
})
Вы также можете проверить и поэкспериментировать с скрипкой.
Сначала добавьте html, и вы сможете использовать событие нажатия клавиши для отмены
вы также можете попробовать здесь http://jsfiddle.net/surendra786/1v5jxaa0/
<input type="text" class="reset actor_input" name="actor" value="add actors"></input>
<input type="text" name="actors"></input>
<div class="found_actors"></div>
<div id="add" class="button_content">ADD</div>
<div id="undo" class="button_content">UNDO</div>
<div class="actors_list"><textarea readonly style="resize: none;" rows="20" cols="20" name="actors-list"></textarea></div>
</div>
**затем добавьте jquery**
var items = [];
$("#add").click(function() {
// Push the new actor in the array
items.push($("[name='actor']").val());
populate();
});
$(document).keydown(function(e){
if( e.which === 90 && e.ctrlKey ){
console.log('control + z');
if (items.length > 0) {
// remove last element of the array
items.splice(-1,1);
populate();
}
}
});
populate = function() {
$("[name='actors-list']").text('');
$("[name='actors-list']").append(items.join(' '));
$("[name='actors']").val(items.join(','));
}
вы можете попробовать здесь http://jsfiddle.net/surendra786/1v5jxaa0/
это работает для меня
Здесь есть много применимых ответов, которые будут работать для того, что вы хотите. Вот что бы я сделал на вашем месте. Это позволяет изменить текстовую переменную, которую вы, скорее всего, будете использовать, вы можете установить ее или пользователь может установить ее с помощью другого поля и т. д.
Суть этого была бы примерно такой.
$(document).ready(function(){
function deployText(){
var textArray = [];
var textToAdd = 'let\'s go ahead and add some more text';
var textarea = $('textarea');
var origValue = textarea.text();
textArray.push(origValue);
$('button').on('click', function(e){
textArray.push(textToAdd);
textarea.text(textArray);
console.log(textArray.length);
console.log(textArray);
});
$(document).on('keypress', function(e){
var zKey = 26;
if(e.ctrlKey && e.which === zKey){
removePreviousText();
}
})
function removePreviousText(){
console.log(textArray);
if(textArray.length > 1){
textArray.pop();
$('textarea').text(textArray);
}
}
}
deployText()
})