On Github bmeurant / jsecosystem
Réseau ARAMIS - 23/03/2017
if (Modernizr.awesomeNewFeature) { showOffAwesomeNewFeature(); } else { getTheOldLameExperience(); }
npm install -g modernizrhttps://modernizr.com/
a { transition: transform 1s }generated
a { -webkit-transition: -webkit-transform 1s; transition: -ms-transform 1s; transition: transform 1s }
// Changing the HTML of an element. $( "#myDiv p:first" ).html( "New <strong>first</strong> paragraph!" ); // Manipulating a single attribute. $( "#myDiv a:first" ).attr( "href", "newDestination.html" );Events:
var hiddenBox = $( "#banner-message" ); $( "#button-container button" ).on( "click", function( event ) { hiddenBox.show(); });Ajax:
$.ajax({ url: "/api/getWeather", data: { zipcode: 97201 }, success: function( result ) { $( "#weather-temp" ).html( "<strong>" + result + "</strong> degrees" ); } });
<script src="lodash.js">
$ npm i -g npm $ npm i --save lodashExtreme modularity
// Load the full build. var _ = require('lodash'); // Load the core build. var _ = require('lodash/core'); // Load method categories. var array = require('lodash/array'); // Cherry-pick methods. var at = require('lodash/at');
_.chunk(['a', 'b', 'c', 'd'], 2); // => [['a', 'b'], ['c', 'd']]
_.forEach([1, 2], function(value) { console.log(value); }); // => Logs `1` then `2`.
_.gt(3, 1); // => true
_.max([4, 2, 8, 6]); // => 8
_.random(0, 5); // => an integer between 0 and 5
_.has({ 'a': { 'b': 2 }}, 'a'); // => true
_.camelCase('Foo Bar'); // => 'fooBar'
var button = document.querySelector('button'); button.addEventListener('click', () => console.log('Clicked!'));
var button = document.querySelector('button'); Rx.Observable.fromEvent(button, 'click') .subscribe(() => console.log('Clicked!'));
var button = document.querySelector('button'); Rx.Observable.fromEvent(button, 'click') .scan(count => count + 1, 0) .subscribe(count => console.log(`Clicked ${count} times`));
var button = document.querySelector('button'); Rx.Observable.fromEvent(button, 'click') .throttleTime(1000) .map(event => event.clientX) .scan((count, clientX) => count + clientX, 0) .subscribe(count => console.log(count));
var observer = { next: x => console.log('Observer got a next value: ' + x), error: err => console.error('Observer got an error: ' + err), complete: () => console.log('Observer got a complete notification') };
$(function() { $("#datepicker").datepicker(); });
<p>Date: <input id="datepicker"></p>
<div class="dropdown"> <button type="button" data-toggle="dropdown" aria-expanded="false"> Dropdown <span class="caret"></span> </button> <ul class="dropdown-menu"> ... </ul> </div>
$('.dropdown-toggle').dropdown();
moment().format('MMMM Do YYYY, h:mm:ss a'); // March 10th 2017, 12:45:16 am
moment("20111031", "YYYYMMDD").fromNow(); // 5 years ago
moment().subtract(6, 'days').calendar(); // Last Saturday at 00:58
moment.locale(); // fr moment().format('LL'); // 10 mars 2017
<!-- Stack the columns on mobile by making one full-width and the other half-width --> <div class="row"> <div class="col col-md-8">.col .col-md-8</div> <div class="col-6 col-md-4">.col-6 .col-md-4</div> </div> <!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop --> <div class="row"> <div class="col-6 col-md-4">.col-6 .col-md-4</div> <div class="col-6 col-md-4">.col-6 .col-md-4</div> <div class="col-6 col-md-4">.col-6 .col-md-4</div> </div> <!-- Columns are always 50% wide, on mobile and desktop --> <div class="row"> <div class="col-6">.col-6</div> <div class="col-6">.col-6</div> </div>
// app/route.js import { TodoListComponent } from './components/todo-list/todo-list.component'; export let routes = [ { path: '', component: TodoListComponent, pathMatch: 'full' }, { path: ':status', component: TodoListComponent } ]; // app/components/todo-list/todo-list.component.js import { TodoStoreService } from '../../services/todo-store.service'; import template from './todo-list.template.html'; @Component({ selector: 'todo-list', template: template }) export class TodoListComponent { constructor(todoStore: TodoStoreService, route: ActivatedRoute) { this._todoStore = todoStore; this._route = route; this._currentStatus = ''; } ngOnInit() { this._route.params .map(params => params.status).subscribe((status) => { this._currentStatus = status; }); } ... }code from angular2-esnext-todomvc
// app/router.js import Ember from 'ember'; import config from './config/environment'; const Router = Ember.Router.extend({ location: config.locationType, rootURL: config.rootURL }); Router.map(function () { this.route('active'); this.route('completed'); }); export default Router; // app/routes.application.js import Ember from 'ember'; export default Ember.Route.extend({ repo: Ember.inject.service(), model() { return this.get('repo').findAll(); } });code from todomvc emberjs
// js/app.jsx var app = app || {}; (function () { 'use strict'; app.ALL_TODOS = 'all'; app.ACTIVE_TODOS = 'active'; app.COMPLETED_TODOS = 'completed'; var TodoApp = React.createClass({ getInitialState: function () { return { nowShowing: app.ALL_TODOS, editing: null, newTodo: '' }; }, componentDidMount: function () { var setState = this.setState; var router = Router({ '/': setState.bind(this, {nowShowing: app.ALL_TODOS}), '/active': setState.bind(this, {nowShowing: app.ACTIVE_TODOS}), '/completed': setState.bind(this, {nowShowing: app.COMPLETED_TODOS}) }); router.init('/'); }, ... }code from todomvc react
<!-- app/components/app/app.template.html --> <router-outlet></router-outlet> <footer class="info"> <p>Double-click to edit a todo</p> <p>Written by <a href="https://github.com/blacksonic">{{ author }}</a></p> </footer> <!-- app/components/todo-list/todo-list.template.html --> <div class="todoapp"> <todo-header></todo-header> <div class="main" *ngif="getTodos().length"> <input class="toggle-all" type="checkbox" #toggleall="" [checked]="allCompleted()" (click)="setAllTo(toggleall)"> <ul class="todo-list"> <todo-item *ngfor="let todo of getTodos()" [todo]="todo" (itemremoved)="remove($event)" (itemmodified)="update($event)"></todo-item> </ul> </div> <todo-footer></todo-footer> </div>code from angular2-esnext-todomvc
<!-- //app/templates/application.hbs --> <div id="todoapp"> <header id="header">...</header> {{outlet}} <footer id="footer">...</footer> </div> <footer id="info"> <p>Double-click to edit a todo</p> <p>Created by <a href="http://github.com/cibernox">Miguel Camba</a>, <a href="http://github.com/addyosmani">Addy Osmani</a></p> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p> </footer> <!-- app/templates/index.hbs --> {{#if model.length}} {{todo-list todos=model}} {{/if}} <!-- app/templates/components/todo-list.hbs --> {{#if todos.length}} {{#if canToggle}} <input type="checkbox" id="toggle-all" checked="{{allCompleted}}" onchange="{{action" 'toggleall'}}=""> {{/if}} <ul id="todo-list" class="todo-list"> {{#each todos as |todo|}} {{todo-item todo=todo onStartEdit=(action 'disableToggle') onEndEdit=(action 'enableToggle')}} {{/each}} </ul> {{/if}}code from todomvc emberjs
//js/app.jsx render: function () { var todoItems = shownTodos.map(function (todo) { return ( <todoitem key="{todo.id}" todo="{todo}" ontoggle="{this.toggle.bind(this," todo)}="" ondestroy="{this.destroy.bind(this," onedit="{this.edit.bind(this," editing="{this.state.editing" =="=" todo.id}="" onsave="{this.save.bind(this," oncancel="{this.cancel}"></todoitem> ); }, this); if (todos.length) { main = ( <div classname="main"> <input classname="toggle-all" type="checkbox" onchange="{this.toggleAll}" checked="{activeTodoCount" =="=" 0}=""> <ul classname="todo-list">{todoItems}</ul> </div> ); } return ( <div> <header classname="header"> <h1>todos</h1> <input classname="new-todo" placeholder="What needs to be done?" value="{this.state.newTodo}" onkeydown="{this.handleNewTodoKeyDown}" onchange="{this.handleChange}" autofocus="{true}"> </header> {main} {footer} </div> ); }code from todomvc react
npm installpackage.json
{ "name": "my_package", "description": "", "version": "1.0.0", "description": "", "dependencies": { "my_dep": "^1.0.0" }, "devDependencies" : { "my_test_framework": "^3.1.0" } }registry: https://www.npmjs.com/
npm search lodash NAME DESCRIPTION lodash Lodash modular utilities. lodash-es Lodash exported as ES modules.
npm install -g bower
bower installbower.json
{ "name": "my_package", "version": "1.0.0", "description": "", "dependencies": { "my_dep": "^1.0.0" }, "devDependencies" : { "my_test_framework": "^3.1.0" } }search: https://bower.io/search/
bower search jquery Search results: jQuery https://github.com/jquery/jquery.git jquery https://github.com/jquery/jquery-dist.git
npm install --global yarn"lockfiles = awesome for apps, bad for libs"
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 package-1@^1.0.0: version "1.0.3" resolved "https://registry.npmjs.org/package-1/-/package-1-1.0.3.tgz#a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
"scripts": { "lint": "jshint **.js", "test": "mocha test/", "clean": "rm -r dist/*", "deploy": "node bin/deploy.js -- --env", "pretest": "npm run clean && npm run lint", "postclean": "echo \"project is now clean\"" }
npm run test > my-package@0.0.1 pretest ~/my-package > npm run clean && npm run lint > my-package@0.0.1 clean ~/my-package > rm -r dist/* > my-package@0.0.1 postclean ~/my-package > echo "project is now clean" project is now clean > my-package@0.0.1 lint ~/my-package > jshint **.js ... > my-package@0.0.1 test ~/my-package > mocha tests ...
var gulp = require('gulp'); var coffee = require('gulp-coffee'); var concat = require('gulp-concat'); var uglify = require('gulp-uglify'); var imagemin = require('gulp-imagemin'); var sourcemaps = require('gulp-sourcemaps'); var del = require('del'); var paths = { scripts: ['client/js/**/*.coffee', '!client/external/**/*.coffee'], images: 'client/img/**/*' };
// Not all tasks need to use streams // A gulpfile is just another node program and you can use any package available on npm gulp.task('clean', function() { return del(['build']); }); gulp.task('scripts', ['clean'], function() { // Minify and copy all JavaScript (except vendor scripts) // with sourcemaps all the way down return gulp.src(paths.scripts) .pipe(sourcemaps.init()) .pipe(coffee()) .pipe(uglify()) .pipe(concat('all.min.js')) .pipe(sourcemaps.write()) .pipe(gulp.dest('build/js')); }); // Copy all static images gulp.task('images', ['clean'], function() { return gulp.src(paths.images) .pipe(imagemin({optimizationLevel: 5})) .pipe(gulp.dest('build/img')); }); // Rerun the task when a file changes gulp.task('watch', function() { gulp.watch(paths.scripts, ['scripts']); gulp.watch(paths.images, ['images']); }); // The default task (called when you run `gulp` from cli) gulp.task('default', ['watch', 'scripts', 'images']);
npm install babel --save-dev
window.$ = function() { ... }; var App = {}; App.Models = {};Module formats to the rescue AMD: for browser, parallelisation, verbosity
define(['dependencyA', 'dependencyB', function(dependencyA, dependencyB) { return { doSomething: dependencyA.foo() + dependencyB.foo(); } });CommonJS: for Node.js only, straightforward
var dependencyA = require('dependencyA'); var dependencyB = require('dependencyB'); module.exports = { doSomething: dependencyA.foo() + dependencyB.foo() };UMD: attempt of reunification
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['dependencyA', 'dependencyB'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like module.exports = factory(require('dependencyA'), require('dependencyB')); } else { // Browser globals (root is window) root.returnExports = factory(root.dependencyA, root.dependencyB); } }(this, function (dependencyA, dependencyB) { doSomething: dependencyA.foo() + dependencyB.foo() }));
// zoo.js export let Dog = function (name) { this.talk = function() { return `${name}: Woof Woof`; }; }; export let Wolf = function (name) { this.talk = function() { return `${name}: WoooooooW`; }; }; export default {Dog, Wolf};
// main.js import Zoo, { Dog, Wolf } from './zoo'; let myDog = new Dog('Sherlock'); console.log(myDog.talk()); // Sherlock: Woof Woof let myWolf = new Wolf('Werewolf'); console.log(myWolf.talk()); // Werewolf: WooooooW let otherDog = new Zoo.Dog('Snoopy'); console.log(otherDog.talk()); // Snoopy: Woof Woof
npm install webpack -g
module.exports = { entry: "./app.js", output: { filename: "bundle.js" }, module: { loaders: [ { test: /\.es6$/, exclude: /node_modules/, loader: 'babel-loader', query: { presets: ['react', 'es2015'] } } ] }, resolve: { extensions: ['', '.js', '.es6'] } }
# Debug mode webpack # Production mode (minified version) webpack -p
$base-color: #0066A1; body { color: $base-color; }nesting
section { .logos { & > * { margin: .25em auto; } img { height: 55px; } } }imports
@import 'variables'; body { font: 100% $base-font; }mixins
@mixin my-border($color, $width: 1px) { border: $width solid $color; } p { @include my-border(blue, 2px); }inheritance
.message { border: 1px solid #ccc; padding: 10px; color: #333; } .success { @extend .message; border-color: green; }structures & control
@each $header, $size in (h1: 2em, h2: 1.5em, h3: 1.2em) { #{$header} { font-size: $size; } }
$i: 6; @while $i > 0 { .item-#{$i} { width: 2em * $i; } $i: $i - 2; }operators & functions
p { width: 1em + (2em * 3); color: lighten($base-color, 20%); }build with gulp
var gulp = require('gulp'); var sass = require('gulp-sass'); gulp.task('styles', function() { gulp.src('sass/**/*.scss') .pipe(gulp.dest('./css/')); });
body { font: 100% Helvetica, sans-serif; } body { color: #0066A1; } section .logos > * { margin: .25em auto; } section .logos img { height: 55px; } p { border: 2px solid blue; } .message, .success { border: 1px solid #ccc; padding: 10px; color: #333; } .success { border-color: green; }
h1 { font-size: 2em; } h2 { font-size: 1.5em; } h3 { font-size: 1.2em; } p { width: 7em; color: #08a4ff; } .item-6 { width: 12em; } .item-4 { width: 8em; } .item-2 { width: 4em; }
npm install mocha
var assert = require('chai').assert; describe('Array', function() { describe('#indexOf()', () => { it('should return -1 when the value is not present', () => { assert.equal(-1, [1,2,3].indexOf(4)); }); }); });
describe('User', function() { describe('#save()', function() { it('should save without error', function(done) { var user = new User('Luna'); user.save(done); }); }); });
beforeEach(() => { return db.clear() .then(() => { return db.save([tobi, loki, jane]); }); }); describe('#find()', () => { it('respond with matching records', () => { return db.find({ type: 'User' }) .should.eventually.have.length(3); }); });
function add() {...} describe('add()', () => { var tests = [ {args: [1, 2], expected: 3}, {args: [1, 2, 3], expected: 6} ]; tests.forEach((test) => { it('correctly adds ' + test.args.length + ' args', () => { var res = add.apply(null, test.args); assert.equal(res, test.expected); }); }); });
// .eslintrc.json { "extends" : "eslint:recommended", "root": true, "rules": { "camelcase": 2, "space-infix-ops": 2 } }
var gulp = require('gulp'); var eslint = require('gulp-eslint'); gulp.task('check-code', function() { return gulp.src(['**/*.js']) .pipe(eslint()) .pipe(eslint.format()); });
main.js -> main-5d94bdc916e7d2.js
ember serve Livereload server on http://localhost:49152 Serving on http://localhost:4200/ Build successful - 5562ms. Slowest Nodes (totalTime => 5% ) | Total (avg) ----------------------------------------------+--------------------- Babel (31) | 1633ms (52 ms) SassCompiler (2) | 1129ms (564 ms) Concat (16) | 713ms (44 ms) Funnel (60) | 543ms (9 ms) # ok
ember generate route foo installing create app/routes/foo.js create app/templates/foo.hbs installing create tests/unit/routes/foo-test.js
class Student { fullName: string; constructor(public firstName, public middleInitial, public lastName) { this.fullName = firstName + " " + middleInitial + " " + lastName; } } interface Person { firstName: string; lastName: string; } function greeter(person : Person) { return "Hello, " + person.firstName + " " + person.lastName; } var user = new Student("Jane", "M.", "User"); document.body.innerHTML = greeter(user);