JavaScriptでbaseを指定して相対URLを絶対URLに変換する

メモがわり。
baseとなるURLを指定して相対URLを絶対URLに変換するには、ChromeやFireofxではURLUtilsを用いて以下のように書くことで簡単に実現できる。

var absolute = (new URL( "foo", "http://example.jp/bar/baz" ) ).href; // http://example.jp/bar/foo

IEではURLコンストラクタはサポートされていないが、IE9以上ではDOMParsercreateHTMLDocumentを使って現在のDOMとは分離したdocumentを生成し、その中に<base>要素を用いてbase URLを指定し、そのdocument内で<a>要素を用いて相対URLを絶対URLに変換するという手段によって相対URLを絶対URLに変換可能である。

function getAbsoluteUrl( url, base ){
    var doc, baseElm;

    var fallback = function( doc, url ){
        var elm = doc.createElement( "a" );
        elm.setAttribute( "href", "/test" );
        if( elm.href === "/test" ){
            // IE6, IE7
            elm.setAttribute( "href", url );
            return elm.getAttribute( "href", 4 );
        }else{
            elm.setAttribute( "href", url );
            return elm.href;
        }
    }
    if( base === undefined ){
        try{
            return (new URL( url, loation.href )).href;
        }catch( e ){
            return fallback( document, url );
        }
    }else{
        try{
            return (new URL( url, base )).href;
        }catch( e ){
            if( typeof DOMParser !== "undefined" ){
                try{
                    var parser = new DOMParser();
                    doc = parser.parseFromString( "<html><head></head><body></body>", "text/html" );
                    baseElm = doc.createElement( "base" );
                    baseElm.setAttribute( "href", base );
                    doc.head.appendChild( baseElm );
                }catch( e ){
                    doc = undefined;
                }
            }
            if( !doc && document.implementation && document.implementation.createHTMLDocument ){
                try{
                    doc = document.implementation.createHTMLDocument("");
                    baseElm = doc.createElement( "base" );
                    baseElm.setAttribute( "href", base );
                    doc.head.appendChild( baseElm );
                }catch( e ){
                    doc = undefined;
                }
            }
            if( doc ){
                return fallback( doc, url );
            }else{
                return "";
            }
        }
    }
}