jQuery中的queue和dequeue是一组很有用的方法,他们对于一系列需要按次序运行的函数特别有用。特别animate动画,ajax,以及timeout等需要一定时间的函数

queue和dequeue的过程主要是:
1,用queue把函数加入队列(通常是函数数组)
2,用dequeue将函数数组中的第一个函数取出,并执行(用shift()方法取出并执行)

也就意味着当再次执行dequeue的时候,得到的是另一个函数了
同时也意味着,如果不执行dequeue,那么队列中的下一个函数永远不会执行

对于一个元素上执行animate方法加动画,jQuery内部也会将其加入名为 fx 的函数队列
而对于多个元素要依次执行动画,则必须我们手动设置队列进行了。

一个例子,要两个div依次向左移动,点击这里查看

div {
background:#aaa;
width:18px;
height:18px;
position:absolute;
top:10px;
}

如果只是轮流移动次数较少,可以使用animate的回调函数来做,一个动画放在另一个动画的回调里边
比如

$(“#block1″).animate({left:”+=100″},function() {
$(“#block2″).animate({left:”+=100″},function() {
$(“#block1″).animate({left:”+=100″},function() {
$(“#block2″).animate({left:”+=100″},function() {
$(“#block1″).animate({left:”+=100″},function(){
alert(“动画结束”);
});
});
});
});
});
但这种方法当动画较多的时候简直是残忍。

此时利用queue和dequeue则显得简单很多:

var FUNC=[
function() {$("#block1").animate({left:"+=100"},aniCB);},
function() {$("#block2").animate({left:"+=100"},aniCB);},
function() {$("#block1").animate({left:"+=100"},aniCB);},
function() {$("#block2").animate({left:"+=100"},aniCB);},
function() {$("#block1").animate({left:"+=100"},aniCB);},
function(){alert("动画结束")}
];
var aniCB=function() {
$(document).dequeue(“myAnimation”);
}
$(document).queue(“myAnimation”,FUNC);
aniCB();
1,我首先建议建立了一个函数数组,里边是一些列需要依次执行的动画
2,然后我定义了一个回调函数,用dequeue方法用来执行队列中的下一个函数
3,接着把这个函数数组放到document上的myAnimation的队列中(可以选择任何元素,我只是为了方便而把这个队列放在document上)
4,最后我开始执行队列中的第一个函数

这样做的好处在于函数数组是线性展开,增减起来非常方便。
而且,当不要要继续进行接下来动画的时候(比如用户点了某个按钮),只需要清空那个队列即可。而要增加更多则只需要加入队列即可

//清空队列
$(document).queue(“myAnimation”,[]);
//加一个新的函数放在最后
$(document).queue(“myAnimation”,function(){alert(“动画真的结束了!”)});
以前发过一个wait插件,用于让动画之间可以暂停一段时间

http://shawphy.com/2008/07/enabling-settimout-within-chained-functions-in-jquery.html

可以看一下,他也就是利用了这个原理,默认在fx中插入一个timeout,放到队列中,直到timeout结束后才执行dequeue继续执行队列中的下一个函数。

这当然也可以用于ajax之类的方法,如果需要一系列ajax交互,每个ajax都希望在前一个结束之后开始,之前最原始的方法就是用回调函数,但这样太麻烦了。同样利用queue添加队列,每次ajax之后的回调中执行一次dequeue即可。

如果没有使用jQuey库,也可以自己写段简易代码来解决这个问题。

来自:http://shawphy.com/2009/04/how-to-use-queue-and-dequeue.html

 

兼容浏览器的清空select的方法

On 2010年10月10日, in JavaScript, jquery, by admin
主旨: 清空select的兼容做法为 obj.options.length=0;

在用jQuery做类似多级联动效果时遇到的问题,具体流程为:

