New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular Wrapper Directive #538

Closed
campbeln opened this Issue Mar 17, 2016 · 3 comments

Comments

Projects
None yet
2 participants
@campbeln

campbeln commented Mar 17, 2016

In order to use Tooltipster I had to roll an Angular directive and I thought it might be worthwhile to share the code back to the community!

Exclusive scoping is not required and everything is 100% overrideable. I have added a single option setting that is consumed by the directive - selector. This specifies a DOM object that is selected via jQuery(_selector_) to act as the content of the tooltip. This value can either be set as a string specifying the selector or as true (which specifies that the value of [title] is to be used as the selector).

ngApp.directive('title', ["$timeout", function ($timeout) {
    function isStr(s, bDisallowNullString) {
        return (
            (typeof s == 'string' || s instanceof String) &&
            (!bDisallowNullString || s !== '')
        ) ? true : false;
    }

    function isFn(f) {
        return (Object.prototype.toString.call(f) === '[object Function]') ? true : false;
    }

    function makeObj(o) {
        return (o && o === Object(o) && !isFn(o) ? o : {});
    }

    return {
        restrict: 'A',
        link: function ($scope, $element, $attrs) {
            var oOptions = makeObj($scope.$eval($attrs.titleOptions)),
                bTitleIsSelector = (oOptions.selector === true),
                b$evalTitle = true
            ;

            //# Configure the .tooltipster for the $element
            $element.tooltipster(jQuery.extend({
                //# Hook the .functionBefore to reset the .content based on the latest data from Angular
                functionBefore: function(origin, continueTooltip) {
                    var sContent = $attrs.title;

                    //# If a .selector was passed (either in the .title or in .selector), set the sContent to its .html 
                    if (bTitleIsSelector || isStr(oOptions.selector, true)) {
                        sContent = jQuery(bTitleIsSelector ? sContent : oOptions.selector).html();
                    }
                    //# Else if we can b$evalTitle
                    else if (b$evalTitle) {
                        try {
                            sContent = $scope.$eval(sContent);
                        } catch (e) {
                            b$evalTitle = false;
                            //console.log("$eval Error: ", $element, sContent, e);
                        }
                    }

                    //# Clear the [title] so the browser doesn't pop up the element
                    $timeout(function() {
                        $element.attr("title", "");
                    });

                    //# Update the sContent, .continueTooltip'ing if there is sContent to display
                    origin.tooltipster('content', (oOptions.contentAsHTML ? jQuery(sContent) : sContent));
                    sContent && continueTooltip();
                }
            }, oOptions));
        }
    };
}]);

Usage:

<div title="My Title!" title-options="{ position: 'bottom-left', offsetX: -10 }">blah</div>
<div title="This will be ignored" title-options="{ selector: '#MyContent', contentAsHTML: true }">blah</div>
<div title="#MyContent" title-options="{ selector: true, contentAsHTML: true }">blah</div>
<div id="MyContent">
    <b>HTML</b> Content here!
</div>
@louisameline

This comment has been minimized.

Show comment
Hide comment
@louisameline

louisameline Mar 18, 2016

Collaborator

Thank you ! I lack experience on Angular to fully appreciate the results of this snippet but I'll probably end up trying at some point and hint at this in the documentation. Thanks again !

Collaborator

louisameline commented Mar 18, 2016

Thank you ! I lack experience on Angular to fully appreciate the results of this snippet but I'll probably end up trying at some point and hint at this in the documentation. Thanks again !

@louisameline

This comment has been minimized.

Show comment
Hide comment
@louisameline

louisameline Jul 15, 2016

Collaborator

A small update would be required for this to work with Tooltipster v4 since the signature of functionBefore has changed.

functionBefore: function(origin, continueTooltip) {
becomes
functionBefore: function(instance, helper) {

origin.tooltipster('content', (oOptions.contentAsHTML ? jQuery(sContent) : sContent));
becomes
instance.content(oOptions.contentAsHTML ? jQuery(sContent) : sContent);
but actually could be
instance.content(sContent);
since Tooltipster itself appends the content as an HTML node if contentAsHTML is true.

The sContent && continueTooltip(); line can be removed, Tooltipster continues when you don't return false but then stops by itself if sContent is null.

And a selector for HTML content can now be passed in a data-tooltip-content attribute, so I think you don't need to do that yourself anymore.

...and I think it should work.

Collaborator

louisameline commented Jul 15, 2016

A small update would be required for this to work with Tooltipster v4 since the signature of functionBefore has changed.

functionBefore: function(origin, continueTooltip) {
becomes
functionBefore: function(instance, helper) {

origin.tooltipster('content', (oOptions.contentAsHTML ? jQuery(sContent) : sContent));
becomes
instance.content(oOptions.contentAsHTML ? jQuery(sContent) : sContent);
but actually could be
instance.content(sContent);
since Tooltipster itself appends the content as an HTML node if contentAsHTML is true.

The sContent && continueTooltip(); line can be removed, Tooltipster continues when you don't return false but then stops by itself if sContent is null.

And a selector for HTML content can now be passed in a data-tooltip-content attribute, so I think you don't need to do that yourself anymore.

...and I think it should work.

@louisameline

This comment has been minimized.

Show comment
Hide comment
@louisameline

louisameline Aug 24, 2016

Collaborator

I have listed this page in the documentation, thanks.

Collaborator

louisameline commented Aug 24, 2016

I have listed this page in the documentation, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment