0
\$\begingroup\$

I'm using bootstrap 3.0 to display a tooltip (this example isn't specific to boot-strap) where the html inside the tooltip is fed from an AJAX call. In the future I want to be able to use the same element to fire different AJAX calls (something like fire a different AJAX call if the shift+click was used). To make that easy, I decided to use a tooltipManager object. This object currently has two properties:

  1. title: in bootstrap, this is the html represented when an element is hovered over
  2. placement: the values for this are left,right,top,bottom

EDIT: I just got the program working, but I need to know WHY it's working because I tried something like this for hours and had nothing but bad luck. Why is setPlacement able to return the correct value?

 $(document).ready(function () {
        //in the future there will be n amount of these
        //each will have the ability to use different urls to make different AJAX calls (not implemented yet)
        var tooltipManager = {
            title: function () {
                //ajax code to get title from database
                $.ajax({
                    type: "POST",
                    contentType: "application/json",
                    url: "Service.asmx/GetDrugs",
                    dataType: "json",
                    success: function (data) {
                        //bootstrap uses the title attribute to set the html inside the tooltip
                        //here it's set to the results of the AJAX
                        $('#click').attr('title', data.d)
                                   .tooltip({
                                       trigger: 'click',
                                       html: false,
                                       //using the sizer function the tooltip is placed where it needs to be.
                                       placement: tooltipManager.placement.setPlacement(data.d)
                                       //it seems to me that it would be better design to call the tooltipManager
                                       //setPlacement function, but since it's an async request, it fails

                                   }).click();
                    },
                    error: function (xhr) {
                        console.log('failed: ' + xhr.status);
                    }
                });

            },
            placement: {
                left: 'left',
                top: 'top',
                right: 'right',
                bottom: 'bottom',
                setPlacement: function (data) {
                    if (data.length > 4) {
                        return this.bottom;
                    }
                    else {
                        return this.right;
                    }
                }
            }
        }
        $('#click').one('click', function () {
            //how can I pass the entire state of the object here, instead of invoking these methods one by one.
            tooltipManager.title();
        });
        //not sure if this is good design to have this not a property of the tooltipManager object
        //this works currently for placing the tooltip in the correct position
        function sizer(data) {
            if (data.length > 4) {
                return tooltipManager.placement.bottom
            }
            else {
                return tooltipManager.placement.right
            }
        }

    });
\$\endgroup\$
1
+50
\$\begingroup\$

Your setPlacement method returns the "correct" data because whatever d is in your data object you receive from Service.asmx/GetDrugs is compared to be greater than 4. If it is then it will set the tooltip placement of the $('#click') element to bottom, otherwise it will set it to right. You can check it out by sticking this code at the bottom of the page:

alert('this is 3 characters: ' + tooltipManager.placement.setPlacement('asd'));
alert('this is 5 characters: ' + tooltipManager.placement.setPlacement('asdfg'));

All that placement does is it returns the words "left","top","right", or "bottom" depending on what it's set to in the placement object. You can change that object to this and it will still work:

placement: {
    l: 'left',
    t: 'top',
    r: 'right',
    b: 'bottom',
    setPlacement: function (data) {
        if (data.length > 4) {
            return this.b;
        }
        else {
            return this.r;
        }
    }
}

The setPlacement method doesn't actually set anything. What does is your jQuery's tooltip method.

You can change up all of line 48 like this (you also had a typo):

$('#click').on('click', tooltipManager.title);

You can delete the sizer function as I don't see a use for it. Something like that should be a method of the tooltipManager object anyways. On the same subject, since setPlacement doesn't actually set anything, you should probably change it to getPlacement or calcPlacement. It's more semantic and will help other developers that come behind you.

I would personally redo the entire tooltipManager.placement object to show the actual data that would be unknown. As an example, why on Earth would you need a static object to tell you what the number 2 is? Same for the string 'bottom'. tooltipManager.placement.bottom is the same thing as 'bottom'. Here's how I would structure that:

var tooltipManager = {
    setTitle: function () {
        $.ajax({
            type: "POST",
            contentType: "application/json",
            url: "Service.asmx/GetDrugs",
            dataType: "json",
            success: function (data) {
                $('#click').attr('title', data.d)
                .tooltip({
                    trigger: 'click',
                    html: false,
                    placement: tooltipManager.setPlacement(data.d)
                }).click();
            },
            error: function (xhr) {
                console.error('Failed tooltip request: ' + xhr.status);
            }
        });
    },
    setPlacement: function (data) {
        if (data.length > 4) {
            tooltipManager.placement = 'bottom';
            return 'bottom';
        } else {
            tooltipManager.placement = 'right';
            return 'right';
        }
    }
}

$('#click').on('click', tooltipManager.setTitle);

Note: I actually kept the setPlacement method, I just changed it so that it actually sets data. You can access the placement of the tooltip in javascript with tooltipManager.placement if you want. If you intend on having multiple tooltips you can just convert this all into a class. Also, I changed the tooltipManager.title method into tooltipManager.setTitle because it actually sets data.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.