peerlibrary / meteor-blaze-components Goto Github PK
View Code? Open in Web Editor NEWReusable components for Blaze
Home Page: http://components.meteorapp.com/
License: BSD 3-Clause "New" or "Revised" License
Reusable components for Blaze
Home Page: http://components.meteorapp.com/
License: BSD 3-Clause "New" or "Revised" License
What would be good API for accessing parent data context? Blaze's access by fixed number of levels is really fragile to cod refactoring.
Do we even need it? In the past, in most cases when I needed parent data context was to access what we now have a as a top-level component data context.
And maybe we just have to support accessing parent components, and then use .data()
on them to access the data context there?
So, what are use cases?
Router.route('/', {
name: 'MyRoute',
template: 'MyComponent'
});
Still trying to wrap my head around the whole concept, so bare with me if these are silly questions :)
I have my (mentioned earlier) Viewstack setup working in BC (Blaze-Components) now. And apart from an untrackable "must be attached" exception from somewhere deep within Blaze itself, everything is going fine.
So when I wanted to go the next step, I started thinking about "extend" in BC. It means the class itself, I get that. But what are the current thoughts about the template in the parent? E.g., Let's say I have a BC called ParentComponent, which has a template associated with it. In that template I could render all "chrome" for that component. Then if I want to create ChildComponent, I only want to add specific content for that Child without having to copy all the html from the ParentComponent.
In classic Blaze, I did something similar with:
<template name="Child">
{{#wrapper}}
My child content
{{/wrapper}}
</template>
Acces to "view": I'm already having trouble with everything related to views/templates/templateinstances and what not, I hoped the components wouldn't add to that list but abstract it all away. That maybe coming in the future. But until then I found that the only way to access the view the component is related to was through _componentInternals. Maybe something like a "getView" on the component? Preference is to abstract it away though :)
Mixins.Scrollable = BlazeComponent.extendComponent({
onRendered: function () {
if (this.find('.scrollable').length) {
// Do something
}
}
});
Components.ContentBody = BlazeComponent.extendComponent({
template: function () {
return 'ContentBody';
}
mixins: function () {
return [Mixins.Scrollable];
}
}).register('ContentBody');
<template name="test">
{{#ContentBody}}
asdfafwefwaef
{{/ContentBody}}
</template>
I'm getting this error:
Exception from Tracker afterFlush function:
debug.js:41 TypeError: Cannot read property 'find' of undefined
at BlazeComponent.(anonymous function) [as find] (http://dev.profab.io:3003/packages/peerlibrary_blaze-components.js?9b7844536f047cd606db4358273147e3c555de69:875:63)
at Mixins.Scrollable.Components.BaseComponent.extendComponent.onRendered (http://dev.profab.io:3003/client/mixins/scrollable.js?71c7734c2f592e839680099e36edd14d66ddc0cc:3:14)
at BlazeComponent.renderComponent.Tracker.nonreactive.registerHooks.onRendered (http://dev.profab.io:3003/packages/peerlibrary_blaze-components.js?9b7844536f047cd606db4358273147e3c555de69:712:34)
at http://dev.profab.io:3003/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:3155:22
at Function.Template._withTemplateInstanceFunc (http://dev.profab.io:3003/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:3476:12)
at fireCallbacks (http://dev.profab.io:3003/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:3151:12)
at null.<anonymous> (http://dev.profab.io:3003/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:3244:5)
at http://dev.profab.io:3003/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:1778:14
at Object.Blaze._withCurrentView (http://dev.profab.io:3003/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:2197:12)
at http://dev.profab.io:3003/packages/blaze.js?a5c324925e5f6e800a4c618d71caf2848b53bf51:1777:15
Currently we do not really provide a way to register global helpers which would work inside a component context. You can access the component from a global template helper (using Template.instance().get('component')
) but this is ugly and mostly an implementation detail.
We might want to provide a simple helper which would register something like a global template helper, just that this
would be the component, as other methods are bound otherwise.
One additional advantage would be that helper would not depend on data context by itself if it would not call .data()
. (All template helpers otherwise depend.)
I try to include a template (not a component) from a blaze-component using {{> Template.dynamic}}
, but it causes an infinite loop.
Here is a minimal reproduction: https://github.com/mquandalle/blaze-components-template-dynamic. In this example commit-1 is working fine, and then after I transform my template into a blaze component in commit-2 there is an infinite loop.
Provide equivalents to Blaze.render
, Blaze.renderWithData
and Blaze.remove
.
For now you can use for Blaze.render
:
renderedView = Blaze.render MyComponent.renderComponent parentComponent
or
renderedView = Blaze.render BlazeComponent.get('MyComponent').renderComponent parentComponent
For renderWithData
:
renderedView = Blaze.renderWithData MyComponent.renderComponent(parentComponent), data
And Blaze.remove
:
Blaze.remove renderedView
This is a potential function for BlazeMixin
(the BlazeComponent
extension that might or might not be part of the package).
I have a hard time coming to terms that the implementer of the component needs to know what functions the mixins are overriding (or the component is overriding from them, depending which way you look at it).
We'll see in practice how often this would be useful, but if more simple cases like PersistentInputMixin
(previously Frozen
) from the demo could function by simply augmenting the parent class, a helper for that might be worth it.
So you would say:
override: ->
value: (_super) ->
@storedValue.get() or _super()
This is exactly how we have written this function through inheritance:
value: ->
@storedValue.get() or super
(We could also go for Super
instead of _super
.)
I did not test what happens if two mixins override the same function โฆ I guess they would just get chained in order of mixins (assuming they are instantiated in that order), so it's like inheritance from the component on top and mixins going from first to last. So the last mixin is also at the bottom of this 'inheritance' chain. It's up to them to call _super()
to travel up the chain to the component on top. Which is not the nicest, since the idea of composition is that mixins shouldn't have to worry about each other.
Anyway, the code to make override
work is:
onCreated: ->
super
parent = @mixinParent()
for name, func of @override()
old = parent[name]
parent[name] = (args...) =>
_super = (args...) ->
old.call parent, args...
func.call @, _super, args...
I wonder if I could modify the code so that all mixins who overrided a function are called in parallel instead of as a chain. And they all get the same _super
that is component's implementation. A downside of this is that _super
can get called multiple times, which doesn't play well with functions that have side effects. Neither is it clear what to actually return as the final value from the function (first result? last?).
Global helpers don't work in components, which might be a problematic. I wonder if by default BlazeComponent
should inherit all global helpers? Not sure what the best solution is to this, so what I did was create a super base BlazeComponent that essentially just encapsulates all global helpers and then created components that extend off of it so that I can use the global helpers:
Components.BaseComponent = BlazeComponent.extendComponent(Blaze._globalHelpers);
You can get it using Blaze.getView(...).templateInstance().get('component')
, but those are internals one should probably not have to know about.
Where should this helper be? As a class method on BlazeComponent
?
I'm trying to call a mixin method as per the docs.
Code:
class MyComponent extends BlazeComponent
@register 'MyComponent'
template: ->
'MyComponent'
mixins: ->
[BlazeComponent.getComponent 'MyMixin']
events: -> [
'click button': @onClick
]
onClick: ->
@callFirstWith null, 'clickHandler'
class MyMixin extends BlazeComponent
@register 'MyMixin'
clickHandler: ->
console.log 'ive been clicked'
If an event handler is set inside the mixin, i.e. 'click button': @clickHandler
where the button is inside MyComponent
, it works as expected.
I can also access @mixinParent()
, so it appears to be set up correctly.
However if I try to call the clickHandler
method from the parent, it is undefined.
Uncaught TypeError: undefined is not a function
Currently, Blaze uses to store data context a reactive variable with default equality function:
A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set. If it returns true, no set is performed. If omitted, the default
equalsFunc
returns true if its arguments are===
and are of type number, boolean, string, undefined, or null.
This makes content being rerendered potentially unnecessarily. In fact, often just helpers are rerun and Blaze notices that there is nothing to update DOM with and does nothing, but still. More complex logic we have in components, more complicated it can get.
Currently, Blaze Components improve on the situation because there is no automatic dependency on the data context, but it is registered only when you access .data()
or .currentData()
. But still. Dependency is registered using the default equality.
It might be useful to provide alternative data context access methods using different equality functions:
===
), assuming that data context is immutable (or that you do not care if content inside objects in data contexts change, only if the whole object change)EJSON.equals
for structural equalitySo maybe someting like .dataReferential()
and .dataStructural()
?
Imagine that I define a openable
mixin with a few methods on it (open()
, close()
, toogle()
, and isOpen()
). I then use this mixin in a UI component.
In the body of this component methods I find it very unatural to call this.callFirstWith(this, 'open');
where what I simply want to express is this.open()
. Maybe the mixins
functions could put mixins methods directly on the parent component?
This would be similar to how React does it:
var SetIntervalMixin = {
componentWillMount: function() {
this.intervals = [];
},
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
},
componentWillUnmount: function() {
this.intervals.map(clearInterval);
}
};
var TickTock = React.createClass({
mixins: [SetIntervalMixin], // Use the mixin
getInitialState: function() {
return {seconds: 0};
},
componentDidMount: function() {
this.setInterval(this.tick, 1000); // Call a method on the mixin
},
tick: function() {
this.setState({seconds: this.state.seconds + 1});
},
render: function() {
return (
<p>
React has been running for {this.state.seconds} seconds.
</p>
);
}
});
Putting an autoform inside a component is gonna break isn't it?
When a component includes another component, what would be good API to access that parent component from the included one? What are use cases? Message passing/communication across components? Or should that be simply done through custom DOM events?
Allowing accessing the parent component would allow accessing parent data contexts for free, see #1.
But we do not want to provide an API where one has to specify a fixed number of levels of traversal to the wanted component. While code refactoring would often be mostly done on template basis, so relations between components would change rarer, it is still fragile because you cannot wrap a component with another component without then having to change number of levels to traverse in the most inner component.
Moreover, finding the first component of some class might as well not work as intended because if you wrap with a component of the same class, things break as well.
Do we want to allow accessing only the parent component, and not arbitrary level of ancestors?
So, what are use cases?
Similar to Template.dynamic, but for components.
We could make a site which would be a simple package explorer for Meteor packages which provide Blaze Components. There is an API.
It would be great if we could put into Meteor package metadata somehow a way to display an example of a component automatically in the list. So that it would be more like a gallery of components one can browse through. Buttons, tabs, dialogs, you name it.
Of course this app should be written using Blaze Components. :-)
Currently we have a way to pass arguments to a component when it is included:
{{> ComponentName args a='42'}}
But if there is a method on the current component you cannot call:
{{> renderMyComponent args a='42'}}
We should find a way that renderMyComponent
would be called with those arguments the same as it would be called when calling a method as a helper {{renderMyComponent a='42'}}
.
This is tracked in Meteor as meteor/meteor#3913.
Any ideas how to do this?
Hi! Thanks for the awesome package. I'm attempting to convert most of my site structure over. There's one issue that I need clarification on, and maybe you can help.
I see that component has access to the underlying template utility methods. Currently I am using subs-manager (https://github.com/meteorhacks/subs-manager) to manage and cache subscriptions. Are there any plans to support this? Or will I have to manually load and unload using onCreated / onDestroyed?
We could add a bit modified version of Spacebars.call
which makes sure that all undefined values
are converted to null
values. This makes it much easier to work with template inclusions
{{> foobar}}
which require inclusion to be a Blaze Template or null
, but not undefined
.
Additionally, if value is null
or undefined
, do not complain about not being a function.
This then works much more like CoffeeScript ?
, so that {{foo.bar 'test'}}
is more like
{{foo?.bar? 'test'}}
instead of failing if bar
is not defined. In practice, this allows
us to do things like {{> this.lookup.renderEditor}}
and {{editor.getValue 'foobar'}}
even if this
or editor
is undefined
.
See meteor/meteor#4230 and meteor/meteor#4232.
This is not a necessary change for Blaze Components to work. But it makes things really simpler sometimes.
Spacebars.call = (value) ->
if _.isFunction value
# Evaluate arguments if they are functions (by calling them).
newArgs = []
for i in [1...arguments.length]
arg = arguments[i]
newArgs.push if _.isFunction(arg) then arg() else arg
# Always return null instead of undefined.
value.apply(null, newArgs) ? null
# If value is not null or undefined, then return it as it is.
else if value?
if arguments.length > 1
throw new Error('Can\'t call non-function: ' + value)
value
# But if it is null or undefined, always return null instead.
else
null
with this example from the demo:
mixins: -> [
....
new StorageMixin Values, 'value', => @data().id
]
class StorageMixin extends BlazeComponent
constructor: (@collection, @fieldName, @selector) ->
I would like to change
new StorageMixin Values
to something like
new StorageMixin @data().collection
so I can do
{{> MyComponent collection='Values'}}
I do want the component to re-render if the collection changes, so do I use args in the MyComponent constructor? what is the correct way to do this?
I'd like to see a fullfeatured TodoMVC example with Blaze Components.
It would be interesting to compare with https://github.com/grigio/todomvc-meteor-react
I think requireMixin
better describes what the function does than addMixin
. Add
doesn't describe that the function will not do anything in case the mixin is already present. With Require
it's more intuitive to imagine that multiple mixins can call it. And it works just like require
calls from other platforms (node etc).
Current API with folding and aleady*
flags is cumbersome. It is questionable how much composability it really offers. Maybe it would be better to simply allow each mixin to guide calling through getFirstMixin
and getNextMixin
(see #3). And maybe those methods should simply check the status of the DOM before doing anything. If they observe that DOM was already inserted, they do not do anything, for example. Or do it differently.
So in some way communication between mixins would work through node objects themselves. Similarly to how we communicate between event handlers by calling methods on the event object itself.
Currently we are attaching mixins' first, then component's. See a1fdbc8. But this was just a gut feeling that it is more reasonable. What are arguments for and against for them?
I want to write something like this in my app:
{{> MyComponent shadow disabled}}
and something like this in my component template:
<my-component {{attr}}></my-component>
with the output being
<my-component shadow disabled></my-component>
what's the best way to do this? can I do it without the use of a helper, like I can if I write class='{{name}}'
in the helper and class='{{class}}'
in the template?
It's not clear how to use args
, especially if you haven't used Spacebars.kw({key: 'xyz'})
before!
From tests, componentParent().renderRow()
when called through templates does not set parent component correctly, because Template.instance()
is not available at that time.
There is a commented out tests case for it in testBlockHelpersStructure
test.
A consequence of: meteor/meteor#4386
Is it possible for two or more components to share a mixin's data without having to instantiate multiple instances of that mixin or does it work like this already?
For example, I'd like this mixin to be like a data source that these different components read from.
I think the documentation and demo app text content would benefit from a native English speaker going over it and fix things. :-)
I think we should remove callFirstMixin
method. While it helps with the common case, I think that getFirstMixin
is enough. You can always do .getFirstMixin('property')?.property()
. This would also give you an exception if property
is not a function. Which we currently ignore in callFirstMixin
and return undefined
. Which makes it impossible to distinguish between an error and returned value undefined
.
callMixins
and foldMixins
are interesting, but maybe they should not be part of the core API. Instead, a more low-level method could be offered:
getNextMixin: (mixin, propertyName) ->
This would return the next mixin with propertyName
after the mixin
mixin. In some way this is similar to super
, just that it moves across mixins. So from a component you call:
foo: ->
@getFirstMixin('foo')?.foo()
And that mixin can then do:
foo: ->
@mixinParent().getNextMixin(@, 'foo')?.foo()
In some way, mixins themselves control the traversal. Instead of caller controlling when calling callMixins
and foldMixins
(it goes over all mixins no matter what).
And getFirstMixin('foo')
could be simply the same as getNextMixin(null, 'foo')
. Or we should have getFirstMixin(propertyName, [mixinToSearchFrom])
. Or getMixinWith(propertyName, [mixinToSearchFrom])
?
(What would be a way then to implement callMixins
and foldMixins
using getFirstMixin
and getNextMixin
?)
As discussed in this ticket, it would be maybe useful to allow mixins to configure whcih template is used. This would allow for an existence of a mixin component authors could use to make others replace the template with some other official (instead of overriding template
class method on prototype).
I was working on a project with BlazeComponent 0.5.0 and everything was running smoothly.
I upgraded to 0.6.0 and now the reference of this/@
has no template instance. The templates are not rendering as well. Any thoughts?
If these two things are almost always the same, is there an occasion why we would make them different from each other?
is there anything to prevent the following from working? (where app is the only package installed using meteor add
, and the others are added via dependencies)
BUTTON-BASE
/packages/button-base/button-base.coffee
class buttonBase extends BlazeComponent
@register 'buttonBase'
....
ANOTHER-BUTTON
/packages/another-button/package.js
api.use([
'button-base'
])
/packages/another-button/another-button.coffee
class anotherButton extends buttonBase
@register 'anotherButton'
APP
/packages/app/package.js
api.use([
'another-button'
])
Currently I'm getting this error:
Uncaught ReferenceError: buttonBase is not defined
I assume it's a load order issue?
Update: I copy and pasted one of the demos into a single file (components.coffee) in a barebones hello meteor app, which of course works. But if I split it into two files (componentOne.coffee componentTwo.coffee), I get the same issue.
I've been through the tutorial and looked over the docs again, and it's not clear what the problem is...
You do not have to export [classname] from your package for components to be available in templates throughout your project. The registry of components is shared between all packages and the project.
What am I missing?
getMixinWith
allows to not specify afterMixin
, but expects it as the first property. If we change the signature to:
getMixinWith: (propertyName, afterMixin) ->
we can have cleaner calls getMixinWith 'value'
instead of getMixinWith null, 'value'
Same applies to callMixinWith
.
I also propose to change callMixinWith
to something else. callMixinWith
to me doesn't sound great, because it sounds ambiguous to what is being called (are you calling a mixin? how do you call a mixin?). It works really well for getMixinWith
as in getMixinWith 'value'
, but in the call case I hope we can find something better, ideally more aligned to super
. This should go hand in hand with callMixins
that returns the array of results.
Possible ideas:
callMixin 'value'
and callMixins 'value'
This implies that we want value
that comes from a mixin. You don't care which mixin, just that it comes from a mixin, which is exactly what this method does.
callMixins 'value'
and callAllMixins 'value'
Because the call does in fact go over all the mixins, this naming preserves more of how the thing is implemented. So you call mixins to find value
. And if you want all the results (in an array) you are specific to call all mixins.
fromMixin 'value'
and fromMixins 'value'
or
fromMixins 'value'
and fromAllMixins 'value'
Alternative naming that more explicitly expresses that we want value
that comes from a mixin. But it loses the maybe important notion that a function call is executed.
whoops
It doesn't work by just passing the registered component name into the template property of Template.dynamic.
All going great when included with {{> myTemplate}}. Kudos. But my app uses a lot of Blaze.renderWithData to render the state of the app, so no routers.
O couldn't get the BlazeComponent class matching with the template I'm rendering to trigger. Is it possible that I need to do extra actions to kick it off after a Blaze.render().?
This example doesn't work if you wrap {{> subTemplate}}
inside a Blaze Component block helper.
Here's a reproduction:
http://meteorpad.com/pad/ZMbC8Ta6ocS45MySk/Blaze%20Component%20Test
I would actually need to pass currentComponent
into it to access it.
If the block helper was a regular Blaze block helper, it has no issues accessing the component instance.
First of all, ๐ for this. I haven't got time to use it yet, but the docs and demo/tutorial look impressive etc.
I totally understand the possibilities of mixins, but I'm hesitant about it because there's no real ES6 way for this yet, and as we know ES6 is here. I wonder if you have any thoughts on this issue and if you're worried that some core functionality will be rewritten as things take shape (or worse, a project is abandoned because of it).
Some references;
https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750
remix-run/react-router#659
Cheers
Not sure about this, but trying to link a child to a parent by reacting on a "this.componentChildren" count. It seems it's triggered when adding child components, but not when removing them. After checking manually, the child is removed though. The reaction just doesn't fire. Or is it me :)
I am trying to build reusable components that could be used in a package. I would like to give a package user the ability to override the default template.
class @InputComponent.Checkbox extends InputComponent
@register 'InputComponent.Checkbox'
template: -> 'InputComponent.Checkbox'
...
InputComponent.Checkbox.setTemplate 'myCheckbox'
The use case would be something like changing user accounts forms.
I could use some education on what think-errors I'm making with the setup below. I think the core is that I'm trying to approach everything in OOP, but that that is not the complete way BC is set up (maybe). e.g:
I have a base component, which doesn't do much. I use it to encapsulate all kind of things for all extended instances. Enabled/visible, that kind of stuff.
BasePanelComponent = BlazeComponent.extendComponent({});
From this base, I create instances like so:
InstancePanelComponent = BasePanelComponent.extendComponent({
template: function() {
return "InstancePanelComponent";
},
onCreated: function() {
this.subscribe('getEverything');
}
}).register("InstancePanelComponent");
They do a bit more and handle their own subscriptions and so fort.
In the respective template, I used a bit of unsupported syntax (I think) but it seemed to work ok. Like so:
<template name="BasePanelComponent">
{{#if subscriptionsReady}}
All done loading!
{{/if}}
{{> Template.contentBlock}}
</template>
<template name="InstancePanelComponent">
{{#BasePanelComponent}}
Anything...
{{/BasePanelComponent}}
</template>
Now the challenge, it seems the "subscriptionsReady" is not acting. I'm guessing because the Instance is the one making the subscriptions and not the base, so base knows nothing about these subscriptions. So should I tackle the above differently or is there a way to access the subscriptionsReady with maybe a slightly different call, from the "instance".
Can we provide a shorthand mixinSibling
in addition to mixinParent
? It would do:
mixinSibling(nameOrMixin) ->
mixinParent().getMixin(nameOrMixin)
I have the following setup. See comments
class @FormComponent extends BlazeComponent
@register 'FormComponent'
template: -> 'FormComponent'
...
class @ExampleComponent extends FormComponent
@register 'ExampleComponent'
template: -> 'ExampleComponent'
onRendered: -> #my issue is here
for input in @componentChildren()
console.log input #logically this should be only the children
...
//- sorry for the jade, but it may be the cause so I left it unconverted
template(name='ExampleComponent')
form
+InputComponent.Text name='name'
br
+InputComponent.Checkbox name='bool'
br
input(type='submit' disabled='{{isInvalid}}')
This returns Text, Checkbox and ExampleComponent!
@mitar If you don't mind, I'm going to build on what you have here and make blaze-components usable/accessible as webcomponents similar to https://atmospherejs.com/numtel/webcomponent. That will allow the use of blaze-components
from
{{> mycomponent k='foo'}}
to
<mycomponent k='foo'></mycomponent>
//better yet
<mycomponent k='{{reactivedata}}'></mycomponent>
I will take sometime to digest you code. Is there any gotcha's I need to be aware of. Thanks for putting this together.
Currently, we are calling them from the life-cycle methods, allowing user to do things before, after, or event not call super
. But if they forget to call super
, mixins are not called. The question is if we really want to allow not calling them. Or do this customization of allowing to do things before or after is even a good one.
We could just have it so that mixins are always called, and then methods are called, which are empty by default.
(Same for DOM changes hooks?)
Order could match the same order of calling events
. See #4. But while for events
we have to decide when to call them because of unclear way how to offer customization. Leaving mixins calling in methods could allow such customization. But it can introduce also silent errors.
Currently we do not call mixins in DOM manipulation hooks out of fear that it would introduce performance issues. This means that on each DOM element insert, move and remove we would iterate over all mixins to find potential DOM manipulation hooks, even if there are none (in which case we would scan all mixins all the time).
But how much is this really a problem? Could we just do this all the time and make use of animation mixins much easier and uniform then?
The problem:
There aren't really enough users yet to ask questions on stack overflow.
The only place to ask questions is on github; @mitar is the only person answering.
The questions disappear from the issues feed when closed.
With 50 installs there have to be more people who can share gotchas and advice to new users, which will save them time, speed up the development of the package as opinions, suggestions and contributions are shared, and help to grow the community.
The solution:
I propose we extend components.meteor.com and add a forum (telescope-based would be fine) for questions, answers and discussion.
Answers could then be accepted and added to an FAQ section.
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.