惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
About on SuperTechFans
Y
Y Combinator Blog
V
V2EX
Engineering at Meta
Engineering at Meta
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Visual Studio Blog
博客园 - 叶小钗
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
H
Help Net Security
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
WordPress大学
WordPress大学
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
MongoDB | Blog
MongoDB | Blog
B
Blog
G
Google Developers Blog
J
Java Code Geeks
博客园 - 三生石上(FineUI控件)
IT之家
IT之家
N
Netflix TechBlog - Medium
腾讯CDC

博客园 - 薛端阳

12小时包你学会基于ReactMix框架的ReactNativeApp开发(二)基于Css+HTML写第一个app页面 12小时包你学会基于ReactMix框架的ReactNativeApp开发(一)Hello World! ReactMix框架,让你实现一套js代码,基于ReactNative在H5,App都能完美跑起来,Write Once,Run Anywhere [分享黑科技]纯js突破localstorage存储上线,远程抓取图片,并转码base64保存本地,最终实现整个网站所有静态资源离线到用户手机效果却不依赖浏览器的缓存机制,单页应用最新黑科技 不要听吹牛逼什么前端MVVM框架就是好,其实都是一帮没学好分层设计的搞出来的,让你彻底看清前端MVVM的本质 基于Css反射形自触发事件,优化你的延时事件 巧用正则零宽断言实现靓号检索逻辑 HTML5触屏版多线程渲染模板技术分享 分享Css3设计---纯Css实现超酷的iphone玻璃气泡效果 中文前端UI框架Kit(十四)超酷的瀑布流特效动画 中文前端UI框架Kit(十三)使用RequireJs托管你的类库和js代码 中文前端UI框架Kit(十二)整合Mustache做kitjs模板引擎,基本写法${varname} 中文前端UI框架Kit(十一)摇头动画?让你的页面元素嗑药嗑起来?? 中文前端UI框架Kit(十)Javascript多线程工作模型的实现 中文前端UI框架Kit(九)IE下实现W3C标准的range对象所有api,支持通过xpath跨浏览器实现特定选区高亮,书签标记功能 中文前端UI框架Kit(八)无插件异步文件上传组件源码解析 中文前端UI框架Kit(七)无插件异步文件上传组件,带进度,支持文件拖拽 中文前端UI框架Kit(六)javascript动画代码实现原理和一些小技巧 不知道大家知道不知道,iOS开发,web页面的链接的active属性无效,但是今天发现一个hack办法可以让Css的active有效
(造福中国前端界)纯前端Js完美解决各种汉字urlencode,urldec...
薛端阳 · 2013-05-30 · via 博客园 - 薛端阳

最后补充一下:IE6,7用vbscript可以decode,传送门:http://www.baidu.com/s?wd=vbscript+urldecode+gbk

(昨晚更新)IE8是不支持script的src的datauri的,昨晚想了一个hack方法

MSND传送门:http://msdn.microsoft.com/en-us/library/cc848897(v=vs.85).aspx

IE8支持link的datauri,我想是否可以构造一个link过来的css,通过设置background-image,然后通过ie的currentStyle[‘backgroundImage’]取到中文

image

这里定义了一个隐藏的元素,通过datauri方式引入css,然后应用,即可以通过js获得该背景图src,测试IE8通过(2013.5.31早更新)

我们都知道javascript在做表单提交的时候,会遇到很多坑爹的 中文需要转换成gbk encode或者big5 encode的问题,

比如 中文的

javascript原生的escape只是将中文转换为unicode编码,encodeURI或者encodeURIComponent也是对于中文unicode编码的url再编码

对于“中文”这个汉字来说,他的utf-8的urlencode是%E4%B8%AD%E6%96%87,而gbk的urlencode是%D6%D0%CE%C4

而js本身没有特性支持gbk的urlencode,大部分的时候我们是通过后台(java,urlencode.encode(“中文”,”gbk”))这样来实现的

本文介绍一个借助浏览器,纯前端实现各种编码集的urlencode方式和decode方法

