Fixes #2886 - Text Editor deletes text unrecoverably if quicktext was canceled with Ctrl+Backspace.
This commit is contained in:
parent
6da7f50f9b
commit
7e488ad134
4 changed files with 65 additions and 9 deletions
4
Gemfile
4
Gemfile
|
@ -223,6 +223,10 @@ group :development, :test do
|
||||||
|
|
||||||
# Slack helper for testing
|
# Slack helper for testing
|
||||||
gem 'slack-ruby-client', require: false
|
gem 'slack-ruby-client', require: false
|
||||||
|
|
||||||
|
# Can be used to detect for example the current
|
||||||
|
# operating system in tests, to handle things differently.
|
||||||
|
gem 'os'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Want to extend Zammad with additional gems?
|
# Want to extend Zammad with additional gems?
|
||||||
|
|
|
@ -394,6 +394,7 @@ GEM
|
||||||
omniauth (~> 1.5)
|
omniauth (~> 1.5)
|
||||||
omniauth-oauth2 (>= 1.4.0)
|
omniauth-oauth2 (>= 1.4.0)
|
||||||
openssl (2.2.0)
|
openssl (2.2.0)
|
||||||
|
os (1.1.1)
|
||||||
overcommit (0.58.0)
|
overcommit (0.58.0)
|
||||||
childprocess (>= 0.6.3, < 5)
|
childprocess (>= 0.6.3, < 5)
|
||||||
iniparse (~> 1.4)
|
iniparse (~> 1.4)
|
||||||
|
@ -710,6 +711,7 @@ DEPENDENCIES
|
||||||
omniauth-twitter
|
omniauth-twitter
|
||||||
omniauth-weibo-oauth2
|
omniauth-weibo-oauth2
|
||||||
openssl
|
openssl
|
||||||
|
os
|
||||||
overcommit
|
overcommit
|
||||||
pg (= 0.21.0)
|
pg (= 0.21.0)
|
||||||
pry-rails
|
pry-rails
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
this.collection = []
|
this.collection = []
|
||||||
this.active = false
|
this.active = false
|
||||||
this.buffer = ''
|
this.buffer = ''
|
||||||
|
this.oldElementText = ''
|
||||||
|
|
||||||
// check if ce exists
|
// check if ce exists
|
||||||
if ( $.data(element, 'plugin_ce') ) {
|
if ( $.data(element, 'plugin_ce') ) {
|
||||||
|
@ -55,10 +56,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin.prototype.onKeydown = function (e) {
|
Plugin.prototype.onKeydown = function (e) {
|
||||||
//console.log("onKeydown", this.isActive())
|
// Saves the old element text for some special situations.
|
||||||
|
this.oldElementText = this.$element.text()
|
||||||
|
|
||||||
// navigate through item
|
// navigate through item
|
||||||
if (this.isActive()) {
|
if (this.isActive()) {
|
||||||
|
|
||||||
// esc
|
// esc
|
||||||
if (e.keyCode === 27) {
|
if (e.keyCode === 27) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -133,7 +135,7 @@
|
||||||
|
|
||||||
// reduce buffer, in case close it
|
// reduce buffer, in case close it
|
||||||
// backspace
|
// backspace
|
||||||
if (e.keyCode === 8 && this.buffer) {
|
if (e.keyCode === 8 && !( e.ctrlKey || e.metaKey ) && this.buffer) {
|
||||||
|
|
||||||
var trigger = this.findTrigger(this.buffer)
|
var trigger = this.findTrigger(this.buffer)
|
||||||
// backspace + buffer === :: -> close textmodule
|
// backspace + buffer === :: -> close textmodule
|
||||||
|
@ -162,19 +164,47 @@
|
||||||
|
|
||||||
Plugin.prototype.onKeypress = function (e) {
|
Plugin.prototype.onKeypress = function (e) {
|
||||||
this.log('BUFF', this.buffer, e.keyCode, String.fromCharCode(e.which))
|
this.log('BUFF', this.buffer, e.keyCode, String.fromCharCode(e.which))
|
||||||
|
|
||||||
// gets the character and keycode from event
|
// gets the character and keycode from event
|
||||||
// this event does not have keyCode and which value set
|
// this event does not have keyCode and which value set
|
||||||
// so we take char and set those values to not break the flow
|
// so we take char and set those values to not break the flow
|
||||||
// if originalEvent.data is null that means a non char key is pressed like delete, space
|
// if originalEvent.data is null that means a non char key is pressed like delete, space
|
||||||
if(e.originalEvent && e.originalEvent.data) {
|
if(e.originalEvent && e.originalEvent.data) {
|
||||||
var char = e.originalEvent.data;
|
var char = e.originalEvent.data
|
||||||
var keyCode = char.charCodeAt(0);
|
var keyCode = char.charCodeAt(0)
|
||||||
e.keyCode = e.which = keyCode;
|
e.keyCode = e.which = keyCode
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore invalid key codes if search is opened (issue #3637)
|
// ignore invalid key codes if search is opened (issue #3637)
|
||||||
if (this.isActive() && e.keyCode === undefined) return
|
if (this.isActive() && e.keyCode === undefined) {
|
||||||
|
|
||||||
|
// Check if the trigger still exists in the new text, after a special key was pressed, otherwise
|
||||||
|
// close the collection.
|
||||||
|
var indexOfBuffer = this.oldElementText.indexOf(this.buffer)
|
||||||
|
var trigger = this.findTrigger(this.buffer)
|
||||||
|
|
||||||
|
if (this.buffer && indexOfBuffer !== -1 && trigger) {
|
||||||
|
foundCurrentBuffer = this.$element.text().substr(indexOfBuffer, this.buffer.length)
|
||||||
|
|
||||||
|
if ( this.$element.text().substr(indexOfBuffer, trigger.trigger.length) !== trigger.trigger ) {
|
||||||
|
this.close(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check on how many characters the trigger needs to be reduced, in the case it's not the same.
|
||||||
|
else if ( foundCurrentBuffer !== this.buffer ) {
|
||||||
|
var existingLength = 0
|
||||||
|
for (var i = 0; i < this.buffer.length; i++) {
|
||||||
|
if (this.buffer.charAt(i) !== foundCurrentBuffer.charAt(i)) {
|
||||||
|
existingLength = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.buffer = this.buffer.substr(0, existingLength)
|
||||||
|
this.result(trigger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// skip on shift + arrow_keys
|
// skip on shift + arrow_keys
|
||||||
if (_.contains([16, 37, 38, 39, 40], e.keyCode)) return
|
if (_.contains([16, 37, 38, 39, 40], e.keyCode)) return
|
||||||
|
@ -186,7 +216,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var newChar = String.fromCharCode(e.which)
|
var newChar = String.fromCharCode(e.which)
|
||||||
|
|
||||||
// observe other keys
|
// observe other keys
|
||||||
if (this.hasAvailableTriggers(this.buffer)) {
|
if (this.hasAvailableTriggers(this.buffer)) {
|
||||||
if(this.hasAvailableTriggers(this.buffer + newChar)) {
|
if(this.hasAvailableTriggers(this.buffer + newChar)) {
|
||||||
|
|
|
@ -19,6 +19,27 @@ RSpec.shared_examples 'text modules' do |path:|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'does not break after usage of Ctrl/Command+Backspace' do
|
||||||
|
visit path
|
||||||
|
within(:active_content) do
|
||||||
|
find(:richtext).send_keys(':')
|
||||||
|
find(:richtext).send_keys(':')
|
||||||
|
find(:richtext).send_keys('bur')
|
||||||
|
|
||||||
|
# The click is needed to get the focus back to the field for chrome.
|
||||||
|
find(:richtext).click
|
||||||
|
if OS.mac?
|
||||||
|
find(:richtext).send_keys(%i[command backspace])
|
||||||
|
else
|
||||||
|
find(:richtext).send_keys(%i[control backspace])
|
||||||
|
end
|
||||||
|
|
||||||
|
find(:richtext).send_keys('Some other text')
|
||||||
|
find(:richtext).send_keys(:enter)
|
||||||
|
expect(find(:richtext)).to have_text 'Some other text'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'does not show when send :enter:' do
|
it 'does not show when send :enter:' do
|
||||||
visit path
|
visit path
|
||||||
within(:active_content) do
|
within(:active_content) do
|
||||||
|
|
Loading…
Reference in a new issue