annotate .svn/pristine/2d/2de3a87e3fe026c2ba56948a00c54c7c54909e85.svn-base @ 1519:afce8026aaeb redmine-2.4-integration

Merge from branch "live"
author Chris Cannam
date Tue, 09 Sep 2014 09:34:53 +0100
parents cbb26bc654de
children
rev   line source
Chris@909 1 /* redMine - project management software
Chris@909 2 Copyright (C) 2006-2008 Jean-Philippe Lang */
Chris@909 3
Chris@909 4 function checkAll (id, checked) {
Chris@909 5 var els = Element.descendants(id);
Chris@909 6 for (var i = 0; i < els.length; i++) {
Chris@909 7 if (els[i].disabled==false) {
Chris@909 8 els[i].checked = checked;
Chris@909 9 }
Chris@909 10 }
Chris@909 11 }
Chris@909 12
Chris@909 13 function toggleCheckboxesBySelector(selector) {
Chris@909 14 boxes = $$(selector);
Chris@909 15 var all_checked = true;
Chris@909 16 for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } }
Chris@909 17 for (i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }
Chris@909 18 }
Chris@909 19
Chris@909 20 function setCheckboxesBySelector(checked, selector) {
Chris@909 21 var boxes = $$(selector);
Chris@909 22 boxes.each(function(ele) {
Chris@909 23 ele.checked = checked;
Chris@909 24 });
Chris@909 25 }
Chris@909 26
Chris@909 27 function showAndScrollTo(id, focus) {
Chris@909 28 Element.show(id);
Chris@909 29 if (focus!=null) { Form.Element.focus(focus); }
Chris@909 30 Element.scrollTo(id);
Chris@909 31 }
Chris@909 32
Chris@909 33 function toggleRowGroup(el) {
Chris@909 34 var tr = Element.up(el, 'tr');
Chris@909 35 var n = Element.next(tr);
Chris@909 36 tr.toggleClassName('open');
Chris@909 37 while (n != undefined && !n.hasClassName('group')) {
Chris@909 38 Element.toggle(n);
Chris@909 39 n = Element.next(n);
Chris@909 40 }
Chris@909 41 }
Chris@909 42
Chris@909 43 function collapseAllRowGroups(el) {
Chris@909 44 var tbody = Element.up(el, 'tbody');
Chris@909 45 tbody.childElements('tr').each(function(tr) {
Chris@909 46 if (tr.hasClassName('group')) {
Chris@909 47 tr.removeClassName('open');
Chris@909 48 } else {
Chris@909 49 tr.hide();
Chris@909 50 }
Chris@909 51 })
Chris@909 52 }
Chris@909 53
Chris@909 54 function expandAllRowGroups(el) {
Chris@909 55 var tbody = Element.up(el, 'tbody');
Chris@909 56 tbody.childElements('tr').each(function(tr) {
Chris@909 57 if (tr.hasClassName('group')) {
Chris@909 58 tr.addClassName('open');
Chris@909 59 } else {
Chris@909 60 tr.show();
Chris@909 61 }
Chris@909 62 })
Chris@909 63 }
Chris@909 64
Chris@909 65 function toggleAllRowGroups(el) {
Chris@909 66 var tr = Element.up(el, 'tr');
Chris@909 67 if (tr.hasClassName('open')) {
Chris@909 68 collapseAllRowGroups(el);
Chris@909 69 } else {
Chris@909 70 expandAllRowGroups(el);
Chris@909 71 }
Chris@909 72 }
Chris@909 73
Chris@909 74 function toggleFieldset(el) {
Chris@909 75 var fieldset = Element.up(el, 'fieldset');
Chris@909 76 fieldset.toggleClassName('collapsed');
Chris@909 77 Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2});
Chris@909 78 }
Chris@909 79
Chris@909 80 function hideFieldset(el) {
Chris@909 81 var fieldset = Element.up(el, 'fieldset');
Chris@909 82 fieldset.toggleClassName('collapsed');
Chris@909 83 fieldset.down('div').hide();
Chris@909 84 }
Chris@909 85
Chris@909 86 var fileFieldCount = 1;
Chris@909 87
Chris@909 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@909 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@909 119 }
Chris@909 120
Chris@909 121 function showTab(name) {
Chris@909 122 var f = $$('div#content .tab-content');
Chris@909 123 for(var i=0; i<f.length; i++){
Chris@909 124 Element.hide(f[i]);
Chris@909 125 }
Chris@909 126 var f = $$('div.tabs a');
Chris@909 127 for(var i=0; i<f.length; i++){
Chris@909 128 Element.removeClassName(f[i], "selected");
Chris@909 129 }
Chris@909 130 Element.show('tab-content-' + name);
Chris@909 131 Element.addClassName('tab-' + name, "selected");
Chris@909 132 return false;
Chris@909 133 }
Chris@909 134
Chris@909 135 function moveTabRight(el) {
Chris@909 136 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
Chris@909 137 var tabsWidth = 0;
Chris@909 138 var i;
Chris@909 139 for (i=0; i<lis.length; i++) {
Chris@909 140 if (lis[i].visible()) {
Chris@909 141 tabsWidth += lis[i].getWidth() + 6;
Chris@909 142 }
Chris@909 143 }
Chris@909 144 if (tabsWidth < Element.up(el, 'div.tabs').getWidth() - 60) {
Chris@909 145 return;
Chris@909 146 }
Chris@909 147 i=0;
Chris@909 148 while (i<lis.length && !lis[i].visible()) {
Chris@909 149 i++;
Chris@909 150 }
Chris@909 151 lis[i].hide();
Chris@909 152 }
Chris@909 153
Chris@909 154 function moveTabLeft(el) {
Chris@909 155 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
Chris@909 156 var i = 0;
Chris@909 157 while (i<lis.length && !lis[i].visible()) {
Chris@909 158 i++;
Chris@909 159 }
Chris@909 160 if (i>0) {
Chris@909 161 lis[i-1].show();
Chris@909 162 }
Chris@909 163 }
Chris@909 164
Chris@909 165 function displayTabsButtons() {
Chris@909 166 var lis;
Chris@909 167 var tabsWidth = 0;
Chris@909 168 var i;
Chris@909 169 $$('div.tabs').each(function(el) {
Chris@909 170 lis = el.down('ul').childElements();
Chris@909 171 for (i=0; i<lis.length; i++) {
Chris@909 172 if (lis[i].visible()) {
Chris@909 173 tabsWidth += lis[i].getWidth() + 6;
Chris@909 174 }
Chris@909 175 }
Chris@909 176 if ((tabsWidth < el.getWidth() - 60) && (lis[0].visible())) {
Chris@909 177 el.down('div.tabs-buttons').hide();
Chris@909 178 } else {
Chris@909 179 el.down('div.tabs-buttons').show();
Chris@909 180 }
Chris@909 181 });
Chris@909 182 }
Chris@909 183
Chris@909 184 function setPredecessorFieldsVisibility() {
Chris@909 185 relationType = $('relation_relation_type');
Chris@909 186 if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) {
Chris@909 187 Element.show('predecessor_fields');
Chris@909 188 } else {
Chris@909 189 Element.hide('predecessor_fields');
Chris@909 190 }
Chris@909 191 }
Chris@909 192
Chris@909 193 function promptToRemote(text, param, url) {
Chris@909 194 value = prompt(text + ':');
Chris@909 195 if (value) {
Chris@909 196 new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
Chris@909 197 return false;
Chris@909 198 }
Chris@909 199 }
Chris@909 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@909 234 function collapseScmEntry(id) {
Chris@909 235 var els = document.getElementsByClassName(id, 'browser');
Chris@909 236 for (var i = 0; i < els.length; i++) {
Chris@909 237 if (els[i].hasClassName('open')) {
Chris@909 238 collapseScmEntry(els[i].id);
Chris@909 239 }
Chris@909 240 Element.hide(els[i]);
Chris@909 241 }
Chris@909 242 $(id).removeClassName('open');
Chris@909 243 }
Chris@909 244
Chris@909 245 function expandScmEntry(id) {
Chris@909 246 var els = document.getElementsByClassName(id, 'browser');
Chris@909 247 for (var i = 0; i < els.length; i++) {
Chris@909 248 Element.show(els[i]);
Chris@909 249 if (els[i].hasClassName('loaded') && !els[i].hasClassName('collapsed')) {
Chris@909 250 expandScmEntry(els[i].id);
Chris@909 251 }
Chris@909 252 }
Chris@909 253 $(id).addClassName('open');
Chris@909 254 }
Chris@909 255
Chris@909 256 function scmEntryClick(id) {
Chris@909 257 el = $(id);
Chris@909 258 if (el.hasClassName('open')) {
Chris@909 259 collapseScmEntry(id);
Chris@909 260 el.addClassName('collapsed');
Chris@909 261 return false;
Chris@909 262 } else if (el.hasClassName('loaded')) {
Chris@909 263 expandScmEntry(id);
Chris@909 264 el.removeClassName('collapsed');
Chris@909 265 return false;
Chris@909 266 }
Chris@909 267 if (el.hasClassName('loading')) {
Chris@909 268 return false;
Chris@909 269 }
Chris@909 270 el.addClassName('loading');
Chris@909 271 return true;
Chris@909 272 }
Chris@909 273
Chris@909 274 function scmEntryLoaded(id) {
Chris@909 275 Element.addClassName(id, 'open');
Chris@909 276 Element.addClassName(id, 'loaded');
Chris@909 277 Element.removeClassName(id, 'loading');
Chris@909 278 }
Chris@909 279
Chris@909 280 function randomKey(size) {
Chris@909 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@909 282 var key = '';
Chris@909 283 for (i = 0; i < size; i++) {
Chris@909 284 key += chars[Math.floor(Math.random() * chars.length)];
Chris@909 285 }
Chris@909 286 return key;
Chris@909 287 }
Chris@909 288
Chris@909 289 function observeParentIssueField(url) {
Chris@909 290 new Ajax.Autocompleter('issue_parent_issue_id',
Chris@909 291 'parent_issue_candidates',
Chris@909 292 url,
Chris@909 293 { minChars: 3,
Chris@909 294 frequency: 0.5,
Chris@909 295 paramName: 'q',
Chris@909 296 method: 'get',
Chris@909 297 updateElement: function(value) {
Chris@909 298 document.getElementById('issue_parent_issue_id').value = value.id;
Chris@909 299 }});
Chris@909 300 }
Chris@909 301
Chris@909 302 function observeRelatedIssueField(url) {
Chris@909 303 new Ajax.Autocompleter('relation_issue_to_id',
Chris@909 304 'related_issue_candidates',
Chris@909 305 url,
Chris@909 306 { minChars: 3,
Chris@909 307 frequency: 0.5,
Chris@909 308 paramName: 'q',
Chris@909 309 method: 'get',
Chris@909 310 updateElement: function(value) {
Chris@909 311 document.getElementById('relation_issue_to_id').value = value.id;
Chris@909 312 },
Chris@909 313 parameters: 'scope=all'
Chris@909 314 });
Chris@909 315 }
Chris@909 316
Chris@909 317 function setVisible(id, visible) {
Chris@909 318 var el = $(id);
Chris@909 319 if (el) {if (visible) {el.show();} else {el.hide();}}
Chris@909 320 }
Chris@909 321
Chris@909 322 function observeProjectModules() {
Chris@909 323 var f = function() {
Chris@909 324 /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
Chris@909 325 var c = ($('project_enabled_module_names_issue_tracking').checked == true);
Chris@909 326 setVisible('project_trackers', c);
Chris@909 327 setVisible('project_issue_custom_fields', c);
Chris@909 328 };
Chris@909 329
Chris@909 330 Event.observe(window, 'load', f);
Chris@909 331 Event.observe('project_enabled_module_names_issue_tracking', 'change', f);
Chris@909 332 }
Chris@909 333
Chris@909 334 /*
Chris@909 335 * Class used to warn user when leaving a page with unsaved textarea
Chris@909 336 * Author: mathias.fischer@berlinonline.de
Chris@909 337 */
Chris@909 338
Chris@909 339 var WarnLeavingUnsaved = Class.create({
Chris@909 340 observedForms: false,
Chris@909 341 observedElements: false,
Chris@909 342 changedForms: false,
Chris@909 343 message: null,
Chris@909 344
Chris@909 345 initialize: function(message){
Chris@909 346 this.observedForms = $$('form');
Chris@909 347 this.observedElements = $$('textarea');
Chris@909 348 this.message = message;
Chris@909 349
Chris@909 350 this.observedElements.each(this.observeChange.bind(this));
Chris@909 351 this.observedForms.each(this.submitAction.bind(this));
Chris@909 352
Chris@909 353 window.onbeforeunload = this.unload.bind(this);
Chris@909 354 },
Chris@909 355
Chris@909 356 unload: function(){
Chris@909 357 this.observedElements.each(function(el) {el.blur();})
Chris@909 358 if(this.changedForms)
Chris@909 359 return this.message;
Chris@909 360 },
Chris@909 361
Chris@909 362 setChanged: function(){
Chris@909 363 this.changedForms = true;
Chris@909 364 },
Chris@909 365
Chris@909 366 setUnchanged: function(){
Chris@909 367 this.changedForms = false;
Chris@909 368 },
Chris@909 369
Chris@909 370 observeChange: function(element){
Chris@909 371 element.observe('change',this.setChanged.bindAsEventListener(this));
Chris@909 372 },
Chris@909 373
Chris@909 374 submitAction: function(element){
Chris@909 375 element.observe('submit',this.setUnchanged.bindAsEventListener(this));
Chris@909 376 }
Chris@909 377 });
Chris@909 378
Chris@909 379 /*
Chris@909 380 * 1 - registers a callback which copies the csrf token into the
Chris@909 381 * X-CSRF-Token header with each ajax request. Necessary to
Chris@909 382 * work with rails applications which have fixed
Chris@909 383 * CVE-2011-0447
Chris@909 384 * 2 - shows and hides ajax indicator
Chris@909 385 */
Chris@909 386 Ajax.Responders.register({
Chris@909 387 onCreate: function(request){
Chris@909 388 var csrf_meta_tag = $$('meta[name=csrf-token]')[0];
Chris@909 389
Chris@909 390 if (csrf_meta_tag) {
Chris@909 391 var header = 'X-CSRF-Token',
Chris@909 392 token = csrf_meta_tag.readAttribute('content');
Chris@909 393
Chris@909 394 if (!request.options.requestHeaders) {
Chris@909 395 request.options.requestHeaders = {};
Chris@909 396 }
Chris@909 397 request.options.requestHeaders[header] = token;
Chris@909 398 }
Chris@909 399
Chris@909 400 if ($('ajax-indicator') && Ajax.activeRequestCount > 0) {
Chris@909 401 Element.show('ajax-indicator');
Chris@909 402 }
Chris@909 403 },
Chris@909 404 onComplete: function(){
Chris@909 405 if ($('ajax-indicator') && Ajax.activeRequestCount == 0) {
Chris@909 406 Element.hide('ajax-indicator');
Chris@909 407 }
Chris@909 408 }
Chris@909 409 });
Chris@909 410
Chris@909 411 function hideOnLoad() {
Chris@909 412 $$('.hol').each(function(el) {
Chris@909 413 el.hide();
Chris@909 414 });
Chris@909 415 }
Chris@909 416
Chris@909 417 Event.observe(window, 'load', hideOnLoad);