API参考 - 筋斗云前端(移动Web版)

最后更新:2016-12-21

Modules

common.js (module)

MUI (module)


Keywords

#footer (key)

$.getScriptWithCache (fn)

.mui-android (key)

.mui-container (key)

.mui-cordova (key)

.mui-dialog (key)

.mui-ios (key)

.mui-menu (key)

.mui-navbar (key)

.mui-navbar.noactive (key)

.mui-page (key)

.mui-pullHint (key)

.mui-weixin (key)

.noSwipe (key)

BASE_URL (var)

CComManager (class)

CPageManager (class)

Date.add (fn)

Date.addDay (fn)

Date.addHours (fn)

Date.addMin (fn)

Date.addMonth (fn)

Date.diff (fn)

Date.format (fn)

IsBusy (var)

MUI (module)

MUI.activePage (var)

MUI.app_alert (fn)

MUI.batchCall (class)

MUI.callSvr (fn)

MUI.callSvrExt (key)

MUI.callSvrExt['default'] (key)

MUI.callSvrExt[].dataFilter (key)

MUI.callSvrExt[].makeUrl (key)

MUI.callSvrSync (fn)

MUI.callSvrSync (fn)

MUI.closeDialog (fn)

MUI.container (var)

MUI.defDataProc (fn)

MUI.disableBatch (var)

MUI.enhanceWithin (fn)

MUI.enterWaiting (fn)

MUI.formatField (fn)

MUI.getOptions (fn)

MUI.getToPageId (fn)

MUI.handleLogin (fn)

MUI.hideLoading (fn)

MUI.initClient (fn)

MUI.lastError (var)

MUI.leaveWaiting (fn)

MUI.logout (fn)

MUI.m_app (var)

MUI.m_curBatch (var)

MUI.m_enhanceFn (var)

MUI.m_pageStack (var)

MUI.makeUrl (fn)

MUI.options (var)

MUI.popPageStack (fn)

MUI.prevPageId (var)

MUI.reloadPage (fn)

MUI.setApp (fn)

MUI.setFormSubmit (fn)

MUI.setOnError (fn)

MUI.setupCallSvrViaForm (fn)

MUI.setupDialog (fn)

MUI.showDialog (fn)

MUI.showFirstPage (var)

MUI.showHome (fn)

MUI.showLoading (fn)

MUI.showLogin (fn)

MUI.showPage (fn)

MUI.showValidateErr (fn)

MUI.syslog (fn)

MUI.tryAutoLogin (fn)

MUI.unloadPage (fn)

MUI.useBatchCall (fn)

Plugins (class)

Plugins.exists (fn)

Plugins.list (fn)

app_abort (fn)

app_alert (alias)

appendParam (fn)

applyTpl (fn)

assert (fn)

basename (fn)

callSvr (alias)

callSvr.noex (key)

callSvrSync (alias)

common.js (module)

delCookie (fn)

delStorage (fn)

delayDo (fn)

deviceready (key)

enterWaiting (alias)

evalAttr (fn)

example-list-choose (key)

example-upload (key)

filterCordovaModule (fn)

g_args (var)

g_args._app (var)

g_cfg (var)

g_cfg.PAGE_SZ (var)

g_cfg.logAction (var)

g_cfg.logAction (var)

g_cfg.manualSplash (key)

g_cordova (var)

g_data (var)

g_data.initClient (key)

g_data.serverRev (key)

g_data.testMode,g_data.mockMode (key)

g_data.userInfo (key)

getCookie (fn)

getFormData (fn)

getStorage (fn)

getTimeDiffDscr (fn)

initNavbarAndList (alias)

initPageDetail (fn)

initPageList (fn)

initPullList (fn)

isAndroid (fn)

isIOS (fn)

isWeixin (fn)

leaveWaiting (alias)

loadScript (fn)

makeUrl (alias)

mui-initfn (key)

mui-loadPrompt (key)

mui-nofix (key)

mui-origin (key)

mui-pullPrompt (key)

mui-script (key)

mui-swipenav (key)

muiInit (event)

pagebeforeshow (event)

pagecreate (event)

pagehide (event)

pageshow (event)

parseDate (fn)

parseQuery (fn)

parseTime (fn)

parseValue (fn)

randAlphanum (fn)

randInt (fn)

reloadSite (fn)

rs2Array (fn)

rs2Hash (fn)

rs2MultiHash (fn)

setCookie (fn)

setDateBox (fn)

setFormData (fn)

setStorage (fn)

setTimeBox (fn)

showByFormMode (fn)

tobool (fn)

waitFor (fn)


@module common.js

JS通用函数库


@fn randInt(from, to)

生成一个随机整数。如生成10到20间的随机整数:

var n = randInt(10, 20)

@fn randAlphanum(cnt)

生成指定长度(cnt)的随机代码。不出现"0","1","o","l"这些易混淆字符。

示例:生成8位随机密码

var dyn_pwd = randAlphanum(8);

@fn basename(name, ext?)

取名字的基础部分,如

var name = basename("/cc/ttt.asp"); // "ttt.asp"
var name2 = basename("c:\\aaa\\bbb/cc/ttt.asp", ".asp"); // "ttt"

@fn assert(cond, dscr?)


@fn parseQuery(str)

解析url编码格式的查询字符串,返回对应的对象。

if (location.search) {
    var queryStr = location.search.substr(1); // "?id=100&name=abc&val=3.14"去掉"?"号
    var args = parseQuery(queryStr); // {id: 100, name: "abc", val: 3.14}
}

注意:

如果值为整数或小数,则会转成相应类型。如上例中 id为100,不是字符串"100".


@fn tobool(v)

将字符串转成boolean值。除"0", "1"外,还可以支持字符串 "on"/"off", "true"/"false"等。


@fn reloadSite()

重新加载当前页面,但不要#hash部分。


@fn Date.format(fmt?=L)

日期对象格式化字符串。

@param fmt 格式字符串。由以下组成:

yyyy - 四位年,如2008, 1999
yy - 两位年,如 08, 99
mm - 两位月,如 02, 12
dd - 两位日,如 01, 30
HH - 两位小时,如 00, 23
MM - 两位分钟,如 00, 59
SS - 两位秒,如 00, 59

支持这几种常用格式:
L - 标准日期时间,相当于 "yyyy-mm-dd HH:MM:SS"
D - 标准日期,相当于 "yyyy-mm-dd"
T - 标准时间,相当于 "HH:MM:SS"

示例:

var dt = new Date();
var dtStr1 = dt.format("D"); // "2009-10-20"
var dtStr2 = dt.format("yyyymmdd-HHMM"); // "20091020-2038"

@fn Date.addDay(n)


@fn Date.addHours(n)


@fn Date.addMin(n)


@fn Date.addMonth(n)


@fn parseTime(s)

将纯时间字符串生成一个日期对象。

var dt1 = parseTime("10:10:00");
var dt2 = parseTime("10:11");

@fn parseDate(dateStr)

将日期字符串转为日期时间格式。其效果相当于new Date(Date.parse(dateStr)),但兼容性更好(例如在safari中很多常见的日期格式无法解析)

示例:

var dt1 = parseDate("2012-01-01");
var dt2 = parseDate("2012/01/01 20:00:09");
var dt3 = parseDate("2012.1.1 20:00");

@fn Date.add(sInterval, n)

为日期对象加几天/小时等。参数n为整数,可以为负数。

@param sInterval Enum. 间隔单位. d-天; m-月; y-年; h-小时; n-分; s-秒

示例:

var dt = new Date();
dt.add("d", 1); // 1天后
dt.add("m", 1); // 1个月后
dt.add("y", -1); // 1年前
dt.add("h", 3); // 3小时后
dt.add("n", 30); // 30分钟后
dt.add("s", 30); // 30秒后

@see Date.diff


@fn Date.diff(sInterval, dtEnd)

计算日期到另一日期间的间隔,单位由sInterval指定(具体值列表参见Date.add).

var dt = new Date();
...
var dt2 = new Date();
var days = dt.diff("d", dt2); // 相隔多少天

@see Date.add


@fn setCookie(name, value, days?=30)

设置cookie值。如果只是为了客户端长时间保存值,一般建议使用 setStorage.

@see getCookie

@see delCookie

@see setStorage


@fn getCookie(name)

取cookie值。

@see setCookie

@see delCookie


@fn delCookie(name)

删除一个cookie项。

@see getCookie

@see setCookie


@fn setStorage(name, value, useSession?=false)

使用localStorage存储(或使用sessionStorage存储, 如果useSession=true)。
注意只能存储字符串,所以value不可以为数组,对象等,必须序列化后存储。

如果浏览器不支持Storage,则使用cookie实现.

示例:

setStorage("id", "100");
var id = getStorage("id");
delStorage("id");

示例2:对象需要序列化后存储:

var obj = {id:10, name:"Jason"};
setStorage("obj", JSON.stringify(obj));
var obj2 = getStorage("obj");
alert(obj2.name);

@see getStorage

@see delStorage


@fn getStorage(name, useSession?=false)

取storage中的一项。
默认使用localStorage存储,如果useSession=true,则使用sessionStorage存储。

如果浏览器不支持Storage,则使用cookie实现.

@see setStorage

@see delStorage


@fn delStorage(name)

删除storage中的一项。

@see getStorage

@see setStorage


@fn rs2Array(rs)

@param rs= {h=[header], d=[ @row ]} rs对象(RowSet)

@return arr=[ %obj ]

rs对象用于传递表格,包含表头与表内容。
函数用于将服务器发来的rs对象转成数组。

示例:

var rs = {
    h: ["id", "name"], 
    d: [ [100, "Tom"], [101, "Jane"] ] 
};
var arr = rs2Array(rs); 

// 结果为
arr = [
    {id: 100, name: "Tom"},
    {id: 101, name: "Jane"} 
];

@see rs2Hash

@see rs2MultiHash


@fn rs2Hash(rs, key)

@param rs= {h, d} rs对象(RowSet)

@return hash= {key => %obj}

示例:

var rs = {
    h: ["id", "name"], 
    d: [ [100, "Tom"], [101, "Jane"] ] 
};
var hash = rs2Hash(rs, "id"); 

// 结果为
hash = {
    100: {id: 100, name: "Tom"},
    101: {id: 101, name: "Jane"}
};

@see rs2Array


@fn rs2MultiHash(rs, key)

@param rs= {h, d} rs对象(RowSet)

@return hash= {key => [ %obj ]}

示例:

var rs = {
    h: ["id", "name"], 
    d: [ [100, "Tom"], [101, "Jane"], [102, "Tom"] ] 
};
var hash = rs2Hash(rs, "name");  

// 结果为
hash = {
    "Tom": [{id: 100, name: "Tom"}, {id: 102, name: "Tom"}],
    "Jane": [{id: 101, name: "Jane"}]
};

@see rs2Hash

@see rs2Array


@var IsBusy

标识应用当前是否正在与服务端交互。一般用于自动化测试。


@var g_args

应用参数。

URL参数会自动加入该对象,例如URL为 http://{server}/{app}/index.html?orderId=10&dscr=上门洗车,则该对象有以下值:

g_args.orderId=10; // 注意:如果参数是个数值,则自动转为数值类型,不再是字符串。
g_args.dscr="上门洗车"; // 对字符串会自动进行URL解码。

此外,框架会自动加一些参数:

@var g_args._app ?="user" 应用名称,由setApp({appName})指定。

@see parseQuery URL参数通过该函数获取。


@var g_cordova

值是一个整数,默认为0.
如果非0,表示WEB应用在苹果或安卓APP中运行,且数值代表原生应用容器的大版本号。

示例:检查用户APP版本是否可以使用某些插件。

if (g_cordova) { // 在原生APP中。可以使用插件。
    // 假如在IOS应用的大版本3中,加入了某插件,如果用户未升级,可提示他升级:
    if (g_cordova < 3 && isIOS()) {
        app_alert("您的版本太旧,XX功能无法使用,请升级到最新版本");
    }
}

@var g_data = {userInfo?, serverRev?, initClient?}

应用全局共享数据。

在登录时,会自动设置userInfo属性为个人信息。所以可以通过 g_data.userInfo==null 来判断是否已登录。

serverRev用于标识服务端版本,如果服务端版本升级,则应用可以实时刷新以更新到最新版本。

@key g_data.userInfo

@key g_data.serverRev

@key g_data.initClient

应用初始化时,调用initClient接口得到的返回值,通常为{plugins, ...}

@key g_data.testMode,g_data.mockMode 测试模式和模拟模式


@var g_cfg

应用配置项。

@var g_cfg.logAction ?=false Boolean. 是否显示详细日志。

@var g_cfg.PAGE_SZ ?=20 分页大小,作为每次调用{obj}.query的缺省值。


@var BASE_URL

设置应用的基本路径, 应以"/"结尾.

当用于本地调试网页时, 可以临时修改它, 比如在app.js中临时设置:

var BASE_URL = "http://oliveche.com/jdcloud/";

@fn appendParam(url, param)

示例:

var url = "http://xxx/api.php";
if (a)
    url = appendParam(url, "a=" + a);
if (b)
    url = appendParam(url, "b=" + b);

@fn isWeixin()

当前应用运行在微信中。


@fn isIOS()

当前应用运行在IOS平台,如iphone或ipad中。


@fn isAndroid()

当前应用运行在安卓平台。


@fn loadScript(url, fnOK, sync?=false)

动态加载一个script. 如果曾经加载过, 可以重用cache.

注意: $.getScript一般不缓存(仅当跨域时才使用Script标签方法加载,这时可用缓存), 自定义方法$.getScriptWithCache与本方法类似.

@see $.getScriptWithCache


@fn getFormData(jo)

取DOM对象中带name属性的子对象的内容, 放入一个JS对象中, 以便手工调用callSvr.

注意:

与setFormData配合使用时, 可以只返回变化的数据.

jf.submit(function () {
    var ac = jf.attr("action");
    callSvr(ac, fn, getFormData(jf));
});

@see setFormData


@fn setFormData(jo, data?, opt?)

用于为带name属性的DOM对象设置内容为data[name].
要清空所有内容, 可以用 setFormData(jo), 相当于增强版的 form.reset().

注意:

@param opt {setOrigin?=false}

选项 setOrigin: 为true时将data设置为数据源, 这样在getFormData时, 只会返回与数据源相比有变化的数据.
缺省会设置该DOM对象数据源为空.

对象关联的数据源, 可以通过 jo.data("origin") 来获取, 或通过 jo.data("origin", newOrigin) 来设置.

示例:

<div id="div1">
    <p>订单描述:<span name="dscr"></span></p>
    <p>状态为:<input type=text name="status"></p>
    <p>金额:<span name="amount"></span>元</p>
</div>

Javascript:

var data = {
    dscr: "筋斗云教程",
    status: "已付款",
    amount: "100"
};
var jo = $("#div1");
var data = setFormData(jo, data); 
$("[name=status]").html("已完成");
var changedData = getFormData(jo); // 返回 { dscr: "筋斗云教程", status: "已完成", amount: "100" }

var data = setFormData(jo, data, {setOrigin: true}); 
$("[name=status]").html("已完成");
var changedData = getFormData(jo); // 返回 { status: "已完成" }
$.extend(jo.data("origin_"), changedData); // 合并变化的部分到数据源.

@see getFormData


@fn $.getScriptWithCache(url, options?)

@param options ? 传递给$.ajax的选项。

@see loadScript


@fn setDateBox(jo, defDateFn?)

设置日期框, 如果输入了非法日期, 自动以指定日期(如未指定, 用当前日期)填充.

setDateBox($("#txtComeDt"), function () { return genDefVal()[0]; });

@fn setTimeBox(jo, defTimeFn?)

设置时间框, 如果输入了非法时间, 自动以指定时间(如未指定, 用当前时间)填充.

setTimeBox($("#txtComeTime"), function () { return genDefVal()[1]; });

@fn waitFor(deferredObj)

用于简化异步编程. 可将不易读的回调方式改写为易读的顺序执行方式.

var dfd = $.getScript("http://...");
function onSubmit()
{
    dfd.then(function () {
        foo();
        bar();
    });
}

可改写为:

function onSubmit()
{
    if (waitFor(dfd)) return;
    foo();
    bar();
}

@fn evalAttr(jo, name)

返回一个属性做eval后的js值。

示例:读取一个对象值:

var opt = evalAttr(jo, "data-opt");

<div data-opt="{id:1, name:\"data1\"}"><div>

考虑兼容性,也支持忽略括号的写法,

<div data-opt="id:1, name:\"data1\""><div>

读取一个数组:

var arr = evalAttr(jo, "data-arr");

<div data-arr="['aa', 'bb']"><div>

读取一个函数名(或变量):

var fn = evalAttr(jo, "mui-initfn");

<div mui-initfn="initMyPage"><div>

@fn getTimeDiffDscr(tm, tm1)

从tm到tm1的时间差描述,如"2分钟前", "3天前"等。

tm和tm1可以为时间对象或时间字符串


@fn parseValue(str)

如果str符合整数或小数,则返回相应类型。


@fn filterCordovaModule(module)

原生插件与WEB接口版本匹配。
在cordova_plugins.js中使用,用于根据APP版本与当前应用标识,过滤当前Web可用的插件。

例如,从客户端(应用标识为user)版本2.0,商户端(应用标识为store)版本3.0开始,添加插件 geolocation,可配置filter如下:

module.exports = [
    ...
    {
        "file": "plugins/cordova-plugin-geolocation/www/android/geolocation.js",
        "id": "cordova-plugin-geolocation.geolocation",
        "clobbers": [
            "navigator.geolocation"
        ],
        "filter": [ ["user",2], ["store",3] ] // 添加filter
    }
];

filterCordovaModule(module); // 过滤模块

配置后,尽管WEB已更新,但旧版本应用程序不会具有该接口。

filter格式: [ [app1, minVer?=1, maxVer?=9999], ...], 仅当app匹配且版本在minVer/maxVer之间才使用
如果未指定filter, 表示总是使用
app标识由应用定义,常用如: "user"-客户端;"store"-商户端


@fn applyTpl(tpl, data)

对模板做字符串替换

var tpl = "<li><p>{name}</p><p>{dscr}</p></li>";
var data = {name: 'richard', dscr: 'hello'};
var html = applyTpl(tpl, data);
// <li><p>richard</p><p>hello</p></li>

@module MUI

1 基于逻辑页面的单网页应用

1.1 应用容器

1.2 逻辑页面

1.2.1 逻辑页内嵌style

1.2.2 逻辑页内嵌script

2 服务端交互API

3 登录与退出

4 常用组件

4.1 导航栏

4.2 对话框

4.3 弹出菜单

4.4 底部导航

5 图片按需加载

6 原生应用支持

7 系统类标识

8 手势支持

9 跨域前端开发支持

筋斗云移动UI框架 - JDCloud Mobile UI framework

1 基于逻辑页面的单网页应用

亦称“变脸式应用”。应用程序以逻辑页面(page)为基本单位,每个页面的html/js可完全分离。主要特性:

@see MUI.showPage

@see MUI.popPageStack

@see CPageManager

1.1 应用容器

@key .mui-container 应用容器。

@event muiInit () DOM事件。this为当前应用容器。

先在主应用html中,用.mui-container类标识应用容器,在运行时,所有逻辑页面都将在该对象之下。如:

<body class="mui-container">

应用初始化时会发出muiInit事件,该事件在页面加载完成($.ready)后,显示首页前调用。在这里调用MUI.showPage可动态显示首页。

1.2 逻辑页面

每个逻辑页面(page)以及它对应的脚本(js)均可以独立出一个文件开发,也可以直接嵌在主页面的应用容器中。

如添加一个订单页,使用外部页面,可以添加一个order.html (html片段):

<div mui-initfn="initPageOrder" mui-script="order.js">
    ...
</div>

如果使用内部页面,则可以写为:

<script type="text/html" id="tpl_order">
    <div mui-initfn="initPageOrder" mui-script="order.js">
        ...
    </div>
</script>

@key .mui-page 逻辑页面。

@key mui-script DOM属性。逻辑页面对应的JS文件。

@key mui-initfn DOM属性。逻辑页面对应的初始化函数,一般包含在mui-script指定的JS文件中。

该页面代码模块(即初始化函数)可以放在一个单独的文件order.js:

function initPageOrder() 
{
    var jpage = $(this);
    jpage.on("pagebeforeshow", onBeforeShow);
    jpage.on("pageshow", onShow);
    jpage.on("pagehide", onHide);
    ...
}

逻辑页面加载过程,以加载页面"#order"为例:

MUI.showPage("#order");

@event pagecreate () DOM事件。this为当前页面jpage。

@event pagebeforeshow () DOM事件。this为当前页面jpage。

@event pageshow () DOM事件。this为当前页面jpage。

@event pagehide () DOM事件。this为当前页面jpage。

1.2.1 逻辑页内嵌style

逻辑页代码片段允许嵌入style,例如:

<div mui-initfn="initPageOrder" mui-script="order.js">
<style>
.p-list {
    color: blue;
}
.p-list div {
    color: red;
}
</style>
</div>

@key mui-origin

style将被插入到head标签中,并自动添加属性mui-origin={pageId}.

(版本v3.2)
框架在加载页面时,会将style中的内容自动添加逻辑页前缀,以便样式局限于当前页使用,相当于:

<style>
#order .p-list {
    color: blue;
}
#order .p-list div {
    color: red;
}
</style>

为兼容旧版本,如果css选择器以"#{pageId} "开头,则不予处理。

@key mui-nofix

如果不希望框架自动处理,可以为style添加属性mui-nofix:

<style mui-nofix>
</style>
1.2.2 逻辑页内嵌script

逻辑页中允许但不建议内嵌script代码,js代码应在mui-script对应的脚本中。非要使用时,注意将script放到div标签内:

<div mui-initfn="initPageOrder" mui-script="order.js">
<script>
// js代码
</script>
    ...
</div>

(版本v3.2)
如果逻辑页嵌入在script模板中,这时要使用script, 应换用__script__标签,如:

<script type="text/html" id="tpl_order">
    <div mui-initfn="initPageOrder" mui-script="order.js">
        ...
    </div>
    <__script__>
    // js代码,将在逻辑页加载时执行
    </__script__>
</script>

2 服务端交互API

@see callSvr 系列调用服务端接口的方法。

@see CComManager

3 登录与退出

框架提供MUI.showLogin/MUI.logout操作.
调用MUI.tryAutoLogin可以支持自动登录.

登录后显示的主页,登录页,应用名称等均通过MUI.setApp设置。

@see MUI.tryAutoLogin

@see MUI.showLogin

@see MUI.logout

@see MUI.setApp

4 常用组件

框架提供导航栏、对话框、弹出框、弹出菜单等常用组件。

4.1 导航栏

@key .mui-navbar 导航栏

@key .mui-navbar.noactive

默认行为是点击后添加active类(比如字体发生变化),如果不需要此行为,可再添加noactive类。

4.2 对话框

@key .mui-dialog 对话框

4.3 弹出菜单

@key .mui-menu 菜单

4.4 底部导航

@key #footer 底部导航栏

设置id为"footer"的导航, 框架会对此做些设置: 如果当前页面为导航栏中的一项时, 就会自动显示导航栏.
例: 在html中添加底部导航:

<div id="footer">
    <a href="#home">订单</a></li>
    <a href="#me">我</a>
</div>

如果要添加其它底部导航,可在page内放置如下部件:

<div class="ft mui-navbar">
    <a href="#home" class="active">订单</a></li>
    <a href="#me">我</a>
</div>

注意:mui-navbar与ft类并用后,在点击后不会自动设置active类,请自行添加。

5 图片按需加载

仅当页面创建时才会加载。

<img src="../m/images/ui/carwash.png">

6 原生应用支持

使用MUI框架的Web应用支持被安卓/苹果原生应用加载(通过cordova技术)。

设置说明:

不同的app大版本(通过URL参数cordova=?识别)或不同平台加载的插件是不一样的,要查看当前加载了哪些插件,可以在Web控制台中执行:

cordova.require('cordova/plugin_list')

对原生应用的额外增强包括:

@key g_cfg.manualSplash

如果使用了StatusBar插件, 可以取消该行为.
先在setApp中设置, 如

MUI.setApp({noHandleIosStatusBar: true, ...});

然后在deviceready事件中自行设置样式, 如

function muiInit() {
    $(document).on("deviceready", onSetStatusBar);
    function onSetStatusBar()
    {
        var bar = window.StatusBar;
        if (bar) {
            bar.styleLightContent();
            bar.backgroundColorByHexString("#ea8010");
        }
    }
}

@key deviceready APP初始化后回调事件

APP初始化成功后,回调该事件。如果deviceready事件未被回调,则出现启动页无法消失、插件调用无效、退出程序时无提示等异常。
其可能的原因是:

7 系统类标识

框架自动根据系统环境为应用容器(.mui-container类)增加以下常用类标识:

@key .mui-android 安卓系统

@key .mui-ios 苹果IOS系统

@key .mui-weixin 微信浏览器

@key .mui-cordova 原生环境

在css中可以利用它们做针对系统的特殊设置。

8 手势支持

如果使用了 jquery.touchSwipe 库,则默认支持手势:

@key mui-swipenav DOM属性

如果页面中某组件上的左右划与该功能冲突,可以设置属性mui-swipenav="no"来禁用该功能:

<div mui-swipenav="no"></div>

@key .noSwipe CSS-class

左右划前进后退功能会导致横向滚动生效。可以通过添加noSwipe类(注意大小写)的方式禁用swipe事件恢复滚动功能:

<div class="noSwipe"></div>

9 跨域前端开发支持

典型应用是, 在开发前端页面时, 本地无须运行任何后端服务器(如apache/iis/php等), 直接跨域连接远程接口进行开发.

支持直接在浏览器中打开html/js文件运行应用.
需要浏览器支持CORS相关设置. 以下以chrome为例介绍.
例如, 远程接口的基础URL地址为 http://oliveche.com/jdcloud/

这时直接在chrome中打开html文件即可连接远程接口运行起来.


@class CPageManager(app)

页面管理器。提供基于逻辑页面的单网页应用,亦称“变脸式应用”。

该类作为MUI模块的基类,仅供内部使用,但它提供showPage等操作,以及pageshow等各类事件。

@param app IApp={homePage?="#home", pageFolder?="page"}


@var MUI.activePage

当前页面。

注意:

要查看从哪个页面来,可以用 MUI.prevPageId。
要查看最近一次调用MUI.showPage转向的页面,可以用 MUI.getToPageId().

@see MUI.prevPageId

@see MUI.getToPageId ()


@var MUI.prevPageId

上一个页面的id, 首次进入时为空.


@var MUI.container

现在为$(document.body)


@var MUI.showFirstPage?=true

如果为false, 则必须手工执行 MUI.showPage 来显示第一个页面。


@var MUI.options

缺省配置项:

{
    ani: 'auto' // 缺省切页动画效果. 'none'表示无动画。
}

@fn MUI.unloadPage(pageId?)

@param pageId 如未指定,表示当前页。

删除一个页面。


@fn MUI.reloadPage(pageId?)

@param pageId 如未指定,表示当前页。

重新加载指定页面。不指定pageId时,重加载当前页。


@var MUI.m_pageStack

页面栈,MUI.popPageStack对它操作


@fn MUI.popPageStack(n?=1)

n=0: 退到首层, >0: 指定pop几层

离开页面时, 如果不希望在点击后退按钮后回到该页面, 可以调用

MUI.popPageStack()

如果要在后退时忽略两个页面, 可以调用

MUI.popPageStack(2)

如果要在后退时直接回到主页(忽略所有历史记录), 可以调用

MUI.popPageStack(0)

@fn MUI.showPage(pageId/pageRef, opt)

@param pageId String. 页面名字. 仅由字母、数字、"_"等字符组成。

@param pageRef String. 页面引用(即location.hash),以"#"开头,后面可以是一个pageId(如"#home")或一个相对页的地址(如"#info.html", "#emp/info.html")。

@param opt {ani?}

ani:: String. 动画效果。设置为"none"禁用动画。

在应用内无刷新地显示一个页面。

例:

MUI.showPage("order");  // 或者
MUI.showPage("#order");

显示order页,先在已加载的DOM对象中找id="order"的对象,如果找不到,则尝试找名为"tpl_home"的模板DOM对象,如果找不到,则以ajax方式动态加载页面"page/order.html"。

注意:

加载成功后,会将该页面的id设置为"order",然后依次:

调用 mui-initfn中指定的初始化函数,如 initPageOrder
触发pagecreate事件
触发pagebeforeshow事件
触发pageshow事件

动态加载页面时,缺省目录名为page,如需修改,应在初始化时设置app.pageFolder属性:

MUI.setApp({pageFolder: "mypage"}) 

也可以显示一个指定路径的页面:

MUI.showPage("#page/order.html"); 

由于它对应的id是order, 在显示时,先找id="order"的对象是否存在,如果不存在,则动态加载页面"page/order.html"并为该对象添加id="order".

在HTML中, 如果标签的href属性以"#"开头,则会自动以showPage方式无刷新显示,如:

<a href="#order">order</a>
<a href="#emp/empinfo.html">empinfo</a>

可以通过mui-opt属性设置showPage的参数(若有多项,以逗号分隔),如:

<a href="#me" mui-opt="ani:'none'">me</a>

如果不想在应用内打开页面,只要去掉链接中的"#"即可:

<a href="emp/empinfo.html">empinfo</a>

特别地,如果href属性以"#dlg"开头,则会自动以showDialog方式显示对话框,如

<a href="#dlgSetUserInfo">set user info</a>

点击后相当于调用:

MUI.showDialog(MUI.activePage.find("#dlgSetUserInfo"));

@fn MUI.getToPageId()

返回最近一次调用MUI.showPage时转向页面的Id.

@see MUI.prevPageId


@var MUI.m_enhanceFn


@fn MUI.enhanceWithin(jparent)


@fn MUI.getOptions(jo)


@fn MUI.showDialog(jdlg)


@fn MUI.closeDialog(jdlg, remove=false)


@fn MUI.setupDialog(jdlg, initfn)

@return 可以不返回, 或返回一个回调函数beforeShow, 在每次Dialog显示前调用.

使用该函数可设置dialog的初始化回调函数和beforeShow回调.

使用方法:

MUI.setupDialog(jdlg, function () {
    var jdlg = this;
    jdlg.find("#btnOK").click(btnOK_click);

    function btnOK_click(ev) { }

    function beforeShow() {
        // var jdlg = this;
        var jtxt = jdlg.find("#txt1");
        callSvr("getxxx", function (data) {
            jtxt.val(data);
        });
    }
    return beforeShow;
});

@fn MUI.app_alert(msg, [type?=i], [fn?], opt?={timeoutInterval?, defValue?, onCancel()?})

@alias app_alert

@param type 对话框类型: "i": info, 信息提示框; "e": error, 错误框; "w": warning, 警告框; "q": question, 确认框(会有"确定"和"取消"两个按钮); "p": prompt, 输入框

@param fn Function(text?) 回调函数,当点击确定按钮时调用。当type="p" (prompt)时参数text为用户输入的内容。

@param opt Object. 可选项。 timeoutInterval表示几秒后自动关闭对话框。defValue用于输入框(type=p)的缺省值.

onCancel: 用于"q", 点取消时回调.

示例:

// 信息框
app_alert("操作成功", function () {
    MUI.showPage("#orderInfo");
}, {timeoutInterval: 3});

// 错误框
app_alert("操作失败", "e");

// 确认框(确定/取消)
app_alert("立即付款?", "q", function () {
    MUI.showPage("#pay");
});

// 输入框
app_alert("输入要查询的名字:", "p", function (text) {
    callSvr("Book.query", {cond: "name like '%" + text + "%'});
});

可自定义对话框,接口如下:

示例:

<div id="muiAlert" class="mui-dialog">
    <h3 class="p-title"></h3>
    <div class="p-msg"></div>
    <input type="text" id="txtInput"> <!-- 当type=p时才会显示 -->
    <div>
        <a href="javascript:;" id="btnOK" class="mui-btn primary">确定</a>
        <a href="javascript:;" id="btnCancel" class="mui-btn">取消</a>
    </div>
</div>

app_alert一般会复用对话框 muiAlert, 除非层叠开多个alert, 这时将clone一份用于显示并在关闭后删除。


@class CComManager

@param app IApp={appName?=user}

提供callSvr等与后台交互的API.

@see MUI.callSvr

@see MUI.useBatchCall

@see MUI.setupCallSvrViaForm


@var MUI.lastError = ctx

出错时,取出错调用的上下文信息。

ctx: {ac, tm, tv, ret}


@var MUI.disableBatch ?= false

设置为true禁用batchCall, 仅用于内部测试。


@var MUI.m_curBatch

当前batchCall对象,用于内部调试。


@fn app_abort()

中止之后的调用, 直接返回.


@fn MUI.syslog(module, pri, content)

向后端发送日志。后台必须已添加syslog插件。
日志可在后台Syslog表中查看,客户端信息可查看ApiLog表。

注意:如果操作失败,本函数不报错。


@fn MUI.setOnError()

一般框架自动设置onerror函数;如果onerror被其它库改写,应再次调用该函数。
allow throw("abort") as abort behavior.


@fn delayDo(fn, delayCnt?=3)

设置延迟执行。当delayCnt=1时与setTimeout效果相同。
多次置于事件队列最后,一般3次后其它js均已执行完毕,为idle状态


@fn MUI.enterWaiting(ctx?)

@param ctx {ac, tm, tv?, tv2?, noLoadingImg?}

@alias enterWaiting ()


@fn MUI.leaveWaiting(ctx?)

@alias leaveWaiting


@fn MUI.defDataProc(rv)

@param rv BQP协议原始数据,如 "[0, {id: 1}]",一般是字符串,也可以是JSON对象。

@return data 按接口定义返回的数据对象,如 {id: 1}. 如果返回==null,调用函数应直接返回,不回调应用层。

注意:服务端不应返回null, 否则客户回调无法执行; 习惯上返回false表示让回调处理错误。


@fn MUI.makeUrl(action, params)

@alias makeUrl

生成对后端调用的url.

var params = {id: 100};
var url = makeUrl("Ordr.set", params);

注意:调用该函数生成的url在结尾有标志字符串"zz=1", 如"../api.php/login?_app=user&zz=1"

支持callSvr扩展,这时action可以是一个数组,如:

var url = MUI.makeUrl(['login', 'zhanda']);

@see MUI.callSvrExt


@fn MUI.callSvr(ac, [param?], fn?, postParams?, userOptions?)

1 调用监控

2 文件上传支持(FormData)

3 callSvr扩展

@alias callSvr

@param ac String. action, 交互接口名. 也可以是URL(比如由makeUrl生成)

@param param Object. URL参数(或称HTTP GET参数)

@param postParams Object. POST参数. 如果有该参数, 则自动使用HTTP POST请求(postParams作为POST内容), 否则使用HTTP GET请求.

@param fn Function(data). 回调函数, data参考该接口的返回值定义。

@param userOptions 用户自定义参数, 会合并到$.ajax调用的options参数中.可在回调函数中用"this.参数名"引用.

常用userOptions:

@key callSvr.noex 调用接口时忽略出错,可由回调函数fn自己处理错误。

当后端返回错误时, 回调fn(false)(参数data=false). 可通过 MUI.lastError.ret 取到返回的原始数据。

例:

callSvr("logout");
callSvr("logout", api_logout);
callSvr("login", {wantAll:1}, api_login);
callSvr("info/hotline.php", {q: '大众'}, api_hotline);

// 也兼容使用makeUrl的旧格式如:
callSvr(makeUrl("logout"), api_logout);
callSvr(makeUrl("logout", {a:1}), api_logout);

callSvr("User.get", function (data) {
    if (data === false) { // 仅当设置noex且服务端返回错误时可返回false
        // var originalData = MUI.lastError.ret;
        return;
    }
    foo(data);
}, null, {noex:1});

@see MUI.lastError 出错时的上下文信息

1 调用监控

@var g_cfg.logAction

框架会自动在ajaxOption中增加ctx_属性,它包含 {ac, tm, tv, tv2, ret} 这些信息。
当设置g_cfg.logAction=1时,将输出这些信息。

2 文件上传支持(FormData)

callSvr支持FormData对象,可用于上传文件等场景。示例如下:

@key example-upload

HTML:

file: <input id="file1" type="file" multiple>
<button type="button" id="btn1">upload</button>

JS:

jpage.find("#btn1").on('click', function () {
    var fd = new FormData();
    $.each(jpage.find('#file1')[0].files, function (i, e) {
        fd.append('file' + (i+1), e);
    });
    callSvr('upload', api_upload, fd);

    function api_upload(data) { ... }
});

3 callSvr扩展

@key MUI.callSvrExt

当调用第三方API时,也可以使用callSvr扩展来代替$.ajax调用以实现:

例:合作方接口使用HTTP协议,格式如(以生成token调用为例)

http://<Host IP Address>:<Host Port>/lcapi/token/get-token?user=用户名&password=密码

返回格式为:{code, msg, data}

成功返回:

{
    "code":"0",
    "msg":"success",
    "data":[ { "token":"xxxxxxxxxxxxxx" } ]
}

失败返回:

{
    "code":"4001",
    "msg":"invalid username or password",
    "data":[]
}

callSvr扩展示例:

MUI.callSvrExt['zhanda'] = {
    makeUrl: function(ac) {
        return 'http://hostname/lcapi/' + ac;
    }
    dataFilter: function (data) {
        if ($.isPlainObject(data) && data.code !== undefined) {
            if (data.code == 0)
                return data.data;
            if (this.noex)
                return false;
            app_alert("操作失败:" + data.message, "e");
        }
        else {
            app_alert("服务器通讯协议异常!", "e"); // 格式不对
        }
    }
};

在调用时,ac参数传入一个数组:

callSvr(['token/get-token', 'zhanda'], {user: 'test', password: 'test123'}, function (data) {
    console.log(data);
});

@key MUI.callSvrExt[].makeUrl (ac)

根据调用名ac生成url.

注意:
对方接口应允许JS跨域调用,或调用方支持跨域调用。

@key MUI.callSvrExt[].dataFilter (data) = null/false/data

对调用返回数据进行通用处理。返回值决定是否调用callSvr的回调函数以及参数值。

callSvr(ac, callback);

当返回false时,应用层可以通过MUI.lastError.ret来获取服务端返回数据。

@see MUI.lastError 出错时的上下文信息

@key MUI.callSvrExt['default']

(支持版本: v3.1)
如果要修改callSvr缺省调用方法,可以改写 MUI.callSvrExt['default'].
例如,定义以下callSvr扩展:

MUI.callSvrExt['default'] = {
    makeUrl: function(ac) {
        return '../api.php/' + ac;
    },
    dataFilter: function (data) {
        var ctx = this.ctx_ || {};
        if (data && $.isArray(data) && data.length >= 2 && typeof data[0] == "number") {
            if (data[0] == 0)
                return data[1];

            if (this.noex)
            {
                return false;
            }

            if (data[0] == E_NOAUTH) {
                // 如果支持自动重登录
                //if (MUI.tryAutoLogin()) {
                //  $.ajax(this);
                //}
                // 不支持自动登录,则跳转登录页
                MUI.popPageStack(0);
                MUI.showLogin();
                return;
            }
            else if (data[0] == E_AUTHFAIL) {
                app_alert("验证失败,请检查输入是否正确!", "e");
                return;
            }
            else if (data[0] == E_ABORT) {
                console.log("!!! abort call");
                return;
            }
            logError();
            app_alert("操作失败:" + data[1], "e");
        }
        else {
            logError();
            app_alert("服务器通讯协议异常!", "e"); // 格式不对
        }

        function logError()
        {
            console.log("failed call");
            console.log(ctx);
        }
    }
};

这样,以下调用

callSvr(['login', 'default']);

可以简写为:

callSvr('login');

@fn MUI.callSvrSync(ac, params?, fn?, postParams?, userOptions?)

@fn MUI.callSvrSync (ac, fn?, postParams?, userOptions?)

@alias callSvrSync

@return data 原型规定的返回数据

同步模式调用callSvr.

@see callSvr


@fn MUI.setupCallSvrViaForm($form, $iframe, url, fn, callOpt)

该方法已不建议使用。上传文件请用FormData。

@see example-upload callSvr

@param $iframe 一个隐藏的iframe组件.

@param callOpt 用户自定义参数. 参考callSvr的同名参数. e.g. {noex: 1}

一般对后端的调用都使用callSvr函数, 但像上传图片等操作不方便使用ajax调用, 因为要自行拼装multipart/form-data格式的请求数据.
这种情况下可以使用form的提交和一个隐藏的iframe来实现类似的调用.

先定义一个form, 在其中放置文件上传控件和一个隐藏的iframe. form的target属性设置为iframe的名字:

<form data-role="content" action="upload" method=post enctype="multipart/form-data" target="ifrUpload">
    <input type=file name="file[]" multiple accept="image/*">
    <input type=submit value="上传">
    <iframe id='ifrUpload' name='ifrUpload' style="display:none"></iframe>
</form>

然后就像调用callSvr函数一样调用setupCallSvrViaForm:

var url = makeUrl("upload", {genThumb: 1});
MUI.setupCallSvrViaForm($frm, $frm.find("iframe"), url, onUploadComplete);
function onUploadComplete(data) 
{
    alert("上传成功");
}

@fn MUI.showLoading()


@fn MUI.hideLoading()


@class MUI.batchCall(opt?={useTrans?=0})

批量调用。将若干个调用打包成一个特殊的batch调用发给服务端。
注意:

示例:

var batch = new MUI.batchCall();
callSvr("Family.query", {res: "id,name"}, api_FamilyQuery);
callSvr("User.get", {res: "id,phone"}, api_UserGet);
batch.commit();

以上两条调用将一次发送到服务端。
在批处理中,默认每条调用是一个事务,如果想把批处理中所有调用放到一个事务中,可以用useTrans选项:

var batch = new MUI.batchCall({useTrans: 1});
callSvr("Attachment.add", api_AttAdd, {path: "path-1"});
callSvr("Attachment.add", api_AttAdd, {path: "path-2"});
batch.commit();

在一个事务中,所有调用要么成功要么都取消。
任何一个调用失败,会导致它后面所有调用取消执行,且所有已执行的调用会回滚。

参数中可以引用之前结果中的值,引用部分需要用"{}"括起来,且要在opt.ref参数中指定哪些参数使用了引用:

var batch = new MUI.batchCall({useTrans: 1});
callSvr("Attachment.add", api_AttAdd, {path: "path-1"}); // 假如返回 22
var opt = {ref: ["id"]};
callSvr("Attachment.get", {id: "{$1}"}, api_AttGet, null, opt); // {$1}=22, 假如返回 {id: 22, path: '/data/1.png'}
opt = {ref: ["cond"]};
callSvr("Attachment.query", {res: "count(*) cnt", cond: "path='{$-1.path}'"}, api_AttQuery, null, opt); // {$-1.path}计算出为 '/data/1.png'
batch.commit();

以下为引用格式示例:

{$-2} // 前2次的结果。
{$2[0]} // 取第2次结果(是个数组)的第0个值。
{$-1.path} // 取前一次结果的path属性
{$2 -1}  // 可以做简单的计算

如果值计算失败,则当作"null"填充。

@see MUI.useBatchCall

@see MUI.disableBatch

@see MUI.m_curBatch


@fn MUI.useBatchCall(opt?={useTrans?=0}, tv?=0)

之后的callSvr调用都加入批量操作。例:

MUI.useBatchCall();
callSvr("Family.query", {res: "id,name"}, api_FamilyQuery);
callSvr("User.get", {res: "id,phone"}, api_UserGet);

可指定多少毫秒以内的操作都使用批处理,如10ms内:

MUI.useBatchCall(null, 10);

如果MUI.disableBatch=true, 该函数不起作用。

@see MUI.batchCall

@see MUI.disableBatch


@var MUI.m_app

参考MUI.setApp


@fn MUI.setFormSubmit(jf, fn?, opt?={rules, validate?, onNoAction?})

@param fn ? Function(data); 与callSvr时的回调相同,data为服务器返回的数据。

函数中可以使用this["userPost"] 来获取post参数。

opt.rules: 参考jquery.validate文档
opt.validate: Function(jf, queryParam={ac?,res?,...}). 如果返回false, 则取消submit. queryParam为调用参数,可以修改。

form提交时的调用参数, 如果不指定, 则以form的action属性作为queryParam.ac发起callSvr调用.
form提交时的POST参数,由带name属性且不带disabled属性的组件决定, 可在validate回调中设置.
如果之前调用过setFormData(jo, data, {setOrigin:true})来展示数据, 则提交时会只加上修改的字段.

opt.onNoAction: Function(jf). 当form中数据没有变化时, 不做提交. 这时可调用该回调函数.


@fn MUI.showValidateErr(jvld, jo, msg)

TODO: remove
show error using jquery validator's method by jo's name


@fn MUI.showLogin(jpage?)

@param jpage 如果指定, 则登录成功后转向该页面; 否则转向登录前所在的页面.

显示登录页. 注意: 登录页地址通过setApp({loginPage})指定, 缺省为"#login".

<div data-role="page" id="login">
...
</div>

注意:


@fn MUI.showHome()

显示主页。主页是通过 MUI.setApp({homePage: '#home'}); 来指定的,默认为"#home".

要取主页名可以用:

var jpage = $(MUI.m_app.homePage);

@see MUI.setApp


@fn MUI.logout(dontReload?)

@param dontReload 如果非0, 则注销后不刷新页面.

注销当前登录, 成功后刷新页面(除非指定dontReload=1)


@fn MUI.tryAutoLogin(onHandleLogin, reuseCmd?, allowNoLogin?=false)

尝试自动登录,如果失败则转到登录页(除非allowNoLogin=true)。

@param onHandleLogin Function(data). 调用后台login()成功后的回调函数(里面使用this为ajax options); 可以直接使用MUI.handleLogin

@param reuseCmd String. 当session存在时替代后台login()操作的API, 如"User.get", "Employee.get"等, 它们在已登录时返回与login相兼容的数据. 因为login操作比较重, 使用它们可减轻服务器压力.

@param allowNoLogin Boolean. 缺省未登录时会自动跳转登录页面, 如果设置为true, 如不会自动跳转登录框, 表示该应用允许未登录时使用.

@return Boolean. true=登录成功; false=登录失败.

该函数应该在muiInit事件中执行, 以避免框架页面打开主页。

$(document).on("muiInit", myInit);

function myInit()
{
    // redirect to login if auto login fails
    MUI.tryAutoLogin(handleLogin, "User.get");
}

function handleLogin(data)
{
    MUI.handleLogin(data);
    // g_data.userInfo已赋值
}

@fn MUI.handleLogin(data)

@param data 调用API "login"成功后的返回数据.

处理login相关的操作, 如设置g_data.userInfo, 保存自动登录的token等等.


@fn MUI.initClient(param?)


@class Plugins


@fn Plugins.exists(pluginName)


@fn Plugins.list()


@fn MUI.setApp(app)

@param app= {appName?=user, allowedEntries?, loginPage?="#login", homePage?="#home", pageFolder?="page", noHandleIosStatusBar?=false}


@fn MUI.formatField(obj) -> obj

对obj中的以字符串表示的currency/date等类型进行转换。
判断类型的依据是属性名字,如以Tm结尾的属性(也允许带数字后缀)为日期属性,如"tm", "tm2", "createTm"都会被当作日期类型转换。

注意:它将直接修改传入的obj,并最终返回该对象。

obj = {id: 1, amount: "15.0000", payAmount: "10.0000", createTm: "2016-01-11 11:00:00"}
var order = MUI.formatField(obj); // obj会被修改,最终与order相同
// order = {id: 1, amount: 15, payAmount: 10, createTm: (datetime类型)}

@fn initPullList(container, opt)

为列表添加下拉刷新和上拉加载功能。

例:页面元素如下:

<div mui-initfn="initPageOrders" mui-script="orders.js">
    <div class="bd">
        <div class="p-list"></div>
    </div>
</div>

设置下拉列表的示例代码如下:

var pullListOpt = {
    onLoadItem: showOrderList
};
var container = jpage.find(".bd")[0];
initPullList(container, pullListOpt);

var nextkey;
function showOrderList(isRefresh)
{
    var jlst = jpage.find(".p-list");
    var param = {res: "id desc", cond: "status=1"};
    if (nextkey == null)
        isRefresh = true;
    if (isRefresh)
        jlst.empty();
    param._pagekey = nextkey;

    callSvr("Ordr.query", param, function (data) {
        // create items and append to jlst
        // ....
        if (data.nextkey)
            nextkey = data.nextkey;
        // TODO: 处理分页结束即nextkey为空的情况。
    });
}

注意:

本函数参数如下:

@param container 容器,它的高度应该是限定的,因而当内部内容过长时才可出现滚动条

@param opt {onLoadItem, autoLoadMore?=true, threshold?=180, onHint?}

@param onLoadItem function(isRefresh)

在合适的时机,它调用 onLoadItem(true) 来刷新列表,调用 onLoadItem(false) 来加载列表的下一页。在该回调中this为container对象(即容器)。实现该函数时应当自行管理当前的页号(pagekey)

@param autoLoadMore 当滑动到页面下方时(距离底部TRIGGER_AUTOLOAD=30px以内)自动加载更多项目。

@param threshold 像素值。

手指最少下划或上划这些像素后才会触发实际加载动作。

@param onHint function(ac, dy, threshold)

ac  动作。"D"表示下拉(down), "U"表示上拉(up), 为null时应清除提示效果.
dy,threshold  用户移动偏移及临界值。dy>threshold时,认为触发加载动作。

提供提示用户刷新或加载的动画效果. 缺省实现是下拉或上拉时显示提示信息。

@param onHintText function(ac, uptoThreshold)

修改用户下拉/上拉时的提示信息。仅当未设置onHint时有效。onHint会生成默认提示,如果onHintText返回非空,则以返回内容替代默认内容。
内容可以是一个html字符串,所以可以加各种格式。

ac:: String. 当前动作,"D"或"U".
uptoThreshold:: Boolean. 是否达到阈值

@fn initPageList(jpage, opt) -> PageListInterface

1 例:一个navbar与若干list的组合

2 例:若干button与若干list的组合

3 例:只有一个list

4 框架基本原理

5 参数说明

6 css类

7 列表页用于选择

8 分页机制与后端接口适配

9 下拉刷新提示信息

@alias initNavbarAndList

列表页逻辑框架.

对一个导航栏(class="mui-navbar")及若干列表(class="p-list")的典型页面进行逻辑封装;也可以是若干button对应若干div-list区域,一次只显示一个区域;
特别地,也可以是只有一个list,并没有button或navbar对应。

它包括以下功能:

  1. 首次进入页面时加载默认列表
  2. 任一列表支持下拉刷新,上拉加载(自动管理刷新和分页)
  3. 点击导航栏自动切换列表,仅当首次显示列表时刷新数据
  4. 支持强制刷新所有列表的控制,一般定义在page接口中,如 PageOrders.refresh

1 例:一个navbar与若干list的组合

基本页面结构如下:

<div mui-initfn="initPageOrders" mui-script="orders.js">
    <div class="hd">
        <h2>订单列表</h2>
        <div class="mui-navbar">
            <a href="javascript:;" class="active" mui-linkto="#lst1">待服务</a>
            <a href="javascript:;" mui-linkto="#lst2">已完成</a>
        </div>
    </div>

    <div class="bd">
        <div id="lst1" class="p-list active" data-cond="status='PA'"></div>
        <div id="lst2" class="p-list" data-cond="status='RE'" style="display:none"></div>
    </div>
</div>

上面页面应注意:

js调用逻辑示例:

var lstItf = initPageList(jpage, {
    pageItf: PageOrders,

    //以下两项是缺省值:
    //navRef: ">.hd .mui-navbar",
    //listRef: ">.bd .p-list",

    // 设置查询参数,静态值一般通过在列表对象上设置属性 data-ac, data-cond以及data-queryParam等属性来指定更方便。
    onGetQueryParam: function (jlst, queryParam) {
        queryParam.ac = "Ordr.query";
        queryParam.orderby = "id desc";
        // queryParam.cond 已在列表data-cond属性中指定
    },
    onAddItem: function (jlst, itemData) {
        var ji = $("<li>" + itemData.title + "</li>");
        ji.appendTo(jlst);
    },
    onNoItem: function (jlst) {
        var ji = $("<li>没有订单</li>");
        ji.appendTo(jlst);
    }
});

由于指定了pageItf属性,当外部页面设置了 PageOrders.refresh = true后,再进入本页面,所有关联的列表会在展现时自动刷新。且PageOrders.refresh会被自动重置为false.

2 例:若干button与若干list的组合

一个button对应一个list; 打开页面时只展现一个列表,点击相应按钮显示相应列表。

如果没有用navbar组件,而是一组button对应一组列表,点一个button显示对应列表,也可以使用本函数。页面如下:

<div mui-initfn="initPageOrders" mui-script="orders.js">
    <div class="hd">
        <h2>订单列表</h2>
    </div>

    <div class="bd">
        <div class="p-panelHd">待服务</div>
        <div class="p-panel">
            <div id="lst1" class="p-list active"></div>
        </div>

        <div class="p-panelHd">已完成</div>
        <div class="p-panel">
            <div id="lst2" class="p-list" style="display:none"></div>
        </div>
    </div>
</div>

js调用逻辑示例:

jpage.find(".p-panel").height(500); // !!! 注意:必须为list container指定高度,否则无法出现下拉列表。一般根据页高自动计算。

var lstItf = initPageList(jpage, {
    pageItf: PageOrders,
    navRef: ".p-panelHd", // 点标题栏,显示相应列表区
    listRef: ".p-panel .p-list", // 列表区
    ...
});

注意:navRef与listRef中的组件数目一定要一一对应。除了使用选择器,也可以直接用jQuery对象为navRef和listRef赋值。

3 例:只有一个list

只有一个list 的简单情况,也可以调用本函数简化分页处理.
仍考虑上例,假如那两个列表需要进入页面时就同时显示,那么可以分开一一设置如下:

jpage.find(".p-panel").height(500); // 一定要为容器设置高度

var lstItf = initPageList(jpage, {
    pageItf: PageOrders,
    navRef: "", // 置空,表示不需要button链接到表,下面listRef中的多表各自显示不相关。
    listRef: ".p-panel .p-list", // 列表区
    ...
});

上例中,listRef参数也可以直接使用jQuery对象赋值。
navRef是否为空的区别是,如果非空,则表示listRef是一组互斥的列表,点击哪个button,就会设置哪个列表为active列表。当切到当前页时,只显示或刷新active列表。

如果是只包含一个列表的简单页面:

<div mui-initfn="initPageOrders" mui-script="orders.js">
    <div class="hd">
        <h2>订单列表</h2>
    </div>

    <div class="bd">
        <div class="p-list"></div>
    </div>
</div>

由于bd对象的高度已自动设置,要设置p-list对象支持上下拉加载,可以简单调用:

var lstItf = initPageList(jpage, {
    pageItf: PageOrders,
    navRef: "", // 一定置空,否则默认值是取mui-navbar
    listRef: ".p-list"
    ...
});

4 框架基本原理

原理是在合适的时机,自动调用类似这样的逻辑:

var queryParam = {ac: "Ordr.query"};
opt.onGetQueryParam(jlst, queryParam);
callSvr(queryParam.ac, queryParam, function (data) {
    $.each(rs2Array(data), function (i, itemData) {
        opt.onAddItem(jlst, itemData);
    });
    if (data.d.length == 0)
        opt.onNoItem(jlst);
});

5 参数说明

@param opt {onGetQueryParam?, onAddItem?, onNoItem?, pageItf?, navRef?=">.hd .mui-navbar", listRef?=">.bd .p-list", onBeforeLoad?, onLoad?, onGetData?}

@param opt 分页相关 { pageszName?="_pagesz", pagekeyName?="_pagekey" }

@param onGetQueryParam Function(jlst, queryParam/o)

queryParam: {ac?, res?, cond?, ...}

框架在调用callSvr之前,先取列表对象jlst上的data-queryParam属性作为queryParam的缺省值,再尝试取data-ac, data-res, data-cond, data-orderby属性作为queryParam.ac等参数的缺省值,
最后再回调 onGetQueryParam。

<ul data-queryParam="{q: 'famous'}" data-ac="Person.query" data-res="*,familyName" data-cond="status='PA' and name like '王%'">
</ul>

此外,框架将自动管理 queryParam._pagekey/_pagesz 参数。

@param onAddItem (jlst, itemData, param)

param={idx, arr, isFirstPage}

框架调用callSvr之后,处理每条返回数据时,通过调用该函数将itemData转换为DOM item并添加到jlst中。
判断首页首条记录,可以用

param.idx == 0 && param.isFirstPage

这里无法判断是否最后一页(可在onLoad回调中判断),因为有可能最后一页为空,这时无法回调onAddItem.

@param onNoItem (jlst)

当没有任何数据时,可以插入提示信息。

@param pageItf - page interface {refresh?/io}

在订单页面(PageOrder)修改订单后,如果想进入列表页面(PageOrders)时自动刷新所有列表,可以设置 PageOrders.refresh = true。
设置opt.pageItf=PageOrders, 框架可自动检查和管理refresh变量。

@param navRef,listRef 指定navbar与list,可以是选择器,也可以是jQuery对象;或是一组button与一组div,一次显示一个div;或是navRef为空,而listRef为一个或多个不相关联的list.

@param onBeforeLoad (jlst, isFirstPage)->Boolean 如果返回false, 可取消load动作。参数isFirstPage=true表示是分页中的第一页,即刚刚加载数据。

@param onLoad (jlst, isLastPage) 参数isLastPage=true表示是分页中的最后一页, 即全部数据已加载完。

@param onGetData (data, pagesz, pagekey?) 每次请求获取到数据后回调。pagesz为请求时的页大小,pagekey为页码(首次为null)

@return PageListInterface= {refresh, markRefresh}

refresh: Function(), 刷新当前列表
markRefresh: Function(jlst?), 刷新指定列表jlst或所有列表(jlst=null), 下次浏览该列表时刷新。

6 css类

可以对以下两个CSS class指定样式:

@key mui-pullPrompt CSS-class 下拉刷新提示块

@key mui-loadPrompt CSS-class 自动加载提示块

7 列表页用于选择

@key example-list-choose

常见需求:在一个页面上,希望进入另一个列表页,选择一项后返回。

可定义页面接口如下(主要是choose方法和onChoose回调):

var PageOrders = {
    ...
    // onChoose(order={id,dscr,...})
    choose: function (onChoose) {
        this.chooseOpt_ = {
            onChoose: onChoose
        }
        MUI.showPage('orders');
    },

    chooseOpt_: null // {onChoose}
};

在被调用页面上:

示例:

function initPageOrders()
{
    jpage.on("pagehide", onPageHide);

    function li_click(ev)
    {
        var order = $(this).data('obj');
        if (PageOrders.chooseOpt_) {
            PageOrders.chooseOpt_.onChoose(order);
            return false;
        }

        // 正常点击操作 ...
    }

    function onPageHide()
    {
        PageOrders.chooseOpt_ = null;
    }
}

在调用时:

PageOrders.choose(onChoose);

function onChoose(order)
{
    // 处理order
    history.back(); // 由于进入列表选择时会离开当前页面,这时应返回
}

8 分页机制与后端接口适配

默认按BQP协议的分页机制访问服务端,其规则是:

例1:假定后端分页机制为(jquery-easyui datagrid分页机制):

适配方法为:

var lstIf = initPageList(jpage, {
    ...

    pageszName: 'rows',
    pagekeyName: 'total',

    // 设置 data.list, data.nextkey (如果是最后一页则不要设置); 注意pagekey可以为空
    onGetData: function (data, pagesz, pagekey) {
        data.list = data.rows;
        if (pagekey == null)
            pagekey = 1;
        if (data.total >  pagesz * pagekey)
            data.nextkey = pagekey + 1;
    }
});

例2:假定后端分页机制为:

例3:假定后端就返回一个列表如[ {...}, {...} ],不支持分页。
什么都不用设置,仍支持下拉刷新,因为刚好会当成最后一页处理,上拉不再加载。

9 下拉刷新提示信息

@key .mui-pullHint 指定下拉提示显示位置

显示下拉刷新提示时,默认是在列表所在容器的最上端位置显示的。如果需要指定显示位置,可使用css类"mui-pullHint",示例如下:

<div class="bd">
    <div>下拉列表演示</div>
    <div class="mui-pullHint"></div> <!-- 如果没有这行,则下拉提示会在容器最上方,即"下拉列表演示"这行文字的上方-->
    <div id="lst1"></div>
    <div id="lst2"></div>
</div>

@fn showByFormMode(jo, formMode)

根据当前formMode自动显示或隐藏jo下的DOM对象.

示例: 对以下DOM对象

<div id="div1">
    <div id="div2"></div>
    <div id="div3" class="forAdd"></div>
    <div id="div4" class="forSet"></div>
    <div id="div5" class="forSet forAdd"></div>
</div>

调用showByFormMode(jo, FormMode.forAdd)时, 显示 div2, div3, div5;
调用showByFormMode(jo, FormMode.forSet)时, 显示 div2, div4, div5;


@fn initPageDetail(jpage, opt) -> PageDetailInterface={refresh(), del()}

详情页框架. 用于对象的添加/查看/更新多合一页面.
form.action为对象名.

@param opt {pageItf, jform?=jpage.find("form:first"), onValidate?, onGetData?, onNoAction?=history.back, onAdd?, onSet?, onGet?, onDel?}

pageItf: {formMode, formData}; formData用于forSet模式下显示数据, 它必须有属性id.
Form将则以pageItf.formData作为源数据, 除非它只有id一个属性(这时将则调用callSvr获取源数据)

onValidate: Function(jform, queryParam); 提交前的验证, 或做字段补全的工作, 或补全调用参数。queryParam是查询参数,它可能包含{ac?, res?, ...},可以进行修改。
onGetData: Function(jform, queryParam); 在forSet模式下,如果需要取数据,则回调该函数,获取get调用的参数。
onNoAction: Function(jform); 一般用于更新模式下,当没有任何数据更改时,直接点按钮提交,其实不做任何调用, 这时将回调 onNoAction,缺省行为是返回上一页。
onAdd: Function(id); 添加完成后的回调. id为新加数据的编号.
onSet: Function(data); 更新完成后的回调, data为更新后的数据.
onGet: Function(data); 获取数据后并调用setFormData将数据显示到页面后,回调该函数, 可用于显示特殊数据.
onDel: Function(); 删除对象后回调.

示例:制作一个人物详情页PagePerson:

逻辑页面(html片段)示例如下:

<div mui-initfn="initPagePerson" mui-script="person.js">
    ...
    <div class="bd">
        <form action="Person">
            <input name="name" required placeholder="输入名称">
            <textarea name="dscr" placeholder="写点简介"></textarea>
            <div class="forSet">人物标签</div>

            <button type="submit" id="btnOK">确定</button>
            <input type="text" style="display:none" name="familyId">

        </form>
    </div>
</div>

调用initPageDetail使它成为支持添加、查看和更新的详情页:

var PagePerson = {
    showForAdd: function (formData) ...
    showForSet: function (formData) ...
};

function initPagePerson()
{
    var jpage = this;
    var pageItf = PagePerson;
    initPageDetail(jpage, {
        pageItf: pageItf, // 需要页面接口提供 formMode, formData等属性。
        onValidate: function (jf) {
            // 补足字段和验证字段,返回false则取消form提交。
            if (pageItf.formMode == FormMode.forAdd) {
                ...
            }
        },
        onAdd: function (id) {
            PagePersons.show({refresh: true}); // 添加成功后跳到列表页并刷新。
        },
        onSet: function (data) {
            app_alert("更新成功!", history.back); // 更新成功后提示信息,然后返回前一页。
        },
        onDel: function () {
            PagePersons.show({refresh: true});
        },
    });
}

// 其它页调用它:
PagePerson.showForAdd({familyId: 1}); // 添加人物,已设置familyId为1
PagePerson.showForSet(person); // 以person对象内容显示人物,可更新。
PagePerson.showForSet({id: 3}); // 以id=3查询人物并显示,可更新。

对于forSet模式,框架先检查formData中是否只有id属性,如果是,则在进入页面时会自动调用{obj}.get获取数据.

<form action="Person">
    <div name=familyName></div>
    ...
</form>

如果formData中有多个属性,则自动以formData的内容作为数据源显示页面,不再发起查询。


Generated by jdcloud-gendoc @ 2016-12-21T23:32:31+08:00