demo地址:http://xueduany.github.io/KitJs/urlencode.html,(这个包含了 解码,编码方法)

http://xueduany.github.io/KitJs/getEncodeStr.html(这个用来iframe回调解码后的值的文件)

image

chrome,firefox,safari测试通过,移动端均可,IE10以下下面会另说

(一) 编码原理

function urlencode(str, charset, callback) {
            //创建form通过accept-charset做encode
            var form = document.createElement('form');
            form.method = 'get';
            form.style.display = 'none';
            form.acceptCharset = charset;
            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'str';
            input.value = str;
            form.appendChild(input);
            form.target = '_urlEncode_iframe_';
            document.body.appendChild(form);
            //隐藏iframe截获提交的字符串
            if (!window['_urlEncode_iframe_']) {
                var iframe = document.createElement('iframe');
                //iframe.name = '_urlEncode_iframe_';
                iframe.setAttribute('name', '_urlEncode_iframe_');
                iframe.style.display = 'none';
                iframe.width = "0";
                iframe.height = "0";
                iframe.scrolling = "no";
                iframe.allowtransparency = "true";
                iframe.frameborder = "0";
                iframe.src = 'about:blank';
                document.body.appendChild(iframe);
            }
            //
            window._urlEncode_iframe_callback = callback;
            //设置回调编码页面的地址,这里需要用户修改
            form.action = 'getEncodeStr.html';
            form.submit();
            setTimeout(function() {
                form.parentNode.removeChild(form);
                iframe.parentNode.removeChild(iframe);
            }, 500)

        }

通过HTML元素form自带属性accept-charset在表单提交发送数据时候,浏览器会根据这个属性值做自动urlencode,get/post方式均可

accept-charset 属性规定服务器处理表单数据所接受的字符集。

accept-charset 属性允许您指定一系列字符集,服务器必须支持这些字符集,从而得以正确解释表单中的数据。

该属性的值是用引号包含字符集名称列表。如果可接受字符集与用户所使用的字符即不相匹配的话,浏览器可以选择忽略表单或是将该表单区别对待。

浏览器支持

除了 Internet Explorer,accept-charset 属性得到几乎所有浏览器的支持。

注释:accept-charset 属性无法在 Internet Explorer 中正确地工作。如果 accept-charset 属性设置为 "ISO-8859-1",IE 将发送以 "Windows-1252" 编码的数据。

语法

<form accept-charset="value">

从例子的代码,我们巧妙的利用了这个属性,构造一个接受gbk encode之后url的页面,通过location.search获取到encode之后的编码,再传递给原页面,即可实现对于任意字符的任意编码urlencode

(二)解码

上面说了编码,现在说说 如果我们获得一串%D6%D0%CE%C4,而且我们知道这个是gbk编码的,那么我们如何得到这个编码的中文呢?

function urldecode(str, charset, callback) {
            window._urlDecodeFn_ = callback;
            var script = document.createElement('script');
            script.id = '_urlDecodeFn_';
            var src = 'data:text/javascript;charset=' + charset + ',_urlDecodeFn_("' + str + '");'
            src += 'document.getElementById("_urlDecodeFn_").parentNode.removeChild(document.getElementById("_urlDecodeFn_"));';
            script.src = src;
            document.body.appendChild(script);
        }

这个问题的核心在于编码是urlencdoe的,那么除了utf-8格式的我们可以借助js自己的decodeURI等之后,对于gbk的,我们一般是无能为力的

这里巧妙构造了一个URI资源,因为通过URI方式引入的script,可以指定字符编码的,而浏览器会根据指定的字符编码,做urldecode,这样就实现了我们想要的urldecode效果

(三)IE

最后,我们来看看比较郁闷的IE,对于IE来说,他完全不认我们的form的accept-charset属性,他们的表单提交的编码格式,是按照页面的meta制定的字符集来的,当然了,他也给广大屌丝前端留了一条后路,就是他们的document.charset属性,是可读可写的,

而且IE为了表现它确实是一傻到底,不但在设置document.charset的时候不会用新的编码解释页面,还会在前进后退(我特地用#作为action来实现后退)的时候又尝试用新的编码去解释页面。

所以我们需要hook之前的编码,在解码后再转换回来

function urlencode(str, charset, callback) {
            //创建form通过accept-charset做encode
            var form = document.createElement('form');
            form.method = 'get';
            form.style.display = 'none';
            form.acceptCharset = charset;
            if (document.all) {
                //如果是IE那么就调用document.charset方法
                window.oldCharset = document.charset;
                document.charset = charset;
            }
            var input = document.createElement('input');
            input.type = 'hidden';
            input.name = 'str';
            input.value = str;
            form.appendChild(input);
            form.target = '_urlEncode_iframe_';
            document.body.appendChild(form);
            //隐藏iframe截获提交的字符串
            if (!window['_urlEncode_iframe_']) {
                var iframe = document.createElement('iframe');
                //iframe.name = '_urlEncode_iframe_';
                iframe.setAttribute('name', '_urlEncode_iframe_');
                iframe.style.display = 'none';
                iframe.width = "0";
                iframe.height = "0";
                iframe.scrolling = "no";
                iframe.allowtransparency = "true";
                iframe.frameborder = "0";
                iframe.src = 'about:blank';
                document.body.appendChild(iframe);
            }
            //
            window._urlEncode_iframe_callback = function(str) {
                callback(str);
                if (document.all) {
                    document.charset = window.oldCharset;
                }
            }
            //设置回调编码页面的地址,这里需要用户修改
            form.action = 'getEncodeStr.html';
            form.submit();
            setTimeout(function() {
                form.parentNode.removeChild(form);
                iframe.parentNode.removeChild(iframe);
            }, 500)

        }
        function urldecode(str, charset, callback) {
            var script = document.createElement('script');
            script.id = '_urlDecodeFn_';
            window._urlDecodeFn_ = callback;
            if (document.all) {
                //隐藏iframe截获提交的字符串
                if (!window['_urlDecode_iframe_']) {
                    var iframe = document.createElement('iframe');
                    //iframe.name = '_urlDecode_iframe_';
                    iframe.setAttribute('name', '_urlDecode_iframe_');
                    iframe.style.display = 'none';
                    iframe.width = "0";
                    iframe.height = "0";
                    iframe.scrolling = "no";
                    iframe.allowtransparency = "true";
                    iframe.frameborder = "0";
                    iframe.src = 'about:blank';
                    document.body.appendChild(iframe);
                }
                //ie下需要指明charset,然后src=datauri才可以
                iframe.contentWindow.document.write('<html><scrip' + 't charset="gbk" src="data:text/javascript;charset=gbk,parent._decodeStr_=\'' + str + '\'"></s'+'cript></html>');
                setTimeout(function() {
                    callback(_decodeStr_);
                    iframe.parentNode.removeChild(iframe);
                }, 300)
            } else {
                var src = 'data:text/javascript;charset=' + charset + ',_urlDecodeFn_("' + str + '");';
                src += 'document.getElementById("_urlDecodeFn_").parentNode.removeChild(document.getElementById("_urlDecodeFn_"));';
                script.src = src;
                document.body.appendChild(script);
            }
        }

关键点在于,编码时

image

解码时的关键在与,对于支持datauri版本的ie,不仅仅在于datauri里面制定编码集,还在在script的charset上指定编码

image

这样就可以实现浏览器的完美兼容

(四)小结

再次感谢腾讯前端QQ群的各位,没有你们的建议和支持,不会想到这么好的解决方案,再次感谢大家,希望看到的广大的前端屌丝们大力扩散,早日每一个jser都知道这一特大喜讯!!!哈哈哈哈哈

程序源代码地址:

https://github.com/xueduany/KitJs/blob/gh-pages/urlencode.html

https://github.com/xueduany/KitJs/blob/gh-pages/getEncodeStr.html