Skip to content

Commit

Permalink
Fixes zammad#2886 - Text Editor deletes text unrecoverably if quickte…
Browse files Browse the repository at this point in the history
…xt was canceled with Ctrl+Backspace.
  • Loading branch information
dominikklein committed Jul 23, 2021
1 parent 6da7f50 commit 7e488ad
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 9 deletions.
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ group :development, :test do

# Slack helper for testing
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

# Want to extend Zammad with additional gems?
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ GEM
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0)
openssl (2.2.0)
os (1.1.1)
overcommit (0.58.0)
childprocess (>= 0.6.3, < 5)
iniparse (~> 1.4)
Expand Down Expand Up @@ -710,6 +711,7 @@ DEPENDENCIES
omniauth-twitter
omniauth-weibo-oauth2
openssl
os
overcommit
pg (= 0.21.0)
pry-rails
Expand Down
47 changes: 38 additions & 9 deletions app/assets/javascripts/app/lib/base/jquery.textmodule.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
this.collection = []
this.active = false
this.buffer = ''
this.oldElementText = ''

// check if ce exists
if ( $.data(element, 'plugin_ce') ) {
Expand Down Expand Up @@ -55,10 +56,11 @@
}

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
if (this.isActive()) {

// esc
if (e.keyCode === 27) {
e.preventDefault()
Expand Down Expand Up @@ -133,7 +135,7 @@

// reduce buffer, in case close it
// backspace
if (e.keyCode === 8 && this.buffer) {
if (e.keyCode === 8 && !( e.ctrlKey || e.metaKey ) && this.buffer) {

var trigger = this.findTrigger(this.buffer)
// backspace + buffer === :: -> close textmodule
Expand Down Expand Up @@ -162,19 +164,47 @@

Plugin.prototype.onKeypress = function (e) {
this.log('BUFF', this.buffer, e.keyCode, String.fromCharCode(e.which))

// gets the character and keycode from event
// this event does not have keyCode and which value set
// 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(e.originalEvent && e.originalEvent.data) {
var char = e.originalEvent.data;
var keyCode = char.charCodeAt(0);
e.keyCode = e.which = keyCode;
var char = e.originalEvent.data
var keyCode = char.charCodeAt(0)
e.keyCode = e.which = keyCode
}

// 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
if (_.contains([16, 37, 38, 39, 40], e.keyCode)) return
Expand All @@ -186,7 +216,6 @@
}

var newChar = String.fromCharCode(e.which)

// observe other keys
if (this.hasAvailableTriggers(this.buffer)) {
if(this.hasAvailableTriggers(this.buffer + newChar)) {
Expand Down
21 changes: 21 additions & 0 deletions spec/system/examples/text_modules_examples.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,27 @@
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
visit path
within(:active_content) do
Expand Down

0 comments on commit 7e488ad

Please sign in to comment.