
JS阻止冒泡方法
JS事件流其中一种是冒泡事件,当一个元素被触发一个事件时,该目标元素的事件会优先被执行,然后向外传播到每个祖先元素,恰如水里的一个泡泡似的,从产生就一直往上浮,到在水平面时,它才消失。在这个过程中,如果你只希望事件发生在目标元素,而不想它传播到祖先元素上去,那么你需要在“泡泡”离开对象之前刺破它。
我在文档中写了一个层,<div id="need_hide">点击以外隐藏该层</div>,并为之设置了简单的样式,现在我希望点击该层以外的地方使之隐藏,那么我给根元素绑定了一个click事件,一点击html就隐藏该DIV,代码如下:
Javascript代码 收藏代码
document.documentElement.onclick = function() {
document.getElementById('need_hide').style.display = 'none';
}
但是点击该层后,也使之隐藏了,这不是我希望得到的效果。由于该层属于根元素的子节点,所以它也被绑定了这个click事件,那么需在该元素被click时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码
function stopPropagation(e) {
e = e || window.event;
if(e.stopPropagation) { //W3C阻止冒泡方法
e.stopPropagation();
} else {
e.cancelBubble = true; //IE阻止冒泡方法
}
}
document.getElementById('need_hide').onclick = function(e) {
stopPropagation(e);
}
如果还想增加一个链接:<a href="#" id="btn_show">显示层</a>,用它来控制该层显示出来,那么仍然需要在该链接被点击时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码
document.getElementById('btn_show').onclick = function(e) {
document.getElementById('need_hide').style.display = 'block';
stopPropagation(e);
}
JS事件流其中一种是冒泡事件,当一个元素被触发一个事件时,该目标元素的事件会优先被执行,然后向外传播到每个祖先元素,恰如水里的一个泡泡似的,从产生就一直往上浮,到在水平面时,它才消失。在这个过程中,如果你只希望事件发生在目标元素,而不想它传播到祖先元素上去,那么你需要在“泡泡”离开对象之前刺破它。
我在文档中写了一个层,<div id="need_hide">点击以外隐藏该层</div>,并为之设置了简单的样式,现在我希望点击该层以外的地方使之隐藏,那么我给根元素绑定了一个click事件,一点击html就隐藏该DIV,代码如下:
Javascript代码 收藏代码
document.documentElement.onclick = function() {
document.getElementById('need_hide').style.display = 'none';
}
但是点击该层后,也使之隐藏了,这不是我希望得到的效果。由于该层属于根元素的子节点,所以它也被绑定了这个click事件,那么需在该元素被click时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码
function stopPropagation(e) {
e = e || window.event;
if(e.stopPropagation) { //W3C阻止冒泡方法
e.stopPropagation();
} else {
e.cancelBubble = true; //IE阻止冒泡方法
}
}
document.getElementById('need_hide').onclick = function(e) {
stopPropagation(e);
}
如果还想增加一个链接:<a href="#" id="btn_show">显示层</a>,用它来控制该层显示出来,那么仍然需要在该链接被点击时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码
document.getElementById('btn_show').onclick = function(e) {
document.getElementById('need_hide').style.display = 'block';
stopPropagation(e);
}
收起阅读 »

