标签归档:jQuery

jQuery UI – Datepicker

单日期选择:

$(function() {
	var dayNamesMin =['日','一', '二', '三', '四', '五', '六'];
	var monthNamesShort = ['一','二','三','四','五','六','七','八','九','十','十一','十二'];
	$('#datepicker').datepicker({
		changeMonth: true,
		changeYear: true,
		dayNamesMin:dayNamesMin,
		monthNamesShort:monthNamesShort,
		dateFormat: 'yy-mm-dd'
	});
});

jquery-ui-datepicker-only

$(function(){
    var dayNamesMin =['日','一', '二', '三', '四', '五', '六'];
    var monthNamesShort = ['一','二','三','四','五','六','七','八','九','十','十一','十二'];
    $("#datefrom").datepicker({
	defaultDate: "+1w",
        changeMonth: true,
        dayNamesMin:dayNamesMin,
	monthNamesShort:monthNamesShort,
	dateFormat: 'yy-mm-dd',
        numberOfMonths: 3,
        onClose: function( selectedDate ) {
        	$("#dateto").datepicker( "option", "minDate", selectedDate );
        }
    });
    
    $("#dateto").datepicker({
        defaultDate: "+1w",
        changeMonth: true,
        dayNamesMin:dayNamesMin,
	monthNamesShort:monthNamesShort,
	dateFormat: 'yy-mm-dd',
        numberOfMonths: 3,
        onClose: function( selectedDate ) {
          	$("#datefrom").datepicker( "option", "maxDate", selectedDate );
        }
    });
});

jquery-ui-datepicker

jQuery UI中提供的是日历选择,无法选择到具体的时间,如果需要选择时间,可以引入一个扩展:

<link href="/css/jquery-ui-timepicker-addon.min.css" rel="stylesheet">
<script src="/js/jquery-ui-timepicker-addon.min.js"></script>
<script type="text/javascript">
$(function(){
	var dayNamesMin =['日','一', '二', '三', '四', '五', '六'];
	var monthNamesShort = ['一','二','三','四','五','六','七','八','九','十','十一','十二'];
	$("#datepicker").datetimepicker({
		changeMonth: true,
		changeYear: true,
		dayNamesMin:dayNamesMin,
		monthNamesShort:monthNamesShort,
		dateFormat: 'yy-mm-dd',
		showSecond: true,
		timeFormat: 'HH:mm:ss',
		stepHour: 1,
		stepMinute: 1,
		stepSecond: 1
	});
});
</script>

