473,383 Members | 1,815 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

JavaScript Events and DOM Element Default Behaviour

Frinavale
9,735 Expert Mod 8TB
[edit]
This thread has been split off of this thread since it no longer pertains to the original question.
[/edit]


Instead of simply returning false I am executing a method that indicates whether or not to allow the postback to continue (it returns true or false accordingly)

Well with this improvement I thought that maybe I didn't have to hard code the __doPostback() method when reissuing the onclick event for my controls, but this isn't the case.

Is there any way to access the onclick attribute of the DOM element so that I can use the eval() method to run the JavaScript that should have been run had the event not been cancelled?
May 15 '09 #1
9 3464
gits
5,390 Expert Mod 4TB
hey frinny,

let's think about this ... since when i read eval() i think there must be a better way ... it's just ugly to use eval() and i guess we wouldn't need it. but since the thread is that long i cannot quite follow it here at the office where i would have something to do ;) ... so when you say you would have a method that always checks whether a postback is allowed or not is that called with the onclick-events in question? may be we could try to just cancel the events by hacking into the event-chain or something like this :) ... something like capturing all events first ... check a condition ... and populating the event or canceling it according to the check-result? do you have a small example snippet that we might use to 'simulate' your problem locally?

kind regards
May 16 '09 #2
Frinavale
9,735 Expert Mod 8TB
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 "onX" 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:
Expand|Select|Wrap|Line Numbers
  1. <html xmlns="http://www.w3.org/1999/xhtml">
  2. <head>
  3.     <title></title>
  4. </head>
  5. <body>
  6.     <form id="form1">
  7.     <div style="border: solid 1px black; padding: 2px; width:50%; margin:0 auto; text-align:center;">
  8.         This section will cancel the original click event when the checkbox is clicked.
  9.         It then displays a button that will issue a click event on the check box.
  10.         <br />
  11.         <div id="promptReissueDiv" style="padding: 2px; display: none; position: relative;">
  12.             <input type="button" id="testElement1" value="Click to re-issue the event" onclick="_raiseOriginalEvent()" />
  13.         </div>
  14.         <input type="checkbox" id="testElement" onclick="if(PostBackPermitted()== false){return false;}; alert('PostBack!');" />
  15.         <label for="testElement">
  16.             testElement</label>
  17.     </div>
  18.     <br />
  19.     <div id="testCheckEventSection" style="border: solid 1px black; padding: 2px; width:50%; margin:0 auto; text-align:center;">
  20.         This section simply tests what happens when you manually fire a click event on a checkbox.
  21.         <br />
  22.         <input type="checkbox" id="testElement2" />
  23.         <label for="testElement2">testElement2</label>
  24.         <br />
  25.         <input type="button" id="test" onclick="FireClick()" value="test click" />
  26.     </div>
  27.  
  28.     <script type="text/javascript">
  29.         var allowPostback = false; //used to indicate if the event is permitted to continue.
  30.         //In my solution I'm tracking whether or not the event is permitted by storing
  31.         //this boolean in Objects that are created for each DOM that
  32.         //my control is monitoring.
  33.  
  34.         var originalEvent; //used to save the original event details.
  35.  
  36.         function PostBackPermitted() {
  37.             //This method returns whether or not the event is permitted 
  38.             alert("The postback is allowed to continue (allowPostback): " + allowPostback);
  39.             return allowPostback;
  40.         }
  41.         function _stopEvent(e) {
  42.             //This method cancels/stops the event from continuing
  43.             if (allowPostback == false) {
  44.                 try {
  45.                     e.preventDefault();
  46.                     e.stopPropagation();
  47.                     e.preventBubble();
  48.                 } catch (ex) {
  49.                     //The following line is added so that IE unchecks the element when
  50.                     //the event is cancelled...
  51.                     //it "cancels" the default action that occurred when the event was fired
  52.                     //FireFox's "preventDefault" does this.
  53.                     e.srcElement.checked = !e.srcElement.checked;
  54.                     e.returnValue = false;
  55.                     e.cancelBubble = true;
  56.                 }
  57.                 originalEvent = e;
  58.                 alert("Original event cancelled by the event listener (the _stopEvent() method). \n Displaying button that lets you re-issue the event.");
  59.                 document.getElementById("promptReissueDiv").style.display = "block";
  60.             } else {
  61.                 //resetting the allowPostback varaible to false for testing purposes.
  62.                 allowPostback = false;
  63.             }
  64.         }
  65.         function _raiseOriginalEvent() {
  66.             //This method recreates the event that was originally issued and dispatches/fires/raises it
  67.  
  68.             var originalControl = document.getElementById('testElement');
  69.             var reissuedOriginalEvent;
  70.             alert("The allowPostback variable is set to true to allow event to continue next time.");
  71.             allowPostback = true;
  72.  
  73.             alert("Recreating the event...");
  74.             try {
  75.                 //FireFox
  76.                 reissuedOriginalEvent = document.createEvent('MouseEvents');
  77.                 reissuedOriginalEvent.initEvent('click', // event type
  78.                         true, // indicates whether or not the event bubbles
  79.                         false, // indicates whether or not the event can be cancelled
  80.                         document.defaultView, // the event's abstract view (window?)
  81.                         1, // mouse click count (or event "detail")
  82.                         originalEvent.screenX, // event's screen x coordinate
  83.                         originalEvent.screenY, // event's screen y coordinate
  84.                         originalEvent.clientX, // event's client x coordinate
  85.                         originalEvent.clientY, // event's client y coordinate
  86.                         originalEvent.ctrlKey, // whether or not CTRL was pressed during event
  87.                         originalEvent.altKey, // whether or not ALT was pressed during event
  88.                         originalEvent.shiftKey, // whether or not SHIFT was pressed during event
  89.                         originalEvent.metaKey, // whether or not the meta key was pressed during
  90.                         originalEvent.button,  // indicates which button (1 = primary button)
  91.                         null); // relatedTarget (only applicable for mouseover/mouseout events)
  92.                 alert("dispatching the event...")
  93.                 originalControl.dispatchEvent(reissuedOriginalEvent);
  94.  
  95.             } catch (ex) {
  96.                 //Internet Explorer
  97.                 reissuedOriginalEvent = document.createEventObject();
  98.                 reissuedOriginalEvent.detail = originalEvent.detail;
  99.                 reissuedOriginalEvent.screenX = originalEvent.screenX;
  100.                 reissuedOriginalEvent.screenY = originalEvent.screenY;
  101.                 reissuedOriginalEvent.clientX = originalEvent.clientX;
  102.                 reissuedOriginalEvent.clientY = originalEvent.clientY;
  103.                 reissuedOriginalEvent.ctrlKey = originalEvent.ctrlKey;
  104.                 reissuedOriginalEvent.altKey = originalEvent.altKey;
  105.                 reissuedOriginalEvent.shiftKey = originalEvent.shiftKey;
  106.                 reissuedOriginalEvent.metaKey = originalEvent.metaKey;
  107.                 reissuedOriginalEvent.button = originalEvent.button;
  108.                 reissuedOriginalEvent.relatedTarget = originalControl;
  109.  
  110.                 //The following line is added so that IE checks the element when
  111.                 //before the event is refired...
  112.                 //IE does not preform this default action when the click event is
  113.                 //fired through code.
  114.                 //    originalControl.checked = !originalEvent.srcElement.checked
  115.  
  116.                 alert("firing the event...")
  117.                 originalControl.fireEvent('onclick', reissuedOriginalEvent);
  118.  
  119.  
  120.             }
  121.             document.getElementById("promptReissueDiv").style.display = "none";
  122.         }
  123.  
  124.  
  125.         function FireClick() {
  126.             //When the button is clicked this method executed.
  127.             //It creates and fires a click event for the second check box.
  128.  
  129.             var originalControl = document.getElementById('testElement2');
  130.             alert("creating event...");
  131.             try {
  132.                 //FireFox
  133.                 reissuedOriginalEvent = document.createEvent('MouseEvents');
  134.                 reissuedOriginalEvent.initEvent('click', // event type
  135.                     true, // indicates whether or not the event bubbles
  136.                     false, // indicates whether or not the event can be cancelled
  137.                     document.defaultView, // the event's abstract view (window?)
  138.                     1, // mouse click count (or event "detail")
  139.                     0, // event's screen x coordinate
  140.                     0, // event's screen y coordinate
  141.                     0, // event's client x coordinate
  142.                     0, // event's client y coordinate
  143.                     false, // whether or not CTRL was pressed during event
  144.                     false, // whether or not ALT was pressed during event
  145.                     false, // whether or not SHIFT was pressed during event
  146.                     false, // whether or not the meta key was pressed during
  147.                     1,  // indicates which button (1 = primary button)
  148.                     null); // relatedTarget (only applicable for mouseover/mouseout events)
  149.                 alert("dispatching event...");
  150.                 originalControl.dispatchEvent(reissuedOriginalEvent);
  151.             } catch (ex) {
  152.                 reissuedOriginalEvent = document.createEventObject();
  153.                 reissuedOriginalEvent.detail = 0;
  154.                 reissuedOriginalEvent.screenX = 0;
  155.                 reissuedOriginalEvent.screenY = 0;
  156.                 reissuedOriginalEvent.clientX = 0;
  157.                 reissuedOriginalEvent.clientY = 0;
  158.                 reissuedOriginalEvent.ctrlKey = 0;
  159.                 reissuedOriginalEvent.altKey = 0;
  160.                 reissuedOriginalEvent.shiftKey = 0;
  161.                 reissuedOriginalEvent.metaKey = 0;
  162.                 reissuedOriginalEvent.button = 1;
  163.                 reissuedOriginalEvent.relatedTarget = originalControl;
  164.                 alert("firing event...");
  165.  
  166.                 //var defaultChecked = originalControl.defaultChecked;
  167.                 //originalControl.checked = !defaultChecked;
  168.                 alert(originalControl.defaultChecked);
  169.  
  170.                 //Uncomment the following to check the checkbox.
  171.                 //originalControl.checked = !originalControl.checked;
  172.             }
  173.         }
  174.  
  175.         //Adding event listener:
  176.         var testElement = document.getElementById('testElement');
  177.         try {
  178.             //FireFox
  179.             testElement.addEventListener('click', _stopEvent, false);
  180.         } catch (ex) {
  181.             //IE
  182.             testElement.attachEvent("onclick", _stopEvent);
  183.         }
  184.     </script>
  185.  
  186.     </form>
  187. </body>
  188. </html>
