[转载]微信公众平台消息接口开发(8)小黄鸡小贱鸡机器人 - 方倍 - 博客园

mikel阅读(985)

转载微信公众平台消息接口开发(8)小黄鸡小贱鸡机器人 – 方倍 – 博客园.

微信公众平台 消息 接口 小黄鸡 小贱鸡 机器人
作者:http://www.cnblogs.com/txw1958/ 

原文:http://www.cnblogs.com/txw1958/archive/2013/02/07/weixin-if8-simsimi.html 

 

本 系统教程以微信公众平台应用天气神(账号WeatherGod,支持国内近2500个城市天气的名称、拼音、简拼、区号、邮编以及语音触发模式,地理位置 查询,以及图片识别技术,语音识别功能(研))为例,讲解微信接口开发过程。欢迎大家关注该账号并查询当地天气,二维码见底部。

一、模拟请求数据

先看一下小黄鸡的网页版界面

我们通过模拟http请求来实现,上面对话抓包如下:

发送消息的包

接收消息的包:

根据上面的包,模拟发起请求如下:

 

二、与微信对接

小黄鸡还可以使用API方式调用,但免费时间有限,代码和上面基本一样,就不多写了。

 

三、演示效果

————————————————————————————————————————–

关注天气神(账号WeatherGod)方法:

1. 依次进入以下路径:朋友们—>添加朋友—>搜号码,输入WeatherGod,不区分大小写,点击查找,然后点击关注

2. 扫描二维码:

猜你喜欢:微信公众平台上的第一个图像处理应用-人脸识别

承接微信公众平台开发业务 联系QQ:1354386063 电子邮件:1354386063@qq.com
■ 原文网址:http://txw1958.cnblogs.com/
■ 版权声明:自由转载-非商用-非衍生-保持署名

[转载]硬盘引导windows系统的误区 - 好研

mikel阅读(918)

[转载]硬盘引导windows系统的误区 – 好研.

win7和XP同硬盘共存机制谈常见的一个问题

电 脑通过BIOS自检,由预先设置的启动设备启动系统,以硬盘为例,系统BIOS将硬盘主引导记录读入内存,将控制权交给主引导程序(MBR,下同),然后 检查分区表的状态,寻找活动的分区。最后,由主引导程序将控制权交给活动分区的引导记录(PBD),由该引导记录加载操作系统。

实现NT5.X和NT6.X系统引导的MBR引导是完全不同的
NT5.X的MBR不能引导多个活动分区,分区表会出错,所以理论上用NT5.X的MBR是可以引导NT6.X系统的
NT6.X可以看做是NT6.X的升级版,MBR支持多个独立活动分区启动(安装时设置的活动分区),然后从第一个设置活动的分区启动系统,即安装系统是在安装时的激活分区,不一定是当前激活分区。

NT6.X系统(Vista、WIN7和WIN8)系统是依赖根目录的bootmgr文件通过boot\BCD 的内容找到windows的winloads.exe来引导实现
NT5.X系统(XP和2000)系统是依赖根目录的ntldr 文件通过boot.ini的内容找到windows的文件夹目录来引导实现

由于实现硬盘引导的MBR、PBD以及引导文件的不同,会造成安装系统后不能直接引导或启动后不能加载引导文件的现象,这都是计算机引导设置错误造成的

NT5.X系统(XP和2000) NT6.X系统(Vista、WIN7和WIN8)
主引导记录(MBR)的差异 从第一激活分区启动系统 可以从多个集合分区启动系统
分区引导记录(PBD)的差异 不能兼容6.X系统 可以向下兼容
引导文件 ntldr bootmgr
引导文件调用文件 系统根目录的boot.ini boot目录下的BCD文件

明白了引导的原理,安装双系统就容易得多。由于NT6.X的引导记录优先并向下兼容NT5.X,所以NT6.X系统在不改变引 导的前提下是支持NT5.X系统启动的。例如安装了XP,主引导记录为NT5.X,在安装win7、win8之后,引导记录被置换为NT6.X的引导记 录,是可以引导原XP系统形成双系统的。
如果先安装的win7、win8,在安装XP后,主引导记录从6.X置换为5.X,而NT5.X引导记录是不能启动NT6.X系统的,不能形成双系统,需要借助工具将主引导记录置换为NT6.X,在BCD中加入NT5.X系统的引导文件项来实现双系统启动。

可见,WIN7下安装XP还是比较容易实现的,XP最好能够使用安装版,使用ghost对系统安装环境有要求,一般安装到第1硬盘第1分区(或第一激活分区),所以常见到ghost版的XP系统安装到其它分区后,无法修复启动或出现系统变量错误的问题。

安装WIN7到C盘之后如果想把XP也安装到这里,需要修改安装文件,如下图:
硬盘引导windows系统的误区—装XP&WIN7双系统参考硬盘引导windows系统的误区—装XP&WIN7双系统参考

[转载]PSD转HTML实例教程——利用JQuery插件实现图片滑动效果 - 万仓一黍 - 博客园

mikel阅读(1001)

[转载]PSD转HTML实例教程——利用JQuery插件实现图片滑动效果 – 万仓一黍 – 博客园.

之前一段时间,翻译了一些国外的PS网页设计教程, 这些教程中都有一些共性,例如包含网页LOGO、导航菜单栏、图片滑动栏、版权信息等。其中在多个教程中都提到了利用JQuery插件实现图片滑动栏。于 是在网上搜索了一番,发现类似的插件千千万万,都有各自的特色。故本教程挑选了其中的一个插件,进行讲解,并在后面结合实例讲解如何在PS中切片,在导出 的网页中完成图片滑动栏栏的制作。

 

插件网址:http://slidesjs.com/

插件示例网址:http://slidesjs.com/examples/standard/

 

插件的参数:

 

preload (boolean)

设置为true时,显示一个预加载图像。在图片比较大的情况下特别有用,能改善用户操控。默认值是false

 

preloadImage (string)

预加载图片的路径和文件名。默认路径是/img/loading.gif

 

container (string)

图片滑动块的容器的Class名。默认的Class名是slides_container

 

generateNextPrev (boolean)

是否自动生成下一个/上一个按钮。默认值是false

 

next (string)

自定义下一个按钮的Class名。默认的Class名是next

 

prev (string)

自定义上一个按钮的Class名。默认的Class名是prev

 

pagination (boolean)

如果不使用页码,可以设置为false,但不是必须设置

 

generatePagination (boolean)

是否自动生成页码。默认值是true

 

paginationClass (string)

页码元素的Class名。默认的Class名是pagination

 

currentClass (string)

当前页的Class名。默认的Class名是current

 

fadeSpeed (number)

设置(以毫秒为单位)的淡出淡入动画的速度。默认值是350毫秒

 

