HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

[源码] MCalenda 基于MUI的日历插件,史上最精简

插件 日历 Calenda 源码

正要用个日历插件,发现mui并没有,基于JQuery的插件都太重了,在我的小米手机上居然会有卡顿。
初学mui, 于是开始造轮子, 目标是抛弃所有依赖和花哨,纯精简,速度快,
先把Demo发布了,慢慢会增加week/day View和事件支持。

实例:

var MC = mui("#container").MCalendar();  
MC.changeDate(new Date())  
MC.hide()  
MC.show()  
MC.getDate()

源码在此:这能不能加精啊?
MCalendar源码

截图:

继续阅读 »

正要用个日历插件,发现mui并没有,基于JQuery的插件都太重了,在我的小米手机上居然会有卡顿。
初学mui, 于是开始造轮子, 目标是抛弃所有依赖和花哨,纯精简,速度快,
先把Demo发布了,慢慢会增加week/day View和事件支持。

实例:

var MC = mui("#container").MCalendar();  
MC.changeDate(new Date())  
MC.hide()  
MC.show()  
MC.getDate()

源码在此:这能不能加精啊?
MCalendar源码

截图:

收起阅读 »

微信支付服务端代码 .net C# MVC

技术分享

研究了很多demo示例,最后整理出了如下的.net MVC版本的微信支付服务端代码,亲测可行,服务端所需要的其他类文件我已经打包存附件了,需要的可以下载使用
以下只实现了基础功能,如果有什么问题还请大神们多多指教。

服务端代码:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using WeddingCarService.Models;  
using Newtonsoft.Json;  
using System.Text;  
using System.Xml;  
using System.Collections;  
using System.Text.RegularExpressions;  
using System.Reflection;  
using WxPayAPI;  
using WeddingCarService.WXPay;  

namespace WeddingCarService.Controllers  
{  
    public class Wx_Pay_Model  
    {  
        public int retcode { get; set; }  
        public string retmsg { get; set; }  
        public string appid { get; set; }  
        public string noncestr { get; set; }  
        public string package { get; set; }  
        public string partnerid { get; set; }  
        public string prepayid { get; set; }  
        public string timestamp { get; set; }  
        public string sign { get; set; }  
    }  
    public class wxPayController : Controller  
    {  

        public static string mchid = "11111"; //mchid  
        public static string appId = "11111"; //appid  
        public static string appsecret = "11111"; //appsecret  
        public static string appkey = "11111"; //paysignkey(非appkey 在微信商户平台设置 (md5)111111111111)    
        public static string notify_url = Common.CommonDefine.ServerPath + "/wxpay/wxtNotify"; //支付完成后的回调处理页面  
        //  
        // GET: /wxPay/  

        public ActionResult Index()  
        {  
            return View();  
        }  

        /// <summary>  
        /// 微信支付主体接口  
        /// </summary>  
        /// <returns></returns>  
        public ActionResult wxpay()  
        {  
            //************************************************支付参数接收********************************  
            ///获取金额  
            string amount = Request.QueryString["_amount"];  
            string sp_billno = string.IsNullOrEmpty(Request.QueryString["_orderid"]) ? DateTime.Now.ToString("yyyyMMddhhmmssffff") : Request.QueryString["_orderid"];  
            string detail = Request.QueryString["_detail"];  
            double dubamount;  
            double.TryParse(amount, out dubamount);  
            //根据appid和appappsecret获取refresh_token  
            //string url_token = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, appsecret);  
            //string returnStr = tokenservice.GetToken(appId, appsecret);  
            //时间戳  
            var timeStamp = TenpayUtil.getTimestamp();  
            //随机验证码  
            var nonceStr = TenpayUtil.getNoncestr();  

            //****************************************************************获取预支付订单编号***********************  
            //设置package订单参数  
            Hashtable packageParameter = new Hashtable();  
            packageParameter.Add("appid", appId);//开放账号ID    
            packageParameter.Add("mch_id", mchid); //商户号  
            packageParameter.Add("nonce_str", nonceStr); //随机字符串  
            packageParameter.Add("body", detail); //商品描述      
            packageParameter.Add("out_trade_no", sp_billno); //商家订单号   
            packageParameter.Add("total_fee", (dubamount*100).ToString()); //商品金额,以分为单位      
            packageParameter.Add("spbill_create_ip", Request.UserHostAddress); //订单生成的机器IP,指用户浏览器端IP    
            packageParameter.Add("notify_url", notify_url); //接收财付通通知的URL    
            packageParameter.Add("trade_type", "APP");//交易类型    
            packageParameter.Add("fee_type", "CNY"); //币种,1人民币   66    
            //获取签名  
            var sign = CreateMd5Sign("key", appkey, packageParameter, Request.ContentEncoding.BodyName);  
            //拼接上签名  
            packageParameter.Add("sign", sign);  
            //生成加密包的XML格式字符串  
            string data = parseXML(packageParameter);  
            //调用统一下单接口,获取预支付订单号码  
            string prepayXml = HttpUtil.Send(data, "https://api.mch.weixin.qq.com/pay/unifiedorder");  

            //获取预支付ID  
            var prepayId = string.Empty;  
            var xdoc = new XmlDocument();  
            xdoc.LoadXml(prepayXml);  
            XmlNode xn = xdoc.SelectSingleNode("xml");  
            XmlNodeList xnl = xn.ChildNodes;  
            if (xnl.Count > 7)  
            {  
                prepayId = xnl[7].InnerText;  
            }  

            //**************************************************封装调起微信客户端支付界面字符串********************  
            //设置待加密支付参数并加密  
            Hashtable paySignReqHandler = new Hashtable();  
            paySignReqHandler.Add("appid", appId);  
            paySignReqHandler.Add("partnerid", mchid);  
            paySignReqHandler.Add("prepayid", prepayId);  
            paySignReqHandler.Add("package", "Sign=WXPay");  
            paySignReqHandler.Add("noncestr", nonceStr);  
            paySignReqHandler.Add("timestamp", timeStamp);  
            var paySign = CreateMd5Sign("key", appkey, paySignReqHandler, Request.ContentEncoding.BodyName);  

            //设置支付包参数  
            Wx_Pay_Model wxpaymodel = new Wx_Pay_Model();  
            wxpaymodel.retcode = 0;//5+固定调起参数  
            wxpaymodel.retmsg = "ok";//5+固定调起参数  
            wxpaymodel.appid = appId;//AppId,微信开放平台新建应用时产生  
            wxpaymodel.partnerid = mchid;//商户编号,微信开放平台申请微信支付时产生  
            wxpaymodel.prepayid = prepayId;//由上面获取预支付流程获取  
            wxpaymodel.package = "Sign=WXpay";//APP支付固定设置参数  
            wxpaymodel.noncestr = nonceStr;//随机字符串,  
            wxpaymodel.timestamp = timeStamp;//时间戳  
            wxpaymodel.sign = paySign;//上面关键参数加密获得  
            //将参数对象直接返回给客户端  
            return Json(new { msg = "", result = wxpaymodel }, JsonRequestBehavior.AllowGet);  
        }  

        /// <summary>  
        /// 将类对象拼接成调起支付字符串  
        /// </summary>  
        /// <param name="_model"></param>  
        /// <returns></returns>  
        private string ReSetPayString(Wx_Pay_Model _model)  
        {  
            StringBuilder strpay = new StringBuilder();  
            PropertyInfo[] props = _model.GetType().GetProperties();  
            strpay.Append("{");  
            foreach (PropertyInfo property in props)  
            {  
                strpay.Append(property.Name + ":\""+property.GetValue(_model, null).ToString()+"\",");  
            }  
            strpay.Remove(strpay.Length - 1, 1);  
            strpay.Append("}");  
            return strpay.ToString();  
        }  

