组件库

IOS风格的精美组件.

示例

页面基本结构

我们对页面的基本结构是有要求的,否则可能会出现样式错误或者无法正确加载页面等问题。

基本的页面布局如下:

<!-- page 容器 -->
<div class="page">
  <!-- 标题栏 -->
  <header class="bar bar-nav">
    <a class="icon icon-me pull-left open-panel"></a>
    <h1 class="title">标题</h1>
  </header>

  <!-- 工具栏 -->
  <nav class="bar bar-tab">
    <a class="tab-item external active" href="#">
      <span class="icon icon-home"></span>
      <span class="tab-label">首页</span>
    </a>
    <a class="tab-item external" href="#">
      <span class="icon icon-star"></span>
      <span class="tab-label">收藏</span>
    </a>
    <a class="tab-item external" href="#">
      <span class="icon icon-settings"></span>
      <span class="tab-label">设置</span>
    </a>
  </nav>

  <!-- 这里是页面内容区 -->
  <div class="content">
    <div class="content-block">这里是content</div>
  </div>
</div>

<!-- popup, panel 等放在这里 -->
<div class="panel-overlay"></div>
<!-- Left Panel with Reveal effect -->
<div class="panel panel-left panel-reveal">
  <div class="content-block">
    <p>这是一个侧栏</p>
    <p></p>
    <!-- Click on link with "close-panel" class will close panel -->
    <p><a href="#" class="close-panel">关闭</a></p>
  </div>
</div>

注意!从 v0.0.7 版本之后,我们增加了一个 .page 容器。如果你的页面中没有这个容器,很可能导致如侧栏之类的组件无法正常工作。

rem

rem 是相对于 html 元素的 font-size 的一个单位。如果 html 上定义了 font-size: 20px;,则无论在任何地方都是 1rem = 20px 这个大小不会受到父元素的影响。

我们统一使用rem对页面进行整体缩放。强烈建议大家对需要适应页面大小的任何元素都使用 rem 为单位来定义。

事实上,除了 border-width 之外,MSUI中已经没有用到px单位的地方。

我们在 iphone6 上使用 1rem = 20px 来换算。小于 375px 的设备上不做缩小处理,对 大于 375px 宽度的设备进行等比缩放。

关于 rem 可以参考 MDN 上的定义

初始化

注意,从 v0.2.1 开始,初始化方法变成了 $.init()$.config.autoInit = false;,也就是默认不会调用 $.init 方法。现在需要自己手动调用 $.init,他会调用 $.initPage 方法初始化页面组件,并且触发一个 pageInit 事件,所以请确保在所有的 pageInit 事件绑定之后再调用 $.init() 方法。

请不要修改 $.init 方法,这个方法是MSUI提供好的,调用它就会初始化页面。

如果设置了 $.config.autoInit = true;,那么在 document.onload的时候就会执行 $.init方法,从而触发 pageInit事件,如果在这之后监听了 pageInit 事件是无法被执行的。强烈建议不要设置为true,而是在绑定完所有的 pageInit 事件之后,再调用 $.init方法

关于如何初始化,可以参考demos中的写法

全局配置

我们提供了一些全局配置,可以在初始化之前通过这些配置改变一些默认行为。 在引入JS之前通过一个 $.config 变量来改变默认配置:

从 v0.2.1 版本开始, autoInit 默认为 false

<script>
  //打开自动初始化页面的功能
  //建议不要打开自动初始化,而是自己调用 $.init 方法完成初始化
  $.config = {
    autoInit: true
  }
</script>
<script src='sm.js'></script>
所有配置项如下:
参数名 默认值 说明
autoInit false document.onload 之后自动调用 $.init 方法。如果你的页面内容是异步加载的,应该关闭这个配置,并且在加载完成之后手动调用 $.init
router true 默认启用MSUI内置的Router功能。如果想关闭此功能,在页面加载MSUI之前配置$.config.router = false 即可。
routerFilter null 当前点击链接是否使用路由功能的自定义过滤器。这是一个函数,实参是当前点击的链接的 jQuery 对象(即 $('the-link')),返回 false 表示不使用路由功能,返回 true 表示进入路由功能后续处理。
showPageLoadingIndicator true 在加载新页面过程中显示一个加载指示器。
swipePanel "left" 是否可以通过左右滑动打开侧栏,一次只能指定一个方向。
swipePanelOnlyClose true 只允许滑动关闭侧栏,不允许滑动打开。

内容区

如果你希望页面内容所有两边有间距,可以把内容放在 .content-padded 容器中

我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白

<div class="content-padded">
  <p>我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白,我的左右两边有留白</p>
</div>

路由

更详细的极端测试Demo

Router默认开启,会自动拦截所有链接的Touch行为,如果希望一个链接走浏览器原生跳转而不使用router,可以在链接上增加 class="external" 或者自定义属性,如 <a href="xxx" external>xxx</a>.

如果需要禁用路由功能,那么可以在 jQuery 之后, msui 之前使用 script $.config = {router: false} 来禁用.

路由新增direction参数用来指定页面打开加载的动画方向,默认为right,也可以设置为left, 在a标签上可以用data-direction来指定.

如只需禁用部分链接,除了使用external外,还可用自定义动态过滤器 $.config.routerFilter = function($link) {},实参 $link 是当前点击的链接,返回 false 表示不使用路由功能,返回 true 表示进入路由处理,参考初始化,示例如下:

    $.config = {
        // 路由功能开关过滤器,返回 false 表示当前点击链接不使用路由
        routerFilter: function($link) {
            // 某个区域的 a 链接不想使用路由功能
            if ($link.is('.disable-router a')) {
                return false;
            }

            return true;
        }
    };
    

路由功能前提

如果需要使用路由功能,那么页面代码结构上需要满足下面两个条件:

  1. 和之前相比的差异:每个 url 对应的 html 文档, 所有的展示内容都必须放在 div.page-group。 形式可以参考router Demo
  2. html 文档中, 每个可以用来切换显示的块都应该有 page 的 class
也就是说,每个 html 页面的基本结构都应该是下面这样(示例中省略 body 等):
    ...
    <div class="page-group">
        <div class="page">...</div>
        <div class="page">...</div>

        <!-- 如果有 popup -->
        <div class="popup popup-about">...</div>
    </div>
    ...
    

内联页面

你可以在同一个HTML文件中内联编写多个页面。每一个页面都是一个 .page 容器,如果有多个页面,则需要用 .page-current 标记出第一次进入的时候应该显示的页面。

每一个 .page 容器都应该有一个全局唯一的id,路由器会使用这个id作为唯一标示,如果没有设置id,可能会导致路由出错。你只需要这样写一个链接就可以跳转到id对应的内联页面 <a href='#{page-id}'>跳转</a>.

<div class="page page-current" id='router'>
  <header class="bar bar-nav">
    <h1 class='title'>路由</h1>
  </header>
  <div class="content">
    <div class="content-block">
      <ul>
        <li><a href="/docs-demos/router2">ajax加载新页面</a></li>
        <li><a href="#router3">内联的新页面</a></li>
      </ul>
    </div>
  </div>
</div>

<div class="page" id='router3'>
  <header class="bar bar-nav">
    <a class="button button-link button-nav pull-left back" href="/docs-demos/router">
      <span class="icon icon-left"></span>
      返回
    </a>
    <h1 class='title'>路由</h1>
  </header>
  <div class="content">
    <div class="content-block">
      这是内联编写的页面,点击左上角的 <a href="#" class='back'>返回</a> 按钮返回上一页。
    </div>
  </div>
</div>

ajax页面

注意: ajax 和 pushState 限制了 ajax 加载的页面只能是同域.

除了内联编写多个页面以外,你还可以通过ajax来加载新页面。通过ajax加载新页面和普通的链接写法没有区别,路由器会自动拦截链接的点击事件,并通过ajax请求加载新的页面。

<!-- page 1 -->
<div class="page page-current" id='router'>
  <header class="bar bar-nav">
    <h1 class='title'>路由</h1>
  </header>
  <div class="content">
    <div class="content-block">
      <ul>
        <li><a href="/docs-demos/router2">ajax加载新页面</a></li>
      </ul>
    </div>
  </div>
</div>
<!-- page 2 -->
<div class="page" id='router2'>
  <header class="bar bar-nav">
    <a class="button button-link button-nav pull-left back" href="/docs-demos/router">
      <span class="icon icon-left"></span>
      返回
    </a>
    <h1 class='title'>路由</h1>
  </header>
  <div class="content">
    <div class="content-block">
      这是ajax 加载的新页面,点击左上角的 <a href="#" class='back'>返回</a> 按钮返回上一页。
    </div>
  </div>
</div>

后退

我们对后退操作进行了封装,你只需要在任意链接上增加一个 .back 类,点击就会自动返回到上一页(调用 history.back)。

或者你可以通过调用 $.router.back() 来执行返回上一页操作。

<a class="button button-link button-nav pull-left back" href="/docs-demos/router">返回上一页</a>

缓存

默认地,对于加载过的页面,只要页面没刷新,那么再次进入该页面时,都会优先读取缓存而不发送网络请求。如果需要强制请求,可以用下面两种方式:
  • 在 a 链接上添加 data-no-cache="true" 属性来标明点击该链接时不使用缓存,如:<a href="/detail" data-no-cache="true">no cache</a>
  • 使用 js 方法 load 来加载时,把可选的参数 ignoreCache 设为 true,如:$.router.load('/detail', true)

JS方法

你可以通过调用 $.router.load(url, ignoreCache) 来加载一个页面,参数url既可以是一个ajax页面的地址,也可以是一个内联页面的id.

$.router.load("/detail");  //加载ajax页面
$.router.load("#about");  //加载内联页面
// ignoreCache 是加载一个新页面时是否忽略缓存而发网络请求,默认是 false,表示使用缓存,可以设为 true 来忽略缓存
$.router.load('/detail', true);
// direction 是指定加载新页面时的动画方向,默认是right,表示从右移动到左,可以设置为left来从左向右加载
$.router.load('/detail', true , 'left');

事件

从一个页面准备开始加载,到执行完加载动画,会按顺序触发以下事件:

事件 说明
pageLoadStart 发送Ajax之前触发
pageLoadCancel 取消了正在发送的ajax请求
pageLoadError Ajax 请求失败
pageLoadComplete Ajax 请求结束,无论是成功还是失败
pageAnimationStart 新页面的DOM插入当前页面之后,动画执行之前
pageAnimationEnd 新页面动画执行完毕
beforePageRemove 加载新的页面,动画切换完成后,移除旧的 document 前发送,事件回调函数参数是event, $pageContainer,其中$pageContainer.page-group(注:在 window 上触发,且内联 page 的切换不会触发此事件)
pageRemoved 加载新的页面,动画切换完成后,移除旧的 document 后发送(注:在 window 上触发,且内联 page 的切换不会触发此事件)
beforePageSwitch page 切换前触发,该事件在 pageAnimationStart 前,beforePageSwitch 之后会做一些额外的处理才触发 pageAnimationStart
pageInit 新页面中的组件初始化完毕

其中 pageLoad* 事件是在 window 上触发,其他都是在 .page 元素上触发。为了性能考虑,最好通过 document 代理监听。如果是内联页面,则没有前面的四个 pageLoad* 事件。

你可以这样监听事件:

$(document).on("pageInit", "#page-index", function(e, pageId, $page) {});
<!--或者-->
$(document).on("pageInit", function(e, pageId, $page) {
  if(pageId == "pageIndex") {}
});

文本样式

基础文本样式.

标题一

标题二

标题三

标题四

标题五
标题六

这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落

<div class="content-padded">
  <h1>标题一</h1>
  <h2>标题二</h2>
  <h3>标题三</h3>
  <h4>标题四</h4>
  <h5>标题五</h5>
  <h6>标题六</h6>
  <p>这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落这是一个段落</p>
</div>

标题栏

标题栏放在页面顶部

标题

<header class="bar bar-nav">
  <h1 class="title">标题</h1>
</header>

带按钮的标题栏

Title

<header class="bar bar-nav">
  <button class="button pull-left">
    按钮
  </button>
  <button class="button pull-right">
    按钮
  </button>
  <h1 class="title">标题</h1>
</header>

带图标的标题栏

标题

<header class="bar bar-nav">
  <a class="icon icon-left pull-left"></a>
  <a class="icon icon-refresh pull-right"></a>
  <h1 class="title">标题</h1>
</header>

带链接和图标

标题

<header class="bar bar-nav">
  <button class="button button-link button-nav pull-left">
    <span class="icon icon-left"></span>
    返回
  </button>
  <button class="button button-link button-nav pull-right">
    下一步
    <span class="icon icon-right"></span>
  </button>
  <h1 class="title">标题</h1>
</header>

带标签页

<header class="bar bar-nav">
  <button class="button pull-left">
    Left
  </button>
  <button class="button pull-right">
    Right
  </button>
  <div class="buttons-row">
    <a href="#tab1" class="tab-link active button">Tab 1</a>
    <a href="#tab2" class="tab-link button">Tab 2</a>
    <a href="#tab3" class="tab-link button">Tab 3</a>
  </div>
</header>

工具栏

<nav class="bar bar-tab">
  <a class="tab-item external active" href="#">
    <span class="icon icon-home"></span>
    <span class="tab-label">文案</span>
  </a>
  <a class="tab-item external" href="#">
    <span class="icon icon-me"></span>
    <span class="tab-label">文案</span>
    <span class="badge">2</span>
  </a>
  <a class="tab-item external" href="#">
    <span class="icon icon-star"></span>
    <span class="tab-label">文案</span>
  </a>
  <a class="tab-item external" href="#">
    <span class="icon icon-cart"></span>
    <span class="tab-label">文案</span>
  </a>
  <a class="tab-item external" href="#">
    <span class="icon icon-settings"></span>
    <span class="tab-label">文案</span>
  </a>
</nav>

工具栏 (只有文案)

  <nav class="bar bar-tab">
      <a class="tab-item external active" href="#">
  文案
</a>
      <a class="tab-item external" href="#">
  文案
</a>
      <a class="tab-item external" href="#">
  文案
</a>
  </nav>
  

二级标题栏

<nav class="bar bar-nav bar-standard">
  <h1 class="title">多级标题栏和工具栏</h1>
</nav>

<!-- Block button in standard bar fixed below top bar -->
<div class="bar bar-header-secondary">
  <button class="button button-block">Block level button</button>
</div>

<!-- Block button in standard bar fixed above the footer -->
<div class="bar bar-footer-secondary">
  <button class="button button-block">Block level button</button>
</div>

<!-- Icons in standard bar fixed to the bottom of the screen -->
<div class="bar bar-footer">
  <a class="icon icon-edit pull-left"></a>
  <a class="icon icon-settings pull-right"></a>
</div>

按钮

按钮

<header class="bar bar-nav">
  <h1 class='title'>按钮</h1>
</header>
<div class="content">
  <div class="content-block">
    <p><a href="#" class="button">Usual Button 1</a></p>
    <p><a href="#" class="button button-light">light button</a></p>
    <p><a href="#" class="button button-dark">dark button</a></p>
    <p><a href="#" class="button button-success">success button</a></p>
    <p><a href="#" class="button button-danger">danger button</a></p>
    <p><a href="#" class="button button-warning">warning button</a></p>
    <p><a href="#" class="button disabled">disabled button</a></p>
  </div>
  <div class="content-block">
    <p><a href="#" class="button button-round">Round Button 1</a></p>
  </div>
  <div class="content-block">
    <p><a href="#" class="button button-big">Big Button </a></p>
    <p><a href="#" class="button button-big button-round">Big Round Button </a></p>
  </div>
</div>

按钮组

<header class="bar bar-nav">
  <h1 class='title'>按钮组</h1>
</header>
<div class="content">
  <div class="content-block">
    <p class="buttons-row"><a href="#" class="button">Button 1</a><a href="#" class="button">Button 2</a><a href="#" class="button">Button 3</a></p>
    <p class="buttons-row"><a href="#" class="button active">Button 1</a><a href="#" class="button">Button 2</a><a href="#" class="button">Button 3</a></p>
    <p class="buttons-row"><a href="#" class="button">Button 1</a><a href="#" class="button active">Button 2</a><a href="#" class="button">Button 3</a></p>
    <p class="buttons-row"><a href="#" class="button button-round">Button 1</a><a href="#" class="button button-round">Button 2</a></p>
    <p class="buttons-row"><a href="#" class="button button-round">Button 1</a><a href="#" class="button button-round active">Button 2</a></p>
  </div>
</div>

填充按钮

填充按钮

<header class="bar bar-nav">
  <h1 class='title'>填充按钮</h1>
</header>
<div class="content">
  <div class="content-block">
    <p><a href="#" class="button button-fill">Fill Button </a></p>
    <p><a href="#" class="button button-fill button-success">Fill Button </a></p>
    <p><a href="#" class="button button-fill button-danger">Fill Button </a></p>
    <p><a href="#" class="button button-fill button-warning">Fill Button </a></p>
  </div>
</div>

使用列表和栅格

使用列表和栅格来进行按钮布局

列表和栅格布局按钮

List block buttons
Inset list block buttons
Using Grid
<header class="bar bar-nav">
  <h1 class='title'>列表和栅格布局按钮</h1>
</header>
<div class="content">
  <div class="content-block-title">List block buttons</div>
  <div class="list-block">
    <ul>
      <li><a href="#" class="item-link list-button">List Button 1</a></li>
      <li><a href="#" class="item-link list-button">List Button 2</a></li>
      <li><a href="#" class="item-link list-button">List Button 3</a></li>
    </ul>
  </div>
  <div class="content-block-title">Inset list block buttons</div>
  <div class="list-block inset">
    <ul>
      <li><a href="#" class="item-link list-button">List Button 1</a></li>
      <li><a href="#" class="item-link list-button">List Button 2</a></li>
      <li><a href="#" class="item-link list-button">List Button 3</a></li>
    </ul>
  </div>
  <div class="content-block-title">Using Grid</div>
  <div class="content-block">
    <div class="row">
      <div class="col-50"><a href="#" class="button button-big button-fill button-danger">Cancel</a></div>
      <div class="col-50"><a href="#" class="button button-big button-fill button-success">Submit</a></div>
    </div>
  </div>
</div>

表单

表单

表单

  • 姓名
  • 邮箱
  • 密码
  • 性别
  • 生日
  • 开关
  • 文本域
<header class="bar bar-nav">
  <h1 class='title'>表单</h1>
</header>
<div class="content">
  <div class="list-block">
    <ul>
      <!-- Text inputs -->
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-name"></i></div>
          <div class="item-inner">
            <div class="item-title label">姓名</div>
            <div class="item-input">
              <input type="text" placeholder="Your name">
            </div>
          </div>
        </div>
      </li>
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-email"></i></div>
          <div class="item-inner">
            <div class="item-title label">邮箱</div>
            <div class="item-input">
              <input type="email" placeholder="E-mail">
            </div>
          </div>
        </div>
      </li>
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-password"></i></div>
          <div class="item-inner">
            <div class="item-title label">密码</div>
            <div class="item-input">
              <input type="password" placeholder="Password" class="">
            </div>
          </div>
        </div>
      </li>
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-gender"></i></div>
          <div class="item-inner">
            <div class="item-title label">性别</div>
            <div class="item-input">
              <select>
                <option>Male</option>
                <option>Female</option>
              </select>
            </div>
          </div>
        </div>
      </li>
      <!-- Date -->
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-calendar"></i></div>
          <div class="item-inner">
            <div class="item-title label">生日</div>
            <div class="item-input">
              <input type="date" placeholder="Birth day" value="2014-04-30">
            </div>
          </div>
        </div>
      </li>
      <!-- Switch (Checkbox) -->
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-toggle"></i></div>
          <div class="item-inner">
            <div class="item-title label">开关</div>
            <div class="item-input">
              <label class="label-switch">
                <input type="checkbox">
                <div class="checkbox"></div>
              </label>
            </div>
          </div>
        </div>
      </li>
      <li class="align-top">
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-comment"></i></div>
          <div class="item-inner">
            <div class="item-title label">文本域</div>
            <div class="item-input">
              <textarea></textarea>
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
  <div class="content-block">
    <div class="row">
      <div class="col-50"><a href="#" class="button button-big button-fill button-danger">取消</a></div>
      <div class="col-50"><a href="#" class="button button-big button-fill button-success">提交</a></div>
    </div>
  </div>
</div>

只有图标的表单

只有图标的表单

只有图标的表单

<header class="bar bar-nav">
  <h1 class='title'>只有图标的表单</h1>
</header>
<div class="content">
  <div class="list-block">
    <ul>
      <!-- Text inputs -->
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-name"></i></div>
          <div class="item-inner">
            <div class="item-input">
              <input type="text" placeholder="Your name">
            </div>
          </div>
        </div>
      </li>
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-email"></i></div>
          <div class="item-inner">
            <div class="item-input">
              <input type="email" placeholder="E-mail">
            </div>
          </div>
        </div>
      </li>

      <!-- Select -->
      <li>
        <div class="item-content">
          <div class="item-media"><i class="icon icon-form-gender"></i></div>
          <div class="item-inner">
            <div class="item-input">
              <select>
                <option>Male</option>
                <option>Female</option>
              </select>
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
</div>

只有文案的表单

只有文案的表单

只有文案的表单

  • Name
  • E-mail
  • Gender
<header class="bar bar-nav">
  <h1 class='title'>只有文案的表单</h1>
</header>
<div class="content">
  <div class="list-block">
    <ul>
      <!-- Text inputs -->
      <li>
        <div class="item-content">
          <div class="item-inner">
            <div class="item-title label">Name</div>
            <div class="item-input">
              <input type="text" placeholder="Your name">
            </div>
          </div>
        </div>
      </li>
      <li>
        <div class="item-content">
          <div class="item-inner">
            <div class="item-title label">E-mail</div>
            <div class="item-input">
              <input type="email" placeholder="E-mail">
            </div>
          </div>
        </div>
      </li>

      <!-- Select -->
      <li>
        <div class="item-content">
          <div class="item-inner">
            <div class="item-title label">Gender</div>
            <div class="item-input">
              <select>
                <option>Male</option>
                <option>Female</option>
              </select>
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
</div>

侧栏

可以从左侧或者右侧滑出的面板。

使用侧栏

在任何元素上增加 .open-panel 类都可以使它能点击打开侧栏。如果有多个侧栏,你可以通过 data-panel='{panel的选择}'来指定具体打开哪一个侧栏

在任何元素上增加 .close-panel 类都可以使他点击关闭侧栏,因为侧栏只能同时打开一个,所以关闭的时候你不用指定是哪一个侧栏。

可以通过 .panel-left 或者 .panel-right 来指定侧栏是从左边还是右边出现。

可以通过 .panel-cover 或者 .panel-reveal 指定侧栏是覆盖在页面上还是推开页面。

配置

默认配置下,侧栏可以通过滑动手势打开,但是不能通过滑动手势关闭。

你可以通过 $.config.swipePanel$.config.swipePanelOnlyClose等参数来配置。具体配置请参见 初始化参数

<div class="page">
  <header class="bar bar-nav">
    <h1 class='title'>侧栏</h1>
  </header>
  <div class="content">
    <div class="content-block">
      <p><a href="#" class="button button-fill open-panel" data-panel='#panel-left-demo'>打开左侧栏</a></p>
    </div>
  </div>
</div>
<div class="panel-overlay"></div>
<!-- Left Panel with Reveal effect -->
<div class="panel panel-left panel-reveal theme-dark" id='panel-left-demo'>
  <div class="content-block">
    <p>这是一个侧栏</p>
    <p>你可以在这里放用户设置页面</p>
    <p><a href="#" class="close-panel">关闭</a></p>
  </div>
  <div class="list-block">
    <!-- .... -->
  </div>
</div>
<div class="panel panel-right panel-reveal">
  <div class="content-block">
    <p>这是一个侧栏</p>
    <!-- Click on link with "close-panel" class will close panel -->
    <p><a href="#" class="close-panel">关闭</a></p>
  </div>
</div>

使用侧栏的时候请注意,务必用 .page 容器把 .bar.content 包裹起来。

使用JS操作侧栏

除了使用 .open-panel.close-panel之外。你可以直接调用 $.openPanel(panel)$.closePanel() 来打开和关闭侧栏

  • $.openPanel(panel): 打开一个指定的panel, 其中 panel 是你需要打开的panel,可以是选择器或者DOM或者Zepto对象。如果没有传panel参数则会自动打开第一个panel。返回bool值表示是否打开成功。
  • $.closePanel(): 关闭打开的panel。返回bool值表示是否关闭成功。
<div class="page">
  <header class="bar bar-nav">
    <h1 class='title'>侧栏</h1>
  </header>
  <div class="content">
    <div class="content-block">
      <p><a href="#" class="button button-fill my-btn">JS打开侧栏</a></p>
    </div>
  </div>
</div>
<div class="panel-overlay"></div>
<!-- Left Panel with Reveal effect -->
<div class="panel panel-right panel-cover theme-dark" id='panel-js-demo'>
  <div class="content-block">
    <p>我是从右边出现的</p>
    <p>并且我是覆盖在页面上而不是推开页面</p>
    <p></p>
    <!-- Click on link with "close-panel" class will close panel -->
    <p><a href="#" class="close-panel">关闭</a></p>
  </div>
</div>
<div class="panel panel-right panel-reveal">
  <div class="content-block">
    <p>这是一个侧栏</p>
    <!-- Click on link with "close-panel" class will close panel -->
    <p><a href="#" class="close-panel">关闭</a></p>
  </div>
</div>
$(document).on("click", ".my-btn", function() {
  $.openPanel("#panel-js-demo");
});

事件

侧栏打开或者关闭的时候,会在 .panel 上触发对应的事件。

事件 说明
open 打开动画开始之前触发。
opened 打开动画结束之后 触发。
close 关闭动画开始之前触发。
closed 关闭动画结束之后 触发。

轻量级搜索栏

轻量级搜索栏适合放在页面内部,而不是固定在顶部。布局是通过栅格来实现的。所以可以非常灵活调整宽度以及组合任何你需要的组件。

<div class="content-padded">
  <div class="searchbar">
    <div class="search-input">
      <label class="icon icon-search" for="search"></label>
      <input type="search" id='search' placeholder='输入关键字...'/>
    </div>
  </div>

  <div class="searchbar row">
    <div class="search-input col-80">
      <label class="icon icon-search" for="search"></label>
      <input type="search" id='search' placeholder='输入关键字...'/>
    </div>
    <a class="button button-fill button-primary col-20">搜索</a>
  </div>

  <div class="searchbar row">
    <div class="search-input col-85">
      <input type="search" id='search' placeholder='输入关键字...'/>
    </div>
    <a class="button button-fill button-primary col-15"><span class="icon icon-search"></span></a>
  </div>
</div>

标签页

一级标签页

标签页

This is tab 1 content

This is tab 2 content

This is tab 3 content

<header class="bar bar-nav">
  <h1 class='title'>标签页</h1>
</header>
<div class="content">
  <div class="buttons-tab">
    <a href="#tab1" class="tab-link active button">全部</a>
    <a href="#tab2" class="tab-link button">待付款</a>
    <a href="#tab3" class="tab-link button">待发货</a>
  </div>
  <div class="content-block">
    <div class="tabs">
      <div id="tab1" class="tab active">
        <div class="content-block">
          <p>This is tab 1 content</p>
        </div>
      </div>
      <div id="tab2" class="tab">
        <div class="content-block">
          <p>This is tab 2 content</p>
        </div>
      </div>
      <div id="tab3" class="tab">
        <div class="content-block">
          <p>This is tab 3 content</p>
        </div>
      </div>
    </div>
  </div>
</div>

二级标签页

比一级标签页更轻量的标签页

标签页

This is tab 1 content

This is tab 2 content

This is tab 3 content

<header class="bar bar-nav">
  <h1 class='title'>标签页</h1>
</header>
<div class="content">
  <div class="content-block">
    <div class="buttons-row">
      <a href="#tab1" class="tab-link active button">Tab 1</a>
      <a href="#tab2" class="tab-link button">Tab 2</a>
      <a href="#tab3" class="tab-link button">Tab 3</a>
    </div>
  </div>
  <div class="tabs">
    <div id="tab1" class="tab active">
      <div class="content-block">
        <p>This is tab 1 content</p>
      </div>
    </div>
    <div id="tab2" class="tab">
      <div class="content-block">
        <p>This is tab 2 content</p>
      </div>
    </div>
    <div id="tab3" class="tab">
      <div class="content-block">
        <p>This is tab 3 content</p>
      </div>
    </div>
  </div>
</div>

fixed标签页

标签页滚动到顶部后固定在顶部,可以通过添加“fixed-tab”,如:

class="buttons-tab fixed-tab"

自动初始化调用fixedTab组件

固定位置的top默认值为0,可以通过在"fixed-tab"元素上添加data-offset="44"来调整高度

也可以直接调用js方法来手动初始化

  $(document).on("pageInit", function() {
      $('.buttons-tab').fixedTab({offset:44});
   });

html标签初始化

 <div class="content">
    <p>其他内容区域</p>
    <p>其他内容区域</p>
    <p>其他内容区域</p>
    <p>其他内容区域</p>
    <p>其他内容区域</p>
    <div class="buttons-tab fixed-tab" data-offset="44">
      <a href="#tab1" class="tab-link active button">全部</a>
      <a href="#tab2" class="tab-link button">待付款</a>
      <a href="#tab3" class="tab-link button">待发货</a>
    </div>

    <div class="tabs">
      <div id="tab1" class="tab active">
        <div class="content-block">
          <div class="buttons-row">
            <a href="#tab1-1" class="tab-link active button">Tab 1</a>
            <a href="#tab1-2" class="tab-link button">Tab 2</a>
            <a href="#tab1-3" class="tab-link button">Tab 3</a>
          </div>
          <div class="tabs">
            <p class='tab active' id='tab1-1' style="height:600px">This is tab 1-1 content</p>
            <p class='tab' id='tab1-2'>This is tab 1-2 content</p>
            <p class='tab' id='tab1-3'>13855589778</p>
          </div>
        </div>
      </div>
      <div id="tab2" class="tab">
        <div class="content-block">
          <p style="height:600px">This is tab 2 content start</p>
          <p >This is tab 2 content end</p>
        </div>
      </div>
      <div id="tab3" class="tab">
        <div class="content-block">
          <p style="height:600px">This is tab 3 content start</p>
          <p >This is tab 3 content end</p>
        </div>
      </div>
    </div>
  </div>

响应式栅格

栅格

50%
50%
33%
33%
33%
20%
80%

无间距

20%
80%
<header class="bar bar-nav">
  <h1 class='title'>栅格</h1>
</header>
<div class="content">
  <div class="content-padded grid-demo">
    <div class="row">
      <div class="col-50">50%</div>
      <div class="col-50">50%</div>
    </div>
    <div class="row">
      <div class="col-33">33%</div>
      <div class="col-33">33%</div>
      <div class="col-33">33%</div>
    </div>
    <div class="row">
      <div class="col-20">20%</div>
      <div class="col-80">80%</div>
    </div>
    <h2>无间距</h2>
    <div class="row no-gutter">
      <div class="col-20">20%</div>
      <div class="col-80">80%</div>
    </div>
  </div>
</div>

Confirm

Confirm modal 经常在需要确认一些行为时被使用. 打开Alert modal同样也需要调用以下任一一种App方法:$.confirm(text, [title, callbackOk, callbackCancel])
或者
$.confirm(text, [callbackOk, callbackCancel])

  • text - string. Confirm 文本
  • title - string. Optional. Confirm modal 标题
  • callbackOk - function. Optional. 在 Confirm modal下,当用户点击“Ok”按钮时,回调函数将被执行。(当用户确认操作)
  • callbackCancel - function. Optional. 在 Confirm modal下,当用户点击“Cancel”按钮时,回调函数将被执行。(当用户不想进行操作)

该方法返回动态创建的modal的HTML元素。

  <header class="bar bar-nav">
    <h1 class="title">Confirm</h1>
  </header>
  ...
  <div class="content">
    <div class="content-block">
      <p><a href="#" class="confirm-ok">Confirm with text and Ok callback</a></p>
      <p><a href="#" class="confirm-ok-cancel">Confirm with text, Ok and Cancel callbacks</a></p>
      <p><a href="#" class="confirm-title-ok">Confirm with text, title and Ok callback</a></p>
      <p><a href="#" class="confirm-title-ok-cancel">Confirm with text, title, Ok and Cancel callback</a></p>
    </div>
  </div>
  ...
  
  $(document).on('click','.confirm-ok', function () {
      $.confirm('Are you sure?', function () {
          $.alert('You clicked Ok button');
      });
  });

  $(document).on('click', '.confirm-ok-cancel',function () {
      $.confirm('Are you sure?',
        function () {
          $.alert('You clicked Ok button');
        },
        function () {
          $.alert('You clicked Cancel button');
        }
      );
  });
  $(document).on('click','.confirm-title-ok', function () {
      $.confirm('Are you sure?', 'Custom Title', function () {
          $.alert('You clicked Ok button');
      });
  });
  $(document).on('click','.confirm-title-ok-cancel', function () {
      $.confirm('Are you sure?', 'Custom Title',
        function () {
          $.alert('You clicked Ok button');
        },
        function () {
          $.alert('You clicked Cancel button');
        }
      );
  });
  

Prompt

Prompt modal 经常在需要从用户那里得到一些数据/答案时使用。打开 Prompt modal同样也需要调用以下任一一种App方法:$.prompt(text, [title, callbackOk, callbackCancel])
或者
$.prompt(text, [callbackOk, callbackCancel])

  • text - string. Prompt 文本/问题
  • title - string. Optional. Prompt modal 标题
  • callbackOk - function. Optional. 在 Prompt modal下,当用户点击“Ok”按钮时,回调函数将被执行。回调函数的参数是输入框的值
  • callbackCancel - function. Optional. 在 Prompt modal下,当用户点击“Cancel”按钮时,回调函数将被执行。回调函数的参数是输入框的值

该方法返回动态创建的modal的HTML元素。

  <header class="bar bar-nav">
    <h1 class="title">Prompt</h1>
  </header>
  ...
  <div class="content">
    <div class="content-block">
      <p><a href="#" class="prompt-ok">Prompt with text and Ok callback</a></p>
      <p><a href="#" class="prompt-ok-cancel">Prompt with text, Ok and Cancel callbacks</a></p>
      <p><a href="#" class="prompt-title-ok">Prompt with text, title and Ok callback</a></p>
      <p><a href="#" class="prompt-title-ok-cancel">Prompt with text, title, Ok and Cancel callback</a></p>
    </div>
  </div>
  ...
  
  $(document).on('click','.prompt-ok', function () {
      $.prompt('What is your name?', function (value) {
          $.alert('Your name is "' + value + '". You clicked Ok button');
      });
  });

  $(document).on('click','.prompt-ok-cancel', function () {
      $.prompt('What is your name?',
        function (value) {
          $.alert('Your name is "' + value + '". You clicked Ok button');
        },
        function (value) {
          $.alert('Your name is "' + value + '". You clicked Cancel button');
        }
      );
  });
  $(document).on('click', '.prompt-title-ok',function () {
      $.prompt('What is your name?', 'Custom Title', function (value) {
          $.alert('Your name is "' + value + '". You clicked Ok button');
      });
  });
  $(document).on('click', '.prompt-title-ok-cancel',function () {
      $.prompt('What is your name?', 'Custom Title',
        function (value) {
          $.alert('Your name is "' + value + '". You clicked Ok button');
        },
        function (value) {
          $.alert('Your name is "' + value + '". You clicked Cancel button');
        }
      );
  });
  

自定义Modals

Ok, 所有的预定义modals都只是一些适用于特定的场景的方法. 让我们看看如何创建自定义的 modals:

$.modal(parameters) - 显示 custom modal

  • parameters - object. Modal 的 parameters/options对象

该方法返回动态创建的modal的HTML元素。

这里有 Modal 的参数列表:

参数 类型 默认值 描述
title 字符串 可选. Modal 标题 (可以是html字符串)
text 字符串 可选. Modal 文本 (可以是html字符串)
afterText 字符串 可选. 将被放在"text"后的文本 (可以是html字符串)
buttons 数组 可选. 按钮数组. 每个按钮应该被表示为带按钮参数的对象 (看下面)
extraClass 字符串 可选. 给modal的根节点.modal附加1或多个自定义class(如'bg-red','bg-blue share-type'),方便按需定制不同的modal样式。
verticalButtons boolean false Optional. Set to true to enable vertical buttons layout
onClick 函数 可选. 回调函数将在用户点击任何Modal按钮后被触发执行. 它接收 modal (Modal的 HTML元素) 和 index作为参数 (被点击按钮的索引号)

让我们一起来看看按钮参数:

参数 类型 默认值 描述
text 字符串 按钮文本 (可以是 HTML 字符串)
bold 布尔值 false 可选. 设置为true会加粗按钮文本
close 布尔值 true 可选. 如果是“true”,点击这个按钮后modal会被关闭
onClick 函数 可选. 用户点击这个按钮后,回调函数会被执行

这样的配置选项允许我们创建灵活的modals。让我们来看一些例子

  <header class="bar bar-nav">
      <h1 class="title">自定义Modals</h1>
  </header>
  ...
  <div class="content">
    <div class="content-block">
      <p><a href="#" class="open-3-modal">Modal With 3 Buttons</a></p>
      <p><a href="#" class="open-slider-modal">Modal With Slider</a></p>
      <p><a href="#" class="open-tabs-modal">Modal With Tabs</a></p>
      <p><a href="#" class="open-vertical-modal">Modal With Vertical Buttons</a></p>
    </div>
  </div>
  ...
  
  $(document).on('click','.open-3-modal', function () {
    $.modal({
      title:  'Modal with 3 buttons',
      text: 'Vivamus feugiat diam velit. Maecenas aliquet egestas lacus, eget pretium massa mattis non. Donec volutpat euismod nisl in posuere. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae',
      buttons: [
        {
          text: 'B1',
          onClick: function() {
            $.alert('You clicked first button!')
          }
        },
        {
          text: 'B2',
          onClick: function() {
            $.alert('You clicked second button!')
          }
        },
        {
          text: 'B3',
          bold: true,
          onClick: function() {
            $.alert('You clicked third button!')
          }
        },
      ]
    })
    });
    $(document).on('click','.open-slider-modal', function () {
    var modal = $.modal({
      title: 'Awesome Photos?',
      text: 'What do you think about my photos?',
      afterText:  '<div class="swiper-container" style="width: auto; margin:5px -15px -15px">'+
                    '<div class="swiper-pagination"></div>'+
                    '<div class="swiper-wrapper">'+
                      '<div class="swiper-slide"><img src="..." height="150" style="display:block"></div>' +
                      '<div class="swiper-slide"><img src="..." height="150" style="display:block"></div>'+
                    '</div>'+
                  '</div>',
      buttons: [
        {
          text: 'Bad :('
        },
        {
          text: 'Awesome!',
          bold: true,
          onClick: function () {
            $.alert('Thanks! I know you like it!')
          }
        },
      ]
    })
    $.swiper($$(modal).find('.swiper-container'), {pagination: '.swiper-pagination'});
    });

    $(document).on('click','.open-tabs-modal', function () {
    $.modal({
      title:  '<div class="buttons-row">'+
                '<a href="#tab1" class="button active tab-link">Tab 1</a>'+
                '<a href="#tab2" class="button tab-link">Tab 2</a>'+
              '</div>',
      text: '<div class="tabs">'+
              '<div class="tab active" id="tab1">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam convallis nunc non dolor euismod feugiat. Sed at sapien nisl. Ut et tincidunt metus. Suspendisse nec risus vel sapien placerat tincidunt. Nunc pulvinar urna tortor.</div>'+
              '<div class="tab" id="tab2">Vivamus feugiat diam velit. Maecenas aliquet egestas lacus, eget pretium massa mattis non. Donec volutpat euismod nisl in posuere. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae</div>'+
            '</div>',
      buttons: [
        {
          text: 'Ok, got it',
          bold: true
        },
      ]
    })
    });

    $(document).on('click','.open-vertical-modal', function () {
    $.modal({
      title:  'Vertical Buttons Layout',
      text: 'Vivamus feugiat diam velit. Maecenas aliquet egestas lacus, eget pretium massa mattis non. Donec volutpat euismod nisl in posuere. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae',
      verticalButtons: true,
      buttons: [
        {
          text: 'Button 1',
          onClick: function() {
            $.alert('You clicked first button!')
          }
        },
        {
          text: 'Button 2',
          onClick: function() {
            $.alert('You clicked second button!')
          }
        },
        {
          text: 'Button 3',
          onClick: function() {
            $.alert('You clicked third button!')
          }
        },
      ]
    })
    });
  

用 JavaScript 关闭 Modals

任何 Modal 可以用 JavaScript 来关闭,不仅仅是通过点击按钮。因此我们需要看看相关App方法:

$.closeModal(modal) - 关闭任意 modal

  • modal - HTMLElement or string ( CSS 选择器). 可选. 除了指定的,任何被打开modal都将被关闭。

带标题的加载指示器

预加载 Modal 用来提示一些后台活动(像Ajax请求)和阻止在这个活动期间的任何用户操作。 打开预加载 modal 我们也需要调用适当的App方法: $.show预加载([title])- 显示 预加载 modal

  • title - string. Optional. 预加载 modal 标题. 默认(没有指定)的时候,它等同于 "Loading...". 你可以在App初始化时通过 modal预加载Title 参数改变默认的 预加载 标题。

该方法返回动态创建的modal的HTML元素。

$.hide预加载() - 隐藏/关闭 预加载 modal. 因为 预加载 modal 没有任何按钮, 它应该用 JavaScript 来关闭

  <header class="bar bar-nav">
    <h1 class="title">预加载 Modal (Preloader Modal)</h1>
  </header>
  ...
  <div class="content">
    <div class="content-block">
      <p><a href="#" class="open-preloader">Open Preloader</a></p>
      <p><a href="#" class="open-preloader-title">Open Preloader with custom title</a></p>
    </div>
  </div>
  ...
  
  $(document).on('click', '.open-preloader', function () {
    $.showPreloader();
    setTimeout(function () {
        $.hidePreloader();
    }, 2000);
  });
  $(document).on('click','.open-preloader-title', function () {
    $.showPreloader('Custom Title')
    setTimeout(function () {
        $.hidePreloader();
    }, 2000);
  });
  

迷你指示器

如果你不需要用像预加载Modal这样如此大的modal 窗口去指示活动, 你可以使用简单并且小的指示器modal:

$.showIndicator() - 显示指示器 modal

$.hideIndicator() - 隐藏/关闭指示器 modal. 因为指示器modal没有任何按钮, 它需要用JavaScript来关闭

  <header class="bar bar-nav">
      <h1 class="title">指示器(indicator)</h1>
  </header>
  ...
  <div class="content">
    <div class="content-block">
      <p><a href="#" class="open-indicator">Open Indicator</a></p>
    </div>
  </div>
  ...
  
  $(document).on('click','.open-indicator', function () {
      $.showIndicator();
      setTimeout(function () {
          $.hideIndicator();
      }, 2000);
  });
  

toast

toast是一种轻量的提示,在页面中间显示,并且会在2秒(默认值,可修改)之后自动消失。

可以用来显示一些不会打断用户操作的提示。

/* msg{string}: toast内容
 * duration{number}:toast显示时间,默认2000
 * extraclass{string}:给toast根节点附加class,高度自定义属性,方便用户自行控制不同场景的样式。
 * 如果使用了第三个参数,请自行在业务css里添加extraclass对应的样式
 * /
$.toast("操作失败");

$.toast('操作成功,正在跳转...', 2345, 'success top');

使用 JavaScript

我们也可以用使用JavaScript来打开和关闭Popups ,因此我们需要看一下相关的App方法:

$.popup(popup) - 打开 Popup

  • popup - HTML元素 或者 字符串 (需要打开的popup的 CSS 选择器) . 必需

$.closeModal(popup) - 关闭 Popup

  • popup - HTML元素 或者 字符串 (需要打开的popup的 CSS 选择器). 可选. 如果没有设置这个值,任何打开着的Popup/Modal 都将被关闭
  
<header class="bar bar-nav">
    <h1 class="title">Popup(JavaScript)</h1>
</header>
...
<div class="content">
    <div class="content-block">
      <p><a href="#" class="open-about">Open About Popup </a></p>
      <p><a href="#" class="open-services">Open Services Popup </a></p>
    </div>
       
</div> 
<!-- About Popup -->
<div class="popup popup-about">
  <div class="content-block">
    <p>About</p>
    <p><a href="#" class="close-popup">Close popup</a></p>
    <p>Lorem ipsum dolor ...</p>
  </div>
</div>
<!-- Services Popup -->
<div class="popup popup-services">
  <div class="content-block">
    <p>Services</p>
    <p><a href="#" class="close-popup">Close popup</a></p>
    <p>Lorem ipsum dolor ...</p>
  </div>
</div>  
  
$(document).on('click','.open-about', function () {
  $.popup('.popup-about');
});
 
$(document).on('click','.open-services', function () {
  $.popup('.popup-services');
});   

Popup 事件

Popup 和 Modals有一样的事件, 如果你需要在打开/关闭popup时使用JavaScript做一些事情的时候,这些事件会很有用。

事件 目标 描述
open Popup Element<div class="popup"> 当 Popup 开始打开动画时,事件将被触发。
opened Popup Element<div class="popup"> 当 Popup 完成打开动画时,事件将被触发。
close Popup Element<div class="popup"> 当 Popup 开始结束动画时,事件将被触发。
closed Popup Element<div class="popup"> 当 Popup 完成结束动画后,事件将被触发。
  
<header class="bar bar-nav">
    <h1 class="title">Popup事件</h1>
</header>
...
<div class="content">
  <div class="content-block">
    <!-- In data-popup attribute we specify CSS selector of popup we need to open -->
    <p><a href="#" data-popup=".popup-about" class="open-popup">Open About Popup </a></p>
    <p><a href="#" data-popup=".popup-services" class="open-popup">Open Services Popup </a></p>
  </div>
</div>
<!-- About Popup -->
<div class="popup popup-about">
  <div class="content-block">
    <p>About</p>
    <p><a href="#" class="close-popup">Close popup</a></p>
    <p>Lorem ipsum dolor ...</p>
  </div>
</div>
<!-- Services Popup -->
<div class="popup popup-services">
  <div class="content-block">
    <p>Services</p>
    <p><a href="#" class="close-popup">Close popup</a></p>
    <p>Lorem ipsum dolor ...</p>
  </div>
</div>  
  
$(document).on('click','.popup-about', function () {
  console.log('About Popup opened')
});
$(document).on('click','.popup-about', function () {
  console.log('About Popup is closing')
});
$(document).on('click','.popup-services', function () {
  console.log('Services Popup is opening')
});
$(document).on('click','.popup-services', function () {
  console.log('Services Popup is closed')
});    

动态的 Popup

允许你调用相关的App方法时传递HTML内容来动态地创建Popup:

$.popup(popupHTML, removeOnClose) - 打开 Popup

  • popupHTML - string. popup的HTML字符串
  • removeOnClose - boolean. 可选, 默认 - true. 如果是 true, 那么 Popup 在关闭时将从DOM中移除
  
<header class="bar bar-nav">
    <h1 class="title">动态的 Popup</h1>
</header>
...
<div class="content">
  <div class="content-block">
    <!-- In data-popup attribute we specify CSS selector of popup we need to open -->
    <p><a href="#" class="create-popup">Create Popup</a></p>
  </div>
</div>
  
$(document).on('click','.create-popup', function () {
  var popupHTML = '<div class="popup">'+
                    '<div class="content-block">'+
                      '<p>Popup created dynamically.</p>'+
                      '<p><a href="#" class="close-popup">Close me</a></p>'+
                    '</div>'+
                  '</div>'
  $.popup(popupHTML);
}); 

日历

日历组件用来选择年月日,可以代替系统原生的日历组件,提供更统一的视觉和交互以及更好的兼容性。

日历组件需要初始化才能使用,最简单的方式是通过一下JS代码来初始化,绑定到一个input元素上:

$("#my-input").calendar({
    value: ['2015-12-05']
});

当你点击input元素后,会自动弹出一个JS生成的日历组件。当用户选择日期之后,input的值会被设置为用户选择的日期。

如果你不想写js,可以通过以下方式来自动初始化:

<input type="text" data-toggle='date' />

参数

你可以在初始化的时候指定如下参数:

参数名 默认值 说明
value undefined 初始化打开后默认选中的时间。格式是value: ['2012-06-18']
inputReadOnly true 是否在input上增加一个 readonly 属性使用户无法自己输入
dateFormat 'yyyy-mm-dd' 格式化日期
minDate undefined 最小可选日期,比如 2015-06-01
maxDate undefined 最大可选日期,比如 2015-08-01
onChange function(p, values, displayValues){} 当用户选择日期时触发
onOpen function(p){} 日历弹层打开时触发
onClose function(p){} 日历弹层关闭时触发

当用户选择完日期之后,会在 input 上触发 change 事件,你可以监听此事件。

如果你只同时选择日期和时间 , 请使用 日期时间选择器

内联日历

日历插件是非常智能的,如果在一个非 input 元素上初始化,它会自动变成内联形式。

<div data-toggle='date' />

操作表

操作表可以让用户从多个可选的操作中选择一个

$.actions(buttons) - 创建并弹出一个操作表

  • buttons - 显示的几个按钮,你也可以把按钮分组

你可以通过 color: "danger" 来指定按钮的文案为红色

或者通过 bg: "danger" 来指定按钮的背景为红色

操作表

  
  <header class="bar bar-nav">
      <h1 class="title">操作表</h1>
  </header>
  <div class="content">
    <div class="content-block">
      <!-- In data-popup attribute we specify CSS selector of popup we need to open -->
      <p><a href="#" class="create-actions">选择操作</a></p>
    </div>
  </div>
  
  
  $(document).on('click','.create-actions', function () {
      var buttons1 = [
        {
          text: '请选择',
          label: true
        },
        {
          text: '卖出',
          bold: true,
          color: 'danger',
          onClick: function() {
            $.alert("你选择了“卖出“");
          }
        },
        {
          text: '买入',
          onClick: function() {
            $.alert("你选择了“买入“");
          }
        }
      ];
      var buttons2 = [
        {
          text: '取消',
          bg: 'danger'
        }
      ];
      var groups = [buttons1, buttons2];
      $.actions(groups);
  }); 
  

picker

picker是一个JS实现的类似select的组件,他可以代替原生的select组件,并且功能更加强大、样式更加统一。

picker 需要初始化才能使用,你可以在一个 input 元素上初始化picker,当用户点击input的时候会弹出picker的弹层

<input type="text" id='picker'/>
<script>
$("#picker").picker({
  toolbarTemplate: '<header class="bar bar-nav">\
  <button class="button button-link pull-left">按钮</button>\
  <button class="button button-link pull-right close-picker">确定</button>\
  <h1 class="title">标题</h1>\
  </header>',
  cols: [
    {
      textAlign: 'center',
      values: ['iPhone 4', 'iPhone 4S', 'iPhone 5', 'iPhone 5S', 'iPhone 6', 'iPhone 6 Plus', 'iPad 2', 'iPad Retina', 'iPad Air', 'iPad mini', 'iPad mini 2', 'iPad mini 3']
    }
  ]
});
</script>

关闭picker

在任何元素上加上一个 .close-picker 类,点击它就会关闭 picker。

你也可以通过调用 $(".picker").picker("close") 或者 $.closeModal(".picker-modal.modal-in") 来关闭。

picker参数

你可以通过设置 toolbarTemplate 参数来自定义工具栏模板。在 cols 参数中可以传入多列值。

$("#picker-name").picker({
  toolbarTemplate: '<header class="bar bar-nav">\
  <button class="button button-link pull-right close-picker">确定</button>\
  <h1 class="title">请选择称呼</h1>\
  </header>',
  cols: [
    {
      textAlign: 'center',
      values: ['赵', '钱', '孙', '李', '周', '吴', '郑', '王']
      //如果你希望显示文案和实际值不同,可以在这里加一个displayValues: [.....]
    },
    {
      textAlign: 'center',
      values: ['杰伦', '磊', '明', '小鹏', '燕姿', '菲菲', 'Baby']
    },
    {
      textAlign: 'center',
      values: ['先生', '小姐']
    }
  ]
});

所有可用参数如下:

参数名 默认值 说明
toolbarTemplate <header class="bar bar-nav"> <button class="button button-link pull-right close-picker">确定</button> <h1 class="title"></h1> </header> 工具栏的模板,可以自己定义。
value input元素的value属性。
多列默认值用空格隔开,如<input value="钱 明 小姐">。如果任一列默认值本身含空格(如‘ipad mini 2’),那就只能用JS方法调用模式传入value参数
为 picker 添加默认值,数组里每一项对应每一列默认值,如["钱", "明", "小姐"]
rotateEffect false 是否启用3D效果,启用3D可能会影响性能
toolbar true 是否显示工具栏
inputReadOnly true 是否会在input上添加一个 readonly 属性
cssClass undefined 为 picker 容器增加额外的类,可以用来自定义样式
onOpen undefined 自定义 picker 打开时的触发动作
onClose undefined 自定义 picker 关闭时的触发动作
formatValue undefined 自定义方法,用来控制如何显示picker的选中值,formatValue: function (picker, value, displayValue){},value, displayValue为数组,长度等于cols长度

picker方法

你可以通过 $(".picker").picker("method", args1, args2...) 的方式来调用相关的方法。

$("#picker-name").picker("open");
$("#picker-name").picker("close");
$("#picker-name").picker("setValue", ["2012", "12", "12"]);

所有可用方法如下:

方法名 参数说明 方法说明
open 打开picker
close 关闭picker
setValue 一个字符串数组,其中每个字符串对应每一列 设置值

日期时间选择器

日期时间选择器是一个定制的picker,因此他的用法和picker完全一致。打开picker的默认值是当前时间,可以通过value参数指定

datetime-picker 定制了 onChange 和 cols 参数,请不要设置这两个参数。

<input type="text" id='datetime-picker'/>
<script>
  $("#datetime-picker").datetimePicker({
    value: ['1985', '12', '04', '9', '34']
  });
</script>

如果你只想选择日期,请使用 日历

列表

常在iOS应用中看到的列表,是种多功能且强大的交互组件。列表将数据展现在一个可滚动的多行的列表中,可以将数据划分成不同的片段/组(sections/groups)。

列表有以下用途:

  • 让用户可以浏览结构化的多级数据
  • 展现一个索引列表
  • 在可视化的不同分组中,显示详细信息和控件
  • 展现一个可以选择的列表
<header class="bar bar-nav">
  <h1 class="title">视图列表</h1>
</header>
<div class="content">
  <div class="content-block-title">图标、标题和副标题</div>
  <div class="list-block">
    <ul>
      <li class="item-content">
        <div class="item-media"><i class="icon icon-f7"></i></div>
        <div class="item-inner">
          <div class="item-title">商品名称</div>
          <div class="item-after">杜蕾斯</div>
        </div>
      </li>
      <li class="item-content">
        <div class="item-media"><i class="icon icon-f7"></i></div>
        <div class="item-inner">
          <div class="item-title">型号</div>
          <div class="item-after">极致超薄型</div>
        </div>
      </li>
    </ul>
  </div>
  <div class="content-block-title">标题和副标题</div>
  <div class="list-block">
    <ul>
      <li class="item-content">
        <div class="item-inner">
          <div class="item-title">商品名称</div>
          <div class="item-after">杜蕾斯</div>
        </div>
      </li>
      <li class="item-content">
        <div class="item-inner">
          <div class="item-title">型号</div>
          <div class="item-after">极致超薄型</div>
        </div>
      </li>
    </ul>
  </div>
  <div class="content-block-title">带箭头</div>
  <div class="list-block">
    <ul>
      <li class="item-content item-link">
        <div class="item-media"><i class="icon icon-f7"></i></div>
        <div class="item-inner">
          <div class="item-title">商品名称</div>
          <div class="item-after">杜蕾斯</div>
        </div>
      </li>
      <li class="item-content item-link">
        <div class="item-media"><i class="icon icon-f7"></i></div>
        <div class="item-inner">
          <div class="item-title">型号</div>
          <div class="item-after">极致超薄型</div>
        </div>
      </li>
    </ul>
  </div>
</div>

其中:

  • item-content - item-mediaitem-inner的主要弹性(flex)容器。必选元素。
  • item-media - 媒体元素(如图标,图片等)的容器。可选元素。
  • item-inner - item-titleitem-after的主要弹性(flex)容器。必选元素。
  • item-title - 单行列表项目标题。必选元素。
  • item-after - 列表项目标签。可以包含任意额外的html元素(例如标签文本、徽章、switch/toggle、按钮等等)。可选元素。

.item-content 上加上 .item-link 会增加一个向右的箭头。

联系人列表(Contacts List)

联系人列表用来展示个人的联系方式。

联系人列表是分组列表(Grouped Lists)的一个特殊的类型,主要有2点不同:

  • 列表区域元素(“list-block”)需要带上额外的“contacts-block”类
<header class="bar bar-nav">
  <h1 class="title">联系人列表</h1>
</header>
<div class="content">
  <div class="list-block contacts-block">
    <div class="list-group">
      <ul>
        <li class="list-group-title">A</li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题1</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题2</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题3</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题4</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题5</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题6</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题7</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题8</div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    <div class="list-group">
      <ul>
        <li class="list-group-title">B</li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题1</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题2</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题3</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题4</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题5</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题6</div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    <div class="list-group">
      <ul>
        <li class="list-group-title">C</li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题1</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题2</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题3</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题4</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题5</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题6</div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题7</div>
            </div>
          </div>
        </li>
      </ul>
    </div>
    <div class="list-group">
      <ul>
        <li class="list-group-title">V</li>
        <li>
          <div class="item-content">
            <div class="item-inner">
              <div class="item-title">标题1</div>
            </div>
          </div>
        </li>
      </ul>
    </div>
  </div>
</div>

多媒体列表(Media List View)

多媒体列表是列表(list view)的扩展,它是为了展示更复杂的数据比如产品,服务,用户等等。

当然,它的布局更为复杂:

<header class="bar bar-nav">
  <h1 class="title">多媒体列表</h1>
</header>
<div class="content">
  <div class="content-block-title">曲目</div>
  <div class="list-block media-list">
    <ul>
      <li>
        <a href="#" class="item-link item-content">
          <div class="item-media"><img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" style='width: 4rem;'></div>
          <div class="item-inner">
            <div class="item-title-row">
              <div class="item-title">标题</div>
              <div class="item-after">$15</div>
            </div>
            <div class="item-subtitle">标题</div>
            <div class="item-text">此处是文本内容...</div>
          </div>
        </a>
      </li>
    </ul>
  </div>
  <div class="content-block-title">邮件应用</div>
  <div class="list-block media-list">
    <ul>
      <li>
        <a href="#" class="item-link item-content">
          <div class="item-inner">
            <div class="item-title-row">
              <div class="item-title">Facebook</div>
              <div class="item-after">17:14</div>
            </div>
            <div class="item-subtitle">子标题</div>
            <div class="item-text">此处是文本内容...</div>
          </div>
        </a>
      </li>
    </ul>
  </div>
  <div class="content-block-title">简单列表</div>
  <div class="list-block media-list">
    <ul>
      <li>
        <div class="item-content">
          <div class="item-media"><img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" style='width: 2.2rem;'></div>
          <div class="item-inner">
            <div class="item-title-row">
              <div class="item-title">标题</div>
            </div>
            <div class="item-subtitle">子标题</div>
          </div>
        </div>
      </li>
    </ul>
  </div>
  <div class="content-block-title">嵌入式</div>
  <div class="list-block media-list inset">
    <ul>
      <li>
        <a href="#" class="item-link item-content">
          <div class="item-media"><img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" style='width: 2.2rem;'></div>
          <div class="item-inner">
            <div class="item-title-row">
              <div class="item-title">标题</div>
            </div>
            <div class="item-subtitle">子标题</div>
          </div>
        </a>
      </li>
    </ul>
  </div>
</div>

其中:

  • item-mediaitem-inner的主要弹性(flex)容器。必选元素。
  • item-media - 媒体元素(如图标,图片等)的容器. 可选元素。
  • item-inner - item-titleitem-after的主要弹性(flex)容器。必选元素。
  • item-title-row - item-titleitem-after的主要弹性(flex)容器。必选元素。
  • item-title - 单行列表项目标题。可选元素。
  • item-after - 列表项目标签。可以包含任意额外的html元素(例如标签文本、徽章、switch/toggle、按钮等等)。可选元素。
  • item-subtitle - 额外的单行标题。可选元素。
  • item-text - 额外的两行布局的容器,用来放置细节描述。可选元素。

可选择列表

列表可以支持单选和多选,我们只是修改了 checkboxradio 的样式,并没有进行任何JS操作。所以如果取数据,需要从其中隐藏的 input 元素中取,和原生的表单用法完全一样。

列表是单选还是多选,完全取决于 inputtype 属性设置。目前我们对单选和多选的图标样式是没有做区分的,后续可能会设置不同的样式以区分单选和多选。

<ul>
  <li>
    <label class="label-checkbox item-content">
      <input type="radio" name="my-radio">
      <div class="item-media"><i class="icon icon-form-checkbox"></i></div>
      <div class="item-inner">
        <div class="item-title-row">
          <div class="item-title">石头</div>
          <div class="item-after">17:14</div>
        </div>
        <div class="item-subtitle">New messages from John Doe</div>
        <div class="item-text">Lorem ipsum dolor sit amet...</div>
      </div>
    </label>
  </li>
  <li>
    <label class="label-checkbox item-content">
      <input type="radio" name="my-radio">
      <div class="item-media"><i class="icon icon-form-checkbox"></i></div>
      <div class="item-inner">
        <div class="item-title-row">
          <div class="item-title">剪刀</div>
          <div class="item-after">17:14</div>
        </div>
        <div class="item-subtitle">New messages from John Doe</div>
        <div class="item-text">Lorem ipsum dolor sit amet...</div>
      </div>
    </label>
  </li>
</ul>

因为选择操作是由原生的 input 实现的,所以只需要把上面的代码中的 input 元素的 type="radio" 改成 type="checkbox" 就可以变成多选。

卡片(Cards)

伴随着列表视图,卡片是一种很好的方法来控制和组织你的信息。卡片含有独特的相关数据,例如,照片,文字和所有关于一个主题的链接。卡片通常是更复杂的和详细的信息的一个切入点。

<header class="bar bar-nav">
  <h1 class="title">卡片</h1>
</header>
<div class="content">
  <div class="content-block-title">简单卡片</div>
  <div class="card">
    <div class="card-content">
      <div class="card-content-inner">这是一个用纯文本的简单卡片。但卡片可以包含自己的页头,页脚,列表视图,图像,和里面的任何元素。</div>
    </div>
  </div>
  <div class="card">
    <div class="card-header">卡头</div>
    <div class="card-content">
      <div class="card-content-inner">头和尾的卡片。卡头是用来显示一些额外的信息,或自定义操作卡标题和页脚。</div>
    </div>
    <div class="card-footer">卡脚</div>
  </div>
  <div class="card">
    <div class="card-content">
      <div class="card-content-inner">这是一个用纯文本的简单卡片。但卡片可以包含自己的页头,页脚,列表视图,图像,和里面的任何元素。</div>
    </div>
  </div>
  <div class="content-block-title">风格卡片</div>
  <div class="card demo-card-header-pic">
    <div valign="bottom" class="card-header color-white no-border no-padding">
      <img class='card-cover' src="//gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" alt="">
    </div>
    <div class="card-content">
      <div class="card-content-inner">
        <p class="color-gray">发表于 2015/01/15</p>
        <p>此处是内容...</p>
      </div>
    </div>
    <div class="card-footer">
      <a href="#" class="link"></a>
      <a href="#" class="link">更多</a>
    </div>
  </div>
  <div class="content-block-title">Facebook卡片</div>
  <div class="card facebook-card">
    <div class="card-header no-border">
      <div class="facebook-avatar"><img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" width="34" height="34"></div>
      <div class="facebook-name">夜萧</div>
      <div class="facebook-date">星期一 3:47pm</div>
    </div>
    <div class="card-content"><img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" width="100%"></div>
    <div class="card-footer no-border">
      <a href="#" class="link"></a>
      <a href="#" class="link">评论</a>
      <a href="#" class="link">分享</a>
    </div>
  </div>
  <div class="content-block-title">列表视图卡片</div>
  <div class="card">
    <div class="card-content">
      <div class="list-block">
        <ul>
          <li>
            <a href="#" class="item-link item-content">
              <div class="item-media"><i class="icon icon-f7"></i></div>
              <div class="item-inner">
                <div class="item-title">链接 1</div>
              </div>
            </a>
          </li>
        </ul>
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header">新的公布:</div>
    <div class="card-content">
      <div class="list-block media-list">
        <ul>
          <li class="item-content">
            <div class="item-media">
              <img src="http://gqianniu.alicdn.com/bao/uploaded/i4//tfscom/i3/TB10LfcHFXXXXXKXpXXXXXXXXXX_!!0-item_pic.jpg_250x250q60.jpg" width="44">
            </div>
            <div class="item-inner">
              <div class="item-title-row">
                <div class="item-title">标题</div>
              </div>
              <div class="item-subtitle">子标题</div>
            </div>
          </li>
        </ul>
      </div>
    </div>
    <div class="card-footer">
      <span>2015/01/15</span>
      <span>5 评论</span>
    </div>
  </div>            
</div>

卡片列表视图

可以用卡片在列表视图中有用的元素,在这种情况下就可以使用搜索栏,虚拟列表和列表视图功能卡片。在这种情况下我们需要添加额外的卡片列表类<div class="list-block">

  <header class="bar bar-nav">
    <h1 class="title">列表卡片</h1>
  </header>
  <div class="content">
    <div class="list-block cards-list">
      <ul>
        <li class="card">
          <div class="card-header">卡头</div>
          <div class="card-content">
            <div class="card-content-inner">卡内容</div>
          </div>
          <div class="card-footer">卡脚</div>
        </li>
        <li class="card">
          <div class="card-header">卡头</div>
          <div class="card-content">
            <div class="card-content-inner">卡内容</div>
          </div>
          <div class="card-footer">卡脚</div>
        </li>
        <li class="card">
          <div class="card-header">卡头</div>
          <div class="card-content">
            <div class="card-content-inner">卡内容</div>
          </div>
          <div class="card-footer">卡脚</div>
        </li>
      </ul>
    </div>
  </div>
  

滚动条

因为部分低版本安卓机型上,如果一个容器通过 position: absolute; 或者 transform: translate3d(x,x,x); 定位,那么在滚动的时候有可能会出现闪烁问题。

为了解决这种bug,我们实现了原生滚动和JS滚动条两种模式,并且可以自由切换。从 v0.3.1 版本开始,默认的滚动条类型就是 "native" ,即默认使用系统原生滚动条。只有当你发现页面存在滚动闪烁的问题无法解决时,才建议使用 js 滚动条。

为了保证页面在任何滚动条模式下都能使用,强烈建议在任何导致页面高度变化的操作之后都要执行一次 $.refreshScroller() 操作。否则在js滚动条模式下可能会导致页面没有重现计算高度而无法滚动。

    <header class="bar bar-nav">
        <h1 class="title">滚动条</h1>
    </header>
    <div class="content">
        <div class="card">
            <div class="card-header">滚动方式</div>
            <div class="card-content">
                <div class="card-content-inner">
                    <h3>滚动具有三种模式:</h3>
                    <ul>
                        <li>1. auto模式: scroller.js 根据系统版本号来决定什么时候使用js的滚动(默认)</li>
                        <li>2. js模式: 总是使用js滚动(即IScroll)</li>
                        <li>3. native模式: 总是使用原生滚动条</li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="card">
            <div class="card-header">滚动方式</div>
            <div class="card-content">
                <div class="card-content-inner">
                    <h3>滚动具有三种模式:</h3>
                    <ul>
                        <li>1. auto模式: scroller.js 根据系统版本号来决定什么时候使用js的滚动(默认)</li>
                        <li>2. js模式: 使用js滚动</li>
                        <li>3. native模式: 总是使用原生滚动条</li>
                    </ul>
                </div>
            </div>
        </div>
        <div class="card">
            <div class="card-header">滚动方式</div>
            <div class="card-content">
                <div class="card-content-inner">
                    <h3>滚动具有三种模式:</h3>
                    <ul>
                        <li>1. auto模式: scroller.js 根据系统版本号来决定什么时候使用js的滚动(默认)</li>
                        <li>2. js模式: 使用js滚动</li>
                        <li>3. native模式:总是使用原生滚动条</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    

js 模式是为了解决一些原生滚动条下很难解决的问题。如果你的页面内容比较简单,没有用到幻灯片、滑动删除等复杂的组件,完全不需要使用 js 模式。并且JS模式滚动性能是比原生滚动条差的。

注意,在 js 模式下,或者 auto模式自动切换到js模式下,如果你的 .content 中不存在 .content-inner,那么JS滚动条会自动增加一个 .content-inner容器用来滚动页面,这会导致 .content 中所有的元素都被重写一遍,这个重写操作是在 pageInit 事件触发之前就完成了。你可以自己在 .content 容器下面再套一层 .content-inner容器来防止重写html。

滚动条初始化

一般情况下你不需要自行初始化滚动条,因为 $.init()方法会自动初始化滚动条。如果你希望自行初始化,可以这样:

 
$(function() {
    $(".content").scroller({
        type: 'js'
    });
});   
    

滚动的方式可以通过配置项 type 来进行配置:

  • 1. auto: ios版本小于6.0.0和android版本小于4.4.0使用js滚动,其他使用native的滚动条
  • 2. js: 都使用js的滚动条,不建议选择此选项
  • 3. native: 直接使用native的滚动条,如果页面没有复杂的布局(比如 position: absolute或者 translate3D)那么可以选择此类型

上边demo使用的是javascript接口的调用方式,scroller.js 同时提供data-api的模式。通过添加标签属性 data-toggle="scroller"。 滚动类型通过:data-type="auto"来配置。

你可以在 .content 容器上通过 data-type='native' 指定在当前页面使用原生滚动条。

注意: scroller 插件会页面载入完成后,默认初始化带有class.content或者属性data-toggle="scroller"的元素为auto模式的滚动条。如果想要.content的元素全部初始为js的模式,需要在.content 标签加上属性data-type="js"

重置滚动

在js模式下,滚动区域高度发生变化时,需要对滚动条进行刷新,scroller 提供两种方式来进行刷新:

1. 局部刷新,只针对某个容器的刷新

 
$(function() {
    $(".content").scroller('refresh');
});   
    

2. 全局刷新,会刷新页面上所有的滚动条

 
$(function() {
    $.refreshScroller();
});   
    

滚动接口

scroller插件重置的了zepto的滚动方法,无论在js模式下或者native模式下都是一样的调用方式:

 
$(function() {
    $('.content').scrollTop(); //==> number
    $('.content').scrollTop(number); // ==>self
    $('.content').scrollLeft(); //==> number
    $('.content').scrollLeft(number); // ==>self
});   
    

滚动事件

滚动条提供三个事件:
  • 1. scrollStart: 滚动开始时触发(目前只能在js模式下,才会触发)
  • 2. scroll: 滚动中触发
  • 3. scrollEnd: 滚动结束后触发(目前只能在js模式下,才会触发)

直接通过下边的方式进行监听

 
$(function() {
    $(".content").on('scrollStart',function(){
     //dosomething
    });
});   
    

下拉刷新

下拉刷新是一个特别的组件,可以用来初始化页面内容的刷新。

下拉刷新的demo

HTML:

下拉刷新

card
这里是第1个card,下拉刷新会出现第2个card。
<header class="bar bar-nav">
    <h1 class='title'>下拉刷新</h1>
</header>
<!-- content应该拥有"pull-to-refresh-content"类,表示启用下拉刷新 -->
<div class="content pull-to-refresh-content" data-ptr-distance="55">
    <!-- 默认的下拉刷新层 -->
    <div class="pull-to-refresh-layer">
        <div class="preloader"></div>
        <div class="pull-to-refresh-arrow"></div>
    </div>
    <!-- 下面是正文 -->
    <div class="card-container">
        <div class="card">
            <div class="card-header">card</div>
            <div class="card-content">
                <div class="card-content-inner">
                    这里是第1个card,下拉刷新会出现第2个card。
                </div>
            </div>
        </div>
    </div>
</div>

javascript:

// 添加'refresh'监听器
$(document).on('refresh', '.pull-to-refresh-content',function(e) {
    // 模拟2s的加载过程
    setTimeout(function() {
        var cardNumber = $(e.target).find('.card').length + 1;
        var cardHTML = '<div class="card">' +
                          '<div class="card-header">card'+cardNumber+'</div>' +
                          '<div class="card-content">' +
                            '<div class="card-content-inner">' +
                                '这里是第' + cardNumber + '个card,下拉刷新会出现第' + (cardNumber + 1) + '个card。' +
                            '</div>' +
                          '</div>' +
                      '</div>';

        $(e.target).find('.card-container').prepend(cardHTML);
        // 加载完毕需要重置
        $.pullToRefreshDone('.pull-to-refresh-content');
    }, 2000);
});

其中

  • content需要额外添加pull-to-refresh-content类,它会开启下拉刷新。
  • pull-to-refresh-layer平时隐藏的布局块,包含下拉刷新的可视元素:加载提示符和上/下箭头。
  • data-ptr-distance="55"可以配置下拉刷新的下拉距离. 默认是 44px.

下拉刷新的行为顺序

当用户开始下拉的时候, pull-to-refresh-layer会增加一个额外的 pull-down 类。

当用户下拉使pull-to-refresh-content元素下降超过44px时(即pull-to-refresh-layer元素完全可视),pull-to-refresh-layer元素将自动添加"pull-up"类,使箭头转向180度,以提醒用户界面将在他松开手指时刷新。

当用户在“pull-up”状态释放下拉区块使页面刷新时,pull-to-refresh-layer区块将会添加一个"refreshing"类。在“refreshing”状态,箭头将会隐藏,同时会展现一个加载提示符。这个时候你通常需要进行Ajax异步请求并刷新页面内容。

下拉刷新事件

以下是下拉刷新的特殊事件,用以帮助我们识别需要刷新界面的时机:

事件(Event) 对象(Target) 描述(Description)
refresh 拥有下拉刷新功能的界面
事件会在下拉刷新进入“refreshing”状态时触发

重置下拉刷新

在我们刷新页面内容之后,需要重置下拉刷新组件,以使用户可以再次下拉:

$.pullToRefreshDone(ptrContent) // 重置特定的下拉刷新界面

//ptrContent  我们想要重置的下拉刷新页面的HTML元素或CSS选择器

JS触发下拉刷新

我们也可以通过下面的方法手工触发下拉刷新:

$.pullToRefreshTrigger(ptrContent) //触发特定界面的下拉刷新

ptrContent //我们想要触发的下拉刷新页面的HTML元素或CSS选择器

销毁/禁用下拉刷新

有的时候你可能需要禁用下拉刷新。我们可以通过这个方法来做到:

$.destroyPullToRefresh(ptrContent) //销毁/禁用 下拉刷新

ptrContent // HTMLElement or string (CSS 选择器) 我们需要销毁/禁用的下拉刷新

我们可以再次初始化/启用它:

$.initPullToRefresh(ptrContent) - 初始化/启用下拉刷新

ptrContent - HTMLElement or string (with CSS Selector) 需要启用的下拉刷新

无限滚动

无限滚动用来在页面滚动到接近底部时加载新内容或进行其他操作。

在底部的无限滚动

你只需在可滚动的容器上添加“infinite-scroll”类,一般是页面滚动区域 - div.content

      <style type="text/css">
      .infinite-scroll-preloader {
        margin-top:-20px;
      }
      </style>

      <header class="bar bar-nav">
          <h1 class="title">底部无限滚动</h1>
      </header>
      <!-- 添加 class infinite-scroll 和 data-distance  向下无限滚动可不加infinite-scroll-bottom类,这里加上是为了和下面的向上无限滚动区分-->
      <div class="content infinite-scroll infinite-scroll-bottom" data-distance="100">
          <div class="list-block">
              <ul class="list-container">
              </ul>
          </div>
          <!-- 加载提示符 -->
          <div class="infinite-scroll-preloader">
              <div class="preloader"></div>
          </div>
      </div>
    

其中:

  • div class="content infinite-scroll" -是我们无限滚动的容器
  • data-distance - 属性用来配置页面滚动到离底部多远时触发无限滚动事件,默认是50 (px)

javacript:

      // 加载flag
      var loading = false;
      // 最多可加载的条目
      var maxItems = 100;

      // 每次加载添加多少条目
      var itemsPerLoad = 20;

      function addItems(number, lastIndex) {
              // 生成新条目的HTML
              var html = '';
              for (var i = lastIndex + 1; i <= lastIndex + number; i++) {
                  html += '<li class="item-content"><div class="item-inner"><div class="item-title">Item ' + i + '</div></div></li>';
              }
              // 添加新条目
              $('.infinite-scroll-bottom .list-container').append(html);

          }
          //预先加载20条
      addItems(itemsPerLoad, 0);

      // 上次加载的序号

      var lastIndex = 20;

      // 注册'infinite'事件处理函数
      $(document).on('infinite', '.infinite-scroll-bottom',function() {

          // 如果正在加载,则退出
          if (loading) return;

          // 设置flag
          loading = true;

          // 模拟1s的加载过程
          setTimeout(function() {
              // 重置加载flag
              loading = false;

              if (lastIndex >= maxItems) {
                  // 加载完毕,则注销无限加载事件,以防不必要的加载
                  $.detachInfiniteScroll($('.infinite-scroll'));
                  // 删除加载提示符
                  $('.infinite-scroll-preloader').remove();
                  return;
              }

              // 添加新条目
              addItems(itemsPerLoad, lastIndex);
              // 更新最后加载的序号
              lastIndex = $('.list-container li').length;
              //容器发生改变,如果是js滚动,需要刷新滚动
              $.refreshScroller();
          }, 1000);
      });
  

无限滚动事件

事件(Event) 对象(Target) 描述(Description)
infinite 可无限滚动的容器 div.content.infinite-scroll" 事件会在页面滚动至距底部还有特定距离(可在data-distance中配置)时触发

无限滚动API

有2个App方法:

      $.attachInfiniteScroll(container) - 为指定的HTML元素容器添加无限滚动事件监听器
      parameters - 表示无限滚动容器的HTML元素或CSS选择器。必选。

    
      $.detachInfiniteScroll(container) - 从指定的HTML元素容器删除无限滚动事件监听器
      parameters - 表示无限滚动容器的HTML元素或CSS选择器。必选。

    

注意,仅在你使用$.detachInfiniteScroll方法删除过事件监听器后,才可能需要使用 $.attachInfiniteScroll方法,因为无限滚动组件的事件监听器会在“initPage”时被自动添加。

在顶部的无限滚动

如果你需要向上滚动到顶部时进行无限滚动,那么需要在 “content”添加额外的class infinite-scroll-top

    <header class="bar bar-nav">
        <h1 class="title">在顶部的无限滚动</h1>
    </header>
    <div class="content infinite-scroll infinite-scroll-top" data-distance="50">
        <div class="list-block">
          <ul class="list-container">
           
          </ul>
        </div>

        <!-- 加载提示符 -->
        <div class="infinite-scroll-preloader" >
          <div class="preloader">
          </div>
        </div>
    </div>      
  

javacript:

       $(function() {
          // 最多可加载的条目
          var maxItems = 100;

          // 每次加载添加多少条目
          var itemsPerLoad = 20;

          function addItemsTop(number, lastIndex) {
            // 生成新条目的HTML
            var html = '';
            for (var i = lastIndex+ number; i > lastIndex ; i--) {
              html += '<li class="item-content"><div class="item-inner"><div class="item-title">条目'+i+'</div></div></li>';
            }
            // 添加新条目
            $('.infinite-scroll .list-container').prepend(html);

          }
          var timer = false;
          $(document).on('infinite', '.infinite-scroll-top',function() {
            var lastIndex = $('.infinite-scroll-top .list-block li').length;
            var lastLi = $(".list-container li")[0];
            var scroller = $('.infinite-scroll-top');
            var scrollHeight = scroller[0].scrollHeight; // 获取当前滚动元素的高度
            // 如果正在加载,则退出
            if (timer) {
              clearTimeout(timer);
            }

            // 模拟1s的加载过程
            timer = setTimeout(function() {

              addItemsTop(itemsPerLoad,lastIndex);
             
              $.refreshScroller();
             
              // 将滚动条的位置设置为最新滚动元素高度和之前的高度差
              scroller.scrollTop(scroller[0].scrollHeight - scrollHeight);
            }, 1000);
          });
      })
  

多个标签页下的无限滚动

一个页面的多个标签中可单独初始化infinite-scroll,在需要无限滚动的tab上加"infinite-scroll"

  <div class="content" data-type="">
    <p>其他内容区域</p>
    <p>其他内容区域</p>
    ...
    <p>其他内容区域</p>
    <div class="buttons-tab fixed-tab" data-offset="44">
      <a href="#tab1" class="tab-link active button">全部</a>
      <a href="#tab2" class="tab-link button">待付款</a>
      <a href="#tab3" class="tab-link button">待发货</a>
    </div>

    <div class="tabs">
      <div id="tab1" class="tab active">
        <div class="content-block">
          <div class="buttons-row">
            <a href="#tab1-1" class="tab-link active button">Tab 1</a>
            <a href="#tab1-2" class="tab-link button">Tab 2</a>
            <a href="#tab1-3" class="tab-link button">Tab 3</a>
          </div>
          <div class="tabs">
            <p class='tab active' id='tab1-1'>This is tab 1-1 content</p>
            <p class='tab' id='tab1-2'>This is tab 1-2 content</p>
            <p class='tab' id='tab1-3'>13855589778</p>
          </div>
        </div>
      </div>
      <div id="tab2" class="tab infinite-scroll">
          <div class="list-block">
            <ul class="list-container">
              <li class="item-content"><div class="item-inner"><div class="item-title">条目</div></div></li>
             ....
              <li class="item-content"><div class="item-inner"><div class="item-title">条目</div></div></li>
            </ul>
          </div>
          <!-- 加载提示符 -->
          <div class="infinite-scroll-preloader">
            <div class="preloader">
            </div>
          </div>
      </div>
      <div id="tab3"  class="tab infinite-scroll">
          <div class="list-block">
            <ul class="list-container">
              <li class="item-content"><div class="item-inner"><div class="item-title">条目</div></div></li>
             ....
              <li class="item-content"><div class="item-inner"><div class="item-title">条目</div></div></li>
            </ul>
          </div>
          <!-- 加载提示符 -->
          <div class="infinite-scroll-preloader">
            <div class="preloader">
            </div>
          </div>
      </div>
    </div>
  </div>

javacript:

  $(document).on("pageInit", function() {
      //多个标签页下的无限滚动
      var loading = false;
      // 每次加载添加多少条目
      var itemsPerLoad = 20;
      // 最多可加载的条目
      var maxItems = 100;
      var lastIndex = $('.list-container li')[0].length;
      function addItems(number, lastIndex) {
        // 生成新条目的HTML
        var html = '';
        for (var i = lastIndex + 1; i <= lastIndex + number; i++) {
          html += '<li class="item-content" onClick="alert(1)"><div class="item-inner"><div class="item-title">新条目</div></div></li>';
        }
        // 添加新条目
        $('.infinite-scroll.active .list-container').append(html);
      }
      $(page).on('infinite', function() {
        // 如果正在加载,则退出
        if (loading) return;
        // 设置flag
        loading = true;
        var tabIndex = 0;
        if($(this).find('.infinite-scroll.active').attr('id') == "tab2"){
          tabIndex = 0;
        }
        if($(this).find('.infinite-scroll.active').attr('id') == "tab3"){
          tabIndex = 1;
        }
        lastIndex = $('.list-container').eq(tabIndex).find('li').length;
        // 模拟1s的加载过程
        setTimeout(function() {
          // 重置加载flag
          loading = false;
          if (lastIndex >= maxItems) {
            // 加载完毕,则注销无限加载事件,以防不必要的加载:$.detachInfiniteScroll($('.infinite-scroll').eq(tabIndex));多个无线滚动请自行根据自己代码逻辑判断注销时机
            // 删除加载提示符
            $('.infinite-scroll-preloader').eq(tabIndex).hide();
            return;
          }
          addItems(itemsPerLoad,lastIndex);
          // 更新最后加载的序号
          lastIndex =  $('.list-container').eq(tabIndex).find('li').length;
          $.refreshScroller();
        }, 1000);
      });
  });

图标

使用iconfont的图标

<div class="content-padded docs-icons">
  <span class="icon icon-app"></span>
  <span class="icon icon-browser"></span>
  <span class="icon icon-card"></span>
  <span class="icon icon-cart"></span>
  <span class="icon icon-code"></span>
  <span class="icon icon-computer"></span>
  <span class="icon icon-remove"></span>
  <span class="icon icon-download"></span>
  <span class="icon icon-edit"></span>
  <span class="icon icon-emoji"></span>
  <span class="icon icon-star"></span>
  <span class="icon icon-friends"></span>
  <span class="icon icon-gift"></span>
  <span class="icon icon-phone"></span>
  <span class="icon icon-clock"></span>
  <span class="icon icon-home"></span>
  <span class="icon icon-menu"></span>
  <span class="icon icon-message"></span>
  <span class="icon icon-me"></span>
  <span class="icon icon-picture"></span>
  <span class="icon icon-share"></span>
  <span class="icon icon-settings"></span>
  <span class="icon icon-refresh"></span>
  <span class="icon icon-caret"></span>
  <span class="icon icon-down"></span>
  <span class="icon icon-up"></span>
  <span class="icon icon-right"></span>
  <span class="icon icon-left"></span>
  <span class="icon icon-check"></span>
  <span class="icon icon-search"></span>
</div>

夜间模式

现在我们提供一个夜间模式,你只需要在 body 或者 .page 或者 .content 上加上 .theme-dark。它和其中所有子元素都会变成夜间模式。

你也可以单独给 .bar 加上 .theme-dark,这样可以单独使标题栏或者工具栏变成夜间模式。

夜间模式最大的区别是他的背景变成了黑色,而前景色变成了白色。

夜间模式还处在测试阶段,可能会有某些组件在夜间模式下显示不正常。有任何问题都可以及时在旺旺群中反馈。

下一节是介绍颜色主题的用法,颜色主题主要是改变前景色,可以和 .theme-dark 结合使用以在夜间模式下实现不同的颜色。

设备侦测工具

$.device提供了一些基本的设备侦测信息可供使用。举例如下:

console.log($.device)
// --------
{
    android: true
    androidChrome: false
    ios: false
    ipad: false
    iphone: false
    isWeixin: false
    os: "android"
    osVersion: "4.4.1"
    pixelRatio: 3
    statusBar: false
    webView: null
}

同时提供$.compareVersion工具用以方便的进行版本号比较:

// arg1 > arg2, return 1; arg1 == arg2, return 0; arg1 < arg2, return -1
$.compareVersion('8.0', '7.1.1')
// return 1
$.compareVersion('4.2', $.device.osVersion)
// return -1
$.compareVersion('5.0', '5.0')
// return 0