大多数网页表单上的地址字段都会要求填写城市、州和邮政编码(或城市和邮政编码,美国以外地区)。但正如我们这些极客经常抱怨的那样,城市和州在邮政编码存在的情况下是冗余的。或者至少它们可以从正确输入的邮政编码中推断出来。这正是计算机擅长的事情。我们需要一个合适的 API 来根据需要为我们提供这些信息。
输入 Ziptastic,一个专门用于此的 API。**2017年4月更新**:Ziptastic 现在提供付费计划。在其常见问题解答中,他们表示仍然提供免费版本的版本 2 API,该版本每天限制 100 次请求。我们的演示将使用此版本!
表单标记
五个字段。两个用于街道,然后是城市、州和邮政编码。所有这些都包含在一个表单和字段集中。没有什么特别的。
<form action="#" method="post" class="fancy-form">
<fieldset>
<legend>Address</legend>
<div>
<div>
<input type="text" name="address-line-1" id="address-line-1">
<label for="address-line-1">Street #1</label>
</div>
</div>
<div>
<div>
<input type="text" name="address-line-2" id="address-line-2">
<label for="address-line-2">Street #2</label>
</div>
</div>
<div>
<div class="city-wrap">
<input type="text" name="city" id="city">
<label for="city">City</label>
</div>
<div class="state-wrap">
<input type="text" name="state" id="state">
<label for="state">State</label>
</div>
<div class="zip-wrap">
<input type="text" pattern="[0-9]*" name="zip" id="zip">
<label for="zip">Zip</label>
<p class="zip-error">Not a real zip code.</p>
</div>
</div>
<div>
<input type="submit" value="Submit">
</div>
</fieldset>
</form>
最初只显示邮政编码
我们将隐藏所有包含表单元素行的 div。我们将使用 JavaScript,这样如果用户禁用了 JavaScript,表单仍然可用。
$(".fancy-form div > div").hide();
然后只显示邮政编码。
form .zip-wrap {
display: block !important;
}
前端验证
在前端,我们已经尽最大努力通过 HTML5 输入属性 pattern、maxlength 和 required 来帮助正确输入邮政编码。
<input type="text" pattern="[0-9]*" maxlength="5" required name="zip" id="zip">
请注意,它不是 number
类型。在考虑 type=number
时,请考虑“我是否可以接受浏览器在这个数字中添加逗号?”,如果答案是否定的,请不要使用它,因为某些浏览器会这样做。
jQuery:监视有效邮政编码的输入
我们将监视邮政编码输入的按键。如果按键后的最终值是有效的邮政编码,我们将尝试通过 Ziptastic 获取城市和州,并显示其他字段。
$("#zip").keyup(function() {
var el = $(this);
if ((el.val().length == 5) && (is_int(el.val()))) {
// Make Ajax call, etc
}
}
is_int 函数只是一些额外的保护,以确保数字为整数(如所有邮政编码),以防当前浏览器不支持必要的 HTML5。
function is_int(value){
if ((parseFloat(value) == parseInt(value)) && !isNaN(value)) {
return true;
} else {
return false;
}
}
jQuery:Ajax 数据
是的,jQuery。我们之前使用它来简化输入上的事件处理,但在这里确实需要它,因为它能够比使用原生 JavaScript 更轻松地进行 62 倍的 ajax 调用和错误处理。
通过验证后,我们可以进行 Ajax 调用。我们提供给它的数据只是我们收集到的邮政编码,然后我们得到一些 JSON 数据,从中可以轻松访问城市和州,并将它们作为值应用于相应的输入。
$.ajax({
url: "http://zip.elevenbasetwo.com",
cache: false,
dataType: "json",
type: "GET",
data: "zip=" + el.val(),
success: function(result, success) {
$(".fancy-form div > div").slideDown(); /* Show the fields */
$("#city").val(result.city); /* Fill the data */
$("#state").val(result.state);
$(".zip-error").hide(); /* In case they failed once before */
$("#address-line-1").focus(); /* Put cursor where they need it */
},
error: function(result, success) {
$(".zip-error").show(); /* Ruh row */
}
});
当然,我们可以整天验证邮政编码的有效格式,但并非**每个** 5 位整数都是邮政编码。如果我们请求 Ziptastic 获取不存在的邮政编码,它将返回错误。在这种情况下,我们只需显示错误消息。
演示
查看 Chris Coyier 在 CodePen 上的 使用 Ziptastic 示例。(@chriscoyier)
笔记
- 我不会告诉你这是万无一失的。地址很复杂。我听说有些邮政编码跨越州界。
Ziptastic 仅限美国使用。在发布本文后的几天内,Ziptastic 开始支持国际邮政编码。 Zippopotamus 类似,支持 60 个国家/地区。
太酷了。注意……会导致完全的极客狂喜。
感谢演示!
看起来您可能需要在 keyup 事件处理程序中监视 Tab 键。如果已存在有效的邮政编码,则切换到邮政编码字段将对其进行验证并自动聚焦街道地址字段。
非常好。
通常,那些有复杂邮政编码的人通常已经知道它。例如,我姐姐住在明尼苏达州的 Maplewood,邮政编码为 55109。她与明尼苏达州圣保罗接壤,几乎每次您输入 55109 时(表单、地图等),它都会返回明尼苏达州圣保罗。
这太棒了!我注意到 Katie 发现的同样的事情——我也使用了我在明尼阿波利斯郊区长大的邮政编码,但它将城市填写为明尼阿波利斯。
但它说明了要点,即使您写下附近的较大的城市,邮局通常也能正确投递。
我想做的一项小改进是将 $(“.zip-error”).hide(); 移动到 ajax 调用之前。
如果没有此更改,如果用户输入错误的邮政编码,然后尝试更正它,可能会让用户感到困惑。即使更正后,错误消息仍然可见,直到收到 ajax 回调。
通过更改,错误消息在输入 5 位整数并等待回调时消失。
非常感谢!我总是想知道为什么大多数网站都不尝试自动建议我的邮政编码,尽管大多数浏览器的自动填充功能帮助我保持懒惰;)
Travis 的提示很好。
嗨,Chris,
你再次提供了很棒的东西。我喜欢智能表单的想法。
发现了一个问题,虽然很容易解决:它与以 0 开头的邮政编码不兼容——例如,佛蒙特州的所有邮政编码都以 05 开头——我的邮政编码是 05641(佛蒙特州巴雷)。输入后,无法注册。再次尝试输入 01234(马萨诸塞州波士顿/贝德福德),也无济于事。我猜脚本忽略了前导 0。
使用 parseInt 时始终提供基数。parseFloat 将 05641 解释为 5641,而 parseInt(没有基数)将 05641 解释为 13011(八进制 05641)。parseInt( '05641', 10) 将为您提供所需的结果。
更出乎意料的是,parseInt('05922') 将只返回 5,因为 9 不是有效的八进制字符,parseInt 会解析直到遇到非数字字符。
有人知道计算“x 英里内的位置”的方法吗?
(顺便说一句,帖子很棒!)
有点复杂的问题。您需要一个包含位置及其中心坐标(或质心)的数据集。
然后,您获取您感兴趣的位置(比如加利福尼亚州旧金山)的中心点。您可以计算一个边界框(它只是表示框的每个角的 4 个坐标)。然后,您将对数据集运行查询,以查找位于您计算出的边界框内的其他中心点。
* 中心点 ~ 3 英里 = 边界框
* 获取边界框内的中心点
使用 Google Maps API 计算两点之间的距离 =)
我找出输入的邮政编码的纬度/经度,然后在数据库查询中进行计算,将其与存储的邮政编码进行比较(如果您已将其存储),这样您就可以执行类似于“Y 邮政编码附近的 X 家商店”的操作,因为一旦您计算出距离,您就可以在 select 语句中使用 where 子句指定所需的距离,例如 50 英里、100 英里等。
一个工作示例:http://www.craftcourses.com/search/PO8%208PT
当然 - 这是直线距离(而非道路距离),因此 100 英里在道路上可能意味着 140 英里。如果您想了解更详细的信息,请告诉我 :)
这在美国有效,但我们加拿大的人怎么办?
加拿大在哪里?哈哈
根据注释,Zippopotomus…您应该阅读注释。
根据注释,Zippopotomus…您应该阅读注释。
非常棒的东西。感谢!
我绝对喜欢这个演示,但我不知道这是否会带来一些可用性问题?如果我来到一个网页表单,期望看到一个地址表单,但只看到一个邮政编码字段,我可能会(错误地)认为表单没有正确加载或页面已损坏。
我知道这是一个演示,所以我并不是想说这是“错误的”。但作为对这种模式的实际应用的建议,您应该考虑包含一些微文案,例如“嗨!只需输入您的邮政编码,我们会处理城市和州的信息!”
仅供参考。
也许可以保留城市/州字段可见,但将其禁用并稍微淡化(除了您的微文案)。
确实,您可以这样做,这可能是我会做的事情:使用 JavaScript,将一个类应用于表单/表单元素以使这些字段淡出。
我只是担心通过这种方式,您需要按传统顺序显示字段:城市和州字段将出现在邮政编码字段**之前**。否则,就会引入另一个可能令人震惊的可用性问题。因此,如果您保留传统顺序,则用户可能会忽略微文案(这不是开发人员的错,我明白),并按顺序输入项目(1. 城市、2. 州、3. 邮政编码),从而使此方法在此用例中毫无用处。再说一次,如果发生这种情况,也不是世界末日。并且用户同时忽略您的文案和视觉提示可能是一个极端情况。我只是在这里随口说说…
实际上,我认为我对此过于分析了。
另外,“rending”应为“rendering”。
现在我们只需要一个适用于英国的版本。
现在我们只需要将英国包含在其中。
很棒的 API。仅供参考:我为此服务创建了一个 .NET 接口此处。在您的 ASP.Net、C#.Net 或 VB.Net 项目中引用它,并按如下方式使用它(C#)
好主意 - 我住在 10 个国家,但从未在美国住过
如果第一个字段
*国家*
第二个字段
*邮政编码*
将使其能够在国际上使用
特别是对于包含标点符号等的地名,匹配邮政编码是数据清理问题,以确保没有打字错误(例如在邮政编码中),以及以便您可以挖掘干净的数据。它也是人们在表单中反复输入相同(完整地址)信息的一种浪费。因此,在这方面提供适当的自动化帮助非常受欢迎,并且人们不会因填写信息而感到沮丧。如果您的客户面临注册或订单表单,表单的沮丧感会导致销售损失。
所有需要重复大量已知信息(因为您已获得标识符)的表单都是我们不需要的麻烦。如果您将世界上所有系统中重复输入数据的浪费时间加起来,那将是许多人的一生…这本质上源于数据收集和处理系统不足。并且许多人的一生都花在了清理不应该存在的脏数据上。
…静静地走下讲台。
加拿大的邮政编码中包含字母。只是说一下。
d。
我想从地址验证行业的角度对这种方法发表评论。我是SmartyStreets的开发人员,在那里我积累了丰富的美国邮政服务地址质量产品经验。
感谢您指出“地址很难”,以及邮政编码跨州边界。我可以进一步说明,虽然邮政编码确实跨越州界(非常罕见),但它们经常跨越城市和县界。邮政编码通常还有一些美国邮政服务分配的备用名称,这些名称在邮件发送时是有效的(并且通常比默认名称更合适),以及一些在邮件发送时**不**合适的备用名称。我浏览代码后发现,Ziptastic 没有考虑这一点(“SELECT * FROM zipcodes WHERE zipcode=’$zip’ LIMIT 1”无法做到这一点)。
我对像 Ziptastic 这样的服务的另一个担忧是底层数据源。Ziptastic 数据库包含 80,000 多条记录,考虑到我提到的备用名称,这大约是正确的,但我担心 Ziptastic 存储库中没有参考显示 ZIP 编码数据是从哪里获取的(如果我遗漏了什么,请更正我)。如果它是从第三方购买的,那么是否允许将其发布到公共存储库中,以便其他人可以公开访问它?他多久更新一次?美国邮政服务每月都会添加和删除邮政编码。
最后,我尊重 Ziptastic 的作者——他们在努力解决网络上简化 UX 和减少用户错误的真正挑战。我担心这种简单的方法会给那些选择将其用于其应用程序的人带来虚假的安全感。事实是,确保城市/州/邮政编码组合正确的唯一方法是使用CASS 认证地址验证服务验证整个地址。
伙计…我看到的所有地方都是你在为 Smartystreets 做垃圾邮件推广。
我不会使用你的产品,仅仅是因为我现在对此感到厌烦。
你正在获得市场饱和度,但你也在我找到的每个消息线程中发送垃圾邮件。
你好,
它非常适合邮政编码。但您能否告诉我它是否已获得国际认可。
嗯,有点困惑。据我所知,$.ajax 不适用于外部 URL。是吗?
我认为你是对的。几天前我读到了一些关于它的信息,它与同源策略有关。jQuery 文档中写道
“由于浏览器的安全限制,大多数“Ajax”请求都受同源策略的约束;请求无法成功从不同的域、子域或协议中检索数据。”
但此策略取决于浏览器,这可能是我的 Firefox(407 代理身份验证所需)中演示根本不起作用的原因。我认为有一些方法可以解决此问题,但我不确定它们是否在此处使用。
对此没有解决方法 - 我尝试了很多方法,最终使用服务器 CURL 得到了结果:)。只有一件事让我对我的想法产生了怀疑 - JSON。也许 AJAX 与 JSON 允许在非源域上使用。Chris,您能否对此进行澄清?
你知道吗。我真的不确定为什么这有效。我可以说它在我的所有测试过的 Firefox 浏览器中都有效。在我看来,跨域限制在浏览器之间非常一致。
通常,答案是JSONP,这是一种无需涉及任何服务器端操作即可解决此问题的简单/巧妙的方法。但这似乎没有在此处使用。
还有其他人知道为什么这有效吗?
查看了一些文章 - 是的,原因是您正在使用 JSON。使用异步跨域 JS 请求确实是允许的。您为我在 JQuery/Javascript 中打开了一个新事物。它改变了很多东西:) 非常感谢
很高兴知道。
我之前无法使用的原因是,我位于公司代理后面。现在一切正常了。
我认为它可以跨域工作,因为他们的服务器返回标头
Access-Control-Allow-Origin: *
它应该适用于 IE8 及更高版本。
有人可以解释一下 is_int 函数中的以下相等性检查吗?
parseFloat(value) == parseInt(value)
是为了检查字符串中是否包含浏览器添加的“,” 或“.” 吗?它与 isNaN 检查有什么关系?我感到困惑,它正在困扰我。
谢谢,很棒的帖子
我感到困惑 - 这在美国难道还不存在吗?当我在英国通过网络购买商品时,我通常只需要提供门牌号/名称和邮政编码,地址(街道名称、城市/镇、国家等)就会自动填充。这可能已经存在至少 5 年了?
美国比欧洲落后大约 5 年。给我们一点时间,我们会赶上的。
虽然我同意它并不像您所说的那样“万无一失”,但我不确定如果您将其用于小型企业网站是否重要,只要您了解客户群的位置即可。
总而言之,我认为这最终将成为一个非常有用的工具。
很酷的工具,遗憾的是演示似乎不适用于 RI 邮政编码,正如之前有人所说,可能是前导零(RI 邮政编码以这种方式开头)。
@chris - 正如您所指出的:地址很难处理。我认为我对此有一些答案,但无法为您编写代码。对我们来说有点棘手,我们为一张治疗床支付了一大笔费用,但“无法”送货,因为他们的电脑无法识别我们所在区域 11 个月前更改的邮政编码(不是开玩笑)。恢复尝试升级到涉及电视的“获得盖哈特”(监察员)的地步,并为我们提供了一张免费的床。5 年后的今天,我发现一些加油站由于(您猜对了)无法识别我们的邮政编码。
邮局系统是免费的,并且有权自行更改边界和号码,因此充其量这只能被视为“预填充”默认字段的东西。1) 首先询问邮政编码(以便大多数人填写);2) 展开字段 - 使用预填充(如果可能)的字段;3) 如果整数、正则表达式、AJAX 失败:提供“我们不识别该邮政编码”的警告;但是,4) 始终允许,并且永远不要阻止用户的手动输入。
演示在我的本地邮政编码(如 90260、90278 等)上不起作用。尝试了 FF 12 和 IE8
我用 90260(我的邮政编码)试用了演示,并在输入第 5/最后一个数字后立即显示错误信息“不是有效的邮政编码”。尝试了其他一些已知的有效邮政编码,错误相同。此外,忽略了错误,按下回车键 & 它会清除字段,不显示城市、州(确实看到了立即消失的空字段)。
谢谢
克雷格
http://geocoder.ca 在过去 5 年中一直在提供相同的功能。例如。
http://geocoder.ca/?postal=K1R7S8&geoit=xml&jsonp=1&callback=test&standard=1
适用于加拿大
或者
http://geocoder.ca/?postal=10001&geoit=xml&jsonp=1&callback=test&standard=1 适用于美国
它还可以根据经纬度进行反向地理编码等等。而且它一直都是免费的,将来也会一直免费。
如果您需要更多功能,请告诉我。
如何在美国包含 ZIP+4?例如:75704-2933。这可能会返回如下地址
某某街 123 号
德克萨斯州某地 75704
这可能吗?
仍然只有州(没有国际)
我很快就会添加。明天回来查看一个可用的示例。
e。
完成
http://geocoder.ca/?postal=75704-2933&geoit=xml&jsonp=1&callback=test&standard=1&showcountry=1&moreinfo=1
非常流畅,但在 IE-9 中失败了 - 唉
非常酷!但不幸的是,我住在印度尼西亚。如何替换国家代码、URL、范围和计数?
感谢您的关注
这太棒了,而且是我一段时间以来一直在使用我维护的数据库实施的一种策略。喜欢这个 API!
我也非常喜欢在选择邮政编码后显示的隐藏元素,因为我将邮政编码放在城市/州之上,并且一直觉得有点笨拙。
可能会对城市/州使用过渡,而不是整个表单。
一如既往,我的朋友,很棒的文章!
嗨!仅供参考,对于可能正在使用 Ziptastic 的任何人。我们已更新我们的数据库以支持更多国家/地区。
有时它在 IE 中有效,有时无效。有什么可以修复的吗?
但不幸的是,我住在印度尼西亚。如何替换国家代码、URL、范围和计数?
这确实很棒,但我仍然认为当用户输入邮政编码时收集城市/州是没有意义的
由于它现在支持国际邮政编码,因此建议更新示例以允许长度大于 5,因为国际邮政编码需要此功能。
令人震惊。这就是我一直在寻找的东西。
感谢作者。 :)
直到最近,我们一直使用谷歌地图来解决这个问题。仍在寻找合适的替代方案。对于某些项目,我们还需要地理定位,因此目前最佳选择似乎是使用来自 openstreetmap.org 的数据设置我们自己的 Nominatim 安装。
嗨,Chris,
我一直关注您的文章,并从中学习了很多东西。感谢您成为我创建精美网站的灵感来源之一。期待您其他真正帮助我的文章。
这项工作太棒了!!!
我可以从 My SQL 中提取源数据吗?
Mysql 数据库是本地的,名为 Psyc,有一个名为 Zip 的表
zip 表中包含以下字段
Stree1
Stree 2
City
State
Zip
我确实需要从 Mysql 获取数据,因此我非常感谢任何帮助。
提前感谢,
cibsrk
嗯,我尝试了芝加哥的区号 60657,它将城市设置为格雷斯兰。这是错误的。
也许是因为他们将区号切换为超过 5 位数字?我正在寻找的芝加哥地区的官方区号是 60657-2012
有人知道为什么城市被切断了?
例如:19103
费城,宾夕法尼亚州
为什么没有拼写出完整的名称费城?有没有办法得到它?
此外,它在任何版本的 IE 中都不起作用:(
不知道为什么……有人知道吗?
此代码不适用于印度邮政编码,例如 160015、456001、208214、452001…………….
我们需要一个产品来输入邮政编码……我有姓名、地址、城镇和州……只是在寻找邮政编码……是否存在这样的产品?谢谢~劳拉
(不是这里的时间……在我写这篇文章的时候,已经三年了。)
有人告诉我“Ziptastic 已经死了”,但网站看起来还活着,运行良好。 不确定那里发生了什么。 演示在这个网站上也失败了,看起来 Ajax 请求失败了(404?)。
有人推荐了这个作为替代方案:https://code.google.com/archive/p/ziplookup/
如果我得到关于 Ziptastic 状态的某种确认,我将把这段内容放在文章开头,而不是放在这里。