May 22 '09 #3
Frinavale
9,735 Expert Mod 8TB
@Frinavale

The problem isn't so bad for CheckBoxes, RadioButtons etc....because I can just force the default action to happen (setting the checked value to checked)....

But the problem is really bad with concerns to Submit buttons.

The Submit buttons do not preform their default behaviour: they do not submit to the server. If I simply call the form submit, the server side button click event will be lost and it will by-pass any additional JavaScript code that should have been executed when the button was clicked.

I'm not fond of the idea of forcing the default behaviour for every DOM element that is the target of the re-issued event...there has to be a better way.
May 22 '09 #4
Frinavale
9,735 Expert Mod 8TB
I think I found a clue that will help me find an answer to my question in the w3c specifications for events.

According to the specification (section 1.4):

... the activation behavior of the event target is the default action of the event type DOMActivate. DOM applications should use this event type whenever they wish to make or react to an activation request.
Since I want to activate the DOM that is the target of the re-fired event, I believe I need to use the DOMActivate event type (since the DOM application (IE) isn't doing this).

I'm just not sure how or when to use this (yet...)

According to the specification (section 1.3):
Before invoking a default action, the implementation must first dispatch the event as described in the Event dispatch and DOM event flow
So, I think I need to dispatch 2 events: the Event that I'm re-dispatching and then the DOMActivate event.
May 22 '09 #5
Frinavale
9,735 Expert Mod 8TB
Uugg...that clue wasn't very helpful other than confirming what I already knew....well I guess it was helpful in that it helped me understand how Browser Implementation was supposed to be implemented.

I'm stuck.

I wish I read this article sooner:
Note that manually firing an event does not generate the default action associated with that event. For example, manually firing a focus event does not cause the element to receive focus (you must use its focus method for that), manually firing a submit event does not submit a form (use the submit method), manually firing a key event does not cause that letter to appear in a focused text input, and manually firing a click event on a link does not cause the link to be activated, etc. In the case of UI events, this is important for security reasons, as it prevents scripts from simulating user actions that interact with the browser itself.
Apparently FireFox is the browser that's not correctly implemented this time.

I think I'm back to my original problem... I'm going to have to manually cause the submit/postback to the server. I just don't like the solution. (In this case I'm going to need your help grabbing what should have been executed if the DOM was activated by the event...which is what I was originally asking for help with)

