ajax插件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>图片瀑布流</title>
  6. <link rel="stylesheet" href="css/index.css" />
  7. </head>
  8. <body>
  9. <div class="wrap js_box"></div>
  10. <script src="js/utils.js"></script>
  11. <script src="js/index.js"></script>
  12. <script type="text/javascript">
  13. new Waterfall('js_box', {
  14. imgApi: 'server/index.php',
  15. column: 8,
  16. gap: 10
  17. }).init();
  18. </script>
  19. </body>
  20. </html>
;
(function (doc) {

  var Waterfall = function (wrapper, opt) {
    console.log(wrapper);
    this.oWrapper = doc.getElementsByClassName(wrapper)[0];
    this.column = opt.column;
    this.gap = opt.gap;
    this.imgApi = opt.imgApi;
    this.itemWidth = (this.oWrapper.offsetWidth - (this.column - 1) * this.gap) / this.column;
    this.pageNum = 0;
    this.pageSize = 0;
    this.heightArr = [];
  }

  Waterfall.prototype = {
    init: function () {
      this.getImgDatas(this.pageNum);
      this.bindEvent();
    },
    bindEvent: function () {
      console.log(this);
      // 这里的bindthis原因:scrollToBottom在Waterfall的原型链上 window要使用scrollToBottom 方法 必须绑定 scrollToBottom的this指向否则无法使用?
      window.addEventListener('scroll', this.scrollToBottom.bind(this), false);
    },

    scrollToBottom: function () {
      // 滚到底部页码+1
      if (getScrollTop() + getWindowHeight() == getScrollHeight()) {
        this.pageNum++;
        // 如果还有数据则再次渲染
        // 页码下标从0开始所以比较条件< 页数-1
        if (this.pageNum <= this.pageSize - 1) {
          this.getImgDatas(this.pageNum);
        }
      }
    },

    getImgDatas: function (pageNum) {
      var _self = this;

      xhr.ajax({
        url: this.imgApi,
        type: 'POST',
        dataType: 'JSON',
        data: {
          pageNum: pageNum
        },
        success: function (data) {
          if (data != 'NO DATA') {
            console.log(data);
            var pageData = JSON.parse(data.pageData);
            _self.pageSize = parseInt(data.pageSize);
            _self.renderList(pageData, _self.pageNum);
          }
        }
      })
    },
    renderList: function (data, pageNum) {
      var _self = this,
        oItems = null,
        minIdx = -1;

      data.forEach(function (elem, idx) {
        var oItem = doc.createElement('div'),
          oImg = new Image(),
          // oTitle = doc.createElement('div'),
          // 设置第元素的左边距第一列为0 其他的列:下标*(元素宽度+边距)
          itemLeft = (idx + 1) % _self.column === 1 ? '0' : idx * (_self.itemWidth + _self.gap);

        oItem.className = 'wf-item';
        oItem.style.width = _self.itemWidth + 'px';
        // 元素高度:旧高度*新计算出的宽度/旧宽度+要留的间隙
        oItem.style.height = (elem.height * _self.itemWidth / elem.width) + 'px';
        oImg.src = elem.img;
        // oTitle.innerHTML = '<p>测试文本</p>';
        // oTitle.className = 'title-box';

        oItem.appendChild(oImg);
        // oItem.appendChild(oTitle);
        _self.oWrapper.appendChild(oItem);

        oItems = doc.getElementsByClassName('wf-item');
        // 设置第一页的左边距与上边距
        if (idx < _self.column && pageNum == 0) {
          _self.heightArr.push(oItem.offsetHeight);
          oItem.style.top = '0';
          oItem.style.left = itemLeft + 'px';
        } else {
          // 找出高度最小的元素
          minIdx = getMinIdx(_self.heightArr);
          // 左边距:与当前找出的高度最小元素一致
          oItem.style.left = oItems[minIdx].offsetLeft + 'px';
          // 上边距:当前找出的高度最小元素 + 需要间隔的上边距
          oItem.style.top = (_self.heightArr[minIdx] + _self.gap) + 'px';
          // 当前元素的高度加上新增元素+间隔的上边距;
          _self.heightArr[minIdx] += (oItems[idx].offsetHeight + _self.gap);
        }
        oImg.style.opacity = '1';
      });
    }
  }

  function getMinIdx(arr) {
    // 1.先找最小高度 2.找到位置
    return [].indexOf.call(arr, Math.min.apply(null, arr));
  }
  window.Waterfall = Waterfall;
})(document);