33

HTML5 provides for automatic URL validation :-

<form>
   <input type="url" name="someUrl">
</form>

This will fail validation for URL's that don't have a protocol prefix - e.g. stackoverflow.com will fail while http://stackoverflow.com will pass.

How can I automatically add http:// to a url if there isn't already a protocol?

I could add a onblur event handler but is there a better way like some before validation event?

dove
  • 20,469
  • 14
  • 82
  • 108
Ryan
  • 23,871
  • 24
  • 86
  • 132
  • 11
    Perhaps a bit pendantic but `stackoverflow.com` really isnt a URL. It's just a host name... – J. Holmes Jul 30 '13 at 12:39
  • 13
    True - but pedantic ;) The average person seeing a form with a "Website" label just can't be bothered with the difference between stackoverflow.com and http: // stackoverflow.com' – Ryan Jul 30 '13 at 12:51
  • 18
    In defense of mr. Average Person: most browsers actually hide the "http://" part of the URL. – frnhr Mar 18 '15 at 14:52
  • 1
    The cleaner way would be to prepend http during form submission. Form `onsubmit` event. – SparK May 02 '16 at 12:16
  • Also, `http` URLs are just one kind of URL. `ftp://`, `ssh://`, `https://`, `git://` are all common schemes for URLs. The `type="url"` input doesn’t accept scheme-less URLs _because_ of that: a scheme-less URL is not a URL and the assumed protocol depends on your application. – bfontaine Mar 21 '18 at 11:10

9 Answers9

25

The code for this should not interrupt the user's action, but should instead wait until the user leaves the form field to check the input text for "http". So use "onblur" instead of "onkeyup".

Then, just see if the string contains "http" using indexOf. If not, it will return -1, which is falsey.

function checkURL (abc) {
  var string = abc.value;
  if (!~string.indexOf("http")) {
    string = "http://" + string;
  }
  abc.value = string;
  return abc
}
<form>
  <input type="url" name="someUrl" onblur="checkURL(this)" />
  <input type="text"/>
</form>

Fiddle

Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
ginna
  • 1,723
  • 1
  • 16
  • 16
  • 15
    Doesn't work for e.g. `example.com/http`. You should use a stricter check, like `(string.indexOf("http:") === 0)`... or actually, this will make it prepend `http://` to `https://` urls, so rather `(string.match(/^https?:/))` Of course, it'll still prepend it to valid `ftp://` urls, etc. so if you want to allow any protocol then it would be `(string.match(/^\w+:/))` – 1j01 Apr 27 '15 at 19:40
  • 5
    this code is furthermore wrong in case someone just tabs through the input without entering anything. You just use tab to get to the next field, now you have a stupid `http://` in the url field you didn't want there – Toskan Sep 27 '17 at 15:23
10

if you don't want the browser validation (it can vary between browsers) you can add the following novalidate attribute

<input type="url" name="someUrl"  formnovalidate="formnovalidate"> 

else you might want to be more transparent about prefixing http:// by simply adding once someone starts to type or even to have http:// already typed into the box on the page load

(credit to editor who rightly points out that novalidate applies to form, while above overrides that, debit to creditor for approach to edit ;)

dove
  • 20,469
  • 14
  • 82
  • 108
9

what you guys probably want to use is this:

$(function(){
         $('input[type="url"]').on('blur', function(){
           var string = $(this).val();
           if (!string.match(/^https?:/) && string.length) {
             string = "https://" + string;
              $(this).val(string)
           }
         });
});

this runs on document ready

checks if value is empty or has missing http at the beginning

inserts it in that case on blur

thanks @1j01

