/*
*
* @(#) $Id: html_editor.js,v 1.47 2010/09/07 22:49:18 mlemos Exp $
*
*/
if(typeof(ML) === 'undefined')
ML = { }
if(typeof(ML.HTMLEditor) === 'undefined')
ML.HTMLEditor = { }
if(typeof(ML.HTMLEditor.Editor) === 'undefined')
{
ML.HTMLEditor.HTMLEditors = {}
ML.HTMLEditor.defaultVisualToolbar = {
'character': [
{
type: 'bold'
},
{
type: 'italic'
},
{
type: 'underline'
},
{
type: 'strikethrough'
},
{
type: 'createlink'
},
{
type: 'unlink'
}
],
'paragraph': [
{
type: 'justifyleft'
},
{
type: 'justifycenter'
},
{
type: 'justifyright'
},
{
type: 'justifyfull'
},
{
type: 'space'
},
{
type: 'formatblock'
},
{
type: 'inserttemplate'
}
],
'document': [
{
type: 'copy'
},
{
type: 'cut'
},
{
type: 'paste'
},
{
type: 'delete'
},
{
type: 'space'
},
{
type: 'undo'
},
{
type: 'redo'
},
{
type: 'space'
},
{
type: 'html'
}
]
}
ML.HTMLEditor.defaultHTMLToolbar = {
'document': [
{
type: 'visual'
}
]
}
ML.HTMLEditor.linkEmulationStyle = 'color: #0000FF; text-decoration: underline'
ML.HTMLEditor.Editor = function()
{
this.id = ''
this.error = ''
this.debug = true
this.editorStyle = 'background-color: #ffffff; border-style: solid; border-width: 1px; margin: 0px; border-color: #707070 #e0e0e0 #e0e0e0 #707070'
this.templateVariableStyle = 'border-style: dashed; border-width: 1px; margin: 1px; padding: 1px'
this.templateMarkStyle = 'background-color: #cedee6; border-style: solid; border-width: 1px; margin: 0px; padding: 2px; border-color: #e0e0e0 #707070 #707070 #e0e0e0; font-size: 8pt; opacity: 0.75; filter:alpha(opacity=75)'
this.menuStyle = 'background-color: #d0d0d0; border-style: solid; border-width: 1px; margin: 0px; border-color: #e0e0e0 #707070 #707070 #e0e0e0'
this.itemStyle = 'padding: 4px; color: #000000'
this.itemSelectStyle = 'padding: 4px; color: #ffffff; background-color: #000080'
this.mode = 'visual'
this.showToolbars = true
this.templateVariables = {}
this.externalCSS = []
this.openVariable = '{'
this.closeVariable = '}'
this.alternativesMark = '+'
/*
* private variables
*/
this.editor = null
this.textarea = null
this.iframe = null
this.editorDocument = null
this.htmlEditor = null
this.visualEditor = null
this.lastMenu = ''
this.lastMenuTime = 0
this.menuDelayTime = 100
this.lastOpenedMenu = null
var hasAttribute = function (element, attribute)
{
if(element.hasAttribute)
return(element.hasAttribute(attribute))
return typeof(element.attributes[attribute]) != 'undefined'
}
var getElementsByName = function(element, name, tags)
{
var l = []
for(var t = 0; t < tags.length; ++t)
{
var e = element.getElementsByTagName(tags[t])
for(var i = 0; i < e.length; ++i)
if(e[i].getAttribute('name') == name)
l[l.length] = e[i]
}
return l
}
var getElementBox = function (element)
{
var box = {}
var d = element.ownerDocument
var win = d.defaultView ? d.defaultView : d.parentWindow
if(element.getBoundingClientRect)
{
var b = element.getBoundingClientRect()
box.x = b.left + d.body.scrollLeft
box.y = b.top + d.body.scrollTop
box.width = b.right - b.left + 1
box.height = b.bottom - b.top + 1
}
else
{
if(d.getBoxObjectFor)
{
var b = d.getBoxObjectFor(element)
box.x = b.x
box.y = b.y
box.width = b.width
box.height = b.height
if(win.getComputedStyle)
{
var s = win.getComputedStyle(element, null)
var o = parseInt(s.borderLeftWidth) + parseInt(s.borderRightWidth)
box.x -= o
box.width += o
o = parseInt(s.borderTopWidth) + parseInt(s.borderBottomWidth)
box.y -= o
box.height += o
}
}
else
{
var p = element.style.position
element.style.position = 'relative'
box.x = element.offsetLeft
box.y = element.offsetTop
box.width = element.offsetWidth
box.height = element.offsetHeight
element.style.position = p
}
}
return box
}
var getElementSize = function (element)
{
var box = getElementBox(element)
return { width: box.width, height: box.height }
}
var repositionElement = function (element, parent, frame)
{
var d = parent.ownerDocument
var win = d.defaultView ? d.defaultView : d.parentWindow
var b = getElementBox(parent)
var x = b.x
var y = b.y + b.height
var w = parseInt(b.width)
if(!isNaN(w))
{
var s = getElementSize(element)
if(!isNaN(parseInt(s.width)))
{
x += (w - parseInt(s.width)) / 2
if(x < 0)
x = 0
}
}
if(frame)
{
b = getElementBox(frame)
x += b.x
y += b.y
if(typeof(frame.contentWindow.pageXOffset) == 'number')
{
x -= frame.contentWindow.pageXOffset
y -= frame.contentWindow.pageYOffset
}
else
if(frame.contentWindow.document.documentElement
&& frame.contentWindow.document.compatMode
&& frame.contentWindow.document.compatMode != "BackCompat")
{
x -= frame.contentWindow.document.documentElement.scrollLeft
y -= frame.contentWindow.document.documentElement.scrollTop
}
else
{
x -= frame.contentWindow.document.body.scrollLeft
y -= frame.contentWindow.document.body.scrollTop
}
}
element.style.left = x + 'px'
element.style.top = y + 'px'
}
var addEventListener = function(element, event, listener, capture)
{
if(element.addEventListener)
element.addEventListener(event, listener, capture)
else
{
if(element.attachEvent)
element.attachEvent('on' + event, listener)
}
}
var replaceStrings = function(value, replace)
{
for(var v in replace)
{
var c = ''
for(var p = 0; p < value.length;)
{
var f = value.indexOf(v, p)
if(f == -1)
{
c += value.substring(p)
break
}
c += value.substring(p, f) + replace[v]
p = f + v.length
}
value = c
}
return value
}
var encodeHTML = function(value)
{
return replaceStrings(value, {
'&': '&',
'"': '"',
'<': '<',
'>': '>'
})
}
var escapeHTML = function(value)
{
return value.replace(/<a([^>]*)>([^<]*)<\/a>/gi, '<span style="' + ML.HTMLEditor.linkEmulationStyle + '">$2</span>')
}
var encodeString = function(value)
{
return "'" + replaceStrings(value, {
"'": "\\'"
}) + "'"
}
var expandTemplates = function(e, value, insert)
{
var variables = {}, created = {}
if(insert)
{
for(var v in e.templateVariables)
{
v = e.openVariable + v + e.closeVariable
var r = getElementsByName(e.editorDocument, v, ['div', 'span'])
for(var i = 0; i < r.length; ++i)
{
var n = (variables[v] ? variables[v].length : 0)
if(n == 0)
variables[v] = []
variables[v][n] = r[i]['id']
}
}
}
var style = e.templateVariableStyle.length ? ' style="' + encodeHTML(e.templateVariableStyle) + '"' : ''
var v = value
value = ''
for(var p = 0; p < v.length;)
{
var b = v.indexOf(e.openVariable, p)
if(b == -1)
{
value += v.substring(p)
break
}
b += e.openVariable.length;
var f = v.indexOf(e.closeVariable, b)
if(f == -1)
{
value += v.substring(p)
break
}
var s = v.indexOf(' ', b)
if(s == -1
|| s > f)
s = f
var tv = v.substring(b, s)
if(e.templateVariables[tv])
{
var a, h, expand
if(e.templateVariables[tv].alternatives)
{
a = (s == f ? null : v.substring(s + 1, f))
if(a
&& !e.templateVariables[tv].alternatives[a])
a = null
}
else
a = null
h = typeof(e.templateVariables[tv].inline) != 'undefined'
if(h)
{
var t = (e.templateVariables[tv].inline ? 'span' : 'div')
var i = encodeHTML(e.openVariable + tv + e.closeVariable)
var n = (variables[i] ? variables[i].length : 0)
expand = '<' + t + ' id="' + i + '_' + n +'" name="' + i + '"' + style + ' contentEditable="false"' + (e.templateVariables[tv].title ? ' title="' + encodeHTML(e.templateVariables[tv].title) + '"' : '') + (a ? ' data="' + encodeHTML(a) + '"' : '') + '></' + t + '>'
}
else
expand = (a ? e.templateVariables[tv].alternatives[a].value : e.templateVariables[tv].value)
value += v.substring(p, b - e.openVariable.length) + expand
p = f + e.closeVariable.length
if(h)
{
if(n == 0)
variables[i] = []
var c = (created[tv] ? created[tv].length : 0)
if(c == 0)
created[tv] = []
variables[i][n] = created[tv][c] = i + '_' + n
}
}
else
{
value += v.substring(p, b)
p = b
}
}
return { value: value, created: created }
}
var handleMenus = function(e)
{
return function(event)
{
var id, parent
if(event.target)
id = (parent = event.target).id
else
{
if(event.srcElement)
id = (parent = event.srcElement).id
else
return
}
if(id.length == 0
|| !parent)
return
var now = (new Date()).getTime()
if(e.lastMenu != id
|| now - e.lastMenuTime > e.menuDelayTime)
{
var menu = e.visualEditor.ownerDocument.getElementById(id + '_menu');
if(e.toggleMenu(menu, parent, e.iframe))
menu.setAttribute('data', parent.parentNode.id)
e.lastMenu = id
e.lastMenuTime = now
}
if(event)
{
if(event.preventDefault)
event.preventDefault()
event.cancelBubble = true
event.returnValue = false
}
}
}
this.formatMark = function(variable, alternative)
{
var e = this
return '<span style="float: left; ' + encodeHTML(e.templateMarkStyle) + '">' + encodeHTML(e.openVariable + variable + (alternative ? ' ' + alternative : '') + e.closeVariable + (e.templateVariables[variable].alternatives ? ' ' + e.alternativesMark : '')) + '</span><br style="clear: both">' + escapeHTML(alternative ? e.templateVariables[variable].alternatives[alternative].preview : e.templateVariables[variable].preview)
}
this.changeMark = function(mark, variable, alternative)
{
var e = this
var i = e.editorDocument.createElement('button')
i.setAttribute('id', e.id + '_' + variable)
var s = (e.templateVariables[variable].inline ? '' : 'display: block; width: 100%; text-align: left; ') + 'background-color: inherit; border-style: none; border-width: 0px; padding: 0px; font-family: inherit; font-size: inherit; color: inherit'
if(i.currentStyle)
i.style.cssText = s
else
i.setAttribute('style', s)
i.setAttribute('contentEditable', 'false')
i.innerHTML = e.formatMark(variable, alternative)
mark.innerHTML = ''
mark.appendChild(i)
}
this.setAlternative = function(mark, variable, alternative)
{
var e = this, p, i
p = e.editorDocument.getElementById(mark)
if(alternative)
p.setAttribute('data', alternative)
else
{
p.setAttribute('data', '')
p.removeAttribute('data')
}
e.changeMark(p, variable, alternative)
}
this.loadTemplates = function()
{
var e = this, setup = 'var e = ML.HTMLEditor.HTMLEditors[\'' + e.id + '\']; '
for(var v in e.templateVariables)
{
var r = getElementsByName(e.editorDocument, e.openVariable + v + e.closeVariable, [ 'div', 'span' ])
for(var n = 0; n < r.length; ++n)
{
var i, s, id = e.id + '_' + v
r[n].innerHTML = ''
if(e.templateVariables[v].alternatives)
{
i = e.visualEditor.ownerDocument.createElement('div')
i.setAttribute('id', id + '_menu')
e.visualEditor.appendChild(i)
s = e.menuStyle + '; position: absolute; visibility: hidden'
if(i.currentStyle)
i.style.cssText = s
else
i.setAttribute('style', s)
var o = {}
o[v] = e.templateVariables[v].title
for(var a in e.templateVariables[v].alternatives)
o[a] = e.templateVariables[v].alternatives[a].title
var oo = ''
for(var a in o)
oo += '<div style="' + encodeHTML(e.itemStyle) + '" onmouseover="' + encodeHTML('var s = ' + encodeString(e.itemSelectStyle) + '; if(this.currentStyle) { this.style.cssText = s } else { this.setAttribute(\'style\', s) }') + '" onmouseout="' + encodeHTML('var s = ' + encodeString(e.itemStyle) + '; if(this.currentStyle) { this.style.cssText = s } else { this.setAttribute(\'style\', s) }') + '" onmousedown="' + setup + 'e.setAlternative(this.ownerDocument.getElementById(' + encodeString(id + '_menu') + ').getAttribute(\'data\'), ' + encodeHTML(encodeString(v) + ', ' + (oo.length ? encodeString(a) : 'null')) +'); e.hideMenu(this.ownerDocument.getElementById(' + encodeString(id + '_menu') + ')); return false">' + o[a] + '</div>'
i.innerHTML = oo
}
e.changeMark(r[n], v, (e.templateVariables[v].alternatives && hasAttribute(r[n],'data')) ? r[n].getAttribute('data') : null)
if(e.templateVariables[v].alternatives)
addEventListener(r[n], 'click', handleMenus(e), true)
}
}
}
this.hideMenu = function(menu)
{
if(menu)
{
menu.style.visibility = 'hidden'
this.lastOpenedMenu = null
}
}
this.showMenu = function(menu, parent, frame)
{
if(menu)
{
if(this.lastOpenedMenu
&& this.lastOpenedMenu.id != menu.id)
this.hideMenu(this.lastOpenedMenu)
repositionElement(menu, parent, frame)
menu.style.visibility = 'visible'
this.lastOpenedMenu = menu
return true
}
return false
}
this.toggleMenu = function(menu, parent, frame)
{
if(menu)
{
if(menu.style.visibility == 'visible')
this.hideMenu(menu)
else
return this.showMenu(menu, parent, frame)
}
return false
}
var convertValue = function(e, toEditor)
{
var value
if(toEditor)
{
value = expandTemplates(e, e.textarea.value, false).value
e.editorDocument.body.innerHTML = value
return value
}
else
{
var v, n, r, t = document.getElementById(e.id + '_temporary')
t.innerHTML = e.editorDocument.body.innerHTML
for(v in e.templateVariables)
{
if(typeof(e.templateVariables[v].inline) != 'undefined')
{
r = getElementsByName(t, e.openVariable + v + e.closeVariable, ['div', 'span'])
for(n = 0; n < r.length; ++n)
r[n].parentNode.replaceChild(document.createTextNode(e.openVariable + v + (hasAttribute(r[n], 'data') ? ' ' + r[n].getAttribute('data') : '') + e.closeVariable), r[n])
}
}
value = t.innerHTML
t.innerHTML = ''
for(v in e.templateVariables)
{
if(typeof(e.templateVariables[v].inline) == 'undefined')
{
var replace = { }
replace[e.templateVariables[v].value] = e.openVariable + v + e.closeVariable
if(e.templateVariables[v].alternatives)
{
for(a in e.templateVariables[v].alternatives)
replace[e.templateVariables[v].alternatives[a].value] = e.openVariable + v + ' ' + a + e.closeVariable
}
value = replaceStrings(value, replace)
}
}
return value
}
}
this.synchronize = function()
{
var e = this
var converted = convertValue(e, false)
if(converted != e.textarea.value)
{
if(e.mode == 'visual')
{
e.textarea.value = converted
if(typeof(e.textarea.onchange) == 'function')
e.textarea.onchange()
}
else
{
convertValue(e, true)
}
}
}
var renderToolbar = function(e, toolbars)
{
var render = '<table style="display: ' + (e.showToolbars ? 'block' : 'none') + '">'
var setup = 'var e = ML.HTMLEditor.HTMLEditors[\'' + e.id + '\']; '
for(var t in toolbars)
{
render += '<tr><td>'
for(var b = 0; b < toolbars[t].length; ++b)
{
var type = toolbars[t][b].type
switch(type)
{
case 'visual':
case 'html':
case 'bold':
case 'italic':
case 'underline':
case 'strikethrough':
case 'createlink':
case 'unlink':
case 'copy':
case 'cut':
case 'paste':
case 'delete':
case 'undo':
case 'redo':
case 'html':
case 'visual':
case 'justifyleft':
case 'justifycenter':
case 'justifyright':
case 'justifyfull':
action = setup + 'if(!e.execCommand("' + type + '", true) && !e.debug) { alert("Could not execute the ' + type + ' command in this browser.") }'
switch(type)
{
case 'bold':
content = '<span style="font-weight: bold">B</span>'
title = 'Bold'
break
case 'italic':
content = '<span style="font-style: italic">I</span>'
title = 'Italic'
break
case 'underline':
content = '<span style="text-decoration: underline">U</span>'
title = 'Underline'
break
case 'strikethrough':
content = '<span style="text-decoration: line-through">S</span>'
title = 'Strike-through'
break
case 'createlink':
content = '<span style="text-decoration: underline; color: #0000ff">www</span>'
title = 'Create link'
action = 'var url = prompt("Link URL:", "http://www."); if(url == null || url == "") return false; ' + setup + 'if(!e.execCommand("' + type + '", url) && !e.debug) { alert("Could not execute the ' + type + ' command in this browser.") }';
break
case 'unlink':
content = '<span style="text-decoration: underline line-through; color: #0000ff">www</span>'
title = 'Remove link'
break
case 'copy':
content = 'Copy'
title = 'Copy selected'
break
case 'cut':
content = 'Cut'
title = 'Cut selected'
break
case 'paste':
content = 'Paste'
title = 'Paste copied'
break
case 'delete':
content = 'Delete'
title = 'Delete selected'
break
case 'undo':
content = 'Undo'
title = 'Undo'
break
case 'redo':
content = 'Redo'
title = 'Redo'
break
case 'justifyleft':
content = 'Left'
title = 'Justify left'
break
case 'justifycenter':
content = 'Center'
title = 'Justify center'
break
case 'justifyright':
content = 'Right'
title = 'Justify right'
break
case 'justifyfull':
content = 'Full'
title = 'Justify full'
break
case 'visual':
content = 'Visual'
title = 'Edit visually'
action = setup + 'e.setEditMode("visual");'
break
case 'html':
content = 'HTML'
title = 'Edit HTML'
action = setup + 'e.setEditMode("html");'
break
default:
if(e.debug)
alert('toolbar element of type ' + type + ' is not implemented')
action = ''
content = title = type
}
if(action.length)
render += '<button onclick="' + encodeHTML(action) + ' return false" title="' + encodeHTML(title) + '">' + content + '</button>'
break
case 'justify':
case 'inserttemplate':
case 'formatblock':
var action, o, oo, menu
switch(type)
{
case 'justify':
menu = 'Justify'
o = {
'justifyleft': 'Left',
'justifycenter': 'Center',
'justifyright': 'Right',
'justifyfull': 'Full'
}
action = 'if(!e.execCommand({item}, true) && !e.debug) { alert("Could not execute the justify command in this browser.") }'
break
case 'inserttemplate':
menu = 'Insert template'
o = {}
if(e.templateVariables.length == 0)
break
var comma = ''
for(v in e.templateVariables)
{
if(typeof(e.templateVariables[v].inline) != 'undefined')
o[e.openVariable + v + e.closeVariable] = (e.templateVariables[v].title ? e.templateVariables[v].title : v)
comma = ', '
}
action = 'if(!e.execCommand("inserthtml", {item}) && !e.debug) { alert("Could not execute the inserthtml command in this browser.") }; e.loadTemplates();'
break
case 'formatblock':
menu = 'Format block'
o = {
'p': '<p style="margin: 0px">Paragraph</p>',
'pre': '<pre style="margin: 0px">Preformatted</pre>',
'address': '<address style="margin: 0px">Address</address>',
'h1': '<h1 style="margin: 0px">Heading 1</h1>',
'h2': '<h2 style="margin: 0px">Heading 2</h2>',
'h3': '<h3 style="margin: 0px">Heading 3</h3>',
'h4': '<h4 style="margin: 0px">Heading 4</h4>',
'h5': '<h5 style="margin: 0px">Heading 5</h5>',
'h6': '<h6 style="margin: 0px">Heading 6</h6>'
}
action = 'if(!e.execCommand("formatblock", {item} ) && !e.debug) { alert("Could not execute the formatblock command in this browser.") }'
break
}
var id = e.id + '_' + type
oo = ''
for(var v in o)
oo += '<div style="' + encodeHTML(e.itemStyle) + '" onmouseover="' + encodeHTML('var s = ' + encodeString(e.itemSelectStyle) + '; if(this.currentStyle) { this.style.cssText = s } else { this.setAttribute(\'style\', s) }') + '" onmouseout="' + encodeHTML('var s = ' + encodeString(e.itemStyle) + '; if(this.currentStyle) { this.style.cssText = s } else { this.setAttribute(\'style\', s) }') + '" onmousedown="' + setup + encodeHTML(replaceStrings(action, { '{item}': encodeString(v) })) + '; e.hideMenu(this.ownerDocument.getElementById(' + encodeString(id) + ')); return false">' + o[v] + '</div>'
render += '<div id="' + id + '" style="' + encodeHTML(e.menuStyle) + '; position: absolute; visibility: hidden; white-space: nowrap">' + oo + '</div><button onkeydown="if(event.keyCode == 27) { ' + setup + 'e.hideMenu(this.ownerDocument.getElementById(' + encodeString(id) + ')); return false }" onclick="' + setup + 'e.toggleMenu(this.ownerDocument.getElementById(' + encodeString(id) + '), this, null); return false" title="' + encodeHTML(menu) + '">' + menu + '</button>'
break
case 'separator':
render += (toolbars[t][b].content ? toolbars[t][b].content : ' | ')
break
case 'space':
render += (toolbars[t][b].content ? toolbars[t][b].content : ' ')
break
default:
if(e.debug)
alert('toolbar element of type ' + type + ' is not implemented')
break
}
}
render += '</td></tr>'
}
render += '</table>'
return render
}
this.setError = function(error)
{
this.error = error
if(this.debug)
alert(error)
return false
}
this.insertEditor = function(editor, textarea)
{
var e = this
var l = document.getElementById(editor)
if(!l)
return e.setError('editor block "' + editor + '" was not found in this document.')
e.id = textarea.id
var editor_document = editor + '_iframe'
var html_editor = editor + '_html'
var visual_editor = editor + '_visual'
l.innerHTML = '<div id="' + encodeHTML(html_editor) + '">' + renderToolbar(e, ML.HTMLEditor.defaultHTMLToolbar) + '<div><textarea id="' + encodeHTML(textarea.id) + '" name="' + encodeHTML(textarea.name) + (textarea.rows ? '" rows="' + textarea.rows : '') + (textarea.cols ? '" cols="' + textarea.cols : '') + (textarea.className ? '" class="' + encodeHTML(textarea.className) : '') + (textarea.style ? '" style="' + encodeHTML(textarea.style) : '') + '">' + (textarea.value ? encodeHTML(textarea.value) : '') + '</textarea></div></div><div id="' + encodeHTML(visual_editor) + '">' + renderToolbar(e, ML.HTMLEditor.defaultVisualToolbar) + '<div><iframe id="' + encodeHTML(editor_document) + '" src="javascript:;" frameborder="0" marginwidth="0" marginheight="0" style="' + encodeHTML(textarea.style ? textarea.style : e.editorStyle) + '"></iframe></div></div><div id="' + e.id + '_temporary" style="display: none"></div>'
if(!(e.htmlEditor = document.getElementById(html_editor)))
return e.setError('could not create the HTML editor section')
if(!(e.visualEditor = document.getElementById(visual_editor)))
return e.setError('could not create the visual editor section')
if(!(e.textarea = document.getElementById(textarea.id)))
return e.setError('could not create the editor textarea')
if(!(l = e.iframe = document.getElementById(editor_document)))
return e.setError('could not create the editor iframe')
if(!l.contentWindow
|| !l.contentWindow.document)
return e.setError('could not access the editor iframe')
e.editorDocument = l.contentWindow.document
e.editorDocument.open()
e.editorDocument.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>Editor</title>')
if(e.externalCSS.length)
{
for(var c = 0; c < e.externalCSS.length; ++c)
e.editorDocument.write('<link rel="stylesheet" type="text/css" href="' + encodeHTML(e.externalCSS[c]) + '">')
}
e.editorDocument.write('</head><body></body></html>')
e.editorDocument.close()
var html_size = getElementSize(e.htmlEditor)
var visual_size = getElementSize(e.visualEditor)
var size = getElementSize(e.textarea)
var i = getElementSize(e.iframe)
l.style.width = size.width
l.style.height = i.height + html_size.height - visual_size.height
if(e.mode == 'visual')
e.htmlEditor.style.display = 'none'
else
e.visualEditor.style.display = 'none'
convertValue(e, true)
if(typeof(e.editorDocument.designMode) == 'string'
&& e.editorDocument.designMode == 'off')
e.editorDocument.designMode = 'on'
else
{
if(typeof(e.editorDocument.body.contentEditable) != 'undefined')
e.editorDocument.body.contentEditable = true
else
return e.setError('HTML editing in this browser is not yet supported')
}
addEventListener(e.textarea, 'change', function()
{
e.synchronize()
}, false
)
addEventListener(e.editorDocument.body, 'blur', function()
{
this.synchronize()
}, false
)
ML.HTMLEditor.HTMLEditors[textarea.id] = e
e.loadTemplates()
return true
}
this.execCommand = function(command, argument)
{
var exception, e = this
if(e.editorDocument == null)
return e.setError('the HTML editor elements are not yet setup')
try
{
var enabled, expanded
switch(command)
{
case 'inserthtml':
try
{
enabled = e.editorDocument.queryCommandEnabled(command)
}
catch(exception)
{
enabled = false
}
expanded = expandTemplates(e, argument, true)
argument = expanded.value
break
default:
enabled = true
}
if(enabled)
e.editorDocument.execCommand(command, false, argument)
switch(command)
{
case 'copy':
case 'cut':
case 'paste':
if(!e.editorDocument.queryCommandSupported(command))
throw('Not supported')
break
case 'inserthtml':
if(!enabled)
{
e.editorDocument.body.focus()
var r = e.editorDocument.selection.createRange()
r.pasteHTML(argument)
}
/*
for(var v in expanded.created)
{
if(e.templateVariables[v].alternatives)
{
for(var i = 0; i < expanded.created[v].length; ++i)
addEventListener(e.editorDocument.getElementById(expanded.created[v][i]), 'click', handleMenus(e), true)
}
}
*/
}
}
catch(exception)
{
return e.setError(command + ' command is not allowed in this browser: ' + exception.message)
}
return true
}
this.setEditMode = function(mode)
{
switch(mode)
{
case 'visual':
this.textarea.blur()
this.htmlEditor.style.display = 'none'
this.synchronize()
this.visualEditor.style.display = 'block'
this.loadTemplates()
this.editorDocument.body.focus()
break
case 'html':
this.editorDocument.body.blur()
this.visualEditor.style.display = 'none'
this.synchronize()
this.htmlEditor.style.display = 'block'
this.textarea.focus()
break
default:
return this.setError(mode + ' is not valid edit mode')
}
this.mode = mode
return true
}
this.setValue = function(value)
{
var e = this
e.textarea.value = value
convertValue(e, true);
}
}
}
|