Extended HT for Web HTML5 table component renderer and editor

Source: Internet
Author: User
Tags event listener table definition

The HT for Web provides several commonly used editor, namely:

    • Slider: Pull Bar

    • Color Picker: Colour picker

    • Enum: Enum type

    • Boolean: True and False editor

    • String: Normal text editor

In addition to these common editors, you can also implement a custom editor by inheriting the Ht.widget.BaseItemEditor class.

While the renderer, the renderer available in the HT for Web are:

    • Enum: Enum type

    • Color: Colour type

    • Boolean: True and False renderer

    • Text: Literal renderer

As well as the editor, you can customize the renderer, but in a different way, the renderer is customizing the cell presentation effect by defining the Drawcell () method in the column.

Today we're going to implement a custom HTML5 table component of the renderer and editor, in order to demonstrate the editing effect more visually, we just take advantage of the HT for Web powerful HTML5 topology diagram component

First look at the effect:

, the second column in the left table defines an editor that represents the rotation angle of the current text with a disk, which can be dragged to achieve the angle transformation; The third column of the table is the Drawcell () method to draw the contents of the cell, and the middle line identifies a zero rotation angle. Left indicates that the text rotates counterclockwise to the specified angle, and to the right indicates that the text rotates clockwise.

HT for Web topology diagram Network node text, simple modification label.rotation properties can realize the text rotation function, in order to more intuitive I specifically add label.background make network topology diagram node text has background effect.

Let's take a look at the specific implementation, first to understand the implementation of the renderer:

{    name :  ' label.rotation ',    accesstype :  ' Style ',     drawcell : function (G, data, selected, column, x,  y, w, h, tableview)  {        var degree  = math.round (DATA.S (' label.rotation ')  / math.pi * 180),                 width = math.abs (w /  360 * degree),                 begin = w / 2,                 rectColor =  ' #29BB9C ',                 fontColor =  ' #000 ',                 background =  ' #F8F0E5 ';         if  (selected)  {             rectColor =  ' #F7F283 ';             background =  ' #29BB9C ';        }         g.beginpath ();         g.fillstyle =  background;        g.fillrect (x, y, w, h);         g.beginpath ();         if   (degree < 0)  begin -= width;         G.fillstyle = rectcolor;        g.fillrect (x +  Begin, y, widTH,&NBSP;H);         g.beginpath ();         g.font =  ' 12px arial, sans-serif ';         g.fillstyle = fontcolor;        g.textalign =   ' Center ';        g.textbaseline =  ' middle ';         g.filltext (degree, x + w / 2, y + &NBSP;H&NBSP;/&NBSP;2);     }}

The code above is the code that defines the third column of the table, and you can see that in addition to defining the column's own properties, the Drawcell () method is added and the parameters passed in through the Drawcell () method are used to draw the desired effect.

Rendering is so simple, the editor is not so easy, before you design a custom editor, you need to understand the following editor's base class Ht.widget.BaseItemEditor, the code is as follows:

Ht.widget.BaseItemEditor = function (data, column, Master, editinfo) {this._data = data;    this._column = column;    This._master = master; This._editinfo = Editinfo;}; Ht. Default.def (' Ht.widget.BaseItemEditor ', Object, {ms_ac:["data", "column", "Master", "Editinfo"], Editbeginning:fun Ction () {}, Getview:function () {}, Getvalue:function () {}, Setvalue:function () {}});

It handles the initialization of class variables in constructors, and defines several interfaces that allow user overloading to implement the relevant business Operation logic processing. Then let's talk about the specific purpose of these interfaces:

    • Editbeginning: Called before the cell starts editing

    • GetView: Get editor View, value type is DOM element

    • GetValue: Get editor values

    • SetValue: Set editor values, and do the editor's page initialization operation

When creating a custom editor, you must implement these interfaces and do different things in different interfaces.

Now let's look at how the custom editing of the rotation angle is designed:

1. According to the design conventions of the HT for Web component, we need to create a div as a view that contains a canvas element in the view, and the component content is drawn on the canvas;

2. Editor needs to interact with the user, therefore, the need to add event monitoring on the view, monitoring the user's possible actions, in this demo, we want the user to drag the angle control disk to control the angle, so, We have added MouseDown, MouseMove and MouseUp three event monitoring on the view;

3. The user can change the angle by dragging the component, this change is continuous, and it is possible to drag the mouse away from the component area, in order to leave the component area can also change the value correctly, then you need to call the HT for Web Startdragging () method;

The actions described above are handled in the constructor, followed by a look at what the constructor looks like:

  Class Ht.widget.RotationEditor constructor Ht.widget.rotationeditor = function (data, column,  Master, editinfo)  {    //  Call parent class constructor initialization parameters      This.getsuperclass (). Call (This, data, column, master, editinfo);     Var self = this,        view = self._view  = creatediv (1),         canvas = self._canvas  = createcanvas (Self._view);    view.style.boxshadow =  ' 2px 2px  10px  #000 ';    //  add mousemove monitoring on view      View.addeventlistener (' MouseMove ',  function (e)  {        if   (self._state)  {            ht. Default.startdragging (self, e);         }    });    //  add MouseDown monitoring on view      view.addeventlistener (' MouseDown ',  function (e)  {         self._state = 1;         Self.handlewindowmousemove (e);     });    //  add MouseUp listening on the view, Do some cleanup operations     view.addeventlistener (' MouseUp ',  function (e)  {         self.clear ();     });

   4. The next step is through Def () method to define the Ht.widget.RotationEditor class to inherit from the Ht.widget.BaseItemEditor, and implement the method of the parent class, the code is as follows, in the code, I did not post the implementation of the SetValue () method, because this block is somewhat complex, We take it out separately to explain it;

Ht. Default.def (' Ht.widget.RotationEditor ', ht.widget.baseitemeditor, {     Editbeginning : function ()  {        var self  = this,            editinfo =  Self.geteditinfo (),            rect =  editinfo.rect;        //  edit before the component layout, to avoid the component width and height calculation is not in place          layout (Self, rect.x, rect.y, rect.width, rect.width);     },    getview : function ()  {         return this._view;    },     Getvalue : function ()  {        return this._value;     },  &nBsp; setvalue : function (Val)  {       //  set editor values, And do the editor's page initialization operation &NBSP;&NBSP;&NBSP;&NBSP;});

5. In the SetValue () method, we will draw the above-mentioned effect of the beginning of the article, which is roughly decomposed, and can be drawn in the following four steps, of course, before drawing the context object of the canvas to get the line:

5.1. Draw the inner and outer discs and draw two concentric circles with 10px intervals through the arc () method;

5.2. draw a region of values by combining the arc () method and the LineTo () method to draw a sector region that fills the color with the Fill method;

5.3. Draw a pointer, draw two pointers by LineTo () method;

5.4. when drawing text, the text cannot be drawn directly at the center of the Circle, because the center of the circle is the intersection of the pointer, and if the text is drawn directly, it overlaps with the pointer, and the text area is cleared by the Clearrect () method. Fill the background with the FillRect () method, or the text area block will be transparent, then call the Filltext () method to draw the text.

These are all the logic that the component draws, but it is important to note that after the component is drawn, the next restore () method must be called, because the Save () operation is done in the Initcontext () method, followed by a look at the specific implementation (the code is a bit long);

Setvalue : function (val)  {    var self = this;     if  (self._value === val)  return;    //  Set component values      self._value = val;    var editInfo =  Self.geteditinfo (),        rect = editinfo.rect,         canvas = self._canvas,         radius = self._radius = rect.width / 2,         det = 10,        border = 2,         x = radius,         y = radius;    //  Radian-to-angle conversion     val =  math.round (VAL&NBSP;/&NBSP;MATH.PI&Nbsp;* 180);    //  Set the canvas size     setcanvas (canvas,  rect.width, rect.width);    //  Get brush     var g =  initcontext (canvas);     translateandscale (g, 0, 0, 1);     //  drawing Background     g.fillStyle =  ' #FFF ';     G.fillrect (0, 0, radius * 2, radius * 2);    //  Set line color and line width     g.strokeStyle =  ' #969698 ';     g.linewidth  = border;    //  Draw Outer Ring     g.beginpath ();     g.arc (x, y, radius - border, 0, math.pi * 2, true);     g.stroke ();    //  draw inner Ring     g.beginpath ();     g.arc (X,&NBSP;Y,&NBsp;radius - det - border, 0, math.pi * 2, true);     g.stroke ();    //  plot value area     var start =  -math.pi / 2,        end = math.pi *  val / 180 - math.pi / 2;    g.beginpath ();     g.fillStyle =  ' Rgba (255, 0, 0, 0.7) ';     g.arc (x,  y, radius - border, end, start, ! (val < 0));     g.lineto (X, border + det);     g.arc (X, y,  radius - det - border, start, end, val < 0);     g.closepath ();    //  Fill value Area     g.fill ();     //  draw the line at the end of the value area to the center      g.lineto (x, y);     g.lineto (X, det + border);     g.stroke ();    //  drawing text     var font =  ' 12px  arial, sans-serif ';    //  calculate text size     var textsize  = ht. Default.gettextsize (font,  ' -180 ');    //  text area     var  textrect = {        x : x -  textsize.width / 2,        y : y -  Textsize.height / 2,        width : textsize.width ,        height : textsize.height    };     g.beginpath ();    //  empty text area      G.clearrect (Textrect.x, textrect.y, textrect.width, textrect.height);    g.fillstyle =  ' #FFF ';    //  the background     g.fillrect (textrect.x, textrect.y,  Textrect.width, textrect.height);    //  set Text style      g.textalign =  ' center ';    g.textbaseline =  ' middle ';     g.font = font;    g.fillStyle =  ' Black ';     //  Draw Text     g.filltext (val, x, y);    //  Restore () and save () are paired, and the Save () operation has been done in the Initcontext () method     g.restore ();}

6. When the design of the editor is generally complete, how can the editor use the form? It is simple to use the following two lines of code to start using the editor when the table definition column is defined.

Editable:true,//start edit itemeditor: ' ht.widget.RotationEditor '//Pointing editor class

Here, the editor can be drawn normally, but in the operation, you will find that the editor does not change the angle according to the position of the drag, this is why? Take a look at the following note:

7. In the constructor, the MouseMove event of view calls the Startdragging () method, in fact this method is dependent, it requires component overloading Handlewindowmousemove () and Handlewindowmouseup () Two methods. The reason is very simple, as mentioned in the 3rd, the user in the drag component, it is possible to drag away from the component area, this time only through the window of the MouseMove and MouseUp two event monitoring to enable the user to continue operation;

  listens to the window's MouseMove event, in the view's MouseMove event, calls the Startdragging () method,//  and Startdragging () The essence of the method is to trigger the window's MouseMove event//  The method calculates the value change and change the value by the SetValue () method Handlewindowmousemove : function (E)  {    var rect = this._view.getboundingclientrect (),         x = e.x - rect.left,         y = e.y - rect.top,        radius  = this._radius,        //  calculate radians by inverse trigonometric function, then convert radians to angles          value = math.round (Math.atan2 (y - radius, x  - radius)  / math.pi * 180);    if  (value >  90)  {        value = -(180 - value &NBSP;+&NBSP;90);     }    else {        value = value +  90;    }    this.setvalue (value / 180 *  Math.PI);},handlewindowmouseup : function (e)  {    this.clear ();},clear  : function ()  {    //  Clear status Component Status     delete this . _state;}

With the above three methods, the code can be run to find that the editor can be edited normally. But only after the end of the edit, you can see the text rotation angle changes on the topology map, if you can update the text rotation on the topology map in real-time, it will be more intuitive, then what to do now?

8. Custom Editor This block and like other already implemented editor can specify the properties of the editor, the custom editor can specify only one class name, so it is useless to set parameters on the editor, the user cannot be set to the editor. A Shang method is to tamper with the column, drawing on the design ideas of other editors, add a property named _instant on the column, and in the code to determine whether to update the corresponding property value immediately, so you only need to SetValue () By adding the following code to the method, we can realize the effect of updating the property value in real time.

Determines whether the column object is set with the _instant property if (column._instant) {var table = Self.getmaster (); Table.setvalue (Self.getdata (), column, Val);}

9. At this point, the design of the editor has been completed, now look at the specific usage, the following code is a table in the specific column definition, in the column definition, specify the Itemeditor property value, and set the _instant property is true, you can implement the editor real-time update effect

{accessType: ' style ', Name: ' Label.rotation ', Editable:true, ItemEditor: ' Ht.widget.RotationEditor ',    _instant:true, Formatvalue:function (value) {return Math.Round (VALUE/MATH.PI * 180); }}

In the code you will find a Formatvalue () method that is defined to match the value type edited in the editor, converting radians to angles.

In the third column of the table, the cell style is customized by the renderer, and I've also defined another editor that allows you to change the angle by dragging and dropping the cells around, which is slightly different from the editor mentioned above, except that the third column editor passes the HT for the Ms_listener module, defined in the Web, is added to the listener, allowing the constructors to be separated from the interaction and appear clearer.

Introduce the next Ms_listener module, if the class adds a Ms_listener module, there will be two more methods in the class:

    • Addlisteners: Adds the Handle_xxx () method defined in the class (XXX represents a DOM event name, such as: MouseMove, etc.) as the corresponding event listener function to the component's view;

    • Removelisteners: Removes the event corresponding to the HANDLE_XXX () method defined in the class from view.

So how to add the Ms_listener module in the class, simply add the ms_listener:true line of code on the method definition of the class in the Def () method, and add the handle function corresponding to the DOM event on the method definition, The Addlisteners () method of the class is then called in the constructor.

The specific code I will not be elaborated, the idea is similar to the idea of the editor described earlier.

Finally attach all the code of the program, for your reference, what is the question welcome message consultation.

Tablerenderereditor.zip


Extended HT for Web HTML5 table component renderer and editor

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.