fadeEasing (string)

设置淡出淡入动画的宽松的效果。

必须在项目中包含Easing插件

 

slideSpeed (number)

设置(以毫秒为单位)的滑动动画的速度。默认值是350毫秒

 

slideEasing (string)

设置滑动动画的宽松的效果。

必须在项目中包含Easing插件

 

start (number)

设置滑动动画的开始的序号。默认值是1,表示从第一张图片开始动画

 

effect (string)

设置动画效果,给下一个/上一个按钮和页码添加滑动(slide)和淡出淡入(fade)的动画效果,如果你只使用了一个动画效果的名字。你也可以 添加两个效果的名字。第一个将会是下一个/上一个按钮的动画效果,第二个会是页码的动画效果。两个效果之间用逗号分开。默认的动画效果是slide,会使 下一个/上一个按钮和分页的动画效果都是滑动。

 

crossfade (boolean)

动画的切换是否是交叉淡变图像效果。默认值是false

 

randomize (boolean)

设置为true的时候随机滑动图片。默认值是false

 

play (number)

自动播放幻灯片,一个正数将设置为true,表示幻灯片动画之间的时间(以毫秒为单位)。默认值是0表示false

 

pause (number)

当单击上一个/下一个按钮或者页码时暂停动画。一个正数将设置为true,表示暂停的时间(以毫秒为单位)。默认值是0表示false

 

hoverPause (boolean)

设置为true时,鼠标在图片上方时暂停动画。默认值是false

 

autoHeight (boolean)

设置为true时自动调整高度。默认值是false

 

autoHeightSpeed (number)

设置自动高度动画的时间(以毫秒为单位)。默认值是350毫秒

 

bigTarget (boolean)

设置为true时,点击整个图片时链接到下一张图片。默认值是false

 

animationStart() (callback)

设置在动画开始时的回调函数。默认值是空值

 

animationComplete() (callback)

设置在动画完成时的回调函数。默认值是空值

 

示例:

接下来一步一步实现示例中的效果,先准备一些图片

图片滑动栏的背景图片(frame.png)

frame

左上角飘带的图片(new-ribbon.png)

new-ribbon

 

上一个/下一个按钮的图片(arrow-prev.png和arrow-next.png)

arrow-prev

arrow-next

 

页码图片(pagination.png)

pagination

 

如下是完成基本的页面结构

<body>
<!–图片滑动块区域–>
<div id=”container”>
<!–左上角飘带–>
<img src=”Image/new-ribbon.png” alt=”New Ribbon” id=”ribbon”/>
<!–滑动块背景–>
<img src=”Image/frame.png” alt=”Frame” id=”frame” />
<!–滑动区域–>
<div id=”slides”>
<!–上一个/下一个按钮,两个图片超链接–>
<a href=”#” class=”prev”><img src=”Image/arrow-prev.png” alt=”Arrow Prev” /></a>
        <a href=”#” class=”next”><img src=”Image/arrow-next.png” alt=”Arrow Next” /></a>
<!–滑动图片,一个Div,若干图片超链接–>
<div class=”slides_container”>
<a href=”1.html”><img alt=”1″ src=”Image/1.jpg” /></a>
<a href=”2.html”><img alt=”2″ src=”Image/2.jpg” /></a>
<a href=”3.html”><img alt=”3″ src=”Image/3.jpg” /></a>
<a href=”4.html”><img alt=”4″ src=”Image/4.jpg” /></a>
<a href=”5.html”><img alt=”5″ src=”Image/5.jpg” /></a>
</div>
</div>
</div>
</body>

上面的结构中,每一部分都有解释,应该能看得比较清楚。标签(div)container表示这块内容是一个图片滑动区块;飘带和背景以Img标签 存在,也可以将两张图片合并成一张图片,这样只需要一个Img标签即可,或可增加其他的装饰图案;标签(div)slides,表示图片的滑动区域,也是 本插件的作用区域,它包含三块内容,一是上一个/下一个按钮,以图片链接形式存在;一是滑动图片组,以若干图片超链接形式存在;一是页码组,由插件自动生 成。

 

上面仅仅是页面的基本结构,还得给它们添加CSS样式,以完成如样张的效果

先是设置页面的背景颜色和图片的边框为无(这会去除超链接中Img标签的蓝色边框,蓝色边框在IE中会出现),以及去除超链接在点击后的虚框

body { background-color:#efefef}
img { border:none;}
:focus { outline:0; }

 

对图片滑动块区域添加样式,重点是position属性的设置,设置为relative后,其子元素的position属性才能起效果

#container { width:760px; height:360px; padding:10px; margin:0 auto; position:relative; z-index:0; }

 

对飘带和背景设置样式,两个元素的position属性都是absolute(以父容器为参照,绝对定位)

#ribbon { position:absolute; left:76px; top:10px; z-index:500; }
#frame { position:absolutewidth:740px; height:340px; z-index:0; }

 

对滑动区域设置样式,slides的position属性也是absolute。绝对定位的两个参数top和left一定要设置精确

#slides { position:absolute; top:28px; left:94px; z-index:100; }
.slides_container { width:571px; overflow:hidden; position:relative; display:none; }

 

对滑动的图片设置样式,超链接和图片用相同的样式
.slides_container a , .slides_container a img { width:571px; height:269px; display:block; }

 

对上一个/下一个按钮设置样式,先设置相同的样式,在对下一个按钮另外设置left样式,使之居于右侧

#slides .next,#slides .prev { position:absolute; top:107px; left:-39px; display:block; z-index:101; }
#slides .next { left:586px;}

 

最后对页码按钮设置样式,页码按钮是由插件直接生成的,是一组超级链接

.pagination { margin:26px auto 0; width:100px; }
.pagination li { float:left; margin:0 1px; list-style:none; }
.pagination li a { display:block; width:12px; height:0; padding-top:12px; background-image:url(Image/pagination.png); float:left; overflow:hidden; }

 

由于页码按钮中的用的图片是两张图片合在一张图片里的,故在current样式中直接设置background-position样式即可

.pagination li.current a {background-position:0 -12px;}

 

 

到目前为止,页面结构和CSS样式都已经完成了。那么该对插件的应用了

<script src=”Scripts/JQuery-1.9.1.min.js” type=”text/JavaScript ></script>
<script src=”Scripts/slides.min.JQuery.js” type=”text/JavaScript ></script>
<script src=”Scripts/jQuery.easing.min.js” type=”text/JavaScript”></script>
<script type=”text/javascript”>
$(function () {
$(‘#slides’).slides({
play: 5000,
pause: 2500,
hoverPause: true
});
});
</script>

