Fixed issue #2924 - Unable to paste from clipboard in note field in ticket zoom.
This commit is contained in:
parent
343415d6e8
commit
ddb4bb5150
3 changed files with 180 additions and 85 deletions
|
@ -73,6 +73,8 @@ class App.Utils
|
||||||
ascii = @textCleanup(ascii)
|
ascii = @textCleanup(ascii)
|
||||||
#ascii = @htmlEscape(ascii)
|
#ascii = @htmlEscape(ascii)
|
||||||
ascii = @linkify(ascii)
|
ascii = @linkify(ascii)
|
||||||
|
ascii = ascii.replace(/(\n\r|\r\n|\r)/g, "\n")
|
||||||
|
ascii = ascii.replace(/ /g, ' ')
|
||||||
ascii = '<div>' + ascii.replace(/\n/g, '</div><div>') + '</div>'
|
ascii = '<div>' + ascii.replace(/\n/g, '</div><div>') + '</div>'
|
||||||
ascii.replace(/<div><\/div>/g, '<div><br></div>')
|
ascii.replace(/<div><\/div>/g, '<div><br></div>')
|
||||||
|
|
||||||
|
@ -1269,3 +1271,42 @@ class App.Utils
|
||||||
.filter (elem) ->
|
.filter (elem) ->
|
||||||
elem?
|
elem?
|
||||||
.join '/'
|
.join '/'
|
||||||
|
|
||||||
|
@clipboardHtmlIsWithText: (html) ->
|
||||||
|
if !html
|
||||||
|
return false
|
||||||
|
|
||||||
|
parsedHTML = jQuery(jQuery.parseHTML(html))
|
||||||
|
|
||||||
|
if !parsedHTML || !parsedHTML.text
|
||||||
|
return false
|
||||||
|
|
||||||
|
if parsedHTML.text().trim().length is 0
|
||||||
|
return false
|
||||||
|
|
||||||
|
true
|
||||||
|
|
||||||
|
@clipboardHtmlInsertPreperation: (htmlRaw, options) ->
|
||||||
|
if options.mode is 'textonly'
|
||||||
|
if !options.multiline
|
||||||
|
html = App.Utils.htmlRemoveTags(htmlRaw)
|
||||||
|
else
|
||||||
|
html = App.Utils.htmlRemoveRichtext(htmlRaw)
|
||||||
|
else
|
||||||
|
html = App.Utils.htmlCleanup(htmlRaw)
|
||||||
|
|
||||||
|
htmlString = html.html()
|
||||||
|
|
||||||
|
if !htmlString && html && html.text && html.text()
|
||||||
|
htmlString = App.Utils.text2html(html.text())
|
||||||
|
|
||||||
|
# as fallback, get text from htmlRaw
|
||||||
|
if !htmlString || htmlString == ''
|
||||||
|
parsedHTML = jQuery(jQuery.parseHTML(htmlRaw))
|
||||||
|
if parsedHTML
|
||||||
|
text = parsedHTML.text().trim()
|
||||||
|
|
||||||
|
if text
|
||||||
|
htmlString = App.Utils.text2html(text)
|
||||||
|
|
||||||
|
htmlString
|
||||||
|
|
|
@ -263,11 +263,32 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin.prototype.onPaste = function (e) {
|
Plugin.prototype.getHtmlFromClipboard = function(clipboardData) {
|
||||||
e.preventDefault()
|
try {
|
||||||
this.log('paste')
|
return clipboardData.getData('text/html')
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log('Sorry, can\'t get html of clipboard because browser is not supporting it.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// insert and in case, resize images
|
Plugin.prototype.getTextFromClipboard = function(clipboardData) {
|
||||||
|
var text
|
||||||
|
try {
|
||||||
|
text = clipboardData.getData('text/plain')
|
||||||
|
if (!text || text.length === 0) {
|
||||||
|
text = clipboardData.getData('text')
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log('Sorry, can\'t get text of clipboard because browser is not supporting it.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.getClipboardData = function(e) {
|
||||||
var clipboardData
|
var clipboardData
|
||||||
if (e.clipboardData) { // ie
|
if (e.clipboardData) { // ie
|
||||||
clipboardData = e.clipboardData
|
clipboardData = e.clipboardData
|
||||||
|
@ -281,30 +302,41 @@
|
||||||
else {
|
else {
|
||||||
throw "No clipboardData support"
|
throw "No clipboardData support"
|
||||||
}
|
}
|
||||||
|
return clipboardData
|
||||||
|
}
|
||||||
|
|
||||||
if (clipboardData && clipboardData.items && clipboardData.items[0]) {
|
Plugin.prototype.getClipboardDataImage = function(clipboardData) {
|
||||||
var imageInserted = false
|
if (!clipboardData.items || !clipboardData.items[0]) {
|
||||||
var item
|
return
|
||||||
|
}
|
||||||
|
return $.grep(clipboardData.items, function(item){
|
||||||
|
return item.kind == 'file' && (item.type == 'image/png' || item.type == 'image/jpeg')
|
||||||
|
})[0]
|
||||||
|
}
|
||||||
|
|
||||||
// look for image only if no HTML with textual content is available.
|
Plugin.prototype.onPaste = function (e) {
|
||||||
// E.g. Excel provides images of the spreadsheet along with HTML.
|
e.preventDefault()
|
||||||
// While some browsers make images available in clipboard as HTML,
|
var clipboardData, clipboardImage, text, htmlRaw, htmlString
|
||||||
// sometimes wrapped in multiple nodes.
|
|
||||||
|
|
||||||
var rawHTML = clipboardData.getData('text/html')
|
this.log('paste')
|
||||||
var parsedHTML = jQuery(jQuery.parseHTML(rawHTML))
|
|
||||||
|
|
||||||
if(parsedHTML.text().trim().length == 0) {
|
clipboardData = this.getClipboardData(e)
|
||||||
item = jQuery.grep(clipboardData.items, function(item){
|
|
||||||
return item.kind == 'file' && (item.type == 'image/png' || item.type == 'image/jpeg')
|
|
||||||
})[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item) {
|
// look for image only if no HTML with textual content is available.
|
||||||
this.log('paste image', item)
|
// E.g. Excel provides images of the spreadsheet along with HTML.
|
||||||
console.log(item)
|
// While some browsers make images available in clipboard as HTML,
|
||||||
|
// sometimes wrapped in multiple nodes.
|
||||||
|
htmlRaw = this.getHtmlFromClipboard(clipboardData)
|
||||||
|
|
||||||
var imageFile = item.getAsFile()
|
if (!App.Utils.clipboardHtmlIsWithText(htmlRaw)) {
|
||||||
|
|
||||||
|
// insert and in case, resize images
|
||||||
|
clipboardImage = this.getClipboardDataImage(clipboardData)
|
||||||
|
if (clipboardImage) {
|
||||||
|
|
||||||
|
this.log('paste image', clipboardImage)
|
||||||
|
|
||||||
|
var imageFile = clipboardImage.getAsFile()
|
||||||
var reader = new FileReader()
|
var reader = new FileReader()
|
||||||
|
|
||||||
reader.onload = $.proxy(function (e) {
|
reader.onload = $.proxy(function (e) {
|
||||||
|
@ -340,74 +372,35 @@
|
||||||
}, this)
|
}, this)
|
||||||
|
|
||||||
reader.readAsDataURL(imageFile)
|
reader.readAsDataURL(imageFile)
|
||||||
imageInserted = true
|
return true
|
||||||
} else {
|
|
||||||
item = clipboardData.items[0]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (imageInserted) {
|
|
||||||
|
// insert html
|
||||||
|
if (htmlRaw) {
|
||||||
|
htmlString = App.Utils.clipboardHtmlInsertPreperation(htmlRaw, this.options)
|
||||||
|
if (htmlString) {
|
||||||
|
this.log('insert html from clipboard', htmlString)
|
||||||
|
this.paste(htmlString)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert text
|
||||||
|
text = this.getTextFromClipboard(clipboardData)
|
||||||
|
if (!text) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
htmlString = App.Utils.text2html(text)
|
||||||
|
|
||||||
|
// check length limit
|
||||||
|
if (!this.maxLengthOk(htmlString.length)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check existing + paste text for limit
|
htmlString = App.Utils.removeEmptyLines(htmlString)
|
||||||
var text, docType
|
this.log('insert text from clipboard', htmlString)
|
||||||
try {
|
this.paste(htmlString)
|
||||||
text = clipboardData.getData('text/html')
|
|
||||||
docType = 'html'
|
|
||||||
if (!text || text.length === 0) {
|
|
||||||
docType = 'text'
|
|
||||||
text = clipboardData.getData('text/plain')
|
|
||||||
}
|
|
||||||
if (!text || text.length === 0) {
|
|
||||||
docType = 'text2'
|
|
||||||
text = clipboardData.getData('text')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.log('Sorry, can\'t insert markup because browser is not supporting it.')
|
|
||||||
docType = 'text3'
|
|
||||||
text = clipboardData.getData('text')
|
|
||||||
}
|
|
||||||
this.log('paste', docType, text)
|
|
||||||
|
|
||||||
if (docType == 'html') {
|
|
||||||
if (this.options.mode === 'textonly') {
|
|
||||||
if (!this.options.multiline) {
|
|
||||||
text = App.Utils.htmlRemoveTags(text)
|
|
||||||
this.log('htmlRemoveTags', text)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.log('htmlRemoveRichtext', text)
|
|
||||||
text = App.Utils.htmlRemoveRichtext(text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.log('htmlCleanup', text)
|
|
||||||
text = App.Utils.htmlCleanup(text)
|
|
||||||
}
|
|
||||||
text = text.html()
|
|
||||||
this.log('text.html()', text)
|
|
||||||
|
|
||||||
// as fallback, take text
|
|
||||||
if (!text) {
|
|
||||||
text = App.Utils.text2html(text.text())
|
|
||||||
this.log('text2html', text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
text = App.Utils.text2html(text)
|
|
||||||
this.log('text2html', text)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.maxLengthOk(text.length)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// cleanup
|
|
||||||
text = App.Utils.removeEmptyLines(text)
|
|
||||||
this.log('insert', text)
|
|
||||||
|
|
||||||
this.paste(text)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,35 @@ test("text2html", function() {
|
||||||
result = App.Utils.text2html(source)
|
result = App.Utils.text2html(source)
|
||||||
equal(result, should, source)
|
equal(result, should, source)
|
||||||
|
|
||||||
|
source = "Some\nValue\n"
|
||||||
|
should = "<div>Some</div><div>Value</div>"
|
||||||
|
result = App.Utils.text2html(source)
|
||||||
|
equal(result, should, source)
|
||||||
|
|
||||||
|
source = "Some\rValue\r"
|
||||||
|
should = "<div>Some</div><div>Value</div>"
|
||||||
|
result = App.Utils.text2html(source)
|
||||||
|
equal(result, should, source)
|
||||||
|
|
||||||
|
source = "Some\n\rValue\n\r"
|
||||||
|
should = "<div>Some</div><div>Value</div>"
|
||||||
|
result = App.Utils.text2html(source)
|
||||||
|
equal(result, should, source)
|
||||||
|
|
||||||
|
source = "Some\r\nValue\r\n"
|
||||||
|
should = "<div>Some</div><div>Value</div>"
|
||||||
|
result = App.Utils.text2html(source)
|
||||||
|
equal(result, should, source)
|
||||||
|
|
||||||
|
source = "Some Value 123"
|
||||||
|
should = "<div>Some Value 123</div>"
|
||||||
|
result = App.Utils.text2html(source)
|
||||||
|
equal(result, should, source)
|
||||||
|
|
||||||
|
source = "Some\n Value\n 123"
|
||||||
|
should = "<div>Some</div><div> Value</div><div> 123</div>"
|
||||||
|
result = App.Utils.text2html(source)
|
||||||
|
equal(result, should, source)
|
||||||
});
|
});
|
||||||
|
|
||||||
// htmlStrip
|
// htmlStrip
|
||||||
|
@ -3306,3 +3335,35 @@ test('App.Utils.joinUrlComponents()', function() {
|
||||||
// expect @joinUrlComponents() to filter them out of the results before joining the rest with slashes
|
// expect @joinUrlComponents() to filter them out of the results before joining the rest with slashes
|
||||||
equal(App.Utils.joinUrlComponents('foo', undefined, 'bar', null, 'baz'), 'foo/bar/baz', 'with a list including null or undefined')
|
equal(App.Utils.joinUrlComponents('foo', undefined, 'bar', null, 'baz'), 'foo/bar/baz', 'with a list including null or undefined')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('App.Utils.clipboardHtmlIsWithText()', function() {
|
||||||
|
|
||||||
|
// no content with text
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('<div></div>'), false)
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('<div> </div>'), false)
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('<div><img src="test.jpg"/></div>'), false)
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('<div><!-- some comment --></div>'), false)
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('<div><!-- some comment --> </div>'), false)
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText("<div><!-- some comment --> \n </div>"), false)
|
||||||
|
|
||||||
|
// content with text
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('test'), true)
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('<div>test</div>'), true)
|
||||||
|
equal(App.Utils.clipboardHtmlIsWithText('<meta http-equiv="content-type" content="text/html; charset=utf-8">sometext'), true)
|
||||||
|
});
|
||||||
|
|
||||||
|
test('App.Utils.clipboardHtmlInsertPreperation()', function() {
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div></div>', {}), '')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div> </div>', {}), ' ')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div><img src="test.jpg"/></div>', {}), '<img src="test.jpg">')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div><!-- some comment --></div>', {}), '')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div><!-- some comment --> </div>', {}), ' ')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation("<div><!-- some comment --> \n </div>", {}), " \n ")
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('test', {}), 'test')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div>test</div>', {}), 'test')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<meta http-equiv="content-type" content="text/html; charset=utf-8">sometext', {}), '<div>sometext</div>')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b> 123</div>', { mode: 'textonly' }), 'test 123')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b><br> 123</div>', { mode: 'textonly' }), 'test 123')
|
||||||
|
equal(App.Utils.clipboardHtmlInsertPreperation('<div><b>test</b><br> 123</div>', { mode: 'textonly', multiline: true }), 'test<br> 123')
|
||||||
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue