GithubHelp home page GithubHelp logo

montagejs / montage Goto Github PK

View Code? Open in Web Editor NEW
1.5K 82.0 225.0 31.62 MB

Montage is an elegant, open source HTML5 framework maintained by Montage Studio that rivals native SDKs, yet is easier to learn. It offers modular components, two-way data binding, and much more. Join us on irc.freenode.net#montage. Sign up for our beta to build Montage applications in the cloud.

Home Page: http://montagestudio.com/montagejs

License: Other

JavaScript 88.79% HTML 9.58% CSS 1.62% Shell 0.02%

montage's Introduction

Montage

npm version

Build Status

Analytics

Montage is a new type of application framework powered by standard web technologies. Designed with an eye toward maintainability and performance, Montage simplifies the development of rich HTML5 applications by providing modular components, real-time two-way data binding, object serialization with DOM mapping, event handling, a managed component draw cycle, CommonJS dependency management, and many more conveniences to help build robust single-page web applications.

Encapsulated Components

Montage has a clean interface for creating custom user interface components. Each component can stand alone or be composed of other components. Each component is modeled as a stand-alone web application with its own HTML template, JavaScript, CSS, serialized component object model, and resources. With few exceptions, a component can stand on the web platform like any other web page. There are no fully JavaScript-driven templates in Montage. This separation of concerns allows designers to use the technologies they are comfortable with (without having to dig into the JavaScript) and developers to isolate and test individual components using familiar techniques.

Declarative Data Binding

Montage makes it easier to manage your application and UI state with data bindings. A UI component or Montage object can establish a simple or bi-directional binding with another component or object. When the bound property, or deeper property path, of the bound object is updated then the source object is kept in sync.

Montage uses functional reactive bindings (FRB). Unlike “traditional” bindings, FRB can gracefully bind long property paths and the contents of collections. They can also incrementally update the results of chains of queries including maps, flattened arrays, sums, and averages as well as add and remove elements from sets based on the changes to a flag. FRB makes it easy to incrementally ensure consistent state. FRB is built from a combination of powerful functional and generic building blocks, making it reliable, easy to extend, and easy to maintain.

For more information, see FRB.

CommonJS

Montage fully supports CommonJS modules and is a part of the Node and npm package ecosystem.

For more information, see CommonJS.

Requirements

To get started with Montage, you will need the following:

  • Node.js and npm. Montage application development depends on npm, which is distributed with Node.js.
  • A recent stable release of Chrome, Safari or Firefox. Montage is intended to leverage the evolving web platform of modern browsers.
  • To contribute: A Git client and public SSH key. For details on installing Git and creating your key, see the setup guides on github.com.

Quick Setup

To start using Montage, follow these steps:

  1. Download and run the prebuilt Node.js installer for your platform from the Node.js website.

  2. Install minit, the Montage Initializer.

    minit is a command line utility that will help kickstart your Montage project by generating prebuilt Montage application templates and components and placing the associated files inside the proper directories of your project.

    Mac OS X / Linux

    $ mkdir -p ~/.npm
    $ sudo npm install -gq minit@latest
    

    Windows

    Run the "Node.js command prompt"

    $ npm install -gq minit@latest
    
  3. Use minit to create your Montage project:

    $ minit create:app -n yourappname
    

    Note: If you get an EACCES warning when trying to run minit:create, use sudo chown -R <username> ~/.npm and then use $ minit create:app -n hello. This is a workaround due to a bug in npm.

    This generates a new directory—yourappname, which contains the default Montage application template, including the production dependencies—in your current directory.

  4. To verify your installation, switch to yourappname directory and serve your new Montage project using minit:

    $ cd yourappname
    $ minit serve &
    
  5. Point your browser to http://localhost:8083/.

    You should see the contents of the Welcome component—a simple single-page application, which is explicitly loaded to accompany our two-part quick start tutorial tutorial.

Where to Go from Here

For a quick introduction on how to assemble Montage components into a user interface, refer to “Hello Montage” in our Quick Start tutorial. For more information on Montage components, bindings, event handling, serialization etc. refer to the documentation (be patient: we are currently in the process of updating the docs).

Maintenance

Tests are in the test directory. Use npm test to run the tests in NodeJS or open test/run.html in a browser.

To run the tests in your browser, simply use npm run test:jasmine.

To run the tests using Karma use npm run test:karma and for continious tests run with file changes detection npm run test:karma-dev. Finally to open a remote debug console on karma use npm run test:karma-debug.

montage's People

Contributors

3on avatar aadsm avatar asolove avatar cdebost avatar cesine avatar dharcourt avatar ducarroz avatar francoisfrisch avatar heatherdouglass avatar hthetiot avatar hugodaniel avatar johnnykahalawai avatar jonfu86 avatar joshuarule avatar jseidelin avatar kishores avatar kriskowal avatar marchant avatar mczepiel avatar mikokim avatar nv avatar pchaussalet avatar rayshan avatar rdwrite avatar romancortes avatar simurai avatar spearway avatar stuk avatar tejaede avatar thibaultzanini avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

montage's Issues

we can't serialize elements without id

we can't serialize elements without id, and the id is being dropped when the first draw happens.. Afonso is thinking how to rewrite the html serialization..

Repetition component + Slot component redrawing incorrectly

When a Repetition is managing a set of Slots, and an element is removed from the Repetition's array using splice(), the view is redrawn incorrectly.

Steps to Reproduce:

  1. Create a simple Repetition that manages Slots.
  2. Bind the content of the Slots to the Repetition's objectAtCurrentIteration.
  3. Insert several things into the Repetition's array (e.g. Dynamic Text Fields)
  4. Remove one of the things from the Repetition's array using Array.splice().

Actual Results:
The Repetition's array is correctly modified, but the view is redrawn such that the desired objectAtCurrentIteration is removed, as well as the last objectAtCurrentIteration. Sometimes the last object is replaced with an empty object.

Expected Results:
The Repetition's array should be correctly modified and the view should be redrawn to reflect the removal of the associated objectAtCurrentIteration.

Test case available.

Substitution inside Repetition not rendering at all

See this example

One more thing, I added a logger to see the contents of switchComponents inside the substitution and I get this:

log

Notice that text is not an Object, is directly taking text.value. Also notice that the switchComponent is wrapped inside a <div> only if it's an Object.

DOM

Maybe related to #91

Finalize specs for first batch of components

Spec: TextArea
Spec: Anchor
Spec: ToggleButton
Spec: Button
Spec: NumberInput
Spec: Image
Spec: RangeInput
Spec: Textfield
Spec: SelectInput
Spec: Checkbox
Spec: Radiobutton
*Spec: Repetition

some popup component issues

Hi,
I am facing couple of issues while opening a popup within a popup:

Issue# 1.
I am opening a modal popup from within another modal popup. However, when I close the second popup, the modal block screen goes away, thus leaving the first modal popup as non-modal.
I would expect the modal block screen to remain on closing the second popup.

Issue# 2.
If I open a non-modal popup from within a modal popup, then the second popup goes behind the modal popup.
Is there a way to bring the 2nd popup, above first modal popup ?

I would appreciate if these can be addressed soon.

Thanks.

we can't serialize elements without id

we can't serialize elements without id, and the id is being dropped when the first draw happens.. Afonso is thinking how to rewrite the html serialization..

Could url resolve be speed up by building a cache?

in montage.js, exports.resolve = function (base, relative) {..}. It looks like the data set passed through may have multiple time the same value coming in and out, so if that's the case we could get some gains by building a cache and do a lookup first?

Request new Callback for Components in a Substitution/Slot

Problem:

Lets say I have Components - A, B, C - in a Substitution. Component A must refresh while it is in view such as a Twitter feed view. When the Component is hidden from View, the refresh must stop.

I was looking for callbacks in the Component that are similar to:

    Component A {
        didBecomeActiveInSlot: function(slot, componentThatWasHidden) { }
        didBecomeInactiveInSlot: function(slot, componentThatWillBeShownNext) { .. }
    }

In this case, I can start a timer in didBecomeActiveInSlot callback and stop the timer in the didBecomeInactiveInSlot callback.

Other examples:

  • The Component must refresh the contents whenever it comes into view
  • The Component can release memory when it is not in view

Update CHANGES.md with release notes

  • Added UndoManager
  • Custom Events now propagate through component tree by default
  • didCreate is called on every instance if available
  • All components now dispatch an action
  • Condition component improvements
  • PhotoFX example improvements
  • Added flow component
  • IE10 Fixes
  • Bug fixes in:
    • require packaging
    • Dependent properties listening
    • Promises
    • Selection in ArrayController
    • Scrollview

Loader sometimes doesn't load

@toji reports that the loader sometimes doesn't go away and the main component doesn't appear.

This is the log

Should be empty: []
Loader.anonymous() templateDidLoad
Loader.anonymous() bootstrapping has not started yet…
Loader.anonymous() _loadMainComponent
Loader.anonymous() _mainLoadedCallback
...
Loader.anonymous() main preparing to draw

- end of console -

@jfahrenkrug : Easier test server than Apache: Sinatra

Orginally created by @jfahrenkrug

@jfahrenkrug
Setting up Apache just to serve up the demos might be too much for some.
A tiny Sinatra script does the trick too:

require 'rubygems'
require 'sinatra'

set :public, "."

Save that in a file called "testserver.rb" inside the montage directory and then run ruby testserver.rb and you can open the PhotoFX demo like so: http://localhost:4567/examples/photofx/index.html

@francoisfrisch
Ya, I guess running a ruby server would be more familiar for some. Do you know of an easy way to set some response headers?

@jfahrenkrug
Yes, you can set any http response header your heart desires: http://stackoverflow.com/questions/4199624/how-do-i-set-http-headers-in-ruby-sinatra-app-hosted-on-heroku

Are you looking for different response headers based on the file (type) you're serving?

@francoisfrisch
Setting CacheControl to no-cache is important for dev on webkit to ensure file changes are taken into account.

Duplication of component location in serialization

This is an issue created after this discussion: http://tetsubo.org/forum/montage/avoid-duplication-of-the-component-location/

The problem boils down to the verbosity of the module id of objects, every time a developer wants to add an object to the serialization he needs to write the entire module path regardless of having done so already for another entry of the same type.

Some of the suggestions to solve this problem are:

  1. Additional Markup
{
    "$metadata": { /* not proposing this name, just for illustrative purpose */
        "names": {
            "Button": "montage/ui/button.reel"
        }
    },
    "component1": {
        "name": "Button",
        "properties": {
            "element": {"#": "button"}
        }
    }
}
  1. Default prototype name + Single entry
"type": "montage/ui/button.reel.Button"

with

"type": "montage/ui/button.reel"
defaulting to
"type": "montage/ui/button.reel.Button"
  1. Variation of 2)
"module": "montage/ui/button.reel"
defaulting to
"module": "montage/ui/button.reel", "name": "Button"

id's get removed from Components' elements.

Here's a breakdown of the issue (full discussion at http://tetsubo.org/forum/montage-components/id-gets-removed-from-elements-associated-with-montage-components/) :

Id's in components' elements are currently being removed because they are going to be repeated as soon as the component is used twice. Since we only provide a way to reference elements using ids it's not possible for the developer to avoid creating an invalid HTML document if we don't remove the ids.

A solution for this problem is to come up with a data- attribute on elements that can be referenced in the serialization, this way there's no need to mess up with the id, each developer is responsible to deal with that.
To avoid performance issues (getElementById vs querySelector) the template can be optimized to use id's after being instantiated in memory or at "mop time", this will be completely transparent for the developer.

Something to have in mind with this change is that when the developer is using a component and provides an id on its element this id will prevail, any id set the template's element will be ignored.

Example:

Usage: <div id="slider1"></div>
Template: <div id="slider">markup here</div>

Rendered: <div id="slider1">markup here</div>

Two items still need to be decided:

  1. Which data- attribute name to use, current suggestions: data-id, data-montage, data-montage-id data-mid
  2. Which "#"-like key to use in the serialization, current suggestions: "m#"

Type system improvements

Montage.create(prototype, descriptor) and MontageDerrivative.create().init() are confused. They overload too many responsibilities on a single function. It is difficult to categorically say whether "create" is a static method like Object.create or a polymorphic method. It doesn’t provide a fluid syntax for either instantiation or subtyping.

Montage.create was inspired by Object.create, a static method of the Object constructor. Since Montage is a prototype in title-case and not a constructor, this is a bit confusing but forgivable, as long as we use create as if Montage were a constructor and create as a static method. Montage.create should merely be an extension of Object.create, accepting additional descriptor metadata and more suitable defaults for our designs. A missing property should only imply the use of a default, not distinguish instantiation from subtyping.

We could support much more elegant patterns, separating subytping, instantiation, and initialization into separate idioms. I propose adding type, new, and init functions with the following semantics.

These functions and patterns can be implemented in a backward-compatible fashion, with us withdrawing special behaviors of Montage.create only if and after migration has been completed.

Montage#type(descriptor_opt)

This is a polymorphic shorthand for creating subtypes and also allocating (but not initializing) instances.

return Montage.create(this, descriptor);

Usage would look like:

var MyButton = Button.type({
    // …
})

The descriptor should default to {} but there should be no other difference in behavior.

Montage#new(properties_opt)

This would be used by the deserializer to create instances. It would be polymorphic but typically not overridden.

var instance = this.type();
for (var name in properties) {
    if (this[properties] === undefined) {
        throw new Error("Initial properties must be defined on the descriptor");
    }
    this[properties] = name;
}
if (instance.init) {
    instance.init();
}
instance.init = null;
instance.type = null;
return instance;

Nulling (or replacing with functions that throw friendly errors) init and type discourages the hazards of reinitialization and mixing types and instances.

The name new would place us solidly in ES5, which we have already seen we can’t do because of *$%@ Safari 5.0 and the delete keyword. make is an option. create is taken and would make make confusing: what’s the difference? instantiate is too verbose.

Montage#init()

A polymorphic initializer. It accepts no arguments, but because it gets called after initial properties have been set, it has an opportunity to munge them into a consistent state. Using properties instead of positional arguments is good (for Montage) because it enforces serializability and deserializability.

We could postpone binding propagation until after initialization.

Ability to store and load the state of a component

We currently don't have this ability, even if we save the state in a template like the Repetition does it will be useless when instantiating it because components might have their own templates that will override whatever was serialized before.

Dimitri needs this for the code he's working on.

My idea is for a component to detect if it's being serialized with state (after its own template instantiation), store that info in "_isTemplateInstantiated" so it can call "templateDidLoad" at expandComponent time instead of loading its own template.

Fix ParentComponent Chaining

Currently, in order to get an event to fire up the component tree, I have to continually define the parentProperty to parentComponent all the way up the chain until I get to the component I'm looking to handle. This line is repeated throughout my code and it would make sense if this tree was established by default.

@mczepiel
All we need to do to enable this for the component tree is set the Component's parentProperty to be "parentComponent". There's still work to be done to enable "capture" phase distribution along these trees. The parentProperty really only enables bubble distribution.

@marchant
So why don't we implement that on Component directly?

All we need to do to enable this for the component tree is set the Component's parentProperty to be "parentComponent".

There's still work to be done to enable "capture" phase distribution along these trees. The parentProperty really only enables bubble distribution.

Ok, I thought the full bubble/capture was operational. Following a discussion with Pierre, I think we'll need it for the persistence layer. How much work do you feel is left?

