Xmlplus Component Design Series Separated Box (DividedBox) (8), xmlplusdividedbox

Source: Internet
Author: User

Xmlplus Component Design Series Separated Box (DividedBox) (8), xmlplusdividedbox

DividedBox)A layout component can be divided into two types. One is HDividedBox, and the other is VDividedBox ). The horizontal split box divides its child into two columns, while the Vertical Split box divides its child into two rows. There is usually a drag-and-drop between columns and between rows to change the size of child widgets. The following uses vertical separation boxes as an example to describe how to design and implement such components.

Finished component use case

Based on our previous design experience, we can first write the expected finished component use cases, which will help us further design and implementation. Since the vertical separator is a component of the layout class, it must also be a container that contains the Three-seed components we mentioned above. For ease of use, we should not include the separation boxes, which should be implemented inside the components. After analysis, we can get an example of the following application:

Example1: { css: "#example div { width: 80%; height: 80%; background: #AAA; }", xml: `<VDividedBox id="example">    <div id='top'/>    <div id='bottom'/>   </VDividedBox>`}

In this example, two div elements are enclosed by a vertical separator box. Here, the width and height of the two div elements are set to 80% of the parent level, and their background color is set to gray, which is just for convenience of testing. In addition, we also need to consider the initial proportional distribution of a subbox. We can set the default ratio to 50: 50. It is best to specify the ratio statically during component instantiation, and provide a dynamic interface for proportional setting. So we have the following improvement case.

Example2: { css: "#example div { width: 80%; height: 80%; background: #AAA; }", xml: `<VDividedBox id="example" percent='30'>    <div id='top'/>    <div id='bottom'/>   </VDividedBox>`, fun: function (sys, items, opts) {  sys.top.on("click", e => sys.example.percent = 50); }}

In this case, the initial proportion of the subbox is set to 30: 70 when the vertical separation box is initialized. When the user clicks the first subbox, the ratio allocation is restored to 50: 50. However, you should note that the proportional distribution refers to the proportion of the remaining space after the space occupied by the exclusion separator is allocated.

Design and Implementation

Now let's focus on the component. Let's roughly determine the basic components. Intuitively, the vertical separation box contains three components: the upper and lower boxes, the separators, and the lower boxes. So now we can get the following view items:

VDividedBox: { xml: `<div id='hbox'>   <div id='top'/>   <div id='handle'/>   <div id='bottom'/>   </div>`}

Next, make sure that the child part of the vertical separator box is correctly mapped to the top and bottom boxes bottom. The method is to add all child element objects to the top of the Child box, and then add the child element to the bottom Frame bottom in the function item.

VDividedBox: { xml: `<div id='hbox'>   <div id='top'/>   <div id='handle'/>   <div id='bottom'/>   </div>`, map: {appendTo: "top" }, fun: function (sys, items, opts) {  sys.bottom.elem().appendChild(this.last().elem()); }}

Now let's take the style of the view item into consideration. For the top-level div element, we set its positioning method to relative positioning. The three sub-level elements are set to absolute positioning. In addition, set the height of the separator bar to 5px.

VDividedBox: { 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: `<div id='hbox'>   <div id='top'/>   <div id='handle'/>   <div id='bottom'/>   </div>`, map: {appendTo: "top" }, fun: function (sys, items, opts) {  sys.bottom.elem().appendChild(this.last().elem()); }}

Finally, let's take a look at how to respond to the drag event of the separator bar to change the allocation ratio of the Child box. We need to define a function to change the proportion of sub-boxes and listen for drag and drop events of separation bars. The following is an implementation.

VDividedBox: {// view item same as 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 });}}

The ing item of the above Code has a setting about the percent format, which ensures that percent is an integer. In addition, the ratio setting of the Child box in the function item uses the calc computing function of css3, and the function can still work when the browser form is changed. If you want to be compatible with more browsers, you need to do more work. In addition, to ensure good performance of components, the event dragover is listened only when the user starts to drag the component.

Further Improvement

Let's perform a small test and write an application instance that contains two text fields as sub-level vertical separator boxes. Drag the separator bar to see what results will appear.

Example3: { css: `#example textarea { width: 80%; height: 80%; }`, xml: `<VDividedBox id="example">    <textarea id='top'/>    <textarea id='bottom'/>   </VDividedBox>`}

In this example, sometimes the separator bar fails and the proportion of the sub-box does not change with the position of the separator bar. The problem is that the drag-and-drop event is hijacked in the text field, and we cannot receive the RESPONSE event in our components. We need some patches.

VDividedBox: { 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; }\   #mask { width: 100%; height: 100%; position: absolute; display: none; z-index: 10; }", xml: "<div id='hbox'>\   <div id='top'/>\   <div id='handle' draggable='true'/>\   <div id='bottom'/>\   <div id='mask'/>\   </div>", map: { format: {"int": "percent"}, appendTo: "top" },  fun: function (sys, items, opts) {  var percent = 50;  sys.handle.on("dragstart", function (e) {   sys.mask.show();   sys.hbox.on("dragover", dragover);  });  sys.hbox.on("dragend", function (e) {   sys.mask.hide();   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}); }}

To solve the problem, we reference the extra div Element Object mask in the component. This element is not displayed by default. When the drag starts, it will overwrite the sub-box and the separation bar. When the drag ends, it is hidden. In this way, the hijacking of text fields to drag events is avoided.

Combined with the horizontal separator box

With the above vertical separation box design experience, it is not difficult to create a horizontal separation box. We will not list it here. Here is an example of using the horizontal and vertical separation boxes. Of course, at the beginning of the design, we did not expect such use.

Example4: { css: `#example div { width: 100%; height: 100%; }`, xml: `<HDividedBox id='example'>    <VDividedBox percent='30'>     <div/><div/>    </VDividedBox>    <VDividedBox percent='30'>     <div/><div/>    </VDividedBox>   </HDividedBox>`}

This example is mainly used to show how the Delimiter is nested. This example contains a horizontal split box, which contains two vertical split boxes. This layout is common in many editors, we have implemented it simply and efficiently.

This series of articles is based on the xmlplus framework. If you do not know much about xmlplus, visit www.xmlplus.cn. Here are detailed introductory documents for your reference.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.