OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openproject/app/assets/javascripts/application.js.erb

428 lines
18 KiB

//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
//= require lib/jquery.colorcontrast
//= require lib/jquery.trap
//= require lib/jquery.is_visible_within
//= require top_menu
//= require action_menu
//= require breadcrumb
//= require findDomElement
//= require settings
//= require modal
//= require tab_handling
//= require openproject_plugins
//= require versions
//= require forums
//= require_tree ./specific
//= require custom-fields
//= require date-range
//= require search
//= require colors
//= require tooltips
//= require danger_zone_validation
//= require flash_messages
jQuery(document).ready(function ($) {
//remove modal layout=false if we ctrl-click!
jQuery(document.body).on("click", "a", function (e) {
if (top != self && e.ctrlKey) {
if (e.target && e.target.href) {
var url = e.target.href;
if (url.match(/(&)?layout=false/)) {
url = url.replace(/(&)?layout=false/g, "").replace(/\?$/, "");
window.open(url);
e.preventDefault();
}
}
}
});
});
function checkAll(selector, checked) {
jQuery('#' + selector + ' input:checkbox').not(':disabled').each(function() {
this.checked = checked;
});
}
function toggleCheckboxesBySelector(selector) {
boxes = jQuery(selector);
var all_checked = true;
for (i = 0; i < boxes.length; i++) { if (boxes[i].checked === false) { all_checked = false; } }
for (i = 0; i < boxes.length; i++) { boxes[i].checked = !all_checked; }
}
function setCheckboxesBySelector(checked, selector) {
var boxes = $(selector);
boxes.each(function(ele) {
ele.checked = checked;
});
}
var fileFieldCount = 1;
function addFileField() {
fileFieldCount++;
if (fileFieldCount >= 10) return false;
var clone = jQuery('#attachment_template').clone(true);
clone.removeAttr('id');
clone.html(clone.html().replace(/\[1\]/g, '['+ fileFieldCount + ']'));
jQuery('#attachments_fields').append(clone);
}
function randomKey(size) {
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');
var key = '';
for (i = 0; i < size; i++) {
key += chars[Math.floor(Math.random() * chars.length)];
}
return key;
}
// Automatic project identifier generation
var projectIdentifierLocked;
var projectIdentifierDefault;
var projectIdentifierMaxLength;
function generateProjectIdentifier() {
var identifier = jQuery('#project_name').val(); // project name
var diacriticsMap = [
{'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},
{'base':'aa','letters':/[\uA733\uA732]/g},
{'base':'ae','letters':/[\u00E4\u00E6\u01FD\u01E3\u00C4\u00C6\u01FC\u01E2]/g},
{'base':'ao','letters':/[\uA735\uA734]/g},
{'base':'au','letters':/[\uA737\uA736]/g},
{'base':'av','letters':/[\uA739\uA73B\uA738\uA73A]/g},
{'base':'ay','letters':/[\uA73D\uA73C]/g},
{'base':'b', 'letters':/[\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181]/g},
{'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},
{'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},
{'base':'dz','letters':/[\u01F3\u01C6\u01F1\u01C4\u01F2\u01C5]/g},
{'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},
{'base':'f', 'letters':/[\u0066\u24D5\uFF46\u1E1F\u0192\uA77C\u0046\u24BB\uFF26\u1E1E\u0191\uA77B]/g},
{'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},
{'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},
{'base':'hv','letters':/[\u0195]/g},
{'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},
{'base':'j', 'letters':/[\u006A\u24D9\uFF4A\u0135\u01F0\u0249\u004A\u24BF\uFF2A\u0134\u0248]/g},
{'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},
{'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},
{'base':'lj','letters':/[\u01C9\u01C7\u01C8]/g},
{'base':'m', 'letters':/[\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C]/g},
{'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},
{'base':'nj','letters':/[\u01CC\u01CA\u01CB]/g},
{'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},
{'base':'oe','letters': /[\u00F6\u0153\u00D6\u0152]/g},
{'base':'oi','letters':/[\u01A3\u01A2]/g},
{'base':'ou','letters':/[\u0223\u0222]/g},
{'base':'oo','letters':/[\uA74F\uA74E]/g},
{'base':'p','letters':/[\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754]/g},
{'base':'q','letters':/[\u0071\u24E0\uFF51\u024B\uA757\uA759\u0051\u24C6\uFF31\uA756\uA758\u024A]/g},
{'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},
{'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},
{'base':'ss','letters':/[\u00DF]/g},
{'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},
{'base':'tz','letters':/[\uA729\uA728]/g},
{'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},
{'base':'ue','letters':/[\u00FC\u00DC]/g},
{'base':'v','letters':/[\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245]/g},
{'base':'vy','letters':/[\uA761\uA760]/g},
{'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},
{'base':'x','letters':/[\u0078\u24E7\uFF58\u1E8B\u1E8D\u0058\u24CD\uFF38\u1E8A\u1E8C]/g},
{'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},
{'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}
];
for(var i=0; i<diacriticsMap.length; i++) {
identifier = identifier.replace(diacriticsMap[i].letters, diacriticsMap[i].base);
}
identifier = identifier.replace(/[^a-z0-9]+/gi, '-'); // remaining non-alphanumeric => hyphen
identifier = identifier.replace(/^[-\d]*|-*$/g, ''); // remove hyphens and numbers at beginning and hyphens at end
identifier = identifier.toLowerCase(); // to lower
identifier = identifier.substr(0,projectIdentifierMaxLength); // max characters
return identifier;
}
function observeProjectName() {
jQuery('#project_name').keyup(function() {
if(!projectIdentifierLocked) {
jQuery('#project_identifier').val(generateProjectIdentifier());
}
});
}
function observeProjectIdentifier() {
jQuery('#project_identifier').keyup(function() {
if(jQuery('#project_identifier').getValue() !== '' &&
jQuery('#project_identifier').getValue() != generateProjectIdentifier()) {
projectIdentifierLocked = true;
} else {
projectIdentifierLocked = false;
}
});
}
function hideOnLoad() {
jQuery('.hol').hide();
}
jQuery(hideOnLoad);
function addClickEventToAllErrorMessages() {
jQuery('a.afocus').each(function() {
var target = jQuery(this);
target.click(function(evt) {
var field = jQuery('#' + target.readAttribute('href').substr(1));
if (field === null) {
// Cut off '_id' (necessary for select boxes)
field = jQuery('#' + target.readAttribute('href').substr(1).concat('_id'));
}
if (field) {
field.down('input, textarea, select').focus();
}
target.unbind(evt);
return false;
});
});
}
// a few constants for animations speeds, etc.
var animationRate = 100;
/* jQuery code from #263 */
// returns viewport height
jQuery.viewportHeight = function() {
return self.innerHeight ||
jQuery.boxModel && document.documentElement.clientHeight ||
document.body.clientHeight;
};
/*
* 1 - registers a callback which copies the csrf token into the
* X-CSRF-Token header with each ajax request. Necessary to
* work with rails applications which have fixed
* CVE-2011-0447
* 2 - shows and hides ajax indicator
*/
jQuery(document).ready(function($) {
jQuery(document).ajaxSend(function (event, request) {
if ($(event.target.activeElement).closest('[ajax-indicated]').length &&
$('ajax-indicator')) {
$('#ajax-indicator').show();
}
var csrf_meta_tag = $('meta[name=csrf-token]');
if (csrf_meta_tag) {
var header = 'X-CSRF-Token',
token = csrf_meta_tag.attr('content');
request.setRequestHeader(header, token);
}
request.setRequestHeader('X-Authentication-Scheme', "Session");
});
// ajaxStop gets called when ALL Requests finish, so we won't need a counter as in PT
jQuery(document).ajaxStop(function () {
if ($('#ajax-indicator')) {
$('#ajax-indicator').hide();
}
addClickEventToAllErrorMessages();
});
// file table thumbnails
jQuery("table a.has-thumb").hover(function() {
jQuery(this).removeAttr("title").toggleClass("active");
// grab the image dimensions to position it properly
var thumbImg = $(this).find("img");
var thumbImgLeft = -(thumbImg.outerWidth() );
var thumbImgTop = -(thumbImg.height() / 2 );
thumbImg.css({top: thumbImgTop, left: thumbImgLeft}).show();
}, function() {
jQuery(this).toggleClass("active").find("img").hide();
});
// show/hide the files table
jQuery(".attachments h4").click(function() {
jQuery(this).toggleClass("closed").next().slideToggle(animationRate);
});
jQuery(window).resize(function() {
// wait 200 milliseconds for no further resize event
// then readjust breadcrumb
if(this.resizeTO) clearTimeout(this.resizeTO);
this.resizeTO = setTimeout(function() {
jQuery(this).trigger('resizeEnd');
}, 200);
});
// Do not close the login window when using it
jQuery('#nav-login-content').click(function(event){
event.stopPropagation();
});
jQuery('table.cal div.issue.tooltip').each(function(){
var div = $(this);
div.find('a').first().focus(function(){
div.addClass('hover');
});
div.find('a').first().blur(function(){
div.removeClass('hover');
});
});
// Set focus on first error message
var error_focus = $('a.afocus').first();
var input_focus = $('.autofocus').first();
if (error_focus !== undefined) {
error_focus.focus();
}
else if (input_focus !== undefined){
input_focus.focus();
if (input_focus.tagName === "INPUT") {
input_focus.select();
}
}
// Focus on field with error
addClickEventToAllErrorMessages();
// Skip menu on content
jQuery('#skip-navigation--content').click(skipMenu);
// Click handler for formatting help
jQuery(document.body).on('click', '.formatting-help-link-button', function() {
window.open(window.appBasePath + '/help/wiki_syntax',
"",
"resizable=yes, location=no, width=600, height=640, menubar=no, status=no, scrollbars=yes"
);
return false;
});
});
var Administration = (function ($) {
var update_default_language_options,
init_language_selection_handling,
toggle_default_language_select;
update_default_language_options = function (input) {
var default_language_select = $('#setting_default_language select'),
default_language_select_active;
if (input.attr('checked')) {
default_language_select.find('option[value="' + input.val() + '"]').removeAttr('disabled');
} else {
default_language_select.find('option[value="' + input.val() + '"]').attr('disabled', 'disabled');
}
default_language_select_active = default_language_select.find('option:not([disabled="disabled"])');
toggle_disabled_state(default_language_select_active.length === 0);
if (default_language_select_active.length === 1) {
default_language_select_active.attr('selected', true);
} else if (default_language_select.val() === input.val() && !input.attr('checked')) {
default_language_select_active.first().attr('selected', true);
}
};
toggle_disabled_state = function (active) {
jQuery('#setting_default_language select').attr('disabled', active)
.closest('form')
.find('input:submit')
.attr('disabled', active);
};
init_language_selection_handling = function () {
jQuery('#setting_available_languages input:not([checked="checked"])').each(function (index, input) {
update_default_language_options($(input));
});
jQuery('#setting_available_languages input').click(function () {
update_default_language_options($(this));
});
};
return {
init_language_selection_handling: init_language_selection_handling
};
}(jQuery));
var activateFlash = function(selector) {
var flashMessages = jQuery(selector);
// Ignore flash messages of class 'ignored-by-flash-activation' because those
// messages are completely handled via JavaScript (see types_checkboxes.js for
// details). We wouldn't have to ignore this message if the flash element
// would be completely created via JavaScript and not available in the DOM by
// default.
flashMessages.each(function (ix, e) {
flashMessage = jQuery(e);
if (!flashMessage.hasClass('ignored-by-flash-activation')) {
flashMessage.show();
}
});
};
var activateFlashNotice = function () {
var notice = '.flash';
activateFlash(notice);
};
var activateFlashError = function () {
var error = '.errorExplanation[role="alert"]';
activateFlash(error);
};
var focusFirstErroneousField = function() {
var firstErrorSpan = jQuery('span.errorSpan').first();
var erroneousInput = firstErrorSpan.find('*').filter(":input");
erroneousInput.focus();
};
var setupServerResponse = function() {
initMainMenuExpandStatus();
focusFirstErroneousField();
activateFlashNotice();
activateFlashError();
jQuery(document).ajaxComplete(activateFlashNotice);
jQuery(document).ajaxComplete(activateFlashError);
};
jQuery(document).ready(setupServerResponse);