summaryrefslogtreecommitdiff
path: root/js/dojo-1.7.2/dojox/editor/plugins/Blockquote.js
diff options
context:
space:
mode:
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.js524
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 !=="&nbsp;" && 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;
+
+});