聚合物1.0试图制造一个像核心分离器一样工作的分离器,可称为分流器

时间:2015-09-29 18:05:53

标签: javascript polymer web-component

我正在尝试创建一个名为core-splitter的元素,该元素在1.0中已弃用,因为它在我们的项目中起着关键作用。

如果你不知道什么是核心分离器,我可以提供一个简短的描述。 core-splitter提供了一个分割条,在分割条上拖动将调整兄弟元素的大小。通常你会想要使用core-splitter和flex布局,这样其他兄弟元素就可以灵活。不幸的是,这只适用于Polymer 0.5,但是在1.0中已经弃用了。这是Polymer 0.5版本的演示。 Demo for core-splitter in Polymer 0.5

我能够在普通的javascript中执行此操作,但无法在Polymer 1.0中使其工作。

这是fiddle

<link rel="import"       href="https://cdn.rawgit.com/Polymer/polymer/master/polymer.html">
    <dom-module id="splitter-element">
      <template>
        <div id="div1" class="split">Bacon ipsum dolor amet beef ribs         meatloaf picanha pork loin pork chop rump pig sausage bacon shank boudin beef fatback. Pork loin turducken t-bone chicken.</div>
        <div class="gutter" style="width: 10px;"></div>
        <div id="div2" class="split">Brisket andouille cow ball tip. Ham ground round short loin tri-tip ribeye t-bone boudin, pork loin turkey drumstick tongue pork chop. Kielbasa doner picanha turducken, swine bacon shank pastrami andouille.</div>
      </template>
     <style>
    .gutter {
       background-color: #eee;
       background-image: url('https://ssl.gstatic.com/ui/v1/icons/mail/grippy_large.png');
       background-repeat: no-repeat;
       background-position: 50%;
       cursor: move;
       cursor: grab;
       cursor: -moz-grab;
       cursor: -webkit-grab;
    }
  .split, .gutter {
      height: 100%;
      float: left;
  }
.gutter:active {
    cursor: grabbing;
    cursor: -moz-grabbing;
    cursor: -webkit-grabbing;
 }
.split {
    box-sizing: border-box;
    padding: 20px;
    overflow-y: scroll;
    overflow-x: hidden;
}
  </style>
  <script>
  Polymer({
    is: 'splitter-element',
    properties:{
      "dragging":{
       Value:false
     }
    },
    "split":function(ids, options){
    options = typeof options !== 'undefined' ?  options : {};

    if (!options.gutterWidth) options.gutterWidth = 10;
    if (!options.minWidth) options.minWidth = 100;
    if (!options.snapOffset) options.snapOffset = 30;

  // Event listeners for drag events, bound to a pair object.
  // Save the pair's left position and width when dragging starts.
  // Prevent selection on start and re-enable it when done.

    var startDragging = function (e) {
        console.log('start');
        e.preventDefault();

         this.dragging = true;

        this.width = this.left.clientWidth + this.right.clientWidth + options.gutterWidth;
        this.x = this.left.getBoundingClientRect().left;

        this.left.addEventListener('selectstart', preventSelection);
        this.left.addEventListener('dragstart', preventSelection);
        this.right.addEventListener('selectstart', preventSelection);
        this.right.addEventListener('dragstart', preventSelection);

        this.left.style.userSelect = 'none';
        this.left.style.webkitUserSelect = 'none';
        this.left.style.MozUserSelect = 'none';

        this.right.style.userSelect = 'none';
        this.right.style.webkitUserSelect = 'none';
        this.right.style.MozUserSelect = 'none';

        if (options.onDragStart) {
            options.onDragStart();
        }
    },

    stopDragging = function () {
        this.dragging = false;

        this.left.removeEventListener('selectstart', preventSelection);
        this.left.removeEventListener('dragstart', preventSelection);
        this.right.removeEventListener('selectstart', preventSelection);
        this.right.removeEventListener('dragstart', preventSelection);

        this.left.style.userSelect = '';
        this.left.style.webkitUserSelect = '';
        this.left.style.MozUserSelect = '';

        this.right.style.userSelect = '';
        this.right.style.webkitUserSelect = '';
        this.right.style.MozUserSelect = '';

        if (options.onDragEnd) {
            options.onDragEnd();
        }
    },

    drag = function (e) {
        if (!this.dragging) return;

        // Get the relative position of the event from the left side of the
        // pair.

        var offsetX = e.clientX - this.x;

        // If within snapOffset of min or max, set offset to min or max

        if (offsetX <=  this.leftMin + options.snapOffset) {
            offsetX = this.leftMin;
        } else if (offsetX >= this.width - this.rightMin - options.snapOffset) {
            offsetX = this.width - this.rightMin;
        }

        // Left width is the same as offset. Right width is total width - left width.

        this.left.style.width = 'calc(' + (offsetX / this.width * 100) + '% - ' + options.gutterWidth / 2 + 'px)';
        this.right.style.width = 'calc(' + (100 - (offsetX / this.width * 100)) + '% - ' + options.gutterWidth / 2 + 'px)';

        if (options.onDrag) {
            options.onDrag();
        }
    },

    preventSelection = function () { return false; },

    // Given a list of DOM element ids and a list of percentage widths,
    // assign each element a width allowing for a gutter between each
    // pair. The number of gutters is ids.length - 1, and the total gutter
    // width is gutterWidth * (ids.length - 1). Before calculating
    // each width, subtract the total gutter width for the parent width.

    parent = document.getElementById(ids[0]).parentNode;

if (!options.widths) {
    var percent = 100 / ids.length;

    options.widths = [];

    for (var i = 0; i < ids.length; i++) {
        options.widths.push(percent);
    };
}

if (!Array.isArray(options.minWidth)) {
    var minWidths = [];

    for (var i = 0; i < ids.length; i++) {
        minWidths.push(options.minWidth);
    };

    options.minWidth = minWidths;
}

for (var i = 0; i < ids.length; i++) {
    var el = document.getElementById(ids[i]);

    if (i > 0) {
        var pair = {
                left: document.getElementById(ids[i - 1]),
                right: el,
                leftMin: options.minWidth[i - 1],
                rightMin: options.minWidth[i],
                dragging: false,
                parent: parent
            },
            gutter = document.createElement('div');

        gutter.className = 'gutter';
        gutter.style.width = options.gutterWidth + 'px';

        gutter.addEventListener('mousedown', startDragging.bind(pair));

        parent.addEventListener('mouseup', stopDragging.bind(pair));
        parent.addEventListener('mousemove', drag.bind(pair));
        parent.addEventListener('mouseleave', stopDragging.bind(pair));

        parent.insertBefore(gutter, el);

        pair.gutter = gutter;
    }

    el.style.width = 'calc(' + options.widths[i] + '% - ' + options.gutterWidth / 2 + 'px)';
}
  },
  "ready":function(){
      this.split(['div1', 'div2'], {
        widths: [25, 75],
        minWidth: 200
    });
  }
});
</script>
</dom-module>
<splitter-element>
</splitter-element>

1 个答案:

答案 0 :(得分:1)

更新:我升级了一个核分裂器分支,以便与Polymer 1.0 Local DOM

兼容

<强>答案: 问题是聚合物元素必须解决{{3}}而不是常规DOM。这是使用this.$[]代替document.getElementById()以及Polymer.dom(this.root)代替parent实现的。 我能够通过相应的下一步更改来执行代码:

// parent = document.getElementById(ids[0]).parentNode;
parent = this.$[ids[0]].parentNode;

// var el = document.getElementById(ids[i]);
var el = this.$[ids[i]];

// left: document.getElementById(ids[i - 1]),
left: this.$[ids[i - 1]],

//parent.insertBefore(gutter, el);
Polymer.dom(this.root).insertBefore(gutter, el);

我还在模板部分评论了gutter div,因为当在javascript代码中创建了一个装订线时它被复制了:

<!-- <div id="gutter1" class="gutter" style="width: 10px;"></div> -->

我使用了从_https://github.com/Polymer/polymer安装聚合物1.0的本地服务器以及splitter-element目录中的下两个文件。

demo.html:

<!DOCTYPE html>
<html>
<head>
  <title>splitter-element</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../webcomponentsjs/webcomponents-lite.js"></script>

  <link rel="import" href="splitter-element.html">

  <style>
    .container {
      height: 240px;
      border: 4px solid #aaa;
    }
  </style>
</head>
<body>
  <div class="container" horizontal="" layout="">
    <splitter-element direction="left" minsize="128px"></core-splitter>
  </div>

</body>
</html>

和splitter-element.html

<link rel="import"       href="../polymer/polymer.html">
<dom-module id="splitter-element">
  <template>
     <div id="div1" class="split">Bacon ipsum dolor amet beef ribs         meatloaf picanha pork loin pork chop rump pig sausage bacon shank boudin beef fatback. Pork loin turducken t-bone chicken.</div>
     <!-- <div id="gutter1" class="gutter" style="width: 10px;"></div> -->
     <div id="div2" class="split">Brisket andouille cow ball tip. Ham ground round short loin tri-tip ribeye t-bone boudin, pork loin turkey drumstick tongue pork chop. Kielbasa doner picanha turducken, swine bacon shank pastrami andouille.</div>
  </template>
  <style>
    .gutter {
      background-color: #eee;
      background-image: url(handle.svg);
      background-repeat: no-repeat;
      background-position: 50%;
      cursor: move;
      cursor: grab;
      cursor: -moz-grab;
      cursor: -webkit-grab;
    }
    .split, .gutter {
      height: 100%;
      float: left;
    }
    .gutter:active {
      cursor: grabbing;
      cursor: -moz-grabbing;
      cursor: -webkit-grabbing;
    }
    .split {
      box-sizing: border-box;
      padding: 20px;
      overflow-y: scroll;
      overflow-x: hidden;
    }
  </style>
  <script>
    Polymer({
      is: 'splitter-element',
      properties:{
        "dragging":{
         Value:false
        }
      },
      "split":function(ids, options){
        options = typeof options !== 'undefined' ?  options : {};

        if (!options.gutterWidth) options.gutterWidth = 10;
        if (!options.minWidth) options.minWidth = 100;
        if (!options.snapOffset) options.snapOffset = 30;

        // Event listeners for drag events, bound to a pair object.
        // Save the pair's left position and width when dragging starts.
        // Prevent selection on start and re-enable it when done.

        var startDragging = function (e) {
        console.log('start');
        e.preventDefault();

        this.dragging = true;

        this.width = this.left.clientWidth + this.right.clientWidth + options.gutterWidth;
        this.x = this.left.getBoundingClientRect().left;

        this.left.addEventListener('selectstart', preventSelection);
        this.left.addEventListener('dragstart', preventSelection);
        this.right.addEventListener('selectstart', preventSelection);
        this.right.addEventListener('dragstart', preventSelection);

        this.left.style.userSelect = 'none';
        this.left.style.webkitUserSelect = 'none';
        this.left.style.MozUserSelect = 'none';

        this.right.style.userSelect = 'none';
        this.right.style.webkitUserSelect = 'none';
        this.right.style.MozUserSelect = 'none';

        if (options.onDragStart) {
        options.onDragStart();
        }
      },

      stopDragging = function () {
        this.dragging = false;

        this.left.removeEventListener('selectstart', preventSelection);
        this.left.removeEventListener('dragstart', preventSelection);
        this.right.removeEventListener('selectstart', preventSelection);
        this.right.removeEventListener('dragstart', preventSelection);

        this.left.style.userSelect = '';
        this.left.style.webkitUserSelect = '';
        this.left.style.MozUserSelect = '';

        this.right.style.userSelect = '';
        this.right.style.webkitUserSelect = '';
        this.right.style.MozUserSelect = '';

        if (options.onDragEnd) {
        options.onDragEnd();
        }
      },

      drag = function (e) {
        if (!this.dragging) return;

        // Get the relative position of the event from the left side of the
        // pair.

        var offsetX = e.clientX - this.x;

        // If within snapOffset of min or max, set offset to min or max

        if (offsetX <=  this.leftMin + options.snapOffset) {
        offsetX = this.leftMin;
        } else if (offsetX >= this.width - this.rightMin - options.snapOffset) {
        offsetX = this.width - this.rightMin;
        }

        // Left width is the same as offset. Right width is total width - left width.

        this.left.style.width = 'calc(' + (offsetX / this.width * 100) + '% - ' + options.gutterWidth / 2 + 'px)';
        this.right.style.width = 'calc(' + (100 - (offsetX / this.width * 100)) + '% - ' + options.gutterWidth / 2 + 'px)';

        if (options.onDrag) {
        options.onDrag();
        }
      },

      preventSelection = function () { return false; },

      // Given a list of DOM element ids and a list of percentage widths,
      // assign each element a width allowing for a gutter between each
      // pair. The number of gutters is ids.length - 1, and the total gutter
      // width is gutterWidth * (ids.length - 1). Before calculating
      // each width, subtract the total gutter width for the parent width.

      // parent = document.getElementById(ids[0]).parentNode;
      parent = this.$[ids[0]].parentNode;

      if (!options.widths) {
        var percent = 100 / ids.length;

        options.widths = [];

        for (var i = 0; i < ids.length; i++) {
        options.widths.push(percent);
        };
      }

      if (!Array.isArray(options.minWidth)) {
        var minWidths = [];

        for (var i = 0; i < ids.length; i++) {
        minWidths.push(options.minWidth);
        };

        options.minWidth = minWidths;
      }

      for (var i = 0; i < ids.length; i++) {
        // var el = document.getElementById(ids[i]);
        var el = this.$[ids[i]];

        if (i > 0) {
        var pair = {
          // left: document.getElementById(ids[i - 1]),
          left: this.$[ids[i - 1]],
          right: el,
          leftMin: options.minWidth[i - 1],
          rightMin: options.minWidth[i],
          dragging: false,
          parent: parent
        },
        gutter = document.createElement('div');
        //gutter = this.$['gutter1']; 
        // This is the only case in this polymer element where 
        // using the normal DOM is appropriate.

        gutter.className = 'gutter';
        gutter.style.width = options.gutterWidth + 'px';

        gutter.addEventListener('mousedown', startDragging.bind(pair));

        parent.addEventListener('mouseup', stopDragging.bind(pair));
        parent.addEventListener('mousemove', drag.bind(pair));
        parent.addEventListener('mouseleave', stopDragging.bind(pair));

        // https://www.polymer-project.org/1.0/docs/devguide/local-dom.html
        //parent.insertBefore(gutter, el);
        Polymer.dom(this.root).insertBefore(gutter, el);

        pair.gutter = gutter;
      }

      el.style.width = 'calc(' + options.widths[i] + '% - ' + options.gutterWidth / 2 + 'px)';
      }
    },
    "ready":function(){
      this.split(['div1', 'div2'], {
      widths: [25, 75],
      minWidth: 200
      });
    }
    });
  </script>
</dom-module>