123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- define("dojox/editor/plugins/PasteFromWord", [
- "dojo",
- "dijit",
- "dojox",
- "dijit/_base/manager",
- "dijit/_editor/_Plugin",
- "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"
- ], function(dojo, dijit, dojox) {
- dojo.declare("dojox.editor.plugins.PasteFromWord",dijit._editor._Plugin,{
- // summary:
- // This plugin provides PasteFromWord cabability 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'>${cancel}</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: ""}
- ],
- _initButton: function(){
- this._filters = this._filters.slice(0);
-
- // summary:
- // Over-ride for creation of the save button.
- var strings = dojo.i18n.getLocalization("dojox.editor.plugins", "PasteFromWord");
- 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 ncie 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.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.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 dojox.editor.plugins.PasteFromWord({
- width: ("width" in o.args)?o.args.width:"400px",
- height: ("height" in o.args)?o.args.width:"300px"
- });
- }
- });
- return dojox.editor.plugins.PasteFromWord;
- });
|