У меня есть текстовое поле и кнопка. Нажатие кнопки заставляет текст вставляться в текстовое поле.
Есть ли способ разрешить пользователю нажимать Ctrl/Cmd + z, чтобы отменить вставку текста и вернуть текстовое поле в прежнее состояние?
У меня есть текстовое поле и кнопка. Нажатие кнопки заставляет текст вставляться в текстовое поле.
Есть ли способ разрешить пользователю нажимать Ctrl/Cmd + z, чтобы отменить вставку текста и вернуть текстовое поле в прежнее состояние?
Вам нужно вставить текст особым образом, чтобы пользователь мог использовать нормальное поведение отменить/повторить.
var textEvent = document.createEvent('TextEvent');
textEvent.initTextEvent('textInput', true, true, null, "new text");
document.getElementById("your-textarea").dispatchEvent(textEvent);
Сохраните исходное значение 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');
});
Я думаю, что самый простой подход к использованию стека браузера для отмены, а не для захвата событий.
Для этого вам нужно использовать разные коды для разных браузеров. К счастью из всех основных браузеров только 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 = /*@[email protected]*/ 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>
$("#target").keypress(function(event) {
if ( event.which == 'Z' && first press == 'Cmd' && second press == 'Ctrl') {//check for key press
event.preventDefault();
text.value = defaultValueForTextField
}
});
Это должно быть то, что вы ищете. Первое и второе нажатие необходимо сохранить, как вы хотите, комбо-прессы. Вам действительно нужно сохранить текстовое значение по умолчанию.
Вот мысль:
Если мы сможем генерировать события 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
(для любого события, сгенерированного с помощью script, он будет иметь false
)Ссылки MDN:
Даже если этот вопрос год назад старый, я тоже хочу поделиться своим путем.
Вы можете сделать это следующим образом:
$(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 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/
Я написал код, подобный этому, для хорошего понимания, но вы должны, конечно, написать реальный код лучше и менее подробный, чем это.
Конкретные библиотеки и технологии сильно зависят от вашего стека.
Есть два общих способа, о которых я могу думать мгновенно.
Во-первых: Сохраните предыдущее состояние в контроллере. Вставьте ярлык и замените содержимое на предыдущее состояние. Если сделаны другие модификации, удалите крючок. Более-менее ваш подход к 2013 году
Это быстрый способ и не играет хорошо, если вы хотите иметь стек с историей редактирования более одного раза.
Во-вторых: Следите за текстом и периодически сохраняйте состояние в стеке. Захватите ярлык. (Возьмите весь процесс). Это более чистый способ, потому что ваша модификация концептуально совпадает с модификациями пользователя.
Это может быть довольно просто с архитектурой сокращения/потока http://redux.js.org/docs/recipes/ImplementingUndoHistory.html
Для захвата cmd/ctrl + z вы можете посмотреть https://github.com/madrobby/keymaster
Если вы подробно расскажете о своем стеке/требованиях, я был бы рад расширить этот ответ.
Самый простой способ выглядит так:
Сейчас:
$('#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);
}
})
})
Вы также можете проверить и поэкспериментировать с fiddle.
Сначала добавьте 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\ 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()
})