Looking forward to considering anyone's input regarding the problem.

-Frinny
May 22 '09 #6
gits
5,390 Expert Mod 4TB
hi frinny ...

i was on a vacation the last days and probably will have a look at this in the evening ... since there is a lot of info in here right now :) ...

kind regards,
gits
May 25 '09 #7
Frinavale
9,735 Expert Mod 8TB
Updated code in post 3 so that it makes more sense when reading it.
May 25 '09 #8
Frinavale
9,735 Expert Mod 8TB
I've tested in Chrome and Safari and have found that they work the same way as FireFox:
  • they properly cancel events when events are cancelled,
  • they preform the default behaviour on DOM elements when I issue an event via JavaScript,
  • and they execute all event handlers when I issue an event via JavaScirpt.

So that means that IE is the only strange one here. I can see why they prevent the default action when events originate from JavaScript (to prevent scripts from doing something that the user was not expecting) but after about a minute of thinking about it I was able to get around this. If I can think of a way around this than anyone with fairly basic knowledge of JavaScript can as well...so why bother making the developer jump through hoops?!

I'm really not happy with IE right now because it's:
  • forcing me to properly revert the DOM element back to it's original state when I cancel an event
  • forcing me to code the default behaviour of the DOM elements when I fire events
  • and it's forcing me to hard code calls to JavaScript that should have been called as event handlers to the event that I'm raising.

Thanks for your time Gits, but I'm just going to live with the ugliness that IE demands and stick to the hard coded JavaScript calls (whenever IE is using my Object).

Disappointed,

-Frinny
May 25 '09 #9
gits
5,390 Expert Mod 4TB
hi frinny,

so as always the IE is messing up the slick things ;) ... and i guess that you should use your solution because it seems to work ... and ignore the ugliness :) ... and i'm not very aware of such things since i never found it very useful or even necessary to fire events from a script ... since that is quite unusual from my point of view and so i never really needed that ... and so i'm not aware of those pitfalls you encountered ... that are interesting ones though ...

kind regards,
gits
May 26 '09 #10

Sign in to post your reply or Sign up for a free account.

Similar topics

6
by: Andy Fish | last post by:
Hi, I want to use an anchor tag to invoke some javascript and I've read that it's bad form to use <a href="javascript:foo()"> I've read endless usenet posts and hint sites on the net, they all...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.