新的广告交换、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”查看所有信息,今天为这是纳闷了半天,因为切换显示错误分类的时候没有任何征兆。

参考:

自己写js代替手工点击

有一些变态网页,会有一大堆radio或者checkbox让用户去点,或者有很多+要逐个展开,如果经常使用这样的功能,手工一个个的去点是很笨的做法,如果结合我原来介绍过的用js丰富你的书签功能,自己写点javascript就方便多啦。

例如,网页上有几百个+需要展开,而+部分的html代码如下:

<img src=”collapse.gif” title=”展开列表” style=”cursor:hand” onclick=”uf_Expand(this, ‘6’, ‘909.2500’)”>

其中onclick动作调用的uf_Expand就是实现展开的函数,于是,我们可以遍历所有的img对象,利用src=”collapse.gif”来辨别这是一个点击展开的“+”(如果能配合id来使用当然更好啦),然后调用它的onclick动作:

javascript: void( ( function() { var img=document.getElementsByTagName(“img”); var length=img.length; for (var i=0;i<length;i++) { obj=img[i]; if (“http://www.fwolf.com/collapse.gif”==obj.src) { obj.onclick(); } } } ) () );

注意img的src属性和html中看到的并不完全一样,加上了前面的域名部分,这是浏览器在解析html的时候自动加上的。现在只需我们轻轻点一下做好的书签按钮,就可以展开所有的+了。

还有一种情况,那就是两次展开之间需要一定的时间间隔,毕竟谁的服务器也无法承受一下子多出几百次请求,一般这种情况的解决都是写两个函数,一个为启动函数,使用setTimeout方法启动另外一个主体函数,主体函数在作完一次处理之后,再使用setTimeout调用自身。由于我们这里需要作的处理比较简单,所以也可以采取直接setTimeout,通过增加timeout时间的方式来实现。只需把上例代码中的“obj.onclick();”这一行更改为:

setTimeout(“document.getElementsByTagName(‘img’)[” + i + “].onclick()”, 3000*i);

就可以实现每隔3秒自动展开下一个“+”了。

用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在同步的时候,这项书签会丢失的。

[Js]如何取鼠标的当前位置/坐标

一般在Javascript中,我们用event.clientX来取当前鼠标在文档中的坐标,用event.ScreenX来去当前鼠标在屏幕中的坐标。但是,在Mozilla系列浏览器中,直接使用event是不行的,会提示说event没有定义,因此在Mozilla或Firefox中调用时,需要变通一下。

在调用函数的时候,始终传一个event参数进去,在Mozilla中,会将Event对象传进去,而在IE下默认就有Event对象,也不冲突,这个问题就解决了。

以下这个例子就能够在IE和Mozilla中都正常运行。

当前鼠标坐标为:
X:
Y:

源代码:

<pre onmousemove=”DisplayMp(event)” class=”code”> 当前鼠标坐标为: X:<span id=”mp_x”></span> Y:<span id=”mp_y”></span> </pre> <script type=”text/javascript”> <!–//–><![CDATA[//> <!– /** * 显示/隐藏指定的对象(style.display方式) * @param object event 事件,用于捕捉鼠标位置等,可省略 */ function DisplayMp(event) { document.getElementById(‘mp_x’).innerHTML = event.clientX + ‘px’; document.getElementById(‘mp_y’).innerHTML = event.clientY + ‘px’; } // end of function DisplayMp //–><!]]> </script>

另外取到鼠标的坐标,赋值给style.top等属性的时候,后面需要加上单位,不然也会提示错误。下面就是一个正确的例子:

obj.style.top = event.clientX + 10 + ‘px’;

See Also:

Update @ 2007-03-29

如果在js中使用html_obj.onclick = function () { some_action uses Event }这类语法时,如果遇到Event,注意Event最好大写,不然不会生效。

Update @ 2008-05-18

似乎找到最终的优秀解决方法了,首先用一句话解决event对象的兼容性:

if (!e) var e = window.event;

同时在调用函数的时候,如果没有显式传递Event,它会自动赋值。同时还找到取鼠标位置更兼容的方法:

if (e.pageX || e.pageY) {
    posx = e.pageX;
    posy = e.pageY;
}
else if (e.clientX || e.clientY) {
    posx = e.clientX + document.body.scrollLeft
        + document.documentElement.scrollLeft;
    posy = e.clienty + document.body.scrollTop
        + document.documentElement.scrollTop;
}

结合起来,用jQuery调用的例子:

$("#showhide_svninfo").mouseover(function(e) {
    SwitchDisplay('#svninfo', 'block', e);
});

这样综合下来,兼容性就非常好了。不过本文中的例子我没有再按照这个改,好像在IE下又不灵光了。

参考:Event properties