fb5941dffe89ededc684e95041997bff36017355
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / htmlarea / plugins / TYPO3Browsers / typo3browsers.js
1 /***************************************************************
2 * Copyright notice
3 *
4 * (c) 2005, 2006 Stanislas Rolland <stanislas.rolland(arobas)fructifor.ca>
5 * All rights reserved
6 *
7 * This script is part of the TYPO3 project. The TYPO3 project is
8 * free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * The GNU General Public License can be found at
14 * http://www.gnu.org/copyleft/gpl.html.
15 * A copy is found in the textfile GPL.txt and important notices to the license
16 * from the author is found in LICENSE.txt distributed with these scripts.
17 *
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 /**
27 * TYPO3 Image & Link Browsers Plugin for TYPO3 htmlArea RTE
28 *
29 * TYPO3 CVS ID: $Id$
30 */
31
32 TYPO3Browsers = function(editor,args) {
33 this.editor = editor;
34 var cfg = this.editor.config;
35 cfg.btnList.CreateLink[1] = this.editor.imgURL("ed_link.gif", "TYPO3Browsers");
36 };
37
38 TYPO3Browsers.I18N = TYPO3Browsers_langArray;
39
40 TYPO3Browsers._pluginInfo = {
41 name : "TYPO3Browsers",
42 version : "1.7",
43 developer : "Stanislas Rolland",
44 developer_url : "http://www.fructifor.ca/",
45 c_owner : "Stanislas Rolland",
46 sponsor : "Fructifor Inc.",
47 sponsor_url : "http://www.fructifor.ca/",
48 license : "GPL"
49 };
50
51 /*
52 * CreateLink: Typo3-RTE function, use this instead of the original.
53 */
54 HTMLArea.prototype.renderPopup_link = function() {
55 var editorNumber = this._editorNumber,
56 addUrlParams = "?" + RTEarea[editorNumber]["RTEtsConfigParams"],
57 backreturn,
58 sel = this.getParentElement();
59
60 // Download the definition of special anchor classes if not yet done
61 if(RTEarea[editorNumber]["classesAnchorUrl"] && !this.classesAnchorSetup) {
62 var classesAnchorData = HTMLArea._getScript(0, false, RTEarea[editorNumber]["classesAnchorUrl"]);
63 var editor = this;
64 if(classesAnchorData) eval(classesAnchorData);
65 editor = null;
66 }
67
68 var el = HTMLArea.getElementObject(sel,"a");
69 if (el != null && el.tagName && el.tagName.toLowerCase() == "a") sel = el;
70 if (sel != null && sel.tagName && sel.tagName.toLowerCase() == "a") {
71 addUrlParams = "?curUrl[href]=" + encodeURIComponent(sel.getAttribute("href"));
72 addUrlParams += "&curUrl[typo3ContentLanguage]=" + RTEarea[editorNumber]["typo3ContentLanguage"];
73 addUrlParams += "&curUrl[typo3ContentCharset]=" + RTEarea[editorNumber]["typo3ContentCharset"];
74 if (sel.target) addUrlParams += "&curUrl[target]=" + encodeURIComponent(sel.target);
75 if (sel.className) addUrlParams += "&curUrl[class]=" + encodeURIComponent(sel.className);
76 if (sel.title) addUrlParams += "&curUrl[title]=" + encodeURIComponent(sel.title);
77 addUrlParams += RTEarea[editorNumber]["RTEtsConfigParams"];
78 } else if (this.hasSelectedText()) {
79 var text = this.getSelectedHTML();
80 if (text && text != null) {
81 var offset = text.toLowerCase().indexOf("<a");
82 if (offset!=-1) {
83 var ATagContent = text.substring(offset+2);
84 offset = ATagContent.toUpperCase().indexOf(">");
85 ATagContent = ATagContent.substring(0,offset);
86 addUrlParams = "?curUrl[all]=" + encodeURIComponent(ATagContent);
87 addUrlParams += RTEarea[editorNumber]["RTEtsConfigParams"];
88 }
89 }
90 }
91 this._popupDialog(RTEarea[0]["pathLinkModule"] + addUrlParams + "&editorNo=" + editorNumber + "&typo3ContentLanguage=" + RTEarea[editorNumber]["typo3ContentLanguage"] + "&typo3ContentCharset=" + encodeURIComponent(RTEarea[editorNumber]["typo3ContentCharset"]), null, backreturn, 550, 350, null, "yes");
92 return false;
93 };
94
95 /*
96 * Add a link to the selection.
97 * This function is called from the TYPO3 link popup.
98 */
99 HTMLArea.prototype.renderPopup_addLink = function(theLink,cur_target,cur_class,cur_title) {
100 var a, sel = null, range = null, node = null, imageNode = null;
101 this.focusEditor();
102 node = this.getParentElement();
103 var el = HTMLArea.getElementObject(node,"a");
104 if (el != null && el.tagName && el.tagName.toLowerCase() == "a") node = el;
105 if (node != null && node.tagName && node.tagName.toLowerCase() == "a") this.selectNode(node);
106 // Clean images from existing anchors otherwise Mozilla may create nested anchors
107 if (this.classesAnchorSetup) {
108 sel = this._getSelection();
109 range = this._createRange(sel);
110 this.cleanAllLinks(node, range, true);
111 }
112
113 this._doc.execCommand("CreateLink", false, theLink);
114
115 sel = this._getSelection();
116 range = this._createRange(sel);
117 node = this.getParentElement();
118 var el = HTMLArea.getElementObject(node,"a");
119 if (el != null && el.tagName && el.tagName.toLowerCase() == "a") node = el;
120 if (node) {
121 if (this.classesAnchorSetup && cur_class) {
122 for (var i = this.classesAnchorSetup.length; --i >= 0;) {
123 var anchorClass = this.classesAnchorSetup[i];
124 if(anchorClass['name'] == cur_class && anchorClass["image"]) {
125 imageNode = this._doc.createElement("img");
126 imageNode.src = anchorClass["image"];
127 imageNode.alt = anchorClass["altText"];
128 break;
129 }
130 }
131 }
132 // We may have created multiple links in as many blocks
133 this.setLinkAttributes(node, range, cur_target, cur_class, cur_title, imageNode);
134 }
135
136 Dialog._modal.close();
137 this.updateToolbar();
138 };
139
140 /*
141 * Set attributes of anchors intersecting a range in the given node
142 */
143 HTMLArea.prototype.setLinkAttributes = function(node,range,cur_target,cur_class,cur_title,imageNode) {
144 if (node.tagName && node.tagName.toLowerCase() == "a") {
145 var nodeInRange = false;
146 if (HTMLArea.is_gecko) {
147 nodeInRange = this.rangeIntersectsNode(range, node);
148 } else {
149 if (this._getSelection().type.toLowerCase() == "control") {
150 // we assume an image is selected
151 nodeInRange = true;
152 } else {
153 var nodeRange = this._doc.body.createTextRange();
154 nodeRange.moveToElementText(node);
155 nodeInRange = range.inRange(nodeRange) || (range.compareEndPoints("StartToStart", nodeRange) == 0) || (range.compareEndPoints("EndToEnd", nodeRange) == 0);
156 }
157 }
158 if (nodeInRange) {
159 if (imageNode != null) node.insertBefore(imageNode.cloneNode(false), node.firstChild);
160 if (cur_target.trim()) node.target = cur_target.trim();
161 else node.removeAttribute("target");
162 if (cur_class.trim()) {
163 node.className = cur_class.trim();
164 } else {
165 if (HTMLArea.is_gecko) node.removeAttribute('class');
166 else node.removeAttribute('className');
167 }
168 if (cur_title.trim()) {
169 node.title = cur_title.trim();
170 } else {
171 node.removeAttribute("title");
172 node.removeAttribute("rtekeep");
173 }
174 }
175 } else {
176 for (var i = node.firstChild;i;i = i.nextSibling) {
177 if (i.nodeType == 1 || i.nodeType == 11) this.setLinkAttributes(i, range, cur_target, cur_class, cur_title, imageNode);
178 }
179 }
180 };
181
182 /*
183 * Clean up images in special anchor classes
184 */
185 HTMLArea.prototype.cleanClassesAnchorImages = function(node) {
186 var nodeArray = [], splitArray1 = [], splitArray2 = [];
187 for (var childNode = node.firstChild; childNode; childNode = childNode.nextSibling) {
188 if (childNode.tagName && childNode.tagName.toLowerCase() == "img") {
189 splitArray1 = childNode.src.split("/");
190 for (var i = this.classesAnchorSetup.length; --i >= 0;) {
191 if (this.classesAnchorSetup[i]["image"]) {
192 splitArray2 = this.classesAnchorSetup[i]["image"].split("/");
193 if (splitArray1[splitArray1.length-1] == splitArray2[splitArray2.length-1]) {
194 nodeArray.push(childNode);
195 break;
196 }
197 }
198 }
199 }
200 }
201 for (i = nodeArray.length; --i >= 0;) {
202 node.removeChild(nodeArray[i]);
203 }
204 };
205
206 /*
207 * Clean up all anchors intesecting with the range in the given node
208 */
209 HTMLArea.prototype.cleanAllLinks = function(node,range,keepLinks) {
210 if (node.tagName && node.tagName.toLowerCase() == "a") {
211 var intersection = false;
212 if (HTMLArea.is_gecko) {
213 intersection = this.rangeIntersectsNode(range, node);
214 } else {
215 if (this._getSelection().type.toLowerCase() == "control") {
216 // we assume an image is selected
217 intersection = true;
218 } else {
219 var nodeRange = this._doc.body.createTextRange();
220 nodeRange.moveToElementText(node);
221 intersection = range.inRange(nodeRange) || ((range.compareEndPoints("StartToStart", nodeRange) > 0) && (range.compareEndPoints("StartToEnd", nodeRange) < 0)) || ((range.compareEndPoints("EndToStart", nodeRange) > 0) && (range.compareEndPoints("EndToEnd", nodeRange) < 0));
222 }
223 }
224 if (intersection) {
225 this.cleanClassesAnchorImages(node);
226 if (!keepLinks) {
227 while(node.firstChild) node.parentNode.insertBefore(node.firstChild, node);
228 node.parentNode.removeChild(node);
229 }
230 }
231 } else {
232 for (var i = node.firstChild;i;i = i.nextSibling) {
233 if (i.nodeType == 1 || i.nodeType == 11) this.cleanAllLinks(i, range, keepLinks);
234 }
235 }
236 };
237
238 /*
239 * Unlink the selection.
240 * This function is called from the TYPO3 link popup and from the context menu.
241 */
242 HTMLArea.prototype.renderPopup_unLink = function() {
243 this.focusEditor();
244 var node = this.getParentElement();
245 var el = HTMLArea.getElementObject(node,"a");
246 if (el != null && el.tagName && el.tagName.toLowerCase() == "a") node = el;
247 if (node != null && node.tagName && node.tagName.toLowerCase() == "a") this.selectNode(node);
248 if (this.classesAnchorSetup) {
249 var sel = this._getSelection();
250 var range = this._createRange(sel);
251 if (HTMLArea.is_gecko) {
252 this.cleanAllLinks(node, range, false);
253 } else {
254 this.cleanAllLinks(node, range, true);
255 this._doc.execCommand("Unlink", false, "");
256 }
257
258 } else {
259 this._doc.execCommand("Unlink", false, "");
260 }
261 if(Dialog._modal) Dialog._modal.close();
262 };
263
264 /*
265 * IE-Browsers strip URL's to relative URL's. But for the TYPO3 backend we need absolute URL's.
266 * This function overloads the normal stripBaseURL-function (which generate relative URLs).
267 */
268 HTMLArea.prototype.nonStripBaseURL = function(url) {
269 return url;
270 };
271
272 TYPO3Browsers.prototype.onGenerate = function() {
273 var editor = this.editor;
274 //editor._insertImage = editor.renderPopup_image;
275 editor._createLink = editor.renderPopup_link;
276 editor.stripBaseURL = editor.nonStripBaseURL;
277 };