0

I'm new to jQuery and I did my best to throw together a function that on click opens a dialog message, and on click again closes it. What I want is to be able to click outside the dialog (anywhere on the screen) to close that dialog. How can I accomplish this in the setup I wrote? Also, is the code I currently have done correctly, or could I do it another, easier way?

EDIT (10/17/12):

I've updated the jQuery below to include part of Ryan Wheale's code, and this is the current status:

-"clickoutside" works for the currently open span

-Trying to open another span closes the current span and subsequently the new span

jQuery: http://www.eclipsisna.com/?ena=services

        $(".service_outline a, .service_title a, .service_price a").click(function() {
            $(this).closest("a").children("span").fadeToggle("fast", function() {
                $("span").not(this).fadeOut("fast");
            });
            $(this).one("clickoutside", function () {
                $("span").fadeOut("fast");
            });
        });

HTML:

    <td class="service_outline">
            <h11><a>Opti-<br><h12>Coat</h12><span><font color="#ffcc00">&bull;</font> Application of permanent, nano ceramic clear resin coating (replaces "Wax"/"Sealant")<br><font color="#ffcc00">&bull;</font> Extended durability for 2+ years<br><font color="#ffcc00">&bull;</font> $250<p><center><img src="images/opti-coat.png"></center></span></a></h11>
    </td>
eclipsis
  • 1,541
  • 3
  • 20
  • 56

1 Answers1

0

If you are using Ben Allman's clickoutside plugin found here, your life is easy:

http://jsfiddle.net/ryanwheale/c89Vr/

var $links = $(".service_outline a, .service_title a, .service_price a"),
    $dialogs = $links.find( 'span' );

$links.on( 'click', showDialog );

/* -- EDIT: old code kept for historical purposes
$dialogs.on( 'clickoutside', hideDialogs );
*/

function showDialog (ev) {
    var $thisDialog = $(this).find( 'span' );

    /* -- EDIT: old code kept here for historical purposes
    $dialogs.not( $thisDialog ).fadeOut();
    */

    if(!$thisDialog.is(':visible')) {
        $thisDialog.fadeIn();

        /* -- EDIT: New code */
        setTimeout( function() {
            // IMPORTANT: touch events only supported when you use the 
            // modified plugin at the bottom of this example
            $thisDialog.one('clickoutside.closeDialog, touchstartoutside.closeDialog', function() {
                $thisDialog.unbind('.closeDialog').fadeOut();
            });
        }, 0);
    }
}

/* -- EDIT: old code kept here for historical purposes
function hideDialogs() {
    $dialogs.fadeOut();
}
*/

/*
 * jQuery outside events - v1.1 - 3/16/2010
 * http://benalman.com/projects/jquery-outside-events-plugin/
 * 
 * Copyright (c) 2010 "Cowboy" Ben Alman
 * Dual licensed under the MIT and GPL licenses.
 * http://benalman.com/about/license/

 * IMPORTANT: Modified to support touch events
 */
(function($,c,b){$.map("click dblclick mousemove mousedown mouseup mouseover mouseout change select submit keydown keypress keyup touchstart touchmove touchend".split(" "),function(d){a(d)});a("focusin","focus"+b);a("focusout","blur"+b);$.addOutsideEvent=a;function a(g,e){e=e||g+b;var d=$(),h=g+"."+e+"-special-event";$.event.special[e]={setup:function(){d=d.add(this);if(d.length===1){$(c).bind(h,f)}},teardown:function(){d=d.not(this);if(d.length===0){$(c).unbind(h)}},add:function(i){var j=i.handler;i.handler=function(l,k){l.target=k;j.apply(this,arguments)}}};function f(i){$(d).each(function(){var j=$(this);if(this!==i.target&&!j.has(i.target).length){j.triggerHandler(e,[i.target])}})}}})(jQuery,document,"outside");
Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
  • This solutions requires a jQuery plugin - 'clickoutside' is not an event supported by jQuery. – coderabbi Oct 15 '12 at 23:57
  • @coderabbi - Thanks for that. I have used ben allman's clickoutside plugin for so long that I didn't mention it. I am writing a better solution now. – Ryan Wheale Oct 16 '12 at 00:07
  • As I started to write a better solution, I could see that I was starting down the path of Ben Allman's solution... so I defer to that `:(` - I updated my answer to reflect that. – Ryan Wheale Oct 16 '12 at 00:51
  • I installed the plugin and updated the site to show your code, but now once a span is clicked, it fades in, then immediately fades out. You can see it in the link. – eclipsis Oct 16 '12 at 17:08
  • I updated my code (leaving old code in there... commented out). See if that helps at all. – Ryan Wheale Oct 17 '12 at 02:08
  • Same thing is happening, fades in then fades out on one click. Should still show in the OP's link. – eclipsis Oct 17 '12 at 15:16
  • I updated my code. A timeout was needed to delay the binding of the "clickoutside" event. If you would like an explanation of why the timeout is needed, let me know. – Ryan Wheale Oct 17 '12 at 18:53
  • That works now, but it broke something else. Click a button to open a span, click again to close it, then click again to try and open it. On the 2nd open, the same fadeOut event occurs immediately. Would we have to setTimeout for that as well? – eclipsis Oct 17 '12 at 19:22
  • ok... sheesh I'm earning this one ;) - I added a check to make sure the dialog wasn't visible... mocks a true toggle behavior. – Ryan Wheale Oct 18 '12 at 18:50
  • Hahaha - maybe award me points ;) This was a good challenge. I learned something out of it. – Ryan Wheale Oct 18 '12 at 19:06
  • Done :) Do you know if there's any way to get "clickoutside" to work on mobile devices? As it is it doesn't look like it's supported. – eclipsis Oct 18 '12 at 19:25
  • hmmm, you can try modifying the plugin. At the very beginning, you should see a space delimited list of events: `"click dblclick mousemove..."` - try adding `"touchstart touchend touchmove"` to the list. – Ryan Wheale Oct 18 '12 at 19:51
  • Tried that, nothing. Would I have to have the jquery Mobile plugin installed to make it work? – eclipsis Oct 18 '12 at 20:20
  • I wish you had enough points to chat... anyhow, I don't have my phone right now, but you should be able to update my code to read `$thisDialog.one('clickoutside, touchstartoutside', function() { ...` - I don't want to update my example because this relies on a custom modification to Ben Alman's plugin. – Ryan Wheale Oct 18 '12 at 21:01
  • That worked for the mobile, only now if the same icon is clicked twice on a mobile device, that same "immediate fade out on 2nd open" happens like the issue you resolved when you made the dialog visible. And yes, I wish I had enough points for chat. – eclipsis Oct 19 '12 at 17:12
  • Ok, so I was binding 2 events using the `one()` function of jQuery, which means one of the events was getting unbound and not the other. I was afraid this might cause problems and was being lazy. I have updated the code accordingly. – Ryan Wheale Oct 19 '12 at 19:08
  • I replaced lines 82-86 of Ben Alman's code w/ the custom plugin you added; same issue is happening. – eclipsis Oct 19 '12 at 20:01
  • ryan [dot] wheale [at] gmail [dot] com – Ryan Wheale Oct 19 '12 at 23:24