要注意的是,在VS2010中默认引用的jQuery是1.4.1版本。该插件使用的至少是1.9.1版本。要重新下载高版本的jQuery

下面看看效果吧

image

 

最后,以教程“PS网页设计教程XXI——在Photoshop中创建一个光质感网页设计”中的PSD为例,讲解如何切片,导出HTML,并实现图片切换效果

下图是该教程中的图片滑动部分的效果图

image

 

打开PSD文件,找寻该部分的图层,如下所示(题外话,在制作PSD的时候,合理的安排图层的顺序和分组,对后面的PSD转HTML的工作要省心不少)

image

 

切片工具在图片滑动栏附近切出一个切片,在该切片上右键选择编辑切片选项,在弹出的对话框中,进行如下的设置

image

 

image

 

打开图层面板,隐藏相关的图层,如下图所示

image

 

点击:文件 > 存储为web和设备所用的格式,图片格式选择PNG-24,点击存储按钮,在弹出的对话框中,选择HTML和图像

这是第一次导出切片,目的是获得图片滑动栏的背景。用PS打开刚才导出图片中的背景图片

image

用魔棒工具,容差设置为10,点击当中的背景,按Delete删除当中的背景。将图片保存为frame.png

image

 

将left arrow组复制到新的文件,移到左上角,设置合理的大小

image

将该文件保存为left.png

类似的复制right arrow组,将文件保存为right.png

 

将radio buttons复制到新的文件,移到左上角,设置合理的大小,将文件分别保存为current.png和pagination.png

imagecurrent.png

imagepagination.png

 

至此,图片滑动栏的图片就全部准备好了。(本教程只实现图片滑动部分)

现在,开始制作图片滑动效果

在VS2010中打开刚才导出的网页,如下图所示:

image

其中03.png的部分就是刚才图片滑动部分

按照之前的教程部分,对该网页进行修改

 

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>

<head>
<title>PSD转HTML——SlideShow</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>

<style type=”text/css”>
:focus { outline:0; }
img {     border:none;}

#container {   width:620px;
height:360px;
margin:0 auto;
position:relative;
z-index:0;
}

#frame {        position:absolute;
z-index:110;
width:620px;
height:360px;
}

#slides {        position:absolute;
z-index:100;
}

.slides_container {   width:600px;
overflow:hidden;
position:relative;
left:10px;
top:10px;
display:none;
}

.slides_container a,.slides_container a img {    width:600px;
height:320px;
display:block;
}

#slides .next,#slides .prev {    position:absolute;
top:148px;
left:-17px;
display:block;
z-index:200;
}

#slides .nextleft:594px;}

.pagination {    margin:20px auto 0px;
width:100px;
}

.pagination lifloat:left;
margin:0 5px;
list-style:none;
}

.pagination li a {     display:block;
width:10px;
height:0px;
padding-top:30px;
background-image:url(images/pagination.png);
float:left;
overflow:hidden;
}

.pagination li.current a {background-image:url(images/current.png);}

</style>

<script src=”Scripts/jquery-1.9.1.min.js” type=”text/javascript” ></script>
<script src=”Scripts/slides.min.jquery.js” type=”text/javascript” ></script>
<script src=”Scripts/jquery.easing.min.js” type=”text/javascript”></script>
<script type=”text/javascript”>
$(function () {
$(‘#slides’).slides({
play: 5000,
pause: 2500,
hoverPause: true
});
});

</script>

</head>

<body >
<table id=”__01″ width=”1200″ height=”1900″ border=”0″ cellpadding=”0″ cellspacing=”0″>
  <tr><td colspan=”3″><img src=”images/01.jpg” width=”1200″ height=”185″ alt=”” /></td></tr>
  <tr><td rowspan=”2″><img src=”images/02.jpg” width=”450″ height=”1715″ alt=”” /></td>
        <td>
<!–下面是修改部分–>
<!–图片滑动块区域—>

<div id=”container”>

<!–滑动区域–>
<div id=”slides”>
<!–滑动块背景–>
<img src=”images/frame.png” alt=”Frame” id=”frame” />
<!–上一个/下一个按钮,两个图片超链接—>
<a href=”#” class=”prev”><img src=”images/left.png” alt=”” /></a>
<a href=”#” class=”next”><img src=”images/right.png” alt=”” /></a>
<!–滑动图片,一个Div,若干图片超链接–>
<div class=”slides_container”>
<a href=”1.html”><img alt=”1″ src=”images/1.jpg” /></a>
<a href=”2.html”><img alt=”2″ src=”images/2.jpg” /></a>
<a href=”3.html”><img alt=”3″ src=”images/3.jpg” /></a>
<a href=”4.html”><img alt=”4″ src=”images/4.jpg” /></a>
<a href=”5.html”><img alt=”5″ src=”images/5.jpg” /></a>
</div>
</div>

</div>
<!–上面是修改部分—>
</td>
         <td rowspan=”2″><img src=”images/04.jpg” width=”130″ height=”1715″ alt=”” /></td>
   </tr>
<tr><td><img src=”images/05.jpg” width=”620″ height=”1355″ alt=”” /></td></tr>
</table>
</body>
</html>

 

下面是滑动栏效果图

image

 

效果不错,非常完美。不过要注意的是在PS中切片导出的网页中,少了<!DOCTYPE>标签和html标签对xml空间的定义,还需要手动添加。没有这两个,做出的效果会有所差别。

[转载]瀑布流布局——JavaScript+绝对定位 - 庄丶大虾 - 博客园

mikel阅读(917)

转载瀑布流布局——JS+绝对定位 – 庄丶大虾 – 博客园.

绝对定位方式的瀑布流布局:

一、布局

1、包围块框的容器:

<div id="main"> ... ... <div>

2、一个块框:

<div class="pin"> <div class="box"> <img src="./images/g (1).jpg"/> </div> </div>

3、初始化第一行/5个块框:

复制代码
 .pin{ padding: 15px 0 0 15px; float: left;} .box{ padding: 10px; border:1px solid #ccc;} .box img{ width:192px; height:auto;}
复制代码

 

 效果:

 二、思路:

1、设置父级main的样式:水平居中。
2、设置每个块框pin的样式:绝对定位。
3、设置窗口滚动事件的监听函数:读取数据添加块框。

JS实现:

  1-①:获取父级oParent:
  1-②:创建函数getClassObj()-通过父级id和块框类名-获取包含块框的数组。

 var oParent=document.getElementById('main');// 父级对象 var aPin=getClassObj(oParent,pin);// 获取存储块框pin的数组aPin var num=Math.floor(document.documentElement.clientWidth/aPin[0].offsetWidth);//获取-每行中能容纳的块框个数-num【窗口宽度除以一个块框宽度】
  oParent.style.cssText='width:'+iPinW*num+'px;margin:0 auto;';//用cssText属性为父级main添加居中样式:定宽+自动水平外边距
复制代码
 function getClassObj(parent,className){ var obj=parent.getElementsByTagName('*');//获取 父级的所有子集 var pinS=[];//创建一个数组 用于存储类为className的元素 for (var i=0;i<obj.length;i++) {//遍历子集、判断类名、压入数组 if (obj[i].className==className) pinS.push(obj[i]); }; return pinS;}
复制代码

 

  2-①:创建数组pinHArr-用于存储每一列高度;
  2-②:for语句遍历每个块框aPin[i],将前num个块框赋值给数组pinHArr,对超出一行能容纳的块框数num的块框绝对定位。
  2-③:用创建函数getminHIndex()-返回一个数组中的最小值

复制代码
 var pinHArr=[];//用于存储 每列中的所有块框相加的高度【随着列数的不同此数组的length也随之改变】 for(var i=0;i<aPin.length;i++){//遍历数组aPin的每个块框元素 var pinH=aPin[i].offsetHeight;//获取数组aPin的第i个块框的可见宽offsetHeight if(i<num){// pinHArr[i]=pinH; //第一行中的num个块框aPin 先添加进数组pinHArr }else{ var minH=Math.min.apply(null,pinHArr);//计算数组pinHArr中的最小值minH var minHIndex=getminHIndex(pinHArr,minH);//通过创建的getminHIndex()-获取最小值minH在数组pinHArr中的索引minHIndex aPin[i].style.position='absolute';//设置绝对位移 aPin[i].style.top=minH+'px'; aPin[i].style.left=aPin[minHIndex].offsetLeft+'px';//数组 最小高元素的高 + 添加上的aPin[i]块框高 pinHArr[minHIndex]+=aPin[i].offsetHeight;//更新添加块框后的列高 } }
复制代码
 function getminHIndex(arr,minH){ for(var i in arr){ if(arr[i]==minH)return i; } }

 

   3:设置窗口滚动事件的监听函数:读取数据添加块框。

复制代码
 var dataInt={'data':[{'src':'g (1).jpg'},{'src':'g (9).jpg'},{'src':'g (2).jpg'},{'src':'g (4).jpg'}]};//一个临时的数据对象  //下面定义窗口滚动事件监听函数 window.onscroll=function(){ if(checkscrollside()){ var oParent=document.getElementById('main');// 父级对象 for(var i=0;i<dataInt.data.length;i++){ var oPin=document.createElement('div'); //创建添加 元素节点pin oPin.className='pin'; //添加 类名 name属性 oParent.appendChild(oPin); //创建添加 子节点box var oBox=document.createElement('div'); oBox.className='box'; oPin.appendChild(oBox); var oImg=document.createElement('img');//创建添加 子节点img oImg.src='./images/'+dataInt.data[i].src; oBox.appendChild(oImg); } waterfall('main','pin');//将①②封装成函数waterfall(),将添加的节点添加到添加和定位到文档中。 }; }
复制代码

 

复制代码
 function checkscrollside(){ var oParent=document.getElementById('main'); var aPin=getClassObj(oParent,'pin'); var lastPinH=aPin[aPin.length-1].offsetTop+Math.floor(aPin[aPin.length-1].offsetHeight/2);//创建【触发添加块框函数waterfall()】的高度:最后一个块框的距离网页顶部+自身高的一半(实现未滚到底就开始加载) var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;//注意解决兼容性 var documentH=document.documentElement.clientHeight;//窗口高度 return (lastPinH<scrollTop+documentH)?true:false;//到达指定高度后 返回true,触发waterfall()函数 }
复制代码

 

 三、最终效果:

 

四、总结:此为让自己梳理一下思路,表达不太仔细连贯,仅供参考。

[转载]开发者应了解的一些SQL优化准则 - 数据库 - ITeye资讯

mikel阅读(951)

[转载]开发者应了解的一些SQL优化准则 – 数据库 – ITeye资讯.

下面介绍一些开发者在数据库操作中要注意的SQL编码准则。虽然本文不能覆盖所有的准则,但还是希望能给开发者带来些许帮助。下面就来看看在编码实践中哪些应该做,哪些不应该做。

1.  在长时间运行的查询和短查询中使用事务

如果预期有一个长时间运行的查询,并且有大量的数据输出时,开发者就应该在BEGIN TRAN 和END TRAN之间使用事务。

这样事务会在缓冲区缓存为独立事务,并会被分配特定内存,以此来提高处理速度。

2.  不要使用SELECT *

如果使用SELECT * 来选择表中的所有记录,那么一些不必要的记录也被读取、缓存,增加了磁盘的I/O和内存消耗。

3.  避免在WHERE子句中使用显式或隐式函数,比如Convert ()

4.  避免在触发器中执行长时间的操作

5.  适当使用临时表和表变量

当结果集较小的时候,请尽量使用表变量;当结果集相当大时,使用临时表。

6.  使用连接(JOIN)代替子查询(Sub-Queries)

子查询通常作为内联代码来使用,而连接(JOIN)则作为表来使用,这样速度会更快。所以,应尽量避免在连接中使用子查询。

7.  连接条件中表的顺序

在连接条件中,应尽量首先使用较小的表,然后逐步使用较大的表。

8.  循环优化

如果操作在循环内部没有任何影响,那么应尽量将操作放到循环外面,这样可以减少不必要的重复工作。因为,SQL Server优化器不会自动识别这种低效率的代码,更不会自动优化(其他一些语言的编译器可以)。

9.  参数探测

不要在正执行的SP(存储过程)中使用SP参数,这样会导致参数探测(Parameter Sniffing)。应该在声明和设置后再使用SP参数。由于这个原因,SP的行为在每次运行期间都不相同。

10.  当使用条件语句时,可以使用Index(索引)Hint(提示)

比如在SQL Server 2008中,可以使用Index hint,也可以使用fixed plan hint强制在查询中使用hint,以提高运行速度。

11.  在声明中明确指定存储过程中数据类型的大小

开发者随机声明数据类型的大小是不可取的,如:Varchar (500)。这在执行时会在缓冲区中增加不必要的预留空间。

12.  在查询中有效利用MAXDOP(最大并行度)设置

询问数据库管理员关于四核CPU可用性的设置,包括内存的设置,然后适当使用hint,可以有效改善查询速度。

13.  SQL Server 2008中的GROUPING SETS

如果数据库服务器为SQL Server 2008,那么可以在所有的Unions中使用Grouping Set来代替Group By。这样在Union中重新进行group by排序时,优化器不会每次都制定一个计划。

14.  当发生死锁时,总是使用With (nolock) 和With (rowlock)

15.  使用Update From,而不是简单的Update

Sql代码
  1. UPDATE titleauthor  
  2. SET royaltyper = 90  
  3. WHERE au_id = (SELECT au_id FROM authors  
  4. WHERE au_lname = ‘Ringer’ AND au_fname = ‘Albert’)  
  5. AND title_id = (SELECT title_id FROM titles  
  6. WHERE title = ‘Life without Fear’)  
  7. Update from  
  8. UPDATE titleauthor  
  9. SET royaltyper = 90  
  10. FROM authors a, titles t  
  11. WHERE titleauthor.au_id = a.au_id  
  12. AND a.au_lname = ‘Ringer’  
  13. AND a.au_fname = ‘Albert’  
  14. AND titleauthor.title_id = t.title_id  
  15. AND t.title = ‘Life Without Fear’  

16.  使用UNION ALL代替UNION

UNION和UNION ALL的差别就在于UNION会对数据做一个distanct的动作,而这个distanct动作的速度则取决于现有数据的数量,数量越大时间越长。因此尽量使用UNION ALL来代替UNION。

17.  避免高成本操作,如NOT LIKE

英文原文:Coding Guidelines for the Developer During Development

[转载]javascript的单元测试 - 刘璋 - 博客园

mikel阅读(864)

[转载]js的单元测试 – 刘璋 – 博客园.

  最近在优化以前的项目,重写一些地方,由于这些数据都是从客户端行情获取,自己也没 有做测试的习惯,运行的时候,数据一直出不来,也不报错,这就俺们神奇的客户端。没办法,一步一步还原调试,最后找出来了,一个函数的参数,我调用的时 候,参数的首字母变成大写了。可能最近雾大,哥每天吸收太多,变痴呆了!还有一个地方value 写成val。于是决定用单元测试,汤姆大叔曾经提到过qunit,自己搜一下,原来是JQuery团队开发的,所有JQuery的代码均由其测试。

我自己看了一下,自己深深的爱上了他,只需引用两个文件就行了

<link rel="stylesheet" href="/resources/qunit.css">
<script src="/resources/qunit.js"></script>

非常简单!
随便看一个简单的例子

 

test( "hello test", function() {  ok( 1 == "1", "Passed!" );});

ok( state, message )  state 会转换成true or false, 如果是true 则通过,反则失败

还有一个是比较常用 equal

 

test( "a test", function() {  equal( 1, "1", "String '1' and number 1 have the same value" );});

equal( actual, expected, message )  actual 是object类型,expected 也是object 适合数组,对象进行比较!

ok 和equal 属于比较常用的断言

下面是我自己做的例子

复制代码
<!DOCTYPE html>
<html>
<head>  
<meta charset="utf-8">  
<title>QUnit Example</title>  
<link rel="stylesheet" href="qunit/qunit.css">
<style> .myclass { color : red}; </style>
</head>
<body>  
<div id="qunit"></div>  
<div id="qunit-fixture"></div>  
<script src="qunit/qunit.js"></script>
<script src="qunit/jquery-1.6.3.js"></script>
<div id="mytest"></div>
</body>
</html>
<script>
function changeEl(el, text) { el.html(text); el.addClass('myclass'); } module('my first test'); test('测试插入的元素操作', function(){ var el = $('#mytest'); changeEl(el, '') equal(el.text(), '', '测试通过'); equal(el.hasClass('myclass'), true, '测试通过'); }) </script>
复制代码

下面是测试界面

 

ok,洗洗睡了

[转载]电商产品价格实时抓取小工具 - iPersia - 博客园

mikel阅读(1189)

[转载]【自主开发】电商产品价格实时抓取小工具 – iPersia – 博客园.

  各位朋友,你是不是曾经想从网店够买心仪的产品,奈何一次又一次的错过好价格呢?如果你曾经碰到过,那么下面的这个小工具也许可以帮你买到心仪的产品。

好价的出现往往随机的,而且时间短暂。机会是给有准备的人的。难道时时的关注网站,不停的刷新页面,才能等到机会么,当然不是。这种低级、乏味的事情当然要由电脑来做啦!

好,不扯皮了,下面开始介绍故事的主角:电商产品价格实时抓取小工具!

这个小工具是我在工作之余完成的,它可以实时的抓取指定商品的价格,是否有货等状态,并在达到心理价位上,弹窗提醒用户。

1、支持的电商

  • 京东(360buy)
  • 亚马逊(Amazon.cn)
  • 易迅(51buy)
  • 当当(dangdang)

2、工作原理

就是一遍又一遍的抓取产品页面,分析出产品的价格,库存等信息啦~~~~~~

3、工具特点

主要有以下五个小特点:

1)自动抓取

完全自动化

2) 价格识别

京东产品的价格是图片格式的(png),所以需要用到一些图像识别的小知识。

3) 多个产品多线程查询

