1 |
1 |
/* Redmine - project management software
|
2 |
2 |
Copyright (C) 2006-2022 Jean-Philippe Lang */
|
3 |
3 |
|
4 |
|
var contextMenuObserving;
|
|
4 |
var observing;
|
5 |
5 |
|
6 |
|
function contextMenuRightClick(event) {
|
|
6 |
function rightClick(event) {
|
7 |
7 |
var target = $(event.target);
|
8 |
8 |
if (target.is('a:not(.js-contextmenu)')) {return;}
|
9 |
9 |
var tr = target.closest('.hascontextmenu').first();
|
10 |
10 |
if (tr.length < 1) {return;}
|
11 |
11 |
event.preventDefault();
|
12 |
|
if (!contextMenuIsSelected(tr)) {
|
13 |
|
contextMenuUnselectAll();
|
14 |
|
contextMenuAddSelection(tr);
|
15 |
|
contextMenuSetLastSelected(tr);
|
|
12 |
if (!isSelected(tr)) {
|
|
13 |
unselectAll();
|
|
14 |
addSelection(tr);
|
|
15 |
setLastSelected(tr);
|
16 |
16 |
}
|
17 |
|
contextMenuShow(event);
|
|
17 |
show(event);
|
18 |
18 |
}
|
19 |
19 |
|
20 |
|
function contextMenuClick(event) {
|
|
20 |
function click(event) {
|
21 |
21 |
var target = $(event.target);
|
22 |
22 |
var lastSelected;
|
23 |
23 |
|
... | ... | |
25 |
25 |
event.preventDefault();
|
26 |
26 |
return;
|
27 |
27 |
}
|
28 |
|
contextMenuHide();
|
|
28 |
hide();
|
29 |
29 |
if (target.is('a') || target.is('img')) { return; }
|
30 |
30 |
if (event.which == 1 || (navigator.appVersion.match(/\bMSIE\b/))) {
|
31 |
31 |
var tr = target.closest('.hascontextmenu').first();
|
... | ... | |
45 |
45 |
}
|
46 |
46 |
} else {
|
47 |
47 |
if (event.ctrlKey || event.metaKey) {
|
48 |
|
contextMenuToggleSelection(tr);
|
49 |
|
contextMenuClearDocumentSelection();
|
|
48 |
toggleSelection(tr);
|
|
49 |
clearDocumentSelection();
|
50 |
50 |
} else if (event.shiftKey) {
|
51 |
|
lastSelected = contextMenuLastSelected();
|
|
51 |
lastSelected = getLastSelected();
|
52 |
52 |
if (lastSelected.length) {
|
53 |
53 |
var toggling = false;
|
54 |
54 |
$('.hascontextmenu').each(function(){
|
55 |
55 |
if (toggling || $(this).is(tr)) {
|
56 |
|
contextMenuAddSelection($(this));
|
57 |
|
contextMenuClearDocumentSelection();
|
|
56 |
addSelection($(this));
|
|
57 |
clearDocumentSelection();
|
58 |
58 |
}
|
59 |
59 |
if ($(this).is(tr) || $(this).is(lastSelected)) {
|
60 |
60 |
toggling = !toggling;
|
61 |
61 |
}
|
62 |
62 |
});
|
63 |
63 |
} else {
|
64 |
|
contextMenuAddSelection(tr);
|
|
64 |
addSelection(tr);
|
65 |
65 |
}
|
66 |
66 |
} else {
|
67 |
|
contextMenuUnselectAll();
|
68 |
|
contextMenuAddSelection(tr);
|
|
67 |
unselectAll();
|
|
68 |
addSelection(tr);
|
69 |
69 |
}
|
70 |
|
contextMenuSetLastSelected(tr);
|
|
70 |
setLastSelected(tr);
|
71 |
71 |
}
|
72 |
72 |
} else {
|
73 |
73 |
// click is outside the rows
|
... | ... | |
76 |
76 |
} else if (target.is('.toggle-selection') || target.is('.ui-dialog *') || $('#ajax-modal').is(':visible')) {
|
77 |
77 |
// nop
|
78 |
78 |
} else {
|
79 |
|
contextMenuUnselectAll();
|
|
79 |
unselectAll();
|
80 |
80 |
}
|
81 |
81 |
}
|
82 |
82 |
}
|
83 |
83 |
}
|
84 |
84 |
|
85 |
|
function contextMenuCreate() {
|
|
85 |
function create() {
|
86 |
86 |
if ($('#context-menu').length < 1) {
|
87 |
87 |
var menu = document.createElement("div");
|
88 |
88 |
menu.setAttribute("id", "context-menu");
|
... | ... | |
91 |
91 |
}
|
92 |
92 |
}
|
93 |
93 |
|
94 |
|
function contextMenuShow(event) {
|
|
94 |
function show(event) {
|
95 |
95 |
var mouse_x = event.pageX;
|
96 |
96 |
var mouse_y = event.pageY;
|
97 |
97 |
var mouse_y_c = event.clientY;
|
... | ... | |
161 |
161 |
});
|
162 |
162 |
}
|
163 |
163 |
|
164 |
|
function contextMenuSetLastSelected(tr) {
|
|
164 |
function setLastSelected(tr) {
|
165 |
165 |
$('.cm-last').removeClass('cm-last');
|
166 |
166 |
tr.addClass('cm-last');
|
167 |
167 |
}
|
168 |
168 |
|
169 |
|
function contextMenuLastSelected() {
|
|
169 |
function getLastSelected() {
|
170 |
170 |
return $('.cm-last').first();
|
171 |
171 |
}
|
172 |
172 |
|
173 |
|
function contextMenuUnselectAll() {
|
|
173 |
function unselectAll() {
|
174 |
174 |
$('input[type=checkbox].toggle-selection').prop('checked', false);
|
175 |
175 |
$('.hascontextmenu').each(function(){
|
176 |
|
contextMenuRemoveSelection($(this));
|
|
176 |
removeSelection($(this));
|
177 |
177 |
});
|
178 |
178 |
$('.cm-last').removeClass('cm-last');
|
179 |
179 |
}
|
180 |
180 |
|
181 |
|
function contextMenuHide() {
|
|
181 |
function hide() {
|
182 |
182 |
$('#context-menu').hide();
|
183 |
183 |
}
|
184 |
184 |
|
185 |
|
function contextMenuToggleSelection(tr) {
|
186 |
|
if (contextMenuIsSelected(tr)) {
|
187 |
|
contextMenuRemoveSelection(tr);
|
|
185 |
function toggleSelection(tr) {
|
|
186 |
if (isSelected(tr)) {
|
|
187 |
removeSelection(tr);
|
188 |
188 |
} else {
|
189 |
|
contextMenuAddSelection(tr);
|
|
189 |
addSelection(tr);
|
190 |
190 |
}
|
191 |
191 |
}
|
192 |
192 |
|
193 |
|
function contextMenuAddSelection(tr) {
|
|
193 |
function addSelection(tr) {
|
194 |
194 |
tr.addClass('context-menu-selection');
|
195 |
|
contextMenuCheckSelectionBox(tr, true);
|
|
195 |
checkSelectionBox(tr, true);
|
196 |
196 |
}
|
197 |
197 |
|
198 |
|
function contextMenuRemoveSelection(tr) {
|
|
198 |
function removeSelection(tr) {
|
199 |
199 |
tr.removeClass('context-menu-selection');
|
200 |
|
contextMenuCheckSelectionBox(tr, false);
|
|
200 |
checkSelectionBox(tr, false);
|
201 |
201 |
}
|
202 |
202 |
|
203 |
|
function contextMenuIsSelected(tr) {
|
|
203 |
function isSelected(tr) {
|
204 |
204 |
return tr.hasClass('context-menu-selection');
|
205 |
205 |
}
|
206 |
206 |
|
207 |
|
function contextMenuCheckSelectionBox(tr, checked) {
|
|
207 |
function checkSelectionBox(tr, checked) {
|
208 |
208 |
tr.find('input[type=checkbox]').prop('checked', checked);
|
209 |
209 |
}
|
210 |
210 |
|
211 |
|
function contextMenuClearDocumentSelection() {
|
|
211 |
function clearDocumentSelection() {
|
212 |
212 |
// TODO
|
213 |
213 |
if (document.selection) {
|
214 |
214 |
document.selection.empty(); // IE
|
... | ... | |
217 |
217 |
}
|
218 |
218 |
}
|
219 |
219 |
|
220 |
|
function contextMenuInit() {
|
221 |
|
contextMenuCreate();
|
222 |
|
contextMenuUnselectAll();
|
|
220 |
function init() {
|
|
221 |
create();
|
|
222 |
unselectAll();
|
223 |
223 |
|
224 |
|
if (!contextMenuObserving) {
|
225 |
|
$(document).click(contextMenuClick);
|
226 |
|
$(document).contextmenu(contextMenuRightClick);
|
227 |
|
$(document).on('click', '.js-contextmenu', contextMenuRightClick);
|
228 |
|
contextMenuObserving = true;
|
|
224 |
if (!observing) {
|
|
225 |
$(document).click(click);
|
|
226 |
$(document).contextmenu(rightClick);
|
|
227 |
$(document).on('click', '.js-contextmenu', rightClick);
|
|
228 |
observing = true;
|
229 |
229 |
}
|
230 |
230 |
}
|
231 |
231 |
|
... | ... | |
252 |
252 |
}
|
253 |
253 |
|
254 |
254 |
$(document).ready(function(){
|
255 |
|
contextMenuInit();
|
|
255 |
init();
|
256 |
256 |
$('input[type=checkbox].toggle-selection').on('change', toggleIssuesSelection);
|
257 |
257 |
});
|