        /// <summary>  
        /// 输出XML  
        /// </summary>  
        /// <returns></returns>  
        public string parseXML(Hashtable _parameters)  
        {  
            var sb = new StringBuilder();  
            sb.Append("<xml>");  
            var akeys = new ArrayList(_parameters.Keys);  
            foreach (string k in akeys)  
            {  
                var v = (string)_parameters[k];  
                if (Regex.IsMatch(v, @"^[0-9.]$"))  
                {  
                    sb.Append("<" + k + ">" + v + "</" + k + ">");  
                }  
                else  
                {  
                    sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">");  
                }  
            }  
            sb.Append("</xml>");  
            return sb.ToString();  
        }  

        /// <summary>  
        /// 创建package签名  
        /// </summary>  
        /// <param name="key">密钥键</param>  
        /// <param name="value">财付通商户密钥(自定义32位密钥)</param>  
        /// <returns></returns>  
        public virtual string CreateMd5Sign(string key, string value, Hashtable parameters, string _ContentEncoding)  
        {  
            var sb = new StringBuilder();  
            //数组化键值对,并排序  
            var akeys = new ArrayList(parameters.Keys);  
            akeys.Sort();  
            //循环拼接包参数  
            foreach (string k in akeys)  
            {  
                var v = (string)parameters[k];  
                if (null != v && "".CompareTo(v) != 0  
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)  
                {  
                    sb.Append(k + "=" + v + "&");  
                }  
            }  
            //最后拼接商户自定义密钥  
            sb.Append(key + "=" + value);  
            //加密  
            string sign = MD5Util.GetMD5(sb.ToString(), _ContentEncoding).ToUpper();  
            //返回密文  
            return sign;  
        }  

        /// <summary>  
        /// 日志记录工具类  
        /// </summary>  
        /// <param name="pathWrite"></param>  
        /// <param name="content"></param>  
        public static void WriteFile(string pathWrite, string content)  
        {  
            try  
            {  
                if (System.IO.File.Exists(pathWrite))  
                {  
                    //System.IO.File.Delete(pathWrite);  
                }  
                else  
                {  
                    System.IO.File.Create(pathWrite);  
                }  
                System.IO.File.AppendAllText(pathWrite, content + "\r\n----------------------------------------\r\n",  
                    Encoding.GetEncoding("utf-8"));  
            }  
            catch (Exception e)  
            {  

            }  
        }  

        /// <summary>  
        /// 微信支付异步回调方法  
        /// </summary>  
        /// <returns></returns>  
        public ActionResult wxtNotify()  
        {  
            ResultNotify resultNotify = new ResultNotify(Request);  
            resultNotify.ProcessNotify();  
            return Json(new { msg = "成功" }, JsonRequestBehavior.AllowGet);  
        }  
    }  
}  

客户端代码:  
<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <script src="js/mui.min.js"></script>  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
            var channel = null;  
            var channels = null;  
             // 1. 获取支付通道  
            function plusReady() {  
                // 获取支付通道  
                plus.payment.getChannels(function(cs) {  
                    channels = cs;  
                }, function(e) {  
                    alert("获取支付通道失败:" + e.message);  
                });  
            }  
            document.addEventListener('plusready', plusReady, false);  
            var ALIPAYSERVER = 'http://demo.dcloud.net.cn/helloh5/payment/alipay.php?total=';  
            var WXPAYSERVER = 'http://192.168.3.141/wxPay/wxpay';  
            /*var WXPAYSERVER = 'http://demo.dcloud.net.cn/payment/?payid=wxpay&appid=HBuilder&total=1';*/  
             // 2. 发起支付请求  
            function pay(id) {  
                // 从服务器请求支付订单  
                var PAYSERVER = '';  
                if (id == 'alipay') {  
                    PAYSERVER = ALIPAYSERVER;  
                } else if (id == 'wxpay') {  
                    PAYSERVER = WXPAYSERVER;  
                } else {  
                    plus.nativeUI.alert("不支持此支付通道!", null, "捐赠");  
                    return;  
                }  
                //获取支付通道  
                for (var i in channels) {  
                    if (channels[i].id == id) {  
                        channel = channels[i];  
                    }  
                }  
                mui.get(PAYSERVER, {  
                    _amount: 1,  
                    _orderid: "",  
                    _detail: "测试微信支付"  
                }, function(data) {  
                    var varpay = {  
                        retcode: 0,  
                        retmsg: "ok",  
                        appid: data.result.appid,  
                        noncestr: data.result.noncestr,  
                        package: "Sign=WXPay",  
                        partnerid: data.result.partnerid,  
                        prepayid: data.result.prepayid,  
                        timestamp: data.result.timestamp,  
                        sign: data.result.sign  
                    }  
                    plus.payment.request(channel, varpay, function(result) {  
                        plus.nativeUI.alert("支付成功!", function() {  
                            back();  
                        });  
                    }, function(e) {  
                        plus.nativeUI.alert("支付失败:" + e.code + "支付失败:" + e.message);  
                        console.log(e.code);  
                        console.log(e.message);  
                    });  
                }, "json");  
                var xhr = new XMLHttpRequest();  
                xhr.onreadystatechange = function() {  
                        switch (xhr.readyState) {  
                            case 4:  
                                if (xhr.status == 200) {  
                                    alert(xhr.result);  
                                    plus.payment.request(channel, xhr.result, function(result) {  
                                        plus.nativeUI.alert("支付成功!", function() {  
                                            back();  
                                        });  
                                    }, function(error) {  
                                        plus.nativeUI.alert("支付失败:" + error.code);  
                                    });  
                                } else {  
                                    alert("获取订单信息失败!");  
                                }  
                                break;  
                            default:  
                                break;  
                        }  
                    }  
                    /*          xhr.open('GET',PAYSERVER);  
                                xhr.send();*/  
            }  
        </script>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">支付测试</h1>  
        </header>  
        <div class="mui-content">  
            <input type="button" class="btn btn-lg" id="pay" value="pay" onclick="pay('wxpay')" />  
        </div>  

    </body>  

</html>
继续阅读 »

研究了很多demo示例,最后整理出了如下的.net MVC版本的微信支付服务端代码,亲测可行,服务端所需要的其他类文件我已经打包存附件了,需要的可以下载使用
以下只实现了基础功能,如果有什么问题还请大神们多多指教。

服务端代码:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Web;  
using System.Web.Mvc;  
using WeddingCarService.Models;  
using Newtonsoft.Json;  
using System.Text;  
using System.Xml;  
using System.Collections;  
using System.Text.RegularExpressions;  
using System.Reflection;  
using WxPayAPI;  
using WeddingCarService.WXPay;  

namespace WeddingCarService.Controllers  
{  
    public class Wx_Pay_Model  
    {  
        public int retcode { get; set; }  
        public string retmsg { get; set; }  
        public string appid { get; set; }  
        public string noncestr { get; set; }  
        public string package { get; set; }  
        public string partnerid { get; set; }  
        public string prepayid { get; set; }  
        public string timestamp { get; set; }  
        public string sign { get; set; }  
    }  
    public class wxPayController : Controller  
    {  

        public static string mchid = "11111"; //mchid  
        public static string appId = "11111"; //appid  
        public static string appsecret = "11111"; //appsecret  
        public static string appkey = "11111"; //paysignkey(非appkey 在微信商户平台设置 (md5)111111111111)    
        public static string notify_url = Common.CommonDefine.ServerPath + "/wxpay/wxtNotify"; //支付完成后的回调处理页面  
        //  
        // GET: /wxPay/  

        public ActionResult Index()  
        {  
            return View();  
        }  

        /// <summary>  
        /// 微信支付主体接口  
        /// </summary>  
        /// <returns></returns>  
        public ActionResult wxpay()  
        {  
            //************************************************支付参数接收********************************  
            ///获取金额  
            string amount = Request.QueryString["_amount"];  
            string sp_billno = string.IsNullOrEmpty(Request.QueryString["_orderid"]) ? DateTime.Now.ToString("yyyyMMddhhmmssffff") : Request.QueryString["_orderid"];  
            string detail = Request.QueryString["_detail"];  
            double dubamount;  
            double.TryParse(amount, out dubamount);  
            //根据appid和appappsecret获取refresh_token  
            //string url_token = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, appsecret);  
            //string returnStr = tokenservice.GetToken(appId, appsecret);  
            //时间戳  
            var timeStamp = TenpayUtil.getTimestamp();  
            //随机验证码  
            var nonceStr = TenpayUtil.getNoncestr();  

            //****************************************************************获取预支付订单编号***********************  
            //设置package订单参数  
            Hashtable packageParameter = new Hashtable();  
            packageParameter.Add("appid", appId);//开放账号ID    
            packageParameter.Add("mch_id", mchid); //商户号  
            packageParameter.Add("nonce_str", nonceStr); //随机字符串  
            packageParameter.Add("body", detail); //商品描述      
            packageParameter.Add("out_trade_no", sp_billno); //商家订单号   
            packageParameter.Add("total_fee", (dubamount*100).ToString()); //商品金额,以分为单位      
            packageParameter.Add("spbill_create_ip", Request.UserHostAddress); //订单生成的机器IP,指用户浏览器端IP    
            packageParameter.Add("notify_url", notify_url); //接收财付通通知的URL    
            packageParameter.Add("trade_type", "APP");//交易类型    
            packageParameter.Add("fee_type", "CNY"); //币种,1人民币   66    
            //获取签名  
            var sign = CreateMd5Sign("key", appkey, packageParameter, Request.ContentEncoding.BodyName);  
            //拼接上签名  
            packageParameter.Add("sign", sign);  
            //生成加密包的XML格式字符串  
            string data = parseXML(packageParameter);  
            //调用统一下单接口,获取预支付订单号码  
            string prepayXml = HttpUtil.Send(data, "https://api.mch.weixin.qq.com/pay/unifiedorder");  

            //获取预支付ID  
            var prepayId = string.Empty;  
            var xdoc = new XmlDocument();  
            xdoc.LoadXml(prepayXml);  
            XmlNode xn = xdoc.SelectSingleNode("xml");  
            XmlNodeList xnl = xn.ChildNodes;  
            if (xnl.Count > 7)  
            {  
                prepayId = xnl[7].InnerText;  
            }  

            //**************************************************封装调起微信客户端支付界面字符串********************  
            //设置待加密支付参数并加密  
            Hashtable paySignReqHandler = new Hashtable();  
            paySignReqHandler.Add("appid", appId);  
            paySignReqHandler.Add("partnerid", mchid);  
            paySignReqHandler.Add("prepayid", prepayId);  
            paySignReqHandler.Add("package", "Sign=WXPay");  
            paySignReqHandler.Add("noncestr", nonceStr);  
            paySignReqHandler.Add("timestamp", timeStamp);  
            var paySign = CreateMd5Sign("key", appkey, paySignReqHandler, Request.ContentEncoding.BodyName);  

            //设置支付包参数  
            Wx_Pay_Model wxpaymodel = new Wx_Pay_Model();  
            wxpaymodel.retcode = 0;//5+固定调起参数  
            wxpaymodel.retmsg = "ok";//5+固定调起参数  
            wxpaymodel.appid = appId;//AppId,微信开放平台新建应用时产生  
            wxpaymodel.partnerid = mchid;//商户编号,微信开放平台申请微信支付时产生  
            wxpaymodel.prepayid = prepayId;//由上面获取预支付流程获取  
            wxpaymodel.package = "Sign=WXpay";//APP支付固定设置参数  
            wxpaymodel.noncestr = nonceStr;//随机字符串,  
            wxpaymodel.timestamp = timeStamp;//时间戳  
            wxpaymodel.sign = paySign;//上面关键参数加密获得  
            //将参数对象直接返回给客户端  
            return Json(new { msg = "", result = wxpaymodel }, JsonRequestBehavior.AllowGet);  
        }  

        /// <summary>  
        /// 将类对象拼接成调起支付字符串  
        /// </summary>  
        /// <param name="_model"></param>  
        /// <returns></returns>  
        private string ReSetPayString(Wx_Pay_Model _model)  
        {  
            StringBuilder strpay = new StringBuilder();  
            PropertyInfo[] props = _model.GetType().GetProperties();  
            strpay.Append("{");  
            foreach (PropertyInfo property in props)  
            {  
                strpay.Append(property.Name + ":\""+property.GetValue(_model, null).ToString()+"\",");  
            }  
            strpay.Remove(strpay.Length - 1, 1);  
            strpay.Append("}");  
            return strpay.ToString();  
        }  

        /// <summary>  
        /// 输出XML  
        /// </summary>  
        /// <returns></returns>  
        public string parseXML(Hashtable _parameters)  
        {  
            var sb = new StringBuilder();  
            sb.Append("<xml>");  
            var akeys = new ArrayList(_parameters.Keys);  
            foreach (string k in akeys)  
            {  
                var v = (string)_parameters[k];  
                if (Regex.IsMatch(v, @"^[0-9.]$"))  
                {  
                    sb.Append("<" + k + ">" + v + "</" + k + ">");  
                }  
                else  
                {  
                    sb.Append("<" + k + "><![CDATA[" + v + "]]></" + k + ">");  
                }  
            }  
            sb.Append("</xml>");  
            return sb.ToString();  
        }  

        /// <summary>  
        /// 创建package签名  
        /// </summary>  
        /// <param name="key">密钥键</param>  
        /// <param name="value">财付通商户密钥(自定义32位密钥)</param>  
        /// <returns></returns>  
        public virtual string CreateMd5Sign(string key, string value, Hashtable parameters, string _ContentEncoding)  
        {  
            var sb = new StringBuilder();  
            //数组化键值对,并排序  
            var akeys = new ArrayList(parameters.Keys);  
            akeys.Sort();  
            //循环拼接包参数  
            foreach (string k in akeys)  
            {  
                var v = (string)parameters[k];  
                if (null != v && "".CompareTo(v) != 0  
                    && "sign".CompareTo(k) != 0 && "key".CompareTo(k) != 0)  
                {  
                    sb.Append(k + "=" + v + "&");  
                }  
            }  
            //最后拼接商户自定义密钥  
            sb.Append(key + "=" + value);  
            //加密  
            string sign = MD5Util.GetMD5(sb.ToString(), _ContentEncoding).ToUpper();  
            //返回密文  
            return sign;  
        }  

        /// <summary>  
        /// 日志记录工具类  
        /// </summary>  
        /// <param name="pathWrite"></param>  
        /// <param name="content"></param>  
        public static void WriteFile(string pathWrite, string content)  
        {  
            try  
            {  
                if (System.IO.File.Exists(pathWrite))  
                {  
                    //System.IO.File.Delete(pathWrite);  
                }  
                else  
                {  
                    System.IO.File.Create(pathWrite);  
                }  
                System.IO.File.AppendAllText(pathWrite, content + "\r\n----------------------------------------\r\n",  
                    Encoding.GetEncoding("utf-8"));  
            }  
            catch (Exception e)  
            {  

            }  
        }  

        /// <summary>  
        /// 微信支付异步回调方法  
        /// </summary>  
        /// <returns></returns>  
        public ActionResult wxtNotify()  
        {  
            ResultNotify resultNotify = new ResultNotify(Request);  
            resultNotify.ProcessNotify();  
            return Json(new { msg = "成功" }, JsonRequestBehavior.AllowGet);  
        }  
    }  
}  

客户端代码:  
<!DOCTYPE html>  
<html>  

    <head>  
        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <script src="js/mui.min.js"></script>  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
            var channel = null;  
            var channels = null;  
             // 1. 获取支付通道  
            function plusReady() {  
                // 获取支付通道  
                plus.payment.getChannels(function(cs) {  
                    channels = cs;  
                }, function(e) {  
                    alert("获取支付通道失败:" + e.message);  
                });  
            }  
            document.addEventListener('plusready', plusReady, false);  
            var ALIPAYSERVER = 'http://demo.dcloud.net.cn/helloh5/payment/alipay.php?total=';  
            var WXPAYSERVER = 'http://192.168.3.141/wxPay/wxpay';  
            /*var WXPAYSERVER = 'http://demo.dcloud.net.cn/payment/?payid=wxpay&appid=HBuilder&total=1';*/  
             // 2. 发起支付请求  
            function pay(id) {  
                // 从服务器请求支付订单  
                var PAYSERVER = '';  
                if (id == 'alipay') {  
                    PAYSERVER = ALIPAYSERVER;  
                } else if (id == 'wxpay') {  
                    PAYSERVER = WXPAYSERVER;  
                } else {  
                    plus.nativeUI.alert("不支持此支付通道!", null, "捐赠");  
                    return;  
                }  
                //获取支付通道  
                for (var i in channels) {  
                    if (channels[i].id == id) {  
                        channel = channels[i];  
                    }  
                }  
                mui.get(PAYSERVER, {  
                    _amount: 1,  
                    _orderid: "",  
                    _detail: "测试微信支付"  
                }, function(data) {  
                    var varpay = {  
                        retcode: 0,  
                        retmsg: "ok",  
                        appid: data.result.appid,  
                        noncestr: data.result.noncestr,  
                        package: "Sign=WXPay",  
                        partnerid: data.result.partnerid,  
                        prepayid: data.result.prepayid,  
                        timestamp: data.result.timestamp,  
                        sign: data.result.sign  
                    }  
                    plus.payment.request(channel, varpay, function(result) {  
                        plus.nativeUI.alert("支付成功!", function() {  
                            back();  
                        });  
                    }, function(e) {  
                        plus.nativeUI.alert("支付失败:" + e.code + "支付失败:" + e.message);  
                        console.log(e.code);  
                        console.log(e.message);  
                    });  
                }, "json");  
                var xhr = new XMLHttpRequest();  
                xhr.onreadystatechange = function() {  
                        switch (xhr.readyState) {  
                            case 4:  
                                if (xhr.status == 200) {  
                                    alert(xhr.result);  
                                    plus.payment.request(channel, xhr.result, function(result) {  
                                        plus.nativeUI.alert("支付成功!", function() {  
                                            back();  
                                        });  
                                    }, function(error) {  
                                        plus.nativeUI.alert("支付失败:" + error.code);  
                                    });  
                                } else {  
                                    alert("获取订单信息失败!");  
                                }  
                                break;  
                            default:  
                                break;  
                        }  
                    }  
                    /*          xhr.open('GET',PAYSERVER);  
                                xhr.send();*/  
            }  
        </script>  
    </head>  

    <body>  
        <header class="mui-bar mui-bar-nav">  
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>  
            <h1 class="mui-title">支付测试</h1>  
        </header>  
        <div class="mui-content">  
            <input type="button" class="btn btn-lg" id="pay" value="pay" onclick="pay('wxpay')" />  
        </div>  

    </body>  

</html>
收起阅读 »

关于guide的研究

[6.0.0.201506290132]新增App首次启动欢迎页,也就是mui项目中examples/guide.html
APP启动流程:

  1. APP启动打开启动页面,也就是splashscreen,可以在manifest.html中设置自动关闭或者手动关闭:代码视图中plus下的splashscreen,autoclose值为false即需要手动关闭,值为true即自动关闭;
  2. 进入设置的入口页面webview;在入口页面或者入口页面的子webview即APP启动后就执行js的webview中判断APP是否为第一次启动。如何判断呢?使用localStorage,这个很简单就不说了;若不是第一次打开,则需要使用plus.navigator.closeSplashscreen()来关闭启动画面;若为第一次打开,则进入guide.html,在guide.html加载完后需要关闭启动画面;
  3. guide.html跳转至入口页面;

在MUI demo中,判断是否为第一次启动APP的代码在入口页面index.html的子页面list.html中;

看demo时发现若是ios则设置全屏(显示顶部状态栏),我测试了下,ios和安卓都可以全屏,不知道hbcui1984为何这样写,我看了下好几个安卓APP的guide都不是全屏的;

关于在使用过程中出现的问题:
1.有的娃娃做出来之后表现是看到启动画面后先看到入口页面,然后才看到guide页面,这是因为未正确设置启动画面的关闭;

若有问题,请在评论中指出。
by 鑫花璐放

继续阅读 »

[6.0.0.201506290132]新增App首次启动欢迎页,也就是mui项目中examples/guide.html
APP启动流程:

  1. APP启动打开启动页面,也就是splashscreen,可以在manifest.html中设置自动关闭或者手动关闭:代码视图中plus下的splashscreen,autoclose值为false即需要手动关闭,值为true即自动关闭;
  2. 进入设置的入口页面webview;在入口页面或者入口页面的子webview即APP启动后就执行js的webview中判断APP是否为第一次启动。如何判断呢?使用localStorage,这个很简单就不说了;若不是第一次打开,则需要使用plus.navigator.closeSplashscreen()来关闭启动画面;若为第一次打开,则进入guide.html,在guide.html加载完后需要关闭启动画面;
  3. guide.html跳转至入口页面;

在MUI demo中,判断是否为第一次启动APP的代码在入口页面index.html的子页面list.html中;

看demo时发现若是ios则设置全屏(显示顶部状态栏),我测试了下,ios和安卓都可以全屏,不知道hbcui1984为何这样写,我看了下好几个安卓APP的guide都不是全屏的;

关于在使用过程中出现的问题:
1.有的娃娃做出来之后表现是看到启动画面后先看到入口页面,然后才看到guide页面,这是因为未正确设置启动画面的关闭;

若有问题,请在评论中指出。
by 鑫花璐放

收起阅读 »

【分享交流】MUI实现城市列表的选择

项目需要选择城市,MUI给的案例是机场的,所以只能自己改写了;
城市列表的数据组合了好久,现在分享给大家,相互交流学习;

效果:

完整案例在附件:

项目需要选择城市,MUI给的案例是机场的,所以只能自己改写了;
城市列表的数据组合了好久,现在分享给大家,相互交流学习;

效果:

完整案例在附件:

WebSQL Demo 给大家参考

mui websql

初学,发现没有WebSQL的资料(其实google 有很多), 于是写了一个Demo练手,也给没用过的一个参考吧。
WebSQL官方文档在此

发现Sqlite 没有删除某条记录的功能... 只能整表删除,谁知道怎么删除某一条记录吗?

加一个别人写的Html5SQL helper
html5sql

DEMO 在此

继续阅读 »

初学,发现没有WebSQL的资料(其实google 有很多), 于是写了一个Demo练手,也给没用过的一个参考吧。
WebSQL官方文档在此

发现Sqlite 没有删除某条记录的功能... 只能整表删除,谁知道怎么删除某一条记录吗?

加一个别人写的Html5SQL helper
html5sql

DEMO 在此

收起阅读 »

增量升级

增量升级

增量升级的实现方式

增量升级的问题
增量、差量升级是H5的一个优势,现在被越来越多的引用采用。但是在使用H5 的增量升级的时候遇到一个问题。纠结我很长时间一直在找解决方案,而且严重影响了用户体验。
我遇到最主要的问题是:
当APP启动是出现升级页面,用户点击增量升级后不重新启动APP。
如果我们的页面中存在父子webview的时候,这个时候有一些业务webview在显示的时候会发现父webview丢失了,导致用户体验直线下降,正常业务无法走通。
在尝试了很多方法后找到了一个解决方案。目前测试下来一切正常,但是可能测试的方法不全面。希望提出来对大家有所帮助

解决方案
其实解决方法很简单,就是关闭所有webview,然后再执行plus.runtime.restart();。下面是我的代码

            var wvs=plus.webview.all();  
            for(var i=0;i<wvs.length;i  ){  
                if(plus.webview.currentWebview().id!=wvs[i].id){  
                    plus.webview.close(wvs[i]);  
                }  
            }  
            plus.runtime.restart();

本人不善言语,希望大家有更好的方法可以提出来,方便大家借鉴。

继续阅读 »

增量升级的实现方式

增量升级的问题
增量、差量升级是H5的一个优势,现在被越来越多的引用采用。但是在使用H5 的增量升级的时候遇到一个问题。纠结我很长时间一直在找解决方案,而且严重影响了用户体验。
我遇到最主要的问题是:
当APP启动是出现升级页面,用户点击增量升级后不重新启动APP。
如果我们的页面中存在父子webview的时候,这个时候有一些业务webview在显示的时候会发现父webview丢失了,导致用户体验直线下降,正常业务无法走通。
在尝试了很多方法后找到了一个解决方案。目前测试下来一切正常,但是可能测试的方法不全面。希望提出来对大家有所帮助

解决方案
其实解决方法很简单,就是关闭所有webview,然后再执行plus.runtime.restart();。下面是我的代码

            var wvs=plus.webview.all();  
            for(var i=0;i<wvs.length;i  ){  
                if(plus.webview.currentWebview().id!=wvs[i].id){  
                    plus.webview.close(wvs[i]);  
                }  
            }  
            plus.runtime.restart();

本人不善言语,希望大家有更好的方法可以提出来,方便大家借鉴。

收起阅读 »

分享iOS平台使用H5原生滚动的下拉刷新功能v1.0.0 [不推荐]

回弹 技术分享 mui 下拉刷新

上一篇给大家分享了《使用H5原生滚动的上拉加载功能》,但是没有下拉刷新的功能,今天赶快补上。

我们在上一篇中提到,因为iOS下mui中的下拉刷新插件,使用的是自绘的模拟滚动条,不是原生的,而上拉加载和下拉刷新的实现是一体的,因为HTML结构相互依赖,所以无法使用原生的上拉加载功能+mui的下拉刷新,来混合使用。

hello mui中的下拉刷新例子,使用的是新增数据插入头部的方式,这里我使用重新刷新的方式,当然两种情况都有各自使用的场景,请根据各自的需求来写。

功能特性

~原生实现,不依赖任何前端框架
~监听事件下拉刷新,segment+下拉刷新也可轻松支持
~代码轻量模块化

下一阶段功能

下拉刷新的时候列表底部会多出几十像素的小bug,暂不知什么原因,有高人解决了希望相告之

如何使用

1、html,结构与mui的上拉刷新基本一致,但是多了ios-content,因为使用的是区域滚动,来激活iOS的原生滚动

<!--下拉刷新容器 #content -->  
<div id="content" class="ios-content mui-scroll-wrapper">  
    <div id="content_inner" class="mui-scroll">  

        <!--数据列表  
        <ul class="mui-table-view">  
        </ul>  
        -->  

    </div><!-- #content_inner -->  
</div><!-- #content -->

2、css 使用div的区域滚动产生滚动条,同时新增mui-scroll的动画样式transitioning

.ios-content{  
    text-align: left;  
    width: 100%;  
    position: absolute;  
    top: 44px;  
    bottom: 0;  
    overflow-y: scroll;  
    -webkit-overflow-scrolling: touch;  
}  
.transitioning{  
    -webkit-transition: -webkit-transform 0.25s ease;  
            transition:         transform 0.25s ease;  
}

3、js 这里主要为了演示上拉加载,没有使用模板引擎,只是简单创建li元素

document.addEventListener('plusready', plus_ready, false);  

var pulldown = null; // 定义全局的下拉刷新对象,ajax请求成功需要endPullDownToRefresh()  
function plus_ready(){  
    // 初始化商品列表  
    get_goods_list();  

    // 下拉刷新  
    pulldown = pulldown_refresh({  
        container: '#content',  
        callback: get_goods_list  
    });  
}  

var last_length = 20;  
function get_goods_list(){  
    // 模拟ajax加载网络数据  
    setTimeout(function(){  
        var table_node = document.createElement('ul');  
        table_node.setAttribute('class', 'mui-table-view');  

        for (var i = 0; i < 20; i++) {  
            var li = document.createElement('li');  
            li.className = 'mui-table-view-cell';  
            li.innerHTML = '<a class="mui-navigate-right">Item ' + (last_length-i) + '</a>';  
            table_node.appendChild(li);  
        }  

        // 兼容下拉刷新的情况,先清空节点后插入数据  
        var parent = document.getElementById("content_inner");  
        while(parent.firstChild)  
            parent.removeChild(parent.firstChild);  

        parent.appendChild(table_node);  

        // 下拉刷新的时候,区域收回,使用之前定义的全局变量  
        if(pulldown){  
            pulldown.endPullDownToRefresh();   
        }  

        last_length += 2;  
    }, 1000);  
}

源代码

/**  
 * 下拉刷新类定义  
 */  
var PullDownRefresh = function(options){  
    this.container     = options['container'];  
    this.callback      = options['callback'];  
    this.is_draging    = false;  
    this.start_delta_y = 0;  
    this.delta_y       = 0;  
};  
PullDownRefresh.prototype = {  
    //可以在这里提供Person的基本功能  
    init : function(){  
        // 创建下拉可以刷新div  
        var div_node = document.createElement('div');  
        div_node.setAttribute('class', 'mui-pull-top-pocket mui-block mui-visibility');  
        var html = '<!--div class="mui-pull-top-pocket mui-block mui-visibility" style="-webkit-transform: translate3d(0px, -50px, 0px);"-->'+  
                   '     <div class="mui-pull">'+  
                   '        <div class="mui-pull-loading mui-icon mui-icon-pulldown" style="-webkit-transition: -webkit-transform 200ms ease; transition: -webkit-transform 200ms ease; -webkit-transform: rotate(0deg);"></div>'+  
                   '        <div class="mui-pull-caption">下拉可以刷新</div>'+  
                   '     </div>'+  
                   '<!--/div-->';  
        div_node.innerHTML = html;  

        var parent = document.querySelector(this.container);  
        parent.insertBefore(div_node, parent.childNodes[0]);  

        // 设置初始位置  
        document.querySelector(this.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,-50px,0)';  
        document.querySelector(this.container+" .mui-scroll").style.webkitTransform = 'translate3d(0,0,0)';  

        var that = this;  
        document.querySelector(this.container).addEventListener('drag', function(e){  
            // 第一次滑动  
            if(!that.is_draging){  
                if(e.detail.direction === 'down'){  
                    that.is_draging = true;  
                    that.start_delta_y = e.detail.deltaY;  

                    document.querySelector(that.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,-50px,0)';  
                    document.querySelector(that.container+" .mui-pull-loading").setAttribute('class', 'mui-pull-loading mui-icon mui-icon-pulldown');  

                    document.querySelector(that.container+" .mui-pull-top-pocket").classList.remove('transitioning');  
                    document.querySelector(that.container+" .mui-scroll").classList.remove('transitioning');  
                }  
            }  
            if(that.is_draging){  
                if(e.detail.direction === 'down'){  
                    e.stopPropagation();  

                    that.delta_y = e.detail.deltaY - that.start_delta_y;  
                    // 判断滑动距离,如果大于下拉加载区域的高,就翻转箭头  
                    if(that.delta_y >= 100){  
                        document.querySelector(that.container+" .mui-pull-caption").innerText = '释放立即刷新';  
                        document.querySelector(that.container+" .mui-pull-loading").style.webkitTransform = 'rotate(-180deg)';  
                    }else{  
                        document.querySelector(that.container+" .mui-pull-caption").innerText = '下拉可以刷新';  
                        document.querySelector(that.container+" .mui-pull-loading").style.webkitTransform = 'rotate(0deg)';  
                    }  
                }  
            }  
        });  

        document.querySelector(this.container).addEventListener('dragend', function(e){  
            if(that.is_draging){  
                that.is_draging = false;  

                // 放开的时候,判断当前滚动条距离顶部滚动了多远, 如果没有往下拉,滚动条在下面,则return;  
                var scroll_top = document.querySelector(that.container).scrollTop;  
                if(scroll_top >= 0){  
                    // 当在底部下拉滑动到顶部时,拖动距离可能超过100,始终保持文字为“下拉可以刷新”  
                    document.querySelector(that.container+" .mui-pull-caption").innerText = '下拉可以刷新';  
                    document.querySelector(that.container+" .mui-pull-loading").style.webkitTransform = 'rotate(0deg)';  
                    return;  
                }  

                if(that.delta_y >= 100){  
                    document.querySelector(that.container+" .mui-pull-caption").innerText = '努力加载中...';  
                    document.querySelector(that.container+" .mui-pull-loading").setAttribute('class', 'mui-pull-loading mui-icon mui-spinner');  

                    document.querySelector(that.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,0,0)';  
                    document.querySelector(that.container+" .mui-scroll").style.webkitTransform = 'translate3d(0,50px,0)';  

                    document.querySelector(that.container+" .mui-pull-top-pocket").classList.add('transitioning');  
                    //TODO 有点小不足的地方,.mui-scroll加上动画后,在刷新后,底部会出现一块空白,再刷新又正常,循环往复  
                    // 因为.mui-scroll延迟0.25s再滑上去,而框架没有缩回, 需要以后解决  
                    document.querySelector(that.container+" .mui-scroll").classList.add('transitioning');  

                    // callback  
                    that.callback();  
                }  
            }  
        })  

    },  
    endPullDownToRefresh: function(){  
        document.querySelector(this.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,-50px,0)';  
        document.querySelector(this.container+" .mui-scroll").style.webkitTransform = 'translate3d(0,0,0)';  
    }  
}  

/**  
 * 上拉加载功能实现, 使用H5原生滚动  
 * @param {Array} options  
 * options: {  
 *    container: '#content' // 容器   
 *    callback: get_list_function // 下拉刷新业务逻辑  
 * }  
 * @author fanrong33  
 * @version 1.0.0 build 20150705  
 */  
var pulldown_refresh = function(options){  
    var obj = new PullDownRefresh(options);  
    obj.init();  
    return obj;  
}
继续阅读 »

上一篇给大家分享了《使用H5原生滚动的上拉加载功能》,但是没有下拉刷新的功能,今天赶快补上。

我们在上一篇中提到,因为iOS下mui中的下拉刷新插件,使用的是自绘的模拟滚动条,不是原生的,而上拉加载和下拉刷新的实现是一体的,因为HTML结构相互依赖,所以无法使用原生的上拉加载功能+mui的下拉刷新,来混合使用。

hello mui中的下拉刷新例子,使用的是新增数据插入头部的方式,这里我使用重新刷新的方式,当然两种情况都有各自使用的场景,请根据各自的需求来写。

功能特性

~原生实现,不依赖任何前端框架
~监听事件下拉刷新,segment+下拉刷新也可轻松支持
~代码轻量模块化

下一阶段功能

下拉刷新的时候列表底部会多出几十像素的小bug,暂不知什么原因,有高人解决了希望相告之

如何使用

1、html,结构与mui的上拉刷新基本一致,但是多了ios-content,因为使用的是区域滚动,来激活iOS的原生滚动

<!--下拉刷新容器 #content -->  
<div id="content" class="ios-content mui-scroll-wrapper">  
    <div id="content_inner" class="mui-scroll">  

        <!--数据列表  
        <ul class="mui-table-view">  
        </ul>  
        -->  

    </div><!-- #content_inner -->  
</div><!-- #content -->

2、css 使用div的区域滚动产生滚动条,同时新增mui-scroll的动画样式transitioning

.ios-content{  
    text-align: left;  
    width: 100%;  
    position: absolute;  
    top: 44px;  
    bottom: 0;  
    overflow-y: scroll;  
    -webkit-overflow-scrolling: touch;  
}  
.transitioning{  
    -webkit-transition: -webkit-transform 0.25s ease;  
            transition:         transform 0.25s ease;  
}

3、js 这里主要为了演示上拉加载,没有使用模板引擎,只是简单创建li元素

document.addEventListener('plusready', plus_ready, false);  

var pulldown = null; // 定义全局的下拉刷新对象,ajax请求成功需要endPullDownToRefresh()  
function plus_ready(){  
    // 初始化商品列表  
    get_goods_list();  

    // 下拉刷新  
    pulldown = pulldown_refresh({  
        container: '#content',  
        callback: get_goods_list  
    });  
}  

var last_length = 20;  
function get_goods_list(){  
    // 模拟ajax加载网络数据  
    setTimeout(function(){  
        var table_node = document.createElement('ul');  
        table_node.setAttribute('class', 'mui-table-view');  

        for (var i = 0; i < 20; i++) {  
            var li = document.createElement('li');  
            li.className = 'mui-table-view-cell';  
            li.innerHTML = '<a class="mui-navigate-right">Item ' + (last_length-i) + '</a>';  
            table_node.appendChild(li);  
        }  

        // 兼容下拉刷新的情况,先清空节点后插入数据  
        var parent = document.getElementById("content_inner");  
        while(parent.firstChild)  
            parent.removeChild(parent.firstChild);  

        parent.appendChild(table_node);  

        // 下拉刷新的时候,区域收回,使用之前定义的全局变量  
        if(pulldown){  
            pulldown.endPullDownToRefresh();   
        }  

        last_length += 2;  
    }, 1000);  
}

源代码

/**  
 * 下拉刷新类定义  
 */  
var PullDownRefresh = function(options){  
    this.container     = options['container'];  
    this.callback      = options['callback'];  
    this.is_draging    = false;  
    this.start_delta_y = 0;  
    this.delta_y       = 0;  
};  
PullDownRefresh.prototype = {  
    //可以在这里提供Person的基本功能  
    init : function(){  
        // 创建下拉可以刷新div  
        var div_node = document.createElement('div');  
        div_node.setAttribute('class', 'mui-pull-top-pocket mui-block mui-visibility');  
        var html = '<!--div class="mui-pull-top-pocket mui-block mui-visibility" style="-webkit-transform: translate3d(0px, -50px, 0px);"-->'+  
                   '     <div class="mui-pull">'+  
                   '        <div class="mui-pull-loading mui-icon mui-icon-pulldown" style="-webkit-transition: -webkit-transform 200ms ease; transition: -webkit-transform 200ms ease; -webkit-transform: rotate(0deg);"></div>'+  
                   '        <div class="mui-pull-caption">下拉可以刷新</div>'+  
                   '     </div>'+  
                   '<!--/div-->';  
        div_node.innerHTML = html;  

        var parent = document.querySelector(this.container);  
        parent.insertBefore(div_node, parent.childNodes[0]);  

        // 设置初始位置  
        document.querySelector(this.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,-50px,0)';  
        document.querySelector(this.container+" .mui-scroll").style.webkitTransform = 'translate3d(0,0,0)';  

        var that = this;  
        document.querySelector(this.container).addEventListener('drag', function(e){  
            // 第一次滑动  
            if(!that.is_draging){  
                if(e.detail.direction === 'down'){  
                    that.is_draging = true;  
                    that.start_delta_y = e.detail.deltaY;  

                    document.querySelector(that.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,-50px,0)';  
                    document.querySelector(that.container+" .mui-pull-loading").setAttribute('class', 'mui-pull-loading mui-icon mui-icon-pulldown');  

                    document.querySelector(that.container+" .mui-pull-top-pocket").classList.remove('transitioning');  
                    document.querySelector(that.container+" .mui-scroll").classList.remove('transitioning');  
                }  
            }  
            if(that.is_draging){  
                if(e.detail.direction === 'down'){  
                    e.stopPropagation();  

                    that.delta_y = e.detail.deltaY - that.start_delta_y;  
                    // 判断滑动距离,如果大于下拉加载区域的高,就翻转箭头  
                    if(that.delta_y >= 100){  
                        document.querySelector(that.container+" .mui-pull-caption").innerText = '释放立即刷新';  
                        document.querySelector(that.container+" .mui-pull-loading").style.webkitTransform = 'rotate(-180deg)';  
                    }else{  
                        document.querySelector(that.container+" .mui-pull-caption").innerText = '下拉可以刷新';  
                        document.querySelector(that.container+" .mui-pull-loading").style.webkitTransform = 'rotate(0deg)';  
                    }  
                }  
            }  
        });  

        document.querySelector(this.container).addEventListener('dragend', function(e){  
            if(that.is_draging){  
                that.is_draging = false;  

                // 放开的时候,判断当前滚动条距离顶部滚动了多远, 如果没有往下拉,滚动条在下面,则return;  
                var scroll_top = document.querySelector(that.container).scrollTop;  
                if(scroll_top >= 0){  
                    // 当在底部下拉滑动到顶部时,拖动距离可能超过100,始终保持文字为“下拉可以刷新”  
                    document.querySelector(that.container+" .mui-pull-caption").innerText = '下拉可以刷新';  
                    document.querySelector(that.container+" .mui-pull-loading").style.webkitTransform = 'rotate(0deg)';  
                    return;  
                }  

                if(that.delta_y >= 100){  
                    document.querySelector(that.container+" .mui-pull-caption").innerText = '努力加载中...';  
                    document.querySelector(that.container+" .mui-pull-loading").setAttribute('class', 'mui-pull-loading mui-icon mui-spinner');  

                    document.querySelector(that.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,0,0)';  
                    document.querySelector(that.container+" .mui-scroll").style.webkitTransform = 'translate3d(0,50px,0)';  

                    document.querySelector(that.container+" .mui-pull-top-pocket").classList.add('transitioning');  
                    //TODO 有点小不足的地方,.mui-scroll加上动画后,在刷新后,底部会出现一块空白,再刷新又正常,循环往复  
                    // 因为.mui-scroll延迟0.25s再滑上去,而框架没有缩回, 需要以后解决  
                    document.querySelector(that.container+" .mui-scroll").classList.add('transitioning');  

                    // callback  
                    that.callback();  
                }  
            }  
        })  

    },  
    endPullDownToRefresh: function(){  
        document.querySelector(this.container+" .mui-pull-top-pocket").style.webkitTransform = 'translate3d(0,-50px,0)';  
        document.querySelector(this.container+" .mui-scroll").style.webkitTransform = 'translate3d(0,0,0)';  
    }  
}  

