diff options
Diffstat (limited to 'js/dojo-1.7.2/dojox/editor/plugins/Blockquote.js')
| -rw-r--r-- | js/dojo-1.7.2/dojox/editor/plugins/Blockquote.js | 524 |
1 files changed, 524 insertions, 0 deletions
diff --git a/js/dojo-1.7.2/dojox/editor/plugins/Blockquote.js b/js/dojo-1.7.2/dojox/editor/plugins/Blockquote.js new file mode 100644 index 0000000..8be4529 --- /dev/null +++ b/js/dojo-1.7.2/dojox/editor/plugins/Blockquote.js @@ -0,0 +1,524 @@ +//>>built +define("dojox/editor/plugins/Blockquote", [ + "dojo", + "dijit", + "dojox", + "dijit/_editor/range", + "dijit/_editor/selection", + "dijit/_editor/_Plugin", + "dijit/form/ToggleButton", + "dojo/_base/connect", + "dojo/_base/declare", + "dojo/i18n", + "dojo/i18n!dojox/editor/plugins/nls/Blockquote" +], function(dojo, dijit, dojox) { + +dojo.declare("dojox.editor.plugins.Blockquote",dijit._editor._Plugin,{ + // summary: + // This plugin provides Blockquote cabability to the editor. + // window/tab + + // iconClassPrefix: [const] String + // The CSS class name for the button node icon. + iconClassPrefix: "dijitAdditionalEditorIcon", + + _initButton: function(){ + // summary: + // Over-ride for creation of the preview button. + this._nlsResources = dojo.i18n.getLocalization("dojox.editor.plugins", "Blockquote"); + this.button = new dijit.form.ToggleButton({ + label: this._nlsResources["blockquote"], + showLabel: false, + iconClass: this.iconClassPrefix + " " + this.iconClassPrefix + "Blockquote", + tabIndex: "-1", + onClick: dojo.hitch(this, "_toggleQuote") + }); + }, + + 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(); + this.connect(this.editor, "onNormalizedDisplayChanged", "updateState"); + // We need the custom undo code since we manipulate the dom + // outside of the browser natives and only customUndo really handles + // that. It will incur a performance hit, but should hopefully be + // relatively small. + editor.customUndo = true; + }, + + _toggleQuote: function(arg){ + // summary: + // Function to trigger previewing of the editor document + // tags: + // private + try{ + var ed = this.editor; + ed.focus(); + + var quoteIt = this.button.get("checked"); + var sel = dijit.range.getSelection(ed.window); + var range, elem, start, end; + if(sel && sel.rangeCount > 0){ + range = sel.getRangeAt(0); + } + if(range){ + ed.beginEditing(); + if(quoteIt){ + // Lets see what we've got as a selection... + var bq, tag; + if(range.startContainer === range.endContainer){ + // No selection, just cursor point, we need to see if we're + // in an indentable block, or similar. + if(this._isRootInline(range.startContainer)){ + // Text at the 'root' of the document, so we need to gather all of it., + + // First, we need to find the toplevel inline element that is rooted + // to the document 'editNode' + start = range.startContainer; + while(start && start.parentNode !== ed.editNode){ + start = start.parentNode; + } + // Now we need to walk up its siblings and look for the first one in the rooting + // that isn't inline or text, as we want to grab all of that for indent. + while(start && start.previousSibling && ( + this._isTextElement(start) || + (start.nodeType === 1 && + this._isInlineFormat(this._getTagName(start)) + ))){ + start = start.previousSibling; + } + if(start && start.nodeType === 1 && + !this._isInlineFormat(this._getTagName(start))){ + // Adjust slightly, we're one node too far back in this case. + start = start.nextSibling; + } + + // Okay, we have a configured start, lets grab everything following it that's + // inline and make it part of the blockquote! + if(start){ + bq = ed.document.createElement("blockquote"); + dojo.place(bq, start, "after"); + bq.appendChild(start); + end = bq.nextSibling; + while(end && ( + this._isTextElement(end) || + (end.nodeType === 1 && + this._isInlineFormat(this._getTagName(end))) + )){ + // Add it. + bq.appendChild(end); + end = bq.nextSibling; + } + } + }else{ + // Figure out what to do when not root inline.... + var node = range.startContainer; + while ((this._isTextElement(node) || + this._isInlineFormat(this._getTagName(node)) + || this._getTagName(node) === "li") && + node !== ed.editNode && node !== ed.document.body){ + node = node.parentNode; + } + if(node !== ed.editNode && node !== node.ownerDocument.documentElement){ + bq = ed.document.createElement("blockquote"); + dojo.place(bq, node, "after"); + bq.appendChild(node); + } + } + if(bq){ + dojo.withGlobal(ed.window, + "selectElementChildren", dijit._editor.selection, [bq]); + dojo.withGlobal(ed.window, + "collapse", dijit._editor.selection, [true]); + } + }else{ + var curNode; + // multi-node select. We need to scan over them. + // Find the two containing nodes at start and end. + // then move the end one node past. Then ... lets see + // what we can blockquote! + start = range.startContainer; + end = range.endContainer; + // Find the non-text nodes. + + while(start && this._isTextElement(start) && start.parentNode !== ed.editNode){ + start = start.parentNode; + } + + // Try to find the end node. We have to check the selection junk + curNode = start; + while(curNode.nextSibling && dojo.withGlobal(ed.window, + "inSelection", dijit._editor.selection, [curNode])){ + curNode = curNode.nextSibling; + } + end = curNode; + if(end === ed.editNode || end === ed.document.body){ + // Unable to determine real selection end, so just make it + // a single node indent of start + all following inline styles, if + // present, then just exit. + bq = ed.document.createElement("blockquote"); + dojo.place(bq, start, "after"); + tag = this._getTagName(start); + if(this._isTextElement(start) || this._isInlineFormat(tag)){ + // inline element or textnode + // Find and move all inline tags following the one we inserted also into the + // blockquote so we don't split up content funny. + var next = start; + while(next && ( + this._isTextElement(next) || + (next.nodeType === 1 && + this._isInlineFormat(this._getTagName(next))))){ + bq.appendChild(next); + next = bq.nextSibling; + } + }else{ + bq.appendChild(start); + } + return; + } + + // Has a definite end somewhere, so lets try to blockquote up to it. + // requires looking at the selections and in some cases, moving nodes + // into separate blockquotes. + end = end.nextSibling; + curNode = start; + while(curNode && curNode !== end){ + if(curNode.nodeType === 1){ + tag = this._getTagName(curNode); + if(tag !== "br"){ + if(!window.getSelection){ + // IE sometimes inserts blank P tags, which we want to skip + // as they end up blockquoted, which messes up layout. + if(tag === "p" && this._isEmpty(curNode)){ + curNode = curNode.nextSibling; + continue; + } + } + if(this._isInlineFormat(tag)){ + // inline tag. + if(!bq){ + bq = ed.document.createElement("blockquote"); + dojo.place(bq, curNode, "after"); + bq.appendChild(curNode); + }else{ + bq.appendChild(curNode); + } + curNode = bq; + }else{ + if(bq){ + if(this._isEmpty(bq)){ + bq.parentNode.removeChild(bq); + } + } + bq = ed.document.createElement("blockquote"); + dojo.place(bq, curNode, "after"); + bq.appendChild(curNode); + curNode = bq; + } + } + }else if(this._isTextElement(curNode)){ + if(!bq){ + bq = ed.document.createElement("blockquote"); + dojo.place(bq, curNode, "after"); + bq.appendChild(curNode); + }else{ + bq.appendChild(curNode); + } + curNode = bq; + } + curNode = curNode.nextSibling; + } + // Okay, check the last bq, remove it if no content. + if(bq){ + if(this._isEmpty(bq)){ + bq.parentNode.removeChild(bq); + }else{ + dojo.withGlobal(ed.window, + "selectElementChildren", dijit._editor.selection, [bq]); + dojo.withGlobal(ed.window, + "collapse", dijit._editor.selection, [true]); + } + bq = null; + } + } + }else{ + var found = false; + if(range.startContainer === range.endContainer){ + elem = range.endContainer; + // Okay, now see if we can find one of the formatting types we're in. + while(elem && elem !== ed.editNode && elem !== ed.document.body){ + var tg = elem.tagName?elem.tagName.toLowerCase():""; + if(tg === "blockquote"){ + found = true; + break; + } + elem = elem.parentNode; + } + if(found){ + var lastChild; + while(elem.firstChild){ + lastChild = elem.firstChild; + dojo.place(lastChild, elem, "before"); + } + elem.parentNode.removeChild(elem); + if(lastChild){ + dojo.withGlobal(ed.window, + "selectElementChildren", dijit._editor.selection, [lastChild]); + dojo.withGlobal(ed.window, + "collapse", dijit._editor.selection, [true]); + } + } + }else{ + // Multi-select! Gotta find all the blockquotes contained within the selection area. + start = range.startContainer; + end = range.endContainer; + while(start && this._isTextElement(start) && start.parentNode !== ed.editNode){ + start = start.parentNode; + } + var selectedNodes = []; + var cNode = start; + while(cNode && cNode.nextSibling && dojo.withGlobal(ed.window, + "inSelection", dijit._editor.selection, [cNode])){ + if(cNode.parentNode && this._getTagName(cNode.parentNode) === "blockquote"){ + cNode = cNode.parentNode; + } + selectedNodes.push(cNode); + cNode = cNode.nextSibling; + } + + // Find all the blocknodes now that we know the selection area. + var bnNodes = this._findBlockQuotes(selectedNodes); + while(bnNodes.length){ + var bn = bnNodes.pop(); + if(bn.parentNode){ + // Make sure we haven't seen this before and removed it. + while(bn.firstChild){ + dojo.place(bn.firstChild, bn, "before"); + } + bn.parentNode.removeChild(bn); + } + } + } + } + ed.endEditing(); + } + ed.onNormalizedDisplayChanged(); + }catch(e){ /* Squelch */ } + }, + + updateState: function(){ + // summary: + // Overrides _Plugin.updateState(). This controls whether or not the current + // cursor position should toggle on the quote button or not. + // tags: + // protected + var ed = this.editor; + var disabled = this.get("disabled"); + + if(!ed || !ed.isLoaded){ return; } + if(this.button){ + this.button.set("disabled", disabled); + if(disabled){ + return; + } + + // Some browsers (WebKit) doesn't actually get the tag info right. + // So ... lets check it manually. + var elem; + var found = false; + + // Try to find the ansestor element (and see if it is blockquote) + var sel = dijit.range.getSelection(ed.window); + if(sel && sel.rangeCount > 0){ + var range = sel.getRangeAt(0); + if(range){ + elem = range.endContainer; + } + } + // Okay, now see if we can find one of the formatting types we're in. + while(elem && elem !== ed.editNode && elem !== ed.document){ + var tg = elem.tagName?elem.tagName.toLowerCase():""; + if(tg === "blockquote"){ + found = true; + break; + } + elem = elem.parentNode; + } + // toggle whether or not the current selection is blockquoted. + this.button.set("checked", found); + } + }, + + _findBlockQuotes: function(nodeList){ + // summary: + // function to find a ll the blocknode elements in a collection of + // nodes + // nodeList: + // The list of nodes. + // tags: + // private + var bnList = []; + if(nodeList){ + var i; + for(i = 0; i < nodeList.length; i++){ + var node = nodeList[i]; + if(node.nodeType === 1){ + if(this._getTagName(node) === "blockquote"){ + bnList.push(node); + } + if(node.childNodes && node.childNodes.length > 0){ + bnList = bnList.concat(this._findBlockQuotes(node.childNodes)); + } + } + } + } + return bnList; + }, + + /*****************************************************************/ + /* Functions borrowed from NormalizeIndentOutdent */ + /*****************************************************************/ + + _getTagName: function(node){ + // summary: + // Internal function to get the tag name of an element + // if any. + // node: + // The node to look at. + // tags: + // private + var tag = ""; + if(node && node.nodeType === 1){ + tag = node.tagName?node.tagName.toLowerCase():""; + } + return tag; + }, + + _isRootInline: function(node){ + // summary: + // This functions tests whether an indicated node is in root as inline + // or rooted inline elements in the page. + // node: + // The node to start at. + // tags: + // private + var ed = this.editor; + if(this._isTextElement(node) && node.parentNode === ed.editNode){ + return true; + }else if(node.nodeType === 1 && this._isInlineFormat(node) && node.parentNode === ed.editNode){ + return true; + }else if(this._isTextElement(node) && this._isInlineFormat(this._getTagName(node.parentNode))){ + node = node.parentNode; + while(node && node !== ed.editNode && this._isInlineFormat(this._getTagName(node))){ + node = node.parentNode; + } + if(node === ed.editNode){ + return true; + } + } + return false; + }, + + _isTextElement: function(node){ + // summary: + // Helper function to check for text nodes. + // node: + // The node to check. + // tags: + // private + if(node && node.nodeType === 3 || node.nodeType === 4){ + return true; + } + return false; + }, + + _isEmpty: function(node){ + // summary: + // Internal function to determine if a node is 'empty' + // Eg, contains only blank text. Used to determine if + // an empty list element should be removed or not. + // node: + // The node to check. + // tags: + // private + if(node.childNodes){ + var empty = true; + var i; + for(i = 0; i < node.childNodes.length; i++){ + var n = node.childNodes[i]; + if(n.nodeType === 1){ + if(this._getTagName(n) === "p"){ + if(!dojo.trim(n.innerHTML)){ + continue; + } + } + empty = false; + break; + }else if(this._isTextElement(n)){ + // Check for empty text. + var nv = dojo.trim(n.nodeValue); + if(nv && nv !==" " && nv !== "\u00A0"){ + empty = false; + break; + } + }else{ + empty = false; + break; + } + } + return empty; + }else{ + return true; + } + }, + + _isInlineFormat: function(tag){ + // summary: + // Function to determine if the current tag is an inline + // element that does formatting, as we don't want to + // break/indent around it, as it can screw up text. + // tag: + // The tag to examine + // tags: + // private + switch(tag){ + case "a": + case "b": + case "strong": + case "s": + case "strike": + case "i": + case "u": + case "em": + case "sup": + case "sub": + case "span": + case "font": + case "big": + case "cite": + case "q": + case "img": + case "small": + return true; + default: + return false; + } + } +}); + +// Register this plugin. +dojo.subscribe(dijit._scopeName + ".Editor.getPlugin",null,function(o){ + if(o.plugin){ return; } + var name = o.args.name.toLowerCase(); + if(name === "blockquote"){ + o.plugin = new dojox.editor.plugins.Blockquote({}); + } +}); + +return dojox.editor.plugins.Blockquote; + +}); |
