JavaScript Table Sort 2.0 (update) _javascript tips

Source: Internet
Author: User
have been so busy lately, take advantage of 51 to update the program.
This edition mainly adds and improves the following things:
1, to compare the string to Localecompare instead;
2, multiple Sort objects can be used in one sort (reorder when values are equal);
3, to correct some of the problems found;
4, improve the structure of the program, the individual feel is more flexible and convenient;
5, increase the type of bool to compare;
6, add the content of Attribute/property;
7, Fix the IE6/7 radio/checkbox state to recover the bug;
8, add the custom value function.
<! DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 transitional//en" "Http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd "> <ptml xmlns=" http://www.w3.org/1999/xhtml "> <pead> <meta http-equiv=" Content-type "content=" text/html; charset=gb2312 "/> <title>table sort </title> <style type=" Text/css ">. odtable {width:500px; border:1px solid #ebebeb; line-height:20px; font-size:12px; Background: #FFF; }. odtable thead td {Background-color: #ebebeb; }. odtable a {outline:none;/*ff*/hide-focus:expression (this.hidefocus=true);/*ie*/} odtable a:link,. OdTable A:vi Sited, Odtable a:hover,. odtable a:active {text-decoration:none; Color: #333; padding-right:15px; }. odtable a.up,. odtable a.down {background:url ([img]/upload/20090507150209227.jpg[/img]) right center no-repeat; }. odtable A.down {background-image:url ([img]/upload/20090507150209265.jpg[/img]); } </style> <script type= "Text/javascript" > var Isie = (document.all)? True:false; var isIE6 = Isie && (navigator.userAgent.indexOf (' MSIE 6.0 ')!=-1); var isIE7 = Isie && (navigator.userAgent.indexOf (' MSIE 7.0 ')!=-1); var isie6or7 = IsIE6 | | isIE7; var $ = function (ID) {return "string" = = typeof ID? document.getElementById (ID): ID; }; var Extend = function (destination, source) {for (var property in source) {Destination[property] = Source[property]; return destination; The var Bind = function (object, fun) {var args = Array.prototype.slice.call (arguments). Slice (2); return function () {return Fun.apply (object, Args.concat (Array.prototype.slice.call (arguments)); The var ForEach = function (array, callback, Thisobject) {if (Array.foreach) {Array.foreach (callback, Thisobject); }else{for (var i = 0, len = Array.Length i < len; i++) {Callback.call (Thisobject, array[i], I, array); } var Map = function (array, callback, Thisobject) {if (Array.map) {return Array.map (callback, ThiSobject); }else{var res = []; for (var i = 0, len = Array.Length i < len; i++) {Res.push (Callback.call (Thisobject, array[i), I, array);} return res; The var Filter = function (array, callback, Thisobject) {if (Array.filter) {return Array.filter (callback, Thisobject); }else{var res = []; for (var i = 0, len = Array.Length i < len; i++) {Callback.call (Thisobject, array[i], I, array) && Res.push (A Rray[i]); return res; } var TableOrder = function (table, options) {this._checked = [];//checkbox and radio Collection (to resolve IE6/7 State recovery bugs) this.tbody = $ (table). Tbodies[0];//tbody object this. Rows = Map (this.tBody.rows, Function (o) {return o;}); /Line Collection this. SetOptions (options); Tableorder.prototype = {//Set default properties Setoptions:function (options) {this.options = {//default value INDEX:0,//TD index Attri: "Inne RHTML ",//Gets the property of the data DataType:" string ",//The data type of the comparison desc:true,//whether to compare:null,//the custom sort function in descending order getvalue:null,//custom value function Startsort:function () {}//sort before performing endsort:function () {},//sortExecution}; Extend (this.options, Options | | {}); },//Sort and display sort:function () {var orders = Array.prototype.slice.call (arguments); No Sort object returns if (!orders.length) {return false}; Perform additional functions orders[0].startsort (); Sort this. Rows.sort (Bind (this, this.compare, orders, 0)); Get collection Isie6or7 && this. GetChecked (); Show Table var ofragment = Document.createdocumentfragment (); ForEach (this. Rows, Function (o) {ofragment.appendchild (o);}); This.tBody.appendChild (ofragment); Restore status Isie6or7 && this. Setchecked (); Perform additional functions orders[0].endsort (); },//Comparison function compare:function (orders, I, O1, O2) {var order = Orders[i], value1 = this. GetValue (order, O1), value2 = this. GetValue (order, O2), result = Order.compare? Order.compare (value1, value2)://Use custom sort function typeof value2 = "string"? Value1.localecompare (value2): (value1-value2); If result is 0 (same value) and has the next sort object, continue to compare otherwise, and return to!result && Orders[++i] According to Desc. This.compare (Orders, I, O1, O2): (Order. Desc? -1:1) * result; },//Get the comparison value getvalue:function (order, TR) {var td = Tr.cells[order. Index], att = order. Attri, data = order. GetValue? Order. GetValue (TD)://Use custom value function att in TD? Td[att]: Td.getattribute (ATT); Data Conversion switch (order. Datatype.tolowercase ()) {case ' int ': return parseint (data, 10) | | 0; Case "float": return parsefloat (data, 10) | | 0; Case "Date": Return Date.parse (data) | | 0; Case "BOOL": return data = = TRUE | | String (data). toLowerCase () = = "true"? 1:0; Case "string": Default:return data.tostring () | | ""; },///creates and returns a Sort object Creat:function (options) {return Extend (Extend ({}, This.options), Options | | {}); //Gets the checkbox and radio collection to be modified Getchecked:function () {this._checked = Filter (this.tBody.getElementsByTagName ("input"). Function (o) {return (isIE6 && o.type = "checkbox") | | o.type = "Radio") && o.checked!= O.defaultcheck Ed }); },//Set checked setchecked:function () {ForEach (this._checked, Function (o) {) of the checkbox and radio Collection o.checked =!o.defaultchecked; }); } </script> </pead> <body> <table border= "0" cellspacing= "0" cellpadding= "5" class= "odtable" I d= "IDTable" > <thead> <tr> <td align= "center" >ID</td> <td>  name/type </td> &L T;TD width= "align=" center "> Upload time </td> <td width=" align= "center" > Size </td> <td width= "30 "align=" center ">C</td> <td width=" align= "center" >R</td> </tr> </thead> <tbod y> <tr> <td align= "center" >1</td> <td _ext= "htm" >new.htm</td> <td align= "Center" & gt;2008/9/12</td> <td align= "right" _order= "9" >423.09 k</td> <td align= "center" ><input type= "checkbox"/></td> <td align= "center" ><input name= "C" type= "Radio"/></td> </tr > <tr> <td align= "center" >2</td> <td _ext= "js" >Scroller.js</td> <td align= "Center ">2008/9/23</td> <td align= "right" _order= ">2.5 k</td> <td align=" center "><input type=" CheckBox "/></td> <td align=" center "><input name=" C "type=" Radio "/></td> </tr> < tr> <td align= "center" >3</td> <td _ext= "js" >AlertBox.js</td> <td align= "center" > 2008/9/23</td> <td align= "right" _order= "290" >3.48 k</td> <td align= "center" ><input type= " CheckBox "/></td> <td align=" center "><input name=" C "type=" Radio "/></td> </tr> < tr> <td align= "center" >4</td> <td _ext= "xml" >1.xml</td> <td align= "center" >2008/10/ 4</td> <td align= the "right" _order= ">11.13 k</td> <td align=" center "><input type=" checkbox "/></td> <td align=" center "><input name=" C "type=" Radio "/></td> </tr> <tr> TD align= "Center" >5</td> <td _ext= "xml" &Gt;4.xml</td> <td align= "center" >2008/10/4</td> <td align= "right" _order= "1000" >351 b</td > &LT;TD align= "center" ><input type= "checkbox"/></td> <td align= "center" ><input name= "C" Type= "Radio"/></td> </tr> <tr> <td align= "center" >6</td> <td _ext= "htm" > news.htm</td> <td align= "center" >2008/10/4</td> <td align= "right" _order= "14074" >13.74 k< /td> <td align= "center" ><input type= "checkbox"/></td> <td align= "center" ><input name= " C "type=" Radio "/></td> </tr> <tr> <td align=" center ">7</td> <td _ext=" JS ">func tion.js</td> <td align= "center" >2008/10/4</td> <td align= "right" _order= "2844" >2.78 k</td > &LT;TD align= "center" ><input type= "checkbox"/></td> <td align= "center" ><input name= "C" Type= "Radio"/></td> </tr> <tr> &LT;TD align= "center" >8</td> <td _ext= "MP3" > Secret Garden-nocturne.mp3</td> <td "center" align= 9/20</td> <td align= "right" _order= "3111293" >2.97 m</td> <td align= "center" ><input type= " CheckBox "/></td> <td align=" center "><input name=" C "type=" Radio "/></td> </tr> < tr> <td align= "center" >9</td> <td _ext= "Doc" > Detailed work + plot process (a) .doc</td> <td align= "Center" & gt;2009/2/2</td> <td align= "right" _order= "63488" >62 k</td> <td align= "center" ><input type = "checkbox"/></td> <td align= "center" ><input name= "C" type= "Radio"/></td> </tr> <tr> <td align= "center" >10</td> <td _ext= "Doc" > Detail work + plot process (ii) .doc</td> &LT;TD " Center ">2009/2/2</td> &LT;TD align=" right "_order=" 164352 ">160.5 k</td> <td align=" center "> <input type= "checkbox"/></td> <td align= "C"Enter ><input name= "C" type= "Radio"/></td> </tr> <tr> <td align= "center" >11</td& Gt &LT;TD _ext= "TXT" > Disable file Preview .txt</td> <td align= "center" >2008/8/7</td> <td align= "right" _ Order= "860" >860 b</td> <td align= "center" ><input type= "checkbox"/></td> <td align= " Center "><input name=" C "type=" Radio "/></td> </tr> <tr> <td align=" center ">12</td > <td _ext= "txt" > Super Invincible Wonderful Effect collection .txt</td> <td align= "center" >2009/2/2</td> &LT;TD align= " Right "_order=" 351 ">351 b</td> <td align=" center "><input type=" checkbox "/></td> &LT;TD align= "center" ><input name= "C" type= "Radio"/></td> </tr> </tbody> </table> have Chinese front row Face, and then reverse chronological order: <input name= "" "type=" button "value=" Sort "id=" idbtn "/>" <script "type=" Text/javascript "> VA R to = new TableOrder ("IDTable"), Odid = to. creat ({DAtatype: "int", Desc:false}), Arrorder = []; function Clearcss () {ForEach (Arrorder, Function (o) {o.classname = "";});} function Setorder (obj, options) {var o = $ (obj), order = to. creat (options); Order.startsort = function () {clearcss (); Odid.desc = this. Desc; } Order.endsort = function () {o.classname = this. Desc? ' Down ': ' Up ';//Set style this. Desc =!this. desc;//the reverse sort} O.onclick = function () {to. Sort (order, Odid); return false; } arrorder.push (o);//record sort items (used primarily to set styles)} setorder ("Idnum", {DataType: "int"}); Setorder ("Idtitle", {index:1}); Setorder ("Idext", {index:1, Attri: "_ext"}); Setorder ("Idaddtime", {index:2, DataType: "Date"}); Setorder ("Idsize", {index:3, Attri: "_order", DataType: "int"}); function Getcheck (o) {return o.getelementsbytagname ("input") [0].checked; } setorder ("Idcheckbox", {index:4, DataType: "bool", Getvalue:getcheck}); Setorder ("Idradio", {index:5, DataType: "bool", Getvalue:getcheck}); $ ("Idnum"). OnClick (); ///var od1 = to. Creat ({index:1, endsort:clearcss, Compare:function (value1, value2) {var re =/[\u4e00-\u9fa5]/i, V1 = re.test (value 1), V2 = Re.test (value2); return V1 = = v2? 0: (v1? 1:-1); }), od2 = to. Creat ({index:2, DataType: "Date"}), od3 = to. Creat ({DataType: "int"}); $ ("idbtn"). onclick = function () {to. Sort (Od1, OD2, od3); } </script> </body> </ptml>
[Ctrl + A All SELECT Note: If the need to introduce external JS need to refresh to perform]

Packaging code
Basic steps

1, put the rows that need to be sorted into the TBODY (the program will take tbody rows directly);

2, place the sort row in an array;

This. Rows = Map (this.tBody.rows, Function (o) {return o;});

3, sorted according to the needs of the array (with the sort method of arrays);

This. Rows.sort (Bind (this, this.compare, orders, 0));

4, use a document fragment (Document.createdocumentfragment ()) to save the rows in order;


var ofragment = document.createdocumentfragment ();
ForEach (this. Rows, Function (o) {ofragment.appendchild (o);});

PS: Document fragmentation is not required, but it is recommended that the use of document fragmentation in a large number of DOM operations is more efficient.

5, insert the document fragment into the tbody.

This.tBody.appendChild (ofragment);


Program Description

"Sort Function"

The sort has to say the sort method in the array, as described in the manual: Returns an array object that has been sorted by an element. That is, an array is sorted, and many sort-related operations use this method.

The default is sorted in ascending order of ASCII characters, using parameters to customize the sorting method, and the program's compare program is sorted by custom.
In general, the sort function will have two default parameters are two comparison objects, in the program when called compare when the call to bind two parameters, so there will be 4 parameters.
Note that the sort function must return one of the following values:
Negative value if the first argument passed is smaller than the second argument.
0 if two parameters are equal.
Positive value if the first argument is larger than the second argument.

Compare values after you get the comparison value (described later).
In the program if it is a string, will use Localecompare to obtain the comparison result, otherwise directly subtracts obtains the comparison result:

result = Order.compare? Order.compare (value1, value2)://Use custom sort
typeof value2 = = "string"? Value1.localecompare (value2): (value1-value2);

If the Desc property is true (in reverse order), then multiplying by 1 on result can get the opposite sort: order. Down? -1:1) * Result


"Get Comparison value"

In the program, the comparison value is obtained from each TR according to the Sort object and the GetValue method.
First, the corresponding value is obtained by index (TD Index) and Attri (attribute).
If there is no suitable attribute to put the value to compare, you can give TD a custom attribute to put this value (such as the _ext in the example).
For custom attributes that are set in HTML, IE can be fetched with [x] and getattribute, and FF can only be obtained using getattribute (described later).
So just consider the FF case, in which the program uses in to determine whether this property can be obtained by [X]:

var td = Tr.getelementsbytagname ("TD") [order. Index]
, at = order. Attri, data = at in TD? Td[at]: Td.getattribute (at);

If the in operation is true, you can use the keyword method to take the value, otherwise use getattribute to fetch.
After the value is obtained, a comparison value conversion is made, where the date is converted to an integer in the form of Date.parse to facilitate comparison:

