ContextMenu_wev8.js
5.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
Copyright (c) 2004-2005, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.widget.html.ContextMenu");
dojo.require("dojo.html");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.ContextMenu");
dojo.require("dojo.lang");
dojo.widget.html.ContextMenu = function(){
dojo.widget.ContextMenu.call(this);
dojo.widget.HtmlWidget.call(this);
this.isShowing = 0;
this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlContextMenuTemplate.html");
this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/Menu_wev8.css");
this.targetNodeIds = []; // fill this with nodeIds upon widget creation and it only responds to those nodes
// default event detection method
var eventType = "oncontextmenu";
var doc = document.documentElement || dojo.html.body();
var _blockHide = false;
this.fillInTemplate = function(args, frag){
var func = "onOpen";
var attached = false;
// connect with rightclick if oncontextmenu is not around
// NOTE: It would be very nice to have a dojo.event.browser.supportsEvent here
// NOTE: Opera does not have rightclick events, it is listed here only because
// it bails out when connecting with oncontextmenu event
if((dojo.render.html.khtml && !dojo.render.html.safari) || (dojo.render.html.opera)){
eventType = "onmousedown";
func = "_checkRightClick";
}
// attach event listeners to our selected nodes
for(var i=0; i<this.targetNodeIds.length; i++){
var node = document.getElementById(this.targetNodeIds[i]);
if(node){
dojo.event.connect(node, eventType, this, func);
attached = true;
}else{
// remove this nodeId
dj_debug("Couldent find "+this.targetNodeIds[i]+", cant do ContextMenu on this node");
this.targetNodeIds.splice(i,1);
}
}
// if we got attached to a node, hide on all non node contextevents
if(attached){ func = "_canHide"; }
dojo.event.connect(doc, eventType, this, func);
}
this.onOpen = function(evt){
// if (this.isShowing){ this.onHide(evt); } // propably not needed
this.isShowing = 1;
// if I do this, I cant preventDefault in khtml
//evt = dojo.event.browser.fixEvent(evt);
// stop default contextmenu, needed in khtml
if (evt.preventDefault){ evt.preventDefault(); }
// need to light up this one before we check width and height
this.domNode.style.left = "-9999px";
this.domNode.style.top = "-9999px";
this.domNode.style.display = "block";
// calculate if menu is going to apear within window
// or if its partially out of visable area
with(dojo.html){
var menuW = getInnerWidth(this.domNode);
var menuH = getInnerHeight(this.domNode);
var viewport = getViewportSize();
var scrolloffset = getScrollOffset();
}
var minX = viewport[0];
var minY = viewport[1];
var maxX = (viewport[0] + scrolloffset[0]) - menuW;
var maxY = (viewport[1] + scrolloffset[1]) - menuH;
var posX = evt.clientX + scrolloffset[0];
var posY = evt.clientY + scrolloffset[1];
if (posX > maxX){ posX = posX - menuW; }
if (posY > maxY){ posY = posY - menuH; }
this.domNode.style.left = posX + "px";
this.domNode.style.top = posY + "px";
// block the onclick that follows this particular right click
// not if the eventtrigger is documentElement and always when
// we use onmousedown hack
_blockHide = (evt.currentTarget!=doc || eventType=='onmousedown');
//return false; // we propably doesnt need to return false as we dont stop the event as we did before
}
/*
* _canHide is meant to block the onHide call that follows the event that triggered
* onOpen. This is (hopefully) faster that event.connect and event.disconnect every
* time the code executes and it makes connecting with onmousedown event possible
* and we dont have to stop the event from bubbling further.
*
* this code is moved into a separete function because it makes it possible for the
* user to connect to a onHide event, if anyone would like that.
*/
this._canHide = function(evt){
// block the onclick that follows the same event that turn on contextmenu
if(_blockHide){
// the onclick check is needed to prevent displaying multiple
// menus when we have 2 or more contextmenus loaded and are using
// the onmousedown hack
if(evt.type=='click' || eventType=='oncontextmenu'){
_blockHide = false;
return;
}else{
return;
}
}
this.onHide(evt);
}
this.onHide = function(evt){
// FIXME: use whatever we use to do more general style setting?
this.domNode.style.display = "none";
//dojo.event.disconnect(doc, "onclick", this, "onHide");
this.isShowing = 0;
}
// callback for rightclicks, needed for browsers that doesnt implement oncontextmenu, konqueror and more?
this._checkRightClick = function(evt){
// for some reason konq comes here even when we are not clicking on the attached nodes
// added check for targetnode
if (evt.button==2 && (this.targetNodeIds.length==0 || (evt.currentTarget.id!="" && dojo.lang.inArray(this.targetNodeIds, evt.currentTarget.id)))){
return this.onOpen(evt);
}
}
dojo.event.connect(doc, "onclick", this, "_canHide");
}
dojo.inherits(dojo.widget.html.ContextMenu, dojo.widget.HtmlWidget);