swisnl / jquery-contextmenu Goto Github PK
View Code? Open in Web Editor NEWjQuery contextMenu plugin & polyfill
Home Page: https://swisnl.github.io/jQuery-contextMenu/
License: MIT License
jQuery contextMenu plugin & polyfill
Home Page: https://swisnl.github.io/jQuery-contextMenu/
License: MIT License
When I try to return false from build callback I see the context menu just without items.
This is example:
$.contextMenu({
selector: ".category",
build: function($trigger, e) {
return false;
}
}
If an item declares a callback function for its 'disabled' property, when that callback returns false, the subsequent item.callback is not called.
The Demo at http://medialize.github.com/jQuery-contextMenu/demo.html shows this behavior.
To reproduce, load the Demo page and in "menu 2" of the first demo, attempt to select the Golf menu item, which is not disabled. The item's callback (alert_click) is never fired.
Hi,
Working on this example http://medialize.github.com/jQuery-contextMenu/demo/html5-import.html i'm trying to use a custom class for some of the menu items adding className="custom-class" to a command element. I guess the way i'm doing it is wrong since is not working.
<menu id="html5menu" type="context" style="display:none" class="showcase">
<command label="rotate" onclick="alert('rotate')" icon="images/door.png" className="custom-class" ></command>
</menu>
Is jQuery-contextMenu suppose to read the className option when using HTML5 menu?
Hi,
Great context menu, but theming with jQuery ThemeRoller is totally missing. Can you add theming support please?
Thanks a lot in advance.
Hi Rod,
I am using jquery context menu with kendo grid. Whenever the user clicks on the different headers of the grid, the context menu should open up based on the column name - i.e. the context menu items should be populated dynamically.
I have used to create the context menus based on http://medialize.github.com/jQuery-contextMenu/demo/dynamic-create.html
But I see the sub-menu options are not being correctly displayed. The sub-menu is getting displayed not at the position where the parent menu is opening. Please refer to the fiddle I have created : http://jsfiddle.net/anirbankundu/pR6nq/2/
If you do a right click on column Header = "colA", you will see a context menu with sub menus.But the sub-menu option is not opening at a position relative to its parent menu. If you click column Header ="colB", you will see a different context menu.
Could you please let me know why the sub-menus are not getting displayed correctly.
Thanks,
Anirban
I use html5
import feature, and i don't know how I can determine if a command is disabled at triggering. jquery.contextMenu.js : line 1349
disabled: !!$node.attr('disabled'),
Thanks for your help
Hi,
for some reason the item order is inverted in chrome (version 18.0.1025.168 m).
Both IE and Firefox show the items in the order they are declared.
I assume there is no option/parameter to define the order (at least i couldn't find it in the api).
Is it a plugin issue or chrome's fault?
some SS:
http://dl.dropbox.com/u/6551/ssChrome.png
http://dl.dropbox.com/u/6551/ssIE.png
It might be just my setup, but, I'm trying to get the alternate types to work ('text', 'checkbox', etc) - however, they cause a DOM exception (INVALID_STATE_ERR) in jquery.
It occurs in function "clean", on this line:
// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];
It happens with every alternate type except for 'textarea', which seems to function properly. Is there some sort of prerequisite to get types to work? I tried the exact same version of all third party libs that you're using on your Demo page, yet it still doesn't work.
Hi,
I have been trying to implement some contextual menu with input fields and I have found an error that also appears in the "input command" demo page.
If you right click, write some text in any of the 3 areas and press return the console outputs:
"Syntax error, unrecognized expression: textarea"
I think that I have isolated where the problem could be. By inserting console.log messages in jquery.contextMenu.js, I have found that the error is yield when line 396 is executed:
if (opt.$selected && !opt.$selected.is(':textarea, :select')) {
Best regards and thank you for your nice work.
Biel
(browser Chrome latest)
In these lines (1063, 1075):
callback: (function(){ return function(){ node.click(); }; })()
happens an error
Uncaught TypeError: Object #<HTMLElement> has no method 'click'
'$node' is likely to be used there instead of 'node' to trigger click event using jQuery.
Not sure if this is an issue or if I'm missing something. I create submenu items when I loop through an array. I try to create the keynames from a field in the array as well as use a value in the array for something in the callback. I think the keyname is not getting set properly because I get the wrong callbacks. If I hard code a basic string keyname it all works perfect. Problem is I don't know how many will be in the submenu. For now I'll just create a big case statement and plan for larger than what I think will be used. Here is an example of my code:
$.contextMenu({
selector: '#pwx_frame_content',
zIndex: '9999',
className: 'ui-widget',
build: function ($trigger, e) {
var options = {
items: {
"fold1": {
"name": "Chart Forms <span class='pwx-submenu_arrow-icon'></span>",
"items": {},
disabled: false
},
"sep3": "---------",
"Select All": { "name": "Select All", callback: function (key, opt) { pwx_select_all('pwx_row_selected'); } },
"Deselect All": { "name": "Deselect All", callback: function (key, opt) { pwx_deselect_all('pwx_row_selected'); } }
}
};
var testForms = new Array(3);
testForms[0] = new Array(2);
testForms[0][0] = 'Test Name 1';
testForms[0][1] = 123456;
testForms[1] = new Array(2);
testForms[1][0] = 'Test Name 2';
testForms[1][1] = 654321;
testForms[2] = new Array(2);
testForms[2][0] = 'Test Name 3';
testForms[2][1] = 22222;
for (var cc = 0; cc < testForms.length; cc++) {
options.items["fold1"].items[testForms[cc][0]] = { "name": testForms[cc][0], callback: function (key, opt) { alert(testForms[cc][1]); } }
}
// -- this was missing --
return options;
}
});
Page Up and Page Down should be grabbed (and ignored, like Space) to prevent page scrolling, for consistency with normal context menus.
I ran into an issue when invoking contextual menus near the far right edge of the window. Submenus were at the same zindex as the main context menu. I added a quick fix for our project. We don't use github at work so I didn't fork anything.
positionSubmenu: function($menu) {
if ($.ui && $.ui.position) {
// .position() is provided as a jQuery UI utility
// (...and it won't work on hidden elements)
$menu.css('display', 'block').position({
my: "left top",
at: "right top",
of: this,
collision: "fit"
}).css('display', '');
} else {
// determine contextMenu position
var offset = this.offset();
offset.top += 0;
offset.left += this.outerWidth();
$menu.css(offset);
}
//increases the submenu zindex by 1 to appear above the parent menu
$menu.css('z-index', parseInt(zindex(this)) + 1);
},
Hello. Awesome plugin, but looks like "disabled" is not working in submenus.
I use HTML5 menu import. When I disable a sub menu item, item's callback is still called on click.
To illustrate, I just disabled a sub item from official HTML import demo :
<menu id="html5menu" type="context" style="display:none" class="showcase">
<command label="rotate" onclick="alert('rotate')">
<command label="resize" onclick="alert('resize')">
<menu label="share">
<command label="twitter" onclick="alert('twitter')" disabled="true">
<hr>
<command label="facebook" onclick="alert('facebook')">
</menu>
</menu>
thanks
Hi,
I was wondering, why isn't there an auto-hide option for contextMenu triggered by hover?
First let me thank you for that great plugin! I have implemented that in an application of mine where i have a table with multiple rows. each row is right-clickable and opens the context menu, but when I right-click on row no.1 for example and then right-click on row 2 it just closes the first opened context menu from row 1. then i have to do a second right-click on row 2 in order to open the context menu. It would be a much better user experience if a click on row 2 would automatically close the first context menu and open the second one.
In a normal context menu, the Home and End keys take you to the first and last (respectively) enabled items in the context menu. They're not captured in this and so go to the start or end of the page, which is undesirable.
I wonder if you might consider adding the ability to pass in the "ignoreRightClick" option as a function? This would be useful for the case I'm looking at just now where I need to decide a menu 'show time' if the menu can be shown or not.
This is the code that I've added to allow this behaviour:
if (o.trigger != 'hover' && o.ignoreRightClick) {
$body.on('mousedown' + o.ns, o.selector, function (e) {
if ( typeof o.ignoreRightClick === 'function' ) {
if ( o.ignoreRightClick() ) {
handle.ignoreRightClick(e);
}
} else {
handle.ignoreRightClick(e);
}
} );
}
I realise that there is the "context-menu-disabled" class option - which would work for me, and I would imagine will work in most cases, but not interfering with the DOM for this ability might be nice, and allows me to do the calculation of if the menu should be shown or not on demand rather than whenever the logic elements that control that get updated.
After calling $.contextMenu('destroy'), I cannot create my context menu anymore.
This happens ONLY when I use 'Dynamic on-demand Menu'.
I reproduce this error on 'Dynamic on-demand Menu' demo using firebug debugger and trying to destroy menu before to recreate it.
It reproduce the bug on Firefox 12 and Chrome.
Javascript error on chrome :
Uncaught TypeError: Cannot read property 'show' of undefined jquery.contextMenu.js : 737
Edit: Menu need to be opened at least one time before being destroyed to reproduce the problem.
I'm trying to use this plugin for a really long list of items.
I've tried using CSS overflow-y:scroll and fixed width, but nope, it doesn't work well cause I've got submenus as well.
Any suggested workarounds?
Thanks!
Use the API of jQuery contextMenu to generate native context menus. This can still be done delegated and on demand, as demonstrated in this fiddle. Reason: People might actually want the native integration. Caveats: possible item-types are restricted to [checkbox, radio, command, submenu].
I ran into an issue with the current version of jQuery-contextMenu not being able to handle objects that I wanted to associate draggable or resizable to. Basically the current code stops propagation of left mouse events, thereby breaking certain types of events/actions that you would want to associate with an element that has a context menu associated with it. The fix is simple, after line 34 in jquery.contextMenu.js add
if( evt.button == 0) return;
If your line numbers are different you will want to do that after $(this).mousdown(functino(e){ .... and before evt.stopPropagation();
Thanks for writing the code and making it open.
esse
I need to disabled right click and trigger manually the context menu. (My final purpose is to tigger the menu on an AJAX response).
First, I declared my context menu using ignoreRightClick :
$.contextMenu({
selector : selector,
items: ...,
ignoreRightClick: true
});
Then, I bound mouseup to trigger context menu :
$(selector).bind('mouseup', function(e) {
if (e.button == 2) {
$(selector).contextmenu();
}
}
The issue is that my manual trigger is ignored instead of the right click trigger
I temporarly fixed it adding a test on the button attribute:
// jquery.contextmenu.js line 190
// ignore right click trigger
if (ignoreThisClick && e.button == 2) {
ignoreThisClick = false;
return;
}
Thanks
Hi.
Just googled this plugin. I like it, great job, thanks!
I opened this issue just to point you out that a link from README.md that should point to this plugin on jQuery plugins directory is obsolete or initially wrong.
WBR,
inst
I am trying to use an Input Field in a Sub-Menu, however in Chrome and Safari the input fields are effectively disabled. This works without issue in Firefox.
Take the following example. You can enter text under Firefox, but not Chrome/Safari:
$.contextMenu({
selector: '.context-menu-one',
callback: function(key, options) {
var m = "clicked: " + key;
window.console && console.log(m) || alert(m);
},
items: {
"edit": {name: "Edit", icon: "edit"},
"cut": {name: "Cut", icon: "cut"},
"copy": {name: "Copy", icon: "copy"},
"paste": {name: "Paste", icon: "paste"},
"delete": {name: "Delete", icon: "delete"},
"sep1": "---------",
"quit": {name: "Quit", icon: "quit"},
"aForm": {name: "New Entry",
items: {
"newTitle": {
name: "Title",
type: 'text'
}
}
}
}
});
If, however, I add an extra input on the root menu it works on all browsers.
$.contextMenu({
selector: '.context-menu-one',
callback: function(key, options) {
var m = "clicked: " + key;
window.console && console.log(m) || alert(m);
},
items: {
"edit": {name: "Edit", icon: "edit"},
"cut": {name: "Cut", icon: "cut"},
"copy": {name: "Copy", icon: "copy"},
"paste": {name: "Paste", icon: "paste"},
"delete": {name: "Delete", icon: "delete"},
"sep1": "---------",
"quit": {name: "Quit", icon: "quit"},
"title": {
name: "Title",
type: 'text'
},
"aForm": {name: "New Entry",
items: {
"newTitle": {
name: "Title",
type: 'text'
}
}
}
}
});
It seems like something is not being initialized in the former case.
The display of the '>' indicator for a submenu is not positioned correctly for the first level. It is positioned at the right but 1 line below the menu.
It's hard to see but if you look carefully at: http://medialize.github.com/jQuery-contextMenu/demo/sub-menus.html you can see that the '>' is positioned at the right and below the "Other group" menu item.
The second level submenu indicator is positioned correctly.
Hi,
This most likely is not a bug, rather I could not find any reference in the documentation.
I am using the data event property to pass some small information upon event triggering and subsequently executing an ajax call, which uses this data. Alas, I cannot find any reference as to where, and how to use this functionality withe the contextMenu.
Your advice, and help are appreciated.
Cheers.
Hi,
This is a feature request rather than an issue ticket.
I would love to have the possibility to dynamically add items to a contextmenu at runtime.
The scenario: A contextmenu gets triggered and the menu items are created depending on info from the trigger element.
Like 'Add to' > [bunch of dynamic elements]
I tried to alter the opt.commands
and opt.items
objects in the show event of the contextmenu but with no effect.
One way to achieve this would be a beforeRender
event where it's possible to replace the items created at registration with new ones.
Another way (seen at jjmenu plugin) is instead of a hardcoded item object literal one can use a function which provides context (of the trigger element) and returns a dynamically created item.
As a workaround (haven't tested this yet) it should be possible to register a click event with jQuery which then (functions as wrapper and) creates a $.contextMenu with items in the context of the click event.
But this could get messy really quick with a lot of different trigger events.
I don't know if this functionality is within the designated scope of jQuery-contextMenu,
but it would greatly enhance the overall very good experience with this plugin. :)
Thanks.
for programming bind , such syntax is needed , when i use your plugin with http://wwwendt.de/tech/dynatree/doc/samples.html (jquery dynaTree plugin) it's difficult for me to find a proper selector to bind context menu .
the dynatree can go well with abeautifulsite's contextMenu :
// Add context menu to this node:
$(span).contextMenu({menu: "myMenu"}, function(action, el, pos) {
// The event was bound to the tag, but the node object
// is stored in the parent
but i was failed do the same thing with your plugins , need help here is my gitAddress(https://github.com/yiqing-95)
When I set the events.show and events.hide, they are never fired. It looks like they're not actually making it into the 'opt' object (in other words, they're always the default empty anonymous function).
Here's what my code looks like:
$.contextMenu({
selector: '#'+$container[0].id + ', #'+$container[0].id+' li > a',
zIndex: 2000,
events: {
show: function(){
console.log('show', this);
this.addClass('contextMenu');
},
hide: function(){
console.log('hide', this);
this.removeClass('contextMenu');
}
},
build: function(){
...
}
});
Hello,
first of all thanks for this really great plugin!
I have some weird issues when applying a contextmenu to elements that have a fixed position.
I've created a demo fiddle here (including steps to reproduce the issue I have):
http://jsfiddle.net/KcZNL/17/
It appears as if the position of the fixed element (the selector) is only determined once, but not updated?
I've reproduced this issue in FF 8 and Chrome 16ish.
I have a case where I have to use my body as the selector to declare the context menu on, which causes an error in the zindex function because my body is in an iframe. I fixed mine by changing this line:
if (!$tt || !$tt.length || $tt.prop('nodeName').toLowerCase() == 'body'
to
if (!$tt || !$tt.length || $tt.prop('nodeName').toLowerCase() == 'body' || $tt.prop('nodeName').toLowerCase() == 'html')
Figured I would let you know so you can test and/or incorporate the change to your next version :)
Hi! I'm using your fantastic plugin with jQuery 1.7. In previous versions, with older jQuery, i could use a css class selector with svg element, but in this version it doesn't work. (but It works with id selector of svg element)
This is a working example of issue, just paste in a new blank html page and see what i mean
<html>
<head>
<script src='http://code.jquery.com/jquery-1.7.js'></script>
<script src='http://medialize.github.com/jQuery-contextMenu/src/jquery.ui.position.js'></script>
<script src='http://medialize.github.com/jQuery-contextMenu/src/jquery.contextMenu.js'></script>
<link rel="stylesheet" type="text/css" href="./jquery.contextMenu.css">
<script>
$(document).ready(function(){
newRectCallback = function(){
alert('Click rect!!');
}
$.contextMenu({selector: '.rect-menu', items: {
newrect: {name: "Add new rect", callback: newRectCallback}
}});
$.contextMenu({selector: '#rect-menu-ok', items: {
newrect: {name: "Add new rect", callback: newRectCallback}
}});
});
</script>
</head>
<body>
<h1 class='rect-menu'>Hello</h1>
<svg style="overflow-x: hidden; overflow-y: hidden; position: relative; " height="301" version="1.1" width="1280" xmlns="http://www.w3.org/2000/svg">
<rect
x="10"
y="20"
width="100"
height="60"
r="10"
rx="10"
ry="10"
fill="#ff0000"
stroke="#ff0000"
class="rect-menu"
fill-opacity="0.1"
stroke-width="2">
</rect>
<rect
x="10"
y="90"
width="100"
height="60"
r="10"
rx="10"
ry="10"
fill="#0000ff"
stroke="#0000ff"
id="rect-menu-ok"
fill-opacity="0.1"
stroke-width="2">
</rect>
</svg>
</body>
What I'm trying to do is pass a javascript call from a link on my page and pass it through the context menu to display results from a database.
Basically how this works is, a user clicks on a date for a particular invoice and the context menu shows up and gives the option to have that particular report run again when the user clicks on RE-RUN in the context menu. But the context menu has to know exactly which report that is before it can display the RE-RUN link. So it has to hit the database first, put that info into the context menu ITEM for RE-RUN and then display the results when the user clicks RE-RUN.
the HTML link:
a href="javascript:GoToHREF('SystemServlet?obj=<%=wpb.encryptURLParams("page=" + wpb.getInvoiceDate())%>')"
which would open a context menu :
$(function actionContext(x){
// make button open the menu
$('#activate-menu').on('click', function(e) {
e.preventDefault();
//$('.context-menu-one').contextMenu();
$('.context-menu-one').trigger("contextmenu");
// or $('.context-menu-one').contextMenu({x: 100, y: 100});
})
$.contextMenu({
selector: '.context-menu-actions',
className: 'title-Actions',
autoHide: true,
trigger: 'right',
callback: function(key, options) {
var m = "clicked: " + key;
},
items: {
"Re-run": {name: "Re-run", callback: function(){ var url = "#";
$(location).attr('href',url); }}
}
});
});
When the user clicks on the RE-RUN item in the context menu, the requested report would be run again.
Thanks in advance.
Hello. Eclipse javascript validator complains with an error for contextMenu and a duplicate case 9. I just ran contextMenu through lint:
302 switch (e.keyCode) {
303 case 9:
304 case 38: // up
305 // if keyCode is [38 (up)] or [9 (tab) with shift]
306 if (opt.isInput) {
307 if (e.keyCode == 9 && e.shiftKey) {
319 return;
320 }
321
322 case 9: // tab
======================^
lint warning: duplicate case in switch statements
323 case 40: // down
324 if (opt.isInput) {
325 if (e.keyCode == 9) {
Thanks for a great plugin!
Sorry to be a nuisance. Can you provide practical example of positioning Context Menu, ideally bottom left of calling element.
The option 'build'
{selector: ".awesome-menu",
build: function($trigger){
return {
callback: function(){},
items: {
foo: {name: "Foo"}
}
};
}};
does not pass the location the mouse event occurred at.
This would be useful for working with context menu for a CANVAS element where the context menu to be displayed depends on what the mouse is pointing at.
Changing line 205 from:
$.extend(true, e.data, defaults, e.data.build($currentTrigger) || {});
to:
$.extend(true, e.data, defaults, e.data.build($currentTrigger, { pageX: e.pageX, pageY: e.pageY }) || {});
Adds support for passing the location to the build function.
Hi,
I'm trying to create a sub menu with data from an array. This array is updated regulary and I want each element of my array to be a sub menu item.. Is there a solution to this problem or the plugin doesn't offer this case?
Here's a little snip of my current code:
$.contextMenu({
selector: '.context-menu-contacts-module',
ignoreRightClick: false,
build: function($trigger, e) {
// this callback is executed every time the menu is to be shown
// its results are destroyed every time the menu is hidden
// e is the original contextmenu event, containing e.pageX and e.pageY (amongst other data)
return {
callback: function(key, options) {
var m = "clicked: " + key;
window.console && console.log(m) || alert(m);
},
items: {
"listContacts": {name: "Liste des contatcs", icon: "edit"},
"addContacts": {name: "Ajouter un contact", icon: "cut"},
"fold1": {
"name": "Raccourcis de contacts",
"items": {
$.each(itemsMenuContext,function(index, item){
document.write('"fold1-key1": {"name": "Nom Prénom"},')
})
"fold1-key1": {"name": "Nom Prénom"},
"fold1-key3": {"name": "Nom Prénom 1"}
},
disabled: false
}
}
};
}
});
Thanks for the help !
The native context menu will not be blocked when disallow “Disable or replace context menus” in firefox (Tools > Options > Content > Advanced and deselect the “Disable or replace context menus” option)
I did found Redmine make it work well, see, right click the related issues.
Is possible to enable a disabled item for example after a click on a button?
thanks
When submenu width is larger then min-width, submenu can't automatically adjust width.
Hi Rodney!
First of all: Thank you for that great plugin!
I'm not sure if understand you documentation. I don't find a way to get the trigger, if I have a checkbox in a contextmenu and i want to observe the click event of that checkbox. With a click at it i want to show or hide a div. - Can you please help me?
Thank you!
-Joerg
I have a list of items, each of them has an individual context menu. I use event delegation to keep the number of bound events low and bind the context menu to the list itself instead of each list item. Then, I use the build callback to generate the individual menus.
$.contextMenu({
selector: 'ul',
build: function($trigger, e) {
var $listEntry = $(e.target).closest('li');
// build dynamic menu
return {};
}
}
The problem with this approach is when I right-click one list item the context menu opens but when I immediately right-click another one the existing (wrong) menu is simply moved to the new position instead of generating the menu for the new item. This behaviour makes sense when right-clicking multiple times on the same trigger, but not in my case when menu generation depends on event generation (where I have kind of multiple triggers).
What can be done here (not sure this justifies a github issue)?
Additionally it would be helpful if the selector option would accept a jQuery object or DOM element in addition to the selector string.
Wrong items are clicked when importing an HTML 5 menu with multiple sub menus.
Try to click on facebook item on this example : http://jsfiddle.net/jpimag/CKw86/
Reproduced on Firefox 13 and Chrome.
I want to know if is possible to get the id/class or the element that the menu is called from, can you help me?
How can I implement multiple context menus with different options each on the same html page?
Thanks! :D
Awesome plugin btw!
Now I hacked library with Javascript below. Can I have feature to specific icon for items that have submenu?
$('li.context-menu-item').has('li').css(
'background','url("http://cdn1.iconfinder.com/data/icons/lullacons/bullet-arrow-right.png") no-repeat scroll right center transparent'
);
Hi, the menu does not auto hide on IE6. You can test it on your very own demo page: http://medialize.github.com/jQuery-contextMenu/demo/trigger-hover-autohide.html
Thanks & regards
I couldn't find how to do this in your documentation and please forgive me for asking what is most likely a very simple solution, but I am designer by trade who is learning to use JQuery. I am needing to put a link on the Items. Just a regular link, for example - "mypage.html" Right now my JavaScript is as such:
$(function(){
$.contextMenu({
selector: '.context-menu-view',
className: 'title-View',
trigger: 'hover',
callback: function(key, options) {
var m = "clicked: " + key;
},
items: {
"HTML": {name: "HTML"},
"PDF": {name: "PDF"},
"Excel": {name: "Excel"}
}
});
});
Thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.