使用 HTML5 URL 输入验证,假设 URL 以 http:// 开头。

33

HTML5 提供了自动 URL 验证功能 :-

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

这将使没有协议前缀的URL验证失败,例如stackoverflow.com将会失败,而http://stackoverflow.com将会通过。

如果没有协议,我该如何自动添加 http:// 到 URL 中?

我可以添加一个 onblur 事件处理程序,但是否有更好的方法,比如一些在验证之前触发的事件?


11
或许有点学究气,但是stackoverflow.com并不真正是一个URL,它只是主机名... - J. Holmes
14
确实如此,但有点学究气;) 普通人看到一个带有“网站”标签的表单时,可能并不关心stackoverflow.com与http://stackoverflow.com之间的区别。 - Ryan
19
为捍卫普通人的权益:大多数浏览器实际上会隐藏URL中的"http://"部分。 - frnhr
1
更加规范的方式是在表单提交时添加 http。可以使用表单的 onsubmit 事件来实现。 - SparK
此外,http URL 只是一种 URL。ftp://ssh://https://git:// 都是常见的 URL 方案。type="url" 输入不接受无方案的 URL,因为无方案的 URL 不是 URL,假定的协议取决于您的应用程序。 - bfontaine
9个回答

25
此代码不应打断用户的操作,而应等待用户离开表单字段后检查输入文本中是否包含“http”。因此,请使用“onblur”而不是“onkeyup”。 然后,只需使用indexOf检查字符串是否包含“http”。如果没有,则返回-1,这是虚假值。

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


15
不适用于例如 example.com/http。你应该使用更严格的检查,比如 (string.indexOf("http:") === 0)... 或者实际上这会在https:// URL前添加 http://,所以最好使用 (string.match(/^https?:/))。当然,它仍然会在有效的 ftp:// URL 等前面添加它,所以如果你想允许任何协议,那么应该使用 (string.match(/^\w+:/)) - 1j01
5
如果有人只是通过按制表键浏览输入框而没有输入任何内容,那么这段代码也是错误的。你只需要使用Tab键就可以转到下一个字段,但现在你的URL输入框中有一个你不想要的愚蠢的“http://”。请修正此问题。 - Toskan

10

如果你不想要浏览器验证(因为在各种浏览器中可能会有差异),你可以添加以下 novalidate 属性。

<input type="url" name="someUrl"  formnovalidate="formnovalidate"> 
否则,您可能希望更加透明地添加前缀http://,即在某人开始输入时只需添加一次,甚至在页面加载时已将http://键入到框中。 (感谢正确指出novalidate适用于表单的编辑器,而上述内容覆盖了该内容; 另一方面,对于编辑方法的借方进行扣款 ;) )

9
你们可能想要使用的是这个:

。这是一个在HTML中常用的标签。
$(function(){
         $('input[type="url"]').on('blur', function(){
           var string = $(this).val();
           if (!string.match(/^https?:/) && string.length) {
             string = "https://" + string;
              $(this).val(string)
           }
         });
});

这段代码在文档加载完成后运行。

它检查值是否为空或者开头缺少http。

如果是的话,就在失去焦点时插入它。

感谢 @1j01。


1
这就是它。处理了所有有关已接受答案的异常情况。对于以下所有情况都能完美运行:example.com www.example.com http://example.com https://example.com example.com?otherurl=http://foo.bar。即使只输入example这样的情况,也会变成http://example,虽然仍无法验证,但仍然很有帮助,也是预期的结果。空值处理是必不可少的,并且运行良好。 - squarecandy
1
问题与HTML5有关,而不是jQuery。 - kuzey beytar
这个可以正常工作,但是我建议使用https而不是http,以确保安全;-)。 - Jan Salvador van der Ven
@JanSalvadorvanderVen - 世界上仍有相当数量的网站没有安全证书,只使用 http:,而大多数安全网站会从 http: 重定向到 https:。无论哪种方式都存在妥协,但似乎最好不要破坏 http 网站,并依赖于其他网站的重定向到 https。一旦全球统计数据达到95%左右,我会考虑切换到默认的 https。 - squarecandy

6

您可以通过提供初始值和占位符来尝试强制用户输入有效的URL。

<label for="some-url">Some url:</label>
<input id="some-url" type="url" placeholder="http://example.com" value="http://">


7
以下是一份确保用户复制粘贴时不会出现http://http://example.com的方案。 - squarecandy
1
@squarecandy 是的,但是那些用户应该放弃使用互联网。 - Jim41Mavs
4
无论程序员有多么技术才华横溢,只要持有这种态度,我都会标记他们为“不予雇用”。我们的工作是尽可能地让所有技能水平的人都能轻松使用网络。 - squarecandy

5
你可以使用
HTML:
<form>
   <input type="url" name="someUrl" onkeyup="checkUR(this)" >
</form>

脚本:

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

例子

希望它能有所帮助


4
你只需要 /^https?:/ - 1j01

4

使用URL类会更好。

    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}`;
        }
    }

这里的优点在于首先检查任何协议。如果用户错误输入了协议(例如htts:),它将被替换为http:。上面的答案都会添加新的协议,这将导致类似于http:// htts:的结果。如果没有协议,它将在catch块中添加http://

2

一句话总结:

<input type="url" onblur="if (!~this.value.indexOf('http')) this.value = 'https://' + this.value">

2

这将有助于用户解决 HTTP 前缀的问题,而不会显得过于烦人。只需在您的网页中添加此 JavaScript 代码,以及 type="url" <input> 元素,一切都会自动运行。

// 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;
            }
        });
    }
});

优点

  1. 如果输入框的值中没有添加 httphttps,则在输入框的值之前添加 https://
  2. 即使存在未在开头的 httphttps,也会在其前面添加 https://
  3. 在用户离开输入框后自动修改值
  4. 如果输入框没有值,则不添加 https://
  5. 不区分大小写
  6. 在不需要修改 HTML 输入框元素的情况下,自动处理所有 url 类型的输入框

局限性

  1. 在有效的 URL 开头添加 https://,而这些有效的 URL 的方案(scheme)不是 httphttps,例如 ftptel,将导致这些 URL 无法使用

PS:如果您还想将 http 更改为 https,请将此 else if 语句附加到上一个代码中的最后一个 if 语句。

else if (urlValue.match(/^http:/i)) {
    urlValue = urlValue.replace(/^http:/i, "https:");
    this.value = urlValue;
}

1
如果URL中没有httphttps,则此代码将在提交之前添加URL。它也是大小写不敏感的(末尾的i)。为了考虑用户按下回车键并以这种方式提交表单,我还使用onchange而不是其他事件。
function checkURL(o) {
    if (!/^https?:\/\//i.test(o.value)) {
        o.value = "http://" + o.value;
    }
}

替代脚本:(始终正确为“http://”)
function checkURL(o) {
    o.value = o.value.replace(/^(https?:\/\/)?/i, "http://");
}

HTML:

<form>
   <input type="url" name="someUrl" onchange="checkURL(this)" >
</form>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接