以下兼容主要面向IE8以上的兼容。
一.window.navigator浏览器信息
1 <script> 2 console.log(window.navigator); 3 // 用户浏览器的类型 到底是 谷歌还是火狐,ie等 4 console.log(window.navigator.userAgent); 5 // 判断浏览器所在的系统平台类型 ,window还是mac 6 console.log(window.navigator.platform); 7 </script>
二.查找页面元素的几种方式
1 <script> 2 window.onload = function () { 3 // 无兼容问题放心使用 4 // 1) 通过id查找元素,获取到匹配的第一个id元素 5 // var btn = document.getElementById('btn'); 6 // console.log(btn); 7 // 2) 通过标签名称查找元素,获取到的是伪数组 8 // var buttons = document.getElementsByTagName('button'); 9 //// 伪数组不能调用数组里的全部方法和属性 10 //// console.log( buttons.push("123") ); // 报错 11 // console.log( buttons ); 12 13 // 了解:兼容问题 ie 9+ 14 // 3) 通过类名查找元素,获取到的是伪数组 ie 9+ 15 // var btnClass = document.getElementsByClassName("btn-class"); 16 // console.log(btnClass); 17 18 // 4) 通过name属性查找元素,获取到的是伪数组 19 // name标准用法应该是表单的,如提交表单数据时,name是作为数据的key 20 // var btnName = document.getElementsByName('btn-name'); 21 // console.log(btnName); 22 23 // 5) 通过合法的css选择器去查找到第一个元素 24 // var query1 = document.querySelector("#btn"); 25 // var query1 = document.querySelector("[name='btn-name']"); 26 // console.log(query1); 27 // 28 // 6) 通过合法的css选择器去查找到所有元素(做手机项目的时候常用) 29 // var query2 = document.querySelectorAll("#btn"); // 不推荐用这种方式找id 30 var query2 = document.querySelectorAll(".btn-class"); 31 console.log(query2); 32 33 } 34 </script>
三.innerText、innerHTML、textContent兼容问题
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <script> 7 /** 8 * innerHTML 9 * 全部浏览器都兼容 10 * innerText firefox45+后支持 11 * ie,chrome,opera,safari,firefox45+ 12 * textContent ie9+ 13 * firefox,chrome, ie9+ 14 * 15 * */ 16 window.onload = function () { 17 var btns = document.getElementsByTagName('button'); 18 var uls = document.getElementsByTagName('ul'); 19 btns[0].onclick = function () { 20 // 如果innerText获取到不是undefined,说明兼容innerText 21 if( uls[0].innerText !== undefined ){ 22 uls[0].innerText = "123"; 23 }else{ 24 // 其他情况:如低版本获取用另一种方式修改 25 uls[0].textContent = "低版本火狐修改"; 26 } 27 } 28 29 } 30 </script> 31 </head> 32 <body> 33 <button>换一换新闻</button> 34 <ul> 35 <li>牛大</li> 36 <li>拉面的老板去参加比赛了</li> 37 </ul> 38 </body> 39 </html>
四.注册事件的三种方式、解绑事件的兼容方式、阻止事件传播(冒泡)
1.注册事件的三种方式
1 <script> 2 window.onload = function () { 3 4 /** 5 * 一、事件三要素 6 * 事件源 7 * 事件类型 8 * 事件处理程序 9 * 10 * 11 * 二、注册事件三种方式 12 * 第一种: 13 * 事件源.on事件类型 = 事件处理程序 14 * 第二种: ie8不支持 15 * 事件源.addEventListener('事件类型',事件处理程序,false) 16 * 第三种: chrome、Firefox、Safari、ie11都不支持,ie6~10支持 17 * 事件源.attachEvent('on事件类型',事件处理程序) 18 * 19 * */ 20 var btn = document.getElementById('btn'); 21 22 // 第一种:快速注册事件 23 // btn.onclick = function () { 24 // alert("我们给按钮添加了一个事件"); 25 // } 26 27 28 // 第二种:事件监听 不支持ie8 29 // 事件源.addEventListener('事件类型',事件处理程序) false是事件冒泡(默认) true是事件捕获 30 btn.addEventListener('click',function () { 31 alert("我们给按钮添加了一个事件"); 32 }); 33 34 btn.addEventListener('click',function () { 35 alert("AAAAAAA"); 36 },false); 37 38 39 // 第三种:事件监听 Chrome、Firefox、Safari,ie11都不支持,ie6~10支持 40 // btn.attachEvent('onclick',function () { 41 // alert("我们给按钮添加了一个事件"); 42 // }); 43 // btn.attachEvent('onclick',function () { 44 // alert("我们给按钮添加了一个事件2222"); 45 // }); 46 // btn.attachEvent('onclick',function () { 47 // alert("我们给按钮添加了一个事件3333"); 48 // }); 49 50 51 52 } 53 </script>
事件注册兼容处理:
1 <script> 2 /* 3 谷歌和ie8注册方式不同, 4 所以我们要进行判断支持哪种注册方式,就使用哪种注册方式添加事件 5 */ 6 function myEventListener(element,type,fn) { 7 if( element.addEventListener ){ 8 element.addEventListener(type,fn); 9 }else if( element.attachEvent ){ 10 element.attachEvent("on"+type,fn); 11 }else{ 12 element["on"+type] = fn; 13 } 14 } 15 myEventListener(btn,'click',function () { 16 alert("兼容版的事件注册方式"); 17 }); 18 </script>
2.解绑事件的兼容方式
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <script> 7 window.onload = function () { 8 /** 9 * 一、事件三要素 10 * 事件源 11 * 事件类型 12 * 事件处理程序 13 * 14 * 15 * 二、注册事件三种方式 16 * 第一种: 17 * 事件源.on事件类型 = 事件处理程序 18 * 第二种: ie8不支持 19 * 事件源.addEventListener('事件类型',事件处理程序,false) 20 * 第三种: chrome不支持 21 * 事件源.attachEvent('on事件类型',事件处理程序) 22 * 23 * 24 * 三、事件解绑 25 * 第一种: 26 * 事件源.on事件类型 = null 27 * 第二种: ie8不支持 28 * 事件源.removeEventListener('事件类型',事件处理程序,false) 29 * 第三种: chrome不支持 30 * 事件源.detachEvent('on事件类型',事件处理程序) 31 * 32 * 33 * */ 34 var btn = document.getElementById('btn'); 35 var btn2 = document.getElementById('btn2'); 36 // 事件注册兼容方式 37 function myEventListener(element,type,fn) { 38 // 主流浏览器注册方式 39 if( element.addEventListener ){ 40 element.addEventListener(type,fn,false); 41 // 42 }else if( element.attachEvent ){ 43 element.attachEvent("on"+type,fn); 44 }else{ 45 element["on"+type] = fn; 46 } 47 }// 事件解绑兼容方式 48 function myRemoveEventListener(element,type,fn) { 49 if( element.removeEventListener ){ 50 element.removeEventListener(type,fn,false); 51 }else if( element.detachEvent ){ 52 element.detachEvent("on"+type,fn); 53 }else{ 54 element["on"+type] = null; 55 } 56 } 57 58 function fn() { 59 alert("兼容版的事件注册方式"); 60 } 61 myEventListener(btn,'click',fn); 62 // 独立fn是为了浏览器能区分每个事件注册 63 btn2.onclick = function () { 64 myRemoveEventListener(btn,'click',fn); 65 } 66 67 console.log( btn.addEventListener ); 68 console.log( btn.attachEvent ); 69 70 } 71 </script> 72 </head> 73 <body> 74 <button id="btn">按钮</button> 75 <button id="btn2">解绑事件</button> 76 </body> 77 </html>
3.阻止事件传播(冒泡)兼容
1 <!DOCTYPE html> 2 <html lang="en" xmlns="http://www.w3.org/1999/html"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 #yeye{ 8 500px; 9 height: 500px; 10 background-color: #f24b4b; 11 } 12 #baba{ 13 400px; 14 height: 400px; 15 background-color: #44c28d; 16 } 17 #erzi{ 18 300px; 19 height: 300px; 20 background-color: #6e8cd5; 21 } 22 </style> 23 <script> 24 window.onload = function () { 25 26 /** 27 * 28 * 29 * 事件捕获: 30 * 浏览器就好像盲人一样,要找某个元素,其实挨个挨个问的方式去找 31 * 这个过程我们叫事件的捕获过程. 32 * // 从外到里,直到找到目标 33 * 34 * 事件冒泡: 35 * 找到到目标后,其实还有一个回馈的过程,逐级往上传播 36 * 这个过程我们叫事件的冒泡过程. 37 * // 从里到外,直到传到window 38 * 39 * 注意: 40 * 我们一般都是事件冒泡的方式注册事件的 41 * 42 * 43 * 事件的三个阶段 44 45 1. 捕获阶段 46 2. 当前目标阶段 47 3. 冒泡阶段 48 事件对象.eventPhase属性可以查看事件触发时所处的阶段 49 50 * 51 * */ 52 53 var yeye = document.getElementById("yeye"); 54 var baba = document.getElementById("baba"); 55 var erzi = document.getElementById("erzi"); 56 57 erzi.onclick = function (event) { 58 event = event || window.event; 59 if(event.stopPropagation) { 60 // ie9+ 其余全支持 61 event.stopPropagation(); 62 }else{ 63 // 全部兼容,火狐不兼容 64 event.cancelBubble = true; 65 } 66 console.log("儿子", event); 67 } 68 baba.onclick = function (event) { 69 event = event || window.event; 70 if(event.stopPropagation) { 71 // ie9+ 其余全支持 72 event.stopPropagation(); 73 }else{ 74 // 全部兼容,火狐不兼容 75 event.cancelBubble = true; 76 } 77 console.log("爸爸", event); 78 } 79 yeye.onclick = function (event) { 80 event = event || window.event; 81 if(event.stopPropagation) { 82 // ie9+ 其余全支持 83 event.stopPropagation(); 84 }else{ 85 // 全部兼容,火狐不兼容 86 event.cancelBubble = true; 87 } 88 console.log("爷爷", event); 89 } 90 } 91 </script> 92 </head> 93 <body> 94 <div id="yeye"> 95 <div id="baba"> 96 <div id="erzi"></div> 97 </div> 98 </div> 99 </body> 100 </html>
五.event事件对象兼容问题
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <script> 7 /** 8 * 9 * 事件对象兼容写法: 10 * event IE不兼容 window.event火狐(Firefox 不支持) 11 * event = event || window.event; 12 * 13 * 事件目标元素兼容写法: 14 * event.target IE9.0版本才开始支持 15 * event.srcElement 火狐(Firefox 不支持) 16 * event.target = event.target || event.srcElement; 17 * 18 * 19 * */ 20 21 window.onload = function () { 22 var btn = document.getElementById('btn'); 23 btn.onclick = function (event) { 24 // console.log(event); 25 // console.log(window.event); 26 event = event || window.event; // 短路写法 27 event.target = event.target || event.srcElement; // 短路写法 28 // event.target 29 console.log( event.target ); 30 console.log( event.srcElement ); 31 } 32 33 } 34 </script> 35 </head> 36 <body> 37 <button id="btn">按钮</button> 38 </body> 39 </html>
六.兼容ie8的获取样式函数
注意点
1 // window.getComputedStyle(box,null) -- box 是目标标签 2 // 这种写法是获取到计算完成的样式,所以这种写法能获取到各种样式表 3 // 甚至可以获取到继承过来的属性和默认样式 4 console.log(boxStyle); 5 console.log(boxStyle.width); 6 console.log(boxStyle["width"]); 7 console.log(boxStyle['padding-left']); 8 console.log(boxStyle['paddingLeft']); // 推荐驼峰写法 9 console.log(box.style.width);*/ 10 11 //兼容IE6~8 12 // console.log(box.currentStyle); 13 14 // if(window.getComputedStyle) { 15 // var boxStyle = window.getComputedStyle(box,null); 16 // }else if(box.currentStyle){ 17 // var boxStyle = box.currentStyle; 18 // } 19 // console.log(boxStryle);
封装函数
1 /** 2 * 获取样式函数 3 * @param element 要获取的样式的对象 4 * return 目标css样式对象 5 * */ 6 function getStyle(element) { 7 if(window.getComputedStyle) { 8 return window.getComputedStyle(element,null); 9 }else if(element.currentStyle){ 10 return element.currentStyle; 11 } 12 }
应用例子--缓动动画函数:
1 /** 2 * 获取样式函数 3 * @param element 要获取的样式的对象 4 * return 目标css样式对象 5 * */ 6 function getStyle(element) { 7 if(window.getComputedStyle) { 8 return window.getComputedStyle(element,null); 9 }else if(element.currentStyle){ 10 return element.currentStyle; 11 } 12 } 13 14 /** 15 * 动画函数 16 * @param element html标签 17 * @param attr 标签属性 18 * @param target 目标参数 19 * */ 20 function animate(element,obj) { 21 clearInterval(element.timer); 22 element.timer = setInterval(function () { 23 var flag = true; 24 for(var attr in obj){ 25 // 在for in 的内部要区别开到底是透明度还是像素px的变化 26 if( attr == "opacity") { 27 var current = getStyle(element)[attr]; 28 var target = obj[attr]; 29 current = current * 100; 30 target = target * 100; 31 // Math.round() 函数返回一个数字四舍五入后最接近的整数值。 32 current = Math.round(current); 33 var step = (target - current) / 10; 34 current += current <= target ? Math.ceil(step):Math.floor(step); 35 if(current != target) { 36 flag = false; 37 } 38 // element.style.left等 39 element.style[attr] = current / 100; 40 }else if(attr == "zIndex"){ 41 element.style[attr] = obj[attr]; 42 } else{ 43 var current = parseInt(getStyle(element)[attr]); 44 var target = obj[attr]; 45 var step = (target - current) / 10; 46 current += current <= target ? Math.ceil(step):Math.floor(step); 47 if(current != target) { 48 flag = false; 49 } 50 // element.style.left等 51 element.style[attr] = current+ "px"; 52 } 53 } 54 if(flag) { 55 clearInterval(element.timer); 56 } 57 },40); 58 }
七.pageX、pageY还有event、clientX、clientY等兼容
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 *{ 8 margin: 0; 9 padding: 0; 10 } 11 .box { 12 200px; 13 height: 200px; 14 background-color: pink; 15 margin-top:1000px; 16 margin-left:100px; 17 margin-bottom:100px; 18 position: absolute; 19 /*left: 100px;*/ 20 21 } 22 .txt { 23 color: red; 24 font-size: 20px; 25 } 26 </style> 27 </head> 28 <body> 29 <div class="box" id="box"> 30 200px<br> 31 height: 200px<br> 32 background-color: pink<br> 33 margin-top:1000px<br> 34 margin-left:100px<br> 35 margin-bottom:100px<br> 36 <h2 class="txt" id="txt" ></h2> 37 </div> 38 39 </body> 40 </html> 41 <script> 42 /*封装event*/ 43 var eventTool = { 44 getEvent : function (event) { 45 return event || window.event; 46 }, 47 48 getClienX: function (event) { 49 return this.getEvent(event).clientX; 50 }, 51 getClienY: function (event) { 52 return this.getEvent(event).clientY; 53 }, 54 getPageY : function () { 55 // pageY = 页面滚动出去垂直距离 + 事件在当前视口的距离 56 return (window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0) + this.getClienY(event); 57 }, 58 59 getPageX : function () { 60 // pageX = 页面滚动出去横向距离 + 事件在当前视口的距离 61 return (window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft || 0) + this.getClienX(event); 62 } 63 64 } 65 var box = document.getElementById('box'); 66 var txt = document.getElementById('txt'); 67 box.onclick = function (event) { 68 // ie8下event兼容 69 // var event = eventTool.getEvent(event); 70 // console.log(event); 71 // pageY = 页面滚动出去垂直距离 + 事件在当前视口的距离 72 // console.log(window.pageYOffset + event.clientY); 73 // console.log(window.pageYOffset); 74 // console.log(event.pageY); 75 76 console.log(eventTool.getPageY(event)); 77 txt.innerHTML = eventTool.getPageX(event); 78 // txt.innerHTML += eventTool.getClienY(event); 79 // txt.innerHTML = "pageX:"+event.pageX+"<br> pageY:"+event.pageY; 80 81 // 获取window滚动条滚动的距离window.pageYOffset/scrollY的别名 window.pageXOffset/ scrollX的别名 82 83 } 84 </script>
封装写法
eventTool.js
1 /*封装eventTool*/ 2 var eventTool = { 3 getEvent : function (event) { 4 return event || window.event; 5 }, 6 7 getClienX: function (event) { 8 return this.getEvent(event).clientX; 9 }, 10 getClienY: function (event) { 11 return this.getEvent(event).clientY; 12 }, 13 getPageY : function () { 14 // pageY = 页面滚动出去垂直距离 + 事件在当前视口的距离 15 return (window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop || 0) + this.getClienY(event); 16 }, 17 18 getPageX : function () { 19 // pageX = 页面滚动出去横向距离 + 事件在当前视口的距离 20 return (window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft || 0) + this.getClienX(event); 21 } 22 23 }
封装方法2:
my.js
1 function $(id) {return document.getElementById(id);} 2 function show(obj) { obj.style.display = "block";} 3 function hide(obj) { obj.style.display = "none";} 4 function scroll() { 5 if(window.pageYOffset != null) // ie9+ 和其他浏览器 6 { 7 return { 8 left: window.pageXOffset, 9 top: window.pageYOffset 10 } 11 } 12 else if(document.compatMode == "CSS1Compat") // 声明的了 DTD 13 // 检测是不是怪异模式的浏览器 -- 就是没有 声明<!DOCTYPE html> 14 { 15 return { 16 left: document.documentElement.scrollLeft, 17 top: document.documentElement.scrollTop 18 } 19 } 20 return { // 剩下的肯定是怪异模式的 21 left: document.body.scrollLeft, 22 top: document.body.scrollTop 23 } 24 }
使用例子--返回顶部小火箭:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 body{ 8 2000px; 9 } 10 .top{ 11 position: fixed; 12 right: 50px; 13 bottom: 100px; 14 display: none; 15 } 16 17 </style> 18 <script src="my.js"></script> 19 <script> 20 window.onload = function () { 21 var goTop = $("gotop"); 22 window.onscroll = function () { 23 scroll().top > 0 ?show(goTop) : hide(goTop); 24 leader = scroll().top; // 把减去的头部给起始位置 25 console.log(scroll().top); 26 } 27 28 var leader = 0,target = 0 ,timer = null; 29 goTop.onclick = function () { 30 target = 0; 31 timer = setInterval(function () { 32 leader = leader + (target - leader) / 10; 33 window.scrollTo(0,leader); // 去往页面的某个位置 34 if(leader == target) { 35 clearInterval(timer); 36 } 37 },20); 38 } 39 } 40 </script> 41 </head> 42 <body> 43 <div id="gotop" class="top"> 44 <img src="images/Top.jpg" alt=""> 45 </div> 46 <p>我是顶部</p> 47 <p>我是内容部分</p> 48 <p>我是内容部分</p> 49 <p>我是内容部分</p> 50 <p>我是内容部分</p> 51 <p>我是内容部分</p> 52 <p>我是内容部分</p> 53 <p>我是内容部分</p> 54 <p>我是内容部分</p> 55 <p>我是内容部分</p> 56 <p>我是内容部分</p> 57 <p>我是内容部分</p> 58 <p>我是内容部分</p> 59 <p>我是内容部分</p> 60 <p>我是内容部分</p> 61 <p>我是内容部分</p> 62 <p>我是内容部分</p> 63 <p>我是内容部分</p> 64 <p>我是内容部分</p> 65 <p>我是内容部分</p> 66 <p>我是内容部分</p> 67 <p>我是内容部分</p> 68 <p>我是内容部分</p> 69 <p>我是内容部分</p> 70 <p>我是内容部分</p> 71 <p>我是内容部分</p> 72 <p>我是内容部分</p> 73 <p>我是内容部分</p> 74 <p>我是内容部分</p> 75 <p>我是内容部分</p> 76 <p>我是内容部分</p> 77 <p>我是内容部分</p> 78 <p>我是内容部分</p> 79 <p>我是内容部分</p> 80 <p>我是内容部分</p> 81 <p>我是内容部分</p> 82 <p>我是内容部分</p> 83 <p>我是内容部分</p> 84 <p>我是内容部分</p> 85 <p>我是内容部分</p> 86 <p>我是内容部分</p> 87 <p>我是内容部分</p> 88 <p>我是内容部分</p> 89 <p>我是内容部分</p> 90 <p>我是内容部分</p> 91 <p>我是内容部分</p> 92 <p>我是内容部分</p> 93 <p>我是内容部分</p> 94 <p>我是内容部分</p> 95 <p>我是内容部分</p> 96 <p>我是内容部分</p> 97 <p>我是内容部分</p> 98 <p>我是内容部分</p> 99 <p>我是内容部分</p> 100 <p>我是内容部分</p> 101 <p>我是内容部分</p> 102 <p>我是内容部分</p> 103 <p>我是内容部分</p> 104 <p>我是内容部分</p> 105 <p>我是内容部分</p> 106 <p>我是内容部分</p> 107 <p>我是内容部分</p> 108 <p>我是内容部分</p> 109 <p>我是内容部分</p> 110 <p>我是内容部分</p> 111 <p>我是内容部分</p> 112 <p>我是内容部分</p> 113 <p>我是内容部分</p> 114 <p>我是内容部分</p> 115 <p>我是内容部分</p> 116 <p>我是内容部分</p> 117 <p>我是内容部分</p> 118 <p>我是内容部分</p> 119 <p>我是内容部分</p> 120 <p>我是内容部分</p> 121 <p>我是内容部分</p> 122 <p>我是内容部分</p> 123 <p>我是内容部分</p> 124 <p>我是内容部分</p> 125 <p>我是内容部分</p> 126 <p>我是内容部分</p> 127 <p>我是内容部分</p> 128 <p>我是内容部分</p> 129 <p>我是内容部分</p> 130 <p>我是内容部分</p> 131 <p>我是内容部分</p> 132 <p>我是内容部分</p> 133 <p>我是内容部分</p> 134 <p>我是内容部分</p> 135 <p>我是内容部分</p> 136 <p>我是内容部分</p> 137 <p>我是内容部分</p> 138 <p>我是内容部分</p> 139 <p>我是内容部分</p> 140 <p>我是内容部分</p> 141 <p>我是内容部分</p> 142 <p>我是内容部分</p> 143 <p>我是内容部分</p> 144 <p>我是内容部分</p> 145 <p>我是内容部分</p> 146 <p>我是内容部分</p> 147 <p>我是内容部分</p> 148 <p>我是内容部分</p> 149 <p>我是内容部分</p> 150 <p>我是内容部分</p> 151 <p>我是内容部分</p> 152 <p>我是内容部分</p> 153 <p>我是内容部分</p> 154 <p>我是内容部分</p> 155 <p>我是内容部分</p> 156 <p>我是内容部分</p> 157 <p>我是内容部分</p> 158 <p>我是内容部分</p> 159 <p>我是内容部分</p> 160 <p>我是内容部分</p> 161 <p>我是内容部分</p> 162 <p>我是内容部分</p> 163 <p>我是内容部分</p> 164 <p>我是内容部分</p> 165 <p>我是内容部分</p> 166 <p>我是内容部分</p> 167 <p>我是内容部分</p> 168 <p>我是内容部分</p> 169 <p>我是内容部分</p> 170 <p>我是内容部分</p> 171 <p>我是内容部分</p> 172 <p>我是内容部分</p> 173 <p>我是内容部分</p> 174 <p>我是内容部分</p> 175 <p>我是内容部分</p> 176 <p>我是内容部分</p> 177 <p>我是内容部分</p> 178 <p>我是内容部分</p> 179 <p>我是内容部分</p> 180 <p>我是内容部分</p> 181 <p>我是底部</p> 182 </body> 183 </html>