从api接口返回数据生成表单项,如下:
<select name=”PARAM02″ id=”PARAM02″>…</select>  //下拉1
<select name=”PARAM03″ id=”PARAM03″>…</select> //下拉2
如上,下拉1 为一个分类,下拉2为分类下的子项,下拉1的change事件动态改变下拉2的内容
之前代码是(部分代码省略):
var AttachCataID = json . Items [ i ]. AttachCataID ;
function ( c , a ){
fitem . change ( function (){
var value = $ ( this ). val ();
var cataId = $ ( ”#” + a ). attr ( ”cid” );
var url = Urls . Catalog + ”?zid=” + zid + ”&ActionID=” +actionid + ”&CataLogID=” + cataId + ”&CataValue=” + value + ”&CurrentPage=1&PageSize=” + that .pageSize + ”&” + that . prevUrl + ”&” + that . sufUrl ;
$ ( ”#” + a ). html ( ”<option>载入中…</option>” );
$ . getJSON ( url , function ( json ){
$ ( “#” + a ). empty ();
//返回状态信息
if ( json . StatusInfo ) {
var Status = json . StatusInfo . Status ;
var ReturnCode = json . StatusInfo . ReturnCode ;
that . showLoading ( ReturnCode );
//隐藏loading
if ( Status == 1 ) {
setTimeout ( that . hideLoading , 1000 );
//处理数据
if ( json . Items ) {
var len = json . Items . length ;
forvar i = 0 ; i < len ; i ++) {
var Text = json . Items [ i ]. Text ;
var Value = json . Items [ i ]. Value;
var aopt = $ ( ”<option value=’” +Value + ”‘>” + Text + ”</option>” );
$ ( ”#” + a ). append ( aopt );
}
}
}
else {
return false ;
}
}
else {
return false ;
}
})
})
})( CataLogID , AttachCataID )
以上代码在chrome Firefox 等浏览器均能正常运行 而唯独在IE有问题,具体情况为,大概我在下拉1中触发了change事件后,下拉2中也出现了加载效果,但是显示内容没有更新,而当鼠标在下拉2中选择时,却发现其实内容已更新,只是显示的不一致,用开发者工具调试发现html代码也没有更新(在遨游浏览器中下拉2不能选择,鄙视之).
回头翻了下之前jQuery处理select的小工具代码,发现用的empty()没问题,可能是因为其没有运行在IE中的缘故。
不过这个问题不解决实在是不爽
随后精简了一下代码并用obj.options.length=0;来清空下拉2
if ( json . Items [ i ]. AttachCataID ) {
var AttachCataID = json . Items [ i ]. AttachCataID ;
fitem . bind ( ”change” , function (){
var value = $ ( this ). val ();
var cataId = $ ( ”#” + AttachCataID ). attr ( ”cid” );
var url = Urls . Catalog + ”?zid=” + zid + ”&ActionID=” +actionid + ”&CataLogID=” + cataId + ”&CataValue=” + value + ”&CurrentPage=1&PageSize=” + that .pageSize + ”&” + that . prevUrl + ”&” + that . sufUrl ;
$ ( ”#” + AttachCataID ). html ( ”<option>载入中…</option>” );
$ . getJSON ( url , function ( json ){
$ ( ”#” + AttachCataID ). get ( 0 ). options . length = 0 ;
if ( json . Items ) {
$ . each ( json . Items , function ( i , item ){
var Text = item . Text ;
var Value = item . Value ;
var aopt = $ ( ”<option value=’” + Value + ”‘>” + Text + ”</option>” );
$ ( ”#” + AttachCataID ). append ( aopt );
})
else {
return false ;
}
})
})
}
 

JavaScript正则替换可变字符串

On 2010年09月30日, in Ajax, JavaScript, by admin

标题有些拗口,看不懂标题的看下文,看不懂下文的call me~

今天在做追信API2.0处理分页时用到了正则替换,直接贴代码:


var re = /CurrentPage=\d*&{1}/g ;
uri = uri . replace ( re , function (){
return “CurrentPage=” + nextPage + ”&” ;
});
具体情况是:
注意:只有一个api接口,即List.json。
在做加载内容列表时,会有分类和最新两种情况:加载分类会传递参数到条目(类似最新),这时就会把参数带到URL中,然后通过改变后的URL用加载最新的方式加载列表,注意,此时页面参数已经在URL里面;加载分类则简单很多,每次加载都会更新页码。
为了解决在点击分类后又点击加载更多(分页)URL参数不会更新的问题,这里用了正则替换的方法,就是上面的代码部分,其中Uri为点击分类传递过来的URL.
处理分页代码:
//全部
if ( json . PageInfo ) {
var CurrentPage = json . PageInfo . CurrentPage ;
var TotalPages = json . PageInfo . TotalPages ;
var PageSize = json . PageInfo . PageSize ;
listbox . find ( ”.more” ). remove ();
if ( CurrentPage < TotalPages ) {
var nextPage = Number ( CurrentPage + 1 );
if ( uri ) {
var re = /CurrentPage=\d*&{1}/g ;
uri = uri . replace ( re , function (){
return “CurrentPage=” + nextPage + ”&” ;
});
}
var more = $ ( ”<div url=’” + uri + ”‘ nextpage=’” + nextPage + ”‘ class=’more’/>” ) ||”" ;
more . html ( ”更多?” );
function ( n ){
more . click ( function (){
$ ( this ). html ( ”加载中…” );
that . loadList ( zid , actionid , n , 1 , uri , $ ( this ));
})
})( nextPage );
listbox . append ( more );
}

}

 

这个是之前优化追信客户端时写的代码,今天提取出来又补充了点东西(由于之前客户端没有涉及到下拉菜单(select),所以没有针对它做适配,现已加上).

当时的需求是这样的:根据接口返回的信息生成表单,所以不能预先知道表单的名(name)和值(value)。不同的栏目生成不同的表单,同一个函数处理这些生成的表单,最重要的一点是:当在不能用jQuery的环境中(nokia widget).

HTML代码:

<form id=”testForm”>

<label>姓名:</label><input type=”text” name=”user”/><br/>

<label>密码:</label><input type=”password” name=”pass”/><br/>

<label>性别:</label><input type=”radio” name=”sex” value=”1″/>男<input type=”radio” name=”sex” value=”0″/>女<br/>

<label>出生年份:</label><select name=”year”><option value=”1980″>1980</option><option value=”1981″>1981</option><option value=”1982″>1982</option></select>(option务必加value属性)<br/>

<label>喜好:</label><input type=”checkbox” name=”fav” value=”0″/>读书<input type=”checkbox” name=”fav” value=”1″/>上网<input type=”checkbox” name=”fav” value=”2″/>旅游<br/>

<button name=”more”>test</button><br/>

<input type=”submit” name=”sub” id=”formSub” value=”提交”/>

</form>

JS代码:

<script type=”text/javascript”>

function $(ele){

if (typeof ele == “object”) {

return ele;

}

else

if (typeof ele == “string” || typeof ele == “number”) {

return document.getElementById(ele.toString());

}

else {

return false;

}

}

function serialize(formID){

var form;

if (typeof formID == “object”) {

form = formID;

}

else {

form = $(formID);

}

var param = “”;

for (var i = 0; i < form.length; i++) {

if (form[i].type == “radio” || form[i].type == “checkbox”) {

if (!form[i].checked) {

continue;

}

}

if (form[i].type == “submit”) {

continue;

}

var name = form[i].name;

var val = form[i].value;

param += name + “=” + val + “&”;

}

return param.substr(0, param.length – 1);

}

$(“formSub”).onclick = function(){

$(“result”).innerHTML = serialize(“testForm”);

return false;

}

</script>

观看演示:http://www.showfan.cn/demo/serialize.html

 

最近在用jquery的ajax方法传递接收json数据时发现一个问题,那就是返回的data数据,有时候可以直接作为json数据使用,可有时候又不行。

经过网友指出,这个问题已经有了比较明确的结论,那就是jquery ajax方法的complete方法是不会处理dataType的,所以如果你是在complete里面试图直接用json数据是不可行的,必须先通过eval。

以下是我原来的文章,大家仅作个参考,已经没有太大价值了。

$.ajax方法如下:

Java代码
$.ajax({
type: “POST”,
url: ctxRoot+’FolderAction!saveInformSetting.action’,
data: ‘jsonStr=’ + inform_settingListStr,
dataType: “json”,
complete: function(data){
//在这里做些事情,假设返回的json数据里有name这个属性
//有时候可以直接data.name或者data['name']去访问
//但有时候,却要通过var jsonData = eval(“(“+data.responseText+”)”);才可以通过jsonData.name访问,而且这种情况下,需要是complete而不是success
}
});

ok, 问题已经在代码的注释里面说明了,下面说下造成这两种不同的原因。

先说明第一种情况:

我发现能够直接 data.属性名访问的情况,服务器端代码一定是直接renturn的一个常量字符串。
什么是常量字符串呢,有些人可能不太清楚,常量字符串就是指直接用“”组成的字符串,没有定义String 变量直接把一串“”print到前台的情况,就可以直接data.属性名访问,而且jquery端只要写success就可以拿到。

下面是造成要eval并且不能进入success的原因:

这种情况是因为服务器端向外print的时候是一个String对象,通常此类问题在我的代码里是因为后台json比较复杂,在组织的时候我用到了StringBuffer,然后最后print的时候print的是StringBuffer对象的toString,所以就相当于print了一个String对象

这种情况下jquery的ajax方法就不会进入success方法,只能用complete接收,并且想要解析data里的json数据的话,必须对data.responseText进行eval

除此两点,还有需要注意的是,如果你使用的是jq1.4,那么他对json的格式有着更严格的要求,所有的key和属性都要用双引号标注起来,虽然key不用双引号原生的js是允许的,但是jq1.4似乎有这个要求。

以上就是我个人对于这一问题的一些想法和体会,如果有片面或者不正确的地方,欢迎大家评论指正,谢谢。

From:http://www.javaeye.com/topic/722028

 

这次是我第四次参加《web标准交流会》,因为最近工作挺忙,所以没能及时关注WEB标准交流会网站,当我看到本期话题《前端工程师应该如何学习javascript》时,眼前一亮。由于前几次话题大多是分享工作中部门之间配合,而很少有这种纯技术的话题(也可能是我参加的次数不多,错过了以前的技术讨论).

这次交流会解决了我最近工作中遇到的一个JavaScript跨域调用数据的问题。就我个人来说,平时工作中使用Ajax无非以下几种:

1.基本调用(代码片段):

var request=new XMLHttpRequest(); //仅作参考

request.open(“GET”,url,true);

request.onreadystatechange=function(){…};

request.send(”);

2.使用jQuery框架(代码片段):

$.ajax({

type:”GET”,

url:”",

data:{},

beforeSend:function(){…},

success:function(){….},

error:function(){…}

})

3.jQuery的$.getJSON(url,data,callback),即JSONP技术;

和上面2相比差异如下:

优点 :跨域;

缺点:不提供错误处理,如果动态插入的代码正常运行,你可以得到返回,但是如果失败了,那么什么都不会发生。你无法获得一个404的错误,也不能取消这个请求。我处理的方式可见$.getJSON的错误处理(原创)


重点来了:

虽然上面这些方法在处理常规的交互已经足够了,不过我有个需求:不使用jQuery框架实现JSONP功能。其实这个从原理上来讲写起来并不难,

下面是我的最初版:

定义函数:

function getJSON ( url , func ){

if (! document . getElementById ){
return false ;
}
if ( document . getElementById ( ”jsonscript” )){
var oldscript = document . getElementsByTagName ( ”script” );
for ( var i = 0 ; i < oldscript . length ; i ++){
if ( oldscript [ i ]. getAttribute ( ”src” ) == url ) {
oldscript . parentNode . removeChild ( oldscript );
}
}
}
var script = document . createElement ( ”script” );
script . setAttribute ( ”src” , url );
script . setAttribute ( ”id” , ”jsonscript” );
document . getElementsByTagName ( ”head” )[ 0 ]. appendChild ( script );

}

回调函数:

function parseDZList ( json ){
var show = document . getElementById ( ”show” );
var Status = json . StatusInfo . Status ;
var items = json . Items ;
for ( var i = 0 ; i < items . length ; i ++){
show . innerHTML += items [ i ]. ZName ;
}

}

页面调用:

window.onload = function (){
getJSON ( ”http://api.zhui.cn/content/ZIDList.json?jsoncallback=parseDZList” );

}

虽然可以实现效果,但是代码凌乱,不便重用。


今天在会上请教JavaScript大牛后代码如下:

定义函数:

function getJSON(url, func){

if (!document.getElementById) {

return false;

}

if (document.getElementById(“jsonscript”)) {

var oldscript = document.getElementsByTagName(“script”);

for (var i = 0; i < oldscript.length; i++) {

if (oldscript[i].getAttribute(“src”) == url) {

oldscript.parentNode.removeChild(oldscript);

}

}

}

var script = document.createElement(“script”);

var rnd=parseInt(Math.random()*1e8);

url+=”?jsoncallback=callback”+rnd;

script.setAttribute(“src”, url);

window["callback"+rnd]=func;

script.setAttribute(“id”, “jsonscript”);

document.getElementsByTagName(“head”)[0].appendChild(script);

}

回调函数:

function parseDZList(json){

var show = document.getElementById(“show”);

var Status = json.StatusInfo.Status;

var items = json.Items;

for (var i = 0; i < items.length; i++) {

var ZIMG=items[i].ZIMG

ZIMG=ZIMG.replace(“{0}”,”64×64″)

show.innerHTML += ”

  • “+items[i].ZName+”
  • “;

    }

    }

    页面调用:

    window.onload = function(){

    getJSON(“http://api.zhui.cn/content/ZIDList.json”,parseDZList);

    }

    后来在群里分享时Along对var rnd=parseInt(Math.random()*1e8)提出自己的观点,并提示可以用生成数组的方式来处理,更大程度上避免了碰撞.不过还好这个只是为了避免缓存,不用太花心思.为了方便我还是使用了数组。

    然后小肥猪(冯恒),在群里发了一段代码:

    $getJSON = function(url,fun){

    var s  = document.createElement(‘script’);

    s.src = url;

    var callback = ‘callback’+ (+new Date());

    window[callback] = fun;

    document.body.appendChild(s);

    }

    这个主要是改良了随机数(小小提示下哦,这个代码没有实现JSONP的功能哦);


    于是融合上面的代码后最终代码如下:

    定义函数:

    function getJSON(url, func){

    if (!document.getElementById) {

    return false;

    }

    if (document.getElementById(“jsonscript”)) {

    var oldscript = document.getElementsByTagName(“script”);

    for (var i = 0; i < oldscript.length; i++) {

    if (oldscript[i].getAttribute(“src”) == url) {

    oldscript.parentNode.removeChild(oldscript);

    }

    }

    }

    var script = document.createElement(“script”);

    var callback = ‘callback’+ (+new Date());

    url+=”?jsoncallback=”+callback;

    script.setAttribute(“src”, url);

    window[callback]=func;

    script.setAttribute(“id”, “jsonscript”);

    document.getElementsByTagName(“head”)[0].appendChild(script);

    }

    回调函数:

    function parseDZList(json){

    var show = document.getElementById(“show”);

    var Status = json.StatusInfo.Status;

    var items = json.Items;

    for (var i = 0; i < items.length; i++) {

    var ZIMG=items[i].ZIMG

    ZIMG=ZIMG.replace(“{0}”,”64×64″)

    show.innerHTML += “<li><img src=”+ZIMG+” />”+items[i].ZName+”</li>”;

    }

    }

    页面调用:

    window.onload = function(){

    getJSON(“http://api.zhui.cn/content/ZIDList.json”,parseDZList);

    }

    终于松了一口气~

    演示地址:http://www.showfan.cn/demo/getJSON.html

     

    JavaScript缓动效果加强版(一)

    On 2010年05月25日, in JavaScript, by admin

    在上一篇简单的JavaScript缓动效果的效果上加入暂停和继续;

    重点在于:暂停时记录一下当前的动作,留着点击继续用

    DEMO:http://showfan.cn/demo/moveElement2.html

     

    简单的JavaScript缓动效果

    On 2010年05月25日, in JavaScript, by admin

    DEMO:http://showfan.cn/demo/moveElement.html

    难点:计算运动过程中的位移

    function moveElement(elementID,final_x,final_y,interval){
    if(!document.getElementById) return false;
    if(!document.getElementById(elementID)) return false;
    var elem=document.getElementById(elementID);
    var xpos=parseInt(elem.style.left);
    var ypos=parseInt(elem.style.top);
    if(xpos==final_x&&ypos==final_y){
    return false;
    }
    if(xpos
    var dist=Math.ceil((final_x-xpos)/10)
    xpos=xpos+dist;
    }
    if(xpos>final_x){
    var dist=Math.ceil((xpos-final_x)/10)
    xpos=xpos-dist;
    }
    if(ypos
    var dist=Math.ceil((final_y-ypos)/10)
    ypos=ypos+dist;
    }
    if(ypos>final_y){
    var dist=Math.ceil((ypos-final_y)/10)
    ypos=ypos-dist;
    }

    elem.style.left=xpos+”px”;
    elem.style.top=ypos+”px”;
    var repeat=”moveElement(‘”+elementID+”‘,”+final_x+”,”+final_y+”,”+interval+”)”;
    timer=setTimeout(repeat,interval);
    }

     

    aptana 不能安装nokia wrt plugin的解决办法

    On 2010年05月21日, in widget, by admin

    这个方法很早之前就在用了,当时以为这只是个小bug,以为Nokia会及时修复,不过到现在aptana装Nokia wrt插件还是报错。就写上来供大家参考:

    当用正常方法安装失败的情况下情使用下面的方法:

    第一步:

    打开aptana->help->Install New Software

    第二步:

    在Work with处输入:http://www.showfan.cn/com.nokia.wrt.2.1.0.v20090707223056

    第三步:

    取消选中”Group items by catagory”这一项,这时会列出可用的插件,

    第四步:

    然后选中”Nokia Web Runtime plug-in…..”这一项,继续”下一步”

    第五步,默认安装直到完成

     

    啊哈,偶的佳能IXUS中奖了

    On 2010年05月20日, in 关于站长, by admin

    期待已久的开奖日终于到来,偶滴大名也在获奖名单上面啊~~只不过不知道是几等奖,真希望是一等奖哇(*^__^*) ……

    ~~~估计是三等奖~~~