/* redMine - project management software Copyright (C) 2006-2008 Jean-Philippe Lang */ function checkAll (id, checked) { var els = Element.descendants(id); for (var i = 0; i < els.length; i++) { if (els[i].disabled==false) { els[i].checked = checked; } } } function toggleCheckboxesBySelector(selector) { boxes = $$(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; }); } function showAndScrollTo(id, focus) { Element.show(id); if (focus!=null) { Form.Element.focus(focus); } Element.scrollTo(id); } function toggleRowGroup(el) { var tr = Element.up(el, 'tr'); var n = Element.next(tr); tr.toggleClassName('open'); while (n != undefined && !n.hasClassName('group')) { Element.toggle(n); n = Element.next(n); } } function collapseAllRowGroups(el) { var tbody = Element.up(el, 'tbody'); tbody.childElements('tr').each(function(tr) { if (tr.hasClassName('group')) { tr.removeClassName('open'); } else { tr.hide(); } }) } function expandAllRowGroups(el) { var tbody = Element.up(el, 'tbody'); tbody.childElements('tr').each(function(tr) { if (tr.hasClassName('group')) { tr.addClassName('open'); } else { tr.show(); } }) } function toggleAllRowGroups(el) { var tr = Element.up(el, 'tr'); if (tr.hasClassName('open')) { collapseAllRowGroups(el); } else { expandAllRowGroups(el); } } function toggleFieldset(el) { var fieldset = Element.up(el, 'fieldset'); fieldset.toggleClassName('collapsed'); Effect.toggle(fieldset.down('div'), 'slide', {duration:0.2}); } function hideFieldset(el) { var fieldset = Element.up(el, 'fieldset'); fieldset.toggleClassName('collapsed'); fieldset.down('div').hide(); } var fileFieldCount = 1; function addFileField() { if (fileFieldCount >= 10) return false fileFieldCount++; var f = document.createElement("input"); f.type = "file"; f.name = "attachments[" + fileFieldCount + "][file]"; f.size = 30; var d = document.createElement("input"); d.type = "text"; d.name = "attachments[" + fileFieldCount + "][description]"; d.size = 60; var dLabel = new Element('label'); dLabel.addClassName('inline'); // Pulls the languge value used for Optional Description dLabel.update($('attachment_description_label_content').innerHTML) p = document.getElementById("attachments_fields"); p.appendChild(document.createElement("br")); p.appendChild(f); p.appendChild(dLabel); dLabel.appendChild(d); } function showTab(name) { var f = $$('div#content .tab-content'); for(var i=0; i0) { lis[i-1].show(); } } function displayTabsButtons() { var lis; var tabsWidth = 0; var i; $$('div.tabs').each(function(el) { lis = el.down('ul').childElements(); for (i=0; i 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() { var f = function() { if(!projectIdentifierLocked) { $('project_identifier').setValue(generateProjectIdentifier()); } }; Event.observe('project_name', 'keyup', f); } function observeProjectIdentifier() { var f = function() { if($('project_identifier').getValue() != '' && $('project_identifier').getValue() != generateProjectIdentifier()) { projectIdentifierLocked = true; } else { projectIdentifierLocked = false; } }; Event.observe('project_identifier', 'keyup', f); } function observeParentIssueField(url) { new Ajax.Autocompleter('issue_parent_issue_id', 'parent_issue_candidates', url, { minChars: 1, frequency: 0.5, paramName: 'q', updateElement: function(value) { document.getElementById('issue_parent_issue_id').value = value.id; }, parameters: 'scope=all' }); } function observeRelatedIssueField(url) { new Ajax.Autocompleter('relation_issue_to_id', 'related_issue_candidates', url, { minChars: 1, frequency: 0.5, paramName: 'q', updateElement: function(value) { document.getElementById('relation_issue_to_id').value = value.id; }, parameters: 'scope=all' }); } function setVisible(id, visible) { var el = $(id); if (el) {if (visible) {el.show();} else {el.hide();}} } function observeProjectModules() { var f = function() { /* Hides trackers and issues custom fields on the new project form when issue_tracking module is disabled */ var c = ($('project_enabled_module_names_issue_tracking').checked == true); setVisible('project_trackers', c); setVisible('project_issue_custom_fields', c); }; Event.observe(window, 'load', f); Event.observe('project_enabled_module_names_issue_tracking', 'change', f); } /* * Class used to warn user when leaving a page with unsaved textarea * Author: mathias.fischer@berlinonline.de */ var WarnLeavingUnsaved = Class.create({ observedForms: false, observedElements: false, changedForms: false, message: null, initialize: function(message){ this.observedForms = $$('form'); this.observedElements = $$('textarea'); this.message = message; this.observedElements.each(this.observeChange.bind(this)); this.observedForms.each(this.submitAction.bind(this)); window.onbeforeunload = this.unload.bind(this); }, unload: function(){ if(this.changedForms) return this.message; }, setChanged: function(){ this.changedForms = true; }, setUnchanged: function(){ this.changedForms = false; }, observeChange: function(element){ element.observe('change',this.setChanged.bindAsEventListener(this)); }, submitAction: function(element){ element.observe('submit',this.setUnchanged.bindAsEventListener(this)); } }); /* * 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 */ Ajax.Responders.register({ onCreate: function(request){ var csrf_meta_tag = $$('meta[name=csrf-token]')[0]; if (csrf_meta_tag) { var header = 'X-CSRF-Token', token = csrf_meta_tag.readAttribute('content'); if (!request.options.requestHeaders) { request.options.requestHeaders = {}; } request.options.requestHeaders[header] = token; } if ($('ajax-indicator') && Ajax.activeRequestCount > 0) { Element.show('ajax-indicator'); } }, onComplete: function(){ if ($('ajax-indicator') && Ajax.activeRequestCount == 0) { Element.hide('ajax-indicator'); } addClickEventToAllErrorMessages(); } }); function hideOnLoad() { $$('.hol').each(function(el) { el.hide(); }); } function addClickEventToAllErrorMessages() { $$('a.afocus').each(function(a) { $(a).observe('click', function(event) { var field; field = $($(a).readAttribute('href').substr(1)); if (field == null) { // Cut off '_id' (necessary for select boxes) field = $($(a).readAttribute('href').substr(1).concat('_id')); } field.down('input, textarea, select').focus(); Event.stop(event); return false; }); }); } $(document).observe('dom:loaded', function() { // Set focus on first error message var focus = $$('a.afocus').first(); if (focus != undefined) { focus.focus(); } // Focus on field with error addClickEventToAllErrorMessages(); }); Event.observe(window, 'load', hideOnLoad); // 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; }; /* TODO: integrate with existing code and/or refactor */ jQuery(document).ready(function($) { // file table thumbnails $("table a.has-thumb").hover(function() { $(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() { $(this).toggleClass("active").find("img").hide(); }); // show/hide the files table $(".attachments h4").click(function() { $(this).toggleClass("closed").next().slideToggle(animationRate); }); // custom function for sliding the main-menu. IE6 & IE7 don't handle sliding very well $.fn.slideAndFocus = function() { this.toggleClass("open").find("> ul").mySlide(function() { // actually a simple focus should be enough. // The rest is only there to work around a rendering bug in webkit (as of Oct 2011) TODO: fix if ($("input#username-pulldown").is(":visible")) { var input = $("input#username-pulldown"); } else { // reset input value and project search list var input = $(".chzn-search input"); input.val(""); $("select#project-search").trigger($.Event("liszt:updated")); } if (input.is(":visible")) { input.blur(); setTimeout(function() { input.focus(); }, 100); } else { $(this).find("li > a:first").focus(); } }); return false; }; // custom function for sliding the main-menu. IE6 & IE7 don't handle sliding very well $.fn.mySlide = function(callback) { if (parseInt($.browser.version, 10) < 8 && $.browser.msie) { // no animations, just toggle this.toggle(); if (callback != undefined) { callback(); } // this forces IE to redraw the menu area, un-bollocksing things $("#main-menu").css({paddingBottom:5}).animate({paddingBottom:0}, 10); } else { this.slideToggle(animationRate,callback); } return this; }; // open and close the main-menu sub-menus $("#main-menu li:has(ul) > a").not("ul ul a") .append("") .click(function() { $(this).toggleClass("open").parent().find("ul").not("ul ul ul").mySlide(); return false; }); // submenu flyouts $("#main-menu li li:has(ul)").hover(function() { $(this).find(".profile-box").show(); $(this).find("ul").slideDown(animationRate); }, function() { $(this).find("ul").slideUp(animationRate); }); // add filter dropdown menu $(".button-large:has(ul) > a").click(function(event) { var tgt = $(event.target); // is this inside the title bar? if (tgt.parents().is(".title-bar")) { $(".title-bar-extras:hidden").slideDown(animationRate); } $(this).parent().find("ul").slideToggle(animationRate); return false; }); jQuery("#account-nav > li").hover(function() { if ($("#account-nav").hasClass("hover") && ($("#account-nav > li.drop-down.open").get(0) !== $(this).get(0))){ //Close all other open menus //Used to work around the rendering bug TODO: fix jQuery("input#username-pulldown").blur(); $("#account-nav > li.drop-down.open").toggleClass("open").find("> ul").mySlide(); $(this).slideAndFocus(); return false; } }, function(){ return false; }); jQuery("#account-nav > li.drop-down").click(function() { if (($("#account-nav > li.drop-down.open").get(0) !== $(this).get(0))){ $("#account-nav > li.drop-down.open").toggleClass("open").find("> ul").mySlide(); } $(this).slideAndFocus(); $("#account-nav").toggleClass("hover"); return false; }); // deal with potentially problematic super-long titles $(".title-bar h2").css({paddingRight: $(".title-bar-actions").outerWidth() + 15 }); // rejigger the main-menu sub-menu functionality. $("#main-menu .toggler").remove(); // remove the togglers so they're inserted properly later. $("#main-menu li:has(ul) > a").not("ul ul a") // 1. unbind the current click functions .unbind("click") // 2. wrap each in a span that we'll use for the new click element .wrapInner("") // 3. reinsert the so that it sits outside of the above .append("") // 4. attach a new click function that will follow the link if you clicked on the span itself and toggle if not .click(function(event) { if (!$(event.target).hasClass("toggle-follow") ) { var menuParent = $(this).toggleClass("open").parent().find("ul").not("ul ul ul"); menuParent.mySlide(); if ($(this).hasClass("open")) { menuParent.find("li > a:first").focus(); } return false; } }); $('#header li.drop-down select.chzn-select').each(function (ix, select) { // trigger an artificial mousedown event var parent = $(select).parents('li.drop-down'); // deselect all options $(select).find(":selected").each(function (ix, option) { $(option).attr("selected", false); }); $(select).chosen({allow_single_deselect:false}); parent.find('div.chzn-container').trigger(jQuery.Event("mousedown")) parent.find('a.chzn-single').hide(); // prevent menu from getting closed prematurely jQuery('div.chzn-search').click(function(event){ event.stopPropagation(); }); // remove highlights parent.find(".chzn-results .active-result.highlighted").each(function (ix, option){ $(option).removeClass("highlighted"); }); }); $('html').click(function() { $("#header .drop-down.open").toggleClass("open").find("ul").mySlide(); $("#account-nav.hover").toggleClass("hover"); }); // Do not close the login window when using it $('#account-nav li li').click(function(event){ event.stopPropagation(); }); $('#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'); }); }); });