Commit 1b7ddb3c authored by Andrew Smith's avatar Andrew Smith Committed by Felix Schäfer

jQuery version of the issue context menu

parent 27160b76
......@@ -885,7 +885,7 @@ module ApplicationHelper
def context_menu(url)
unless @context_menu_included
content_for :header_tags do
javascript_include_tag('context_menu') +
javascript_include_tag('context_menu.jquery') +
stylesheet_link_tag('context_menu')
end
if l(:direction) == 'rtl'
......@@ -895,7 +895,7 @@ module ApplicationHelper
end
@context_menu_included = true
end
javascript_tag "new ContextMenu('#{ url_for(url) }')"
javascript_tag "jQuery(document).ContextMenu('#{ url_for(url) }')"
end
def context_menu_link(name, url, options={})
......
......@@ -138,9 +138,9 @@
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@issue.project} - #{@issue.tracker} ##{@issue.id}: #{@issue.subject}") %>
<%= stylesheet_link_tag 'scm' %>
<%= javascript_include_tag 'context_menu' %>
<%= javascript_include_tag 'context_menu.jquery' %>
<%= stylesheet_link_tag 'context_menu' %>
<%= stylesheet_link_tag 'context_menu_rtl' if l(:direction) == 'rtl' %>
<% end %>
<div id="context-menu" style="display: none;"></div>
<%= javascript_tag "new ContextMenu('#{issues_context_menu_path}')" %>
<%= javascript_tag "jQuery(document).ContextMenu('#{issues_context_menu_path}')" %>
(function($) {
var observingContextMenuClick;
var url;
var lastSelected;
var menu;
var menuId = 'context-menu';
var selectorName = 'hascontextmenu';
var contextMenuSelectionClass = 'context-menu-selection';
var reverseXClass = 'reverse-x';
var reverseYClass = 'reverse-y';
var methods = {
createMenu: function() {
if(!menu) {
$('#wrapper').append('<div id="' + menuId + '" style="display:none"></div>');
menu = $('#' + menuId);
}
},
click: function(e) {
var target = $(e.target);
if(target.is('a')) {
return;
}
switch(e.which) {
case 1:
if(e.type === 'click') {
methods.hideMenu();
methods.leftClick(e);
break;
}
case 3:
if(e.type === 'contextmenu') {
methods.hideMenu();
methods.rightClick(e);
break;
}
default:
return;
}
},
leftClick: function(e) {
var target = $(e.target);
var tr = target.parents('tr');
if((tr.size() > 0) && tr.hasClass(selectorName))
{
// a row was clicked, check if the click was on checkbox
if(target.is('input'))
{
// a checkbox may be clicked
if (target.is(':checked')) {
tr.addClass(contextMenuSelectionClass);
} else {
tr.removeClass(contextMenuSelectionClass);
}
}
else
{
if (e.ctrlKey || e.metaKey)
{
methods.toggleSelection(tr);
}
else if (e.shiftKey)
{
if (lastSelected !== null)
{
var toggling = false;
var rows = $(selectorName);
for (i = 0; i < rows.length; i++)
{
if (toggling || rows[i] == tr)
{
methods.addSelection(rows[i]);
}
if (rows[i] == tr || rows[i] == lastSelected)
{
toggling = !toggling;
}
}
} else {
methods.addSelection(tr);
}
} else {
methods.unselectAll();
methods.addSelection(tr);
}
lastSelected = tr;
}
}
else
{
// click is outside the rows
if (target.is('a') === false) {
this.unselectAll();
} else {
if (target.hasClass('disabled') || target.hasClass('submenu')) {
e.preventDefault();
}
}
}
},
rightClick: function(e) {
var target = $(e.target);
var tr = target.parents('tr');
if((tr.size() === 0) || !(tr.hasClass(selectorName))) {
return;
}
e.preventDefault();
if(!methods.isSelected(tr)) {
methods.unselectAll();
methods.addSelection(tr);
lastSelected = tr;
}
methods.showMenu(e);
},
unselectAll: function() {
var rows = $('.' + contextMenuSelectionClass);
rows.each(function() {
methods.removeSelection($(this));
});
},
hideMenu: function() {
menu.hide();
},
showMenu: function(e) {
var target = $(e.target);
var params = target.parents('form').serialize();
var mouseX = e.pageX;
var mouseY = e.pageY;
var renderX = mouseX;
var renderY = mouseY;
$.ajax({
url: url,
data: params,
success: function(response, success) {
menu.html(response);
var maxWidth = mouseX + (2 * menu.width());
var maxHeight = mouseY + menu.height();
if(maxWidth > $(window).width()) {
renderX -= menu.width();
menu.addClass(reverseXClass);
} else {
menu.removeClass(reverseXClass);
}
if(maxHeight > $(window).height()) {
renderY =+ menu.height();
menu.addClass(reverseYClass);
} else {
menu.removeClass(reverseYClass);
}
if(renderX <= 0) {
renderX = 1;
}
if(renderY <= 0) {
renderY = 1;
}
menu.css('top', renderY).css('left', renderX);
menu.show();
}
});
},
addSelection: function(element) {
element.addClass(contextMenuSelectionClass);
methods.checkSelectionBox(element, true);
},
isSelected: function(element) {
return element.hasClass(contextMenuSelectionClass);
},
toggleSelection: function(element) {
if(methods.isSelected(element)) {
methods.removeSelection(element);
} else {
methods.addSelection(element);
}
},
removeSelection: function(element) {
element.removeClass(contextMenuSelectionClass);
methods.checkSelectionBox(element, false);
},
checkSelectionBox: function(element, checked) {
var inputs = element.find('input');
inputs.each(function() {
inputs.attr('checked', checked ? 'checked' : false);
});
}
};
$.fn.ContextMenu = function(u) {
url = u;
methods.createMenu();
if(!observingContextMenuClick) {
$(document).bind('click.contextMenu', methods.click);
$(document).bind('contextmenu.contextMenu', methods.click);
observingContextMenuClick = true;
}
methods.unselectAll();
lastSelected = null;
};
})(jQuery);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment