Merge branch 'private-richtext-object-resizing-shim' into develop
This commit is contained in:
commit
fa53eeb33a
5 changed files with 724 additions and 482 deletions
|
@ -66,402 +66,408 @@
|
||||||
this.browserMagicKey = App.Browser.magicKey()
|
this.browserMagicKey = App.Browser.magicKey()
|
||||||
this.browserHotkeys = App.Browser.hotkeys()
|
this.browserHotkeys = App.Browser.hotkeys()
|
||||||
|
|
||||||
this.init();
|
this.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Plugin.prototype.init = function () {
|
Plugin.prototype.init = function () {
|
||||||
var _this = this
|
this.bindEvents()
|
||||||
|
this.$element.enableObjectResizingShim()
|
||||||
|
}
|
||||||
|
|
||||||
this.toggleBlock = function(tag) {
|
Plugin.prototype.bindEvents = function () {
|
||||||
sel = window.getSelection()
|
this.$element.on('keydown', this.onKeydown.bind(this))
|
||||||
node = $(sel.anchorNode)
|
this.$element.on('paste', this.onPaste.bind(this))
|
||||||
if (node.is(tag) || node.parent().is(tag) || node.parent().parent().is(tag)) {
|
this.$element.on('dragover', this.onDragover.bind(this))
|
||||||
document.execCommand('formatBlock', false, 'div')
|
this.$element.on('drop', this.onDrop.bind(this))
|
||||||
//document.execCommand('RemoveFormat')
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.toggleBlock = function(tag) {
|
||||||
|
sel = window.getSelection()
|
||||||
|
node = $(sel.anchorNode)
|
||||||
|
if (node.is(tag) || node.parent().is(tag) || node.parent().parent().is(tag)) {
|
||||||
|
document.execCommand('formatBlock', false, 'div')
|
||||||
|
//document.execCommand('RemoveFormat')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
document.execCommand('formatBlock', false, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.onKeydown = function (e) {
|
||||||
|
this.log('keydown', e.keyCode)
|
||||||
|
if (this.preventInput) {
|
||||||
|
this.log('preventInput', this.preventInput)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// strap the return key being pressed
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
|
||||||
|
// disbale multi line
|
||||||
|
if (!this.options.multiline) {
|
||||||
|
e.preventDefault()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
document.execCommand('formatBlock', false, tag)
|
// break <blockquote> after enter on empty line
|
||||||
|
sel = window.getSelection()
|
||||||
|
if (sel) {
|
||||||
|
node = $(sel.anchorNode)
|
||||||
|
if (node && node.parent() && node.parent().is('blockquote')) {
|
||||||
|
e.preventDefault()
|
||||||
|
document.execCommand('Insertparagraph')
|
||||||
|
document.execCommand('Outdent')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// behavior to enter new line on alt+enter
|
||||||
|
// on alt + enter not realy newline is fired, to make
|
||||||
|
// it compat. to other systems, do it here
|
||||||
|
if (!e.shiftKey && e.altKey && !e.ctrlKey && !e.metaKey) {
|
||||||
|
e.preventDefault()
|
||||||
|
this.paste('<br><br>')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle enter
|
// on zammad magicKey + i/b/u/s
|
||||||
this.$element.on('keydown', function (e) {
|
// hotkeys + u -> Toggles the current selection between underlined and not underlined
|
||||||
_this.log('keydown', e.keyCode)
|
// hotkeys + b -> Toggles the current selection between bold and non-bold
|
||||||
if (_this.preventInput) {
|
// hotkeys + i -> Toggles the current selection between italic and non-italic
|
||||||
this.log('preventInput', _this.preventInput)
|
// hotkeys + v -> Toggles the current selection between strike and non-strike
|
||||||
return
|
// hotkeys + f -> Removes the formatting tags from the current selection
|
||||||
|
// hotkeys + y -> Removes the formatting from while textarea
|
||||||
|
// hotkeys + z -> Inserts a Horizontal Rule
|
||||||
|
// hotkeys + l -> Toggles the text selection between an unordered list and a normal block
|
||||||
|
// hotkeys + k -> Toggles the text selection between an ordered list and a normal block
|
||||||
|
// hotkeys + o -> Draws a line through the middle of the current selection
|
||||||
|
// hotkeys + w -> Removes any hyperlink from the current selection
|
||||||
|
var richtTextControl = false
|
||||||
|
if (this.browserMagicKey == 'cmd') {
|
||||||
|
if (!e.altKey && !e.ctrlKey && e.metaKey) {
|
||||||
|
richtTextControl = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// strap the return key being pressed
|
else {
|
||||||
if (e.keyCode === 13) {
|
if (!e.altKey && e.ctrlKey && !e.metaKey) {
|
||||||
|
richtTextControl = true
|
||||||
// disbale multi line
|
|
||||||
if (!_this.options.multiline) {
|
|
||||||
e.preventDefault()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// break <blockquote> after enter on empty line
|
|
||||||
sel = window.getSelection()
|
|
||||||
if (sel) {
|
|
||||||
node = $(sel.anchorNode)
|
|
||||||
if (node && node.parent() && node.parent().is('blockquote')) {
|
|
||||||
e.preventDefault()
|
|
||||||
document.execCommand('Insertparagraph')
|
|
||||||
document.execCommand('Outdent')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// behavior to enter new line on alt+enter
|
|
||||||
// on alt + enter not realy newline is fired, to make
|
|
||||||
// it compat. to other systems, do it here
|
|
||||||
if (!e.shiftKey && e.altKey && !e.ctrlKey && !e.metaKey) {
|
|
||||||
e.preventDefault()
|
|
||||||
_this.paste('<br><br>')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// on zammad magicKey + i/b/u/s
|
if (richtTextControl && this.options.richTextFormatKey[ e.keyCode ]) {
|
||||||
// hotkeys + u -> Toggles the current selection between underlined and not underlined
|
e.preventDefault()
|
||||||
// hotkeys + b -> Toggles the current selection between bold and non-bold
|
if (e.keyCode == 66) {
|
||||||
// hotkeys + i -> Toggles the current selection between italic and non-italic
|
document.execCommand('bold')
|
||||||
// hotkeys + v -> Toggles the current selection between strike and non-strike
|
|
||||||
// hotkeys + f -> Removes the formatting tags from the current selection
|
|
||||||
// hotkeys + y -> Removes the formatting from while textarea
|
|
||||||
// hotkeys + z -> Inserts a Horizontal Rule
|
|
||||||
// hotkeys + l -> Toggles the text selection between an unordered list and a normal block
|
|
||||||
// hotkeys + k -> Toggles the text selection between an ordered list and a normal block
|
|
||||||
// hotkeys + o -> Draws a line through the middle of the current selection
|
|
||||||
// hotkeys + w -> Removes any hyperlink from the current selection
|
|
||||||
var richtTextControl = false
|
|
||||||
if (_this.browserMagicKey == 'cmd') {
|
|
||||||
if (!e.altKey && !e.ctrlKey && e.metaKey) {
|
|
||||||
richtTextControl = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!e.altKey && e.ctrlKey && !e.metaKey) {
|
|
||||||
richtTextControl = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (richtTextControl && _this.options.richTextFormatKey[ e.keyCode ]) {
|
|
||||||
e.preventDefault()
|
|
||||||
if (e.keyCode == 66) {
|
|
||||||
document.execCommand('bold')
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (e.keyCode == 73) {
|
|
||||||
document.execCommand('italic')
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (e.keyCode == 85) {
|
|
||||||
document.execCommand('underline')
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (e.keyCode == 83) {
|
|
||||||
document.execCommand('strikeThrough')
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var hotkeys = false
|
|
||||||
if (_this.browserHotkeys == 'ctrl+shift') {
|
|
||||||
if (!e.altKey && e.ctrlKey && !e.metaKey && e.shiftKey) {
|
|
||||||
hotkeys = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (e.altKey && e.ctrlKey && !e.metaKey) {
|
|
||||||
hotkeys = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hotkeys && (_this.options.richTextFormatKey[ e.keyCode ]
|
|
||||||
|| e.keyCode == 49
|
|
||||||
|| e.keyCode == 50
|
|
||||||
|| e.keyCode == 51
|
|
||||||
|| e.keyCode == 66
|
|
||||||
|| e.keyCode == 70
|
|
||||||
|| e.keyCode == 90
|
|
||||||
|| e.keyCode == 70
|
|
||||||
|| e.keyCode == 73
|
|
||||||
|| e.keyCode == 75
|
|
||||||
|| e.keyCode == 76
|
|
||||||
|| e.keyCode == 85
|
|
||||||
|| e.keyCode == 86
|
|
||||||
|| e.keyCode == 88
|
|
||||||
|| e.keyCode == 90
|
|
||||||
|| e.keyCode == 89)) {
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
// disable rich text b/u/i
|
|
||||||
if ( _this.options.mode === 'textonly' ) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.keyCode == 49) {
|
|
||||||
_this.toggleBlock('h1')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 50) {
|
|
||||||
_this.toggleBlock('h2')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 51) {
|
|
||||||
_this.toggleBlock('h3')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 66) {
|
|
||||||
document.execCommand('bold')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 70) {
|
|
||||||
document.execCommand('removeFormat')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 73) {
|
|
||||||
document.execCommand('italic')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 75) {
|
|
||||||
document.execCommand('insertOrderedList')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 76) {
|
|
||||||
document.execCommand('insertUnorderedList')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 85) {
|
|
||||||
document.execCommand('underline')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 86) {
|
|
||||||
document.execCommand('strikeThrough')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 88) {
|
|
||||||
document.execCommand('unlink')
|
|
||||||
}
|
|
||||||
if (e.keyCode == 89) {
|
|
||||||
var cleanHtml = App.Utils.htmlRemoveRichtext(_this.$element.html())
|
|
||||||
_this.$element.html(cleanHtml)
|
|
||||||
}
|
|
||||||
if (e.keyCode == 90) {
|
|
||||||
document.execCommand('insertHorizontalRule')
|
|
||||||
}
|
|
||||||
_this.log('content editable richtext key', e.keyCode)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (e.keyCode == 73) {
|
||||||
// limit check
|
document.execCommand('italic')
|
||||||
if ( !_this.allowKey(e) ) {
|
return true
|
||||||
if ( !_this.maxLengthOk(1) ) {
|
|
||||||
e.preventDefault()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
if (e.keyCode == 85) {
|
||||||
|
document.execCommand('underline')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (e.keyCode == 83) {
|
||||||
|
document.execCommand('strikeThrough')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// just paste text
|
var hotkeys = false
|
||||||
this.$element.on('paste', function (e) {
|
if (this.browserHotkeys == 'ctrl+shift') {
|
||||||
|
if (!e.altKey && e.ctrlKey && !e.metaKey && e.shiftKey) {
|
||||||
|
hotkeys = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (e.altKey && e.ctrlKey && !e.metaKey) {
|
||||||
|
hotkeys = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hotkeys && (this.options.richTextFormatKey[ e.keyCode ]
|
||||||
|
|| e.keyCode == 49
|
||||||
|
|| e.keyCode == 50
|
||||||
|
|| e.keyCode == 51
|
||||||
|
|| e.keyCode == 66
|
||||||
|
|| e.keyCode == 70
|
||||||
|
|| e.keyCode == 90
|
||||||
|
|| e.keyCode == 70
|
||||||
|
|| e.keyCode == 73
|
||||||
|
|| e.keyCode == 75
|
||||||
|
|| e.keyCode == 76
|
||||||
|
|| e.keyCode == 85
|
||||||
|
|| e.keyCode == 86
|
||||||
|
|| e.keyCode == 88
|
||||||
|
|| e.keyCode == 90
|
||||||
|
|| e.keyCode == 89)) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
_this.log('paste')
|
|
||||||
|
|
||||||
// insert and in case, resize images
|
// disable rich text b/u/i
|
||||||
var clipboardData
|
if ( this.options.mode === 'textonly' ) {
|
||||||
if (e.clipboardData) { // ie
|
|
||||||
clipboardData = e.clipboardData
|
|
||||||
}
|
|
||||||
else if (window.clipboardData) { // ie
|
|
||||||
clipboardData = window.clipboardData
|
|
||||||
}
|
|
||||||
else if (e.originalEvent.clipboardData) { // other browsers
|
|
||||||
clipboardData = e.originalEvent.clipboardData
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "No clipboardData support"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clipboardData && clipboardData.items && clipboardData.items[0]) {
|
|
||||||
var imageInserted = false
|
|
||||||
var item = clipboardData.items[0]
|
|
||||||
if (item.kind == 'file' && (item.type == 'image/png' || item.type == 'image/jpeg')) {
|
|
||||||
_this.log('paste image', item)
|
|
||||||
console.log(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
|
|
||||||
maxWidth = _this.$element.width() || 500
|
|
||||||
scaleFactor = 2
|
|
||||||
//scaleFactor = 1
|
|
||||||
//if (window.isRetina && window.isRetina()) {
|
|
||||||
// scaleFactor = 2
|
|
||||||
//}
|
|
||||||
|
|
||||||
insert = function(dataUrl, width, height, isResized) {
|
|
||||||
//console.log('dataUrl', dataUrl)
|
|
||||||
//console.log('scaleFactor', scaleFactor, isResized, maxWidth, width, height)
|
|
||||||
_this.log('image inserted')
|
|
||||||
result = dataUrl
|
|
||||||
if (_this.options.imageWidth == 'absolute') {
|
|
||||||
img = "<img style=\"width: " + width + "px; height: " + height + "px\" src=\"" + result + "\">"
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
img = "<img style=\"width: 100%; max-width: " + width + "px;\" src=\"" + result + "\">"
|
|
||||||
}
|
|
||||||
_this.paste(img)
|
|
||||||
}
|
|
||||||
|
|
||||||
// resize if to big
|
|
||||||
App.ImageService.resize(img.src, maxWidth, 'auto', scaleFactor, 'image/jpeg', 'auto', insert)
|
|
||||||
}
|
|
||||||
reader.readAsDataURL(imageFile)
|
|
||||||
imageInserted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (imageInserted) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// check existing + paste text for limit
|
if (e.keyCode == 49) {
|
||||||
var text, docType
|
this.toggleBlock('h1')
|
||||||
try {
|
|
||||||
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) {
|
if (e.keyCode == 50) {
|
||||||
console.log('Sorry, can\'t insert markup because browser is not supporting it.')
|
this.toggleBlock('h2')
|
||||||
docType = 'text3'
|
|
||||||
text = clipboardData.getData('text')
|
|
||||||
}
|
}
|
||||||
_this.log('paste', docType, text)
|
if (e.keyCode == 51) {
|
||||||
|
this.toggleBlock('h3')
|
||||||
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 {
|
if (e.keyCode == 66) {
|
||||||
text = App.Utils.text2html(text)
|
document.execCommand('bold')
|
||||||
_this.log('text2html', text)
|
|
||||||
}
|
}
|
||||||
|
if (e.keyCode == 70) {
|
||||||
if (!_this.maxLengthOk(text.length)) {
|
document.execCommand('removeFormat')
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
if (e.keyCode == 73) {
|
||||||
// cleanup
|
document.execCommand('italic')
|
||||||
text = App.Utils.removeEmptyLines(text)
|
}
|
||||||
_this.log('insert', text)
|
if (e.keyCode == 75) {
|
||||||
|
document.execCommand('insertOrderedList')
|
||||||
_this.paste(text)
|
}
|
||||||
|
if (e.keyCode == 76) {
|
||||||
|
document.execCommand('insertUnorderedList')
|
||||||
|
}
|
||||||
|
if (e.keyCode == 85) {
|
||||||
|
document.execCommand('underline')
|
||||||
|
}
|
||||||
|
if (e.keyCode == 86) {
|
||||||
|
document.execCommand('strikeThrough')
|
||||||
|
}
|
||||||
|
if (e.keyCode == 88) {
|
||||||
|
document.execCommand('unlink')
|
||||||
|
}
|
||||||
|
if (e.keyCode == 89) {
|
||||||
|
var cleanHtml = App.Utils.htmlRemoveRichtext(this.$element.html())
|
||||||
|
this.$element.html(cleanHtml)
|
||||||
|
}
|
||||||
|
if (e.keyCode == 90) {
|
||||||
|
document.execCommand('insertHorizontalRule')
|
||||||
|
}
|
||||||
|
this.log('content editable richtext key', e.keyCode)
|
||||||
return true
|
return true
|
||||||
})
|
}
|
||||||
|
|
||||||
this.$element.on('dragover', function (e) {
|
// limit check
|
||||||
e.stopPropagation()
|
if ( !this.allowKey(e) ) {
|
||||||
e.preventDefault()
|
if ( !this.maxLengthOk(1) ) {
|
||||||
_this.log('dragover')
|
e.preventDefault()
|
||||||
})
|
return
|
||||||
|
|
||||||
this.$element.on('drop', function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
_this.log('drop')
|
|
||||||
|
|
||||||
var dataTransfer
|
|
||||||
if (window.dataTransfer) { // ie
|
|
||||||
dataTransfer = window.dataTransfer
|
|
||||||
}
|
|
||||||
else if (e.originalEvent.dataTransfer) { // other browsers
|
|
||||||
dataTransfer = e.originalEvent.dataTransfer
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "No clipboardData support"
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// x and y coordinates of dropped item
|
Plugin.prototype.onPaste = function (e) {
|
||||||
x = e.clientX
|
e.preventDefault()
|
||||||
y = e.clientY
|
this.log('paste')
|
||||||
var file = dataTransfer.files[0]
|
|
||||||
|
|
||||||
// look for images
|
// insert and in case, resize images
|
||||||
if (file.type.match('image.*')) {
|
var clipboardData
|
||||||
|
if (e.clipboardData) { // ie
|
||||||
|
clipboardData = e.clipboardData
|
||||||
|
}
|
||||||
|
else if (window.clipboardData) { // ie
|
||||||
|
clipboardData = window.clipboardData
|
||||||
|
}
|
||||||
|
else if (e.originalEvent.clipboardData) { // other browsers
|
||||||
|
clipboardData = e.originalEvent.clipboardData
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "No clipboardData support"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clipboardData && clipboardData.items && clipboardData.items[0]) {
|
||||||
|
var imageInserted = false
|
||||||
|
var item = clipboardData.items[0]
|
||||||
|
if (item.kind == 'file' && (item.type == 'image/png' || item.type == 'image/jpeg')) {
|
||||||
|
this.log('paste image', item)
|
||||||
|
console.log(item)
|
||||||
|
|
||||||
|
var imageFile = item.getAsFile()
|
||||||
var reader = new FileReader()
|
var reader = new FileReader()
|
||||||
reader.onload = (function(e) {
|
|
||||||
|
reader.onload = $.proxy(function (e) {
|
||||||
var result = e.target.result
|
var result = e.target.result
|
||||||
var img = document.createElement('img')
|
var img = document.createElement('img')
|
||||||
img.src = result
|
img.src = result
|
||||||
maxWidth = _this.$element.width() || 500
|
maxWidth = this.$element.width() || 500
|
||||||
scaleFactor = 2
|
scaleFactor = 2
|
||||||
//scaleFactor = 1
|
//scaleFactor = 1
|
||||||
//if (window.isRetina && window.isRetina()) {
|
//if (window.isRetina && window.isRetina()) {
|
||||||
// scaleFactor = 2
|
// scaleFactor = 2
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//Insert the image at the carat
|
insert = $.proxy(function(dataUrl, width, height, isResized) {
|
||||||
insert = function(dataUrl, width, height, isResized) {
|
|
||||||
|
|
||||||
//console.log('dataUrl', dataUrl)
|
//console.log('dataUrl', dataUrl)
|
||||||
//console.log('scaleFactor', scaleFactor, isResized, maxWidth, width, height)
|
//console.log('scaleFactor', scaleFactor, isResized, maxWidth, width, height)
|
||||||
_this.log('image inserted')
|
this.log('image inserted')
|
||||||
result = dataUrl
|
result = dataUrl
|
||||||
if (_this.options.imageWidth == 'absolute') {
|
if (this.options.imageWidth == 'absolute') {
|
||||||
img = $("<img style=\"width: " + width + "px; height: " + height + "px\" src=\"" + result + "\">")
|
img = "<img tabindex=\"0\" style=\"width: " + width + "px; height: " + height + "px\" src=\"" + result + "\">"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
img = $("<img style=\"width: 100%; max-width: " + width + "px;\" src=\"" + result + "\">")
|
img = "<img tabindex=\"0\" style=\"width: 100%; max-width: " + width + "px;\" src=\"" + result + "\">"
|
||||||
}
|
}
|
||||||
img = img.get(0)
|
this.paste(img)
|
||||||
|
}, this)
|
||||||
if (document.caretPositionFromPoint) {
|
|
||||||
var pos = document.caretPositionFromPoint(x, y)
|
|
||||||
range = document.createRange();
|
|
||||||
range.setStart(pos.offsetNode, pos.offset)
|
|
||||||
range.collapse()
|
|
||||||
range.insertNode(img)
|
|
||||||
}
|
|
||||||
else if (document.caretRangeFromPoint) {
|
|
||||||
range = document.caretRangeFromPoint(x, y)
|
|
||||||
range.insertNode(img)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log('could not find carat')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resize if to big
|
// resize if to big
|
||||||
App.ImageService.resize(img.src, maxWidth, 'auto', scaleFactor, 'image/jpeg', 'auto', insert)
|
App.ImageService.resize(img.src, maxWidth, 'auto', scaleFactor, 'image/jpeg', 'auto', insert)
|
||||||
})
|
}, this)
|
||||||
reader.readAsDataURL(file)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
reader.readAsDataURL(imageFile)
|
||||||
|
imageInserted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (imageInserted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// check existing + paste text for limit
|
||||||
|
var text, docType
|
||||||
|
try {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.onDragover = function (e) {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
this.log('dragover')
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.onDrop = function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
this.log('drop')
|
||||||
|
|
||||||
|
var dataTransfer
|
||||||
|
if (window.dataTransfer) { // ie
|
||||||
|
dataTransfer = window.dataTransfer
|
||||||
|
}
|
||||||
|
else if (e.originalEvent.dataTransfer) { // other browsers
|
||||||
|
dataTransfer = e.originalEvent.dataTransfer
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "No clipboardData support"
|
||||||
|
}
|
||||||
|
|
||||||
|
// x and y coordinates of dropped item
|
||||||
|
x = e.clientX
|
||||||
|
y = e.clientY
|
||||||
|
var file = dataTransfer.files[0]
|
||||||
|
|
||||||
|
// look for images
|
||||||
|
if (file.type.match('image.*')) {
|
||||||
|
var reader = new FileReader()
|
||||||
|
reader.onload = (function(e) {
|
||||||
|
var result = e.target.result
|
||||||
|
var img = document.createElement('img')
|
||||||
|
img.src = result
|
||||||
|
maxWidth = this.$element.width() || 500
|
||||||
|
scaleFactor = 2
|
||||||
|
//scaleFactor = 1
|
||||||
|
//if (window.isRetina && window.isRetina()) {
|
||||||
|
// scaleFactor = 2
|
||||||
|
//}
|
||||||
|
|
||||||
|
//Insert the image at the carat
|
||||||
|
insert = function(dataUrl, width, height, isResized) {
|
||||||
|
|
||||||
|
//console.log('dataUrl', dataUrl)
|
||||||
|
//console.log('scaleFactor', scaleFactor, isResized, maxWidth, width, height)
|
||||||
|
this.log('image inserted')
|
||||||
|
result = dataUrl
|
||||||
|
if (this.options.imageWidth == 'absolute') {
|
||||||
|
img = $("<img tabindex=\"0\" style=\"width: " + width + "px; height: " + height + "px\" src=\"" + result + "\">")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
img = $("<img tabindex=\"0\" style=\"width: 100%; max-width: " + width + "px;\" src=\"" + result + "\">")
|
||||||
|
}
|
||||||
|
img = img.get(0)
|
||||||
|
|
||||||
|
if (document.caretPositionFromPoint) {
|
||||||
|
var pos = document.caretPositionFromPoint(x, y)
|
||||||
|
range = document.createRange();
|
||||||
|
range.setStart(pos.offsetNode, pos.offset)
|
||||||
|
range.collapse()
|
||||||
|
range.insertNode(img)
|
||||||
|
}
|
||||||
|
else if (document.caretRangeFromPoint) {
|
||||||
|
range = document.caretRangeFromPoint(x, y)
|
||||||
|
range.insertNode(img)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('could not find carat')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize if to big
|
||||||
|
App.ImageService.resize(img.src, maxWidth, 'auto', scaleFactor, 'image/jpeg', 'auto', insert)
|
||||||
|
})
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if key is allowed, even if length limit is reached
|
// check if key is allowed, even if length limit is reached
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
(function ($, window, undefined) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
# mode: textonly/richtext / disable b/i/u/enter + strip on paste
|
||||||
|
# pasteOnlyText: true
|
||||||
|
# maxlength: 123
|
||||||
|
# multiline: true / disable enter + strip on paste
|
||||||
|
# placeholder: 'some placeholder'
|
||||||
|
#
|
||||||
|
*/
|
||||||
|
|
||||||
|
var pluginName = 'enableObjectResizingShim',
|
||||||
|
defaults = {
|
||||||
|
debug: false
|
||||||
|
}
|
||||||
|
|
||||||
|
function Plugin(element, options) {
|
||||||
|
this.element = element
|
||||||
|
this.$element = $(element)
|
||||||
|
|
||||||
|
this.options = $.extend({}, defaults, options)
|
||||||
|
|
||||||
|
this._defaults = defaults
|
||||||
|
this._name = pluginName
|
||||||
|
|
||||||
|
// only run if needed
|
||||||
|
if (!document.queryCommandSupported('enableObjectResizing')) {
|
||||||
|
this.bindEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.bindEvents = function () {
|
||||||
|
this.$element.on('click', 'img', this.createEditor.bind(this))
|
||||||
|
this.$element.on('click', this.destroyEditors.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.createEditor = function (event) {
|
||||||
|
event.stopPropagation()
|
||||||
|
this.destroyEditors()
|
||||||
|
var $img = $(event.currentTarget)
|
||||||
|
|
||||||
|
if (!$img.hasClass('objectResizingEditorActive')) {
|
||||||
|
new Editor($img)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.destroyEditors = function () {
|
||||||
|
this.$element.find('img.objectResizingEditorActive').each(function(i, img){
|
||||||
|
editor = $(img).data('objectResizingEditor')
|
||||||
|
if(editor){
|
||||||
|
editor.destroy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Resize Editor
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
function Editor($element) {
|
||||||
|
this.$element = $element
|
||||||
|
this.isResizing = false
|
||||||
|
|
||||||
|
this.$element.data('objectResizingEditor', this)
|
||||||
|
this.$element.addClass('objectResizingEditorActive')
|
||||||
|
this.$element.wrap('<div class="enableObjectResizingShim" contenteditable="false"></div>')
|
||||||
|
|
||||||
|
for (var i=0; i<4; i++) {
|
||||||
|
this.$element.before('<div class="enableObjectResizingShim-handle"></div>')
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).one('click.objectResizingEditor', this.destroy.bind(this))
|
||||||
|
$(document).one('keydown.objectResizingEditor', this.onKeydown.bind(this))
|
||||||
|
this.$element.on('click.objectResizingEditor', this.stopPropagation.bind(this))
|
||||||
|
this.$element.parent().find('.enableObjectResizingShim-handle').on('mousedown', this.startResize.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.prototype.onKeydown = function (event) {
|
||||||
|
this.destroy()
|
||||||
|
|
||||||
|
switch (event.keyCode) {
|
||||||
|
case 8: // backspace
|
||||||
|
this.$element.remove()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
event.stopPropagation()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.prototype.stopPropagation = function (event) {
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.prototype.destroy = function (event) {
|
||||||
|
if(this.isResizing) return
|
||||||
|
this.$element.off('click.objectResizingEditor')
|
||||||
|
$(document).off('click.objectResizingEditor')
|
||||||
|
$(document).off('keydown.objectResizingEditor')
|
||||||
|
this.$element.removeClass('objectResizingEditorActive')
|
||||||
|
this.$element.siblings().remove()
|
||||||
|
this.$element.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.prototype.startResize = function (event) {
|
||||||
|
var $handle = $(event.currentTarget)
|
||||||
|
this.resizeCorner = $handle.index()
|
||||||
|
this.resizeDir = this.resizeCorner == 0 || this.resizeCorner == 3 ? -1 : 1
|
||||||
|
this.startX = event.pageX
|
||||||
|
this.startWidth = this.$element.width()
|
||||||
|
this.$clone = this.$element.clone().css({width: '', height: ''}).addClass('enableObjectResizingShim-clone enableObjectResizingShim-clone--'+ this.resizeCorner)
|
||||||
|
this.$element.after(this.$clone)
|
||||||
|
this.isResizing = true
|
||||||
|
$(document).on('mousemove.enableObjectResizing', this.resize.bind(this))
|
||||||
|
$(document).on('mouseup.enableObjectResizing', this.resizeEnd.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.prototype.resize = function (event) {
|
||||||
|
event.preventDefault()
|
||||||
|
var dx = event.pageX - this.startX
|
||||||
|
this.$clone.css('width', this.startWidth + (this.resizeDir * dx))
|
||||||
|
}
|
||||||
|
|
||||||
|
Editor.prototype.resizeEnd = function (event) {
|
||||||
|
$(document).off('mousemove.enableObjectResizing')
|
||||||
|
$(document).off('mouseup.enableObjectResizing')
|
||||||
|
|
||||||
|
this.$element.css({
|
||||||
|
width: this.$clone.width(),
|
||||||
|
height: this.$clone.height()
|
||||||
|
})
|
||||||
|
this.$clone.remove()
|
||||||
|
|
||||||
|
// reset isResizing with a delay to prevent a mouseup in the editor to trigger a editor-destroy
|
||||||
|
setTimeout(function(){
|
||||||
|
this.isResizing = false
|
||||||
|
}.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$.fn[pluginName] = function (options) {
|
||||||
|
return this.each(function () {
|
||||||
|
if (!$.data(this, 'plugin_' + pluginName)) {
|
||||||
|
$.data(this, 'plugin_' + pluginName, new Plugin(this, options))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}(jQuery, window));
|
|
@ -34,160 +34,163 @@
|
||||||
this.ce = $.data(element, 'plugin_ce')
|
this.ce = $.data(element, 'plugin_ce')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.init();
|
this.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
Plugin.prototype.init = function () {
|
Plugin.prototype.init = function () {
|
||||||
this.renderBase()
|
this.renderBase()
|
||||||
var _this = this
|
this.bindEvents()
|
||||||
|
}
|
||||||
|
|
||||||
this.$element.on('keydown', function (e) {
|
Plugin.prototype.bindEvents = function () {
|
||||||
|
this.$element.on('keydown', this.onKeydown.bind(this))
|
||||||
|
this.$element.on('keypress', this.onKeypress.bind(this))
|
||||||
|
this.$element.on('focus', this.onFocus.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
// navigate through item
|
Plugin.prototype.onFocus = function (e) {
|
||||||
if (_this.isActive()) {
|
this.close()
|
||||||
|
}
|
||||||
|
|
||||||
// esc
|
Plugin.prototype.onKeydown = function (e) {
|
||||||
if (e.keyCode === 27) {
|
console.log("onKeydown", this.isActive())
|
||||||
e.preventDefault()
|
// navigate through item
|
||||||
e.stopPropagation()
|
if (this.isActive()) {
|
||||||
_this.close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// enter
|
|
||||||
if (e.keyCode === 13) {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
var id = _this.$widget.find('.dropdown-menu li.is-active').data('id')
|
|
||||||
|
|
||||||
// as fallback use hovered element
|
|
||||||
if (!id) {
|
|
||||||
id = _this.$widget.find('.dropdown-menu li:hover').data('id')
|
|
||||||
}
|
|
||||||
|
|
||||||
// as fallback first element
|
|
||||||
if (!id) {
|
|
||||||
id = _this.$widget.find('.dropdown-menu li:first-child').data('id')
|
|
||||||
}
|
|
||||||
_this.take(id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// arrow keys left/right
|
|
||||||
if (e.keyCode === 37 || e.keyCode === 39) {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// up or down
|
|
||||||
if (e.keyCode === 38 || e.keyCode === 40) {
|
|
||||||
e.preventDefault()
|
|
||||||
e.stopPropagation()
|
|
||||||
var active = _this.$widget.find('.dropdown-menu li.is-active')
|
|
||||||
active.removeClass('is-active')
|
|
||||||
|
|
||||||
if (e.keyCode == 38 && active.prev().size()) {
|
|
||||||
active = active.prev()
|
|
||||||
}
|
|
||||||
else if (e.keyCode == 40 && active.next().size()) {
|
|
||||||
active = active.next()
|
|
||||||
}
|
|
||||||
|
|
||||||
active.addClass('is-active')
|
|
||||||
|
|
||||||
var menu = _this.$widget.find('.dropdown-menu')
|
|
||||||
|
|
||||||
if (!active.get(0)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (active.position().top < 0) {
|
|
||||||
// scroll up
|
|
||||||
menu.scrollTop( menu.scrollTop() + active.position().top )
|
|
||||||
}
|
|
||||||
else if ( active.position().top + active.height() > menu.height() ) {
|
|
||||||
// scroll down
|
|
||||||
var invisibleHeight = active.position().top + active.height() - menu.height()
|
|
||||||
menu.scrollTop( menu.scrollTop() + invisibleHeight )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// esc
|
// esc
|
||||||
if (e.keyCode === 27) {
|
if (e.keyCode === 27) {
|
||||||
_this.close()
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
this.close()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
// reduce buffer, in case close it
|
|
||||||
this.$element.on('keydown', function (e) {
|
|
||||||
|
|
||||||
// backspace
|
|
||||||
if (e.keyCode === 8 && _this.buffer) {
|
|
||||||
|
|
||||||
// backspace + buffer === :: -> close textmodule
|
|
||||||
if (_this.buffer === '::') {
|
|
||||||
_this.close(true)
|
|
||||||
e.preventDefault()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// reduce buffer and show new result
|
|
||||||
var length = _this.buffer.length
|
|
||||||
_this.buffer = _this.buffer.substr(0, length-1)
|
|
||||||
_this.log('BS backspace', _this.buffer)
|
|
||||||
_this.result(_this.buffer.substr(2, length-1))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// build buffer
|
|
||||||
this.$element.on('keypress', function (e) {
|
|
||||||
_this.log('BUFF', _this.buffer, e.keyCode, String.fromCharCode(e.which))
|
|
||||||
|
|
||||||
// shift
|
|
||||||
if (e.keyCode === 16) return
|
|
||||||
|
|
||||||
// enter
|
// enter
|
||||||
if (e.keyCode === 13) return
|
if (e.keyCode === 13) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
var id = this.$widget.find('.dropdown-menu li.is-active').data('id')
|
||||||
|
|
||||||
// arrow keys
|
// as fallback use hovered element
|
||||||
if (e.keyCode === 37 || e.keyCode === 38 || e.keyCode === 39 || e.keyCode === 40) return
|
if (!id) {
|
||||||
|
id = this.$widget.find('.dropdown-menu li:hover').data('id')
|
||||||
// observer other second key
|
|
||||||
if (_this.buffer === ':' && String.fromCharCode(e.which) !== ':') {
|
|
||||||
_this.buffer = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// oberserve second :
|
|
||||||
if (_this.buffer === ':' && String.fromCharCode(e.which) === ':') {
|
|
||||||
_this.buffer = _this.buffer + ':'
|
|
||||||
}
|
|
||||||
|
|
||||||
// oberserve first :
|
|
||||||
if (!_this.buffer && String.fromCharCode(e.which) === ':') {
|
|
||||||
_this.buffer = _this.buffer + ':'
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_this.buffer && _this.buffer.substr(0,2) === '::') {
|
|
||||||
|
|
||||||
var sign = String.fromCharCode(e.which)
|
|
||||||
if ( sign && sign !== ':' && e.which != 8 ) { // 8 == backspace
|
|
||||||
_this.buffer = _this.buffer + sign
|
|
||||||
//_this.log('BUFF ADD', sign, this.buffer, sign.length, e.which)
|
|
||||||
}
|
|
||||||
_this.log('BUFF HINT', _this.buffer, _this.buffer.length, e.which, String.fromCharCode(e.which))
|
|
||||||
|
|
||||||
if (!_this.isActive()) {
|
|
||||||
_this.open()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_this.result(_this.buffer.substr(2, _this.buffer.length))
|
// as fallback first element
|
||||||
|
if (!id) {
|
||||||
|
id = this.$widget.find('.dropdown-menu li:first-child').data('id')
|
||||||
|
}
|
||||||
|
this.take(id)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}).on('focus', function (e) {
|
// arrow keys left/right
|
||||||
_this.close()
|
if (e.keyCode === 37 || e.keyCode === 39) {
|
||||||
})
|
e.preventDefault()
|
||||||
};
|
e.stopPropagation()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// up or down
|
||||||
|
if (e.keyCode === 38 || e.keyCode === 40) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
var active = this.$widget.find('.dropdown-menu li.is-active')
|
||||||
|
active.removeClass('is-active')
|
||||||
|
|
||||||
|
if (e.keyCode == 38 && active.prev().size()) {
|
||||||
|
active = active.prev()
|
||||||
|
}
|
||||||
|
else if (e.keyCode == 40 && active.next().size()) {
|
||||||
|
active = active.next()
|
||||||
|
}
|
||||||
|
|
||||||
|
active.addClass('is-active')
|
||||||
|
|
||||||
|
var menu = this.$widget.find('.dropdown-menu')
|
||||||
|
|
||||||
|
if (!active.get(0)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (active.position().top < 0) {
|
||||||
|
// scroll up
|
||||||
|
menu.scrollTop( menu.scrollTop() + active.position().top )
|
||||||
|
}
|
||||||
|
else if ( active.position().top + active.height() > menu.height() ) {
|
||||||
|
// scroll down
|
||||||
|
var invisibleHeight = active.position().top + active.height() - menu.height()
|
||||||
|
menu.scrollTop( menu.scrollTop() + invisibleHeight )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// esc
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// reduce buffer, in case close it
|
||||||
|
// backspace
|
||||||
|
if (e.keyCode === 8 && this.buffer) {
|
||||||
|
|
||||||
|
// backspace + buffer === :: -> close textmodule
|
||||||
|
if (this.buffer === '::') {
|
||||||
|
this.close(true)
|
||||||
|
e.preventDefault()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// reduce buffer and show new result
|
||||||
|
var length = this.buffer.length
|
||||||
|
this.buffer = this.buffer.substr(0, length-1)
|
||||||
|
this.log('BS backspace', this.buffer)
|
||||||
|
this.result(this.buffer.substr(2, length-1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.prototype.onKeypress = function (e) {
|
||||||
|
this.log('BUFF', this.buffer, e.keyCode, String.fromCharCode(e.which))
|
||||||
|
|
||||||
|
// shift
|
||||||
|
if (e.keyCode === 16) return
|
||||||
|
|
||||||
|
// enter
|
||||||
|
if (e.keyCode === 13) return
|
||||||
|
|
||||||
|
// arrow keys
|
||||||
|
if (e.keyCode === 37 || e.keyCode === 38 || e.keyCode === 39 || e.keyCode === 40) return
|
||||||
|
|
||||||
|
// observer other second key
|
||||||
|
if (this.buffer === ':' && String.fromCharCode(e.which) !== ':') {
|
||||||
|
this.buffer = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// oberserve second :
|
||||||
|
if (this.buffer === ':' && String.fromCharCode(e.which) === ':') {
|
||||||
|
this.buffer = this.buffer + ':'
|
||||||
|
}
|
||||||
|
|
||||||
|
// oberserve first :
|
||||||
|
if (!this.buffer && String.fromCharCode(e.which) === ':') {
|
||||||
|
this.buffer = this.buffer + ':'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.buffer && this.buffer.substr(0,2) === '::') {
|
||||||
|
|
||||||
|
var sign = String.fromCharCode(e.which)
|
||||||
|
if ( sign && sign !== ':' && e.which != 8 ) { // 8 == backspace
|
||||||
|
this.buffer = this.buffer + sign
|
||||||
|
//this.log('BUFF ADD', sign, this.buffer, sign.length, e.which)
|
||||||
|
}
|
||||||
|
this.log('BUFF HINT', this.buffer, this.buffer.length, e.which, String.fromCharCode(e.which))
|
||||||
|
|
||||||
|
if (!this.isActive()) {
|
||||||
|
this.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.result(this.buffer.substr(2, this.buffer.length))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create base template
|
// create base template
|
||||||
Plugin.prototype.renderBase = function() {
|
Plugin.prototype.renderBase = function() {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
*= require ./font.css
|
*= require ./font.css
|
||||||
*= require ./svg-dimensions.css
|
*= require ./svg-dimensions.css
|
||||||
*= require ./highlighter-github.css
|
*= require ./highlighter-github.css
|
||||||
|
*= require ./jquery.enableObjectResizingShim.css
|
||||||
*= require ./zammad.scss
|
*= require ./zammad.scss
|
||||||
*
|
*
|
||||||
*= require_tree ./custom/
|
*= require_tree ./custom/
|
||||||
|
|
77
app/assets/stylesheets/jquery.enableObjectResizingShim.css
Normal file
77
app/assets/stylesheets/jquery.enableObjectResizingShim.css
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
.enableObjectResizingShim {
|
||||||
|
box-shadow: 0 0 0 1px black;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block !important;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-handle {
|
||||||
|
position: absolute;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin: -10px;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
cursor: nwse-resize;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-handle:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 6px;
|
||||||
|
top: 6px;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: white;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-handle:hover:after {
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-handle:nth-child(2) {
|
||||||
|
left: 100%;
|
||||||
|
cursor: nesw-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-handle:nth-child(3) {
|
||||||
|
left: 100%;
|
||||||
|
top: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-handle:nth-child(4) {
|
||||||
|
top: 100%;
|
||||||
|
cursor: nesw-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-clone {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
opacity: 0.5;
|
||||||
|
border: 1px dashed black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-clone--0 {
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-clone--1 {
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-clone--2 {
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.enableObjectResizingShim-clone--3 {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
Loading…
Reference in a new issue