4296dfc7d9712c99e7e0fc28b29b4dd54dd58fe8
[Packages/TYPO3.CMS.git] / typo3 / tree.js
1 /***************************************************************
2 *
3 * javascript functions regarding the page & folder tree
4 * relies on the javascript library "prototype"
5 *
6 *
7 * Copyright notice
8 *
9 * (c) 2006 Benjamin Mack <bmack@xnos.org>
10 * All rights reserved
11 *
12 * This script is part of the TYPO3 t3lib/ library provided by
13 * Kasper Skaarhoj <kasper@typo3.com> together with TYPO3
14 *
15 * Released under GNU/GPL (see license file in tslib/)
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * This copyright notice MUST APPEAR in all copies of this script
22 *
23 * TYPO3 SVN ID: $Id$
24 *
25 ***************************************************************/
26
27 // Call this function, refresh_nav(), from another script in the backend if you want
28 // to refresh the navigation frame (eg. after having changed a page title or moved pages etc.)
29 // See t3lib_BEfunc::getSetUpdateSignal()
30 function refresh_nav() { window.setTimeout('_refresh_nav();',0); }
31 function _refresh_nav() {
32 var r = new Date();
33 // randNum is useful so pagetree does not get cached in browser cache when refreshing
34 window.location.href = Tree.thisScript + '?randNum=' + r.getTime();
35 }
36
37
38 var Tree = {
39 thisScript: null,
40 frameSetModule: null,
41 activateDragDrop: true,
42
43 // reloads a part of the page tree (useful when "expand" / "collapse")
44 load: function(params, isExpand, obj) {
45 // fallback if AJAX is not possible (e.g. IE < 6)
46 if (!Ajax.getTransport()) {
47 window.location.href = this.thisScript + '?PM=' + params;
48 return;
49 }
50
51 // immediately collapse the subtree and change the plus to a minus when collapsing
52 // without waiting for the response
53 if (!isExpand) {
54 $(obj.parentNode.getElementsByTagName('ul')[0]).remove();
55 var pm = $(obj.parentNode).getElementsByClassName('pm')[0].firstChild;
56 pm.src = pm.src.replace('minus', 'plus');
57 } else {
58 obj.style.cursor = 'wait';
59 }
60
61 new Ajax.Request(this.thisScript, {
62 method: 'get',
63 parameters: 'ajax=1&PM=' + params,
64 onComplete: function(xhr) {
65 // the parent node needs to be overwritten, not the object
66 $(obj.parentNode).replace(xhr.responseText);
67 this.registerDragDropHandlers();
68 this.reSelectActiveItem();
69 }.bind(this)
70 });
71 },
72
73 // attaches the events to the elements needed for the drag and drop (for the titles and the icons)
74 registerDragDropHandlers: function() {
75 if (!this.activateDragDrop) return;
76 this._registerDragDropHandlers('dragTitle');
77 this._registerDragDropHandlers('dragIcon');
78 },
79
80 _registerDragDropHandlers: function(className) {
81 var elements = document.getElementsByClassName(className, $('tree'));
82 for (var i = 0; i < elements.length; i++) {
83 Event.observe(elements[i], 'mousedown', function(event) { DragDrop.dragElement(event); }, true);
84 Event.observe(elements[i], 'dragstart', function(event) { DragDrop.dragElement(event); }, false);
85 Event.observe(elements[i], 'mouseup', function(event) { DragDrop.dropElement(event); }, false);
86 }
87 },
88
89 // selects the activated item again, in case it collapsed and got expanded again
90 reSelectActiveItem: function() {
91 obj = $(top.fsMod.navFrameHighlightedID[this.frameSetModule]);
92 if (obj) Element.addClassName(obj, 'active');
93 },
94
95 // highlights an active list item in the page tree and registers it to the top-frame
96 // used when loading the page for the first time
97 highlightActiveItem: function(frameSetModule, highlightID) {
98 this.frameSetModule = frameSetModule;
99
100 // Remove all items that are already highlighted
101 obj = $(top.fsMod.navFrameHighlightedID[frameSetModule]);
102 if (obj) Element.removeClassName(obj, 'active');
103
104 // Set the new item
105 top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID;
106 if ($(highlightID)) Element.addClassName(highlightID, 'active');
107 }
108
109 }
110
111
112
113 // new object-oriented drag and drop - code,
114 // tested in IE 6, Firefox 2, Opera 9
115 var DragDrop = {
116 dragID: null,
117 dragIconCSS: null,
118
119 // options needed for doing the changes when dropping
120 table: null, // can be "pages" or "folders"
121 changeURL: null,
122 backPath: null,
123
124
125 dragElement: function(event, elementID) {
126 Event.stop(event); // stop bubbling
127 this.dragID = this.getIdFromEvent(event);
128 if (this.dragID == 0) return false;
129
130 if (!elementID) elementID = this.dragID;
131 if (!$('dragIcon')) this.addDragIcon();
132
133 $('dragIcon').innerHTML = $('dragIconID_'+elementID).innerHTML
134 + $('dragTitleID_'+elementID).firstChild.innerHTML;
135
136 this.dragIconCSS = new GL_getObjCss('dragIcon');
137 this.dragIconCSS.whiteSpace = 'nowrap';
138 document.onmouseup = function(event) { DragDrop.cancelDragEvent(event); };
139 document.onmousemove = function(event) { DragDrop.mouseMoveEvent(event); };
140 return false;
141 },
142
143 dropElement: function(event) {
144 var dropID = this.getIdFromEvent(event);
145 if ((this.dragID) && (this.dragID != dropID)) {
146 var url = this.changeURL
147 + '?dragDrop=' + this.table
148 + '&srcId=' + this.dragID
149 + '&dstId=' + dropID;
150 + '&backPath=' + this.backPath;
151 showClickmenu_raw(url);
152 }
153 this.cancelDragEvent();
154 return false;
155 },
156
157
158 cancelDragEvent: function(event) {
159 this.dragID = null;
160 if (this.dragIconCSS && this.dragIconCSS.visibility) { this.dragIconCSS.visibility = 'hidden'; }
161 document.onmouseup = null;
162 document.onmousemove = null;
163 },
164
165 mouseMoveEvent: function(event) {
166 this.dragIconCSS.left = (GLV_x + 5) + 'px';
167 this.dragIconCSS.top = (GLV_y - 5) + 'px';
168 this.dragIconCSS.visibility = 'visible';
169 return false;
170 },
171
172
173 // -- helper functions --
174 getIdFromEvent: function(event) {
175 var obj = Event.element(event);
176 while (obj.id == false && obj.parentNode) { obj = obj.parentNode; }
177 return obj.id.substring(obj.id.indexOf('_')+1);
178 },
179
180 // dynamically manipulates the DOM to add the div needed for drag&drop at the bottom of the <body>-tag
181 addDragIcon: function() {
182 var code = '<div id="dragIcon" style="visibility: hidden;">&nbsp;</div>';
183 new Insertion.Bottom(document.getElementsByTagName('body')[0], code);
184 }
185 }