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