Toskan
  • 13,911
  • 14
  • 95
  • 185
  • 1
    This is the one. Takes care of all of the exceptions noted about the accepted answer. Works perfectly for all of the following: `example.com` `www.example.com` `http://example.com` `https://example.com` `example.com?otherurl=http://foo.bar`. Even cases like just entering `example` becomes `http://example` which still does not validate, but is still helpful and is the expected result. And the blank value handling is essential and works great. – squarecandy Dec 18 '18 at 19:31
  • 1
    Question is related with HTML5, not jQuery – kuzey beytar May 11 '19 at 18:13
  • This works fine, however, I would recommend it to add https instead of http, to be save ;-). – Jan Salvador van der Ven Oct 02 '20 at 07:16
  • @JanSalvadorvanderVen - there are still a decent amount of sites out there in the world without security certs that only use `http:` and most secure sites redirect from `http:` to `https:`. Definitely a compromise either way, but it seems better to not break the `http` sites and to rely on the redirects to `https` for the other. I would consider switching to https default once [global stats](https://w3techs.com/technologies/details/ce-httpsdefault) are above 95% or so. – squarecandy May 11 '21 at 13:42
6

You can try to force users enter valid url by providing initial value and placeholder.

<label for="some-url">Some url:</label>
<input id="some-url" type="url" placeholder="http://example.com" value="http://">
Vladimir Vovk
  • 688
  • 8
  • 9
  • 7
    This is a sure recipe for users who are copy and pasting ending up with `http://http://example.com` – squarecandy Dec 18 '18 at 19:33
  • 1
    @squarecandy ye but those users should just give up on using the internet. – Jim41Mavs May 08 '21 at 21:43
  • 4
    That's the kind of attitude that makes me flag programmers as "do not hire" no matter how technically talented they are. It's our job to make the web as easy as possible to use for people of all skill levels. – squarecandy May 11 '21 at 13:46
5

you can use

HTML :

<form>
   <input type="url" name="someUrl" onkeyup="checkUR(this)" >
</form>

SCRIPT:

function checkUR(abc){
    string = abc.value
    if(!(/^http:\/\//.test(string))){
        string = "http://" + string;
    }
    abc.value=string
}

example

I hope it will help

Sonu Sindhu
  • 1,752
  • 15
  • 25
3

Using the URL class would be even better.

    function validateUrl(value) {
        try {
            const currentUrl = new URL(value);
            const { protocol } = currentUrl;

            if (protocol !== 'http:' && protocol !== 'https:') {
                currentUrl.protocol = 'http:';
                return currentUrl.toString();
            }
        } catch(e) {
            return `http://${value}`;
        }
    }

The advantage here is that you check for any protocol first. In case the user mistyped the protocol (e.g. htts:), it will be replaced by http:. The answers above would all prepend a new protocol which would result in something like http://htts:. In case there is no protocol it will just prepend http:// in the catch block.

Lars
  • 79
  • 11
2

It will help users with http prepending annoyance without being intrusive. Just add this JavaScript code to your webpages with type="url" <input> elements, and everything will work automatically.

// Run a callback function after DOM is fully loaded
function domReady(callback) {
    if (document.readyState != "loading") {
        callback();
    } else {
        document.addEventListener("DOMContentLoaded", callback);
    }
}

// Prepend https to url input field value if already not prepended by http or https
domReady(() => {
    const urlInput = document.querySelectorAll('input[type="url"]');
    for(i = 0; i < urlInput.length; i++) {
        urlInput[i].addEventListener('change', function(){
            let urlValue = this.value;
            // If http or https isn't prepended as case insensitive characters and if the input field has any value
            if (!urlValue.match(/^https?:/i) && urlValue.length) {
                urlValue = "https://" + urlValue;
                this.value = urlValue;
            }
        });
    }
});

Advantages

  1. prepending https:// if http or https isn't already prepended in the input field value
  2. prepending https:// even when there is http or https that isn't in the beginning
  3. automatically modifying value after users leave input field
  4. not adding https:// if input field has no value
  5. working in a case insensitive manner
  6. automatically working on all url type input fields without requiring to modify HTML input field elements

Limitations

  1. adding https:// in front of valid urls that start with any schemes other than http or https such as ftp and tel which will cause those valid URLs to not work

PS: If you also want to change http to https, append this else if statement to the last if statement in the previous code.

else if (urlValue.match(/^http:/i)) {
    urlValue = urlValue.replace(/^http:/i, "https:");
    this.value = urlValue;
}
arafatgazi
  • 341
  • 4
  • 5
2

One-liner:

<input type="url" onblur="if (!~this.value.indexOf('http')) this.value = 'https://' + this.value">
Grzegorz Adam Kowalski
  • 5,243
  • 3
  • 29
  • 40
1

This will prepend the URL before submitted if it does not have a http or https in the URL. It is also case insensitive (the i at the end). I'm also using onchange instead of the other events to account for users pressing the enter key and submitting the form that way.

SCRIPT:

function checkURL(o) {
    if (!/^https?:\/\//i.test(o.value)) {
        o.value = "http://" + o.value;
    }
}

ALTERNATE SCRIPT: (Always correct to "http://")

function checkURL(o) {
    o.value = o.value.replace(/^(https?:\/\/)?/i, "http://");
}

HTML:

<form>
   <input type="url" name="someUrl" onchange="checkURL(this)" >
</form>
Carter Medlin
  • 11,857
  • 5
  • 62
  • 68