[2008-07-24 07:49:47] 基于Picasa、PHP、AJAX的图片REST架构的简单实现 完结篇

//NOTOC 一如既往的前情提要: *[blog:98|基于Picasa、PHP、AJAX的图片REST架构的简单实现(1)] *[blog:99|基于Picasa、PHP、AJAX的图片REST架构的简单实现(2)] *[blog:104|基于Picasa、PHP、AJAX的图片REST架构的简单实现(3)] 现在,服务器端的架设终于全部结束了,我们可以向服务器端同一个URL发送不同的Header请求,从而得到不同的反馈,REST简单说来也就是这么一回事。但很遗憾,URL只有一个,而且现在的浏览器并没有智能到可以通过超链接携带Header信息。我们只能通过附加手段达到目的,这个附加手段毫无疑问就是最后一位主角:Ajax。 ====Step.3 客户端通过Ajax发送不同的Header请求==== 准确的说我们利用的是[http://www.w3.org/TR/XMLHttpRequest/|XMLHttpRequest]对象,来对服务器发送不同的header请求。在W3C的定义中,不仅能够找到GET、POST,XMLHttpRequest支持的header类型一共包括 *GET *POST *HEAD *PUT *DELETE *OPTIONS 这些Methods早在1999年就被定义于[http://www.ietf.org/rfc/rfc2616|RFC2616]里,到今天终于有了用武之地,真是可喜可贺。
var client = new XMLHttpRequest();
client.open("GET", "test.txt", true);
client.send();
这就是一个最简单的通过XMLHttpRequest发送请求的例子,同理可以将GET替换为其他Method。如果再加上监听状态变化的readystatechange,以及获得反馈的responseXXX,你会发现Ajax原来就是这么一回事。 这里为了使演示更加简单,使用JQuery的Ajax应用,以下是客户端代码:
	$("img").each(function(){
		var src = $(this).attr("src");
		var aim = $(this);
		$.ajax({
			type: "GET",
			url: src,
			dataType : 'json',
			success: function(json){
				var title= "<p>这是一张名为「" + json.title + "」的相片<br />拍摄于:" + json.date + "<br />你可以访问:" + json.full + "来获得这张照片的全图。</p>";
				aim.after(title);
				aim.attr("alt",json.title);
			}
		});
		return false;
	});
