ASP.NET自定义控件组件开发 第一章 第三篇
第三篇:第一章的完结篇
系列文章链接:
ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件
ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇
ASP.NET自定义控件组件开发 第三章 为控件添加事件 后篇
ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl
ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡
第二章讲解:继承WebControl 的控件
相信大家看了前几篇文章后应该觉得自定义控件很简单,无非就是把一大堆的html代码包装一下就行了。不错,前
几篇写的控件确实很简单。不知道大家想过没有,难道我们每次写控件都要大费力气的把一大堆的html代码写进去吗。
不知道大家试了没有:如果在write.Write()方法中写的html代码有了错误,如果把<table..>写成了<talbe..>,在编译
的时候,编译器是不会发现错误,但是当我们把控件拖上来使用的时候,就发现控件的呈现错误。就是说,这样的错误只能
到最后才能被我们发现,这样我们又得回去改代码,然后重新的编译,生成。
我们开发的那个控件真的很好的,我们也也许没有考虑到浏览器版本的问题,因为不同的浏览器对html的不同版本的显
示还是有区别的。看看我们的代码,我们就敢保证我们的控件在所有的浏览器上都显示的是我们想要的结果吗?
基于上述原因,我们对之前的控件再来一次修改。
在.NET中,我们写代码经常用到他的智能感应功能,比如我们写完后加个".",然后,后面的一些属性,方法都显示出来
了 。而且在编译的时候,也提示我们一些错误信息。
下面我们就来改下:
- Code
- amespace CreditCardForm
- {
- public class CreditCardForm3:CreditCardForm2
- {
因为我们之前开发的控件已经实现了很多的特性,我们不想再意义的重新实现,所以就继承前面已经有的控件,相信大家
都理解这点。
- Code
- writer.Write("<table style='width:287px;height:128px;border-width:0'>");
大家还记得这段代码吧,我们想显示一个table,而且确定他的一些属性等等。如前所说,出错的可能很大,而且兼容也
有问题。怎样改?
这样:
我们用.NET里面的专门用来生成这些html标记的一些方法和属性
- Code
- writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "287px");
- writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "128px");
- writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "");
- writer.AddAttribute(HtmlTextWriterAttribute.Id, "mytable");
- writer.RenderBeginTag(HtmlTextWriterTag.Table);
这段代码和上端代码的最终的显示结果都是一样的(都生成相同的html标记)。也许大家会认为这段代码很多,难道写
这么多的代码就是好的吗,还不如之前的方便。但是,想想之前所说的问题,这段代码就解决了那些问题。
代码我来解释下:用AddStyleAttribute方法来添加CCS样式;AddStyleAttribute添加非CSS样式,如name,id等,
用RenderBeginTag来添加开始的标记。还有一点就是这些代码都是“反的”:先定义样式,属性,最后才定义我们要写的
个table标记。就是说,想给某个标记加属性,要先写属性,
样式的语句,在写这个标记。
- Code
- writer.RenderBeginTag(HtmlTextWriterTag.Table);
看看上面的代码,显示的是个table标记,如果想显示tr?这样做:
- Code
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
大家应该明白我的意思了吧:HtmlTextWriterTag接不同的属性,就显示不同的标记。
还有一点要特别的注意,有开始,就是结束。我们用了一个RenderBeginTag方法,就一定要有个RenderEndTag方法
与之对应。
看个例子:
- Code
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.Write(PaymentMethodText);
- writer.RenderEndTag();
大家懂了吧!
我把代码贴上,大家看看,有问题就说!
- Code
- 1 protected override void Render(HtmlTextWriter writer)
- 2 {
- 3 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "287px");
- 4 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "128px");
- 5 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "");
- 6 writer.AddAttribute(HtmlTextWriterAttribute.Id, "mytable");
- 7 writer.RenderBeginTag(HtmlTextWriterTag.Table);
- 8
- 9 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- 10
- 11 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 12 writer.Write(PaymentMethodText);
- 13 writer.RenderEndTag();
- 14
- 15 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 16 writer.AddAttribute(HtmlTextWriterAttribute.Name, "PaymentMethod");
- 17 writer.AddAttribute(HtmlTextWriterAttribute.Id, "PaymentMethod");
- 18 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%");
- 19 writer.RenderBeginTag(HtmlTextWriterTag.Select);
- 20
- 21 writer.AddAttribute(HtmlTextWriterAttribute.Value, "");
- 22 writer.RenderBeginTag(HtmlTextWriterTag.Option);
- 23 writer.Write("Master");
- 24 writer.RenderEndTag();
- 25
- 26 writer.AddAttribute(HtmlTextWriterAttribute.Value, "");
- 27 writer.RenderBeginTag(HtmlTextWriterTag.Option);
- 28 writer.Write("Visa");
- 29 writer.RenderEndTag();
- 30
- 31 writer.RenderEndTag();
- 32 writer.RenderEndTag();
- 33 writer.RenderEndTag();
- 34
- 35 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- 36 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 37 writer.Write(CreditCardNoText);
- 38 writer.RenderEndTag();
- 39
- 40 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 41 writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
- 42 writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo");
- 43 writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo");
- 44 writer.RenderBeginTag(HtmlTextWriterTag.Input);
- 45 writer.RenderEndTag();
- 46 writer.RenderEndTag();
- 47 writer.RenderEndTag();
- 48
- 49 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- 50 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 51 writer.Write(CardholderNameText);
- 52 writer.RenderEndTag();
- 53
- 54 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 55 writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
- 56 writer.AddAttribute(HtmlTextWriterAttribute.Name, "CardholderName");
- 57 writer.AddAttribute(HtmlTextWriterAttribute.Id, "CardholderName");
- 58 writer.RenderBeginTag(HtmlTextWriterTag.Input);
- 59 writer.RenderEndTag();
- 60 writer.RenderEndTag();
- 61 writer.RenderEndTag();
- 62
- 63 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- 64 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 65 writer.Write(ExpirationDateText);
- 66 writer.RenderEndTag();
- 67
- 68 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 69 writer.AddAttribute(HtmlTextWriterAttribute.Name, "Month");
- 70 writer.AddAttribute(HtmlTextWriterAttribute.Id, "Month");
- 71 writer.RenderBeginTag(HtmlTextWriterTag.Select);
- 72 for (int month = ; month < ; month++)
- 73 {
- 74 writer.AddAttribute(HtmlTextWriterAttribute.Value, month.ToString());
- 75 writer.RenderBeginTag(HtmlTextWriterTag.Option);
- 76 writer.Write(month.ToString());
- 77 writer.RenderEndTag();
- 78 }
- 79
- 80 writer.RenderEndTag();
- 81
- 82 writer.Write(" ");
- 83
- 84 writer.AddAttribute(HtmlTextWriterAttribute.Name, "Year");
- 85 writer.AddAttribute(HtmlTextWriterAttribute.Id, "Year");
- 86 writer.RenderBeginTag(HtmlTextWriterTag.Select);
- 87
- 88 for (int year =; year < ; year++)
- 89 {
- 90 writer.AddAttribute(HtmlTextWriterAttribute.Value, year.ToString());
- 91 writer.RenderBeginTag(HtmlTextWriterTag.Option);
- 92 writer.Write(year.ToString());
- 93 writer.RenderEndTag();
- 94 }
- 95
- 96 writer.RenderEndTag();
- 97
- 98 writer.RenderEndTag();
- 99 writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "");
- writer.AddAttribute(HtmlTextWriterAttribute.Align, "center");
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit");
- writer.AddAttribute(HtmlTextWriterAttribute.Value, SubmitButtonText);
- writer.RenderBeginTag(HtmlTextWriterTag.Input);
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- //table的结束标记
- writer.RenderEndTag();
- }
下面开始说说。状态的管理,即ViewState;
之前的控件还有一个问题:
如下:
我们在页面后面写代码:
- Code
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!this.IsPostBack)
- {
- CreditCardForm2_1.PaymentMethodText = " 我的支付方式";
- CreditCardForm2_1.CardholderNameText = "小洋";
- }
- }
运行页面看见:
但是当你点击”提交“按钮,页面马上就变为了如下:
变回来了!!!!?????
这里就要讲讲ASP.NET的页面保存值的方式:因为现在的ASP.NET网站是基于http这种无状态协议的。大家应该都懂。
在ASP.NET的我们提交的一个页面,虽然看起来是一样的,但是他们本质上已经不是同一个页面了。而是我们现在看见的页
面获取了之前提交的那个页面的一些状态值。关于这点,到第四章详细讲述”页面的生命周期“中讲。
所有我们就要用个ViewState来保存页面回传的值。这里我不想讲很多的理论东西,大家先看看现在的问题怎样解决:
- Code
- public override string PaymentMethodText
- {
- get
- {
- return ViewState["PaymentMethodText"] != null ? (string)ViewState["PaymentMethodText"] : "支付方式";
- }
- set
- {
- ViewState["PaymentMethodText"] = value;
- }
- }
因为我们继承于CreditCardForm2,大家看看我们在CreditCardForm2中写的:
- Code
- 1
- 2 [Browsable (true )]//在属性窗口中是否可见
- 3 [Category ("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类
- 4 [DefaultValue ("支付方式")]
- 5 [Description ("支付方式")]//这些是显示在属性窗口底下的
- 6
- 7 //virtual 方便以后二次开发
- 8 public virtual string PaymentMethodText
- 9 {
- get
- {
- return paymentMethod;
- }
- set
- {
- paymentMethod = value;
- }
- }
注意:Virtual。
这样之后,我们的控件就完成了。完整的代码如下:希望大家支持!
- Code
- 1using System;
- 2using System.Collections.Generic;
- 3using System.Text;
- 4using System.Web;
- 5using System.Web.UI;
- 6using System.Web.UI.WebControls;
- 7
- 8namespace CreditCardForm
- 9{
- 10 public class CreditCardForm3:CreditCardForm2
- 11 {
- 12 public override string PaymentMethodText
- 13 {
- 14 get
- 15 {
- 16 return ViewState["PaymentMethodText"] != null ? (string)ViewState["PaymentMethodText"] : "支付方式";
- 17 }
- 18 set
- 19 {
- 20 ViewState["PaymentMethodText"] = value;
- 21 }
- 22 }
- 23
- 24 public override string CreditCardNoText
- 25 {
- 26 get
- 27 {
- 28 return ViewState["CreditCardNoText"] != null ? (string)ViewState["CreditCardNoText"] : "信用卡号";
- 29 }
- 30 set
- 31 {
- 32 ViewState["CreditCardNoText"] = value;
- 33 }
- 34 }
- 35
- 36 public override string CardholderNameText
- 37 {
- 38 get
- 39 {
- 40 return ViewState["CardholderNameText"] != null ? (string)ViewState["CardholderNameText"] : "持卡人";
- 41 }
- 42 set
- 43 {
- 44 ViewState["CardholderNameText"] = value;
- 45 }
- 46 }
- 47
- 48 public override string ExpirationDateText
- 49 {
- 50 get
- 51 {
- 52 return ViewState["ExpirationDateText"] != null ? (string)ViewState["ExpirationDateText"] : "过期时间";
- 53 }
- 54 set
- 55 {
- 56 ViewState["ExpirationDateText"] = value;
- 57 }
- 58 }
- 59
- 60 public override string SubmitButtonText
- 61 {
- 62 get
- 63 {
- 64 return ViewState["SubmitButtonText"] != null ? (string)ViewState["SubmitButtonText"] : "提交";
- 65 }
- 66 set
- 67 {
- 68 ViewState["SubmitButtonText"] = value;
- 69 }
- 70 }
- 71 protected override void Render(HtmlTextWriter writer)
- 72 {
- 73 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "287px");
- 74 writer.AddStyleAttribute(HtmlTextWriterStyle.Height, "128px");
- 75 writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "");
- 76 writer.AddAttribute(HtmlTextWriterAttribute.Id, "mytable");
- 77 writer.RenderBeginTag(HtmlTextWriterTag.Table);
- 78
- 79 writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- 80
- 81 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 82 writer.Write(PaymentMethodText);
- 83 writer.RenderEndTag();
- 84
- 85 writer.RenderBeginTag(HtmlTextWriterTag.Td);
- 86 writer.AddAttribute(HtmlTextWriterAttribute.Name, "PaymentMethod");
- 87 writer.AddAttribute(HtmlTextWriterAttribute.Id, "PaymentMethod");
- 88 writer.AddStyleAttribute(HtmlTextWriterStyle.Width, "100%");
- 89 writer.RenderBeginTag(HtmlTextWriterTag.Select);
- 90
- 91 writer.AddAttribute(HtmlTextWriterAttribute.Value, "");
- 92 writer.RenderBeginTag(HtmlTextWriterTag.Option);
- 93 writer.Write("Master");
- 94 writer.RenderEndTag();
- 95
- 96 writer.AddAttribute(HtmlTextWriterAttribute.Value, "");
- 97 writer.RenderBeginTag(HtmlTextWriterTag.Option);
- 98 writer.Write("Visa");
- 99 writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.Write(CreditCardNoText);
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
- writer.AddAttribute(HtmlTextWriterAttribute.Name, "CreditCardNo");
- writer.AddAttribute(HtmlTextWriterAttribute.Id, "CreditCardNo");
- writer.RenderBeginTag(HtmlTextWriterTag.Input);
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.Write(CardholderNameText);
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
- writer.AddAttribute(HtmlTextWriterAttribute.Name, "CardholderName");
- writer.AddAttribute(HtmlTextWriterAttribute.Id, "CardholderName");
- writer.RenderBeginTag(HtmlTextWriterTag.Input);
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.Write(ExpirationDateText);
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.AddAttribute(HtmlTextWriterAttribute.Name, "Month");
- writer.AddAttribute(HtmlTextWriterAttribute.Id, "Month");
- writer.RenderBeginTag(HtmlTextWriterTag.Select);
- for (int month = ; month < ; month++)
- {
- writer.AddAttribute(HtmlTextWriterAttribute.Value, month.ToString());
- writer.RenderBeginTag(HtmlTextWriterTag.Option);
- writer.Write(month.ToString());
- writer.RenderEndTag();
- }
- writer.RenderEndTag();
- writer.Write(" ");
- writer.AddAttribute(HtmlTextWriterAttribute.Name, "Year");
- writer.AddAttribute(HtmlTextWriterAttribute.Id, "Year");
- writer.RenderBeginTag(HtmlTextWriterTag.Select);
- for (int year =; year < ; year++)
- {
- writer.AddAttribute(HtmlTextWriterAttribute.Value, year.ToString());
- writer.RenderBeginTag(HtmlTextWriterTag.Option);
- writer.Write(year.ToString());
- writer.RenderEndTag();
- }
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderBeginTag(HtmlTextWriterTag.Tr);
- writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "");
- writer.AddAttribute(HtmlTextWriterAttribute.Align, "center");
- writer.RenderBeginTag(HtmlTextWriterTag.Td);
- writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit");
- writer.AddAttribute(HtmlTextWriterAttribute.Value, SubmitButtonText);
- writer.RenderBeginTag(HtmlTextWriterTag.Input);
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- writer.RenderEndTag();
- }
- }
- }
ASP.NET自定义控件组件开发 第一章 第三篇的更多相关文章
- ASP.NET自定义控件组件开发 第一章 第三篇 第一章的完结篇
ASP.NET自定义控件组件开发 第一章 第三篇 第三篇:第一章的完结篇 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ...
- ASP.NET自定义控件组件开发 第一章 第二篇 接着待续
原文:ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 很感谢大家给我的第一篇ASP.NET控件开发的支持!在写这些之前,我也看了 ...
- ASP.NET自定义控件组件开发 第一章 待续
原文:ASP.NET自定义控件组件开发 第一章 待续 第一章:从一个简单的控件谈起 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接 ...
- ASP.NET自定义控件组件开发 第一章 第一章:从一个简单的控件谈起
第一章:从一个简单的控件谈起 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第三 ...
- ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件
原文:ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件 第二章 继承于WebControl的自定义控件 到现在为止,我已经写了三篇关于自定义控件开发的文章,很感谢大家的支 ...
- ASP.NET自定义控件组件开发 第五章 模板控件开发
原文:ASP.NET自定义控件组件开发 第五章 模板控件开发 第五章 模板控件开发 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接 ...
- ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl
原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 第四章 组合控件开发CompositeControl 大家好,今天我们来实现一个自定义的控件,之前我们已经 ...
- ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡
原文:ASP.NET自定义控件组件开发 第四章 组合控件开发CompositeControl 后篇 --事件冒泡 CompositeControl 后篇 --事件冒泡 系列文章链接: ASP.NET ...
- ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇
原文:ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇 第三章 为控件添加事件 好了,我们之前以前开发一个控件.而且也添加了属性,开发也很规范,但是那个控件还差最后一点:添加事件. 系列 ...
随机推荐
- 浅谈JAVA ThreadPoolExecutor(转)
这篇文章分为两部分,前面是ThreadPoolExecutor的一些基本知识,后一部分则是Mina中一个特殊的ThreadPoolExecutor代码解析.算是我的Java学习笔记吧. 基础 在我看来 ...
- hdu2412(树形dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2412 题意:给定一棵关系树 , 从中选择一些点 , 使这些点均不存在亲子关系 , 最多能取多少个点 , ...
- 解决Android Device Chooser 找不到设备问题
第一种情况: 已经启动了官方的模拟器也进入了Android手机界面,可是在Android Device Chooser 看不到设备,怎么办? 例如以下图所看到的,使用Reset adb 或者在adb所 ...
- Java 里把 InputStream 转换成 String 的几种方法
我们在 Java 中经常会碰到如何把 InputStream 转换成 String 的情形,比如从文件或网络得到一个 InputStream,需要转换成字符串输出或赋给别的变量. 未真正关注这个问题之 ...
- include设置属性在relativelayout布局中无效
转自:http://4265337.blog.163.com/blog/static/195375820127935731114/ 再来说一个在使用这两个标签时最容易出现的问题. 经常会有同学在Rel ...
- 采用keepalived施工可用性MySQL-HA
描述了使用keepalived施工可用性MySQL-HA,两个保证MySQL数据一致性,然后,keepalived虚拟IP,经keepalived内置的在线监测功能来实现MySQL. AD: 关于My ...
- 黄聪:Microsoft Enterprise Library 5.0 系列教程(一) : Caching Application Block (初级)
原文:黄聪:Microsoft Enterprise Library 5.0 系列教程(一) : Caching Application Block (初级) 本篇文章具体官方解释请参照以下链接: h ...
- codechef Little Elephant and Permutations题解
The Little Elephant likes permutations. This time he has a permutation A[1], A[2], ..., A[N] of numb ...
- Windows Phone开发(8):关于导航的小技巧
原文:Windows Phone开发(8):关于导航的小技巧 前文用几个例子对导航做了简单介绍,在一般应用中,使用上一篇文章中说到的方法,其实也够用了,不过,为了能够处理一些特殊的情况,有几个小技巧还 ...
- 疯狂Java学习笔记(84)----------大约 Java 对象序列化,你不知道 5 事
几年前,.当一个软件团队一起用 Java 书面申请.我认识比一般程序猿多知道一点关于 Java 对象序列化的知识所带来的优点. 关于本系列 您认为自己懂 Java 编程?其实,大多数程序猿对于 Jav ...