easyui 插件规范 编写 倒计时demo

/*******************************************************************************
 * @author caihaibin <243008827@qq.com>
 * @version 1.1.1 
 *******************************************************************************/
(function($) {

	function getTxt(target) {
		if($(target).prop("tagName") == 'INPUT') {
			return $(target).val();
		} else {
			return $(target).html();
		}
	}

	/**
	 * 根据按钮类型,自动识别文本字段来自value还是html
	 * @param {targetect} target
	 */
	function setTxt(target, txt) {
		if($(target).prop("tagName") == 'INPUT') {
			//恢复文本
			$(target).val(txt);
		} else {
			//恢复文本
			$(target).html(txt);
		}
	}
	/**
	 * 停止计时器
	 */
	function stop(target) {
		//恢复按键文本
		setTxt(target, $.data(target, 'countdown').data.text);
		//恢复点击
		$(target).removeAttr('disabled');
		//清除计时器对象
		clearInterval($.data(target, 'countdown').data.time_id);
	}

	function bindEvents(target) {
		//绑定点击事件
		//click.xxx为命名空间形式,可以通过unbind('.xxx')一次性解除所有该命名空间下的绑定
		//取消原".countdown"命名空间下,所有绑定事件
		$(target).unbind('.countdown');
		//直接绑定新事件
		$(target).bind('click.countdown', function() {
			var time = $.data(target, 'countdown').options.time;
			//禁止二次点击
			$(target).attr('disabled', 'disabled');
			//获取计时器标志(int类型)
			var time_id = setInterval(function() {
				if(time <= 0) {
					//统一调用计时器插件结束动作
					$(target).countdown('stop');
					$.data(target, 'countdown').options.onEnd();
					return;
				}
				$.data(target, 'countdown').options.onShowtime(target, time, time + '秒');
				//显示倒计时结果
				setTxt(target, time + '秒');
				time--;
			}, 1000);
			//记录计时器标志到对象数据中,用于计时结束时,clear动作
			$.data(target, 'countdown').data.time_id = time_id;
		});
	}

	/**
	 * 初始化计时器插件
	 * @param {Object} options
	 */
	function create(target) {}
	/**
	 * parse options from markup.
	 */
	function parseOptions(target) {
		var t = $(target);
		return $.extend({}, {
			//如果参数内容为空或undefined,不会覆盖前面的内容.如果有值,依次会覆盖前面数组的具体键值
			time: t.attr('time') ? t.attr('time') : undefined
		});
	}
	$.fn.countdown = function(options, param) {
		if(typeof options == 'string') {
			var method = $.fn.countdown.methods[options];
			if(method) {
				return method(this, param);
			}
			$.error('Method ' + options + ' does not exist on jQuery.countdown');
		}
		options = options || {};
		return this.each(function() {
			//实现针对每元素级的函数和变量
			var state = $.data(this, 'countdown');
			if(state) {
				//二次初始化,只覆盖变量,重新绑定事件等..
				$.extend(state.options, options);
			} else {
				state = $.data(this, 'countdown', {
					//该对象所有选项,包括配置参数,传入配置,都存放在options
					//如果参数内容为空或undefined,不会覆盖前面的内容.如果有值,依次会覆盖前面数组的具体键值
					options: $.extend({}, $.fn.countdown.defaults, parseOptions(this), options),
					//该对象所有临时变量
					data: {
						//按钮文本内容,用于复原
						text: getTxt(this),
						//计时器标志,用于clear时,触发
						time_id: 0
					}
				});
			}
			//创建元素,只针对元素部分的调整.需要区分事件和元素的操作
			create(this);
			//绑定相关事件,可重复绑定;重复绑定时,通过事件命名空间进行解除
			bindEvents(this);
		});
	};
	//开放给外部调用动作
	//注:函数内部需要二次调用闭包中所定义函数,jq对象为数组,请求的闭包中的函数动作是单体.
	$.fn.countdown.methods = {
		//解析出参数配置
		parseOptions: function(jq) {
			//参数只需要一份,列表对象中参数相同,所以只需要返回首个
			return parseOptions(jq[0]);
		},
		//返回所配置参数
		options: function(jq) {
			//参数只需要一份,列表对象中参数相同,所以只需要返回首个
			return $.data(jq[0], 'countdown').options;
		},
		//停止计时动作
		stop: function(jq) {
			return jq.each(function() {
				stop(this);
			});
		}
	};
	//外部参数配置,允许参数和函数事件等
	$.fn.countdown.defaults = {
		/**
		 * 默认时长
		 */
		time: 60,
		/**
		 * 计时事件
		 * @param {Object} target
		 * @param {Object} time 当前秒数
		 * @param {Object} txt 秒数文本
		 */
		onShowtime: function(target, time, txt) {},
		/**
		 * 结束事件
		 * @param {Object} target
		 */
		onEnd: function(target) {}
	};
})(jQuery);
<!DOCTYPE html>
<html>

	<head>
		<title>计时器测试</title>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
		<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0">
		<meta name="apple-mobile-web-app-capable" content="yes">
		<meta http-equiv="pragma" content="no-cache">
		<meta http-equiv="cache-control" content="no-cache">
		<meta http-equiv="expires" content="0">
		<script src="scripts/jquery.js"></script>
		<script src="scripts/jquery.countdown.js"></script>
	</head>

	<body>
		<button time="3">3秒倒计时</button>
		<button onclick="$('button[time]').countdown('stop')">取消倒计时</button>
		<input type="button" value="60秒倒计时">
		<button onclick="$('input[type=button]').countdown('stop')">取消倒计时</button>
		<a time="3">a倒计时</a>
		<script>
			$(function() {
				$('input[time],button[time]').countdown({
					onShowtime: function(target, time, txt) {
						console.log(time, txt);
					},
					onEnd: function(target) {
						console.log('end');
					}
				});
				$('a[time]').countdown();
				//				$('a,button,input').css('pointer-events', 'none');
			})
		</script>
	</body>

</html>

 

纯代码编写拖动加载

iscroll 功能强大,也只能在手机下面用。pc只能模仿个差不多的东西。

不过iscroll的东西,只能在单独的页面好用,如果添加太多东西,得到的效果和付出的代价划不来,只能手动编写一个。支持手机pc,因为是纯jq,没有兼容问题

<div class='indexList'>
	<!-- 数据集合 -->
</div>
<!-- 用于放置底部,当滚动条超过这个时,触发相关动作,实现拖动加载,手机本身有滚动特效,同样以滚动条滚动做为媒介 -->
<div id="gd_iscroll_bottom"
	style="height: 25px; font-size: 16px; visibility: hidden; overflow: hidden; width: 100%; text-align: center;">
	下拉加载更多</div>

 

	//仿php时间函数
	function time() {
		return Math.floor(new Date().getTime() / 1000);
	}
	//分页的索引页面
	var shop_page_index = 1;
	//滚动的记录时间,用来识别滚动时间,当停止滚动时触发对应函数
	var is_on_scroll_time = 0;
	//加载数据已经结束
	//当数据加载结束,不进行二次加载
	var is_load_end = 0;
	//用于触摸设备,判断是否触摸和离开,离开状态下才进行数据加载
	var is_mobile_touch = false;
	setInterval(function() {
                //时间阀值,当滚动触发时,超过3秒,则表示用户停止滚动,触发对应的加载事件
		if (!is_mobile_touch && is_on_scroll_time
				&& is_on_scroll_time - time() <= 3) {
			console.log('is stop');
			is_on_scroll_time = 0;
			$('#gd_iscroll_bottom').html('加载中...');
			//停止动画链表执行
			$('body').stop(true);
			//调用目标地址加载数据
			$.post('xxxxxx', {
				page : shop_page_index
			}, function(result) {
				var htmlstr = '';
				for (i = 0; i < result.length; i++) {
					model = result[i];
					//拼接数据
					$('.indexList').append('xxx');
				}
				//当返回为空时,不进行数据触发和加载
				if (result.length == 0) {
					$('#gd_iscroll_bottom').html('暂无更多数据...');
					$('body')
							.animate(
									{
										scrollTop : $('#gd_iscroll_bottom')
												.offset().top
												- $(window).height()
									}, 1200);
				} else {
					shop_page_index++;
				}
				//$('.indexList').append($('.indexList').html());
				//$('body').animate({scrollTop:$('#gd_iscroll_bottom').offset().top-$(window).height()}, 1200);
			}, 'json');
		}
	}, 1000);
	$(document)
			.ready(
					function() {
						$(window)
								.scroll(
										function() {
											//滚动条超过底部加载条时,记录
											if ($(window).height()
													+ $(window).scrollTop() >= $(
													'#gd_iscroll_bottom')
													.offset().top
													+ $('#gd_iscroll_bottom')
															.height()) {
												//记录当前滚动时间,用于判断用户是否停止鼠标滚动
												is_on_scroll_time = time();
												console
														.log('gd event on bottom');
												$('body').stop(true);
												//$('body').animate({scrollTop:$('#gd_iscroll_bottom').offset().top-$(window).height()}, 800)
											} else if ($(window).height()
													+ $(window).scrollTop() < $(
													'#gd_iscroll_bottom')
													.offset().top) {
												//当用户滚动到底部,又直接往上拖动时,停止相关触发,否则当上拉时,动画会自动往下拖动
												is_on_scroll_time = 0;
												//停止页面滚动特效
												$('body').stop(true);
											}
										});
					});
	//手机触摸相关触发
	function load() {
		document.addEventListener('touchstart', touch, false);
		document.addEventListener('touchmove', touch, false);
		document.addEventListener('touchend', touch, false);
		function touch(event) {
			var event = event || window.event;
			switch (event.type) {
			case "touchstart"://用户触摸中
				is_mobile_touch = true;
				break;
			case "touchend":
				//用户释放
				is_mobile_touch = false;
				break;
			case "touchmove":
				//event.preventDefault();
				break;
			}

		}
	}
	try {
		window.addEventListener('load', load, false);
	} catch (e) {
		//不是手机
	}

 

