Thanks Gits :)
@gits
It's not just onclick events that are being handled. There are some UI events (like onchange) that I have to handle as well.
The whole purpose of my control is to provide the same functionality of the JavaScript "confirm". The difference is that it displays some DOM UI instead so that the look and feel of my web application is kept consistent.
My Server control is "attached" to 1 or many ASP.NET controls. I have developed a JavaScript Object that works with server control. This JavaScript Object is responsible for asking the user to confirm their actions (like the JavaScript "confirm").
When it's loaded in the browser it loops through a list of Element IDs (the client IDs of the ASP.NET controls) that it needs to monitor and adds the appropriate event listeners to each element in order to prevent it from posting back to the server.
When it prevents the control from posting to the server it displays the UI asking the user to confirm their actions. If the user confirms, this control indicates that the event is allowed to proceed, recreates the original event and fires/dispatches/raises it...so that the server side code for the control can be executed.
@gits
That's what I'm doing right now.
I'm adding event listeners to each control that my Object is monitoring.
I am pretty much "hijacking" the event....
But the problem was that even though I had hijacked and stopped the event, any code in the DOM elements "on
X" event would still be executed.
For example, say I had a select element that looked like:
<select onchange="__doPostBack(....)">
My Object would hijack the onchange event and cancel the event but the __doPostBack() method would still be executed.
At first I was removing the __doPostBack() method in my Server Code. This method is added by ASP.NET to cause the control to postback to the server so that server side code can handle the client side event; therefore, I had to manually call __doPostBack method for the controls in my JavaScript Object when I re-issued the event. I never did like this solution because I was sure that I was eventually going to call the __doPostBack method incorrectly (by not passing correct parameters etc) and also I'd be calling the __doPostBack() method for controls that may not even need it to be called (I had no way of telling in my client side code).
Apparently though, this solution didn't work for all ASP.NET controls. As a result I appended a method that checks if the event is permitted:
<select onchange="if(checkIfPostBackIsPermitted('controlID ')==false){return false;}; __doPostBack(....)">
I don't know why I didn't think of this before... it changed everything.
@gits
I tried to write a version of my control so that it would be simple enough for help purposes and as a result you made me re-think my solution.
It took me this long to clean up my code and come up with something that would simulate what I'm working with.
The only place where I'm using the eval() method right now is to call JavaScript in hyperlink href's. My solution is (of course) working well in FireFox but I'm having problems in Internet Explorer.
In IE, the default action for elements does not occur when you fire a click event; however in FireFox the default action does occur (except for hyperlinks...hence the eval() call). I'm trying to figure out if I can change this behaviour in IE (maybe I'm doing something wrong).
I'll post back here if I am completely suck.
If you're interested, here is the code that you requested (I'm actually using it right now to test with before returning to my control)...like I said right now I'm testing with IE:
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
<head>
-
<title></title>
-
</head>
-
<body>
-
<form id="form1">
-
<div style="border: solid 1px black; padding: 2px; width:50%; margin:0 auto; text-align:center;">
-
This section will cancel the original click event when the checkbox is clicked.
-
It then displays a button that will issue a click event on the check box.
-
<br />
-
<div id="promptReissueDiv" style="padding: 2px; display: none; position: relative;">
-
<input type="button" id="testElement1" value="Click to re-issue the event" onclick="_raiseOriginalEvent()" />
-
</div>
-
<input type="checkbox" id="testElement" onclick="if(PostBackPermitted()== false){return false;}; alert('PostBack!');" />
-
<label for="testElement">
-
testElement</label>
-
</div>
-
<br />
-
<div id="testCheckEventSection" style="border: solid 1px black; padding: 2px; width:50%; margin:0 auto; text-align:center;">
-
This section simply tests what happens when you manually fire a click event on a checkbox.
-
<br />
-
<input type="checkbox" id="testElement2" />
-
<label for="testElement2">testElement2</label>
-
<br />
-
<input type="button" id="test" onclick="FireClick()" value="test click" />
-
</div>
-
-
<script type="text/javascript">
-
var allowPostback = false; //used to indicate if the event is permitted to continue.
-
//In my solution I'm tracking whether or not the event is permitted by storing
-
//this boolean in Objects that are created for each DOM that
-
//my control is monitoring.
-
-
var originalEvent; //used to save the original event details.
-
-
function PostBackPermitted() {
-
//This method returns whether or not the event is permitted
-
alert("The postback is allowed to continue (allowPostback): " + allowPostback);
-
return allowPostback;
-
}
-
function _stopEvent(e) {
-
//This method cancels/stops the event from continuing
-
if (allowPostback == false) {
-
try {
-
e.preventDefault();
-
e.stopPropagation();
-
e.preventBubble();
-
} catch (ex) {
-
//The following line is added so that IE unchecks the element when
-
//the event is cancelled...
-
//it "cancels" the default action that occurred when the event was fired
-
//FireFox's "preventDefault" does this.
-
e.srcElement.checked = !e.srcElement.checked;
-
e.returnValue = false;
-
e.cancelBubble = true;
-
}
-
originalEvent = e;
-
alert("Original event cancelled by the event listener (the _stopEvent() method). \n Displaying button that lets you re-issue the event.");
-
document.getElementById("promptReissueDiv").style.display = "block";
-
} else {
-
//resetting the allowPostback varaible to false for testing purposes.
-
allowPostback = false;
-
}
-
}
-
function _raiseOriginalEvent() {
-
//This method recreates the event that was originally issued and dispatches/fires/raises it
-
-
var originalControl = document.getElementById('testElement');
-
var reissuedOriginalEvent;
-
alert("The allowPostback variable is set to true to allow event to continue next time.");
-
allowPostback = true;
-
-
alert("Recreating the event...");
-
try {
-
//FireFox
-
reissuedOriginalEvent = document.createEvent('MouseEvents');
-
reissuedOriginalEvent.initEvent('click', // event type
-
true, // indicates whether or not the event bubbles
-
false, // indicates whether or not the event can be cancelled
-
document.defaultView, // the event's abstract view (window?)
-
1, // mouse click count (or event "detail")
-
originalEvent.screenX, // event's screen x coordinate
-
originalEvent.screenY, // event's screen y coordinate
-
originalEvent.clientX, // event's client x coordinate
-
originalEvent.clientY, // event's client y coordinate
-
originalEvent.ctrlKey, // whether or not CTRL was pressed during event
-
originalEvent.altKey, // whether or not ALT was pressed during event
-
originalEvent.shiftKey, // whether or not SHIFT was pressed during event
-
originalEvent.metaKey, // whether or not the meta key was pressed during
-
originalEvent.button, // indicates which button (1 = primary button)
-
null); // relatedTarget (only applicable for mouseover/mouseout events)
-
alert("dispatching the event...")
-
originalControl.dispatchEvent(reissuedOriginalEvent);
-
-
} catch (ex) {
-
//Internet Explorer
-
reissuedOriginalEvent = document.createEventObject();
-
reissuedOriginalEvent.detail = originalEvent.detail;
-
reissuedOriginalEvent.screenX = originalEvent.screenX;
-
reissuedOriginalEvent.screenY = originalEvent.screenY;
-
reissuedOriginalEvent.clientX = originalEvent.clientX;
-
reissuedOriginalEvent.clientY = originalEvent.clientY;
-
reissuedOriginalEvent.ctrlKey = originalEvent.ctrlKey;
-
reissuedOriginalEvent.altKey = originalEvent.altKey;
-
reissuedOriginalEvent.shiftKey = originalEvent.shiftKey;
-
reissuedOriginalEvent.metaKey = originalEvent.metaKey;
-
reissuedOriginalEvent.button = originalEvent.button;
-
reissuedOriginalEvent.relatedTarget = originalControl;
-
-
//The following line is added so that IE checks the element when
-
//before the event is refired...
-
//IE does not preform this default action when the click event is
-
//fired through code.
-
// originalControl.checked = !originalEvent.srcElement.checked
-
-
alert("firing the event...")
-
originalControl.fireEvent('onclick', reissuedOriginalEvent);
-
-
-
}
-
document.getElementById("promptReissueDiv").style.display = "none";
-
}
-
-
-
function FireClick() {
-
//When the button is clicked this method executed.
-
//It creates and fires a click event for the second check box.
-
-
var originalControl = document.getElementById('testElement2');
-
alert("creating event...");
-
try {
-
//FireFox
-
reissuedOriginalEvent = document.createEvent('MouseEvents');
-
reissuedOriginalEvent.initEvent('click', // event type
-
true, // indicates whether or not the event bubbles
-
false, // indicates whether or not the event can be cancelled
-
document.defaultView, // the event's abstract view (window?)
-
1, // mouse click count (or event "detail")
-
0, // event's screen x coordinate
-
0, // event's screen y coordinate
-
0, // event's client x coordinate
-
0, // event's client y coordinate
-
false, // whether or not CTRL was pressed during event
-
false, // whether or not ALT was pressed during event
-
false, // whether or not SHIFT was pressed during event
-
false, // whether or not the meta key was pressed during
-
1, // indicates which button (1 = primary button)
-
null); // relatedTarget (only applicable for mouseover/mouseout events)
-
alert("dispatching event...");
-
originalControl.dispatchEvent(reissuedOriginalEvent);
-
} catch (ex) {
-
reissuedOriginalEvent = document.createEventObject();
-
reissuedOriginalEvent.detail = 0;
-
reissuedOriginalEvent.screenX = 0;
-
reissuedOriginalEvent.screenY = 0;
-
reissuedOriginalEvent.clientX = 0;
-
reissuedOriginalEvent.clientY = 0;
-
reissuedOriginalEvent.ctrlKey = 0;
-
reissuedOriginalEvent.altKey = 0;
-
reissuedOriginalEvent.shiftKey = 0;
-
reissuedOriginalEvent.metaKey = 0;
-
reissuedOriginalEvent.button = 1;
-
reissuedOriginalEvent.relatedTarget = originalControl;
-
alert("firing event...");
-
-
//var defaultChecked = originalControl.defaultChecked;
-
//originalControl.checked = !defaultChecked;
-
alert(originalControl.defaultChecked);
-
-
//Uncomment the following to check the checkbox.
-
//originalControl.checked = !originalControl.checked;
-
}
-
}
-
-
//Adding event listener:
-
var testElement = document.getElementById('testElement');
-
try {
-
//FireFox
-
testElement.addEventListener('click', _stopEvent, false);
-
} catch (ex) {
-
//IE
-
testElement.attachEvent("onclick", _stopEvent);
-
}
-
</script>
-
-
</form>
-
</body>
-
</html>