移动页面点击穿透问题解决方案
近期在做页面的时候,遇到了点击遮罩层时穿透下层的checkbox的问题,由于为了兼顾用户的流畅度,只能使用tap事件,click事件虽然解决了穿透的问题,但总会有300ms的延时,因此最终使用settimeout方法规避了这个问题。下面是我找到的一篇造成这些问题的简单分析,希望对大家有用!
一.click与300ms延迟
移动浏览器提供一个特殊的功能:双击(double tap)放大
300ms的延迟就来自这里,用户碰触页面之后,需要等待一段时间来判断是不是双击(double tap)动作,而不是立即响应单击(click),等待的这段时间大约是300ms。之前有过简单介绍: 黯羽轻扬:HTML5触摸事件
移动事件提供了 touchstart 、 touchmove 、 touchend 却没有提供tap支持,主流框架(库)都是手动实现了自定义tap事件,以求消除300ms延迟,提高页面响应速度。对于简单的页面,可以把 touchstart 或者 touchend 当作tap来用,但存在一些问题,比如手指接触目标元素,按住不放,慢慢移出响应区域,会触发 touchstart 事件执行对应的事件处理器(本不应该触发), touchend 事件也存在类似的问题。
此外, 使用原生touch事件也存在点击穿透的问题 ,因为click是在touch系列事件发生后大约300ms才触发的,混用touch和click肯定会导致点透问题,下面详细介绍
二.点击穿透问题
点击穿透现象有3种:
点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件
蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件,touch事件触发之后,蒙层消失了,300ms后这个点的click事件fire,event的target自然就是按钮下面的元素,因为按钮跟蒙层一起消失了
跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转
因为 a标签跳转默认是click事件触发 ,所以原理和上面的完全相同
另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了
和蒙层的道理一样,js控制页面跳转的逻辑如果是绑定在touch事件上的,而且新页面中对应位置的元素绑定的是click事件,而且页面在300ms内完成了跳转,三个条件同时满足,就出现这种情况了
非要细分的话还有第四种,不过概率很低,就是新页面中对应位置元素恰好是a标签,然后就发生连续跳转了。。。诸如此类的,都是点击穿透问题
三.解决方案
问题已经很明了了,有很多解决方案,但思路不外乎2种:
不要混用touch和click
既然touch之后300ms会触发click,只用touch或者只用click就自然不会存在问题了
吃掉(或者说是消费掉)touch之后的click
依旧用tap,只是在可能发生点击穿透的情形做额外的处理,拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测(配合全局flag)等等,能吃掉就行
详细解决方案:
只用touch
最简单的解决方案,完美解决点击穿透问题
把页面内所有click全部换成touch事件( touchstart 、’touchend’、’tap’), 需要特别注意 a标签,a标签的href也是click,需要去掉换成js控制的跳转,或者直接改成span + tap控制跳转。如果要求不高,不在乎滑走或者滑进来触发事件的话,span + touchend就可以了,毕竟tap需要引入第三方库
不用a标签其实没什么,移动app开发不用考虑SEO,即便用了a标签,一般也会去掉所有默认样式,不如直接用span
只用click
下下策 ,因为会带来300ms延迟,页面内任何一个自定义交互都将增加300毫秒延迟,想想都慢
不用touch就不会存在touch之后300ms触发click的问题,如果交互性要求不高可以这么做, 强烈不推荐 ,快一点总是好的
拿个东西来挡住
比较笨的方法, 千万不要用
叶小钗的“菊花”大法,更多信息请查看 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)
tap后延迟350ms再隐藏mask
改动最小,缺点是隐藏mask变慢了,350ms还是能感觉到慢的
只需要针对mask做处理就行,改动非常小,如果要求不高的话,用这个比较省力
pointer-events
比较麻烦且有缺陷, 不建议使用
mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应
缺陷是mask消失后的的350ms内,用户可以看到按钮下面的元素点着没反应,如果用户手速很快的话一定会发现
在下面元素的事件处理器里做检测(配合全局flag)
比较麻烦, 不建议使用
全局flag记录按钮点击的位置(坐标点),在下面元素的事件处理器里判断event的坐标点,如果相同则是那个可恶的click,拒绝响应
上面说的只是想法,没测试过,实在不行就用记录时间戳判断,等待350ms,这样就和 pointer-events 差不多
fastclick
好用的解决方案,不介意多加载几KB的话, 不建议使用 ,因为有人遇到了bug,更多信息请查看: Fastclick 导致click事件触发两次的问题
首先引入fastclick库,再把页面内所有touch事件都换成click,其实稍微有点麻烦,建议引入这几KB就为了解决点透问题不值得,不如用第一种方法呢
原文地址:http://www.tuicool.com/articles/6NfaUnM
近期在做页面的时候,遇到了点击遮罩层时穿透下层的checkbox的问题,由于为了兼顾用户的流畅度,只能使用tap事件,click事件虽然解决了穿透的问题,但总会有300ms的延时,因此最终使用settimeout方法规避了这个问题。下面是我找到的一篇造成这些问题的简单分析,希望对大家有用!
一.click与300ms延迟
移动浏览器提供一个特殊的功能:双击(double tap)放大
300ms的延迟就来自这里,用户碰触页面之后,需要等待一段时间来判断是不是双击(double tap)动作,而不是立即响应单击(click),等待的这段时间大约是300ms。之前有过简单介绍: 黯羽轻扬:HTML5触摸事件
移动事件提供了 touchstart 、 touchmove 、 touchend 却没有提供tap支持,主流框架(库)都是手动实现了自定义tap事件,以求消除300ms延迟,提高页面响应速度。对于简单的页面,可以把 touchstart 或者 touchend 当作tap来用,但存在一些问题,比如手指接触目标元素,按住不放,慢慢移出响应区域,会触发 touchstart 事件执行对应的事件处理器(本不应该触发), touchend 事件也存在类似的问题。
此外, 使用原生touch事件也存在点击穿透的问题 ,因为click是在touch系列事件发生后大约300ms才触发的,混用touch和click肯定会导致点透问题,下面详细介绍
二.点击穿透问题
点击穿透现象有3种:
点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件
蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件,touch事件触发之后,蒙层消失了,300ms后这个点的click事件fire,event的target自然就是按钮下面的元素,因为按钮跟蒙层一起消失了
跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转
因为 a标签跳转默认是click事件触发 ,所以原理和上面的完全相同
另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了
和蒙层的道理一样,js控制页面跳转的逻辑如果是绑定在touch事件上的,而且新页面中对应位置的元素绑定的是click事件,而且页面在300ms内完成了跳转,三个条件同时满足,就出现这种情况了
非要细分的话还有第四种,不过概率很低,就是新页面中对应位置元素恰好是a标签,然后就发生连续跳转了。。。诸如此类的,都是点击穿透问题
三.解决方案
问题已经很明了了,有很多解决方案,但思路不外乎2种:
不要混用touch和click
既然touch之后300ms会触发click,只用touch或者只用click就自然不会存在问题了
吃掉(或者说是消费掉)touch之后的click
依旧用tap,只是在可能发生点击穿透的情形做额外的处理,拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测(配合全局flag)等等,能吃掉就行
详细解决方案:
只用touch
最简单的解决方案,完美解决点击穿透问题
把页面内所有click全部换成touch事件( touchstart 、’touchend’、’tap’), 需要特别注意 a标签,a标签的href也是click,需要去掉换成js控制的跳转,或者直接改成span + tap控制跳转。如果要求不高,不在乎滑走或者滑进来触发事件的话,span + touchend就可以了,毕竟tap需要引入第三方库
不用a标签其实没什么,移动app开发不用考虑SEO,即便用了a标签,一般也会去掉所有默认样式,不如直接用span
只用click
下下策 ,因为会带来300ms延迟,页面内任何一个自定义交互都将增加300毫秒延迟,想想都慢
不用touch就不会存在touch之后300ms触发click的问题,如果交互性要求不高可以这么做, 强烈不推荐 ,快一点总是好的
拿个东西来挡住
比较笨的方法, 千万不要用
叶小钗的“菊花”大法,更多信息请查看 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)
tap后延迟350ms再隐藏mask
改动最小,缺点是隐藏mask变慢了,350ms还是能感觉到慢的
只需要针对mask做处理就行,改动非常小,如果要求不高的话,用这个比较省力
pointer-events
比较麻烦且有缺陷, 不建议使用
mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应
缺陷是mask消失后的的350ms内,用户可以看到按钮下面的元素点着没反应,如果用户手速很快的话一定会发现
在下面元素的事件处理器里做检测(配合全局flag)
比较麻烦, 不建议使用
全局flag记录按钮点击的位置(坐标点),在下面元素的事件处理器里判断event的坐标点,如果相同则是那个可恶的click,拒绝响应
上面说的只是想法,没测试过,实在不行就用记录时间戳判断,等待350ms,这样就和 pointer-events 差不多
fastclick
好用的解决方案,不介意多加载几KB的话, 不建议使用 ,因为有人遇到了bug,更多信息请查看: Fastclick 导致click事件触发两次的问题
首先引入fastclick库,再把页面内所有touch事件都换成click,其实稍微有点麻烦,建议引入这几KB就为了解决点透问题不值得,不如用第一种方法呢
原文地址:http://www.tuicool.com/articles/6NfaUnM

关于mui发送ajax请求总是失败,我所遇到的问题总结
1.服务器端未设置跨域。不要问我怎么设置
2.本地测试请求的地址不要用localhost,发布到iis,用ip访问,不然会找不到的!!!
3.防火墙得记得关闭
1.服务器端未设置跨域。不要问我怎么设置
2.本地测试请求的地址不要用localhost,发布到iis,用ip访问,不然会找不到的!!!
3.防火墙得记得关闭