通过调度器,可以同时支持多个产品查询。而通过多线程,则可以提供更快的响应!

4)设置心理价格,当价格出现时,弹窗提醒。

当你的心理价位出现时,会弹窗提醒,一定把握时机!

5)状态监控

监控当前队列数量,线程数量、执行次数和网络流量等等。

4、未来的工作

1)支持更多的电商

一号店、天猫、新蛋、亚马逊米国等等

2)完善库存状态的抓取

目前,京东商城的产品库存状态抓取不到,需要进一步研究。

5、简易使用教程

1)Add a product – 添加产品

填写名称、网址、间隔和目标价格,点击确定即可!

也可以通过配置文件来添加产品,配置文件名为:products.xml。格式如下:

<?xml version=”1.0″ encoding=”gb2312″?>
<infor>
<configuration>
<MaxAsyncInvokeCount>16</MaxAsyncInvokeCount>
<ThreadDelayTime>1000</ThreadDelayTime>
</configuration>
<productlist>
<product id=”ue900″>
<name>ue900</name>
<url>http://item.51buy.com/item-448742.html</url>
<interval>5000</interval>
<targetprice>2000</targetprice>
</product>
<product id=”ue9000″>
<name>ue9000</name>
<url>http://item.51buy.com/item-448746.html</url>
<interval>5000</interval>
<targetprice>2000</targetprice>
</product>
</productlist>
</infor>

其中configuration用来配置多线程数量和抓取时间间隔(ms).

product为产品信息,包括产品名称、网址、抓取间隔(ms,已经无效了)、目标价位即心理价位。

2)Clear Queue – 清除队列

清除队列中的页面请求。

3)Start? – 开始抓取

开始抓取价格信息。

4)Stop? – 停止抓取

停止抓取价格信息。

  6、下载试用

    http://files.cnblogs.com/junier/ProductClawer.zip

[转载]微信公众平台消息接口开发(2)启用接口2 - txw1958 - 博客园

