annotate public/javascripts/application.js @ 245:051f544170fe

* Update to SVN trunk revision 4993
author Chris Cannam
date Thu, 03 Mar 2011 11:42:28 +0000
parents 8661b858af72
children 73ff0e6a11b1 cbce1fd3b1b7
rev   line source
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@0 43 function toggleFieldset(el) {
Chris@0 44 var fieldset = Element.up(el, 'fieldset');
Chris@0 45 fieldset.toggleClassName('collapsed');
Chris@0 46 Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2});
Chris@0 47 }
Chris@0 48
Chris@245 49 function hideFieldset(el) {
Chris@245 50 var fieldset = Element.up(el, 'fieldset');
Chris@245 51 fieldset.toggleClassName('collapsed');
Chris@245 52 fieldset.down('div').hide();
Chris@245 53 }
Chris@245 54
Chris@0 55 var fileFieldCount = 1;
Chris@0 56
Chris@0 57 function addFileField() {
Chris@0 58 if (fileFieldCount >= 10) return false
Chris@0 59 fileFieldCount++;
Chris@0 60 var f = document.createElement("input");
Chris@0 61 f.type = "file";
Chris@0 62 f.name = "attachments[" + fileFieldCount + "][file]";
Chris@0 63 f.size = 30;
Chris@0 64 var d = document.createElement("input");
Chris@0 65 d.type = "text";
Chris@0 66 d.name = "attachments[" + fileFieldCount + "][description]";
Chris@0 67 d.size = 60;
Chris@1 68 var dLabel = new Element('label');
Chris@0 69 dLabel.addClassName('inline');
Chris@0 70 // Pulls the languge value used for Optional Description
Chris@0 71 dLabel.update($('attachment_description_label_content').innerHTML)
Chris@0 72 p = document.getElementById("attachments_fields");
Chris@0 73 p.appendChild(document.createElement("br"));
Chris@0 74 p.appendChild(f);
Chris@0 75 p.appendChild(dLabel);
Chris@0 76 dLabel.appendChild(d);
Chris@0 77
Chris@0 78 }
Chris@0 79
Chris@0 80 function showTab(name) {
Chris@0 81 var f = $$('div#content .tab-content');
Chris@0 82 for(var i=0; i<f.length; i++){
Chris@0 83 Element.hide(f[i]);
Chris@0 84 }
Chris@0 85 var f = $$('div.tabs a');
Chris@0 86 for(var i=0; i<f.length; i++){
Chris@0 87 Element.removeClassName(f[i], "selected");
Chris@0 88 }
Chris@0 89 Element.show('tab-content-' + name);
Chris@0 90 Element.addClassName('tab-' + name, "selected");
Chris@0 91 return false;
Chris@0 92 }
Chris@0 93
Chris@0 94 function moveTabRight(el) {
Chris@0 95 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
Chris@0 96 var tabsWidth = 0;
Chris@0 97 var i;
Chris@0 98 for (i=0; i<lis.length; i++) {
Chris@0 99 if (lis[i].visible()) {
Chris@0 100 tabsWidth += lis[i].getWidth() + 6;
Chris@0 101 }
Chris@0 102 }
Chris@0 103 if (tabsWidth < Element.up(el, 'div.tabs').getWidth() - 60) {
Chris@0 104 return;
Chris@0 105 }
Chris@0 106 i=0;
Chris@0 107 while (i<lis.length && !lis[i].visible()) {
Chris@0 108 i++;
Chris@0 109 }
Chris@0 110 lis[i].hide();
Chris@0 111 }
Chris@0 112
Chris@0 113 function moveTabLeft(el) {
Chris@0 114 var lis = Element.up(el, 'div.tabs').down('ul').childElements();
Chris@0 115 var i = 0;
Chris@0 116 while (i<lis.length && !lis[i].visible()) {
Chris@0 117 i++;
Chris@0 118 }
Chris@0 119 if (i>0) {
Chris@0 120 lis[i-1].show();
Chris@0 121 }
Chris@0 122 }
Chris@0 123
Chris@0 124 function displayTabsButtons() {
Chris@0 125 var lis;
Chris@0 126 var tabsWidth = 0;
Chris@0 127 var i;
Chris@0 128 $$('div.tabs').each(function(el) {
Chris@0 129 lis = el.down('ul').childElements();
Chris@0 130 for (i=0; i<lis.length; i++) {
Chris@0 131 if (lis[i].visible()) {
Chris@0 132 tabsWidth += lis[i].getWidth() + 6;
Chris@0 133 }
Chris@0 134 }
Chris@0 135 if ((tabsWidth < el.getWidth() - 60) && (lis[0].visible())) {
Chris@0 136 el.down('div.tabs-buttons').hide();
Chris@0 137 } else {
Chris@0 138 el.down('div.tabs-buttons').show();
Chris@0 139 }
Chris@0 140 });
Chris@0 141 }
Chris@0 142
Chris@0 143 function setPredecessorFieldsVisibility() {
Chris@0 144 relationType = $('relation_relation_type');
Chris@0 145 if (relationType && (relationType.value == "precedes" || relationType.value == "follows")) {
Chris@0 146 Element.show('predecessor_fields');
Chris@0 147 } else {
Chris@0 148 Element.hide('predecessor_fields');
Chris@0 149 }
Chris@0 150 }
Chris@0 151
Chris@0 152 function promptToRemote(text, param, url) {
Chris@0 153 value = prompt(text + ':');
Chris@0 154 if (value) {
Chris@0 155 new Ajax.Request(url + '?' + param + '=' + encodeURIComponent(value), {asynchronous:true, evalScripts:true});
Chris@0 156 return false;
Chris@0 157 }
Chris@0 158 }
Chris@0 159
Chris@0 160 function collapseScmEntry(id) {
Chris@0 161 var els = document.getElementsByClassName(id, 'browser');
Chris@0 162 for (var i = 0; i < els.length; i++) {
Chris@0 163 if (els[i].hasClassName('open')) {
Chris@0 164 collapseScmEntry(els[i].id);
Chris@0 165 }
Chris@0 166 Element.hide(els[i]);
Chris@0 167 }
Chris@0 168 $(id).removeClassName('open');
Chris@0 169 }
Chris@0 170
Chris@0 171 function expandScmEntry(id) {
Chris@0 172 var els = document.getElementsByClassName(id, 'browser');
Chris@0 173 for (var i = 0; i < els.length; i++) {
Chris@0 174 Element.show(els[i]);
Chris@0 175 if (els[i].hasClassName('loaded') && !els[i].hasClassName('collapsed')) {
Chris@0 176 expandScmEntry(els[i].id);
Chris@0 177 }
Chris@0 178 }
Chris@0 179 $(id).addClassName('open');
Chris@0 180 }
Chris@0 181
Chris@0 182 function scmEntryClick(id) {
Chris@0 183 el = $(id);
Chris@0 184 if (el.hasClassName('open')) {
Chris@0 185 collapseScmEntry(id);
Chris@0 186 el.addClassName('collapsed');
Chris@0 187 return false;
Chris@0 188 } else if (el.hasClassName('loaded')) {
Chris@0 189 expandScmEntry(id);
Chris@0 190 el.removeClassName('collapsed');
Chris@0 191 return false;
Chris@0 192 }
Chris@0 193 if (el.hasClassName('loading')) {
Chris@0 194 return false;
Chris@0 195 }
Chris@0 196 el.addClassName('loading');
Chris@0 197 return true;
Chris@0 198 }
Chris@0 199
Chris@0 200 function scmEntryLoaded(id) {
Chris@0 201 Element.addClassName(id, 'open');
Chris@0 202 Element.addClassName(id, 'loaded');
Chris@0 203 Element.removeClassName(id, 'loading');
Chris@0 204 }
Chris@0 205
Chris@0 206 function randomKey(size) {
Chris@0 207 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 208 var key = '';
Chris@0 209 for (i = 0; i < size; i++) {
Chris@0 210 key += chars[Math.floor(Math.random() * chars.length)];
Chris@0 211 }
Chris@0 212 return key;
Chris@0 213 }
Chris@0 214
Chris@0 215 function observeParentIssueField(url) {
Chris@0 216 new Ajax.Autocompleter('issue_parent_issue_id',
Chris@0 217 'parent_issue_candidates',
Chris@0 218 url,
Chris@0 219 { minChars: 3,
Chris@0 220 frequency: 0.5,
Chris@0 221 paramName: 'q',
Chris@0 222 updateElement: function(value) {
Chris@0 223 document.getElementById('issue_parent_issue_id').value = value.id;
Chris@0 224 }});
Chris@0 225 }
Chris@0 226
Chris@119 227 function observeRelatedIssueField(url) {
Chris@119 228 new Ajax.Autocompleter('relation_issue_to_id',
Chris@119 229 'related_issue_candidates',
Chris@119 230 url,
Chris@119 231 { minChars: 3,
Chris@119 232 frequency: 0.5,
Chris@119 233 paramName: 'q',
Chris@119 234 updateElement: function(value) {
Chris@119 235 document.getElementById('relation_issue_to_id').value = value.id;
Chris@119 236 },
Chris@119 237 parameters: 'scope=all'
Chris@119 238 });
Chris@119 239 }
Chris@119 240
Chris@119 241 function setVisible(id, visible) {
Chris@119 242 var el = $(id);
Chris@119 243 if (el) {if (visible) {el.show();} else {el.hide();}}
Chris@119 244 }
Chris@119 245
Chris@119 246 function observeProjectModules() {
Chris@119 247 var f = function() {
Chris@119 248 /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */
Chris@119 249 var c = ($('project_enabled_module_names_issue_tracking').checked == true);
Chris@119 250 setVisible('project_trackers', c);
Chris@119 251 setVisible('project_issue_custom_fields', c);
Chris@119 252 };
Chris@119 253
Chris@119 254 Event.observe(window, 'load', f);
Chris@119 255 Event.observe('project_enabled_module_names_issue_tracking', 'change', f);
Chris@119 256 }
Chris@119 257
Chris@245 258 /*
Chris@245 259 * Class used to warn user when leaving a page with unsaved textarea
Chris@245 260 * Author: mathias.fischer@berlinonline.de
Chris@245 261 */
Chris@245 262
Chris@245 263 var WarnLeavingUnsaved = Class.create({
Chris@245 264 observedForms: false,
Chris@245 265 observedElements: false,
Chris@245 266 changedForms: false,
Chris@245 267 message: null,
Chris@245 268
Chris@245 269 initialize: function(message){
Chris@245 270 this.observedForms = $$('form');
Chris@245 271 this.observedElements = $$('textarea');
Chris@245 272 this.message = message;
Chris@245 273
Chris@245 274 this.observedElements.each(this.observeChange.bind(this));
Chris@245 275 this.observedForms.each(this.submitAction.bind(this));
Chris@245 276
Chris@245 277 window.onbeforeunload = this.unload.bind(this);
Chris@245 278 },
Chris@245 279
Chris@245 280 unload: function(){
Chris@245 281 if(this.changedForms)
Chris@245 282 return this.message;
Chris@245 283 },
Chris@245 284
Chris@245 285 setChanged: function(){
Chris@245 286 this.changedForms = true;
Chris@245 287 },
Chris@245 288
Chris@245 289 setUnchanged: function(){
Chris@245 290 this.changedForms = false;
Chris@245 291 },
Chris@245 292
Chris@245 293 observeChange: function(element){
Chris@245 294 element.observe('change',this.setChanged.bindAsEventListener(this));
Chris@245 295 },
Chris@245 296
Chris@245 297 submitAction: function(element){
Chris@245 298 element.observe('submit',this.setUnchanged.bindAsEventListener(this));
Chris@245 299 }
Chris@245 300 });
Chris@119 301
Chris@0 302 /* shows and hides ajax indicator */
Chris@0 303 Ajax.Responders.register({
Chris@0 304 onCreate: function(){
Chris@0 305 if ($('ajax-indicator') && Ajax.activeRequestCount > 0) {
Chris@0 306 Element.show('ajax-indicator');
Chris@0 307 }
Chris@0 308 },
Chris@0 309 onComplete: function(){
Chris@0 310 if ($('ajax-indicator') && Ajax.activeRequestCount == 0) {
Chris@0 311 Element.hide('ajax-indicator');
Chris@0 312 }
Chris@0 313 }
Chris@0 314 });
Chris@0 315
Chris@0 316 function hideOnLoad() {
Chris@0 317 $$('.hol').each(function(el) {
Chris@0 318 el.hide();
Chris@0 319 });
Chris@0 320 }
Chris@0 321
Chris@0 322 Event.observe(window, 'load', hideOnLoad);