Switch (order. Datatype.tolowercase ()) {
Case "int":
return parseint (data) | | 0;
Case "float":
return parsefloat (data) | | 0;
Case "Date":
return Date.parse (data) | | 0;
Case "string":
Default
Return data.tostring () | | "";
}

Note that date.parse parameters must conform to the date format of JS (refer to here).
PS: If you feel that adding custom attributes does not conform to the criteria, consider placing them in a property such as title.


"Attribute/property"

When the comparison value is obtained, it is used in to determine whether the [X] method can be used, in fact, to determine if the attribute or property is considered.
What is the difference between the attribute and the property? This may be a lot of people do not pay attention to, perhaps think is the same thing.
To be clear about the difference between attribute and property is to know what they are respectively, this is difficult to understand, for example.
Here we first to FF as the standard, followed by ie the difference. Take Div as an example, check the Web page to make a complete manual, will find it has the following attributes:
ALIGN ALIGN
CLASS ClassName
ID ID
Title Title
... ...
The first column is attribute, and the second column is property.
attribute is the property that the DOM element has as an HTML tag in the document, and property is the attribute that the DOM element has as an object in JS.
For example, in HTML, Dom as a page element should be used directly with the class attribute, and corresponding to the DOM object in JS must use the classname attribute.
Because attribute is not case-sensitive, this makes most attributes and property looks the same, making people mistakenly think the same thing (ie, of course, the responsibility is also very large).
Don't believe it. Use FF to see the following example:

<div id= "T" tt= "1" >test </div>
<script>
var o = document.getElementById (' t ');
o["tt"]= "2";
Document.writeln (O.getattribute ("tt"));
Document.writeln (o["tt"]);
</script>

