[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 // Modification to htmlArea to insert Paragraphs instead of 2 // linebreaks, under Gecko engines, circa January 2004 3 // By Adam Wright, for The University of Western Australia 4 // 5 // Distributed under the same terms as HTMLArea itself. 6 // This notice MUST stay intact for use (see license.txt). 7 8 function EnterParagraphs(editor, params) { 9 this.editor = editor; 10 // activate only if we're talking to Gecko 11 if (HTMLArea.is_gecko) 12 this.onKeyPress = this.__onKeyPress; 13 }; 14 15 EnterParagraphs._pluginInfo = { 16 name : "EnterParagraphs", 17 version : "1.0", 18 developer : "Adam Wright", 19 developer_url : "http://blog.hipikat.org/", 20 sponsor : "The University of Western Australia", 21 sponsor_url : "http://www.uwa.edu.au/", 22 license : "htmlArea" 23 }; 24 25 // An array of elements who, in html4, by default, have an inline display and can have children 26 // we use RegExp here since it should be a bit faster, also cleaner to check 27 EnterParagraphs.prototype._html4_inlines_re = /^(a|abbr|acronym|b|bdo|big|cite|code|dfn|em|font|i|kbd|label|q|s|samp|select|small|span|strike|strong|sub|sup|textarea|tt|u|var)$/i; 28 29 // Finds the first parent element of a given node whose display is probably not inline 30 EnterParagraphs.prototype.parentBlock = function(node) { 31 while (node.parentNode && (node.nodeType != 1 || this._html4_inlines_re.test(node.tagName))) 32 node = node.parentNode; 33 return node; 34 }; 35 36 // Internal function for recursively itterating over a all nodes in a fragment 37 // If a callback function returns a non-null value, that is returned and the crawl is therefore broken 38 EnterParagraphs.prototype.walkNodeChildren = function(me, callback) { 39 if (me.firstChild) { 40 var myChild = me.firstChild; 41 var retVal; 42 while (myChild) { 43 if ((retVal = callback(this, myChild)) != null) 44 return retVal; 45 if ((retVal = this.walkNodeChildren(myChild, callback)) != null) 46 return retVal; 47 myChild = myChild.nextSibling; 48 } 49 } 50 }; 51 52 // Callback function to be performed on each node in the hierarchy 53 // Sets flag to true if we find actual text or an element that's not usually displayed inline 54 EnterParagraphs.prototype._isFilling = function(self, node) { 55 if (node.nodeType == 1 && !self._html4_inlines_re.test(node.nodeName)) 56 return true; 57 else if (node.nodeType == 3 && node.nodeValue != '') 58 return true; 59 return null; 60 //alert(node.nodeName); 61 }; 62 63 // Inserts a node deeply on the left of a hierarchy of nodes 64 EnterParagraphs.prototype.insertDeepLeftText = function(target, toInsert) { 65 var falling = target; 66 while (falling.firstChild && falling.firstChild.nodeType == 1) 67 falling = falling.firstChild; 68 //var refNode = falling.firstChild ? falling.firstChild : null; 69 //falling.insertBefore(toInsert, refNode); 70 falling.innerHTML = toInsert; 71 }; 72 73 // Kind of like a macros, for a frequent query... 74 EnterParagraphs.prototype.isElem = function(node, type) { 75 return node.nodeName.toLowerCase() == type.toLowerCase(); 76 }; 77 78 // The onKeyPress even that does all the work - nicely breaks the line into paragraphs 79 EnterParagraphs.prototype.__onKeyPress = function(ev) { 80 81 if (ev.keyCode == 13 && !ev.shiftKey && this.editor._iframe.contentWindow.getSelection) { 82 83 var editor = this.editor; 84 85 // Get the selection and solid references to what we're dealing with chopping 86 var sel = editor._iframe.contentWindow.getSelection(); 87 88 // Set the start and end points such that they're going /forward/ through the document 89 var rngLeft = editor._doc.createRange(); var rngRight = editor._doc.createRange(); 90 rngLeft.setStart(sel.anchorNode, sel.anchorOffset); rngRight.setStart(sel.focusNode, sel.focusOffset); 91 rngLeft.collapse(true); rngRight.collapse(true); 92 93 var direct = rngLeft.compareBoundaryPoints(rngLeft.START_TO_END, rngRight) < 0; 94 95 var startNode = direct ? sel.anchorNode : sel.focusNode; 96 var startOffset = direct ? sel.anchorOffset : sel.focusOffset; 97 var endNode = direct ? sel.focusNode : sel.anchorNode; 98 var endOffset = direct ? sel.focusOffset : sel.anchorOffset; 99 100 // Find the parent blocks of nodes at either end, and their attributes if they're paragraphs 101 var startBlock = this.parentBlock(startNode); var endBlock = this.parentBlock(endNode); 102 var attrsLeft = new Array(); var attrsRight = new Array(); 103 104 // If a list, let the browser take over, if we're in a paragraph, gather it's attributes 105 if (this.isElem(startBlock, 'li') || this.isElem(endBlock, 'li')) 106 return; 107 108 if (this.isElem(startBlock, 'p')) { 109 for (var i = 0; i < startBlock.attributes.length; i++) { 110 attrsLeft[startBlock.attributes[i].nodeName] = startBlock.attributes[i].nodeValue; 111 } 112 } 113 if (this.isElem(endBlock, 'p')) { 114 for (var i = 0; i < endBlock.attributes.length; i++) { 115 // If we start and end within one paragraph, don't duplicate the 'id' 116 if (endBlock != startBlock || endBlock.attributes[i].nodeName.toLowerCase() != 'id') 117 attrsRight[endBlock.attributes[i].nodeName] = endBlock.attributes[i].nodeValue; 118 } 119 } 120 121 // Look for where to start and end our chopping - within surrounding paragraphs 122 // if they exist, or at the edges of the containing block, otherwise 123 var startChop = startNode; var endChop = endNode; 124 125 while ((startChop.previousSibling && !this.isElem(startChop.previousSibling, 'p')) 126 || (startChop.parentNode && startChop.parentNode != startBlock && startChop.parentNode.nodeType != 9)) 127 startChop = startChop.previousSibling ? startChop.previousSibling : startChop.parentNode; 128 129 while ((endChop.nextSibling && !this.isElem(endChop.nextSibling, 'p')) 130 || (endChop.parentNode && endChop.parentNode != endBlock && endChop.parentNode.nodeType != 9)) 131 endChop = endChop.nextSibling ? endChop.nextSibling : endChop.parentNode; 132 133 // Set up new paragraphs 134 var pLeft = editor._doc.createElement('p'); var pRight = editor._doc.createElement('p'); 135 136 for (var attrName in attrsLeft) { 137 var thisAttr = editor._doc.createAttribute(attrName); 138 thisAttr.value = attrsLeft[attrName]; 139 pLeft.setAttributeNode(thisAttr); 140 } 141 for (var attrName in attrsRight) { 142 var thisAttr = editor._doc.createAttribute(attrName); 143 thisAttr.value = attrsRight[attrName]; 144 pRight.setAttributeNode(thisAttr); 145 } 146 147 // Get the ranges destined to be stuffed into new paragraphs 148 rngLeft.setStartBefore(startChop); 149 rngLeft.setEnd(startNode,startOffset); 150 pLeft.appendChild(rngLeft.cloneContents()); // Copy into pLeft 151 152 rngRight.setEndAfter(endChop); 153 rngRight.setStart(endNode,endOffset); 154 pRight.appendChild(rngRight.cloneContents()); // Copy into pRight 155 156 // If either paragraph is empty, fill it with a nonbreakable space 157 var foundBlock = false; 158 foundBlock = this.walkNodeChildren(pLeft, this._isFilling); 159 if (foundBlock != true) 160 this.insertDeepLeftText(pLeft, ' '); 161 162 foundBlock = false; 163 foundBlock = this.walkNodeChildren(pRight, this._isFilling); 164 if (foundBlock != true) 165 this.insertDeepLeftText(pRight, ' '); 166 167 // Get a range for everything to be replaced and replace it 168 var rngAround = editor._doc.createRange(); 169 170 if (!startChop.previousSibling && this.isElem(startChop.parentNode, 'p')) 171 rngAround.setStartBefore(startChop.parentNode); 172 else 173 rngAround.setStart(rngLeft.startContainer, rngLeft.startOffset); 174 175 if (!endChop.nextSibling && this.isElem(endChop.parentNode, 'p')) 176 rngAround.setEndAfter(endChop.parentNode); 177 else 178 rngAround.setEnd(rngRight.endContainer, rngRight.endOffset); 179 180 rngAround.deleteContents(); 181 rngAround.insertNode(pRight); 182 rngAround.insertNode(pLeft); 183 184 // Set the selection to the start of the (second) new paragraph 185 if (pRight.firstChild) { 186 while (pRight.firstChild && this._html4_inlines_re.test(pRight.firstChild.nodeName)) 187 pRight = pRight.firstChild; 188 // Slip into any inline tags 189 if (pRight.firstChild && pRight.firstChild.nodeType == 3) 190 pRight = pRight.firstChild; // and text, if they've got it 191 192 var rngCaret = editor._doc.createRange(); 193 rngCaret.setStart(pRight, 0); 194 rngCaret.collapse(true); 195 196 sel = editor._iframe.contentWindow.getSelection(); 197 sel.removeAllRanges(); 198 sel.addRange(rngCaret); 199 } 200 201 // Stop the bubbling 202 HTMLArea._stopEvent(ev); 203 } 204 };
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |