Search code examples
javascriptjqueryjquery-uitooltipdraggable

jQuery Draggable with Bootstrap Tooltip TypeError: e.$element is null


I have a draggable element (see the code snippet and click on picture to add pins) which shows a tooltip on mouseover and deletes it on mouseout.

The below code throws tens of errors "TypeError: e.$element is null" in Firefox or "Uncaught TypeError: Cannot read property 'trigger' of null" in Chrome as soon as I start dragging the pin element.

I tried:

$('.tooltip').remove();
$('.tooltip').tooltip('destroy');
$('.pin').tooltip('destroy');

but none of these solve that.

How can I stop the tooltip errors when dragging the element?

var pic_wrapper = $('#pic_wrapper');

var selected_picture = $('#selected_picture');

selected_picture.on('click', function(e) {
  var pin = $('<div class="pin"></div>');
  x = ((e.offsetX) / $(this).width()) * 100 + "%";
  y = ((e.offsetY) / $(this).height()) * 100 + "%";
  pin.uniqueId();
  pic_wrapper.append(pin);
  pin.css({
    transform: 'translate(-50%, -50%)'
  });
  pin.css({
    left: x,
    top: y
  }).show();
  pin.draggable({
    containment: 'parent'
  });
  pin.on('dragstart', function() {
    pin.css({
      transform: 'translate(0%, 0%)'
    });
  });
  pin.on('dragstop', function(e, ui) {
    x = (ui.position.left / pic_wrapper.width()) * 100 + "%";
    y = (ui.position.top / pic_wrapper.height()) * 100 + "%";
    pin.css({
      left: x,
      top: y
    });
  });
});

pic_wrapper.on('mouseenter', '.pin', function(e) {
  $(this).attr('title', 'tooltip text');
  $(this).tooltip({
    placement: function(context, source) {
      return "right";
    }
  });
  $(this).tooltip('show');
});

pic_wrapper.on('mouseout', '.pin', function(e) {
  $(this).tooltip('destroy');
});
#pic_wrapper {
  display: block;
  position: relative;
  padding: 0;
  border: 1px dotted #0099ff;
}

#selected_picture {
  width: 100%;
  height: auto;
  border: 1px solid #0099ff;
}

#selected_picture img {
  width: 100%;
  height: auto;
}

.pin {
  display: none;
  position: absolute;
  padding: 0;
  margin: 0;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #ff4100;
  cursor: pointer;
  box-shadow: 0 0 0 rgba(255, 65, 0, 0.4);
  animation: pulse 2s infinite;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<fieldset>
  <div class="col-xs-12">
    <div class="form-group">
      <div id="pic_wrapper">
        <div id="selected_picture">
          <img src="http://www.outline-world-map.com/map-images-original/blank-thin-gray-white-world-map-b9a.png" />
        </div>
      </div>
    </div>
  </div>
</fieldset>


Solution

  • Try with:

     $('.tooltip').tooltip('destroy').remove();
    

    it should do the trick

    I think the reason why you got this error, is that when you do the $('.tooltip').tooltip('destroy') it doesn't remove also all the events linked to the tooltip.

    update: It's necessary to update also

    $(this).attr('title', 'tooltip text');
    

    with

    $(this).attr('data-original-title', 'tooltip text');
    

    otherwise it display 2 tooltip!

    full JS code:

    var pic_wrapper = $('#pic_wrapper');
    
    var selected_picture = $('#selected_picture');
    
    selected_picture.on('click', function(e) {
      var pin = $('<div class="pin"></div>');
      x = ((e.offsetX) / $(this).width()) * 100 + "%";
      y = ((e.offsetY) / $(this).height()) * 100 + "%";
      pin.uniqueId();
      pic_wrapper.append(pin);
      pin.css({
        transform: 'translate(-50%, -50%)'
      });
      pin.css({
        left: x,
        top: y
      }).show();
      pin.draggable({
        containment: 'parent'
      });
      pin.on('dragstart', function() {
        pin.css({
          transform: 'translate(0%, 0%)'
        });
      });
      pin.on('dragstop', function(e, ui) {
        x = (ui.position.left / pic_wrapper.width()) * 100 + "%";
        y = (ui.position.top / pic_wrapper.height()) * 100 + "%";
        pin.css({
          left: x,
          top: y
        });
      });
    });
    
    pic_wrapper.on('mouseenter', '.pin', function(e) {
      $(this).attr('data-original-title', 'tooltip text');
      $(this).tooltip({
        placement: function(context, source) {
          return "right";
        }
      });
      $(this).tooltip('show');
    });
    
    pic_wrapper.on('mouseout', '.pin', function(e)
    {
      $('.tooltip').tooltip('destroy').remove();
    });