0

I have a simple and nice tooltip code (written by someone else), it works well without angular, unlike with it. I've been thinking about the best way I could use it with angular. Here the code is:

$(document).ready(function () {
    (function () {

    var moveLeft = 0;
    var moveDown = 0;
    $('a.popper').hover(function (e) {
        console.log("Here it is");
        var target = '#' + ($(this).attr('data-popbox'));

        $(target).show();
        //moveLeft = $(this).outerWidth();
        moveLeft = 15;
        //moveDown = ($(target).outerHeight() / 4);
        moveDown = -15;
    }, function () {
        var target = '#' + ($(this).attr('data-popbox'));
        $(target).hide();
    });

    $('a.popper').mousemove(function (e) {
        console.log('mousemove');
        var target = '#' + ($(this).attr('data-popbox'));

        leftD = e.pageX + parseInt(moveLeft);
        maxRight = leftD + $(target).outerWidth();
        windowLeft = $(window).width() - 40;
        windowRight = 0;
        maxLeft = e.pageX - (parseInt(moveLeft) + $(target).outerWidth() + 20);

        if (maxRight > windowLeft && maxLeft > windowRight) {
            leftD = maxLeft;
        }

        topD = e.pageY - parseInt(moveDown);
        maxBottom = parseInt(e.pageY + parseInt(moveDown) + 20);
        windowBottom = parseInt(parseInt($(document).scrollTop()) + parseInt($(window).height()));
        maxTop = topD;
        windowTop = parseInt($(document).scrollTop());
        if (maxBottom > windowBottom) {
            topD = windowBottom - $(target).outerHeight() - 20;
        } else if (maxTop < windowTop) {
            topD = windowTop + 20;
        }

        $(target).css('top', topD).css('left', leftD);


    });

    })();
});

Please keep in mind that this code works well, I have jQuery included on the top, and if I inject this code with the chrome console, tooltip appears where it is supposed to. I'm kindly asking you guys for a way, this code could be used with angular, maybe with service/factory. The only problem I can see is as far as I know, DOM logic should not be written in services or factories (correct me f I'm wrong). I'm thinking about putting it in a directive, but I'm not sure if thats right, and how I could do it.

I have several views using tooltip, so I can't just put the whole code in the controller itself.

Kiss Koppány
  • 919
  • 5
  • 15
  • 33
  • 1
    This is not really an answer but angular-bootstrap has a pretty neat tooltip: https://angular-ui.github.io/bootstrap/#/tooltip – Muli Yulzary Dec 26 '16 at 23:19
  • 1
    Any code like this has to be put in directive but there are numerous available angular modules that you can use for tooltips which do not have any jQuery dependency. Strongly suggest reading [thinking-in-angularjs-if-i-have-a-jquery-background](http://stackoverflow.com/questions/14994391/thinking-in-angularjs-if-i-have-a-jquery-background) – charlietfl Dec 26 '16 at 23:21
  • 1
    Code that manipulates DOM should be put in a directive. AngularJS directives use an augmented subset of jQuery called [jqLite](https://docs.angularjs.org/api/ng/function/angular.element#angular-s-jqlite). The AngularJS framework will automatically replace the jqLite with jQuery augmanted with jqLite Extras if the jQuery library is included before the AngularJS library. For more information, see [AngularJS angular.element API Reference](https://docs.angularjs.org/api/ng/function/angular.element). – georgeawg Dec 26 '16 at 23:26
  • @MuliYulzary +1 for alternative – Kiss Koppány Dec 26 '16 at 23:57
  • @charlietfl +1 for the article you linked, and extra infos about directives – Kiss Koppány Dec 26 '16 at 23:58
  • @georgeawg +1 for angular elements, haven't used it so far. I think I'll go with directives, and see how it works – Kiss Koppány Dec 27 '16 at 00:02
  • 1
    To manipulate the DOM, put code in a directive or service, but never in a controller. – Fabio Silva Lima Dec 27 '16 at 00:44

1 Answers1

0

Thanks to everyone for suggestions how it could be done. Finally, I made it work by using angular directives. I'm sharing it with you all in case you need it, on github, link: ng-tooltip. I'm more than glad to hear from you about it, if you have any more suggestions please share with me.

Here's the directive itself:

.directive('ngTooltip', function () {
    return {
        link: function (scope, element, attribute) {
            //Our tooltip element
            var $target = angular.element('#tooltipcontent');
            var innerHtml = '';

            //Here you can customize what attributes you accept and how you show them on tooltip
            if (attribute.tooltipTitle) {
                innerHtml += '<h2>' + attribute.tooltipTitle + '</h2>';
            }

            if (attribute.tooltipBody) {
                innerHtml += '<p>' + attribute.tooltipBody + '</p>';
            }

            if (attribute.tooltipFooter) {
                innerHtml += '<p class="info">' + attribute.tooltipFooter + '</p>';
            }

            element.hover(function (e) {

                //Set inner content
                angular.element($target).html(innerHtml);

                //Show tooltip
                angular.element($target).show();

                //Distance X from the cursor
                moveLeft = 10;

                //Distance Y from the cursor
                moveDown = -10;
            }, function () {

                //Hide tooltip upon element mouseleaving
                angular.element($target).hide();
            });

            element.mousemove(function (e) {

                //Calculating positions
                leftD = e.pageX + parseInt(moveLeft);
                maxRight = leftD + angular.element($target).outerWidth();
                windowLeft = angular.element(window).width() - 40;
                windowRight = 0;
                maxLeft = e.pageX - (parseInt(moveLeft) + angular.element($target).outerWidth() + 20);

                if (maxRight > windowLeft && maxLeft > windowRight) {
                    leftD = maxLeft;
                }

                topD = e.pageY - parseInt(moveDown);
                maxBottom = parseInt(e.pageY + parseInt(moveDown) + 20);
                windowBottom = parseInt(parseInt(angular.element(document).scrollTop()) + parseInt(angular.element(window).height()));
                maxTop = topD;
                windowTop = parseInt(angular.element(document).scrollTop());
                if (maxBottom > windowBottom) {
                    topD = windowBottom - angular.element($target).outerHeight() - 20;
                } else if (maxTop < windowTop) {
                    topD = windowTop + 20;
                }

                angular.element($target).css('top', topD).css('left', leftD);
            });
        }
    }
});
Kiss Koppány
  • 919
  • 5
  • 15
  • 33