核心内容概述
1.JavaScript加强,涉及到ECMAScript语法、BOM对象、DOM对象以及事件。
2.Ajax传统编程。
3.jQuery框架,九种选择器为核心学习内容
4.JQuery UI插件
5.jQuery Ajax编程
6.jQuery第三方插件
7.反向Ajax编程(彗星)
一、JavaScript基础加强
JavaScript是在浏览器内容运行,无需编译、解释执行动态脚本语言,是一种弱类型语言,所有变量使用var定义。
JavaScript的3个组成部分分别为:核心(ECMAScript)、文档对象模型(DOM)、浏览器对象模型(BOM)
1.ECMAScript核心语法
①:代码编写位置
分为内部JS和外部JS【使用src进行引入】
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>JavaScript程序编写</title>
<!-- 内部JS -->
<script type="text/javascript">
// 编写JavaScript代码
alert(1);
</script>
<!-- 外部JS-->
<script type="text/javascript" src="1.js"></script>
②:学习顺序
JavaScript依次从变量(标示符、关键字),运算符,程序结构(if while for),以及函数来进行学习。
(1)所有的变量使用var来定义,是弱类型变量,不代表没有类型,变量本身还是有类型的。【var a=10,var b=1.5;他们分别为整数以及浮点数类型】
(2)每行结尾分号可有可无,建议编写。
(3)注释和Java类似,支持单行注释(//)和多行注释(/* */)
③:数据类型
JavaScript分为原始数据类型和引用数据类型,分别存储于栈和堆中。
原始数据类型:number、string、boolean、null和undefined
引用数据类型:存在很多种,每种都是object对象
可以使用typeof查看数据类型,使用instanceof判断变量数据类型
Demo:
<script type="text/javascript">
// 定义所有变量都用var,但是变量本身具有类型
var a = 10; // 整数
var b = 1.5; // 浮点数
var c = true; // 布尔
var d = "abc"; // 字符串 基本数据类型
var e = 'abc'; // 字符串
// 通过typeof查看数据类型
alert(typeof d);
// 通过instanceof判断变量数据类型
alert(d instanceof Object);//falae
alert(a instanceof Object);//falae
var s = new String("abc"); // 对象类型
alert(s instanceof Object);
</script>
④:null和undefined的区分
null:对象不存在;
undefined:对象存在,访问属性或者方法不存在(对象未初始化)
2.ECMAScript对象
ECMAScript常用的有7个对象,依次为String、Number、Boolean、Math、Date、Array以及Regxp。
①:String类型常用属性方法
建议查看手册,这里需要注意的为length属性以及match方法
charAt()、concat()、indexOf()、lastIndexOf()、match()、replace()、split()、substr()、substring()、toLowerCase()、toUpperCase()
Java中提供matches方法 例如:"1234".matches("\\d+") ---- 返回true
JavaScript 与 matches方法等价的那个方法,是 RegExp 对象提供test方法
例如:/^\d+$/.test("1234") --- 返回true
/^\d+$/ 等价于 new RegExp("^\\d+$")
"1234".match("^\\d+$") 返回是匹配正则表达式内容,而不是布尔值,等价于 /^\d+$/.exec("1234")
②:Math常用属性和方法
PI 属性
round(x) 把数四舍五入为最接近的整数
random() 返回 0 ~ 1 之间的随机数
pow(x,y) 次幂
sqrt(x) 平方根
③:Date常用属性和方法
toLocaleString() 返回当地本地化日期格式 2012年12月12日 11:07:52
getTime() 返回从1970年1月1日到目前为止 毫秒值
Demo:
<script type="text/javascript">
var s1 = "abc"; // s1是基本数据类型
var s2 = new String("abc") ; // s2是对象类型
//alert(s1 == s2); //
//alert("98"==98);// true
//alert("true"==true); // false
//alert(1==true); // true
var d = 010;// 八进制
var d2 = 0x10; // 十六进制
// match方法 类似 Java中 matches,有区别
//alert(/^\d+$/.test("1234abc")); // 等价于 java中matches
//alert("1234".match("^\\d+$")); // math方法返回的是匹配正则表达式内容,而不是布尔值
//alert(/^\d+$/.exec("1234abc1234"));// 返回匹配的内容
// Date使用
var date = new Date(); //当前日期
alert(date.toLocaleString());// 返回当地国际化日期格式
var dateStr = date.getFullYear()+"-"+date.getMonth()
+"-"+date.getDate()+" "+date.getHours()+":"+date.getMinutes()
+":"+date.getSeconds();
alert(dateStr);
</script>
④:Array常用属性方法
push() 加入元素到数组
pop() 从数组移除最后一个元素
reverse()反转
join() 连接数组元素 通过特定内容 返回字符串
sort() 排序
slice() 截取数组中指定元素 从start到end
Demo:
<script type="text/javascript">
// 定义数组 使用Array对象
// 方式一
var arr1 = [1,2,3];
// 数组的遍历 通过长度和下标
for(var i=0;i< arr1.length ; i++){
//alert(arr1[i]);
}
// 方式二
var arr2 = new Array(3);// 定义长度为3的数组
arr2[0] = "aa";
arr2[1] = "bb";
arr2[2] = "cc"
arr2["100"] = "dd";
//alert(arr2.length);
//alert(arr2[4]);
// 方式三
var arr3 = new Array(1,2,3);// 数组三个元素 1, 2 ,3
//alert(arr3.join("-")); // 1-2-3
alert(arr3.slice(1,3)); // 从1下标,截取到3下标,1下标包含,3下标不包含
</script>
3.ECMAScript核心语法——函数
①:函数定义的三种方式
注意:第二种方式使用越来越多,第三种不常用,第一种常用
<script type="text/javascript">
// 方式一
function add(a,b){ // 没有返回值,形参不需要声明类型
return a+b; // 可以返回
}
//alert(add(1,2));
// 方式二 function 匿名函数, sub成为函数名称
var sub = function(a,b){
return a-b;
}
//alert(sub(10,8));
// 方式三 使用Function对象 定义函数
// 语法 new Funtion(arg1,arg2 ... , body)
var mul = new Function("a","b","return a*b;"); // 不常用
//alert(mul(10,20));
// 所有函数 都是Function实例
alert(mul instanceof Function);// true
</script>
②:JavaScript全局函数(内置函数)
一组与编码解码相关的函数
encodeURI()&decodeURI()
encodeURIComponent()&decodeURIComponent()
escape()&unescape()
此块具体内容请参照W3C文档查看。
4.ECMAScript核心——JavaScript面向对象编程
Java是面向对象,写Java程序,写类和对象。JavaScript是基于对象,写Js,不用创建类,使用Js内部已经定义好的对象。
①:定义JavaScript对象的两种方式
方式一:使用已经存在的对象,通过关键字进行创建
var s = new String("aaaa");
var o = new Object();
var date = new Date();
//alert(date instanceof Object);// true
// JS对象 类似一个map结构
var arr = new Array(3);
arr[0] = 100;// 使用数组下标 为数组元素赋值
arr['aaa'] = 1000; // 定义对象属性
//alert(arr['aaa']);
arr.showInfo = function(){// 定义对象方法
alert(arr.join(","));
};
//arr.showInfo(); //100, ,
Js其实就是一个类似map结构,key为属性名和方法名,value为属性值和方法定义
方式二:通过{}创建
var obj = {
name : '张三',
age : 20,
getName : function(){
// 访问对象属性 通过关键字 this
return this.name;
}
};
// 访问对象 属性 [] 和 .
//alert(obj.name);
//alert(obj["age"]);
alert(obj.getName());
// 添加一个方法到 obj对象
obj.getAge = function(){
return this.age;
}
alert(obj.getAge());
JavaScript中的对象是通过 new function创建的,在Js中function等同于一个类结构
// 定义类 结构
var Product = function(name,price){
this.name = name; // 保存name的值 到对象属性中
this.price = price;
}
// 基于类结构创建对象,使用new 关键字
var p1 = new Product("冰箱",1000);
var p2 = new Product("洗衣机",1500);
//alert(p1.name);
//alert(p1.price);
function本身代表一个函数,JavaScript对象通过new function来获得的,理解function就是对象构造函数
②:Object和function的关系
JavaScript中所有引用类型都是对象Object实例 ------- Function instanceOf Object //true
JavaScript 中所有对象都是通过 new Function实例(function) 获得 ------ Object instance Function //true
JavaScript所有对象构造函数都是function实例;JavaScript所有对象都是object实例,function也是object实例。
使用JavaScript的传递性进行推论!
A:function是用来定义一个函数,所有函数实例都是Function对象
B:JavaScript中,所有对象都是通过new function得到的
Var Object = function(){...}
Var String = function(){...}
Var Array = function(){...}
Var Date = function(){...}
结论:所有对象构造器都是Function实例
alert(String instanceOf Function) //true
alert(Object instanceOf Function) //true
C:创建一个对象,需要使用new function
Var s = new String()
Var o = new Object()
Var arr = new Array()
Var date = new Date()
结论:JavaScript中,一切对象都是object实例
alert(s instanceOf Object) //true
alert(Function instanceOf Object) //true
var f = new Function(); // 实例化Function对象
var o = new Object(); // 实例化Object对象
alert(f instanceof Function); // true
alert(f instanceof Object); // true
alert(o instanceof Function); // false
alert(o instanceof Object); // true
③:function原型属性
JavaScript所有对象都由function构造函数得来的 ,通过修改 function构造函数 prototype属性,动态修改对象属性和方法。
④:继承
A:使用原型链完成JavaScript单继承
var A = function(){
this.name = 'xxx';
}
var B = function(){
this.age = 20;
}
// 方式一 可以通过 prototype原型完成单继承 B的原型指向A
B.prototype = new A(); // 从A实例中,继承所有属性
var b = new B();
alert(b.name);
// 练习:通过prototype为String类添加一个trim方法
String.prototype.trim = function(){
return this.replace(/(^\s*)(\s*$)/g, "");
}
B:对象冒充完成多继承
var C = function(){
this.info = 'c';
}
var D = function(){
this.msg = 'd';
}
var E = function(){
// 同时继承C和D
this.methodC = C;
this.methodC();
delete this.methodC;
this.methodD = D;
this.methodD();
delete this.methodD;
this.desc = 'e';
}
var e = new E();
//alert(e.info);
//alert(e.msg);
//alert(e.desc);
⑤:动态方法调用
可以改变this的指向,可以完成对象多继承
// 定义函数
function printInfo(){
alert(this.name);
}
// 属性name 值 张三
var o = {name: '张三'};
//o.printInfo();// 函数不属于对象o
// JS提供动态方法调用两个方法,允许一个对象调用不是属于它自己的方法(call apply)
//printInfo.call(o);
//printInfo.apply(o);
function add(a,b){
this.sum = a+b;
}
// call传 多个参数
//add.call(o,8,10);
// apply 传递参数数组
add.apply(o,new Array(8,10));
//alert(o.sum);
// 动态方法调用 ,实现多重继承,原理就是对象冒充
var A = function(){
this.info = 'a';
}
var B = function(){
// 动态方法调用继承
A.call(this);
}
var b = new B();
alert(b.info);
二、JavaScript浏览器对象BOM
DOM Window 代表窗体
DOM History 历史记录
DOM Location 浏览器导航
DOM Navigator 浏览器信息 不讲
DOM Screen 屏幕 不讲
重点:window、history、location ,最重要的是window对象
1.window对象
Window 对象表示浏览器中打开的窗口,如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象
window.frames 返回窗口中所有命名的框架
parent是父窗口(如果窗口是顶级窗口,那么parent==self==top)
top是最顶级父窗口(有的窗口中套了好几层frameset或者iframe)
self是当前窗口(等价window)
opener是用open方法打开当前窗口的那个窗口
①:父子窗体之间的通讯
在页面内嵌入一个iframe,在iframe中提供一个输入项,输入后,在iframe外面窗口中显示内容
显示结果如上图所示,实现思路如下:
子窗体:2.html
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>Untitled Document</title>
<script type="text/javascript">
function showOutter(){
// 获得输入内容
var content = document.getElementById("content").value;
// 将输入的内容显示到主窗体info 中
window.parent.document.getElementById("info").innerHTML = content;
}
</script>
</head>
<body>
<h1>子窗体</h1>
<input type="text" id="content" />
<input type="button" value="显示到主窗体" onclick="showOutter();"/>
</body>
主窗体:1.html
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>父子窗体通信</title>
<script type="text/javascript">
function showContent(){
// 用主窗体读取子窗体内容
var content = window.frames[0].document.getElementById("content").value;
alert(content);
}
</script>
</head>
<body>
<h1>主窗体</h1>
<div id="info"></div>
<!-- 在主窗体中获得子窗体内容 -->
<input type="button" value="获取子窗体输入内容" onclick="showContent();" />
<iframe src="2.html"></iframe>
</body>
②:window的open close
<head>
<title>打开关闭窗体</title>
<meta http-equiv="content-type" content="text/html; charset=gbk">
<script type="text/javascript">
//用一个变量记录打开的网页
var openNew;
function openWindow(){
openNew = window.open("http://www.itcast.cn");
}
//关闭的时候需要注意关闭的是打开的网页,而不是本身
function closeWindow(){
openNew.close();
}
</script>
</head>
<body>
<input type="button" value="打开传智播客网页" onclick="openWindow()">
<input type="button" value="关闭传智播客网页" onclick="closeWindow()">
</body>
③:window弹出对话框相关的3个方法
alert()警告框 confirm()确认框 prompt()输入框
<script type="text/javascript">
alert("这是警告框!")
var con = confirm("你想好了吗?");
alert(con);
var msg = prompt("请输入姓名","张三");
alert(msg);
</script>
④:定时操作setInterval & setTimeout
setInterval:定时任务会重复执行
setTimeout:定时任务只执行一次
在页面动态显示当前时间
<script type="text/javascript">
window.onload = function(){
var date = new Date();
document.getElementById("time1").innerHTML =date.toLocaleString();
document.getElementById("time2").innerHTML =date.toLocaleString();
setInterval("show1();",1000); //间隔1秒后重复执行
setTimeout("show2();",1000);//1秒后执行,执行1次
}
function show1(){
var date = new Date();
document.getElementById("time1").innerHTML =date.toLocaleString();
}
function show2(){
var date = new Date();
document.getElementById("time2").innerHTML =date.toLocaleString();
setTimeout("show2();",1000);//不终止
}
</script>
<body>
<div id="time1"></div>
<div id="time2"></div>
</body>
2.history 对象
代表历史记录,常用来制作页面中返回按钮
<input type="button" value="返回" onclick="history.back();" />
<input type="button" value="返回" onclick="history.go(-1);" />
3.Location 对象
代表浏览器导航 在js函数中发起href链接效果
location.href='跳转后url' ; 等价于 <a href='xxx'></a>
三、JavaScript文档对象模型DOM
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gbk">
<title>History和Location使用</title>
</head>
<body>
<input type="button" value="返回" onclick="history.back();" />
</body>
</html>
DOM 解析模型,将文档加载到 内存,形成一个树形结构 <html> 就是根节点,每个标签会成为一个元素节点、标签的属性成为属性节点,标签内部的文本内容成为文本节点
注意:属性节点,它不属于DOM树形结构,不属于任何节点父节点,也不属于任何节点的子节点 ,属性节点依附于元素节点上 一种附加节点
【上面代码 产生6个元素节点,5个属性节点,9个文本节点】
HTML 本身也是 XML,所有可以使用XML DOM API规范
DOM Element
DOM Attr
DOM Text
DOM Document
HTML DOM是对XML DOM的扩展, HTML DOM比XML DOM 开发JS来说更加简单方便!
HTML DOM最优秀的地方是,操作form对象和table数据
1.BOM和HTML DOM关系图
学习DOM 编程,从Document对象开始,document代表当前HTML网页文档对象,是window对象一个属性,可以直接使用 ,所有HTML DOM对象都是Document子对象
2.DOM编程开发
window.document 代表整个HTML文档
①:通过document获得Node节点对象
document.forms 获得页面中所有form元素集合
document.body 访问页面中<body> 元素
document.cookie 用JS操作网页cookie信息
全局检索提供了三个重要的方法:
document.getElementById():通过id属性检索,获得Node节点(Element元素)
document.getElementsByName 通过name 属性检索 ,获得NodeList
document.getElementsByTagName 通过标签元素名称 获得NodeList
其中NodeList可以作为数组进行操作
Demo:在每一个h1标签后追加itcast
<script type="text/javascript">
//在每一个h1标签内追加一个itcast
window.onload = function(){
var nodeList = document.getElementsByTagName("h1");
for(var i=0; i<nodeList.length;i++){
// var h1 = nodeList[i];
var h1 = nodeList.item(i);
alert(h1.innerHTML);
h1.innerHTML += "itcast";
}
}
</script>
<body>
<h1>AAA</h1>
<h1>BBB</h1>
<h1>CCC</h1>
<h1>DDD</h1>
</body>
②:获得node后
如果node是元素,去操作里面的文本内容 innerHTML (HTML页面内所有元素,一定是HTML 元素,innerHTML 是所有HTML元素通用属性 )
XML 取得一个元素内部文本内容 element.firstChild.nodeValue(看批注32)
③:通过节点Node相对位置关系访问元素
childNodes
firstChild
lastChild
nextSibling
parentNode
previousSibling
用2种方式打印——明天休息
<h1 id="h1">明天休息</h1> <br>
var h1 = document.getElementById("h1");
alert(h1.innerHTML);//方式一
alert(h1.firstChild.nodeValue);//方式二
3.DOM元素常见操作
DOM 获取节点:节点查询 参上
DOM 改变节点: 元素属性修改setAttribute(name,value)
内部文本元素的修改 innerHTML
DOM 删除节点:removeChild 删除子元素 、removeAttribute(name)删除节点指定属性
* 要删除节点o o.parentNode.removeChild(o)
DOM 替换节点:replaceChild:父节点.replaceChild(新节点,被替换节点) ;
如果对于一个已经存在节点,执行 appendChild、 replaceChild都会造成该节点一个移动效果,可以采取先克隆再复制来消除此效果。
DOM 创建节点:document对象提供createElement() 创建元素、createAttribute(name) 创建属性、createTextNode() 创建文本节点
DOM 添加节点 appendChild 父元素.appendChild(新的子节点) ;
insertBefore 父节点.insertBefore(新子节点, 已经存在子节点)
DOM 克隆节点 源节点.cloneNode(true); 该方法可以返回一个节点的克隆节点, 克隆节点包含原节点的属性和子元素
此节内容有大量的练习,建议大家做写,增强代码的熟练度。
四、JavaScript事件
事件通常与函数配合使用,这样就可以通过发生的事件来驱动函数执行。事件是基于对象存在,事件通常可以修饰多种对象。
1.为对象添加事件的2种方式
①:在HTML元素中添加对象的事件
<head>
<title>事件</title>
<meta http-equiv="content-type" content="text/html; charset=gbk">
<script type="text/javascript">
function overtest(){
alert("移动到图片上方");
}
</script>
</head>
<body>
<img src="1.jpg" width="200" height="300" onmouseover = "overtest()";/>
</body>
②:在JS代码中为元素添加事件
<head>
<title>事件</title>
<meta http-equiv="content-type" content="text/html; charset=gbk">
<script type="text/javascript">
function overtest(){
alert("移动到图片上方");
}
window.onload = function(){
document.getElementById("myimg").onmouseover = overtest;
}
</script>
</head>
<body>
<img src="1.jpg" width="200" height="300" id="myimg";/>
</body>
总结:优先使用第二种,将js代码与HTML元素代码分离开,更加方便统一管理维护。
问题:HTML 元素添加事件, 与JS添加事件是否可以完全等价?
在实际开发中,如果传参数,使用HTML元素绑定事件,如果不传参数,使用JS绑定事件。传参数也可以使用与JS绑定事件【使用匿名函数】。示例代码如下:
<head>
<title>HTML事件绑定与JS绑定</title>
<meta http-equiv="content-type" content="text/html; charset=gbk">
<script type="text/javascript">
function clicktest(o){
alert(o);
}
window.onload = function(){
document.getElementById("mybutton").onclick = function(){
clicktest('次奥');
}
}
</script>
</head>
<body>
<input type="button" id="mybutton" value="点击我!">
<input type="button" value="别碰我!" onclick = "clicktest('次奥')"/>
</body>
2.鼠标移动事件
Mousemove: 鼠标移动时触发事件 鼠标跟随效果
Mouseover: 鼠标从元素外,移动元素之上,信息提示、字体变色
Mouseout: 鼠标从元素上,移出元素范围,和mouseover一起使用
3.鼠标点击事件(左键相关事件)
click 鼠标单击事件
dbclick 鼠标双击事件
mousedown/mouseup 鼠标按下、按键弹起 click = mousedown + mouseup;
oncontextmenu 鼠标右键菜单事件 (不是浏览器兼容事件)
4.聚焦离焦事件
focus 聚焦 页面焦点定位到目标元素
blur 离焦 页面焦点由目标元素移开
Demo:
<script type="text/javascript">
window.onload= function(){
//页面加载后,在输入框加入默认值,并以灰色显示
document.getElementById("username").value= "用户名";
document.getElementById("username").style.color="gray";
//聚焦事件
document.getElementById("username").onfocus= function(){
document.getElementById("username").value="";
document.getElementById("username").style.color="black";
}
//离焦事件
document.getElementById("username").onblur=function(){
var name = document.getElementById("username").value;
if(name==""){
document.getElementById("username").value="张三";
document.getElementById("username").style.color="gray";
}
}
}
</script>
</head>
<body>
请输入用户名:<input type="text" id="username"><br/>
</body>
5.键盘事件
使用场景:没有提交按钮,我们一般采用回车进行提交
Demo:
<script type="text/javascript">
window.onload = function(){
document.getElementById("message").onkeypress = function(e){
// 判断用户 按键是否为 回车键
if(e && e.which){
// 火狐浏览器
if(e.which == 13){
alert("提交")
}
}else{
// IE浏览器
if(window.event.keyCode ==13 ){
alert("提交")
}
}
}
}
</script>
<body>
发送消息 <input type="text" name="message" id="message"/>
</body>
IE 中window对象,提供event属性,所以在IE中可以直接使用 event对象
火狐没有全局event对象,必须在发生事件时,产生一个event对象 ,传递默认方法
6.form的提交、重置事件
submit/reset
onsubmit = "return validateForm" 对表单进行校验
7.改变事件
onchange 制作select联动效果 ---- 省市联动
重点 : onclick 、onchange 、onblur、 onsubmit
8.默认事件的阻止和传播阻止
使用场景极为常见,超链接用户点击后,取消了不发生跳转。
<script type="text/javascript">
// 阻止默认事件发生
function confirmDel(e){
var isConfirm = window.confirm("确认删除吗?");
if(!isConfirm){// 用户选择了取消
// 阻止默认事件
if(e && e.preventDefault){
// 火狐
e.preventDefault();
}else{
// IE
window.event.returnValue = false;
}
}
}
// 阻止事件冒泡
function aclick(e){
alert("a");
if(e && e.stopPropagation){
// 火狐浏览器
e.stopPropagation();
}else{
// IE 浏览器
window.event.cancelBubble = true;
}
}
function divclick(){
alert("div");
}
</script>
<body>
<h1>默认事件</h1>
<!-- 删除时,询问用户是否删除,然后再跳转-->
<a href="del?id=1" onclick="confirmDel(event);">这是一个链接</a>
<h1>事件传播</h1>
<!-- 事件冒泡传播 -->
<div onclick="divclick();"><a href="#" onclick="aclick(event);">这个链接 会触发两个事件执行</a></div>
</body>
HTML DOM Event对象
提供preventDefault()用于阻止默认事件的发生, 该方法IE 不支持 ,在IE中使用 returnValue
提供stopPropagation()用与阻止事件传播,该方法IE不支持,在IE中 cancelBubble
五、Ajax编程入门
1.web交互的2种模式对比
①:2种交互模式的流程
②:2种交互模式用户体验
同步交互模式:客户端提交请求,等待,在响应回到客户端前,客户端无法进行其他操作
异步交互模型:客户端将请求提交给Ajax引擎,客户端可以继续操作,由Ajax引擎来完成与服务武器端通信,当响应回来后,
<>
<>
&
>>
<>
<>
<><>
<>
<>
<><>
<><>
<>
<>
<>
<><>
<>
>
>
<><>
<>
<>
<>
<><>
<><>
<><>
<><>
<><>
<><>
<><>
<><>
<><>
<>
>>
<><>
<>
>
<>
<>
<>
<><>
<>
<><>
<>
<>
<><>
<>
<><>
<>
<><>
<>
<><>
<>
<>
<>
<><>
<><>
<>
<>
<><>
<><>
<><>
<><>
<>
<>
<><>
<><>
<><>
<><>
<>
<>
<><>
<><>
<><>
<><>
<>
<>
<><>
<><>
<><>
<><>
<>
<>
<><>
<><>
<><>
<><>
<>
<>
<>
<>
<>
<>
<>
<><>
<>
<>
<>
<><>
<><>
<><><><>
<><>
<><><><>
<><>
<>
<><>
<>
<>
<>
<>
<>
<
>
<>
<>
<>
<>
<><>
<>
<>
<><>
<>
<>
<><>
<>
<>
<>
<><>
<>
<>
<>
<><>
<><>
<><>
<><>
<><>
<><>
<><>
<>
<><>
<>
<>
<>
<>
<>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><><><>
<><><><>
<>
<>
<><><><>
<><>
<>
<>
<>
<>
<><>
<><>
<>
<><>
<>
<><>
<><>
<>
<><>
<>
<>
<>
<><>
<>
<>
<>
<>
<>
<><>
<>
<>
<>
<><>
<>
<><>
<><>
<><>
<><>
<>
<>
<><>
<>
<>
<>
<>
<><>
<>
<>
<><>
<>
<>
<>
<>
<><>
<>
<>
<>
&&
<><><><>
<><>
<>
<><><><>
<><><><>
<>
<>
<>
<><>
<>
<><>
<>
<><>
<><>
<><>
<><>
<>
<>
<><>>
<><>
<>
<>
<>
<>
<>
<><>
<><>
<><>
<><>
<>
<><>
<><>
<>
<><>
<>
<>
<><>
<><>
<><>
<><>
<>
<><>
<>
<>
<>
<>
<><>
<><>
<>
<><>
<>
<><><><><><><><><><><><>
<>
<>
<>
<>
<>
<>
<><>
<>
<>
<>
<>
<><>
<><>
<><>
<><>
<>
<>
<><><><>
<><>
<><>
<>
<>
<>
<>
<><>
<>
<>
<>
<><>
<>
<>
<>
<>
<><>
<>
<>
<>
<>
<>
<><>
<><>
<><>
<><>
<><>
<><>
<><>
<><>
<>
<>>
<>>
<<>
<<>
<>
<><>
<>
<>
<><>
<>
<><>
<>
<>
<>
<><>
<><>
<>
<><>
<>
<>
<>
<><>
<>
<>
<>
<><>
<>
<>
<>
<><>
<>
<>
<><>
<>
<>
<>
<><>
<><><><>
<>
&
<>
<>
<><><><>
<><>
<>
<>