(http://trentrichardson.com/examples/timepicker)
jquery-ui-datetime

这个时间选择器的JS文件体积有点大。

jQuery中的Deferred

官方参考:http://api.jquery.com/category/deferred-object/

从jQuery 1.5.0开始,jQuery提供了Deferred对象。defer的意思是“延迟”,那么deferred大概就是被延迟的意思,Deferred对象实际上就是一种回调函数解决方案。

jQuery中的ajax方法:

$.ajax({
	url:"getData.php",
	success:function(){},
	error:function(){}
});

在Ajax请求成功和失败时分别调用对应的方法。jQuery中最为强大的特征是链式操作,但是如果在jQuery 1.5.0之前,$.ajax是不支持链式操作的,因为它会返回XHR对象。但是在jQuery 1.5.0之后,就可以如下使用:

$.ajax("getData.php").done(function(){}).fail(function(){});

这个写法和前一个例子实现了相同的逻辑,不过这里的是链式操作。

在第一个例子中,$.ajax成功时调用success指定的方法,但是如果希望成功时想执行多个方法是做不到的。但是使用如下方法可以做到:

$.ajax("getData.php")
.done(function(){})
.done(function(){})
.fail(function(){})

可以在成功或失败时绑定多个回调函数。

同时发起多个Ajax请求的情况也是很常见的,如果希望多个请求都成功了,就调用指定的回调函数,这个传统做法也是实现不了的,jQuery中可以这样做:

$.when($.ajax("getData1.php"),$.ajax("getData2.php"))
.done(function(){})
.fail(function(){})

这个写法的意思是:如果两个Ajax请求都成功,执行done绑定的函数,只有有一个失败或都失败,执行fail绑定的函数。

以上针对的都是Ajax这种操作,实际上,可以扩展到一般情况,比如针对一个耗时操作,希望它执行完毕后调用回调函数:

var big = function(){
	var defer = $.deferred();
	//耗时操作
	defer.resolve();

	return defer;
}

var df = big();
$.when(df)
.done(function(){})
.fail(function(){})

这样,耗时操作执行完毕就可以执行对应回调了。这个例子实际就是jQuery 1.5.0之后$.ajax实现的基本原理(jQuery 1.5.0之后ajax实现被重写,内部使用$.deferred)。实际这个过程不难理解,$.deferred()获取一个Deferred对象,耗时操作完毕后调用它的resolve()标志Deferred对象是已经解决的(后续执行回调的切入点),$.when函数接收Deferred对象为参数,它会检查这个对象的状态(是否被resolve),然后对应执行相应的回调函数。

这里需要对resolve()做一些说明:
deferred对象有三种执行状态—-未完成,已完成和已失败。如果执行状态是”已完成”(resolved),deferred对象立刻调用done()方法指定的回调函数;如果执行状态是”已失败”,调用fail()方法指定的回调函数;如果执行状态是”未完成”,则继续等待,或者调用progress()方法指定的回调函数(jQuery1.7版本添加)

jQuery中的Ajax操作这个过程是自动完成的。但是如果是自定义的方式,我们就需要自己去调用deferred.resolve()方法和deferred.reject()方法(把未完成状态改为已失败)。

到这里,原理上的东西应该已经说明白了,但是,还有一个叫promise的东西。考虑如上的代码,它返回的是Deferred对象,这个对象状态被改变时执行相应的回调,但是我们完全可以对返回的Deferred对象再次调用deferred.reject()方法使得原本应该是成功的,变成失败,然后调用失败对应的回调函数,意思就是说,状态的改变可以在外部被再次改变,为了改变这个缺陷,引入了promise对象,它几乎跟deferred对象一样,只是被剔除了可以改变状态的方法,比如resolve()和reject()等方法,使得状态不会在外部被再次改变。所以以上代码可以改为:

var big = function(){
	var defer = $.deferred();
	//耗时操作
	defer.resolve();

	return defer.promise();
}

var df = big();
$.when(df)
.done(function(){})
.fail(function(){})

Deferred对象的promise()返回一个promise对象,是一个被处理过的(阉割了方法)的Deferred对象,后续操作跟之前的一样。

另外,jQuery中还提供了一些便利的操作手法:

var fn = function(df){
	//
	df.resolve();
}

var defer = $.Deferred(fn);

$.when(defer).done().fail();

就是$.Deferred可以接受一个函数,这个函数接受当前这个对象作为参数,玛尼,这个绝对是淫技。

———————————-
AngularJS中的$q服务,实现了类似的东西:

//AngularJS
var defer = $q.defer();
defer.resolve();
var promise = defer.promise();

$q.all([defer1,defer2,defer3]).then(function(){});

//jQuery
$.when(defer1,defer2,defer3).then(function(){});

jQuery中的$.when对应AngularJS中的$q.all。then方法一样意思。AngularJS中的$http服务,和jQuery中的Ajax用法是一样的:

// AngularJS
$http({
	method:'POST',
	url:'getData.php',
	params:{}
}).success(function(d){});

//jQuery
$.ajax(
	url:'getData.php',
	type:'POST',
	data:{},
	success:function(){}
);

$.ajax({
	url:'getData.php',
	type:'POST',
	data:{}	
}).done(function(d){});

———————————-

函数简单说明:

deferred.always()	//当Deferred(延迟)对象解决或拒绝时,调用添加处理程序。
deferred.done()		//当Deferred(延迟)对象解决时,调用添加处理程序。
deferred.fail()		//当Deferred(延迟)对象拒绝时,调用添加处理程序。
deferred.isRejected()	//确定一个Deferred(延迟)对象是否已被拒绝。
deferred.isResolved()	//确定一个Deferred(延迟)对象是否已被解决。
deferred.notify()	//根据给定的 args参数 调用Deferred(延迟)对象上进行中的回调 (progressCallbacks)。
deferred.notifyWith() 	//根据给定的上下文(context)和args递延调用Deferred(延迟)对象上进行中的回调(progressCallbacks )。
deferred.pipe()		//实用的方法来过滤 and/or 链Deferreds。
deferred.progress()	//当Deferred(延迟)对象生成进度通知时,调用添加处理程序。
deferred.promise()	//返回Deferred(延迟)的Promise(承诺)对象。
deferred.reject()	//拒绝Deferred(延迟)对象,并根据给定的args参数调用任何失败回调函数(failCallbacks)。
deferred.rejectWith()	//拒绝Deferred(延迟)对象,并根据给定的 context和args参数调用任何失败回调函数(failCallbacks)。
deferred.resolve()	//解决Deferred(延迟)对象,并根据给定的args参数调用任何完成回调函数(doneCallbacks)。
deferred.resolveWith()	//解决Deferred(延迟)对象,并根据给定的 context和args参数调用任何完成回调函数(doneCallbacks)。
deferred.state()	//确定一个Deferred(延迟)对象的当前状态。
deferred.then()		//当Deferred(延迟)对象解决,拒绝或仍在进行中时,调用添加处理程序。
jQuery.Deferred()	//一个构造函数,返回一个链式实用对象方法来注册多个回调,回调队列, 调用回调队列,并转达任何同步或异步函数的成功或失败状态。
jQuery.when()		//提供一种方法来执行一个或多个对象的回调函数, Deferred(延迟)对象通常表示异步事件。
deferred.promise()	//返回一个 Promise 对象用来观察当某种类型的所有行动绑定到集合,排队与否还是已经完成。

jQuery客户端翻页测试

这段程序也是常常使用到的范例。

<?php
header('Content-Type:application/json; charset=utf-8');

$page = !empty($_REQUEST['page'])?(int)$_REQUEST['page']:1;
$pageSize = !empty($_REQUEST['pageSize'])?(int)$_REQUEST['pageSize']:20;

// 修正页大小
if($pageSize < 10){ $pageSize = 10; }
if($pageSize > 200){ $pageSize = 20; }

// 总记录
//$total = mt_rand(1000,10000);
$total = 26100;

// 总页数
$pageTotal = ceil($total/$pageSize);

// 修正页数
if(($page < 1) || ($page > $pageTotal)){
	$page = 1;
}

// 开始 与 结束
$from = (($page-1)*$pageSize+1);
$to   = $from + $pageSize - 1;

$data = array();
for($i=$from; $i<=$to; $i++){
	$data[] = array(
			'id' => $i,
			'word' => 'word_'.$i,
			'logo' => 'logo_'.$i,
			'site' => 'site_'.$i
	);
}

echo json_encode(array(
		'total' => $total,
		'pageSize' => $pageSize,
		'page' => $page,
		'data' => $data
));

HTML页面:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
ul,li{
	margin:0px;
	padding:0px;
	list-style:none;	
}
li{ float:left; padding:5px 10px;}
table{ border-left:1px solid #ccc; border-top:1px solid #ccc;}
table td,table th{ padding:5px; border-right:1px solid #ccc; border-bottom:1px solid #ccc;}
</style>
<script type="text/javascript" src="jquery.js"></script>
<script>
var displayPageNum = 10;
$(function(){
	$(document).on('click', '.page',function(){
		var page = $(this).attr("page");
		pager(page);
		return false;
	});
	
	function pager(page){
		$.get("data.php",{"page":page,"pageSize":20},function(d){
			var total = d.total;
			var page =  d.page;
			var pageSize = d.pageSize;
			var data = d.data;
			
			var table = "<table><tr><th>id</th><th>word</th><th>logo</th><th>site</th></tr>";
	
			$.each(data,function(i,v){
				table += "<tr>";
				table += "<td>"+v.id+"</td>";
				table += "<td>"+v.word+"</td>";
				table += "<td>"+v.logo+"</td>";
				table += "<td>"+v.site+"</td>";
				table += "</tr>";	
			});
			
			table += "</table>";
			$("#dtable").html(table);
			
			var pageTotal = Math.ceil(total / pageSize);
			
			var pageList = '<ul>';
			if(pageTotal > 0){
				pageList += '<li><a href="#" class="page" page="1">首页</a></li>';	
			}
			if((pageTotal > 0) && (page > 1)){
				pageList += '<li><a href="#" class="page" page="'+(page-1)+'">上一页</a></li>';	
			}
			//////////////////////////
			if(page >= displayPageNum){
				var to = page + displayPageNum/2;
				if(to > pageTotal){
					to = pageTotal; 
				}
				from = to - displayPageNum + 1;
				if(from < 1){ 
					from = 1;   
				}
			}else{
				var from = page - displayPageNum/2;
				if(from < 1){
					from = 1;
				}
				to = from + displayPageNum -1;
				if(to > pageTotal){ 
					to = pageTotal;   
				}
			}
			for(var i=from; i<=to; i++){
				if(i == page){
					pageList += '<li><b>第'+i+'页</b></li>';
				}else{
					pageList += '<li><a href="#" class="page" page="'+i+'">第'+i+'页</a></li>';
				}
			}
			//////////////////////////
			
			if((pageTotal > 0) && (page < pageTotal)){
				pageList += '<li><a href="#" class="page" page="'+(page+1)+'">下一页</a></li>';
			}
			if(pageTotal > 0){
				pageList += '<li><a href="#" class="page" page="'+pageTotal+'">最后页</a></li>';	
			}
			pageList += '</ul>';
			
			$("#pageList").html(pageList);
			
		},'json');
	}
	
	pager(1);
});

</script>
</head>
<body>
<div id="dtable"></div>
<div id="pageList"></div>
</body>
</html>

参考地址:htp://blog.ifeeline.com/jquery/dtable/index.php

jQuery Ajax请求同步 异步…

jQuery.ajax()
Perform an asynchronous HTTP (Ajax) request.(执行一个异步的HTTP请求)
一般我们认为Ajax请求就是异步请求的别名,jQuery中所有的Ajax请求的方法都是异步的($.get() $.post()这些实际是$.ajax()方法的封装,$.ajax()方法默认就是异步的)。

$(function(){
	$("#searchForm").submit(function(){
		var success = true;
		
		$.get('index.php?mod=title&act=admin', {}, function(d){
			if(d.success == 'nook'){
				success = false;
			}
		},'json');
		
		if(!success){
			return false;	
		}
	});
});

这段代码并没有办法实现预期。因为$.get()方法是异步执行的,它没有返回结果之前,就可以执行它之后的代码。当我遇到这个问题的时候,才意识到,自己平时使用Ajax的方法时只在意去获取数据,而几乎忽略了它是否是异步执行。

到达到以上的效果,需要使用$.ajax()函数,把里面的参数async设置为false(即同步运行代码),以下是一段典型的,可作为模子的代码:

$.ajax({ 
	url:'/xx/xxx/xxxx/',
	async:false,
	type:"POST",
	data:form.serializeArray(),
	dataType:"json",
	beforeSend:loading,
	complete:closeLoading,
	success:function(data){
		if(data.success == "OK"){
			$("#dialog").dialog('close');
		}else{
			$("#errInfo").html(data.error);
		}
	},
	error:function(){
		alert("Error occurred");
	}
});

注意dataType参数,当指定时,jQuery会按照指定的类型解析,比如指定为json,jQuery会把返回的字符串自动使用parseJSON()进行解析,如果没有指定,jQuery会自动判断(根据HTTP头信息)然后做相应处理。如果要自己处理,可以把dataType指定为text,然后自己针对这个字符串进行处理,比如调用parseJSON()。一般,在返回JSON前,发送一个JSON头(header(‘Content-Type:application/json; charset=utf-8’);),然后在客户端指定dataType为json,这样就不需要自己处理了。

如果要把数据转换成JSON字符串,可以参考:http://blog.ifeeline.com/913.html。

jQuery插件 – zTree

jQuery插件zTree, 项目地址:http://www.ztree.me/v3/main.php#_zTreeInfo, 国人开发,中文文档。使用上相对容易。累世这类插件的使用,往往会有很多配置信息,所以需要花一些时间理清楚配置参数的作用,然后学习基本的API。通过例子学习是一个捷径。

以下是一个例子,在这个例子中,我实现了根据勾选的叶子节点,获取整个路径的信息,因为我实际中需要保存这个路径:

<?php 
/*
[
  {
     "id":"1",
     "parentid":"0",
     "name":"服装及配饰"
  },
  {}
]
*/
include 'inc.php';
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script src="jquery.min.js"></script>
<script src="js/jquery.ztree.all-3.5.min.js"></script>
<link rel="stylesheet" href="css/zTreeStyle/zTreeStyle.css" type="text/css" media="all" />

<script>
treeJson = <?php echo $tree?>;

var setting = {
	view:{  
		// 双击展开
		dblClickExpand: true,
		// 是否显示对齐线 
		showLine: false,  
		// 是否显示图标
		showIcon:false
	},  
	data: {  
		simpleData: {
			// 是否启用简单数据模式(这个方式只要把每个目录按照如下格式读出放入数组即可)
			enable: true,
			// 目录ID的标识符
			idKey: "id",
			// 符目录ID标识符
			pIdKey: "parentid",
			// 根目录ID值
			rootPId: 0
		}  
	},
	check: {
		// 是否启用选框
		enable: true,
		// 设置自动关联勾选时是否触发 beforeCheck / onCheck 事件回调函数
		autoCheckTrigger: true,
		chkStyle: "checkbox"
	}
};


$(function(){
	// 第一个参数是一个容器(jQuery包装),第二参数是配置信息,第三参数是Json数据
	// 注意:容器需要应用一个叫ztree的CSS类,也可以修改,不过对应CSS样式要替换(一般不需要改动)
	zTree = $.fn.zTree.init($("#erpTree"), setting, treeJson);	
	
	
	$("#trigger").click(function(){
		var set = $(this);
		if(set.attr('clear') == 'false'){
			set.attr('clear','true');
			// 清楚所有勾选
			zTree.checkAllNodes(false);
			return;
		}else if(set.attr('clear') == 'true'){
			set.attr('clear','false');
		}
		
		// 节点ID,不需要区分子节点 和 父节点
		var nodes = [82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,403,404,405,406,445,476,510,511];
		for(i in nodes){
			// 获取节点对象
			var node = zTree.getNodeByParam('id',nodes[i]);
			// 选中节点 第一参数必须是zTree内部节点对象,第二参数表示是否选中,第三参数表示是否联动操作(子节点选中,父节点也选上)
			zTree.checkNode(node, true, true);
			// 更新节点信息
			//zTree.updateNode(node);
		}
	});
	
	$("#getNodes").click(function(){
		// 获取所有选中的节点对象
		var checkedNodes = zTree.getCheckedNodes(true);
		// 选中节点ID与对象对照表
		var cates = {};
		for(var ii in checkedNodes){
			cates[checkedNodes[ii]['id']] =  checkedNodes[ii];
		}
			
		// 子节点路径对应
		var catePath = {};
		for(i in checkedNodes){
			// 子节点 回溯 获取路径
			if(!checkedNodes[i]['isParent']){
				var id = checkedNodes[i]['id'], name = checkedNodes[i]['name'];
				var ids = [], names = [];
				ids.push(id); names.push(name);
				pid = checkedNodes[i]['parentid'];
				for(var j=0; j<30; j++){
					if(pid != 0){
						node = cates[pid];
						ids.push(node['id']);
						names.push(node['name']);
						pid = node['parentid'];
					}else{
						break;
					}
				}
				catePath[id] = [ids.reverse().join('-'),names.reverse().join('-')];
			}
		}
		
		var outStr = '';
		$.each(catePath,function(){
			//console.log(this.join('|'));
			outStr += this.join('|')+"<br />";
		});
		
		$("#log").html(outStr);
	});
});

</script>
</head>
<body>
<table>
	<tr>
    	<td style="vertical-align:top;width:350px;">
        <div id="erpTree" class="ztree"></div>
        <button id="trigger" clear="true">设置节点</button> -- <button id="getNodes">获取节点</button>
        </td>
        <td style="vertical-align:top">
        <div id="log"></div>
        </td>
    </tr>
</table>
</body>
</html>

Demo地址:http://blog.ifeeline.com/jquery/zTree_v3/index.php

图表工具 – jQuery插件jqplot

jQuery插件jqplot这个画图表的工具功能很齐全,个人觉得它虽然不是最好的画图表的工具,但是它提供了根据当前数据自动画趋势图的功能,是我去使用它的主要原因。
jqplot-graph
经过研究,它只能画直线的趋势线(而不能像在Excel中的那样画多项式趋势线),不过目前暂时还没有发现哪个JS或PHP工具提供了画趋势线的…

这个工具的使用,刚开始是比较困难的,参数很多,搞不清楚参数有什么作用,当然可以看文档说明,然后多去尝试。也可以对着官方提供的例子去看。这个工具本身提供了很多的插件,特别是渲染器,不同的渲染器提供了不同的选项,而且它画图的时候使用的是canvas元素。当使用了某个渲染器时必须把对应的JS插件加载进来,否则,就无法工作。以下是一份简要说明:

$(document).ready(function () {

    var s1 = [<?php echo implode(', ', $ods);?>];
    var s2 = [<?php echo implode(', ', $ods_);?>];

    plot = $.jqplot("chart1", [s1, s2], {
    	// 是否动画显示
        animate: true,
        //animateReplot: true,
        
        // --指定可选颜色,线条等可用的颜色
    	seriesColors: [ "#4bb2c5", "#c5b47f", "#EAA228", "#579575" ],
        // --标题 也可以使用另一只方式
    	title: "--- xxx统计 ---",
    	//title: {
        //    text: '',
        //    show: true,
        //},
    	// --
    	// stackSeries: false

    	// -- 设置轴线的默认值
    	// 1 三个概念, Label渲染器(Label), 刻度线的渲染器(选项),刻度渲染器(选项)
    	// 2 不同的渲染器会有不同的选项,对应有不同的选项,不同的轴线的默认值从axesDefaults中继承
    	// 3 轴线可定义最大最小值,指定刻度值...
        axesDefaults: {
            show: false,
            min: null, 				// 刻度最小值
            max: null,				// 刻度最大值
            pad: 0,					
            ticks: [],				// 固定刻度,默认时自动确定的,有多个Y轴时,如果指定,最好元素一样多
            numberTicks: undefined,
            renderer: $.jqplot.LinearAxisRenderer, 	// 画轴时使用的渲染器
            rendererOptions: {},					// 画轴时使用的渲染器的选项
            tickOptions: {
                mark: 'outside',
                showMark: true,
                showGridline: true,					// 是否显示网格线
                markSize: 4,
                show: true,
                showLabel: true,					// 是否显示Label
                formatString: '',					// 刻度值的格式化字符串
            },
            showTicks: false,
            showTickMarks: false,
        },
        // --具体的轴定义,每个轴的可用参数跟axesDefaults一样
        axes: {
            // X轴
            xaxis: {
                 // 轴线渲染器  默认使用继承的线条渲染器,这里的X轴要使用分类轴渲染器
	           	 renderer: $.jqplot.CategoryAxisRenderer,
	           	 // 轴的标签显示,渲染器使用Canvas轴标签渲染器
	             label: 'X轴',
	             labelRenderer: $.jqplot.CanvasAxisLabelRenderer,
	             // 刻度的渲染器,这里是要转角度
	             tickRenderer: $.jqplot.CanvasAxisTickRenderer,
	             tickOptions: {
	            	 showGridline: false,
	                 angle: -30
	             }
            },
            // Y轴(左)
            yaxis: {
                // 可以指定有效的刻度值
            	//ticks: [],
                tickOptions: {
                	//轴的网格线是否显示
                	//showGridline: false,
                    formatString: "%'d"
                },
                rendererOptions: {
                    forceTickAt0: true
                }
            },
            // Y轴(右)
            y2axis: {
            	//ticks: [],
                tickOptions: {
                    //轴的网格线是否显示
                	showGridline: false,
                    formatString: "%.2f%"
                },
                rendererOptions: {
                    // 多个轴时,刻度是否对齐
                    alignTicks: true,
                    forceTickAt0: true
                }
            }
        },
        
        // 线条的默认值
        seriesDefaults: {
            show: true,     // wether to render the series.
            xaxis: 'xaxis', // either 'xaxis' or 'x2axis'.
            yaxis: 'yaxis', // either 'yaxis' or 'y2axis'.
            label: '',      // label to use in the legend for this line.
            color: '',      // CSS color spec to use for the line.  Determined automatically.
            lineWidth: 1.5, // Width of the line in pixels.
            shadow: true,   // show shadow or not.
            shadowAngle: 45,    // angle (degrees) of the shadow, clockwise from x axis.
            shadowOffset: 1.25, // offset from the line of the shadow.
            shadowDepth: 3,     // Number of strokes to make when drawing shadow.  Each
                                // stroke offset by shadowOffset from the last.
            shadowAlpha: 0.1,   // Opacity of the shadow.
            showLine: true,     // whether to render the line segments or not.
            showMarker: true,   // render the data point markers or not.
            fill: false,        // fill under the line,
            fillAndStroke: false,       // *stroke a line at top of fill area.
            fillColor: undefined,       // *custom fill color for filled lines (default is line color).
            fillAlpha: undefined,       // *custom alpha to apply to fillColor.
            renderer: $.jqplot.LineRenderer,    // renderer used to draw the series.
            rendererOptions: {}, 				// options passed to the renderer.  LineRenderer has no options.

            // 折线图上的点
            markerRenderer: $.jqplot.MarkerRenderer,
            markerOptions: {
                show: true,             // wether to show data point markers.
                style: 'filledSquare',  // circle, diamond, square, filledCircle.
                                        // filledDiamond or filledSquare.
                lineWidth: 1,       // width of the stroke drawing the marker.
                size: 9,            // size (diameter, edge length, etc.) of the marker.
                //color: '#666666', // color of marker, set to color of line by default.
                shadow: true,       // wether to draw shadow on marker or not.
                shadowAngle: 45,    // angle of the shadow.  Clockwise from x axis.
                shadowOffset: 1,    // offset from the line of the shadow,
                shadowDepth: 3,     // Number of strokes to make when drawing shadow.  Each stroke
                                    // offset by shadowOffset from the last.
                shadowAlpha: 0.07   // Opacity of the shadow
            },
            
            // 趋势线  需要jqplot.trendline.js插件
            trendline: {
                // 是否显示
                show: true,
                // 趋势线的颜色
                color: '#000',
                // label
                label: '趋势线',
                // 类型,线条  和 指数  'linear', 'exponential' or 'exp'
                type: 'exp',
                // 趋势线宽度
                lineWidth: 1,
                // 趋势线的阴影设置
                shadow: false,
                shadowAngle: 45,
                shadowOffset: 1.5,
                shadowDepth: 3,            
                shadowAlpha: 0.07 
            }
        },
        
        series:[
       		{
            	label: "XXX订单总量",
                // 是否显示点上的值
                pointLabels: {
                	show: true
             	},
             	// 鼠标放到点上时是否显示值
             	showHighlight: false,
                rendererOptions: {
                    // 动画显示速度
                	animation: {
                    	speed: 2000
                 	}
              	},
              	trendline: {
              		label: '-- 趋势线',
                }
            },
            {
                label: "XXX缺货率",
                // 是否显示点上的值
                pointLabels: {
                    show: true
                },
                // 鼠标放到点上时是否显示值
                showHighlight: false,
                yaxis: 'y2axis',
                rendererOptions: {
                    animation: {
                        speed: 2500
                    }
                },
              	trendline: {
              		label: '-- 趋势线',
                }
            }
        ],

        // 自动抓取线了Label和颜色
        legend: {
            show: true,
            //这个Renderer可以点击对应的指示标,显示和隐藏对应的线,但是无法显示趋势线 XX
            //renderer: $.jqplot.EnhancedLegendRenderer,
            //rendererOptions: {
            //    numberRows: 4
            //},
            placement: 'outsideGrid',
            location: 'e'
        },
        grid: {
            drawGridLines: true,        // wether to draw lines across the grid or not.
            gridLineColor: '#cccccc',   // *Color of the grid lines.
            background: '#fffdff',      // CSS color spec for background color of grid.
            borderColor: '#999999',     // CSS color spec for border around grid.
            borderWidth: 1.0,           // pixel width of border around grid.
            shadow: true,               // draw a shadow for grid.
            shadowAngle: 45,            // angle of the shadow.  Clockwise from x axis.
            shadowOffset: 2.5,          // offset from the line of the shadow.
            shadowWidth: 3,             // width of the stroke for the shadow.
            shadowDepth: 3,             // Number of strokes to make when drawing shadow.
                                        // Each stroke offset by shadowOffset from the last.
            shadowAlpha: 0.07,          // Opacity of the shadow
            renderer: $.jqplot.CanvasGridRenderer,  // renderer to use to draw the grid.
            rendererOptions: {}         // options to pass to the renderer.  Note, the default
                                        // CanvasGridRenderer takes no additional options.
        }, 
	// 鼠标放入图中指针的样式
        cursor: {
            // 指针样式
            style: 'pointer',     // A CSS spec for the cursor type to change the
                                    // cursor to when over plot.
            // 是否显示
            show: true,
            // 是否可以放大
            zoom: false,
            looseZoom: false,
            // 是否显示提示框 跟随鼠标 位置 偏移...
            showTooltip: true,
            followMouse: false,
            tooltipLocation: 'se', 
            tooltipOffset: 6,
            showTooltipGridPosition: false,
            showTooltipUnitPosition: true,
            tooltipFormatString: '%.4P',
            useAxesFormatters: true,
            tooltipAxesGroups: [],
        },
        highlighter: {
            show: true, 
            showLabel: true, 
            tooltipAxes: 'y',
            sizeAdjust: 7.5 , tooltipLocation : 'ne'
        },
    });
});

jQuery jqplot Demo
jQuery jqplot Demo 下载

永久链接:http://blog.ifeeline.com/1706.html

jQuery UI 插件 multiselect

这个插件可以使传统的多选变得更加友好,特别是提供了一个过滤的功能,感觉比较不错。Github地址:https://github.com/ehynds/jquery-ui-multiselect-widget,看这里代码的提交,视乎也已经很久没有更新了。

基本使用:

<!-- CSS -->
<link rel="stylesheet" type="text/css" href="css/jquery-ui.css" />
<link rel="stylesheet" type="text/css" href="css/jquery.multiselect.css" />
<link rel="stylesheet" type="text/css" href="css/jquery.multiselect.filter.css" />

<!-- JS  -->
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery-ui.js"></script>
<script type="text/javascript" src="js/jquery.multiselect.js"></script>
<script type="text/javascript" src="js/jquery.multiselect.filter.js"></script>

<script type="text/javascript">
$(function(){
	
	// 单选 没有太多意义
	$("#select1").multiselect({
		multiple: false,
		header: "选择一个",
		noneSelectedText: "没有选择",
		selectedList: 1
	});
	
	// 基本用法
	$("#select2").multiselect({
		checkAllText:'全选',		// 全选文本
		uncheckAllText:'清除',	        // 全部不选文本
		noneSelectedText:'当前没有选择', // 没有选中时的提示文本
		selectedText:'选择了#个',
			
	}); 
	
	// 头部显示 隐藏 与自定义
	$("#select3").multiselect({
		header: false
	});
	
	// 应用过滤器
	$("#select4").multiselect({
		checkAllText:'全选',
		uncheckAllText:'清除',
		noneSelectedText:'当前没有选择',
		selectedText:'选择了#个',
	}).multiselectfilter({
		label:'过滤',
		width:'120',
		placeholder:'请输入文本',
		autoReset:false
	});
	$("#select5").multiselect().multiselectfilter();
	
	var conf = {
		// 基本配置
		header:true, 					// true false string, 显示 隐藏 设置头部字符串
		height:175,					// 下拉框的高度
		minWidth:225,					// 最小宽度
		checkAllText:'Check All',		        // 全选文本
		uncheckAllText:'Uncheck All',	                // 全部不选文本
		noneSelectedText:'Select options',              // 没有选中时的提示文本
		selectedText:'#selected',		        // selectedList为false时,选中时显示的文本,#表示多少个
		selectedList:false,				// 是否显示选中项的内容
		show:'',					// 设置打开效果
		hide:'',					// 设置隐藏效果
		autoOpen:false,					// 自动弹出
		multiple:true,					// 是否多选
		classes:'',					// 添加类
		position:{},					// 显示位置设置 position:{my:'center',at:'center'}
		
		// 事件
		create:function(event,ui){},
		beforeopen:function(event,ui){},
		open:function(event,ui){},
		beforeclose:function(event,ui){},
		close:function(event,ui){},
		checkall:function(event,ui){},
		uncheckall:function(event,ui){},
		optgrouptoggle:function(event,ui){},
		click:function(event,ui){}
	};
	
	// 已经也可以通过这个方式绑定回调函数到事件
	$("#multiselect").bind("multiselectopen", function(event, ui){
	    // event handler here
	});
	
	// 按照jQuery UI惯例,可以用如下方式调用方法
	$("#multiselect").multiselect("method_name");
	/* method_name 列表
	open
	close
	refresh
	disable		// 禁用,不可用
	enable		// 启用
	checkAll	// 全选
	uncheckAll	// 清除选择
	isOpen		// 是否打开
	getChecked	// 获取所有选中
	getButton
	widget		// 
	option		// 
	destroy
	*/
	
	// 应用过滤器
	// 引入jquery.multiselect.filter.css 和 jquery.multiselect.filter.js
	var filter = {
		label:'Filter',			//文本
		width:'100px',			//宽度
		placeholder:'Enter keywords',	//占位符
		autoReset:false
	};
	
});
</script>

jquery.ui.multiselect

Multiselect是基于jQuery UI的,所以jQuery 和 jQuery UI要新引入(包括它的CSS),而multiselect.filter又是基于multiselect的插件,所以对应的JS和CSS都需要引入。

在使用上,和使用select元素一样(记得添加multiple=”multiple”属性,表示可以多少),另外,在PHP中,这个select应该命名为xxx[]这样的形式,这样表单POST过去时就可以以一个数组的方式组织选中的值(否则只会接收最后一个值):

// select命名为multi_select[]
Array
(
    [multi_select] => Array
        (
            [0] => green
            [1] => blue
            [2] => orange
        )

)

以下是一些在线例子(来自官方压缩包):
http://blog.ifeeline.com/jquery/ui/multiselect/index.htm

永久链接:http://blog.ifeeline.com/1664.html

jQuery插件 – jQuery Validation Plugin

下载地址:http://jqueryvalidation.org

———————————————————————
有如下特点:
1.内置验证规则: 拥有必填、数字、Email、URL和信用卡号码等19类内置验证规则
2.自定义验证规则: 可以很方便地自定义验证规则
3.简单强大的验证信息提示: 默认了验证信息提示,并提供自定义覆盖默认的提示信息的功能
4.实时验证: 可通过keyup或blur事件触发验证,而不仅仅在表单提交的时候验证

使用方法:

// 应用库文件
<script src="jquery.js"></script>
<script src="jquery.validate.js"></script>
// 确定应用到哪个表单
$("#commentForm").validate();

Validation插件的验证信息默认语言是英文,如果要改成中文,只需要引入Validation提供的中文验证信息即可

<script src="scripts/jquery.validate.messages_cn.js" type="text/javascript"></script> 

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

可以使用注释语法 和 自定义语法添加自定义规则。比如:

<input id="cemail" type="email" name="email" required>

$("#commentForm").validate();

其中required表示字段必填,type为email表示填入的内容必须是一个合法的电子邮件地址。也可以使用自定义规则:

<input id="cemail" type="email" name="email">

$("#signupForm").validate({
    rules: {
        email: {
	    required: true,
	    email: true
	}
    },
    messages: {
        email: "Please enter a valid email address"
    }
});

看起来,注释语法更加方便一些。这是基本用法,具体例子可以参考:

整个插件,实际就是在表单上调用validate方法,这样表单字段就会按照规则验证。跟jQuery风格一致,这个方法支持一个可选的配置对象。

1 debug (default: false) 是否开启debug模式,如果为true,表单不会提交并且相关信息会在终端显示
2 submitHandler (default: native form submit) 表单通过验证后的回调函数,比如要通过Ajax方式提交表单,这里提供接口。默认是表单默认行为。

$(".selector").validate({
	submitHandler: function(form) {
		$(form).ajaxSubmit();
	}
});

3 invalidHandler 表单没有通过验证时的回调函数,对错误进行统一处理

$(".selector").validate({
	invalidHandler: function(event, validator) {
	// 'this' refers to the form
	var errors = validator.numberOfInvalids();
	if (errors) {
		var message = errors == 1
			? 'You missed 1 field. It has been highlighted'
			: 'You missed ' + errors + ' fields. They have been highlighted';
			$("div.error span").html(message);
			$("div.error").show();
		} else {
			$("div.error").hide();
		}
	}
});

这里的validator参数是指应用到当前表单的验证器。
4 ignore (default: “:hidden”) 排除不需要验证的表单元素

$("#myform").validate({
	ignore: ".ignore"
});

默认隐藏表单元素被忽略,另外提交和重置按钮总是被忽略的。
5 rules (default: rules are read from markup (classes, attributes, data)) 默认规则从标签的类 属性 data中读取
规则是一组键值对,键是元素的名称,值是一个包含规则/参数对 或 是一个纯文本。 Can be combined with class/attribute/data rules. 每个规则可以有一个特定条件的依赖属性。

$(".selector").validate({
	rules: {
		// simple rule, converted to {required:true}
		name: "required",
		// compound rule
		email: {
			required: true,
			email: true
		}
	}
});

$(".selector").validate({
	rules: {
		contact: {
			required: true,
			email: {
				depends: function(element) {
					return $("#contactform_email").is(":checked");
				}
			}
		}
	}
});

$(".selector").validate({
	rules: {
		// at least 15€ when bonus material is included
		pay_what_you_want: {
			required: true,
			min: {
				// min needs a parameter passed to it
				param: 15,
				depends: function(element) {
					return $("#bonus-material").is(":checked");
				}
			}
		}
	}
});

6 messages (default: the default message for the method used)

$(".selector").validate({
	rules: {
		name: "required",
		email: {
			required: true,
			email: true
		}
	},
	messages: {
		name: "Please specify your name",
		email: {
			required: "We need your email address to contact you",
			email: "Your email address must be in the format of name@domain.com"
		}
	}
});

$(".selector").validate({
	rules: {
		name: {
			required: true,
			minlength: 2
		}
	},
	messages: {
		name: {
			required: "We need your email address to contact you",
			minlength: jQuery.format("At least {0} characters required!")
		}
	}
});

7 groups 对错误信息进行分组

$("#myform").validate({
	groups: {
		username: "fname lname"
	},
	errorPlacement: function(error, element) {
		if (element.attr("name") == "fname" || element.attr("name") == "lname" ) {
			error.insertAfter("#lastname");
		} else {
			error.insertAfter(element);
		}
	}
});

username由元素fname和lname是组成(组成元素中间用空格隔开)….
8 onsubmit (default: true)
在提交表单是验证表单。
9 onfocusout
10 onkeyup
11 onclick
针对单选和复选框
…..
详情内容参考(http://jqueryvalidation.org/validate)

当在一个表单上调用validate方法后,它返回一个应用到当前表单的validate,一些回调函数也需要携带这个validate的引用。

    Validator.form() – Validates the form.
    Validator.element() – Validates a single element.
    Validator.resetForm() – Resets the controlled form.
    Validator.showErrors() – Show the specified messages.
    Validator.numberOfInvalids() – Returns the number of invalid fields.

还提供了一些静态方法:

    jQuery.validator.addMethod() – Add a custom validation method.
    jQuery.validator.format() – Replaces {n} placeholders with arguments.
    jQuery.validator.setDefaults() – Modify default settings for validation.
    jQuery.validator.addClassRules() – Add a compound class method.

比如要添加一个验证方法,addMethod就用得上。

以下是内置的验证方法:

    required – Makes the element required.
    remote – Requests a resource to check the element for validity.
    minlength – Makes the element require a given minimum length.
    maxlength – Makes the element require a given maxmimum length.
    rangelength – Makes the element require a given value range.
    min – Makes the element require a given minimum.
    max – Makes the element require a given maximum.
    range – Makes the element require a given value range.
    email – Makes the element require a valid email
    url – Makes the element require a valid url
    date – Makes the element require a date.
    dateISO – Makes the element require an ISO date.
    number – Makes the element require a decimal number.
    digits – Makes the element require digits only.
    creditcard – Makes the element require a credit card number.
    equalTo – Requires the element to be the same as another one

官方提供的例子:更多例子

jQuery UI 实践

jQuery UI基于jQuery,提供了一系列可用UI组件,使用非常方便,这些组件的外观是可定制的(虽然只能改下颜色),在它的下载页http://jqueryui.com/download/,可以选择你需要的组件,最后还可以选择UI样式,然后下载下来。如果对这些颜色不满意,可以到http://jqueryui.com/themeroller自定义外观。

在http://jqueryui.com/demos/中提供了每个UI的例子,可以参考。

下载的jQuery UI文件夹中:
jquery ui

使用jQuery UI的方法:

<link href="jquery-ui.css" rel="stylesheet">
<script src=jquery.js"></script>
<script src="jquery-ui.js"></script>

CSS文件需要使用到images中的图片,images文件夹应该和CSS在同一级目录。后面添加了min的表示是去空白压缩之后的版本。实际上,先引用了jQuery库后,在引用jquery-ui.min.css和jquery-ui.min.js即可。


Dialog就是一个对话框,在jQuery中,需要定义一块HTML内容对应这个对话框的内容,对话框的外围(比如标题,关闭按钮,外边框样式等)是JQuery提供的,看例子:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
body{
font: 62.5% "Trebuchet MS", sans-serif;
margin: 50px;
}
</style>
<link href="jquery-ui.css" rel="stylesheet">
<script src="jquery.js"></script>
<script src="jquery-ui.js"></script>
<script>
jQuery(function(){
	$( "#dialog" ).dialog({
		autoOpen: false,
		width: 800,
		buttons: [
			{
				text: "提交",
				click: function() {
					$( this ).dialog( "close" );
				}
			},
			{
				text: "取消",
				click: function() {
					$( this ).dialog( "close" );
				}
			}
		]
	});	
	// Link to open the dialog
	$( "#dialog-link" ).click(function( event ) {
		$( "#dialog" ).dialog( "open" );
		event.preventDefault();
	});
	
});
</script>
</head>
<body>
<p>
	<a href="#" id="dialog-link" class="ui-state-default ui-corner-all">
		<span class="ui-icon ui-icon-newwin"></span>Open Dialog
	</a>
</p>

<!-- ui-dialog -->
<div id="dialog" title="Dialog Title">
	<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
</body>
</html>

代码$( “#dialog” ).dialog()传入一个配置对象(jQuery UI组件都是这个操作方式),它定义了这个组件的行为,比如在按下提交按钮时将要做的操作(如可以通过Ajax提交数据)。一种非常有用的交互方式是:在触发窗口弹出来时先通过Ajax获取数据填充到这个对话框中(对话框对应的HTML块),然后弹出,用户做了某些操作(比如填表单等),然后在提交按钮中通过Ajax提交数据,根据返回结果做进一步处理(比如关闭对话框等)。

在发出Ajax请求时,一般需要一个正在处理的加载启示,示例如下:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
body{
color: #002200;
font: 76% georgia;
margin: 0px;
padding:0px;
}
</style>
<link href="jquery-ui.css" rel="stylesheet">
<script src="external/jquery/jquery.js"></script>
<script src="jquery-ui.js"></script>
<script src="jquery.blockUI.js"></script>
<script>
var img ='<img src="data:image/gif;base64,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" />';

function loading(){
    $.blockUI({ 
    	message: img+"正在处理,请耐心等待...",
        css: {
            padding:        0,
            margin:         0,
            width:          '100%',
            height:	    '38px',
            top:	    'none',
            bottom:	    '0',
            left:           '0',
            textAlign:      'center',
            color:          'none',
            border:         'none',
            backgroundColor:'#fff',
            cursor:         'wait'
        },
        overlayCSS:  {
            backgroundColor: '#000',
            opacity:         0.4,
            cursor:          'wait'
        },
    });
    $('.blockOverlay').attr('title','Click to unblock').click($.unblockUI);
}
function closeLoading(){
	$.unblockUI({ fadeOut: 200 });
}

jQuery(function(){
	$( "#dialog").dialog({
		autoOpen: false,
		width: 800,
		buttons: [
			{
				text: "提交",
				click: function() {
					$( this ).dialog( "close" );
				}
			},
			{
				text: "取消",
				click: function() {
					$( this ).dialog( "close" );
				}
			}
		]
	});	
	// Link to open the dialog
	$( "#dialog-link" ).click(function( event ) {
		$.ajax({ 
			url:'../t.php',
			async:true,
			type:"POST",
			data:{"id":1},
			dataType:"json",
			beforeSend:loading,
			complete:closeLoading,
			success:function(data){
				$( "#dialog" ).dialog( "open" );
			},
			error:function(){
				closeLoading();
				alert("Error occurred");
			}
		});
		
		
		event.preventDefault();
	});
	
	$( "#progressbar" ).progressbar({
		value: true
	}); 	
});
</script>
</head>
<body>
<p>
<a href="#" id="dialog-link" class="ui-state-default ui-corner-all">
<span class="ui-icon ui-icon-newwin"></span>Open Dialog
</a>
</p>
<!-- ui-dialog -->
<div id="dialog" title="Dialog Title">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>	
</div>
</body>
</html>

这里引入了jQuery BlockUI(http://malsup.com/jquery/block/#demos),它提供了一个可定制的AJAX提示加载框。
loading


关于进度条和服务端交互的例子:

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery UI Progressbar - Custom Label</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<style>
#progressbar{
	
}
.ui-progressbar {
	position: relative;
}
.progress-label {
	position: absolute;
	left: 50%;
	top: 4px;
	font-weight: bold;
	text-shadow: 1px 1px 0 #fff;
}
</style>
<script>
$(function() {
	var progressbar = $("#progressbar"),
	progressLabel = $(".progress-label");
	progressbar.progressbar({
		value: false,
		change: function() {
			progressLabel.text( progressbar.progressbar( "value" ) + "%" );
		},
		complete: function() {
			progressLabel.text( "Complete!" );
		}
	});
	
	$("#sync").click(function(){
		// 注册一个进度条唯一编号
		$.get("../s.php","type=new",function(data){
			var sssn = data.sid;
			
			var progress = function(){
				var val = progressbar.progressbar( "value" ) || 0;
				
				if ( val < 99 ) {
					setTimeout(progress, 1000);
				}
				
				$.get("../s.php","type=getvalue&sid="+sssn,function(d){
					var v = d.value;
					if(v > val){
						progressbar.progressbar( "value", v);
					}
				},'json');
			}			
			
			setTimeout(progress, 1000);
			progressbar.show();
			$.get("../t.php","sid="+sssn,function(d){
				progressbar.hide();
				$("#result").html(d.text);
			},'json');
			
						
		},'json');
	});
});
</script>
</head>
<body>
<button id="sync">同步</button>
<div id="progressbar" style="display:none;"><div class="progress-label">Loading...</div></div>
<div id="result">
</div>
</body>
</html>

用到的服务器段脚本:

///////////////////////////
//t.php
<?php
$server="localhost";
$user="root";
$pwd="";
$db="test";
$port=3306;
$sock='/var/lib/mysql/mysql.sock';
$charset='utf8';

function mysqlidb($server,$user,$pwd,$db,$charset,$port,$sock){
	$link = false;

	$connectionRetry = 10;

	while (!isset($link) || ($link == FALSE && $connectionRetry !=0) ){
		$link = mysqli_connect($server,$user,$pwd,$db,$port,$sock);
		$connectionRetry--;
	}

	if($link) {
		if (@mysqli_select_db($link, $db)) {
			if ((trim($charset) != '') && version_compare(@mysqli_get_server_info(), '4.1.0', '>=')) {
				@mysqli_query($link, "SET NAMES '" . trim($charset) . "'");
				if (function_exists('mysqli_set_charset')) {
					@mysqli_set_charset($link, trim($charset));
				} else {
					@mysqli_query($link, "SET CHARACTER_SET_CLIENT = '" . trim($charset) . "'");
					@mysqli_query($link, "SET CHARACTER_SET_RESULTS = '" . trim($charset) . "'");
				}
			}
		}
	}
	return $link;
}

$db = mysqlidb($server,$user,$pwd,$db,$charset,$port,$sock);

if(!empty($_GET['sid'])){
	$key = trim($_GET['sid']);
	
	$total = 120;
	
	$process = 0;
	for($i=0;$i<$total;$i++){
		usleep(200000);
		$process = (int)((100/120)*$i);
	
		mysqli_query($db,"update process_bar set key_value=".$process." where key_name='".$key."' limit 1");
	}
}



echo json_encode(array("text"=>"一共同步了1000条数据。"));
exit;


/////////////////////////
//s.php
<?php
$server="localhost";
$user="root";
$pwd="";
$db="test";
$port=3306;
$sock='/var/lib/mysql/mysql.sock';
$charset='utf8';

function mysqlidb($server,$user,$pwd,$db,$charset,$port,$sock){
	$link = false;
	
	$connectionRetry = 10;
	
	while (!isset($link) || ($link == FALSE && $connectionRetry !=0) ){
		$link = mysqli_connect($server,$user,$pwd,$db,$port,$sock);
		$connectionRetry--;
	}
	
	if($link) {
		if (@mysqli_select_db($link, $db)) {
			if ((trim($charset) != '') && version_compare(@mysqli_get_server_info(), '4.1.0', '>=')) {
				@mysqli_query($link, "SET NAMES '" . trim($charset) . "'");
				if (function_exists('mysqli_set_charset')) {
					@mysqli_set_charset($link, trim($charset));
				} else {
					@mysqli_query($link, "SET CHARACTER_SET_CLIENT = '" . trim($charset) . "'");
					@mysqli_query($link, "SET CHARACTER_SET_RESULTS = '" . trim($charset) . "'");
				}
			}
		}
	}
	return $link;
}

$db = mysqlidb($server,$user,$pwd,$db,$charset,$port,$sock);


if(!empty($_GET['type']) && ($_GET['type'] == "new")){
	$key = md5(time().rand(10000,99999));
	mysqli_query($db,"insert into process_bar (key_name,key_value) values('".$key."',0)");
	
	echo json_encode(array("sid"=>$key));
	exit;
}else if(!empty($_GET['type']) && ($_GET['type'] == "getvalue")){
	$sid = trim($_GET['sid']);
	
	$d = mysqli_query($db,"select * from process_bar where key_name='".$sid."' limit 1");
	$row = mysqli_fetch_assoc($d);
		
	echo json_encode(array("value"=>(int)$row['key_value']));
	exit;
}

///////////////////////////////////
// 数据表
CREATE TABLE IF NOT EXISTS `process_bar` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `key_name` varchar(128) NOT NULL,
  `key_value` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

这个进度条和一般的正在加载提示框最主要的区别在于对一个已知任务,进度条可以提示处理完成了多少,而一般提示框不知道这个,可能永远都不会结束。实际客户端的进度条实现应该是比较简单的,传递一个值给它然后修改显示。这个工具要和服务端搭配才有实际意义。

当要去请求一个脚本时,这个脚本要把自己处理完成了多少通过某种途径表示出来,客户端通过定时扫描获取这个值来设置进度条。以上例子中,通过请求一个进度条ID编号(插入数据库),处理任务的脚本把完成的值写入对应的标号中,客户端定时获取这个标号对应的最新值设置进度条。

待续….

jQuery插件 – Datatable

官方地址:http://www.datatables.net/

这是一个客户端表格工具,以jQuery的插件方式提供。面对不是非常大的集合进行操作时,把所有数据一次性返回到客户端,然后进行操作也未尝不是一个比较好的方案,但是如果数据大到感觉到被卡主了就没有多大意义了。我试图从服务器一次性返回大概1万条数据,然后在客户端进行操作,实际情况是浏览器首先被卡死一会,然后才能操作,所以我最终放弃了使用而改为传统的翻页操作。尽管如此,在操作有限数据集合时,Datatable还是一个不错的解决方案。

以下是做压力测试时使用的例子:

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title></title>
	<link rel="stylesheet" type="text/css" href="css/jquery.dataTables.css">
	<script type="text/javascript" language="javascript" src="js/jquery.js"></script>
	<script type="text/javascript" language="javascript" src="js/jquery.dataTables.js"></script>
    <script>
$(document).ready(function() {
	var str = '';
	$.get("d.php",function(d){
		for(var i=0;i<d.length;i++){
			str += "<tr>";
			for(var j=0;j<d[i].length;j++){
				str += "<td>"+d[i][j]+"</td>";
			}
			str += "</tr>";
		}
		
		$('#example tbody').html(str);
		
	    $('#example').dataTable();		
	},'json');

} );
    </script>
</head>
<body>
<table id="example" class="display" cellspacing="0" width="100%">
    <thead>
        <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
        </tr>
    </thead>
 
    <tfoot>
        <tr>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Age</th>
            <th>Start date</th>
            <th>Salary</th>
        </tr>
    </tfoot>
 
    <tbody>
       
    </tbody>
</table>
</body>
</html>

服务端脚本:

<?php
function getPassword(){
	$str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
	$pwdlen = rand(9,20);
	$passwd = '';
	for($i=0;$i<$pwdlen;$i++){
		$chr = rand(0,61);
		$passwd .= $str[$chr];
	}
	return $passwd;	
}
$data = array();
for($i=0;$i<8000;$i++){
	$data[] = array(getPassword(),getPassword(),getPassword(),getPassword(),getPassword(),getPassword());
}

echo json_encode($data);

以上测试虽然在本地运行,但是还是要稍等一会才有数据返回。如果是在互联网环境并且数据集合继续加大的情况,估计卡顿的情况就会比较明显。
jQuery Datatable

永久链接:http://blog.ifeeline.com/1504.html