lumapictures / meteor-jquery-datatables Goto Github PK
View Code? Open in Web Editor NEWSort, page, and filter millions of records reactively.
Home Page: http://jquery-datatables.meteor.com
License: MIT License
Sort, page, and filter millions of records reactively.
Home Page: http://jquery-datatables.meteor.com
License: MIT License
The following console error is thrown when loading a table state that has reordered columns ( colReorder extension )
To replicate ( assumes meteor / meteorite / node installation )
$ git clone https://github.com/lumapictures/meteor-jquery-datatables
$ cd meteor-jquery-datatables
$ git checkout stateSave
$ cd example
$ mrt add jquery-datatables
$ meteor
Go to http://localhost:3000/column-reorder and check the console, you'll see:
Exception from Deps recompute function: TypeError: Cannot read property '_ColReorder_iOrigCol' of undefined
at Object.ColReorder._fnStateSave (http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:16294:74)
at null.<anonymous> (http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:16185:22)
at http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:5029:19
at Function.jQuery.extend.map (http://localhost:3000/packages/jquery.js?265926494aaa3929cd2e30da265211c5929f37a4:544:13)
at _fnCallbackFire (http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:5028:12)
at _fnSaveState (http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:4757:3)
at http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:5029:19
at Function.jQuery.extend.map (http://localhost:3000/packages/jquery.js?265926494aaa3929cd2e30da265211c5929f37a4:544:13)
at _fnCallbackFire (http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:5028:12)
at _fnDraw (http://localhost:3000/packages/jquery-datatables.js?f5e10cc4d9dddab2d0d17445b421e10c7be210a4:2007:3)
The variable scope when the error is thrown is:
Table config options ( these are merged together when passed into datatables ):
display:
# ##### Bootstrap 3 Markup
# You can change this by setting `Template.dataTable.defaultOptions.sDom` property.
# For some example Less / CSS styles check out [luma-ui's dataTable styles](https://github.com/LumaPictures/luma-ui/blob/master/components/dataTables/dataTables.import.less)
sDom: "<\"datatable-header\"Rfl><\"datatable-scroll\"rt><\"datatable-footer\"ip>"
pagination:
sPaginationType: "full_numbers"
oLanguage:
sSearch: "_INPUT_"
sLengthMenu: "<span>Show :</span> _MENU_"
# ##### Loading Message
# Set `oLanguage.sProcessing` to whatever you want, event html. I haven't tried a Meteor template yet, could be fun!
sProcessing: "Loading"
oPaginate:
sFirst: "First"
sLast: "Last"
sNext: ">"
sPrevious: "<"
stateSave:
stateSave: true
stateSaveParams: ( settings, data ) ->
console.log 'save params'
console.log settings
console.log data
stateLoaded: ( settings, data ) ->
console.log 'loaded'
console.log settings
console.log data
stateLoadParams: ( settings, data ) ->
console.log 'load params'
console.log settings
console.log data
Seems to only be a problem with column reorder, colvis and the default tables seem to work fine.
I have a number stored as a string in my collection. It's sorting the following way:
5
4
35
34
3
...
I'd like to sort them as numbers. Here's what I've tried -- none of the commented approaches fix this.
{
title: "Quantity"
data: "quantity"
# type: "num"
# sType: "numeric"
# mData: (obj, type) -> return parseInt(obj.quantity)
# mRender: (val, type, obj) -> return parseInt(val)
}
Any ideas what would work?
Current the tables start in a collapsed state and expand when the data is availabe. This makes for a very janky page load. No bueno.
I have the following:
Template.noticesSearch.notices = function () {
return {
id: 'notices-table',
columns: [{
title: 'Date',
data: 'noticedate',
mRender: function (data, type, row) {
return moment(row.noticedate).format('DD/MM/YYYY');
}
}, {
title: 'Died on',
data: 'diedon',
mRender: function (data, type, row) {
return moment(row.diedon).format('DD/MM/YYYY');
}
},{
title: 'Family name',
data: 'familyname'
},{
title: 'First names',
data: 'firstnames'
},{
title: 'Estate value',
data: 'estatevalue',
mRender: function (data, type, row) {
return accounting.formatMoney(row.estatevalue, '£ ', 0);;
}
}],
subscription: 'all_notices',
options: {
order: [0, 'desc'],
searching: false
}
}
};
Adding the 'searching' option results in an error in the JS console:
Uncaught TypeError: Cannot read property 'value' of undefined Query.mixin.coffee:86include.mapTableState Query.mixin.coffee:86
DataTableComponent.fnServerData DataTables.component.coffee:56
later underscore.js:731
I was led to believe, from the datatable docs, that this option would allow me to suppress the live search/filter box.
As suggested on the Datatables.net forum
I've noticed every now and then that records to not update when the underlying collection changes.
From what I have seen this is only the case in property updates, inserts and remove seem to work just fine.
Hey @austinrivas I'm testing the changes for the reactive query & server-side limiting. One thing I just noticed is that the "selector" option when initialising DataTables is no longer working. Is this an intended change or a bug?
I've updated from v0.1.24 to v1.0.1.
Template:
{{> DataTable table}}
Helper:
Template.portfolio.helpers({
table: function() {
return {
subscription: "holdings",
selector: "portfolio-table"
};
}
});
});
When the DataTable loads, the HTML looks like this:
<div id="DataTable-122" class="dataTable-container">
<div id="DataTables_Table_0_wrapper" class="dataTables_wrapper no-footer">
...
</div>
</div>
Prior to the v1.0.1 update, the div id was "portfolio-table", not "DataTables_Table_0_wrapper".
Currently properties of nested arrays can be displayed using an mData
method instead of assigning the property key directly.
mData: ( rawData, call ) ->
max = "null"
if _.isArray rawData.someArray
rawData.someArray.forEach ( doc ) ->
if doc.someProperty
if doc.someProperty > max or max is "null"
max = doc.someProperty
return max
This should be cleaned up and abstracted away from the config object, and prepare the global search query to search the nested arrays for that property.
It's the only decent solution for meteor everything for meteor table just sucks, There is no complete solution maybe super simple table without almost any functions the only way is to have datatables (my opnion) so my question is this dead? I see so many bug reports no activity. I don't have the expertise to fix those bug, It's weird that no one take this project and keep on developing!
I'm trying to disable paging on the Reactive Query example. It works fine on the Blaze Templates example so I'm guessing it has something to do with the data source?
Using the bundled example with only a small modification (200 rows instead of 100k)
Disabled paging by doing the following modification in example.controller.coffee
options:
paging: false
Shows: Showing 1 to 0 of 200 entries
Is that not the correct way to disable paging?
I have Responses collection that is subscribed to on multiple pages and filtered in different ways. On the initial view of one of these datatables everything works great. However, when i navigate to a different view (where the Responses collection is queried differently), the data show up correctly but the pagination is messed up because it is keeping the iRecordsDisplay and iRecordsTotal from the first subscription. The server side debug is showing the correct count:total and count:filtered, but it doesn't show up correctly on the client.
Hello,
would be great if the dataTable source would get updated to the latest version. The new version added easy translation for the search placeholder:
DataTables/DataTables@2300aa8
Thanks Dominic
wait-on-lib lets you dynamically load libraries through the controller or even through the template component itself.
Could potentially lower the on load size of this package.
@austinrivas I seem to be getting an error every time I try to remove a row from a table.
Here's the exception:
Exception in queued task: TypeError: Object #<Object> has no method 'collection'
at Object.collection.find.observe.removedAt (packages/jquery-datatables/lib/mixins/Publish.mixin.coffee:53:40)
at observeChangesCallbacks.removed (packages/minimongo/observe.js:142)
at self.applyChange.removed (packages/minimongo/observe.js:71)
at packages/mongo-livedata/observe_multiplex.js:163
at Array.forEach (native)
at Function._.each._.forEach (packages/underscore/underscore.js:105)
at Object.task (packages/mongo-livedata/observe_multiplex.js:157)
at _.extend._run (packages/meteor/fiber_helpers.js:150)
at packages/meteor/fiber_helpers.js:128
So I jumped into node-inspector and I think I know what the problem is. in the removedAt
function, it tries to call collection()
on args
instead of component
. See the code block below.
observer: function(args) {
var component;
component = this;
return this.collection().find(args.filteredQuery, args.options).observe({
addedAt: function(doc, index, before) {
component.updateCount(args);
args.publish.added(args.collectionName, doc._id, doc);
args.publish.added(component.collection()._name, doc._id, doc);
return component.log("" + (component.subscription()) + ":added", doc._id);
},
changedAt: function(newDoc, oldDoc, index) {
component.updateCount(args);
args.publish.changed(args.collectionName, newDoc._id, newDoc);
args.publish.changed(component.collection()._name, newDoc._id, newDoc);
return component.log("" + (component.subscription()) + ":changed", newDoc._id);
},
removedAt: function(doc, index) {
component.updateCount(args);
args.publish.removed(args.collectionName, doc._id);
args.publish.removed(args.collection()._name, doc._id);
return component.log("" + (component.subscription()) + ":removed", doc._id);
However, being a bit of a newb with coffeescript, I can't work out where this is mapped from the .coffee file in order to do a Pull Request.
I believe this is related to the count subscription failing ( duh ), just not sure where yet.
I need to show tables that have incomplete data values in rows, some rows have the values defined, others do not, in mRender I am doing a try/catch to catch undefined values, but for "data" field in the columns array, if the value is undefined in the collection users get a dialog box detailing the error. When they click ok, the table renders. But I don't want users to see this dialog box.
It seems the solution for datatables is: "$.fn.dataTableExt.sErrMode = 'throw';" but when I try this it put the error in the console log, but it prevents the table from rendering.
Any ideas?
Thanks for the help!
A friend of mine wanted to install jquery-datatables but GitHub shows that the build is failing, so they chose reactive-table instead.
Hello,
I just made a quick tryout to show all Meteor.users in a DataTable to test this plugin.
Template.userList.users = function () {
return {
id: "operator-user-list",
columns: [
{
title: "ID",
data: "_id"
},
{
title: "First name",
data: "profile.firstName"
},
{
title: "Last name",
data: "profile.lastName"
}
],
subscription: "operatorAllUser"
}
};
Template.html:
{{> DataTable users}}
Publication:
var UserTable = new DataTableComponent({
subscription: "operatorAllUser",
collection: Meteor.users
});
UserTable.publish();
The _id
of the user is displayed, but profile.firstName
and profile.lastName
is empty. Thanks for some infos.
Hi there, I have some simple questions that I haven't been able to figure out with this package.
question 1. In the normal Meteor way, I'd publish a collection like this (sorry I don't know coffeescript)
Meteor.publish('profiles', function(listId) {
check(listId, Match.Optional(String));
return Profiles.find({
listId: listId
}
});
but what is the equivalent with dataTables if I wanted to pass in a listId? Just from the example, I have the following that returns all collection items rather than a subset since I am not adding listId to the query.
// how do I add {listId: listId} ?
var ProfileList2 = new DataTableComponent({
id: "ProfileList2", // <--- what is id in this case?
subscription: "profileList2",
collection: Profiles
});
ProfileList2.publish();
question 2. I have a table that has returned, but some columns are blank. I think it has to do with the nested object structure. So if I have a Profile with a name at "contact.name" that column returns blank.
profiles: function() {
return {
columns: [{
title: "Name",
data: "contact.name" // this column is blank, am I doing this incorrectly?
}, {
title: "Emails",
data: "email" // this column is ok and returns the email address as desired
}],
subscription: "profileList2"
};
}
I hope I am clear. Let me know if it doesn't make sense, thanks for any help.
Passing sort: undefined
as a mongo query option causes the Collection args check to throw an error.
Meteor.Collection._getFindOptions
Easily fixed by guarding the query options.
I've noticed that the pagination for Collections-based datatables just doesn't work sometimes. It seems to happen when you navigate away from a page with a datatable on it (via iron-router) then navigate back to the original page and use the pagination.
To Reproduce:
mrt install; meteor
localhost:3000
in browserloadDummyImports()
(that will load a bunch of trades to populate the table)I'll try and reproduce it with a simpler example but here are some screenshots from my finance project in the meantime.
@austinrivas It seems that the change you've made to allow limiting the publication data won't work for my use-case, or any use-case involving restricting the dataset to a particular user.
In my example, this.userId
is not available when I initialise on the server:
PortfolioTable = new DataTableComponent({
subscription: 'holdings',
collection: Holdings,
query: {'userId': this.userId} // this.userId == undefined
});
PortfolioTable.publish();
I'm guessing this is because it only calls the query once when the server starts up (when it doesn't know any client details), instead of calling the query each time a new subscription is made, as other publish functions do.
Given this is the case, it seems like the usage of this feature is be pretty limited, security-wise. Or perhaps I have just called it incorrectly?
Currently the datatable is locked to the initial configuration and base query when the component instance is created. In order to change the base query a new component must be instantiated to replace the current component.
Ideally the base query and table configuration options would be reactive and could be updated from outside of the datatable component.
An example use case would be to have an external date range widget that updates the base query for the datatable and only returns documents within that date range.
Hello,
I tried to use the bootstrap-3 plugin from the DataTables source, but the plugin html-structure is getting ignored. Not sure if this is an issue of this package but I would be curious if anyone got this running:
http://datatables.net/examples/styling/bootstrap.html
https://github.com/DataTables/Plugins/tree/master/integration/bootstrap/3
Would be great if this plugin would provide the inclusion automatically, I guess there are many people using Bootstrap 3 currently. Thanks
I'm having a problem where if you have a reactive filter set, and you go to another page, and then come back, the available rows get messed up, and some rows become non accessible.
Here is how to recreate the issue:
Take note that the bottom of the table says "Showing 1 to 10 of 101,266 entries"
I've tried all sorts of things like resetting session variables in my own app that I using jquery-datatables with, I think there may be a problem with the subscription that the package controls getting stuck when a filter is set and the route changes. So when you come back it is stuck somehow.
Any ideas?
This is an amazing package by the way, thank you!
I see that jquery-datatables depends on luma-component, but it doesn't include styles on purpose. Just checking whether this may be a leftover from the luma-datatables days... if luma-component is explicitly required, maybe it's worth mentioning that in the README?
Implement the dataTables colVis Plugin
Investigate using arunoda's find-faster package to improve dataTable performance and lower cpu load.
There are two column filtering options available :
@stevenswanson would you mind weighing in and letting me know which you prefer, or both?
@austinrivas I'm wondering if there would be any way to modify the table columns reactively. For example, I'd like to be able to change which columns are shown based on a checkbox, to switch between e.g. percent vs absolute performance.
Something like the below, where Session.get('displayPercent')
is linked to a checkbox, so the change
column switches data source when it is checked and unchecked.
columns: [{
title: "symbol",
data: "symbol"
},{
title: "price",
data: "price"
},{
title: "change",
data: function() {
return ( Session.get('displayPercent') ? 'changePercent' : 'change' );
}]
Outside of my specific use-case, I think it would be a useful feature for doing things like selecting columns to show in a table, etc.
Would there be any way to achieve this?
mrt install; meteor
localhost:3000
in browserTable displays NAB.AX rows in the table
Table info shows filtered info, e.g. "Showing 1 to 10 of 16 entries (filtered from 32 total entries)"
Table pagination is reduced to only 2 pages
Table displays "No matches found", until you use the pagination to go to the 2nd page
Table info still shows all rows
Table pagination is not reduced (still shows all pages)
Hi @austinrivas, I've been trying to use this package to implement a portfolio/holdings table for a finance app and I'm having trouble getting it to behave reactively.
For example, I'm trying to show/hide holdings with no shares based on a checkbox.
See screens for how I want it to behave:
Show "closed positions" (i.e. holdings with zero shares):
So I bind the "show closed" checkbox to a Session variable zeroShares like so:
'click #show-closed': function(event, template) {
if ( Session.get('zeroShares') === 0 ) {
Session.set('zeroShares', undefined);
} else {
Session.set('zeroShares', 0);
}
}
Then I link this to the query
field on initialization like so:
query: {'userId': Meteor.userId(), 'shares': {Session.get('zeroShares') }
I was hoping this would reactively rerun the query when the Session variable changes but this doesn't appear to be the case. Only adding/removing to the Holdings collection would probably work but that would mean adding and removing holdings on both the client and server every time they check the box; seems like a clunky solution for a presentation-layer issue.
Any ideas on this? I can provide more code if you think it is an implementation issue rather than a limitation of the package.
Note: I include the 'userId' part in the query because I don't seem to be able to restrict the Holdings collection that I publish via DataTables.publish on the server-side; this seems really bad from a security point of view (i.e. every client has access to all holdings if they wish). Any tips for limiting the published collection server-side?
Both use the same subscription, but with a different client-side initial query. Only the second table renders.
Implement datatables colReorderWithResize Plugin
Hi Austin, thanks for your hard work on jquery-datatables package. It's very awesome :-) Since Meteor version 0.8.3 has just released, could you please help upgrade jquery-datatables for the new version? Thank you.
Following is my current temporary workaround F.Y.I. For maintantance considerations, I wrote these codes in an additional file, rather than modifying the existing codes in the package.
# patch for jquery-datatables v1.0.5 for Meteor v0.8.3
DataTableComponent.prototype.oldRendered = DataTableComponent.prototype.rendered
DataTableComponent.prototype.rendered = ->
that = this
setTimeout ->
that.oldRendered()
, 0
return
DataTableComponent.prototype.setQuery = (query) ->
if @subscription
@prepareQuery() unless @query
#unless @query() is query
if true
@query query
@rendered()
Template.DataTable.created = ->
@.__component__ = @.__view__
dataTableInstance = new DataTableComponent @
Hi @austinrivas thanks for this awesome package! A great contribution to the meteor environment.
I'm been using with success, but after configuring 3 datatables I notice that all the data from the DataTableComponent are subscribed to all pages.
Notice some patterns:
-All the data is subscribed in the DataTable pages. ( saw via find().fetch() in browser console )
-if I change something in the same collection added to DataTable in another page the data are subscribed in this another page.
Server side
CustomersTable = new DataTableComponent({
subscription: "customers_table",
collection: Meteor.users
});
CustomersTable.publish();
Client side
Template.AdminCustomers.customers = function() {
return {
columns: [
{
title: "ID",
data: "_id"
},
{
title: "Creation Date",
data: null,
mRender: function(data, type, row) {
if (row.createdAt === undefined) {
row.createdAt = "";
}
if (row.createdAt) {
return moment(row.createdAt).format('DD/MM/YYYY');
} else {
return row.createdAt;
}
}
},
{
title: "Email",
data: null,
mRender: function(data, type, row) {
if (row.emails[0].address === undefined) {
row.emails[0].address = "";
}
return row.emails[0].address;
}
},
{
title: "First Name",
data:null,
mRender: function(data, type, row) {
if (row.profile.firstName === undefined) {
row.profile.firstName = "";
}
return row.profile.firstName;
}
},
{
title: "Last Name",
data: null,
mRender: function(data, type, row) {
if (row.profile.lastName === undefined) {
row.profile.lastName = "";
}
return row.profile.lastName;
}
},
],
subscription: "customers_table"
};
};
{{> DataTable
columns=customers.columns
options=customers.options
subscription=customers.subscription
}}
Where do you think I can look to fix this problem?
Thanks man!!
From the demo (nestedTable), I find this line:
tr = event.currentTarget.parentElement
row = @self.$.api().row( tr )
Then I tried @self.$.api().row(tr).data()
and it works.
So @self.$.api()
in the event handler is returning the datatable's api? If so, can you add it to the readme?
Support the ability to render a Blaze Template into a datatable cell via a columns mRender
method.
In magic code land where everything works the way I want the code would look like this ->
mRender: ( dataSource, call, rawData ) ->
return UI.renderWithData Template[ 'some_template'], rawData
In the sample app, when navigating to page 2 (or higher) in the results panel there are no entries shown, only the text "No matching records found". However in the bottom page navigation it says: "Showing 11 to 20 of 83,333 entries." This happens on a clean installation using meteor version 0.8.0.1.
Thanks for the great package.
I wonder if there is a clean way how to limit reading access to the collection.
In a normal publication I would limit the access like this:
Meteor.publish('MyCollection', function() {
if(!Roles.userIsInRole(this.userId, ["admin"])) {
return false;
} else {
return MyCollection.find();
}
});
Is there a way to archive the same with the DataTableComponent
?
I'm injecting a falsy condition into the query when my role doesn't match:
var RowsTable = new DataTableComponent({
subscription: "MyCollection",
collection: MyCollection,
debug: "userId",
query: function(component) {
if(!Roles.userIsInRole(this.userId, ["admin"])) {
return {
dummyValue: "doesn't exist"
};
} else {
return {}
}
}
});
RowsTable.publish();
But that feels little hacky. Is there something better?
Thanks!
Thank you for making this package. It seems I cannot get the reactive query to work properly. First, I include my datatable component:
{{> DataTable groups }}
Then I setup the data in my controller:
Template.manageGroups.groups = function() {
return {
columns: [
...
],
subscription: "all_groups",
query: Session.get('reactiveQuery')
}
}
I publish data server side:
var GroupsTable;
GroupsTable = new DataTableComponent({
subscription: "all_groups",
collection: Groups,
query: function(component) {
component.log("userId: " + this.userId);
return { userId: this.userId }
},
debug: "userId"
});
GroupsTable.publish();
I tried to followed the sample code for reactive query
Template.manageGroups.helpers({
reactiveQuery: function() {
return Session.get('reactiveQuery');
}
});
Template.manageGroups.events({
'change #filter-groups': function (e, t) {
var query = Session.get('reactiveQuery'),
value, active, filter;
filter = $('#filter-groups').val();
if (filter === "all") {
delete query.isActive;
} else {
if (filter === "active")
value = true;
if (filter === "inactive")
value = false;
active = {
isActive: value
}
_.extend(query, active);
}
Session.set('reactiveQuery', query);
}
});
When the page loads, I can filter the table by selecting one of the options. If I select another option, however, the table doesn't redraw, so I can only filter once. I also tried to get it to work by creating a datatable that already exists in the DOM with no success. Do you have any suggestions on how I can get this to work? Thank you for your time.
Make the table responsive to window size changes, not sure if this should be via CSS or dataTables fnDraw
method.
using the latest meteor & datatables version the blaze template rendering as used in the examples was not working for me anymore. after some test I found a perfect (for my case) solution by defining a column like this:
{title: 'name', data: 'name', fnCreatedCell: function (td, cellData, rowData, iRow, iCol) {
UI.insert(UI.renderWithData(Template.mytemplate, rowData), td);
}}
the nice thing is, that meteor will update the table cell automatically if the data sources that are used in the template get updated!
I've just got the Meteor version of DataTables up and running (and awesome!), but I have one problem.
I'd like to use the Bootstrap styling, but because of the way the meteor datatables package works, the bootstrap.js fires before the DataTable has been created so does not actually change the styling.
Is it possible to force the bootstrap.js to be run after the DataTables has been loaded, using the same js file? to get the nice styling of prev/next buttons etc
Rachel
If I follow the example using a reactive query, and perform a filter on the table, only rows on the current page are considered for the filter. This means that searches are always limited to the current page.
It would be cool if the live demo had a simple console on every page that allowed the user to easily add new entries, and thereby see the reactivity in action.
@austinrivas I'm using the fnInitComplete callback to do some DOM manipulation (basically to add some custom buttons to the table header along with the filter and length). However, it appears this is not playing nicely with the reactive query because every time it changes, the callback is re-run.
I just thought this was a little weird because using other elements such as the table length, the pagination or the filter don't cause the callback to be re-run.
I know the DOM manipulation is a bit of a hack anyway, so it's not a huge deal, but I just thought I'd flag it.
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.