2016/05/31 · HTML5 · Crash
原文出处: 小胡子哥(@Barret李靖)
我们知道,支撑页面在 webview 上良好运转的前提是具备一个高效并且稳定的 webview 容器,而容器的高效稳定不仅仅由容器提供方来保障,也需要容器使用者遵守一些基本准则,否则就有可能出现页面 Crash 的情况,这些准则是什么?什么样的上层代码会引起容器异常退出?这是本文需要阐述的内容。
Button ,可以使用 <button> <input> <a>。 <input> 中的不同类型,submit , radio , checkbox 。还能加上 icon ,split button 。
一、单选按钮确定提交是否可用
嘿嘿,今天学习到了事件,其实在C#中事件只需要我们触发即可实现,但是在javascript并不是这样的,在这里,事件是javascript与html的交互,就是文档或者浏览器窗口发生的一件特定的交互瞬间。其实从定义上面你很难想象吧,那么下面就简单的举例说下。
一.实现文字改变位置
<head>
<title></title>
<script>
function getDomText() { //该方法适用于让“链接”和“文字”交换位置显示在提示在提示框中
var pnode = document.getElementsByTagName("p"); //获取p元素,让他的子节点交换位置
var str = "";
str = document.getElementById("myspan").innerHTML; //获取id为myspan的元素的文本
str = document.getElementById("myid").innerHTML; //获取id为myid的元素的文本
alert(str);
}
</script>
</head>
<body>
<p>
<a id="myid" href="#">链接</a>
<span id="myspan">文字</span><br />
<input type="button" name="name" value="按钮" onclick="getDomText()" />
</p>
</body>
上面的button就实现了onclick单击事件,然后通过事件调用了一个方法使其文本信息改变位置。
二.替换文本信息
<script>
function replaceTextContent(){ //该方法适用于替换文本信息
var pnode = document.getElementById("myDom");
pnode.innerHTML = '<span>一句话</span> <a href="">一个链接</a>';//改变id为myDom的元素的文本信息
}
</script>
<body>
<p>
<input type="button" value="替换内容 " onclick=" replaceTextContent()" />
</p>
<p id="myDom">
<a href="#">一个链接</a> <span>一句话</span>
</p>
</body>
其实在这里是替换文本信息,不局限于是原来的文本信息交换位置,可以是任意内容的,嘿嘿。
三..改变图片大小
<script>
function updateImgAttribute() {
var imgmsg = document.getElementById("myimg"); //获取图片的元素
imgmsg.width = "500"; //图片存在属性width和height,然后设置即可
imgmsg.height = "500";
}
</script>
<body>
<p>
<input type="button" name="btn" value="修改属性" onclick="updateImgAttribute()" />
</p>
<img src="4.jpg" id="myimg" alt="加载中!" height="200" width="200"/>
</body>
改变图片大小其实是通过元素的属性设置即可,或者通过获取其元素,在使用setAttribute也可以实现的,这样是最简单的。
四.显示另一个元素的值
<script>
function getOthBtnValue(btn) { //接收一个元素节点
var pnode =btn.parentNode; //把传进来的这个元素作为p的子节点
for (var i = 0; i < pnode.childNodes.length; i ) {
if (pnode.childNodes[i] != btn && pnode.childNodes[i].nodeType == btn.nodeType) {
alert(pnode.childNodes[i].value); //if中的条件:当子节点满足不是btn而且子节点的类型和btn一样
}
}
}
</script>
<body>
<p>
<input type="button" name="btn1" value="显示btn2的值 " onclick="getOthBtnValue(this)"/> <!--this在这里是指当前元素-->
<input type="button" name="btn1" value="显示btn1的值 " onclick="getOthBtnValue(this)"/>
</p>
</body>
在这里写if'语句中的条件时间可能不太容易理解,但是我们可以寻找下pnode.childNodes的节点的个数即可知道我们的条件为什么要这样写,子节点的个数输出的是5,包括空白的文本节点等,所以在显示时间需要注意的。
五.克隆图片
<script>
function cloneImg() {
var imgmsg = document.getElementById("myimg");
var newimg = imgmsg.cloneNode(true); //在cloneNode中需要一个bool类型的参数,true表示强度
document.getElementById("myid").appendChild(newimg); //获取p元素,然后再p元素中添加新克隆出来的元素
}
</script>
<body>
<p id="myid">
<input type="button" name="btn" value="克隆图片" onclick="cloneImg()"/>
<br />
<img src="4.jpg" id="myimg" alt="加载中" height="200" width="200"/>
</p>
</body>
其实克隆图片,从名字上面的方法的名字cloneNode就知道了实现的功能,可以点击按钮克隆多张图片。
六.隐藏图片
<script>
function showOrHide() {
var myimg = document.getElementById("myimg");
var displaymsg = myimg.style.display; //display是用来显示或者隐藏
//alert(displaymsg);
if (displaymsg != 'none') { //当参数为none是为显示
myimg.style.display = 'none';
}
else {
myimg.style.display = ''; //当为空时间为隐藏
}
}
</script>
<body>
<p id="myid">
<input type="button" name="btn" value="隐藏图片" onclick="showOrHide()"/>
<br />
<img src="4.jpg" id="myimg" alt="加载中" height="200" width="200"/>
</p>
</body>
之前没有介绍display的使用方法,它应该是style的属性,在这里需要注意的是它的参数,仅仅存在none和空。
七.文本信息排序
<script>
function changeSeriation() {
var ulnode = document.getElementsByTagName("ul")[0];//获取页面的ul元素, 在这里[0]是代表第一个ul
if (ulnode.hasChildNodes) { //判断是否包含子节点
var length = ulnode.childNodes.length; //获取子节点的长度
var str = [];
for (var i = 0; i < length; i ) {
str[i] = ulnode.childNodes[0]; //每次获取的子节点元素放在最前面
ulnode.removeChild(ulnode.childNodes[0]); //清除当前的子节点元素,按照上面的顺序依次输出
}
for (var i = length-1; i >=0; i--) {
ulnode.appendChild(str[i]); //这个是相反的,每次输出的排在最后一个
}
}
}
</script>
<body>
<ul>
<li >item1</li>
<li >item2</li>
<li >item3</li>
<li >item4</li>
<li >item5</li>
</ul>
<input type="button" name="btn" value="交换顺序 " onclick="changeSeriation()"/>
</body>
在这里理解起来可能刚接触不太容易理解,但是我感觉之前学习了pop方法和push方法,其实这个就是那个理解起来相似,但是最后的显示的信息还是打不同的,仅限于理解上面,
八.form表单
<script>
window.onload = function () {
document.getElementsByName("btn").onclick = function(e){ // 在这使用一个匿名的方法实现单击事件
//function getAllValue(e) {
var formmsg = document.forms[0]; //获取第一个form元素
var formelements = formmsg.elements; //获取form表单中的元素
//var str = "";
var count=0;
for (var i = 0; i < formelements.length; i ) {
//str[i] = formelements[i].name = "text";
//alert(formelements[i].name);
if (formelements[i].getAttribute("type") == "text") {
count ;
}
alert(count);
}
}
}
</script>
<body>
<form action="/" method="post">
文本框:<input type="text" name="mytext" value="文本框 " /><br />
单选框:<input type="radio" name="myradio" value="单选框1" /><input type="radio" name="myradio" value="单选框2" /><br />
下拉列表:
<select name="myselect">
<option value="下拉列表" >==请选择==
</option>
<option value="下拉列表1">第一项</option>
<option value="下拉列表2">第二项</option>
</select>
<br />
<input type="button" name="name" id="btn" value="得到所有控件的value" onclick="" />
</form>
</body>
在这里需要注意的获取form表单中的元素的value的使用和name的使用,很可惜的是我没有写出来,不知道哪出了问题,希望写出来能够改正。
九.通过一个按钮触发事件获取另一个按钮触发事件
<script>
function changeValue() {
var mybtnmsg = document.getElementById("btnid").click(); //元素存在一个单击事件
}
</script>
<body>
<p>
<input type="button" value="触发按钮的事件 " onclick="changeValue()" />
<input type="button" id="btnid" value="按钮提示 " onclick="alert('我被触发了')" /></p>
</body>
十.创建新元素
<script>
function createNewElement() {
document.getElementById("p1").innerHTML = "<span>我是新添加进来的文本1</span>"; //直接通过innerHTML添加文本元素
var newspanelement = createNewElement("span"); //也可通过创建元素添加新的文本,这里创建的是span标签
newspanelement.appendChild(document.createTextNode("我是新添加进来的文本2"));//添加文本
var pnode = document.getElementById("p2"); //添加id为p2的p标签的的子节点span
pnode.appendChild(newspanelement); //把span的所有元素添加到p标签中
}
</script>
<body>
<p>
<input type="button" name="name" value="创建新元素 " onclick="createNewElement()" /></p>
<p id="p1"></p>
<p id="p2"></p>
</body>
十一.通过页面加载事件打开一个网页
<script>
//Window.onload() =function(){ //页面加载事件
// document.body.onclick = function () { //元素可以实现onclick事件
// alert(this.innerHTML)
// }
//}
window.navigate("
window.location.href = "
</script>
<body>
<body style="background-color:red">
<p id="p">第一个DOM</p>
</body>
十二.onfocus与onblur的使用
<script>
window.onload = function () {
document.getElementById("txtname").onfocus = function () { //给文本框设置一默认值,当鼠标进入时间显示空白
this.value = '';
};
document.getElementById("txtname").onblur = function () { //当鼠标离开时间仍然显示默认值
this.value = '用户名';
}
}
</script>
<body>
<form action="/" method="post">
<table>
<tr><td>UserName</td><td>
<input type="text" id="txtname" name="txtname" value="用户名 " /></td></tr>
<tr>
<td>UserPwd</td>
<td>
<input type="password" name="txtpwd" value="密码" />
</td>
</tr>
<tr>
<td>
<input type="button" name="name" value="登录 " /></td>
<td>
<input type="reset" name="name" value="充值 " /></td>
</tr>
</table>
</form>
</body>
嘿嘿,今天学习到了事件,其实在C#中事件只需要我们触发即可实现,但是在javascript并不是这样的,在这里...
下图是 H5 Crash 的大致流程图:
由于前端没办法捕捉到页面 Crash 的状态和堆栈,但是 H5 页面上发生的错误会传递到 Java 和更底层的 Native 直到容器异常退出,在退出的那一刻,容器会将堆栈写入到日志中,当下次打开容器时(也可能是定时上报)就会上报这些堆栈信息。
Autoconplete 为校准 文本 <input>提供了一个文本选择的菜单。当浏览者开始在<input>中输入时,会自动匹配输入的字符,显示建议。 允许通过箭头按键导航,Enter键选中,Esc键关闭菜单。当箭头键被用来导航时,每个建议都会出现在<input>中。如果Esc用来关闭导航,<input>的 value 会回复到用户输入的状态。
<input id="a" type="radio" name="a" onclick="check()"/>
测试代码 仓库地址:
git clone ; cd demo;
1
2
|
git clone https://github.com/barretlee/h5crash.git;
cd demo;
|
注意: 代码需要在 Webview 容器中测试,PC 浏览器下不会出现异常。
H5 Crash 的原因不太明显,但是从经验上判断和摸索,大致归类为以下三种:
1. 内存问题
XHTML
<script> var Closure = function() { var _cache = []; var cache = 0; var add = function(size) { cache = size; size = size * 1024 * 1024; _cache.push(new Array(size).join('x')); refresh(); }; var refresh = function() { r.innerHTML = '内存消耗: ' cache 'M'; }; return { cache: cache 'M', add: add, refresh: refresh } }; var closure = Closure(); </script> <button onclick="closure.add(1)">增加 1M 内存消耗</button> <button onclick="closure.add(10)">增加 10M 内存消耗</button> <button onclick="closure.add(20)">增加 20M 内存消耗</button> <button onclick="closure.add(50)">增加 50M 内存消耗</button> <button onclick="closure.add(100)">增加 100M 内存消耗</button> <div id="r">内存消耗:0 M</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
<script>
var Closure = function() {
var _cache = [];
var cache = 0;
var add = function(size) {
cache = size;
size = size * 1024 * 1024;
_cache.push(new Array(size).join('x'));
refresh();
};
var refresh = function() {
r.innerHTML = '内存消耗: ' cache 'M';
};
return {
cache: cache 'M',
add: add,
refresh: refresh
}
};
var closure = Closure();
</script>
<button onclick="closure.add(1)">增加 1M 内存消耗</button>
<button onclick="closure.add(10)">增加 10M 内存消耗</button>
<button onclick="closure.add(20)">增加 20M 内存消耗</button>
<button onclick="closure.add(50)">增加 50M 内存消耗</button>
<button onclick="closure.add(100)">增加 100M 内存消耗</button>
<div id="r">内存消耗:0 M</div>
|
存在的干扰:这种测试存在比较多的干扰,比如设备类型、系统类型(iOS/Android)、和设备内存运行状态等。
2. Layers 数问题
Layers 数的获取比较麻烦,Chrome Driver 没有提供该数据的接口,目前也没有比较好的办法拿到这个数据。
XHTML
<style>.transform { transform: translateZ(0); } .animation { width:100px; height:100px; background:red; position:relative; animation:move 5s infinite; } @keyframes move { from {left:0px;} to {left:200px;} } </style> <script> var Layer = function() { function getType() { return document.querySelector('input:checked').value; }; return { createOne: function(index) { var div = document.createElement('div'); div.appendChild(document.createTextNode(index)); switch(getType()) { case 'opacity': div.style.cssText = "opacity:" (index / 1000); break; case 'transform': div.className = 'transform'; break; case 'animation': div.className = 'animation'; break; case 'zindex': div.style.cssText = "position:relative; z-index:" index; break; } document.body.appendChild(div); }, create: function(num) { [].slice.call(document.querySelectorAll('div')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.createOne(num); } } } }; var layer = Layer(); </script> <strong>层类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 创建层</span></label></li> <li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创建层</span></label></li> <li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创建层</span></label></li> <li><label><input type="radio" name="type" value="zindex"> <span>通过绝对定位分层</span></label></li> </ul> <button onclick="layer.create(1)">创建 1 个层</button> <button onclick="layer.create(10)">创建 10 个层</button> <button onclick="layer.create(20)">创建 20 个层</button> <button onclick="layer.create(50)">创建 50 个层</button> <button onclick="layer.create(100)">创建 100 个层</button> <button onclick="layer.create(200)">创建 200 个层</button> <button onclick="layer.create(500)">创建 500 个层</button> <button onclick="layer.create(1000)">创建 1000 个层</button> <button onclick="layer.create(2000)">创建 2000 个层</button> <button onclick="layer.create(5000)">创建 5000 个层</button> <button onclick="layer.create(10000)">创建 10000 个层</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
<style>.transform {
transform: translateZ(0);
}
.animation {
width:100px;
height:100px;
background:red;
position:relative;
animation:move 5s infinite;
}
@keyframes move {
from {left:0px;}
to {left:200px;}
}
</style>
<script>
var Layer = function() {
function getType() {
return document.querySelector('input:checked').value;
};
return {
createOne: function(index) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(index));
switch(getType()) {
case 'opacity':
div.style.cssText = "opacity:" (index / 1000);
break;
case 'transform':
div.className = 'transform';
break;
case 'animation':
div.className = 'animation';
break;
case 'zindex':
div.style.cssText = "position:relative; z-index:" index;
break;
}
document.body.appendChild(div);
},
create: function(num) {
[].slice.call(document.querySelectorAll('div')).forEach(function(item) {
item.parentNode && item.parentNode.removeChild(item);
});
while(num--) {
this.createOne(num);
}
}
}
};
var layer = Layer();
</script>
<strong>层类型: </strong>
<ul>
<li><label><input type="radio" checked name="type" value="opacity"> <span>通过 opacity 创建层</span></label></li>
<li><label><input type="radio" name="type" value="transform"> <span>通过 transforms 创建层</span></label></li>
<li><label><input type="radio" name="type" value="animation"> <span>通过 animation 创建层</span></label></li>
<li><label><input type="radio" name="type" value="zindex"> <span>通过绝对定位分层</span></label></li>
</ul>
<button onclick="layer.create(1)">创建 1 个层</button>
<button onclick="layer.create(10)">创建 10 个层</button>
<button onclick="layer.create(20)">创建 20 个层</button>
<button onclick="layer.create(50)">创建 50 个层</button>
<button onclick="layer.create(100)">创建 100 个层</button>
<button onclick="layer.create(200)">创建 200 个层</button>
<button onclick="layer.create(500)">创建 500 个层</button>
<button onclick="layer.create(1000)">创建 1000 个层</button>
<button onclick="layer.create(2000)">创建 2000 个层</button>
<button onclick="layer.create(5000)">创建 5000 个层</button>
<button onclick="layer.create(10000)">创建 10000 个层</button>
|
3. 并发过多问题
XHTML
<script> var Request = function() { function getType() { return document.querySelector('input:checked').value; }; function getResource() { var type = getType(); var resource = { fetch: '/', xhr: '/', script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js', css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css' }; return resource[type]; }; return { emitOne: function() { var url = getResource() "?_t=" (new Date * 1 Math.random()); switch(getType()) { case 'fetch': return fetch('/'); case 'xhr': with(new XMLHttpRequest) { open('GET', url); send(); } return; case 'script': var s = document.createElement('script'); s.src = url; document.body.appendChild(s); return; case 'css': var s = document.createElement('link'); s.href = url; document.body.appendChild(s); } }, emit: function(num) { [].slice.call(document.querySelectorAll('script,link')).forEach(function(item) { item.parentNode && item.parentNode.removeChild(item); }); while(num--) { this.emitOne(); } } } }; var request = Request(); </script> <strong>请求类型: </strong> <ul> <li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送请求</span></label></li> <li><label><input type="radio" name="type" value="xhr"> <span>使用 XHR 发送请求</span></label></li> <li><label><input type="radio" name="type" value="script"> <span>并发请求脚本资源</span></label></li> <li><label><input type="radio" name="type" value="css"> <span>并发请求样式资源</span></label></li> </ul> <button onclick="request.emit(1)">并发 1 个请求</button> <button onclick="request.emit(10)">并发 10 个请求</button> <button onclick="request.emit(20)">并发 20 个请求</button> <button onclick="request.emit(50)">并发 50 个请求</button> <button onclick="request.emit(100)">并发 100 个请求</button> <button onclick="request.emit(500)">并发 500 个请求</button> <button onclick="request.emit(1000)">并发 1000 个请求</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
<script>
var Request = function() {
function getType() {
return document.querySelector('input:checked').value;
};
function getResource() {
var type = getType();
var resource = {
fetch: '/',
xhr: '/',
script: '//g.alicdn.com/sd/data_sufei/1.5.1/aplus/index.js',
css: '//g.alicdn.com/kg/global-util/1.0.3/index-min.css'
};
return resource[type];
};
return {
emitOne: function() {
var url = getResource() "?_t=" (new Date * 1 Math.random());
switch(getType()) {
case 'fetch':
return fetch('/');
case 'xhr':
with(new XMLHttpRequest) {
open('GET', url);
send();
}
return;
case 'script':
var s = document.createElement('script');
s.src = url;
document.body.appendChild(s);
return;
case 'css':
var s = document.createElement('link');
s.href = url;
document.body.appendChild(s);
}
},
emit: function(num) {
[].slice.call(document.querySelectorAll('script,link')).forEach(function(item) {
item.parentNode && item.parentNode.removeChild(item);
});
while(num--) {
this.emitOne();
}
}
}
};
var request = Request();
</script>
<strong>请求类型: </strong>
<ul>
<li><label><input type="radio" checked name="type" value="fetch"> <span>使用 Fetch 发送请求</span></label></li>
<li><label><input type="radio" name="type" value="xhr"> <span>使用 XHR 发送请求</span></label></li>
<li><label><input type="radio" name="type" value="script"> <span>并发请求脚本资源</span></label></li>
<li><label><input type="radio" name="type" value="css"> <span>并发请求样式资源</span></label></li>
</ul>
<button onclick="request.emit(1)">并发 1 个请求</button>
<button onclick="request.emit(10)">并发 10 个请求</button>
<button onclick="request.emit(20)">并发 20 个请求</button>
<button onclick="request.emit(50)">并发 50 个请求</button>
<button onclick="request.emit(100)">并发 100 个请求</button>
<button onclick="request.emit(500)">并发 500 个请求</button>
<button onclick="request.emit(1000)">并发 1000 个请求</button>
|
<label for="a">同意</label>
测试结果:
以上临界值还可以继续精确。
当使用<a>或 <button> 元素创建 button ,一个<span>元素会被自动创建,并嵌入其中。这个<span>会包含button 的 label text.
1 <a href="" id="myButton">A link button</a>2 <button id="myButton2"> button </button>3 <input id="myButton3" value="An input button">4 $(function(){ 5 $("#myButton").button(); 6 $("#myButton2").button(); 7 $("#myButton3").button(); 8 });
<input> 元素不允许包含子元素,所以<span>不会在使用<input>创建button的时候出现。
<a>元素通过制定 href 属性,会简单地将浏览者送往新的页面或anchor。
使用 <button> 元素同上,只是不需要添加 href属性。使用<input>元素也很简单,它使用 value属性设置 button 的文本。
<input id="b" type="radio" name="a" onclick="check()" />
本文主要是对 H5 Crash 做了一个预研,测试可能存在诸多误差,测试方法也需要改进,不过沿着这些的思路考究会比较容易找到结论。
后续会给出比较有意义的边界数据以及探测工具。
1 赞 3 收藏 评论
Option | Default Value | Used to… |
disabled | false | 禁用button实例 |
icons | {primary:null,secondary:null} | 设置button实例的icons |
label | value属性或下层元素的文本 | 设置button实例的text |
text | true | 当使用icon-only时,隐藏button的 text |
label选项配置的值会覆盖<a>元素的文本。
<label for="b">不同意</label><br />
button在大多数情况下顶多有另个icon。当一个<a>或<button>元素被用来创建button,我们可以使用icons配置选项来为其指定一个或两个icons。
1 var buttonOpts={ 2 icons:{ 3 primary:"ui-icon-disk", 4 secondary:"ui-icon-triangle-1-s" 5 }, 6 text:false 7 };
icons属性接受一个对象,它包含最多两个键,primary和secondary。这些选项的值可以是 jquery.ui.theme.css 文件中的任何 ui-icon- classes。icons使用<span>元素添加到控件中。
<input type="button" name="d" id="c" value="提交" disabled="disabled"/>
尽管子元素<span>可以用来显示指定的icon,但是我们不能为<input>元素添加子元素。我们可以使用额外的容器,包含<span>元素和一些自定义的CSS,简单地为<input>添加我们自己的icons。
1 <style> 2 .iconic-input { display:inline-block; position:relative;} 3 .ui-icon { z-index:2;} 4 .iconic-input input { border:none; margin:0;} 5 </style> 6 </script> 7 <div class="iconic-input ui-button-text-icons ui-state-default ui-corner-all"> 8 <span class="ui-button-icon-primary ui-icon ui-icon-disk"></span> 9 <input id="myButton" type="button" value="Input icons" class="ui-button-text">10 <span class="ui-button-icon-secondary ui-icon ui-icon-triangle-1-s"></span>11 </div>
在较老版本的IE中不支持display:inline-block样式。为了防止button占满它的容器,我们需要将其浮动,设置期望宽度。
两端的icons 没有 hover states,这是因为控件为<input>应用了必须的 classnames,没有给我们自定义的容器。我们可以为icon添加必要的行为。
1 $("#myButton").button().hover(function(){ 2 $(this).parent().addClass("ui-state-hover"); 3 },function(){ 4 $(this).parent().removeClass("ui-state-hover"); 5 });
为icon添加悬停效果。多数情况下,使用<a> 和<button>元素创建 button 会更简单,更有效率。
<script>
使用<a>元素创建的button,会通过href跳转。在 <form>中使用 <button>或<input>元素,创建带有 type 属性的设置,会提交表单数据。
button控件只暴露了一个事件 create 事件。当 button 实例初始化创建后被触发。
我们也许想要收集一些注册信息,并使用 button 发送信息到服务器。
1 <form method="post" action="aa.php"> 2 <label for="name">Name: 3 <input type="text" id="name" name="name"> 4 </label> 5 <label for="email">Email: 6 <input type="text" id="email" name="email"> 7 </label> 8 <button type="submit" id="myButton">Register</button> 9 </form>10 11 $(function(){ 12 $("#myButton").button().click(function(e){ 13 e.preventDefault(); 14 var form=$("form"), 15 formData={ 16 name:form.find("#name").val(), 17 email:form.find("#email").val() 18 }; 19 console.log(formData); 20 $.post("aa.php",formData,function(){ 21 $("#myButton").button("option","disabled",true); 22 form.find("label").remove(); 23 $("<label />").text("Thanks for registering!").prependTo(form); 24 }) 25 }); 26 });
function check(){
button控件也可以用来结合 radio buttons 和 checkboxes 。button是 jQuery UI 控件中,独一无二的,有两个方法的控件,它还有一个 buttonset() 方法,用来创建一组由 radio buttons 和 chekboxes 组成的button。
var yes=document.getElementById("a");
1 <div id="buttons"> 2 <h2>Programming Languages</h2> 3 <p>Select all languages you know:</p> 4 <label for="js">JavaScript</label> 5 <input id="js" type="checkbox"> 6 <label for="py">Python</label> 7 <input id="py" type="checkbox"> 8 <label for="cSharp">C#</label> 9 <input id="cSharp" type="checkbox">10 <label for="jv">Java</label>11 <input id="jv" type="checkbox">12 </div>13 $(function(){ 14 $("#buttons").buttonset(); 15 });
当一个checkbox被选中,它会被应用 selected 状态。在HTML5中,使用关联的<label>元素构建form时,不允许使用button 控件。
var no=document.getElementById("b");
与checkbox 的区别仅仅在行为上,所有的<input>都必须有 name 属性。
1 <div id="buttons"> 2 <h2>Programming Languages</h2> 3 <p>Select all languages you know:</p> 4 <label for="js">JavaScript</label> 5 <input id="js" type="radio" name="lang"> 6 <label for="py">Python</label> 7 <input id="py" type="radio" name="lang"> 8 <label for="cSharp">C#</label> 9 <input id="cSharp" type="radio" name="lang">10 <label for="jv">Java</label>11 <input id="jv" type="radio" name="lang">12 </div>
var btn=document.getElementById("c");
除了 destroy , disable, enable ,widget , option 这些公共的方法,button 控件只暴露了一个自定义的方法,refresh方法。它用来以代码的方式改变checkbox 和 raido 的状态。
1 <div id="buttons"> 2 <h2>Programming Languages</h2> 3 <p>Select all languages you know:</p> 4 <label for="js">JavaScript</label> 5 <input id="js" type="checkbox"> 6 <label for="py">Python</label> 7 <input id="py" type="checkbox"> 8 <label for="cSharp">C#</label> 9 <input id="cSharp" type="checkbox">10 <label for="jv">Java</label>11 <input id="jv" type="checkbox">12 </div>13 <br>14 <button type="button" id="select">Select all</button>15 <button type="button" id="deselect">Deselect all</button>16 17 $(function(){ 18 $("#buttons").buttonset(); 19 $("#select").button().click(function(){ 20 $("#buttons").find("input").attr("checked",true).button("refresh"); 21 }); 22 $("#deselect").button().click(function(){ 23 $("#buttons").find("input").attr("checked",false).button("refresh"); 24 }); 25 });
当 Select all button被点击,我们设置 cheked 属性为 true 。这会检查底层并且隐藏的check boxes,单不会对作为button显示的<label>元素做任何事情。更新这些button 的状态,让他们显示被选中,需要调用 refresh 方法。
// if(yes.getAttribute("checked")) 这个行不通,记住下面这个yes.check
1 <label>Enter your city:</label> 2 <input id="city"> 3 4 $(function(){ 5 var autoOpts = { 6 source: [ 7 "Aberdeen", "Armagh", "Bangor", "Bath", "Canterbury", 8 "Cardiff", 9 "Derby", "Dundee", "Edinburgh", "Exeter", "Glasgow", 10 "Gloucester", 11 "Hereford", "Inverness", "Leeds", "London", "Manchester", 12 "Norwich", 13 "Newport", "Oxford", "Plymouth", "Preston", "Ripon", 14 "Southampton", 15 "Swansea", "Truro", "Wakefield", "Winchester", "York" 16 ] 17 }; 18 $("#city").autocomplete(autoOpts); 19 });
在配置对象中,使用了 source 选项,指定了一个本地字符串数组。source选项时强制性地,必须被定义。
if(yes.checked)
1 var autoOpts = { 2 source: [ 3 { value: "AB", label: "Aberdeen" }, 4 { value: "AR", label: "Armagh" } 5 ] 6 }
每个对象有两个keys : value 和 label 。value的值是选中的值,label 用来显示在建议的选择列表中。如果某一个对象只有一个 key,则它既是value 也是 label。
{
Option | Default Value | Used to… |
appendTo | “body” | 指定将控件添加到哪个元素上 |
autofocus | false | 当显示建议列表时,focus第一个建议 |
delay | 300 | 指定浏览者输入字符后,延迟显示建议列表的milliseconds数 |
disabled | false | 禁用控件 |
minLength | 1 | 指定在显示建议列表前,访问者需要输入的最短字符长度 |
position | {my:”left top”,at:”left bottom”,collision:”none”} | 指定建议列表应该显示在相对<input>的位置。它和 position 功能接受一样的值 |
source | 指定用来填充建议列表的数据源。这个选项是强制和必须被配置的。它接受一个数组,字符串,或一个函数。 |
btn.removeAttribute("disabled");
设置 minLength 选项为高于默认值1 的数,可以使建议列表变窄。在处理大量远程数据源时,这很重要,可以缩小远程数据源返回的数据。
}
默认地,建议列表被附加到页面的<body>,position 功能用来定义列表的位置,所以他能显示到关联的<input>上。我们可以使用 appendTo 选项,改变,并制定该元素。
1 appendTo: "#container"
这可以使创建出来的 <ul> 被附加到 container上,而不是body上。
if(no.checked){
Evnet | Fired when… |
change | 列表中的一个建议被选中。这个事件会被触发,一旦列表已经关闭,并且<input>已经社区focus |
close | 建议列表已经关闭 |
create | 一个控件实例被创建 |
focus | 键盘被用来focus一个建议 |
open | 建议目录被显示 |
search | 请求将要显示的建议 |
select | 一个建议被选中 |
当我们使用一个对象数组作为数据源,对象中有超过 label 和 value 属性之外的附加数据时,select事件此时很有用。
1 <label>Enter your city:</label> 2 <input id="city"> 3 $(function(){ 4 var autoOpts = { 5 source: [ 6 { value: "AB", label: "Aberdeen", population: 212125 }, 7 { value: "AR", label: "Armagh", population: 54263 } 8 ], 9 select:function(e,ui){ 10 if($("#pop").length){ 11 $("#pop").text(ui.item.label "'s population is : " ui.item.population); 12 } 13 else{ 14 $("<p></p>").attr("id","pop").text(ui.item.label "'s population is : " ui.item.population).insertAfter("#city"); 15 } 16 } 17 }; 18 $("#city").autocomplete(autoOpts);
我们使用select 事件,来获得 label 和 我们额外的属性。
btn.setAttribute("disabled","disabled");
Method | Used to… |
close | 关闭建议目录 |
search | 从数据源请求建议列表,指定 search term 作为可选参数 |
}
}
1 var autoOpts = { 2 source: "" 3 };
因此,当使用一个字符串作为数据源选项的值时,传回来的数据应该是一个对象数组。每个对象包含至少一个key ,label。数据可以通过 cross-domain 请求获得 JSON 或 JSONP 。控件会自动在输入的字符后,添加查询字符串 term= 。
当我们从我们不能控制的公共网络服务器获取数据时,数据格式也许不正确。我们需要使用一个函数作为数据源选项的值,手工转换数据。
</script>
我们使用函数请求数据,处理数据,然后将其传给控件。
1 <div id="formWrap"> 2 <form id="messageForm" action="#" method="post"> 3 <fieldset> 4 <legend>New message form</legend> 5 <span>New message</span> 6 <div class="inner-form ui-helper-clearfix"> 7 <label for="toList">To:</label> 8 <div id="toList" class="ui-helper-clearfix"> 9 <input id="to" type="text"> 10 <input id="emails" type="hidden"> 11 </div> 12 <label for="message">Message:</label> 13 <textarea id="message" name="message" rows="2" cols="50"> 14 </textarea> 15 </div> 16 <div class="button ui-helper-clearfix"> 17 <button type="submit">Send</button> 18 <a href="#" title="Cancel">Cancel</a> 19 20 </div> 21 </fieldset> 22 </form> 23 </div> 24 <input id="country"> 25 <script src="jq/jquery-1.4.4.js"></script> 26 <script src="jq/jquery-ui-1.8.9.js"></script> 27 <script src="jq/jquery-ui-i18n.min-1.8.9.js"></script> 28 <script> 29 var autoOpts={ 30 source:function(req,resp){ 31 $.getJSON("", 32 req, 33 function(data){ 34 var suggestions=[]; 35 $.each(data,function(i,val){ 36 var obj={}; 37 obj.value=val.name; 38 obj.email=val.email; 39 suggestions.push(obj); 40 }); 41 resp(suggestions); 42 }); 43 }, 44 select:function(e,ui){ 45 var emailList=$("#emails"), 46 emails=emailList.val().split(","),//split分割出来的是数组 47 span=$("<span>" ui.item.value "</span>"), 48 a=$("<a href='#' class='remove' title='Remove'>x</a>").appendTo(span); 49 span.insertBefore("#to"); 50 emails.push(ui.item.email); 51 emailList.val(emails.join(",")); 52 $("#to").remove(); 53 $("<input id='to'>").insertBefore("#emails").autocomplete(autoOpts); 54 } 55 }; 56 $("#to").autocomplete(autoOpts); 57 $("#toList").click(function(){ 58 $("#to").focus(); 59 }); 60 //delegate() 方法为指定的元素(属于被选元素的一个或多个子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。 61 //使用 delegate() 方法的事件处理程序适用于当前或未来的元素(比如由脚本创建的新元素)。 62 $("#toList").delegate("a","click",function(){ 63 var email=$(this).parent().data("email"), 64 65 emails=$(this).val().split(","); 66 $(this).parent().remove(); 67 $.each(emails,function(i,val){ 68 if(val===email){ 69 emails.splice(i,1);//从数组中移除某些元素, StartIndex,Count 70 } 71 }); 72 73 $("#emails").val(emails); 74 }); 75 </script> 76 <style> 77 #formWrap{ 78 padding:10px;position:absolute;background-color:#000; 79 background:rgba(82,82,82,0.7);border-radius:8px; 80 font:bold 14px "lucida grande",tahoma,verdana,arial,sans-serif; 81 } 82 #formWrap a:hover{color:#ff0000;} 83 #messageForm{ 84 width:467px;border:1px solid #666;background-color:#eee; 85 } 86 #messageForm fieldset{ 87 padding:0;margin:0;position:relative;border:none #CCC; 88 background-color:#fff; 89 } 90 #messageForm legend{ 91 visibility:hidden;height:0; 92 } 93 #messageForm span{ 94 display:block;width:467p;padding:10px 0;background-color:#6D84B4; 95 border:#3B5998 #3B5998;color:#fff;text-indent:20px; 96 } 97 .inner-form{padding:20px;} 98 #toList{ 99 width:349px;min-height:27px;padding:3px 3px 0 3px;100 border:1px solid #6D84B4; mairgin-bottom:8px;float:left;101 background-color:#fff;cursor:text;102 }103 #messageForm #to{104 width:10px;padding:0;position:relative;top:4px;float:left;105 border:none;106 }107 #messageForm input,#messageForm textarea{108 display:block;width:349px;padding:3px;border:1px solid #6D84B4;109 float:left;outline:none;110 }111 #messageForm textarea{resize:vertical;}112 #messageForm label{113 width:60px;margin:7px 10px 0 0;float:left;corlor:#666;114 font-size:11px;text-align:right;115 }116 .buttons{padding:10px 20px;background-color:#f2f2f2;}117 .button a{118 margin:3px 10px 0 0;float:right;font-size:11px;color:#6D84B4;119 }120 .buttons button{float:right}121 #toList span{122 width:auto;margin:0 3px 3px 0;padding:3px 20px 4px 8px;123 border:1px solid #9DACCC; border-radius:3px;position:relative;124 float:left;font-size:11px;font-weight:normal;text-indent:0;125 background-color:#E2E6F0;color:#1C2A47;126 }127 #toList span a{128 position:absolute;right:7px;top:1px;color:#666;129 font-weight:bold;font-size:12px;text-decoration:none;130 }131 .ui-menu .ui-menu-item{132 white-space:nowrap;padding:0 10px 0 0;133 }134 </style>
1 jsonp1376905372318([{"name":"Admiral Ackbar","email":"akbar@alliance.org"},{"name":"Admiral Ozzel","email":"ozzy@empire.org"}])
我们使用<div>,设置它的样式,是它看起来像一个 <input>,在它里面使用一个无样式的真实的<input> 。这个真实的<input>是必须的,这样浏览者能输入,autocomplete与其关联。我们使用<div>元素师因为我们不能在<input>中插入<span>元素。我们也需要一个隐藏的<input>,它被用来存储实际的 e-mail 地址。
在脚本里,我们使用一个函数作为数据源选项的值。每次<input>里的文本改变,这个函数就会被调用。这个函数接受两个参数,第一个是 req ,包含一个叫做 term 的属性,是输入到<input>里的字符。第二个, resp ,是一个回调函数,我们在显示建议目录时会调用的。
这个函数中,我们首先做JSON 请求。建一个空数组,将请求到的每个 json 对象中的 item。
我们使用 jQuery 的 each() 方法处理每一个返回的item。我们创建一个新的对象,给它加上value和email属性。控件会显示value属性。
每个新创建的对象都被加入建议数组,这个数组会传给resp的回调函数。
我们使用 select 配置选项,来处理不标准的远程数据。这个函数接受两个参数,event 对象 和一个 ui 对象。
在这个函数中,我们首先缓存隐藏的<input>的选择器,并通过它的吻遍,创建一个数组存储分隔后的e-mail地址。
我们然后创建一个<span>元素,并通过 ui.item.value 设置它的文本为被选择的值。偶们也创建了一个 <a> 元素,将它附加到这个新的 <span>上。这个元素用来移除 收件人列表中的<span>。我们也在 <span> 上添加了e-mail 地址作为 data,所以每个收件人名字都能关联到它的 e-mail 地址。
然后我们将这个<span>元素插入到 <div> 元素,对它使用样式,使它看起来像一个 <input> ,然后,通过 ui.item.email 将它的 email 属性添加到 emails 数组,作为 隐藏的 <input> 的值。
显示效果如下:
默认地,autocomplete 控件会仅仅播放每个建议的文本。这里有一个扩展插件,可以帮助我们在建议列表中显示html,来高亮用户输入的字符。
1 <label for"city">Enter a city</label> 2 <input id="city"> 3 4 <script src="jq/jquery.ui.autocomplete.html.js"></script> 5 6 $(function(){ 7 var data = [ 8 { value: "Aberdeen", label: "Aberdeen" }, 9 { value: "York", label: "York" } 10 ], 11 autoOpts={ 12 html:true, 13 source:function(req,resp){ 14 var suggestions=[], 15 regEx=new RegExp("^" req.term,"i"); 16 $.each(data,function(i,val){ 17 if(val.label.match(regEx)){ 18 var obj={}; 19 obj.value=val.value; 20 obj.label=val.label.replace(regEx,"<span>" req.term "</span>"); 21 suggestions.push(obj); 22 } 23 }); 24 resp(suggestions); 25 } 26 }; 27 $("#city").autocomplete(autoOpts); 28 }); 29 30 <style>31 span { color:red !important;}32 </style>
在我们的配置对象中,我们指定一个新选项 html 被设为 true ,用来结合 html 扩展。
我们创建一个新的空数组,定义了一个新的正则表达式对象,它会在毫无知觉的情况下,匹配用户输入的字符。
未点击前,提交按钮不可用;在点击同意之后后提交按钮可用。
二、倒计时:
Eg1:
<script>
function shijian(){
alert("哈哈");
}
window.setTimeout("shijian()",2000);
</script>
注:setTimeoout属性是指延长多少时间发生的事,以毫秒计数。
此处显示效果: 哈哈界面就会在刷新页面2000毫秒后弹出。
Eg2:
<script>
function shijian(){
alert("哈哈");
}
for(i=0;i<4;i ){
window.setTimeout("shijian()",i*2000);
}
</script>
显示效果:利用for循环控制显示次数,即每隔2秒显示一次哈哈,共显示4次。
Eg3:
<span id="time">8</span>
<input id="btn" name="next" type="button" disabled="disabled" value="下一步" />
<script>
function shijian(){
var s=document.getElementById("time").innerText;
s=parseInt(s); -------变量转换成整数。
if(s<=0){ ------当秒数小于0时,“下一步”按钮生效。
document.getElementById("btn").removeAttribute("disabled");
}
else{
s--; -------时间每隔2秒减1
document.getElementById("time").innerText=s;
}
}
for(i=0;i<=9;i ){ -------设置循环次数和时间间隔
window.setTimeout("shijian()",i*2000);
}
</script>
注:次数的设置,可能会因为少一次导致按钮不可用。
三、向列表内添加数据:
1、利用<ol>列表
<body>
<ol id="ol1"> -------定义一个有序列表
<li>开始值</li>
</ol>
<input type="text" id="txt"/> -----------输出一个文本框
<input type="button" value="添加" id="btn" onclick="add()"/>
-----------设置一个添加按钮,并创建一个点击事件
<script>
function add()
{
var x = document.getElementById("txt").value; ---将文本内容定义给x
var y = document.getElementById("ol1"); -------将列表内容定义给y
y.innerHTML ="<li>" x "</li>"; --------将x值添加到y中
}
</script>
</body>
2、利用<select>做列表
<select size="7" id="ol1"> -----显示一个有5列的列表,最多可到7列
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</select>
<input type="text" id="txt"/>
<input type="button" value="添加" id="btn" onclick="add()"/>
<script>
function add()
{
var x = document.getElementById("txt").value;
var y = document.getElementById("ol1");
y.innerHTML ="<option>" x "</option>";
}
</script>
Everything will go okay. Just go ahead.
本文由pc28.am发布于前端技术,转载请注明出处:javascript的贯彻事件的一对实例,学习笔记