重写WeixinApi.js 兼容原代码

官方文档

http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html

为了兼容原来的代码,重写WeixinApi的js,只处理分享的部分….

/**
 * ! 微信内置浏览器的Javascript API,功能包括:
 * 
 * 1、分享到微信朋友圈 2、分享给微信好友 3、分享到腾讯微博 4、隐藏/显示右上角的菜单入口 5、隐藏/显示底部浏览器工具栏 6、获取当前的网络状态
 * 7、调起微信客户端的图片播放组件 8、关闭公众平台Web页面
 * 
 * @author zhaoxianlie(http://www.baidufe.com)
 * 
 * @author caihaibin 1.只重写分享部分,兼容原代码
 */
var WeixinApi = (function() {

	"use strict";
	/**
	 * 分享到微信朋友圈
	 * 
	 * @param {Object}
	 *            data 待分享的信息
	 * @p-config {String} appId 公众平台的appId(服务号可用)
	 * @p-config {String} imageUrl 图片地址
	 * @p-config {String} link 链接地址
	 * @p-config {String} desc 描述
	 * @p-config {String} title 分享的标题
	 * 
	 * @param {Object}
	 *            callbacks 相关回调方法
	 * @p-config {Boolean} async ready方法是否需要异步执行,默认false
	 * @p-config {Function} ready(argv) 就绪状态
	 * @p-config {Function} dataLoaded(data) 数据加载完成后调用,async为true时有用,也可以为空
	 * @p-config {Function} cancel(res) 取消
	 * @p-config {Function} fail(res) 失败
	 * @p-config {Function} confirm(res) 成功
	 * @p-config {Function} all(res) 无论成功失败都会执行的回调
	 */
	function weixinShareTimeline(data, callbacks) {
		callbacks = callbacks || {};
		var theData = data;
		wx.onMenuShareTimeline({
			title : theData.title,
			desc : theData.desc,
			link : theData.link,
			imgUrl : theData.imgUrl,
			trigger : function(res) {
				callbacks.ready && callbacks.ready(res);
			},
			success : function(res) {
				callbacks.confirm && callbacks.confirm(res);
			},
			cancel : function(res) {
				callbacks.cancel && callbacks.cancel(res);
			},
			fail : function(res) {
				callbacks.fail && callbacks.fail(res);
			}
		});
	}

	/**
	 * 发送给微信上的好友
	 * 
	 * @param {Object}
	 *            data 待分享的信息
	 * @p-config {String} appId 公众平台的appId(服务号可用)
	 * @p-config {String} imageUrl 图片地址
	 * @p-config {String} link 链接地址
	 * @p-config {String} desc 描述
	 * @p-config {String} title 分享的标题
	 * 
	 * @param {Object}
	 *            callbacks 相关回调方法
	 * @p-config {Boolean} async ready方法是否需要异步执行,默认false
	 * @p-config {Function} ready(argv) 就绪状态
	 * @p-config {Function} dataLoaded(data) 数据加载完成后调用,async为true时有用,也可以为空
	 * @p-config {Function} cancel(res) 取消
	 * @p-config {Function} fail(res) 失败
	 * @p-config {Function} confirm(res) 成功
	 * @p-config {Function} all(res) 无论成功失败都会执行的回调
	 */
	function weixinSendAppMessage(data, callbacks) {
		callbacks = callbacks || {};
		var theData = data;
		wx.onMenuShareAppMessage({
			title : theData.title,
			desc : theData.desc,
			link : theData.link,
			imgUrl : theData.imgUrl,
			trigger : function(res) {
				callbacks.ready && callbacks.ready(res);
			},
			success : function(res) {
				callbacks.confirm && callbacks.confirm(res);
			},
			cancel : function(res) {
				callbacks.cancel && callbacks.cancel(res);
			},
			fail : function(res) {
				callbacks.fail && callbacks.fail(res);
			}
		});
	}

	/**
	 * 分享到腾讯微博
	 * 
	 * @param {Object}
	 *            data 待分享的信息
	 * @p-config {String} imageUrl 图片地址
	 * @p-config {String} link 链接地址
	 * @p-config {String} desc 描述
	 * @p-config {String} title 分享的标题
	 * 
	 * @param {Object}
	 *            callbacks 相关回调方法
	 * @p-config {Boolean} async ready方法是否需要异步执行,默认false
	 * @p-config {Function} ready(argv) 就绪状态
	 * @p-config {Function} dataLoaded(data) 数据加载完成后调用,async为true时有用,也可以为空
	 * @p-config {Function} cancel(res) 取消
	 * @p-config {Function} fail(res) 失败
	 * @p-config {Function} confirm(res) 成功
	 * @p-config {Function} all(res) 无论成功失败都会执行的回调
	 */
	function weixinShareWeibo(data, callbacks) {
		callbacks = callbacks || {};
		var theData = data;
		wx.onMenuShareWeibo({
			title : theData.title,
			desc : theData.desc,
			link : theData.link,
			imgUrl : theData.imgUrl,
			trigger : function(res) {
				callbacks.ready && callbacks.ready(res);
			},
			success : function(res) {
				callbacks.confirm && callbacks.confirm(res);
			},
			cancel : function(res) {
				callbacks.cancel && callbacks.cancel(res);
			},
			fail : function(res) {
				callbacks.fail && callbacks.fail(res);
			}
		});
	}

	/**
	 * 分享到腾讯微博
	 * 
	 * @param {Object}
	 *            data 待分享的信息
	 * @p-config {String} imageUrl 图片地址
	 * @p-config {String} link 链接地址
	 * @p-config {String} desc 描述
	 * @p-config {String} title 分享的标题
	 * 
	 * @param {Object}
	 *            callbacks 相关回调方法
	 * @p-config {Boolean} async ready方法是否需要异步执行,默认false
	 * @p-config {Function} ready(argv) 就绪状态
	 * @p-config {Function} dataLoaded(data) 数据加载完成后调用,async为true时有用,也可以为空
	 * @p-config {Function} cancel(res) 取消
	 * @p-config {Function} fail(res) 失败
	 * @p-config {Function} confirm(res) 成功
	 * @p-config {Function} all(res) 无论成功失败都会执行的回调
	 */
	function onMenuShareQQ(data, callbacks) {
		callbacks = callbacks || {};
		var theData = data;
		wx.onMenuShareQQ({
			title : theData.title,
			desc : theData.desc,
			link : theData.link,
			imgUrl : theData.imgUrl,
			trigger : function(res) {
				callbacks.ready && callbacks.ready(res);
			},
			success : function(res) {
				callbacks.confirm && callbacks.confirm(res);
			},
			cancel : function(res) {
				callbacks.cancel && callbacks.cancel(res);
			},
			fail : function(res) {
				callbacks.fail && callbacks.fail(res);
			}
		});
	}

	/**
	 * 调起微信Native的图片播放组件。 这里必须对参数进行强检测,如果参数不合法,直接会导致微信客户端crash
	 * 
	 * @param {String}
	 *            curSrc 当前播放的图片地址
	 * @param {Array}
	 *            srcList 图片地址列表
	 */
	function imagePreview(curSrc, srcList) {
		if (!curSrc || !srcList || srcList.length == 0) {
			return;
		}
		WeixinJSBridge.invoke('imagePreview', {
			'current' : curSrc,
			'urls' : srcList
		});
	}

	/**
	 * 显示网页右上角的按钮
	 */
	function showOptionMenu() {
		WeixinJSBridge.call('showOptionMenu');
	}

	/**
	 * 隐藏网页右上角的按钮
	 */
	function hideOptionMenu() {
		WeixinJSBridge.call('hideOptionMenu');
	}

	/**
	 * 显示底部工具栏
	 */
	function showToolbar() {
		WeixinJSBridge.call('showToolbar');
	}

	/**
	 * 隐藏底部工具栏
	 */
	function hideToolbar() {
		WeixinJSBridge.call('hideToolbar');
	}

	/**
	 * 返回如下几种类型:
	 * 
	 * network_type:wifi wifi网络 network_type:edge 非wifi,包含3G/2G
	 * network_type:fail 网络断开连接 network_type:wwan 2g或者3g
	 * 
	 * 使用方法: WeixinApi.getNetworkType(function(networkType){
	 * 
	 * });
	 * 
	 * @param callback
	 */
	function getNetworkType(callback) {
		if (callback && typeof callback == 'function') {
			WeixinJSBridge.invoke('getNetworkType', {}, function(e) {
				// 在这里拿到e.err_msg,这里面就包含了所有的网络类型
				callback(e.err_msg);
			});
		}
	}

	/**
	 * 关闭当前微信公众平台页面
	 */
	function closeWindow() {
		WeixinJSBridge.call("closeWindow");
	}

	/**
	 * 当页面加载完毕后执行,使用方法: WeixinApi.ready(function(Api){ // 从这里只用Api即是WeixinApi
	 * });
	 * 
	 * @param readyCallback
	 */
	function wxJsBridgeReady(readyCallback) {
		if (readyCallback && typeof readyCallback == 'function') {
			var Api = this;
			// 当在微信中时,才进行签名处理.
			if (Api.inWeixin) {
				/**
				 * 需要引用jquery weixinjs_url 获取当前url的签名参数
				 */
				$.post('http://xxxxxxxx/weixinjs/index', {
					weixinjs_url : location.href
				}, function(result) {
					wx.config(result.obj);
				}, 'json');
			}
			var wxReadyFunc = function() {
				readyCallback(Api);
			};
			wx.ready(wxReadyFunc);
			return;
		}
	}
	return {
		version : "1.6",
		ready : wxJsBridgeReady,
		shareToTimeline : weixinShareTimeline,
		shareToWeibo : weixinShareWeibo,
		shareToFriend : weixinSendAppMessage,
		shareToQq : onMenuShareQQ,
		showOptionMenu : showOptionMenu,
		hideOptionMenu : hideOptionMenu,
		showToolbar : showToolbar,
		hideToolbar : hideToolbar,
		getNetworkType : getNetworkType,
		imagePreview : imagePreview,
		closeWindow : closeWindow,
		// 在微信内才进行签名判断.
		inWeixin : navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == "micromessenger"
	};
})();

 