You can see that getattribute and [x] methods get different answers.
Here we must first say the difference between getattribute and [x] ways, getattribute and setattribute are specifically used to acquire and set attributes,
and [x] is to get and set property properties, this property is the same as our general operation of the JS object properties are the same.
Perhaps some people may have the question, like id,title not all point to the same attribute, the Modification property correspondence attribute also will follow the modification.
In fact, we can also customize one such property, in the FF test the following code:

<div id= "T" tt= "1" >test </div>
<script>
var o = document.getElementById (' t ');
O.__DEFINESETTER__ ("TT", function (x) {This.setattribute ("tt", x);});
O.__DEFINEGETTER__ ("TT", function () {return This.getattribute ("TT");});
o.tt= "2";
Document.writeln (O.getattribute ("tt"));
Document.writeln (o["tt"]);
</script>

This enables the "modify property corresponding attribute will also be modified" attribute.
From the test example, you can see that the attribute and the corresponding property can use a different name, such as class and classname effect.
The value of the attribute can be processed and returned in the getter, just as the property value of href is the full path form of attribute.
and property can have no corresponding attribute, vice versa, like innerHTML such a property has no corresponding attribute.
PS: The above is just a description of the principle of implementation, in fact, do not need to achieve this.

Since we know that attribute and property are different things, then how can we tell whether an attribute is attributed or not?
We can use in to Judge property, use Hasattribute to judge attribute.
But Ie6/7 no hasattribute, is not only in to judge it? By the half, Ie6/7 doesn't need hasattribute at all.
In the IE6/7, there is no good area division attribute and property. For example IE6/7 run the following code:

<div id= "T" tt= "1" >test </div>
<script>
var o = document.getElementById (' t ');
o["tt"]= "2";
Document.writeln (O.getattribute ("tt"));
Document.writeln (o["tt"]);
O.setattribute ("tt", "3");
Document.writeln (O.getattribute ("tt"));
Document.writeln (o["tt"]);
o["RR"]= "4";
Document.writeln (O.getattribute ("RR"));
Document.writeln (o["RR"]);
Document.writeln (O.getattribute ("InnerHTML"));
Document.writeln (o["InnerHTML"]);
</script>

You can see that there is basically no attribute and property of the points, and IE8 results in addition to GetAttribute ("InnerHTML"), and other like IE6/7.
Of course, I think IE's system author must know the difference between attribute and property, but they do so to get the user to take for granted results.
There was nothing wrong with being so fooled, but then I found a problem:

<div id= "T" class= "a" >test </div>
<script>
var o = document.getElementById (' t ');
O.setattribute ("Class", "B");
alert (o.outerhtml);
</script>

This modification of the style is invalid, according to the rules of IE to use classname, but the problem is from the outerhtml actually see the div tag has two class attributes.
I've never known how to understand IE, but this has been corrected in IE8.
The attribute and property have been distinguished in the IE8 (see Differences in Internet Explorer 8).
For example, GetAttribute ("InnerHTML") returns NULL, stating that InnerHTML is no longer attribute;setattribute ("class", X) is modified by attribute, Instead of adding an inexplicable class attribute to the DOM element, it looks like GetAttribute has no second argument (GetAttribute's second argument can look here).
However, IE8 still uses the addition of new attributes to be both attribute and property, and is estimated to be compatible with previous versions.

PS: All of the above are in [x] as an example, and the effect of using the. operator is the same as [x].
PS2: This part may be problematic due to the lack of a very deep understanding of DOM, as you are welcome to point out.
PS3: I found out that I have too little dom knowledge, and I'm looking for a book of Dom.


"Radio/checkbox Checked status Bug"

You can test the following code with IE6/7:
<div id= "C" >
<input type= "checkbox" Id= "a"
/>
<input name= "B" type= "Radio" id= "B"
/>
</div>
<input type= "button" value= "click" id= "BTN"
/>
<script>
var a = document.getElementById ("a");
var B = document.getElementById ("B");
var c = document.getElementById ("C");
document.getElementById ("btn"). onclick =
function () {
C.appendchild (a);
C.appendchild (b);
var O1 = document.createelement ("input");
O1.type =
"checkbox"; o1.checked =
True
C.appendchild (O1);
var O2 = document.createelement ("input");
O2.type =
"Radio"; o2.checked =
True
C.appendchild (O2);
}
</script>

Select the checkbox and radio first, then click on the button, in the IE6 will find that checkbox and radio are restored to the state of no point selection, IE7 better just radio have problems.
and the newly inserted checkbox and radio, although checked are set to True, are not displayed in the selected state.
Here is actually a problem, checkbox and radio after some DOM operations (such as the appendchild here), checked automatically reverts to defaultchecked state.
The question of creating elements can be referenced here.
In the program, TR in the sort will use AppendChild reinsert the document, the result will cause the above problem, the solution for the moment think of three:
1, modify the defaultchecked before appendchild.
After the appendchild is automatically restored to defaultchecked, then we modify the defaultchecked to the current checked value before appendchild.
This solution is good, as long as the appendchild before sweeping the form control on the line, but the problem is that this will affect the result of reset, because after the reset Checkbox/radio checked will revert to the defaultchecked value, If you modify the defaultchecked, the reset will lose its effect.
2, save the checked state before appendchild, and restore after appendchild.
There are two ways to implement this, one is to save Checkbox/radio the current checked value with an array or object, and then find the corresponding value and set it after appendchild.
The other is to save the current checked value of Checkbox/radio directly into a custom property of the control, and then get it and set it after appendchild.
Two methods have to sweep the form control two times, the following method is more convenient.
3, locate the checked and defaultchecked that are not equal before appendchild, and then reset the controls after appendchild.
This method is slightly better than the previous one, as long as you sweep the control before AppendChild and filter out what needs to be corrected (checked and defaultchecked are not equal), After appendchild, set checked to the opposite value of defaultchecked.
The program uses the 3rd method to get the Checkbox/radio set to be fixed by using the GetChecked method before AppendChild:
Getchecked:function () {
this._checked = Filter (this.tBody.getElementsByTagName ("input"), function (o) {
Return (isIE6 && O.type = =
"checkbox") | | O.type = =
"Radio") && o.checked!= o.defaultchecked;
});
},

Reset the checked value with setchecked after AppendChild:
Setchecked:function () {
ForEach (this._checked, Function (o) {o.checked =
!o.defaultchecked; });
}

But this efficiency is still relatively low, if there is a better way to remember to tell me AH.


"Sort Objects"

For a more flexible program, add a Sort object to the thing.
This sort object has the following properties:
Property default value//description
INDEX:0,//TD Index
Attri: "InnerHTML",//Get the properties of the data
DataType: "string",//data type of comparison
desc:true,//whether descending
compare:null,//Custom Sort function
Startsort:function () {},//before sort execution
Endsort:function () {}//sort after

You can see that this sort of object is used to hold the rules and ways of sorting, which is used to tell the program how to sort.
This pattern is used because a table usually requires a number of different sorting methods, using the Sort object is like playing the champ, which is the right one.
The program can also set multiple sort objects in a single order, one being KO (equal to the comparison), and the other on.
In this way it will be more convenient and more reusable.

In a program, you create a sort object by using the Creat program, whose parameters are custom attributes:

Creat:function (options) {
Return Extend (Extend ({}, This.options), Options | | {});
}

The sort program is sorted, but one or more of the sorted objects must be parameters.
In the sort program, you first convert the Sort object arguments to an array:

var orders = Array.prototype.slice.call (arguments);

It is then passed to the Compare program, where the comparison result is 0 (that is, equality), and the next sort object continues to compare with the next sort object:

return!result && orders[++i]? This.compare (Orders, I, O1, O2): (Order. Desc? -1:1) * result;

This way you can make the most of the sort objects you've created.


How to use

First instantiate a primary sort object, and the parameter is the ID of the table:

var to = new TableOrder ("idtable");

If you need to set a default property, it is generally recommended to set it at new time.

Then add a Sort object with the Creat method, which is the Property object to set (refer to "Sort Object"):

Odid = To. Creat ({DataType: "int", Desc:false})

You can then sort by using the sort method with the sorted object as a parameter:

To. Sort (order, Odid);

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.