The Hunt for the missing /: A story of anchors, location and Internet Explorer's pathname
Tags: internetexplorer, javascript, location, pathname
Published: 2019-06-05 12:20:20

---
title: The Hunt for the missing /: A story of anchors, location and Internet Explorer's pathname
published: true
description: Using location protocol from anchors, and pathname in Internet Explorer
tags: Internet Explorer, javascript, location, pathname
---

## The nice trick with anchors and location

There’s a really nice way to get the pathname off URLs that aren’t the current `window.location`. If you set them as the `href` of an anchor element, the anchor element actually implements the same `location` Protocol as `window`.

```js
// on https://adamdawkins.uk/articles
window.location.pathname // => “/articles”

var url = document.createElement('a');
url.href = "https://adamdawkins.uk/articles";
url.pathname; // => "/articles"
```

Where can this be useful? On any site where you need to manipulate or analyse URLs client-side, or, as in my case, when you’re using `browser.pushState` but still want to read state from a `location` object in the same way regardless.

On a project recently I used it like this:

```js
//    getState :: Location -> Object
const getState = (location) => ({
    page: location.pathname,
    ...getQueryParams(location)
})
```

I’d call `getState(window.location)` on page load,  but, when I changed the URL with `history.pushState` I needed to pass _that_ URL into my `getState` function as well. Instead of trying to change the simplicity of `getState` (takes a location, returns an object, lovely) - we can use the fact that anchors implement the location protocol to get something we can pass to this.

```js
 //   toLocation :: URL -> <a>
const toLocation = (url) => {
  const anchor = document.createElement('a');
  anchor.href = url;
	
  return anchor
}

const newURL = setQueryParams({foo: 'bar'}) // returns the whole URL, e.g. "https://adamdawkins.uk/articles?foo=bar"
const newState = getState(toLocation(newURL))
```

Note the the anchor DOM Element _itself_ implements the Location protocol, not anchor.location.

## Internet Explorer and relative pathnames
Lovely stuff. Enter Internet Explorer, stage right.

Internet Explorer takes _relative_ URLs and does not treat the initial  `/` as part of the `pathname`

Using our code above: 

```js
// All other browsers 
toLocation("/articles?foo=bar").pathname // => "/articles"
// Internet Explorer
toLocation("/articles?foo=bar").pathname // => "articles"
```

Great, thanks.

Maybe I was just unlucky, but I was matching on that `/` to check which page I was on:

```js
if (state.page.match(/\/checkout/delivery\//)) {
 // …
}
```

And it would work, unless I pushed state in Internet Explorer, now `state.page` is “checkout/delivery”.

## What to fix?
There’s a dilemma here. The easiest fix is to loosen my regex on the page, and not check for a preceding `/`, but the problem is - _that is what I mean_ - I do want to match `/checkout/delivery`, and it feels wrong to change that because IE has anxiety issues about the initial `/`.

The fix I went for was to create a simple `pathname()` function that would replace the `/` if it had been lopped off by IE:

```js
//    pathname :: Location -> String
const pathname = (location) =>  (
    // in IE location.pathname strips the first `/` from relative URLs, here we add it back
    location.pathname.match(/^\//) ? location.pathname : `/${location.pathname}`
)
```

Phew.

This article was originally published on [adamdawkins.uk](https://adamdawkins.uk/2019/6/5/the-hunt-for-the-missing-a-story-of-anchors-location-and-internet-explorers-pathname)