Project

General

Profile

Defect #1485 ยป context_menu.js

Context Menu for Firefox 3 - Lev T, 2008-07-08 22:41

 
1
/* 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

    
11
	// prevent selection when using Ctrl/Shit key
12
	var tables = $$('table.issues');
13
	for (i=0; i<tables.length; i++) {
14
		tables[i].onselectstart = function () { return false; } // ie
15
		tables[i].onmousedown = function () { return false; } // mozilla
16
	}
17

    
18
	if (!observingContextMenuClick) {
19
		Event.observe(document, 'click', this.Click.bindAsEventListener(this));
20
		observingContextMenuClick = true;
21
	}
22
	
23
	this.unselectAll();
24
	this.lastSelected = null;
25
	},
26
  
27
	RightClick: function(e) {
28
		this.hideMenu();
29
		// do not show the context menu on links
30
		if (Event.findElement(e, 'a') != document && Event.findElement(e, 'a') != undefined) { return; }
31
		// right-click simulated by Alt+Click with Opera
32
		if (window.opera && !e.altKey) { return; }
33
		var tr = Event.findElement(e, 'tr');
34
		if (tr == document || tr == undefined  || !tr.hasClassName('hascontextmenu')) { return; }
35
		Event.stop(e);
36
		if (!this.isSelected(tr)) {
37
			this.unselectAll();
38
			this.addSelection(tr);
39
			this.lastSelected = tr;
40
		}
41
		this.showMenu(e);
42
	},
43

    
44
  Click: function(e) {
45
  	this.hideMenu();
46
  	if (Event.findElement(e, 'a') != document && Event.findElement(e, 'a') != undefined ) { return; }
47
    if (window.opera && e.altKey) {	return; }
48
    if (Event.isLeftClick(e) || (navigator.appVersion.match(/\bMSIE\b/))) {      
49
      var tr = Event.findElement(e, 'tr');
50
      if (tr!=document && tr.hasClassName('hascontextmenu')) {
51
        // a row was clicked, check if the click was on checkbox
52
        var box = Event.findElement(e, 'input');
53
        if (box!=document && box!=undefined) {
54
          // a checkbox may be clicked
55
          if (box.checked) {
56
            tr.addClassName('context-menu-selection');
57
          } else {
58
            tr.removeClassName('context-menu-selection');
59
          }
60
        } else {
61
          if (e.ctrlKey) {
62
            this.toggleSelection(tr);
63
          } else if (e.shiftKey) {
64
            if (this.lastSelected != null) {
65
              var toggling = false;
66
              var rows = $$('.hascontextmenu');
67
              for (i=0; i<rows.length; i++) {
68
                if (toggling || rows[i]==tr) {
69
                  this.addSelection(rows[i]);
70
                }
71
                if (rows[i]==tr || rows[i]==this.lastSelected) {
72
                  toggling = !toggling;
73
                }
74
              }
75
            } else {
76
              this.addSelection(tr);
77
            }
78
          } else {
79
            this.unselectAll();
80
            this.addSelection(tr);
81
          }
82
          this.lastSelected = tr;
83
        }
84
      } else {
85
        // click is outside the rows
86
        var t = Event.findElement(e, 'a');
87
        if ((t != document) && (Element.hasClassName(t, 'disabled') || Element.hasClassName(t, 'submenu'))) {
88
          Event.stop(e);
89
        }
90
      }
91
    }
92
    else{
93
      this.RightClick(e);
94
    }
95
  },
96
  
97
  showMenu: function(e) {
98
    var mouse_x = Event.pointerX(e);
99
    var mouse_y = Event.pointerY(e);
100
    var render_x = mouse_x;
101
    var render_y = mouse_y;
102
    var dims;
103
    var menu_width;
104
    var menu_height;
105
    var window_width;
106
    var window_height;
107
    var max_width;
108
    var max_height;
109

    
110
    $('context-menu').style['left'] = (render_x + 'px');
111
    $('context-menu').style['top'] = (render_y + 'px');		
112
    Element.update('context-menu', '');
113

    
114
    new Ajax.Updater({success:'context-menu'}, this.url, 
115
      {asynchronous:true,
116
       evalScripts:true,
117
       parameters:Form.serialize(Event.findElement(e, 'form')),
118
       onComplete:function(request){
119
				 dims = $('context-menu').getDimensions();
120
				 menu_width = dims.width;
121
				 menu_height = dims.height;
122
				 max_width = mouse_x + 2*menu_width;
123
				 max_height = mouse_y + menu_height;
124
			
125
				 var ws = window_size();
126
				 window_width = ws.width;
127
				 window_height = ws.height;
128
			
129
				 /* display the menu above and/or to the left of the click if needed */