关于MUI提前注入5+API的尝试
原文地址:http://blog.csdn.net/u012843100/article/details/52838928
HBuilder是在开发hybrid app时不错的工具。为了使hybrid app的性能更加接近原生,程序猿们做了很多努力。例如近日在HBuilder7.5.0版本中,增加了一个振奋人心的特性。
Android平台新增提前注入5+ API,支持在plusready事件前调用,具体参考http://ask.dcloud.net.cn/article/921
以往在5+ Runtime环境中,通常情况下需要html页面解析完成后才会注入5+ API,执行的顺序为:
- 加载html页面
- 解析html页面(下载script/link等节点引用的资源,如js/css文件)
- 触发DOMContentLoaded事件
- 注入5+ API
- 触发plusready事件
这样导致5+ API生效时间比较延后,在html中引用js执行之后才能调用5+ AP,于是很多人选择在plusready时间中编写逻辑代码,这样写的最大缺点是使脚本的执行时间稍微延后了,如果在页面的DOMContentLoaded(mui.ready)事件中处理逻辑代码,会在一定程度上提升页面加载速度。但是,往往在逻辑代码中需要调用5+API,怎么办呢?
于是在不断对性能较为挑剔的程序猿们先在ready事件中处理与5+API无关的页面逻辑(渲染页面等);然后在plusready事件中处理需要调用5+API的逻辑代码。这样在一定程序上提升了APP的体验及速度,但却使代码分散各处,不利于管理。
此次提前加载5+API突破了这个限制,以下是官方示例:
在HBuilder7.5版本之后将支持提前注入5+ API,可以在plusready事件触发之前调用5+ API,操作方法是在页面中添加以下节点:
<script src="html5plus://ready"/>,示例如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
<title>HTML5+ API</title>
<script src="html5plus://ready"/>
<script type="text/javascript" charset="utf-8">
// 这里可以调用5+ API了,为了更好的兼容性,应该使用以下代码进行判断
if(window.plus){
// 在这里调用5+ API
}else{// 兼容老版本的plusready事件
document.addEventListener('plusready',function () {
// 在这里调用5+ API
},false);
}
</script>
</head>
<body>
Hello HTML5 plus.
</body>
</html>
注意
- 仅仅是提前注入5+ API,并不会提前触发plusready事件(仅步骤4提前操作了)
- Android3.0及以上平台才支持提前注入,Android2.*版本无法提前注入
- 在流应用环境中的wap2app会自动提前注入(第一次引用网络js时注入),不需要添加<script src="html5plus://ready"/>节点
官方示例中,通过判断判断window.plus对象来判断plus模块是否已经加载完毕,如果加载完毕则可直接调用,由于plusready事件并没有提前,所以如同以往使用
document.addEventListener('plusready',function () {
// 在这里调用5+ API
},false);
来添加监听,跟以往没有任何差别。
但是在使用过程中,我发现5+API可能在mui对象加载完毕前已经加载好了,于是在官方示例中的if语句成立时调用mui方法会导致mui未定义的情况。所以我把实例中的:
if(window.plus)
改成:
if(window.plus && window.mui)
但是这样如果plus加载完毕但mui未加载完毕时可能在效率上并没有提升。所以我又做了一下修改,在mui.ready中调用window.plus判断:
mui.ready(function(){
if(window.plus){
// 在这里调用5+ API
}else{// 兼容老版本的plusready事件
document.addEventListener('plusready',function () {
// 在这里调用5+ API
},false);
}
});
这样似乎在性能上有一定提升,但我并不确定这样是否是最好的方法,或者这样是否会导致其他问题,还望指点。
另外,使用官方示例过程中还有一点不是很确定,就是在if(window.plus)中处理dom元素时可能会出现找不到的情况,此时将<script src="html5plus://ready"></script>注释掉就不会了。初步猜测可能是因为plus对象在DOMContentLoaded前就已经加载完毕了,此时页面并未渲染完造成的。
H5 app的优化之路还很长,继续埋头写代码去了。
原文地址:http://blog.csdn.net/u012843100/article/details/52838928
HBuilder是在开发hybrid app时不错的工具。为了使hybrid app的性能更加接近原生,程序猿们做了很多努力。例如近日在HBuilder7.5.0版本中,增加了一个振奋人心的特性。
Android平台新增提前注入5+ API,支持在plusready事件前调用,具体参考http://ask.dcloud.net.cn/article/921
以往在5+ Runtime环境中,通常情况下需要html页面解析完成后才会注入5+ API,执行的顺序为:
- 加载html页面
- 解析html页面(下载script/link等节点引用的资源,如js/css文件)
- 触发DOMContentLoaded事件
- 注入5+ API
- 触发plusready事件
这样导致5+ API生效时间比较延后,在html中引用js执行之后才能调用5+ AP,于是很多人选择在plusready时间中编写逻辑代码,这样写的最大缺点是使脚本的执行时间稍微延后了,如果在页面的DOMContentLoaded(mui.ready)事件中处理逻辑代码,会在一定程度上提升页面加载速度。但是,往往在逻辑代码中需要调用5+API,怎么办呢?
于是在不断对性能较为挑剔的程序猿们先在ready事件中处理与5+API无关的页面逻辑(渲染页面等);然后在plusready事件中处理需要调用5+API的逻辑代码。这样在一定程序上提升了APP的体验及速度,但却使代码分散各处,不利于管理。
此次提前加载5+API突破了这个限制,以下是官方示例:
在HBuilder7.5版本之后将支持提前注入5+ API,可以在plusready事件触发之前调用5+ API,操作方法是在页面中添加以下节点:
<script src="html5plus://ready"/>,示例如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no"/>
<title>HTML5+ API</title>
<script src="html5plus://ready"/>
<script type="text/javascript" charset="utf-8">
// 这里可以调用5+ API了,为了更好的兼容性,应该使用以下代码进行判断
if(window.plus){
// 在这里调用5+ API
}else{// 兼容老版本的plusready事件
document.addEventListener('plusready',function () {
// 在这里调用5+ API
},false);
}
</script>
</head>
<body>
Hello HTML5 plus.
</body>
</html>
注意
- 仅仅是提前注入5+ API,并不会提前触发plusready事件(仅步骤4提前操作了)
- Android3.0及以上平台才支持提前注入,Android2.*版本无法提前注入
- 在流应用环境中的wap2app会自动提前注入(第一次引用网络js时注入),不需要添加<script src="html5plus://ready"/>节点
官方示例中,通过判断判断window.plus对象来判断plus模块是否已经加载完毕,如果加载完毕则可直接调用,由于plusready事件并没有提前,所以如同以往使用
document.addEventListener('plusready',function () {
// 在这里调用5+ API
},false);
来添加监听,跟以往没有任何差别。
但是在使用过程中,我发现5+API可能在mui对象加载完毕前已经加载好了,于是在官方示例中的if语句成立时调用mui方法会导致mui未定义的情况。所以我把实例中的:
if(window.plus)
改成:
if(window.plus && window.mui)
但是这样如果plus加载完毕但mui未加载完毕时可能在效率上并没有提升。所以我又做了一下修改,在mui.ready中调用window.plus判断:
mui.ready(function(){
if(window.plus){
// 在这里调用5+ API
}else{// 兼容老版本的plusready事件
document.addEventListener('plusready',function () {
// 在这里调用5+ API
},false);
}
});
这样似乎在性能上有一定提升,但我并不确定这样是否是最好的方法,或者这样是否会导致其他问题,还望指点。
另外,使用官方示例过程中还有一点不是很确定,就是在if(window.plus)中处理dom元素时可能会出现找不到的情况,此时将<script src="html5plus://ready"></script>注释掉就不会了。初步猜测可能是因为plus对象在DOMContentLoaded前就已经加载完毕了,此时页面并未渲染完造成的。
H5 app的优化之路还很长,继续埋头写代码去了。
收起阅读 »
iOS平台Widget集成使用wgt/wgtu升级说明
用户在使用Widget集成时,使用plus.runtime.install API进行5+应用升级时会发现,方法回调升级成功,但是应用重启后加载的依然是老版本的应用。这是因为会用Widget方式集成时调用 PDRCoreAppManager 类 openAppAtLocation方法创建PDRCoreApp对象时需要传入WebApp的保存路径作为参数

一般情况下WebApp的资源是放在原生工程的Pandora/apps目录下,在生成ipa安装包后这个目录下的文件是不能修改。 5+SDK在wgt/wgtu升级后会将资源释放到应用沙盒的~Library目录下,路径为~Library/Pandora/apps/[WebApp的ID]/www目录下,所以需要在调用PDRCoreAppManager 类 openAppAtLocation方法时传入的参数进行调整。
我们知道了问题的原因,下面我们来解决问题。
我们可以通过判断 ~Library/Pandora/apps/[WebApp的ID]/www目录下是否有应用的mainfest.json文件存在的方式判断应用是否升级,如果该文件存在则设置该路径为应用启动路径,否则使用ipa下的Pandora/apps目录下的资源为启动路径
ipa在升级时~Library/Pandora/apps/[WebApp的ID]/www 目录下的内容不会被系统删除,
为了保证升级后不会使用到以前遗留的WebApp资源,建议在WebApp启动时写文件保存当前ipa的版本号,每次启动时判断保存的版本号与当前ipa的版本号是否一致,如果不一致则需要删除~Library/Pandora/apps/[WebApp的ID]/www 目录下的全部内容,这样可以保证使用正确的WebApp资源
用户在使用Widget集成时,使用plus.runtime.install API进行5+应用升级时会发现,方法回调升级成功,但是应用重启后加载的依然是老版本的应用。这是因为会用Widget方式集成时调用 PDRCoreAppManager 类 openAppAtLocation方法创建PDRCoreApp对象时需要传入WebApp的保存路径作为参数
一般情况下WebApp的资源是放在原生工程的Pandora/apps目录下,在生成ipa安装包后这个目录下的文件是不能修改。 5+SDK在wgt/wgtu升级后会将资源释放到应用沙盒的~Library目录下,路径为~Library/Pandora/apps/[WebApp的ID]/www目录下,所以需要在调用PDRCoreAppManager 类 openAppAtLocation方法时传入的参数进行调整。
我们知道了问题的原因,下面我们来解决问题。
我们可以通过判断 ~Library/Pandora/apps/[WebApp的ID]/www目录下是否有应用的mainfest.json文件存在的方式判断应用是否升级,如果该文件存在则设置该路径为应用启动路径,否则使用ipa下的Pandora/apps目录下的资源为启动路径
ipa在升级时~Library/Pandora/apps/[WebApp的ID]/www 目录下的内容不会被系统删除,
为了保证升级后不会使用到以前遗留的WebApp资源,建议在WebApp启动时写文件保存当前ipa的版本号,每次启动时判断保存的版本号与当前ipa的版本号是否一致,如果不一致则需要删除~Library/Pandora/apps/[WebApp的ID]/www 目录下的全部内容,这样可以保证使用正确的WebApp资源

Android平台Widget集成使用wgt/wgtu升级说明
用户在使用Widget集成时,使用plus.runtime.install API进行5+应用升级时会发现,方法回调安装成功,但是应用重启后加载的依然是老版本的Web应用。
这是因为会用Widget方式集成时调用 SDK.startWebApp 方法创建IApp对象时,需要传入WebApp的保存路径作为参数
一般情况下WebApp的资源是放在原生工程的assets/apps目录下,在生成apk安装包后这个目录下的文件是不能修改。 5+SDK在wgt/wgtu升级后会将资源释放到SD卡下,路径为 SD卡/android/data/[apk包名]/apps/[WebApp的ID]/www,所以在资源升级后调用SDK.startWebApp方法时传入的参数需要进行调整。
我们知道了问题的原因,下面我们来解决问题。
我们可以通过判断SD卡/android/data/[apk包名]/apps/[WebApp的ID]/www目录下是否有应用的mainfest.json文件存在的方式判断应用是否升级,如果该文件存在则设置该路径为应用启动路径,否则使用apk下的assets目录为启动路径
apk在卸载时SD卡/Android/data/[apk包名] 目录下的内容有可能不会被系统删除,为了保证 安装/升级 apk后,不会使用到以前遗留的WebApp资源,建议在WebApp启动前写文件保存当前apk的版本号,每次启动时判断保存的版本号与当前apk的版本号是否一致,如果不一致需要则删除 SD卡/android/data/[apk包名]/apps/[WebApp的ID]/www 目录下的全部内容,这样可以保证使用正确的WebApp资源,
用户在使用Widget集成时,使用plus.runtime.install API进行5+应用升级时会发现,方法回调安装成功,但是应用重启后加载的依然是老版本的Web应用。
这是因为会用Widget方式集成时调用 SDK.startWebApp 方法创建IApp对象时,需要传入WebApp的保存路径作为参数
一般情况下WebApp的资源是放在原生工程的assets/apps目录下,在生成apk安装包后这个目录下的文件是不能修改。 5+SDK在wgt/wgtu升级后会将资源释放到SD卡下,路径为 SD卡/android/data/[apk包名]/apps/[WebApp的ID]/www,所以在资源升级后调用SDK.startWebApp方法时传入的参数需要进行调整。
我们知道了问题的原因,下面我们来解决问题。
我们可以通过判断SD卡/android/data/[apk包名]/apps/[WebApp的ID]/www目录下是否有应用的mainfest.json文件存在的方式判断应用是否升级,如果该文件存在则设置该路径为应用启动路径,否则使用apk下的assets目录为启动路径
apk在卸载时SD卡/Android/data/[apk包名] 目录下的内容有可能不会被系统删除,为了保证 安装/升级 apk后,不会使用到以前遗留的WebApp资源,建议在WebApp启动前写文件保存当前apk的版本号,每次启动时判断保存的版本号与当前apk的版本号是否一致,如果不一致需要则删除 SD卡/android/data/[apk包名]/apps/[WebApp的ID]/www 目录下的全部内容,这样可以保证使用正确的WebApp资源,
收起阅读 »
上拉刷新,下拉加载
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link href="css/mui.min.css" rel="stylesheet" />
<link href="css/TopBottomScroll.css" />
</head>
<body>
<div id="slider" class="mui-slider mui-fullscreen">
<div id="sliderSegmentedControl" class="mui-slider-indicator mui-segmented-control mui-segmented-control-inverted">
<a class="mui-control-item" href="#item1mobile">
公司新闻
</a>
<a class="mui-control-item" href="#item2mobile">
媒体关注
</a>
<a class="mui-control-item" href="#item3mobile">
最新公告
</a>
</div>
<div id="sliderProgressBar" class="mui-slider-progress-bar mui-col-xs-4"></div>
<div class="mui-slider-group">
<div id="item1mobile" class="mui-slider-item mui-control-content mui-active mui-content">
<div id="scroll1" class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul class="mui-table-view">
<li class="mui-table-view-cell">
第一个选项卡子项-1
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-2
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-3
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-4
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-5
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-6
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-7
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-8
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-9
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-10
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-11
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-12
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-13
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-14
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-15
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-16
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-17
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-18
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-19
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-20
</li>
</ul>
</div>
</div>
</div>
<div id="item2mobile" class="mui-slider-item mui-control-content">
<div id="scroll2" class="mui-scroll-wrapper">
<div class="mui-scroll">
<div class="mui-loading">
<div class="mui-spinner">
</div>
</div>
</div>
</div>
</div>
<div id="item3mobile" class="mui-slider-item mui-control-content">
<div id="scroll3" class="mui-scroll-wrapper">
<div class="mui-scroll">
<div class="mui-loading">
<div class="mui-spinner">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="js/mui.min.js"></script>
<script src="js/TopBootomScroll.js"></script>
<script type="text/javascript">
mui.init();
(function($) {
var createFragment = function(ul, index, count, reverse) {
var length = ul.querySelectorAll('li').length;
var fragment = document.createDocumentFragment();
var li;
for (var i = 0; i < count; i++) {
li = document.createElement('li');
li.className = 'mui-table-view-cell';
li.innerHTML = '<a href="javascript:;">'
+' <img class="mui-media-object mui-pull-left" src="images/slider/slider_image_6.jpg">'
+' <div class="mui-media-body">'
+' 房子限购,股票大跌'
+' <p class="mui-ellipsis">能和心爱的人一起睡觉,是件幸福的事情;可是,打呼噜怎么办?</p>'
+' </div>'
+'</a>';
fragment.appendChild(li);
}
return fragment;
};
var html2 = '<ul class="mui-table-view"></ul>';
var html3 = '<ul class="mui-table-view"></ul>';
var item2 = document.getElementById('item2mobile');
var item3 = document.getElementById('item3mobile');
document.getElementById('slider').addEventListener('slide', function(e) {
if (e.detail.slideNumber === 1) {
if (item2.querySelector('.mui-loading')) {
setTimeout(function() {
item2.querySelector('.mui-scroll').innerHTML = html2;
var ul = item2.querySelector('.mui-scroll').querySelector("ul");
ul.appendChild(createFragment(ul,0,20,""));
}, 500);
}
} else if (e.detail.slideNumber === 2) {
if (item3.querySelector('.mui-loading')) {
setTimeout(function() {
item3.querySelector('.mui-scroll').innerHTML = html3;
var ul = item3.querySelector('.mui-scroll').querySelector("ul");
ul.appendChild(createFragment(ul,0,20,""));
}, 500);
}
}
});
$("#scroll1").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
$("#scroll2").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
$("#scroll3").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
})(mui);
</script>
</body>
</html>
TopBootomScroll.js
(function($){
$.fn.TopBootomScroll = function(options){
var obl = true;
if(options){
obl = false;
}
$(this).scroll({
indicators: true //是否显示滚动条
});
options = options || {};
options = $.extend(true,{
down:{
obl:false,
Y:50,//下拉超出的(downY)长度,开始加载
callback: function(sllef) {}
},
up: {
obl:false,
Y:50,//上拉超出的(downY)长度,开始加载
callback: function(sllef) {}
}
},options);
this.each(function() {
var sllef = this;
sllef.options = options;
sllef.removeTopStyle = function(){
if(this.querySelector(".mui-scroll").querySelector(".topStyle") != null){
this.querySelector(".mui-scroll").removeChild(this.querySelector(".mui-scroll").querySelector(".topStyle"));
}
};
sllef.removeButtonStyle = function(){
if(this.querySelector(".mui-scroll").querySelector(".buttonStyle") != null){
this.querySelector(".mui-scroll").removeChild(this.querySelector(".mui-scroll").querySelector(".buttonStyle"));
console.info("scrollerWidth:"+sllef.scrollerWidth)
$(this).scroll().scrollTo(0,-(sllef.scrollerWidth-this.options.up.Y-10),100);
}
};
sllef.addEventListener("scroll",function(e){
console.info(e.detail.scrollerWidth);
sllef.scrollerWidth = e.detail.scrollerWidth;
console.info("scroll")
if(e.detail.lastY == 0){
console.info("下拉到顶部")
console.info("lastY:"+e.detail.lastY)
console.info("maxScrollY:"+e.detail.maxScrollY)
if(obl){
setTimeout(function(){
sllef.removeTopStyle();
},500);
}
if(options.down.obl){
var html = '<div class="mui-loading">'
+ '<div class="mui-spinner">'
+ '</div>'
+ '<div class="mui-pull-caption">正在加载中...</div>'
+'</div>';
this.querySelector(".mui-scroll").querySelector(".topStyle").innerHTML = html;
options.down.obl = false;
options.down.callback(this);
}else{
sllef.removeTopStyle();
}
}else if(e.detail.lastY > 0){
console.info("下拉超过顶部")
console.info(this.querySelector(".mui-scroll").querySelector(".topStyle") == null)
if(this.querySelector(".mui-scroll").querySelector(".topStyle") == null){
var div = document.createElement("div");
div.className = "topStyle";
div.innerHTML = "下拉可以刷新";
var fragment = document.createDocumentFragment();
fragment.appendChild(div);
this.querySelector(".mui-scroll").insertBefore(div,this.querySelector(".mui-scroll").firstChild);
}
console.info(options.down.Y)
console.info(e.detail.lastY)
console.info(e.detail.lastY >= options.down.Y)
if(e.detail.lastY >= options.down.Y){
this.querySelector(".mui-scroll").querySelector(".topStyle").innerHTML = "释放立即刷新";
options.down.obl = true;
}
console.info("lastY:"+e.detail.lastY)
}else if(e.detail.lastY == e.detail.maxScrollY){
console.info("上拉到底部")
if(obl){
setTimeout(function(){
sllef.removeButtonStyle();
},500);
}
if(options.up.obl){
var html = '<div class="mui-loading">'
+ '<div class="mui-spinner">'
+ '</div>'
+ '<div class="mui-pull-caption">正在加载中...</div>'
+'</div>';
this.querySelector(".mui-scroll").querySelector(".buttonStyle").innerHTML = html;
options.up.obl = false;
options.up.callback(this);
}else{
sllef.removeButtonStyle();
}
}else if(e.detail.lastY < e.detail.maxScrollY){
console.info("上拉超过底部")
if(this.querySelector(".mui-scroll").querySelector(".buttonStyle") == null){
var div = document.createElement("div");
div.className = "buttonStyle";
div.innerHTML = "上拉可以刷新";
this.querySelector(".mui-scroll").appendChild(div);
}
console.info("lastY:"+e.detail.lastY)
console.info(e.detail.lastY - e.detail.maxScrollY <= -options.up.Y)
if(e.detail.lastY - e.detail.maxScrollY <= -options.up.Y){
this.querySelector(".mui-scroll").querySelector(".buttonStyle").innerHTML = "释放立即刷新";
options.up.obl = true;
}
}
});
});
};
$("#scroll1").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
})(mui);
TopBottomScroll.css
.topStyle,.buttonStyle{
text-align: center;
padding: 5px;
}
.topStyle .mui-loading,.buttonStyle .mui-loading{
margin-top: 0;
}
.topStyle{
border-bottom: 1px solid #E4E3E6;
}
.buttonStyle{
border-top: 1px solid #E4E3E6;
}
.topStyle .mui-loading .mui-spinner,.buttonStyle .mui-loading .mui-spinner{
display: inline-block;
vertical-align: middle;
margin-right: 7px;
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link href="css/mui.min.css" rel="stylesheet" />
<link href="css/TopBottomScroll.css" />
</head>
<body>
<div id="slider" class="mui-slider mui-fullscreen">
<div id="sliderSegmentedControl" class="mui-slider-indicator mui-segmented-control mui-segmented-control-inverted">
<a class="mui-control-item" href="#item1mobile">
公司新闻
</a>
<a class="mui-control-item" href="#item2mobile">
媒体关注
</a>
<a class="mui-control-item" href="#item3mobile">
最新公告
</a>
</div>
<div id="sliderProgressBar" class="mui-slider-progress-bar mui-col-xs-4"></div>
<div class="mui-slider-group">
<div id="item1mobile" class="mui-slider-item mui-control-content mui-active mui-content">
<div id="scroll1" class="mui-scroll-wrapper">
<div class="mui-scroll">
<ul class="mui-table-view">
<li class="mui-table-view-cell">
第一个选项卡子项-1
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-2
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-3
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-4
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-5
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-6
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-7
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-8
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-9
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-10
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-11
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-12
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-13
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-14
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-15
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-16
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-17
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-18
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-19
</li>
<li class="mui-table-view-cell">
第一个选项卡子项-20
</li>
</ul>
</div>
</div>
</div>
<div id="item2mobile" class="mui-slider-item mui-control-content">
<div id="scroll2" class="mui-scroll-wrapper">
<div class="mui-scroll">
<div class="mui-loading">
<div class="mui-spinner">
</div>
</div>
</div>
</div>
</div>
<div id="item3mobile" class="mui-slider-item mui-control-content">
<div id="scroll3" class="mui-scroll-wrapper">
<div class="mui-scroll">
<div class="mui-loading">
<div class="mui-spinner">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="js/mui.min.js"></script>
<script src="js/TopBootomScroll.js"></script>
<script type="text/javascript">
mui.init();
(function($) {
var createFragment = function(ul, index, count, reverse) {
var length = ul.querySelectorAll('li').length;
var fragment = document.createDocumentFragment();
var li;
for (var i = 0; i < count; i++) {
li = document.createElement('li');
li.className = 'mui-table-view-cell';
li.innerHTML = '<a href="javascript:;">'
+' <img class="mui-media-object mui-pull-left" src="images/slider/slider_image_6.jpg">'
+' <div class="mui-media-body">'
+' 房子限购,股票大跌'
+' <p class="mui-ellipsis">能和心爱的人一起睡觉,是件幸福的事情;可是,打呼噜怎么办?</p>'
+' </div>'
+'</a>';
fragment.appendChild(li);
}
return fragment;
};
var html2 = '<ul class="mui-table-view"></ul>';
var html3 = '<ul class="mui-table-view"></ul>';
var item2 = document.getElementById('item2mobile');
var item3 = document.getElementById('item3mobile');
document.getElementById('slider').addEventListener('slide', function(e) {
if (e.detail.slideNumber === 1) {
if (item2.querySelector('.mui-loading')) {
setTimeout(function() {
item2.querySelector('.mui-scroll').innerHTML = html2;
var ul = item2.querySelector('.mui-scroll').querySelector("ul");
ul.appendChild(createFragment(ul,0,20,""));
}, 500);
}
} else if (e.detail.slideNumber === 2) {
if (item3.querySelector('.mui-loading')) {
setTimeout(function() {
item3.querySelector('.mui-scroll').innerHTML = html3;
var ul = item3.querySelector('.mui-scroll').querySelector("ul");
ul.appendChild(createFragment(ul,0,20,""));
}, 500);
}
}
});
$("#scroll1").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
$("#scroll2").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
$("#scroll3").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
})(mui);
</script>
</body>
</html>
TopBootomScroll.js
(function($){
$.fn.TopBootomScroll = function(options){
var obl = true;
if(options){
obl = false;
}
$(this).scroll({
indicators: true //是否显示滚动条
});
options = options || {};
options = $.extend(true,{
down:{
obl:false,
Y:50,//下拉超出的(downY)长度,开始加载
callback: function(sllef) {}
},
up: {
obl:false,
Y:50,//上拉超出的(downY)长度,开始加载
callback: function(sllef) {}
}
},options);
this.each(function() {
var sllef = this;
sllef.options = options;
sllef.removeTopStyle = function(){
if(this.querySelector(".mui-scroll").querySelector(".topStyle") != null){
this.querySelector(".mui-scroll").removeChild(this.querySelector(".mui-scroll").querySelector(".topStyle"));
}
};
sllef.removeButtonStyle = function(){
if(this.querySelector(".mui-scroll").querySelector(".buttonStyle") != null){
this.querySelector(".mui-scroll").removeChild(this.querySelector(".mui-scroll").querySelector(".buttonStyle"));
console.info("scrollerWidth:"+sllef.scrollerWidth)
$(this).scroll().scrollTo(0,-(sllef.scrollerWidth-this.options.up.Y-10),100);
}
};
sllef.addEventListener("scroll",function(e){
console.info(e.detail.scrollerWidth);
sllef.scrollerWidth = e.detail.scrollerWidth;
console.info("scroll")
if(e.detail.lastY == 0){
console.info("下拉到顶部")
console.info("lastY:"+e.detail.lastY)
console.info("maxScrollY:"+e.detail.maxScrollY)
if(obl){
setTimeout(function(){
sllef.removeTopStyle();
},500);
}
if(options.down.obl){
var html = '<div class="mui-loading">'
+ '<div class="mui-spinner">'
+ '</div>'
+ '<div class="mui-pull-caption">正在加载中...</div>'
+'</div>';
this.querySelector(".mui-scroll").querySelector(".topStyle").innerHTML = html;
options.down.obl = false;
options.down.callback(this);
}else{
sllef.removeTopStyle();
}
}else if(e.detail.lastY > 0){
console.info("下拉超过顶部")
console.info(this.querySelector(".mui-scroll").querySelector(".topStyle") == null)
if(this.querySelector(".mui-scroll").querySelector(".topStyle") == null){
var div = document.createElement("div");
div.className = "topStyle";
div.innerHTML = "下拉可以刷新";
var fragment = document.createDocumentFragment();
fragment.appendChild(div);
this.querySelector(".mui-scroll").insertBefore(div,this.querySelector(".mui-scroll").firstChild);
}
console.info(options.down.Y)
console.info(e.detail.lastY)
console.info(e.detail.lastY >= options.down.Y)
if(e.detail.lastY >= options.down.Y){
this.querySelector(".mui-scroll").querySelector(".topStyle").innerHTML = "释放立即刷新";
options.down.obl = true;
}
console.info("lastY:"+e.detail.lastY)
}else if(e.detail.lastY == e.detail.maxScrollY){
console.info("上拉到底部")
if(obl){
setTimeout(function(){
sllef.removeButtonStyle();
},500);
}
if(options.up.obl){
var html = '<div class="mui-loading">'
+ '<div class="mui-spinner">'
+ '</div>'
+ '<div class="mui-pull-caption">正在加载中...</div>'
+'</div>';
this.querySelector(".mui-scroll").querySelector(".buttonStyle").innerHTML = html;
options.up.obl = false;
options.up.callback(this);
}else{
sllef.removeButtonStyle();
}
}else if(e.detail.lastY < e.detail.maxScrollY){
console.info("上拉超过底部")
if(this.querySelector(".mui-scroll").querySelector(".buttonStyle") == null){
var div = document.createElement("div");
div.className = "buttonStyle";
div.innerHTML = "上拉可以刷新";
this.querySelector(".mui-scroll").appendChild(div);
}
console.info("lastY:"+e.detail.lastY)
console.info(e.detail.lastY - e.detail.maxScrollY <= -options.up.Y)
if(e.detail.lastY - e.detail.maxScrollY <= -options.up.Y){
this.querySelector(".mui-scroll").querySelector(".buttonStyle").innerHTML = "释放立即刷新";
options.up.obl = true;
}
}
});
});
};
$("#scroll1").TopBootomScroll({
down:{
callback: function(sllef) {
setTimeout(function(){
sllef.removeTopStyle();
},5000);
}
},
up: {
callback: function(sllef) {
setTimeout(function(){
sllef.removeButtonStyle();
},5000);
}
}
});
})(mui);
TopBottomScroll.css
.topStyle,.buttonStyle{
text-align: center;
padding: 5px;
}
.topStyle .mui-loading,.buttonStyle .mui-loading{
margin-top: 0;
}
.topStyle{
border-bottom: 1px solid #E4E3E6;
}
.buttonStyle{
border-top: 1px solid #E4E3E6;
}
.topStyle .mui-loading .mui-spinner,.buttonStyle .mui-loading .mui-spinner{
display: inline-block;
vertical-align: middle;
margin-right: 7px;
}
收起阅读 »

滚动条上拉到底部和下拉到顶部事件监听
<div id="scroll1" class="mui-scroll-wrapper mui-fullscreen">
<div class="mui-scroll">
<ul class="mui-table-view">
<li class="mui-table-view-cell">第一个选项卡子项-1</li>
<li class="mui-table-view-cell">第一个选项卡子项-2</li>
<li class="mui-table-view-cell">第一个选项卡子项-3</li>
<li class="mui-table-view-cell">第一个选项卡子项-4</li>
<li class="mui-table-view-cell">第一个选项卡子项-5</li>
<li class="mui-table-view-cell">第一个选项卡子项-6</li>
<li class="mui-table-view-cell">第一个选项卡子项-7</li>
<li class="mui-table-view-cell">第一个选项卡子项-8</li>
<li class="mui-table-view-cell">第一个选项卡子项-9</li>
<li class="mui-table-view-cell">第一个选项卡子项-10</li>
<li class="mui-table-view-cell">第一个选项卡子项-11</li>
<li class="mui-table-view-cell">第一个选项卡子项-12</li>
<li class="mui-table-view-cell">第一个选项卡子项-13</li>
<li class="mui-table-view-cell">第一个选项卡子项-14</li>
<li class="mui-table-view-cell">第一个选项卡子项-15</li>
<li class="mui-table-view-cell">第一个选项卡子项-16</li>
<li class="mui-table-view-cell">第一个选项卡子项-17</li>
<li class="mui-table-view-cell">第一个选项卡子项-18</li>
<li class="mui-table-view-cell">第一个选项卡子项-19</li>
<li class="mui-table-view-cell">第一个选项卡子项-20</li>
</ul>
</div>
</div>
<script>
document.getElementById("scroll1").addEventListener("scrollbottom",function(e){
console.info("上拉到底部")
});
document.getElementById("scroll1").addEventListener("scroll",function(e){
console.info("scroll")
if(e.detail.lastY == 0){
console.info("下拉到顶部")
console.info("lastY:"+e.detail.lastY)
console.info("maxScrollY:"+e.detail.maxScrollY)
}else if(e.detail.lastY > 0){
console.info("下拉超过顶部")
console.info("lastY:"+e.detail.lastY)
}
});
</script>
<div id="scroll1" class="mui-scroll-wrapper mui-fullscreen">
<div class="mui-scroll">
<ul class="mui-table-view">
<li class="mui-table-view-cell">第一个选项卡子项-1</li>
<li class="mui-table-view-cell">第一个选项卡子项-2</li>
<li class="mui-table-view-cell">第一个选项卡子项-3</li>
<li class="mui-table-view-cell">第一个选项卡子项-4</li>
<li class="mui-table-view-cell">第一个选项卡子项-5</li>
<li class="mui-table-view-cell">第一个选项卡子项-6</li>
<li class="mui-table-view-cell">第一个选项卡子项-7</li>
<li class="mui-table-view-cell">第一个选项卡子项-8</li>
<li class="mui-table-view-cell">第一个选项卡子项-9</li>
<li class="mui-table-view-cell">第一个选项卡子项-10</li>
<li class="mui-table-view-cell">第一个选项卡子项-11</li>
<li class="mui-table-view-cell">第一个选项卡子项-12</li>
<li class="mui-table-view-cell">第一个选项卡子项-13</li>
<li class="mui-table-view-cell">第一个选项卡子项-14</li>
<li class="mui-table-view-cell">第一个选项卡子项-15</li>
<li class="mui-table-view-cell">第一个选项卡子项-16</li>
<li class="mui-table-view-cell">第一个选项卡子项-17</li>
<li class="mui-table-view-cell">第一个选项卡子项-18</li>
<li class="mui-table-view-cell">第一个选项卡子项-19</li>
<li class="mui-table-view-cell">第一个选项卡子项-20</li>
</ul>
</div>
</div>
<script>
document.getElementById("scroll1").addEventListener("scrollbottom",function(e){
console.info("上拉到底部")
});
document.getElementById("scroll1").addEventListener("scroll",function(e){
console.info("scroll")
if(e.detail.lastY == 0){
console.info("下拉到顶部")
console.info("lastY:"+e.detail.lastY)
console.info("maxScrollY:"+e.detail.maxScrollY)
}else if(e.detail.lastY > 0){
console.info("下拉超过顶部")
console.info("lastY:"+e.detail.lastY)
}
});
</script>
收起阅读 »

在mac下对android版app进行签名
在Android 系统中,所有安装 到 系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个 permission的protectionLevel为signature,那么就只有那些跟该permission所在的程序拥有同一个数字证书的应 用程序才能取得该权限。
Android使用Java的数字证书相关的机制来 给apk加盖数字证书,要理解android的数字证书,需要先了解以下数字证书的概念和java的数字证书机制。
Android系统要求每一个安装进系 统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。
Android将数字证书用来标识应用程序的作者和在应用程序之间建立信 任关系,不是用来决定最终用户可以安装哪些应用程序。
这个数字证书并不需要权威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。
下面我将详细的说一下mac电脑下如何申请数字证书:
(1)先用命令‘sudo -s’ 获得系统权限 Mac终端命令,下载java jdk
(2)java mac 安装路径,我用的是这个:/Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home; 1、Mac OS自带的JDK 6:/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java。看到有朋友说OS 10.10删除了自带的JDK 6,但是我升级10.10之后还是能找到该路径,不知搜索道是否需要重新在苹果网站下载JDK 6呢?
2、Oracle的JDK 7/8 (1)用/usr/libexec/java_home命令得到的Java Home路径是:/Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home,这是我之前在Oracle网站下载的jdk 8 update 20。 (2)在Java控制面板显示的路径:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java,版本是Java 8 update 25。
(3)在cmd下支座android apk 签名时,输入命令:keytool -genkey -alias MyAndroidKey.keystore -keyalg RSA -validity 20000 -keystore MyAndroidKey.keystore,到最后提示keytool 错误: java.io.FileNotFoundException: MyAndroidKey.keystore (拒绝访问).这是因为权限问题:你的jdk目录在c盘,当前用户无写入权限。
所以要么更改jdk的保存目录,要么更改权限。方法一更改保存目录:就是讲jdk从c盘挪到其它盘。方法二更改权限:以管理员身份运行CMD。任意一种修改后,再键入keytool -genkey -alias MyAndroidKey.keystore -keyalg RSA -validity 20000 -keystore MyAndroidKey.keystore,按提示填写即可。
(4)找到本机电脑上jdk安装的目录,使用cmd命令打开命令窗口,输入cd jdk目录(替换成你的jdk的bin目录),进入到jdk的bin目录,接下来你才可以使用jdk的命令进行操作
(5)使用keytool命令,keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore
其中参数-validity为证书有效天数,这里我们写的大些10000天。还有在输入密码时没有回显(尽管输就是啦) 并且 退格,tab等都属于密码内容,这个密码在给.apk文件签名的时候需要。输入这个命令之后会提示您输入秘钥库的口令,接着是会提示你输入:姓氏,组织单位名称,组织名称,城市或区域名称,省市,国家、地区代码,密钥口令。按你自己的设置输入对应的数据就完成了
(6)生成完成之后在jdk的bin目录之下就可以找到生成的keystore文件了,android.keystore就是刚才生成的文件了,打包android应用的时候就可以直接用了,不过一台电脑生成的keystore只能用一个应用。
相关参考:http://jingyan.baidu.com/article/59703552e877f98fc00740f0.html
http://blog.csdn.net/sherrylhang/article/details/50183417
http://zhidao.baidu.com/link?url=O7B4fJC_N0QP8hDvC0DZQFrwICHo5FCHuZNLqgJqubNZ8h4QJ6zyO37z4fCeesQBaombcr6elv7Oj7uIPbCWKqy5hfLZ3zMaVmc066ZbUMO
http://bbs.360safe.com/thread-2932254-1-1.html
在Android 系统中,所有安装 到 系统的应用程序都必有一个数字证书,此数字证书用于标识应用程序的作者和在应用程序之间建立信任关系,如果一个 permission的protectionLevel为signature,那么就只有那些跟该permission所在的程序拥有同一个数字证书的应 用程序才能取得该权限。
Android使用Java的数字证书相关的机制来 给apk加盖数字证书,要理解android的数字证书,需要先了解以下数字证书的概念和java的数字证书机制。
Android系统要求每一个安装进系 统的应用程序都是经过数字证书签名的,数字证书的私钥则保存在程序开发者的手中。
Android将数字证书用来标识应用程序的作者和在应用程序之间建立信 任关系,不是用来决定最终用户可以安装哪些应用程序。
这个数字证书并不需要权威的数字证书签名机构认证,它只是用来让应用程序包自我认证的。
下面我将详细的说一下mac电脑下如何申请数字证书:
(1)先用命令‘sudo -s’ 获得系统权限 Mac终端命令,下载java jdk
(2)java mac 安装路径,我用的是这个:/Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home; 1、Mac OS自带的JDK 6:/System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java。看到有朋友说OS 10.10删除了自带的JDK 6,但是我升级10.10之后还是能找到该路径,不知搜索道是否需要重新在苹果网站下载JDK 6呢?
2、Oracle的JDK 7/8 (1)用/usr/libexec/java_home命令得到的Java Home路径是:/Library/Java/JavaVirtualMachines/jdk1.8.0_20.jdk/Contents/Home,这是我之前在Oracle网站下载的jdk 8 update 20。 (2)在Java控制面板显示的路径:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java,版本是Java 8 update 25。
(3)在cmd下支座android apk 签名时,输入命令:keytool -genkey -alias MyAndroidKey.keystore -keyalg RSA -validity 20000 -keystore MyAndroidKey.keystore,到最后提示keytool 错误: java.io.FileNotFoundException: MyAndroidKey.keystore (拒绝访问).这是因为权限问题:你的jdk目录在c盘,当前用户无写入权限。
所以要么更改jdk的保存目录,要么更改权限。方法一更改保存目录:就是讲jdk从c盘挪到其它盘。方法二更改权限:以管理员身份运行CMD。任意一种修改后,再键入keytool -genkey -alias MyAndroidKey.keystore -keyalg RSA -validity 20000 -keystore MyAndroidKey.keystore,按提示填写即可。
(4)找到本机电脑上jdk安装的目录,使用cmd命令打开命令窗口,输入cd jdk目录(替换成你的jdk的bin目录),进入到jdk的bin目录,接下来你才可以使用jdk的命令进行操作
(5)使用keytool命令,keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore
其中参数-validity为证书有效天数,这里我们写的大些10000天。还有在输入密码时没有回显(尽管输就是啦) 并且 退格,tab等都属于密码内容,这个密码在给.apk文件签名的时候需要。输入这个命令之后会提示您输入秘钥库的口令,接着是会提示你输入:姓氏,组织单位名称,组织名称,城市或区域名称,省市,国家、地区代码,密钥口令。按你自己的设置输入对应的数据就完成了
(6)生成完成之后在jdk的bin目录之下就可以找到生成的keystore文件了,android.keystore就是刚才生成的文件了,打包android应用的时候就可以直接用了,不过一台电脑生成的keystore只能用一个应用。
相关参考:http://jingyan.baidu.com/article/59703552e877f98fc00740f0.html
http://blog.csdn.net/sherrylhang/article/details/50183417
http://zhidao.baidu.com/link?url=O7B4fJC_N0QP8hDvC0DZQFrwICHo5FCHuZNLqgJqubNZ8h4QJ6zyO37z4fCeesQBaombcr6elv7Oj7uIPbCWKqy5hfLZ3zMaVmc066ZbUMO
http://bbs.360safe.com/thread-2932254-1-1.html

MUI 的 Ajax 跨域请求失败
尝试 mui.ajax,发现在网页端无法跨域(不是同源策略,而是405)。
之后在同一页面中试了原生 ajax 和 jQuery 里的,都正常。
调试看区别是
mui 的 request 头里有
Access-Control-Request-Headers:accept, x-requested-with
Access-Control-Request-Method:GET
同时是
OPTIONS
,未被相应。
(知道 CORS 里的 OPTIONS 请求,但这里其他方法都好用,只有 mui 的不行)
跟踪到源码里
setHeader('X-Requested-With', 'XMLHttpRequest');
这一行,注释掉一切正常。
请问有什么区别?
谢谢
MUI v2.8.0
已自己解决。沿用这里的传统,就不说解决方案了……
原文地址:http://ask.dcloud.net.cn/question/16436
尝试 mui.ajax,发现在网页端无法跨域(不是同源策略,而是405)。
之后在同一页面中试了原生 ajax 和 jQuery 里的,都正常。
调试看区别是
mui 的 request 头里有
Access-Control-Request-Headers:accept, x-requested-with
Access-Control-Request-Method:GET
同时是
OPTIONS
,未被相应。
(知道 CORS 里的 OPTIONS 请求,但这里其他方法都好用,只有 mui 的不行)
跟踪到源码里
setHeader('X-Requested-With', 'XMLHttpRequest');
这一行,注释掉一切正常。
请问有什么区别?
谢谢
MUI v2.8.0
已自己解决。沿用这里的传统,就不说解决方案了……
原文地址:http://ask.dcloud.net.cn/question/16436