mikel阅读(1016)

[转载]微信公众平台消息接口开发(2)启用接口2 – txw1958 – 博客园.

微信 平台 消息 接口 启用
作者:http://txw1958.cnblogs.com/

 

本系统教程以微信公众平台应用天气神(账号WeatherGod,支持国内近400个城市天气的名称、拼音、区号、邮编以及语音触发模式查询)为例,讲解微信接口开发过程。欢迎大家关注该账号并使用语音方式查询当地天气,二维码见底部。

 

本文是微信公众平台消息接口开发(1)启用接口 的下部分

 

三、服务器没有响应Token验证的解决方法

1.  技术分析法

这次我们在代码里面加入跟踪http记录的方法来查看我们自己的服务器收到了请求没有回应,还是微信根本没有发请求过来。
通过调用系统环境变量$_SERVER,可以查看到HTTP请求的信息,其中两项重要的是

$_SERVER["REMOTE_ADDR"]  //记录来访者的IP,我们记录微信服务器是否访问过
$_SERVER["QUERY_STRING"]  //查询请求字符串

把其加入代上面的代码中,并且将其写入到本地文件中来,全部代码如下:

复制代码
<?php define("TOKEN", "天气神"); date_default_timezone_set('Asia/Hong_Kong'); traceHttp(); $wechatObj = new wechatCallbackapiTest(); $wechatObj->valid(); class wechatCallbackapiTest { public function valid() { $echoStr = $_GET["echostr"];    //随机字符串
        if($this->checkSignature()){ echo $echoStr; exit; } } private function checkSignature() { $signature = $_GET["signature"];    //微信加密签名
        $timestamp = $_GET["timestamp"];    //时间戳
        $nonce = $_GET["nonce"];            //随机数

        $token = TOKEN; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr); //sha1加密后与签名对比
        if( sha1(implode($tmpArr)) == $signature ){ return true; }else{ return false; } } } function traceHttp() { logger(""); logger("REMOTE_ADDR:".$_SERVER["REMOTE_ADDR"].((strpos($_SERVER["REMOTE_ADDR"], "101.226"))?" From WeiXin":" Unknown IP")); logger("QUERY_STRING:".$_SERVER["QUERY_STRING"]); } function logger($content) { file_put_contents("log.html", date('Y-m-d H:i:s  ').$content."<br>", FILE_APPEND); } ?>
复制代码

 

这样,当我们提交之后,就会生成一个log.html文件在当前目录
用浏览器直接打开填写的url,也会写一次文件。

直接用浏览器打开url+log.html路径,我的记录如下:

2013-01-30 10:15:18 
2013-01-30 10:15:18 REMOTE_ADDR:212.179.24.103 Unknown IP 2013-01-30 10:15:18 QUERY_STRING:

在微信中点击提交一次,再一次生成记录,如下:

2013-01-30 10:15:49 
2013-01-30 10:15:49 REMOTE_ADDR:101.226.89.83 From WeiXin 2013-01-30 10:15:49 QUERY_STRING:signature=eded789463180edf6c13691398d0cb4c85fb0e23&echostr=5838479218127813673×tamp=1359100969&nonce=1359376876

从上可以看到,这次IP来自101.226.89.83,是微信的IP,我把这个IP加入到代码中自行判断了
另外它的查询请求和官方指南中描述的一致,所以可以确定,微信把消息提交到服务器中了。提交应该成功。如果不成功,原因在于自己这边。

 

2. 万能成功法

如果你用上面的白方法还没提交成功,被接口启用问题已经折腾了N次,心灰意冷,打算退出微信接口开发,那你一定要再多看一眼下面的万能方法。
再看一下验证部分的源代码

复制代码
$wechatObj = new wechatCallbackapiTest(); $wechatObj->valid(); class wechatCallbackapiTest { public function valid() { $echoStr = $_GET["echostr"];        //随机字符串
        if($this->checkSignature()){ echo $echoStr; exit; } }
复制代码

其实就调用一下valid()函数,在valid()函函数中检查签名,如果签名成功,就应答echoStr。
如果我们跳过这个签名呢……

复制代码
    public function valid() { $echoStr = $_GET["echostr"]; if(true){ echo $echoStr; exit; } }
复制代码

经过试验,提交也成功。证明也是可行的。但是。。。。
好像,这后面存在着微信一个很大的漏洞,很大很大,可能是无穷大!!!

 

原文地址:http://www.cnblogs.com/txw1958/archive/2013/01/31/weixin-if2-enable.html 

 

 

———————————————————————————————————

关注天气神(账号WeatherGod)方法:

1. 依次进入以下路径:朋友们—>添加朋友—>搜号码,输入WeatherGod,不区分大小写,点击查找,然后点击关注

2. 扫描二维码:

 

猜你喜欢:微信平台上第一个不输入文字就能查询的天气预报

■ 原文网址:http://txw1958.cnblogs.com/
■ 版权声明:自由转载-非商用-非衍生-保持署名

[转载]仿微博字符统计和本地存储功能的实现 - JK_Rush - 博客园

mikel阅读(872)

[转载]仿微博字符统计和本地存储功能的实现 – JK_Rush – 博客园.

1.1.1 摘要

随着移动设备和Web应用的普及,为了更好的便于用户的使用,对于网页或应用程序的用户体验要求就越来越高,确实是这样,作为用户更喜欢选择用户体验效果好的网站或应用程序,所以作为开发者的我们就需要开发出更人生化的应用程序了。

相信许多人有使用微博的经验,像微博这样的社交平台,好的用户体验就变得尤其重要了。

例如:我们在发微博时,文本框会实时地提示我们剩余字符数,这样人性化的提示方便了用户知道微博字数的限制,同时也限制了用户的输入字数。

有一句话我们要牢记在心的是:凡是输入,必有限制;凡是输入,必须校验。

在接下来的博文中,我们将介绍如何实现输入字符实时提示功能和本地存储(localStorage)技术。

本文目录

1.1.2 正文

JQuery字符统计插件

现在,我们以新浪微博发送微博输入框为例子,介绍使用JQuery实现实时提示用户剩余字符数。

新浪微博是限制140个中文(280个英文),当然还有各种其他字符空格的情况,在用户输入达到限制之前或达到了,好的用户体验应该提示用户接近或达到了限制,当然我们可以通过使用不同颜色或加粗字体方式提示用户。

charcount0

图1新浪微博用户输入限制

字符数统计插件会在输入框后创建一个同级元素span,它用来显示当前剩余字符数,当触发输入框的keyup、keydown和change事件时,实时修改span中剩余字符数,如果剩余字符数接近“warning”(接近零)修改CSS样式提示用户接近输入限制。

当剩余字符达到“warning”时,在span元素中添加相应的样式类,当剩余字符等于或大于输入限制时,添加相应的样式类提示用户已经超出字符数限制。

我们通过字符数统计插件在页面中动态地插入如下代码:

<!-- adds element dynamic --> <span class="counter">140</span>

在默认情况下,字符限制是140个,当可输入字符数少于等于25个提示用户,当可输入字符数少于等于0时,提示用户字符数超出了限制。下面我们定义默认情况下条件对象:

// The default limitation. var defaults = {
    allowed: 140,
    warning: 25,
    css: 'counter',
    counterElement: 'span',
    cssWarning: 'warning',
    cssExceeded: 'exceeded',
    counterText: '' };