@mczepiel
I misspoke; apparently I do have it working in both phases, according to the jasmine specs at least. (Shows how little I use this feature.)

Re: components. We can do exactly that.

On a side note, I am not convinced this solves @zacharyc's end goal. Relying on the top level component to receive all component events within your application is easy and convenient; it is not necessarily the path towards deliberate relationships between and clear responsibilities for objects throughout the application. There's no denying it's a powerful mechanism to consolidate information but authors should guard against erecting a monolithic top level component.

But I digress, I'll add the propertyName to component; It's a reasonable expectation given the component tree and perfect for many applications.

@marchant

I misspoke; apparently I do have it working in both phases, according to the jasmine specs at least. (Shows how little I use this feature.)
Cool

Re: components. We can do exactly that.

On a side note, I am not convinced this solves
@zacharyc's end goal. Relying on the top level component to receive all component events within your application is easy and convenient; it is not necessarily the path towards deliberate relationships between and clear responsibilities for objects throughout the application. There's no denying it's a powerful mechanism to consolidate information but authors should guard against erecting a monolithic top level component.
I agree, why does he needs that? How does he want to use it?

But I digress, I'll add the propertyName to component; It's a reasonable expectation given the component tree and perfect for many applications.

Great, agreed.

@mczepiel
He's writing an app and consolidating state in the top level component. I suspect it's mainly because this component happens to be at the top of the component tree, not because it's necessarily an object that should be the expert on the work it's doing. But given the the relatively small size of the application it's not a problem; maybe it's even the best place for this knowledge.

Anyway, I have the work done and as I said before it does make sense from a tree standpoint. I'm just doing some performance testing to see if it's a concern with all the extra propagation we'll end up doing.

@mczepiel
e88f971 Should address this

Button styled differently for <input> vs. <div>

If you run this code you'll see the <input>-based Button looks different from the <div>-based Button.

<html>
<head>
    <title>Handling events in Montage</title>
    <script src="../../montage.js" type="text/javascript"></script>
    <script type="text/montage-serialization">
    {
        "button1" : {
            "name": "Button",
            "module": "montage/ui/button.reel",
            "properties": {
                "element": {"#": "button_input"},
                "value": "<input>"
            }
        },      

        "button2" : {
            "name": "Button",
            "module": "montage/ui/button.reel",
            "properties": {
                "element": {"#": "button_div"},
                "value": "<div>"
            }
        }
    }
    </script>
</head>
<body>
<div id="main">
    <input id="button_input" type="button" class="text">
    <div id="button_div" type="button" class="text">
</div>
</body>
</html>

Add platform default undo/redo shortcut to UndoManager?

Can we automatically add the platform default undo and redo keyboard shortcuts (mainly for desktop I guess) to the undoManager so that for example on Mac, command-z will perform the last undo action on the stack? If not by default, add some easy way to register the default bindings for this?

MON-566: Add non -webkit- versions of CSS properties where needed

We use a number of -webkit- prefixes in CSS properties, without fallback to the standard version of the property, or using prefixes for other engines.

A number of these don't need prefixes at all anymore, especially with the versions of browsers that Montage is targeting. We should either remove the prefix, or supplement them with the unprefixed version if needed for older webkit browsers (older Android/iOS)

E.g. the styling of the tab component is lacking on Firefox due to only prefixed versions of properties in tabs.css

  • box-shadow doesn't need -webkit- any longer (except in Android and iOS < 5)
  • gradients uses old webkit syntax rather than newer W3C version. Older syntax is needed for Android < 4 and iOS < 5. Other prefixes needed for Gecko, Opera and IE.
  • Other prefixes are needed for transition property.

There are probably similar issues with other components.

Terminology to use when discussing object model

Regarding the terminology of JavaScript prototyping vs. classical OOP terms:

Kris used the verbs "subtype" and "instantiate" (in the email copied below) to describe the two functions of Montage.create(). I like the distinction personally, but I realize this can be a controversial subject.