这段代码遍历页面的所有图片,然后对这张图片的URL发送Get请求。发送的请求被我们编写的服务器端接收并取得对应的Json数据并返回,最终在客户端显示出来。 至此,这个最简单的图片REST架构便完成了,或许花这么大功夫最终只显示出一张图片来,还称之为构架,实在是小题大作。但最终能剔除所有冗余信息并实现HTML代码的最简化,我自己是玩的不亦乐乎的。 最后附上[http://cid-01e48df64f8bd957.skydrive.live.com/embedrowdetail.aspx/Source/photorest.7z|全部代码下载],也可以[lab:/photo_rest/|在线查看]。 =====付录:HTTP-Header最高绝技之翻墙术===== 其实在国内有很多AV国的网站上不了,并不是GFW的功劳,而网站为了避免拦截正常的访问,也很少会去封IP段。那么究竟为什么很多XX站不能访问呢,在HTTP-Header中,有一个叫Accept-Language的字段负责描述用户的系统语言,国内的Accept-Language值一般都是zh-cn,zh,AV国的很多网站都是通过识别这个值来区别用户。 那么很简单,更改Accept-Language伪装成AV国用户就可以了。 *Firefox下,地址栏访问about:config,然后搜索intl.accept_languages,将值由zh-cn,zh改为ja即可。 *IE下,工具——Internet选项——语言——将列表里的语言全部删除即可。 恩恩,这也只是一个技术问题,大家回去自行研究吧。 Read More

[2008-06-04 09:05:16] Javasript Date对象的扩展、国际化、总结及其他

一个优秀的程序必须要兼顾I18n和L10N,但Javascript在Date处理这一方面做得很不友好,问题反映在以下几个方面: #虽然Js也设置了UTC时间函数,但脚本运行时的时区是自动从系统获得的,且无法更改。而在实际应用中,往往需要接受一个非当前系统时区的时间数据进行转换,这时候Js的自作聪明就带来了许多麻烦。 #Js对日期的自动解析和格式化输出根据系统环境、浏览器环境不同,表现也不同,这主要反映在Date.parse和toLocaleString方法上,有兴趣的同学可以自行测试。 为了尽可能简便的改善Js的Date处理能力,这里只对Js的Date对象做了两个扩展
	/**
	 * 获得当前时间的UTC时间戳
	 * @return {int} unix timestamp
	 */
	Date.prototype.getTimeUTC = function() {
		return this.getTime() + this.getTimezoneOffset() * 60 * 1000;
	}
	/**
	 * 将当前操作的时间变更时区(主要用于转换一个其他时区的时间)
	 * 
	 * @param {int} tzo 原时区 -12~13
	 * @param {int} tzo 目标时区 -12~13 默认为当前时区
	 */
	Date.prototype.changeTimezone = function(tzo,tzn) {
		tzo = tzo * 60;
		tzn = tzn ? tzn * 60 : -this.getTimezoneOffset();
		this.setTime(this.getTime() - (tzo - tzn) * 60 * 1000);
	}
至此,就可以基于这个扩展过的Js Date对象进行新的开发。 思路很简单,就是把任意格式任意时区的时间先通过changeTimezone方法转到和当前系统同一时区下,然后再对getTimeUTC生成的UTC Unix时间戳进行操作。 比如我要计算 +8 时区下 4 Jun 2008, 16:30时刻 与 +9 时区下的当前时刻相差的时间
	//自动解析成unix时间戳
	var p = Date.parse('4 Jun 2008, 16:30');

	var time_parse = new Date(p);

	//转换到要对比的时区
	time_parse.changeTimezone(8,9);

	var time_now = new Date();

	//都转换为UTC进行对比
	var der = time_now.getTimeUTC() - time_parse.getTimeUTC();

	alert('相差' + parseInt(der / 1000 / 60) + '分钟');
当然有更简单的编码,但在复杂运用中理清思路更加不容易出错。 如果想要实现本Blog左侧栏XX天XX月前这样更人性化的提示,这里可以根据自己的需要做进一步扩展。实现的函数如下
	/**
	 * 表示指定时间与现在的差值
	 * 
	 * @param {int} t 所要比较的时间 unix timestamp (UTC)
	 * @param {int} n 作为标准的时间,默认为现在时刻 unix timestamp (UTC)
	 * @return {string} 对相差时间的表述
	 */
	Date.prototype.derTime = function(t,n) {
		var n = n ? n : this.getTimeUTC();
		function ms2min(ms) {
			return parseInt(ms / 1000 / 60);
		}
		var der = ms2min(n - t);
		var ba = der > 0 ? '前' : '后';
		der = Math.abs(der);
		var res = '';
		if(der == 0) {
			res = '刚刚';
		}
		else if(0 < der && der < 60) {
			res = der + '分钟' + ba;
		}
		else if(60 <= der && der < 24 * 60) {
			var min = der % 60 == 0 ? '' : String(der % 60) + '分钟';
			res = String(parseInt(der / 60)) + '小时' + min + ba;
		}
		else if(der >= 24 * 60 && der < 24 * 60 * 31) {
			res = String(parseInt(der / 60 / 24)) + '天' + ba;
		}
		else if(der >= 24 * 60 * 31 && der < 24* 60 * 365) {
			res = String(parseInt(der / 60 / 24 / 31)) + '个月' + ba;
		}
		else if(der > 24 * 60 * 365) {
			res = String(parseInt(der / 60 / 24 / 365)) + '年' + ba;
		}
		return res;
	}
	/**
	 * 解析一个时间字段与当前时间的差
	 * @param {string} i
	 * @param {int} 时区 -12~13
	 */
	function time_der(i,tz) {
		var p = Date.parse(i);
		if(!p) {
			return i;
		}
		var time_parse = new Date(p);
		if(tz != undefined) {
			time_parse.changeTimezone(tz);
		}
		var time_now = new Date();
		return time_now.derTime(time_parse.getTimeUTC());
	}
Read More

[2008-05-30 08:49:56] 轻量级的Accordion With JQuery

Jquery的UI中是有Accordion的,200余行代码配合themes带来的负担,让使用前不可不慎重考虑。 仔细分析一下Accordion的动作其实很简单,顺序排列的N个元素,页面载入时只显示其中一个,点击某个元素时,展开当前元素并隐蔽其他。 那么配合JQuery强大的选择器,完全可以用几行代码打造自己的轻量级Accordion。 以本Blog的左边侧栏为例:
//页面载入时隐蔽除第一个元素外所有元素
$("#accordion > li > div + *:not(:first)").hide();
//对所有元素的标题绑定点击动作
$('#accordion > li > div').click(function(){
	$(this).parent().parent().each(function(){
		//隐蔽所有元素
		$("> li > div + *",this).slideUp();
	});
	//展开当前点击的元素
	$("+ *",this).slideDown();
});
总共不过7行,当然选择对象部分需要根据自己的情况灵活指定。 ASUS Eee,华硕又见华硕,难道我是ASUS控么- -||| Read More
Now Loading...