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, TA Bleview) {        var degree = Math.Round (data.s (' label.rotation ')/Math.PI * (),                width = math.abs (w/360 * degree), C5/>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, 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 + h/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:function () {},    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, so you need to add event monitoring on the view, listen to the user's possible actions, in this demo, we want the user to drag the Angle Control Panel to control the angle, so we added MouseDown on the view, MouseMove and MouseUp three events monitoring;

3. The user can change the angle by dragging the component, the change is continuous, and it is possible to drag the mouse away from the component area, to achieve the exit component area can also correctly change the value, then you need to call the HT for Web startdragging () Method

The above-described operations are handled in constructors, and then look at what the constructor looks like:

Class Ht.widget.RotationEditor Constructor ht.widget.RotationEditor = function (data, column, Master, editinfo) {    // Invokes the parent class constructor initialization parameter    This.getsuperclass (). Call (this, data, column, Master, editinfo);    var = this,        view = Self._view = Creatediv (1),        canvas = Self._canvas = Createcanvas (Self._view);    View.style.boxShadow = ' 2px 2px 10px #000 ';    Add MouseMove Listener    view.addeventlistener (' MouseMove ', function (e) {        if (self._state) {HT) on the view            . Default.startdragging (self, e);        }    );    Add MouseDown monitor    view.addeventlistener (' MouseDown ', function (e) {        self._state = 1        ) on view Self.handlewindowmousemove (e);    });    Add MouseUp monitoring on the view, do some cleanup    view.addeventlistener (' MouseUp ', function (e) {        self.clear ();    });};

4. Next is the Def () method to define the Ht.widget.RotationEditor class to inherit from the Ht.widget.BaseItemEditor, and implement the parent class method, the code is as follows, in the code, I did not post SetValue () The implementation of the method, because this piece is somewhat complex, we separate out to explain;
Ht. Default.def (' Ht.widget.RotationEditor ', Ht.widget.BaseItemEditor, {    editbeginning:function () {        var self = This,            editinfo = Self.geteditinfo (),            rect = editinfo.rect;        Before editing 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;    },    SetValue: Function (val) {       //Set editor value and do the editor's page initialization Operation    }});

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 area, fill the color through the Fill method;

5.3. Draw the pointer and draw two pointers through the 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, if the text is drawn directly, the pointer will overlap with the clearrect () method to clear the text area, in the FillRect () Method fills the background, otherwise the text area block will be transparent, and then the Filltext () method is called 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 = this;    if (Self._value = = = val) return;    Set the component value Self._value = val;  var editinfo = Self.geteditinfo (), rect = editinfo.rect, canvas = self._canvas, radius = Self._radius    = RECT.WIDTH/2, Det = ten, border = 2, x = radius, y = radius;    Radians to the angle of the conversion val = Math.Round (VAL/MATH.PI * 180);    Set the canvas size Setcanvas (canvas, Rect.width, rect.width);    Get the brush var g = initcontext (canvas);    Translateandscale (g, 0, 0, 1);    Draw 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, y, 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 ();    Padding value area g.fill ();    Draws the line G.lineto (x, y) at the end of the value area to the center of the circle;    G.lineto (x, det + border);    G.stroke ();    Draw 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 ();    Clear the text area g.clearrect (textrect.x, Textrect.y, Textrect.width, textrect.height);    G.fillstyle = ' #FFF ';    Complement 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,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;

The MouseMove event of the window is monitored, and the startdragging () method is called in the MouseMove event of the view,//And the Essence of the Startdragging () method is the MouseMove event that triggers the window. /The method calculates the change of value and changes 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 angle        value = Ma Th.round (Math.atan2 (Y-radius, X-radius)/Math.PI *;    if (value > +) {        value =-(180-value + +);    }    else {        value = value + +;    }    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 *);}    }

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.


Extended HT for Web HTML5 table component renderer and editor

Related Article

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.