jssdk.php

替换

JSSDK::getSignPackage()
	public function getSignPackage() {
		$jsapiTicket = $this->getJsApiTicket ();
		$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
		// 通过外部参数进行目标的url的签名
		if ($_REQUEST ['weixinjs_url']) {
			$url = $_REQUEST ['weixinjs_url'];
		}
		$timestamp = time ();
		$nonceStr = $this->createNonceStr ();

		// 这里参数的顺序要按照 key 值 ASCII 码升序排序
		$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";

		$signature = sha1 ( $string );

		$signPackage = array (
				"appId" => $this->appId,
				"nonceStr" => $nonceStr,
				"timestamp" => $timestamp,
				"url" => $url,
				"signature" => $signature,
				"rawString" => $string 
		);
		return $signPackage;
	}

服务器端签名

	public function actionIndex() {
		if ($_SERVER ['HTTP_ORIGIN'])
			header ( "Access-Control-Allow-Origin: " . $_SERVER ['HTTP_ORIGIN'] );
		header ( "Access-Control-Allow-Credentials: true" );
		$title = '微信签名相关';
		lib ( "weixin/js/jssdk.php" );
		$jssdk = new JSSDK ( "xxxxxxxx", "xxxxxxx" );
		$signPackage = $jssdk->GetSignPackage ();
		$result = array (
				'appId' => $signPackage ["appId"],
				'timestamp' => $signPackage ["timestamp"],
				'nonceStr' => $signPackage ["nonceStr"],
				'signature' => $signPackage ["signature"],
				'jsApiList' => array (
						'onMenuShareAppMessage',
						'onMenuShareTimeline',
						'onMenuShareQQ',
						'onMenuShareWeibo' 
				) 
		);
		sjson ( true, $title, '', $result );
	}

