0

I want to make my iframes responsive. I am using angular directive with typescript to achieve that.

This is the code:

...
export class ContentDirective implements angular.IDirective {
    public priority =  -1;
    public restrict = 'A';
    public scope = {};

    static $inject = [
        "$window"
    ];

    constructor(private $window, private $timeout, private $compile) {

    }

    public link: angular.IDirectiveLinkFn = (scope: angular.IScope, element: angular.IAugmentedJQuery, attrs: angular.IAttributes): void => {
        this.handleResize(element);
    };

    private handleResize(element): void {
        var win = angular.element(this.$window);
        // Find all iframes
        var $allVideos = element.find("iframe"),
        // The element that is fluid width
            $fluidEl = element;

        // Figure out and save aspect ratio for each iframe
        $allVideos.each(function () {
            $(this)
                .data('aspectRatio', this.height / this.width)
                // and remove the hard coded width/height
                .removeAttr('height')
                .removeAttr('width');
        });

        // When the window is resized
        win.resize(() => {
            var newWidth = $fluidEl.width();
            // Resize all iframes according to their own aspect ratio
            $allVideos.each(function () {
                var $el = $(this);
                $el
                    .width(newWidth)
                    .height(newWidth * $el.data('aspectRatio'));
            });
        }).resize();
    }

    public static factory(): angular.IDirectiveFactory {

        var directive = ($window) => {
            return new ContentDirective($window);
        };

        directive.$inject = ['$window'];
        return directive;
    }
}
...

This is the part of html I am using:

...
<p ng-bind-html="body" content-directive></p>
...

"body" is angular expression with content of p tag. Iframe is in there.

The problem I have is that there isn't any iframe element inside p tag when directive start execution. When I put $timeout to wait for DOM then everything is working correctly.

How can I start execution of directive after DOM is loaded?

I found the solution here:

thanks to mohamedrias

so the working code is looking like this:

export class ContentDirective implements angular.IDirective {
    public priority =  10;
    public restrict = 'A';

    static $inject = [
        "$window"
    ];

    constructor(private $window) {

    }

    public link: angular.IDirectiveLinkFn = (scope: angular.IScope, element: angular.IAugmentedJQuery, attrs): void => {
        scope.$watch(attrs.ngBindHtml, () => {
            this.handleResize(element);
        });
    };

    private handleResize(element): void {
        var win = angular.element(this.$window),
        // Find all iframes
            $allVideos = element.find("iframe"),
        // The element that is fluid width
            $fluidEl = element;

        // Figure out and save aspect ratio for each iframe
        $allVideos.each(function () {
            $(this)
                .data('aspectRatio', this.height / this.width)
                // and remove the hard coded width/height
                .removeAttr('height')
                .removeAttr('width');
        });

        // When the window is resized
        win.resize(() => {
            var newWidth = $fluidEl.width();
            // Resize all iframes according to their own aspect ratio
            $allVideos.each(function () {
                var $el = $(this);
                $el
                    .width(newWidth)
                    .height(newWidth * $el.data('aspectRatio'));
            });
        }).resize();
    }

    public static factory(): angular.IDirectiveFactory {

        var directive = ($window) => {
            return new ContentDirective($window);
        };

        directive.$inject = ['$window'];
        return directive;
    }
}
Community
  • 1
  • 1
kukipei
  • 631
  • 2
  • 8
  • 32

1 Answers1

0

As tyler suggested in comment I am putting answer separately

I found the solution here:

thanks to mohamedrias

so the working code is looking like this:

export class ContentDirective implements angular.IDirective {
public priority =  10;
public restrict = 'A';

static $inject = [
    "$window"
];

constructor(private $window) {

}

public link: angular.IDirectiveLinkFn = (scope: angular.IScope, element: angular.IAugmentedJQuery, attrs): void => {
    scope.$watch(attrs.ngBindHtml, () => {
        this.handleResize(element);
    });
};

private handleResize(element): void {
    var win = angular.element(this.$window),
    // Find all iframes
        $allVideos = element.find("iframe"),
    // The element that is fluid width
        $fluidEl = element;

    // Figure out and save aspect ratio for each iframe
    $allVideos.each(function () {
        $(this)
            .data('aspectRatio', this.height / this.width)
            // and remove the hard coded width/height
            .removeAttr('height')
            .removeAttr('width');
    });

    // When the window is resized
    win.resize(() => {
        var newWidth = $fluidEl.width();
        // Resize all iframes according to their own aspect ratio
        $allVideos.each(function () {
            var $el = $(this);
            $el
                .width(newWidth)
                .height(newWidth * $el.data('aspectRatio'));
        });
    }).resize();
}

public static factory(): angular.IDirectiveFactory {

    var directive = ($window) => {
        return new ContentDirective($window);
    };

    directive.$inject = ['$window'];
    return directive;
}
}
Community
  • 1
  • 1
kukipei
  • 631
  • 2
  • 8
  • 32