Here's a short proposal for terms to use when describing the object model:

  • Prototype (verb or noun) - An object you can subtype or instantiate.
  • Subtype (verb or noun) - Adds functionality to a prototype (or "extends" a prototype?)
  • Instantiate (verb) - Create a new instance of a prototype or subtype.
  • Instance (noun) - An instance of a subtype (or prototype).

On Thu, Jan 12, 2012 at 12:37 PM, Kris Kowal [email protected] wrote:
Tim,

I want to make sure that this gets written in bold somewhere if it
hasn’t been already.

  • Montage.create(Base) is for instantiation. From v0.5, this will
    call .didCreate() on each begotten instance implicitly for
    initialization purposes. It does not accept arguments and occurs
    before the serialization has an opportunity to set initial properties.
    All parameterized initialization must occur as the result of
    observing setters on those properties.
  • Montage.create(Base, descriptor) is for subtyping. This will not
    call didCreate()

In some cases hasOwnProperty doesn't behave correctly

Setting a property descriptor as distinct or adding a binding to a property creates a getter/setter that is unknown to the developer. hasOwnProperty should work as if the property was a value property.
ie: When we assign a value to such a property hasOwnProperty should return true.

'firstDraw' event is dispatch multiple times as per nested child(ren)

If you have an app or component that has nest components, the parent of each component is currently dispatching the 'firstDraw' event for itself but also dispatching itself a 'firstDraw' event for each nest component in it. This was not happening in 0.4 but is now happening in 0.5.

Support for multiple Selections in Repetition using a "select" checkbox

Issues:

  • Repetition supports a single item in its collection to be selected upon touch/click. Upon clicking the item again, the item is deselected. However, it does not support multiple items to be selected and bound to.
  • It is a common pattern to have a checkbox in each item to denote the item's selection. Eg: Google Docs. The usual scenario is to allow the user to select/deselect the checkbox to select multiple items and do something useful with this collection.

Make the repetition respect the draw cycle

At the moment the repetition is writing into the DOM outside of its draw function.
Since I want to make the DCC implementation (setting the contents) to only act in the draw function I also need to change the repetition to act within the draw function.

examples/mixed-list doesn't load

Incorrect use of waitsFor in deserializer spec

I think the test's intermittent error in the console is caused by the deserializer spec.

Uncaught TypeError: Cannot read property 'abort' of undefined
    onCompletejasmine.js:1768
    jasmine.WaitsForBlock.executejasmine.js:2269
    (anonymous function)

list scrollview doesn't work in chrome on the latest montage

my montage version:

SHA: 10557b2
Date: Tue Dec 20 2011 17:08:12 GMT-0800 (PST)
Subject: Fix ArrayController selectedObject to selectedIndexes agreement ..

error:
TypeError: Cannot call method 'join' of null
at deserializeValue (http://localhost/Projects/m-js/core/deserializer.js:570:108)
at deserializeValue (http://localhost/Projects/m-js/core/deserializer.js:519:61)
at deserializeObject (http://localhost/Projects/m-js/core/deserializer.js:468:32)
at Object. (http://localhost/Projects/m-js/core/deserializer.js:401:17)
at Object. (http://localhost/Projects/m-js/core/deserializer.js:620:32)
at http://localhost/Projects/m-js/core/deserializer.js:696:32
at http://localhost/Projects/m-js/core/deserializer.js:298:29
at Array.forEach (native)
at addModules (http://localhost/Projects/m-js/core/deserializer.js:296:50)
at http://localhost/Projects/m-js/core/deserializer.js:230:33

works fine in safari.. any hints? photofx with its list works fine in chrome..

Add the possibility to display = "none" the body of the application during draw.

We have removed this behavior from Montage but want to have it as a development option in the future.

It was removed because it was causing more problems than it was trying to solve/prevent.
Some apps had issues with it and Chrome was having some erratic behavior (slow pauses in painting) when changing DOM elements while the body was display = "none".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.