调用方式

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<!-- 重写后的 js-->
<script src="http://xxxxxx/js/WeixinApi.js"></script>
<!-- 
原来代码不用进行调整,方便修复.如果代码有问题,也可以对WeixinApi.js进行统一修改
 -->

 

ajax 跨域cookie问题 (CORS support in a browser)

介绍

http://software.dzhuvinov.com/cors-filter-tips.html

封装好的js

https://github.com/dkastner/jquery.iecors

请求头部分的设置参考

HTML5 跨域提交和上传实现 及 nginx $_SERVER[‘HTTP_X_FILENAME’]解决

请求头时不可以直接设置:

Access-Control-Allow-Headers: *

不然会冲突下面配置

$.ajax({
	url : 'http://xxxxxx',
	xhrFields : {
		withCredentials : true
	},
	crossDomain : true,
	success : function(result) {
		alert('ajax调用成功' + result)
	}
});

withCredentials 开启时,跨与登录的cookie才会记录到域名中.

如a 域名调用 b域名。b域名中才会记录对应的cookie,否则即使在chrome中看到成功返回cookie,直接访问b时,会不存在。

且withCredentials 只支持html5特性的浏览器 ie8需要参考上面的处理

 

 

 

yii kindeditor sessionid丢失问题

主要原因是kindeditor 中使用了swfupload ,而ff调用时,不会使用浏览器当前的cookie。

