-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrightcontext.js
More file actions
716 lines (612 loc) · 26.1 KB
/
Copy pathrightcontext.js
File metadata and controls
716 lines (612 loc) · 26.1 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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
/*****************************************************************************
RightContext v0.2.5
Author: Harel Malka
http://www.harelmalka.com
harel@harelmalka.com
Bugs: Leave comment on the site
February 2007 - Initial Revision
----------------------------------------------------------------------------
RightContext is a supercharged context menu. I created it to
answer a few requirements I had of context menus which I could not find
anywhere else; mainly provide the *correct* contextualized links depending
on what was triggering the menu. Originaly this was a Right Click menu only,
though this was changed in 0.2.4 to allow menu triggering by Left/Right Click,
or Mouse over actions.
RightContext generates unique context menus that are built based on the DOM
element clicked using special attributes embedded in the element's html.
The attributes are custom generated and can be anything. Menu items can
include [tags] referencing those attributes, which will cause them to be
transformed to contain the actual values when the menu is constructed
(i.e., when an element is left/right clicked or moused over, depending on
the menu's setting.)
Some of the key features of RightClick:
* Trigger items via Right click, Left click or Mouse over (new in 0.2.4)
* Menu items that link somewhere
* Menu items that perform a custom javascript function
* Menu items that display hardcoded text
* Menu items that retrieve text via a remote 'ajax' call
* Menu item separators
* Supports multiple different menus that can be called depending on
the element clicked
* All menu items can contain [tags] which are transformed at runtime to
the values embedded in the clicked element
* Conditional evaluation of menu items. An item can show or not show depending
on a specified condition in the menu template (new in v0.2.3)
* Css based look and feel
* Unobtrusive standalone javascript: no additional js framework required.
RightContext is the menu object. It contains a collection of context menu
definitions which can be retrieved by unique names. A context menu will
receive a set of arguments from any calling Context that can be used to
construct the links or text in it.
This is a singleton object that should have one instance per page.
A few of the object's properties that you can edit:
menuTriggerEvent -> Can be either RIGHT (default), LEFT, or MOVE to
determine what triggers the menus generated (left/right
click or a mouse over event). Value is in UPPER case.
allowedContexts -> A String array of tag names that can have a menu attached
to them. The default list covers A, DIV, SPAN, INPUT tags.
A menu definition is an object with the following spec:
menu1 = { attributes: "attr1,attr2,attr3" ,
items: [
{type:RightContext.TYPE_MENU,
text:"Search for [attr2] on Google",
url:"http://www.goole.com?q=[attr1]",
image: "icon.gif", align:"right" },
{type:RightContext.TYPE_MENU,
text:"The second item in the menu. it will show if attr3=Y (and its: [attr3])",
requires: ["attr3", "Y"],
onclick:function() { alert('This is a custom javascript')} },
{type: RightContext.TYPE_SEPERATOR },
{type: RightContext.TYPE_TEXT,
text: "This is hardcoded, yet dynamic text: attr1=[attr1], attr2=[attr2], attr3=[attr3]"} ,
{type: RightContext.TYPE_TEXT_EXT,
url: "external.html"} ]
};
Each menu definition object contains two properties:
attributes : a comma delimited list of attributes that this menu will
look for in the elements its bound to
items : an array of objects, each describes a menu item of a given
type. The example above covers all
currently supported types and their respective properties.
A couple of notes about item properties:
* Use either url or onclick for TYPE_MENU items - url will take precedence
over onclick.
* For url type menu items, you can add an optional frame property to redirect
the link to a specific frame, or use _blank to open a new window
* The image attribute for TYPE_MENU are optional.
* For TYPE_MENU, you can use the optional 'requires' property. It accepts
an array with two elements; the first one is an attribute to evaluate and
the second is what it should evaluate to if this menu item is to be displayed.
After creating some menu definitions, you need to add them to the menu
collection within RightContext by doing:
RightContext.addMenu("menuOne", menu1);
This adds menu1 and tags it with unique name: menuOne. The unique name is how
we'll refer to this menu later.
Not all html tags are used to allow context menus. By default, only
A, DIV, SPAN and INPUT tags are considered 'contextualizable' but you can add
additional tags by editing the allowedContexts property of the RightContext
object.
To generate a context menu for a particular html tag, first add the context
attribute to it, and then any additional attributes that you'd like it to
have. The context attribute holds which menu to call up.
The additional ones are the attributes defined in the attributes property of
the menu definition.
For the menu definition above, here's an A tag example:
<a href="http://www.freecrm.com" context="menuOne" attr1="freecrm"
attr2="FreeCRM.com" attr3="Hi mum!">Right Click Me</a>
The above link will use the menuOne (mapped to menu1) defintion. When
triggered, the first menu item will a link titled
"Search for freecrm on Google" ([attr1] is replaced by the tag's
attribute value - freecrm)
The second item will pop a javascript alert and will be titled
"The second item in the menu. attr3=Hi Mum!".
It will be followed by a separator and then the following text:
"This is hardcoded, yet dynamic text: attr1=freecrm, attr2=FreeCRM.com,
attr3=Hi mum!"
The last item will retrieve the contents of the external.html file
provided. Obviously, you can also embed url parameters in the url as tags.
Note that the link above will cause the second menu item to not display
because the attr3 attribute is equal to "Hi mum!" while the menu template
defines that the second item will only show if the attr3 is equal to Y.
You can create as many menu definitions as needed for different elements on
your page. Simple define which menu to call in the tag's context attribute.
Finally, to kick of the party and start some context menu action going, you
need to bind the tags that contain the context attribute to their respectful
menus by doing:
RightContext.initialize();
Please see the example file provided (index.html). An example is worth
a thousand comments...
CSS Notes:
The RightContext object makes use of some CSS classes defined in the
rightcontext.css file. You need to include that in your html, or make use
of these classes yourself.
Some credits:
I was always on the lookout for the right context menu but was too busy (or
lazy) to make my own. What finally broke the camel's back was a ContextMenu
script using prototype that i found here:
http://www.ajaxline.com/node/338 (note - last i checked the link was not
active). But, it wasn't stand alone, and it wasn't really "contextualize"
to what's clicked. I wasn't a happy puppy, So i rolled up my sleeves.
I used the getDimensions method from prototype since it worked great and
saved me time doing my own. (http://prototype.conio.net)
I also adapted the logic in Alessandro Fulciniti great bubble tooltip
script's Locate method for the locateMousePos (slightly modified)
method for the same reason (http://pro.html.it and
http://web-graphics.com )
Also thanks to all the good people who bothered to comment about this script.
Thanks to them I added the left click and mouse over trigger options.
In 0.2.5 I also incorporated fixes provided by Ian, CraigD, David Zhang and fanno.
So thanks guys!
LICENSE:
This script is FREE to use and modify for personal or commercial purposes.
I only ask that you either leave this commented message intact, OR leave
credit where credit is due, with all URLs provided (not just to myself,
but also to prototype and Alessandro).
As well, if you make any modifications to this script that enhances its
functionality, please DO give them back to the world and please email them
to me so that I can consider including them into my own version here.
I'd also love to hear of any good use you've made with this script!
WARRANTY:
This code comes with NO Warranty whatsoever. I cannot be help responsible
for any damage of any kind to any thing resulting from using this code.
Do NOT use this code for NASA shuttle launches! It won't work.
Please send bug reports to rightcontext@googlemail.com
Have fun
CHANGE LOG -----------------------------------------------------------------
0.2 : 12 Feb 2007 Added support for tags in menu onclick event handlers.
Added a couple of fixes provided by JDG including a Safari
fix.
0.2.1 : 17 Feb 2007 Bug fix: event handler parsing was overwriting the template
with the first parsed item.
0.2.2 : 20 Feb 2007 Bug fix: IE6-7 issue with onlclick events containing tags
and a menu positioning fix.
0.2.3 : 20 Feb 2007 Added conditional display of menu items based on [tag] values
0.2.4 : 26 Feb 2007 Added menu triggering via LEFT click and mouse over (MOVE)
events.
0.2.5 : 04 Oct 2008 Fixes tags not passing properly on FF3 with onclick events.
Also incorporates all fixes proposed by users.
Thanks to Ian, CraigD, David Zhang and fanno
****************************************************************************/
var RightContext = {
//some final vars:
TYPE_MENU: 0, // menu item
TYPE_TEXT: 1, // inline text (non-mutable hard coded)
TYPE_TEXT_EXT: 2, // external text (retrived via rpc call)
TYPE_SEPERATOR:3, // separator line
TYPE_ATTRIBUTES:4, // menu attributes.
// some simple browser detection
browser: null,
// set the event to trigger the menus: RIGHT,LEFT (right/left click) or mouse MOVE
menuTriggerEvent: "RIGHT",
// object to hold temp mouse position
mousePos: {x:0, y:0},
// offset for menu from mouse pointer
rightOffset: 5,
// kill menu timeout - sets the timeout from mouse out to menu dissapearing
killMenuTimeout: 25,
// type of html tags that can have context menus. You can edit this to
// allow more tags into the party.
allowedContexts: ["a","div","span","input"],
// object to hold a collection of menus indexed by name
menuCollection: new Object(),
// the currently visible context menu DIV element
contextMenu: null,
// some state machine: is the menu showing (LEFT), and should killing it be aborted (MOVE)
isShowing: false,
abortKill: false,
// image cache
images: new Object(),
// var to hold external requests
req: null,
// initialize RightContext object
initialize: function () {
this.browser = RightContext.detectBrowser();
this.attachContextEvents();
},
// adds a menu to the menuCollection
addMenu: function (n, m) {
this.menuCollection[n] = m;
},
// return a menu from the menu collection
getMenu: function (n) {
return this.menuCollection[n];
},
// loop all context allowed tags in the document and attach menu events to
// those that contain the menu attribute
attachContextEvents: function () {
var tagContext, thisTag;
for (var t=0; t<this.allowedContexts.length; t++) {
tags = document.getElementsByTagName(this.allowedContexts[t]);
for (e=0; e<tags.length; e++) {
thisTag = tags[e];
tagContext = thisTag.getAttribute("context");
if (tagContext!=null && tagContext != "undefined") {
this.bindEvent('mousemove', tags[e], function(e) { return RightContext.locateMousePos(e); });
if (this.menuTriggerEvent=="RIGHT") {
tags[e].oncontextmenu = function() { return RightContext.render(this); };
} else if (this.menuTriggerEvent=="LEFT") {
//this.bindEvent('click', tags[e], function() { return RightContext.render(this, tagContext); });
tags[e].onclick = function(e) {
RightContext.killBubble(e);
return RightContext.render(this)
};
tags[e].onmouseout = function(e) { setTimeout("RightContext.killMenu()", 5000);};
} else if (this.menuTriggerEvent=="MOVE") {
if (!document.all) {
this.bindEvent('mouseover', tags[e], function(e) { RightContext.locateMousePos(e); return RightContext.render(this); });
this.bindEvent('mouseout', tags[e], function(e) { setTimeout("RightContext.killMenu()", RightContext.killMenuTimeout); });
} else {
tags[e].onmouseover = function(e) { RightContext.locateMousePos(e); return RightContext.render(this); };
tags[e].onmouseout = function(e) { setTimeout("RightContext.killMenu()", RightContext.killMenuTimeout); };
}
}
}
}
}
},
killBubble: function(e) {
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
},
// binds an event handler to an object
bindEvent: function (evt, obj, act, bubble) {
if (!bubble) bubble = false;
if (obj.addEventListener) {
obj.addEventListener(evt, act, bubble);
} else if (obj.attachEvent) {
obj.attachEvent('on'+evt, act);
}
},
/*
renders a given menu and attaches it to the caller object.
The caller is responsible to contain a few extra attributes
that will help construct the links for this menu (i.e., provide the Context)
*/
render: function (caller, name) {
var url, title;
// if name was not specified, grab it from the caller
// v0.2 - changed to getAttribute (used direct nodeValue access before my mistake). pointed out by JDG.
var name = name || caller.getAttribute("context");
// get the requested menu
var thisMenu = this.getMenu(name);
// extracts this menus attributes list and items
var attributes = thisMenu["attributes"].split(',');
var items = thisMenu.items;
// constructs a map from the callers attributes
var objMap = this.buildAttributeMap(attributes, caller);
// start building the menu itself, but first remove menu if visible
this.killMenu();
this.buildMenu(caller);
// create a table to build the menu items in
tbl = document.createElement("TABLE");
tbl.id = "rcRightContextTable";
// loop the menu items and render each according to its type
for (var m=0; m<items.length; m++) {
switch (items[m]["type"]) {
case this.TYPE_MENU:
// add the menu item
if (this.isDisplayed(items[m], objMap)) {
this.addMenuItem(items[m], objMap, tbl);
}
break;
case this.TYPE_TEXT:
// add fixed text
text = this.transform(items[m]["text"], objMap);
cell = this.addTableCell(tbl, "rcMenuItemText", text);
break;
case this.TYPE_TEXT_EXT:
cell = this.addTableCell(tbl, "rcMenuItemTextExt");
url = this.transform(items[m]["url"], objMap);
this.request(url, function() { if (RightContext.req.readyState == 4 && RightContext.req.status == 200) { cell.innerHTML = RightContext.req.responseText } });
break;
case this.TYPE_SEPERATOR:
cell = this.addTableCell(tbl);
cell.appendChild(this.getSeparator());
break;
default:
// no default behaviour
break;
}
}
// append the menu item table to the menu itself
this.contextMenu.appendChild(tbl);
// make sure we're not overflowed to the edge of the screen.
this.repositionMenu();
if (this.menuTriggerEvent=="MOVE") {
this.bindEvent('mouseout', this.contextMenu, function(e) { RightContext.abortKill = false; setTimeout("RightContext.killMenu()", RightContext.killMenuTimeout); });
this.bindEvent('mouseover', this.contextMenu, function(e) { RightContext.abortKill = true; });
} else if (this.menuTriggerEvent=="LEFT" || this.menuTriggerEvent=="RIGHT") {
this.bindEvent('click', document.body, function(e) { setTimeout("RightContext.killMenu();", RightContext.killMenuTimeout); }, false);
}
this.isShowing = true;
return false;
},
isDisplayed : function(item, objMap) {
var reqVar, reqVal;
var shown = true; // by default all items are shown, unless they require something
// lets make sure this item does not require any condition to be true in order to display
if (item["requires"] != null && item["requires"] != "undefined") {
// yep, this one has a requirement...
reqVar = item["requires"][0];
reqVal = item["requires"][1];
if (objMap[reqVar] != null && objMap[reqVar] != "undefined") {
// if the condition is not met, do not show this item.
if (objMap[reqVar] != reqVal) {
shown = false;
}
} else {
// if the condition is not defined do not show the item
shown = false;
}
}
return shown;
},
// check if the menu goes outside the window boundries and adjust its
// location if so
repositionMenu: function() {
var mPos = this.findPosition(this.contextMenu);
var mDim = this.getDimensions(this.contextMenu);
var winHeight = this.getWindowHeight(); // window.innerHeight || document.body.clientHeight;
var winWidth = window.innerWidth || document.body.clientWidth;
if (mPos.y + mDim.height > winHeight-30 ) {
this.position(this.contextMenu, mPos.x, mPos.y - mDim.height);
mPos = this.findPosition(this.contextMenu);
}
if (mPos.x + mDim.width > winWidth - 30 ) {
this.position(this.contextMenu, mPos.x-mDim.width, mPos.y);
}
},
// returns an HR sepearator which uses the rcMenuSeparator style
getSeparator: function () {
var sep = document.createElement("HR");
sep.className = "rcMenuSeparator";
return sep;
},
// adds a table cell to the provided table and returns it.
// attached a class if provided and initializes the cell with some content
// where applicable
addTableCell: function (table, className, content) {
row = table.insertRow(-1);
cell = row.insertCell(0);
if (className) {
cell.className = className;
if (content) {
cell.innerHTML = content;
}
}
return cell;
},
// adds a menu item to the provided table. transforms all data as defined
// in the objMap argument
addMenuItem: function (item, objMap, tbl) {
var title = this.transform(item["text"], objMap);
var url, frame, img, imgAlign, itemSrc, tmp, itemAction;
var cell = this.addTableCell(tbl, "rcMenuItem", title);
cell.style.cursor = document.all?'hand':'pointer';
this.bindEvent('mouseover', cell, function(e) { cell.className="rcMenuItemHover";});
this.bindEvent('mouseout', cell, function(e) { cell.className="rcMenuItem"; });
// deal with image if applicable
if (item["image"]!=null && item["image"]!="undefined") {
// get image alignment or default to absmiddle
imgAlign = (item["align"]!=null && item["align"]!="undefined") ? item["align"] : "absmiddle";
// load the image from the cache, or from disk (and then cache it)
if (this.images[item["image"]] != null && this.images[item["image"]] != "undefined") {
img = this.images[item["image"]];
} else {
img = this.loadImage(item["image"]);
}
// set image alignment
img.align=imgAlign;
// insert the image as first child of the cell
cell.insertBefore(this.images[item["image"]], cell.childNodes[0]);
}
if (item["url"]!=null && item["url"] != "undefined") {
url = this.transform(item["url"], objMap);
frame = false;
if (item["frame"] != null && item["frame"] != "undefined") {
frame = item["frame"];
}
cell.onclick = function () { RightContext.redirect(url, frame); }
} else {
// we first need to find out if the event handler contains a potential
// tag. if so, we grab its source, transform it and re-evaluate it.
// if this fails, the value reverts back to its original function
itemAction = item["onclick"];
try {
itemSrc = item["onclick"].toString();
if (itemSrc.indexOf('[')>-1) {
itemSrc = this.transform(itemSrc, objMap);
eval('itemAction = ' + itemSrc);
}
} catch (e) {
// nothing...
}
// set the cell onclick event handler.
cell.onclick=itemAction;
}
},
// transforms a string based on the provided map
transform: function (str, map) {
var tStr, tmp;
tStr = str;
for (p in map) {
tmp = "[" + p + "]";
while (tStr.indexOf(tmp) > -1) {
tStr = tStr.replace(tmp, map[p]);
}
}
return tStr;
},
// returns the menu's attributes collection that will be used to construct
// the transformation map
getMenuAttributeArray: function (menu) {
for (var i=0; i<menu.length; i++) {
if (menu[i].type == this.TYPE_ATTRIBUTES) {
return menu[i]["attributes"].split(',');
}
}
return new Array(0);
},
// construct the transformation map for a given object based on the tags in
// attribs
buildAttributeMap: function (attribs, obj) {
var thisAttr, thisValue;
var attrMap = new Object();
for (var a=0; a<attribs.length; a++) {
thisAttr = attribs[a];
thisValue = obj.getAttribute(attribs[a]);
if (typeof thisValue != "undefined") {
attrMap[thisAttr] = thisValue;
}
}
return attrMap;
},
// find the position of an element on the screen and returns an array of [x,y]
findPosition: function (obj) {
var lft = 0;
var top = 0;
if (obj.offsetParent) {
lft = obj.offsetLeft
top = obj.offsetTop
while (obj = obj.offsetParent) {
lft += obj.offsetLeft
top += obj.offsetTop
}
}
return {x:lft,y:top};
},
getWindowHeight: function() {
if (this.browser.khtml || this.browser.safari) {
return this.innerHeight;
} else if (this.browser.opera) {
return document.body.clientHeight;
} else {
return document.documentElement.clientHeight;
}
},
// Returns the dimensions of an element on screen. Lifted from the wonderful
// prototype framework
getDimensions: function(obj) {
//var display = obj.getStyle('display');
//if (display != 'none' && display != null) // Safari bug
// return {width: element.offsetWidth, height: element.offsetHeight};
// All *Width and *Height properties give 0 on elements with display none,
// so enable the element temporarily
var objStyle = obj.style;
var originalVisibility = objStyle.visibility;
var originalPosition = objStyle.position;
var originalDisplay = objStyle.display;
objStyle.visibility = 'hidden';
objStyle.position = 'absolute';
objStyle.display = 'block';
var originalWidth = obj.clientWidth;
var originalHeight = obj.clientHeight;
objStyle.display = originalDisplay;
objStyle.position = originalPosition;
objStyle.visibility = originalVisibility;
return {width: originalWidth, height: originalHeight};
},
// positions object at x,y coordinates
// v0.2 - added px to the position coordinate (provided by JDG)
position: function (obj, x, y) {
obj.style.left = x + 'px';
obj.style.top = y + 'px';
},
// builds a menu for parent object
buildMenu: function (parent) {
var pos, dim, tbl;
//document.onmousemove = RightContext.getMousePos;
this.contextMenu = document.createElement("DIV");
this.contextMenu.id = "rcRightContext";
this.contextMenu.className = 'rcMenuContainer';
// get the position and dimensions of the parent
pos = this.findPosition(parent);
dim = this.getDimensions(parent);
// position the container to the bottom right of the element.
this.position (this.contextMenu, this.mousePos.x + this.rightOffset, pos.y+dim.height);
// set some event handlers
// if the menu is triggered by a right click, disable the right click on the menu itself
if (this.menuTriggerEvent == "RIGHT") {
this.contextMenu.oncontextmenu = function () { return false; };
}
// add the container to the body of the document
document.body.appendChild(this.contextMenu);
},
// kills the currently visible context menu
killMenu: function () {
if (!this.abortKill && this.isShowing) {
try {
rc = this.contextMenu;
document.body.removeChild(rc);
} catch (e) {
// already removed?
}
this.contextMenu = null;
this.isShowing = false;
this.abortKill = false;
}
},
// locate the mouse cursor position
locateMousePos: function(e) {
var posx = 0, posy =0;
if(e==null) e=window.event;
if(e.pageX || e.pageY) {
posx=e.pageX; posy=e.pageY;
} else if (e.clientX || e.clientY) {
if(document.documentElement.scrollTop){
posx=e.clientX+document.documentElement.scrollLeft;
posy=e.clientY+document.documentElement.scrollTop;
} else {
posx=e.clientX+document.body.scrollLeft;
posy=e.clientY+document.body.scrollTop;
}
}
this.mousePos = {x:posx , y:posy};
},
// redirects the browser to given url
// if frame!=false, it will open in provided frame (or new win if _blank)
redirect: function (u, frame) {
if (!frame) {
document.location = u;
} else {
if (frame=="_blank") {
w = window.open(u, 'w');
} else {
window.frames[frame].document.location = u;
}
}
},
// performs a request - ajax style
request: function (url, callBack) {
if (window.XMLHttpRequest) { // native XMLHttpRequest
this.req = new XMLHttpRequest();
this.req.onreadystatechange = callBack;
this.req.open("GET", url, true);
this.req.send(null);
} else if (window.ActiveXObject) { // The M$ 'standard'
this.req = new ActiveXObject("Microsoft.XMLHTTP");
if (this.req) {
this.req.onreadystatechange = callBack;
this.req.open("GET", url, true);
this.req.send();
}
}
},
loadImage: function (url) {
var img = new Image();
img.src = url;
img.className = "rcImage";
this.images[url] = img;
return img;
},
detectBrowser: function() {
var ua = navigator.userAgent.toUpperCase();
var up = navigator.platform.toUpperCase().substr(0,3);
var isSafari = (ua.indexOf("SAFARI" )>0);
var isKHTML = (ua.indexOf("KONQUEROR")>0 || isSafari);
var isFirefox = (ua.indexOf("FIREFOX" )>0);
var isOpera = (ua.indexOf("OPERA" )>=0);
return { safari: isSafari, khtml: isKHTML, opera: isOpera, firefox: isFirefox, platform: up }
}
};