To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / public / javascripts / context_menu.js @ 1298:4f746d8966dd
History | View | Annotate | Download (6.39 KB)
| 1 | 1115:433d4f72a19b | Chris | var contextMenuObserving;
|
|---|---|---|---|
| 2 | var contextMenuUrl;
|
||
| 3 | 0:513646585e45 | Chris | |
| 4 | 1115:433d4f72a19b | Chris | function contextMenuRightClick(event) { |
| 5 | var target = $(event.target); |
||
| 6 | if (target.is('a')) {return;} |
||
| 7 | var tr = target.parents('tr').first(); |
||
| 8 | if (!tr.hasClass('hascontextmenu')) {return;} |
||
| 9 | event.preventDefault(); |
||
| 10 | if (!contextMenuIsSelected(tr)) {
|
||
| 11 | contextMenuUnselectAll(); |
||
| 12 | contextMenuAddSelection(tr); |
||
| 13 | contextMenuSetLastSelected(tr); |
||
| 14 | } |
||
| 15 | contextMenuShow(event); |
||
| 16 | } |
||
| 17 | 0:513646585e45 | Chris | |
| 18 | 1115:433d4f72a19b | Chris | function contextMenuClick(event) { |
| 19 | var target = $(event.target); |
||
| 20 | var lastSelected;
|
||
| 21 | 0:513646585e45 | Chris | |
| 22 | 1115:433d4f72a19b | Chris | if (target.is('a') && target.hasClass('submenu')) { |
| 23 | event.preventDefault(); |
||
| 24 | return;
|
||
| 25 | } |
||
| 26 | contextMenuHide(); |
||
| 27 | if (target.is('a') || target.is('img')) { return; } |
||
| 28 | if (event.which == 1 || (navigator.appVersion.match(/\bMSIE\b/))) { |
||
| 29 | var tr = target.parents('tr').first(); |
||
| 30 | if (tr.length && tr.hasClass('hascontextmenu')) { |
||
| 31 | // a row was clicked, check if the click was on checkbox
|
||
| 32 | if (target.is('input')) { |
||
| 33 | // a checkbox may be clicked
|
||
| 34 | if (target.attr('checked')) { |
||
| 35 | tr.addClass('context-menu-selection');
|
||
| 36 | } else {
|
||
| 37 | tr.removeClass('context-menu-selection');
|
||
| 38 | } |
||
| 39 | } else {
|
||
| 40 | if (event.ctrlKey || event.metaKey) {
|
||
| 41 | contextMenuToggleSelection(tr); |
||
| 42 | } else if (event.shiftKey) { |
||
| 43 | lastSelected = contextMenuLastSelected(); |
||
| 44 | if (lastSelected.length) {
|
||
| 45 | var toggling = false; |
||
| 46 | $('.hascontextmenu').each(function(){ |
||
| 47 | if (toggling || $(this).is(tr)) { |
||
| 48 | contextMenuAddSelection($(this)); |
||
| 49 | } |
||
| 50 | if ($(this).is(tr) || $(this).is(lastSelected)) { |
||
| 51 | toggling = !toggling; |
||
| 52 | } |
||
| 53 | }); |
||
| 54 | 0:513646585e45 | Chris | } else {
|
| 55 | 1115:433d4f72a19b | Chris | contextMenuAddSelection(tr); |
| 56 | 0:513646585e45 | Chris | } |
| 57 | } else {
|
||
| 58 | 1115:433d4f72a19b | Chris | contextMenuUnselectAll(); |
| 59 | contextMenuAddSelection(tr); |
||
| 60 | 0:513646585e45 | Chris | } |
| 61 | 1115:433d4f72a19b | Chris | contextMenuSetLastSelected(tr); |
| 62 | } |
||
| 63 | } else {
|
||
| 64 | // click is outside the rows
|
||
| 65 | if (target.is('a') && (target.hasClass('disabled') || target.hasClass('submenu'))) { |
||
| 66 | event.preventDefault(); |
||
| 67 | 0:513646585e45 | Chris | } else {
|
| 68 | 1115:433d4f72a19b | Chris | contextMenuUnselectAll(); |
| 69 | 0:513646585e45 | Chris | } |
| 70 | } |
||
| 71 | } |
||
| 72 | } |
||
| 73 | |||
| 74 | 1115:433d4f72a19b | Chris | function contextMenuCreate() { |
| 75 | if ($('#context-menu').length < 1) { |
||
| 76 | var menu = document.createElement("div"); |
||
| 77 | menu.setAttribute("id", "context-menu"); |
||
| 78 | menu.setAttribute("style", "display:none;"); |
||
| 79 | document.getElementById("content").appendChild(menu);
|
||
| 80 | } |
||
| 81 | } |
||
| 82 | |||
| 83 | function contextMenuShow(event) { |
||
| 84 | var mouse_x = event.pageX;
|
||
| 85 | var mouse_y = event.pageY;
|
||
| 86 | var render_x = mouse_x;
|
||
| 87 | var render_y = mouse_y;
|
||
| 88 | var dims;
|
||
| 89 | var menu_width;
|
||
| 90 | var menu_height;
|
||
| 91 | var window_width;
|
||
| 92 | var window_height;
|
||
| 93 | var max_width;
|
||
| 94 | var max_height;
|
||
| 95 | |||
| 96 | $('#context-menu').css('left', (render_x + 'px')); |
||
| 97 | $('#context-menu').css('top', (render_y + 'px')); |
||
| 98 | $('#context-menu').html(''); |
||
| 99 | |||
| 100 | $.ajax({
|
||
| 101 | url: contextMenuUrl,
|
||
| 102 | data: $(event.target).parents('form').first().serialize(), |
||
| 103 | success: function(data, textStatus, jqXHR) { |
||
| 104 | $('#context-menu').html(data); |
||
| 105 | menu_width = $('#context-menu').width(); |
||
| 106 | menu_height = $('#context-menu').height(); |
||
| 107 | max_width = mouse_x + 2*menu_width;
|
||
| 108 | max_height = mouse_y + menu_height; |
||
| 109 | |||
| 110 | var ws = window_size();
|
||
| 111 | window_width = ws.width; |
||
| 112 | window_height = ws.height; |
||
| 113 | |||
| 114 | /* display the menu above and/or to the left of the click if needed */
|
||
| 115 | if (max_width > window_width) {
|
||
| 116 | render_x -= menu_width; |
||
| 117 | $('#context-menu').addClass('reverse-x'); |
||
| 118 | } else {
|
||
| 119 | $('#context-menu').removeClass('reverse-x'); |
||
| 120 | } |
||
| 121 | if (max_height > window_height) {
|
||
| 122 | render_y -= menu_height; |
||
| 123 | $('#context-menu').addClass('reverse-y'); |
||
| 124 | } else {
|
||
| 125 | $('#context-menu').removeClass('reverse-y'); |
||
| 126 | } |
||
| 127 | if (render_x <= 0) render_x = 1; |
||
| 128 | if (render_y <= 0) render_y = 1; |
||
| 129 | $('#context-menu').css('left', (render_x + 'px')); |
||
| 130 | $('#context-menu').css('top', (render_y + 'px')); |
||
| 131 | $('#context-menu').show(); |
||
| 132 | |||
| 133 | //if (window.parseStylesheets) { window.parseStylesheets(); } // IE
|
||
| 134 | |||
| 135 | } |
||
| 136 | }); |
||
| 137 | } |
||
| 138 | |||
| 139 | function contextMenuSetLastSelected(tr) { |
||
| 140 | $('.cm-last').removeClass('cm-last'); |
||
| 141 | tr.addClass('cm-last');
|
||
| 142 | } |
||
| 143 | |||
| 144 | function contextMenuLastSelected() { |
||
| 145 | return $('.cm-last').first(); |
||
| 146 | } |
||
| 147 | |||
| 148 | function contextMenuUnselectAll() { |
||
| 149 | $('.hascontextmenu').each(function(){ |
||
| 150 | contextMenuRemoveSelection($(this)); |
||
| 151 | }); |
||
| 152 | $('.cm-last').removeClass('cm-last'); |
||
| 153 | } |
||
| 154 | |||
| 155 | function contextMenuHide() { |
||
| 156 | $('#context-menu').hide(); |
||
| 157 | } |
||
| 158 | |||
| 159 | function contextMenuToggleSelection(tr) { |
||
| 160 | if (contextMenuIsSelected(tr)) {
|
||
| 161 | contextMenuRemoveSelection(tr); |
||
| 162 | } else {
|
||
| 163 | contextMenuAddSelection(tr); |
||
| 164 | } |
||
| 165 | } |
||
| 166 | |||
| 167 | function contextMenuAddSelection(tr) { |
||
| 168 | tr.addClass('context-menu-selection');
|
||
| 169 | contextMenuCheckSelectionBox(tr, true);
|
||
| 170 | contextMenuClearDocumentSelection(); |
||
| 171 | } |
||
| 172 | |||
| 173 | function contextMenuRemoveSelection(tr) { |
||
| 174 | tr.removeClass('context-menu-selection');
|
||
| 175 | contextMenuCheckSelectionBox(tr, false);
|
||
| 176 | } |
||
| 177 | |||
| 178 | function contextMenuIsSelected(tr) { |
||
| 179 | return tr.hasClass('context-menu-selection'); |
||
| 180 | } |
||
| 181 | |||
| 182 | function contextMenuCheckSelectionBox(tr, checked) { |
||
| 183 | tr.find('input[type=checkbox]').attr('checked', checked); |
||
| 184 | } |
||
| 185 | |||
| 186 | function contextMenuClearDocumentSelection() { |
||
| 187 | // TODO
|
||
| 188 | if (document.selection) {
|
||
| 189 | 1295:622f24f53b42 | Chris | document.selection.empty(); // IE
|
| 190 | 1115:433d4f72a19b | Chris | } else {
|
| 191 | window.getSelection().removeAllRanges(); |
||
| 192 | } |
||
| 193 | } |
||
| 194 | |||
| 195 | function contextMenuInit(url) { |
||
| 196 | contextMenuUrl = url; |
||
| 197 | contextMenuCreate(); |
||
| 198 | contextMenuUnselectAll(); |
||
| 199 | |||
| 200 | if (!contextMenuObserving) {
|
||
| 201 | $(document).click(contextMenuClick);
|
||
| 202 | $(document).contextmenu(contextMenuRightClick);
|
||
| 203 | contextMenuObserving = true;
|
||
| 204 | } |
||
| 205 | } |
||
| 206 | |||
| 207 | 0:513646585e45 | Chris | function toggleIssuesSelection(el) { |
| 208 | 1115:433d4f72a19b | Chris | var boxes = $(el).parents('form').find('input[type=checkbox]'); |
| 209 | var all_checked = true; |
||
| 210 | boxes.each(function(){ if (!$(this).attr('checked')) { all_checked = false; } }); |
||
| 211 | boxes.each(function(){
|
||
| 212 | if (all_checked) {
|
||
| 213 | $(this).removeAttr('checked'); |
||
| 214 | $(this).parents('tr').removeClass('context-menu-selection'); |
||
| 215 | } else if (!$(this).attr('checked')) { |
||
| 216 | $(this).attr('checked', true); |
||
| 217 | $(this).parents('tr').addClass('context-menu-selection'); |
||
| 218 | } |
||
| 219 | }); |
||
| 220 | 0:513646585e45 | Chris | } |
| 221 | |||
| 222 | function window_size() { |
||
| 223 | 1115:433d4f72a19b | Chris | var w;
|
| 224 | var h;
|
||
| 225 | if (window.innerWidth) {
|
||
| 226 | w = window.innerWidth; |
||
| 227 | h = window.innerHeight; |
||
| 228 | } else if (document.documentElement) { |
||
| 229 | w = document.documentElement.clientWidth; |
||
| 230 | h = document.documentElement.clientHeight; |
||
| 231 | } else {
|
||
| 232 | w = document.body.clientWidth; |
||
| 233 | h = document.body.clientHeight; |
||
| 234 | } |
||
| 235 | return {width: w, height: h}; |
||
| 236 | 0:513646585e45 | Chris | } |