title: jQuery Plugin Authoring, Help with Click Events (drop down menu)
body: <p>I'm trying to create a drop-down menu in a plugin manner. I'm familiar with scripting myself to solutions but I've never created a plugin before so I'm trying to learn how to do this, and therefore raising my level as a jQuery developer.</p>
  
  <p>I'm trying to create basic drop down functionality. You have a link. You click it, a drop down of links appear. You click outside of the link (the document) the menu of links goes away.</p>
  
  <p>I'm having trouble on the go away part. I tried to bind it to document.click but of course that shows the menu and then hides it, as there is nothing making sure it has to be shown first. How do I do this?</p>
  
  <p>How do I make it so that the menu only hides after it is shown if you click outside of it?</p>
  
  <p>application.js</p>
  
  <pre><code>jQuery(document).ready(function($){
    $("ul.drop-down").sillyDropDown();
    // failed attempt (shows and hides). Probably should go in plugin anyway.
    // $(document).click(function(){
    //   $("ul.drop-down").sillyDropDown('hide');
    // });
  });
  </code></pre>
  
  <p>silly_drop_down.js</p>
  
  <pre><code>(function($){
  
    var methods = {
  
      init : function(options){
        return this.each(function(){
          var $this = $(this);
          var selector = $(this).children()[0];
          var link = $(selector);
          link.bind('click.silly', methods.show);
        });
      },
      show : function() {
        var $this = $(this);
        var menu = $this.siblings("ul");
        menu.slideDown("slow");
      },
      hide : function(){
        var $this = $(this);
        var menu = $this.children("ul");
        menu.slideUp("slow");
      }
    };
  
    $.fn.sillyDropDown = function(method){
      if ( methods[method] ) {
        return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
      } else if ( typeof method === 'object' || ! method ) {
        return methods.init.apply( this, arguments );
      } else {
        $.error( 'Method ' +  method + ' does not exist on jQuery.sillyDropDown' );
      } 
    };
  
  })(jQuery);
  </code></pre>
  
  <p>the html if it matters</p>
  
  <pre><code>&lt;ul id="project-settings" class="drop-down"&gt;
    &lt;li&gt;
      &lt;a href="#"&gt;
        Settings
        &lt;img src="/images/iconic/white/cog_alt_16x16.png" class="stale"&gt;
        &lt;img src="/images/iconic/orange/cog_alt_16x16.png" class="hover"&gt;
      &lt;/a&gt;
    &lt;/li&gt;
    &lt;ul style="display: none;"&gt;
      &lt;div class="pointer"&gt;&lt;/div&gt;
      &lt;li class="first"&gt;
        &lt;a href="#"&gt;Settings...&lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;a href="#"&gt;Collaborators...&lt;/a&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;a href="#"&gt;Comments...&lt;/a&gt;
      &lt;/li&gt;
      &lt;hr&gt;
      &lt;li&gt;
        &lt;a href="#"&gt;Delete Project&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/ul&gt;
  </code></pre>
  
  <p>edit (I realized I asked similar question in past). 
  I did the following in application.js</p>
  
  <pre><code>  $("ul.drop-down").sillyDropDown();
    $(document).bind("click.silly", function(e){
      var nav = $("ul.drop-down");
      var target = $(e.target);
      if (target.closest("ul.drop-down").length &lt; 1){
        nav.sillyDropDown('hide');
        return;
      }
    });
  </code></pre>
  
  <p>This does the job. However it doesn't seem elegant to do it in application.js - How would I handle this inside the plugin?</p>
  
  <p><strong>Note: I'll probably have multiple instances of ul.drop-down - Am I missing something in my implementation to take care of this? So far only have one in my tests.</strong></p>
  
  <p>Also, how would I make it so that if I click a link inside the drop down I can force the menu to hide (this would be a modal popup for example).</p>
  
  <p>added this for now in application.js</p>
  
  <pre><code>  $("ul.drop-down ul li a").click(function(e){
      $("ul.drop-down ul").hide();
      return;
    });
  </code></pre>
  
  <p>Feels again, very unelegant and should probably be put somewhere else. Educate me please!</p>