简体   繁体   中英

Binding .click and .blur event handlers

I'm running into a problem binding both a .blur and .click event handler to the same clickable element. The UX I'm going for is as follows:

a user clicks on the search icon and the search field appears; when a user clicks again on the search icon, they can collapse and hide the search field. If they click away, the search field should hide.

So far, I'm able to achieve most of what I want, except that I can't get the .click binding to toggle the class after it's been clicked. I'm thinking it's possibly because after being toggled the $ selector doesn't have any results to select? I'm relatively new to JavaScript so I'm a little unclear on exactly how JavaScript or jQuery would handle something like this.

Jsfiddle here: http://jsfiddle.net/TpXJe/1/

Edit : including code here so future Stack Overflow users can see it:


html:

<form class="hidden-xs search-container navbar-right search-form" method="get">
    <div class="input-group">
        <input id="search-box" type="search" class="search-box" name="s" class="search-field form-control" />
        <label class="hide">Search for something</label>
        <label for="search-box"><span id="searchDivider">|</span>

            <div class="icon-continer"> <span class="glyphicon glyphicon-search search-icon"></span>

            </div>
        </label>
       </div>
</form>

css:

.search-container {
  right: 0px;
}

#searchDivider {
  position: absolute;
  right: 0px;
  top:31px;
  z-index: 1;
  color: @brand-success;
  cursor: pointer;
  font-weight: 200;

}
// Style the search box



$tl: .3s; // transition length

.search-box {
  outline-width: 0;
  transition: width $tl, border-radius $tl, background $tl;
  position: absolute;
  right:-37px;
  top: 20px;
  z-index: 100;
  width: 40px;
  height: 40px;
  border-radius: 20px;
  border: none;
  cursor: pointer;
  background: transparent;
  & + label .search-icon {
    color: black    }
  &:hover {
    color: white;
    background: transparent;
    box-shadow: 0 0 0 1px transparent;
    & + label .search-icon {
       color: white    }
  }
  &.focused {
    transition: width $tl cubic-bezier(.18,.57,.25,.94), border-radius $tl;
    border: none;
    outline: none;
    box-shadow: none;
    padding-left: 15px;
    cursor: text;
    width: 600px;
    border: 1px solid black;
    border-radius: auto;
    background: white;
    color: black;
    & + label .search-icon {
      color: black;    }
  }
  &:not(:focus) {
    text-indent:-5000px;    } // for more-graceful falling back (:not browsers likely support indent)
}

#search-submit {
  position: relative;
  left: -5000px;
}

.search-icon {
  position: absolute;
  right: -45px;
  top: 14px;
  z-index: 1000;
  color: black;
  cursor: pointer;
  width: 60px;
  height: 60px;
  padding: 23px;
}

js:

  $('.search-icon').click(
  function () {
      $('.search-box ').toggleClass(' .search-box focused');
  });
  $('.search-box').blur(
  function () {
      $('.search-box').removeClass('focused');
  });

As Ehsan said in the comments, it appears that clicking the icon while it has already been clicked once fires both click() and blur() events. I just added in a variable to represent the state of clicked/unclicked and it works for me! Also in the updated fiddle below is what I believe you intended to do that Jacob mentioned in the comments-the class name is 'focused' not '.search-box focused'.

Updated JSFiddle Link

Here is the JS Code:

var clicked = false;

$('.search-icon').click(

  function () {
      if (clicked) {
      $('.search-box ').removeClass('focused');
          clicked = false;
      } else {
          $('.search-box ').addClass('focused');
          clicked = true;
      }
  });


  $('.search-box').blur(

  function () {
      $('.search-box').removeClass('focused');

What I have stated to do recently is set up all my event listeners as a variable (object). It makes being able to assign multiple events to a single object very easy.

/**
 * Event listeners.
 * Params: element, event : method
 * NOTE: element is passed in as a string, not jQuery object!
 * This so we have the possibility of multiple events for a single element (eg.    focus & change for the same element). 
 * 
 */
 eventHandlers: {
     'a click': 'onAnchorClick',
     'a hover': 'onAnchorHover'
 }, 


/**
 * Registers all event listeners/handlers.
 * @returns {void}
 * 
 */
registerEventHandlers: function() {
    var that = this;
    $.each(this.eventHandlers, function(key, val) {
        var split = key.split(" ");
        var element = split[0];
        var event = split[1];
        $(document).on(event, element, that[val]);
     });
 }

...

/**
 * Event listener for all anchor click events.
 * @param {object} event | The click event.
 * @returns {void}
 * 
 */
onAnchorClick: function(event) {
     console.log('click event');

    // For example purposes:
    var ga_eventData = {
        'category': 'Text Link',
        'action': 'Click',
        'label': event.currentTarget.innerText,
        'optionalData': {
            'page': window.location.protocol + '//' + window.location.host + window.location.pathname
            }
        }
        GA.registerEvent(ga_eventData);  // GA is my google analytics module in this example
},
/**
 * Event listener for all anchor hover events.
 * @param {object} event | The hover event.
 * @returns {void}
 * 
 */
onAnchorHover: function(event) {
    console.log('hover event');
}

...

Then in my initialization method, I simply call:

/**
 * Initialization method.
 * @returns {void}
 * 
 */
initialize: function() {
    var that = this;
    that.registerEventHandlers();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM