display:talbe table-row table-cell 的区别

1、当设置display:table;时,table的padding设置会失效
2、当设置display:table-row;时,margin和padding设置会失效。
3、当设置display:table-cell;时,margin设置会失效。

为表格设置合并边框模型:

  1. border-collapse:collapse;


text-indent

text-indent 属性能定义一个块元素首行文本内容之前的缩进量

setSelectionRange()
HTMLInputElement.setSelectionRange 方法用于设定<input><textarea> 元素中当前选中文本的起始和结束位置。

HTMLInputElement.select()
HTMLInputElement.select() 方法选中一个 <textarea> 元素或者一个带有 text 字段的 <input> 元素里的所有内容。

event.type
只读属性 Event.type 会返回一个字符串, 表示该事件对象的事件类型。

后台管理实战

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>后台管理列表</title>
    <link rel="stylesheet" href="">
    <link rel="stylesheet" href="css/icons.min.css" />
    <link rel="stylesheet" href="css/common.css" />
    <link rel="stylesheet" href="css/index.css" />
</head>
<body>
    <div class="list-wrap">
        <table class="list-tb">
            <caption><h1>腾讯课堂课程管理系统</h1></caption>
            <thead>
                <tr>
                    <td colspan="6">
                        <ul class="nav-list J_nav clearfix">
                            <li class="nav-item active" data-field="manage">
                                <a href="javascript:;" class="nav-lk">列表管理</a>
                            </li>
                            <li class="nav-item" data-field="trash">
                                <a href="javascript:;" class="nav-lk">垃圾箱</a>
                            </li>
                            <li class="nav-item" data-field="search">
                                <a href="javascript:;" class="nav-lk">课程搜索</a>
                            </li>
                        </ul>
                    </td>
                </tr>
                <tr class="J_searchRow search-row">
                    <td colspan="6" class="search-cell">
                        <div class="search-wrap">
                            <span class="fa fa-search"></span>
                            <input type="text" id="J_searchInput" class="search-input" placeholder="课程搜索" />
                        </div>
                    </td>
                </tr>
                <tr class="field-tt">
                    <th>ID</th>
                    <th>课程名称</th>
                    <th>课时数</th>
                    <th>任课老师</th>
                    <th>课程类型</th>
                    <th>课程操作</th>
                </tr>
                <tr class="J_tipRow tip-row">
                    <td colspan="6" class="warning-tip J_warningTip">- 暂无数据 -</td>
                </tr>
            </thead>
            <tbody class="J_courseList"></tbody>
            <tfoot>
                <tr class="page-btn-row J_pageBtnRow">
                    <td colspan="6">
                        <ul class="page-btn-list J_pageBtnList clearfix"></ul>
                    </td>
                </tr>
            </tfoot>
        </table>
    </div>
<!-- 渲染课程列表 -->
    <script type="text/html" id="J_listItemTpl">
        <tr>
            <td>{{id}}</td>
            <td class="course-name-cell">
                <!-- span框与修改的输入框 -->
                <span class="course-name">{{course}}</span>
                <input type="text" data-id="{{id}}" class="course-name-input" value="{{course}}" />
            </td>
            <td>{{hour}}小时</td>
            <td>{{teacher}}老师</td>
            <td>{{field}}</td>
            <td><button data-id="{{id}}" class="list-btn {{type}}">{{typeText}}</button></td>
        </tr>
    </script>
    <!-- 渲染页码列表 -->
    <script type="text/html" id="J_pageBtnItemTpl">
        <li class="btn-item {{isCur}}">
            <a href="javascript:;" class="page-btn">{{pageNum}}</a>
        </li>
    </script>

  <script src="js/utils.js"></script>
    <script src="js/index.js"></script>
</body>
</html>
.list-wrap {
    width: 1000px;
    margin: 100px auto;
}

.list-tb {
    width: 100%;
    border: 1px solid #ccc;
    border-collapse: collapse;
}

.list-tb caption {
    height: 60px;
}

.list-tb tr {
    height: 44px;
}

.list-tb td,
.list-tb th {
    position: relative;
    border-bottom: 1px solid #ccc;
    text-align: center;
}

.list-tb .field-tt {
    background-color: #eee;
}

.list-tb td .nav-item {
    float: left;
    width: 130px;
    height: 30px;
    margin: auto 15px;
    background-color: #ddd;
    text-align: center;
    line-height: 30px;
}

.list-tb td .nav-item .nav-lk {
    display: block;
    height: 100%;
    color: #999;
}

.list-tb td .nav-item.active .nav-lk {
    color: #fff;
    background-color: #000;
}

/* 课程搜索框默认隐藏 */
.list-tb .search-row {
    display: none;
}

.list-tb .search-row.show {
    display: table-row;
}

.list-tb .search-cell .search-wrap {
    position: relative;
    width: 300px;
    height: 30px;
}

.list-tb .search-cell .search-wrap .fa {
    position: absolute;
    left: 25px;
    top: 5px;
}

.list-tb .search-cell .search-input {
    width: 100%;
    height: 100%;
    margin-left: 15px;
    border: 1px solid #ddd;
    font-size: 16px;
    text-indent: 30px;
}

/* 暂无数据默认隐藏 */
.list-tb .tip-row.hide {
    display: none;
}

.list-tb .warning-tip {
    color: #999;
}

.list-tb .list-btn {
    height: 30px;
    padding: 0 15px;
    color: #fff;
    font-size: 14px;
}

.list-tb .list-btn.delete {
    background-color: red;
}

.list-tb .list-btn.regain {
    background-color: orange;
}

.list-tb .course-name-cell {
    text-align: left;
    padding-left: 15px;
}

.list-tb .course-name-input {
    display: none;
    position: absolute;
    top: 6px;
    left: 15px;
    width: 100%;
    height: 30px;
    border: 1px solid #ddd;
    text-indent: 10px;
    font-size: 14px;
}

/* 设置行内块的作用是为了跟前面的不换行跟前面的span元素设置为同一行 */
.list-tb .course-name-input.show {
    display: inline-block;
}

.list-tb .page-btn-row {
    display: none;
}

.list-tb .page-btn-row.show {
    display: table-row;
}

.list-tb .page-btn-list {
    width: 100%;
    margin-left: 15px;
}

.list-tb .btn-item {
    float: left;
    width: 60px;
    height: 100%;
}

.list-tb .btn-item .page-btn {
    display: block;
    width: 22px;
    height: 22px;
    background-color: #ddd;
    text-align: center;
    line-height: 22px;
    font-size: 14px;
}

/* 点击时的页码样式 */
.list-tb .btn-item.cur .page-btn {
    background-color: #000;
    color: #fff;
}
;
(function (doc) {

  var oNav = doc.getElementsByClassName('J_nav')[0],
    oNavItems = oNav.getElementsByClassName('nav-item'),
    oSearchRow = doc.getElementsByClassName('J_searchRow')[0],
    oWarningTip = doc.getElementsByClassName('J_tipRow')[0],
    oCourseList = doc.getElementsByClassName('J_courseList')[0],
    oSearchInput = doc.getElementById('J_searchInput'),
    oPageBtnRow = doc.getElementsByClassName('J_pageBtnRow')[0],
    oPageBtnList = doc.getElementsByClassName('J_pageBtnList')[0],
    oBtnItems = oPageBtnList.getElementsByClassName('btn-item'),
    oCourseInputs = oCourseList.getElementsByClassName('course-name-input'),
    oCourseSpans = oCourseList.getElementsByClassName('course-name'),

    listItemTpl = doc.getElementById('J_listItemTpl').innerHTML,
    pageBtnItemTpl = doc.getElementById('J_pageBtnItemTpl').innerHTML,

    oNavItemsLen = oNavItems.length,
    field = 'manage',
    pageNum = 0,
    // curId :选中的input的 data-id 属性 
    // curIdx 选中的input 在列表中的位置  用于定位与显示与input输入框同一位置的span标签  以及更新的信息
    curId = 0,
    curIdx = -1;

  var API = {
    getCourseList: 'http://localhost/api_for_study/index.php/List/getCourseListForManage',
    getSearchList: 'http://localhost/api_for_study/index.php/List/getSearchListForManage',
    doListItem: 'http://localhost/api_for_study/index.php/List/doListItemForManage',
    updateCourseName: 'http://localhost/api_for_study/index.php/List/updateCourseNameForManage'
  }

  var init = function () {
    getCourseList(field, pageNum);
    bindEvent();
  }

  function bindEvent() {
    oNav.addEventListener('click', navClick, false);
    oSearchInput.addEventListener('input', throttle(courseSearch, 1000), false);
    oPageBtnList.addEventListener('click', changePage, false);
    oCourseList.addEventListener('click', listClick, false);
  }

  // tab选项卡
  function navClick(e) {
    var e = e || window.event,
      tar = e.target || e.srcElement,
      className = tar.className;
    // 阻止事件的冒泡与捕获
    e.stopPropagation();

    if (className === 'nav-lk') {

      // 寻找a标签的父元素li标签
      var oParent = tar.parentNode,
        item;

      field = oParent.getAttribute('data-field');

      for (var i = 0; i < oNavItemsLen; i++) {
        // 循坏遍历tab的每一项
        item = oNavItems[i];
        // 取消所有tab的样式
        item.className = 'nav-item';
      }
      oParent.className += ' active';
      if (field === 'search') {
        showSearchInput(true);
        showWarningTip(true);
        showPageBtnRow(false);
        return;
      }
      getCourseList(field, pageNum);
    }
  }

  function courseSearch(e) {
    var e = e || window.event,
      val = this.value,
      valLen = val.length;
    if (valLen > 0) {
      getSearchList(val);
    } else {
      showWarningTip(true);
    }
  }

  // 是否显示搜索输入框
  function showSearchInput(show) {
    if (show) {
      oSearchRow.className += ' show';
    } else {
      oSearchRow.className = 'J_searchRow search-row';
      oSearchInput.value = ''
    }
  }

  // 是否显示数据 默认没数据
  function showWarningTip(show) {
    if (show) {
      oWarningTip.className = 'J_tipRow tip-row';
      oCourseList.innerHTML = '';
    } else {
      oWarningTip.className += ' hide';
    }
  }

  //是否显页码按钮组 默认隐藏
  function showPageBtnRow(show) {
    if (show) {
      oPageBtnRow.className += ' show';
    } else {
      oPageBtnRow.className = 'page-btn-row J_pageBtnRow';
    }
  }


  function _setDatas(field, data, pageCount, pageNum) {
    console.log(pageCount, pageNum);
    if (data && data.length > 0) {
      // 把模板渲染到指定oCourseList列表
      oCourseList.innerHTML = renderList(field, data);
      showWarningTip(false);

      if (pageCount > 1 && field !== 'search') {
        oPageBtnList.innerHTML = renderPageBtns(pageCount, pageNum);
        showPageBtnRow(true);
      } else {
        oPageBtnList.innerHTML = '';
        showPageBtnRow(false);
      }
      // 没有数据则显示暂无数据
    } else {
      showWarningTip(true);
    }
  }

  // 渲染列表
  function renderList(listField, data) {

    var list = '';

    data.forEach(function (elem) {
      list += listItemTpl.replace(/{{(.*?)}}/g, function (node, key) {
        return {
          id: elem.id,
          course: elem.course,
          hour: elem.hour,
          teacher: elem.teacher,
          field: elem.field,
          type: listField == 'trash' ? 'regain' : 'delete',
          typeText: listField == 'trash' ? '恢复' : "删除"
        } [key];
      });
    });
    return list;
  }

  function renderPageBtns(pageCount, pageNum) {
    var list = '';

    for (var i = 0; i < pageCount; i++) {
      list += pageBtnItemTpl.replace(/{{(.*?)}}/g, function (node, key) {
        return {
          pageNum: i + 1,
          isCur: i == pageNum && 'cur'
        } [key];
      });
    }
    return list;
  }

  //更改页面 
  function changePage(e) {
    var e = e || window.event,
      tar = e.target || e.srcElement,
      className = tar.className;

    e.stopPropagation();

    if (className === 'page-btn') {
      var oParent = tar.parentNode,
        oBtnItemsLen = oBtnItems.length,
        item;

      pageNum = [].indexOf.call(oBtnItems, oParent);
      console.log(oBtnItems, oParent, pageNum);
      // 遍历所有分页按钮还原成默认样式
      for (var i = 0; i < oBtnItemsLen; i++) {
        item = oBtnItems[i];
        item.className = 'btn-item';
      }
      // 给点击的按钮添加样式
      oParent.className += ' cur';
      getCourseList(field, pageNum);
    }
  }

  function listClick(e) {
    var e = e || window.event,
      tar = e.target || e.srcElement,
      className = tar.className,
      itemId = tar.getAttribute('data-id');
    e.stopPropagation();

    switch (className) {
      case 'list-btn delete':
        var c = confirm('确认删除');
        c && doListItem('remove', pageNum, itemId);
        break;
      case 'list-btn regain':
        var c = confirm('确认恢复');
        c && doListItem('regain', pageNum, itemId);
        break;
      case 'course-name':
        showInput(tar);
        break;
      default:
        break;
    }
  }


  // 请求课程列表
  // 传参请求页数 与点击的tab项目
  function getCourseList(field, pageNum) {

    showSearchInput(false);

    xhr.ajax({
      url: API.getCourseList,
      type: 'POST',
      dataType: 'JSON',
      data: {
        field: field,
        pageNum: pageNum
      },
      success: function (data) {
        var res = data.res,
          pageCount = data.pages;

        // 点击的具体项目名 具体的数据列表 总页数 与默认显示的页码
        _setDatas(field, res, pageCount, pageNum);
      },
      error: function () {
        alert('列表获取失败,请重试!');
      }
    });
  }

  function getSearchList(keyword) {
    xhr.ajax({
      url: API.getSearchList,
      type: 'POST',
      dataType: 'JSON',
      data: {
        keyword: keyword
      },
      success: function (data) {
        var res = data.res;
        _setDatas('manage', res);
      },
      error: function () {
        alert('搜索操作失败,请重试!');
      }
    })
  }

  // 删除或恢复数据 重新请求列表
  function doListItem(type, pageNum, itemId) {
    xhr.ajax({
      url: API.doListItem,
      type: 'POST',
      dataType: 'JSON',
      data: {
        type: type,
        pageNum: pageNum,
        itemId: itemId
      },
      success: function (data) {

        var res = data.res,
          pageCount = data.pages;
        _setDatas(field, res, pageCount, pageNum);
      },
      error: function () {
        alert('操作列表失败,请重试!');
      }
    })
  }

  function submitNewCourseName(curId, curIdx) {
    // 单击前确认隐藏所有input输入框 以及更新事件
    hideAllInputs();
    var newVal = oCourseInputs[curIdx].value,
      thisCourseSpan = oCourseSpans[curIdx];
    console.log(newVal, thisCourseSpan.innerHTML);
    if (newVal !== thisCourseSpan.innerHTML) {
      xhr.ajax({
        url: API.updateCourseName,
        type: 'POST',
        dataType: 'JSON',
        data: {
          itemId: curId,
          newVal: newVal
        },
        success: function (data) {
          // 如果成功则将输入框的值替换span标签的值
          if (data === 'success') {
            thisCourseSpan.innerHTML = newVal;
          } else {
            alert('更改课程名称失败,请重试');
          }
          curId = 0;
          curIdx = -1;
        },
        error: function () {
          alert('更改课程名称失败,请重试');
        }
      });
    }
  }

  function updateCourseName(e) {
    var e = e || window.event,
      eventType = e.type;
    // 如果是按键事件
    if (eventType === 'keyup') {
      var keyCode = e.keyCode;
      // 单击了回车键
      if (keyCode === 13) {
        submitNewCourseName(curId, curIdx);
      }
      return;
    }
    // 否则是其他事件例如单击click事件
    submitNewCourseName(curId, curIdx);
  }

  function showInput(target) {
    hideAllInputs();
    var oParent = target.parentNode,
      thisInput = oParent.getElementsByClassName('course-name-input')[0],
      thisInputLen = thisInput.value.length;
    curId = thisInput.getAttribute('data-id');
    // 查找点击的input在列表中对应的oCourseInputs中的位置
    curIdx = [].indexOf.call(oCourseInputs, thisInput);
    console.log(curId, curIdx);

    thisInput.className += ' show';
    // 将当前输入框设置焦点
    thisInput.focus();
    // 全选输入框输入的内容
    thisInput.setSelectionRange(0, thisInputLen);

    // 每次单击输入框时设置点击任何地方或是按回车则更新输入框内容
    document.addEventListener('click', updateCourseName, false);
    document.addEventListener('keyup', updateCourseName, false);
  }

  function hideAllInputs() {
    var inputsLen = oCourseInputs.length,
      item;
    for (var i = 0; i < inputsLen; i++) {
      item = oCourseInputs[i];
      item.className = 'course-name-input';
      // 取消所有input输入框的焦点
      item.blur();
    }
    // 每次单击输入框之前 移除点击任何地方或是按任意按键则更新输入框内容的事件
    document.removeEventListener('click', updateCourseName, false);

    document.removeEventListener('keyup', updateCourseName, false);
  }
  init();
})(document);