/* ***** BEGIN LICENSE BLOCK *****
* This file is part of DotClear.
* Copyright (c) 2005 Nicolas Martin & Olivier Meunier and contributors. All
* rights reserved.
*
* DotClear is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* DotClear is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DotClear; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ***** END LICENSE BLOCK *****
*/
jsToolBar.prototype.can_wwg = (document.designMode != undefined);
jsToolBar.prototype.iframe = null;
jsToolBar.prototype.iwin = null;
jsToolBar.prototype.ibody = null;
jsToolBar.prototype.iframe_css = null;
/* Editor methods
-------------------------------------------------------- */
jsToolBar.prototype.drawToolBar = jsToolBar.prototype.draw;
jsToolBar.prototype.draw = function(mode) {
mode = mode || 'xhtml';
if (this.can_wwg) {
this.mode = 'wysiwyg';
this.drawToolBar('wysiwyg');
this.initWindow();
} else {
this.drawToolBar(mode);
}
};
jsToolBar.prototype.switchMode = function(mode) {
mode = mode || 'xhtml';
if (mode == 'xhtml') {
this.draw(mode);
} else {
if (this.wwg_mode) {
this.syncContents('iframe');
}
this.removeEditor();
this.textarea.style.display = '';
this.drawToolBar(mode);
}
};
jsToolBar.prototype.syncContents = function(from) {
from = from || 'textarea';
var This = this;
if (from == 'textarea') {
initContent();
} else {
this.validBlockquote();
var html = this.applyHtmlFilters(this.ibody.innerHTML);
if (html == '
') { html = '
'; }
this.textarea.value = html;
}
function initContent() {
if (!This.iframe.contentWindow.document || !This.iframe.contentWindow.document.body) {
setTimeout(initContent, 1);
return;
}
This.ibody = This.iframe.contentWindow.document.body;
if (This.textarea.value != '' && This.textarea.value != '') {
This.ibody.innerHTML = This.applyWysiwygFilters(This.textarea.value);
if (This.ibody.createTextRange) { //cursor at the begin for IE
var IErange = This.ibody.createTextRange();
IErange.execCommand("SelectAll");
IErange.collapse();
IErange.select();
}
} else if (window.navigator.product != undefined &&
window.navigator.product == 'Gecko') {
This.ibody.innerHTML = '
';
} else {
var idoc = This.iwin.document;
var para = idoc.createElement('p');
para.appendChild(idoc.createTextNode(''));
while (idoc.body.hasChildNodes()) {
idoc.body.removeChild(idoc.body.lastChild);
}
idoc.body.appendChild(para);
}
}
};
jsToolBar.prototype.htmlFilters = {
tagsoup: function(str){
return this.tagsoup2xhtml(str);
}
};
jsToolBar.prototype.applyHtmlFilters = function(str) {
for (var fn in this.htmlFilters) {
str = this.htmlFilters[fn].call(this, str);
}
return str;
};
jsToolBar.prototype.wysiwygFilters = {};
jsToolBar.prototype.applyWysiwygFilters = function( str) {
for (var fn in this.wysiwygFilters) {
str = this.wysiwygFilters[fn].call(this, str);
}
return str;
};
jsToolBar.prototype.switchEdit = function() {
if (this.wwg_mode) {
this.textarea.style.display = '';
this.iframe.style.display = 'none';
this.syncContents('iframe');
this.drawToolBar('xhtml');
this.wwg_mode = false;
this.focusEditor();
} else {
this.iframe.style.display = '';
this.textarea.style.display = 'none';
this.syncContents('textarea');
this.drawToolBar('wysiwyg');
this.wwg_mode = true;
this.focusEditor();
}
this.setSwitcher();
};
/** Creates iframe for editor, inits a blank document
*/
jsToolBar.prototype.initWindow = function() {
var This = this;
this.iframe = document.createElement('iframe');
this.textarea.parentNode.insertBefore(this.iframe,this.textarea.nextSibling);
this.switcher = document.createElement('ul');
this.switcher.className = 'jstSwitcher';
this.editor.appendChild(this.switcher);
this.iframe.height = this.textarea.offsetHeight + 0;
this.iframe.width = this.textarea.offsetWidth + 0;
if (this.textarea.tabIndex != undefined) {
this.iframe.tabIndex = this.textarea.tabIndex;
}
function initIframe() {
var doc = This.iframe.contentWindow.document;
if (!doc) {
setTimeout(initIframe,1);
return false;
}
doc.open();
var html =
'\n'+
'\n'+
'\n'+
(This.base_url != '' ? '' : '')+
'\n'+
'\n'+
'\n'+
'';
doc.write(html);
doc.close();
if (document.all) { // for IE
doc.designMode = 'on';
// warning : doc is now inaccessible for IE6 sp1
}
This.iwin = This.iframe.contentWindow;
This.syncContents('textarea');
if (This.wwg_mode == undefined) {
This.wwg_mode = true;
}
if (This.wwg_mode) {
This.textarea.style.display = 'none';
} else {
This.iframe.style.display = 'none';
}
// update textarea on submit
if (This.textarea.form) {
chainHandler(This.textarea.form,'onsubmit', function() {
if (This.wwg_mode) {
This.syncContents('iframe');
}
});
}
for (var evt in This.iwinEvents) {
var event = This.iwinEvents[evt];
This.addIwinEvent(This.iframe.contentWindow.document, event.type, event.fn, This);
}
This.setSwitcher();
setTimeout(function(){This.focusEditor();},1);
return true;
}
initIframe();
};
jsToolBar.prototype.addIwinEvent = function(target, type, fn, scope) {
var myFn = function(e){fn.call(scope, e)};
addEvent(target, type, myFn, true);
// fix memory leak
addEvent(scope.iwin, 'unload', function(){
removeEvent(target, type, myFn, true);
}, true);
};
jsToolBar.prototype.iwinEvents = {
block1: {
type: 'mouseup',
fn: function(){ this.adjustBlockLevelCombo() }
},
block2: {
type: 'keyup',
fn: function(){ this.adjustBlockLevelCombo() }
}
};
/** Insert a mode switcher after editor area
*/
jsToolBar.prototype.switcher_visual_title = 'visual';
jsToolBar.prototype.switcher_source_title = 'source';
jsToolBar.prototype.setSwitcher = function() {
while (this.switcher.hasChildNodes()) {
this.switcher.removeChild(this.switcher.firstChild);
}
var This = this;
function setLink(title,link) {
var li = document.createElement('li');
if (link) {
var a = document.createElement('a');
a.href = '#';
a.editor = This;
a.onclick = function() { this.editor.switchEdit(); return false; };
a.appendChild(document.createTextNode(title));
} else {
li.className = 'jstSwitcherCurrent';
a = document.createTextNode(title);
}
li.appendChild(a);
This.switcher.appendChild(li);
}
setLink(this.switcher_visual_title,!this.wwg_mode);
setLink(this.switcher_source_title,this.wwg_mode);
};
/** Removes editor area and mode switcher
*/
jsToolBar.prototype.removeEditor = function() {
if (this.iframe != null) {
this.iframe.parentNode.removeChild(this.iframe);
this.iframe = null;
}
if (this.switcher != undefined && this.switcher.parentNode != undefined) {
this.switcher.parentNode.removeChild(this.switcher);
}
};
/** Focus on the editor area
*/
jsToolBar.prototype.focusEditor = function() {
if (this.wwg_mode) {
try { this.iwin.document.designMode = 'on'; } catch (e) {}; // Firefox needs this
var This = this;
setTimeout(function() {This.iframe.contentWindow.focus()},1);
} else {
this.textarea.focus();
}
};
/** Resizer
*/
jsToolBar.prototype.resizeSetStartH = function() {
if (this.wwg_mode && this.iframe != undefined) {
this.dragStartH = this.iframe.offsetHeight;
return;
}
this.dragStartH = this.textarea.offsetHeight + 0;
};
jsToolBar.prototype.resizeDragMove = function(event) {
var new_height = (this.dragStartH+event.clientY-this.dragStartY)+'px';
if (this.iframe != undefined) {
this.iframe.style.height = new_height;
}
this.textarea.style.height = new_height;
};
/* Editing methods
-------------------------------------------------------- */
/** Replaces current selection by given node
*/
jsToolBar.prototype.insertNode = function(node) {
var range;
if (this.iwin.getSelection) { // Gecko
var sel = this.iwin.getSelection();
range = sel.getRangeAt(0);
// deselect all ranges
sel.removeAllRanges();
// empty range
range.deleteContents();
// Insert node
range.insertNode(node);
range.selectNodeContents(node);
range.setEndAfter(node);
if (range.endContainer.childNodes.length > range.endOffset &&
range.endContainer.nodeType != Node.TEXT_NODE) {
range.setEnd(range.endContainer.childNodes[range.endOffset], 0);
} else {
range.setEnd(range.endContainer.childNodes[0]);
}
sel.addRange(range);
sel.collapseToEnd();
} else { // IE
// lambda element
var p = this.iwin.document.createElement('div');
p.appendChild(node);
range = this.iwin.document.selection.createRange();
range.execCommand('delete');
// insert innerHTML from element
range.pasteHTML(p.innerHTML);
range.collapse(false);
range.select();
}
this.iwin.focus();
};
/** Returns a document fragment with selected nodes
*/
jsToolBar.prototype.getSelectedNode = function() {
if (this.iwin.getSelection) { // Gecko
var sel = this.iwin.getSelection();
var range = sel.getRangeAt(0);
var content = range.cloneContents();
} else { // IE
var sel = this.iwin.document.selection;
var d = this.iwin.document.createElement('div');
d.innerHTML = sel.createRange().htmlText;
var content = this.iwin.document.createDocumentFragment();
for (var i=0; i < d.childNodes.length; i++) {
content.appendChild(d.childNodes[i].cloneNode(true));
}
}
return content;
};
/** Returns string representation for selected node
*/
jsToolBar.prototype.getSelectedText = function() {
if (this.iwin.getSelection) { // Gecko
return this.iwin.getSelection().toString();
} else { // IE
var range = this.iwin.document.selection.createRange();
return range.text;
}
};
jsToolBar.prototype.replaceNodeByContent = function(node) {
var content = this.iwin.document.createDocumentFragment();
for (var i=0; i < node.childNodes.length; i++) {
content.appendChild(node.childNodes[i].cloneNode(true));
}
node.parentNode.replaceChild(content, node);
};
jsToolBar.prototype.getBlockLevel = function() {
var blockElts = ['p','h1','h2','h3','h4','h5','h6'];
var range, commonAncestorContainer;
if (this.iwin.getSelection) { //gecko
var selection = this.iwin.getSelection();
range = selection.getRangeAt(0);
commonAncestorContainer = range.commonAncestorContainer;
while (commonAncestorContainer.nodeType != 1) {
commonAncestorContainer = commonAncestorContainer.parentNode;
}
} else { //ie
range = this.iwin.document.selection.createRange();
commonAncestorContainer = range.parentElement();
}
var ancestorTagName = commonAncestorContainer.tagName.toLowerCase();
while (arrayIndexOf(blockElts, ancestorTagName)==-1 && ancestorTagName!='body') {
commonAncestorContainer = commonAncestorContainer.parentNode;
ancestorTagName = commonAncestorContainer.tagName.toLowerCase();
}
if (ancestorTagName == 'body') return null;
else return commonAncestorContainer;
};
jsToolBar.prototype.adjustBlockLevelCombo = function() {
var blockLevel = this.getBlockLevel();
if (blockLevel !== null)
this.toolNodes.blocks.value = blockLevel.tagName.toLowerCase();
else {
if (this.mode == 'wysiwyg') this.toolNodes.blocks.value = 'none';
if (this.mode == 'xhtml') this.toolNodes.blocks.value = 'nonebis';
}
};
/** HTML code cleanup
-------------------------------------------------------- */
jsToolBar.prototype.simpleCleanRegex = new Array(
/* Remove every tags we don't need */
[//gim,''],
[/