[JQuery]客户端验证插件Validate使用

mikel阅读(539)

最近在做一个用户注册登录的页面,资料查寻过程中发现了一个非常不错的客户端验证的极品-JQuery.validate
它是著名的JavaScriptJQuery的一个插件,其实它还有其它的一些插件应该都爽,有待慢慢来学习
官方地址:http://bassistance.de/JQuery-plugins/jQuery-plugin-validation/
jQuery用户手册:http://jQuery.org.cn/visual/cn/index.xml
开发使用起来非常简单明了,
我的代码:

Java代码
  1. $(document).ready(function(){   
  2.   
  3. /* 设置默认属性 */   
  4. $.validator.setDefaults({   
  5.   submitHandler: function(form) { form.submit(); }   
  6. });   
  7. // 中文字两个字节   
  8. jQuery.validator.addMethod("byteRangeLength", function(value, element, param) {   
  9.   var length = value.length;   
  10.   for(var i = 0; i < value.length; i++){   
  11.    if(value.charCodeAt(i) > 127){   
  12.     length++;   
  13.    }   
  14.   }   
  15.   return this.optional(element) || ( length >= param[0] && length <= param[1] );   
  16. }, "请确保输入的值在3-15个字节之间(一个中文字算2个字节)");   
  17.   
  18. /* 追加自定义验证方法 */   
  19. // 身份证号码验证   
  20. jQuery.validator.addMethod("isIdCardNo", function(value, element) {   
  21.   return this.optional(element) || isIdCardNo(value);   
  22. }, "请正确输入您的身份证号码");   
  23.   
  24. // 字符验证   
  25. jQuery.validator.addMethod("userName", function(value, element) {   
  26.   return this.optional(element) || /^[\u0391-\uFFE5\w]+$/.test(value);   
  27. }, "用户名只能包括中文字、英文字母、数字和下划线");   
  28.   
  29. // 手机号码验证   
  30. jQuery.validator.addMethod("isMobile", function(value, element) {   
  31.   var length = value.length;   
  32.   return this.optional(element) || (length == 11 && /^(((13[09]{1})|(15[09]{1}))+\d{8})$/.test(value));   
  33. }, "请正确填写您的手机号码");   
  34.   
  35. // 电话号码验证   
  36. jQuery.validator.addMethod("isPhone", function(value, element) {   
  37.   var tel = /^(\d{3,4}-?)?\d{7,9}$/g;   
  38.   return this.optional(element) || (tel.test(value));   
  39. }, "请正确填写您的电话号码");   
  40.   
  41. // 邮政编码验证   
  42. jQuery.validator.addMethod("isZipCode", function(value, element) {   
  43.   var tel = /^[09]{6}$/;   
  44.   return this.optional(element) || (tel.test(value));   
  45. }, "请正确填写您的邮政编码");   
  46. $(regFrom).validate({   
  47. /* 设置验证规则 */   
  48.   rules: {   
  49.    userName: {   
  50.     required: true,   
  51.     userName: true,   
  52.     byteRangeLength: [3,15]   
  53.    },   
  54.    password: {   
  55.     required: true,   
  56.     minLength: 5   
  57.    },   
  58.    repassword: {   
  59.     required: true,   
  60.     minLength: 5,   
  61.     equalTo: "#password"   
  62.    },   
  63.    question: {   
  64.     required: true   
  65.    },   
  66.    answer: {   
  67.     required: true   
  68.    },   
  69.    realName: {   
  70.     required: true   
  71.    },   
  72.    cardNumber: {   
  73.     isIdCardNo: true   
  74.    },   
  75.    mobilePhone: {   
  76.     isMobile: true   
  77.    },   
  78.    phone: {   
  79.     isPhone: true   
  80.    },   
  81.    email: {   
  82.     required: true,   
  83.     email: true   
  84.    },   
  85.    zipCode: {   
  86.     isZipCode:true   
  87.    }   
  88.   },   
  89. /* 设置错误信息 */   
  90.   messages: {   
  91.    userName: {   
  92.     required: "请填写用户名",   
  93.     byteRangeLength: "用户名必须在3-15个字符之间(一个中文字算2个字符)"   
  94.    },   
  95.    password: {   
  96.     required: "请填写密码",   
  97.     minlength: jQuery.format("输入{0}.")   
  98.    },   
  99.    repassword: {   
  100.     required: "请填写确认密码",   
  101.     equalTo: "两次密码输入不相同"   
  102.    },   
  103.    question: {   
  104.     required: "请填写您的密码提示问题"   
  105.    },   
  106.    answer: {   
  107.     required: "请填写您的密码提示答案"   
  108.    },   
  109.    realName: {   
  110.     required: "请填写您的真实姓名"   
  111.    },   
  112.    email: {   
  113.     required: "请输入一个Email地址",   
  114.     email: "请输入一个有效的Email地址"   
  115.    }   
  116.   },   
  117. /* 错误信息的显示位置 */   
  118.   errorPlacement: function(error, element) {   
  119.    error.appendTo( element.parent() );   
  120.   },   
  121. /* 验证通过时的处理 */   
  122.   success: function(label) {   
  123.    // set   as text for IE   
  124.    label.html(" ").addClass("checked");   
  125.   },   
  126. /* 获得焦点时不验证 */   
  127.   focusInvalid: false,   
  128.   onkeyup: false   
  129. });   
  130.   
  131. // 输入框获得焦点时,样式设置   
  132. $('input').focus(function(){   
  133.   if($(this).is(":text") || $(this).is(":password"))   
  134.    $(this).addClass('focus');   
  135.   if ($(this).hasClass('have_tooltip')) {   
  136.    $(this).parent().parent().removeClass('field_normal').addClass('field_focus');   
  137.   }   
  138. });   
  139.   
  140. // 输入框失去焦点时,样式设置   
  141. $('input').blur(function() {   
  142.   $(this).removeClass('focus');   
  143.   if ($(this).hasClass('have_tooltip')) {   
  144.    $(this).parent().parent().removeClass('field_focus').addClass('field_normal');   
  145.   }   
  146. });   
  147. });   

网上的资料有人说,它跟prototype包会有冲突,我还没有同时使用过,这点不是很清楚,但我是发现一个问题:
对于最小/大长度的验证方法,作者可能考虑到大家的命名习惯不同,同时做了minLength和minlength(maxLength和 maxlength)方法,应该哪一个都是可以的,但对于用户Message来说,只能够定义针对minlength(maxlength),才能调用用 户自定义的Message,
否则只是调用包的默认Message,但具体原因还没有查清楚。同时,这个插件提供了本地化的消息,但对于我这里初学者来说,怎么使用它还有待摸索!

[Web]如何让网页更快

mikel阅读(475)

谷歌官方博客与代码博客联合发布


发表于:2009年6月23日 下午 15:55:00

为了让谷歌提供的服务更快速,我们在世界不同地区建立数据中心并设计更高更有效的用户界面。我们把专注于 速度的提升看做产品和基础结构发展,这是因为,我们的研究表明,搜索速度越快越容易被认可。通过多年来不断的测试,我们发现了一些在网络社区上最好的应用,并通过 http://code.google.com/speed 与大家分享,这是为网站开发者设计的,里面有教程、技巧和实际操作的工具。

