/**
* @author Shea Frederick - http://www.vinylfox.com
* @class Ext.ux.form.HtmlEditor.Word
* @extends Ext.util.Observable
* <p>A plugin that creates a button on the HtmlEditor for pasting text from Word without all the jibberish html.</p>
*/
Ext.ux.form.HtmlEditor.Word = Ext.extend(Ext.util.Observable, {
// Word language text
langTitle: 'Word Paste',
langToolTip: 'Cleanse text pasted from Word or other Rich Text applications',
wordPasteEnabled: true,
// private
curLength: 0,
lastLength: 0,
lastValue: '',
// private
init: function(cmp){
this.cmp = cmp;
this.cmp.on('render', this.onRender, this);
this.cmp.on('initialize', this.onInit, this, {delay:100, single: true});
},
// private
onInit: function(){
Ext.EventManager.on(this.cmp.getDoc(), {
'keyup': this.checkIfPaste,
scope: this
});
this.lastValue = this.cmp.getValue();
this.curLength = this.lastValue.length;
this.lastLength = this.lastValue.length;
},
// private
checkIfPaste: function(e){
var diffAt = 0;
this.curLength = this.cmp.getValue().length;
if (e.V == e.getKey() && e.ctrlKey && this.wordPasteEnabled){
this.cmp.suspendEvents();
diffAt = this.findValueDiffAt(this.cmp.getValue());
var parts = [
this.cmp.getValue().substr(0, diffAt),
this.fixWordPaste(this.cmp.getValue().substr(diffAt, (this.curLength - this.lastLength))),
this.cmp.getValue().substr((this.curLength - this.lastLength)+diffAt, this.curLength)
];
this.cmp.setValue(parts.join(''));
this.cmp.resumeEvents();
}
this.lastLength = this.cmp.getValue().length;
this.lastValue = this.cmp.getValue();
},
// private
findValueDiffAt: function(val){
for (i=0;i<this.curLength;i++){
if (this.lastValue[i] != val[i]){
return i;
}
}
},
/**
* Cleans up the jubberish html from Word pasted text.
* @param wordPaste String The text that needs to be cleansed of Word jibberish html.
* @return {String} The passed in text with all Word jibberish html removed.
*/
fixWordPaste: function(wordPaste) {
var removals = [/ /ig, /[\r\n]/g, /<(xml|style)[^>]*>.*?<\/\1>/ig, /<\/?(meta|object|span)[^>]*>/ig,
/<\/?[A-Z0-9]*:[A-Z]*[^>]*>/ig, /(lang|class|type|href|name|title|id|clear)=\"[^\"]*\"/ig, /style=(\'\'|\"\")/ig, /<![\[-].*?-*>/g,
/MsoNormal/g, /<\\?\?xml[^>]*>/g, /<\/?o:p[^>]*>/g, /<\/?v:[^>]*>/g, /<\/?o:[^>]*>/g, /<\/?st1:[^>]*>/g, / /g,
/<\/?SPAN[^>]*>/g, /<\/?FONT[^>]*>/g, /<\/?STRONG[^>]*>/g, /<\/?H1[^>]*>/g, /<\/?H2[^>]*>/g, /<\/?H3[^>]*>/g, /<\/?H4[^>]*>/g,
/<\/?H5[^>]*>/g, /<\/?H6[^>]*>/g, /<\/?P[^>]*><\/P>/g, /<!--(.*)-->/g, /<!--(.*)>/g, /<!(.*)-->/g, /<\\?\?xml[^>]*>/g,
/<\/?o:p[^>]*>/g, /<\/?v:[^>]*>/g, /<\/?o:[^>]*>/g, /<\/?st1:[^>]*>/g, /style=\"[^\"]*\"/g, /style=\'[^\"]*\'/g, /lang=\"[^\"]*\"/g,
/lang=\'[^\"]*\'/g, /class=\"[^\"]*\"/g, /class=\'[^\"]*\'/g, /type=\"[^\"]*\"/g, /type=\'[^\"]*\'/g, /href=\'#[^\"]*\'/g,
/href=\"#[^\"]*\"/g, /name=\"[^\"]*\"/g, /name=\'[^\"]*\'/g, / clear=\"all\"/g, /id=\"[^\"]*\"/g, /title=\"[^\"]*\"/g,
/<span[^>]*>/g, /<\/?span[^>]*>/g, /<title>(.*)<\/title>/g, /class=/g, /<meta[^>]*>/g, /<link[^>]*>/g, /<style>(.*)<\/style>/g,
/<w:[^>]*>(.*)<\/w:[^>]*>/g];
Ext.each(removals, function(s){
wordPaste = wordPaste.replace(s, "");
});
// keep the divs in paragraphs
wordPaste = wordPaste.replace(/<div[^>]*>/g, "<p>");
wordPaste = wordPaste.replace(/<\/?div[^>]*>/g, "</p>");
return wordPaste;
},
// private
onRender: function() {
this.cmp.getToolbar().add({
iconCls: 'x-edit-wordpaste',
pressed: true,
handler: function(t){
t.toggle(!t.pressed);
this.wordPasteEnabled = !this.wordPasteEnabled;
},
scope: this,
tooltip: {
text: this.langToolTip
},
overflowText: this.langTitle
});
}
});