[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"list-\u002Farticles\u002Fweb\u002F4":3},{"items":4,"total":110},[5,23,32,42,52,61,70,79,89,99],{"id":6,"type":7,"slug":8,"title":9,"date":10,"category":11,"tags":12,"body_markdown":16,"permalink":17,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},157,"article","xheditor_paste_images","xheditor从剪贴板粘贴图片的实现原理","2011-11-30 10:08","web",[13,14,15],"剪贴板","复制","粘贴","\r\n[xheditor](http:\u002F\u002Fxheditor.com\u002F)是一个优秀的国产富文本编辑器，最近的（其实我也不知道有多久了）版本推出了一个粘贴剪贴板图片的功能，很是喜爱，好奇了好久，最终不住去看了下源码，基本明白了。\r\n\r\n> 2016-07-29 似乎这个编辑器也很久没更新了，现在对上面这段话持保留态度，不做推荐。\r\n\r\n首先，这个功能很新，不支持IE系列浏览器……用的是一些新的API。我手上的代码是1.1.10，所以代码行数以这个版本为准。\r\n\r\n一点前置小知识是必备的，那就是对大部分截图软件来说，截图操作是一个把截取的图片转换成指定格式（windows自带的是bmp）然后放入剪贴板的过程。所以，要粘贴图片，核心就是读取剪贴板。\r\n\r\n\u003C!-- more -->\r\n\r\n## 一、读取剪贴板的时机\r\n\r\n近几年浏览器在拼标准、拼性能的时候，其实也在暗里拼安全，为了防止某个网页一打开就自动把你剪贴板的内容传网上去（IE6可以做到），现代浏览器不允许随时读写剪贴板。\r\n\r\n浏览器为我们提供了`onpaste`事件（粘贴），读取剪贴板数据仅能在该事件发生时在事件处理程序中进行。因这里理解就好，所以就不贴代码。\r\n\r\n## 二、图片数据\r\n\r\n之所以IE不能粘贴图片，就在于IE没有处理二进制文件的机制，它只能处理文本。\r\n\r\n在现代浏览器中，则有关于文件的API，这里用到的就是File Reader，主要用来处理二进制文件数据。\r\n\r\n首先，在xheditor的第1922行，有一个`cleanPaste()`函数，它的作用就是读取剪贴板的数据，然后放入编辑器中，具体见代码注释。\r\n\r\n```javascript\r\nvar clipboardData,items,item;\u002F\u002Ffor chrome\r\n\r\n\u002F\u002Fev是事件，其实大家都喜欢用e或者evt或者event\r\n\u002F\u002F这句主要是确定剪贴板中是否有图片\r\nif(ev&&\r\n\t(clipboardData=ev.originalEvent.clipboardData)&&\r\n\t(items=clipboardData.items)&&\r\n\t(item=items[0])&&item.kind=='file'&&item.type.match(\u002F^image\\\u002F\u002Fi)\r\n){\r\n\tvar blob = item.getAsFile(),\t\u002F\u002Fblob就是剪贴板中的二进制图片数据\r\n\t\treader = new FileReader();\r\n\r\n\t\u002F\u002F定义fileReader读取完数据后的回调\r\n\treader.onload=function(){\r\n\t\tvar sHtml='\u003Cimg src=\"'+event.target.result+'\">';\t\u002F\u002Fresult是base64编码后的图片\r\n\t\t\u002F\u002F这里执行了一个将base64上报到服务器，然后将图片url从base64编码的图片数据换成上传后的图片地址\r\n\t\tsHtml=replaceRemoteImg(sHtml);\r\n\t\t_this.pasteHTML(sHtml);\u002F\u002F这里应该是关于光标和插入代码的具体操作\r\n\t}\r\n\r\n\treader.readAsDataURL(blob);\t\u002F\u002F用fileReader读取二进制图片，完成后会调用上面定义的回调函数\r\n\treturn false;\r\n}\r\n```\r\n\r\n好吧，本来还想写下中间上报到服务器的代码的，想了想觉得也没什么很特别的地方。最多是把base64数据当成普通URL上报，然后服务端再解码成图片。\r\n\r\n嗯。就这样，当笔记了。\r\n","\u002Farticle\u002Fxheditor_paste_images.html",null,0,"2026-08-28 04:37:17","published","",{"id":24,"type":7,"slug":25,"title":26,"date":27,"category":11,"tags":28,"body_markdown":31,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},152,"exam-of-netease","纪念网易笔试错题","2010-09-28 14:35:41",[29,30],"笔试","网易","\n网易2010年校园招聘页面工程师笔试题，不幸做错，留下代码作为纪念。\n\n```\n\u003Chtml>\n\u003Chead>\n\t\u003Ctitle>网易笔试题\u003C\u002Ftitle>\n\u003C\u002Fhead>\n\u003Cbody>\n\t\u003Cdiv style=\"width:350px;margin:200px;\">\n\t\t\u003Cp style=\"text-indent:-2em;\">\u003Cspan>问：\u003C\u002Fspan>网易邮箱都有哪些品牌？\u003C\u002Fp>\n\t\u003Cp style=\"text-indent:-2em;\">\u003Cspan>答：\u003C\u002Fspan>网易的免费邮箱有126，163，Yeah等品牌，除此外还有免费的域名邮箱，有收费的188邮箱。还有收费的企业邮箱。\u003C\u002Fp>\n\u003C\u002Fdiv>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n```\n\n居然做错了，真恶心，居然把text-indent这么重要的属性给忘了！晕啊晕……\n",{"id":33,"type":7,"slug":34,"title":35,"date":36,"category":11,"tags":37,"body_markdown":41,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},153,"javascript-version-of-24-points-game","JavaScript版24点","2010-05-12 02:02:30",[38,39,40],"游戏","JavaScript","24点","\n前几天去森林公园烧烤，和同学一起玩24点。以前玩过，再次玩起来还是觉得不甘心，尤其是当我们都认为无解的情况。\n\n回来后就想写24点的计算程序，想了一下，似乎除了穷举之外没有其他的方法，上网搜了一下，也都是用的穷兴举法。不过算法不算很高效，其中[http:\u002F\u002Fwww.blogjava.net\u002Fcomic222\u002Farchive\u002F2009-01-06\u002F250101.html](http:\u002F\u002Fwww.blogjava.net\u002Fcomic222\u002Farchive\u002F2009-01-06\u002F250101.html)所述算法取2个数字有6种取法，运算有6种（减法和除法是有顺序的），第二次取数有3种取法，运算有6种，第三次取数有1种取法，运算有6种，所以一共有6\\*6\\*3\\*6\\*1\\*6=3888个表达式，而[http:\u002F\u002Fhi.baidu.com\u002Fgreation\u002Fblog\u002Fitem\u002F1f68fbfa808d10d9b58f3106.html](http:\u002F\u002Fhi.baidu.com\u002Fgreation\u002Fblog\u002Fitem\u002F1f68fbfa808d10d9b58f3106.html)就更夸张了，直接用循环（多少重，我没数……）要判断次数：4\\*3\\*2\\*1\\*4\\*4\\*4\\*11=16896。（不过这个思路挺好的，设定了11个表达式形式，不过经我验证，第一个表达式可以完全归入下面十个。）\n\n分析发现，在穷举过程中存在大量重复表达式，比如1，2，3，4这四个数字，1+2+3+4要运算一次，2+1+3+4又要运算一次，这样1+2+3+4等价的表达式就多达24个！\n\n为了尽量减少重复表达式，我决定将表达式按运算符类型分类，方案如下：\n\n1. 将所有只含有加减法提出来，将第一个数字前面也加上运算符，共有4个运算符，所以共有2^4=16种运算符方案，因为加减法是可以交换可以结合的，所以等价的表达式就不用再验证。又因为24点中不能4个数字前全是减号（负号），即至少有一个正数作为被减数，所以共有16-15个表达式；同理可知，只含有乘除法的表达式有15个（除号放在数前面用“1\u002F”表式，即该数的倒数）。\n2. 若是两端乘除再中间一加减（如2\\*9+1\\*6），用于乘除的两两组合有C(4,2)\u002F2=3种，每个乘除运算有3种（两数相乘，前者除后者，后者除前者），加减有3种（两数相加，前者减后者，后者减前者），共有3\\*3^2\\*3=81个表达式；同理，若是两端加减再中间一乘除，共有81个表达式。\n3. 若是前面两个乘除运算，后面一个加减运算，用于乘除运算的数字组合有4种选择，乘除方案有2^3-1=7种（因为不能全是除，所以减一），加减有3种，共有4\\*7\\*3=84个表达式，同理，若是先两个加减运算，再一个乘除运算，有84个表达式。\n4. 若是先乘除一次，再加减一次，再加减或者乘除一次，则第一步乘除运算取数字有6种取法，乘除方案有3种，第二步取数字有2种取法，加减方案有3种，第三步取数字有1种取法，加减乘除方案有7种（2\\*4-1），共有6\\*3\\*2\\*3\\*1\\*7=756个表达式；同理，先加减再乘除再加减，共有756个表达式。\n\n共计需要判断的表达式有15+15+81+81+84+84+756+756=1872个。\n\n已经用JavaScript实现，未加入对输入是否合法的判断。因为乘法中“负负得正”，所以有时候会出现几乎重复的方案，是否能够进一步优化待尚探讨。凌晨2点写完。以下是具体的程序代码：\n\n\t\u003C!DOCTYPE html PUBLIC \"-\u002F\u002FW3C\u002F\u002FDTD XHTML 1.0 Transitional\u002F\u002FEN\" \"http:\u002F\u002Fwww.w3.org\u002FTR\u002Fxhtml1\u002FDTD\u002Fxhtml1-transitional.dtd\">\n\t\u003Chtml xmlns=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxhtml\">\n\t\t\u003Chead>\n\t \t\u003Ctitle>JavaScript 24点\u003C\u002Ftitle>\n\t\t\u003C\u002Fhead>\n\t\u003Cbody>\n\t\t数1：\u003Cinput type=\"text\" \u002F>\u003Cbr \u002F>\n\t\t数2：\u003Cinput type=\"text\" \u002F>\u003Cbr \u002F>\n\t\t数3：\u003Cinput type=\"text\" \u002F>\u003Cbr \u002F>\n\t\t数4：\u003Cinput type=\"text\" \u002F>\u003Cbr \u002F>\n\t\t\u003Cinput type=\"submit\" value=\"计算\" onclick=\"startcalc();\" \u002F>\n\t\t\u003Cdiv id=\"result\">\u003C\u002Fdiv>\n\t\u003C\u002Fbody>\n\t\u003Cscript language=\"javascript\">\n\tvar n=new Array(0,0,0,0)\n\tvar o=new Array(\"\",\"\",\"\",\"\",\"\",\"\")\n\tvar count=0;\n\tfunction check(expression)\n\t{\n\t\tcount++;\n\t\tif (Math.abs(eval(expression)-24)\u003C0.0001)\n\t\t{\n\t\t\tdocument.getElementById(\"result\").innerHTML=document.getElementById(\"result\").innerHTML+\"第\"+count+\"次判断，找到有效解：\"+expression+\"\u003Cbr \u002F>\";\n\t\t}\n\t}\n\tfunction startcalc()\n\t{\n\t\tcount=0;\n\t\tfor (var i=0;i\u003C4;i++)\n\t\t{\n\t\t\tn[i]=document.getElementsByTagName(\"input\")[i].value;\n\t\t}\n\t\t\u002F\u002F全加减和全乘除，类似a+b-c+d\n\t\tfor (var i=0;i\u003C2;i++)\n\t\t\tfor (var j=0;j\u003C2;j++)\n\t\t\t\tfor (var k=0;k\u003C2;k++)\n\t\t\t\t\tfor (var l=0;l\u003C2;l++)\n\t\t\t\t\t{\n\t\t\t\t\t\t\u002F\u002F加减\n\t\t\t\t\t\to[0]=[\"\",\"-\"][i];\n\t\t\t\t\t\to[1]=[\"+\",\"-\"][j];\n\t\t\t\t\t\to[2]=[\"+\",\"-\"][k];\n\t\t\t\t\t\to[3]=[\"+\",\"-\"][l];\n\t\t\t\t\t\tif(!(o[0]==\"-\"&&o[1]==\"-\"&&o[2]==\"-\"&&o[3]==\"-\"))\n\t\t\t\t\t\t\tcheck(o[0]+n[0]+o[1]+n[1]+o[2]+n[2]+o[3]+n[3]);\n\t\t\t\t\t\t\u002F\u002F乘除\n\t\t\t\t\t\to[0]=[\"\",\"1\u002F\"][i];\n\t\t\t\t\t\to[1]=[\"*\",\"\u002F\"][j];\n\t\t\t\t\t\to[2]=[\"*\",\"\u002F\"][k];\n\t\t\t\t\t\to[3]=[\"*\",\"\u002F\"][l];\n\t\t\t\t\t\tif(!(o[0]==\"1\u002F\"&&o[1]==\"\u002F\"&&o[2]==\"\u002F\"&&o[3]==\"\u002F\"))\n\t\t\t\t\t\t\tcheck(o[0]+n[0]+o[1]+n[1]+o[2]+n[2]+o[3]+n[3]);\n\t\t\t\t\t}\n\t\t\u002F\u002F两端乘除中间加减或者两端加减中间乘除，如（6-2）*（8-2）\n\t\tfor(var i=1;i\u003C4;i++)\n\t\t{\n\t\t\tvar temparr=new Array(0,0,0,0);\n\t\t\ttemparr=n;\n\t\t\tvar tempnum=temparr[i];\n\t\t\ttemparr[i]=temparr[1];\n\t\t\ttemparr[1]=tempnum;\n\t\t\tfor(var j1=0;j1\u003C2;j1++)\n\t\t\t\tfor(var j2=0;j2\u003C2;j2++)\n\t\t\t\t\tfor(var j3=0;j3\u003C2;j3++)\n\t\t\t\t\t\tfor(var j4=0;j4\u003C2;j4++)\n\t\t\t\t\t\t\tfor(var j5=0;j5\u003C2;j5++)\n\t\t\t\t\t\t\t\tfor(var j6=0;j6\u003C2;j6++)\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\u002F\u002F先加减后乘除\n\t\t\t\t\t\t\t\t\to[0]=[\"\",\"1\u002F\"][j1];\n\t\t\t\t\t\t\t\t\to[1]=[\"\",\"-\"][j2];\n\t\t\t\t\t\t\t\t\to[2]=[\"+\",\"-\"][j3];\n\t\t\t\t\t\t\t\t\to[3]=[\"*\",\"\u002F\"][j4];\n\t\t\t\t\t\t\t\t\to[4]=[\"\",\"-\"][j5];\n\t\t\t\t\t\t\t\t\to[5]=[\"+\",\"-\"][j6];\n\t\t\t\t\t\t\t\t\tif(!(o[0]==\"1\u002F\"&&o[3]==\"\u002F\") && !(o[1]==\"-\"&&o[2]==\"-\") && !(o[4]==\"-\"&&o[5]==\"-\"))\n\t\t\t\t\t\t\t\t\t\tcheck(o[0]+\"(\"+o[1]+temparr[0]+o[2]+temparr[1]+\")\"+o[3]+\"(\"+o[4]+temparr[2]+o[5]+temparr[3]+\")\");\n\t\t\t\t\t\t\t\t\t\u002F\u002F先乘除后加减\n\t\t\t\t\t\t\t\t\to[0]=[\"\",\"-\"][j1];\n\t\t\t\t\t\t\t\t\to[1]=[\"\",\"1\u002F\"][j2];\n\t\t\t\t\t\t\t\t\to[2]=[\"*\",\"\u002F\"][j3];\n\t\t\t\t\t\t\t\t\to[3]=[\"+\",\"-\"][j4];\n\t\t\t\t\t\t\t\t\to[4]=[\"\",\"1\u002F\"][j5];\n\t\t\t\t\t\t\t\t\to[5]=[\"*\",\"\u002F\"][j6];\n\t\t\t\t\t\t\t\t\tif(!(o[0]==\"-\"&&o[3]==\"-\") && !(o[1]==\"1\u002F\"&&o[2]==\"\u002F\") && !(o[4]==\"1\u002F\"&&o[5]==\"\u002F\"))\n\t\t\t\t\t\t\t\t\t\tcheck(o[0]+o[1]+temparr[0]+o[2]+temparr[1]+o[3]+o[4]+temparr[2]+o[5]+temparr[3]);\n\t\t\t\t\t\t\t\t}\n\t\t}\n\t\t\u002F\u002F两次乘除一次加减或者两次加减一次乘除，如3*4*3-12\n\t\tfor(var i=0;i\u003C4;i++)\n\t\t{\n\t\t\tvar temparr=new Array(0,0,0,0);\n\t\t\ttemparr=n;\n\t\t\tvar tempnum=temparr[i];\n\t\t\ttemparr[i]=temparr[3];\n\t\t\ttemparr[3]=tempnum;\n\t\t\tfor(var j1=0;j1\u003C2;j1++)\n\t\t\t\tfor(var j2=0;j2\u003C2;j2++)\n\t\t\t\t\tfor(var j3=0;j3\u003C2;j3++)\n\t\t\t\t\t\tfor(var j4=0;j4\u003C2;j4++)\n\t\t\t\t\t\t\tfor(var j5=0;j5\u003C2;j5++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\u002F\u002F先加减后乘除\n\t\t\t\t\t\t\t\to[0]=[\"\",\"1\u002F\"][j1];\n\t\t\t\t\t\t\t\to[1]=[\"\",\"-\"][j2];\n\t\t\t\t\t\t\t\to[2]=[\"+\",\"-\"][j3];\n\t\t\t\t\t\t\t\to[3]=[\"+\",\"-\"][j4];\n\t\t\t\t\t\t\t\to[4]=[\"*\",\"\u002F\"][j5];\n\t\t\t\t\t\t\t\tif(!(o[1]==\"-\"&&o[2]==\"-\"&&o[3]==\"-\") && !(o[0]==\"1\u002F\"&&o[4]==\"\u002F\"))\n\t\t\t\t\t\t\t\t\tcheck(o[0]+\"(\"+o[1]+temparr[0]+o[2]+temparr[1]+o[3]+temparr[2]+\")\"+o[4]+temparr[3]);\n\t\t\t\t\t\t\t\t\u002F\u002F先乘除后加减\n\t\t\t\t\t\t\t\to[0]=[\"\",\"-\"][j1];\n\t\t\t\t\t\t\t\to[1]=[\"\",\"1\u002F\"][j2];\n\t\t\t\t\t\t\t\to[2]=[\"*\",\"\u002F\"][j3];\n\t\t\t\t\t\t\t\to[3]=[\"*\",\"\u002F\"][j4];\n\t\t\t\t\t\t\t\to[4]=[\"+\",\"-\"][j5];\n\t\t\t\t\t\t\t\tif(!(o[1]==\"1\u002F\"&&o[2]==\"\u002F\"&&o[3]==\"\u002F\") && !(o[0]==\"-\"&&o[4]==\"-\"))\n\t\t\t\t\t\t\t\t\tcheck(o[0]+o[1]+temparr[0]+o[2]+temparr[1]+o[3]+temparr[2]+o[4]+temparr[3]);\n\t\t\t\t\t\t\t}\n\t\t}\n\t\t\u002F\u002Falert(count);\n\t\t\u002F\u002F至此共判断360次，与预期一样\n\t\t\u002F\u002F乘除一次，加减一次，加减乘除一次，或者反过来，如(（3+4）*3)+3\n\t\tfor(var i=0;i\u003C4;i++)\n\t\t\tfor(var j=i+1;j\u003C4;j++)\n\t\t\t{\n\t\t\t\tvar temparr=new Array(0,0,0,0);\n\t\t\t\ttemparr=n;\n\t\t\t\tvar tempnum=temparr[i];\n\t\t\t\ttemparr[i]=temparr[0];\n\t\t\t\ttemparr[0]=tempnum;\n\t\t\t\ttempnum=temparr[j];\n\t\t\t\ttemparr[j]=temparr[1];\n\t\t\t\ttemparr[1]=tempnum;\n\t\t\t\tfor (var k=2;k\u003C4;k++)\n\t\t\t\t{\n\t\t\t\t\ttempnum=temparr[k];\n\t\t\t\t\ttemparr[k]=temparr[2]\n\t\t\t\t\ttemparr[2]=tempnum;\n\t\t\t\t\tfor(var j1=0;j1\u003C2;j1++)\n\t\t\t\t\t\tfor(var j2=0;j2\u003C2;j2++)\n\t\t\t\t\t\t\tfor(var j3=0;j3\u003C2;j3++)\n\t\t\t\t\t\t\t\tfor(var j4=0;j4\u003C2;j4++)\n\t\t\t\t\t\t\t\t\tfor(var j5=0;j5\u003C2;j5++)\n\t\t\t\t\t\t\t\t\t\tfor(var j6=0;j6\u003C4;j6++)\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\u002F\u002F先加减后乘除再加减\n\t\t\t\t\t\t\t\t\t\t\to[0]=[\"\",\"-\"][j1];\n\t\t\t\t\t\t\t\t\t\t\to[1]=[\"\",\"1\u002F\"][j2];\n\t\t\t\t\t\t\t\t\t\t\to[2]=[\"\",\"-\"][j3];\n\t\t\t\t\t\t\t\t\t\t\to[3]=[\"+\",\"-\"][j4];\n\t\t\t\t\t\t\t\t\t\t\to[4]=[\"*\",\"\u002F\"][j5];\n\t\t\t\t\t\t\t\t\t\t\to[5]=[\"+\",\"-\",\"*\",\"\u002F\"][j6];\n\t\t\t\t\t\t\t\t\t\t\tif(!(o[2]==\"-\"&&o[3]==\"-\")&&!(o[1]==\"1\u002F\"&&o[4]==\"\u002F\")&&!(o[0]==\"-\"&&o[5]==\"-\"))\n\t\t\t\t\t\t\t\t\t\t\t\tcheck(o[0]+\"(\"+o[1]+\"(\"+o[2]+temparr[0]+o[3]+temparr[1]+\")\"+o[4]+temparr[2]+\")\"+o[5]+temparr[3]);\n\t\t\t\t\t\t\t\t\t\t\t\u002F\u002F先乘除后加减再乘除\n\t\t\t\t\t\t\t\t\t\t\to[0]=[\"\",\"1\u002F\"][j1];\n\t\t\t\t\t\t\t\t\t\t\to[1]=[\"\",\"-\"][j2];\n\t\t\t\t\t\t\t\t\t\t\to[2]=[\"\",\"1\u002F\"][j3];\n\t\t\t\t\t\t\t\t\t\t\to[3]=[\"*\",\"\u002F\"][j4];\n\t\t\t\t\t\t\t\t\t\t\to[4]=[\"+\",\"-\"][j5];\n\t\t\t\t\t\t\t\t\t\t\to[5]=[\"+\",\"-\",\"*\",\"\u002F\"][j6];\n\t\t\t\t\t\t\t\t\t\t\tif(!(o[2]==\"1\u002F\"&&o[3]==\"\u002F\")&&!(o[1]==\"-\"&&o[4]==\"-\")&&!(o[0]==\"1\u002F\"&&o[5]==\"\u002F\"))\n\t\t\t\t\t\t\t\t\t\t\t\tcheck(o[0]+\"(\"+o[1]+\"(\"+o[2]+temparr[0]+o[3]+temparr[1]+\")\"+o[4]+temparr[2]+\")\"+o[5]+temparr[3]);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\t\tdocument.getElementById(\"result\").innerHTML=document.getElementById(\"result\").innerHTML+\"共计判断表达式\"+count+\"次\";\n\t}\n\t\u003C\u002Fscript>\n\t\u003C\u002Fhtml>\n\n> 演示地址已经放到[https:\u002F\u002Frawcdn.githack.com\u002FTooBug\u002Fworks\u002Fgh-pages\u002F24points\u002Findex.html](https:\u002F\u002Frawcdn.githack.com\u002FTooBug\u002Fworks\u002Fgh-pages\u002F24points\u002Findex.html)。\n",{"id":43,"type":7,"slug":44,"title":45,"date":46,"category":11,"tags":47,"body_markdown":51,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},154,"map-for-the-dom-count","（腾讯面试）js遍历页面输出dom数量","2010-04-26 07:55:19",[48,49,50],"javascript","dom","面试","\n昨天去参加了腾讯的面试，面试官现场出了一道题，要求用JS统计页面的DOM数量。\n\n现场写了一下，但是由于对JS原生DOM操作不基了了，具体的结点操作不会写，只好留了个大致思路。\n\n晚上回到宿舍，终于写出来了。\n\n```javascript\nvar domcount=0;\nfunction domsearch(domobj)\n{\nif(domobj.firstChild)\n\t{\n\t\tvar tempdom=domobj.firstChild;\n\t\tdo{\n\t\t\tdomsearch(tempdom);\n\t\t\ttempdom=tempdom.nextSibling;\n\t\t}while(tempdom);\n\t};\n\tif(domobj.nodeType==1)\n\t{\n\t\tdomcount++;\n\t}\n}\ndomsearch(document.getElementsByTagName(&apos;html&apos;)[0]);\nalert(domcount);\n```\n\n这个遍历过程实际上是用的树的孩子兄弟表示法，直接用孩子结点，得到以下代码：\n\n```\nvar domcount=0;\nfunction domsearch(domobj)\n{\n\tif(domobj.hasChildNodes)\n\t\tfor(var i=0;i\u003Cdomobj.childNodes.length;i++)\n\t\t{\n\t\t\tdomsearch(domobj.childNodes[i]);\n\t\t};\n\tif(domobj.nodeType==1)\n\t{\n\t\tdomcount++;\n\t}\n}\ndomsearch(document.getElementsByTagName(&apos;html&apos;)[0]);\nalert(domcount);\n```\n\n感想：基础知识还是要扎实才行，整个面试过程都没有问很虚无飘渺的东西，都是很基础很实在的知识。JS的具体函数可以记不住，但是一定要知道它能做些什么。回来查资料了才知道JS对DOM结点的原生操作是怎样的。另外，DOM编程的电子书在我电脑里好久了，很少去翻，罪过。\n",{"id":53,"type":7,"slug":54,"title":55,"date":56,"category":11,"tags":57,"body_markdown":60,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},150,"asp-mvc","mvc三层构架在asp中的应用","2010-02-13 14:44:28",[58,59],"asp","mvc","\n前段时间读了不少关于MVC的文章，试着在ASP中应用了一下，发现对于小程序，代码量会大幅度增加，但是逻辑清晰，数据封装很合理，以前需要仔细规划的代码复用竟然成了理所当然的事情。\n\n所谓MVC，即Model（模型），View（视图），Control（控制）三层架构。各部分各司其职，Model即底层构架，包含与数据库连接的部分，View即UI展示部分，与用户直接打交道，Control即控制层，负责接收View的请求并做适当预处理后交由Model处理，然后接收Model返回值并做格式化处理返回View层。简单地说，Model直接与系统底层如数据库等打交道，而不管数据出去后如何用，View只负责请求和展示数据，而不管详细流程，Control分别与View和Model打交道，并负责数据的验证、格式化等工作。\n\n写了一个获取用户资料的ASP中应用：\n\n先写Model层，定义数据库地址，打开连接数据库，获取记录。\n\n在写Model层之前定义了两个类：Cls_Config整站设置，包括数据库地址；Cls_DatabaseModel，负责打开关闭数据库连接。\n\nCls_ConfigModel.asp代码如下：\n\n```asp\n\u003C%\nClass Cls_ConfigModel\n\tPrivate i_datapath,i_sitename,i_sitedomain,i_mastermail\n\tPrivate Sub Class_Initialize()\n\t\ti_datapath=\"data\\testtdata.mdb\"\n\t\ti_sitename=\"testsite\"\n\t\ti_sitedomain=\"www.test.cn\"\n\t\ti_mastermail=\"master@test.cn\"\n\tEnd Sub\n\tPublic property get DataPath\n\t\tDataPath=server.MapPath(i_datapath)\n\tEnd property\n\tPublic property get SiteName\n\t\tSiteName=i_sitename\n\tEnd property\n\tPublic property get SiteDomain\n\t\tSiteDomain=i_sitedomain\n\tEnd property\n\tPublic property get MasterMail\n\t\tMasterMail=i_mastermail\n\tEnd property\nEnd Class\n%>\n```\n\nCls_DatabaseModel.asp代码如下：\n\n```asp\n\u003C!--#include file=\"cls_configmodel.asp\" -->\n\u003C!--#include file=\"..\u002Fpublic\u002Fcls_cache.asp\" -->\n\u003C%\nClass Cls_DatabaseModel\n\tPrivate i_config,i_cache,i_datapath\n\tPrivate i_conn\n\tPrivate Sub Class_Initialize()\n\t\tset i_cache = new Cls_Cache\n\t\tif i_cache.GetCache(\"Config\",\"DataPath\") = \"\" then\n\t\t\tset i_config = new Cls_ConfigModel\n\t\t\ti_datapath = i_config.DataPath\n\t\t\tCall i_cache.SetCache(\"Config\",\"DataPath\",i_datapath)\n\t\telse\n\t\t\ti_datapath = i_cache.GetCache(\"Config\",\"DataPath\")\n\t\tend if\n\t\tset i_cache = nothing\n\tEnd Sub\n\tPrivate Sub Class_Terminate()\n\t\tset i_config=nothing\n\tEnd Sub\n\tPublic property get Conn\n\t\tset Conn=i_conn\n\tEnd property\n\tPublic Function OpenConn()\n\t\tset i_conn=server.createobject(\"adodb.connection\")\n\t\ti_conn.open \"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"& i_datapath &\";User ID=admin;Password=;Jet OLEDB:Database Password=\"\n\tEnd Function\n\tPublic Function CloseConn()\n\t\tset i_conn=nothing\n\tEnd Function\nEnd Class\n%>\n```\n\n其中Cls_Cache是一个缓存类，这里缓存了数据库地址。\n\n用户Model层Cls_UserModel.asp代码如下：\n\n```asp\n\u003C!--#include file=\"cls_databasemodel.asp\" -->\n\u003C%\nClass Cls_UserModel\n\tPrivate i_database,i_sql,i_rs\n\tPublic UserInfo()\n\tPrivate Sub Class_Initialize()\n\t\tset i_database=new Cls_DatabaseModel\n\tEnd Sub\n\tPrivate Sub Class_Terminate()\n\t\tset i_database=nothing\n\tEnd Sub\n\tPublic Function GetUserInfo(KeyType,Key)\n\t\tselect case KeyType\n\t\tcase \"uid\"\n\t\t\ti_sql=\"select * from [MYT_User] where UserId=\" & Key\n\t\tcase \"uname\"\n\t\t\ti_sql=\"select * from [MYT_User] where UserName=&#39;\" & Key & \"&#39;\"\n\t\tend select\n\t\ti_database.OpenConn()\n\t\tset i_rs = i_database.Conn.execute(i_sql)\n\t\tif not i_rs.eof then\n\t\t\tReDim UserInfo(i_rs.fields.count)\n\t\t\tfor i=0 to i_rs.fields.count-1\n\t\t\t\tUserInfo(i)=i_rs(i)\n\t\t\tnext\n\t\telse\n\t\t\tReDim UserInfo(2)\n\t\t\tUserInfo(0)=0\n\t\t\tUserInfo(1)=\"guest\"\n\t\tEnd if\n\t\ti_rs.close\n\t\tset i_rs=nothing\n\t\ti_database.CloseConn()\n\tEnd Function\nEnd Class\n%>\n```\n\nModel层构造SQL语句并查询，然后将记录集存入UserInfo数组，供Control层调用。\n\nControl层Cls_User.asp代码如下：\n\n```asp\n\u003C!--#include file=\"..\u002Fmodel\u002Fcls_usermodel.asp\" -->\n\u003C%\nClass Cls_User\n\tPrivate i_uid,i_uname,i_user\n\tPrivate Sub Class_Initialize()\n\t\tset i_user = new Cls_UserModel\n\tEnd Sub\n\tPrivate Sub Class_Terminate()\n\t\tset i_user=nothing\n\tEnd Sub\n\tPublic property get Uid\n\t\tUid=i_uid\n\tEnd property\n\tPublic property get UName\n\t\tUname=i_uname\n\tEnd property\n\tPublic property let Uid(Userid)\n\t\ti_uid=Userid\n\t\tCall i_user.GetUserInfo(\"uid\",Userid)\n\t\tFillInfo()\n\tEnd property\n\tPublic property let UName(UserName)\n\t\ti_uname=UserName\n\t\tCall i_user.GetUserInfo(\"uname\",UserName)\n\t\tFillInfo()\n\tEnd property\n\tPrivate Function FillInfo()\n\t\ti_uid=i_user.UserInfo(0)\n\t\ti_uname=i_user.UserInfo(1)\n\tEnd Function\nEnd Class\n%>\n```\n\nCls_User类中只定义了两个属性：i_uid，i,uname。当View层给i_uid或者i_uname赋值的时候调用Model层查询用户信息，然后用Fillinfo函数填写属性供View层调用。\n\nView层UserInfo.asp代码如下：\n\n```asp\n\u003C!--#include file=\"control\u002Fcls_user.asp\" -->\n\u003C!DOCTYPE html PUBLIC \"-\u002F\u002FW3C\u002F\u002FDTD XHTML 1.0 Transitional\u002F\u002FEN\" \"http:\u002F\u002Fwww.w3.org\u002FTR\u002Fxhtml1\u002FDTD\u002Fxhtml1-transitional.dtd\">\n\u003Chtml xmlns=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxhtml\">\n\u003Chead>\n\u003Cmeta http-equiv=\"Content-Type\" content=\"text\u002Fhtml; charset=gb2312\" \u002F>\n\u003Ctitle>显示用户信息\u003C\u002Ftitle>\n\u003C\u002Fhead>\n\u003Cbody>\n\u003C%\nset User=new Cls_User\nfor iii=1 to 100\n\tUser.Uid=2\n\tresponse.write User.Uid\n\tresponse.write User.UName\nnext\nset User=nothing\n%>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n```\n\n这样调用逻辑就非常清晰了。\n\n试着加了一个循环（注释掉的代码），查询100个用户大约要3秒左右，看来频繁连接数据库开销确实很大。\n\n另外，循环的时候变量不能用i，不然只能显示第一个用户信息，不知何故。\n\n三层构架的大致思想基本算是掌握了，缓存应用还不够自如，模板类的实现还没开始。任重道远。\n\nPS：今天大年三十，祝所有人幸福安康！\n",{"id":62,"type":7,"slug":63,"title":64,"date":65,"category":11,"tags":66,"body_markdown":68,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":69},155,"read-exif-by-asp","ASPJpeg读取exif信息","2010-02-07 20:29:53",[58,67],"exif","\n最近在想怎么优化上传体验，QQ超大附件上传上有一个细节设计让我觉得特别向往，就是上传的时候与服务器文件进行对比，如果已经存在就不用重复上传，直接标记就完了。\n\n可以很遗憾的是这个功能不太容易实现，先说服务端，要进行诸如MD5之类的计算并不容易，在网上也没有看到用ASP得到文件MD5的例子（不通过调用其他组件）。\n\n而客户端，不装控件，通过脚本读取文件更是不可能的事情。想着FLASH也许可以，但是还是没找到实例。\n\n于是退而求其次，想想能不能在服务器识别重复文件。因为在校内混了这么久，发现有很多照片会被重复上传。于是想到提取图片的EXIF信息。\n\n以下部分是ASPJPEG提取EXIF信息的方法，记录一下：\n\n```asp\nPath = Server.MapPath(\"photo.jpg\")\nSet Jpeg = Server.Cr&#101;ateObject(\"Persits.Jpeg\")\nSet Info = Jpeg.OpenInfo( Path )\n\nFor Each Item in Info\n\n\tResponse.Write Item.Name\n\tResponse.Write Item.Description\n\tResponse.Write Item.Value\n\nNext\n```\n加上表格后效果如下：\n\n![读出的EXIF信息](\u002Fassets\u002Fweb\u002F2010\u002Fread-exif-by-asp\u002Fread-exif-by-asp-1.jpg)\n\n另外获取单项属性的方法：\n\n```asp\nInfo(\"Make\")\n```\n\n这样如果EXIF信息完全一样的就可以认为是同一照片了。\n","https:\u002F\u002Fassets.toobug.net\u002Fassets\u002Fweb\u002F2010\u002Fread-exif-by-asp\u002Fread-exif-by-asp-1.jpg",{"id":71,"type":7,"slug":72,"title":73,"date":74,"category":11,"tags":75,"body_markdown":78,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},156,"web-browser-situation-2010-01","2010年1月国内上网客户端情况","2010-01-30 17:58:01",[76,77],"浏览器","客户端","\n分析了一些第三方统计的数据，大致结果如下：\n\n## 网络接入：\n\n- 电信：55%\n- 网通：30%\n\n还有一些二级接入商像长宽之类的份额都很小\n\n## 搜索引擎：\n\n- 百度：75%\n- GOOGLE：20%\n\n仍然是百度和GOOGLE两大巨头主宰搜索市场，百度风头正劲。\n\n另外，腾讯SOSO表现比较突出，估计跟QQ客户端有关，再其次是SOGOU，其他的就不值一提了。\n\n## 操作系统：\n\n- XP：90%\n- VISTA\u002F2008：5%\n- 7：4%\n- 2003：1%\n\n其他系统可以忽略了。试图找到LINUX的身影，找是找到了，但是份额非常非常少，甚至低于WIN98。2000略高于98。\n\n## 浏览器：\n\n- 微软IE6：55%\n- 微软IE7：10%\n- 微软IE8：8%\n- 不明版本IE：7%\n- 360 IE6内核：12%\n- 360 IE7内核：3%\n- TT IE6内核：2%\n- MAXTHON IE6内核：1%\n- FF：1%\n\n- IE6合计：70%\n- IE7合计：13%\n- IE8：8%\n- 不明版本IE：7%\n- FF：1%\n\n目前在内核方面，IE6仍然占绝对优势，虽然设计师对IE6恨之入骨，但是无法逃避巨大的用户群。这个结果和操作系统的比例有极大关系。IE7和IE8普及率仍然不高，估计如果没有盗版装机光盘，这个比率还会低一点。IE以外的内核在中国基本没有市场，Firefox表现稍好，也才1%。CHROME，OPERA等可以忽略。\n\n## 屏幕分辨率：\n\n- 1024*768：40%\n- 1440*900：18%\n- 1280*800：14%\n- 1280*1024：5%\n- 1152*864：3%\n- 800*600：1%\n- …………\n- 1024*600：低于1%\n\n整体来看，屏幕分辨率离散度非常大，这跟目前市场上液晶面板乱七八糟的规则联系很大。1024*768和1440*900分别占领着标准比例和宽屏的老大地位。1200+，1400+，1600+甚至1900+的大分辨率开始出现并占有不小比例。800*600终于淡出视野了。特别值得注意是1024*600，上网本的比例仍然不大，但是绝对数量也不小。最高兴的是设计师终于不用再照顾800*600了，不过像1920的大分辨率怎么呈现又成了另一个问题。\n\n> 以上数量均为样本平均估计值，仅供参考。另外，在取样过程中发现各项数据跟网站类型还是关系挺大的，比如某IT类网站，IE6份额明显偏低，IE8和FF份额高出不少，甚至OPEAR都高于1%，来自GOOGLE搜索流量比例明显偏大。\n",{"id":80,"type":7,"slug":81,"title":82,"date":83,"category":11,"tags":84,"body_markdown":88,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},151,"dynamic-load-pics-with-jquery","jquery实现ajax加载图片","2010-01-29 22:19:57",[39,85,86,87],"jQuery","ajax","加载","\n最近在学习JQuery，想从原理上模拟一下无刷新的相册浏览。\n\n最先想到的思路是利用缓存，也就是先显示提示消息，然后get图片，在get完的时候回调，将img标签的`src`改掉，由于刚刚get过，有了缓存，所以图片会立刻显示出来。\n\n页面元素：\n\n```html\n\u003Cinput class=\"picbtn\" type=\"button\" value=\"Next\" \u002F>\n\u003Cdiv class=\"tip\">正在加载……\u003C\u002Fdiv>\n\u003Cdiv class=\"notice\">\n\t\u003Cimg \u002F>\n\u003C\u002Fdiv>\n```\n\n按钮的事件绑定：\n\n```javascript\n$(\".picbtn\").click(function(){NextPic();});\n```\n\n定义了一个数组PicArr用来记录所有图片。\n\nNextPic内容：\n\n```javascript\n$(\".tip\").slideDown(200);  \u002F\u002F显示提示\t$.get(PicArr[CurrPic],function(){\n\t$(\"img\").attr(\"src\",PicArr[CurrPic]);\n\t$(\".tip\").slideUp(200);\n\tCurrPic++;\n\tif(CurrPic>4)\n\t\tCurrPic=0;\n\t\t});\n};\n```\n\n在CHROME和FF下显示正常，IE6下异常，IE7、8未测试。\n\n后来在ASPRAIN的开发者 稽山草 的帮助下，思路改成了先改src，然后绑定onload事件，在onload中回调。\n\n核心代码：\n\n```javascript\n$(\"img\").attr(\"src\",PicArr[CurrPic])\n\t.bind(load,function(){\n\t\t$(\".tip\").slideUp(200);\n\t\tCurrPic++;\n\t\tif(CurrPic>4)CurrPic=0;\n\t});\n```\n\n后来一看基本正常了，但是仔细看还是不正常，图片顺序开始乱跳，跟踪了好久发现回调函数会多次运行。中间想到会不会是事件绑定的问题，因为`onclick`事件的绑定是`$(Element).bind(\"click\",callback)`，可以简写成`$(Element).click(callback)`，想到`$(Element).bind(\"load\",callback)`和`$(Element).load(url,callback)`会不会是一样，查资料写得都不怎么清楚，改了试一下，还是不一样，不过在chrome和ff下依然能工作，但是数据不太正常，IE下报错。\n\n再次检查 稽山草 给的代码，发现问题在哪了。\n\nload事件的绑定的是一个匿名函数，而当按钮按下时会再次绑定，所以会重复执行。于是将绑定`bind`改成`one`搞定。最终完整代码如下：\n\n```html\n\u003C!DOCTYPE html PUBLIC \"-\u002F\u002FW3C\u002F\u002FDTD XHTML 1.0 Transitional\u002F\u002FEN\" \"http:\u002F\u002Fwww.w3.org\u002FTR\u002Fxhtml1\u002FDTD\u002Fxhtml1-transitional.dtd\">\n\u003Chtml xmlns=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxhtml\">\n\u003Chead>\n\t\u003Cmeta http-equiv=\"Content-Type\" content=\"text\u002Fhtml; charset=gb2312\" \u002F>\n\t\u003Ctitle>JQUERY动态加载图片\u003C\u002Ftitle>\n\t\u003Cscript type=\"text\u002Fjavascript\" src=\"jquery\u002Fjquery-1.3.2.min.js\">\u003C\u002Fscript>\n\t\u003Cscript type=\"text\u002Fjavascript\">\n\t\t(function($){\n\t\t\t$.NextPic=function(){\n\t\t\t\t$(\".tip\").slideDown(200);\n\t\t\t\t$(\"img\").attr(\"src\",PicArr[CurrPic]).one(load,function(){\n\t\t\t\t\t$(\".tip\").slideUp(200);\n\t\t\t\t\tCurrPic++;\n\t\t\t\t\tif(CurrPic>4)CurrPic=0;\n\t\t\t\t});\n\t\t\t\t\u002F*(\"img\").load(PicArr[CurrPic],function(){\n\t\t\t\t\t$(this).attr(\"src\",PicArr[CurrPic]);\n\t\t\t\t\t$(\".tip\").slideUp(200);\n\t\t\t\t\talert(CurrPic);\n\t\t\t\t\tCurrPic++;\n\t\t\t\t\tif(CurrPic>4)CurrPic=0;\n\t\t\t\t});*\u002F\n\t\t\t}\n\t\t})(jQuery);\n\n\t\t$(document).ready(function(){\n\t\t\tPicArr = new Array(\"1.jpg\",\"2.jpg\",\"3.jpg\",\"4.jpg\",\"5.jpg\");\n\t\t\tCurrPic=0;\n\t\t\t$(\".tip\").css({\"position\":\"absolute\",\"top\":\"100px\",\"left\":\"50px\"});\n\t\t\t$(\".tip\").hide();\n\t\t\t$(\".scoll\").click(function(){$.NextPic();});\n\t\t})\n\t\u003C\u002Fscript>\n\u003C\u002Fhead>\n\u003Cbody>\n\t\u003Cinput class=\"picbtn\" type=\"button\" value=\"Next\" \u002F>\n\t\u003Cdiv class=\"tip\">正在加载……\u003C\u002Fdiv>\n\t\u003Cdiv class=\"notice\">\n\t\t\u003Cimg id=\"img\"\u002F>\n\t\u003C\u002Fdiv>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n```\n",{"id":90,"type":7,"slug":91,"title":92,"date":93,"category":11,"tags":94,"body_markdown":98,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},148,"advantage-of-multi-sub-domains","见识多子域名的好处","2008-06-11 16:30:22",[95,96,97],"域名","性能","http","\n\n今天在新浪博客上传了一大堆的图片，然后自己看的时候显示效果还算好。但是不管是在教育网还是网通的网络都会有几张不能显示。\n\n起初怀疑是图片上传出了问题，后来确认不是。再仔细看了一下，发现新浪是将图片存在不同的服务器上的，初步判断是随机挑选服务器。各服务器使用不同的二级域名，域名如下http:\u002F\u002FstaticXX.photo.sina.com.cn，我遇到的XX从1到16，意味着最少有16台这样的服务器。\n\n其实这样做有其坏处，比如域名解析需要大量的时间，且有服务器连接不上的话这台服务器上的图片就不能显示出来。\n\n但是，这样做的好处会比坏处更大。首先，目前IE除8以外，其他版本的均只支持同时从1个域名并发两个请求，即最多同时可以在一台服务器上请求两张图片，再通俗一点，就是说最多只能同时下载两张，要下载第三张就必须等两张中的一张下载完毕。（其实不止图片，网页文件本身，以及相关的JS文件，CSS文件等等都受此限制。）因此，使用多个服务器可以大大地增加并发数量，加快图片显示的速度。另一方面，多个服务器出现同时不能连接的可能性较小，因此即使网络不好，也会有一部分图片显示出来。（我现在的情况就是这样。）\n\n好像以前采用这种方式的网站并不很多，最多只是根据内容的不同区分不同的服务器，但现在很多网站都考虑到了并发的问题，采用了多域名。典型的像校内就是，它根据内容的不同区分了不同的服务器，例如登录后就是home.xiaonei.com，好友页面是friend.xiaonei.com，分享页面是share.xiaonei.com等等。同时相同内容的例如上传的附件也是随机存储在很多服务器上的。\n\n这样的构架确实不错，但是技术含量应该也是很高的。这其中涉及到域名的分配问题，多服务器的数据共享，以及WEB服务器与数据服务器通讯等等一系列问题。当然，作为专用的图片服务器，还会涉及到关于图片存储、处理、读取等问题（反向代理好像用得很多）。限于资金问题，还没有玩过独立的服务器，更没有接触过多服务器之间的数据处理问题，只看过一些文章，因此也只能做上述分析，更细的东西在亲自接触过之后应该会有很多心得。\n\n那么对于小网站，没有资本做多服务器的能得到些什么启示呢？首先，多域名同样是可用的，即把多个域名绑定到一台主机上，然后在网站显示的时候请求不同的域名。其次，可以对图片或者其他文件进行优化，例如在一定限度内进行压缩处理，以加快传输。再者，就只能在网页制作技术上下工夫了，尽量减少服务器的负担，使之能稳定运行，当然，这里面还涉及到用户的体验问题，无法再空泛地讨论，因此打住。\n",{"id":100,"type":7,"slug":101,"title":102,"date":103,"category":11,"tags":104,"body_markdown":109,"permalink":18,"excerpt_src":18,"media_type":18,"media_title":18,"media_author":18,"media_url":18,"rating":18,"layout":18,"pv":19,"admin_only":19,"created_at":20,"updated_at":20,"deleted_at":18,"status":21,"cover":22},149,"ascii-table-and-text-format","ASCII码表代码＋文本格式化处理代码","2008-01-07 14:38",[105,106,107,108],"vbscript","ASCII","文本","格式化","\n真的发现网页可以做很多事情，我现在已经用网页写了4个程序出来了。\n先贴两个今天写完的。\n\nASCII码表：\n\n```html\n\u003Chtml>\n\u003Chead>\u003Ctitle>ASCII码表\u003C\u002Ftitle>\u003C\u002Fhead>\n\u003Cbody onload=\"asciitable()\">\n\u003Cscript language=\"vbscript\">\nfunction asciitable()\n    document.write \"\u003Ctable align='center' border='0'>\"&chr(13)\n    document.write \"\u003Ctr>\u003Ctd colspan='20' align='center'>ASCII码表(VBScript自动生成)\u003C\u002Ftd>\u003C\u002Ftr>\"&chr(13)\n    j=0\n    for i=1 to 127\n        if j=0 then document.write \"\u003Ctr>\"\n        document.write \"\u003Ctd>\"&i&\"\u003C\u002Ftd>\u003Ctd>\"&chr(i)&\"\u003C\u002Ftd>\"\n        j=j+1\n        if j=10 then\n            document.write \"\u003C\u002Ftr>\"&chr(13)\n        j=0\n        end if\n    next\n    document.write \"\u003C\u002Ftable>\"\nend function\n\u003C\u002Fscript>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n```\n\n文本格式化处理：\n\n```html\n\u003C!DOCTYPE html PUBLIC \"-\u002F\u002FW3C\u002F\u002FDTD XHTML 1.0 Transitional\u002F\u002FEN\" \"http:\u002F\u002Fwww.w3.org\u002FTR\u002Fxhtml1\u002FDTD\u002Fxhtml1-transitional.dtd\">\n\u003Chtml xmlns=\"http:\u002F\u002Fwww.w3.org\u002F1999\u002Fxhtml\">\n\u003Chead>\u003Ctitle>文本格式化处理－抒寒开发\u003C\u002Ftitle>\u003C\u002Fhead>\n\u003Cbody>\n\u003Cscript language=\"vbscript\">\nfunction trans()\n    text=text1.value\n    text=\"    \"&text\n    text=replace(text,\"`\",\"'\")\n    text=replace(text,\",\",\"，\")\n    text=replace(text,\".\",\"。\")\n    text=replace(text,\"．\",\"。\")\n    text=replace(text,\"?\",\"？\")\n    text=replace(text,\"!\",\"！\")\n    text=replace(text,\":\",\"：\")\n    text=replace(text,\"(\",\"（\")\n    text=replace(text,\")\",\"）\")\n    text=replace(text,\"\u003C\u003C\",\"《\")\n    text=replace(text,\">>\",\"》\")\n    text=replace(text,\"。。。\",\"…\")\n    text=replace(text,\"…。\",\"…\")\n    text=replace(text,\"…。\",\"…\")\n    text=replace(text,\"：\"&chr(13),\"：　　\")\n    text=replace(text,\"。\"&chr(13),\"。　　\")\n    text=replace(text,\"？\"&chr(13),\"？　　\")\n    text=replace(text,\"！\"&chr(13),\"！　　\")\n    text=replace(text,\"…\"&chr(13),\"…　　\")\n    text=replace(text,chr(13),\"\")\n    text=replace(text,chr(10),\"\")\n    text=replace(text,\"  \",\"　\")\n    text=replace(text,\"　 \",\"　　\")\n    text=replace(text,\"　　　　\",\"　　\")\n    text=replace(text,\"　　　\",\"　　\")\n    text=replace(text,\"　　　\",\"　　\")\n    text=replace(text,\"　　\",chr(13)&\"　　\")\n    text=right(text,len(text)-1)\n    text2.value=text\nend function\n\u003C\u002Fscript>\n\u003Cscript language=\"javascript\">\nfunction copytext(obj,formname) {\n    ie = (document.all)? true:false\n    if (ie){\n        var rng = document.body.createTextRange();\n        rng.moveToElementText(obj);\n        rng.scrollIntoView();\n        rng.select();\n        rng.execCommand(\"Copy\");\n        rng.collapse(false);\n        alert(\"文本复制成功！\")\n    }\n}\n\u003C\u002Fscript>\n\u003Cdiv align=\"center\" style=\"margin:auto;padding:2px;width:760px;border:1px dotted;font-size:12px;color:#5d78bf;\">\n    \u003Cdiv align=\"left\" style=\"padding:8px; height:20px;background:#e4f1ff;\">\n        \u003Cdiv style=\"width:400px;float:left;font-size:16px;\">文本格式化处理程序V1.0\u003C\u002Fdiv>\n        \u003Cdiv style=\"width:50px;float:right\">\u003Ca href=\"javascript:window.close()\">关闭窗口\u003C\u002Fa>\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv align=\"left\" style=\"padding:10px 20px;\">请粘贴待处理文本并按“处理”：\u003Cinput type=\"button\" value=\"处理\" onclick=\"trans()\" \u002F>\u003C\u002Fdiv>\n    \u003Ctextarea rows=\"10\" cols=\"100\" name=\"text1\" id=\"text1\">\u003C\u002Ftextarea>\n    \u003Cdiv align=\"left\" style=\"padding:10px 20px;\">处理后的文本，可点击按钮复制：\u003Cinput type=\"button\" value=\"复制\" onclick=\"copytext(text2)\" \u002F>\u003C\u002Fdiv>\n    \u003Ctextarea rows=\"10\" cols=\"100\" name=\"text2\" id=\"text2\">\u003C\u002Ftextarea>\n    \u003Cdiv align=\"left\" style=\"padding:20px;\">\n        说明：\u003Cbr \u002F>\n        1、本程序仅适合处理中文文章，英文文章、源代码等请勿用本程序处理。\u003Cbr \u002F>\n        2、本程序处理内容：英文标点换中文标点，段首空格、换行符、标点符号等标准化。\u003Cbr \u002F>\n        3、本程序尚处于测试阶段，可能存在功能不稳定的情况，处理前请务必备份好原文件。\u003Cbr \u002F>\n    \u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n```\n",46]