You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
231 lines
7.8 KiB
231 lines
7.8 KiB
define([ |
|
"dojo", |
|
"dijit", |
|
"dojox", |
|
"dijit/_editor/_Plugin", |
|
"dijit/_base/manager", |
|
"dijit/_editor/RichText", |
|
"dijit/form/Button", |
|
"dijit/Dialog", |
|
"dojox/html/format", |
|
"dojo/_base/connect", |
|
"dojo/_base/declare", |
|
"dojo/i18n", |
|
"dojo/string", |
|
"dojo/i18n!dojox/editor/plugins/nls/PasteFromWord", |
|
"dojo/i18n!dijit/nls/common", |
|
"dojo/i18n!dijit/_editor/nls/commands" |
|
], function(dojo, dijit, dojox, _Plugin) { |
|
|
|
var PasteFromWord = dojo.declare("dojox.editor.plugins.PasteFromWord", _Plugin, { |
|
// summary: |
|
// This plugin provides PasteFromWord capability to the editor. When |
|
// clicked, a dialog opens with a spartan RichText instance to paste |
|
// word content into via the keyboard commands. The contents are |
|
// then filtered to remove word style classes and other meta-junk |
|
// that tends to cause issues. |
|
|
|
// iconClassPrefix: [const] String |
|
// The CSS class name for the button node is formed from `iconClassPrefix` |
|
// and `command` |
|
iconClassPrefix: "dijitAdditionalEditorIcon", |
|
|
|
// width: [public] String |
|
// The width to use for the rich text area in the copy/pate dialog, in px. Default is 400px. |
|
width: "400px", |
|
|
|
// height: [public] String |
|
// The height to use for the rich text area in the copy/pate dialog, in px. Default is 300px. |
|
height: "300px", |
|
|
|
_template: ["<div class='dijitPasteFromWordEmbeddedRTE'>", |
|
"<div style='width: ${width}; padding-top: 5px; padding-bottom: 5px;'>${instructions}</div>", |
|
"<div id='${uId}_rte' style='width: ${width}; height: ${height}'></div>", |
|
"<table style='width: ${width}' tabindex='-1'>", |
|
"<tbody>", |
|
"<tr>", |
|
"<td align='center'>", |
|
"<button type='button' dojoType='dijit.form.Button' id='${uId}_paste'>${paste}</button>", |
|
" ", |
|
"<button type='button' dojoType='dijit.form.Button' id='${uId}_cancel'>${buttonCancel}</button>", |
|
"</td>", |
|
"</tr>", |
|
"</tbody>", |
|
"</table>", |
|
"</div>"].join(""), |
|
|
|
// _filters: [protected] Array |
|
// The filters is an array of regular expressions to try and strip out a lot |
|
// of style data MS Word likes to insert when pasting into a contentEditable. |
|
// Prettymuch all of it is junk and not good html. The hander is a place to put a function |
|
// for match handling. In most cases, it just handles it as empty string. But the option is |
|
// there for more complex handling. |
|
_filters: [ |
|
// Meta tags, link tags, and prefixed tags |
|
{regexp: /(<meta\s*[^>]*\s*>)|(<\s*link\s* href="file:[^>]*\s*>)|(<\/?\s*\w+:[^>]*\s*>)/gi, handler: ""}, |
|
// Style tags |
|
{regexp: /(?:<style([^>]*)>([\s\S]*?)<\/style>|<link\s+(?=[^>]*rel=['"]?stylesheet)([^>]*?href=(['"])([^>]*?)\4[^>\/]*)\/?>)/gi, handler: ""}, |
|
// MS class tags and comment tags. |
|
{regexp: /(class="Mso[^"]*")|(<!--(.|\s){1,}?-->)/gi, handler: ""}, |
|
// blank p tags |
|
{regexp: /(<p[^>]*>\s*(\ |\u00A0)*\s*<\/p[^>]*>)|(<p[^>]*>\s*<font[^>]*>\s*(\ |\u00A0)*\s*<\/\s*font\s*>\s<\/p[^>]*>)/ig, handler: ""}, |
|
// Strip out styles containing mso defs and margins, as likely added in IE and are not good to have as it mangles presentation. |
|
{regexp: /(style="[^"]*mso-[^;][^"]*")|(style="margin:\s*[^;"]*;")/gi, handler: ""}, |
|
// Scripts (if any) |
|
{regexp: /(<\s*script[^>]*>((.|\s)*?)<\\?\/\s*script\s*>)|(<\s*script\b([^<>]|\s)*>?)|(<[^>]*=(\s|)*[("|')]javascript:[^$1][(\s|.)]*[$1][^>]*>)/ig, handler: ""}, |
|
// Word 10 odd o:p tags. |
|
{regexp: /<(\/?)o\:p[^>]*>/gi, handler: ""} |
|
], |
|
|
|
_initButton: function(){ |
|
// summary: |
|
// Over-ride for creation of the save button. |
|
this._filters = this._filters.slice(0); |
|
|
|
var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "PasteFromWord"); |
|
dojo.mixin(strings, dojo.i18n.getLocalization("dijit", "common")); |
|
dojo.mixin(strings, dojo.i18n.getLocalization("dijit._editor", "commands")); |
|
this.button = new dijit.form.Button({ |
|
label: strings["pasteFromWord"], |
|
showLabel: false, |
|
iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "PasteFromWord", |
|
tabIndex: "-1", |
|
onClick: dojo.hitch(this, "_openDialog") |
|
}); |
|
|
|
this._uId = dijit.getUniqueId(this.editor.id); |
|
|
|
strings.uId = this._uId; |
|
strings.width = this.width || "400px"; |
|
strings.height = this.height || "300px"; |
|
|
|
this._dialog = new dijit.Dialog({title: strings["pasteFromWord"]}).placeAt(dojo.body()); |
|
this._dialog.set("content", dojo.string.substitute(this._template, strings)); |
|
|
|
// Make it translucent so we can fade in the window when the RTE is created. |
|
// the RTE has to be created 'visible, and this is a nice trick to make the creation |
|
// 'pretty'. |
|
dojo.style(dojo.byId(this._uId + "_rte"), "opacity", 0.001); |
|
|
|
// Link up the action buttons to perform the insert or cleanup. |
|
this.connect(dijit.byId(this._uId + "_paste"), "onClick", "_paste"); |
|
this.connect(dijit.byId(this._uId + "_cancel"), "onClick", "_cancel"); |
|
this.connect(this._dialog, "onHide", "_clearDialog"); |
|
}, |
|
|
|
updateState: function(){ |
|
// summary: |
|
// Over-ride for button state control for disabled to work. |
|
this.button.set("disabled", this.get("disabled")); |
|
}, |
|
|
|
setEditor: function(editor){ |
|
// summary: |
|
// Over-ride for the setting of the editor. |
|
// editor: Object |
|
// The editor to configure for this plugin to use. |
|
this.editor = editor; |
|
this._initButton(); |
|
}, |
|
|
|
_openDialog: function(){ |
|
// summary: |
|
// Function to trigger opening the copy dialog. |
|
// tags: |
|
// private |
|
this._dialog.show(); |
|
if(!this._rte){ |
|
// RTE hasn't been created yet, so we need to create it now that the |
|
// dialog is showing up. |
|
setTimeout(dojo.hitch(this, function() { |
|
this._rte = new dijit._editor.RichText({height: this.height || "300px"}, this._uId + "_rte"); |
|
this._rte.startup(); |
|
this._rte.onLoadDeferred.addCallback(dojo.hitch(this, function() { |
|
dojo.animateProperty({ |
|
node: this._rte.domNode, properties: { opacity: { start: 0.001, end: 1.0 } } |
|
}).play(); |
|
})); |
|
}), 100); |
|
} |
|
}, |
|
|
|
_paste: function(){ |
|
// summary: |
|
// Function to handle setting the contents of the copy from dialog |
|
// into the editor. |
|
// tags: |
|
// private |
|
|
|
// Gather the content and try to format it a bit (makes regexp cleanup simpler). |
|
// It also normalizes tag names and styles, so regexps are the same across browsers. |
|
var content = dojox.html.format.prettyPrint(this._rte.get("value")); |
|
|
|
//Close up the dialog and clear old content. |
|
this._dialog.hide(); |
|
|
|
// Apply all the filters to remove MS specific injected text. |
|
var i; |
|
for(i = 0; i < this._filters.length; i++){ |
|
var filter = this._filters[i]; |
|
content = content.replace(filter.regexp, filter.handler); |
|
} |
|
|
|
// Format it again to make sure it is reasonably formatted as |
|
// the regexp applies will have likely chewed up the formatting. |
|
content = dojox.html.format.prettyPrint(content); |
|
|
|
// Paste it in. |
|
this.editor.focus(); |
|
this.editor.execCommand("inserthtml", content); |
|
}, |
|
|
|
_cancel: function(){ |
|
// summary: |
|
// Function to handle cancelling setting the contents of the |
|
// copy from dialog into the editor. |
|
// tags: |
|
// private |
|
this._dialog.hide(); |
|
}, |
|
|
|
_clearDialog: function(){ |
|
// summary: |
|
// simple function to cleat the contents when hide is calledon dialog |
|
// copy from dialog into the editor. |
|
// tags: |
|
// private |
|
this._rte.set("value", ""); |
|
}, |
|
|
|
destroy: function(){ |
|
// sunnary: |
|
// Cleanup function |
|
// tags: |
|
// public |
|
if(this._rte){ |
|
this._rte.destroy(); |
|
} |
|
if(this._dialog){ |
|
this._dialog.destroyRecursive(); |
|
} |
|
delete this._dialog; |
|
delete this._rte; |
|
this.inherited(arguments); |
|
} |
|
|
|
}); |
|
|
|
// Register this plugin. |
|
dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ |
|
if(o.plugin){ return; } |
|
var name = o.args.name.toLowerCase(); |
|
if(name === "pastefromword"){ |
|
o.plugin = new PasteFromWord({ |
|
width: ("width" in o.args)?o.args.width:"400px", |
|
height: ("height" in o.args)?o.args.width:"300px" |
|
}); |
|
} |
|
}); |
|
|
|
return PasteFromWord; |
|
});
|
|
|