这次的教程内容贴近我擅长的技术方向:安全的contact forms。
就像我在前一篇教程中提到的那样,一个最普通的contact forms可以帮助访客同你进行通信来往而不需要暴露你的电子邮件地址给那些可恶的垃圾邮件制造者们。
但如果spammer们已经盯上你,没有什么比一个不安全的contact foms更糟糕的了。想象一下你的网络空间提供商发给你一封措辞强烈的电子邮件,通知说:他们发现你的网站发送了大批量的性药广告以及其他垃圾邮件,另外,直到你停止这种行为之前,你的网站都将处于离线状态–谢谢!
那么,今天我要在这篇教程里告诉大家的是一种在任何contact forms上添加一个额外安全层的简单方法-即使你没有使用我提供的超级安全、超级灵活的Ultimate Form Mail。
当前状况
你意识到spammer们已经通过远程探测技术发现了你的contact forms的弱点,而你希望他们走开。
难点
你不想使用CAPTCHA(Completely Automated Public Turing Test to Tell Computers and Humans Apart),因为你明白,让你的访客先去阅读那些歪七扭八的字母数字才能发送消息只能抑制他们想要互动的欲望,而不是促进它。(数字验证的缺陷)
关键点:你希望那些坏家伙们堵车到天黑,同时希望那些好孩子们一条大道通罗马。
解决方案
你将学会在页面加载的时候使用jQuery来给你的contact forms添加一些隐藏的标签信息。当窗体信息被提交到服务器端的时候,你可以用一些简单的php代码实现如下的步骤:
隐藏的标签被识别出来 隐藏标签的信息与你的网站访客下载到浏览器上的cookie里的某项标志相一致 隐藏标签的有效时间还未过期 换句话说,你的访客们只有在一段有限的时间内才可以填写窗体并进行发送。如果一个spammer尝试通过远程调用来提交窗体信息到你的服务器,他们将会发现自己踢到了一块又厚又硬的铁板,不付出点代价休想通过。
我将要告诉你的这种方法是从一位非常聪明的同事Chris Shiflett提供的蓝本基础上修改而成的。他是位专业的安全专家,对php程序员经常遇到的安全问题了如指掌(我怎么感觉他又要忍不住提到他的Ultimate Form Mail 了~~汗)。
教程
基于上次那篇《斑马线表格轻松制作》的反响良好,我决定再次制作一次类似的“手把手图文教程”。虽然要花费些时间,但很值得这么做。
银弹?1)
“那么,现在我的窗体就是100%安全的,可以假设任何免费的cntact forms程序,然后高枕无忧了?”
呃。。。非也。
这种安全模式基于一个关键的假定:Spammer们总是会拿软柿子捏,浪费时间去解决一个狡猾的对手对他们来说就是浪费金钱。
现在, 好好听着,我的朋友们:
这个技术,尽管相当健壮,但仍然不是解决目前脆弱的窗体处理程序问题的灵丹妙药。
我的这些安全建议的目的是为了让spammer们知难而退。小偷们入室盗窃之前总会进行仔细踩点,他们只对那些可以用最小代价获取最大利益的房间感兴趣。
换句话说,如果在他们动手之前有99%的机会挡住他们的试探,而且实现起来相当容易,为什么不试一试呢?这才是此项技术要实现的目标。
但这还是治标不治本,不能解决所有问题。
-----------------------------------------------------------------------------------------------------------------------------------------------
JQuery第7天:样式表切换
JQuery第7天:样式表切换
我第一次看到样式表切换器是在A List Apart或者Simple Bits,那是两个设计师最应该去的网站。
从那以后,我找到了很多可以让访客通过鼠标点击某个地方切换样式表的方法。但最近我要写一篇如何 使用jQuery编写简单代码实现它的教程。
我将向你们逐步解说整个的过程,不仅仅因为要展示jQuery代码的简介,同时也要揭示jQuery库中的若干高级特性。
首先,代码
$(document).ready(function() { $('.styleswitch').click(function() { switchStylestyle(this.getAttribute("rel")); return false; }); var c = readCookie('style'); if (c) switchStylestyle(c); }); function switchStylestyle(styleName) { $('link[@rel*=style]').each(function(i) { this.disabled = true; if (this.getAttribute('title') == styleName) this.disabled = false; }); createCookie('style', styleName, 365); }
其他这里没有提到的部分是你将在后面看到的创建和读取cookie的函数。
熟悉的开篇
$(document).ready(function() { $('.styleswitch').click(function()
告诉jQuery“以最快的速度查找所有包含对象名‘styleswitch’的元素,并在他们被鼠标点击时执行一个函数”。
看起来不错。当鼠标点击预先指定的元素时,switchStylestyle函数将被调用。从现在开始是重点。
这句话什么意思?
第一次看到这句代码的时候我的脑子有些卡壳:
$('link[@rel*=style]').each(function(i) {
在互联网上搜索了一下后我空手而归。最后不得不找到了jQuery的作者John Resig,向他咨询。
他直接给了我一个jQuery网站的页面地址,里面讲解了若干jQuery提供的高级特性(xpath),可以用来查找并操作页面中的若干元素。
如果你看过这些东西你就能明白上面那句神秘的代码的含义是告诉jQuery“查找所有带rel属性并且属性值字符串中包含‘style’的link链接元素”。
嗯?
让我们看看如何编写包含一个主样式表,两个备用样式表的页面:
<link rel="stylesheet" type="text/css" href="styles1.css" title="styles1" media="screen" /> <link rel="alternate stylesheet" type="text/css" href="styles2.css" title="styles2" media="screen" /> <link rel="alternate stylesheet" type="text/css" href="styles3.css" title="styles3" media="screen" />
我们可以看到所有样式表都含有一个包含‘style’字串的rel属性。
所以结果一目了然,jQuery轻松定位了页面中的样式表链接。
下一步?
each()函数将遍历所有这些样式表链接,并执行下一行中的代码:
this.disabled = true; if (this.getAttribute('title') == styleName) this.disabled = false;
“首先禁用所有的样式表链接,然后开启任何title属性值与switchStylestyle函数传递过来的字串相同的样式表”
一把抓啊,不过很有效。
现在我们需要保证的是那些样式表存在并且有效。
完整代码和演示
既然 Kelvin Luck已经编写了这些代码,我就不在这里重复了。
我相信Kelvin的灵感是从 这个网站那里得到的,我们正好可以看看使用其他工具实现这个功能是否要比jQuery更加复杂冗长。
---------------------------------------------------------------------------------------------------------------------------------------
JQuery第8天:使用java script(jQuery)实现圆角边框
JQuery第8天:使用java script(jQuery)实现圆角边框
当我看到这些实现圆角边框的HTML源代码的时候,我发现这很适合用来写一篇jQuery教程–使用wrap()、prepend()、append() 函数。
这里是原先的HTML代码,我们将从这里开始:
<div class="dialog"> <div class="hd"> <div class="c"></div> </div> <div class="bd"> <div class="c"> <div class="s"> <main content goes here > </div> </div> </div> <div class="ft"> <div class="c"></div> </div> </div>
现在我们怎么使用jQuery来精简这段代码呢?
首先,我们需要一个“钩子”,一个特殊的HTML元素,或者一个id,或者一个对象名–来告诉jQuery处理的目标。
现在我们改成了这个样子:
<div class=“roundbox”> <main content goes here > </div> 下一步,我们使用jQuery来将剩下的代码添加进去:
$(document).ready(function(){ $("div.roundbox") .wrap('<div class="dialog">'+ '<div class="bd">'+ '<div class="c">'+ '<div class="s">'+ '</div>'+ '</div>'+ '</div>'
+ '</div>'); });
其他Div标记去哪里了?
仔细观察代码,你就会发现它们都跑到了js代码里面,在wrap函数执行时它们将嵌套在“钩子Div”的内部。
细心的观众会发现我漏掉了部分代码。这是因为jQuery中的wrap()函数要求div标签必须严格对称嵌套才能工作。
具体的,我去掉了下面两个部分:
<div class="hd"><div class="c"></div></div> <div class="ft"><div class="c"></div></div>
添加和预置一体化
下一步我们将会通过prepend和append函数将这两段代码添加进带有dialog对象名的div标记内部,并且使用“连锁”方法。
$('div.dialog').prepend('<div class="hd">'+ '<div class="c"></div>'+ '</div>') .append('<div class="ft">'+ '<div class="c"></div>'+ '</div>');
示例及代码
我已经在网上放置了一个演示页面供大家查看。建议你看一下页面的源代码,体会jQuery给页面代码带来的清爽和便捷。
这些代码来自 Schillmania的一篇文章,个人推荐大家下载包含点缀图片的zip打包,非常精美。
不使用图片的圆角边框
有很多方法可以实现圆角边框–有些方法甚至不需要图片。
在jQuery的网站上有一个用来制作无图圆角边框的插件。虽然不是适合所有人(或者说所有程序),但也值得学习。
看看它的漂亮代码吧(使用时):
$(document).bind("load", function(){ $("#box1").corner() });
-----------------------------------------------------------------------------------------------------------
JQuery第9天:快速和略显粗劣的AJAX视频教程
JQuery第9天:快速和略显粗劣的AJAX视频教程
今天我的想法有点改变。近段时间以来我一直考虑注册一个YouTube帐号来上传一些教程录像,现在我终于做出了决定并上传了一个。在这里我将手把手的向大家演示为你的网站添加一些AJAX基本应用的方法。
录像很短,因为YouTube对上传影片的长度有限制(10分钟以内)。当然由于制作仓促,错误在所难免。比如在某个地方我称CGI为“服务器端脚本”,而更准确的说法应该是“服务器端语言”。
这是AJAX,还是AHAH,抑或AXAH?
你将看到的东西其实更接近AHAH而不是纯粹的AJAX。
有什么区别么?AJAX中的“X”代表着XML。但更多时候人们喜欢使用简单的文本或者java script代码或者单独文件而不是那种复杂冗长的XML。对此有篇文章有详细论述:AJAX vs. AHAH。
至于AXAH。。。 Cody Lindley的文章
可以解释一切。对AJAX的一些工作理念有兴趣的读者可以看一下。
这个页面上有我提供的演示。
-----------------------------------------------------------------------------------------------------------------------------------
JQuery第10天:使用jQuery(java script) 库实现"即点即改"的AJAX化
JQuery第10天:使用jQuery(java script) 库实现"即点即改"的AJAX化
以前我在Quirksmode网站见过这种代码,后来又在24 Ways网站看到了一个更具Web 2.0风格的方案。这次我将为大家展示两种使用jQuery实现相同功能(甚至更好)的方法。
目标
一个用AJAX(或AHAH)技术设计的页面,访问者无需离开就可以在看到的(x)HTML 页面上编辑内容。
方案
点击需要编辑的文本,变幻出一个带有保存和取消按钮的textarea。修改的部分将通过AHAH传送至服务器端的一个PHP脚本文件,用来更新数据库(MySQL或普通文件)。
演示
在这第一个演示中,我使用了一个id为“editinplace”的div元素。当鼠标划过这里时,背景颜色将变成浅黄色。点击文本将启动一些DOM操作,div元素被一个textarea元素取代–内中包含原先的文本。
点击保存按钮将向服务器端的PHP脚本文件发送新的HTML内容,并重新输出收到的新文本内容(通过 $_POST)。
在真实应用环境下,你还应当添加一个安全性检测,然后才能更新数据库并返回更新后的页面内容,同事告知jQuery执行成功的信息。
但在这个例子中,所有的修改都是成功的,发送给PHP脚本的信息将原封不动的返回到jQuery代码,显示到一个普通的警告窗口里。
解释
开头部分说了很多次了,如果你不想使用jQuery提供的document.ready函数,尽可以选择你自己中意的init()函数。
页面上第一个被执行的就是这个setClickable()函数。它的任务就是做以下内容:
查找包含id为“editinplace”的div元素,然后告诉jQuery在这些div被点击时执行某些操作。
读取div内部的HTML代码的任务将交给jQuery的html()函数来完成。这些HTML将会额外添加若干代码以组成textarea里的保存和取消按钮。
var textarea = '<div><textarea rows="10" cols="60">'+$(this).html()+'</textarea>'; var button = '<div><input type="button" value="SAVE" class="saveButton" /> OR <input type="button" value="CANCEL" class="cancelButton" /></div></div>'; var revert = $(this).html();
同样还是这些在div内部找到的HTML代码将会赋值给一个叫做“revert”的变量。这个变量将用来在取消按钮被按下的事件中输出原始文本。
var revert = $
(this).html();
jQuery的DOM函数“after”用来将新生的textarea HTML代码放置在我们指定的div元素后。我在后面紧跟着连锁上了一个remove()方法 来移除div元素以节省代码。
$(this).after(textarea+button).remove();
在使用jQuery的时候,我通过对象名来定位保存和取消按钮对象。我指示jQuery在任一按钮按下时触发最后一个函数“saveChanges”。我告诉了jQuery在div元素被点击时做什么事情,但我没有在最后加上分号因为我希望在这个div操作语句后面连锁其他方法。
$('.saveButton').click(function(){saveChanges(this, false);}); $('.cancelButton').click(function(){saveChanges(this, revert);}); })
我再连锁了一个简单的mouseover和mouseout事件,告诉jQuery在鼠标指针掠过我们指定的div元素(id=editInPlace)的时候添加和移除一个对象。
.mouseover(function() { $(this).addClass("editable"); }) .mouseout(function() { $(this).removeClass("editable"); }); };//end of function setClickable
函数“saveChanges”将以按钮对象做为第一个参数,而cancel参数则取两种值,false或者保存在revert变量中的html代码内容。
function saveChanges(obj, cancel) {
如果cancel为假,则函数将保存更改并使用html格式发送给服务器端的php脚本。我在这里使用了jQuery内置的一个DOM函数实现对textarea内容的提取操作:parent()和siblings()。
if(!cancel) { var t = $(obj).parent().siblings(0).val();
DOM基础超出了本系列教程的范围,但在这个应用中我只是告诉了jQuery“对象(保存按钮)有一个父元素(div)。。。去找到它。那个元素拥有一个或多个DOM树同级对象。。。我只想找到其中的第一个。然后提取那个对象的所有内容。”
(稍等。。。如果你对DOM风格的代码不是很熟悉的话,前面我的注释可能并不好理解。我还是建议你之前google一下“DOM java script”或者其他相关的信息。)
这些html赋值给了t变量,现在要通过POST方法把它发送给test2.php。
$.post("test2.php",{ content: t },function(txt){ alert( txt); })
; }
如果cancel有一个值,那么必然是保存在revert变量中的原始html内容。所以,在这个时候我希望变量t变为原始html内容。
else { var t = cancel; }
下一步是通过jQuery提供的DOM函数放置一个新的div元素,id为“editInPlace”,在这之后包含了textarea元素。。。然后删除掉这个div元素。
$(obj).parent().parent().after('<div id="editInPlace">'+t+'</div>').remove()
在果壳中,这将告诉jQuery“在DOM树中上跃两次。将HTML代码附在到达位置的对象之后,然后移除那个对象。”
最后,我们再次调用setClickable函数并关闭saveChange()函数。重调setClickable()函数的含义是重新设置onMouseover,onMouseout,和onClick事件到初始状态。
setClickable(); }
第二个示例
第二个方法非常类似但也有点复杂。
没有用到庞大的单独div元素,这个示例将每个段落p标签变换成单独的可编辑区域。
这里的难度在于你如何在向服务器端脚本发送数据时指定正确的段落p标签。
在这里我通过为每个p标签编号并将这个编号一同发送给服务器端的php脚本的方式解决了问题。你会在alert窗口中看到php脚本是如何“知道”哪个p标签里的内容被修改的。
已知的问题
现实的应用中,你在使用类似的功能时首先需要验证更改的内容的合法性,然后才能将数据发送到服务器端。显然在这里我们刻意把这些内容忽略掉了。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
JQuery第11天:实现多文件上传
JQuery第11天:实现多文件上传
好几个月以前,当我在追逐互联网上AJAX热潮的时候,我在 FiftyFourEleven网站上发现了一篇使用创新的java script代码实现当时正在困扰我的“ 单文件元素实现多文件上传”的文章。
所以当我想写作《15天漫游jQuery》的时候,我第一个想到的就是用jQuery实现这个功能。
接触易用性狂热爱好者
几天前当我检查网站记录的时候,发现了一条遗漏的文章trackback。跟过去看的时候我发现我的两篇jQuery文章被作者引用来证明他为什么讨厌java script。
根据这个人的说法,任何工具或技术如果没有将易用性放在第一位都将成为垃圾。
尽管我很不同意这位仁兄一杆子打死的态度,但他还是让我对这篇详细教程有所留意。当我在编写一个简单网页效果的时候,我会尽量小心谨慎的处理。这样如果网站访客们决定关闭java script代码执行功能的时候,他们仍然可以正常使用网站的功能。
关于第一价值的两个教程
- 使用一个文件输入元素实现多文件上传,并让整个交互过程流畅舒适。
- 让多文件上传更加人性化,但要避免以牺牲可用性为代价。关键在于使用不苛刻的java script代码制作多文件输入区域。
演示
- 只有一个文件输入元素,但添加了jQuery和其他代码实现较为亲近用户的多文件上传功能。
- 在页面(x)html代码中使用了多个文件输入元素,但通过jQuery调整为与第一个演示类似的显示页面效果。优点是代码是不苛刻的。。。即使关闭了java script执行,用户也能上传多个文件。
演示二地址(这个演示有bug导致无法使用,作者修正了bug,使用这个后面链接查看演示演示二地址(no bug))
解释
单文件输入框
jQuery的$(document).ready() 函数的工作有两个:
创建一个用来显示最大允许上传文件数的div元素。 查找文件上传框(假设这里只有一个),然后给它附上一个onChange事件。
$("input[@type=file]").change(function(){ doIt(this, fileMax); });
doit()函数(简单又好记,呵呵~)检查是否达到了最大文件数量限制,如果不是,它会隐藏当前文件输入框,在父div里添加一个新的文件输入框,将输入框内的文件名使用id “files_list”作为标记,在最后添加一个“删除”按钮。
在DOM树中导航,我使用jQuery的parent()函数,然后用remove()函数移除元素。我还使用了append()和prepend()函数分别添加文件名和新的输入框。
两个关键点
- 最大文件上传数量设定:
- 输入框必须有适当的定位措施:
"file" class="upload" name="fileX[]"/>
这样弄以后输入框可疑由访问者决定添加还是删除,没有任何关于id或名称的操作。当这个窗体代码发送给服务器端脚本的时候,相关信息就已经被存放在了一个数组中了。
多文件输入框
首先,文件允许上传的数量由页面中的文件输入框的数量决定。其次,你仍然需要通过某种方法为每个输入框接收到的内容用一个数组存放。
"file" class="upload" name="fileX[]"/>
第二个演示跟前面的比起来最大的不同在于,我遍历了每个文件输入框并在其内容有改动时执行doit()函数。通过遍历每一个输入框,我可以为我的代码添加有用的额外信息:输入框内容在“堆栈”中的顺序。
换句话说,当这段代码执行时,它会特别指定第一个输入框,或者第二个,抑或第三个。
代码见下:
$("input[@type=file]:nthoftype("+ n+")")
jQuery的灵活性允许我们使用CSS和XPath描述语句定位指定的元素位置。
你会发现当一个文件被选中时,文件输入框都会被文件名称覆盖。点击文件名就可以选择其他不同的文件。
--------------------------------------------------------------------------------------------------------------------------------
JQuery第12天:Lightbox(插件)
JQuery第12天:Lightbox(插件)
Cody Lindley 移植的第一版“ Thickbox”让我第一次感受到了jQuery的魅力。后来他又做了一些 代码升级以修复若干跨浏览器的兼容性问题。
一些需要注意的地方
$(document).ready 取代了TB_init() 函数,作用是在每个包含对象名“thickbox”的链接上附加一个onClick事件。
function TB_init(){ $("a.thickbox").click(function(){ var t = this.title || this.innerHTML || this.href; TB_show(t,this.href); this.blur(); return false; });
当这些链接被点击时,TB_show()函数就将执行。
$("body") .append("
"); $("#TB_overlay").click(TB_remove); $(window).resize(TB_position); $(window).scroll(TB_position); $("#TB_overlay").show(); $("body").append("
");
如你所见,在文档body元素前添加了两个div元素。换句话说,这两个div元素将被添加在页面html代码的body关闭元素前。
覆盖的div将使用一个特定的包含不透明外表的CSS文件指定表现。TB_window的代码用来通过AHAH在页面中放置一张图片或者加入另一个页面。$(window).resize 和$(window).scroll 告诉jQuery在用户重新调整窗口大小或者拖动页面翻页的时候执行TB_position函数。这是保证Thickbox始终保持在窗口中心部位的手段。
接下来,Cody查询url的后缀。
var urlString = /.jpg|.jpeg|.png|.gif|.html|.htm|.php|.cfm|.asp|.aspx|.jsp|.jst|.rb|.txt/g; var urlType = url.match(urlString); if(urlType == '.jpg' || urlType == '.jpeg' || urlType == '.png' || urlType == '.gif'){//code to show images
如果这是一个图片文件,则jQuery的append函数会添加html代码到适当位置。
"+caption+"); $("#TB_closeWindowButton").click(TB_remove);
另外,远程文件将使用jQuery的load()函数导入。
$("#TB_ajaxContent").load(url, function(){
------------------------------------------------------------------------------------------------------------------------------
JQuery第13天:jQuery表格
JQuery第13天:jQuery表格
一位叫Klaus的朋友编写了一个小插件, 用jQuery实现可用性极佳的java script表格。
设置好正确的(x)HTML 和CSS后,你可以像下面那样创建表格:
$.tabs(”container”); first tab on by default 如果你像在默认位置“上方”再添加一个表格: $.tabs(”container”, 2); second tab on
Klaus这里 示例,你可以看看最终效果。
我的改版
我稍微修改了Klaus的代码,添加了一个简单的表单用来生成表格的表头。
用法:
非常简单。只需要输入每个表格的表头(最多5个),然后点击表单下方的按钮。下一个页面将生成结果HTML代码,你可以复制然后粘贴到文件中。
你还需要 下载Klaus网站的CSS文件,做些你自己的修改,当然还要上传jQuery框架库到你的服务器上。
这里是表格生成器的地址。
--------------------------------------------------------------------------------------------------------------------------------------------------
JQuery第14天:java script工具提示
当我检查HTML代码时,我发现了一个大问题,可访问性。链接在java script关闭的时候无法工作。我并不是倾向于一定要实现全面的可访问性,只是在这里我认为可以有其他更具亲和力的方式实现相同的功能。
尤其是,我个人不喜欢那种为了可访问性而去牺牲可用性来实现在提示框上链接另一个页面链接的方法。我喜欢这个提示框 - 不是对Cody不尊重,只是在我这里我“需要”它能够在各种情况下工作。
今天我要提供给大家的是Cody的工具提示代码的小小修改。如果你不是Cody工具提示的爱好者的话,我的改版对你来说也许不是很在意。但如果你喜欢他的作品同时希望它可以在java script关闭的时候照常工作,这个也许是你需要的。
我的改动
让我产生修改想法的,是他的代码在Yahoo上的应用。我不喜欢他使用的代码:
所以我重写了他的部分代码,成了现在这个样子:
改进:HTML标准校验
我的代码可以通过w3.org的测试
改进:命名
在我修改Cody的代码的时候我发现他使用了一个用来存储链接名称的叫做“title”的变量名,这会导致一些混淆。
我标出了这个命名问题,即使我认为这不过是个小小的失误。
改进:可用性
使用我的代码,你可以让每个提示框都含有真实链接地址到另一个文档,不管内部的还是外部的。或者你只是想要那个提示框,不想关心可用性,你同样可以让链接部分留空。
选择权在你。
感谢
Cody提供了伟大的代码,帮助我节省了大量的时间和精力。我的修改只是对原有代码的轻微“调整”,希望朋友们喜欢。