##// END OF EJS Templates
[js-cleanup] add short copyright notices to javascripts and remove superfluous newline (#20240)....
Jean-Philippe Lang -
r14029:6d78ae91307b
parent child
Show More
@@ -1,657 +1,656
1 1 /* Redmine - project management software
2 2 Copyright (C) 2006-2015 Jean-Philippe Lang */
3 3
4 4 function checkAll(id, checked) {
5 5 $('#'+id).find('input[type=checkbox]:enabled').prop('checked', checked);
6 6 }
7 7
8 8 function toggleCheckboxesBySelector(selector) {
9 9 var all_checked = true;
10 10 $(selector).each(function(index) {
11 11 if (!$(this).is(':checked')) { all_checked = false; }
12 12 });
13 13 $(selector).prop('checked', !all_checked);
14 14 }
15 15
16 16 function showAndScrollTo(id, focus) {
17 17 $('#'+id).show();
18 18 if (focus !== null) {
19 19 $('#'+focus).focus();
20 20 }
21 21 $('html, body').animate({scrollTop: $('#'+id).offset().top}, 100);
22 22 }
23 23
24 24 function toggleRowGroup(el) {
25 25 var tr = $(el).parents('tr').first();
26 26 var n = tr.next();
27 27 tr.toggleClass('open');
28 28 while (n.length && !n.hasClass('group')) {
29 29 n.toggle();
30 30 n = n.next('tr');
31 31 }
32 32 }
33 33
34 34 function collapseAllRowGroups(el) {
35 35 var tbody = $(el).parents('tbody').first();
36 36 tbody.children('tr').each(function(index) {
37 37 if ($(this).hasClass('group')) {
38 38 $(this).removeClass('open');
39 39 } else {
40 40 $(this).hide();
41 41 }
42 42 });
43 43 }
44 44
45 45 function expandAllRowGroups(el) {
46 46 var tbody = $(el).parents('tbody').first();
47 47 tbody.children('tr').each(function(index) {
48 48 if ($(this).hasClass('group')) {
49 49 $(this).addClass('open');
50 50 } else {
51 51 $(this).show();
52 52 }
53 53 });
54 54 }
55 55
56 56 function toggleAllRowGroups(el) {
57 57 var tr = $(el).parents('tr').first();
58 58 if (tr.hasClass('open')) {
59 59 collapseAllRowGroups(el);
60 60 } else {
61 61 expandAllRowGroups(el);
62 62 }
63 63 }
64 64
65 65 function toggleFieldset(el) {
66 66 var fieldset = $(el).parents('fieldset').first();
67 67 fieldset.toggleClass('collapsed');
68 68 fieldset.children('div').toggle();
69 69 }
70 70
71 71 function hideFieldset(el) {
72 72 var fieldset = $(el).parents('fieldset').first();
73 73 fieldset.toggleClass('collapsed');
74 74 fieldset.children('div').hide();
75 75 }
76 76
77 77 // columns selection
78 78 function moveOptions(theSelFrom, theSelTo) {
79 79 $(theSelFrom).find('option:selected').detach().prop("selected", false).appendTo($(theSelTo));
80 80 }
81 81
82 82 function moveOptionUp(theSel) {
83 83 $(theSel).find('option:selected').each(function(){
84 84 $(this).prev(':not(:selected)').detach().insertAfter($(this));
85 85 });
86 86 }
87 87
88 88 function moveOptionTop(theSel) {
89 89 $(theSel).find('option:selected').detach().prependTo($(theSel));
90 90 }
91 91
92 92 function moveOptionDown(theSel) {
93 93 $($(theSel).find('option:selected').get().reverse()).each(function(){
94 94 $(this).next(':not(:selected)').detach().insertBefore($(this));
95 95 });
96 96 }
97 97
98 98 function moveOptionBottom(theSel) {
99 99 $(theSel).find('option:selected').detach().appendTo($(theSel));
100 100 }
101 101
102 102 function initFilters() {
103 103 $('#add_filter_select').change(function() {
104 104 addFilter($(this).val(), '', []);
105 105 });
106 106 $('#filters-table td.field input[type=checkbox]').each(function() {
107 107 toggleFilter($(this).val());
108 108 });
109 109 $('#filters-table').on('click', 'td.field input[type=checkbox]', function() {
110 110 toggleFilter($(this).val());
111 111 });
112 112 $('#filters-table').on('click', '.toggle-multiselect', function() {
113 113 toggleMultiSelect($(this).siblings('select'));
114 114 });
115 115 $('#filters-table').on('keypress', 'input[type=text]', function(e) {
116 116 if (e.keyCode == 13) $(this).closest('form').submit();
117 117 });
118 118 }
119 119
120 120 function addFilter(field, operator, values) {
121 121 var fieldId = field.replace('.', '_');
122 122 var tr = $('#tr_'+fieldId);
123 123 if (tr.length > 0) {
124 124 tr.show();
125 125 } else {
126 126 buildFilterRow(field, operator, values);
127 127 }
128 128 $('#cb_'+fieldId).prop('checked', true);
129 129 toggleFilter(field);
130 130 $('#add_filter_select').val('').find('option').each(function() {
131 131 if ($(this).attr('value') == field) {
132 132 $(this).attr('disabled', true);
133 133 }
134 134 });
135 135 }
136 136
137 137 function buildFilterRow(field, operator, values) {
138 138 var fieldId = field.replace('.', '_');
139 139 var filterTable = $("#filters-table");
140 140 var filterOptions = availableFilters[field];
141 141 if (!filterOptions) return;
142 142 var operators = operatorByType[filterOptions['type']];
143 143 var filterValues = filterOptions['values'];
144 144 var i, select;
145 145
146 146 var tr = $('<tr class="filter">').attr('id', 'tr_'+fieldId).html(
147 147 '<td class="field"><input checked="checked" id="cb_'+fieldId+'" name="f[]" value="'+field+'" type="checkbox"><label for="cb_'+fieldId+'"> '+filterOptions['name']+'</label></td>' +
148 148 '<td class="operator"><select id="operators_'+fieldId+'" name="op['+field+']"></td>' +
149 149 '<td class="values"></td>'
150 150 );
151 151 filterTable.append(tr);
152 152
153 153 select = tr.find('td.operator select');
154 154 for (i = 0; i < operators.length; i++) {
155 155 var option = $('<option>').val(operators[i]).text(operatorLabels[operators[i]]);
156 156 if (operators[i] == operator) { option.attr('selected', true); }
157 157 select.append(option);
158 158 }
159 159 select.change(function(){ toggleOperator(field); });
160 160
161 161 switch (filterOptions['type']) {
162 162 case "list":
163 163 case "list_optional":
164 164 case "list_status":
165 165 case "list_subprojects":
166 166 tr.find('td.values').append(
167 167 '<span style="display:none;"><select class="value" id="values_'+fieldId+'_1" name="v['+field+'][]"></select>' +
168 168 ' <span class="toggle-multiselect">&nbsp;</span></span>'
169 169 );
170 170 select = tr.find('td.values select');
171 171 if (values.length > 1) { select.attr('multiple', true); }
172 172 for (i = 0; i < filterValues.length; i++) {
173 173 var filterValue = filterValues[i];
174 174 var option = $('<option>');
175 175 if ($.isArray(filterValue)) {
176 176 option.val(filterValue[1]).text(filterValue[0]);
177 177 if ($.inArray(filterValue[1], values) > -1) {option.attr('selected', true);}
178 178 } else {
179 179 option.val(filterValue).text(filterValue);
180 180 if ($.inArray(filterValue, values) > -1) {option.attr('selected', true);}
181 181 }
182 182 select.append(option);
183 183 }
184 184 break;
185 185 case "date":
186 186 case "date_past":
187 187 tr.find('td.values').append(
188 188 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="10" class="value date_value" /></span>' +
189 189 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="10" class="value date_value" /></span>' +
190 190 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="3" class="value" /> '+labelDayPlural+'</span>'
191 191 );
192 192 $('#values_'+fieldId+'_1').val(values[0]).datepicker(datepickerOptions);
193 193 $('#values_'+fieldId+'_2').val(values[1]).datepicker(datepickerOptions);
194 194 $('#values_'+fieldId).val(values[0]);
195 195 break;
196 196 case "string":
197 197 case "text":
198 198 tr.find('td.values').append(
199 199 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="30" class="value" /></span>'
200 200 );
201 201 $('#values_'+fieldId).val(values[0]);
202 202 break;
203 203 case "relation":
204 204 tr.find('td.values').append(
205 205 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'" size="6" class="value" /></span>' +
206 206 '<span style="display:none;"><select class="value" name="v['+field+'][]" id="values_'+fieldId+'_1"></select></span>'
207 207 );
208 208 $('#values_'+fieldId).val(values[0]);
209 209 select = tr.find('td.values select');
210 210 for (i = 0; i < allProjects.length; i++) {
211 211 var filterValue = allProjects[i];
212 212 var option = $('<option>');
213 213 option.val(filterValue[1]).text(filterValue[0]);
214 214 if (values[0] == filterValue[1]) { option.attr('selected', true); }
215 215 select.append(option);
216 216 }
217 217 break;
218 218 case "integer":
219 219 case "float":
220 220 case "tree":
221 221 tr.find('td.values').append(
222 222 '<span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_1" size="6" class="value" /></span>' +
223 223 ' <span style="display:none;"><input type="text" name="v['+field+'][]" id="values_'+fieldId+'_2" size="6" class="value" /></span>'
224 224 );
225 225 $('#values_'+fieldId+'_1').val(values[0]);
226 226 $('#values_'+fieldId+'_2').val(values[1]);
227 227 break;
228 228 }
229 229 }
230 230
231 231 function toggleFilter(field) {
232 232 var fieldId = field.replace('.', '_');
233 233 if ($('#cb_' + fieldId).is(':checked')) {
234 234 $("#operators_" + fieldId).show().removeAttr('disabled');
235 235 toggleOperator(field);
236 236 } else {
237 237 $("#operators_" + fieldId).hide().attr('disabled', true);
238 238 enableValues(field, []);
239 239 }
240 240 }
241 241
242 242 function enableValues(field, indexes) {
243 243 var fieldId = field.replace('.', '_');
244 244 $('#tr_'+fieldId+' td.values .value').each(function(index) {
245 245 if ($.inArray(index, indexes) >= 0) {
246 246 $(this).removeAttr('disabled');
247 247 $(this).parents('span').first().show();
248 248 } else {
249 249 $(this).val('');
250 250 $(this).attr('disabled', true);
251 251 $(this).parents('span').first().hide();
252 252 }
253 253
254 254 if ($(this).hasClass('group')) {
255 255 $(this).addClass('open');
256 256 } else {
257 257 $(this).show();
258 258 }
259 259 });
260 260 }
261 261
262 262 function toggleOperator(field) {
263 263 var fieldId = field.replace('.', '_');
264 264 var operator = $("#operators_" + fieldId);
265 265 switch (operator.val()) {
266 266 case "!*":
267 267 case "*":
268 268 case "t":
269 269 case "ld":
270 270 case "w":
271 271 case "lw":
272 272 case "l2w":
273 273 case "m":
274 274 case "lm":
275 275 case "y":
276 276 case "o":
277 277 case "c":
278 278 enableValues(field, []);
279 279 break;
280 280 case "><":
281 281 enableValues(field, [0,1]);
282 282 break;
283 283 case "<t+":
284 284 case ">t+":
285 285 case "><t+":
286 286 case "t+":
287 287 case ">t-":
288 288 case "<t-":
289 289 case "><t-":
290 290 case "t-":
291 291 enableValues(field, [2]);
292 292 break;
293 293 case "=p":
294 294 case "=!p":
295 295 case "!p":
296 296 enableValues(field, [1]);
297 297 break;
298 298 default:
299 299 enableValues(field, [0]);
300 300 break;
301 301 }
302 302 }
303 303
304 304 function toggleMultiSelect(el) {
305 305 if (el.attr('multiple')) {
306 306 el.removeAttr('multiple');
307 307 el.attr('size', 1);
308 308 } else {
309 309 el.attr('multiple', true);
310 310 if (el.children().length > 10)
311 311 el.attr('size', 10);
312 312 else
313 313 el.attr('size', 4);
314 314 }
315 315 }
316 316
317 317 function showTab(name, url) {
318 318 $('div#content .tab-content').hide();
319 319 $('div.tabs a').removeClass('selected');
320 320 $('#tab-content-' + name).show();
321 321 $('#tab-' + name).addClass('selected');
322 322 //replaces current URL with the "href" attribute of the current link
323 323 //(only triggered if supported by browser)
324 324 if ("replaceState" in window.history) {
325 325 window.history.replaceState(null, document.title, url);
326 326 }
327 327 return false;
328 328 }
329 329
330 330 function moveTabRight(el) {
331 331 var lis = $(el).parents('div.tabs').first().find('ul').children();
332 332 var tabsWidth = 0;
333 333 var i = 0;
334 334 lis.each(function() {
335 335 if ($(this).is(':visible')) {
336 336 tabsWidth += $(this).width() + 6;
337 337 }
338 338 });
339 339 if (tabsWidth < $(el).parents('div.tabs').first().width() - 60) { return; }
340 340 while (i<lis.length && !lis.eq(i).is(':visible')) { i++; }
341 341 lis.eq(i).hide();
342 342 }
343 343
344 344 function moveTabLeft(el) {
345 345 var lis = $(el).parents('div.tabs').first().find('ul').children();
346 346 var i = 0;
347 347 while (i < lis.length && !lis.eq(i).is(':visible')) { i++; }
348 348 if (i > 0) {
349 349 lis.eq(i-1).show();
350 350 }
351 351 }
352 352
353 353 function displayTabsButtons() {
354 354 var lis;
355 355 var tabsWidth = 0;
356 356 var el;
357 357 $('div.tabs').each(function() {
358 358 el = $(this);
359 359 lis = el.find('ul').children();
360 360 lis.each(function(){
361 361 if ($(this).is(':visible')) {
362 362 tabsWidth += $(this).width() + 6;
363 363 }
364 364 });
365 365 if ((tabsWidth < el.width() - 60) && (lis.first().is(':visible'))) {
366 366 el.find('div.tabs-buttons').hide();
367 367 } else {
368 368 el.find('div.tabs-buttons').show();
369 369 }
370 370 });
371 371 }
372 372
373 373 function setPredecessorFieldsVisibility() {
374 374 var relationType = $('#relation_relation_type');
375 375 if (relationType.val() == "precedes" || relationType.val() == "follows") {
376 376 $('#predecessor_fields').show();
377 377 } else {
378 378 $('#predecessor_fields').hide();
379 379 }
380 380 }
381 381
382 382 function showModal(id, width, title) {
383 383 var el = $('#'+id).first();
384 384 if (el.length === 0 || el.is(':visible')) {return;}
385 385 if (!title) title = el.find('h3.title').text();
386 386 // moves existing modals behind the transparent background
387 387 $(".modal").zIndex(99);
388 388 el.dialog({
389 389 width: width,
390 390 modal: true,
391 391 resizable: false,
392 392 dialogClass: 'modal',
393 393 title: title
394 394 }).on('dialogclose', function(){
395 395 $(".modal").zIndex(101);
396 396 });
397 397 el.find("input[type=text], input[type=submit]").first().focus();
398 398 }
399 399
400 400 function hideModal(el) {
401 401 var modal;
402 402 if (el) {
403 403 modal = $(el).parents('.ui-dialog-content');
404 404 } else {
405 405 modal = $('#ajax-modal');
406 406 }
407 407 modal.dialog("close");
408 408 }
409 409
410 410 function submitPreview(url, form, target) {
411 411 $.ajax({
412 412 url: url,
413 413 type: 'post',
414 414 data: $('#'+form).serialize(),
415 415 success: function(data){
416 416 $('#'+target).html(data);
417 417 }
418 418 });
419 419 }
420 420
421 421 function collapseScmEntry(id) {
422 422 $('.'+id).each(function() {
423 423 if ($(this).hasClass('open')) {
424 424 collapseScmEntry($(this).attr('id'));
425 425 }
426 426 $(this).hide();
427 427 });
428 428 $('#'+id).removeClass('open');
429 429 }
430 430
431 431 function expandScmEntry(id) {
432 432 $('.'+id).each(function() {
433 433 $(this).show();
434 434 if ($(this).hasClass('loaded') && !$(this).hasClass('collapsed')) {
435 435 expandScmEntry($(this).attr('id'));
436 436 }
437 437 });
438 438 $('#'+id).addClass('open');
439 439 }
440 440
441 441 function scmEntryClick(id, url) {
442 442 var el = $('#'+id);
443 443 if (el.hasClass('open')) {
444 444 collapseScmEntry(id);
445 445 el.addClass('collapsed');
446 446 return false;
447 447 } else if (el.hasClass('loaded')) {
448 448 expandScmEntry(id);
449 449 el.removeClass('collapsed');
450 450 return false;
451 451 }
452 452 if (el.hasClass('loading')) {
453 453 return false;
454 454 }
455 455 el.addClass('loading');
456 456 $.ajax({
457 457 url: url,
458 458 success: function(data) {
459 459 el.after(data);
460 460 el.addClass('open').addClass('loaded').removeClass('loading');
461 461 }
462 462 });
463 463 return true;
464 464 }
465 465
466 466 function randomKey(size) {
467 467 var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
468 468 var key = '';
469 469 for (var i = 0; i < size; i++) {
470 470 key += chars.charAt(Math.floor(Math.random() * chars.length));
471 471 }
472 472 return key;
473 473 }
474 474
475 475 function updateIssueFrom(url) {
476 476 $('#all_attributes input, #all_attributes textarea, #all_attributes select').each(function(){
477 477 $(this).data('valuebeforeupdate', $(this).val());
478 478 });
479 479 return $.ajax({
480 480 url: url,
481 481 type: 'post',
482 482 data: $('#issue-form').serialize()
483 483 });
484 484 }
485 485
486 486 function replaceIssueFormWith(html){
487 487 var replacement = $(html);
488 488 $('#all_attributes input, #all_attributes textarea, #all_attributes select').each(function(){
489 489 var object_id = $(this).attr('id');
490 490 if (object_id && $(this).data('valuebeforeupdate')!=$(this).val()) {
491 491 replacement.find('#'+object_id).val($(this).val());
492 492 }
493 493 });
494 494 $('#all_attributes').empty();
495 495 $('#all_attributes').prepend(replacement);
496 496 }
497 497
498 498 function updateBulkEditFrom(url) {
499 499 $.ajax({
500 500 url: url,
501 501 type: 'post',
502 502 data: $('#bulk_edit_form').serialize()
503 503 });
504 504 }
505 505
506 506 function observeAutocompleteField(fieldId, url, options) {
507 507 $(document).ready(function() {
508 508 $('#'+fieldId).autocomplete($.extend({
509 509 source: url,
510 510 minLength: 2,
511 511 search: function(){$('#'+fieldId).addClass('ajax-loading');},
512 512 response: function(){$('#'+fieldId).removeClass('ajax-loading');}
513 513 }, options));
514 514 $('#'+fieldId).addClass('autocomplete');
515 515 });
516 516 }
517 517
518 518 function observeSearchfield(fieldId, targetId, url) {
519 519 $('#'+fieldId).each(function() {
520 520 var $this = $(this);
521 521 $this.addClass('autocomplete');
522 522 $this.attr('data-value-was', $this.val());
523 523 var check = function() {
524 524 var val = $this.val();
525 525 if ($this.attr('data-value-was') != val){
526 526 $this.attr('data-value-was', val);
527 527 $.ajax({
528 528 url: url,
529 529 type: 'get',
530 530 data: {q: $this.val()},
531 531 success: function(data){ if(targetId) $('#'+targetId).html(data); },
532 532 beforeSend: function(){ $this.addClass('ajax-loading'); },
533 533 complete: function(){ $this.removeClass('ajax-loading'); }
534 534 });
535 535 }
536 536 };
537 537 var reset = function() {
538 538 if (timer) {
539 539 clearInterval(timer);
540 540 timer = setInterval(check, 300);
541 541 }
542 542 };
543 543 var timer = setInterval(check, 300);
544 544 $this.bind('keyup click mousemove', reset);
545 545 });
546 546 }
547 547
548 548 function beforeShowDatePicker(input, inst) {
549 549 var default_date = null;
550 550 switch ($(input).attr("id")) {
551 551 case "issue_start_date" :
552 552 if ($("#issue_due_date").size() > 0) {
553 553 default_date = $("#issue_due_date").val();
554 554 }
555 555 break;
556 556 case "issue_due_date" :
557 557 if ($("#issue_start_date").size() > 0) {
558 558 default_date = $("#issue_start_date").val();
559 559 }
560 560 break;
561 561 }
562 562 $(input).datepicker("option", "defaultDate", default_date);
563 563 }
564 564
565 565 function initMyPageSortable(list, url) {
566 566 $('#list-'+list).sortable({
567 567 connectWith: '.block-receiver',
568 568 tolerance: 'pointer',
569 569 update: function(){
570 570 $.ajax({
571 571 url: url,
572 572 type: 'post',
573 573 data: {'blocks': $.map($('#list-'+list).children(), function(el){return $(el).attr('id');})}
574 574 });
575 575 }
576 576 });
577 577 $("#list-top, #list-left, #list-right").disableSelection();
578 578 }
579 579
580 580 var warnLeavingUnsavedMessage;
581 581 function warnLeavingUnsaved(message) {
582 582 warnLeavingUnsavedMessage = message;
583 583 $(document).on('submit', 'form', function(){
584 584 $('textarea').removeData('changed');
585 585 });
586 586 $(document).on('change', 'textarea', function(){
587 587 $(this).data('changed', 'changed');
588 588 });
589 589 window.onbeforeunload = function(){
590 590 var warn = false;
591 591 $('textarea').blur().each(function(){
592 592 if ($(this).data('changed')) {
593 593 warn = true;
594 594 }
595 595 });
596 596 if (warn) {return warnLeavingUnsavedMessage;}
597 597 };
598 598 }
599 599
600 600 function setupAjaxIndicator() {
601 601 $(document).bind('ajaxSend', function(event, xhr, settings) {
602 602 if ($('.ajax-loading').length === 0 && settings.contentType != 'application/octet-stream') {
603 603 $('#ajax-indicator').show();
604 604 }
605 605 });
606 606 $(document).bind('ajaxStop', function() {
607 607 $('#ajax-indicator').hide();
608 608 });
609 609 }
610 610
611 611 function hideOnLoad() {
612 612 $('.hol').hide();
613 613 }
614 614
615 615 function addFormObserversForDoubleSubmit() {
616 616 $('form[method=post]').each(function() {
617 617 if (!$(this).hasClass('multiple-submit')) {
618 618 $(this).submit(function(form_submission) {
619 619 if ($(form_submission.target).attr('data-submitted')) {
620 620 form_submission.preventDefault();
621 621 } else {
622 622 $(form_submission.target).attr('data-submitted', true);
623 623 }
624 624 });
625 625 }
626 626 });
627 627 }
628 628
629 629 function defaultFocus(){
630 630 if (($('#content :focus').length == 0) && (window.location.hash == '')) {
631 631 $('#content input[type=text], #content textarea').first().focus();
632 632 }
633 633 }
634 634
635 635 function blockEventPropagation(event) {
636 636 event.stopPropagation();
637 637 event.preventDefault();
638 638 }
639 639
640 640 function toggleDisabledOnChange() {
641 641 var checked = $(this).is(':checked');
642 642 $($(this).data('disables')).attr('disabled', checked);
643 643 $($(this).data('enables')).attr('disabled', !checked);
644 644 }
645 645 function toggleDisabledInit() {
646 646 $('input[data-disables], input[data-enables]').each(toggleDisabledOnChange);
647 647 }
648 648 $(document).ready(function(){
649 649 $('#content').on('change', 'input[data-disables], input[data-enables]', toggleDisabledOnChange);
650 650 toggleDisabledInit();
651 651 });
652 652
653 653 $(document).ready(setupAjaxIndicator);
654 654 $(document).ready(hideOnLoad);
655 655 $(document).ready(addFormObserversForDoubleSubmit);
656 656 $(document).ready(defaultFocus);
657
@@ -1,236 +1,239
1 /* Redmine - project management software
2 Copyright (C) 2006-2015 Jean-Philippe Lang */
3
1 4 var contextMenuObserving;
2 5 var contextMenuUrl;
3 6
4 7 function contextMenuRightClick(event) {
5 8 var target = $(event.target);
6 9 if (target.is('a')) {return;}
7 10 var tr = target.parents('tr').first();
8 11 if (!tr.hasClass('hascontextmenu')) {return;}
9 12 event.preventDefault();
10 13 if (!contextMenuIsSelected(tr)) {
11 14 contextMenuUnselectAll();
12 15 contextMenuAddSelection(tr);
13 16 contextMenuSetLastSelected(tr);
14 17 }
15 18 contextMenuShow(event);
16 19 }
17 20
18 21 function contextMenuClick(event) {
19 22 var target = $(event.target);
20 23 var lastSelected;
21 24
22 25 if (target.is('a') && target.hasClass('submenu')) {
23 26 event.preventDefault();
24 27 return;
25 28 }
26 29 contextMenuHide();
27 30 if (target.is('a') || target.is('img')) { return; }
28 31 if (event.which == 1 || (navigator.appVersion.match(/\bMSIE\b/))) {
29 32 var tr = target.parents('tr').first();
30 33 if (tr.length && tr.hasClass('hascontextmenu')) {
31 34 // a row was clicked, check if the click was on checkbox
32 35 if (target.is('input')) {
33 36 // a checkbox may be clicked
34 37 if (target.prop('checked')) {
35 38 tr.addClass('context-menu-selection');
36 39 } else {
37 40 tr.removeClass('context-menu-selection');
38 41 }
39 42 } else {
40 43 if (event.ctrlKey || event.metaKey) {
41 44 contextMenuToggleSelection(tr);
42 45 } else if (event.shiftKey) {
43 46 lastSelected = contextMenuLastSelected();
44 47 if (lastSelected.length) {
45 48 var toggling = false;
46 49 $('.hascontextmenu').each(function(){
47 50 if (toggling || $(this).is(tr)) {
48 51 contextMenuAddSelection($(this));
49 52 }
50 53 if ($(this).is(tr) || $(this).is(lastSelected)) {
51 54 toggling = !toggling;
52 55 }
53 56 });
54 57 } else {
55 58 contextMenuAddSelection(tr);
56 59 }
57 60 } else {
58 61 contextMenuUnselectAll();
59 62 contextMenuAddSelection(tr);
60 63 }
61 64 contextMenuSetLastSelected(tr);
62 65 }
63 66 } else {
64 67 // click is outside the rows
65 68 if (target.is('a') && (target.hasClass('disabled') || target.hasClass('submenu'))) {
66 69 event.preventDefault();
67 70 } else {
68 71 contextMenuUnselectAll();
69 72 }
70 73 }
71 74 }
72 75 }
73 76
74 77 function contextMenuCreate() {
75 78 if ($('#context-menu').length < 1) {
76 79 var menu = document.createElement("div");
77 80 menu.setAttribute("id", "context-menu");
78 81 menu.setAttribute("style", "display:none;");
79 82 document.getElementById("content").appendChild(menu);
80 83 }
81 84 }
82 85
83 86 function contextMenuShow(event) {
84 87 var mouse_x = event.pageX;
85 88 var mouse_y = event.pageY;
86 89 var render_x = mouse_x;
87 90 var render_y = mouse_y;
88 91 var dims;
89 92 var menu_width;
90 93 var menu_height;
91 94 var window_width;
92 95 var window_height;
93 96 var max_width;
94 97 var max_height;
95 98
96 99 $('#context-menu').css('left', (render_x + 'px'));
97 100 $('#context-menu').css('top', (render_y + 'px'));
98 101 $('#context-menu').html('');
99 102
100 103 $.ajax({
101 104 url: contextMenuUrl,
102 105 data: $(event.target).parents('form').first().serialize(),
103 106 success: function(data, textStatus, jqXHR) {
104 107 $('#context-menu').html(data);
105 108 menu_width = $('#context-menu').width();
106 109 menu_height = $('#context-menu').height();
107 110 max_width = mouse_x + 2*menu_width;
108 111 max_height = mouse_y + menu_height;
109 112
110 113 var ws = window_size();
111 114 window_width = ws.width;
112 115 window_height = ws.height;
113 116
114 117 /* display the menu above and/or to the left of the click if needed */
115 118 if (max_width > window_width) {
116 119 render_x -= menu_width;
117 120 $('#context-menu').addClass('reverse-x');
118 121 } else {
119 122 $('#context-menu').removeClass('reverse-x');
120 123 }
121 124 if (max_height > window_height) {
122 125 render_y -= menu_height;
123 126 $('#context-menu').addClass('reverse-y');
124 127 } else {
125 128 $('#context-menu').removeClass('reverse-y');
126 129 }
127 130 if (render_x <= 0) render_x = 1;
128 131 if (render_y <= 0) render_y = 1;
129 132 $('#context-menu').css('left', (render_x + 'px'));
130 133 $('#context-menu').css('top', (render_y + 'px'));
131 134 $('#context-menu').show();
132 135
133 136 //if (window.parseStylesheets) { window.parseStylesheets(); } // IE
134 137
135 138 }
136 139 });
137 140 }
138 141
139 142 function contextMenuSetLastSelected(tr) {
140 143 $('.cm-last').removeClass('cm-last');
141 144 tr.addClass('cm-last');
142 145 }
143 146
144 147 function contextMenuLastSelected() {
145 148 return $('.cm-last').first();
146 149 }
147 150
148 151 function contextMenuUnselectAll() {
149 152 $('.hascontextmenu').each(function(){
150 153 contextMenuRemoveSelection($(this));
151 154 });
152 155 $('.cm-last').removeClass('cm-last');
153 156 }
154 157
155 158 function contextMenuHide() {
156 159 $('#context-menu').hide();
157 160 }
158 161
159 162 function contextMenuToggleSelection(tr) {
160 163 if (contextMenuIsSelected(tr)) {
161 164 contextMenuRemoveSelection(tr);
162 165 } else {
163 166 contextMenuAddSelection(tr);
164 167 }
165 168 }
166 169
167 170 function contextMenuAddSelection(tr) {
168 171 tr.addClass('context-menu-selection');
169 172 contextMenuCheckSelectionBox(tr, true);
170 173 contextMenuClearDocumentSelection();
171 174 }
172 175
173 176 function contextMenuRemoveSelection(tr) {
174 177 tr.removeClass('context-menu-selection');
175 178 contextMenuCheckSelectionBox(tr, false);
176 179 }
177 180
178 181 function contextMenuIsSelected(tr) {
179 182 return tr.hasClass('context-menu-selection');
180 183 }
181 184
182 185 function contextMenuCheckSelectionBox(tr, checked) {
183 186 tr.find('input[type=checkbox]').prop('checked', checked);
184 187 }
185 188
186 189 function contextMenuClearDocumentSelection() {
187 190 // TODO
188 191 if (document.selection) {
189 192 document.selection.empty(); // IE
190 193 } else {
191 194 window.getSelection().removeAllRanges();
192 195 }
193 196 }
194 197
195 198 function contextMenuInit(url) {
196 199 contextMenuUrl = url;
197 200 contextMenuCreate();
198 201 contextMenuUnselectAll();
199 202
200 203 if (!contextMenuObserving) {
201 204 $(document).click(contextMenuClick);
202 205 $(document).contextmenu(contextMenuRightClick);
203 206 contextMenuObserving = true;
204 207 }
205 208 }
206 209
207 210 function toggleIssuesSelection(el) {
208 211 var boxes = $(el).parents('form').find('input[type=checkbox]');
209 212 var all_checked = true;
210 213 boxes.each(function(){ if (!$(this).prop('checked')) { all_checked = false; } });
211 214 boxes.each(function(){
212 215 if (all_checked) {
213 216 $(this).removeAttr('checked');
214 217 $(this).parents('tr').removeClass('context-menu-selection');
215 218 } else if (!$(this).prop('checked')) {
216 219 $(this).prop('checked', true);
217 220 $(this).parents('tr').addClass('context-menu-selection');
218 221 }
219 222 });
220 223 }
221 224
222 225 function window_size() {
223 226 var w;
224 227 var h;
225 228 if (window.innerWidth) {
226 229 w = window.innerWidth;
227 230 h = window.innerHeight;
228 231 } else if (document.documentElement) {
229 232 w = document.documentElement.clientWidth;
230 233 h = document.documentElement.clientHeight;
231 234 } else {
232 235 w = document.body.clientWidth;
233 236 h = document.body.clientHeight;
234 237 }
235 238 return {width: w, height: h};
236 239 }
@@ -1,172 +1,175
1 /* Redmine - project management software
2 Copyright (C) 2006-2015 Jean-Philippe Lang */
3
1 4 var draw_gantt = null;
2 5 var draw_top;
3 6 var draw_right;
4 7 var draw_left;
5 8
6 9 var rels_stroke_width = 2;
7 10
8 11 function setDrawArea() {
9 12 draw_top = $("#gantt_draw_area").position().top;
10 13 draw_right = $("#gantt_draw_area").width();
11 14 draw_left = $("#gantt_area").scrollLeft();
12 15 }
13 16
14 17 function getRelationsArray() {
15 18 var arr = new Array();
16 19 $.each($('div.task_todo[data-rels]'), function(index_div, element) {
17 20 var element_id = $(element).attr("id");
18 21 if (element_id != null) {
19 22 var issue_id = element_id.replace("task-todo-issue-", "");
20 23 var data_rels = $(element).data("rels");
21 24 for (rel_type_key in data_rels) {
22 25 $.each(data_rels[rel_type_key], function(index_issue, element_issue) {
23 26 arr.push({issue_from: issue_id, issue_to: element_issue,
24 27 rel_type: rel_type_key});
25 28 });
26 29 }
27 30 }
28 31 });
29 32 return arr;
30 33 }
31 34
32 35 function drawRelations() {
33 36 var arr = getRelationsArray();
34 37 $.each(arr, function(index_issue, element_issue) {
35 38 var issue_from = $("#task-todo-issue-" + element_issue["issue_from"]);
36 39 var issue_to = $("#task-todo-issue-" + element_issue["issue_to"]);
37 40 if (issue_from.size() == 0 || issue_to.size() == 0) {
38 41 return;
39 42 }
40 43 var issue_height = issue_from.height();
41 44 var issue_from_top = issue_from.position().top + (issue_height / 2) - draw_top;
42 45 var issue_from_right = issue_from.position().left + issue_from.width();
43 46 var issue_to_top = issue_to.position().top + (issue_height / 2) - draw_top;
44 47 var issue_to_left = issue_to.position().left;
45 48 var color = issue_relation_type[element_issue["rel_type"]]["color"];
46 49 var landscape_margin = issue_relation_type[element_issue["rel_type"]]["landscape_margin"];
47 50 var issue_from_right_rel = issue_from_right + landscape_margin;
48 51 var issue_to_left_rel = issue_to_left - landscape_margin;
49 52 draw_gantt.path(["M", issue_from_right + draw_left, issue_from_top,
50 53 "L", issue_from_right_rel + draw_left, issue_from_top])
51 54 .attr({stroke: color,
52 55 "stroke-width": rels_stroke_width
53 56 });
54 57 if (issue_from_right_rel < issue_to_left_rel) {
55 58 draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_from_top,
56 59 "L", issue_from_right_rel + draw_left, issue_to_top])
57 60 .attr({stroke: color,
58 61 "stroke-width": rels_stroke_width
59 62 });
60 63 draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_to_top,
61 64 "L", issue_to_left + draw_left, issue_to_top])
62 65 .attr({stroke: color,
63 66 "stroke-width": rels_stroke_width
64 67 });
65 68 } else {
66 69 var issue_middle_top = issue_to_top +
67 70 (issue_height *
68 71 ((issue_from_top > issue_to_top) ? 1 : -1));
69 72 draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_from_top,
70 73 "L", issue_from_right_rel + draw_left, issue_middle_top])
71 74 .attr({stroke: color,
72 75 "stroke-width": rels_stroke_width
73 76 });
74 77 draw_gantt.path(["M", issue_from_right_rel + draw_left, issue_middle_top,
75 78 "L", issue_to_left_rel + draw_left, issue_middle_top])
76 79 .attr({stroke: color,
77 80 "stroke-width": rels_stroke_width
78 81 });
79 82 draw_gantt.path(["M", issue_to_left_rel + draw_left, issue_middle_top,
80 83 "L", issue_to_left_rel + draw_left, issue_to_top])
81 84 .attr({stroke: color,
82 85 "stroke-width": rels_stroke_width
83 86 });
84 87 draw_gantt.path(["M", issue_to_left_rel + draw_left, issue_to_top,
85 88 "L", issue_to_left + draw_left, issue_to_top])
86 89 .attr({stroke: color,
87 90 "stroke-width": rels_stroke_width
88 91 });
89 92 }
90 93 draw_gantt.path(["M", issue_to_left + draw_left, issue_to_top,
91 94 "l", -4 * rels_stroke_width, -2 * rels_stroke_width,
92 95 "l", 0, 4 * rels_stroke_width, "z"])
93 96 .attr({stroke: "none",
94 97 fill: color,
95 98 "stroke-linecap": "butt",
96 99 "stroke-linejoin": "miter"
97 100 });
98 101 });
99 102 }
100 103
101 104 function getProgressLinesArray() {
102 105 var arr = new Array();
103 106 var today_left = $('#today_line').position().left;
104 107 arr.push({left: today_left, top: 0});
105 108 $.each($('div.issue-subject, div.version-name'), function(index, element) {
106 109 var t = $(element).position().top - draw_top ;
107 110 var h = ($(element).height() / 9);
108 111 var element_top_upper = t - h;
109 112 var element_top_center = t + (h * 3);
110 113 var element_top_lower = t + (h * 8);
111 114 var issue_closed = $(element).children('span').hasClass('issue-closed');
112 115 var version_closed = $(element).children('span').hasClass('version-closed');
113 116 if (issue_closed || version_closed) {
114 117 arr.push({left: today_left, top: element_top_center});
115 118 } else {
116 119 var issue_done = $("#task-done-" + $(element).attr("id"));
117 120 var is_behind_start = $(element).children('span').hasClass('behind-start-date');
118 121 var is_over_end = $(element).children('span').hasClass('over-end-date');
119 122 if (is_over_end) {
120 123 arr.push({left: draw_right, top: element_top_upper, is_right_edge: true});
121 124 arr.push({left: draw_right, top: element_top_lower, is_right_edge: true, none_stroke: true});
122 125 } else if (issue_done.size() > 0) {
123 126 var done_left = issue_done.first().position().left +
124 127 issue_done.first().width();
125 128 arr.push({left: done_left, top: element_top_center});
126 129 } else if (is_behind_start) {
127 130 arr.push({left: 0 , top: element_top_upper, is_left_edge: true});
128 131 arr.push({left: 0 , top: element_top_lower, is_left_edge: true, none_stroke: true});
129 132 } else {
130 133 var todo_left = today_left;
131 134 var issue_todo = $("#task-todo-" + $(element).attr("id"));
132 135 if (issue_todo.size() > 0){
133 136 todo_left = issue_todo.first().position().left;
134 137 }
135 138 arr.push({left: Math.min(today_left, todo_left), top: element_top_center});
136 139 }
137 140 }
138 141 });
139 142 return arr;
140 143 }
141 144
142 145 function drawGanttProgressLines() {
143 146 var arr = getProgressLinesArray();
144 147 var color = $("#today_line")
145 148 .css("border-left-color");
146 149 var i;
147 150 for(i = 1 ; i < arr.length ; i++) {
148 151 if (!("none_stroke" in arr[i]) &&
149 152 (!("is_right_edge" in arr[i - 1] && "is_right_edge" in arr[i]) &&
150 153 !("is_left_edge" in arr[i - 1] && "is_left_edge" in arr[i]))
151 154 ) {
152 155 var x1 = (arr[i - 1].left == 0) ? 0 : arr[i - 1].left + draw_left;
153 156 var x2 = (arr[i].left == 0) ? 0 : arr[i].left + draw_left;
154 157 draw_gantt.path(["M", x1, arr[i - 1].top,
155 158 "L", x2, arr[i].top])
156 159 .attr({stroke: color, "stroke-width": 2});
157 160 }
158 161 }
159 162 }
160 163
161 164 function drawGanttHandler() {
162 165 var folder = document.getElementById('gantt_draw_area');
163 166 if(draw_gantt != null)
164 167 draw_gantt.clear();
165 168 else
166 169 draw_gantt = Raphael(folder);
167 170 setDrawArea();
168 171 if ($("#draw_progress_line").prop('checked'))
169 172 drawGanttProgressLines();
170 173 if ($("#draw_relations").prop('checked'))
171 174 drawRelations();
172 175 }
@@ -1,78 +1,81
1 /* Redmine - project management software
2 Copyright (C) 2006-2015 Jean-Philippe Lang */
3
1 4 // Automatic project identifier generation
2 5
3 6 function generateProjectIdentifier(identifier, maxlength) {
4 7 var diacriticsMap = [
5 8 {'base':'a', 'letters':/[\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g},
6 9 {'base':'aa','letters':/[\uA733\uA732]/g},
7 10 {'base':'ae','letters':/[\u00E4\u00E6\u01FD\u01E3\u00C4\u00C6\u01FC\u01E2]/g},
8 11 {'base':'ao','letters':/[\uA735\uA734]/g},
9 12 {'base':'au','letters':/[\uA737\uA736]/g},
10 13 {'base':'av','letters':/[\uA739\uA73B\uA738\uA73A]/g},
11 14 {'base':'ay','letters':/[\uA73D\uA73C]/g},
12 15 {'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},
13 16 {'base':'c', 'letters':/[\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E]/g},
14 17 {'base':'d', 'letters':/[\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779]/g},
15 18 {'base':'dz','letters':/[\u01F3\u01C6\u01F1\u01C4\u01F2\u01C5]/g},
16 19 {'base':'e', 'letters':/[\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E]/g},
17 20 {'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},
18 21 {'base':'g', 'letters':/[\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E]/g},
19 22 {'base':'h', 'letters':/[\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D]/g},
20 23 {'base':'hv','letters':/[\u0195]/g},
21 24 {'base':'i', 'letters':/[\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197]/g},
22 25 {'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249\u004A\u24BF\uFF2A\u0134\u0248]/g},
23 26 {'base':'k', 'letters':/[\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2]/g},
24 27 {'base':'l', 'letters':/[\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780]/g},
25 28 {'base':'lj','letters':/[\u01C9\u01C7\u01C8]/g},
26 29 {'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},
27 30 {'base':'n', 'letters':/[\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4]/g},
28 31 {'base':'nj','letters':/[\u01CC\u01CA\u01CB]/g},
29 32 {'base':'o', 'letters':/[\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C]/g},
30 33 {'base':'oe','letters': /[\u00F6\u0153\u00D6\u0152]/g},
31 34 {'base':'oi','letters':/[\u01A3\u01A2]/g},
32 35 {'base':'ou','letters':/[\u0223\u0222]/g},
33 36 {'base':'oo','letters':/[\uA74F\uA74E]/g},
34 37 {'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},
35 38 {'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},
36 39 {'base':'r','letters':/[\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782]/g},
37 40 {'base':'s','letters':/[\u0073\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784]/g},
38 41 {'base':'ss','letters':/[\u00DF]/g},
39 42 {'base':'t','letters':/[\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786]/g},
40 43 {'base':'tz','letters':/[\uA729\uA728]/g},
41 44 {'base':'u','letters':/[\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244]/g},
42 45 {'base':'ue','letters':/[\u00FC\u00DC]/g},
43 46 {'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},
44 47 {'base':'vy','letters':/[\uA761\uA760]/g},
45 48 {'base':'w','letters':/[\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72]/g},
46 49 {'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},
47 50 {'base':'y','letters':/[\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE]/g},
48 51 {'base':'z','letters':/[\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762]/g}
49 52 ];
50 53
51 54 for(var i=0; i<diacriticsMap.length; i++) {
52 55 identifier = identifier.replace(diacriticsMap[i].letters, diacriticsMap[i].base);
53 56 }
54 57 identifier = identifier.replace(/[^a-z0-9_]+/gi, '-'); // remaining non-alphanumeric => hyphen
55 58 identifier = identifier.replace(/^[-_\d]*|[-_]*$/g, ''); // remove hyphens/underscores and numbers at beginning and hyphens/underscores at end
56 59 identifier = identifier.toLowerCase(); // to lower
57 60 identifier = identifier.substr(0, maxlength); // max characters
58 61 return identifier;
59 62 }
60 63
61 64 function autoFillProjectIdentifier() {
62 65 var locked = ($('#project_identifier').val() != '');
63 66 var maxlength = parseInt($('#project_identifier').attr('maxlength'));
64 67
65 68 $('#project_name').keyup(function(){
66 69 if(!locked) {
67 70 $('#project_identifier').val(generateProjectIdentifier($('#project_name').val(), maxlength));
68 71 }
69 72 });
70 73
71 74 $('#project_identifier').keyup(function(){
72 75 locked = ($('#project_identifier').val() != '' && $('#project_identifier').val() != generateProjectIdentifier($('#project_name').val(), maxlength));
73 76 });
74 77 }
75 78
76 79 $(document).ready(function(){
77 80 autoFillProjectIdentifier();
78 81 });
@@ -1,33 +1,36
1 /* Redmine - project management software
2 Copyright (C) 2006-2015 Jean-Philippe Lang */
3
1 4 $(document).ready(function() {
2 5 /*
3 6 If we're viewing a tag or branch, don't display it in the
4 7 revision box
5 8 */
6 9 var branch_selected = $('#branch').length > 0 && $('#rev').val() == $('#branch').val();
7 10 var tag_selected = $('#tag').length > 0 && $('#rev').val() == $('#tag').val();
8 11 if (branch_selected || tag_selected) {
9 12 $('#rev').val('');
10 13 }
11 14
12 15 /*
13 16 Copy the branch/tag value into the revision box, then disable
14 17 the dropdowns before submitting the form
15 18 */
16 19 $('#branch,#tag').change(function() {
17 20 $('#rev').val($(this).val());
18 21 $('#branch,#tag').attr('disabled', true);
19 22 $(this).parent().submit();
20 23 $('#branch,#tag').removeAttr('disabled');
21 24 });
22 25
23 26 /*
24 27 Disable the branch/tag dropdowns before submitting the revision form
25 28 */
26 29 $('#rev').keydown(function(e) {
27 30 if (e.keyCode == 13) {
28 31 $('#branch,#tag').attr('disabled', true);
29 32 $(this).parent().submit();
30 33 $('#branch,#tag').removeAttr('disabled');
31 34 }
32 35 });
33 36 })
@@ -1,94 +1,97
1 /* Redmine - project management software
2 Copyright (C) 2006-2015 Jean-Philippe Lang */
3
1 4 var revisionGraph = null;
2 5
3 6 function drawRevisionGraph(holder, commits_hash, graph_space) {
4 7 var XSTEP = 20,
5 8 CIRCLE_INROW_OFFSET = 10;
6 9 var commits_by_scmid = commits_hash,
7 10 commits = $.map(commits_by_scmid, function(val,i){return val;});
8 11 var max_rdmid = commits.length - 1;
9 12 var commit_table_rows = $('table.changesets tr.changeset');
10 13
11 14 // create graph
12 15 if(revisionGraph != null)
13 16 revisionGraph.clear();
14 17 else
15 18 revisionGraph = Raphael(holder);
16 19
17 20 var top = revisionGraph.set();
18 21 // init dimensions
19 22 var graph_x_offset = commit_table_rows.first().find('td').first().position().left - $(holder).position().left,
20 23 graph_y_offset = $(holder).position().top,
21 24 graph_right_side = graph_x_offset + (graph_space + 1) * XSTEP,
22 25 graph_bottom = commit_table_rows.last().position().top + commit_table_rows.last().height() - graph_y_offset;
23 26
24 27 revisionGraph.setSize(graph_right_side, graph_bottom);
25 28
26 29 // init colors
27 30 var colors = [];
28 31 Raphael.getColor.reset();
29 32 for (var k = 0; k <= graph_space; k++) {
30 33 colors.push(Raphael.getColor());
31 34 }
32 35
33 36 var parent_commit;
34 37 var x, y, parent_x, parent_y;
35 38 var path, title;
36 39 var revision_dot_overlay;
37 40 $.each(commits, function(index, commit) {
38 41 if (!commit.hasOwnProperty("space"))
39 42 commit.space = 0;
40 43
41 44 y = commit_table_rows.eq(max_rdmid - commit.rdmid).position().top - graph_y_offset + CIRCLE_INROW_OFFSET;
42 45 x = graph_x_offset + XSTEP / 2 + XSTEP * commit.space;
43 46 revisionGraph.circle(x, y, 3)
44 47 .attr({
45 48 fill: colors[commit.space],
46 49 stroke: 'none'
47 50 }).toFront();
48 51 // paths to parents
49 52 $.each(commit.parent_scmids, function(index, parent_scmid) {
50 53 parent_commit = commits_by_scmid[parent_scmid];
51 54 if (parent_commit) {
52 55 if (!parent_commit.hasOwnProperty("space"))
53 56 parent_commit.space = 0;
54 57
55 58 parent_y = commit_table_rows.eq(max_rdmid - parent_commit.rdmid).position().top - graph_y_offset + CIRCLE_INROW_OFFSET;
56 59 parent_x = graph_x_offset + XSTEP / 2 + XSTEP * parent_commit.space;
57 60 if (parent_commit.space == commit.space) {
58 61 // vertical path
59 62 path = revisionGraph.path([
60 63 'M', x, y,
61 64 'V', parent_y]);
62 65 } else {
63 66 // path to a commit in a different branch (Bezier curve)
64 67 path = revisionGraph.path([
65 68 'M', x, y,
66 69 'C', x, y, x, y + (parent_y - y) / 2, x + (parent_x - x) / 2, y + (parent_y - y) / 2,
67 70 'C', x + (parent_x - x) / 2, y + (parent_y - y) / 2, parent_x, parent_y-(parent_y-y)/2, parent_x, parent_y]);
68 71 }
69 72 } else {
70 73 // vertical path ending at the bottom of the revisionGraph
71 74 path = revisionGraph.path([
72 75 'M', x, y,
73 76 'V', graph_bottom]);
74 77 }
75 78 path.attr({stroke: colors[commit.space], "stroke-width": 1.5}).toBack();
76 79 });
77 80 revision_dot_overlay = revisionGraph.circle(x, y, 10);
78 81 revision_dot_overlay
79 82 .attr({
80 83 fill: '#000',
81 84 opacity: 0,
82 85 cursor: 'pointer',
83 86 href: commit.href
84 87 });
85 88
86 89 if(commit.refs != null && commit.refs.length > 0) {
87 90 title = document.createElementNS(revisionGraph.canvas.namespaceURI, 'title');
88 91 title.appendChild(document.createTextNode(commit.refs));
89 92 revision_dot_overlay.node.appendChild(title);
90 93 }
91 94 top.push(revision_dot_overlay);
92 95 });
93 96 top.toFront();
94 97 };
General Comments 0
You need to be logged in to leave comments. Login now