1

I have text inputs and textareas that I would like to show the user how many characters they have used out of the limit. So I add a tooltip to every element that has a data-maxlength attribute. I create the tooltip for the current text input that includes the length and the maxlength values(x / 250 characters) every time a key is pressed. The problem is that the value of the title attribute of the tooltip never changes after you stop typing for the first time. Here is a jsFiddle to show you.

The jQuery

$(document).ready(function(){
    $('[data-maxlength]').each(function(){
        $(this).on('keyup', function(){
            $(this).tooltip({
                selector: 'data-toggle="tooltip"',
                placement: 'bottom',
                trigger: 'manual',
                title: $(this).val().length + ' / ' + $(this).data('maxlength') + ' characters used.'
            });
            $(this).tooltip('show');
        });
    });
});

The HTML:

<textarea name="description" data-maxlength="250"></textarea>

Thanks for your time.

ShoeLace1291
  • 4,551
  • 12
  • 45
  • 81
  • Just a note: It's better to use `input` event instead of `keyup` when you track input changes, you can see that the tooltip title doesn't change properly if you still pressing some key. – Zakaria Acharki Mar 31 '16 at 09:25
  • @ZakariaAcharki: well that will not work for here, because OP wants to show the user about the character limit on every character entered/deleted on the input field, which is possible only by `keyup` event were as `change` event is triggered only when focus is moved out of the current field. – dreamweiver Mar 31 '16 at 09:52
  • Not sure what you mean @dreamweiver but sure that it will work, https://jsfiddle.net/vw49te7d/7/. – Zakaria Acharki Mar 31 '16 at 10:01
  • 1
    @ZakariaAcharki: my mistake bro, i misunderstood `input` event for `change`. your suggestion is valid :) – dreamweiver Mar 31 '16 at 12:03

4 Answers4

1

The title is set only on first key-event, try this:

title: function() {return $('[data-maxlength]').val().length + ' / ' + $(this).data('maxlength') + ' characters used.';}

see: How do JavaScript closures work?

I agree with dreamveivers comment, so this would be a better implementation:

$(document).ready(function(){
    $('[data-maxlength]').each(function(){
      var maxText = ' / ' + $(this).data('maxlength') + ' characters used.';
      var tooltip = $(this).tooltip({
            selector: 'data-toggle="tooltip"',
            placement: 'bottom',
            trigger: 'manual'
      });
      $(this).on('keyup', function(){
          tooltip.attr('title', $(this).val().length + maxText)
              .tooltip('fixTitle')
              .tooltip('show');
      });
    });
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<textarea name="description" data-maxlength="250"></textarea>

see: Change Twitter Bootstrap Tooltip content on click

Community
  • 1
  • 1
Meiko Rachimow
  • 4,664
  • 2
  • 25
  • 43
  • 2
    thats a nice solution but dont you think initialising the `tooltip` for every keyup event on the same element will create performance issue ? just updating the respective `attr` which holds that title seems more reasonable to me – dreamweiver Mar 31 '16 at 09:47
0

This seems to fix your problem:

$(document).ready(function(){

    $('[data-maxlength]').each(function(){
        $(this).on('keyup', function(){
            $(this).attr('data-original-title', $(this).val().length + ' / ' + $(this).data('maxlength') + ' characters used.');

            $(this)
              .tooltip({
                selector: 'data-toggle="tooltip"',
                placement: 'bottom'
            })
            .data('placement', 'bottom');

            $(this).tooltip('show');
        });
    });
});

https://jsfiddle.net/vw49te7d/

As found here: Change Twitter Bootstrap Tooltip content on click

Community
  • 1
  • 1
Pimmol
  • 1,871
  • 1
  • 8
  • 14
0

Actually this is valid issue which has already been in github issue log & so far there hasn't been any major update on this from past 2+ yrs.

Github issue page

Workaround:

  1. Initialize the tooltip for all text area outside .each() since there is no need to loop through all the elements by class selector txtarea[Usage of class selector is far more better than attribute selector in terms of performance].
  2. Update the attr which holds the title info of the tooltip inside keyup callback

$(this).attr('data-original-title', $(this).val().length + ' / ' + $(this).data('maxlength') + ' characters used.');

Live Demo @ JSFiddle

dreamweiver
  • 6,002
  • 2
  • 24
  • 39
0

I noticed that every time I use .tooltip() for an element (ex. textarea), when the tooltip is displayed, there is always a <div> appended as the next sibling of the element (ex. textarea). The appended <div> has class tooltip. And inside the <div> there is an element with class tooltip-inner which contains the text that is the displayed message in the tooltip. Here is the example of the appended <div>:

<div style="top: 63px; left: 9.5px; display: block;" id="tooltip59349" class="tooltip fade bottom in" role="tooltip">
  <div style="left: 50%;" class="tooltip-arrow"></div>
  <div class="tooltip-inner">
    <span class="n-char">0</span> / 250 characters used.
  </div>
</div>

So, my solution is to replace the text inside that .tooltip-inner. In this solution you don't have to call .tooltip('show') everytime you want to change the title. You won't see blinked tooltip on every keyup.

$(document).ready(function(){
    $('[data-maxlength]').each(function(){
      $(this).tooltip({
        placement: 'bottom',
        trigger: 'focus',
        html: true,
        title: '<span class="n-char">' + $(this).val().length + '</span> / ' + $(this).data('maxlength') + ' characters used.'
      });

      $(this).on('focus keyup', function(){
        $(this).next('.tooltip').find('.tooltip-inner .n-char').text($(this).val().length);
      });
    });
});

https://jsfiddle.net/mikhsan/okpLzg5c/