/*!
* Aloha Editor
* Author & Copyright (c) 2010 Gentics Software GmbH
* aloha-sales@gentics.com
* Licensed unter the terms of http://www.aloha-editor.com/license.html
*/
define(
['aloha', 'aloha/jquery', 'aloha/contenthandlermanager'],
function(Aloha, jQuery, ContentHandlerManager) {
var
GENTICS = window.GENTICS;
/**
* Register the generic content handler
*/
var GenericContentHandler = ContentHandlerManager.createHandler({
/**
* Handle the pasting. Remove all unwanted stuff.
* @param content
*/
handleContent: function( content ) {
if ( typeof content === 'string' ){
content = jQuery( '
' ).append(content);
}
// If we find an aloha-block inside the pasted content,
// we do not modify the pasted stuff, as it most probably
// comes from Aloha and not from other sources, and does
// not need to be cleaned up.
if (content.find('.aloha-block').length > 0) {
return;
}
// clean lists
this.cleanLists(content);
// transform tables
this.transformTables(content);
// remove comments
this.removeComments(content);
// unwrap font and span tags
this.unwrapTags(content);
// remove styles
this.removeStyles(content);
// remove namespaced elements
this.removeNamespacedElements(content);
// transform formattings
this.transformFormattings(content);
// transform links
//this.transformLinks(content);
return content.html();
},
/**
* Clean lists: The only allowed children of ol or ul elements are li's. Everything else will be removed
* @param content
*/
cleanLists: function(content) {
content.find('ul,ol').each(function() {
var $list = jQuery(this);
$list.contents(':not(li,ul,ol)').each(function() {
jQuery(this).remove();
});
// for all li's, trim the text contents
$list.children('li').each(function() {
var $li = jQuery(this);
$li.contents().each(function() {
if (this.nodeType === 3) {
this.data = jQuery.trim(this.data);
}
});
});
});
},
/**
* Transform tables which were pasted
* @param content
*/
transformTables: function(content) {
// remove border, cellspacing, cellpadding from all tables
// @todo what about width, height?
content.find('table').each(function() {
jQuery(this).removeAttr('border').removeAttr('cellspacing').removeAttr('cellpadding');
});
// remove unwanted attributes and cleanup single empty p-tags
content.find('td').each(function() {
// remove width, height and valign from all table cells
jQuery(this).removeAttr('width').removeAttr('height').removeAttr('valign');
if ( this.innerHTML.replace(/[\s\xA0]+/g,'') === '
' ) {
this.innerHTML = ' ';
}
if ( jQuery(this).find('p').length == 1) {
jQuery(this).find('p').contents().unwrap();
}
});
// remove unwanted attributes from tr also? (tested with paste from open/libre office)
// @todo or do this all via sanitize.js
content.find('tr').each(function() {
// remove width, height and valign from all table cells
jQuery(this).removeAttr('width').removeAttr('height').removeAttr('valign');
});
// completely colgroup tags
// @TODO should we remove colgroup? use sanitize for that?
content.find('colgroup').remove();
},
/**
* Transform formattings
* @param content
*/
transformFormattings: function( content ) {
// find all formattings we will transform
content.find('strong,em,s,u').each(function() {
if (this.nodeName.toLowerCase() == 'strong') {
// transform strong to b
Aloha.Markup.transformDomObject(jQuery(this), 'b');
} else if (this.nodeName.toLowerCase() == 'em') {
// transform em to i
Aloha.Markup.transformDomObject(jQuery(this), 'i');
} else if (this.nodeName.toLowerCase() == 's') {
// transform s to del
Aloha.Markup.transformDomObject(jQuery(this), 'del');
} else if (this.nodeName.toLowerCase() == 'u') {
// transform u?
jQuery(this).contents().unwrap();
}
});
},
/**
* Transform links
* @param content
*/
transformLinks: function( content ) {
// find all links and remove the links without href (will be destination anchors from word table of contents)
// aloha is not supporting anchors at the moment -- maybe rewrite anchors in headings to "invisible"
// in the test document there are anchors for whole paragraphs --> the whole P appear as link
content.find('a').each(function() {
if ( typeof jQuery(this).attr('href') === 'undefined' ) {
jQuery(this).contents().unwrap();
}
});
},
/**
* Remove all comments
* @param content
*/
removeComments: function( content ) {
var that = this;
// ok, remove all comments
content.contents().each(function() {
if (this.nodeType == 8) {
jQuery(this).remove();
} else {
// do recursion
that.removeComments(jQuery(this));
}
});
},
/**
* Remove some unwanted tags from content pasted
* @param content
*/
unwrapTags: function( content ) {
var that = this;
content.children('span,font,div').filter(function() {
return this.contentEditable != 'false';
}).each(function() {
if (this.nodeName == 'DIV') {
// safari and chrome cleanup for plain text paste with working linebreaks
if (this.innerHTML == '
') {
jQuery(this).contents().unwrap();
} else {
jQuery( Aloha.Markup.transformDomObject(jQuery(this), 'p').append('
') ).contents().unwrap();
}
} else {
jQuery(this).contents().unwrap();
}
that.unwrapTags(jQuery(this));
});
},
/**
* Remove styles
* @param content
*/
removeStyles: function( content ) {
var that = this;
// completely remove style tags
content.children('style').filter(function() {
return this.contentEditable != 'false';
}).remove();
// remove style attributes and classes
content.children().filter(function() {
return this.contentEditable != 'false';
}).each(function() {
jQuery(this).removeAttr('style').removeClass();
that.removeStyles(jQuery(this));
});
},
/**
* Remove all elements which are in different namespaces
* @param content
*/
removeNamespacedElements: function( content ) {
// get all elements
content.find('*').each(function() {
// try to determine the namespace prefix ('prefix' works for W3C
// compliant browsers, 'scopeName' for IE)
var nsPrefix = this.prefix ? this.prefix
: (this.scopeName ? this.scopeName : undefined);
// when the prefix is set (and different from 'HTML'), we remove the
// element
if ((nsPrefix && nsPrefix != 'HTML') || this.nodeName.indexOf(':') >= 0 ) {
var $this = jQuery(this), $contents = $this.contents();
if ($contents.length) {
// the element has contents, so unwrap the contents
$contents.unwrap();
} else {
// the element is empty, so remove it
$this.remove();
}
}
});
}
});
return GenericContentHandler;
});