HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

在哪里学习跨平台app开发、HBuilder、MUI的课程?

视频教程 学习 外包 mui HBuilder

在今年这个时间开始学习移动开发真是最好不过了,每个人应该都有一些移动应用的创意,而且你并不需要任何的原生应用编程经验,你只需要一些HTML的相关知识, 懂一些CSS和JavaScript就够了,跨平台移动APP开发是利用HTML5+CSS3+JS,快速开发出本地App,一次开发,多平台适配,效果与原生App相媲美。学习跨平台app开发就在这里>>>跨平台app开发全套课程

Dcloud官方合作培训机构-国内首推跨平台app开发培训-东翌学院 咨询课程老师QQ410355878,小班直播教学+课后辅导+全套课程视频+源码,从零基础到实战,30天学会跨平台App开发!

继续阅读 »

在今年这个时间开始学习移动开发真是最好不过了,每个人应该都有一些移动应用的创意,而且你并不需要任何的原生应用编程经验,你只需要一些HTML的相关知识, 懂一些CSS和JavaScript就够了,跨平台移动APP开发是利用HTML5+CSS3+JS,快速开发出本地App,一次开发,多平台适配,效果与原生App相媲美。学习跨平台app开发就在这里>>>跨平台app开发全套课程

Dcloud官方合作培训机构-国内首推跨平台app开发培训-东翌学院 咨询课程老师QQ410355878,小班直播教学+课后辅导+全套课程视频+源码,从零基础到实战,30天学会跨平台App开发!

收起阅读 »

我用Hbuilder打包html,写cookie不成功。我的html就下文一个html文件。

<!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="http://ask.dcloud.net.cn/css/mui.min.css" rel="stylesheet"/>
<script type="text/javascript" charset="utf-8">
mui.init();
</script>
<script>
function getdizhi()
{
var micomosid = document.getElementById("mosip").value;
var exp = new Date();
exp.setTime(exp.getTime() 30 24 60 60 1000);
document.cookie = "mico_cook=" micomosid ";expires=" exp.toGMTString() ";path=/";
window.location.href="http://" micomosid ":81/index.asp";
}

window.onload=function()
{
if (readcookie("mico_cook"))
{
document.getElementById("mosip").value = readcookie("mico_cook");
}
}

var mycookie = document.cookie;
function readcookie(name)
{
var start1 = mycookie.indexOf(name "=");
if (start1== -1)
alert("请输入服务器IP1");
else
{
start=mycookie.indexOf("=",start1) 1;
var end = mycookie.indexOf(";",start);
if (end==-1)
{
end=mycookie.length;}
var value=unescape(mycookie.substring(start,end));
if (value==null)
{alert("请输入服务器IP2");}
else
{return value;}
}
}
</script>
</head>
<body>
<table width="100%">
<tr height="40">
<td align="center"> </td>
</tr>
<tr height="40">
<td align="center"><img src="logo.png" border="0" width="32" height="32"></td>
</tr>
<tr height="40">
<td align="center"><font color="#666666">服务器LAN IP:</font></td>
</tr>
<tr height="40">
<td align="center"><input name="mosip" id="mosip" type="text" value="" style= "width:160px; height:32px; font-size:20px; color:#666666" /></td>
</tr>
<tr height="40">
<td align="center"><input type="button" value="进 入" onClick="getdizhi()" style= "width:160px; height:32px;" /></td>
</tr>
<tr height="40">
<td align="center"><font color="#666666"> </td>
</tr>
<tr height="40">
<td align="center"><font color="#666666">版权所有</td>
</tr>
</table>
</body>
</html>

继续阅读 »

<!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="http://ask.dcloud.net.cn/css/mui.min.css" rel="stylesheet"/>
<script type="text/javascript" charset="utf-8">
mui.init();
</script>
<script>
function getdizhi()
{
var micomosid = document.getElementById("mosip").value;
var exp = new Date();
exp.setTime(exp.getTime() 30 24 60 60 1000);
document.cookie = "mico_cook=" micomosid ";expires=" exp.toGMTString() ";path=/";
window.location.href="http://" micomosid ":81/index.asp";
}

window.onload=function()
{
if (readcookie("mico_cook"))
{
document.getElementById("mosip").value = readcookie("mico_cook");
}
}

var mycookie = document.cookie;
function readcookie(name)
{
var start1 = mycookie.indexOf(name "=");
if (start1== -1)
alert("请输入服务器IP1");
else
{
start=mycookie.indexOf("=",start1) 1;
var end = mycookie.indexOf(";",start);
if (end==-1)
{
end=mycookie.length;}
var value=unescape(mycookie.substring(start,end));
if (value==null)
{alert("请输入服务器IP2");}
else
{return value;}
}
}
</script>
</head>
<body>
<table width="100%">
<tr height="40">
<td align="center"> </td>
</tr>
<tr height="40">
<td align="center"><img src="logo.png" border="0" width="32" height="32"></td>
</tr>
<tr height="40">
<td align="center"><font color="#666666">服务器LAN IP:</font></td>
</tr>
<tr height="40">
<td align="center"><input name="mosip" id="mosip" type="text" value="" style= "width:160px; height:32px; font-size:20px; color:#666666" /></td>
</tr>
<tr height="40">
<td align="center"><input type="button" value="进 入" onClick="getdizhi()" style= "width:160px; height:32px;" /></td>
</tr>
<tr height="40">
<td align="center"><font color="#666666"> </td>
</tr>
<tr height="40">
<td align="center"><font color="#666666">版权所有</td>
</tr>
</table>
</body>
</html>

收起阅读 »

Hbuilder 折叠代码问题

HBuilder HTML5 技巧

各位大神我是> 小白 你们现在讨论的都感觉好高大上 我劳烦你们看下我的问题 我就想请教一个 Hbuilder在编写html5的时候左边有个折叠代码的功能,用基本上一个标签一个折叠按钮,但是当我下载了php插件之后就不能折叠代码,只有html5的头文件那里有一个折叠的按钮其他的标签都没有是什么问题
因为代码敲击的多了,想转回去改一些css 都得重新去找,如果没有折叠标签会很浪费时间!!!

继续阅读 »

各位大神我是> 小白 你们现在讨论的都感觉好高大上 我劳烦你们看下我的问题 我就想请教一个 Hbuilder在编写html5的时候左边有个折叠代码的功能,用基本上一个标签一个折叠按钮,但是当我下载了php插件之后就不能折叠代码,只有html5的头文件那里有一个折叠的按钮其他的标签都没有是什么问题
因为代码敲击的多了,想转回去改一些css 都得重新去找,如果没有折叠标签会很浪费时间!!!

收起阅读 »

【分享】JS 日期工具类-基于yDate

日期 技术分享 HTML5

前言:最近在用到JS日期操作时,发现有一些不方便,于是搜素了一些网上的资料,基于一个开源工具类-yDate 进行了个性化定制,封装成了一个日期工具类
工具函数大概介绍:
1.普通的日期操作

  1. 获得一些绝对时间,如1970年 到现在的绝对年,月份,日期,描述,毫秒数等等
  2. 日期比较,克隆,开始时间,结束时间,字符串(输出时可以自定义格式)输出等
  3. 日期相加,相减(返回一个新的日期对象), 比如1月31日 1天会自动变为 2月1日等等
  4. 简化构造,可以传入字符串进行构造等等
  5. 更多请看源码
    说明-基于yDate:| yDate.js | Copyright (c) 2013 yao.yl | email: redrainyi@126.com | Date: 2012-09-03 | *
    原地址: http://www.oschina.net/code/snippet_913265_20123

源码如下:

/**  
 * @description 日期工具类  
 * 原作来源: | yDate.js | Copyright (c) 2013 yao.yl | email: redrainyi@126.com | Date: 2012-09-03 | *   
 * 地址: http://www.oschina.net/code/snippet_913265_20123#comments  
 * 改动说明: 针对yDate进行了一些个性化的修改,以及增加了一些工具函数  
 * @author dailc  dailc  
 * @version 2.0  
 * @time 2016-01-14 12:57:57  
 * 功能模块:  
 * Date相关模块********************************  
 * core/MobileFrame/DateUtil  
 * 1.构造方法  
 * 2.对象的相关功能函数-见源码和文档  
 * Date相关模块结束*****************************  
 */  
(function(exports) {  
    "use strict";  
    var objectPrototypeToString = Object.prototype.toString;  
    /**  
     * 日期匹配的正则表达式  
     * Y:年  
     * M:月  
     * D:日  
     * h:小时  
     * m:分钟  
     * s:秒  
     * i:毫秒  
     * w:星期(小写的)  
     * W:星期(大写的)  
     */  
    var SIGN_DATE_REG = /([YMDhmsiWw])(\1*)/g;  
    /**  
     * 默认的pattern  
     * 'YYYY-MM-DD hh:mm:ss:iii'  
     */  
    var DEFAULT_PATTERN = 'YYYY-MM-DD hh:mm:ss:iii';  
    /**  
     * @description 判断一个值是否是日期类型  
     * @param {Object} value  
     */  
    function isDate(value) {  
        return objectPrototypeToString.call(value) === '[object Date]';  
    };  
    /**  
     * @description 复制一个日期,如果传入的不是日期,会返回一个最新的日期  
     * @param {Date} targetDate  
     */  
    function cloneDate(targetDate, callBack) {  
        //绝对时间,从1970.1.1开始的毫秒数  
        var absoluteTime = (isDate(targetDate)) ? targetDate.getTime() : undefined;  
        var mDate = new Date(absoluteTime);  
        var year = mDate.getFullYear(), //  
            month = mDate.getMonth(), //  
            date = mDate.getDate(), //  
            hours = mDate.getHours(), //  
            minutes = mDate.getMinutes(), //   
            seconds = mDate.getSeconds(); //  
        //!! 代表将后面的转为一个布尔表达式   例如 !!a 就相当于 a||false  
        (!!callBack) && callBack(mDate, year, month, date, hours, minutes, seconds);  
        return mDate;  
    };  
    /**  
     * @description 日期解析,将日期字符串根据特定的匹配字符串解析为日期格式  
     * 解析失败会返回null,如果传入了奇怪的匹配字符串,会产生奇怪的时间  
     * @param {String} dateString 日期字符串  
     * @param {String} pattern 匹配字符串,可以手动传入,或者采取默认  
     * 手动传入需要和日期字符串保持一致  
     */  
    function parseDate(dateString, pattern) {  

        try {  
            //() 是为了提取匹配的字符串。表达式中有几个()就有几个相应的匹配字符串。  
            //(\s*)表示连续空格的字符串。  
            //[]是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示相应位置的字符要匹配英文字符和数字。  
            //[\s*]表示空格或者*号。  
            //{}一般用来表示匹配的长度,比如 \s{3} 表示匹配三个空格,\s[1,3]表示匹配一到三个空格。  
            //(\1)是后向引用,代表后面引用前面第一个()中的内容  
            //根据日期格式来匹配  
            var matchs1 = (pattern || (dateString.length === 10 ? 'YYYY-MM-DD' : (dateString.length === 19 ? 'YYYY-MM-DD hh:mm:ss' : 'YYYY-MM-DD hh:mm:ss:iii'))).match(SIGN_DATE_REG);  
            //根据整数来匹配,将实际的时间数据提取出来  
            var matchs2 = dateString.match(/(\d)+/g);  
            if (matchs1.length > 0) {  
                //第一个匹配字符串需要大于0才行  
                //生成一个最原始的时间-1970-01-01年的  
                var mDate = new Date(1970, 0, 1);  
                //遍历,分别设置年月日,分秒等等  
                for (var i = 0; i < matchs1.length; i++) {  
                    //这个分别是  年,月,日  时,分,秒等等  
                    var mTarget = parseInt(matchs2[i], 10);  
                    switch (matchs1[i].charAt(0) || '') {  
                        //这个matchs1[i]有可能是  YYYY  所以只去第一个字符  
                        case 'Y':  
                            mDate.setFullYear(mTarget);  
                            break;  
                        case 'M':  
                            mDate.setMonth(mTarget - 1);  
                            break;  
                        case 'D':  
                            mDate.setDate(mTarget);  
                            break;  
                        case 'h':  
                            mDate.setHours(mTarget);  
                            break;  
                        case 'm':  
                            mDate.setMinutes(mTarget);  
                            break;  
                        case 's':  
                            mDate.setSeconds(mTarget);  
                            break;  
                        case 'i':  
                            mDate.setMilliseconds(mTarget);  
                            break;  
                        default:  
                            //默认不操作  
                    }  
                }  
                return mDate;  
            }  
        } catch (e) {  

        }  
        return null;  
    };  
    /**  
     * @description 将字符串多余的长度补齐0  
     * @param {String} s  
     * @param {Number} len  
     */  
    function paddingFillWith0(s, len) {  
        var len = len - (s + "").length;  
        for (var i = 0; i < len; i++) {  
            s = "0" + s;  
        }  
        return s;  
    }  
    /**  
     * @description 格式化时间,返回格式化后的字符串  
     * 如果格式不合要求,返回null  
     * @param {Date} value 目标时间  
     * @param {String} pattern 匹配字符串  
     */  
    function formatDateToString(value, pattern) {  
        if (!isDate(value)) {  
            return '';  
        }  
        try {  
            //默认为输出所有的  
            pattern = pattern || DEFAULT_PATTERN;  
            return pattern.replace(SIGN_DATE_REG, function($0) {  
                //如果传入一个yyyy-MM-dd 的表达式  
                //实际上这个函数会分别回调多次 没符合一次匹配就回调一次  
                //$0:yyyy  $0:MM $0:dd  依次类推  
                //console.log('$0:'+$0);  
                switch ($0.charAt(0)) {  
                    case 'Y':  
                        return paddingFillWith0(value.getFullYear(), $0.length);  
                    case 'M':  
                        return paddingFillWith0(value.getMonth() + 1, $0.length);  
                    case 'D':  
                        return paddingFillWith0(value.getDate(), $0.length);  
                    case 'h':  
                        return paddingFillWith0(value.getHours(), $0.length);  
                    case 'm':  
                        return paddingFillWith0(value.getMinutes(), $0.length);  
                    case 's':  
                        return paddingFillWith0(value.getSeconds(), $0.length);  
                    case 'i':  
                        return paddingFillWith0(value.getMilliseconds(), $0.length);  
                    case 'w':  
                        return value.getDay();  
                    case 'W':  
                        //自动将星期转为了大写  
                        var week = ['日', '一', '二', '三', '四', '五', '六'];  
                        return paddingFillWith0(week[value.getDay()], $0.length);  
                    default:  
                        return '';  
                }  
            });  
        } catch (e) {  
            console.log('error:' + e);  
            return '';  
        }  
    };  
    /**  
     * @description 得到实际日期最大值  
     * @param {Date} date  
     */  
    function getActualMaximum(date) {  
        var vDate = new Date(date.getTime());  
        vDate.setMonth(vDate.getMonth() + 1);  
        vDate.setDate(0);  
        return vDate.getDate();  
    }  
    /**  
     * @description 定义一个自定义日期类的构造方法,  
     * 里面封装日期的常用操作,不通过自带的日期来操作  
     * @constructor 这是一个构造方法  
     */  
    function MyDate() {  
        var p0 = arguments[0];  
        var p1 = arguments[1];  
        //isFinite 用于判断是否是无穷大  
        //如果 number 是有限数字(或可转换为有限数字),那么返回 true  
        //如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false  
        if (typeof p0 === 'number' && isFinite(value)) {  
            this.myDate = new Date(p0); //millis  
        } else if (isDate(p0)) {  
            this.myDate = new Date(p0.getTime());  
        } else if (typeof p0 === 'string') {  
            if (typeof p1 !== 'string' && typeof p1 !== 'undefined') {  
                p1 = undefined;  
            }  
            this.myDate = parseDate(p0, p1);  
        } else if (arguments.length == 0) {  
            this.myDate = new Date();  
        } else {  
            throw 'MyDate Constructor Error!';  
        }  
    };  
    /**  
     * @description 给一个日期设置年份  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setYearG(finalYear, mDate, self) {  
        mDate.setFullYear(finalYear);  
    }  
    /**  
     * @description 给一个日期设置月份  
     * 之所以要单独将设置月份(年,日,时...)的函数抽取出来,是因为  
     * 在日期时间 加,减操作时,会涉及到一个进位问题: 比如,1月31日的下一天应该是2月1日...  
     * 所以单独封装成函数便于调用  
     * 之所以没有 直接调用plusMonth,plusYear...  
     * 是因为这个操作中间有回调,多个回调嵌套后,无法同步返回最准确的数据  
     * (可以自行测试)  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setMonthG(finalMon, mDate, self) {  
        //month 为 0-11  
        if (finalMon > 11) {  
            finalMon = finalMon - 12;  
            setYearG(mDate.getFullYear() + 1, mDate, self);  
        } else if (finalMon < 0) {  
            finalMon += 12;  
            setYearG(mDate.getFullYear() - 1, mDate, self);  
        }  
        /*  
         * 关于月份顺延的bug  
         发现如下规律:只要setMonth()的参数为小于31天的月份时就会变为下一个月。  
          原因是:因为当前月份是31天,而设置的月份小于31天,就会把日期顺延。在setMonth的说明是这样的:  
          dateObj.setMonth(numMonth[, dateVal])  
          dateVal  
        可选项。一个代表日期的数值。  
        如果没有提供此参数,那么将使用通过调用 getDate 方法而得到的数值。  
        所以,从对dataVal参数的说明可以看出,在设置月份的同时,  
        使用getDate获取日期,并使用得到的日期值设置了日期。  
        于是就会发生月份顺延的情况。  
        解决方法:  
      1、设置月份时,将日期设为1,记setMonth(month, 1),  
      当然可以在setMonth之前先调用setDate()设置日期;  
      2、也可以在初始化Date对象时,就指定一个日期,也就是使用:  
      dateObj = new Date(year, month, date[, hours[, minutes[, seconds[,ms]]]]) 的形式。  
      3、也可以使用setFullYear()同时设置年、月、日,即setFullYear(numYear[, numMonth[, numDate]])。   
        *bug简单说明:  
        * 如果当前是10月31日,然后设置月份为11,由于11月没有31天,所以月份会顺延  
        * 自动变为12月,所以解决方法是要在设置月份前先把日期设置下,然后之后再继续设置日期  
        * (因为日期肯定是需要改变的)  
        *   
        * * * */  
        mDate.setMonth(finalMon, 1);  

    }  
    /**  
     * @description 给一个日期设置日期  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setDateG(finalDay, mDate, self) {  
        var month = mDate.getMonth();  
        var monthDays = self.getMonthDays(month + 1);  
        if (finalDay > monthDays) {  
            finalDay -= monthDays;  
            setMonthG(mDate.getMonth() + 1, mDate, self);  
        } else if (finalDay <= 0) {  
            var lastMonthDay = month > 0 ? self.getMonthDays((month + 1 - 1)) : self.getMonthDays(12);  
            finalDay += lastMonthDay;  
            setMonthG(mDate.getMonth() - 1, mDate, self);  
        }  
        mDate.setDate(finalDay);  
    }  
    /**  
     * @description 给一个日期设置小时  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setHourG(finalHour, mDate, self) {  
        if (finalHour >= 24) {  
            finalHour -= 24;  
            setDateG(mDate.getDate() + 1, mDate, self);  
        } else if (finalHour < 0) {  
            finalHour += 24;  
            setDateG(mDate.getDate() - 1, mDate, self);  
        }  
        mDate.setHours(finalHour);  
    }  
    /**  
     * @description 给一个日期设置分钟  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setMinG(finalMin, mDate, self) {  
        if (finalMin >= 60) {  
            finalMin -= 60;  
            setHourG(mDate.getHours() + 1, mDate, self);  
        } else if (finalHour < 0) {  
            finalMin += 60;  
            setHourG(mDate.getHours() - 1, mDate, self);  
        }  
        mDate.setMinutes(finalMin);  
    }  
    /**  
     * @description 给一个日期设置秒  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setSecG(finalSec, mDate, self) {  
        if (finalSec >= 60) {  
            finalSec -= 60;  
            setMinG(mDate.getMinutes() + 1, mDate, self);  
        } else if (finalSec < 0) {  
            finalSec += 60;  
            setMinG(mDate.getMinutes() - 1, mDate, self);  
        }  
        mDate.setSeconds(finalSec);  
    }  
    /**  
     * @description 通过扩充原型添加方法  
     */  
    MyDate.prototype = {  
        /**  
         * @description 得到一个月有多少天  
         * @param {Number} month 对应的月份  
         */  
        getMonthDays: function(month) {  
            switch (month) {  
                case 1:  
                case 3:  
                case 5:  
                case 7:  
                case 8:  
                case 10:  
                case 12:  
                    return 31;  
                    break;  
                case 4:  
                case 6:  
                case 9:  
                case 11:  
                    return 30;  
                    break;  
                case 2:  
                    if (this.isLeapYear()) {  
                        return 29;  
                    } else {  
                        return 28;  
                    }  
                    break;  
                default:  
                    return 0;  
                    break;  
            }  
        },  
        /**  
         * @description 年份相加,返回一个新的日期  
         * @param {Object} value  
         */  
        plusYear: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                setYearG(year + value, mDate, self);  
            }));  
        },  
        plusMonth: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                setMonthG(month + value, mDate, self);  
            }));  
        },  
        plusDate: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalDay = date + value;  
                setDateG(finalDay, mDate, self);  
            }));  
        },  
        plusHours: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalHour = hours + value;  
                setHourG(finalHour, mDate, self);  
            }));  
        },  
        plusMinutes: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalMin = minutes + value;  
                setMinG(finalMin, mDate, self);  
            }));  
        },  
        plusSeconds: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalSec = seconds + value;  
                setSecG(finalSec, mDate, self);  
            }));  
        },  
        minusYear: function(value) {  
            return this.plusYear(-value);  
        },  
        minusMonth: function(value) {  
            return this.plusMonth(-value);  
        },  
        minusDate: function(value) {  
            return this.plusDate(-value);  
        },  
        minusHours: function(value) {  
            return this.plusHours(-value);  
        },  
        minusMinutes: function(value) {  
            return this.plusMinutes(-value);  
        },  
        minusSeconds: function(value) {  
            return this.plusSeconds(-value);  
        },  
        setYear: function(value) {  
            this.myDate.setFullYear(value);  
        },  
        setMonth: function(value) {  
            this.myDate.setMonth(value - 1);  
        },  
        setDate: function(value) {  
            this.myDate.setDate(value);  
        },  
        setHours: function(value) {  
            this.myDate.setHours(value);  
        },  
        setMinutes: function(value) {  
            this.myDate.setMinutes(value);  
        },  
        setSeconds: function(value) {  
            this.myDate.setSeconds(value);  
        },  
        setMilliseconds: function(value) {  
            this.myDate.setMilliseconds(value);  
        },  
        getYear: function() {  
            return this.myDate.getFullYear();  
        },  
        getMonth: function() {  
            //比普通月份小1  
            return this.myDate.getMonth();  
        },  
        getDate: function() {  
            return this.myDate.getDate();  
        },  
        getHours: function() {  
            return this.myDate.getHours();  
        },  
        getMinutes: function() {  
            return this.myDate.getMinutes();  
        },  
        getSeconds: function() {  
            return this.myDate.getSeconds();  
        },  
        getMilliseconds: function() {  
            return this.myDate.getMilliseconds();  
        },  
        /**  
         * @description 得到从1970至今多少年  
         */  
        getAbsoluteYear: function() {  
            return this.myDate.getFullYear() - 1970;  
        },  
        getAbsoluteMonth: function() {  
            return this.getAbsoluteYear() * 12 + this.myDate.getMonth();  
        },  
        /**  
         * @description 获得绝对日期  
         * 这里采取的方法为 得到从1970至今的毫秒数,然后转为天  
         */  
        getAbsoluteDate: function() {  
            var absoluteMillons = this.getAbsoluteMillonsTime();  
            //毫秒-秒-分-时-天  
            return parseInt(absoluteMillons / 1000 / 60 / 60 / 24, 10);  
        },  
        getAbsoluteHours: function() {  
            return this.getAbsoluteDate() * 24 + this.myDate.getHours();  
        },  
        getAbsoluteMinutes: function() {  
            return this.getAbsoluteHours() * 60 + this.myDate.getMinutes();  
        },  
        getAbsoluteSeconds: function() {  
            return this.getAbsoluteMinutes() * 60 + this.myDate.getSeconds();  
        },  
        /**  
         * @description 得到从1970年开始到现在的毫秒数  
         * 单位是毫秒  
         */  
        getAbsoluteMillonsTime: function() {  
            return this.myDate.getTime();  
        },  
        getDayOfWeek: function(pattern) {  
            //0(周日) 到 6(周六  
            //var week = ['日','一','二','三','四','五','六'];  
            return this.myDate.getDay();  
        },  
        isLeapYear: function() {  
            return (0 == this.myDate.getYear() % 4 && ((this.myDate.getYear() % 100 != 0) || (this.myDate.getYear() % 400 == 0)));  
        },  
        toDate: function() {  
            return cloneDate(this.myDate);  
        },  
        clone: function() {  
            return new MyDate(cloneDate(this.myDate));  
        },  
        /**  
         * @description 得到一个日期的最小时间  
         * @param {String}method = [YYYY|MM|DD|hh|mm|ss] field 分别代表年,月,日,时,分,秒的抉择  
         */  
        getBegin: function(field) {  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                switch (field) {  
                    case 'YYYY': //year  
                        mDate.setMonth(0);  
                        mDate.setDate(1);  
                        mDate.setHours(0);  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'MM': //month  
                        mDate.setDate(1);  
                        mDate.setHours(0);  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                    case 'DD': //date  
                        mDate.setHours(0);  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'hh': //hour  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'mm': //minute  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'ss': //seconds  
                        mDate.setMilliseconds(0);  
                        break;  
                    default:  
                        //Ignore  
                }  
            }));  
        },  
        /**  
         * @description 得到一个日期的最大时间  
         * @param {String}method = [YYYY|MM|DD|hh|mm|ss] field 分别代表年,月,日,时,分,秒的抉择  
         */  
        getEnd: function(field) {  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                switch (field) {  
                    case 'YYYY': //year  
                        mDate.setMonth(11);  
                        mDate.setDate(31);  
                        mDate.setHours(23);  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'MM': //month  
                        mDate.setDate(getActualMaximum(mDate));  
                        mDate.setHours(23);  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                    case 'DD': //date  
                        mDate.setHours(23);  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'hh': //hour  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'mm': //minute  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'ss': //seconds  
                        mDate.setMilliseconds(999);  
                        break;  
                    default:  
                        //Ignore  
                }  
            }));  
        },  
        /**  
         * @description 和另一个日期比较,另一个日期必须为MyDate型  
         * @param {Date} targetDate 目标日期,MyDate型  
         * @param {String} method = [YYYY|MM|DD|hh|mm|ss|iii] pettern 选择字符串,目前支持 yyyy,MM,dd,HH,mm,ss以及iii  
         * 分别代表比较到某一个层次,默认为比较到毫秒  
         * @return {Number} 返回结果  
         * -1:比较字符对象不合法  
         * 0:两个日期相等  
         * 1:本日期大于目标日期  
         * 2:本日期小于目标日期  
         */  
        compare: function(targetDate, pattern) {  
            //如果不是时间类型,而且不是MyDate类型  
            if (!isDate(targetDate) && !(targetDate instanceof MyDate)) {  
                return -1;  
            }  
            //默认为毫秒  
            pattern = pattern || 'iii';  
            if (pattern === 'YYYY') {  
                if (this.getAbsoluteYear() == targetDate.getAbsoluteYear()) {  
                    return 0;  
                } else if (this.getAbsoluteYear() > targetDate.getAbsoluteYear()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'MM') {  
                if (this.getAbsoluteMonth() == targetDate.getAbsoluteMonth()) {  
                    return 0;  
                } else if (this.getAbsoluteMonth() > targetDate.getAbsoluteMonth()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'DD') {  
                if (this.getAbsoluteDate() == targetDate.getAbsoluteDate()) {  
                    return 0;  
                } else if (this.getAbsoluteDate() > targetDate.getAbsoluteDate()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'hh') {  
                if (this.getAbsoluteHours() == targetDate.getAbsoluteHours()) {  
                    return 0;  
                } else if (this.getAbsoluteHours() > targetDate.getAbsoluteHours()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'mm') {  
                if (this.getAbsoluteMinutes() == targetDate.getAbsoluteMinutes()) {  
                    return 0;  
                } else if (this.getAbsoluteMinutes() > targetDate.getAbsoluteMinutes()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'ss') {  
                if (this.getAbsoluteSeconds() == targetDate.getAbsoluteSeconds()) {  
                    return 0;  
                } else if (this.getAbsoluteSeconds() > targetDate.getAbsoluteSeconds()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else {  
                if (this.getAbsoluteMillonsTime() == targetDate.getAbsoluteMillonsTime()) {  
                    return 0;  
                } else if (this.getAbsoluteMillonsTime() > targetDate.getAbsoluteMillonsTime()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            }  
        },  
        isMoreThan: function(targetDate, pattern) {  
            return this.compare(targetDate, pattern) == 1 ? true : false;  
        },  
        isLessThan: function(targetDate, pattern) {  
            return this.compare(targetDate, pattern) == 2 ? true : false;  
        },  
        isEqual: function(targetDate, pattern) {  
            return this.compare(targetDate, pattern) == 0 ? true : false;  
        },  
        toString: function(pattern) {  
            return formatDateToString(this.myDate, pattern);  
        }  
    };  
    exports.MyDate = MyDate;       
})(window.DateUtil={});
继续阅读 »

前言:最近在用到JS日期操作时,发现有一些不方便,于是搜素了一些网上的资料,基于一个开源工具类-yDate 进行了个性化定制,封装成了一个日期工具类
工具函数大概介绍:
1.普通的日期操作

  1. 获得一些绝对时间,如1970年 到现在的绝对年,月份,日期,描述,毫秒数等等
  2. 日期比较,克隆,开始时间,结束时间,字符串(输出时可以自定义格式)输出等
  3. 日期相加,相减(返回一个新的日期对象), 比如1月31日 1天会自动变为 2月1日等等
  4. 简化构造,可以传入字符串进行构造等等
  5. 更多请看源码
    说明-基于yDate:| yDate.js | Copyright (c) 2013 yao.yl | email: redrainyi@126.com | Date: 2012-09-03 | *
    原地址: http://www.oschina.net/code/snippet_913265_20123

源码如下:

/**  
 * @description 日期工具类  
 * 原作来源: | yDate.js | Copyright (c) 2013 yao.yl | email: redrainyi@126.com | Date: 2012-09-03 | *   
 * 地址: http://www.oschina.net/code/snippet_913265_20123#comments  
 * 改动说明: 针对yDate进行了一些个性化的修改,以及增加了一些工具函数  
 * @author dailc  dailc  
 * @version 2.0  
 * @time 2016-01-14 12:57:57  
 * 功能模块:  
 * Date相关模块********************************  
 * core/MobileFrame/DateUtil  
 * 1.构造方法  
 * 2.对象的相关功能函数-见源码和文档  
 * Date相关模块结束*****************************  
 */  
(function(exports) {  
    "use strict";  
    var objectPrototypeToString = Object.prototype.toString;  
    /**  
     * 日期匹配的正则表达式  
     * Y:年  
     * M:月  
     * D:日  
     * h:小时  
     * m:分钟  
     * s:秒  
     * i:毫秒  
     * w:星期(小写的)  
     * W:星期(大写的)  
     */  
    var SIGN_DATE_REG = /([YMDhmsiWw])(\1*)/g;  
    /**  
     * 默认的pattern  
     * 'YYYY-MM-DD hh:mm:ss:iii'  
     */  
    var DEFAULT_PATTERN = 'YYYY-MM-DD hh:mm:ss:iii';  
    /**  
     * @description 判断一个值是否是日期类型  
     * @param {Object} value  
     */  
    function isDate(value) {  
        return objectPrototypeToString.call(value) === '[object Date]';  
    };  
    /**  
     * @description 复制一个日期,如果传入的不是日期,会返回一个最新的日期  
     * @param {Date} targetDate  
     */  
    function cloneDate(targetDate, callBack) {  
        //绝对时间,从1970.1.1开始的毫秒数  
        var absoluteTime = (isDate(targetDate)) ? targetDate.getTime() : undefined;  
        var mDate = new Date(absoluteTime);  
        var year = mDate.getFullYear(), //  
            month = mDate.getMonth(), //  
            date = mDate.getDate(), //  
            hours = mDate.getHours(), //  
            minutes = mDate.getMinutes(), //   
            seconds = mDate.getSeconds(); //  
        //!! 代表将后面的转为一个布尔表达式   例如 !!a 就相当于 a||false  
        (!!callBack) && callBack(mDate, year, month, date, hours, minutes, seconds);  
        return mDate;  
    };  
    /**  
     * @description 日期解析,将日期字符串根据特定的匹配字符串解析为日期格式  
     * 解析失败会返回null,如果传入了奇怪的匹配字符串,会产生奇怪的时间  
     * @param {String} dateString 日期字符串  
     * @param {String} pattern 匹配字符串,可以手动传入,或者采取默认  
     * 手动传入需要和日期字符串保持一致  
     */  
    function parseDate(dateString, pattern) {  

        try {  
            //() 是为了提取匹配的字符串。表达式中有几个()就有几个相应的匹配字符串。  
            //(\s*)表示连续空格的字符串。  
            //[]是定义匹配的字符范围。比如 [a-zA-Z0-9] 表示相应位置的字符要匹配英文字符和数字。  
            //[\s*]表示空格或者*号。  
            //{}一般用来表示匹配的长度,比如 \s{3} 表示匹配三个空格,\s[1,3]表示匹配一到三个空格。  
            //(\1)是后向引用,代表后面引用前面第一个()中的内容  
            //根据日期格式来匹配  
            var matchs1 = (pattern || (dateString.length === 10 ? 'YYYY-MM-DD' : (dateString.length === 19 ? 'YYYY-MM-DD hh:mm:ss' : 'YYYY-MM-DD hh:mm:ss:iii'))).match(SIGN_DATE_REG);  
            //根据整数来匹配,将实际的时间数据提取出来  
            var matchs2 = dateString.match(/(\d)+/g);  
            if (matchs1.length > 0) {  
                //第一个匹配字符串需要大于0才行  
                //生成一个最原始的时间-1970-01-01年的  
                var mDate = new Date(1970, 0, 1);  
                //遍历,分别设置年月日,分秒等等  
                for (var i = 0; i < matchs1.length; i++) {  
                    //这个分别是  年,月,日  时,分,秒等等  
                    var mTarget = parseInt(matchs2[i], 10);  
                    switch (matchs1[i].charAt(0) || '') {  
                        //这个matchs1[i]有可能是  YYYY  所以只去第一个字符  
                        case 'Y':  
                            mDate.setFullYear(mTarget);  
                            break;  
                        case 'M':  
                            mDate.setMonth(mTarget - 1);  
                            break;  
                        case 'D':  
                            mDate.setDate(mTarget);  
                            break;  
                        case 'h':  
                            mDate.setHours(mTarget);  
                            break;  
                        case 'm':  
                            mDate.setMinutes(mTarget);  
                            break;  
                        case 's':  
                            mDate.setSeconds(mTarget);  
                            break;  
                        case 'i':  
                            mDate.setMilliseconds(mTarget);  
                            break;  
                        default:  
                            //默认不操作  
                    }  
                }  
                return mDate;  
            }  
        } catch (e) {  

        }  
        return null;  
    };  
    /**  
     * @description 将字符串多余的长度补齐0  
     * @param {String} s  
     * @param {Number} len  
     */  
    function paddingFillWith0(s, len) {  
        var len = len - (s + "").length;  
        for (var i = 0; i < len; i++) {  
            s = "0" + s;  
        }  
        return s;  
    }  
    /**  
     * @description 格式化时间,返回格式化后的字符串  
     * 如果格式不合要求,返回null  
     * @param {Date} value 目标时间  
     * @param {String} pattern 匹配字符串  
     */  
    function formatDateToString(value, pattern) {  
        if (!isDate(value)) {  
            return '';  
        }  
        try {  
            //默认为输出所有的  
            pattern = pattern || DEFAULT_PATTERN;  
            return pattern.replace(SIGN_DATE_REG, function($0) {  
                //如果传入一个yyyy-MM-dd 的表达式  
                //实际上这个函数会分别回调多次 没符合一次匹配就回调一次  
                //$0:yyyy  $0:MM $0:dd  依次类推  
                //console.log('$0:'+$0);  
                switch ($0.charAt(0)) {  
                    case 'Y':  
                        return paddingFillWith0(value.getFullYear(), $0.length);  
                    case 'M':  
                        return paddingFillWith0(value.getMonth() + 1, $0.length);  
                    case 'D':  
                        return paddingFillWith0(value.getDate(), $0.length);  
                    case 'h':  
                        return paddingFillWith0(value.getHours(), $0.length);  
                    case 'm':  
                        return paddingFillWith0(value.getMinutes(), $0.length);  
                    case 's':  
                        return paddingFillWith0(value.getSeconds(), $0.length);  
                    case 'i':  
                        return paddingFillWith0(value.getMilliseconds(), $0.length);  
                    case 'w':  
                        return value.getDay();  
                    case 'W':  
                        //自动将星期转为了大写  
                        var week = ['日', '一', '二', '三', '四', '五', '六'];  
                        return paddingFillWith0(week[value.getDay()], $0.length);  
                    default:  
                        return '';  
                }  
            });  
        } catch (e) {  
            console.log('error:' + e);  
            return '';  
        }  
    };  
    /**  
     * @description 得到实际日期最大值  
     * @param {Date} date  
     */  
    function getActualMaximum(date) {  
        var vDate = new Date(date.getTime());  
        vDate.setMonth(vDate.getMonth() + 1);  
        vDate.setDate(0);  
        return vDate.getDate();  
    }  
    /**  
     * @description 定义一个自定义日期类的构造方法,  
     * 里面封装日期的常用操作,不通过自带的日期来操作  
     * @constructor 这是一个构造方法  
     */  
    function MyDate() {  
        var p0 = arguments[0];  
        var p1 = arguments[1];  
        //isFinite 用于判断是否是无穷大  
        //如果 number 是有限数字(或可转换为有限数字),那么返回 true  
        //如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false  
        if (typeof p0 === 'number' && isFinite(value)) {  
            this.myDate = new Date(p0); //millis  
        } else if (isDate(p0)) {  
            this.myDate = new Date(p0.getTime());  
        } else if (typeof p0 === 'string') {  
            if (typeof p1 !== 'string' && typeof p1 !== 'undefined') {  
                p1 = undefined;  
            }  
            this.myDate = parseDate(p0, p1);  
        } else if (arguments.length == 0) {  
            this.myDate = new Date();  
        } else {  
            throw 'MyDate Constructor Error!';  
        }  
    };  
    /**  
     * @description 给一个日期设置年份  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setYearG(finalYear, mDate, self) {  
        mDate.setFullYear(finalYear);  
    }  
    /**  
     * @description 给一个日期设置月份  
     * 之所以要单独将设置月份(年,日,时...)的函数抽取出来,是因为  
     * 在日期时间 加,减操作时,会涉及到一个进位问题: 比如,1月31日的下一天应该是2月1日...  
     * 所以单独封装成函数便于调用  
     * 之所以没有 直接调用plusMonth,plusYear...  
     * 是因为这个操作中间有回调,多个回调嵌套后,无法同步返回最准确的数据  
     * (可以自行测试)  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setMonthG(finalMon, mDate, self) {  
        //month 为 0-11  
        if (finalMon > 11) {  
            finalMon = finalMon - 12;  
            setYearG(mDate.getFullYear() + 1, mDate, self);  
        } else if (finalMon < 0) {  
            finalMon += 12;  
            setYearG(mDate.getFullYear() - 1, mDate, self);  
        }  
        /*  
         * 关于月份顺延的bug  
         发现如下规律:只要setMonth()的参数为小于31天的月份时就会变为下一个月。  
          原因是:因为当前月份是31天,而设置的月份小于31天,就会把日期顺延。在setMonth的说明是这样的:  
          dateObj.setMonth(numMonth[, dateVal])  
          dateVal  
        可选项。一个代表日期的数值。  
        如果没有提供此参数,那么将使用通过调用 getDate 方法而得到的数值。  
        所以,从对dataVal参数的说明可以看出,在设置月份的同时,  
        使用getDate获取日期,并使用得到的日期值设置了日期。  
        于是就会发生月份顺延的情况。  
        解决方法:  
      1、设置月份时,将日期设为1,记setMonth(month, 1),  
      当然可以在setMonth之前先调用setDate()设置日期;  
      2、也可以在初始化Date对象时,就指定一个日期,也就是使用:  
      dateObj = new Date(year, month, date[, hours[, minutes[, seconds[,ms]]]]) 的形式。  
      3、也可以使用setFullYear()同时设置年、月、日,即setFullYear(numYear[, numMonth[, numDate]])。   
        *bug简单说明:  
        * 如果当前是10月31日,然后设置月份为11,由于11月没有31天,所以月份会顺延  
        * 自动变为12月,所以解决方法是要在设置月份前先把日期设置下,然后之后再继续设置日期  
        * (因为日期肯定是需要改变的)  
        *   
        * * * */  
        mDate.setMonth(finalMon, 1);  

    }  
    /**  
     * @description 给一个日期设置日期  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setDateG(finalDay, mDate, self) {  
        var month = mDate.getMonth();  
        var monthDays = self.getMonthDays(month + 1);  
        if (finalDay > monthDays) {  
            finalDay -= monthDays;  
            setMonthG(mDate.getMonth() + 1, mDate, self);  
        } else if (finalDay <= 0) {  
            var lastMonthDay = month > 0 ? self.getMonthDays((month + 1 - 1)) : self.getMonthDays(12);  
            finalDay += lastMonthDay;  
            setMonthG(mDate.getMonth() - 1, mDate, self);  
        }  
        mDate.setDate(finalDay);  
    }  
    /**  
     * @description 给一个日期设置小时  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setHourG(finalHour, mDate, self) {  
        if (finalHour >= 24) {  
            finalHour -= 24;  
            setDateG(mDate.getDate() + 1, mDate, self);  
        } else if (finalHour < 0) {  
            finalHour += 24;  
            setDateG(mDate.getDate() - 1, mDate, self);  
        }  
        mDate.setHours(finalHour);  
    }  
    /**  
     * @description 给一个日期设置分钟  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setMinG(finalMin, mDate, self) {  
        if (finalMin >= 60) {  
            finalMin -= 60;  
            setHourG(mDate.getHours() + 1, mDate, self);  
        } else if (finalHour < 0) {  
            finalMin += 60;  
            setHourG(mDate.getHours() - 1, mDate, self);  
        }  
        mDate.setMinutes(finalMin);  
    }  
    /**  
     * @description 给一个日期设置秒  
     * @param {Number} finalYear  
     * @param {Date} mDate  
     * @param {MyDate} self  
     */  
    function setSecG(finalSec, mDate, self) {  
        if (finalSec >= 60) {  
            finalSec -= 60;  
            setMinG(mDate.getMinutes() + 1, mDate, self);  
        } else if (finalSec < 0) {  
            finalSec += 60;  
            setMinG(mDate.getMinutes() - 1, mDate, self);  
        }  
        mDate.setSeconds(finalSec);  
    }  
    /**  
     * @description 通过扩充原型添加方法  
     */  
    MyDate.prototype = {  
        /**  
         * @description 得到一个月有多少天  
         * @param {Number} month 对应的月份  
         */  
        getMonthDays: function(month) {  
            switch (month) {  
                case 1:  
                case 3:  
                case 5:  
                case 7:  
                case 8:  
                case 10:  
                case 12:  
                    return 31;  
                    break;  
                case 4:  
                case 6:  
                case 9:  
                case 11:  
                    return 30;  
                    break;  
                case 2:  
                    if (this.isLeapYear()) {  
                        return 29;  
                    } else {  
                        return 28;  
                    }  
                    break;  
                default:  
                    return 0;  
                    break;  
            }  
        },  
        /**  
         * @description 年份相加,返回一个新的日期  
         * @param {Object} value  
         */  
        plusYear: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                setYearG(year + value, mDate, self);  
            }));  
        },  
        plusMonth: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                setMonthG(month + value, mDate, self);  
            }));  
        },  
        plusDate: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalDay = date + value;  
                setDateG(finalDay, mDate, self);  
            }));  
        },  
        plusHours: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalHour = hours + value;  
                setHourG(finalHour, mDate, self);  
            }));  
        },  
        plusMinutes: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalMin = minutes + value;  
                setMinG(finalMin, mDate, self);  
            }));  
        },  
        plusSeconds: function(value) {  
            var self = this;  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                var finalSec = seconds + value;  
                setSecG(finalSec, mDate, self);  
            }));  
        },  
        minusYear: function(value) {  
            return this.plusYear(-value);  
        },  
        minusMonth: function(value) {  
            return this.plusMonth(-value);  
        },  
        minusDate: function(value) {  
            return this.plusDate(-value);  
        },  
        minusHours: function(value) {  
            return this.plusHours(-value);  
        },  
        minusMinutes: function(value) {  
            return this.plusMinutes(-value);  
        },  
        minusSeconds: function(value) {  
            return this.plusSeconds(-value);  
        },  
        setYear: function(value) {  
            this.myDate.setFullYear(value);  
        },  
        setMonth: function(value) {  
            this.myDate.setMonth(value - 1);  
        },  
        setDate: function(value) {  
            this.myDate.setDate(value);  
        },  
        setHours: function(value) {  
            this.myDate.setHours(value);  
        },  
        setMinutes: function(value) {  
            this.myDate.setMinutes(value);  
        },  
        setSeconds: function(value) {  
            this.myDate.setSeconds(value);  
        },  
        setMilliseconds: function(value) {  
            this.myDate.setMilliseconds(value);  
        },  
        getYear: function() {  
            return this.myDate.getFullYear();  
        },  
        getMonth: function() {  
            //比普通月份小1  
            return this.myDate.getMonth();  
        },  
        getDate: function() {  
            return this.myDate.getDate();  
        },  
        getHours: function() {  
            return this.myDate.getHours();  
        },  
        getMinutes: function() {  
            return this.myDate.getMinutes();  
        },  
        getSeconds: function() {  
            return this.myDate.getSeconds();  
        },  
        getMilliseconds: function() {  
            return this.myDate.getMilliseconds();  
        },  
        /**  
         * @description 得到从1970至今多少年  
         */  
        getAbsoluteYear: function() {  
            return this.myDate.getFullYear() - 1970;  
        },  
        getAbsoluteMonth: function() {  
            return this.getAbsoluteYear() * 12 + this.myDate.getMonth();  
        },  
        /**  
         * @description 获得绝对日期  
         * 这里采取的方法为 得到从1970至今的毫秒数,然后转为天  
         */  
        getAbsoluteDate: function() {  
            var absoluteMillons = this.getAbsoluteMillonsTime();  
            //毫秒-秒-分-时-天  
            return parseInt(absoluteMillons / 1000 / 60 / 60 / 24, 10);  
        },  
        getAbsoluteHours: function() {  
            return this.getAbsoluteDate() * 24 + this.myDate.getHours();  
        },  
        getAbsoluteMinutes: function() {  
            return this.getAbsoluteHours() * 60 + this.myDate.getMinutes();  
        },  
        getAbsoluteSeconds: function() {  
            return this.getAbsoluteMinutes() * 60 + this.myDate.getSeconds();  
        },  
        /**  
         * @description 得到从1970年开始到现在的毫秒数  
         * 单位是毫秒  
         */  
        getAbsoluteMillonsTime: function() {  
            return this.myDate.getTime();  
        },  
        getDayOfWeek: function(pattern) {  
            //0(周日) 到 6(周六  
            //var week = ['日','一','二','三','四','五','六'];  
            return this.myDate.getDay();  
        },  
        isLeapYear: function() {  
            return (0 == this.myDate.getYear() % 4 && ((this.myDate.getYear() % 100 != 0) || (this.myDate.getYear() % 400 == 0)));  
        },  
        toDate: function() {  
            return cloneDate(this.myDate);  
        },  
        clone: function() {  
            return new MyDate(cloneDate(this.myDate));  
        },  
        /**  
         * @description 得到一个日期的最小时间  
         * @param {String}method = [YYYY|MM|DD|hh|mm|ss] field 分别代表年,月,日,时,分,秒的抉择  
         */  
        getBegin: function(field) {  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                switch (field) {  
                    case 'YYYY': //year  
                        mDate.setMonth(0);  
                        mDate.setDate(1);  
                        mDate.setHours(0);  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'MM': //month  
                        mDate.setDate(1);  
                        mDate.setHours(0);  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                    case 'DD': //date  
                        mDate.setHours(0);  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'hh': //hour  
                        mDate.setMinutes(0);  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'mm': //minute  
                        mDate.setSeconds(0);  
                        mDate.setMilliseconds(0);  
                        break;  
                    case 'ss': //seconds  
                        mDate.setMilliseconds(0);  
                        break;  
                    default:  
                        //Ignore  
                }  
            }));  
        },  
        /**  
         * @description 得到一个日期的最大时间  
         * @param {String}method = [YYYY|MM|DD|hh|mm|ss] field 分别代表年,月,日,时,分,秒的抉择  
         */  
        getEnd: function(field) {  
            return new MyDate(cloneDate(this.myDate, function(mDate, year, month, date, hours, minutes, seconds) {  
                switch (field) {  
                    case 'YYYY': //year  
                        mDate.setMonth(11);  
                        mDate.setDate(31);  
                        mDate.setHours(23);  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'MM': //month  
                        mDate.setDate(getActualMaximum(mDate));  
                        mDate.setHours(23);  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                    case 'DD': //date  
                        mDate.setHours(23);  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'hh': //hour  
                        mDate.setMinutes(59);  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'mm': //minute  
                        mDate.setSeconds(59);  
                        mDate.setMilliseconds(999);  
                        break;  
                    case 'ss': //seconds  
                        mDate.setMilliseconds(999);  
                        break;  
                    default:  
                        //Ignore  
                }  
            }));  
        },  
        /**  
         * @description 和另一个日期比较,另一个日期必须为MyDate型  
         * @param {Date} targetDate 目标日期,MyDate型  
         * @param {String} method = [YYYY|MM|DD|hh|mm|ss|iii] pettern 选择字符串,目前支持 yyyy,MM,dd,HH,mm,ss以及iii  
         * 分别代表比较到某一个层次,默认为比较到毫秒  
         * @return {Number} 返回结果  
         * -1:比较字符对象不合法  
         * 0:两个日期相等  
         * 1:本日期大于目标日期  
         * 2:本日期小于目标日期  
         */  
        compare: function(targetDate, pattern) {  
            //如果不是时间类型,而且不是MyDate类型  
            if (!isDate(targetDate) && !(targetDate instanceof MyDate)) {  
                return -1;  
            }  
            //默认为毫秒  
            pattern = pattern || 'iii';  
            if (pattern === 'YYYY') {  
                if (this.getAbsoluteYear() == targetDate.getAbsoluteYear()) {  
                    return 0;  
                } else if (this.getAbsoluteYear() > targetDate.getAbsoluteYear()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'MM') {  
                if (this.getAbsoluteMonth() == targetDate.getAbsoluteMonth()) {  
                    return 0;  
                } else if (this.getAbsoluteMonth() > targetDate.getAbsoluteMonth()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'DD') {  
                if (this.getAbsoluteDate() == targetDate.getAbsoluteDate()) {  
                    return 0;  
                } else if (this.getAbsoluteDate() > targetDate.getAbsoluteDate()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'hh') {  
                if (this.getAbsoluteHours() == targetDate.getAbsoluteHours()) {  
                    return 0;  
                } else if (this.getAbsoluteHours() > targetDate.getAbsoluteHours()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'mm') {  
                if (this.getAbsoluteMinutes() == targetDate.getAbsoluteMinutes()) {  
                    return 0;  
                } else if (this.getAbsoluteMinutes() > targetDate.getAbsoluteMinutes()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else if (pattern === 'ss') {  
                if (this.getAbsoluteSeconds() == targetDate.getAbsoluteSeconds()) {  
                    return 0;  
                } else if (this.getAbsoluteSeconds() > targetDate.getAbsoluteSeconds()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            } else {  
                if (this.getAbsoluteMillonsTime() == targetDate.getAbsoluteMillonsTime()) {  
                    return 0;  
                } else if (this.getAbsoluteMillonsTime() > targetDate.getAbsoluteMillonsTime()) {  
                    return 1;  
                } else {  
                    return 2;  
                }  
            }  
        },  
        isMoreThan: function(targetDate, pattern) {  
            return this.compare(targetDate, pattern) == 1 ? true : false;  
        },  
        isLessThan: function(targetDate, pattern) {  
            return this.compare(targetDate, pattern) == 2 ? true : false;  
        },  
        isEqual: function(targetDate, pattern) {  
            return this.compare(targetDate, pattern) == 0 ? true : false;  
        },  
        toString: function(pattern) {  
            return formatDateToString(this.myDate, pattern);  
        }  
    };  
    exports.MyDate = MyDate;       
})(window.DateUtil={});
收起阅读 »

分享移动端图片压缩上传(整理修改微社区图片上传,带UI,带demo,demo服务器端用php)

图片压缩 照片压缩 uploader 源码 技术分享

20160411更新:
使同个页面可以配置调用多个上传图片
20160418更新:
修复上传进度条不准
增加上传样式2,调整部分样式

一些配置问题:
objUploadImg.uploadMaxW = 2000; //生成图片的最大宽度
objUploadImg.uploadMaxH = 2000; //生成图片的最大高度
*建议这两项默认800800
objUploadImg.uploadPicMore = true;//是否允许多图上传 默认单张上传
即便开启,安卓也只支持单张上传
objUploadImg.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
最好不要过多,因为图片在前端用H5 <canvas> 处理,测试过配置最大宽高为2000px时,iPhone6微信端一次上传20张会出现微信自动关闭;如果同个页面调用多个上传方法,一次上传的最大张数之和最好不超过10张**

其他的自行查看附件demo,随便贴几段代码,注意JS代码的引用位置

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="utf-8">  
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />  
    <title>图片上传</title>  
    <link rel="stylesheet" href="css/mobile-uploadImg.css">  

    <script src="js/jquery-1.9.0.js"></script>  
    <script src="js/mobile-uploadCompresserImg.js"></script>  
    <script src="js/mobile-uploadImg.js"></script>  

</head>  
<body style="background: #f5f5f5;">  
<div style="margin:20px 10px;">  
    <form method="post" action="">  
        <div id="uploadImgForm">  
            <div class="mbupload_frame">  
                <div class="mbupload_photoList">  
                    <ul>  
                        <li class="mbupload_on mbupload_addPic mbupload_addImg"></li>  
                    </ul>  
                    <p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>  
                </div>  
                <div class="mbupload_bgimg">  
                    <div class="iconSendImg mbupload_addImg" style="background:url(images/upload_carbg.png) no-repeat 50% 50%;"></div>  
                </div>  
            </div>  
        </div>  

        <div style="margin-top:20px;">  
            <div id="uploadImgForm2" class="uploadImgStyle2">  
                <div class="mbupload_frame">  
                    <div class="mbupload_photoList">  
                        <ul>  
                            <li class="mbupload_on mbupload_addPic mbupload_addImg"></li>  
                        </ul>  
                        <p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>  
                    </div>  
                    <div class="mbupload_bgimg">  
                        <div class="iconSendImg mbupload_addImg" style="background:url(images/upload_licensebg.png) no-repeat 50% 50%;"></div>  
                    </div>  
                </div>  
            </div>  
        </div>  
    </form>  
</div>  

<script type="text/javascript">  
    var objUploadImgForm = {};  
    objUploadImgForm.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址  
    objUploadImgForm.formHtmlId = "#uploadImgForm";//上传图片的ID  
    objUploadImgForm.maxUpload = 20;//上传图片的最大张数  
    objUploadImgForm.uploadMaxW = 2000; //生成图片的最大宽度  
    objUploadImgForm.uploadMaxH = 2000; //生成图片的最大高度  
    objUploadImgForm.uploadQuality = 1; //目标jpg图片输出质量  
    objUploadImgForm.uploadPicSize = 8;//上传限制图片大小(MB)  默认8M  
    objUploadImgForm.uploadPicMore = true;//是否允许多图上传  默认单张上传  
    objUploadImgForm.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10  
    objUploadImgForm.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址  
    mobileUploadImg(objUploadImgForm);  
</script>  

<script type="text/javascript">  
    var objUploadImgForm2 = {};  
    objUploadImgForm2.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址  
    objUploadImgForm2.formHtmlId = "#uploadImgForm2";//上传图片的ID  
    objUploadImgForm2.maxUpload = 1;//上传图片的最大张数  
    objUploadImgForm2.uploadMaxW = 800; //生成图片的最大宽度  
    objUploadImgForm2.uploadMaxH = 800; //生成图片的最大高度  
    objUploadImgForm2.uploadQuality = 1; //目标jpg图片输出质量  
    objUploadImgForm2.uploadPicSize = 8;//上传限制图片大小(MB)  默认8M  
    objUploadImgForm2.uploadPicMore = true;//是否允许多图上传  默认单张上传  
    objUploadImgForm2.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10  
    objUploadImgForm2.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址  
    mobileUploadImg(objUploadImgForm2);  
</script>  
</body>  
</html>
/**  
 * @filename mobile-uploadImg  
 * @description  
 * 作者: 418239385(418239385@qq.com)  
 * 创建时间: 2016-4-6 14:38:03  
 * 修改记录:  
 *  
 **/  
//------------------------------------------------------------------------------  
function mobileUploadImg(opts)  
{  
    if(opts == null){  
        objGlobal.DIC.dialog({content:'请配置上传图片的相关参数!', autoClose:false, okValue:"确定", isMask:true});  
        return;  
    }  
    var objUploadImg = {};  
    var opts = opts || {};  
    //上传图片的表单ID  
    objUploadImg.formHtmlId = opts.formHtmlId || "";  
    //最大上传图片量  
    objUploadImg.maxUpload = opts.maxUpload || 8;  
    //生成图片的最大宽度  
    objUploadImg.uploadMaxW = opts.uploadMaxW || 800;  
    //生成图片的最大高度  
    objUploadImg.uploadMaxH = opts.uploadMaxH || 800;  
    //目标jpg图片输出质量  
    objUploadImg.uploadQuality = opts.uploadQuality || 1;  
    //上传限制图片体积(MB)   默认8M  
    objUploadImg.uploadPicSize = opts.uploadPicSize || 8;  
    //是否允许多图上传  默认单张上传  
    objUploadImg.uploadPicMore = opts.uploadPicMore || false;  
    //多图上传时,一次上传的最大张数 默认10  
    objUploadImg.onceMaxUpload = opts.onceMaxUpload || 10;  
    // 上传图片地址  
    objUploadImg.uploadUrl = opts.uploadUrl || "";  
    //压缩图片时的默认图片地址  
    objUploadImg.uploadDefaultImgUrl = opts.uploadDefaultImgUrl || "";  
    //多图上传时,上传第一张到最后一张的状态  
    objUploadImg.isMoreBusy = false;  
    // 上传信息 主要是 id 对应信息  
    objUploadImg.uploadInfo = {};  
    // 上传队列,里面保存的是 id  
    objUploadImg.uploadQueue = [];  
    // 预览队列,里面保存的是 id  
    objUploadImg.previewQueue = [];  
    // 请求对象  
    objUploadImg.xhr = {};  
    // 是否有图片正在压缩  
    objUploadImg.isEncoderBusy = false;  
    // 是否有任务正在上传  
    objUploadImg.isBusy = false;  

    if(objUploadImg.formHtmlId.length <= 0){  
        objGlobal.DIC.dialog({content:'请配置上传图片的容器ID!', autoClose:false, okValue:"确定", isMask:true});  
        return;  
    }  

    if(objUploadImg.uploadUrl.length <= 0){  
        objGlobal.DIC.dialog({content:'请配置上传图片的URL地址!', autoClose:false, okValue:"确定", isMask:true});  
        return;  
    }  

    objUploadImg.countUpload = function() {  
        var num = 0;  
        $.each(objUploadImg.uploadInfo, function(i, n) {  
            if (n) {  
                ++ num;  
            }  
        });  
        return num;  
    };  

    // 图片预览  
    objUploadImg.uploadPreview = function(id) {  
        var reader = new FileReader();  

        var uploadBase64;  
        var conf = {}, file = objUploadImg.uploadInfo[id].file;  

        conf = {  
            maxW: objUploadImg.uploadMaxW, //目标宽  
            maxH: objUploadImg.uploadMaxH, //目标高  
            quality: objUploadImg.uploadQuality, //目标jpg图片输出质量  
        };  

        reader.onload = function(e) {  
            var result = this.result;  

            // 如果是jpg格式图片,读取图片拍摄方向,自动旋转  
            if (file.type == 'image/jpeg'){  
                try {  
                    var jpg = new objJpegMeata.JpegMeta.JpegFile(result, file.name);  
                } catch (e) {  
                    objGlobal.DIC.dialog({content:'图片不是正确的图片数据', autoClose:true});  
                    $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                    objUploadImg.isEncoderBusy = false;  
                    return false;  
                }  
                if (jpg.tiff && jpg.tiff.Orientation) {  
                    //设置旋转  
                    conf = $.extend(conf, {  
                        orien: jpg.tiff.Orientation.value  
                    });  
                }  
            }  

            // 压缩  
            if (objImageCompresser.ImageCompresser.support()) {  
                var img = new Image();  
                img.onload = function() {  
                    try {  
                        uploadBase64 = objImageCompresser.ImageCompresser.getImageBase64(this, conf);  
                    } catch (e) {  
                        objGlobal.DIC.dialog({content:'压缩图片失败', autoClose:true});  
                        $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                        objUploadImg.isEncoderBusy = false;  
                        return false;  
                    }  
                    if (uploadBase64.indexOf('data:image') < 0) {  
                        objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});  
                        $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                        objUploadImg.isEncoderBusy = false;  
                        return false;  
                    }  

                    objUploadImg.uploadInfo[id].file = uploadBase64;  
                    $(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);  
                    objUploadImg.uploadQueue.push(id);  
                }  
                img.onerror = function() {  
                    objGlobal.DIC.dialog({content:'解析图片数据失败', autoClose:true});  
                    $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                    objUploadImg.isEncoderBusy = false;  
                    return false;  
                }  
                img.src = objImageCompresser.ImageCompresser.getFileObjectURL(file);  
            } else {  
                uploadBase64 = result;  
                if (uploadBase64.indexOf('data:image') < 0) {  
                    objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});  
                    $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                    objUploadImg.isEncoderBusy = false;  
                    return false;  
                }  

                objUploadImg.uploadInfo[id].file = uploadBase64;  
                $(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);  
                objUploadImg.uploadQueue.push(id);  
            }  
        }  

        reader.readAsBinaryString(objUploadImg.uploadInfo[id].file);  
    };  

    // 创建上传请求  
    objUploadImg.createUpload = function(id, type, uploadTimer) {  
        if (!objUploadImg.uploadInfo[id]) {  
            objUploadImg.isEncoderBusy = false;  
            objUploadImg.isBusy = false;  
            return false;  
        }  
        // 移除图片压缩中...  
        $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();  

        // 图片posturl  
        var uploadUrl = objUploadImg.uploadUrl;  
        // 产生进度条  
        var progressHtml = '<div class="mbupload_progress mbupload_brSmall" id="mbupload_progress'+id+'"><div class="mbupload_proBar" style="width:0%;"></div></div>';  
        $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').after(progressHtml);  

        var formData = new FormData();  
        formData.append('upload_pic', objUploadImg.uploadInfo[id].file);  
        formData.append('upload_name', objUploadImg.uploadInfo[id].oldFileInfo.name);  
        formData.append('upload_id', id);  

        var progress = function(e) {  
            if (e.target.response) {  
                var result = $.parseJSON(e.target.response);  

                if (result.errCode != 0) {  
                    // $('#content').val(result.errCode);  
                    objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});  
                    removePic(id);  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    return false;  
                }  
            }  

            var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');  
            if (e.total == e.loaded) {  
                var percent = 100;  
            } else {  
                var percent = 100*(e.loaded / e.total);  
            }  

            // 控制进度条不要超出  
            if (percent > 100) {  
                percent = 100;  
            }  

            progress.width(percent + '%');  
            //progress.animate({'width': '95%'}, 1500);  

            setTimeout(function(){  
                if (percent == 100) {  
                    donePic(id);  
                    var pLength = 0, nLength = 0;  
                    if(objUploadImg.uploadPicMore){  
                        pLength = objUploadImg.previewQueue.length;  
                        nLength = objUploadImg.uploadQueue.length;  
                    }  
                    if(uploadTimer && pLength <= 0 && nLength <= 0){  
                        clearInterval(uploadTimer);  
                    }  
                }  
            }, 400);  
        }  

        var removePic = function(id) {  
            donePic(id);  
            $('#li' + id).remove();  
        }  

        var donePic = function(id) {  
            objUploadImg.isEncoderBusy = false;  
            objUploadImg.isBusy = false;  
            if(objUploadImg.uploadPicMore && (objUploadImg.previewQueue.length <= 0) &&  
                 (objUploadImg.uploadQueue.length <= 0)){  
                objUploadImg.isMoreBusy = false;  
            }  
            if (typeof objUploadImg.uploadInfo[id] != 'undefined') {  
                objUploadImg.uploadInfo[id].isDone = true;  
            }  
            if (typeof objUploadImg.xhr[id] != 'undefined') {  
                objUploadImg.xhr[id] = null;  
            }  
        }  

        var complete = function(e) {  
            var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');  
            progress.css('width', '100%');  
            if($(objUploadImg.formHtmlId + ' #li' + id)){  
                $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();  
            }  
            $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').remove();  
            $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_progress').remove();  
            // 上传结束  
            donePic(id);  

            var result = $.parseJSON(e.target.response);  
            if (result.errCode == 0) {  
                var input = '<input type="hidden" id="input' + result.data.id + '" name="picIds[]" value="' + result.data.picId + '">';  
                if(type == 'replyForm'){  
                    $('#replyForm').append(input);  
                }else{  
                    $(objUploadImg.formHtmlId).append(input);  
                }  

            } else {  
                objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});  
                removePic(id);  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                delete objUploadImg.uploadInfo[id];  
                // 如果传略失败,上传个数少于限制张数则再显示加号  
                if (objUploadImg.countUpload() < objUploadImg.maxUpload) {  
                    $(objUploadImg.formHtmlId + ' .mbupload_addPic').show();  
                }  
            }  
        }  

        var failed = function() {  
            objGlobal.DIC.dialog({content:'网络断开,请稍后重新操作', autoClose:true});  
            removePic(id)  
        }  

        var abort = function() {  
            objGlobal.DIC.dialog({content:'上传已取消', autoClose:true});  
            removePic(id)  
        }  

        // 创建 ajax 请求  
        objUploadImg.xhr[id] = new XMLHttpRequest();  
        objUploadImg.xhr[id].addEventListener("progress", progress, false);  
        objUploadImg.xhr[id].upload.addEventListener("progress", progress, false);  
        objUploadImg.xhr[id].addEventListener("load", complete, false);  
        objUploadImg.xhr[id].addEventListener("abort", abort, false);  
        objUploadImg.xhr[id].addEventListener("error", failed, false);  
        objUploadImg.xhr[id].open("POST", uploadUrl);  
        objUploadImg.xhr[id].send(formData);  
    };  

    // 不能上传系统提示  
    objUploadImg.checkUploadBySysVer = function() {  
        var mb_os = objGlobal.checkUA();  
        if (mb_os.ios && mb_os.version.toString() < '6.0') {  
            objGlobal.DIC.dialog({content:'手机系统不支持传图,请升级到ios6.0以上', autoClose:true});  
            return false;  
        }  

        if (mb_os.wx && mb_os.wxVersion.toString() < '5.2') {  
            objGlobal.DIC.dialog({content:'当前微信版本不支持传图,请升级到最新版', autoClose:true});  
            return false;  
        }  
        return true;  
    };  

    //根据是否可以多图上传生成对应的input  
    objUploadImg.uploadAddInput = function(){  
        var input = "", fistInput = "";  
        if(objUploadImg.uploadPicMore){  
            input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" multiple="">';  
            fistInput = '<input type="file" class="fistUpload" accept="image/*" multiple="">';  
        }else{  
            input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" single="">';  
            fistInput = '<input type="file" class="fistUpload" accept="image/*" single="">';  
        }  
        $(objUploadImg.formHtmlId + ' .mbupload_addPic').append(input);  
        $(objUploadImg.formHtmlId + ' .iconSendImg').append(fistInput);  
    };  

    //剩余上传数  
    objUploadImg.uploadRemaining = function(){  
        var uploadNum = 0;  
        uploadNum = $(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length;  

        var canOnlyUploadNum = objUploadImg.maxUpload;  

        if(uploadNum <= objUploadImg.maxUpload)  
        {  
            canOnlyUploadNum = objUploadImg.maxUpload - uploadNum + 1;  
        }  
        else  
        {  
            canOnlyUploadNum = 0;  
        }  

        //当上传出错则显示第一上传页面  
        if(canOnlyUploadNum == objUploadImg.maxUpload)  
        {  
            $(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();  
            $(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();  
        }  

        //更新剩余可上传图片数  
        $(objUploadImg.formHtmlId + ' .mbupload_onlyUploadNum').html(canOnlyUploadNum);  
    };  

    // 检查图片大小  
    objUploadImg.checkPicSize = function(file) {  
        var uploadPicSize = objUploadImg.uploadPicSize*1024*1024;  
        if (file.size > uploadPicSize) {  
            return false;  
        }  
        return true;  
    };  

    // 检查图片类型  
    objUploadImg.checkPicType = function(file) {  
        var photoReg = (/\.png$|\.bmp$|\.jpg$|\.jpeg$|\.gif$/i);  
        if(!photoReg.test(file.name)){  
           return false;  
        }else{  
            return true;  
        }  
    };  

    var uploadTimer = null;  

    var initUpload = function()  
    {  
        // 上传图片的绑定  
        $(objUploadImg.formHtmlId + ' .mbupload_addImg').on("click", function(){  
            if(!objUploadImg.checkUploadBySysVer()){  
                return false;  
            }  
        });  

        $(objUploadImg.formHtmlId + ' .mbupload_uploadFile').on("click", function(){  
            var thisObj = $(this);  
            if (objUploadImg.isEncoderBusy) {  
                return false;  
            }  
            else if (objUploadImg.isBusy) {  
                objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});  
                return false;  
            }  
            else if (objUploadImg.isMoreBusy) {  
                objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});  
                return false;  
            }  
        });  

        //首次点击图片的图标,触发一次手机的默认上传事件  
        $('body').on('change', objUploadImg.formHtmlId + ' .fistUpload', function(e){  
            $(objUploadImg.formHtmlId + ' .mbupload_photoList').show();  
            $(objUploadImg.formHtmlId + ' .mbupload_bgimg').hide();  
        });  

        // 文件表单发生变化时  
        $('body').on('change', objUploadImg.formHtmlId + ' .mbupload_uploadFile,' + objUploadImg.formHtmlId + ' .fistUpload', function(e) {  
            //执行图片预览、压缩定时器  
            uploadTimer = setInterval(function() {  
                // 预览  
                setTimeout(function() {  
                    if (!objUploadImg.isEncoderBusy && objUploadImg.previewQueue.length) {  
                        var jobId = objUploadImg.previewQueue.shift();  
                        objUploadImg.isEncoderBusy = true;  
                        objUploadImg.uploadPreview(jobId);  
                    }  
                }, 1);  

                // 上传  
                setTimeout(function() {  
                    if (!objUploadImg.isBusy && objUploadImg.uploadQueue.length) {  
                        var jobId = objUploadImg.uploadQueue.shift();  
                        objUploadImg.isBusy = true;  
                        if(objUploadImg.uploadPicMore){  
                            objUploadImg.isMoreBusy = true;  
                        }  
                        objUploadImg.createUpload(jobId, objUploadImg.formHtmlId, uploadTimer);  
                    }  
                }, 10);  
            }, 300);  

            e = e || window.event;  
            var fileList = e.target.files;  

            if (!fileList.length) {  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                $(this).val('');  
                return false;  
            }  

            if (objUploadImg.uploadPicMore && (fileList.length > objUploadImg.onceMaxUpload)) {  
                objGlobal.DIC.dialog({content:'上传图片一次最多只能选' + objUploadImg.onceMaxUpload + '张', autoClose:true});  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                $(this).val('');  
                return false;  
            }  

            if (objUploadImg.uploadPicMore && (fileList.length > (objUploadImg.maxUpload - objUploadImg.countUpload()))) {  
                objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                $(this).val('');  
                return false;  
            }  

            for (var i = 0; i < fileList.length; i++) {  
                if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {  
                    objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    $(this).val('');  
                    break;  
                }  

                var file = fileList[i];  

                if (!objUploadImg.checkPicType(file)) {  
                    objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    $(this).val('');  
                    continue;  
                }  
                // console.log(file);  
                if (!objUploadImg.checkPicSize(file)) {  
                    objGlobal.DIC.dialog({content:'图片大小超过'+ objUploadImg.uploadPicSize + 'MB', autoClose:true});  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    $(this).val('');  
                    continue;  
                }  

                var id = Date.now() + i;  
                // 增加到上传对象中, 上传完成后,修改为 true  
                objUploadImg.uploadInfo[id] = {  
                    oldFileInfo: file,  
                    file: file,  
                    isDone: false,  
                };  

                var html = '<li id="li' + id + '"><div class="mbupload_photoCut"><img src="' + objUploadImg.uploadDefaultImgUrl + '" class="attchImg" alt="photo"></div>' +  
                        '<div class="mbupload_maskLay"></div>' +  
                        '<div class="mbupload_maskTxt">图片压缩中...</div>' +  
                        '<a href="javascript:;" class="mbupload_cBtn mbupload_pa mbupload_db" title="" _id="'+id+'">关闭</a></li>';  
                $(objUploadImg.formHtmlId + ' .mbupload_addPic').before(html);  

                objUploadImg.previewQueue.push(id);  

                // 图片已经上传了 最大限制 张数,隐藏 + 号  
                if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {  
                    $(objUploadImg.formHtmlId + ' .mbupload_addPic').hide();  
                }  
                //更新剩余上传数  
                setTimeout(function(){  
                    objUploadImg.uploadRemaining();  
                }, 400);  
            }  
            // 把输入框清空  
            $(this).val('');  
        });  

        $(objUploadImg.formHtmlId + ' .mbupload_photoList').on('click', '.mbupload_cBtn', function() {  
            var id = $(this).attr('_id');  

            // 取消这个请求  
            if (objUploadImg.xhr[id]) {  
                objUploadImg.xhr[id].abort();  
            }  
            // 图片删除  
            $(objUploadImg.formHtmlId + ' #li' + id).remove();  
            // 表单中删除  
            $(objUploadImg.formHtmlId + ' #input' + id).remove();  
            objUploadImg.uploadInfo[id] = null;  

            // 图片变少了,显示+号  
            if (objUploadImg.countUpload() < objUploadImg.maxUpload) {  
                $(objUploadImg.formHtmlId + ' .mbupload_addPic').show();  
            }  
            //更新剩余上传数  
            objUploadImg.uploadRemaining();  

            //当删除所有图片后隐藏添加图片的图标  
            if($(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length < 2){  
                $(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();  
                $(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();  
            }  
        });          
    };  

    objUploadImg.uploadAddInput();  
    objUploadImg.uploadRemaining();  
    initUpload();  
};
继续阅读 »

20160411更新:
使同个页面可以配置调用多个上传图片
20160418更新:
修复上传进度条不准
增加上传样式2,调整部分样式

一些配置问题:
objUploadImg.uploadMaxW = 2000; //生成图片的最大宽度
objUploadImg.uploadMaxH = 2000; //生成图片的最大高度
*建议这两项默认800800
objUploadImg.uploadPicMore = true;//是否允许多图上传 默认单张上传
即便开启,安卓也只支持单张上传
objUploadImg.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10
最好不要过多,因为图片在前端用H5 <canvas> 处理,测试过配置最大宽高为2000px时,iPhone6微信端一次上传20张会出现微信自动关闭;如果同个页面调用多个上传方法,一次上传的最大张数之和最好不超过10张**

其他的自行查看附件demo,随便贴几段代码,注意JS代码的引用位置

<!DOCTYPE html>  
<html>  
<head>  
    <meta charset="utf-8">  
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />  
    <title>图片上传</title>  
    <link rel="stylesheet" href="css/mobile-uploadImg.css">  

    <script src="js/jquery-1.9.0.js"></script>  
    <script src="js/mobile-uploadCompresserImg.js"></script>  
    <script src="js/mobile-uploadImg.js"></script>  

</head>  
<body style="background: #f5f5f5;">  
<div style="margin:20px 10px;">  
    <form method="post" action="">  
        <div id="uploadImgForm">  
            <div class="mbupload_frame">  
                <div class="mbupload_photoList">  
                    <ul>  
                        <li class="mbupload_on mbupload_addPic mbupload_addImg"></li>  
                    </ul>  
                    <p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>  
                </div>  
                <div class="mbupload_bgimg">  
                    <div class="iconSendImg mbupload_addImg" style="background:url(images/upload_carbg.png) no-repeat 50% 50%;"></div>  
                </div>  
            </div>  
        </div>  

        <div style="margin-top:20px;">  
            <div id="uploadImgForm2" class="uploadImgStyle2">  
                <div class="mbupload_frame">  
                    <div class="mbupload_photoList">  
                        <ul>  
                            <li class="mbupload_on mbupload_addPic mbupload_addImg"></li>  
                        </ul>  
                        <p class="mbupload_textTip mbupload_f12">还可上传<span class="mbupload_onlyUploadNum"></span>张照片呦~</p>  
                    </div>  
                    <div class="mbupload_bgimg">  
                        <div class="iconSendImg mbupload_addImg" style="background:url(images/upload_licensebg.png) no-repeat 50% 50%;"></div>  
                    </div>  
                </div>  
            </div>  
        </div>  
    </form>  
</div>  

<script type="text/javascript">  
    var objUploadImgForm = {};  
    objUploadImgForm.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址  
    objUploadImgForm.formHtmlId = "#uploadImgForm";//上传图片的ID  
    objUploadImgForm.maxUpload = 20;//上传图片的最大张数  
    objUploadImgForm.uploadMaxW = 2000; //生成图片的最大宽度  
    objUploadImgForm.uploadMaxH = 2000; //生成图片的最大高度  
    objUploadImgForm.uploadQuality = 1; //目标jpg图片输出质量  
    objUploadImgForm.uploadPicSize = 8;//上传限制图片大小(MB)  默认8M  
    objUploadImgForm.uploadPicMore = true;//是否允许多图上传  默认单张上传  
    objUploadImgForm.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10  
    objUploadImgForm.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址  
    mobileUploadImg(objUploadImgForm);  
</script>  

<script type="text/javascript">  
    var objUploadImgForm2 = {};  
    objUploadImgForm2.uploadUrl = "<?php echo('http://'.$_SERVER['HTTP_HOST'].'/uploads.php') ?>";//上传图片的地址  
    objUploadImgForm2.formHtmlId = "#uploadImgForm2";//上传图片的ID  
    objUploadImgForm2.maxUpload = 1;//上传图片的最大张数  
    objUploadImgForm2.uploadMaxW = 800; //生成图片的最大宽度  
    objUploadImgForm2.uploadMaxH = 800; //生成图片的最大高度  
    objUploadImgForm2.uploadQuality = 1; //目标jpg图片输出质量  
    objUploadImgForm2.uploadPicSize = 8;//上传限制图片大小(MB)  默认8M  
    objUploadImgForm2.uploadPicMore = true;//是否允许多图上传  默认单张上传  
    objUploadImgForm2.onceMaxUpload = 10;//多图上传时,一次上传的最大张数 默认10  
    objUploadImgForm2.uploadDefaultImgUrl = "images/defaultImg.png";//压缩图片时的默认图片地址  
    mobileUploadImg(objUploadImgForm2);  
</script>  
</body>  
</html>
/**  
 * @filename mobile-uploadImg  
 * @description  
 * 作者: 418239385(418239385@qq.com)  
 * 创建时间: 2016-4-6 14:38:03  
 * 修改记录:  
 *  
 **/  
//------------------------------------------------------------------------------  
function mobileUploadImg(opts)  
{  
    if(opts == null){  
        objGlobal.DIC.dialog({content:'请配置上传图片的相关参数!', autoClose:false, okValue:"确定", isMask:true});  
        return;  
    }  
    var objUploadImg = {};  
    var opts = opts || {};  
    //上传图片的表单ID  
    objUploadImg.formHtmlId = opts.formHtmlId || "";  
    //最大上传图片量  
    objUploadImg.maxUpload = opts.maxUpload || 8;  
    //生成图片的最大宽度  
    objUploadImg.uploadMaxW = opts.uploadMaxW || 800;  
    //生成图片的最大高度  
    objUploadImg.uploadMaxH = opts.uploadMaxH || 800;  
    //目标jpg图片输出质量  
    objUploadImg.uploadQuality = opts.uploadQuality || 1;  
    //上传限制图片体积(MB)   默认8M  
    objUploadImg.uploadPicSize = opts.uploadPicSize || 8;  
    //是否允许多图上传  默认单张上传  
    objUploadImg.uploadPicMore = opts.uploadPicMore || false;  
    //多图上传时,一次上传的最大张数 默认10  
    objUploadImg.onceMaxUpload = opts.onceMaxUpload || 10;  
    // 上传图片地址  
    objUploadImg.uploadUrl = opts.uploadUrl || "";  
    //压缩图片时的默认图片地址  
    objUploadImg.uploadDefaultImgUrl = opts.uploadDefaultImgUrl || "";  
    //多图上传时,上传第一张到最后一张的状态  
    objUploadImg.isMoreBusy = false;  
    // 上传信息 主要是 id 对应信息  
    objUploadImg.uploadInfo = {};  
    // 上传队列,里面保存的是 id  
    objUploadImg.uploadQueue = [];  
    // 预览队列,里面保存的是 id  
    objUploadImg.previewQueue = [];  
    // 请求对象  
    objUploadImg.xhr = {};  
    // 是否有图片正在压缩  
    objUploadImg.isEncoderBusy = false;  
    // 是否有任务正在上传  
    objUploadImg.isBusy = false;  

    if(objUploadImg.formHtmlId.length <= 0){  
        objGlobal.DIC.dialog({content:'请配置上传图片的容器ID!', autoClose:false, okValue:"确定", isMask:true});  
        return;  
    }  

    if(objUploadImg.uploadUrl.length <= 0){  
        objGlobal.DIC.dialog({content:'请配置上传图片的URL地址!', autoClose:false, okValue:"确定", isMask:true});  
        return;  
    }  

    objUploadImg.countUpload = function() {  
        var num = 0;  
        $.each(objUploadImg.uploadInfo, function(i, n) {  
            if (n) {  
                ++ num;  
            }  
        });  
        return num;  
    };  

    // 图片预览  
    objUploadImg.uploadPreview = function(id) {  
        var reader = new FileReader();  

        var uploadBase64;  
        var conf = {}, file = objUploadImg.uploadInfo[id].file;  

        conf = {  
            maxW: objUploadImg.uploadMaxW, //目标宽  
            maxH: objUploadImg.uploadMaxH, //目标高  
            quality: objUploadImg.uploadQuality, //目标jpg图片输出质量  
        };  

        reader.onload = function(e) {  
            var result = this.result;  

            // 如果是jpg格式图片,读取图片拍摄方向,自动旋转  
            if (file.type == 'image/jpeg'){  
                try {  
                    var jpg = new objJpegMeata.JpegMeta.JpegFile(result, file.name);  
                } catch (e) {  
                    objGlobal.DIC.dialog({content:'图片不是正确的图片数据', autoClose:true});  
                    $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                    objUploadImg.isEncoderBusy = false;  
                    return false;  
                }  
                if (jpg.tiff && jpg.tiff.Orientation) {  
                    //设置旋转  
                    conf = $.extend(conf, {  
                        orien: jpg.tiff.Orientation.value  
                    });  
                }  
            }  

            // 压缩  
            if (objImageCompresser.ImageCompresser.support()) {  
                var img = new Image();  
                img.onload = function() {  
                    try {  
                        uploadBase64 = objImageCompresser.ImageCompresser.getImageBase64(this, conf);  
                    } catch (e) {  
                        objGlobal.DIC.dialog({content:'压缩图片失败', autoClose:true});  
                        $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                        objUploadImg.isEncoderBusy = false;  
                        return false;  
                    }  
                    if (uploadBase64.indexOf('data:image') < 0) {  
                        objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});  
                        $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                        objUploadImg.isEncoderBusy = false;  
                        return false;  
                    }  

                    objUploadImg.uploadInfo[id].file = uploadBase64;  
                    $(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);  
                    objUploadImg.uploadQueue.push(id);  
                }  
                img.onerror = function() {  
                    objGlobal.DIC.dialog({content:'解析图片数据失败', autoClose:true});  
                    $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                    objUploadImg.isEncoderBusy = false;  
                    return false;  
                }  
                img.src = objImageCompresser.ImageCompresser.getFileObjectURL(file);  
            } else {  
                uploadBase64 = result;  
                if (uploadBase64.indexOf('data:image') < 0) {  
                    objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});  
                    $(objUploadImg.formHtmlId + ' #li' + id).remove();  
                    objUploadImg.isEncoderBusy = false;  
                    return false;  
                }  

                objUploadImg.uploadInfo[id].file = uploadBase64;  
                $(objUploadImg.formHtmlId + ' #li' + id).find('img').attr('src', uploadBase64);  
                objUploadImg.uploadQueue.push(id);  
            }  
        }  

        reader.readAsBinaryString(objUploadImg.uploadInfo[id].file);  
    };  

    // 创建上传请求  
    objUploadImg.createUpload = function(id, type, uploadTimer) {  
        if (!objUploadImg.uploadInfo[id]) {  
            objUploadImg.isEncoderBusy = false;  
            objUploadImg.isBusy = false;  
            return false;  
        }  
        // 移除图片压缩中...  
        $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();  

        // 图片posturl  
        var uploadUrl = objUploadImg.uploadUrl;  
        // 产生进度条  
        var progressHtml = '<div class="mbupload_progress mbupload_brSmall" id="mbupload_progress'+id+'"><div class="mbupload_proBar" style="width:0%;"></div></div>';  
        $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').after(progressHtml);  

        var formData = new FormData();  
        formData.append('upload_pic', objUploadImg.uploadInfo[id].file);  
        formData.append('upload_name', objUploadImg.uploadInfo[id].oldFileInfo.name);  
        formData.append('upload_id', id);  

        var progress = function(e) {  
            if (e.target.response) {  
                var result = $.parseJSON(e.target.response);  

                if (result.errCode != 0) {  
                    // $('#content').val(result.errCode);  
                    objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});  
                    removePic(id);  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    return false;  
                }  
            }  

            var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');  
            if (e.total == e.loaded) {  
                var percent = 100;  
            } else {  
                var percent = 100*(e.loaded / e.total);  
            }  

            // 控制进度条不要超出  
            if (percent > 100) {  
                percent = 100;  
            }  

            progress.width(percent + '%');  
            //progress.animate({'width': '95%'}, 1500);  

            setTimeout(function(){  
                if (percent == 100) {  
                    donePic(id);  
                    var pLength = 0, nLength = 0;  
                    if(objUploadImg.uploadPicMore){  
                        pLength = objUploadImg.previewQueue.length;  
                        nLength = objUploadImg.uploadQueue.length;  
                    }  
                    if(uploadTimer && pLength <= 0 && nLength <= 0){  
                        clearInterval(uploadTimer);  
                    }  
                }  
            }, 400);  
        }  

        var removePic = function(id) {  
            donePic(id);  
            $('#li' + id).remove();  
        }  

        var donePic = function(id) {  
            objUploadImg.isEncoderBusy = false;  
            objUploadImg.isBusy = false;  
            if(objUploadImg.uploadPicMore && (objUploadImg.previewQueue.length <= 0) &&  
                 (objUploadImg.uploadQueue.length <= 0)){  
                objUploadImg.isMoreBusy = false;  
            }  
            if (typeof objUploadImg.uploadInfo[id] != 'undefined') {  
                objUploadImg.uploadInfo[id].isDone = true;  
            }  
            if (typeof objUploadImg.xhr[id] != 'undefined') {  
                objUploadImg.xhr[id] = null;  
            }  
        }  

        var complete = function(e) {  
            var progress = $(objUploadImg.formHtmlId + ' #mbupload_progress' + id).find('.mbupload_proBar');  
            progress.css('width', '100%');  
            if($(objUploadImg.formHtmlId + ' #li' + id)){  
                $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskTxt').remove();  
            }  
            $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_maskLay').remove();  
            $(objUploadImg.formHtmlId + ' #li' + id).find('.mbupload_progress').remove();  
            // 上传结束  
            donePic(id);  

            var result = $.parseJSON(e.target.response);  
            if (result.errCode == 0) {  
                var input = '<input type="hidden" id="input' + result.data.id + '" name="picIds[]" value="' + result.data.picId + '">';  
                if(type == 'replyForm'){  
                    $('#replyForm').append(input);  
                }else{  
                    $(objUploadImg.formHtmlId).append(input);  
                }  

            } else {  
                objGlobal.DIC.dialog({content:'网络不稳定,请稍后重新操作', autoClose:true});  
                removePic(id);  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                delete objUploadImg.uploadInfo[id];  
                // 如果传略失败,上传个数少于限制张数则再显示加号  
                if (objUploadImg.countUpload() < objUploadImg.maxUpload) {  
                    $(objUploadImg.formHtmlId + ' .mbupload_addPic').show();  
                }  
            }  
        }  

        var failed = function() {  
            objGlobal.DIC.dialog({content:'网络断开,请稍后重新操作', autoClose:true});  
            removePic(id)  
        }  

        var abort = function() {  
            objGlobal.DIC.dialog({content:'上传已取消', autoClose:true});  
            removePic(id)  
        }  

        // 创建 ajax 请求  
        objUploadImg.xhr[id] = new XMLHttpRequest();  
        objUploadImg.xhr[id].addEventListener("progress", progress, false);  
        objUploadImg.xhr[id].upload.addEventListener("progress", progress, false);  
        objUploadImg.xhr[id].addEventListener("load", complete, false);  
        objUploadImg.xhr[id].addEventListener("abort", abort, false);  
        objUploadImg.xhr[id].addEventListener("error", failed, false);  
        objUploadImg.xhr[id].open("POST", uploadUrl);  
        objUploadImg.xhr[id].send(formData);  
    };  

    // 不能上传系统提示  
    objUploadImg.checkUploadBySysVer = function() {  
        var mb_os = objGlobal.checkUA();  
        if (mb_os.ios && mb_os.version.toString() < '6.0') {  
            objGlobal.DIC.dialog({content:'手机系统不支持传图,请升级到ios6.0以上', autoClose:true});  
            return false;  
        }  

        if (mb_os.wx && mb_os.wxVersion.toString() < '5.2') {  
            objGlobal.DIC.dialog({content:'当前微信版本不支持传图,请升级到最新版', autoClose:true});  
            return false;  
        }  
        return true;  
    };  

    //根据是否可以多图上传生成对应的input  
    objUploadImg.uploadAddInput = function(){  
        var input = "", fistInput = "";  
        if(objUploadImg.uploadPicMore){  
            input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" multiple="">';  
            fistInput = '<input type="file" class="fistUpload" accept="image/*" multiple="">';  
        }else{  
            input = '<input type="file" class="mbupload_on mbupload_uploadFile" accept="image/*" single="">';  
            fistInput = '<input type="file" class="fistUpload" accept="image/*" single="">';  
        }  
        $(objUploadImg.formHtmlId + ' .mbupload_addPic').append(input);  
        $(objUploadImg.formHtmlId + ' .iconSendImg').append(fistInput);  
    };  

    //剩余上传数  
    objUploadImg.uploadRemaining = function(){  
        var uploadNum = 0;  
        uploadNum = $(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length;  

        var canOnlyUploadNum = objUploadImg.maxUpload;  

        if(uploadNum <= objUploadImg.maxUpload)  
        {  
            canOnlyUploadNum = objUploadImg.maxUpload - uploadNum + 1;  
        }  
        else  
        {  
            canOnlyUploadNum = 0;  
        }  

        //当上传出错则显示第一上传页面  
        if(canOnlyUploadNum == objUploadImg.maxUpload)  
        {  
            $(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();  
            $(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();  
        }  

        //更新剩余可上传图片数  
        $(objUploadImg.formHtmlId + ' .mbupload_onlyUploadNum').html(canOnlyUploadNum);  
    };  

    // 检查图片大小  
    objUploadImg.checkPicSize = function(file) {  
        var uploadPicSize = objUploadImg.uploadPicSize*1024*1024;  
        if (file.size > uploadPicSize) {  
            return false;  
        }  
        return true;  
    };  

    // 检查图片类型  
    objUploadImg.checkPicType = function(file) {  
        var photoReg = (/\.png$|\.bmp$|\.jpg$|\.jpeg$|\.gif$/i);  
        if(!photoReg.test(file.name)){  
           return false;  
        }else{  
            return true;  
        }  
    };  

    var uploadTimer = null;  

    var initUpload = function()  
    {  
        // 上传图片的绑定  
        $(objUploadImg.formHtmlId + ' .mbupload_addImg').on("click", function(){  
            if(!objUploadImg.checkUploadBySysVer()){  
                return false;  
            }  
        });  

        $(objUploadImg.formHtmlId + ' .mbupload_uploadFile').on("click", function(){  
            var thisObj = $(this);  
            if (objUploadImg.isEncoderBusy) {  
                return false;  
            }  
            else if (objUploadImg.isBusy) {  
                objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});  
                return false;  
            }  
            else if (objUploadImg.isMoreBusy) {  
                objGlobal.DIC.dialog({content:'上传中,请稍后添加', autoClose:true});  
                return false;  
            }  
        });  

        //首次点击图片的图标,触发一次手机的默认上传事件  
        $('body').on('change', objUploadImg.formHtmlId + ' .fistUpload', function(e){  
            $(objUploadImg.formHtmlId + ' .mbupload_photoList').show();  
            $(objUploadImg.formHtmlId + ' .mbupload_bgimg').hide();  
        });  

        // 文件表单发生变化时  
        $('body').on('change', objUploadImg.formHtmlId + ' .mbupload_uploadFile,' + objUploadImg.formHtmlId + ' .fistUpload', function(e) {  
            //执行图片预览、压缩定时器  
            uploadTimer = setInterval(function() {  
                // 预览  
                setTimeout(function() {  
                    if (!objUploadImg.isEncoderBusy && objUploadImg.previewQueue.length) {  
                        var jobId = objUploadImg.previewQueue.shift();  
                        objUploadImg.isEncoderBusy = true;  
                        objUploadImg.uploadPreview(jobId);  
                    }  
                }, 1);  

                // 上传  
                setTimeout(function() {  
                    if (!objUploadImg.isBusy && objUploadImg.uploadQueue.length) {  
                        var jobId = objUploadImg.uploadQueue.shift();  
                        objUploadImg.isBusy = true;  
                        if(objUploadImg.uploadPicMore){  
                            objUploadImg.isMoreBusy = true;  
                        }  
                        objUploadImg.createUpload(jobId, objUploadImg.formHtmlId, uploadTimer);  
                    }  
                }, 10);  
            }, 300);  

            e = e || window.event;  
            var fileList = e.target.files;  

            if (!fileList.length) {  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                $(this).val('');  
                return false;  
            }  

            if (objUploadImg.uploadPicMore && (fileList.length > objUploadImg.onceMaxUpload)) {  
                objGlobal.DIC.dialog({content:'上传图片一次最多只能选' + objUploadImg.onceMaxUpload + '张', autoClose:true});  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                $(this).val('');  
                return false;  
            }  

            if (objUploadImg.uploadPicMore && (fileList.length > (objUploadImg.maxUpload - objUploadImg.countUpload()))) {  
                objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});  
                //更新剩余上传数  
                objUploadImg.uploadRemaining();  
                $(this).val('');  
                return false;  
            }  

            for (var i = 0; i < fileList.length; i++) {  
                if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {  
                    objGlobal.DIC.dialog({content:'你最多只能上传' + objUploadImg.maxUpload + '张照片', autoClose:true});  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    $(this).val('');  
                    break;  
                }  

                var file = fileList[i];  

                if (!objUploadImg.checkPicType(file)) {  
                    objGlobal.DIC.dialog({content:'上传照片格式不支持', autoClose:true});  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    $(this).val('');  
                    continue;  
                }  
                // console.log(file);  
                if (!objUploadImg.checkPicSize(file)) {  
                    objGlobal.DIC.dialog({content:'图片大小超过'+ objUploadImg.uploadPicSize + 'MB', autoClose:true});  
                    //更新剩余上传数  
                    objUploadImg.uploadRemaining();  
                    $(this).val('');  
                    continue;  
                }  

                var id = Date.now() + i;  
                // 增加到上传对象中, 上传完成后,修改为 true  
                objUploadImg.uploadInfo[id] = {  
                    oldFileInfo: file,  
                    file: file,  
                    isDone: false,  
                };  

                var html = '<li id="li' + id + '"><div class="mbupload_photoCut"><img src="' + objUploadImg.uploadDefaultImgUrl + '" class="attchImg" alt="photo"></div>' +  
                        '<div class="mbupload_maskLay"></div>' +  
                        '<div class="mbupload_maskTxt">图片压缩中...</div>' +  
                        '<a href="javascript:;" class="mbupload_cBtn mbupload_pa mbupload_db" title="" _id="'+id+'">关闭</a></li>';  
                $(objUploadImg.formHtmlId + ' .mbupload_addPic').before(html);  

                objUploadImg.previewQueue.push(id);  

                // 图片已经上传了 最大限制 张数,隐藏 + 号  
                if (objUploadImg.countUpload() >= objUploadImg.maxUpload) {  
                    $(objUploadImg.formHtmlId + ' .mbupload_addPic').hide();  
                }  
                //更新剩余上传数  
                setTimeout(function(){  
                    objUploadImg.uploadRemaining();  
                }, 400);  
            }  
            // 把输入框清空  
            $(this).val('');  
        });  

        $(objUploadImg.formHtmlId + ' .mbupload_photoList').on('click', '.mbupload_cBtn', function() {  
            var id = $(this).attr('_id');  

            // 取消这个请求  
            if (objUploadImg.xhr[id]) {  
                objUploadImg.xhr[id].abort();  
            }  
            // 图片删除  
            $(objUploadImg.formHtmlId + ' #li' + id).remove();  
            // 表单中删除  
            $(objUploadImg.formHtmlId + ' #input' + id).remove();  
            objUploadImg.uploadInfo[id] = null;  

            // 图片变少了,显示+号  
            if (objUploadImg.countUpload() < objUploadImg.maxUpload) {  
                $(objUploadImg.formHtmlId + ' .mbupload_addPic').show();  
            }  
            //更新剩余上传数  
            objUploadImg.uploadRemaining();  

            //当删除所有图片后隐藏添加图片的图标  
            if($(objUploadImg.formHtmlId + ' .mbupload_photoList').find('li').length < 2){  
                $(objUploadImg.formHtmlId + ' .mbupload_photoList').hide();  
                $(objUploadImg.formHtmlId + ' .mbupload_bgimg').show();  
            }  
        });          
    };  

    objUploadImg.uploadAddInput();  
    objUploadImg.uploadRemaining();  
    initUpload();  
};
收起阅读 »

iOS键盘弹出后PopPicker出现的临时解决方法

mui

原因:和iOS中其他有input的地方出现错乱的情况一样,poppicker的样式使用了fixed:
.mui-poppicker {
position: fixed;
}
在mui.poppicker.css中。

所以,分别在poppicker的显示和隐藏代码中对poppicker的display做处理。这里的显示和隐藏其实是修改poppicker的样式bottom,分别是0px和-300px,配合了动画的css,并没有改变display,所以,键盘弹出时poppicker露了出来。

解决方法:
mui.poppicker.js中增加初始化、show和hide方法中display的改变。

           ```javascript  
           //init构造函数最后增加两行:                  
           self.panel.style.display = 'none';  
       self.body.style.display = 'none';  

           //显示  
    show: function(callback) {  
        var self = this;  
                    //增加以下2行  
        self.panel.style.display = 'block';  
        self.body.style.display = 'block';  

        self.callback = callback;  
        self.mask.show();  
        document.body.classList.add($.className('poppicker-active-for-page'));  
        self.panel.classList.add($.className('active'));  
        //处理物理返回键  
        self.__back = $.back;  
        $.back = function() {  
            self.hide();  
        };  
    },  
    //隐藏  
    hide: function() {  
        var self = this;  
        if (self.disposed) return;  
        self.panel.classList.remove($.className('active'));  
        self.mask.close();  
        document.body.classList.remove($.className('poppicker-active-for-page'));  

                    //增加以下2行  
        self.panel.style.display = 'none';  
        self.body.style.display = 'none';  

        //处理物理返回键  
        $.back=self.__back;  
    }
继续阅读 »

原因:和iOS中其他有input的地方出现错乱的情况一样,poppicker的样式使用了fixed:
.mui-poppicker {
position: fixed;
}
在mui.poppicker.css中。

所以,分别在poppicker的显示和隐藏代码中对poppicker的display做处理。这里的显示和隐藏其实是修改poppicker的样式bottom,分别是0px和-300px,配合了动画的css,并没有改变display,所以,键盘弹出时poppicker露了出来。

解决方法:
mui.poppicker.js中增加初始化、show和hide方法中display的改变。

           ```javascript  
           //init构造函数最后增加两行:                  
           self.panel.style.display = 'none';  
       self.body.style.display = 'none';  

           //显示  
    show: function(callback) {  
        var self = this;  
                    //增加以下2行  
        self.panel.style.display = 'block';  
        self.body.style.display = 'block';  

        self.callback = callback;  
        self.mask.show();  
        document.body.classList.add($.className('poppicker-active-for-page'));  
        self.panel.classList.add($.className('active'));  
        //处理物理返回键  
        self.__back = $.back;  
        $.back = function() {  
            self.hide();  
        };  
    },  
    //隐藏  
    hide: function() {  
        var self = this;  
        if (self.disposed) return;  
        self.panel.classList.remove($.className('active'));  
        self.mask.close();  
        document.body.classList.remove($.className('poppicker-active-for-page'));  

                    //增加以下2行  
        self.panel.style.display = 'none';  
        self.body.style.display = 'none';  

        //处理物理返回键  
        $.back=self.__back;  
    }
收起阅读 »

上拉加载的坑爹联想!

上拉加载

用Hbuild编辑器做上啦加载,被坑爹的联想害了一整天,无力吐槽,endPullupToRefresh(),就这个关闭方法,操,联想出来的是这样的endPullUpToRefresh,看哪个up,联想出来的是大写的,我就无语了,又遇到相同情况的注意一下!!!

用Hbuild编辑器做上啦加载,被坑爹的联想害了一整天,无力吐槽,endPullupToRefresh(),就这个关闭方法,操,联想出来的是这样的endPullUpToRefresh,看哪个up,联想出来的是大写的,我就无语了,又遇到相同情况的注意一下!!!

[源码分享]wordpress转APP玩具

源码 mui

Wordpress-Mobile-Application

利用wordpress作为后台,构建App

源码地址:github


用到的技术

html5+:http://www.dcloud.io/docs/api/
mui: http://dcloudio.github.io/mui/
hbuilder:[http://www.dcloud.io] (http://www.dcloud.io/)


构建方法

  1. 安装wordpress
  2. wordpress安装 wordpress rest api (2.0版本及以上)
  3. wordpress后台:设置/固定链接设置为文章格式
  4. 更改/js/app.js里面的name和菜单名称和对应的id(可在example.com/wp-json/wp/v2/categories查看)
  5. 下载hbuilde,选择文件/打开目录(打开本项目代码目录),双击manifest.json设置app名称和id,修改app图标和启动图。
  6. 点击发行,发行为原生应用,设置好开发者证书,然后打包。

打包成功后会自动下载到本地目录,这样一个App就制作好了。

项目截图

首页
菜单
搜索
正文

License

The MIT License (MIT)

Copyright (c) 2016 Zhen.Wang

继续阅读 »

Wordpress-Mobile-Application

利用wordpress作为后台,构建App

源码地址:github


用到的技术

html5+:http://www.dcloud.io/docs/api/
mui: http://dcloudio.github.io/mui/
hbuilder:[http://www.dcloud.io] (http://www.dcloud.io/)


构建方法

  1. 安装wordpress
  2. wordpress安装 wordpress rest api (2.0版本及以上)
  3. wordpress后台:设置/固定链接设置为文章格式
  4. 更改/js/app.js里面的name和菜单名称和对应的id(可在example.com/wp-json/wp/v2/categories查看)
  5. 下载hbuilde,选择文件/打开目录(打开本项目代码目录),双击manifest.json设置app名称和id,修改app图标和启动图。
  6. 点击发行,发行为原生应用,设置好开发者证书,然后打包。

打包成功后会自动下载到本地目录,这样一个App就制作好了。

项目截图

首页
菜单
搜索
正文

License

The MIT License (MIT)

Copyright (c) 2016 Zhen.Wang

收起阅读 »

5+App、wap2app的video、视频播放开发注意

video 视频

此文不适于uni-app,仅适于5+app

5+App、wap2app的视频播放有3种解决方案,使用HTML5的自带video、原生视频播放,以及使用Native.js调用外部播放器。

  1. HTML5自带video标签,可以播放符合HTML5规范的视频格式。
    注意不含flv、ra等三方商业公司的规范格式。
    HTML5的video在Android上有较多浏览器兼容性问题,这里有篇网友分享的经典文章讲述了HTML5 video的使用注意,http://ask.dcloud.net.cn/article/569
    注意事项,Android上使用video标签播放视频时,务必打开硬件加速,否则只有声音没有画面。
    HBuilder8.8.4以前的版本,在Android5的部分rom上是默认关闭硬件加速的,此时需强制打开硬件加速。创建webview时style里有个hardwareAccelerated参数,设置为true。
    硬件加速的详解参考文档http://ask.dcloud.net.cn/article/55
    视频全屏播放时有时不能自动横屏最大化,参考http://ask.dcloud.net.cn/article/1077
    HTML5自带video,如果想实现手势拖动进度,这里有篇参考文章http://ask.dcloud.net.cn/article/13263,但受限于HTML5的性能,拖动无法流畅跟手。
    从HBuilderX 2.5.3起,Android上新增了x5内核,使用x5播放视频,表现优于Webview自带的video标签。使用x5详见:https://ask.dcloud.net.cn/article/36806

iOS的视频播放,使用uiWebview和wkWebview有不同效果,wkWebview的视频播放自带AirPlay功能,可以直接连接电视。但需要注意wkWebview和uiWebview的差异,详见http://ask.dcloud.net.cn/article/1318

  1. 原生视频
    很多开发者对于HTML5自带视频有几处不满:
    a) 支持格式不丰富,比如flv
    b) 全屏后手势拖动不流畅,不能顺滑的拖动进度和音量、亮度
    在开发者提供直播推流时,5+引擎引入了专业视频解码库,也就顺便提供了plus.video的原生视频播放能力。
    但plus.video的原生视频播放会增加不少包体积,需要开发者自己平衡好需求。
    5+App里原生视频控件需要使用js创建,参考http://www.html5plus.org/doc/zh_cn/video.html
    uni-app里的video组件,默认不是HTML的video,默认就是原生video。
    使用原生video注意它的层级较高,覆盖原生控件,在5+app里使用plus.nativeObj.view,在uni-app里使用cover-view、plus.nativeObj.view、subnvue都可以,如果是nvue,那不存在层级问题,并且全屏后的视频也可以随意自定义界面。从体验角度,最好的是nvue的video。

  2. 除了HTML5的video,开发者也可以在Android上使用Native.js调用系统播放器来放视频。
    但视频的播放进度等状态无法回传给js层。
    参考http://ask.dcloud.net.cn/question/614

继续阅读 »

此文不适于uni-app,仅适于5+app

5+App、wap2app的视频播放有3种解决方案,使用HTML5的自带video、原生视频播放,以及使用Native.js调用外部播放器。

  1. HTML5自带video标签,可以播放符合HTML5规范的视频格式。
    注意不含flv、ra等三方商业公司的规范格式。
    HTML5的video在Android上有较多浏览器兼容性问题,这里有篇网友分享的经典文章讲述了HTML5 video的使用注意,http://ask.dcloud.net.cn/article/569
    注意事项,Android上使用video标签播放视频时,务必打开硬件加速,否则只有声音没有画面。
    HBuilder8.8.4以前的版本,在Android5的部分rom上是默认关闭硬件加速的,此时需强制打开硬件加速。创建webview时style里有个hardwareAccelerated参数,设置为true。
    硬件加速的详解参考文档http://ask.dcloud.net.cn/article/55
    视频全屏播放时有时不能自动横屏最大化,参考http://ask.dcloud.net.cn/article/1077
    HTML5自带video,如果想实现手势拖动进度,这里有篇参考文章http://ask.dcloud.net.cn/article/13263,但受限于HTML5的性能,拖动无法流畅跟手。
    从HBuilderX 2.5.3起,Android上新增了x5内核,使用x5播放视频,表现优于Webview自带的video标签。使用x5详见:https://ask.dcloud.net.cn/article/36806

iOS的视频播放,使用uiWebview和wkWebview有不同效果,wkWebview的视频播放自带AirPlay功能,可以直接连接电视。但需要注意wkWebview和uiWebview的差异,详见http://ask.dcloud.net.cn/article/1318

  1. 原生视频
    很多开发者对于HTML5自带视频有几处不满:
    a) 支持格式不丰富,比如flv
    b) 全屏后手势拖动不流畅,不能顺滑的拖动进度和音量、亮度
    在开发者提供直播推流时,5+引擎引入了专业视频解码库,也就顺便提供了plus.video的原生视频播放能力。
    但plus.video的原生视频播放会增加不少包体积,需要开发者自己平衡好需求。
    5+App里原生视频控件需要使用js创建,参考http://www.html5plus.org/doc/zh_cn/video.html
    uni-app里的video组件,默认不是HTML的video,默认就是原生video。
    使用原生video注意它的层级较高,覆盖原生控件,在5+app里使用plus.nativeObj.view,在uni-app里使用cover-view、plus.nativeObj.view、subnvue都可以,如果是nvue,那不存在层级问题,并且全屏后的视频也可以随意自定义界面。从体验角度,最好的是nvue的video。

  2. 除了HTML5的video,开发者也可以在Android上使用Native.js调用系统播放器来放视频。
    但视频的播放进度等状态无法回传给js层。
    参考http://ask.dcloud.net.cn/question/614

收起阅读 »

modal 弹出浮层的使用方法

.mui-modal {top:300px !important;}      
.mui-content{overflow-y:auto;}

.mui-modal {top:300px !important;} 用来控制距离顶部高度
.mui-content{overflow-y:auto;} 用来控制内容溢出后的自动上下滚动

就是浮层的背景遮罩效果暂时还不知道怎么弄

mui是好东西,但是文档真的太弱了,这个modal 都是藏在例子中的。。。。

再提供下这个例子的路径 :examples/modals.html

继续阅读 »
.mui-modal {top:300px !important;}      
.mui-content{overflow-y:auto;}

.mui-modal {top:300px !important;} 用来控制距离顶部高度
.mui-content{overflow-y:auto;} 用来控制内容溢出后的自动上下滚动

就是浮层的背景遮罩效果暂时还不知道怎么弄

mui是好东西,但是文档真的太弱了,这个modal 都是藏在例子中的。。。。

再提供下这个例子的路径 :examples/modals.html

收起阅读 »

安利一个小应用,以wordpress为后台的博客/资讯应用

以wordpress的Rest Api构建的app

  1. 为wordpress安装wp rest api插件
  2. 修改代码中url地址和菜单参数即可打包成自己的app
    和现有wordpress站点完美结合,pc+移动端,完美覆盖。

源码地址:GITHUB
(先占个坑,有空来完善,最近较忙,代码未整理,欢迎拍砖。)
还有很多功能未实现。。。。下载地址:http://pan.baidu.com/s/1i47SSTn

继续阅读 »

以wordpress的Rest Api构建的app

  1. 为wordpress安装wp rest api插件
  2. 修改代码中url地址和菜单参数即可打包成自己的app
    和现有wordpress站点完美结合,pc+移动端,完美覆盖。

源码地址:GITHUB
(先占个坑,有空来完善,最近较忙,代码未整理,欢迎拍砖。)
还有很多功能未实现。。。。下载地址:http://pan.baidu.com/s/1i47SSTn

收起阅读 »

HBuilder常用js汇总

/*  
 * 服务器的地址  
 */  
var strservicef = '';  
var strservices = '';  

/*  
 * 主要的公共函数  
 */  
var Fun_App = {  
    /**  
     * 完整的打开新页面方法  
     * @param {Object} _url  
     */  
    OpenPage: function(id, gethtmlurl,action,sendvalue) {  
        var page = mui.preload({  
            url:gethtmlurl,  
            id: gethtmlurl,  
        });  
        var getid = document.getElementById(id);  
        getid.addEventListener('tap', function() {  
                mui.openWindow({  
                    url:gethtmlurl,  
                    id:gethtmlurl,  
                    styles:{  
                      top:"44px",  
                      bottom:"50px",  
                      width:"100%",  
                      height:"100%"  
                    },  
                    extras:{  
                      kid:sendvalue  
                    },  
                    show:{  
                      autoShow:true,//页面loaded事件发生后自动显示,默认为true  
                      aniShow:action,//页面显示动画,默认为”slide-in-right“;  
                      duration:100//页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒;  
                    },  
                    waiting:{  
                      autoShow:true,//自动显示等待框,默认为true  
                      title:"正在加载..."//等待对话框上显示的提示内容  
                    }  
                })  
        });  
    },  
    /*  
     * 页面间传值的获取  
     */  
    getextrasdata: function(kid){  
        var self = plus.webview.currentWebview();  
        return self.kid;  
    },  
    /*  
     * ajax 数据请求方法  
     */  
    ExAjax: function(url, rdata) {  
        mui.ajax({  
            url: url,  
            type: "post",  
            data: rdata.config,  
            dataType: 'json',  
            timeout:10000,  
            success: function(data) {  
                rdata.fun_Success(data);  
            },  
            error: function(xhr, type, errorThrown) {  
                console.log(JSON.stringify(xhr) + type + "---" + errorThrown);  
            }  
        });  
    },  
    /*  
     * 数据存储的函数  
     */  
    storagedata: function(kname,sdata){  
        localStorage.setItem(kname,sdata);  
    },  
    /*  
     * 数据读取  
     */  
    getdata: function(kname){  
        return localStorage.getItem(kname);  
    },  
    /*  
     * 数据删除  
     */  
    deldata: function(kname){  
        localStorage.removeItem(kname);  
    },  
    /*  
     * 手势配置  
     */  
    gesture: function(){  
        var gs = {  
            gestureConfig:{  
               tap: true, //默认为true  
               doubletap: true, //默认为false  
               longtap: true, //默认为false  
               swipe: true, //默认为true  
               drag: true //默认为true  
        }  
        };  
        return gs;  
    },  
    /*  
     * 隐藏滚动条  
     */  
    delscroll: function(){  
        plus.webview.currentWebview().setStyle({  
            scrollIndicator: 'none',  
        });  
    },  
    /*   
     * 返回键退出程序  
     * 1秒内,连续两次按返回键,则退出应用  
     */  
    FunBackQuitAppL: function(){  
        var backFirst = null;  
        this.QuitApp = function() {  
            //首次按键,提示‘再按一次退出应用’  
            if (!backFirst) {  
                backFirst = new Date().getTime();  
                mui.toast('再按一次退出应用程序');  
                setTimeout(function() {  
                    backFirst = null;  
                }, 1000);  
            } else {  
                if ((new Date()).getTime() - backFirst < 1000) {  
                    plus.runtime.quit();  
                }  
            }  
        }  
    }  
}  
继续阅读 »
/*  
 * 服务器的地址  
 */  
var strservicef = '';  
var strservices = '';  

/*  
 * 主要的公共函数  
 */  
var Fun_App = {  
    /**  
     * 完整的打开新页面方法  
     * @param {Object} _url  
     */  
    OpenPage: function(id, gethtmlurl,action,sendvalue) {  
        var page = mui.preload({  
            url:gethtmlurl,  
            id: gethtmlurl,  
        });  
        var getid = document.getElementById(id);  
        getid.addEventListener('tap', function() {  
                mui.openWindow({  
                    url:gethtmlurl,  
                    id:gethtmlurl,  
                    styles:{  
                      top:"44px",  
                      bottom:"50px",  
                      width:"100%",  
                      height:"100%"  
                    },  
                    extras:{  
                      kid:sendvalue  
                    },  
                    show:{  
                      autoShow:true,//页面loaded事件发生后自动显示,默认为true  
                      aniShow:action,//页面显示动画,默认为”slide-in-right“;  
                      duration:100//页面动画持续时间,Android平台默认100毫秒,iOS平台默认200毫秒;  
                    },  
                    waiting:{  
                      autoShow:true,//自动显示等待框,默认为true  
                      title:"正在加载..."//等待对话框上显示的提示内容  
                    }  
                })  
        });  
    },  
    /*  
     * 页面间传值的获取  
     */  
    getextrasdata: function(kid){  
        var self = plus.webview.currentWebview();  
        return self.kid;  
    },  
    /*  
     * ajax 数据请求方法  
     */  
    ExAjax: function(url, rdata) {  
        mui.ajax({  
            url: url,  
            type: "post",  
            data: rdata.config,  
            dataType: 'json',  
            timeout:10000,  
            success: function(data) {  
                rdata.fun_Success(data);  
            },  
            error: function(xhr, type, errorThrown) {  
                console.log(JSON.stringify(xhr) + type + "---" + errorThrown);  
            }  
        });  
    },  
    /*  
     * 数据存储的函数  
     */  
    storagedata: function(kname,sdata){  
        localStorage.setItem(kname,sdata);  
    },  
    /*  
     * 数据读取  
     */  
    getdata: function(kname){  
        return localStorage.getItem(kname);  
    },  
    /*  
     * 数据删除  
     */  
    deldata: function(kname){  
        localStorage.removeItem(kname);  
    },  
    /*  
     * 手势配置  
     */  
    gesture: function(){  
        var gs = {  
            gestureConfig:{  
               tap: true, //默认为true  
               doubletap: true, //默认为false  
               longtap: true, //默认为false  
               swipe: true, //默认为true  
               drag: true //默认为true  
        }  
        };  
        return gs;  
    },  
    /*  
     * 隐藏滚动条  
     */  
    delscroll: function(){  
        plus.webview.currentWebview().setStyle({  
            scrollIndicator: 'none',  
        });  
    },  
    /*   
     * 返回键退出程序  
     * 1秒内,连续两次按返回键,则退出应用  
     */  
    FunBackQuitAppL: function(){  
        var backFirst = null;  
        this.QuitApp = function() {  
            //首次按键,提示‘再按一次退出应用’  
            if (!backFirst) {  
                backFirst = new Date().getTime();  
                mui.toast('再按一次退出应用程序');  
                setTimeout(function() {  
                    backFirst = null;  
                }, 1000);  
            } else {  
                if ((new Date()).getTime() - backFirst < 1000) {  
                    plus.runtime.quit();  
                }  
            }  
        }  
    }  
}  
收起阅读 »