130
				 if (max_width > window_width) {
131
				   render_x -= menu_width;
132
				   $('context-menu').addClassName('reverse-x');
133
				 } else {
134
					 $('context-menu').removeClassName('reverse-x');
135
				 }
136
				 if (max_height > window_height) {
137
				   render_y -= menu_height;
138
				   $('context-menu').addClassName('reverse-y');
139
				 } else {
140
					 $('context-menu').removeClassName('reverse-y');
141
				 }
142
				 if (render_x <= 0) render_x = 1;
143
				 if (render_y <= 0) render_y = 1;
144
				 $('context-menu').style['left'] = (render_x + 'px');
145
				 $('context-menu').style['top'] = (render_y + 'px');
146
				 
147
         Effect.Appear('context-menu', {duration: 0.20});
148
         if (window.parseStylesheets) { window.parseStylesheets(); } // IE
149
      }})
150
  },
151
  
152
  hideMenu: function() {
153
    Element.hide('context-menu');
154
  },
155
  
156
  addSelection: function(tr) {
157
    tr.addClassName('context-menu-selection');
158
    this.checkSelectionBox(tr, true);
159
  },
160
  
161
  toggleSelection: function(tr) {
162
    if (this.isSelected(tr)) {
163
      this.removeSelection(tr);
164
    } else {
165
      this.addSelection(tr);
166
    }
167
  },
168
  
169
  removeSelection: function(tr) {
170
    tr.removeClassName('context-menu-selection');
171
    this.checkSelectionBox(tr, false);
172
  },
173
  
174
  unselectAll: function() {
175
    var rows = $$('.hascontextmenu');
176
    for (i=0; i<rows.length; i++) {
177
      this.removeSelection(rows[i]);
178
    }
179
  },
180
  
181
  checkSelectionBox: function(tr, checked) {
182
  	var inputs = Element.getElementsBySelector(tr, 'input');
183
  	if (inputs.length > 0) { inputs[0].checked = checked; }
184
  },
185
  
186
  isSelected: function(tr) {
187
    return Element.hasClassName(tr, 'context-menu-selection');
188
  }
189
}
190

    
191
function toggleIssuesSelection(el) {
192
	var boxes = el.getElementsBySelector('input[type=checkbox]');
193
	var all_checked = true;
194
	for (i = 0; i < boxes.length; i++) { if (boxes[i].checked == false) { all_checked = false; } }
195
	for (i = 0; i < boxes.length; i++) {
196
		if (all_checked) {
197
			boxes[i].checked = false;
198
			boxes[i].up('tr').removeClassName('context-menu-selection');
199
		} else if (boxes[i].checked == false) {
200
			boxes[i].checked = true;
201
			boxes[i].up('tr').addClassName('context-menu-selection');
202
		}
203
	}
204
}
205

    
206
function window_size() {
207
    var w;
208
    var h;
209
    if (window.innerWidth) {
210
	w = window.innerWidth;
211
	h = window.innerHeight;
212
    } else if (document.documentElement) {
213
	w = document.documentElement.clientWidth;
214
	h = document.documentElement.clientHeight;
215
    } else {
216
	w = document.body.clientWidth;
217
	h = document.body.clientHeight;
218
    }
219
    return {width: w, height: h};
220
}
    (1-1/1)