| 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 |
});
|