上面,我们定义了defaults对象,它包含allowed、warning、css、cssWarning和cssExceeded等属性,通过修改defaults对象属性,我们可以很方便修改字符统计插件。

Allowed:允许输入的字符数。

Warning:提示用户剩余字符数接近限零。

Css:添加到counter元素的CSS样式类名。

cssWarning:警告提示样式。

cssExceeded:超出字符限制提示样式。

接下来,我们在字符统计插件中定义方法calculate(),它计算当前剩余字符数,如果到达了警告范围则在页面中增加样式类“warning”,当剩余字符数少于等于零时,在页面中增加样式“exceeded”。

/*** * Calculates the char * @param obj */ function calculate(obj) {

    // Get the count. var count = getLength($(obj).val());
    var available = options.allowed - count;

    if (available <= options.warning && available >= 0) {
        $(obj).next().addClass(options.cssWarning);
    }
    else {
        $(obj).next().removeClass(options.cssWarning);
    }
    if (available < 0) {
        $(obj).next().addClass(options.cssExceeded);
    }
    else {
        $(obj).next().removeClass(options.cssExceeded);
    }
    $(obj).next().html(options.counterText + available);
}

我们又定义方法getLength(),当输入字符是中文时totLen加1,如果是英文字符或数字时totLen加0.5(默认允许输入140个中文字符)。

/** * Get the length of char. * @param str * @return {Number} */ function getLength(str) {
    var totLen = 0;
    for (var i = 0; i < str.length; i++) {
        // If the char is Chinese. if (str.charCodeAt(i) > 256) {
            totLen += 1;
        }
        else {
            totLen += 0.5;
        }
    }
    return Math.floor(totLen);
}

接下来,我们在控件中绑定keyup(),keydown()和change()事件方法,当页面对象触发keyup(),keydown()或change()事件方法时,调用calculate()方法计算当前剩余的字符数,并且添加相应的CSS样式到页面中。

// Binds text area keyup, keydown and change event. this.each(function() {
    $(this).after('<' + options.counterElement + ' class="' + options.css + '">' + options.counterText + '</' +
                options.counterElement + '>');
    calculate(this);
    $(this).keyup(function() { calculate(this), storeWeibo(this) });
    $(this).keydown(function() { calculate(this), storeWeibo(this) });
    $(this).change(function() { calculatea(this) });
});

Web Storage

现在,我们基本实现了jQuery字符数统计插件功能了,相信许多人都注意到,如果我们在发微博时,没有发送出去的微博下次打开页面,发送框依然保存着我们未发送的微博,即使关闭浏览器重新打开页面,我们没发送的信息依然存在。

其实,要实现这一个功能方法是多种多样的,例如我们可以使用:CookiesSession等技术。

随着HTML5规范的制定,与此同时W3C制定了网络存储(Web Storage)的规范,它提供将数据存储在客户端中,直到Session过期(会话存储)或超出本地容量(本地存储),它比传统的Cookies存储功 能更强大、更容易实现和容量更大(大部分浏览器支持5M的本地存储)。

会话存储

会话存储:它将数据保存在会话中,一旦我们关闭浏览器选项卡时,会话中的数据将失效。

本地存储

本地存储:当数据需要持久地保存在客户端中,这时我们可以使用本地存储(Local Storage),它是以key/value 的形式来存储数据的,如果关闭了页面或浏览器后,重新打开页面数据依然存在,它提供了数据的持久保存。一个简单的应用是:记录用户访问页面的次数。

charcount1

图2存储空间的对比

接下来,我们将介绍如何使用本地存储保存用户数据。

由于,localStorage提供了setItem(),getItem(),removeItem(),key()和clear() 5个方法,和一个属性length,具体定义如下:

// Storage definition. interface Storage {
  readonly attribute unsigned long length;
  DOMString key(in unsigned long index);
  getter any getItem(in DOMString key);
  setter creator void setItem(in DOMString key, in any value);
  deleter void removeItem(in DOMString key);
  void clear();
};

在现代浏览器中使用本地存储是非常的简单,我们只需在JavaScript代码中直接调用localStorage对象的方法或属性就OK了。

// stores the username 'jkrush', // then get the username. localStorage.setItem('username', 'jkrush');
var userName = localStorage.getItem('username');

上面,我们通过调用localStorage的setItem()和getItem()方法实现数据的存储和获取,由于localStorage是 以Key/Value形式存储数据的,所以我们在存储时需要提供Key/Value值,然后调用getItem()方法获取存储在Key中的值。

由于本地存储是以Key/Value的形式进行存储的,那么我们可以很容易存储字符串类型的数据,如果我们需要存储对象类型,那么本地存储就显得捉襟见肘了。

假设,我们把一个student对象存储到localStorage中,具体代码如下:

// Defines a student object. var student = {
    name: 'JK_Rush',
    age: '26',
    sex: 'male' };

// Prints student object console.log(student);

// Stores student object. // Gets student object again. localStorage.setItem('student', student);
console.log(localStorage.getItem('student'));

charcount

图3 localStorage存储对象

通过上面示例,我们注意到在Firebug的控制台中输出的并不是真正的student对象,而是student对象的信息而已。

那么我们该如何把对象存储到localStorage中呢?其实,我们可以把对象序列化为JSON数据进行存储,最后通过反序列化把JSON数据转换为对象。具体实现如下:

// Defines a student object. var student = {
    name: 'JK_Rush',
    age: '26',
    sex: 'male' };

console.log(student);

// Serializes the object to json string. localStorage.setItem('student', JSON.stringify(student));

// Deserializes the json string to object. console.log(JSON.parse(localStorage.getItem('student')));

上面示例中,在存储student对象之前,我们使用JSON的stringify()方法序列化对象为JSON字符串,然后存储到localStorage中;如果我们要获取student对象,只需使用JSON的parse()方法反序列化字符串为对象。

charcount3

图4 localStorage存储对象

上面,我们实现了student对象转换为JSON格式字符串存储到localStorage中,接下来,我们在前面的例子中添加localStorage功能,具体代码如下:

/** * Store user data into local storage. * @param obj */ function storeWeibo(obj) {

    // Checks the browser supports local storage or not. if (window.localStorage) {
        localStorage.setItem('publisherTop_word', $(obj).val());
    }
    else {

        // For instance, ie 6 and 7 do not support local storage, // so we need to provider other way. window.localStorage = {
            getItem: function(sKey) {
                if (!sKey || !this.hasOwnProperty(sKey)) { return null; }
                return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g,
                            "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1"));
            },
            key: function(nKeyId) {
                return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]);
            },
            setItem: function(sKey, sValue) {
                if (!sKey) { return; }
                document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
                this.length = document.cookie.match(/\=/g).length;
            },
            length: 0,
            removeItem: function(sKey) {
                if (!sKey || !this.hasOwnProperty(sKey)) { return; }
                document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
                this.length--;
            },
            hasOwnProperty: function(sKey) {
                return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
            }
        };
        window.localStorage.length = (document.cookie.match(/\=/g) || window.localStorage).length;
    }
}

现在我们在自定义字符统计插件(jQuery.charcount.js)中,添加方法storeWeibo(),首先我们判断当前浏览器是否支持 localStorage,主流的浏览器如:Chrome、Firefox、Opera、Safari以及IE 8都支持本地存储(localStorage)和会话存储(sessionStorage)。

如果浏览器支持本地存储,那么我们可以直接调用localStorage的setItem()方法,将textarea中的数据存储起来;当我们再 次打开页面或浏览器,首先检查localStorage是否存储了相应的数据,如果有数据存储,那么我们再次把数据取出显示到textarea中。

但由于一些用户可能使用旧版的浏览器(如:IE6和IE7),考虑到兼容我们必须提供支持旧版浏览器的方案。

我们知道旧版浏览器(如:IE6和IE7),它们支持Cookies的持久化存储方式,所以我们使用Cookies实现getItem(), setItem()和removeItem()等方法。

charcount4

charcount5

图5 主流浏览器支持Web Storage

现在,我们已经完成了字符统计插件jQuery.charcount.js,由于时间的关系我们已经把发送框的界面设计好了,具体的HTML代码如下:

<!-- From design--> <body> <form id="form" method="post"> <h2> 有什么新鲜事想告诉大家?</h2> <div> <label class="mali_oglas_kategorija" for="message"> 有什么新鲜事想告诉大家?<b></b></label> <textarea id="weiboMsg" placeholder="请Fun享"></textarea> <span class="counter"></span> <input onclick="SaveCache()" type="submit" value="发布"> </div> </form> </body>

charcount6

图6 发送框界面设计

接下来,我们在页面代码中引用jQuery库和自定义字符统计插件jquery.charcount.js,具体代码如下:

<!-- Adds Javascript reference --> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script> <script type="text/javascript" src="./js/jquery.charcount.js"></script> 

上面,我们直接引用Google提供的jQuery库,当然我们也把jQuery库下载到本地,然后引入到项目中,接下来我们在HTML页面中添加调用字符统计插件的代码,具体代码如下:

<!-- When document ready invokes charCount function--> <script type="text/javascript"> $(document).ready(function () {
        // Uses default setting. $("#weiboMsg").charCount();
    });
</script>

上面,我们完成了在页面代码中调用字符统计插件,每当我们在文本框中输入字符时,都会实时地显示剩余的字符数,而且我们在文本框中输入的字符都会保存到localStorage中。

接下来,我们分别在Chrome和Firefox中查看保存在localStorage中的数据。

首先,我们打开Chrome的“开发者工具”(Ctr+Shift+I),然后我们选择“Resources”选项,这时我们就可以看到保存在localStorage中的数据了。

charcount10

图7 Chrome的本地存储

同样,我们打开Firefox的“Firebug”(F12),然后我们选择“DOM”选项,这时我们需要查找window的对象localStorage,这样就可以看到保存在localStorage中的数据了。

charcount9 图8 Firefox的本地存储

我们知道IE8也是支持localStorage对象的,但是我做测试时候发现IE8中一直提示 localStorage对象未定义,后来我上Stackoverflow查看了一下,有人说在IE8中,localStorage对象是依赖于域名的, 所以需要运行在Web服务器中才可以成功保存数据到localStorage中。

 

 

1.1.3 总结

本文通过微博发送框例子介绍了如何定义jQuery字符统计插件和本地存储技术,首先,我们知道限制用户输入是必须的,但如何有效而且人性化提示用户输入限制呢?这里我们通过定义一个jQuery插件,动态地统计剩余字符数。

我们注意到微博通过本地存储技术,保存用户在发送框中的数据,一旦数据发送了就清空本地存储,反之保存用户的输入。

参考

Demo下载

[转载]Json.Net 学习笔记(一) - 资源收集 - 博客园

mikel阅读(1033)

[转载]Json.Net 学习笔记(一) – 资源收集 – 博客园.

使用Newtonsoft.Json这是一个开源的Json.Net库。

下载地址:http://json.codeplex.com/releases/view/50552。当前版本为 Release 8

从下载到的源代码中获取Newtonsoft.Json.Net20.dll,添加到自己的工程中。

using Newtonsoft.Json;

定义类:

 public class Message
{
public string Address { get; set; }
[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
public object Body { get; set; }
}
public class SearchDetails
{
public string Query { get; set; }
public string Language { get; set; }
}

测试:

           Message message = new Message
{
Address = “http://google.com“,
Body = new SearchDetails { Query = “Json.Net”, Language = “en-us” }
};
string jsonMsg = JsonConvert.SerializeObject(message, Formatting.Indented);//Indented表示以缩进形式显示结果
System.Diagnostics.Debug.Write(jsonMsg);
Message deserialized = JsonConvert.DeserializeObject<Message>(jsonMsg);
SearchDetails searchDetails = (SearchDetails)deserialized.Body;
Response.Write(searchDetails.Query + “,” + searchDetails.Language + “<br/>”);

Debug输出结果格式:

{
“Address”: “http://google.com“,
“Body”: {
“$type”: “TestJsonSerialization.SearchDetails, TestJsonSerialization”,
“Query”: “Json.Net”,
“Language”: “en-us”
}
}

注:1.JsonProperty标记字段或属性,用来控制它作为一个Json对象的属性序列化。

       2.TypeNameHandling 用来为Json序列化指定类型名。它有几个枚举值:

Member Description
None Do not include the .NET type name when serializing types.
Objects Include the .NET type name when serializing into a JSON object structure.
Arrays Include the .NET type name when serializing into a JSON array structure.
Auto Include the .NET type name when the type of the object being serialized is not the same as its declared type.
All Always include the .NET type name when serializing.