我们很高兴能与网络社区
讨论谷歌所了解的网络性能。然而,想要让浏览网络的速度与翻杂志的速度一样快,去优化网络应用的速度,我们需要共同努力,来攻克使网络变慢的难题,阻止那些潜在的、导致网络变慢的问题发生:

  • 在宽带和丰富的网页交互程序处于初始阶段的时候,一些为网络和网页发展提供动力的协议已经得到了发展。在过去的20年里,网络已经变得越来越快,通过合作来更新网络协议例如HTML和TCP/IP,我们可以为所有用户创造出更好的网络体验。网络社区协作最好的例证就是 HTML5 。现在 HTML5 的一些特征,例如AppCache,可以让开发者用大量复杂的 JavaScript 网络程序编写,并且让它运行起来就像是桌面应用程序一样快捷。


  • 在过去的十年里,我们看到JavaScript速度提升了近 100。浏览器的开发者和围绕在他们周围的社区需要持续关改进,以此为浏览者提供平台,让他们能够选择更有特色、更复杂的应用。


  • 其实,很多网站只需要很少的努力就能让反应速度变快,多关注用户体验可以让整个网络时间都变得更快。类似于雅虎 YSlow 和谷歌最新发布的 Page Speed 这样的工具,可以帮助网页开发者做出速度更快、更有效的网络插件。作为一个社区,我们需要进一步投资开发新一代工具,来评估、诊断和优化由一次点击带来的工作。


  • 虽然目前全球范围内有超过4亿宽带接入,宽带的渗透发展在一些地区仍然相对较慢。行业中的先锋已开始采取措施将宽带的益处带向更多的人,如 FCC决定 为以谷歌在内的整个互联网社区开放空格频谱。在世界范围内把便宜可靠的宽带接入的好处带给大家,应该成为我们这个行业的主要目标之一。

想要看Googler对提升网络速度有什么想法,请看下面的视频。如果你对怎样为网络加速有自己的想法和见解,请与社区的其他用户分享。让我们一同努力让网络的速度变得更快!

[Flex]FlexPMD开源项目发布

mikel阅读(429)

Adobe Technical Service团队今天发布了一个开源的项目,叫做FlexPMD。
FlexPMD主要用来提升Flex/AS3源文件中的代码质量并且检测常见的不好的代码实践,比如无用的代码,效率低的代码片段,过于复杂的代码等等这些都是FlexPMD检测并报告的对象。
作为开发者,现在你也可以完全获得FlexPMD的项目并参与到其中了。
http://opensource.adobe.com/wiki/display/flexpmd/FlexPMD
下载:
http://opensource.adobe.com/wiki/display/flexpmd/Downloads
获取源代码:
http://opensource.adobe.com/wiki/display/flexpmd/Get+Source+Code

