jQuery EasyUI学习一
1. jQuery EasyUI介绍
- 1. 创建组件的方式和原理(掌握)
- 2. 组件三要素(掌握)
- 3. Panel、LinkButton、上下文菜单;(掌握)
- 简介
2.1. jQuery EasyUI
是一组基于jQuery的UI插件集合,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面。开发者不需要编写复杂的JavaScript,也不需要对css样式有深入的了解,开发者只有需要了解一些简单的html标签。
2.2. 官方网站
http://www.jeasyui.com/
- 中国人开发;
- 个人免费
- 商业收费 $449
2.3. 运行案例
解压apache-tomcat-easyui.zip
双击apache-tomcat-easyui\bin\stratup.bat
浏览器地址:http://localhost:8888/index.php
(别关心这个后缀,这并不是php,这里是直接下载的easyui的官方网站)。
2.4. EasyUI框架项目结构
2.4.1. 目录截图
2.4.2. 子目录说明
demo :web案例
demo-mobile:移动端案例
locale:本地化(汉化包)
plugins:easyui所有插件
src:插件的源码,如果买了商业授权就有全部源码
themes:主题(皮肤),存放css,img
changlog.txt:升级日志
easyloader.js:内部实现了一个js加载器,根据应用的需求加载js文件,而不是一次性加载所有文件;
jquery.easyui.min.js:所有插件集的压缩文件
jquery.min.js : easyui当前版本兼容的jquery库
- 搭建easyui环境
3.1. web项目加入easyui的项目文件夹
建议创建webapp的项目文件名,同maven标准命名
最好不要携带easyui的版本号,升级的时候修改就不是很方便了
3.2. 新建一个公共网页common.jsp
引入easyui需要的js和css;可参考jQuery EasyUI 1.5 版 API 中文版.exe/文档说明。
<!-- easyui的样式主题文件 -->
<link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
<!-- easyui的系统图标-->
<link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">
<!-- easyui依赖的jquery库-->
<script type="text/javascript" src="/easyui/jquery.min.js"></script>
<!-- easyui的插件库-->
<script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
<!-- easyui的汉化包 -->
<script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>
3.3. 把创建的easyui web项目跑起来
去掉这个原来pss的勾
修改tomcat/conf/server.xml,指向easyui1的webapp目录
在启动之前再次确认pss的勾是否取消掉。
- 创建组件
Easyui可以通过HTML或JavaScript创建组件;
4.1. HTML创建组件的方式
<标签 class=”easyui-组件名”
组件配置title=“xxx”
data-options=”title:’xxx’”></标签>
<!--
使用html创建easyui组件(最简单方式)
class = "easyui-panel" 作用: 告诉easyui需要把div转化为easyui组件.
style 作用: 设置组件宽高和其他样式.
title,iconCls,collapsible 组件属性: 告诉easyui如何创建这个组件.
-->
<div id="p1" class="easyui-panel"
style="width: 400px; height: 400px; padding: 10px; color: red; font-weight: bold; font-size: 18px;" title="我的面板"
iconCls="icon-ok" collapsible="true">
<h1>内容xxxx</h1>
</div>
4.2. panel最终生成的html代码分成3个div
4.3. Js代码创建组件
<script type="text/javascript">
$(function() {
//获取p2标签,把他变成easyui面板组件.
$("#p2").panel({
//面板属性
title : "你的面板",
iconCls : "icon-no"
});
});
</script>
<div id="p2" style="width: 400px; height: 400px; padding: 10px; color: red; font-weight: bold; font-size: 18px;">
<h1>是你面板</h1>
</div>
- EasyUI创建组件的原理(html创建的方式)
最终还是调用js的方式来创建,$(“#p”).panel({json参数});
5.1. $.parser.parse()
页面加载完毕后
如果$.parser.auto=true;会自动调用$.parser.parse()方法,进行解析
easyui\src\jquery.parser.js
5.2. 支持创建组件的所有名称
- 1.3.6版本
- 1.5版本
5.3. 通过选择器获取相关元素对象,然后调用对应的组件方法
5.4. 使用
5.5. DIY简易版本linkbutton
<title>EasyUI 创建组件的原理</title>
<!-- easyui的样式主题文件 -->
<link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
<!-- easyui的系统图标-->
<link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">
<!-- easyui依赖的jquery库-->
<script type="text/javascript" src="/easyui/jquery.min.js"></script>
<script type="text/javascript">
/* easyui插件定义 */
$.fn.linkbutton = function(){
//添加类样式
this.addClass("l-btn");
//获取文本
var text = this.text();
//获取iconCls的值
var iconCls = this.attr("iconCls");
this.html('<span class="l-btn-left">'+
'<span class="l-btn-text '+iconCls+' l-btn-icon-left">'+text+'</span>'+
'</span>');
};
$(function(){
//easyui通过html代码创建组建的原理:
/*
1.页面加载完毕
2.获取页面中是以.easyui-{组件名}的选择器元素. {组件名} : easyui中所有组件,比如:panel,linkbutton,tree
3.判断是否有获取到的元素.
4.调用对应的组件方法. (组件 : panel() , linkbutton() )
*/
//var els = $(".easyui-linkbutton");
//els.linkbutton();
$("#mya").linkbutton();
});
</script>
</head>
<body>
<!--
easyui中class有两个用途:
1.用于样式设置.
2.告诉easyui它是一个组件.easyui会通过js对这个div进行包装和添加一些样式
-->
<a id="mya" iconCls="icon-ok">我是一个按钮</a>
</body>
5.6. 是否自动解析EasyUI组件。默认为true;
<script type="text/javascript">
//页面加载的时候,获取页面中以.easyui-{组件名}的元素,然后调用对应组件方法.
$.parser.auto=false;
</script>
</head>
<body>
<a class="easyui-linkbutton" iconCls="icon-ok">我是一个按钮</a>
</body>
- LinkButton组件
Linkbutton组件需要通过<a>进行创建;
<script type="text/javascript">
$(function(){
$("#editBtn").on("click",function(){
console.debug("编辑...");
});
$("#cutBtn").on("click",function(){
//组件的disabled禁用属性,无法控制事件.
if(!$(this).hasClass("l-btn-disabled")){//判断按钮是否有禁用样式.
console.debug("剪切...");
}
});
});
</script>
<body>
<!--
linkbutton组件:
属性:
iconCls:图标;
disabled:是否禁用;
plain:true时显示简洁效果,其实就是没有背景;
iconAlign:按钮图标位置;可以选值为left,right;默认为:left;
toggle: 是否可以选中效果.
group : 分组,一般与toggle配合使用,达到单选效果;
-->
<a href="#" class="easyui-linkbutton" iconCls='icon-remove' toggle="true" onclick="alert('删除....');">删除</a>
<a href="#" class="easyui-linkbutton" iconCls='icon-edit' plain="true" iconAlign="right" id="editBtn">编辑</a>
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cut',disabled:true" id="cutBtn">剪切</a>
<div style="padding:5px;border:1px solid #ddd;">
<a href="#" class="easyui-linkbutton" data-options="toggle:true,group:'g1'">Button 1</a>
<a href="#" class="easyui-linkbutton" data-options="toggle:true,group:'g1'">Button 2</a>
<a href="#" class="easyui-linkbutton" data-options="toggle:true,group:'g2'">Button 3</a>
<a href="#" class="easyui-linkbutton" data-options="toggle:true,group:'g2'">Button 4</a>
<a href="#" class="easyui-linkbutton" data-options="toggle:true,group:'g2'">Button 5</a>
</div>
</body>
- Panel组件
7.1. panel组件需要通过<div>进行创建
面板作为承载其它内容的容器。这是构建其他组件的基础(比如:layout,tabs,accordion等)。它还提供了折叠、关闭、最大化、最小化和自定义行为。面板可以很容易地嵌入到web页面的任何位置。
<!--
panel面板使用div创建
class="easyui-panel"
panel属性:
title:面板的标题;
style:面板的样式;
iconCls:面板标题的图标;
collapsible:定义是否显示可折叠按钮。
minimizable:定义是否显示最小化按钮。
maximizable:定义是否显示最大化按钮。
closable:定义是否显示关闭按钮。
tools : 自定义工具按钮. 参数是一个选择器,代表选择器获取元素中的内容就是工具按钮.
fit:设置为true的时候面板大小"将自适应父容器"; 简单理解: 父容器多大,我就多大. 使用了该属性后,我们设置宽高将失效.
href: 从URL读取远程数据并且显示到面板; 一般用于加载动态的内容比较有用. (只加载body里面内容) 一旦设置,那么面板标签中内容会被覆盖掉.
closed : 设置面板是否显示.
loadingMessage:加载远程数据的时候在面板内显示一条消息。
-->
<div id="p" class="easyui-panel" title="面板1"
style="width: 300px; height: 200px; padding: 10px;"
iconCls="icon-save"
collapsible="true"
minimizable="false"
maximizable="true"
closable="true"
tools="#tt"
fit="false"
loadingMessage="加载中..."
href="/panel_content.txt"
>
<a class="easyui-linkbutton" iconCls="icon-add">添加</a>
<a class="easyui-linkbutton" iconCls="icon-remove">删除</a>
</div>
<div id="tt">
<a href="javascript:void(0)" class="icon-add" onclick="javascript:alert('add')"></a>
<a href="javascript:void(0)" class="icon-ok" onclick="javascript:alert('ok')"></a>
</div>
7.2. Panel组件标签html结构
7.2.1. panel面板的组成
面板头<div class="panel-header"> 和 面板的内容<div class=”panel-body”>
7.2.2. 组件
<div id="p1" cls="mypanel" title="哈哈" style="width: 200px;height: 200px;">
</div>
panel组件被创建后:
<div class="panel mypanel"
style="display: block; left: 500px; width: 200px;">
<div class="panel-header" style="width: 188px;">
<div class="panel-title">哈哈</div>
<div class="panel-tool"></div>
</div>
<div style="width: 198px; height: 171px;" title="" cls="mypanel"
id="p1" class="panel-body">你好吗???</div>
</div>
7.3. 理解:Panel面板并不是每个属性都可以直接使用
<style type="text/css">
.mypanel {
position: absolute;
}
</style>
<script type="text/javascript">
$(function() {
$("#p1").panel({//创建一个easyui的组件
content : "你好吗???",
left : "500px",
cls : 'mypanel'
});
//以下操作都是错误的,因为控件(a,div)一旦变成了一个easyui组件,我们就不能使用"元素对象"操作方式去操作这个组件,我们应该按照easyui组件操作方式.
//$("#p1").width("800px");//只能操作body
//$("#p1").hide();//只能操作body
//$("#p1").attr("title","呵呵");//只能操作body
});
</script>
</head>
<body>
<div id="p1" cls="mypanel" title="哈哈" style="width: 200px; height: 200px;"></div>
</body>
- 组件三要素
Easyui组件都具有属性、方法、事件;
8.1. 属性
8.1.1. 定义:属性描述了组件的更多信息
我们通过配置这些属性,可以让easyui提供不同的显示效果或功能,比如面板组件有title属性,iconCls属性,collapsed属性。
8.1.2. 组件默认属性的值
所有的属性都定义在jQuery.fn.{plugin}.defaults里面。例如,对话框属性定义在jQuery.fn.dialog.defaults里面。
$.fn.{pluginName}.defaults , 作用:如果创建组件的时候,我们没有设置组件的属性,那么就使用默认属性.
//panel面板的默认属性
//console.debug($.fn.panel.defaults);
//修改组件的默认属性
//$.fn.panel.defaults.closable = true;
8.1.3. 属性的作用范围
属性只能在创建(初始化)组件有效,组件创建完毕后,如果对某个属性进行了修改无效;
//以下代码修改只是body的属性而已,并不是面板的属性.
$("#p1").attr("title","你的面板");无效
$("#p1").attr("closed","true");无效
属性编写方式,属性可以写在上面地方
8.2. 使用html定义属性的3种方式
8.2.1. 直接作为标签的自定义属性
<div class="easyui-panel" title="面板标题" closed="true"></div> title,closed都是自定义属性;
8.2.2. 使用html5中规范data属性. data-options
<div class="easyui-panel" data-options="title:'面板标题',closed:true"></div>
8.2.3. 以上两种混合使用
<div class="easyui-panel" title="面板标题" data-options="closed:true"></div>
8.2.4. 以上两种混合的区别
自定义属性的值只能是一个普通的字符串,不能写事件函数名和json数组.
<div id="p1" class="easyui-panel" title="我的面板" closed="false" tools="[
{
iconCls:'icon-add',
handler:function(){alert('add')}
},{
iconCls:'icon-edit',
handler:function(){alert('edit')}
}]">
p1
</div>
data-options属性的值可以写函数名和json数组.
<div id="p1" class="easyui-panel" title="我的面板" closed="false" data-options="tools:[
{
iconCls:'icon-add',
handler:function(){alert('add')}
},{
iconCls:'icon-edit',
handler:function(){alert('edit')}
}]">
p1
</div>
8.2.5. 使用js来创建
使用js创建的时候通过json对象传入
$("#p1").panel({
title:"标题",
closed:false
});
<body>
<div id="p1" class="easyui-panel" title="我的面板" closed="false"> p1 </div>
<a class="easyui-linkbutton" id="changeTitle">修改面板标题</a>
</body>
8.3. 方法
8.3.1. 创建组件的语法
$('selector').plugin(); //没有传递参数
$('selector').plugin({}); //传递json参数
8.3.2. 调用方法的语法
$('selector').plugin('method', [parameter]);
selector 是jQuery对象选择器。
plugin 是插件的名称。
method 是相应插件现有的方法。
parameter 是参数对象,可以是一个对象、字符串等。
8.3.3. 总结
如果写了easyui组件之后传入的第一个参数是字符串,那么就代表执行组件上面某一个方法,
如果不是一个字符串那么就是创建组件,传入的参数是json字符串;如果没有传入参数还是创建组件.
8.3.4. 定义:方法其实就是组件中的某个功能
我们可以调用组件中方法,从而达到我们要求。比如:现在我想隐藏页面中的某个面板。 $(“#mypanel”).panel(“close”);
<script type="text/javascript">$(function(){
$("#openBtn").on("click",function(){
//获取要操作面板
var p1 = $("#p1");
//一旦一个元素变成一个组件,请使用组件方法来操作它.
p1.panel("open"); // 调用panel组件的open方法. 千万别乱搞,p1.open();
});
$("#closeBtn").on("click",function(){
$("#p1").panel("close");
});
$("#loadBtn").on("click",function(){
//刷新面板来装载远程数据。如果'href'属性有了新配置,它将重写旧的'href'属性。
$("#p1").panel("refresh","panel_content.txt?hehe=xxx&xxx=aaaa");
});
});
</script>
<body>
<a id="openBtn" class="easyui-linkbutton" href="javascript:;">打开面板</a>
<a id="closeBtn" class="easyui-linkbutton" href="javascript:;">隐藏面板</a>
<a id="loadBtn" class="easyui-linkbutton" href="javascript:;">加载远程内容</a>
<div id="p1" class="easyui-panel" href="panel_content.txt" title="我的面板" closed="true">
p1111111111111111
</div>
<div id="p2" title="我的面板">
p2222222222222
</div>
<script type="text/javascript">
//不能使用一个非组件的对象,调用组件方法.
$("#p2").panel("open");
</script>
<script type="text/javascript">
$("#p2").panel(); //或者 $("#p2").panel({}); 都代表创建组件,或者就是调用方法.
$("#p2").panel("open");
</script>
8.3.5. 注意点
如果尝试调用一个非组件的组件方法那么直接报错;
创建组件和调用方法的区别
以上代码调用方法
8.4. 事件
8.4.1. 定义:如果组件发生了什么事情
那么它就会通过事件反应给我们。比如:我们点击tree组件的某个节点,那么就会触发onClick事件。
所有的事件(回调函数)也都定义在jQuery.fn.{plugin}.defaults里面。
注意:注册事件不能采用dom传统方式注册,需要通过组件注册;
8.4.2. 树状菜单
<script type="text/javascript">
$(function() {
//组件注册事件的写法与属性一模一样.
$('#tree').tree({
//属性和事件
animate:true,
onClick: function(node){
alert(node.text); // 在用户点击的时候提示
}
});
});
</script>
<body>
<ul id="tree" data-options="url:'tree-data1.json'" ></ul>
</body>
8.4.3. 树需要的Json数据的格式
[
{
"id": 1,
"text": "组织机构",
"iconCls": "icon-save",
"children": [{
"id": 11,
"text": "部门管理",
"iconCls": "icon-ok",
"url": "department.action"
},{
"id": 12,
"text": "员工管理",
"iconCls": "icon-ok",
"url": "employee.action"
}]
},
{
"id": 2,
"text": "系统管理",
"iconCls": "icon-save",
"children": [{
"id": 13,
"text": "权限管理",
"iconCls": "icon-ok",
"url": "permission.action"
},{
"id": 14,
"text": "角色管理",
"iconCls": "icon-ok",
"url": "role.action"
}]
}
]
8.4.4. 因为tree这个树的json格式必须要有输出text的
8.4.5. ssh输出指定text名称的json
@JSON("name=text")
public String getName(){
return name;
}
8.4.6. ssm输出指定名称的json
添加一个兼容代码
public String getText(){//给树或者下拉列表
return name;
}
public String getName(){//显示datagrid
return name;
}
- 右键菜单(上下文菜单)
<script>
$(function() {
//contextmenu : 右键菜单(上下文菜单)
$(document).on('contextmenu', function(event) {
//event 事件对象: 描述了事件发生时所有的信息,包含事件名,事件源,触发事件的坐标.
event.preventDefault();//阻止浏览器默认事件
$("#mm").menu("show", {
left : event.pageX,
top : event.pageY
});
});
});
</script>
</head>
<body>
<!--
创建了一个被隐藏的菜单. 菜单需要我们通过js调用显示.
-->
<div id="mm" class="easyui-menu" style="width: 120px;">
<div onclick="javascript:alert('new')">New</div>
<div>
<span>Open</span>
<div style="width: 150px;">
<div>
<span>M1</span>
<div style="width: 120px;">
<div>sub1</div>
<div>sub2</div>
<div>sub3</div>
</div>
</div>
</div>
</div>
<div data-options="iconCls:'icon-save'">Save</div>
<div data-options="iconCls:'icon-print',disabled:true">Print</div>
<div class="menu-sep"></div>
<div>Exit</div>
</div>
</body>
- 课程总结
10.1. 重点
- 怎样使用easyui,LinkButton,Panel,Tree
- Tree返回的json数据的格式
10.2. 难点
- Html的方式创建组件的原理:本质还是js的方式,理解,面试
- 区分怎样是创建组件,调用方法
- 常见异常
- TypeError: $.data(...) is undefined
尝试调用一个非组件的组件方法那么直接报错;
<div id="p" 普通的div
style="width: 500px; height: 200px; padding: 10px;" title="My Panel"
iconCls="icon-save" collapsible="true">The panel content</div>
$("#p").panel("close");
- 课后练习
- 自学easyui的datagrid
步骤1:把easyui目录拷贝到pss的webapp下面,把今天写的common.jsp里面拷贝里面的内容到datagrid.jsp
步骤2:把pss打一个勾
步骤3:修改tomcat/config/server.xml指向pss/src/main/webapp
步骤4:下面的第一步
案例web路径
http://localhost:8888/demo/main/index.php?plugin=Application&theme=metro&dir=ltr&pitem=
- 面试题
- 扩展知识或课外阅读推荐
14.1. 扩展知识
14.2. 课外阅读
- 怎样才能学会easyui
先看官方案例
http://localhost:8888/demo/main/index.php
jQuery EasyUI学习一的更多相关文章
- jQuery EasyUI学习资源汇总
jQuery EasyUI学习资源汇总 EasyUi – 1.入门 EasyUi – 2.布局Layout + 3.登录界面 EasyUi – 4.datwagrid 学习Jquery EasyUI的 ...
- JQuery EasyUI学习框架
前言 前端技术,新项目的开发拟使用EasyUI框架(基于EasyUI丰富UI组件库),项目负责人的提示EasyUI分配给我这个任务.发展前,我需要这对于一个新手EasyUI框架学习一些基本的入门.记录 ...
- jQuery EasyUI学习二
1. 课程介绍 1. Datagrid组件(掌握) 2. Dialog.form组件(掌握) 3. Layout.Tabs;(掌握) Datagrid组件 2.1. 部署运行pss启动无错 ...
- JQuery EasyUI学习笔记
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6690888.html 简介与准备 jQuery EasyUI 是一个基于 jQuery 的框架,集成了各种用 ...
- JQuery EasyUI学习记录(三)
1.jQuery EasyUI messager使用方式 1.1 alert方法 $(function(){ //1.alert方法---提示框 $.messager.alert("标题&q ...
- JQuery EasyUI学习记录(二)
1.jquery easyUI动态添加选项卡(查看jquery easyUI手册) 1.1 用于动态添加一个选项卡 1.1.1 选中指定的选项卡和判断某个选项卡是否存在 测试代码: <a id= ...
- JQuery EasyUI学习记录(一)
1.主页设计(JQuery EasyUI插件) 下载easyUI开发包: 将easyUI资源文件导入页面中: <link rel="stylesheet" type=&quo ...
- JQuery EasyUI学习记录(五)
1.datagrid使用方法(重要) 1.1将静态html渲染为datagrid样式 <!--方式一: 将静态html渲染为datagrid样式 --> <table class=& ...
- JQuery EasyUI学习记录(四)
1.EasyUI中的validatebox使用 提供的校验规则: 1.非空校验required="required" 2.使用validType指定 email: 正则表达式匹配电 ...
随机推荐
- Mybatis报错invalid comparison: java.util.Date and java.lang.String
请求参数中两个属性确实都是date类型,数据库也确认是data类型,这个错误是因为 在这里把date类型的参数与单引号做了比较出现的,删除就可以正常运行了.
- 图像处理术语解释:什么是PRGBA和Alpha预乘(Premultiplied Alpha )
☞ ░ 前往老猿Python博文目录 ░ Alpha预乘(Premultiplied Alpha)和PRGBA 一般来说四通道图像数据保存的都是ARGB或RGBA,其R.G.B值还没有进行任何透明化处 ...
- PyQt(Python+Qt)学习随笔:QTableView的wordWrap属性
老猿Python博文目录 老猿Python博客地址 wordWrap属性用于控制视图中数据项文本的换行策略.如果此属性为True,则在数据项文本中分词的适当处进行换:否则数据项文本不进行换行处理.默认 ...
- Fiddle重定向请求
以当当网和淘宝网为例: 1.打开浏览器,在地址栏中输入www.dangdang.com,进入当当主页. 2.在规则编辑器中设置规则,将dangdang重定向至taobao,并打开规则. 3.再次刷新当 ...
- 第五篇 Scrum 冲刺博客
一.站立式会议 1. 会议照片 2. 工作汇报 团队成员名称 昨日(26日)完成的工作 今天(27日)计划完成的工作 工作中遇到的困难 陈锐基 - 完成发布页面的布局- 完成发布动态的功能 - 优化当 ...
- 冲刺Day3
每天举行站立式会议照片: 昨天已完成的工作: 1.完成登录注册的后台代码. 2.确定商品查找的接口. 3.尝试与数据库连接. 今天计划完成的工作: 成员 任务 高嘉淳 完成用户信息管理的部分功能 覃泽 ...
- Alpha冲刺——序言篇(任务与计划)
Alpha冲刺--序言篇(任务与计划) 1.整个项目预期的任务量 需求规格说明书 架构设计,原型设计,原型改进(给目标用户展现原型,并进一步理解需求) 编码规范完成.平台环境搭建完成.初步架构搭建 队 ...
- this.$options.data()实战之重置data
刚刚看到这个方法学习了一下,然后想到正在开发的项目有一个需要重置data的操作,正好拿来使用一下,节省了好多代码,美滋滋...
- JVM命令手册
原文链接:https://blog.csdn.net/qq_41345773/article/details/93895532 aconst_null 将null对象引用压入栈iconst_m1 将i ...
- FHQ简要笔记
前言 原文写于 XJ 集训day2 2020.1.19. 现在想想那时候连模板都还没写,只是刚刚理解就在那里瞎yy--之前果然还是太幼稚了. 今天刷训练指南发现全是 Treap 和 Splay ,不想 ...