Home  >  Article  >  Web Front-end  >  Introduction to JavaScript framework (xmlplus) components (8) DividedBox

Introduction to JavaScript framework (xmlplus) components (8) DividedBox

零下一度
零下一度Original
2017-05-06 15:29:011183browse

xmlplus is a JavaScript framework for rapid development of front-end and back-end projects. This article mainly introduces the dividing box of the xmlplus layout component, which has certain reference value. Interested friends can refer to

Separating box (pidedBox) is a layout Class components can be divided into two categories, one is called horizontal separation box (HpidedBox), and the other is called vertical separation box (VpidedBox). A horizontal divider box divides its children into two columns, while a vertical divider box divides its children into two rows. There is generally a separator bar between columns and rows that can be dragged to change the size of child components. The following only uses vertical separation boxes as an example to introduce how such components are designed and implemented.

Finished component use case

According to past design experience, we can first write out the imaginary finished component use case, which will help us in the subsequent Further design and implementation. Since the vertical separation box is a component of the layout class, it must also be a container, which contains the three sub-level components we mentioned above. For ease of use, we should not write the separation box into it. The separation box should be implemented internally in the component. After analysis, we get the following application example:

Example1: {
 css: "#example p { width: 80%; height: 80%; background: #AAA; }",
 xml: `
    

` }

This example consists of a vertical separation box component wrapping two p elements. Here, the width and height of the two p elements are set to 80% of the parent, and their background color is set to gray. This is just for the convenience of testing. In addition, we also need to consider the initial proportion allocation of a sub-frame. We can set the default ratio to 50:50. It is best to specify the ratio statically when the component is instantiated, while providing a dynamic interface for ratio setting. So we have the following improved use case.

Example2: {
 css: "#example p { width: 80%; height: 80%; background: #AAA; }",
 xml: `
    

`, fun: function (sys, items, opts) { sys.top.on("click", e => sys.example.percent = 50); } }

This use case sets the initial ratio distribution of the sub-boxes to 30:70 when the vertical separation box is initialized. When the user clicks on the first sub-box, the ratio distribution is restored to 50:50. Note, however, that these ratios refer to the ratio of the remaining space after excluding the space taken up by the divider bar.

Design and Implementation

Now let’s turn our attention to the internals of the component. Let's first roughly determine the basic composition of the component. Intuitively, the vertical divider frame display contains three component parts: the upper sub-frame part, the divider bar, and the lower sub-frame part. So we can temporarily get the following view item part:

VpidedBox: {
 xml: `

` }

Next, make sure that the child part of the vertical divider box component instance is correctly mapped to the upper sub-box top and the lower sub-box bottom. The method is to first add all child element objects to the upper sub-box top, and then add the lower child elements to the lower sub-box bottom in the function item.

VpidedBox: {
 xml: `

`, map: {appendTo: "top" }, fun: function (sys, items, opts) { sys.bottom.elem().appendChild(this.last().elem()); } }

Now let us consider the style of the view item. For the top-level p element, we set its positioning method to relative positioning. The three child elements are set to absolute positioning. Also, set the divider height to 5px.

VpidedBox: {
 css: `#hbox { position:relative; width:100%; height:100%; box-sizing: border-box; }
   #top { top: 0; height: 30%; } #bottom { bottom: 0; height: calc(70% - 5px); }
   #top,#bottom { left: 0; right: 0; position: absolute; }
   #handle { height: 5px; width: 100%; position:absolute; left:0; top: 30%; z-index:11; cursor:row-resize; }`,
 xml: `

`, map: {appendTo: "top" }, fun: function (sys, items, opts) { sys.bottom.elem().appendChild(this.last().elem()); } }

Finally, let's see how to respond to the drag event of the divider bar to change the allocation ratio of the subboxes. We need to define a function that changes the proportion of the subbox and listens for the drag event of the separator bar. Below is one of our implementations.

VpidedBox: {
 // 视图项同上
 map: { format: {"int": "percent"}, appendTo: "top" }, 
 fun: function (sys, items, opts) {
  var percent = 50;
  sys.handle.on("dragstart", function (e) {
   sys.hbox.on("dragover", dragover);
  });
  sys.hbox.on("dragend", function (e) {
   e.stopPropagation();
   sys.hbox.off("dragover", dragover);
  });
  function dragover(e) {
   e.preventDefault();
   setPercent((e.pageY - sys.hbox.offset().top) / sys.hbox.height() * 100);
  }
  function setPercent(value) {
   sys.handle.css("top", value + "%");
   sys.top.css("height", value + "%");
   sys.bottom.css("height", "calc(" + (100 - value) + "% - 5px)");
  }
  setPercent(opts.percent || percent);
  sys.bottom.elem().appendChild(this.last().elem());
  return Object.defineProperty({}, "percent", {get: () => {return percent}, set: setPercent});
 }
}

There is a setting for percent format in the mapping item of the above code, which ensures that percent is an integer. In addition, the calc calculation function of CSS3 is used to set the proportion of the sub-box in the function item. The modified function can still work when the browser form changes size. If you want to be compatible with more browsers, you need to do more work. Also note that in order to ensure good performance of the component, the dragover event will only be listened to when the user starts dragging.

Further improvements

Let us now do a small test and write an application example of a vertical separator box containing two text fields as children. Drag the divider bar and see what happens.

Example3: {
 css: `#example textarea { width: 80%; height: 80%; }`,
 xml: `