jQuery 1.9 移除了 $.browser 的替代方法

jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合使用 jQuery 1.9 和 2.0, 官方的解决方案是:

<!--[if lt IE 9]>
    <script src='jquery-1.9.0.js'></script>
<![endif]-->
<!--[if gte IE 9]>
    <script src='jquery-2.0.0.js'></script>
<![endif]-->

从长久来看,这样有利于在复杂情况下根据浏览器特性进行分别处理, 而不是简单的检测浏览器类型和版本。 但目前很多旧程序的移植恐怕无法直接过渡为根据浏览器支持特性, 所以在网上找了一些能够直接替换的解决办法。

判断浏览器类型:

$.browser.mozilla = /firefox/.test(navigator.userAgent.toLowerCase());
$.browser.webkit = /webkit/.test(navigator.userAgent.toLowerCase());
$.browser.opera = /opera/.test(navigator.userAgent.toLowerCase());
$.browser.msie = /msie/.test(navigator.userAgent.toLowerCase());

等号后面的表达式返回的就是 true/false, 可以直接用来替换原来的 $.browser.msie 等。

检查是否为 IE6:

// Old
if ($.browser.msie && 7 > $.browser.version) {}
// New
if ('undefined' == typeof(document.body.style.maxHeight)) {}

检查是否为 IE 6-8:

if (!$.support.leadingWhitespace) {}

终极方法是用另外的类库替代,比如 这个 , 但作者也不推荐使用浏览器类型和版本来进行判断。

参考

新的广告交换、51.la统计和web标准

标题又有点风牛马不相及,不过还是有那么一点点关联的,再说了,一篇文章的内容相对广泛,不仅有利于SEO,而且还会给胡乱转载者以困惑,同时还不会干扰正常转载、引用的朋友,嘿嘿。

首先说今天我第一次见到的网站广告交换–BlogUpp,感觉很新颖,很方便,就顺手也弄了一个,放在右边的广告下面,感觉特点如下:

  1. 不用注册,直接输入网址,就得到一段代码,扔网站页面上就行了。
  2. 交换广告是竖向排列的两个,固定的大小和布局,至少目前没得选择,不过适合blog这种右边大条空白的情况。
  3. 加载的时候,先显示文字,然后加载图片,当然文字和图片都是从每个网站上攫取出来的,中文支持良好。
  4. 正常显示广告的情况下,一般是显示图片,鼠标滑过的时候,切换为文字内容,既用图片吸引了眼球,又能让读者根据文字内容来了解是否真的需要打开浏览,应该说这一点我觉得是它设计最好的地方。
  5. 提供两种形式的代码,一种是iframe另外一种是style+div,我鸡蛋里挑点骨头:第二种里面的target="_blank"这种用法是不符合w3c标准的。

之所以对w3c标准如此敏感,是因为下午刚刚为51.la统计代码无法通过w3c验证而头疼(验证的不是本blog的页面,选用dtd是XHTML 1.0 Strict)。先来看一下这段代码吧:

<script type="text/javascript" src="http://js.users.51.la/272422.js"></script>
<noscript><a href="http://www.51.la/?272422" target="_blank"><img alt="&#x6211;&#x8981;&#x5566;&#x514D;&#x8D39;&#x7EDF;&#x8BA1;" src="http://img.users.51.la/272422.asp" style="border:none" /></a></noscript>

w3c的validator一检查,错误就出来了,主要有两处,一处比较简单:

document type does not allow element "a" here; missing one of "p", "h1", "h2", "h3", "h4", "h5", "h6", "div", "pre", "address", "fieldset", "ins", "del" start-tag . 

就是说a不应该出现在这里,它属于inline元素,应该被包含在block元素中云云,img也是一样,解决方法是用p或者div元素来包含他们就可以了。

而第二个不兼容就比较棘手了:

there is no attribute "target" . 

也就是`target=”_blank”这种用法是标准不允许的,这个问题着实难解决了点。

有朋友说了,你不会用js来实现么?的确,网上有解决方式是先赋予a链接rel=xxx属性,然后用js判断属性再脚本运行时添加`target=”_blank”属性,或者直接用js打开脚本的也算一种方法。

可是各位,你们没有发现,这个链接是在<noscript>标签中么?这个标签中的代码只有在浏览器不支持js的时候才会显示,试问,在不支持js的浏览器中,刚才的js解决方案还能用么?

最终,我也没有更合适的解决方案,只有把`target=”_blank”去掉,然后在旁边注上一行字:

<noscript>
    <div>
        <a href="http://www.51.la/?272422">
            <img alt="&#x6211;&#x8981;&#x5566;&#x514D;&#x8D39;&#x7EDF;&#x8BA1;"
                src="http://img.users.51.la/272422.asp" style="border:none" />
            Tips: 在新窗口中打开链接,浏览更方便(点鼠标右键)。
        </a>
    </div>
</noscript>

我想,目前也只能用这种方式解决了吧,好在不支持js的浏览器、又是人在用的(非机器人),应该不多。

其实,51.la代码的兼容性之所以被发现,之所以不得不改,也不是我吹毛求疵,而是用了eclipse之后,它的语法检查给发现的(够强大的),实在是不习惯看到一对error和warning在下面待着,“被迫”修改代码使它们更加“标准”,我想这也是eclipse的一个优点吧。

PS: 在BlogUpp缩图中我网站的首页太难看了,一个图片也没有,hmm…,有没有好一点的wordpress两栏布局模板,突出文章内容的?偶也换换?

参考

Update @ 2008-05-12

看到妖精BlogUpp的上下布局给横过来了,猜测是自己手工改的,官网上好像没这个功能啊。。。

CSS裸奔节之强制脱衣

今天是CSS裸奔节,所谓CSS裸奔,就是把网站的所有css去掉,这样所有的显示格式什么的就都没有了,只剩下html实体显示出来,起源好像是比较无聊的想法,就是剥去css的外衣,让大家看看你的(x)html代码是否工整。

不过今天偶不打算裸奔,而是告诉大家一个可以看到任何网站裸奔形象的方法,参考我以前写的用js丰富你的书签功能,创建一个书签,也可以放到书签工具栏上,内容如下:

javascript:void((function(){var style=document.getElementsByTagName('style');for (i=0; i<style.length; i++)style.item(i).disabled=true;var link = document.getElementsByTagName('link');for (i=0; i<link.length; i++)if ('text/css' == link.item(i).type)link.item(i).disabled=true;var obj = document.getElementsByTagName('*');for (i=0; i<obj.length; i++){obj1 = obj.item(i);if (obj1.attributes.getNamedItem('style')){obj1.attributes.getNamedItem('style').value = '';}}})());

注意一定要是一行才行,作为书签地址就可以了,然后打开任何一个网站,点这个书签,是不是把css全部都脱掉了?懒人也可以直接把这个链接拖到工具栏上使用:

CSS裸奔

公布源代码如下,没有太复杂的地方,有了DOM说明,知道各个对象的方法和属性之后,把stylelink全部禁用,然后把inline的style=""的value全部设置为空串就可以了:

javascript:void((function(){
/* 用style方式引用的css */
var style=document.getElementsByTagName('style');
var s='Style:' + style.length;
for (i=0; i<style.length; i++)
{
    /*s += style.item(i) + '|';*/
    style.item(i).disabled=true;
}
/* 用link方式引用的css */
var link = document.getElementsByTagName('link');
s += 'Link:' + link.length;
for (i=0; i<link.length; i++)
    if ('text/css' == link.item(i).type)
        {
            /*s += link.item(i).href + "|\\n";*/
            link.item(i).disabled=true;
        }
/* 任意对象的style="" */
var obj = document.getElementsByTagName('body').item(0).childNodes;
var obj = document.getElementsByTagName('*');
s += 'Obj:' + obj.length;
for (i=0; i<obj.length; i++)
{   
    obj1 = obj.item(i);
    if (obj1.attributes.getNamedItem('style'))
    {
        s += obj1.nodeName + obj1.attributes.getNamedItem('style').value + "\\n";
        obj1.attributes.getNamedItem('style').value = "";
    }
}
/*alert(s);*/
})());

这个文件删除掉注释以后,可以用下面这个命令转换为一行:

cat css1.js |tr -d \\\\n |sed -r -e 's/$/\\n/' -e 's/\\t//g'

这样就得到了上面那段源代码。

javascript程序调试比较麻烦,以前我的方法是在vim中编辑,然后用命令转化为一行,再手工粘贴到书签的地址中,执行,然后有错误再回到编辑。不过今天发现一个好方法,其实也就是脑子转个弯儿的事,创建一个html文件,在里面把javascript代码调试好,然后再转换为可以用在书签中的形式。

另外Firefox2的Error Console虽然能够监测js错误,但是如果不小心点了上面的“Messages”,就会发现错误不显示了,需要再点“All”查看所有信息,今天为这是纳闷了半天,因为切换显示错误分类的时候没有任何征兆。

参考:

CSS技巧两则——居中和编号列表

update @ 2007-04-10

让对象居中,只需要一句css:margin: auto;,感谢dNgpNg和heiyo的指正。下面是我自己瞎找的笨办法,仅供大家开拓一下思路。

利用css让对象居中,比如是一个div,有人说这还不简单?不就是text-align: center么?其实不对,这只是让对象所包含的内容居中,而不是让对象本身居中,其实,我还没有找到能够直接让div等块div对象居中的css方法,不过从Computing.Net找到了一个替代方案:

比如一个div,宽度设定为60%,那么要使他居中,笨的方法就是用另外一个带有text-align: center属性的div或其他容器包含它,聪明一点的办法是这样:

margin-left: 20%;

左缩进20%加上div本身的宽度60%是80%,剩余的右缩进自然就是20%,所以div看起来就像是居中了一样。

第二个问题是编号列表,如何实现像word或者openoffic那样自动层级的编号?先看我实现的例子吧:

看到没有,在上面这个例子中,有着两级编号,并且和一般html中的<ol>不同的是,两级编号是连续的,并且在标题中可以定制编号的样式。为了让大家看得更清楚,我把代码贴出来。不要想着用查看源代码的方式来观察,由于Wordpress有自动纠错功能,会自动把嵌套的<ol>给补全,所以我改成用javascript+String.fromCharCode(n)方式输出了,查看不方便。

<style type="text/css" media="screen">
<!--
#number_list {counter-reset: c_level1}
#number_list ol {counter-reset: c_level2}
#number_list li {list-style-type: none;}
#number_list li:before {display: marker; content: "§ " counter(c_level1, decimal) "、"; counter-increment: c_level1 1}
#number_list ol li:before {display: marker; content: "§ " counter(c_level1) "." counter(c_level2, decimal) "、"; counter-increment: c_level2 1}
-->
</style>
<ol id="number_list">
    <li>大标题一</li>
    <ol>
        <li>小标题1</li>
        <li>小标题2</li>
    </ol>
    <li>大标题二</li>
</ol>

现在清楚了吧,用display: marker:before来定义列表项目前面显示的内容,用counter来定义计数器,用content定义要显示的形式,用counter-increment定义计数器自增值,用counter-reset定义计数器归零的条件,就可以实现复杂公文处理系统中的可定制多级编号了,在Firefox2中测试通过,不保证在IE下能用。更详细的资料,请查询W3C的CSS文档

什么?不知道word和openoffice的多级编号?Orz…自行放狗搜索吧。

动态载入js并执行(未成功)

说是未成功,也包含了并未失败的含义,只是没有完全达到预期的目的罢了。

最初的想法是这样的,我零星的写过一些小文章或者小工具,都是使用html语言写的,但处于方便保存/转移/备份/浏览的目的,html中所有的内容全部都包含在一个文件当中,不使用图片,css和javascript也都直接包含在文件中。现在我想在这些文章和工具中添加一些统计代码和adsense代码,就想到了如果能有一个js文件,把统计代码和adsense代码都写在里面,然后在那些单独的html文件当中包含一下这个js文件就可以了,这样可维护性就大大的增强了。

首先要排除的是innerHTML方式,因为这种方式只能写入静态内容,写入js代码虽然能够成功,但被写入的代码却不会被执行。所以,最后采用了appendChild的方式,结果如下:

首先在html也中引用js文件:

<div id=”stat_51_la” style=”text-align: center;” /> <!– 这一句的作用稍后解释 –> <script src=”stat_51_la.js” type=”text/javascript”></script>

然后,具体被引用的js文件内容是这样的:

function stat_51_la() { //重定向document.write的输出方向 document.write = function(s) { document.getElementById(‘stat_51_la’).innerHTML += s; return false; } var s = document.createElement(“script”); s.type=”text/javascript”; s.src=”http://js.users.51.la/272422.js”; //document.getElementsByTagName(“body”)[0].appendChild(s); document.body.appendChild(s); } stat_51_la();

思路介绍:先看下面那段代码,就是document.createElement往后的部分,主要思路是通过document.createElement创建一个script对象,然后对他的属性进行赋值,尤其是src属性,代表这要引用的js script文件的uri,最后通过document.body.appendChild(s);把这个script对象添加为body的最后一个对象,实现js文件的动态载入,并且可以正确的执行所载入的js代码。但如果只作这么多工作的话,当动态载入的js文件中有document.write方法时,在IE下没有反应,但在Mozilla Firefox 下就会让你原来的网页消失,只显示document.write出来的内容,所要就要用到document.write = function(s)部分,重新定义document.write函数,把输出重定向到div id=”stat_51_la”当中,就能够比较好的解决这个问题了。

看起来已经解决了问题,并且用在51.la统计代码上效果很好,但在嵌入adsense代码的时候遇到了问题,大概检查了一下,好像是adsense也用到了类似的方法,两种相同的方法一嵌套,就变样了,实在是头大,没有精力再深入的查找原因了,就此打住,像adsense这样复杂一些的应用还是用后台脚本实现更方便。

参考:简单参考复杂讨论

用js丰富你的书签功能

美味书签furlcocomment等服务,都具备利用书签按钮“一键提交”的功能,其实一点儿也不复杂,只要你掌握了在收藏夹中使用js的方法,就可以为你的书签工具栏增色不少。

本文主要测试于firefox浏览器下,ie浏览器应该同理可用。

首先要发挥js在书签中的最大作用,你要知道如何让你的firefox工具栏显示出来,并且在书签项目上点击右键可以修改他们的内容。

在下面的例子中,所有的代码都需要填写在书签项目的Location栏中,并且为了浏览方便,部分内容我进行了分行,而在填到书签项目中的时候一定要合并成一行才行。

先来一个最简单的例子,只包含一个js函数:

javascript:alert(document.lastModified);

点击这个书签项目,将会弹出一个提示框,显示当前网页的生成时间。

如果要修改页面上的内容,然后提交,javascript就要复杂一些了:

javascript: (   function()     {       document.Form1.id.value=’001′;       document.Form1.name.value=’fwolf’;       document.Form1.Submit();     } ) ();

基本原理是:function()是定义了一个函数,它外面加了一对儿()是对这个“无名”函数的引用,后面那对()是引用函数时的参数(没有参数)。上面的代码执行效果就是向网页中指定表单填写内容,然后自动提交。

如果要修改网页上的内容,但是不作提交等动作,仍然显示当前网页,上面那个例子中的方法就不管用了,需要再作一些调整:

javascript: void(   (     function()     {       p=document.getElementById(‘LOGPASS’);       p.readOnly=0;     }   )   () );

就是把上面那个例子中的内容用void()再包含了一遍,也就是整体作为一个不返回内容的函数体来执行了,如果不这样,直接使用上面那个例子的方式来作这些的话,网页内容会显示function()的返回值。如果把void直接加到function上或者他外层的()上道理上应该也可行,但我没有测试。

怎么样,想到什么好的鬼点子没有?上面的最后一个例子就是我在使用建设银行个人网银的时候鼓捣出来的,他的登录页面默认是不让手工输入密码的,而是通过一个js的软键盘,而软键盘的js代码在ff下无法正确执行。现在通过这种方式,我能够成功在ff中登录建行个人网银了,只可惜他内部的功能页面对js依赖很强,并且同样在ff下无法正确执行,所以最终还是要在ie下才能够正常使用。但相比之下,比其他的个人网银要借助activex才能输入密码的方式兼容性已经好很多了。

参考:

update @ 2006-11-28

如果使用这种方法,又同时使用Google Browser Sync来同步书签,记得一定要把location更改为一行(ubuntu下location其实是可以输入多行内容的,粘贴过来即可,并且还能够用上下键选择行进行编辑),不然Google Browser Sync在同步的时候,这项书签会丢失的。