diff options
Diffstat (limited to 'js/dojo/dojox/editor/plugins/PasteFromWord.js')
| -rw-r--r-- | js/dojo/dojox/editor/plugins/PasteFromWord.js | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/js/dojo/dojox/editor/plugins/PasteFromWord.js b/js/dojo/dojox/editor/plugins/PasteFromWord.js new file mode 100644 index 0000000..6e9278f --- /dev/null +++ b/js/dojo/dojox/editor/plugins/PasteFromWord.js @@ -0,0 +1,224 @@ +//>>built +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; +}); |
