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 @ 912:5e80956cc792
History | View | Annotate | Download (6.7 KB)
| 1 | 0:513646585e45 | Chris | /* redMine - project management software
|
|---|---|---|---|
| 2 | Copyright (C) 2006-2008 Jean-Philippe Lang */
|
||
| 3 | |||
| 4 | var observingContextMenuClick;
|
||
| 5 | |||
| 6 | ContextMenu = Class.create(); |
||
| 7 | ContextMenu.prototype = {
|
||
| 8 | initialize: function (url) { |
||
| 9 | this.url = url;
|
||
| 10 | this.createMenu();
|
||
| 11 | |||
| 12 | if (!observingContextMenuClick) {
|
||
| 13 | Event.observe(document, 'click', this.Click.bindAsEventListener(this)); |
||
| 14 | 245:051f544170fe | Chris | Event.observe(document, 'contextmenu', this.RightClick.bindAsEventListener(this)); |
| 15 | 0:513646585e45 | Chris | observingContextMenuClick = true;
|
| 16 | } |
||
| 17 | |||
| 18 | this.unselectAll();
|
||
| 19 | this.lastSelected = null; |
||
| 20 | }, |
||
| 21 | |||
| 22 | RightClick: function(e) { |
||
| 23 | this.hideMenu();
|
||
| 24 | // do not show the context menu on links
|
||
| 25 | if (Event.element(e).tagName == 'A') { return; } |
||
| 26 | var tr = Event.findElement(e, 'tr'); |
||
| 27 | if (tr == document || tr == undefined || !tr.hasClassName('hascontextmenu')) { return; } |
||
| 28 | Event.stop(e); |
||
| 29 | if (!this.isSelected(tr)) { |
||
| 30 | this.unselectAll();
|
||
| 31 | this.addSelection(tr);
|
||
| 32 | this.lastSelected = tr;
|
||
| 33 | } |
||
| 34 | this.showMenu(e);
|
||
| 35 | }, |
||
| 36 | |||
| 37 | Click: function(e) { |
||
| 38 | this.hideMenu();
|
||
| 39 | 441:cbce1fd3b1b7 | Chris | if (Event.element(e).tagName == 'A' || Event.element(e).tagName == 'IMG') { return; } |
| 40 | 0:513646585e45 | Chris | if (Event.isLeftClick(e) || (navigator.appVersion.match(/\bMSIE\b/))) { |
| 41 | var tr = Event.findElement(e, 'tr'); |
||
| 42 | if (tr!=null && tr!=document && tr.hasClassName('hascontextmenu')) { |
||
| 43 | // a row was clicked, check if the click was on checkbox
|
||
| 44 | var box = Event.findElement(e, 'input'); |
||
| 45 | if (box!=document && box!=undefined) { |
||
| 46 | // a checkbox may be clicked
|
||
| 47 | if (box.checked) {
|
||
| 48 | tr.addClassName('context-menu-selection');
|
||
| 49 | } else {
|
||
| 50 | tr.removeClassName('context-menu-selection');
|
||
| 51 | } |
||
| 52 | } else {
|
||
| 53 | 441:cbce1fd3b1b7 | Chris | if (e.ctrlKey || e.metaKey) {
|
| 54 | 0:513646585e45 | Chris | this.toggleSelection(tr);
|
| 55 | } else if (e.shiftKey) { |
||
| 56 | if (this.lastSelected != null) { |
||
| 57 | var toggling = false; |
||
| 58 | var rows = $$('.hascontextmenu'); |
||
| 59 | for (i=0; i<rows.length; i++) { |
||
| 60 | if (toggling || rows[i]==tr) {
|
||
| 61 | this.addSelection(rows[i]);
|
||
| 62 | } |
||
| 63 | if (rows[i]==tr || rows[i]==this.lastSelected) { |
||
| 64 | toggling = !toggling; |
||
| 65 | } |
||
| 66 | } |
||
| 67 | } else {
|
||
| 68 | this.addSelection(tr);
|
||
| 69 | } |
||
| 70 | } else {
|
||
| 71 | this.unselectAll();
|
||
| 72 | this.addSelection(tr);
|
||
| 73 | } |
||
| 74 | this.lastSelected = tr;
|
||
| 75 | } |
||
| 76 | } else {
|
||
| 77 | // click is outside the rows
|
||
| 78 | var t = Event.findElement(e, 'a'); |
||
| 79 | if (t == document || t == undefined) { |
||
| 80 | this.unselectAll();
|
||
| 81 | } else {
|
||
| 82 | if (Element.hasClassName(t, 'disabled') || Element.hasClassName(t, 'submenu')) { |
||
| 83 | Event.stop(e); |
||
| 84 | } |
||
| 85 | } |
||
| 86 | } |
||
| 87 | } |
||
| 88 | }, |
||
| 89 | |||
| 90 | createMenu: function() { |
||
| 91 | if (!$('context-menu')) { |
||
| 92 | var menu = document.createElement("div"); |
||
| 93 | menu.setAttribute("id", "context-menu"); |
||
| 94 | menu.setAttribute("style", "display:none;"); |
||
| 95 | document.getElementById("content").appendChild(menu);
|
||
| 96 | } |
||
| 97 | }, |
||
| 98 | |||
| 99 | showMenu: function(e) { |
||
| 100 | var mouse_x = Event.pointerX(e);
|
||
| 101 | var mouse_y = Event.pointerY(e);
|
||
| 102 | var render_x = mouse_x;
|
||
| 103 | var render_y = mouse_y;
|
||
| 104 | var dims;
|
||
| 105 | var menu_width;
|
||
| 106 | var menu_height;
|
||
| 107 | var window_width;
|
||
| 108 | var window_height;
|
||
| 109 | var max_width;
|
||
| 110 | var max_height;
|
||
| 111 | |||
| 112 | $('context-menu').style['left'] = (render_x + 'px'); |
||
| 113 | $('context-menu').style['top'] = (render_y + 'px'); |
||
| 114 | Element.update('context-menu', ''); |
||
| 115 | |||
| 116 | new Ajax.Updater({success:'context-menu'}, this.url, |
||
| 117 | {asynchronous:true,
|
||
| 118 | 119:8661b858af72 | Chris | method: 'get', |
| 119 | 0:513646585e45 | Chris | evalScripts:true, |
| 120 | parameters:Form.serialize(Event.findElement(e, 'form')), |
||
| 121 | onComplete:function(request){ |
||
| 122 | dims = $('context-menu').getDimensions(); |
||
| 123 | menu_width = dims.width; |
||
| 124 | menu_height = dims.height; |
||
| 125 | max_width = mouse_x + 2*menu_width;
|
||
| 126 | max_height = mouse_y + menu_height; |
||
| 127 | |||
| 128 | var ws = window_size();
|
||
| 129 | window_width = ws.width; |
||
| 130 | window_height = ws.height; |
||
| 131 | |||
| 132 | /* display the menu above and/or to the left of the click if needed */
|
||
| 133 | if (max_width > window_width) {
|
||
| 134 | render_x -= menu_width; |
||
| 135 | $('context-menu').addClassName('reverse-x'); |
||
| 136 | } else {
|
||
| 137 | $('context-menu').removeClassName('reverse-x'); |
||
| 138 | } |
||
| 139 | if (max_height > window_height) {
|
||
| 140 | render_y -= menu_height; |
||
| 141 | $('context-menu').addClassName('reverse-y'); |
||
| 142 | } else {
|
||
| 143 | $('context-menu').removeClassName('reverse-y'); |
||
| 144 | } |
||
| 145 | if (render_x <= 0) render_x = 1; |
||
| 146 | if (render_y <= 0) render_y = 1; |
||
| 147 | $('context-menu').style['left'] = (render_x + 'px'); |
||
| 148 | $('context-menu').style['top'] = (render_y + 'px'); |
||
| 149 | |||
| 150 | Effect.Appear('context-menu', {duration: 0.20}); |
||
| 151 | if (window.parseStylesheets) { window.parseStylesheets(); } // IE |
||
| 152 | }}) |
||
| 153 | }, |
||
| 154 | |||
| 155 | hideMenu: function() { |
||
| 156 | Element.hide('context-menu');
|
||
| 157 | }, |
||
| 158 | |||
| 159 | addSelection: function(tr) { |
||
| 160 | tr.addClassName('context-menu-selection');
|
||
| 161 | this.checkSelectionBox(tr, true); |
||
| 162 | this.clearDocumentSelection();
|
||
| 163 | }, |
||
| 164 | |||
| 165 | toggleSelection: function(tr) { |
||
| 166 | if (this.isSelected(tr)) { |
||
| 167 | this.removeSelection(tr);
|
||
| 168 | } else {
|
||
| 169 | this.addSelection(tr);
|
||
| 170 | } |
||
| 171 | }, |
||
| 172 | |||
| 173 | removeSelection: function(tr) { |
||
| 174 | tr.removeClassName('context-menu-selection');
|
||
| 175 | this.checkSelectionBox(tr, false); |
||
| 176 | }, |
||
| 177 | |||
| 178 | unselectAll: function() { |
||
| 179 | var rows = $$('.hascontextmenu'); |
||
| 180 | for (i=0; i<rows.length; i++) { |
||
| 181 | this.removeSelection(rows[i]);
|
||
| 182 | } |
||
| 183 | }, |
||
| 184 | |||
| 185 | checkSelectionBox: function(tr, checked) { |
||
| 186 | var inputs = Element.getElementsBySelector(tr, 'input'); |
||
| 187 | if (inputs.length > 0) { inputs[0].checked = checked; } |
||
| 188 | }, |
||
| 189 | |||
| 190 | isSelected: function(tr) { |
||
| 191 | return Element.hasClassName(tr, 'context-menu-selection'); |
||
| 192 | }, |
||
| 193 | |||
| 194 | clearDocumentSelection: function() { |
||
| 195 | if (document.selection) {
|
||
| 196 | document.selection.clear(); // IE
|
||
| 197 | } else {
|
||
| 198 | window.getSelection().removeAllRanges(); |
||
| 199 | } |
||
| 200 | } |
||
| 201 | } |
||
| 202 | |||
| 203 | function toggleIssuesSelection(el) { |
||
| 204 | var boxes = el.getElementsBySelector('input[type=checkbox]'); |
||
| 205 | var all_checked = true; |
||
| 206 | for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } } |
||
| 207 | for (i = 0; i < boxes.length; i++) { |
||
| 208 | if (all_checked) {
|
||
| 209 | boxes[i].checked = false;
|
||
| 210 | boxes[i].up('tr').removeClassName('context-menu-selection'); |
||
| 211 | } else if (boxes[i].checked == false) { |
||
| 212 | boxes[i].checked = true;
|
||
| 213 | boxes[i].up('tr').addClassName('context-menu-selection'); |
||
| 214 | } |
||
| 215 | } |
||
| 216 | } |
||
| 217 | |||
| 218 | function window_size() { |
||
| 219 | var w;
|
||
| 220 | var h;
|
||
| 221 | if (window.innerWidth) {
|
||
| 222 | w = window.innerWidth; |
||
| 223 | h = window.innerHeight; |
||
| 224 | } else if (document.documentElement) { |
||
| 225 | w = document.documentElement.clientWidth; |
||
| 226 | h = document.documentElement.clientHeight; |
||
| 227 | } else {
|
||
| 228 | w = document.body.clientWidth; |
||
| 229 | h = document.body.clientHeight; |
||
| 230 | } |
||
| 231 | return {width: w, height: h}; |
||
| 232 | } |