[C#]c#扩展方法奇思妙用高级篇五:ToString(string format) 扩展

mikel阅读(548)

这篇文章将ToString()进行了扩充,加入了Format参数,一直以来表示层用Json数据格式,起始可以将toString函数进行Json数据格式转换,将实体类转换为Json格式,这样方便了表示层使用

转载自:http://www.cnblogs.com/ldp615/archive/2009/09/02/1559020.html

 在.Net中,System.Object.ToString()是用得最多的方法之一,ToString()方法在Object类中被定义为virtual,Object类给了它一个默认实现:

1     public virtual string ToString()
2     {
3         return this.GetType().ToString();
4     }

 .Net中原生的class或struct,如int,DateTime等都对它进行重写(override),以让它返回更有价值的值,而不是 类型的名称。合理重写的ToString()方法中编程、调试中给我们很大方便。但终究一个类只有一个ToString()方法,不能满足我们多样化的需 求,很多类都对ToString()进行了重载。如下:

1     string dateString = DateTime.Now.ToString("yyyy");  //2009
2     string intString = 10.ToString("d4");  //0010

 int、DateTime都实现了ToString(string format)方法,极大方便了我们的使用。

 对于我们自己定义的类型,我们也应该提供一个合理的ToString()重写,如果能够提供再提供一个ToString(string format),就会令我们后期的工作更加简单。试看以下类型: 

 1     public class People
 2     {
 3         private List<People> friends = new List<People>();
 4 
 5         public int Id { getset; }
 6         public string Name { getset; }
 7         public DateTime Brithday { getset; }
 8         public People Son { getset; }
 9         public People[] Friends { get { return friends.ToArray(); } }
10 
11         public void AddFriend(People newFriend)
12         {
13             if (friends.Contains(newFriend)) throw new ArgumentNullException("newFriend""该朋友已添加");
14             else friends.Add(newFriend);
15         }
16         public override string ToString()
17         {
18             return string.Format("Id: {0}, Name: {1}", Id, Name);
19         }
20         
21     }

 一个简单的类,我们给出一个ToString()重写,返回包含Id和Name两个关键属性的字符串。现在我们需要一个ToString(string format)重写,以满足以下应用:

1     People p = new People { Id = 1, Name = "鹤冲天", Brithday = new DateTime(199099) };
2     string s0 = p.ToString("Name 生日是 Brithday"); //理想输出:鹤冲天 生日是 1990-9-9
3     string s1 = p.ToString("编号为:Id,姓名:Name"); //理想输出:编号为:1,姓名:鹤冲天

 想想怎么实现吧,记住format是可变的,不定使用了什么属性,也不定进行了怎样的组合…

 也许一个类好办,要是我们定义很多类,几十、几百个怎么办?一一实现ToString(string format)会把人累死的。好在我们有扩展方法,我们对object作一扩展ToString(string format),.Net中object是所有的基类,对它扩展后所有的类都会自动拥有了。当然已有ToString(string format)实现的不会,因为原生方法的优先级高,不会被扩展方法覆盖掉。

 来看如何实现吧(我们会一步一步改进,为区分各个版本,分别扩展为ToString1、ToString2…分别对应版本一、版本二…):

 1     public static string ToString1(this object obj, string format)
 2     {
 3         Type type = obj.GetType();
 4         PropertyInfo[] properties =  type.GetProperties(
 5             BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
 6 
 7         string[] names = properties.Select(p => p.Name).ToArray();
 8         string pattern = string.Join("|", names);
 9 
10         MatchEvaluator evaluator = match =>
11             {
12                 PropertyInfo property = properties.First(p => p.Name == match.Value);
13                 object propertyValue = property.GetValue(obj, null);
14                 if (propertyValue != nullreturn propertyValue.ToString();
15                 else return "";
16             };
17         return Regex.Replace(format, pattern, evaluator);
18     }

 3~5行通过反射获取了公有的、实例的Get属性(如果需要静态的或私有的,修改第5行中即可),7~8行动态生成一个正则表达式来匹配 format,10~16行是匹配成功后的处理。这里用到反射和正则表达式,如果不熟悉不要紧,先调试运行吧,测试一下前面刚提到的应用:

 第一个和我们理想的有点差距,就是日期上,我们应该给日期加上"yyyy-MM-dd"的格式,这个我们稍后改进,我们现在有一个更大的问题:

 如果我们想输出:“People: Id 1, Name 鹤冲天”,format怎么写呢?写成format="People: Id Id, Name Name",这样没法处理了,format中两个Id、两个Name,哪个是常量,哪个是变量啊?解决这个问题,很多种方法,如使用转义字符,可是属性长 了不好写,如format="\B\r\i\t\h\d\a\y Brithday"。我权衡了一下,最后决定采用类似SQL中对字段名的处理方法,在这里就是给变量加上中括号,如下:

1     People p2 = new People { Id = 1, Name = "鹤冲天", Brithday = new DateTime(199099) };
2     string s2 = p1.ToString2("People:Id [Id], Name [Name], Brithday [Brithday]");

 版本二的实现代码如下:

 1    public static string ToString2(this object obj, string format)
 2    {
 3        Type type = obj.GetType();
 4        PropertyInfo[] properties = type.GetProperties(
 5            BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
 6 
 7        MatchEvaluator evaluator = match =>
 8        {
 9            string propertyName = match.Groups["Name"].Value;
10            PropertyInfo property = properties.FirstOrDefault(p => p.Name == propertyName);
11            if (property != null)
12            {
13                object propertyValue = property.GetValue(obj, null);
14                if (propertyValue != nullreturn propertyValue.ToString();
15                else return "";
16            }
17            else return match.Value;
18        };
19        return Regex.Replace(format, @"\[(?<Name>[^\]]+)\]", evaluator, RegexOptions.Compiled);
20    }

 调试执行一下:

 

  与版本一类似,不过这里没有动态构建正则表达式,因为有了中括号,很容易区分常量和变量,所以我们通过“属性名”来找“属性”(对应代码中第 10行)。如果某个属性找不到,我们会将这“[Name]”原样返回(对就第17行)。另一种做法是抛出异常,我不建议抛异常,在 ToString(string format)是不合乎“常理”的。 

 版本二相对版本一效率有很大提高,主要是因为版本二只使用一个简单的正则表达式:@"\[(?<Name>[^\]]+)\]"。而版本一中的如果被扩展类的属性特别多,动态生成的正则表达式会很长,执行起来也会相对慢。
 

 我们现在来解决两个版本中都存在的时间日期格式问题,把时间日期格式"yyyy-MM-dd"也放入中括号中,测试代码如下:

1     People p3 = new People { Id = 1, Name = "鹤冲天", Brithday = new DateTime(199099) };
2     string s3 = p3.ToString3("People:Id [Id: d4], Name [Name], Brithday [Brithday: yyyy-MM-dd]");

 版本三实现代码:

 1     public static string ToString3(this object obj, string format)
 2     {
 3         Type type = obj.GetType();
 4         PropertyInfo[] properties = type.GetProperties(
 5             BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance);
 6 
 7         MatchEvaluator evaluator = match =>
 8         {
 9             string propertyName = match.Groups["Name"].Value;
10             string propertyFormat = match.Groups["Format"].Value;
11 
12             PropertyInfo propertyInfo = properties.FirstOrDefault(p => p.Name == propertyName);
13             if (propertyInfo != null)
14             {
15                 object propertyValue = propertyInfo.GetValue(obj, null);
16                 if (string.IsNullOrEmpty(propertyFormat) == false)
17                     return string.Format("{0:" + propertyFormat + "}", propertyValue);
18                 else return propertyValue.ToString();
19             }
20             else return match.Value;
21         };
22         string pattern = @"\[(?<Name>[^\[\]:]+)(\s*:\s*(?<Format>[^\[\]:]+))?\]";
23         return Regex.Replace(format, pattern, evaluator, RegexOptions.Compiled);
24     }

 测试一下,可OK了:

 

  对于简单的值类型属性没问题了,但对于复杂一些类型如,如People的属性Son(Son就是儿子,我一开始写成了Sun),他也是一个People类型,他也有属性的,而且他也可能有Son…

 先看下调用代码吧:

1     People p4 = new People { Id = 1, Name = "鹤冲天", Brithday = new DateTime(199099) };
2     p4.Son = new People { Id = 2, Name = "鹤小天", Brithday = new DateTime(201599) };
3     p4.Son.Son = new People { Id = 3, Name = "鹤微天", Brithday = new DateTime(204099) };
4     string s4 = p4.ToString4("[Name] 的孙子 [Son.Son.Name] 的生日是:[Son.Son.Brithday: yyyy年MM月dd日]。");

 “鹤冲天”也就是我了,有个儿子叫“鹤小天”,“鹤小天”有个儿子,也就是我的孙子“鹤微天”。哈哈,祖孙三代名字都不错吧(过会先把小天、微天这两个名字注册了)!主要看第4行,format是怎么写的。下面是版本四实现代码,由版本三改进而来:

 1     public static string ToString4(this object obj, string format)
 2     {
 3         MatchEvaluator evaluator = match =>
 4         {
 5             string[] propertyNames = match.Groups["Name"].Value.Split('.');
 6             string propertyFormat = match.Groups["Format"].Value;
 7 
 8             object propertyValue = obj;
 9             try
10             {
11                 foreach (string propertyName in propertyNames)
12                     propertyValue = propertyValue.GetPropertyValue(propertyName);
13             }
14             catch
15             {
16                 return match.Value;
17             }
18 
19             if (string.IsNullOrEmpty(format) == false)
20                 return string.Format("{0:" + propertyFormat + "}", propertyValue);
21             else return propertyValue.ToString();
22         };
23         string pattern = @"\[(?<Name>[^\[\]:]+)(\s*[:]\s*(?<Format>[^\[\]:]+))?\]";
24         return Regex.Replace(format, pattern, evaluator, RegexOptions.Compiled);
25     }

 为了反射获取属性方法,用到了GetPropertyValue扩展如下(版本三的实现用上这个扩展会更简洁)(考虑性能请在此方法加缓存):

1     public static object GetPropertyValue(this object obj, string propertyName)
2     {
3         Type type = obj.GetType();
4         PropertyInfo info = type.GetProperty(propertyName);
5         return info.GetValue(obj, null);
6     }

 先执行,再分析:

 

 执行正确! 版本四,8~17行用来层层获取属性。也不太复杂,不多作解释了。说明一下,版本四是不完善的,没有做太多处理。

 我们最后再来看一下更复杂的应用,Peoplee有Friends属性,这是一个集合属性,我们想获取朋友的个数,并列出朋友的名字,如下:

1     People p5 = new People { Id = 1, Name = "鹤冲天"};
2     p5.AddFriend(new People { Id = 11, Name = "南霸天" });
3     p5.AddFriend(new People { Id = 12, Name = "日中天" });
4     string s5 = p5.ToString5("[Name] 目前有 [Friends: .Count] 个朋友:[Friends: .Name]。");

 注意,行4中的Count及Name前都加了个小点,表示是将集合进行操作,这个小点是我看着方便自己定义的。再来看实现代码,到版本五了:

 1     public static string ToString5(this object obj, string format)
 2     {
 3         MatchEvaluator evaluator = match =>
 4         {
 5             string[] propertyNames = match.Groups["Name"].Value.Split('.');
 6             string propertyFormat = match.Groups["Format"].Value;
 7 
 8             object propertyValue = obj;
 9 
10             try
11             {
12                 foreach (string propertyName in propertyNames)
13                     propertyValue = propertyValue.GetPropertyValue(propertyName);
14             }
15             catch
16             {
17                 return match.Value;
18             }
19 
20             if (string.IsNullOrEmpty(propertyFormat) == false)
21             {
22                 if (propertyFormat.StartsWith("."))
23                 {
24                     string subPropertyName = propertyFormat.Substring(1);
25                     IEnumerable<object> objs = ((IEnumerable)propertyValue).Cast<object>();
26                     if (subPropertyName == "Count")
27                         return objs.Count().ToString();
28                     else
29                     {
30                         string[] subProperties = objs.Select(
31                             o => o.GetPropertyValue(subPropertyName).ToString()).ToArray();
32                         return string.Join("", subProperties);
33                     }
34                 }
35                 else
36                     return string.Format("{0:" + propertyFormat + "}", propertyValue);
37             }
38             else return propertyValue.ToString();
39         };
40         string pattern = @"\[(?<Name>[^\[\]:]+)(\s*[:]\s*(?<Format>[^\[\]:]+))?\]";
41         return Regex.Replace(format, pattern, evaluator, RegexOptions.Compiled);
42     }

 执行结果:

 

 比较不可思议吧,下面简单分析一下。行22~行33是对集合进行操作的相关处理,这里只是简单实现了Count,当然也可以实现Min、Max、Sum、Average等等。“.Name”这个表示方法不太好,这里主要是为了展示,大家能明白了就好。 

 

 就写到这里吧,版本六、版本七…后面还很多,当然一个比一个离奇,不再写了。给出五个版本,版本一存在问题,主要看后三个版本,给出多个版本 是为满足不同朋友的需要,一般来说版本三足够,对于要求比较高,追求新技术的朋友,我推荐版本四、五。要求更高的,就是没给出的六、七…了。

 ToString(string format)扩展带来便利性的同时,也会带来相应的性能损失,两者很难兼得。

 最后重申下,本系列文章,侧重想法,所给的代码仅供演示、参考,没有考虑性能、异常处理等,如需实际使用,请自行完善。 

 

 本人系列文章《c#扩展方法奇思妙用》,敬请关注! 

[Map]Google Map学习(二) 简单的Google Map,Google Map事件

mikel阅读(468)

      上一节已经学习了Google Map的基础。首先回顾一下上一节的基本内容
            地图对象的创建:var map = new GMap2(document.getElementById("map"));
            设置map的默认显示形式:map.setMapType(G_HYBRID_MAP);
            设置地图的位置(这是必须的):map.setCenter(new GLatLng(22.4977,113.9208),19);
            添加一个信息窗口:map.openInfoWindowHtml(map.getCenter(),document.createTextNode("北科创业大厦"));
      以上内容都非常的简单,但是仅仅是显示了一张地图,非常单一。
      这一节,我们主要学习地图中的事件,并且通过事件做一些简单的交互。
  

Google Map的命名空间

      到现在大家可能已经发现了Google Map API中的类都带有一个大写字母G,G是Google Map API的顶级命名空间,它的原型是google.maps.*,比如GMap2也可以写成google.maps.Map2。
 
地图事件
      JavaScript是”事件驱动的“,也就是说JavaScript通过事件来响应交互。比如用户希望在某个DOM元素移动鼠标时,发生一 些什么,那么在这个DOM元素上移动鼠标就是一个事件,我们要做的就是监听这个事件,为这个事件注册监听器,也就是写一个监听函数,用户所希望的东西,我 们都可以在函数中进行表达。
      Google 地图 API 通过为地图 API 对象定义自定义事件而添加到此事件模型中。虽然不同浏览器中的DOM事件不同,但是Google Map API已经帮包含跨浏览器的机制,我们无需再因为用户使用不同浏览器而苦恼了。
 

注册事件监听器

      通过使用GEvent命名空间中的实用工具函数注册事件监听器,来处理Google Map API中的一些事件。每个对象都包含很多已有的事件,例如GMap2对象的click、dbclick事件。
      注册事件的方法很简单:GEvent.addListener(object,event,function),三个参数分别对象,待监听事件,事件调用函数。例如:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    
<title></title>
    
<script type="text/JavaScript" src="http://ditu.google.cn/maps?file=api&v=2">
    
</script>
    
<script type="text/javascript">
        
function load() {
            
if (GBrowserIsCompatible()) {
                
var px = 30.6562;
                
var py = 104.0639;
                
var cx = px;
                
var cy = py;
                
var zoom = 12;
                
var map = new GMap2(document.getElementById("map"));
                
var point = new GLatLng(px, py);
                map.setCenter(point,zoom);
            }

            
/*
            获得当前点击的地理坐标
            
*/

            GEvent.addListener(map, 
"click"function(marker, point) {
            
if (point) {
            px 
= point.lat();
            py 
= point.lng();
            zoom 
= map.getZoom();
            document.getElementById(
"lat").value = px;
            document.getElementById(
"lng").value = py;           
            }

            }
);
            
/*
            zoomend地图到达新的缩放级别时会触发此事件。事件处理程序接收先前的缩放级别和新缩放级别作为参数。
            
*/

            GEvent.addListener(map, 
"zoomend"function() {
                zoom 
= map.getZoom();
                
//document.getElementById("zoom").value = zoom;
            }
);
            
/*
            moveend结束地图视图的更改时会触发此事件。拖动或放大/缩小都会触发此事件
            
*/

            GEvent.addListener(map, 
"moveend"function() {
                
var center = map.getCenter();
                cx 
= center.lat();
                cy 
= center.lng();
                document.getElementById(
"lat").value = cx;
                document.getElementById(
"lng").value = cy;
                document.getElementById(
"centerLat").value = cx;
                document.getElementById(
"centerLng").value = cy;
                document.getElementById(
"zoom").value = zoom;
            }
);
            document.getElementById(
"lat").value = px;
            document.getElementById(
"lng").value = py;
            document.getElementById(
"centerLat").value = cx;
            document.getElementById(
"centerLng").value = cy;
            document.getElementById(
"zoom").value = zoom;
        }

        window.onload 
= load;
    
</script>
</head>
<body>
    
<div>
    当前经度:
<input type="text" id="lat"/><br />
    当前纬度:
<input type="text" id="lng"/><br />
    中心经度:
<input type="text" id="centerLat"/><br />
    中心纬度:
<input type="text" id="centerLng"/><br />
    当前倍率:
<input type="text" id="zoom"/>
    
</div>
    
<div style="width:500px; height:500px;" id="map"></div>
</body>
</html>

(如果在IE下出现GMap2未定义的错误,请刷新一遍,火狐下是正常的)

将事件绑定到对象方法

<!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></title>

    
<script type="text/javascript" src="http://ditu.google.cn/maps?file=api&v=2">
    
</script>

    
<script type="text/javascript">
        
function MyApplication() {  
            
this.counter = 0;  
            
this.map = new GMap2(document.getElementById("map"));  
            
this.map.setCenter(new GLatLng(39.9493116.3975), 13);  
            GEvent.bind(
this.map, "click"thisthis.onMapClick);
        }

        MyApplication.prototype.onMapClick 
= function() {
            
this.counter++;
            alert(
"这是您第" + this.counter + " " + "次点击");
        }

        window.onload 
= function(){
            
var application = new MyApplication();
        }

    
</script>

</head>
<body>
    
<div id="map" style="width:500px; height:500px;"></div>
</body>
</html>

(如果在IE下出现GMap2未定义的错误,请刷新一遍,火狐下是正常的)

监听DOM事件

       Google地图API事件模型创建并管理自己的自定义事件。但是,DOM也会根据当前使用的特定浏览器事件模型创建和调度自己的事件。如果你希望捕获这 些事件,Google地图API提供的独立于浏览器的包装器可以监听和绑定DOM事件而不需要自定义代码。

      GEvent.addDomListener()方法为DOM节点上的DOM注册事件处理程序。同样,GEvent.bindDom()方法允许你给类实例上的DOM事件注册事件处理程序。

删除事件监听器  

      不再需要事件监听器时,应将其删除。甚至在事件只需触发一次的情况下,也可能需要删除。删除闭包内的匿名函数所定义的事件监听器可能很困难。但是,addListener()addDomListener()bind()bindDom() 函数会返回 GEventListener 句柄,可用来最终取消注册处理程序。

      下面的示例通过在地图上放置标记来响应点击。任何后续点击都可删除事件监听器。请注意,这会导致不再执行 removeOverlay() 代码。另请注意,您甚至可以从事件监听器自身内部删除事件监听器。

     

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    
<title></title>
    
<script type="text/javascript" src="http://ditu.google.cn/maps?file=api&v=2">
    
</script>
    
<script type="text/javascript">
        
function MyApplication(){
            
this.counter = 0;
            
this.map = new GMap2(document.getElementById("map"));  
            
this.map.setCenter(new GLatLng(39.9493116.3975), 13);
            
var myEventListener = GEvent.bind(this.map, "click"thisfunction(overlay, latlng) {    
                
if (this.counter == 0{      
                    
if (latlng) {        
                    
this.map.addOverlay(new GMarker(latlng))        
                    
this.counter++;      
                    }
 
                    
else if (overlay instanceof GMarker) {        
                    
this.removeOverlay(marker);      
                    }
    
                }
 
                
else {      
                GEvent.removeListener(myEventListener);    
                }
  
            }
); 
        }

        window.onload 
= function(){
            
var application = new MyApplication();
        }

    
</script>
</head>
<body onunload = "GUnload()">
    
<div id="map" style="width:500px; height:500px;">
    
</div>
</body>
</html>

(如果在IE下出现GMap2未定义的错误,请刷新一遍,火狐下是正常的)

[Map]Google Map学习(一) 简单的Google Map,Google Map基础

mikel阅读(413)

Google地图API

1、 什么是Google地图API
  Google地图API是一种通过JavaScriptGoogle地图嵌入到您的网页的API。它提供了很多处理地图的功能(类似网页http://ditu.google.cn/上的那些功能)和向地图添加内容的服务,让您能够在您的网站上创建功能全面的地图应用。
一个地图API密钥只对一个“目录”或域有效(你必须有Google 帐户才能获得地图API密钥,并且API密钥会和你的Google账户联系)。
2、 地图基础知识
Google地图的“Hello World
开始学习Google地图API最简单的方式是看一个简单的示例。线面的网页显示以北京的故宫博物院为中心的500*500的地图。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GoogleMapDemo.aspx.cs" Inherits="GoogleMap.GoogleMapDemo" %>
<!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>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>Google Maps JavaScript API Example</title>
    <script src="http://ditu.google.cn/maps?file=api&amp;v=2&amp;key=abcdefg&sensor=true_or_false"
            type="text/javascript">
    </script>
     <script type="text/javascript">
        function intialize(){
            if(GBrowserIsCompatible()){
                var map = new GMap2(document.getElementById("map_canvas"));
                map.setCenter(new GLatLng(39.9493116.3975),13);
            }
        }
     </script>   
</head>
<body onload="intialize()" onunload="GUnload()">
    <div id="map_canvas" style="width: 500px; height: 500px;"></div>
</body>
</html>
 
即使在此简单的示例中,也需要注意五点:
        1、使用script标签包含Google地图API
        2、创建名为"map_canvas"的div元素来包含地图。
        3、编写JavaScript函数创建"map"对象。
        4、将地图的中心设置为制定的地理点。
        5、从body标签的onload事件初始化地图对象。
  
 
下面说明了这些步骤。
 

加载Google地图API

 
<script type="text/javascript" src="http://ditu.google.cn/maps?file=api&amp;v=2&amp;key=abcdefg&sensor=true_or_false">  </script>
      http://ditu.google.cn/maps?file=api&v=2&key=abcdefg网址指向包含使用 Google 地图 API 所需所有符号和定义的 JavaScript 文件的位置。您的页面必须包含指向此网址的 script 标签,使用注册 API 时收到的密钥。在此示例中,该密钥显示为abcdefg
    请注意,我们也传递 sensor 参数以指明此应用程序是否使用传感器来确定用户位置。在此示例中,我们将其设为变量“true_or_false”以强调您必须显式地将此值设置为 true  false
 

地图DOM元素

<div id="map_canvas" style="width: 500px; height: 500px;"></div>

 

Gmap2-基本对象

var map = new GMap2(document.getElementById("map_canvas"));

Gmap2类是表示地图的JavaScript类。此类的对象在页面上定义单个地图。(可以创建此类的多个实例,每个对象将在页面上定义一个不同的地图。)
当创建新的地图实例时,在页面中指定一个DOM节点(通常是div元素)作为地图的容器,通过document.getElementById()方法获得该元素的引用。

构造函数
说明
GMap2(container, opts?)
在通常是一个 DIV 元素的指定 HTML container 内创建新地图。您也可以通过 opts 参数传递 GMap2Options 类型的可选参数
请注意因为JavaScript是松散型语言,我们可以不填写构造函数的任何可选参数。
 

初始化地图

map.setCenter(new GLatLng(39.9493116.3975),13);

通过Gmap2构造函数创建地图后,我们需要再做一件事:将其初始化。初始化通过地图的setCenter()方法完成。SetCenter()方法要求有GlatLng坐标和缩放级别,而且必须先发送此方法,然后再在地图上执行其他任何操作,包括设置地图本身的其他任何属性。
 

加载地图

 

<body onload="intialize()" onunload="GUnload()">

GUnload()函数是用来防止内存泄漏的实用工具函数。


经度和纬度

既然已经有地图了,我们还需要一种方法来引用地图上的位置。在Google地图API中,GLatLng对象提供了此类机制。可以构造一个GLatLng对象,按照制图学的惯例{经度,纬度}的顺序传递参数:

var myGeographicCoordinates = new GLatLng(myLatitude, myLongitude)
注意:将“地址”转变为地理点的过程称为“地址解析”。
就像它可用于轻松地引用地理点一样,它可用于对象的地理边界。例如,地图在称为视口的窗口内显示整个世界的当前“窗口”。此视口可以通过四个角上的巨型点来定义。GLatLngBounds对象提供了这个功能,通过使用分别表示边界框的西南角和东北角的两个GLatLng对象定义一个矩形区域的实现。 
GLatLng对象在Google地图API中用途广泛。例如,GMarker对象在其构造函数中具有GLatLng,并在地图上的制定地理位置放置标记叠加层
下面的示例使用getBounds()放回当前视口,然后在地图上的这些边界内随机放置10个标记:
 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Demo2.aspx.cs" Inherits="GoogleMap.Demo2" %>
<!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>Demo2</title>
    <script type="text/javascript" src="http://maps.google.com/maps?file=api&v1=&key=abcdefg"></script>
    <script type="text/javascript">
        function initialize() {
      var map = new GMap2(document.getElementById("map_canvas"));
      map.setCenter(new GLatLng(39.9493116.3975), 13);
      // Add 10 markers to the map at random locations
      var bounds = map.getBounds();
      var southWest = bounds.getSouthWest();
      var northEast = bounds.getNorthEast();
      var lngSpan = northEast.lng() - southWest.lng();
      var latSpan = northEast.lat() - southWest.lat();
      for (var i = 0; i < 10; i++{
        var point = new GLatLng(southWest.lat() + latSpan * Math.random(),
            southWest.lng() + lngSpan * Math.random());
        map.addOverlay(new GMarker(point));
      }
    }
    </script>
</head>
<body onload="initialize()" onunload="GUnload()">
    <div style="width:500px; height:500px;" id="map_canvas">     
    </div>
</body>
   注意:有关 GMarker 对象的详细信息位于叠加层部分中。

地图属性

默认情况下,在Google地图API中,地图使用标准的“绘制”图块显示。但是,Google地图API也支持其他地图类型。以下是标准地图类型:
G_NORMAL_MAP                   默认视图
G_SATELLITE_MAP               显示Google地球卫星图像
G_HYBRID_MAP                    混合显示普通视图和卫星视图
G_DEFAULT_MAP_TYPES         这三个类型的数组,在需要重复处理的情况下非常有用
 
可以使用GMap2对象的setMapType()方法设置地图类型。例如,下面的代码将地图设置为使用Google地球的卫星视图:
 

var map =new GMap2(document.getElementById("map_canvas"));
map.setMapType(G_SATELLITE_MAP);
 
地图还包含对了解情况非常有用的大量属性。例如,要了解当前视口的尺寸,可使用GMap2对象的getBounds()方法来返回GLatLngBounds值。 
每个地图还包含一个“缩放级别”,用于定义当前视图的分辨率。在普通地图视图内,可以使用0(最低缩放级别,在都吐上可以看到整个世界)到19(最高缩放级别,可以看到独立建筑)之间的缩放级别。缩放级别因所查看地区而异,因为地球上某些地区的数据比其他地区更详细。在卫星视图中可以使用多达20个缩放级别。 
可以通过使用GMap2对象的getZoom()方法检索地图当前使用的缩放级别。
关于缩放级别、地图图块以及创建自己的自定义地图类型的更多信息,请参阅图块叠加层部分。

 
  地图交互

既然现在有了GMap2对象,就可以与之进行交互了。基本地图对象的外观和行为与您在Google地图网站上交互的地图非常相似,并带有大量的内置行为。GMap2对象还提供了大量配置方法来改变地图本身的行为。 
默认情况下,和在 http://ditu.google.cn 上一样,地图对象会对用户的活动做出反应。但您可以使用大量实用工具方法改变此行为。例如,GMap2.disableDragging() 方法禁止了点击并拖拽地图到新位置的功能。
您还可以通过编程与地图交互。GMap2 对象支持可以直接改变地图状态的大量方法。例如,setCenter()panTo  zoomIn() 方法通过编程来操作地图,而不是通过用户交互来操作地图。
下面的示例显示一个地图,等待两秒钟,然后平移到新中心点。panTo 方法将地图中心设置在指定点处。如果指定点位于地图的可见部分,则地图会平稳地平移到该点,否则会跳至该点。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Demo3.aspx.cs" Inherits="GoogleMap.Demo3" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Demo3</title>
    <script type="text/javascript" src="http://ditu.google.cn/maps?file=api&amp;v=2&amp;key=abcdefg"></script>
    <script type="text/javascript">
    function initialize(){
        var map = new GMap2(document.getElementById("map_canvas"));
        map.setCenter(new GLatLng(39.9493116.3975), 19);
        window.setTimeout(function(){
            map.panTo(new GLatLng(39.927116.407));
        },2000);
    }
    </script>
</head>
<body onload = "initialize()" onunload = "GUnload()">
    <div id="map_canvas" style="width:500px; height:500px;">
    </div>
</body>
</html>
 

  信息窗口
所有使用Google 地图API的地图都有可能显示类型为GInfoWindow的单个信息窗口,该窗口上地图上端以浮动窗口显示HTML内容。信息窗口有点像漫画书上的文字气球;它有一个内容区域的锥形引线,引线的头在地图的指定地点上。点击Google地图上的标记可以看到活动的信息窗口。 
GInfoWindow对象没有构造函数。当创建地图时,会自动创建一个信息窗口并将其附加到地图上。对于指定的地图,一次不能显示多个信息窗口,但可以移动信息窗口并可以改变其内容(如果需要)。
GMap2对象提供了openInfoWindow()方法,该方法将一个节点和一个HTML DOM元素作为参数。HTML DOM元素附加到信息窗口容器中,信息窗口的尖端固定在制定点上。
GMap2openInfoWindowHtml()方法相似,但是它使用HTML字符串最为其第二个参数而不是DOM元素。
要创建信息窗口,请调用openInfoWindow方法,并向其传递位置和要显示的DOM元素。下面的示例代码显示了一个信息窗口,该窗口锚定在地图中心,内容为一条简单消息”Hello,  world”

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Demo4.aspx.cs" Inherits="GoogleMap.Demo4" %>
<!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>Demo4</title>
    <script type="text/javascript" src="http://ditu.google.cn/maps?file=api&amp;v=2&amp;key=abcdefg"></script>
    <script type="text/javascript">
    function initialize(){
        var map = new GMap2(document.getElementById("map_canvas"));
        map.setCenter(new GLatLng(39.9493116.3975), 13);
        map.openInfoWindow(map.getCenter(),
        document.createTextNode("Hello, world"));
    }
    </script>
</head>
<body onload = "initialize()" onunload = "GUnload()">
    <div id="map_canvas" style="width:500px; height:500px;">   
    </div>
</body>
</html>
 
效果如图: 

[JQuery]Jquery Tabs 插件简介-更友好地组织你的页面

mikel阅读(374)

关于JQuery Tab插件,比较流行的是JQuery UI Tabs,最近此插件也已经有了更新,地址为http://stilbuero.de/jquery/tabs_3/ ,目前国内很多网站也在使用此插件,希望大家有时间了试用一下。

今天突然发现了一个更加轻量级的,功能更加丰富的 JQuery Tab插件。先展示一下其功能;

1、简单配置一下就可以实现如下效果:

http://flowplayer.org/tools/demos/tabs/index.html

2、扩展CSS样式就可以定做自己的tabs

/* alternate colors: skin2 */ 
ul.skin2 a { 
    background-color:#89a;         
    color:#fff !important; 

 
/* mouSEOver state */ 
ul.skin2 a:hover { 
    background-color:#678

 
/* active tab */ 
ul.skin2 a.current { 
    background-color:#4F5C6A
    border-bottom:2px solid #4F5C6A;     

 
/* tab pane with background gradient */ 
div.skin2 div { 
    color:#fff
    background:#234 url(/img/global/gradient/h300.png) repeat-x scroll 0 -50px
    min-height:200px
}

效果如下:

http://flowplayer.org/tools/demos/tabs/skins.html

3、只是浏览器的【前进】和【后退】

 

Code

效果如下:

http://flowplayer.org/tools/demos/tabs/history.html

4.通过Ajax调用每个Tab的内容,只有第一次点击Tab按钮的时候 调用Tab页内容

使用非常简单,效果如下:

http://flowplayer.org/tools/demos/tabs/ajax.html

5、Tab向导,比如形成购物车订单过程

完善个人信息->修改购物车商品->查看订单

效果如下:http://flowplayer.org/tools/demos/tabs/wizard.html

此种功能特别有用。

6、其他的还有手风琴效果,自己发掘吧,显示地址如下:

http://flowplayer.org/tools/demos/tabs/accordion-horizontal.html

 

此插件的下载地址如下:

http://flowplayer.org/tools/download.html

jQuery.tools.min.js是一个UI功能包,还包括其他的一个UI特效

Tooltip :很不错的提示功能插件

Scrollable :滚动效果插件

Overlay :很好用的遮罩层插件

Expose :背景变暗效果

[Flex]flex3:利用itemRenderer创建在线书店的图书信息显示页面

mikel阅读(458)

第一部分:预备知识—-认识itemRenderer

我们经常用itemRenderer,使用List,DataGrid,TileList等组件时经常动不动就来个itemRenderder。虽然很熟悉了,但是我打算今天还是再好好认识一下它。
使用itemRenderer有两点需要注意:
1,对于flex框架,使用itemRenderer很件很耗费内存的事,如果可以避免尽量不要用。
2,一个误会
假设我有一个List组件,与他绑定的数据有1000条,现在我要渲染这个List。是不是要创建1000个itemRenderer实例啊?这是个误会。
再假设,我这个List只能显示10个条目,那么或许flex或许只会给你创建12个itemRender实例,至于为什么多出两个,是出于缓 存和表现的原因。你拖动滚动条,第一条和第二条项目消失了,但是它们对应的itemRenderder只是改变了位置,加载了新的数据,还显示第十一和十 二条项目。所以,itemRenderer是重用(recycled)的,这一点得格外注意。不要试图调用第X条的itemRenderer再修改它,因 为如果此时它不再显示范围内,第X条对应的itemRenderer就不知道用来显示谁去了?要想改变一个itemRenderer,最好的办法就是根据 它的数据来改变它。
第二部分:初级—-inline itemRenderers
什么叫inline itemRenderer?这就是跟调用它的组件(以后成为list control)写在一起的那种。这是比较简单的那种。现在我们就用这种的itemRenderer先写个显示书单图书信息的页面。
下面是代码:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    
<mx:Script>
        
<![CDATA[
            [Bindable]
    public var bookInfo:XML=
            <books
>
                
<book>
                    
<name>手到病自除</name>
                    
<price>20.10</price>
                    
<writer>杨奕</writer>
                    
<image>bookpic/sdbzc.jpg</image>
                    
<instore>yes</instore>
                
</book>
                
<book>
                    
<name>好妈妈胜过好老师</name>
                    
<price>17.30</price>
                    
<writer>尹建莉</writer>
                    
<image>bookpic/hmmsghls.jpg</image>
                    
<instore>yes</instore>
                
</book>
                
<book>
                    
<name>货币战争</name>
                    
<price>26.90</price>
                    
<writer>宋鸿兵</writer>
                    
<image>bookpic/hbzz.jpg</image>
                    
<instore>no</instore>
                
</book>
                
<book>
                    
<name>不抱怨的世界</name>
                    
<price>15.4</price>
                    
<writer>鲍温</writer>
                    
<image>bookpic/bbydsj.jpg</image>
                    
<instore>yes</instore>
                
</book>
                
<book>
                    
<name>历史是个什么玩意儿</name>
                    
<price>19.60</price>
                    
<writer>袁腾飞</writer>
                    
<image>bookpic/lsssmwy.jpg</image>
                    
<instore>yes</instore>
                
</book>
                
<book>
                    
<name>不生病的智慧</name>
                    
<price>17.20</price>
                    
<writer>马悦凌</writer>
                    
<image>bookpic/bsbdzh.jpg</image>
                    
<instore>no</instore>
                
</book>
            
</books>
        ]]>
    
</mx:Script>
    
<mx:TileList dataProvider="{bookInfo.book}" width="600" height="600" variableRowHeight="true" x="100" y="0">
        
<mx:itemRenderer>
            
<mx:Component>
            
<mx:VBox width="150" height="200" horizontalAlign="center">
                
<mx:Image source="{data.image}"/>
                
<mx:Label text="{data.name}"/>
                
<mx:Button label="buy"/>
            
</mx:VBox>    
            
</mx:Component>
        
</mx:itemRenderer>
    
</mx:TileList>
</mx:Application
要使用inline itemRenderer,方法就是在<mx:itemRenderer>标签里嵌套一个<mx:component>的标签。 在<mx:component>就是你要用来渲染数据的组件。要记住的一点就是应该把<mx:component>里的代码看做 一个单独的外部定义的类,它与其他的代码的并不是一起的。所以,我们不能直接调用写在<mx:Script>里的函数。当我们要处理buy那 个按钮时,就会遇到这个问题。这个按钮虽然简单,但是它负责着itemRender与外部的交互。现在,先不考虑这些,我们只考虑如何调用外部的函数。假 设,在上面的<mx:Script>里有一个buyBook()函数,在上面的itemRender里必须如此调用:
<mx:Button label="buy" click="outerDocument.buyBook()"/>
重点就是那个outerDocument。特别注意一点,buyBook()函数必须声明为public。
好,到现在为止,我们做出的东西就如下面那个样子。
看来背景色不应该用白色的,待会在改吧!O(∩_∩)O~
第三部分:中级—–引用外部组件作为itemRenderer
其实,可以写基于任何组件的自定义组件作为itemRender,但是具体来讲还是有区别的。在选基类时考虑两方面:一就是性能,很明显 Canvas比HBox更轻量级,当然最好是用基于UIComponent的组件作为itenRenderer,这个稍后会写;二就是,看组件是否实现了 IDropInListItemRenderer接口,至于这个接口的作用,稍后会遇到。
现在我们现做的,就是把上面嵌入list control的itemRenderer部分移到外面的文件,我们建立一个BookInfoRenderer组件好了,基于HBox的。
itemRenderer的代码:
Code
引用itemRenderer的相关代码:
<mx:TileList columnWidth="200" rowHeight="150" itemRenderer="BookInfoRenderer" dataProvider="{bookInfo.book}">    
</mx:TileList>
通常情况下,itemRenderer的宽度不会被考虑,即使你设定了。如果你设定了rowHeight,那么原来的itemRenderer的高度就会被忽略,如果你不想让他被忽略,设定variableRowHeight为true。
引用外部的类作为itemRenderer就是这个样子。
现在我们研究一下如何动态的改变itemRenderer。前面说过要改变itemRenderer就必须根据它的数据,因为它是recycled。
重新写一下itemRenderer组件,重写后,书的价格被格式化了(加了个$)。
Code
重写set data方法时,千万不要忘记super.data=value这句话。
现在是这个样子:
第四部分:高级——与list control的交互
那个像是TileList,List,DataGrid之类的就叫list control,反正技术文档里就是这么说的,不知道该怎么翻译,就这样叫吧。那个itemRenderer好像叫做渲染器,inlineh好像翻译为行内。不知道怎么翻译准确,就用原名吧。
现在在来研究那个buy按钮。点了它之后,应该弹出一个对话框告诉用户买的什么东西,价格是多少。现在的问题是,这个弹出对话框的函数写在哪 里,写在itemRenderer对应的函数里吗?按理说,没什么错误。但是我们应该谨记这样的原则,itemRenderer是用来表现数据的,而非处 理数据,处理数据是list control的任务。那好,弹出对话框的函数应该写在list control对应的文件里。那么又遇到了一个问题,弹出的内容包含着书的信息,这个信息保存在itemRenderer的数据里,如何把这个数据传给 list control呢?或许,最好的方法就是利用Event,当点击按钮时派发一个自定义事件,事件里包含着书的信息。好的,现在剩下的最后一个问题就是这个 事件由谁来派发?itemRenderer? or list control?按理说,谁派发都一样,反正事件会冒泡,即使用itemRenderer来派发,list control也会捕捉到。但是,为了逻辑上更清楚和使用上更方便,我们让list control来派发事件。逻辑上更清楚似乎有点不好理解,但是记住itemRenderer的任务是表现数据。使用上更方便时显而易见的,而且可移植性 还会好些,待会就会看到。当然,让itemRenderer来派发事件,也不会有什么错误,而且更方便一些。
好的,现在先定义一个事件:BuyBookEvent
Code
定义完了事件,我们在自定一个TileList组件。这就是有点麻烦的地方,因为它要派发事件,所以必须自定义一下。好在,还不是太麻烦。
MyTileList:
Code
好了,现在我们将迎来最复杂的一步,调整itemRenderer。其实复杂的原因很简单:继承自HBox的itemRenderer不能够调 用到他的list control。前面讲过,你要用那个组件作为基类来实现itemRenderer是有区别的,区别之一就是看它有没有实现 IDropInListItemRenderer接口。只有实现这个接口的组件作为itemRenderer才能有方法调用到他的ilst control。Button,CheckBox,Label都实现了,但是Hbox没有实现。没有实现,我们就必须自己实现它。
来吧!
我把代码再全写一遍:
Code
虽然,涉及到的知识有些复杂但是步骤还是很简单的:
第一步:在跟标签写入implements="mx.controls.listClasses.IDropInListItemRenderer"
第二步:导入import mx.controls.listClasses.BaseListData;
第三步:把相关的代码拷入。
好了,现在的问题是,listData是做什么用的?因为我们实现IDropInListItemRenderer接口就是为了实现这个属性。它是做什么,有些复杂,可以去看参考资料,这里就不粘贴了。只说说怎么用它好了。
回到itemRenderer文件:处理buy按钮的事件:
<mx:Button label="buy">
        
<mx:click>
            
<![CDATA[
                (listData.owner as MyTileList).disPatchBookEvent(data);
            ]]
>
        
</mx:click>
        
</mx:Button>
现在回到list control所在的文件,捕获事件:
<local:MyTileList columnWidth="200" rowHeight="150" buyBook="doBuy(event)"
        itemRenderer
="BookInfoRenderer" dataProvider="{bookInfo.book}"/>
看到了吗?方便的地方就是我可以在标签里直接buyBook="doBuy(event)"这样写。
再加上处理函数doBuy(evnt)就大功告成了.
private function doBuy(event:BuyBookEvent):void{
                mx.controls.Alert.show(event.bookData.name+":"+event.bookData.price);
            }
好了就先写到这里吧,已经写了这么多了,O(∩_∩)O~。
例子虽然简单,可是内容还是很多的……
至于继承自UIComponent的itemRenderer,大概也是这个思路,有空再说吧!

[IIS]用ISAPI_Rewrite实现反向代理(ReverseProxy)

mikel阅读(453)

ISAPI_Rewrite是一个强大的基于正则表达式的URL处理引擎。它非常类似于Apache's mod_Rewrite,但它是专为IIS设计的。
ISAPI_Rewrite有两个版本:ISAPI_Rewrite Full与ISAPI_Rewrite Lite。
ISAPI_Rewrite Lite是免费版本,但不支持反向代理功能。
ISAPI_Rewrite Full只能下载到30天的试用版本。
这篇文章介绍的是基于ISAPI_Rewrite Full实现反向代理。配置实际上很简单。写出来的目的主要是希望给初次使用ISAPI_Rewrite的朋友提供参考。
下面就是配置步骤:
1、下载ISAPI_Rewrite Full: http://www.helicontech.com/download/#isapi_rewrite
2、安装ISAPI_Rewrite Full
3、修改配置文件httpd.ini,默认位置在C:\Program Files\Helicon\ISAPI_Rewrite。假如我们现在有两台Web服务器,一台是www.cnblogs.com, 另一台是 www2.cnblogs.com,  www2作为一台反向代理服务器,客户端浏览器访问www2服务器,www2服务器向www服务器请求内容并返回给客户端。具体在httpd.ini的配置如下:
在httpd.ini中增加下面的内容:
RewriteCond Host: www2\.cnblogs\.com
RewriteProxy (.*) http\://www.cnblogs.com$1 [I,F,U]
参考配置文档:http://www.isapirewrite.com/docs/

[IIS]配置 IIS Rewrite 模块 并修改 httpd.ini文件

mikel阅读(476)

配置 IIS Rewrite 模块 并修改 httpd.ini文件

下载IIS Rewrite模块:http://download.discuz.net/4.1.0/discuz_iis_rewrite.zip
2、 将压缩包解压到任意目录,(如:C:\Rewrite)。然后打开“控制面板”-“管理工具”-“IIS信息服务管理器”-“网站”-“您的站点”-“属 性”。在“ISAPI筛选器”项点击 “添加”,筛选器名称填入Rewrite,可执行文件为C:\Rewrite\Rewrite.dll ;
3、然后修改httpd.ini 文件,添加相应的过滤规则,例如:
RewriteRule ^(.*)/([a-z0-9\-\_]+)$ $1/Default\.aspx\?id=$2 [I,O]
http://localhost/Text 就会等同于 http://localhost/Default.aspx?id=Text
RewriteRule ^(.*)/id_([a-z0-9\-]+)\.html$ $1/Default\.aspx\?id=$2 [I,O]
http://localhost/id_Text.html 就会等同于 http://localhost/Default.aspx?id=Text
^(.*)/html/([0-9]+)/([0-9]+)\.html$ $1/Default\.aspx\?id=$2&name=$3
http://localhost/html/001/007.html 就等同于 http://localhost/Default.aspx?id=001&name=007
RewriteRule 语句我的理解:http://hi.baidu.com/liyuehui1987/blog/item/612fb044d1dbad83b3b7dc80.html
4、重新启动IIS就可以生效了(这一步很重要,每次修改httpd.ini后都要重启 IIS 以加载配置。)。
实际作中发现应该为:
RewriteRule ^(.*)-htm-(.*)$ $1.php\?$2

^(.*)/([a-z0-9\-\_]+)$ $1/Default\.aspx\?id=$2 [I,O]

^(.*) 这个是必须的

/ 这个应该是目录的开始

([a-z0-9\-\_]+) 这个是正则表达式,是用来匹配参数的

$ 这个是必须的就像最前面的 ^(.*)

$1 好像也是必须的

/ 也是一个目录的开始

Default 文件的真实名称(不包括扩展名)

\. 这是个转意字符 转意后面的点

Aspx 文件的扩展名

\? 又是一个转意字符 转意后面的问号

id= 参数的名称

$2 好像代表了参数的值(第一个参数的值)

[I,O] 好像是必须的

http://localhost/Text 就会等同于 http://localhost/Default.aspx?id=Text 这就成了目录式了

^(.*)/id_([a-z0-9\-]+)\.html$ $1/Default\.aspx\?id=$2 [I,O]

^(.*)这个是必须的

/ 这个应该是目录的开始

id_ 这是最终生成的文件名的一部分(最终文件名:id_ 参数值)

([a-z0-9\-\_]+) 这个是正则表达式,是用来匹配参数的

\. 这个是最终文件的名称和后缀名之间的点,\ 为转意字符

Html 为最终文件名的后缀名

$ 这个是必须的就像最前面的 ^(.*)  

$1好像也是必须的

/ 也是一个目录的开始

Default文件的真实名称(不包括扩展名)

\. 这是个转意字符 转意后面的点

Aspx 文件扩展名

\? 又是一个转意字符 转意后面的问号

id= 参数的名称

$2好像代表了参数的值(第一个参数的值)

[I,O] 也是必须的

localhost/id_Text.html 就会等同于 localhost/Default.aspx?id=Text 成静态得了