autoembed.js 3.53 KB
/**
 * This extension auto embeds urls.
 */
(function () {
    angular.module('footyroom')

    .directive('autoEmbed', ['urlEmbedder', function(urlEmbedder) {
        return {
            link: function(scope, element, attrs) {
                if (urlEmbedder.get(attrs.href) === undefined) {
                    var spinner = angular.element('<i class="spinner"></spinner>').appendTo(element);
                }

                urlEmbedder.fetch(attrs.href)

                .then(function(embed) {
                    if (embed) {
                        element.replaceWith(iframeEmbed(embed, attrs.href));
                    }
                })

                .finally(function() {
                    spinner.remove();
                })
            }
        };
    }])

    .service('urlEmbedder', ['$http', '$q', function($http, $q) {
        var service = this;
        
        service.cache = {};
        service.get = get;
        service.fetch = fetch;

        function fetch(url) {
            if (service.cache[url] !== undefined) {
                return $q.when(this.cache[url]);
            }

            return $http.get('/embed?url=' + url)

            .then(function(response) {
                return service.cache[url] = response.data.html;
            })

            .catch(function() {
                return service.cache[url] = null;
            });
        }

        function get(url) {
            return service.cache[url];
        }
    }]);

    function init() {
        var height;
        var src = window.frameElement.getAttribute('data-src');
        
        setInterval(function () {
            resize();
            reload();
        }, 1000);

        function resize() {
            var current = window.document.documentElement.offsetHeight;

            if (height !== current) {
                window.frameElement.style.height = current + "px";
            }

            height = current;
        }

        function reload() {
            var current = window.frameElement.getAttribute('data-src');

            if (src !== current) {
                window.frameElement.src = "javascript: unescape(window.frameElement.getAttribute('src-doc'));";
            }

            src = current;
        }
    }

    function iframeEmbed(embed, url) {
        var i = '(' + init.toString() + ')();';

        return '<div class="embed-wrap"><iframe data-src="'+ url +'"' +
            'src-doc="<!DOCTYPE html><html><head></head><body><script>'+ escape(i) + '<\/script>' + escape(embed) +'</body></html>"' +
            'src="javascript: unescape(window.frameElement.getAttribute(\'src-doc\'));"' +
            'frameborder="0" width="100%" allowfullscreen></iframe></div>';
    }

    function autoEmbed() {
        const urlEmbedder = angular.injector(['ng', 'footyroom']).get('urlEmbedder');
        
        return [{
            type: 'lang',
            filter: function(text) {
                return text.replace(/^((?:[-+*] |\d+\. |>)? *)((?:https:\/\/|www\.)[^'">\s]+\.[^'">\s]+)( *$)/gm, function(match, p1, p2, p3) {
                    var embed = urlEmbedder.get(p2);

                    if (!embed) {
                        return p1 + '<div class="p" href="'+ p2 +'" auto-embed><a href="'+ p2 +'">'+ p2 + '</a></div>' + p3;
                    }

                    return iframeEmbed(embed, p2);
                });
            }
        }];
    }

    if (window && window.showdown) {
        window.showdown.extensions.autoembed = autoEmbed;
    }

    if (typeof module !== 'undefined') {
        module.exports = autoEmbed;
    }
})();