1 | /* |
---|
2 | * WYMeditor : what you see is What You Mean web-based editor |
---|
3 | * Copyright (C) 2007 H.O.net - http://www.honet.be/ |
---|
4 | * Dual licensed under the MIT (MIT-license.txt) |
---|
5 | * and GPL (GPL-license.txt) licenses. |
---|
6 | * |
---|
7 | * For further information visit: |
---|
8 | * http://www.wymeditor.org/ |
---|
9 | * |
---|
10 | * File Name: |
---|
11 | * jquery.wymeditor.mozilla.js |
---|
12 | * Gecko specific class and functions. |
---|
13 | * See the documentation for more info. |
---|
14 | * |
---|
15 | * File Authors: |
---|
16 | * Jean-Francois Hovinne (jf.hovinne@wymeditor.org) |
---|
17 | */ |
---|
18 | |
---|
19 | function WymClassMozilla(wym) { |
---|
20 | |
---|
21 | this._wym = wym; |
---|
22 | }; |
---|
23 | |
---|
24 | WymClassMozilla.prototype.initIframe = function(iframe) { |
---|
25 | |
---|
26 | this._iframe = iframe; |
---|
27 | this._doc = iframe.contentDocument; |
---|
28 | |
---|
29 | this._doc.title = this._wym._index; |
---|
30 | this._doc.designMode="on"; |
---|
31 | this._doc.execCommand("styleWithCSS",'',false); |
---|
32 | |
---|
33 | this.html(this._wym._html); |
---|
34 | if(this._callback) this._callback(); |
---|
35 | |
---|
36 | // handle events within editor |
---|
37 | // NOTE v.mische this needs to be here and not in the generic fi |
---|
38 | this.handleEvents(); |
---|
39 | }; |
---|
40 | |
---|
41 | WymClassMozilla.prototype._exec = function(cmd,param) { |
---|
42 | |
---|
43 | if(param) this._doc.execCommand(cmd,'',param); |
---|
44 | else this._doc.execCommand(cmd,'',null); |
---|
45 | }; |
---|
46 | |
---|
47 | /* @name selected |
---|
48 | * @description Returns the selected container |
---|
49 | */ |
---|
50 | WymClassMozilla.prototype.selected = function() { |
---|
51 | |
---|
52 | var sel=this._iframe.contentWindow.getSelection(); |
---|
53 | var node=sel.focusNode; |
---|
54 | if(node.nodeName=="#text")return(node.parentNode); |
---|
55 | else return(node); |
---|
56 | }; |
---|
57 | |
---|
58 | |
---|
59 | /* @name xhtml |
---|
60 | * @description Cleans up the HTML |
---|
61 | */ |
---|
62 | WymClassMozilla.prototype.xhtml = function() { |
---|
63 | |
---|
64 | var sHtml = this._wym.html(); |
---|
65 | |
---|
66 | var flagTag=false,begTag=false; |
---|
67 | var tag="",ret="",attr=""; |
---|
68 | var level=0; |
---|
69 | |
---|
70 | for(var x=0;x<sHtml.length;x++) |
---|
71 | { |
---|
72 | c=sHtml.charAt(x); |
---|
73 | |
---|
74 | if(begTag) |
---|
75 | { |
---|
76 | if(c==" " || c==">") |
---|
77 | { |
---|
78 | switch(tag) |
---|
79 | { |
---|
80 | case "b": |
---|
81 | tag="strong"; |
---|
82 | break; |
---|
83 | case "/b": |
---|
84 | tag="/strong"; |
---|
85 | break; |
---|
86 | case "i": |
---|
87 | tag="em"; |
---|
88 | break; |
---|
89 | case "/i": |
---|
90 | tag="/em"; |
---|
91 | break; |
---|
92 | case "br": |
---|
93 | tag="br /" |
---|
94 | break; |
---|
95 | case "ol": case "ul": |
---|
96 | level++; |
---|
97 | if(level>1 && ret.substr(ret.length-5)=="</li>") |
---|
98 | ret=ret.substr(0,ret.length-5); |
---|
99 | break; |
---|
100 | default: |
---|
101 | break; |
---|
102 | } |
---|
103 | begTag=false; |
---|
104 | } |
---|
105 | else tag+=c; |
---|
106 | } |
---|
107 | |
---|
108 | if(c=="<"){begTag=true;flagTag=true;} |
---|
109 | |
---|
110 | if(flagTag) |
---|
111 | { |
---|
112 | if(c==">") |
---|
113 | { |
---|
114 | flagTag=false; |
---|
115 | switch(tag) |
---|
116 | { |
---|
117 | case "img": |
---|
118 | case "hr": |
---|
119 | case "input": |
---|
120 | case "link": |
---|
121 | case "base": |
---|
122 | case "basefont": |
---|
123 | case "col": |
---|
124 | case "frame": |
---|
125 | case "isindex": |
---|
126 | case "meta": |
---|
127 | case "param": |
---|
128 | ret+="<"+tag+attr+"/>"; |
---|
129 | break; |
---|
130 | case "/ol": case "/ul": |
---|
131 | if(level>1)ret+="<"+tag+attr+"></li>"; |
---|
132 | else ret+="<"+tag+attr+">"; |
---|
133 | level--; |
---|
134 | break; |
---|
135 | default: |
---|
136 | ret+="<"+tag+attr+">"; |
---|
137 | break; |
---|
138 | } |
---|
139 | |
---|
140 | tag=""; |
---|
141 | attr=""; |
---|
142 | } |
---|
143 | else if(!begTag) |
---|
144 | { |
---|
145 | attr+=c; |
---|
146 | } |
---|
147 | } |
---|
148 | else ret+=c; |
---|
149 | } |
---|
150 | return(ret); |
---|
151 | }; |
---|
152 | |
---|
153 | /********** SELECTION API **********/ |
---|
154 | |
---|
155 | function WymSelMozilla(wym) { |
---|
156 | |
---|
157 | this._wym = wym; |
---|
158 | }; |
---|
159 | |
---|
160 | WymSelMozilla.prototype = { |
---|
161 | getSelection: function() |
---|
162 | { |
---|
163 | var _sel = this._wym._iframe.contentWindow.getSelection(); |
---|
164 | // NOTE v.mische can startNode/endNote be phantom nodes? |
---|
165 | this.startNode = _sel.getRangeAt(0).startContainer; |
---|
166 | this.endNode = _sel.getRangeAt(0).endContainer; |
---|
167 | this.startOffset = _sel.getRangeAt(0).startOffset; |
---|
168 | this.endOffset = _sel.getRangeAt(0).endOffset; |
---|
169 | this.isCollapsed = _sel.isCollapsed; |
---|
170 | this.original = _sel; |
---|
171 | this.container = $j(this.startNode).parentsOrSelf( |
---|
172 | aWYM_CONTAINERS.join(",")); |
---|
173 | |
---|
174 | return this; |
---|
175 | }, |
---|
176 | |
---|
177 | cursorToStart: function(jqexpr) |
---|
178 | { |
---|
179 | if (jqexpr.nodeType == aWYM_NODE.TEXT) |
---|
180 | jqexpr = jqexpr.parentNode; |
---|
181 | |
---|
182 | var firstTextNode = $(jqexpr)[0]; |
---|
183 | |
---|
184 | while (firstTextNode.nodeType!=aWYM_NODE.TEXT) |
---|
185 | { |
---|
186 | if (!firstTextNode.hasChildNodes()) |
---|
187 | break; |
---|
188 | firstTextNode = firstTextNode.firstChild; |
---|
189 | } |
---|
190 | |
---|
191 | if (isPhantomNode(firstTextNode)) |
---|
192 | firstTextNode = firstTextNode.nextSibling; |
---|
193 | |
---|
194 | // e.g. an <img/> |
---|
195 | if (firstTextNode.nodeType == aWYM_NODE.ELEMENT) |
---|
196 | this.original.collapse(firstTextNode.parentNode, 0); |
---|
197 | else |
---|
198 | this.original.collapse(firstTextNode, 0); |
---|
199 | }, |
---|
200 | |
---|
201 | cursorToEnd: function(jqexpr) |
---|
202 | { |
---|
203 | if (jqexpr.nodeType == aWYM_NODE.TEXT) |
---|
204 | jqexpr = jqexpr.parentNode; |
---|
205 | |
---|
206 | var lastTextNode = $(jqexpr)[0]; |
---|
207 | |
---|
208 | while (lastTextNode.nodeType!=aWYM_NODE.TEXT) |
---|
209 | { |
---|
210 | if (!lastTextNode.hasChildNodes()) |
---|
211 | break; |
---|
212 | lastTextNode = lastTextNode.lastChild; |
---|
213 | } |
---|
214 | |
---|
215 | if (isPhantomNode(lastTextNode)) |
---|
216 | lastTextNode = lastTextNode.previousSibling; |
---|
217 | |
---|
218 | // e.g. an <img/> |
---|
219 | if (lastTextNode.nodeType == aWYM_NODE.ELEMENT) |
---|
220 | this.original.collapse(lastTextNode.parentNode, |
---|
221 | lastTextNode.parentNode.childNodes.length); |
---|
222 | else |
---|
223 | this.original.collapse(lastTextNode, lastTextNode.length); |
---|
224 | }, |
---|
225 | |
---|
226 | |
---|
227 | deleteIfExpanded: function() |
---|
228 | { |
---|
229 | if(!this.original.isCollapsed) |
---|
230 | { |
---|
231 | this.original.deleteFromDocument(); |
---|
232 | return true; |
---|
233 | } |
---|
234 | return false; |
---|
235 | } |
---|
236 | }; |
---|
237 | |
---|
238 | |
---|