chrome也尝试过,通过切换不同的flash,会导致该情况发生。

如果flash上传不法传递cookie,则通过post该参数,并替换成原来的session即可.

http://kindeditor.net/docs/option.html#extrafileuploadparams

KindEditor.ready(function(K) {
        K.create('#id', {
                extraFileUploadParams : {
                        GDSESSION_ID : 'XXXXXXXXXXX'
                }
        });
});

yii 端根据session_id切换session代码

/**
 * 直接识别文件类型,修改上传文件扩展,防止缩略变形
 */
class EditorController extends CController {

	public function init() {
		// 切换session 修复部分不支持 flash cookie的浏览器,暂时发现ff
		if (isset ( $_REQUEST ['GDSESSION_ID'] ) && $_REQUEST ['GDSESSION_ID'] != Yii::app ()->session->getSessionID ()) {
			Yii::app ()->session->destroy ();
			Yii::app ()->session->setSessionID ( $_REQUEST ['GDSESSION_ID'] );
			// Yii::app ()->session->open ();
		}
	}
....

 

 

微信实现视频在线播放

pc端可用在线直播方式 mms

安卓端可用 rtsp 协议.

但是微信页面,即htm5 video 不支持上述协议。即使开启flash(微信内置浏览器不支持flash,在uc下测试)。本身也无效。调整。

苹果ios类支持自己实现的HLS协议,即后缀为 m3u8 协议的格式,具体实现原理看。

http://blog.csdn.net/andy1219111/article/details/8863506

 

后经测试,发现本身android 4.0以上版本就可以支持HLS ,

具体兼容支持图表看。

http://www.jwplayer.com/html5/hls/

 

尝试正常,除个别手机如三星 s4 这类播放时,由于可以高度识别问题。导致屏幕只有宽度,没高度,播放正常等问题。直接设置高度比即可。

微信测试结果。正常。因为微信的内置浏览器新版本基本上相同,主要是浏览器的内置限制。所以本身不用太担心兼容的问题。或者说,只要新版本测试基本上不用担心一些奇怪的限制,虽然微信的限制本身就比较奇怪。

举例,版本以5.3为准:

视频播放。加载时可以触发播放,本身开启属性autoplay也是可以的,但是通过按钮事件触发的全屏可以触发,但是直接js触发又不行。会报dom exception 11的异常。

结:

目前主要的测试平台为android和iphone。因为本身ios支持的,只测试一个就不用担心了,android各有差异,但是暂时没有发现哪部手机不可播放。

 

补充一个比较有意思的实现,仅供参考:

http://blog.segmentfault.com/xingrz/1190000000392586?page=1#c-1190000000392586-1050000000393206

 

 

 

生成随机身份证和中文名

中文名:

var originalString='赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮卞齐康伍余元卜顾孟平黄和穆萧尹姚邵湛汪祁毛禹狄米贝明臧计伏成戴谈宋茅庞熊纪舒屈项祝董梁杜阮蓝闵席季麻强贾路娄危江童颜郭梅盛林刁钟徐邱骆高夏蔡田樊胡凌霍虞万支柯昝管卢莫柯房裘缪干解应宗丁宣贲邓郁单杭洪包诸左石崔吉钮龚程嵇邢滑裴陆荣翁荀羊于惠甄曲家封芮羿储靳汲邴糜松井段富巫乌焦巴弓牧隗山谷车侯宓蓬全郗班仰秋仲伊宫宁仇栾暴甘钭历戎祖武符刘景詹束龙叶幸司韶郜黎蓟溥印宿白怀蒲邰从鄂索咸籍赖卓蔺屠蒙池乔阳郁胥能苍双闻莘党翟谭贡劳逄姬申扶堵冉宰郦雍却璩桑桂濮牛寿通边扈燕冀浦尚农温别庄晏柴瞿阎充慕连茹习宦艾鱼容向古易慎戈廖庾终暨居衡步都耿满弘匡国文寇广禄阙东欧殳沃利蔚越夔隆师巩厍聂晁勾敖融冷訾辛阚那简饶空曾毋沙乜养鞠须丰巢关蒯相查后荆红游竺权逮盍益桓公万俟司马上官欧阳夏侯诸葛闻人东方赫连皇甫尉迟公羊澹台公冶宗政濮阳淳于单于太叔申屠公孙仲孙轩辕令狐徐离宇文长孙慕容司徒司空';
function getStr(){
	var tmp="";
	for(var i=0;i<3;i++)
	{
	var stringLength=Math.random()*originalString.length;
	tmp+=originalString.charAt(Math.ceil(stringLength)%originalString.length);
	}
	return tmp;
}

身份证号:

// /地区编码
	var city = new Array("110113","120223","130403","130425","130433","130731","131000","131023","131024","131081","140106","140222","140226","140227","140524","140600","140828","140922","140981","141129","141130","150426","150525","150727","152525","210201","210300","210801","211101","220103","220182","220203","220323","220500","220821","222400","230108","230307","230703","230710","230833","231003","231222","231223","231281","232721","232722","320201","320302","320503","320584","320724","320831","320902","320982","321003","321081","321181","321201","330000","330108","330122","330183","330205","330225","330411","330600","330723","340103","340207","340301","340603","340802","341221","341421","341521","341822","350206","350427","350526","350721","360421","360425","360428","370105","370611","370685","370687","370883","370900","370921","371311","371422","371424","410302","410782","411081","411421","420607","420800","420900","430102","430122","430225","430301","430401","430511","430624","430922","431027","431127","431201","440306","440703","440923","441400","441821","441827","441882","445321","450100","450224","450521","450701","450923","450981","451022","451029","451421","451424","460200","500232","500237","510106","510112","510183","510503","510601","510683","510903","511524","511602","511823","513224","513229","513328","520300","520326","522422","522633","522700","530103","530501","530702","532600","532622","533324","542100","542125","542227","542322","542331","542421","542424","542525","542626","610301","610429","610528","610702","610901","610926","620524","620901","621124","621201","621226","623026","632126","632523","632821","652300","652901","653000","653022","653121","653123","653128","653200","654021"
	);

	var pow = new Array("7","9","10","5","8","4","2","1","6","3","7","9","10","5","8","4","2");
	var ex = new Array("1","0","X","9","8","7","6","5","4","3","2");

	// /年月日
	function getYMD() {
	    var ymd = "";
	    var y =  parseInt(Math.random() * 99);
	    if(y < 10)y = "0" + y;
	    y = "19" + y;
	    var m =  parseInt(Math.random() * 13);
	    if(m < 10)m = "0" + m;
	    if(m == "00")m = "01";
	    var d =  parseInt(Math.random() * 28);
	    if(d < 10) d = "0" + d;
	    if(d == "00") d = "01";
	    ymd = "" + y + m + d;
	    return ymd;
	}

	//生成号码
	function makeId(){
	    var idcard;
	    idcard = city[parseInt(Math.random() * 189)]
	    + getYMD()
	    + parseInt(Math.random() * 9)       //
	    + parseInt(Math.random() * 9)       //
	    + parseInt(Math.random() * 9);      //

	    var sum = 0;
	    for(var i = 0;i < idcard.length;i++){
	        sum += parseInt(idcard.substring(i,i + 1)) * parseInt(pow[i]);
	    }
	    return  idcard + ex[sum % 11];
	}

 

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

详解discuz 之 *_ctrl_menu

默认的html中的select标签默认的样式太一般了。discuz提供了一个自动将select转换成一个js的select函数。
原理是将select隐藏,在原位置生成一个标签,对应的,当点击时,显示对应生成的

形式的新列表。这个看起来就好看多啦。


方法原js:staticjscommon.js
 
方法名:function simulateSelect(selectId, widthvalue)
 

只需将当前的select的id放入该函数。如:simulateSelect(‘types’),就生成了。

显示和隐藏菜单的方法是:function showMenu(v)

隐藏菜单的方法是:function hideMenu(attr, mtype)

这两个方法主要通过JSMENU[‘active’] 进行关联(也就是说可以多个),在显示时,插入数据,在不显示时,再从集合中删除数据。

如何实现动态的显示这个菜单插件?

因为生成只要套方法,是很容易的。

但是动态生成时,得注意几个东西。

1.discuz中,该东西是以一次执行为前提的。即是,一个select只能执行一次,多次执行转换是不成功的。

2.注要问题是相关的id重复,导致相关的事件对象异常。

知道原因的问题,现在好处理啦。

只要在执行前将原对象抹杀,数据清除就ok了。

如有不懂。可以查看martoo.cn的发贴。

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827

discuz中ajax的简单使用

discuz 做为一个顶级的php开源论坛,对ajax的支持是肯定的。
封装Ajax的原始对象在/static/js/common.js 中

函数名为:

/**
*
* recvType 请求的类型
* waitId 和进行等待提示的目标id
* return
*/
function Ajax(recvType, waitId)

声明一个ajax对象
var x = new Ajax("HTML");
执行get方法。类型jquery的操作。
x.get(url, function (s) {

});

 

转发请注明出处http://blog.martoo.cn
如有漏缺,请联系我 QQ 243008827