/**  
 * 上拉加载功能实现, 使用H5原生滚动  
 * @param {Array} options  
 * options: {  
 *    container: '#content' // 容器   
 *    callback: get_list_function // 下拉刷新业务逻辑  
 * }  
 * @author fanrong33  
 * @version 1.0.0 build 20150705  
 */  
var pulldown_refresh = function(options){  
    var obj = new PullDownRefresh(options);  
    obj.init();  
    return obj;  
}
收起阅读 »

HBuilder初次见面——Android_APP——运行

鄙人第一次应用HBuilder这款软件,很陌生。好了,闲话不多聊。  
建立APP就不多说了,自己新建项目试试看,里面可以看到APP字样。建立后如何运行呢?针对AndroidAPP进行说明,要首先保证机器上安装了Android studio或者相关的Android sdk即可。启动Android sdk后,启动相关的avd,说明一点需要在启动HBuilder之前启动sdk。否则需要重启HBuilder之后,就可以在运行中看到相关的模拟器了。  
Android sdk建议安装Android studio(翻墙下载最好),会自带sdk以及avd,直接下载即可(需翻墙)。
继续阅读 »
鄙人第一次应用HBuilder这款软件,很陌生。好了,闲话不多聊。  
建立APP就不多说了,自己新建项目试试看,里面可以看到APP字样。建立后如何运行呢?针对AndroidAPP进行说明,要首先保证机器上安装了Android studio或者相关的Android sdk即可。启动Android sdk后,启动相关的avd,说明一点需要在启动HBuilder之前启动sdk。否则需要重启HBuilder之后,就可以在运行中看到相关的模拟器了。  
Android sdk建议安装Android studio(翻墙下载最好),会自带sdk以及avd,直接下载即可(需翻墙)。
收起阅读 »

64位Mac版HBuilder,解决Mac10.11无法使用的问题

Mac10.11 Mac HBuilder

官网的HBuilder Mac版已经支持Mac 10.11 (除beta3),请移步官网下载

官网的HBuilder Mac版已经支持Mac 10.11 (除beta3),请移步官网下载

分享基于plus.downloader的图片懒加载功能,支持本地缓存v1.1.0

技术分享 懒加载 mui

今天试用了下hello mui上的图片懒加载功能,发现有些地方还无法满足我的需求,ajax动态加载的时候无法实现懒加载。

然后又看了下36kr的示例,因为代码关系实在太多了,耦合度比较高,遂自己动手写了一个轻量级的懒加载功能模块,而且支持图片缓存到本地哦~~~

欢迎各位拍砖,交流碰撞思想!

升级日志

v1.1.0 build 20160107
1、已增加 @LFZ 的代码,不用重复下载两次服务器端的图片
2、新增图片加载淡入特效
3、新增图片加载完成后回调
4、修改data-src为data-lazyload

功能特性

~原生实现,不依赖任何前端框架
~ajax动态加载支持图片懒加载
~支持图片缓存到本地
~轻量模块化

如何使用

1、引入md5.min.js,因为依赖js版md5函数,用于将图片url转换为32位md5

<script s r c="md5.min.js"></script>

2、在头部js包含下面的lazyload方法函数,否则可能报错函数未定义

3、HTML代码使用ajax动态生成如下img标签,src为默认图片,data-src填写图片网络地址,并且必须包含onload事件来触发懒加载功能。

<img s r c="placehold.jpg" data-lazyload="http://...jpg"  onload="lazyload(this)" />

注意:因为函数依赖plus.io和plus.downloader接口,所以在plus还没ready的时候img onload执行lazyload可能会报错,lazyload比plus先执行完毕。

当然,在真实环境中,不管是商品列表、订单列表等,我们的图片一般都是动态加载的,所以问题不大。
在代码的写法策略上需要使用动态加载方式,尽量不使用写死在html里面。

4、添加.img-lazyload 支持图片淡入样式

@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}  
@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}  
.img-lazyload{-webkit-animation: fadeIn 350ms linear 0ms 1 normal both;animation: fadeIn 350ms linear 0ms 1 normal both;opacity:1;}

5、图片默认缓存到_downloads/image/目录下

活动图

函数源代码

/**  
 * 图片懒加载  
 * @param {Object}   obj       DOMElement  
 * @param {Function} callback  加载完成回调函数  
 *   
 * @author fanrong33  
 * @version 1.1.0 build 20160107  
 */  
function lazyload(obj, callback){  
    var debug = false; // 默认打印调试日志  
    if(obj.getAttribute('data-loaded')){  
       return;   
    }  

    var image_url = obj.getAttribute('data-lazyload');  
    debug && console.log(image_url);  

    // 1. 转换网络图片地址为本地缓存图片路径,判断该图片是否存在本地缓存  
    // http://...jpg -> md5  
    // 缓存目录 _downloads/image/(md5).jpg  
    var image_md5           = md5(image_url);  
    var local_image_url     = '_downloads/image/'+image_md5+'.jpg'; // 缓存本地图片url  
    var absolute_image_path = plus.io.convertLocalFileSystemURL(local_image_url); // 平台绝对路径  

    // new temp_img 用于判断图片文件是否存在  
    var temp_img = new Image();  
    temp_img.src = absolute_image_path;  
    temp_img.onload = function(){  
        debug && console.log('存在本地缓存图片文件'+local_image_url+',直接显示');  

        // 1.1 存在,则直接显示(本地已缓存,不需要淡入动画)  
        obj.setAttribute('src', absolute_image_path);  
        obj.setAttribute('data-loaded', true);  
        obj.classList.add('img-lazyload');  

        callback && callback();  
        return;  
    }  
    temp_img.onerror = function(){  
        debug && console.log('不存在本地缓存图片文件');  

        // 1.2 下载图片缓存到本地  
        debug && console.log('开始下载图片'+image_url+' 缓存到本地: '+local_image_url);  
        function download_img(){  
            var download_task = plus.downloader.createDownload(image_url, {  
                filename: local_image_url // filename:下载任务在本地保存的文件路径  
            }, function(download, status) {  
                if(status != 200){  
                    // 下载失败,删除本地临时文件  
                    debug && console.log('下载失败,status'+status);  
                    if(local_image_url != null){  
                        plus.io.resolveLocalFileSystemURL(local_image_url, function(entry) {  
                            entry.remove(function(entry) {  
                                debug && console.log("临时文件删除成功" + local_image_url);  
                                // 重新下载图片  
                                download_img();  
                            }, function(e) {  
                                debug && console.log("临时文件删除失败" + local_image_url);  
                            });  
                        });  
                    }  
                }else{  
                    // 把下载成功的图片显示  
                    // 将本地URL路径转换成平台绝对路径  
                    obj.setAttribute('src', plus.io.convertLocalFileSystemURL(local_image_url));  
                    obj.setAttribute('data-loaded', true);  
                    obj.classList.add('img-lazyload');  

                    callback && callback();  
                }  
            });  
            download_task.start();  
        }  
        download_img();  
    }  

}
继续阅读 »

今天试用了下hello mui上的图片懒加载功能,发现有些地方还无法满足我的需求,ajax动态加载的时候无法实现懒加载。

然后又看了下36kr的示例,因为代码关系实在太多了,耦合度比较高,遂自己动手写了一个轻量级的懒加载功能模块,而且支持图片缓存到本地哦~~~

欢迎各位拍砖,交流碰撞思想!

升级日志

v1.1.0 build 20160107
1、已增加 @LFZ 的代码,不用重复下载两次服务器端的图片
2、新增图片加载淡入特效
3、新增图片加载完成后回调
4、修改data-src为data-lazyload

功能特性

~原生实现,不依赖任何前端框架
~ajax动态加载支持图片懒加载
~支持图片缓存到本地
~轻量模块化

如何使用

1、引入md5.min.js,因为依赖js版md5函数,用于将图片url转换为32位md5

<script s r c="md5.min.js"></script>

2、在头部js包含下面的lazyload方法函数,否则可能报错函数未定义

3、HTML代码使用ajax动态生成如下img标签,src为默认图片,data-src填写图片网络地址,并且必须包含onload事件来触发懒加载功能。

<img s r c="placehold.jpg" data-lazyload="http://...jpg"  onload="lazyload(this)" />

注意:因为函数依赖plus.io和plus.downloader接口,所以在plus还没ready的时候img onload执行lazyload可能会报错,lazyload比plus先执行完毕。

当然,在真实环境中,不管是商品列表、订单列表等,我们的图片一般都是动态加载的,所以问题不大。
在代码的写法策略上需要使用动态加载方式,尽量不使用写死在html里面。

4、添加.img-lazyload 支持图片淡入样式

@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}  
@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}  
.img-lazyload{-webkit-animation: fadeIn 350ms linear 0ms 1 normal both;animation: fadeIn 350ms linear 0ms 1 normal both;opacity:1;}

5、图片默认缓存到_downloads/image/目录下

活动图

函数源代码

/**  
 * 图片懒加载  
 * @param {Object}   obj       DOMElement  
 * @param {Function} callback  加载完成回调函数  
 *   
 * @author fanrong33  
 * @version 1.1.0 build 20160107  
 */  
function lazyload(obj, callback){  
    var debug = false; // 默认打印调试日志  
    if(obj.getAttribute('data-loaded')){  
       return;   
    }  

    var image_url = obj.getAttribute('data-lazyload');  
    debug && console.log(image_url);  

    // 1. 转换网络图片地址为本地缓存图片路径,判断该图片是否存在本地缓存  
    // http://...jpg -> md5  
    // 缓存目录 _downloads/image/(md5).jpg  
    var image_md5           = md5(image_url);  
    var local_image_url     = '_downloads/image/'+image_md5+'.jpg'; // 缓存本地图片url  
    var absolute_image_path = plus.io.convertLocalFileSystemURL(local_image_url); // 平台绝对路径  

    // new temp_img 用于判断图片文件是否存在  
    var temp_img = new Image();  
    temp_img.src = absolute_image_path;  
    temp_img.onload = function(){  
        debug && console.log('存在本地缓存图片文件'+local_image_url+',直接显示');  

        // 1.1 存在,则直接显示(本地已缓存,不需要淡入动画)  
        obj.setAttribute('src', absolute_image_path);  
        obj.setAttribute('data-loaded', true);  
        obj.classList.add('img-lazyload');  

        callback && callback();  
        return;  
    }  
    temp_img.onerror = function(){  
        debug && console.log('不存在本地缓存图片文件');  

        // 1.2 下载图片缓存到本地  
        debug && console.log('开始下载图片'+image_url+' 缓存到本地: '+local_image_url);  
        function download_img(){  
            var download_task = plus.downloader.createDownload(image_url, {  
                filename: local_image_url // filename:下载任务在本地保存的文件路径  
            }, function(download, status) {  
                if(status != 200){  
                    // 下载失败,删除本地临时文件  
                    debug && console.log('下载失败,status'+status);  
                    if(local_image_url != null){  
                        plus.io.resolveLocalFileSystemURL(local_image_url, function(entry) {  
                            entry.remove(function(entry) {  
                                debug && console.log("临时文件删除成功" + local_image_url);  
                                // 重新下载图片  
                                download_img();  
                            }, function(e) {  
                                debug && console.log("临时文件删除失败" + local_image_url);  
                            });  
                        });  
                    }  
                }else{  
                    // 把下载成功的图片显示  
                    // 将本地URL路径转换成平台绝对路径  
                    obj.setAttribute('src', plus.io.convertLocalFileSystemURL(local_image_url));  
                    obj.setAttribute('data-loaded', true);  
                    obj.classList.add('img-lazyload');  

                    callback && callback();  
                }  
            });  
            download_task.start();  
        }  
        download_img();  
    }  

}
收起阅读 »

mui ajax success回调函数为什么会执行二次?

这里应该是一个BUG,我测试了几次都是如此

mui.ajax 成功回调都是执行二次;

这里应该是一个BUG,我测试了几次都是如此

mui.ajax 成功回调都是执行二次;

Js注解

//创建滑动块当前标识盒子
/**

  • @param {Number} index null -正整数,索引号
  • @param {string} src null -传入的图片URL集合
    */
    function createcurr(index, src) {
    。。。。。。。
    }

//创建滑动块当前标识盒子
/**

  • @param {Number} index null -正整数,索引号
  • @param {string} src null -传入的图片URL集合
    */
    function createslidercurr(index, src) {
    。。。。。。。
    }

从表面上来看是没有问题。现在问题来了,这两个函数中有一个函数在函数在引用的时候要提示数据类型与注解,有一个不提示。

createcurr 这个函数会提示
createslidercurr 这个数据不会提示

为什么会这样,刚开始的时候我为了让 createslidercurr 这个函数在引用的时候提示数据类型与注解,搞了很久,但是它就是不提示,郁了个闷啊,猫了个咪的,气死我了。

原因:createslidercurr 这个函数包含了 mui 里面的slider关建字 。

写这篇文章,是希望那个做规范开发有团队协作的人可以看一看哈,希望能帮到大家。。

OVER

继续阅读 »

//创建滑动块当前标识盒子
/**

  • @param {Number} index null -正整数,索引号
  • @param {string} src null -传入的图片URL集合
    */
    function createcurr(index, src) {
    。。。。。。。
    }

//创建滑动块当前标识盒子
/**

  • @param {Number} index null -正整数,索引号
  • @param {string} src null -传入的图片URL集合
    */
    function createslidercurr(index, src) {
    。。。。。。。
    }

从表面上来看是没有问题。现在问题来了,这两个函数中有一个函数在函数在引用的时候要提示数据类型与注解,有一个不提示。

createcurr 这个函数会提示
createslidercurr 这个数据不会提示

为什么会这样,刚开始的时候我为了让 createslidercurr 这个函数在引用的时候提示数据类型与注解,搞了很久,但是它就是不提示,郁了个闷啊,猫了个咪的,气死我了。

原因:createslidercurr 这个函数包含了 mui 里面的slider关建字 。

写这篇文章,是希望那个做规范开发有团队协作的人可以看一看哈,希望能帮到大家。。

OVER

收起阅读 »