| 育炜's profile有为PhotosBlogLists | Help |
|
|
March 06 关于产品设计互联网产品的特点 互联网产品和软件产品不同,相比来说,互联网产品需要更快的开发速度,更灵活的结构,更好的拓展性,更快的更新速度。互联网产品,往往不仅限于功能的实现。而一个成功的产品,除了和用户的交互,功能的强大,便捷,容错能力强之外,文化和氛围的形成,建立,也会对产品起到异常重要的作用。而在产品规模到达一个层面的时候,通常需要对平台本身结构,功能,技术,体验等方面的突破,以至达到概念的突破,才能让产品再次迸发出生命力和竞争力。
什么时候需要产品设计 任何时候产品都需要不断的更迭和完善。但是基于互联网产品的特点,在产品新推出,和平台到达一个规模瓶颈的时候,尤其需要通过设计来提高产品的竞争力,从而迅速占领市场。产品前期的结构是否合理和灵活,也决定了产品后期的改造,平台整合,功能和资源输出是否能快速小代价的执行。
什么人应该懂得产品设计 产品设计人员(产品的功能设计人员)无疑需要精通产品设计。其实,一个产品生产团队的所有人,都应该或多或少懂得产品设计,至少有产品设计的理念。一个再好的功能设计师,也没办法把所有执行层面的产品细节设计到位。而且也没有充足的时间让大家这么作。那么遇到产品执行细节的时候,必定需要各执行层的人员在专业技能之外,用产品的理念进行执行。 例子: 比如yahoo美国首页的更多服务菜单,这个菜单通过一次点击从左边移出。产品人员可以设计这个菜单的通过什么动作激活出现,从什么地方出现,什么时候消失,但是没办法设计这个菜单移出的速度。是匀速移出,加速移出还是减速移出。移出到制定位置的时候是否要做急停或者抖动效果。 上述的这些是需要动画设计师和工程师合作来完成的,不仅仅是产品人员。 产品人员在设计流程的时候,也可能不甚了解某个新特效或者交互形式的应用,会对现有的开发有多大程度的影响。这时候,产品人员需要和相关的技术工程师沟通来确定具体的流程或者交互逻辑应该如何设计。 因此好的产品人员不一定在各个执行层面都是强手,但是好的产品人员一定要懂得如何和专业人员沟通,从而可行的好的产品方案。
产品设计都设计什么 产品设计绝不是单纯对功能的增减。往往出现的一个现象,是产品人员拿着功能列表的单子,和大家讨论哪些功能要,哪些不要,哪些一期做,哪些二期做。在时机不恰当的时候,就陷入了细节的泥潭,而忘记整体的目标。最后的产品就成了一个功能堆砌的场所,而很难表现出原本的主张。之前说过,很多的细节是需要和专业的执行人员协调沟通来执行的。产品人员一定要在整个过程中,可以看到大的产品目标和方向,不能让自己迷失。这个时候一定不能忘记目标用户群、平台优势、定位、资源。
关于用户心理模型和产品设计模型 产品的设计模型,其实我更愿意说产品实现模型。往往设计模型和实现模型是有差距的。而用户也往往没有按照我们预先设计的模型来使用产品。一个产品模型为用户提供了很多可能。产品人员也要通过最终用户的使用情况来判断产品的实现模型是否和用户的心理模型匹配。 用户使用产品的时候通常现如下: 需求目标->分解成若干任务->按照产品规则进行交互->对照心理预期验证执行结果 这个路径通常不是唯一的,也可能在交互的过程中,用户的早期需求目标就发生了改变。因此,条条大路通罗马。关键是不要总让用户在最后失望。
产品设计的依据 如何判断产品设计是否合格,是否达到了目标。产品的数据指标是足够客观的。但是也往往难以直接揭示问题。而且往往在产品发布之前,产品人员就需要取得足够的依据以便可以在验证团队的想法。 通常评审产品的方法有“焦点小组”和“用户可用性测试”。焦点小组的评审方式更崇尚经验和专业。而互联网产品的用户群体和文化往往变化较快,所以焦点小组的评审略显主观和狭窄。目前业界更为推崇“用户可用性测试”。 在可执行层面来说,部分主要功能的可用性测试,整体使用流程的可用性测试,还有在线调查的方式都可以在设计前期取得相当的数据依据。在产品上线后再辅以数据分析,进行产品的调整。
如何理解“我们”设计的平台 产品人员是否真的“懂”我们要设计的平台。对一个有交互氛围的产品平台进行设计把握,一定要真的懂得用户是如何使用类似的平台,用户如何使用我们的平台。这需要产品人员能充分的体验用户使用这些平台的感受,更要能预测出用户即将产生的需求。产品人员一定要大量的使用这些平台,要让自己先成为一个足够深度的“玩家”。 Colors Reference [Transshipment]source url:http://www.smashingmagazine.com/category/color
Sometimes we just don’t know what color to use. Sometimes we have no idea which colors to combine in order to create a beautiful color palette which would attract the visitors of our web-sites. That’s why we’ve decided to create some kind of visual reference cards or cheat sheets for the most popular colors of Web 2.0. Green, Purple, Black, White and other colors will be reviewed and analyzed in the next articles. Today’s Color is green. You can download it from our web-site. Please don’t refer to the image in your blog posts, but to this article. We’ve invested a lot of time creating it. So if you’d like to use it, at least appreciate our work. Please.
July 25 再见了Embed,一些媒体播放器的符合web标准的代码[转]再见了Embed,一些媒体播放器的符合web标准的代码
由于Embed标签是Netscape的私有财产,故一直未被W3C认可,对于各种媒体文件使用Embed标签是非标准的,如何改变?Elizabeth Castro的 Bye Bye Embed 一文对于各种媒体播放器给出了很好的符合web标准的代码。
在线媒体播放--Google Video and YouTube
<object type="application/x-shockwave-flash" data="http://video.google.com/googleplayer.swf? » 8755581808731033658" width="400" height="326" id="VideoPlayback"> <param name="movie" value="http://video.google.com/googleplayer.swf? » docId=8755581808731033658" /> <param name="allowScriptAcess" value="sameDomain" /> <param name="quality" value="best" /> <param name="bgcolor" value="#FFFFFF" /> <param name="scale" value="noScale" /> <param name="salign" value="TL" /> <param name="FlashVars" value="playerMode=embedded" /> </object> 其实就是FLASH文件的调用
Windows Media Player 文件
<object type="video/x-ms-wmv" data="http://www.sarahsnotecards.com/catalunyalive/ » fishstore.wmv" width="320" height="260"> <param name="src" value="http://www.sarahsnotecards.com/catalunyalive/ » fishstore.wmv" /> <param name="autostart" value="true" /> <param name="controller" value="true" /> </object> 上面的代码没有Windows Media Player特有的classid,作者在IE5.5, IE6, IE7, Opera Win/Mac, Firefox Win/Mac, Safari下测试通过。
QuickTime movies 没有 embed 标签
<object classid="clsid:02BF25D5-8C17-4B23-BC80- » D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="320" height="260"> <param name="src" value="http://www.sarahsnotecards.com/catalunyalive/ » diables.mov" /> <param name="controller" value="true" /> <param name="autoplay" value="false" /> <!--[if !IE]>--> <object type="video/quicktime" data="http://www.sarahsnotecards.com/catalunyalive/ » diables.mov" width="320" height="260"> <param name="autoplay" value="false" /> <param name="controller" value="true" /> </object> <!--<![endif]--> </object> 出处:蓝色理想
--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "web 技术研究与应用" group. To post to this group, send email to webbase@googlegroups.com To unsubscribe from this group, send email to webbase-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/webbase -~----------~----~----~----~------~----~------~--~---
July 21 用ASP.NET上传图片并生成带版权信息的缩略图<%@ Page Language="C#" ResponseEncoding="gb2312" %> <%@ import Namespace="System" %> <%@ import Namespace="System.IO" %> <%@ import Namespace="System.Drawing" %> <%@ import Namespace="System.Drawing.Imaging" %> <script runat="server"> void Page_Load(Object sender, EventArgs e) { if(!Page.IsPostBack) { ImgPreview.Visible=false; } } void GetThumbnailImage(int width,int height,string strInfo,int left,int right) { string file="Uploads/"+uploadFile.PostedFile.FileName.Substring(uploadFile.PostedFile.FileName.LastIndexOf('\\')+1); string newfile="Uploads/"+uploadFile.PostedFile.FileName.Substring(uploadFile.PostedFile.FileName.LastIndexOf('\\')+1)+".jpg"; string strAdd=strInfo; System.Drawing.Image oldimage = System.Drawing.Image.FromFile(Server.MapPath(file)); System.Drawing.Image thumbnailImage = oldimage.GetThumbnailImage(width, height,new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero); Response.Clear(); Bitmap output=new Bitmap(thumbnailImage); Graphics g=Graphics.FromImage(output); g.DrawString(strAdd,new Font("Courier New", 14),new SolidBrush(Color.Red),left,right); output.Save(Server.MapPath(newfile),System.Drawing.Imaging.ImageFormat.Jpeg); Response.ContentType = "image/gif"; ImgPreview.Visible=true; ImgPreview.ImageUrl=newfile; } bool ThumbnailCallback() { return true; } void Button_Click(object sender, EventArgs e) { int width,height,left,right; string strAddInfo=txtAddInfo.Text; width=Int32.Parse(txtWidth.Text); height=Int32.Parse(txtHeight.Text); left=Int32.Parse(txtLeft.Text); right=Int32.Parse(txtRight.Text); if(!(uploadFile.PostedFile.ContentLength>0)) { lblErrInfo.Text="没有选择文件"; } else { string path = Server.MapPath("./Uploads/"+uploadFile.PostedFile.FileName.Substring(uploadFile.PostedFile.FileName.LastIndexOf('\\')+1)); if(File.Exists(path)) { lblErrInfo.Text="已经有同名文件"; } else { uploadFile.PostedFile.SaveAs(path); GetThumbnailImage(width,height,strAddInfo,left,right); } } } </script> <html> <head> </head> <body> <form method="post" enctype="multipart/form-data" runat="server"> <p> <input id="uploadFile" type="file" runat="server" /> <asp:Label id="lblErrInfo" runat="server" forecolor="Red"></asp:Label> </p> <p> width:<asp:TextBox id="txtWidth" runat="server" Width="40px">100</asp:TextBox> height:<asp:TextBox id="txtHeight" runat="server" Width="40px">150</asp:TextBox> </p> <p> 添加信息:<asp:TextBox id="txtAddInfo" runat="server">AspxBoy.Com</asp:TextBox> </p> <p> 信息位置:left:<asp:TextBox id="txtLeft" runat="server" Width="40px">10</asp:TextBox> right:<asp:TextBox id="txtRight" runat="server" Width="40px">135</asp:TextBox> </p> <p> <input id="button" type="button" value="上传生成缩略图" onServerClick="Button_Click" runat="server" /> </p> <p><asp:Image id="ImgPreview" runat="server"></asp:Image> </p> <!-- Insert content here --> </form> </body> </html> July 18 MSN无法登陆(登录)的解决方法[转]不知道怎么回事,最近一段时间MSN登陆非常困难,必须尝试多次才有可能成功。一个偶然的机会,发现下面的方法可以快速登陆。
MSN无法登录的几种可能原因和解决方法: 1、最有可能的原因: 系统时间错误 返回信息:80048820,总是说防火墙设置阻止MSN的连接。但在MSN的网络连接测试中都是成功。 解决方法:系统日期不对造成的!!!!,请你认真查看是否在你升级到MSN7.5以后,系统日期变成了2004年,如果是直接将系统日期改成现在的时间。 点击右下角系统时间设置为当前正确时间。OK!
2、原因不明:系统为MSN 7.5 解决方法:打开“Internet Explorer”,点击“工具”里的“Internet选项”,选“高级”,点击“还原默认设置”,再点击“应用”,最后“确定”,一切搞定,就这么简单 3、原因不明: 解决方法:当登陆MSN返回“重试”,“取消”和“帮助”三个选项时,先选择“帮助”,再选择“重试”,这样很快就登陆成功了。 这种方法是某网友WINDOWS 2000,ADSL上网,安装了FW。 4、80048820 错误 故障现象:80048820 错误,用MSN连接检测一下说端口有问题,检查时间是正确的 解决方法:把INTERNET 选项里的 检查服务器证书吊销状态的勾去掉就可以了。 谢谢,我的也是报的这样的错,用这个方法成功了 5、由于病毒防火墙引起 解决方法:如果用的是norton病毒防火墙,在Norton个人防火墙设置中,将程序列表中有MSN MESSAGE程序,左击中间下拉菜单,将其改为全部允许. 6、封包长度不对
故障现象:80048820
供参考: 网友提供的其他一些解决方法:
请按照所列顺序尝试以下解决方法: 2. 确认MSN Messenger是否被防火墙所阻止。请移至http://webmessenger.msn.com/ 登录Web Messenger。点击“启动MSN Web Messenger”确认您是否可以登录。如果可以,那么MSN Messenger有可能被防火墙所阻止。如果您的计算机运行的是第三方(非 Microsoft)软件或防火墙软件(例如,Zone Alarm,Norton网络安全专家,或McAfee),请确保该软件配置为允许 Messenger 运行,然后再次尝试登录 MSN Messenger。请移至http://messenger.msn.com/help/issues.aspx 参阅相关信息。 3. 通过执行下列操作调整 Internet Explorer 中的代理服务器设置: 4. 请按如下步骤在MSN Messenger中清除代理服务器设置: -MSN Messenger6.2 -MSN Messenger7.0 -MSN Messenger7.5 5. 调整 Microsoft Internet Explorer 安全设置: 注意 在成功执行每个命令后,您都会收到“DllRegisterServer succeeded.”消息。请在收到此消息后再执行下一条命令。 - Microsoft Windows XP 和 Microsoft Windows 2000: - Microsoft Windows Millennium Edition (Me) 和 Microsoft Windows 98: f. 如果您使用的是 Windows XP,请清除安全套接字层 (SSL) 状态和自动完成历史记录: 6. 双击屏幕右下角的时区验证您的计算机的日期和时间设置正确无误。 7. 请再次尝试登录MSN Messenger 8. 如果您正在运行反病毒程序,请先关闭,看是否能登录MSN Messenger。如果可以,请联系您的软件制造厂商或查看相关文件如何配置解决此冲突。 9. 如果您收到“无效的用户名或密码”或“81000303”错误信息,请确保您使用的是正确的用户名和密码。确认您可以使用此帐户登录任何站点,请移至 http://www.passport.com 点击“登录”,如果您可以成功登录,您会看见“登出”按钮。如果失败,请更改您的密码,您可以到http: //memberservices.passport.net/default.srf/ 。 如果此方法有效,尝试再次登录MSN Messenger,请按如下步骤: -MSN Messenger7.0或更早的版本 -MSN Messenger7.5 10. 如果您仍然无法登录MSN Messenger, .NET Messenger服务可能临时不可用。请等待几分钟后再尝试登录。或者移至visit http://messenger.msn.com/status.aspx 查看服务器状态。 再试试 @ECHO OFF May 09 动态添加和删除元素a.html 最后访问的效果demo页
<style>
.header{height:20px;background:#eee;} .ct{margin:4px 0 0 4px;} div,ul,li,form{margin:0;padding:0;} body{font-size:12px;font-family:'Arial';} .expItem{width:400px;border:1px solid #999;} .expItem .header{width:400px;} .expItem .header span{position:relative;top:2px;} .expItem textarea{width:300px;height:80px;} </style> <script language="javascript"> var exp=""; var timer=""; var expc=0; function d(url){ var b=document.createElement("script"); b.type="text/javascript"; b.src=url; document.body.appendChild(b); } function ad(ct,id){ var d=document.createElement("div"); d.id=id; d.innerHTML=ct; document.getElementById("mb").appendChild(d); //document.body.appendChild(d); } function add(it){ var url="add.php?it="+it; if(exp==""){ d(url); try{ exp=ct; clearInterval(timer); timer=""; }catch(e){ if(timer==""){ timer=setInterval("add('"+it+"')",200); } return; } } ad(exp,"exp"+expc); expc++; } function del(id){ var obj=document.getElementById("exp"+id); document.getElementById("mb").removeChild(obj); //document.body.removeChild(document.body.lastChild); } </script> <body> <a href="javascript:add('exp.html');">addexp</a> <a href="javascript:del(0);">del</a> dasfasdfasdf <div id="mb"> </div> sdfsladkjflskdfj sdfasdfs sdfsdf </body> exp.html 动态现实的内容的页面载体
<div class="expItem"><form action="" method="post"><ul class="header"> <span>工作经验</span></ul><ul><div class="ct">公司:<input type="text" name="company"/><br/>职位:<input type="text" name="postion"/><br/>职责:<textarea></textarea><br/></div></ul></form></div>
add.php 动态加载内容的后台脚本
<? function getItem($url){ if(!$url)return null; $rel=null; $fp=fopen($url,"r"); $rel=fread($fp,filesize($url)); fclose($fp); return $rel; } $it=$_GET["it"]; ?> var ct='<?=getItem($it)?>'; April 28 一些奇怪的 unix 指令名字的由来(转)一些奇怪的 unix 指令名字的由来
awk = "Aho Weinberger and Kernighan" 这个语言以作者 Al Aho, Peter Weinberger 和 Brian Kernighan 的 姓来命名。 grep = "Global Regular Expression Print" grep 来自 ed 的列印所有符合某 pattern 指令 g/re/p "re" 代表 regular expression fgrep = "Fixed GREP". fgrep □找固定的字串。"f" 不是代表 "fast" - 事实上, "fgrep foobar *.c" 通常比 "egrep foobar *.c" 来得慢(有点意外吧, 不信 的话, 自己试试喽)。 尽管如此,Fgrep 仍然有可取之处,在档案中搜寻字串的时候,Fgrep 能处理的字串数目较 egrep 多。 egrep = "Extended GREP" egrep 用比 grep 更 fancy 的 regular rexpression。许多人始终只 用 egrep,因为它用的 algorithm 比 grep 或 fgrep 用的高级,而 且通常是三个程式中最快的。 cat = "CATenate" catenate 是一个艰深难懂的单字,意思是"把它连成一串", 这就是 "cat" 这个指令对一个或多个档案所做的处理。 请不要跟 C/A/T 混淆了,C/A/T 是指电脑辅助排版系统(Computer Aided Typesetter)。 gecos = "General Electric Comprehensive Operating Supervisor" 不过,当通用电器 (GE) 的大型系统部门卖给 Honeywell 的时候, Honeywell 就把 GECOS 的 E 拿掉了。 目前 Unix 的密码档里面仍保有 "pw_gecos" 这个栏位。这个名字是 从古早的年代沿用过来的。 Dennis Ritchie 曾经说过: "有时候我们会把印表输出或整批工作丢到 GCOS 机器。密码档 里面的 gcos 栏位是用来隐藏 $IDENT 卡片上的资讯,这样做不 够优雅"。 nroff = "New ROFF" troff = "Typesetter new ROFF" 这些字都是从"roff"衍生的, roff 是重写 Multics 上的 runoff 程式得来 的 (runoff 的意思就是"印出文件")。 tee = T 这是管线工人的术语,代表 T 型的管线分叉器。 bss = "Block Started by Symbol" (由符号启始的区块) Dennis Ritchie 曾说过: 这个缩写也许有其他说法,但事实上我们采用这个缩写的本意是 "Block Started by Symbol"。它是 FAP 上的虚拟指令,FAP (Fortran Assembly [-er?] Program) 是指 IBM 704-709-7090-7094 这种机型的组译器。这个指令可定义自己的标号,并且预留一定数目 的字组空间。还有另一个虚拟指令 BES,是 "Block Ended by Symbol",跟 BSS 指令几乎一样,不同点在于标号是定义在预留字组 空间尾端的位址 + 1 的地方。在这些机器上,Fortran 的阵列是以反 方向储存,而且阵列的索引是从 1 算起。 这种用法是合理的,因为这跟 UNIX 上标准的程式载入器一样,程式 码当中并非真的放入这一整块预留空间,而是先用一个数目表示,在 载入时才真的把所需的预留空间定出来。 biff = "BIFF" 这个指令是用来设定当您有新邮件进来时,是否要通知您。这是柏克 莱大学校园内一只狗的名字。 我可以确定这个名称的起源,如果您有兴趣的话,Biff 是 Heidi Stettner 养的宠物,想当年 Heidi (还有我,跟 Bill Joy) 都还是 UCB 的研究生时,早期的 BSD 版本还在发展中。Biff 受到流连于 Evans Halls 这些人的喜爱,也因为它会对前来的邮差吠叫而闻名;因 此就以 biff 当作指令的名称。 (这是卡内基美浓大学的 Eric Cooper 证实的) rc (像是 ".cshrc" 或 "/etc/rc" 中的 rc 这两个字母) = "RunCom" "rc" 是取自 "runcom", 来自麻省理工学院在 1965 年发展的 CTSS 系统。相关文献曾记载这一段话: '具有从档案中取出一系列命令来执 行的功能;这称为 "run commands" 又称为 "runcom",而这种档案又 称为一个 runcom (a runcom)。' Brian Kernighan 与 Dennis Ritchie 告诉 Vicki Brown 说: "rc" 也 是Plan 9 作业系统 shell 的名字。 Perl = "Practical Extraction and Report Language" Perl = "Pathologically Eclectic Rubbish Lister" Perl是 Larry Wall 所发展的一种相当受欢迎的语言, Perl 在处文字, process,与档案时非常便利,可以说是兼得 shell 与 C 之长。想知道 更多关于Perl 的讯息,请看 Usenet newsgroup comp.lang.perl。 Don Libes 的 "Life with Unix" 一书里有更多这类的珍闻轶事。 April 27 windows下清除零时文件的程序@echo off echo 正在清除系统垃圾文件,请稍等...... del /f /s /q %systemdrive%\*.tmp del /f /s /q %systemdrive%\*._mp del /f /s /q %systemdrive%\*.log del /f /s /q %systemdrive%\*.gid del /f /s /q %systemdrive%\*.chk del /f /s /q %systemdrive%\*.old del /f /s /q %systemdrive%\recycled\*.* del /f /s /q %windir%\*.bak del /f /s /q %windir%\prefetch\*.* rd /s /q %windir%\temp & md %windir%\temp del /f /q %userprofile%\cookies\*.* del /f /q %userprofile%\recent\*.* del /f /s /q "%userprofile%\Local Settings\Temporary Internet Files\*.*" del /f /s /q "%userprofile%\Local Settings\Temp\*.*" del /f /s /q "%userprofile%\recent\*.*" echo 清除系统LJ完成! echo. & pause February 23 所谓博客 坦白说我也不知道博客到底是什么。不过听说是博客的精神是自由和分享。如果抛开了这个精神层面的东西,似乎博客就是某个特定的样式,有日志、相册、档案文件。只要有这些东西就叫博客了。好像中国的博客也都是从外国抄过来的。抄到最后大家都只能通过千篇一律的外观或者功能来鉴别或者标榜自己是个什么东西,是SNS、Blog等等。SNS的精神也许是真正做到社会网络服务,而不是好友和发信息的功能。
我也曾在国内某知名IT公司工作过,当时我了解的一些部门对产品的概念都是抄袭。小公司为了避免风险和走太多弯路,抄袭大公司的产品如果还有情可原的话。中国的所谓门户却也一味的抄袭韩国、美国甚至在行业内互相抄来抄去,让我觉得工作非常枯燥而且可悲。大家的都省略了思考和创造的过程,直接做了一个合格的产品工人。
产品的同质现象严重不知道是否也说明的社会的进步,就好像可口可乐和百事可乐,好像麦当劳和肯得基。尽管他们看起来好像都是一样的东西,各方却整天挣扎着去做创新。如果产品方面实在无可修饰了,那么就比比其他。中国的网络产品也是,同质化很严重,可是我却不以为是产品到了无可修饰的地部。
中国一些博客网火了,新浪就出博客,搜狐就一定也要做博客。新浪出博客因为人家有明星,搜狐也有明星,所以搜狐也出博客了。大家最后都知道两个门户在比着拉人,谁争取了更多明星,谁就争取了更多眼球。博客就是一个名人在个页面里贴一些感怀,照片,好像更像是宣传海报。
从我周围一些做产品设计的朋友里也大概了解到,中国目前还不需要产品设计。只是需要廉价能加班的工人。因为国外的创意每年都层出不穷,够我们一直抄下去。。。 February 14 Ajax & PHP without using the XmlHttpRequest Object(转)看到一篇介绍类Ajax技术的,但是不需要xmlhttprequest对象的,大受启发。
贴下来收藏。
A PHP file which looks something like this:
<?php
$html = '<b>This content came from our Ajax Engine</b>'; ?> div = document.getElementById('contentdiv'); When this file is used referenced in a script tag, it will try to set the innerHTML of a div with ID 'contentdiv'. But there's one problem; this file shouldn't be included when the page loads, but only when a button is clicked or some other action. To do this, we must somehow dynamically add a new script tag, which is possible using JavaScript. Something like the following would do the trick: // Get base url url = document.location.href; xend = url.lastIndexOf("/") + 1; var base_url = url.substring(0, xend); function ajax_do (url) { // Create new JS element // Append JS element (therefore executing the 'AJAX' call) It then creates a new script element, using the createElement() function. After that it sets the src attribute of the script element, and adds the script element to the body, effectively 'loading' the file that is referenced by the script element. All we need now is a simple page that triggers the Ajax call, i.e. <html> <head> <title>Demo 1 - The Basic's</title> <script type="text/javascript" src="engine.js"></script> <body> </div> <input type="button" onclick="ajax_do ('page1.php');" value="Get content" />
January 04 基于Java的全文索引引擎Lucene简介(转)在应用中加入全文检索功能
——基于Java的全文索引引擎Lucene简介 作者: 车东 Email: chedongATbigfoot.com/chedongATchedong.com 写于:2002/08 最后更新: 03/16/2005 16:27:52 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明 关键词:Lucene java full-text search engine Chinese word segment 内容摘要: Lucene是一个基于Java的全文索引工具包。
Lucene不是一个完整的全文索引应用,而是是一个用Java写的全文索引引擎工具包,它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。 Lucene的作者:Lucene的贡献者Doug Cutting是一位资深全文索引/检索专家,曾经是V-Twin搜索引擎(Apple的Copland操作系统的成就之一)的主要开发者,后在Excite担任高级系统架构设计师,目前从事于一些INTERNET底层架构的研究。他贡献出的Lucene的目标是为各种中小型应用程序加入全文检索功能。 Lucene的发展历程:早先发布在作者自己的www.lucene.com,后来发布在SourceForge,2001年年底成为APACHE基金会jakarta的一个子项目:http://jakarta.apache.org/lucene/ 已经有很多Java项目都使用了Lucene作为其后台的全文索引引擎,比较著名的有:
对于中文用户来说,最关心的问题是其是否支持中文的全文检索。但通过后面对于Lucene的结构的介绍,你会了解到由于Lucene良好架构设计,对中文的支持只需对其语言词法分析接口进行扩展就能实现对中文检索的支持。 Lucene的API接口设计的比较通用,输入输出结构都很像数据库的表==>记录==>字段,所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构/接口中。总体上看:可以先把Lucene当成一个支持全文索引的数据库系统。 比较一下Lucene和数据库:
全文检索 ≠ like "%keyword%" 通常比较厚的书籍后面常常附关键词索引表(比如:北京:12, 34页,上海:3,77页……),它能够帮助读者比较快地找到相关内容的页码。而数据库索引能够大大提高查询的速度原理也是一样,想像一下通过书后面的索引查找的速度要比一页一页地翻内容高多少倍……而索引之所以效率高,另外一个原因是它是排好序的。对于检索系统来说核心是一个排序问题。 由于数据库索引不是为全文索引设计的,因此,使用like "%keyword%"时,数据库索引是不起作用的,在使用like查询时,搜索过程又变成类似于一页页翻书的遍历过程了,所以对于含有模糊查询的数据库服务来说,LIKE对性能的危害是极大的。如果是需要对多个关键词进行模糊匹配:like"%keyword1%" and like "%keyword2%" ...其效率也就可想而知了。 所以建立一个高效检索系统的关键是建立一个类似于科技索引一样的反向索引机制,将数据源(比如多篇文章)排序顺序存储的同时,有另外一个排好序的关键词列表,用于存储关键词==>文章映射关系,利用这样的映射关系索引:[关键词==>出现关键词的文章编号,出现次数(甚至包括位置:起始偏移量,结束偏移量),出现频率],检索过程就是把模糊查询变成多个可以利用索引的精确查询的逻辑组合的过程。从而大大提高了多关键词查询的效率,所以,全文检索问题归结到最后是一个排序问题。 由此可以看出模糊查询相对数据库的精确查询是一个非常不确定的问题,这也是大部分数据库对全文检索支持有限的原因。Lucene最核心的特征是通过特殊的索引结构实现了传统数据库不擅长的全文索引机制,并提供了扩展接口,以方便针对不同应用的定制。 可以通过一下表格对比一下数据库的模糊查询:
全文检索和数据库应用最大的不同在于:让最相关的头100条结果满足98%以上用户的需求 大部分的搜索(数据库)引擎都是用B树结构来维护索引,索引的更新会导致大量的IO操作,Lucene在实现中,对此稍微有所改进:不是维护一个索引文件,而是在扩展索引的时候不断创建新的索引文件,然后定期的把这些新的小索引文件合并到原先的大索引中(针对不同的更新策略,批次的大小可以调整),这样在不影响检索的效率的前提下,提高了索引的效率。 Lucene和其他一些全文检索系统/应用的比较:
对于中文来说,全文索引首先还要解决一个语言分析的问题,对于英文来说,语句中单词之间是天然通过空格分开的,但亚洲语言的中日韩文语句中的字是一个字挨一个,所有,首先要把语句中按“词”进行索引的话,这个词如何切分出来就是一个很大的问题。 首先,肯定不能用单个字符作(si-gram)为索引单元,否则查“上海”时,不能让含有“海上”也匹配。 但一句话:“北京天安门”,计算机如何按照中文的语言习惯进行切分呢? 另外一个解决的办法是采用自动切分算法:将单词按照2元语法(bigram)方式切分出来,比如: 这样,在查询的时候,无论是查询"北京" 还是查询"天安门",将查询词组按同样的规则进行切分:"北京","天安安门",多个关键词之间按与"and"的关系组合,同样能够正确地映射到相应的索引中。这种方式对于其他亚洲语言:韩文,日文都是通用的。 基于自动切分的最大优点是没有词表维护成本,实现简单,缺点是索引效率低,但对于中小型应用来说,基于2元语法的切分还是够用的。基于2元切分后的索引一般大小和源文件差不多,而对于英文,索引文件一般只有原文件的30%-40%不同,
目前比较大的搜索引擎的语言分析算法一般是基于以上2个机制的结合。关于中文的语言分析算法,大家可以在Google查关键词"wordsegment search"能找到更多相关的资料。 下载:http://jakarta.apache.org/lucene/ 注意:Lucene中的一些比较复杂的词法分析是用JavaCC生成的(JavaCC:JavaCompilerCompiler,纯Java的词法分析生成器),所以如果从源代码编译或需要修改其中的QueryParser、定制自己的词法分析器,还需要从https://javacc.dev.java.net/下载javacc。 lucene的组成结构:对于外部应用来说索引模块(index)和检索模块(search)是主要的外部应用入口
简单的例子演示一下Lucene的使用方法: 索引过程:从命令行读取文件名(多个),将文件分路径(path字段)和内容(body字段)2个字段进行存储,并对内容进行全文索引:索引的单位是Document对象,每个Document对象包含多个字段Field对象,针对不同的字段属性和数据输出的需求,对字段还可以选择不同的索引/存储字段规则,列表如下:
public class IndexFiles {
索引过程中可以看到:
检索过程和结果显示: 搜索结果返回的是Hits对象,可以通过它再访问Document==>Field中的内容。 假设根据body字段进行全文检索,可以将查询结果的path字段和相应查询的匹配度(score)打印出来, public class Search { 在整个检索过程中,语言分析器,查询分析器,甚至搜索器(Searcher)都是提供了抽象的接口,可以根据需要进行定制。
简化的查询分析器 个人感觉lucene成为JAKARTA项目后,画在了太多的时间用于调试日趋复杂QueryParser,而其中大部分是大多数用户并不很熟悉的,目前LUCENE支持的语法: Query ::= ( Clause )* 中间的逻辑包括:and or + - &&||等符号,而且还有"短语查询"和针对西文的前缀/模糊查询等,个人感觉对于一般应用来说,这些功能有一些华而不实,其实能够实现目前类似于Google的查询语句分析功能其实对于大多数用户来说已经够了。所以,Lucene早期版本的QueryParser仍是比较好的选择。 添加修改删除指定记录(Document) Lucene提供了索引的扩展机制,因此索引的动态扩展应该是没有问题的,而指定记录的修改也似乎只能通过记录的删除,然后重新加入实现。如何删除指定的记录呢?删除的方法也很简单,只是需要在索引时根据数据源中的记录ID专门另建索引,然后利用IndexReader.delete(Termterm)方法通过这个记录ID删除相应的Document。 根据某个字段值的排序功能 lucene缺省是按照自己的相关度算法(score)进行结果排序的,但能够根据其他字段进行结果排序是一个在LUCENE的开发邮件列表中经常提到的问题,很多原先基于数据库应用都需要除了基于匹配度(score)以外的排序功能。而从全文检索的原理我们可以了解到,任何不基于索引的搜索过程效率都会导致效率非常的低,如果基于其他字段的排序需要在搜索过程中访问存储字段,速度回大大降低,因此非常是不可取的。 但这里也有一个折中的解决方法:在搜索过程中能够影响排序结果的只有索引中已经存储的docID和score这2个参数,所以,基于score以外的排序,其实可以通过将数据源预先排好序,然后根据docID进行排序来实现。这样就避免了在LUCENE搜索结果外对结果再次进行排序和在搜索过程中访问不在索引中的某个字段值。 这里需要修改的是IndexSearcher中的HitCollector过程: ... 更通用的输入输出接口 虽然lucene没有定义一个确定的输入文档格式,但越来越多的人想到使用一个标准的中间格式作为Lucene的数据导入接口,然后其他数据,比如PDF只需要通过解析器转换成标准的中间格式就可以进行数据索引了。这个中间格式主要以XML为主,类似实现已经不下4,5个: 数据源: WORD PDF HTML DB other 目前还没有针对MSWord文档的解析器,因为Word文档和基于ASCII的RTF文档不同,需要使用COM对象机制解析。这个是我在Google上查的相关资料:http://www.intrinsyc.com/products/enterprise_applications.asp
索引一般分2种情况,一种是小批量的索引扩展,一种是大批量的索引重建。在索引过程中,并不是每次新的DOC加入进去索引都重新进行一次索引文件的写入操作(文件I/O是一件非常消耗资源的事情)。 Lucene先在内存中进行索引操作,并根据一定的批量进行文件的写入。这个批次的间隔越大,文件的写入次数越少,但占用内存会很多。反之占用内存少,但文件IO操作频繁,索引速度会很慢。在IndexWriter中有一个MERGE_FACTOR参数可以帮助你在构造索引器后根据应用环境的情况充分利用内存减少文件的操作。根据我的使用经验:缺省Indexer是每20条记录索引后写入一次,每将MERGE_FACTOR增加50倍,索引速度可以提高1倍左右。 搜索过程优化 lucene支持内存索引:这样的搜索比基于文件的I/O有数量级的速度提升。
Lucene面向全文检索的优化在于首次索引检索后,并不把所有的记录(Document)具体内容读取出来,而起只将所有结果中匹配度最高的头100条结果(TopDocs)的ID放到结果集缓存中并返回,这里可以比较一下数据库检索:如果是一个10,000条的数据库检索结果集,数据库是一定要把所有记录内容都取得以后再开始返回给应用结果集的。所以即使检索匹配总数很多,Lucene的结果集占用的内存空间也不会很多。对于一般的模糊检索应用是用不到这么多的结果的,头100条已经可以满足90%以上的检索需求。 如果首批缓存结果数用完后还要读取更后面的结果时Searcher会再次检索并生成一个上次的搜索缓存数大1倍的缓存,并再重新向后抓取。所以如果构造一个Searcher去查1-120条结果,Searcher其实是进行了2次搜索过程:头100条取完后,缓存结果用完,Searcher重新检索再构造一个200条的结果缓存,依此类推,400条缓存,800条缓存。由于每次Searcher对象消失后,这些缓存也访问那不到了,你有可能想将结果记录缓存下来,缓存数尽量保证在100以下以充分利用首次的结果缓存,不让Lucene浪费多次检索,而且可以分级进行结果缓存。 Lucene的另外一个特点是在收集结果的过程中将匹配度低的结果自动过滤掉了。这也是和数据库应用需要将搜索的结果全部返回不同之处。
Luene的确是一个面对对象设计的典范
这些优点都是非常值得在以后的开发中学习借鉴的。作为一个通用工具包,Lunece的确给予了需要将全文检索功能嵌入到应用中的开发者很多的便利。 此外,通过对Lucene的学习和使用,我也更深刻地理解了为什么很多数据库优化设计中要求,比如:
参考资料: Apache: Lucene Project The Lucene search engine: Powerful, flexible, and free Lucene Tutorial Notes on distributed searching with Lucene 中文语言的切分词 搜索引擎工具介绍 Lucene作者Cutting的几篇论文和专利 Lucene的.NET实现:dotLucene Lucene作者Cutting的另外一个项目:基于Java的搜索引擎Nutch 关于基于词表和N-Gram的切分词比较 特别感谢: December 28 中文排版CSS心得(转)数月来学习web标准,并遵循标准设计和制作web页面。一直想写点什么,整理一下自己的心得体会。写这篇文章,主要是针对中文排版设计,英文排版因为很少做,所以不涉及。 先介绍如何设定字体、颜色、大小、段落空白等比较简单的应用,后面再介绍下比如首字下沉、首行缩进。最后讲一些常用的web页面中文排版,比如中文字的截断、固定宽度词内折行(word-wrap和word-break)等等。因为只是写一些应用方面的心得,如果需要完整的CSS属性介绍,请参考CSS手册。 1、如何设定文字字体、颜色、大小 —— 使用font font-style设定斜体,比如font-style: italic; 以上都可以写在一行font属性里(除了color属性需要单独写): 2、如何控制段落排版 —— 使用margin,text-align 中文段落使用<p>标签,左右(相当于缩进)、段前段后的空白,都可以用margin。比如: PS.谈起margin,我习惯于在写CSS的时候为所有的标签定义margin: 0; 因为时而出现由于默认的margin值导致页面排版问题,而自己找不到原因(特别注意的是ul/ol/p/dt/dd等标签) 3、竖排文字 —— 使用writing-mode writing-mode属性有两个值lr-tb和tb-rl,前者是默认的左-右、上-下,后者是上-下、右-左。 4、项目符号的问题 —— 使用list-style 在CSS里项目符号有disc(实心圆点)、circle(空心圆圈)、square(实心方块)、decimal(阿拉伯数字)、lower-roman(小写罗马数字)、upper-roman(大写罗马数字)、lower-alpha(小写英文字母)、upper-alpha(大写英文字母)、none(无)。比如设定一个列表(ul或ol)的项目符号为方块,如: 5、首字下沉 —— 使用:first-letter 伪对象:first-letter配合font-size、float可以制作首字下沉效果。 6、首行缩进 —— 使用text-indent text-indent可以使得容器内首行缩进一定单位。比如中文段落一般每段前空两个汉字。可以这么写: 7、关于汉字注音 —— 使用ruby标签和ruby-align属性 比如说<ruby>注音<rt style="font-size: 11px;">zhu yin</rt></ruby>,可以利用ruby-align设置对齐方式。这是在CSS手册里面看到的,具体可以自行查阅ruby-align项。 8、固定宽度汉字截断 —— 使用text-overflow 用后台语言可以对从数据库里的字段内容做截断处理,比如说截12个汉字(之后用省略号)。但是有时还需要html标签的过滤等,而用CSS来控制则没有这个问题。比如对列表应用以下样式: 9、固定宽度汉字(词)折行 —— 使用word-break 举个例子,比如说要在一个固定宽度容器里面显示很多地名(假设以空格分隔),为了避免地名中间断开(即一个字在上面而另一个字折断到下一行去了)。则可以使用word-break。比如: CSS的十八般技巧(转)好文一定要收藏。(游泳的鱼按)
最近,经常有朋友问我一些工作中遇到的CSS问题。他们总是不能很好的控制CSS,影响CSS的效率发挥。我来分析总结一下错误所在,帮助大家更加容易使用CSS。 本文总结了我开始使用CSS布局方法以来所有的技巧和兼容方案,我愿意把这些与你分享,我会重点解释一些新手容易犯的错误(包括我自己也犯过的),如果你已经是CSS高手,这些经验技巧可能已经都知道,如果你有更多的,希望可以帮我补充。 一.使用css缩写使用缩写可以帮助减少你CSS文件的大小,更加容易阅读。css缩写的主要规则请参看《常用css缩写语法总结》,这里就不展开描述。 二.明确定义单位,除非值为0忘记定义尺寸的单位是CSS新手普遍的错误。在HTML中你可以只写width="100",但是在CSS中,你必须给一个准确的单位,比如:width:100px width:100em。只有两个例外情况可以不定义单位:行高和0值。除此以外,其他值都必须紧跟单位,注意,不要在数值和单位之间加空格。 三.区分大小写当在XHTML中使用CSS,CSS里定义的元素名称是区分大小写的。为了避免这种错误,我建议所有的定义名称都采用小写。 class和id的值在HTML和XHTML中也是区分大小写的,如果你一定要大小写混合写,请仔细确认你在CSS的定义和XHTML里的标签是一致的。 四.取消class和id前的元素限定当你写给一个元素定义class或者id,你可以省略前面的元素限定,因为ID在一个页面里是唯一的,而clas s可以在页面中多次使用。你限定某个元素毫无意义。例如: div#content { /* declarations */ }
fieldset.details { /* declarations */ } 可以写成 #content { /* declarations */ }
.details { /* declarations */ } 这样可以节省一些字节。 五.默认值通常padding的默认值为0,background-color的默认值是transparent。但是在不同的浏览器默认值可能不同。如果怕有冲突,可以在样式表一开始就先定义所有元素的margin和padding值都为0,象这样: * {
margin:0; padding:0; } 六.不需要重复定义可继承的值CSS中,子元素自动继承父元素的属性值,象颜色、字体等,已经在父元素中定义过的,在子元素中可以直接继承,不需要重复定义。但是要注意,浏览器可能用一些默认值覆盖你的定义。 七.最近优先原则如果对同一个元素的定义有多种,以最接近(最小一级)的定义为最优先,例如有这么一段代码 Update: Lorem ipsum dolor set 在CSS文件中,你已经定义了元素p,又定义了一个class"update" p {
margin:1em 0; font-size:1em; color:#333; } .update { font-weight:bold; color:#600; } 这两个定义中,class="update"将被使用,因为class比p更近。你可以查阅W3C的《 Calculating a selector’s specificity》 了解更多。 八.多重class定义一个标签可以同时定义多个class。例如:我们先定义两个样式,第一个样式背景为#666;第二个样式有10 px的边框。 .one{width:200px;background:#666;}
.two{border:10px solid #F00;} 在页面代码中,我们可以这样调用 <div class="one two"></div>
这样最终的显示效果是这个div既有#666的背景,也有10px的边框。是的,这样做是可以的,你可以尝试一下。 九.使用子选择器(descendant selectors)CSS初学者不知道使用子选择器是影响他们效率的原因之一。子选择器可以帮助你节约大量的class定义。我们来看下面这段代码: <div id="subnav">
<ul> <li class="subnavitem"> <a href="#" class="subnavitem">Item 1</a></li>> <li class="subnavitemselected"> <a href="#" class="subnavitemselected"> Item 1</a> </li> <li class="subnavitem"> <a href="#" class="subnavitem"> Item 1</a> </li> </ul> </div> 这段代码的CSS定义是: div#subnav ul { /* Some styling */ }
div#subnav ul li.subnavitem { /* Some styling */ } div#subnav ul li.subnavitem a.subnavitem { /* Some styling */ } div#subnav ul li.subnavitemselected { /* Some styling */ } div#subnav ul li.subnavitemselected a.subnavitemselected { /* Some styling */ } 你可以用下面的方法替代上面的代码 <ul id="subnav">
<li> <a href="#"> Item 1</a> </li> <li class="sel"> <a href="#"> Item 1</a> </li> <li> <a href="#"> Item 1</a> </li> </ul> 样式定义是: #subnav { /* Some styling */ }
#subnav li { /* Some styling */ } #subnav a { /* Some styling */ } #subnav .sel { /* Some styling */ } #subnav .sel a { /* Some styling */ } 用子选择器可以使你的代码和CSS更加简洁、更加容易阅读。 十.不需要给背景图片路径加引号为了节省字节,我建议不要给背景图片路径加引号,因为引号不是必须的。例如: background:url("images/***.gif") #333;
可以写为 background:url(images/***.gif) #333;
如果你加了引号,反而会引起一些浏览器的错误。 十一.组选择器(Group selectors)当一些元素类型、class或者id都有共同的一些属性,你就可以使用组选择器来避免多次的重复定义。这可以节省不少字节。
例如:定义所有标题的字体、颜色和margin,你可以这样写: h1,h2,h3,h4,h5,h6 {
font-family:"Lucida Grande",Lucida,Arial,Helvetica,sans-serif; color:#333; margin:1em 0; } 如果在使用时,有个别元素需要定义独立样式,你可以再加上新的定义,可以覆盖老的定义,例如: h1 { font-size:2em; }
h2 { font-size:1.6em; } 十二.用正确的顺序指定链接的样式当你用CSS来定义链接的多个状态样式时,要注意它们书写的顺序,正确的顺序是::link :visited :hover :active。抽取第一个字母是"LVHA",你可以记忆成"LoVe HAte"(喜欢讨厌)。为什么这么定义,可以参考Eric Meyer的《Link Specificity》。 如果你的用户需要用键盘来控制,需要知道当前链接的焦点,你还可以定义:focus属性。:focus属性的效果也取决与你书写的位置,如果你希望聚焦元素显示:hover效果,你就把:focus写在:hover前面;如果你希望聚焦效果替代:hover效果,你就把:focus放在:hover后面。 十三.清除浮动一个非常常见的CSS问题,定位使用浮动的时候,下面的层被浮动的层所覆盖,或者层里嵌套的子层超出了外层的范围。 通常的解决办法是在浮动层后面添加一个额外元素,例如一个div或者一个br,并且定义它的样式为clear: both。这个办法有一点牵强,幸运的是还有一个好办法可以解决,参看这篇文章《How To Clear Floats Without Structural Markup》(注:本站将尽快翻译此文)。 上面2种方法可以很好解决浮动超出的问题,但是如果当你真的需要对层或者层里的对象进行clear的时候怎么办?一种简单的方法就是用overflow属性,这个方法最初的发表在《Simple Clearing of Floats》,又在《Clearance》和《Super simple clearing floats》中被广泛讨论。 上面那一种clear方法更适合你,要看具体的情况,这里不再展开论述。另外关于float的应用,一些优秀的文章已经说得很清楚,推荐你阅读:《Floatutorial》、《Containing Floats》和《Float Layouts》 十四.横向居中(centering)这是一个简单的技巧,但是值得再说一遍,因为我看见太多的新手问题都是问这个:CSS如何横向居中?你需要定义元素的宽,并且定义横向的margin,如果你的布局包含在一个层(容器)中,就象这样: 你可以这样定义使它横向居中: #wrap {
width:760px; /* 修改为你的层的宽度 */ margin:0 auto; } 但是IE5/Win不能正确显示这个定义,我们采用一个非常有用的技巧来解决:用text-align属性。就象这样: body {
text-align:center; } #wrap { width:760px; /* 修改为你的层的宽度 */ margin:0 auto; text-align:left; } 第一个body的text-align:center; 规则定义IE5/Win中body的所有元素居中(其他浏览器只是将文字居中) ,第二个text-align:left;是将#warp中的文字居左。 十五.导入(Import)和隐藏CSS因为老版本浏览器不支持CSS,一个通常的做法是使用@import技巧来把CSS隐藏起来。例如: @import url("main.css");
然而,这个方法对IE4不起作用,这让我很是头疼了一阵子。后来我用这样的写法: @import "main.css";
这样就可以在IE4中也隐藏CSS了,呵呵,还节省了5个字节呢。想了解@import语法的详细说明,可以看这里《centricle’s css filter chart》 十六.针对IE的优化有些时候,你需要对IE浏览器的bug定义一些特别的规则,这里有太多的CSS技巧(hacks),我只使用其中的两种方法,不管微软在即将发布的IE7 beta版里是否更好的支持CSS,这两种方法都是最安全的。
另外一种方法,我认为比CSS Hacks更加经得起考验就是采用微软的私有属性条件注释(conditional comments)。用这个方法你可以给IE单独定义一些样式,而不影响主样式表的定义。就象这样: <!--[if IE]><link rel="stylesheet" type="text/css" href="ie.css" /> <![endif]--> 十七.调试技巧:层有多大?当调试CSS发生错误,你就要象排版工人,逐行分析CSS代码。我通常在出问题的层上定义一个背景颜色,这样就能很明显看到层占据多大空间。有些人建议用border,一般情况也是可以的,但问题是,有时候border 会增加元素的尺寸,border-top和boeder-bottom会破坏纵向margin的值,所以使用background更加安全些。 另外一个经常出问题的属性是outline。outline看起来象boeder,但不会影响元素的尺寸或者位置。只有少数浏览器支持outline属性,我所知道的只有Safari、OmniWeb、和Opera。 十八.CSS代码书写样式在写CSS代码的时候,对于缩进、断行、空格,每个人有每个人的书写习惯。在经过不断实践后,我决定采用下面这样的书写样式: selector1,
selector2 { property:value; } 当使用联合定义时,我通常将每个选择器单独写一行,这样方便在CSS文件中找到它们。在最后一个选择器和大括号{之间加一个空格,每个定义也单独写一行,分号直接在属性值后,不要加空格。 我习惯在每个属性值后面都加分号,虽然规则上允许最后一个属性值后面可以不写分号,但是如果你要加新样式时容易忘记补上分号而产生错误,所以还是都加比较好。 最后,关闭的大括号}单独写一行。 空格和换行有助与阅读。 终于寻到了javascript操作xml这部分是代码,其中DataSet是从他人的blog上抄来的。
而那个人也标明是转,无法严明出处,只好不写作者的名字了。
在此说声非常抱歉。
mozzila部分兼容的代码和得到xmldoc还有部分代码是我加的。
让这个东西可以工作起来。
<script language="javascript">
//类的构造,传入xml文档和需要处理的标签名称 function DataSet(xmlFile, tagLabel) { var xmldoc; if(window.ActiveXObject){ xmldoc=new ActiveXObject("Microsoft.XMLDOM"); }else if(document.implementation&&document.implementation.createDocument){ xmldoc=document.implementation.createDocument("","doc",null); } xmldoc.async = false; xmldoc.load(xmlFile); this.rootObj = xmldoc.getElementsByTagName(tagLabel) this.getCount = getCount; this.getData = getData; this.getAttribute = getAttribute; this.getNodeAttribute=getNodeAttribute;
} function getCount(){ return this.rootObj.length } function getData(index, tagName){ if (index >= this.count) return "index overflow" var node = this.rootObj[index] var str = node.getElementsByTagName(tagName)[0].firstChild.data return str } function getAttribute(index, tagName) {
if (index >= this.count) return "index overflow" var node = this.rootObj[index] var str = node.getAttribute(tagName) return str } function getNodeAttribute(index,node,tagName){
if(index>=this.rootObj[index].childNodes.length)return "index overflow"; var str=this.rootObj[index].childNodes[node].getAttribute(tagName); return str; } var set=new DataSet("pubdate.xml","pubdates"); //alert(set.getCount()); alert(set.getAttribute(2,"name")); alert(set.getData(1,"job")); </script> 下面是data.xml,从网上找了个现成的。呵呵。
<?xml version="1.0" encoding="gb2312"?>
<employees> <employee name="Billgates"> <job>Programmer</job> <salary>32768</salary> </employee> <employee name="王涛"> <job>无业游民</job> <salary>70000</salary> </employee> <employee name="Big 中华"> <job>哈尔滨CEO</job> <salary>100000</salary> </employee> </employees> December 27 javascript实现urlencode和urldecode下面是用js实现的urlencode方法,urldecode方法。
urlencode和spell方法是其他大大写的。
urldecode方法是我根据urlencode方法补充的。
这下全套够用啦。嘿嘿。
支持ie和mozzila,firefox,opera。
function UrlEncode(str){
var i,c,ret="",strSpecial="!\"#$%&'()*+,/:;<=>?@[\]^`{|}~%"; for(i=0;i<str.length;i++){ if(str.charCodeAt(i)>=0x4e00){ c=qswhU2GB[str.charCodeAt(i)-0x4e00]; ret+="%"+c.slice(0,2)+"%"+c.slice(-2); }else{ c=str.charAt(i); if(c==" ") ret+="+"; else if(strSpecial.indexOf(c)!=-1) ret+="%"+str.charCodeAt(i).toString(16); else ret+=c; } } return ret; } function UrlDecode(str){
var i,c,d,t,p,ret=""; function findPos(str){ for(var j=0;j<qswhU2GB.length;j++){ if(qswhU2GB[j]==str){return j;} } return -1; } for(i=0;i<str.length;){ c=str.charAt(i);i++; if(c!="%"){ if(c=="+"){ ret+=" "; }else{ ret+=c; } }else{ t=str.substring(i,i+2);i+=2; if(("0x"+t)>0xA0){ d=str.substring(i+1,i+3);i+=3; p=findPos(t+d); if(p!=-1){ ret+=String.fromCharCode(p+0x4e00); } }else{ ret+=String.fromCharCode("0x"+t); } } } return ret; } 竟然说我贴太多了。
对照数组我再贴一个。 December 02 关于CPU(转自和讯)1.主频 18、CPU内部的内存控制器 November 28 js的url编码问题(转自无忧脚本-小虫)编码转换一般用在Microsoft.XMLHTTP传递客户端提交内容
或者XMLdoc .load(xxx.aspx?带有汉字的参数需要转换) 代码测试中,到现在一直运行正常,测试环境Ie5.00 ,Ie6.0 <script language="vbscript">
Function vbChar(thischr) innercode = asc(thischr) If innercode < 0 Then innercode = innercode + &h10000 vbChar=innercode End Function </script> <script language="javascript">
//unicode 转换成Url-gb2312编码 alert(urlencoding("中")); function urlencoding(szInput) { var wch,x,uch="",szRet=""; var strSpecial = "#$%'()*+,/:;<=>?@[\\]^`{|}~%"; //转换特殊的字符&没有包含在里面因为是参数连接符号 for (x=0; x<szInput.length; x++){ wch=vbChar(szInput.charAt(x)); if (!(wch & 0xFF80)){ if (szRet==32)szRet +="+"; else if(strSpecial.indexOf(szInput.charAt(x))>=0) szRet += "%" + wch.toString(16); else szRet += szInput.charAt(x); } else{ uch = "%" + (wch>>8 ).toString(16) + "%" + (wch & 0xFF).toString(16); szRet += uch; } } return(szRet); } </script> 将输入串中的汉字变为UniCode(UTF8),其它字符不变
<script> alert(toUTF8("中")); function toUTF8(szInput){ var wch,x,uch="",szRet=""; for (x=0; x<szInput.length; x++){ wch=szInput.charCodeAt(x); if (!(wch & 0xFF80)){ szRet += szInput.charAt(x); } else if (!(wch & 0xF000)){ uch = "%" + (wch>>6 | 0xC0).toString(16) + "%" + (wch & 0x3F | 0x80).toString(16); szRet += uch; } else{ uch = "%" + (wch >> 12 | 0xE0).toString(16) + "%" + (((wch >> 6) & 0x3F) | 0x80).toString(16) + "%" + (wch & 0x3F | 0x80).toString(16); szRet += uch; } } return(szRet); } </script> November 25 js得到客户端MAC寻觅了一段时间,终于找到这段代码了。
不过还是要调用activeX,在非win的操作系统上还没有测试过。非ie浏览器也没测试过。
不过毕竟还有一个能凑合用着。
^_^
代码如下:
<SCRIPT language=JScript event="OnCompleted(hResult,pErrorObject, pAsyncContext)" for="foo"> document.write (unescape(MACAddr)); </SCRIPT> <SCRIPT language=JScript event="OnObjectReady(objObject,objAsyncContext)" for="foo"> if(objObject.IPEnabled != null && objObject.IPEnabled != "undefined" && objObject.IPEnabled == true && objObject.MACAddress != null && objObject.MACAddress != "undefined")MACAddr = objObject.MACAddress; </SCRIPT> <OBJECT id="locator" classid="CLSID:76A64158-CB41-11D1-8B02-00600806D9B6 VIEWASTEXT"></OBJECT> <OBJECT id="foo" classid="CLSID:75718C9A-F029-11d1-A1AC-00C04FB6C223"></OBJECT> <SCRIPT language=JScript> var service = locator.ConnectServer(); var MACAddr ; var IPAddr ; var DomainAddr; var sDNSName; service.Security_.ImpersonationLevel=3; service.InstancesOfAsync(foo, 'Win32_NetworkAdapterConfiguration'); </SCRIPT> November 20 传说中的AJAX技术在php中的应用以下是ajax在php中的一个实例,任何其他页面脚本用法也相同。
程序很简单,这里就不多做解释了。
前端页面,既始终显示给用户的页面:
<script type="text/javascript" language="javascript">
var http_request = false; function makeRequest(url) { http_request = false; if (window.XMLHttpRequest) { // 非ie浏览器 http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) { http_request.overrideMimeType('text/xml'); } } else if (window.ActiveXObject) { // ie浏览器 try { http_request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { http_request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {} } } if (!http_request) { alert('Giving up :( Cannot create an XMLHTTP instance'); return false; } http_request.onreadystatechange = alertContents; http_request.open('GET', url, true); http_request.send(null); } function alertContents() {
if (http_request.readyState == 4) { if (http_request.status == 200) { content.innerHTML=http_request.responseText; } else { alert('There was a problem with the request.'); } } }
</script> <form name="frmLogin" action="" method="get"> name:<input type="text" name="name"><br> password:<input type="password" name="password"><br> <input type="button" value="ok" onclick="makeRequest('a.php?name='+frmLogin.name.value+'&password='+frmLogin.password.value);"> </form> <div id="content"> </div> 后端页面,也就是上页中所调用的a.php
<?
echo $_GET["name"].$_GET["password"]; ?> 通过http调用前端页面后显示name和password输入框。
输入字符点击ok按钮以后在content层中显示出之前输入的用户名和密码。
而所显示的用户名和密码是通过get方式传递给后端页面,由后端页面打印出来的。
可以通过把上面xmlsocket的方法封装后作为一种普遍的页面级socket调用来使用。
可以把它加在任何想要实现ajax功能的页面元素或者标签上。
在此还想到,一般的表单输入域验证可以通过这样的调用省去前端的js验证部分代码,验证规则可以统一使用动态脚本语言写成的验证类。 November 17 sqlplus命令大全摘录,非本人原创
|
|
|