Allow inline images via c&p.
This commit is contained in:
parent
179582852f
commit
c8ed4a83c3
9 changed files with 93 additions and 14 deletions
|
@ -191,10 +191,10 @@ class App.ControllerForm extends App.Controller
|
||||||
###
|
###
|
||||||
|
|
||||||
formGenItem: (attribute_config, classname, form, attribute_count) ->
|
formGenItem: (attribute_config, classname, form, attribute_count) ->
|
||||||
attribute = clone( attribute_config, true )
|
attribute = clone(attribute_config, true)
|
||||||
|
|
||||||
# create item id
|
# create item id
|
||||||
attribute.id = classname + '_' + attribute.name
|
attribute.id = "#{classname}_#{attribute.name}"
|
||||||
|
|
||||||
# set label class name
|
# set label class name
|
||||||
attribute.label_class = @model.labelClass
|
attribute.label_class = @model.labelClass
|
||||||
|
|
|
@ -128,7 +128,7 @@ class Index extends App.Controller
|
||||||
)
|
)
|
||||||
|
|
||||||
# add resized image
|
# add resized image
|
||||||
App.ImageService.resizeForAvatar( src, 'auto', 160, store )
|
App.ImageService.resizeForAvatar(src, 'auto', 160, store)
|
||||||
|
|
||||||
onUpload: (event) =>
|
onUpload: (event) =>
|
||||||
callback = @storeImage
|
callback = @storeImage
|
||||||
|
|
|
@ -365,7 +365,7 @@ class Base extends App.WizardFullScreen
|
||||||
)
|
)
|
||||||
|
|
||||||
# add resized image
|
# add resized image
|
||||||
App.ImageService.resizeForApp( @params.logo, @logoPreview.width(), @logoPreview.height(), store )
|
App.ImageService.resizeForApp(@params.logo, @logoPreview.width(), @logoPreview.height(), store)
|
||||||
|
|
||||||
hideAlerts: =>
|
hideAlerts: =>
|
||||||
@$('.form-group').removeClass('has-error')
|
@$('.form-group').removeClass('has-error')
|
||||||
|
|
|
@ -4,15 +4,15 @@ class App.ImageService
|
||||||
if @checkUrl(dataURL)
|
if @checkUrl(dataURL)
|
||||||
callback(dataURL)
|
callback(dataURL)
|
||||||
else
|
else
|
||||||
@resize( dataURL, x, y, 2, 'image/jpeg', 0.7, callback )
|
@resize(dataURL, x, y, 2, 'image/jpeg', 0.7, callback)
|
||||||
|
|
||||||
@resizeForApp: (dataURL, x, y, callback) =>
|
@resizeForApp: (dataURL, x, y, callback) =>
|
||||||
if @checkUrl(dataURL)
|
if @checkUrl(dataURL)
|
||||||
callback(dataURL)
|
callback(dataURL)
|
||||||
else
|
else
|
||||||
@resize( dataURL, x, y, 2, 'image/png', 0.7, callback )
|
@resize(dataURL, x, y, 2, 'image/png', 0.7, callback)
|
||||||
|
|
||||||
@resize: ( dataURL, x = 'auto', y = 'auto', sizeFactor = 1, type, quallity, callback) ->
|
@resize: (dataURL, x = 'auto', y = 'auto', sizeFactor = 1, type, quallity, callback, force = true) ->
|
||||||
|
|
||||||
# load image from data url
|
# load image from data url
|
||||||
imageObject = new Image()
|
imageObject = new Image()
|
||||||
|
@ -32,9 +32,15 @@ class App.ImageService
|
||||||
factor = imageWidth / y
|
factor = imageWidth / y
|
||||||
x = imageHeight / factor
|
x = imageHeight / factor
|
||||||
|
|
||||||
|
# check if resize is needed
|
||||||
|
resize = false
|
||||||
if x < imageWidth || y < imageHeight
|
if x < imageWidth || y < imageHeight
|
||||||
|
resize = true
|
||||||
x = x * sizeFactor
|
x = x * sizeFactor
|
||||||
y = y * sizeFactor
|
y = y * sizeFactor
|
||||||
|
else
|
||||||
|
x = imageWidth
|
||||||
|
y = imageHeight
|
||||||
|
|
||||||
# create canvas and set dimensions
|
# create canvas and set dimensions
|
||||||
canvas = document.createElement('canvas')
|
canvas = document.createElement('canvas')
|
||||||
|
@ -43,15 +49,33 @@ class App.ImageService
|
||||||
|
|
||||||
# draw image on canvas and set image dimensions
|
# draw image on canvas and set image dimensions
|
||||||
context = canvas.getContext('2d')
|
context = canvas.getContext('2d')
|
||||||
context.drawImage( imageObject, 0, 0, x, y )
|
context.drawImage(imageObject, 0, 0, x, y)
|
||||||
|
|
||||||
|
# set quallity based on image size
|
||||||
|
if quallity == 'auto'
|
||||||
|
if x < 200 && y < 200
|
||||||
|
quallity = 1
|
||||||
|
else if x < 400 && y < 400
|
||||||
|
quallity = 0.9
|
||||||
|
else if x < 600 && y < 600
|
||||||
|
quallity = 0.8
|
||||||
|
else if x < 900 && y < 900
|
||||||
|
quallity = 0.7
|
||||||
|
else
|
||||||
|
quallity = 0.6
|
||||||
|
|
||||||
# execute callback with resized image
|
# execute callback with resized image
|
||||||
newDataUrl = canvas.toDataURL( type, quallity )
|
newDataUrl = canvas.toDataURL(type, quallity)
|
||||||
callback(newDataUrl)
|
if resize
|
||||||
|
console.log('ImageService', 'resize', x/sizeFactor, y/sizeFactor, quallity, (newDataUrl.length * 0.75)/1024/1024, 'in mb')
|
||||||
|
callback(newDataUrl, x/sizeFactor, y/sizeFactor)
|
||||||
|
return
|
||||||
|
console.log('ImageService', 'no resize', x, y, quallity, (newDataUrl.length * 0.75)/1024/1024, 'in mb')
|
||||||
|
callback(newDataUrl, x, y)
|
||||||
|
|
||||||
# load image from data url
|
# load image from data url
|
||||||
imageObject.src = dataURL
|
imageObject.src = dataURL
|
||||||
|
|
||||||
@checkUrl: (dataURL) ->
|
@checkUrl: (dataURL) ->
|
||||||
ignore = /\.svg$/i
|
ignore = /\.svg$/i
|
||||||
ignore.test( dataURL )
|
ignore.test(dataURL)
|
||||||
|
|
|
@ -206,6 +206,13 @@ class App.Utils
|
||||||
.removeAttr('lang')
|
.removeAttr('lang')
|
||||||
.removeAttr('type')
|
.removeAttr('type')
|
||||||
html
|
html
|
||||||
|
.removeAttr('style')
|
||||||
|
.removeAttr('class')
|
||||||
|
.removeAttr('title')
|
||||||
|
.removeAttr('lang')
|
||||||
|
.removeAttr('type')
|
||||||
|
|
||||||
|
html
|
||||||
|
|
||||||
@_removeComments: (html) ->
|
@_removeComments: (html) ->
|
||||||
html.contents().each( ->
|
html.contents().each( ->
|
||||||
|
|
|
@ -187,6 +187,43 @@
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
_this.log('paste')
|
_this.log('paste')
|
||||||
|
|
||||||
|
// insert and in case, resize images
|
||||||
|
var clipboardData = e.originalEvent.clipboardData
|
||||||
|
if (clipboardData && clipboardData.items) {
|
||||||
|
var imageInserted = false
|
||||||
|
jQuery.each(clipboardData.items, function(index, item){
|
||||||
|
console.log(index, item)
|
||||||
|
if (item.kind == 'file' && item.type == 'image/png') {
|
||||||
|
_this.log('paste image', item)
|
||||||
|
|
||||||
|
var imageFile = item.getAsFile()
|
||||||
|
var reader = new FileReader()
|
||||||
|
|
||||||
|
reader.onload = function (e) {
|
||||||
|
var result = e.target.result
|
||||||
|
var img = document.createElement('img')
|
||||||
|
img.src = result
|
||||||
|
|
||||||
|
insert = function(dataUrl, width, height) {
|
||||||
|
//console.log('dataUrl', dataUrl)
|
||||||
|
_this.log('image inserted')
|
||||||
|
result = dataUrl
|
||||||
|
img = "<img style=\"width: " + width + "px; height: " + height + "px\" src=\"" + result + "\">"
|
||||||
|
document.execCommand('insertHTML', false, img)
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize if to big
|
||||||
|
App.ImageService.resize(img.src, 460, 'auto', 2, 'image/jpeg', 'auto', insert)
|
||||||
|
}
|
||||||
|
reader.readAsDataURL(imageFile)
|
||||||
|
imageInserted = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (imageInserted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// check existing + paste text for limit
|
// check existing + paste text for limit
|
||||||
var text = e.originalEvent.clipboardData.getData('text/html')
|
var text = e.originalEvent.clipboardData.getData('text/html')
|
||||||
var docType = 'html'
|
var docType = 'html'
|
||||||
|
|
|
@ -56,7 +56,7 @@ class CreateBase < ActiveRecord::Migration
|
||||||
|
|
||||||
create_table :signatures do |t|
|
create_table :signatures do |t|
|
||||||
t.string :name, limit: 100, null: false
|
t.string :name, limit: 100, null: false
|
||||||
t.string :body, limit: 5000, null: true
|
t.text :body, limit: 10.megabytes + 1, null: true
|
||||||
t.boolean :active, null: false, default: true
|
t.boolean :active, null: false, default: true
|
||||||
t.string :note, limit: 250, null: true
|
t.string :note, limit: 250, null: true
|
||||||
t.integer :updated_by_id, null: false
|
t.integer :updated_by_id, null: false
|
||||||
|
|
|
@ -153,7 +153,7 @@ class CreateTicket < ActiveRecord::Migration
|
||||||
t.column :in_reply_to, :string, limit: 3000, null: true
|
t.column :in_reply_to, :string, limit: 3000, null: true
|
||||||
t.column :content_type, :string, limit: 20, null: false, default: 'text/plain'
|
t.column :content_type, :string, limit: 20, null: false, default: 'text/plain'
|
||||||
t.column :references, :string, limit: 3200, null: true
|
t.column :references, :string, limit: 3200, null: true
|
||||||
t.column :body, :text, limit: 4.megabytes + 1
|
t.column :body, :text, limit: 20.megabytes + 1, null: false
|
||||||
t.column :internal, :boolean, null: false, default: false
|
t.column :internal, :boolean, null: false, default: false
|
||||||
t.column :preferences, :text, limit: 500.kilobytes + 1, null: true
|
t.column :preferences, :text, limit: 500.kilobytes + 1, null: true
|
||||||
t.column :updated_by_id, :integer, null: false
|
t.column :updated_by_id, :integer, null: false
|
||||||
|
@ -303,7 +303,7 @@ class CreateTicket < ActiveRecord::Migration
|
||||||
t.references :user, null: true
|
t.references :user, null: true
|
||||||
t.column :name, :string, limit: 250, null: false
|
t.column :name, :string, limit: 250, null: false
|
||||||
t.column :keywords, :string, limit: 500, null: true
|
t.column :keywords, :string, limit: 500, null: true
|
||||||
t.column :content, :string, limit: 5000, null: false
|
t.column :content, :text, limit: 10.megabytes + 1, null: false
|
||||||
t.column :note, :string, limit: 250, null: true
|
t.column :note, :string, limit: 250, null: true
|
||||||
t.column :active, :boolean, null: false, default: true
|
t.column :active, :boolean, null: false, default: true
|
||||||
t.column :updated_by_id, :integer, null: false
|
t.column :updated_by_id, :integer, null: false
|
||||||
|
|
11
db/migrate/20160509000001_contenteditable_iamges.rb
Normal file
11
db/migrate/20160509000001_contenteditable_iamges.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
class ContenteditableIamges < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
# return if it's a new setup
|
||||||
|
return if !Setting.find_by(name: 'system_init_done')
|
||||||
|
|
||||||
|
change_column :text_modules, :content, :text, limit: 10.megabytes + 1, null: false
|
||||||
|
change_column :signatures, :body, :text, limit: 10.megabytes + 1, null: true
|
||||||
|
change_column :ticket_articles, :body, :text, limit: 20.megabytes + 1, null: false
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue