MUI.callSvrExt['default'] (key)
MUI.callSvrExt[].dataFilter (key)
MUI.callSvrExt[].makeUrl (key)
JS通用函数库
生成一个随机整数。如生成10到20间的随机整数:
var n = randInt(10, 20)
生成指定长度(cnt)的随机代码。不出现"0","1","o","l"这些易混淆字符。
示例:生成8位随机密码
var dyn_pwd = randAlphanum(8);
取名字的基础部分,如
var name = basename("/cc/ttt.asp"); // "ttt.asp"
var name2 = basename("c:\\aaa\\bbb/cc/ttt.asp", ".asp"); // "ttt"
解析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".
将字符串转成boolean值。除"0", "1"外,还可以支持字符串 "on"/"off", "true"/"false"等。
重新加载当前页面,但不要#hash部分。
日期对象格式化字符串。
@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"
将纯时间字符串生成一个日期对象。
var dt1 = parseTime("10:10:00");
var dt2 = parseTime("10:11");
将日期字符串转为日期时间格式。其效果相当于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");
为日期对象加几天/小时等。参数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
计算日期到另一日期间的间隔,单位由sInterval指定(具体值列表参见Date.add).
var dt = new Date();
...
var dt2 = new Date();
var days = dt.diff("d", dt2); // 相隔多少天
@see Date.add
设置cookie值。如果只是为了客户端长时间保存值,一般建议使用 setStorage.
@see getCookie
@see delCookie
@see setStorage
取cookie值。
@see setCookie
@see delCookie
删除一个cookie项。
@see getCookie
@see setCookie
使用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
取storage中的一项。
默认使用localStorage存储,如果useSession=true,则使用sessionStorage存储。
如果浏览器不支持Storage,则使用cookie实现.
@see setStorage
@see delStorage
删除storage中的一项。
@see getStorage
@see setStorage
@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
@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
@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
标识应用当前是否正在与服务端交互。一般用于自动化测试。
应用参数。
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参数通过该函数获取。
值是一个整数,默认为0.
如果非0,表示WEB应用在苹果或安卓APP中运行,且数值代表原生应用容器的大版本号。
示例:检查用户APP版本是否可以使用某些插件。
if (g_cordova) { // 在原生APP中。可以使用插件。
// 假如在IOS应用的大版本3中,加入了某插件,如果用户未升级,可提示他升级:
if (g_cordova < 3 && isIOS()) {
app_alert("您的版本太旧,XX功能无法使用,请升级到最新版本");
}
}
应用全局共享数据。
在登录时,会自动设置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.logAction ?=false Boolean. 是否显示详细日志。
@var g_cfg.PAGE_SZ ?=20 分页大小,作为每次调用{obj}.query的缺省值。
设置应用的基本路径, 应以"/"结尾.
当用于本地调试网页时, 可以临时修改它, 比如在app.js中临时设置:
var BASE_URL = "http://oliveche.com/jdcloud/";
示例:
var url = "http://xxx/api.php";
if (a)
url = appendParam(url, "a=" + a);
if (b)
url = appendParam(url, "b=" + b);
当前应用运行在微信中。
当前应用运行在IOS平台,如iphone或ipad中。
当前应用运行在安卓平台。
动态加载一个script. 如果曾经加载过, 可以重用cache.
注意: $.getScript一般不缓存(仅当跨域时才使用Script标签方法加载,这时可用缓存), 自定义方法$.getScriptWithCache与本方法类似.
@see $.getScriptWithCache
取DOM对象中带name属性的子对象的内容, 放入一个JS对象中, 以便手工调用callSvr.
注意:
与setFormData配合使用时, 可以只返回变化的数据.
jf.submit(function () {
var ac = jf.attr("action");
callSvr(ac, fn, getFormData(jf));
});
@see setFormData
用于为带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
@param options ? 传递给$.ajax的选项。
@see loadScript
设置日期框, 如果输入了非法日期, 自动以指定日期(如未指定, 用当前日期)填充.
setDateBox($("#txtComeDt"), function () { return genDefVal()[0]; });
设置时间框, 如果输入了非法时间, 自动以指定时间(如未指定, 用当前时间)填充.
setTimeBox($("#txtComeTime"), function () { return genDefVal()[1]; });
用于简化异步编程. 可将不易读的回调方式改写为易读的顺序执行方式.
var dfd = $.getScript("http://...");
function onSubmit()
{
dfd.then(function () {
foo();
bar();
});
}
可改写为:
function onSubmit()
{
if (waitFor(dfd)) return;
foo();
bar();
}
返回一个属性做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>
从tm到tm1的时间差描述,如"2分钟前", "3天前"等。
tm和tm1可以为时间对象或时间字符串
如果str符合整数或小数,则返回相应类型。
原生插件与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"-商户端
对模板做字符串替换
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>
筋斗云移动UI框架 - JDCloud Mobile UI framework
亦称“变脸式应用”。应用程序以逻辑页面(page)为基本单位,每个页面的html/js可完全分离。主要特性:
@see MUI.showPage
@see MUI.popPageStack
@see CPageManager
@key .mui-container 应用容器。
@event muiInit () DOM事件。this为当前应用容器。
先在主应用html中,用.mui-container类标识应用容器,在运行时,所有逻辑页面都将在该对象之下。如:
<body class="mui-container">
应用初始化时会发出muiInit事件,该事件在页面加载完成($.ready)后,显示首页前调用。在这里调用MUI.showPage可动态显示首页。
每个逻辑页面(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。
逻辑页代码片段允许嵌入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>
逻辑页中允许但不建议内嵌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>
@see callSvr 系列调用服务端接口的方法。
@see CComManager
框架提供MUI.showLogin/MUI.logout操作.
调用MUI.tryAutoLogin可以支持自动登录.
登录后显示的主页,登录页,应用名称等均通过MUI.setApp设置。
@see MUI.tryAutoLogin
@see MUI.showLogin
@see MUI.logout
@see MUI.setApp
框架提供导航栏、对话框、弹出框、弹出菜单等常用组件。
@key .mui-navbar 导航栏
@key .mui-navbar.noactive
默认行为是点击后添加active类(比如字体发生变化),如果不需要此行为,可再添加noactive类。
@key .mui-dialog 对话框
@key .mui-menu 菜单
@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类,请自行添加。
仅当页面创建时才会加载。
<img src="../m/images/ui/carwash.png">
使用MUI框架的Web应用支持被安卓/苹果原生应用加载(通过cordova技术)。
设置说明:
不同的app大版本(通过URL参数cordova=?识别)或不同平台加载的插件是不一样的,要查看当前加载了哪些插件,可以在Web控制台中执行:
cordova.require('cordova/plugin_list')
对原生应用的额外增强包括:
@key g_cfg.manualSplash
应用加载完成后,自动隐藏启动画面(SplashScreen)。如果需要自行隐藏启动画面,可以设置
var g_cfg = {
manualSplash: true
...
}
然后开发者自己加载完后隐藏SplashScreen:
if (navigator.splashscreen && navigator.splashscreen.hide)
navigator.splashscreen.hide();
ios7以上, 框架自动为顶部状态栏留出20px高度的空间. 默认为白色,可以修改类mui-container的样式,如改为黑色:
.mui-container {
background-color:black;
}
如果使用了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事件未被回调,则出现启动页无法消失、插件调用无效、退出程序时无提示等异常。
其可能的原因是:
<script type="text/javascript" src="http://3.3.3.3/1.js"></script>
框架自动根据系统环境为应用容器(.mui-container类)增加以下常用类标识:
@key .mui-android 安卓系统
@key .mui-ios 苹果IOS系统
@key .mui-weixin 微信浏览器
@key .mui-cordova 原生环境
在css中可以利用它们做针对系统的特殊设置。
如果使用了 jquery.touchSwipe 库,则默认支持手势:
@key mui-swipenav DOM属性
如果页面中某组件上的左右划与该功能冲突,可以设置属性mui-swipenav="no"来禁用该功能:
<div mui-swipenav="no"></div>
@key .noSwipe CSS-class
左右划前进后退功能会导致横向滚动生效。可以通过添加noSwipe类(注意大小写)的方式禁用swipe事件恢复滚动功能:
<div class="noSwipe"></div>
典型应用是, 在开发前端页面时, 本地无须运行任何后端服务器(如apache/iis/php等), 直接跨域连接远程接口进行开发.
支持直接在浏览器中打开html/js文件运行应用.
需要浏览器支持CORS相关设置. 以下以chrome为例介绍.
例如, 远程接口的基础URL地址为 http://oliveche.com/jdcloud/
为chrome安装可设置CORS的插件(例如ForceCORS), 并设置:
添加URL: http://oliveche.com/*
Access-Control-Allow-Origin: file://
Access-Control-Allow-Credentials: true
在app.js中修改BASE_URL:
var BASE_URL = "http://oliveche.com/jdcloud/";
这时直接在chrome中打开html文件即可连接远程接口运行起来.
页面管理器。提供基于逻辑页面的单网页应用,亦称“变脸式应用”。
该类作为MUI模块的基类,仅供内部使用,但它提供showPage等操作,以及pageshow等各类事件。
@param app IApp={homePage?="#home", pageFolder?="page"}
当前页面。
注意:
要查看从哪个页面来,可以用 MUI.prevPageId。
要查看最近一次调用MUI.showPage转向的页面,可以用 MUI.getToPageId().
@see MUI.prevPageId
@see MUI.getToPageId ()
上一个页面的id, 首次进入时为空.
现在为$(document.body)
如果为false, 则必须手工执行 MUI.showPage 来显示第一个页面。
缺省配置项:
{
ani: 'auto' // 缺省切页动画效果. 'none'表示无动画。
}
@param pageId 如未指定,表示当前页。
删除一个页面。
@param pageId 如未指定,表示当前页。
重新加载指定页面。不指定pageId时,重加载当前页。
页面栈,MUI.popPageStack对它操作
n=0: 退到首层, >0: 指定pop几层
离开页面时, 如果不希望在点击后退按钮后回到该页面, 可以调用
MUI.popPageStack()
如果要在后退时忽略两个页面, 可以调用
MUI.popPageStack(2)
如果要在后退时直接回到主页(忽略所有历史记录), 可以调用
MUI.popPageStack(0)
@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"));
返回最近一次调用MUI.showPage时转向页面的Id.
@see MUI.prevPageId
@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;
});
@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一份用于显示并在关闭后删除。
@param app IApp={appName?=user}
提供callSvr等与后台交互的API.
@see MUI.callSvr
@see MUI.useBatchCall
出错时,取出错调用的上下文信息。
ctx: {ac, tm, tv, ret}
设置为true禁用batchCall, 仅用于内部测试。
当前batchCall对象,用于内部调试。
中止之后的调用, 直接返回.
向后端发送日志。后台必须已添加syslog插件。
日志可在后台Syslog表中查看,客户端信息可查看ApiLog表。
注意:如果操作失败,本函数不报错。
一般框架自动设置onerror函数;如果onerror被其它库改写,应再次调用该函数。
allow throw("abort") as abort behavior.
设置延迟执行。当delayCnt=1时与setTimeout效果相同。
多次置于事件队列最后,一般3次后其它js均已执行完毕,为idle状态
@param ctx {ac, tm, tv?, tv2?, noLoadingImg?}
@alias enterWaiting ()
@alias leaveWaiting
@param rv BQP协议原始数据,如 "[0, {id: 1}]",一般是字符串,也可以是JSON对象。
@return data 按接口定义返回的数据对象,如 {id: 1}. 如果返回==null,调用函数应直接返回,不回调应用层。
注意:服务端不应返回null, 否则客户回调无法执行; 习惯上返回false表示让回调处理错误。
@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
@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 出错时的上下文信息
@var g_cfg.logAction
框架会自动在ajaxOption中增加ctx_属性,它包含 {ac, tm, tv, tv2, ret} 这些信息。
当设置g_cfg.logAction=1时,将输出这些信息。
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) { ... }
});
@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);
callback(data)
.callback
.callSvr(ac, callback, postData, {noex:1})
,表示由应用层回调函数来处理出错: callback(false)
。当返回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, fn?, postParams?, userOptions?)
@alias callSvrSync
@return data 原型规定的返回数据
同步模式调用callSvr.
@see callSvr
该方法已不建议使用。上传文件请用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("上传成功");
}
批量调用。将若干个调用打包成一个特殊的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
之后的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
参考MUI.setApp
@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中数据没有变化时, 不做提交. 这时可调用该回调函数.
TODO: remove
show error using jquery validator's method by jo's name
@param jpage 如果指定, 则登录成功后转向该页面; 否则转向登录前所在的页面.
显示登录页. 注意: 登录页地址通过setApp({loginPage})指定, 缺省为"#login".
<div data-role="page" id="login">
...
</div>
注意:
显示主页。主页是通过 MUI.setApp({homePage: '#home'}); 来指定的,默认为"#home".
要取主页名可以用:
var jpage = $(MUI.m_app.homePage);
@see MUI.setApp
@param dontReload 如果非0, 则注销后不刷新页面.
注销当前登录, 成功后刷新页面(除非指定dontReload=1)
尝试自动登录,如果失败则转到登录页(除非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已赋值
}
@param data 调用API "login"成功后的返回数据.
处理login相关的操作, 如设置g_data.userInfo, 保存自动登录的token等等.
@param app= {appName?=user, allowedEntries?, loginPage?="#login", homePage?="#home", pageFolder?="page", noHandleIosStatusBar?=false}
对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类型)}
为列表添加下拉刷新和上拉加载功能。
例:页面元素如下:
<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为空的情况。
});
}
注意:
*** 由于处理分页的逻辑比较复杂,请调用 initPageList替代, 即使只有一个list;它会屏蔽nextkey, refresh等细节,并做一些优化。像这样调用:
initPageList(jpage, {
pageItf: PageOrders,
navRef: null,
listRef: jlst,
onGetQueryParam: ...
onAddItem: ...
});
本函数参数如下:
@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. 是否达到阈值
@alias initNavbarAndList
列表页逻辑框架.
对一个导航栏(class="mui-navbar")及若干列表(class="p-list")的典型页面进行逻辑封装;也可以是若干button对应若干div-list区域,一次只显示一个区域;
特别地,也可以是只有一个list,并没有button或navbar对应。
它包括以下功能:
基本页面结构如下:
<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.
一个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赋值。
只有一个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"
...
});
原理是在合适的时机,自动调用类似这样的逻辑:
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);
});
@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), 下次浏览该列表时刷新。
可以对以下两个CSS class指定样式:
@key mui-pullPrompt CSS-class 下拉刷新提示块
@key mui-loadPrompt CSS-class 自动加载提示块
@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(); // 由于进入列表选择时会离开当前页面,这时应返回
}
默认按BQP协议的分页机制访问服务端,其规则是:
如果不是最后一页,服务端应返回nextkey字段;返回列表的格式可以是 table格式如
{
h: [ "field1","field2" ],
d: [ ["val1","val2"], ["val3","val4"], ... ]
nextkey: 2
}
也可以用list参数指定列表,如
{
list: [
{field1: "val1", field2: "val2"},
{field1: "val3", field2: "val4"},
],
nextkey: 2
}
例1:假定后端分页机制为(jquery-easyui datagrid分页机制):
page=1&rows=20
{ total: 83, rows: [ {...}, ... ] }
适配方法为:
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:假定后端分页机制为:
curPage=1&maxLine=20
返回数据通过字段curPage, countPage, investList 分别表示当前页码, 总页数,列表数据,如 { curPage:1, countPage: 5, investList: [ {...}, ... ] }
var lstIf = initPageList(jpage, {
...
pageszName: 'maxLine',
pagekeyName: 'curPage',
// 设置 data.list, data.nextkey (如果是最后一页则不要设置); 注意pagekey可以为空
onGetData: function (data, pagesz, pagekey) {
data.list = data.investList;
if (data.curPage < data.countPage)
data.nextkey = data.curPage + 1;
}
});
例3:假定后端就返回一个列表如[ {...}, {...} ]
,不支持分页。
什么都不用设置,仍支持下拉刷新,因为刚好会当成最后一页处理,上拉不再加载。
@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>
根据当前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;
详情页框架. 用于对象的添加/查看/更新多合一页面.
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的内容作为数据源显示页面,不再发起查询。