Passing Mouse Events to Covered Elements
Situation: I have an element that flies in from the side of an article promoting the next post. It is fixed to the lower right corner of the screen and potentially covers right sidebar content. This wouldn't be a problem except that it has a large PNG dropshadow on it that can cover up links and stop the user from interacting with them. What I want to do is tell the browser to ignore the dropshadow area and pass mouse events onto the element behind it at any given time. Unfortunately, this isn't as easy as I thought it would be. Simple Solution: The CSS property pointer-events:none works perfectly in Firefox and Webkit browsers but not in Opera or Internet Explorer (see: When can I use pointer-events?), the browser used most by the target audience. Javascript Solution: So I wrote a simple script to pass clicks through to the elements covered by the background. I wanted to pass all mouse events so I could get hover effects etc (without adding classes to the elements underneath), but I found that :hover states can't be controlled via Javascript. That seems to be conventional wisdom on the Internet, anyway. I cut it down so it only passes click events through. Altogether, this resolves the issue of users not being able to click on links, but it's a little awkward because rollovers, cursor changes, and other effects don't happen. For the time being, I'm going to cut my losses. I'm putting this whole thing in an IE conditional statement and using pointer-events for other browsers. Opera doesn't occur enough that it's worth stressing over. If it becomes an issue, I'll do the browser detection in Javascript instead. It also gave me difficulty on assigning focus to form fields, but I found that I could do a check on the type of element I had clicked on and trigger its focus event instead. ------------------ CODE ON PAGE <script type="text/javascript" src="{{ static_url }}js/jquery.forward-clicks.js"> <script type="text/javascript"> $(document).ready(function() { $(".flyin-container").forwardEvents(".flyin .label, .flyin .headline, .flyin .meta"); }); </script> CODE IN jquery.forward-clicks.js (function($) { $.fn.forwardEvents = function(excludedSelector) { var $mainElement = this; var onElement = null; var pauseForwarding = false; this.click(function(event) { // Ignore if click is in the excluded elements var $targetElement = $(event.target); if (($targetElement.is(excludedSelector) > 0) || ($targetElement.parents().is(excludedSelector) > 0)) return true; // Temporarily hide main element to reveal elements behind it $mainElement.hide(); // Get element behind var element = $.elementFromPoint(event.clientX, event.clientY); // Trigger focus if covered element is a form field if (element.is("input") || element.is("select")) { element.focus(); } // Trigger event on covered element element[0].click(); // Restore main element $mainElement.show(); return false; }); }; })(jQuery); // http://www.zehnet.de/2010/11/19/document-elementfrompoint-a-jquery-solution/ (function ($) { var check=false, isRelative=true; $.elementFromPoint = function(x,y) { if(!document.elementFromPoint) return null; if(!check) { var sl; if((sl = $(document).scrollTop()) >0) { isRelative = (document.elementFromPoint(0, sl + $(window).height() -1) == null); } else if((sl = $(document).scrollLeft()) > 0) { isRelative = (document.elementFromPoint(sl + $(window).width() -1, 0) == null); } check = (sl>0); } if(!isRelative) { x += $(document).scrollLeft(); y += $(document).scrollTop(); } return $(document.elementFromPoint(x,y)); }; })(jQuery);


















