8b95fc003dbf2a3b8c8d70c0054e9a13234d8982
[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 highlightClass: 'active',
43
44 // reloads a part of the page tree (useful when "expand" / "collapse")
45 load: function(params, isExpand, obj) {
46 // fallback if AJAX is not possible (e.g. IE < 6)
47 if (!Ajax.getTransport()) {
48 window.location.href = this.thisScript + '?PM=' + params;
49 return;
50 }
51
52 // immediately collapse the subtree and change the plus to a minus when collapsing
53 // without waiting for the response
54 if (!isExpand) {
55 obj.parentNode.getElementsByTagName('ul')[0].remove();
56 var pm = document.getElementsByClassName('pm', obj.parentNode)[0];
57 pm.onclick = null;
58 pm.firstChild.src = pm.firstChild.src.replace('minus', 'plus');
59 } else {
60 obj.style.cursor = 'wait';
61 }
62
63 new Ajax.Request(this.thisScript, {
64 method: 'get',
65 parameters: 'ajax=1&PM=' + params,
66 onComplete: function(xhr) {
67 // the parent node needs to be overwritten, not the object
68 $(obj.parentNode).replace(xhr.responseText);
69 this.registerDragDropHandlers();
70 this.reSelectActiveItem();
71 }.bind(this)
72 });
73 },
74
75 // attaches the events to the elements needed for the drag and drop (for the titles and the icons)
76 registerDragDropHandlers: function() {
77 if (!this.activateDragDrop) return;
78 this._registerDragDropHandlers('dragTitle');
79 this._registerDragDropHandlers('dragIcon');
80 },
81
82 _registerDragDropHandlers: function(className) {
83 var elements = document.getElementsByClassName(className, $('tree'));
84 for (var i = 0; i < elements.length; i++) {
85 Event.observe(elements[i], 'mousedown', function(event) { DragDrop.dragElement(event); }, true);
86 Event.observe(elements[i], 'dragstart', function(event) { DragDrop.dragElement(event); }, false);
87 Event.observe(elements[i], 'mouseup', function(event) { DragDrop.dropElement(event); }, false);
88 }
89 },
90
91 // selects the activated item again, in case it collapsed and got expanded again
92 reSelectActiveItem: function() {
93 obj = $(top.fsMod.navFrameHighlightedID[this.frameSetModule]);
94 if (obj) Element.addClassName(obj, this.highlightClass);
95 },
96
97 // highlights an active list item in the page tree and registers it to the top-frame
98 // used when loading the page for the first time
99 highlightActiveItem: function(frameSetModule, highlightID) {
100 this.frameSetModule = frameSetModule;
101
102 // Remove all items that are already highlighted
103 obj = $(top.fsMod.navFrameHighlightedID[frameSetModule]);
104 if (obj) Element.removeClassName(obj, this.highlightClass);
105
106 // Set the new item
107 top.fsMod.navFrameHighlightedID[frameSetModule] = highlightID;
108 if ($(highlightID)) Element.addClassName(highlightID, this.highlightClass);
109 }
110
111 }
112
113
114
115 // new object-oriented drag and drop - code,
116 // tested in IE 6, Firefox 2, Opera 9
117 var DragDrop = {
118 dragID: null,
119 dragIconCSS: null,
120
121 // options needed for doing the changes when dropping
122 table: null, // can be "pages" or "folders"
123 changeURL: null,
124 backPath: null,
125
126
127 dragElement: function(event, elementID) {
128 Event.stop(event); // stop bubbling
129 this.dragID = this.getIdFromEvent(event);
130 if (this.dragID == 0) return false;
131
132 if (!elementID) elementID = this.dragID;
133 if (!$('dragIcon')) this.addDragIcon();
134
135 $('dragIcon').innerHTML = $('dragIconID_'+elementID).innerHTML
136 + $('dragTitleID_'+elementID).firstChild.innerHTML;
137
138 this.dragIconCSS = new GL_getObjCss('dragIcon');
139 this.dragIconCSS.whiteSpace = 'nowrap';
140 document.onmouseup = function(event) { DragDrop.cancelDragEvent(event); };
141 document.onmousemove = function(event) { DragDrop.mouseMoveEvent(event); };
142 return false;
143 },
144
145 dropElement: function(event) {
146 var dropID = this.getIdFromEvent(event);
147 if ((this.dragID) && (this.dragID != dropID)) {
148 var url = this.changeURL
149 + '?dragDrop=' + this.table
150 + '&srcId=' + this.dragID
151 + '&dstId=' + dropID;
152 + '&backPath=' + this.backPath;
153 showClickmenu_raw(url);
154 }
155 this.cancelDragEvent();
156 return false;
157 },
158
159
160 cancelDragEvent: function(event) {
161 this.dragID = null;
162 if (this.dragIconCSS && this.dragIconCSS.visibility) { this.dragIconCSS.visibility = 'hidden'; }
163 document.onmouseup = null;
164 document.onmousemove = null;
165 },
166
167 mouseMoveEvent: function(event) {
168 this.dragIconCSS.left = (GLV_x + 5) + 'px';
169 this.dragIconCSS.top = (GLV_y - 5) + 'px';
170 this.dragIconCSS.visibility = 'visible';
171 return false;
172 },
173
174
175 // -- helper functions --
176 getIdFromEvent: function(event) {
177 var obj = Event.element(event);
178 while (obj.id == false && obj.parentNode) { obj = obj.parentNode; }
179 return obj.id.substring(obj.id.indexOf('_')+1);
180 },
181
182 // dynamically manipulates the DOM to add the div needed for drag&drop at the bottom of the <body>-tag
183 addDragIcon: function() {
184 var code = '<div id="dragIcon" style="visibility: hidden;">&nbsp;</div>';
185 new Insertion.Bottom(document.getElementsByTagName('body')[0], code);
186 }
187 }