Created
March 1, 2012 21:22
-
-
Save shesek/1953329 to your computer and use it in GitHub Desktop.
Trac multi project UI enhancement
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Just some small UI enhancement for multi-projects. In my setup, I have an `project` custom field and | |
* "project/" prefixes for the component, version and milestones fields (e.g. "AwesomeProject/1.2" as a, | |
* version, "SomeProject/User" as a component, etc). This JavaScript hides the irrelevant components/versions/ | |
* milestones on the ticket creation/edit forms according to the selected project, adds some navigation | |
* to the roadmap page to only show milestones of a specific project and creates links for the project-specific | |
* roadmap page (using the hash). | |
*/ | |
(function($){ | |
var project={ | |
init: function(){ | |
// Identify current page | |
if (window.location.pathname.indexOf('/newticket') !== -1 || window.location.pathname.indexOf('/ticket/') !== -1) { | |
this.ticket.init(); | |
} | |
else if (window.location.pathname.indexOf('/roadmap') !== -1) { | |
this.roadmap.init(); | |
} | |
}, | |
// # Ticket creation/updating handling | |
ticket:{ | |
// In order to hide/show <option>s, I'm moving them back and forward between the 'real' select element and an anonymous/hidden. Why can't we just apply display:none to <option>s? :( | |
init:function(){ | |
// I'm not using [value*=/] as project selector, because it causes all values that contains "/" in them without a valid project before it to be not accesible at all. | |
var self=this, projectSelector = $('#field-project option').map(function(){return 'option[value^='+this.value+'/]';}).get().join(','); | |
this.opt=$('#field-version, #field-component, #field-milestone').each(function(){ | |
// For each field, create an anonymous select element and move all project-specific options to it (which also makes them invisible) | |
var $t=$(this); | |
$t.data('load_val', $t.val()).data('opt', $(document.createElement('select')).append($t.find(projectSelector).each(function(){$(this).data('parent', $(this).parent());}).attr('isproject',1))); | |
}); | |
// Bind setProject() to the change event + call setProject() with current val | |
this.setProject($('#field-project').change(function(){self.setProject(this.value);}).val()); | |
}, | |
setProject: function(name) { | |
this.opt.each(function(){ | |
// Move all project-specific options from 'real' select to anonymous select, than find options related to current project on the anonymous select and move to 'real' select | |
var $t=$(this); | |
$t.data('opt').append($('option[isproject=1]',this)).find('option[value^='+name+'/]').each(function(){$(this).appendTo($(this).data('parent'));}); | |
// $t.append($t.data('opt').append($('option[isproject=1]',this)).find('option[value^='+name+'/]')); | |
$t.data('load_val') && $t.val($t.data('load_val')).data('load_val',null); // Re-set value that was there during page load and reset load_val | |
}); | |
} | |
}, | |
// # Roadmap handling | |
roadmap: { | |
init: function() { | |
var added={}; | |
// Create a <ul> for list of projects | |
var list = $(document.createElement('ul')).css({listStyleType:'none'}). | |
// Add a 'Display:' label | |
append($(document.createElement('li')).text('Display:').css({fontWeight:'bold',display:'inline',marginRight:25})). | |
// Add an 'All' option | |
append($(document.createElement('li')).addClass('link').text('All').click(function(){project.roadmap.setProject(null)})) | |
// Add a clear:both element after the list | |
//.after($(document.createElement('div')).css({clear:'both'})) | |
; | |
// Iterate over all milestones, add a 'project' attribute and add an <li> with all projects to the list | |
$('li.milestone').each(function(){ | |
var t=$(this),text=t.find('h2 a em').text(), index=text.lastIndexOf('/'); // lastIndexOf is used to support 'subprojects' - foo/bar/baz is considered milestone 'baz' under project 'foo/bar' | |
if (index !== -1){ | |
var name = text.substr(0, index); | |
t.attr('project', name); | |
if (!added[name]) { | |
added[name]=1; | |
$(document.createElement('li')).addClass('link').text(name).click(function(){project.roadmap.setProject(name)}).appendTo(list); | |
} | |
} | |
}); | |
list.find('li.link').css({color:'#BB0000',display:'inline',marginRight:15,cursor:'pointer'}); | |
// Add our <ul> after the 'Roadmap' title | |
$('.roadmap h1').eq(0).after(list); | |
if (document.location.hash.indexOf('#project=') === 0) { | |
this.setProject(document.location.hash.substr(9)); | |
} | |
}, | |
setProject: function(project){ | |
if (project !== null) { | |
$('li.milestone').hide().filter('[project='+project+']').show(); | |
document.location.hash = '#project=' + project; | |
} | |
else { | |
$('li.milestone').show(); | |
document.location.hash = ''; | |
} | |
} | |
} | |
}; | |
$(function(){project.init();}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment