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@909
|
89 var fields = $('attachments_fields');
|
Chris@909
|
90 if (fields.childElements().length >= 10) return false;
|
Chris@909
|
91 fileFieldCount++;
|
Chris@909
|
92 var s = new Element('span');
|
Chris@909
|
93 s.update(fields.down('span').innerHTML);
|
Chris@909
|
94 s.down('input.file').name = "attachments[" + fileFieldCount + "][file]";
|
Chris@909
|
95 s.down('input.description').name = "attachments[" + fileFieldCount + "][description]";
|
Chris@909
|
96 fields.appendChild(s);
|
Chris@909
|
97 }
|
Chris@0
|
98
|
Chris@909
|
99 function removeFileField(el) {
|
Chris@909
|
100 var fields = $('attachments_fields');
|
Chris@909
|
101 var s = Element.up(el, 'span');
|
Chris@909
|
102 if (fields.childElements().length > 1) {
|
Chris@909
|
103 s.remove();
|
Chris@909
|
104 } else {
|
Chris@909
|
105 s.update(s.innerHTML);
|
Chris@909
|
106 }
|
Chris@909
|
107 }
|
Chris@909
|
108
|
Chris@909
|
109 function checkFileSize(el, maxSize, message) {
|
Chris@909
|
110 var files = el.files;
|
Chris@909
|
111 if (files) {
|
Chris@909
|
112 for (var i=0; i<files.length; i++) {
|
Chris@909
|
113 if (files[i].size > maxSize) {
|
Chris@909
|
114 alert(message);
|
Chris@909
|
115 el.value = "";
|
Chris@909
|
116 }
|
Chris@909
|
117 }
|
Chris@909
|
118 }
|
Chris@0
|
119 }
|
Chris@0
|
120
|
Chris@0
|
121 function showTab(name) {
|
Chris@0
|
122 var f = $$('div#content .tab-content');
|
Chris@0
|
123 for(var i=0; i<f.length; i++){
|
Chris@0
|
124 Element.hide(f[i]);
|
Chris@0
|
125 }
|
Chris@0
|
126 var f = $$('div.tabs a');
|
Chris@0
|
127 for(var i=0; i<f.length; i++){
|
Chris@0
|
128 Element.removeClassName(f[i], "selected");
|
Chris@0
|
129 }
|
Chris@0
|
130 Element.show('tab-content-' + name);
|
Chris@0
|
131 Element.addClassName('tab-' + name, "selected");
|
Chris@0
|
132 return false;
|
Chris@0
|
133 }
|
Chris@0
|
134
|
Chris@0
|
135 function moveTabRight(el) {
|
Chris@0
|
136 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
|
Chris@0
|
137 var tabsWidth = 0;
|
Chris@0
|
138 var i;
|
Chris@0
|
139 for (i=0; i<lis.length; i++) {
|
Chris@0
|
140 if (lis[i].visible()) {
|
Chris@0
|
141 tabsWidth += lis[i].getWidth() + 6;
|
Chris@0
|
142 }
|
Chris@0
|
143 }
|
Chris@0
|
144 if (tabsWidth < Element.up(el, 'div.tabs').getWidth() - 60) {
|
Chris@0
|
145 return;
|
Chris@0
|
146 }
|
Chris@0
|
147 i=0;
|
Chris@0
|
148 while (i<lis.length && !lis[i].visible()) {
|
Chris@0
|
149 i++;
|
Chris@0
|
150 }
|
Chris@0
|
151 lis[i].hide();
|
Chris@0
|
152 }
|
Chris@0
|
153
|
Chris@0
|
154 function moveTabLeft(el) {
|
Chris@0
|
155 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
|
Chris@0
|
156 var i = 0;
|
Chris@0
|
157 while (i<lis.length && !lis[i].visible()) {
|
Chris@0
|
158 i++;
|
Chris@0
|
159 }
|
Chris@0
|
160 if (i>0) {
|
Chris@0
|
161 lis[i-1].show();
|
Chris@0
|
162 }
|
Chris@0
|
163 }
|
Chris@0
|
164
|
Chris@0
|
165 function displayTabsButtons() {
|
Chris@0
|
166 var lis;
|
Chris@0
|
167 var tabsWidth = 0;
|
Chris@0
|
168 var i;
|
Chris@0
|
169 $$('div.tabs').each(function(el) {
|
Chris@0
|
170 lis = el.down('ul').childElements();
|
Chris@0
|
171 for (i=0; i<lis.length; i++) {
|
Chris@0
|
172 if (lis[i].visible()) {
|
Chris@0
|
173 tabsWidth += lis[i].getWidth() + 6;
|
Chris@0
|
174 }
|
Chris@0
|
175 }
|
Chris@0
|
176 if ((tabsWidth < el.getWidth() - 60) && (lis[0].visible())) {
|
Chris@0
|
177 el.down('div.tabs-buttons').hide();
|
Chris@0
|
178 } else {
|
Chris@0
|
179 el.down('div.tabs-buttons').show();
|
Chris@0
|
180 }
|
Chris@0
|
181 });
|
Chris@0
|
182 }
|
Chris@0
|
183
|
Chris@0
|
184 function setPredecessorFieldsVisibility() {
|
Chris@0
|
185 relationType = $('relation_relation_type');
|
Chris@0
|
186 if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) {
|
Chris@0
|
187 Element.show('predecessor_fields');
|
Chris@0
|
188 } else {
|
Chris@0
|
189 Element.hide('predecessor_fields');
|
Chris@0
|
190 }
|
Chris@0
|
191 }
|
Chris@0
|
192
|
Chris@0
|
193 function promptToRemote(text, param, url) {
|
Chris@0
|
194 value = prompt(text + ':');
|
Chris@0
|
195 if (value) {
|
Chris@0
|
196 new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
|
Chris@0
|
197 return false;
|
Chris@0
|
198 }
|
Chris@0
|
199 }
|
Chris@0
|
200
|
Chris@909
|
201 function showModal(id, width) {
|
Chris@909
|
202 el = $(id);
|
Chris@909
|
203 if (el == undefined || el.visible()) {return;}
|
Chris@909
|
204 var h = $$('body')[0].getHeight();
|
Chris@909
|
205 var d = document.createElement("div");
|
Chris@909
|
206 d.id = 'modalbg';
|
Chris@909
|
207 $('main').appendChild(d);
|
Chris@909
|
208 $('modalbg').setStyle({ width: '100%', height: h + 'px' });
|
Chris@909
|
209 $('modalbg').show();
|
Chris@909
|
210
|
Chris@909
|
211 var pageWidth = document.viewport.getWidth();
|
Chris@909
|
212 el.setStyle({'width': width});
|
Chris@909
|
213 el.setStyle({'left': (((pageWidth - el.getWidth())/2 *100) / pageWidth) + '%'});
|
Chris@909
|
214 el.addClassName('modal');
|
Chris@909
|
215 el.show();
|
Chris@909
|
216
|
Chris@909
|
217 var submit = el.down("input[type=submit]");
|
Chris@909
|
218 if (submit) {
|
Chris@909
|
219 submit.focus();
|
Chris@909
|
220 }
|
Chris@909
|
221 }
|
Chris@909
|
222
|
Chris@909
|
223 function hideModal(el) {
|
Chris@909
|
224 var modal = Element.up(el, 'div.modal');
|
Chris@909
|
225 if (modal) {
|
Chris@909
|
226 modal.hide();
|
Chris@909
|
227 }
|
Chris@909
|
228 var bg = $('modalbg');
|
Chris@909
|
229 if (bg) {
|
Chris@909
|
230 bg.remove();
|
Chris@909
|
231 }
|
Chris@909
|
232 }
|
Chris@909
|
233
|
Chris@0
|
234 function collapseScmEntry(id) {
|
Chris@0
|
235 var els = document.getElementsByClassName(id, 'browser');
|
Chris@0
|
236 for (var i = 0; i < els.length; i++) {
|
Chris@0
|
237 if (els[i].hasClassName('open')) {
|
Chris@0
|
238 collapseScmEntry(els[i].id);
|
Chris@0
|
239 }
|
Chris@0
|
240 Element.hide(els[i]);
|
Chris@0
|
241 }
|
Chris@0
|
242 $(id).removeClassName('open');
|
Chris@0
|
243 }
|
Chris@0
|
244
|
Chris@0
|
245 function expandScmEntry(id) {
|
Chris@0
|
246 var els = document.getElementsByClassName(id, 'browser');
|
Chris@0
|
247 for (var i = 0; i < els.length; i++) {
|
Chris@0
|
248 Element.show(els[i]);
|
Chris@0
|
249 if (els[i].hasClassName('loaded') && !els[i].hasClassName('collapsed')) {
|
Chris@0
|
250 expandScmEntry(els[i].id);
|
Chris@0
|
251 }
|
Chris@0
|
252 }
|
Chris@0
|
253 $(id).addClassName('open');
|
Chris@0
|
254 }
|
Chris@0
|
255
|
Chris@0
|
256 function scmEntryClick(id) {
|
Chris@0
|
257 el = $(id);
|
Chris@0
|
258 if (el.hasClassName('open')) {
|
Chris@0
|
259 collapseScmEntry(id);
|
Chris@0
|
260 el.addClassName('collapsed');
|
Chris@0
|
261 return false;
|
Chris@0
|
262 } else if (el.hasClassName('loaded')) {
|
Chris@0
|
263 expandScmEntry(id);
|
Chris@0
|
264 el.removeClassName('collapsed');
|
Chris@0
|
265 return false;
|
Chris@0
|
266 }
|
Chris@0
|
267 if (el.hasClassName('loading')) {
|
Chris@0
|
268 return false;
|
Chris@0
|
269 }
|
Chris@0
|
270 el.addClassName('loading');
|
Chris@0
|
271 return true;
|
Chris@0
|
272 }
|
Chris@0
|
273
|
Chris@0
|
274 function scmEntryLoaded(id) {
|
Chris@0
|
275 Element.addClassName(id, 'open');
|
Chris@0
|
276 Element.addClassName(id, 'loaded');
|
Chris@0
|
277 Element.removeClassName(id, 'loading');
|
Chris@0
|
278 }
|
Chris@0
|
279
|
Chris@0
|
280 function randomKey(size) {
|
Chris@0
|
281 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
|
282 var key = '';
|
Chris@0
|
283 for (i = 0; i < size; i++) {
|
Chris@0
|
284 key += chars[Math.floor(Math.random() * chars.length)];
|
Chris@0
|
285 }
|
Chris@0
|
286 return key;
|
Chris@0
|
287 }
|
Chris@0
|
288
|
Chris@0
|
289 function observeParentIssueField(url) {
|
Chris@0
|
290 new Ajax.Autocompleter('issue_parent_issue_id',
|
Chris@0
|
291 'parent_issue_candidates',
|
Chris@0
|
292 url,
|
Chris@0
|
293 { minChars: 3,
|
Chris@0
|
294 frequency: 0.5,
|
Chris@0
|
295 paramName: 'q',
|
Chris@909
|
296 method: 'get',
|
Chris@0
|
297 updateElement: function(value) {
|
Chris@0
|
298 document.getElementById('issue_parent_issue_id').value = value.id;
|
Chris@0
|
299 }});
|
Chris@0
|
300 }
|
Chris@0
|
301
|
Chris@117
|
302 function observeRelatedIssueField(url) {
|
Chris@117
|
303 new Ajax.Autocompleter('relation_issue_to_id',
|
Chris@117
|
304 'related_issue_candidates',
|
Chris@117
|
305 url,
|
Chris@117
|
306 { minChars: 3,
|
Chris@117
|
307 frequency: 0.5,
|
Chris@117
|
308 paramName: 'q',
|
Chris@909
|
309 method: 'get',
|
Chris@117
|
310 updateElement: function(value) {
|
Chris@117
|
311 document.getElementById('relation_issue_to_id').value = value.id;
|
Chris@117
|
312 },
|
Chris@117
|
313 parameters: 'scope=all'
|
Chris@117
|
314 });
|
Chris@117
|
315 }
|
Chris@117
|
316
|
Chris@117
|
317 function setVisible(id, visible) {
|
Chris@117
|
318 var el = $(id);
|
Chris@117
|
319 if (el) {if (visible) {el.show();} else {el.hide();}}
|
Chris@117
|
320 }
|
Chris@117
|
321
|
Chris@117
|
322 function observeProjectModules() {
|
Chris@117
|
323 var f = function() {
|
Chris@117
|
324 /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
|
Chris@117
|
325 var c = ($('project_enabled_module_names_issue_tracking').checked == true);
|
Chris@117
|
326 setVisible('project_trackers', c);
|
Chris@117
|
327 setVisible('project_issue_custom_fields', c);
|
Chris@117
|
328 };
|
Chris@117
|
329
|
Chris@117
|
330 Event.observe(window, 'load', f);
|
Chris@117
|
331 Event.observe('project_enabled_module_names_issue_tracking', 'change', f);
|
Chris@117
|
332 }
|
Chris@117
|
333
|
Chris@245
|
334 /*
|
Chris@245
|
335 * Class used to warn user when leaving a page with unsaved textarea
|
Chris@245
|
336 * Author: mathias.fischer@berlinonline.de
|
Chris@245
|
337 */
|
Chris@245
|
338
|
Chris@245
|
339 var WarnLeavingUnsaved = Class.create({
|
Chris@245
|
340 observedForms: false,
|
Chris@245
|
341 observedElements: false,
|
Chris@245
|
342 changedForms: false,
|
Chris@245
|
343 message: null,
|
Chris@245
|
344
|
Chris@245
|
345 initialize: function(message){
|
Chris@245
|
346 this.observedForms = $$('form');
|
Chris@245
|
347 this.observedElements = $$('textarea');
|
Chris@245
|
348 this.message = message;
|
Chris@245
|
349
|
Chris@245
|
350 this.observedElements.each(this.observeChange.bind(this));
|
Chris@245
|
351 this.observedForms.each(this.submitAction.bind(this));
|
Chris@245
|
352
|
Chris@245
|
353 window.onbeforeunload = this.unload.bind(this);
|
Chris@245
|
354 },
|
Chris@245
|
355
|
Chris@245
|
356 unload: function(){
|
Chris@507
|
357 this.observedElements.each(function(el) {el.blur();})
|
Chris@245
|
358 if(this.changedForms)
|
Chris@245
|
359 return this.message;
|
Chris@245
|
360 },
|
Chris@245
|
361
|
Chris@245
|
362 setChanged: function(){
|
Chris@245
|
363 this.changedForms = true;
|
Chris@245
|
364 },
|
Chris@245
|
365
|
Chris@245
|
366 setUnchanged: function(){
|
Chris@245
|
367 this.changedForms = false;
|
Chris@245
|
368 },
|
Chris@245
|
369
|
Chris@245
|
370 observeChange: function(element){
|
Chris@245
|
371 element.observe('change',this.setChanged.bindAsEventListener(this));
|
Chris@245
|
372 },
|
Chris@245
|
373
|
Chris@245
|
374 submitAction: function(element){
|
Chris@245
|
375 element.observe('submit',this.setUnchanged.bindAsEventListener(this));
|
Chris@245
|
376 }
|
Chris@245
|
377 });
|
Chris@117
|
378
|
Chris@441
|
379 /*
|
Chris@441
|
380 * 1 - registers a callback which copies the csrf token into the
|
Chris@441
|
381 * X-CSRF-Token header with each ajax request. Necessary to
|
Chris@441
|
382 * work with rails applications which have fixed
|
Chris@441
|
383 * CVE-2011-0447
|
Chris@441
|
384 * 2 - shows and hides ajax indicator
|
Chris@441
|
385 */
|
Chris@0
|
386 Ajax.Responders.register({
|
Chris@441
|
387 onCreate: function(request){
|
Chris@441
|
388 var csrf_meta_tag = $$('meta[name=csrf-token]')[0];
|
Chris@441
|
389
|
Chris@441
|
390 if (csrf_meta_tag) {
|
Chris@441
|
391 var header = 'X-CSRF-Token',
|
Chris@441
|
392 token = csrf_meta_tag.readAttribute('content');
|
Chris@441
|
393
|
Chris@441
|
394 if (!request.options.requestHeaders) {
|
Chris@441
|
395 request.options.requestHeaders = {};
|
Chris@441
|
396 }
|
Chris@441
|
397 request.options.requestHeaders[header] = token;
|
Chris@441
|
398 }
|
Chris@441
|
399
|
Chris@0
|
400 if ($('ajax-indicator') && Ajax.activeRequestCount > 0) {
|
Chris@0
|
401 Element.show('ajax-indicator');
|
Chris@0
|
402 }
|
Chris@0
|
403 },
|
Chris@0
|
404 onComplete: function(){
|
Chris@0
|
405 if ($('ajax-indicator') && Ajax.activeRequestCount == 0) {
|
Chris@0
|
406 Element.hide('ajax-indicator');
|
Chris@0
|
407 }
|
Chris@0
|
408 }
|
Chris@0
|
409 });
|
Chris@0
|
410
|
Chris@0
|
411 function hideOnLoad() {
|
Chris@0
|
412 $$('.hol').each(function(el) {
|
Chris@0
|
413 el.hide();
|
Chris@0
|
414 });
|
Chris@0
|
415 }
|
Chris@0
|
416
|
Chris@0
|
417 Event.observe(window, 'load', hideOnLoad);
|
luisf@160
|
418
|
luisf@160
|
419
|
luisf@160
|
420
|
luisf@160
|
421
|