source: branches/1.2/workflow/js/htmlarea/plugins/EnterParagraphs/enter-paragraphs.js @ 1349

Revision 1349, 8.0 KB checked in by niltonneto, 15 years ago (diff)

Ticket #561 - Inclusão do módulo Workflow faltante nessa versão.

  • Property svn:executable set to *
Line 
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
8function 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
15EnterParagraphs._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
27EnterParagraphs.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
30EnterParagraphs.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
38EnterParagraphs.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
54EnterParagraphs.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
64EnterParagraphs.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...
74EnterParagraphs.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
79EnterParagraphs.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, '&nbsp;');
161
162                foundBlock = false;
163                foundBlock = this.walkNodeChildren(pRight, this._isFilling);
164                if (foundBlock != true)
165                        this.insertDeepLeftText(pRight, '&nbsp;');
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};
Note: See TracBrowser for help on using the repository browser.