Chris@0
|
1 /* redMine - project management software
|
Chris@0
|
2 Copyright (C) 2006-2008 Jean-Philippe Lang */
|
Chris@0
|
3
|
Chris@0
|
4 function checkAll (id, checked) {
|
Chris@0
|
5 var els = Element.descendants(id);
|
Chris@0
|
6 for (var i = 0; i < els.length; i++) {
|
Chris@0
|
7 if (els[i].disabled==false) {
|
Chris@0
|
8 els[i].checked = checked;
|
Chris@0
|
9 }
|
Chris@0
|
10 }
|
Chris@0
|
11 }
|
Chris@0
|
12
|
Chris@0
|
13 function toggleCheckboxesBySelector(selector) {
|
Chris@0
|
14 boxes = $$(selector);
|
Chris@0
|
15 var all_checked = true;
|
Chris@0
|
16 for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } }
|
Chris@0
|
17 for (i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }
|
Chris@0
|
18 }
|
Chris@0
|
19
|
chris@37
|
20 function setCheckboxesBySelector(checked, selector) {
|
chris@37
|
21 var boxes = $$(selector);
|
chris@37
|
22 boxes.each(function(ele) {
|
chris@37
|
23 ele.checked = checked;
|
chris@37
|
24 });
|
chris@37
|
25 }
|
chris@37
|
26
|
Chris@0
|
27 function showAndScrollTo(id, focus) {
|
Chris@0
|
28 Element.show(id);
|
Chris@0
|
29 if (focus!=null) { Form.Element.focus(focus); }
|
Chris@0
|
30 Element.scrollTo(id);
|
Chris@0
|
31 }
|
Chris@0
|
32
|
Chris@0
|
33 function toggleRowGroup(el) {
|
Chris@0
|
34 var tr = Element.up(el, 'tr');
|
Chris@0
|
35 var n = Element.next(tr);
|
Chris@0
|
36 tr.toggleClassName('open');
|
Chris@0
|
37 while (n != undefined && !n.hasClassName('group')) {
|
Chris@0
|
38 Element.toggle(n);
|
Chris@0
|
39 n = Element.next(n);
|
Chris@0
|
40 }
|
Chris@0
|
41 }
|
Chris@0
|
42
|
Chris@441
|
43 function collapseAllRowGroups(el) {
|
Chris@441
|
44 var tbody = Element.up(el, 'tbody');
|
Chris@441
|
45 tbody.childElements('tr').each(function(tr) {
|
Chris@441
|
46 if (tr.hasClassName('group')) {
|
Chris@441
|
47 tr.removeClassName('open');
|
Chris@441
|
48 } else {
|
Chris@441
|
49 tr.hide();
|
Chris@441
|
50 }
|
Chris@441
|
51 })
|
Chris@441
|
52 }
|
Chris@441
|
53
|
Chris@441
|
54 function expandAllRowGroups(el) {
|
Chris@441
|
55 var tbody = Element.up(el, 'tbody');
|
Chris@441
|
56 tbody.childElements('tr').each(function(tr) {
|
Chris@441
|
57 if (tr.hasClassName('group')) {
|
Chris@441
|
58 tr.addClassName('open');
|
Chris@441
|
59 } else {
|
Chris@441
|
60 tr.show();
|
Chris@441
|
61 }
|
Chris@441
|
62 })
|
Chris@441
|
63 }
|
Chris@441
|
64
|
Chris@441
|
65 function toggleAllRowGroups(el) {
|
Chris@441
|
66 var tr = Element.up(el, 'tr');
|
Chris@441
|
67 if (tr.hasClassName('open')) {
|
Chris@441
|
68 collapseAllRowGroups(el);
|
Chris@441
|
69 } else {
|
Chris@441
|
70 expandAllRowGroups(el);
|
Chris@441
|
71 }
|
Chris@441
|
72 }
|
Chris@441
|
73
|
Chris@0
|
74 function toggleFieldset(el) {
|
Chris@0
|
75 var fieldset = Element.up(el, 'fieldset');
|
Chris@0
|
76 fieldset.toggleClassName('collapsed');
|
Chris@0
|
77 Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2});
|
Chris@0
|
78 }
|
Chris@0
|
79
|
Chris@245
|
80 function hideFieldset(el) {
|
Chris@245
|
81 var fieldset = Element.up(el, 'fieldset');
|
Chris@245
|
82 fieldset.toggleClassName('collapsed');
|
Chris@245
|
83 fieldset.down('div').hide();
|
Chris@245
|
84 }
|
Chris@245
|
85
|
Chris@0
|
86 var fileFieldCount = 1;
|
Chris@0
|
87
|
Chris@0
|
88 function addFileField() {
|
Chris@0
|
89 if (fileFieldCount >= 10) return false
|
Chris@0
|
90 fileFieldCount++;
|
Chris@0
|
91 var f = document.createElement("input");
|
Chris@0
|
92 f.type = "file";
|
Chris@0
|
93 f.name = "attachments[" + fileFieldCount + "][file]";
|
Chris@0
|
94 f.size = 30;
|
Chris@0
|
95 var d = document.createElement("input");
|
Chris@0
|
96 d.type = "text";
|
Chris@0
|
97 d.name = "attachments[" + fileFieldCount + "][description]";
|
Chris@0
|
98 d.size = 60;
|
Chris@1
|
99 var dLabel = new Element('label');
|
Chris@0
|
100 dLabel.addClassName('inline');
|
Chris@0
|
101 // Pulls the languge value used for Optional Description
|
Chris@0
|
102 dLabel.update($('attachment_description_label_content').innerHTML)
|
Chris@0
|
103 p = document.getElementById("attachments_fields");
|
Chris@0
|
104 p.appendChild(document.createElement("br"));
|
Chris@0
|
105 p.appendChild(f);
|
Chris@0
|
106 p.appendChild(dLabel);
|
Chris@0
|
107 dLabel.appendChild(d);
|
Chris@0
|
108
|
Chris@0
|
109 }
|
Chris@0
|
110
|
Chris@0
|
111 function showTab(name) {
|
Chris@0
|
112 var f = $$('div#content .tab-content');
|
Chris@0
|
113 for(var i=0; i<f.length; i++){
|
Chris@0
|
114 Element.hide(f[i]);
|
Chris@0
|
115 }
|
Chris@0
|
116 var f = $$('div.tabs a');
|
Chris@0
|
117 for(var i=0; i<f.length; i++){
|
Chris@0
|
118 Element.removeClassName(f[i], "selected");
|
Chris@0
|
119 }
|
Chris@0
|
120 Element.show('tab-content-' + name);
|
Chris@0
|
121 Element.addClassName('tab-' + name, "selected");
|
Chris@0
|
122 return false;
|
Chris@0
|
123 }
|
Chris@0
|
124
|
Chris@0
|
125 function moveTabRight(el) {
|
Chris@0
|
126 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
|
Chris@0
|
127 var tabsWidth = 0;
|
Chris@0
|
128 var i;
|
Chris@0
|
129 for (i=0; i<lis.length; i++) {
|
Chris@0
|
130 if (lis[i].visible()) {
|
Chris@0
|
131 tabsWidth += lis[i].getWidth() + 6;
|
Chris@0
|
132 }
|
Chris@0
|
133 }
|
Chris@0
|
134 if (tabsWidth < Element.up(el, 'div.tabs').getWidth() - 60) {
|
Chris@0
|
135 return;
|
Chris@0
|
136 }
|
Chris@0
|
137 i=0;
|
Chris@0
|
138 while (i<lis.length && !lis[i].visible()) {
|
Chris@0
|
139 i++;
|
Chris@0
|
140 }
|
Chris@0
|
141 lis[i].hide();
|
Chris@0
|
142 }
|
Chris@0
|
143
|
Chris@0
|
144 function moveTabLeft(el) {
|
Chris@0
|
145 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
|
Chris@0
|
146 var i = 0;
|
Chris@0
|
147 while (i<lis.length && !lis[i].visible()) {
|
Chris@0
|
148 i++;
|
Chris@0
|
149 }
|
Chris@0
|
150 if (i>0) {
|
Chris@0
|
151 lis[i-1].show();
|
Chris@0
|
152 }
|
Chris@0
|
153 }
|
Chris@0
|
154
|
Chris@0
|
155 function displayTabsButtons() {
|
Chris@0
|
156 var lis;
|
Chris@0
|
157 var tabsWidth = 0;
|
Chris@0
|
158 var i;
|
Chris@0
|
159 $$('div.tabs').each(function(el) {
|
Chris@0
|
160 lis = el.down('ul').childElements();
|
Chris@0
|
161 for (i=0; i<lis.length; i++) {
|
Chris@0
|
162 if (lis[i].visible()) {
|
Chris@0
|
163 tabsWidth += lis[i].getWidth() + 6;
|
Chris@0
|
164 }
|
Chris@0
|
165 }
|
Chris@0
|
166 if ((tabsWidth < el.getWidth() - 60) && (lis[0].visible())) {
|
Chris@0
|
167 el.down('div.tabs-buttons').hide();
|
Chris@0
|
168 } else {
|
Chris@0
|
169 el.down('div.tabs-buttons').show();
|
Chris@0
|
170 }
|
Chris@0
|
171 });
|
Chris@0
|
172 }
|
Chris@0
|
173
|
Chris@0
|
174 function setPredecessorFieldsVisibility() {
|
Chris@0
|
175 relationType = $('relation_relation_type');
|
Chris@0
|
176 if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) {
|
Chris@0
|
177 Element.show('predecessor_fields');
|
Chris@0
|
178 } else {
|
Chris@0
|
179 Element.hide('predecessor_fields');
|
Chris@0
|
180 }
|
Chris@0
|
181 }
|
Chris@0
|
182
|
Chris@0
|
183 function promptToRemote(text, param, url) {
|
Chris@0
|
184 value = prompt(text + ':');
|
Chris@0
|
185 if (value) {
|
Chris@0
|
186 new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
|
Chris@0
|
187 return false;
|
Chris@0
|
188 }
|
Chris@0
|
189 }
|
Chris@0
|
190
|
Chris@0
|
191 function collapseScmEntry(id) {
|
Chris@0
|
192 var els = document.getElementsByClassName(id, 'browser');
|
Chris@0
|
193 for (var i = 0; i < els.length; i++) {
|
Chris@0
|
194 if (els[i].hasClassName('open')) {
|
Chris@0
|
195 collapseScmEntry(els[i].id);
|
Chris@0
|
196 }
|
Chris@0
|
197 Element.hide(els[i]);
|
Chris@0
|
198 }
|
Chris@0
|
199 $(id).removeClassName('open');
|
Chris@0
|
200 }
|
Chris@0
|
201
|
Chris@0
|
202 function expandScmEntry(id) {
|
Chris@0
|
203 var els = document.getElementsByClassName(id, 'browser');
|
Chris@0
|
204 for (var i = 0; i < els.length; i++) {
|
Chris@0
|
205 Element.show(els[i]);
|
Chris@0
|
206 if (els[i].hasClassName('loaded') && !els[i].hasClassName('collapsed')) {
|
Chris@0
|
207 expandScmEntry(els[i].id);
|
Chris@0
|
208 }
|
Chris@0
|
209 }
|
Chris@0
|
210 $(id).addClassName('open');
|
Chris@0
|
211 }
|
Chris@0
|
212
|
Chris@0
|
213 function scmEntryClick(id) {
|
Chris@0
|
214 el = $(id);
|
Chris@0
|
215 if (el.hasClassName('open')) {
|
Chris@0
|
216 collapseScmEntry(id);
|
Chris@0
|
217 el.addClassName('collapsed');
|
Chris@0
|
218 return false;
|
Chris@0
|
219 } else if (el.hasClassName('loaded')) {
|
Chris@0
|
220 expandScmEntry(id);
|
Chris@0
|
221 el.removeClassName('collapsed');
|
Chris@0
|
222 return false;
|
Chris@0
|
223 }
|
Chris@0
|
224 if (el.hasClassName('loading')) {
|
Chris@0
|
225 return false;
|
Chris@0
|
226 }
|
Chris@0
|
227 el.addClassName('loading');
|
Chris@0
|
228 return true;
|
Chris@0
|
229 }
|
Chris@0
|
230
|
Chris@0
|
231 function scmEntryLoaded(id) {
|
Chris@0
|
232 Element.addClassName(id, 'open');
|
Chris@0
|
233 Element.addClassName(id, 'loaded');
|
Chris@0
|
234 Element.removeClassName(id, 'loading');
|
Chris@0
|
235 }
|
Chris@0
|
236
|
Chris@0
|
237 function randomKey(size) {
|
Chris@0
|
238 var chars = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z');
|
Chris@0
|
239 var key = '';
|
Chris@0
|
240 for (i = 0; i < size; i++) {
|
Chris@0
|
241 key += chars[Math.floor(Math.random() * chars.length)];
|
Chris@0
|
242 }
|
Chris@0
|
243 return key;
|
Chris@0
|
244 }
|
Chris@0
|
245
|
Chris@0
|
246 function observeParentIssueField(url) {
|
Chris@0
|
247 new Ajax.Autocompleter('issue_parent_issue_id',
|
Chris@0
|
248 'parent_issue_candidates',
|
Chris@0
|
249 url,
|
Chris@0
|
250 { minChars: 3,
|
Chris@0
|
251 frequency: 0.5,
|
Chris@0
|
252 paramName: 'q',
|
Chris@0
|
253 updateElement: function(value) {
|
Chris@0
|
254 document.getElementById('issue_parent_issue_id').value = value.id;
|
Chris@0
|
255 }});
|
Chris@0
|
256 }
|
Chris@0
|
257
|
Chris@117
|
258 function observeRelatedIssueField(url) {
|
Chris@117
|
259 new Ajax.Autocompleter('relation_issue_to_id',
|
Chris@117
|
260 'related_issue_candidates',
|
Chris@117
|
261 url,
|
Chris@117
|
262 { minChars: 3,
|
Chris@117
|
263 frequency: 0.5,
|
Chris@117
|
264 paramName: 'q',
|
Chris@117
|
265 updateElement: function(value) {
|
Chris@117
|
266 document.getElementById('relation_issue_to_id').value = value.id;
|
Chris@117
|
267 },
|
Chris@117
|
268 parameters: 'scope=all'
|
Chris@117
|
269 });
|
Chris@117
|
270 }
|
Chris@117
|
271
|
Chris@117
|
272 function setVisible(id, visible) {
|
Chris@117
|
273 var el = $(id);
|
Chris@117
|
274 if (el) {if (visible) {el.show();} else {el.hide();}}
|
Chris@117
|
275 }
|
Chris@117
|
276
|
Chris@117
|
277 function observeProjectModules() {
|
Chris@117
|
278 var f = function() {
|
Chris@117
|
279 /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
|
Chris@117
|
280 var c = ($('project_enabled_module_names_issue_tracking').checked == true);
|
Chris@117
|
281 setVisible('project_trackers', c);
|
Chris@117
|
282 setVisible('project_issue_custom_fields', c);
|
Chris@117
|
283 };
|
Chris@117
|
284
|
Chris@117
|
285 Event.observe(window, 'load', f);
|
Chris@117
|
286 Event.observe('project_enabled_module_names_issue_tracking', 'change', f);
|
Chris@117
|
287 }
|
Chris@117
|
288
|
Chris@245
|
289 /*
|
Chris@245
|
290 * Class used to warn user when leaving a page with unsaved textarea
|
Chris@245
|
291 * Author: mathias.fischer@berlinonline.de
|
Chris@245
|
292 */
|
Chris@245
|
293
|
Chris@245
|
294 var WarnLeavingUnsaved = Class.create({
|
Chris@245
|
295 observedForms: false,
|
Chris@245
|
296 observedElements: false,
|
Chris@245
|
297 changedForms: false,
|
Chris@245
|
298 message: null,
|
Chris@245
|
299
|
Chris@245
|
300 initialize: function(message){
|
Chris@245
|
301 this.observedForms = $$('form');
|
Chris@245
|
302 this.observedElements = $$('textarea');
|
Chris@245
|
303 this.message = message;
|
Chris@245
|
304
|
Chris@245
|
305 this.observedElements.each(this.observeChange.bind(this));
|
Chris@245
|
306 this.observedForms.each(this.submitAction.bind(this));
|
Chris@245
|
307
|
Chris@245
|
308 window.onbeforeunload = this.unload.bind(this);
|
Chris@245
|
309 },
|
Chris@245
|
310
|
Chris@245
|
311 unload: function(){
|
Chris@507
|
312 this.observedElements.each(function(el) {el.blur();})
|
Chris@245
|
313 if(this.changedForms)
|
Chris@245
|
314 return this.message;
|
Chris@245
|
315 },
|
Chris@245
|
316
|
Chris@245
|
317 setChanged: function(){
|
Chris@245
|
318 this.changedForms = true;
|
Chris@245
|
319 },
|
Chris@245
|
320
|
Chris@245
|
321 setUnchanged: function(){
|
Chris@245
|
322 this.changedForms = false;
|
Chris@245
|
323 },
|
Chris@245
|
324
|
Chris@245
|
325 observeChange: function(element){
|
Chris@245
|
326 element.observe('change',this.setChanged.bindAsEventListener(this));
|
Chris@245
|
327 },
|
Chris@245
|
328
|
Chris@245
|
329 submitAction: function(element){
|
Chris@245
|
330 element.observe('submit',this.setUnchanged.bindAsEventListener(this));
|
Chris@245
|
331 }
|
Chris@245
|
332 });
|
Chris@117
|
333
|
Chris@441
|
334 /*
|
Chris@441
|
335 * 1 - registers a callback which copies the csrf token into the
|
Chris@441
|
336 * X-CSRF-Token header with each ajax request. Necessary to
|
Chris@441
|
337 * work with rails applications which have fixed
|
Chris@441
|
338 * CVE-2011-0447
|
Chris@441
|
339 * 2 - shows and hides ajax indicator
|
Chris@441
|
340 */
|
Chris@0
|
341 Ajax.Responders.register({
|
Chris@441
|
342 onCreate: function(request){
|
Chris@441
|
343 var csrf_meta_tag = $$('meta[name=csrf-token]')[0];
|
Chris@441
|
344
|
Chris@441
|
345 if (csrf_meta_tag) {
|
Chris@441
|
346 var header = 'X-CSRF-Token',
|
Chris@441
|
347 token = csrf_meta_tag.readAttribute('content');
|
Chris@441
|
348
|
Chris@441
|
349 if (!request.options.requestHeaders) {
|
Chris@441
|
350 request.options.requestHeaders = {};
|
Chris@441
|
351 }
|
Chris@441
|
352 request.options.requestHeaders[header] = token;
|
Chris@441
|
353 }
|
Chris@441
|
354
|
Chris@0
|
355 if ($('ajax-indicator') && Ajax.activeRequestCount > 0) {
|
Chris@0
|
356 Element.show('ajax-indicator');
|
Chris@0
|
357 }
|
Chris@0
|
358 },
|
Chris@0
|
359 onComplete: function(){
|
Chris@0
|
360 if ($('ajax-indicator') && Ajax.activeRequestCount == 0) {
|
Chris@0
|
361 Element.hide('ajax-indicator');
|
Chris@0
|
362 }
|
Chris@0
|
363 }
|
Chris@0
|
364 });
|
Chris@0
|
365
|
Chris@0
|
366 function hideOnLoad() {
|
Chris@0
|
367 $$('.hol').each(function(el) {
|
Chris@0
|
368 el.hide();
|
Chris@0
|
369 });
|
Chris@0
|
370 }
|
Chris@0
|
371
|
Chris@0
|
372 Event.observe(window, 'load', hideOnLoad);
|
luisf@160
|
373
|
luisf@160
|
374
|
luisf@160
|
375
|
luisf@160
|
376
|