SlideShare uma empresa Scribd logo
1 de 162
Baixar para ler offline
Modular JavaScript Heaven
with AMD and Events
@shiota ConFoo 2015
HELLO!slideshare.net/eshiota
github.com/eshiota
@shiota
* 16/02/2015 https://github.com/search?p=1&q=stars%3A%3E1&s=stars&type=Repositories
Out of the top 50 most starred
repos in Github, 25 are
JavaScript related.
JavaScript is awesome!
But sometimes it sucks.
It may become unreadable
and unmaintainable.
(function(){
window.app = jQuery.extend({
init: function(){
tab = $('.tabs li > a.tab-toggle');
tabs = $('.tabs').find('> div');
if (tabs.length > 1){
tab.each(function (i){$(this).attr('href', '#content-' + ++i)});
tabs.each(function(i){$(this).attr('id', 'content-' + ++i)});
tabs.addClass('tab-inactive');
$('.tabs li:first-child a').addClass('state-active');
}
$('#initial-cash, #financing_value_vehicles, #tax, #bid-initial-cash, #bid-product-value').maskMoney({
thousands: '.',
decimal: ',',
allowZero: true,
allowNegative: false,
defaultZero: true
});
/** FINANCING CALCULATOR **/
$("#financing_value_vehicles").on("blur", function(){
var price = (accounting.unformat($(this).val(), ",")) || 0;
var suggestedInitialPayment = price * 0.2;
var formattedResult = accounting.formatMoney(suggestedInitialPayment, "", "2", ".", ",");
$("#initial-cash").val(formattedResult);
});
$("#calculate-financing").click(function(event){
var price = (accounting.unformat($("#financing_value_vehicles").val(), ",")) || 0;
var rate = (accounting.unformat($("#tax").val(), ",") / 100) || 0;
var initialCash = (accounting.unformat($("#initial-cash").val(), ",")) || 0;
var value = (accounting.unformat($("#amount-finance").val(), ",")) || 0;
var finance = price - initialCash;
var months = (accounting.unformat($("#prize_parcela").val(), ",")) || 0;
var tax = parseFloat(rate);
(single JS file,
173 LOC inside one function,
at least 7 different concerns)
It may become a
CALLBACK HELL
(and some libraries just make it worse)
$(document).ready(function () {
$(".submit-button").on("click", function () {
$.ajax({
url : "/create",
type : "POST",
success : function (data) {
$.each(data.created_items, function (index, value) {
var item = $("<div />").text(value);
$(".items-list").append(item).hide().fadeIn(400, function () {
setTimeout(function () {
item.fadeOut(function () {
item.remove();
});
}, 1000);
});
});
}
});
});
});
A modular, event-based
structure solves these
problems and much more.
Modular JavaScript Heaven
with AMD and Events
(on the web)
Agenda
Making it modular
Controlling the flow
Communicating through events
MODULES
Single responsability, part
of a complex system.
Isolated behaviour
and knowledge.
Testable.
Extensible and modifiable.
(good taste is optional)
May be replaced and reused.
Namespaces
Helps organising the
code in separate blocks.
///////////////////////////////
// Code for photo gallery
///////////////////////////////
var gallery = $(".gallery");
var galleryCurrent = 0;
var galleryTimer = 5000;
$(".thumbs").on("click", function (event) {
// ...
});
function goToNext () {
// ...
}
setTimeout(function () {
goToNext();
}, galleryTimer);
///////////////////////////////
// Code for switching tabs
///////////////////////////////
var tabs = $(".tabs");
tabs.on("click", function (event) {
// ...
});
function switchTab(tab) {
// ...
}
✗
MyApp.components.photoGallery($(".gallery"));
MyApp.ui.tabs($(".tabs"))
var MyApp = MyApp || {};
MyApp.components = MyApp.components || {};
MyApp.components.photoGallery = function (element) {
// ...
};
var MyApp = MyApp || {};
MyApp.ui = MyApp.ui || {};
MyApp.ui.tabs = function (element) {
// ...
};
Provides a fairly
logical structure.
/javascript
/myapp
/components
/photoGallery.js
/ui
/tabs.js
Avoids polluting the
global context.
window
$ photoGallery tabs profile login plugin
window
$ MyApp plugin
components ui sections
photoGallery tabs profile login
Module pattern
Provides a scope, and allows
"public" and "private" APIs.
MyApp.components.photoGallery = (function (window, document, $) {
// Private properties
// ------------------
var element;
var thumbs;
var current = 0;
var timer = 5000;
// Private methods
// ---------------
var goToNext = function () {
// ...
};
var setupGallery = function () {
thumbs.on("click", function () {
// ...
});
setTimeout(function () {
goToNext();
}, timer);
}
return {
// Public methods
// --------------
init : function (el) {
element = $(el);
thumbs = element.find("[data-thumbs]");
setupGallery();
}
};
})(window, document, jQuery);
MyApp.components.photoGallery
// Private properties
// ------------------
var
var
var
var
// Private methods
// ---------------
var
};
var
thumbs.on(
});
setTimeout(
goToNext();
}, timer);
}
return
init
element
thumbs
setupGallery();
}
};
})(window
// Private properties
// ------------------
var element;
var thumbs;
var current = 0;
var timer = 5000;
// Private methods
// ---------------
var goToNext = function () {
// ...
};
var setupGallery = function () {
thumbs.on("click", function () {
// ...
});
setTimeout(function () {
goToNext();
}, timer);
}
MyApp.components.photoGallery
// Private properties
// ------------------
var
var
var
var
// Private methods
// ---------------
var
};
var
thumbs.on(
});
setTimeout(
goToNext();
}, timer);
}
return
init
element
thumbs
setupGallery();
}
};
})(window
// Public methods
// --------------
init : function (el) {
element = $(el);
thumbs = element.find("[data-thumbs]");
setupGallery();
}
It's "singleton-like".
Constructors & Prototypes
Allows multiple instances of
the same behaviour, and
prototype inheritance.
B.wishlistMap.ListItem = function (element) {
this.element = $(el);
this.init();
};
B.wishlistMap.ListItem.prototype = {
init : function () {
// ...
},
expandCard : function () {
// ...
},
contractCard : function () {
// ...
}
};
var list = $("#wl-cards");
var items = list.find(".wl-card");
items.each(function () {
$(this).data("ListItem", new B.wishlistMap.ListItem(this));
});
// or
var itemsInstances = [];
items.each(function () {
itemsInstances.push(new B.wishlistMap.ListItem(this));
});
AMD
Asynchronous
Module

Definition
// photoGallery.js
define([
"jQuery",
"myapp/lib/keycodes",
“myapp/components/Map”
], function ($, keycodes, Map) {
// ...
});
Provides a consistent API
to define modules.
// photoGallery.js
define([
],
});
// photoGallery.js
define(
);
It handles dependencies.
// photoGallery.js
define([
],
});
// photoGallery.js
[
"jQuery",
"myapp/lib/keycodes",
“myapp/components/Map”
]
It injects the
dependencies in a
callback function…
// photoGallery.js
define([
],
});
// photoGallery.js
function ($, keycodes, Map) {
}
… which gives you
freedom to implement
your solution.
// Module pattern
define([
"myDependency"
], function(myDependency) {
var myPrivateMethod = function() {
};
return {
myPublicMethod : function() {
myPrivateMethod();
}
}
});
// Constructor
define([
"myDependency"
], function(myDependency) {
var MyConstructor = function() {
};
MyConstructor.prototype.myPublicMethod = function() {
};
return MyConstructor;
});
// Simple execution
define([
"myDependency"
], function(myDependency) {
// do something
});
Whatever is returned by the
callback will be injected when
the module is required.
myapp/
components/
myComponent.js
define(function() {
return "foobar";
});
myapp/
components/
anotherComponent.js
define([
"myapp/components/myComponent"
], function(myComponent) {
console.log(myComponent === "foobar"); // true
})
You can also assign an
object literal to the module.
define({
color : "yellow",
size : "medium",
quantity : 2
});
Modules are defined
by their path…
/myapp
/components
photoGallery.js
define(function() {
});
/myapp
/components
anotherComponent.js
define([
"myapp/components/photoGallery"
], function(photoGallery) {
});
/myapp
/components
anotherComponent.js
define([
"./photoGallery"
], function(photoGallery) {
});
… or by their identifier.
define(“MyApp.components.photoGallery", function() {
});
define("MyApp.components.anotherComponent", [
"MyApp.components.photoGallery"
], function(photoGallery) {
});
// jQuery does this internally
define("jquery", function() { return jQuery; });
You can also use the
require method.
var photoGallery = require("MyApp.components.photoGallery");
photoGallery.init();
require(["MyApp.components.photoGallery"], function(photoGallery) {
photoGallery.init();
});
Its behaviour depends on
the AMD implementation.
RequireJS vs. Almond
RequireJS allows
asynchronous
module loading.
<script src="javascript/require.js" data-main="javascript/myapp/app"></script>
Be REALLY careful
with that.
r.js optimises and
combines dependencies.
(be careful with dynamic
module requests)
// won't work
require(['section/' + section]);
Lean, 1kb AMD loader.
It expects all
modules to be
already loaded.
<script src="javascript/almond.js"></script>
<script src="javascript/vendor/jquery-1.11.2.js"></script>
<script src="javascript/vendor/EventEmitter.js"></script>
<script src="javascript/myapp/components/photoGallery.js"></script>
<script src="javascript/myapp/components/myComponent.js"></script>
<script src="javascript/myapp/section/login.js"></script>
<script src="javascript/myapp/section/profile.js"></script>
<script src="javascript/myapp/ui/dropdown.js"></script>
<script src="javascript/myapp/ui/tabs.js"></script>
<script src="javascript/myapp/core/sectionInitializer.js"></script>
<script src="javascript/myapp/app.js"></script>
<script src="javascript/almond.js"></script>
<script src="javascript/app-41884634e80f3516.js"></script>
It expects all modules
to have a name.
define("myModule", [
"myDependencyA",
"myDependencyB"
],
function() {
});
Since all modules are
loaded, you can use
the simple require
function anywhere.
var photoGallery = require("MyApp.components.photoGallery");
photoGallery.init();
Gives the AMD
syntax without
extra headaches.
It (probably) works
with your existing
codebase.
APPLICATION FLOW
Single entry points
(function(){
window.app = jQuery.extend({
init: function(){
tab = $('.tabs li > a.tab-toggle');
tabs = $('.tabs').find('> div');
if (tabs.length > 1){
tab.each(function (i){$(this).attr('href', '#content-' + ++i)});
tabs.each(function(i){$(this).attr('id', 'content-' + ++i)});
tabs.addClass('tab-inactive');
$('.tabs li:first-child a').addClass('state-active');
}
$('#initial-cash, #financing_value_vehicles, #tax, #bid-initial-cash, #bid-product-value').maskMoney({
thousands: '.',
decimal: ',',
allowZero: true,
allowNegative: false,
defaultZero: true
});
/** FINANCING CALCULATOR **/
$("#financing_value_vehicles").on("blur", function(){
var price = (accounting.unformat($(this).val(), ",")) || 0;
var suggestedInitialPayment = price * 0.2;
var formattedResult = accounting.formatMoney(suggestedInitialPayment, "", "2", ".", ",");
$("#initial-cash").val(formattedResult);
});
$("#calculate-financing").click(function(event){
var price = (accounting.unformat($("#financing_value_vehicles").val(), ",")) || 0;
var rate = (accounting.unformat($("#tax").val(), ",") / 100) || 0;
var initialCash = (accounting.unformat($("#initial-cash").val(), ",")) || 0;
var value = (accounting.unformat($("#amount-finance").val(), ",")) || 0;
var finance = price - initialCash;
var months = (accounting.unformat($("#prize_parcela").val(), ",")) || 0;
var tax = parseFloat(rate);
var nominator = (Math.pow(1 + tax, months));
var denominator = ((Math.pow(1 + tax, months)) - 1);
var formattedFinance = accounting.formatMoney(finance, "", "2", ".", ",");
$("amount-finance").val(formattedFinance);
var financingValue = finance*nominator*tax/denominator;
var result = accounting.formatMoney(financingValue, "R$ ", "2", ".", ",");
$(".calculator_financing li.result p.value").text(result);
this.button = $("#calc");
if( result != ""){
$("a.button").remove();
this.button.after("<a href='financiamento/new?vehicle_value="+price+"' class='button'>Cote Agora</a>");
};
event.preventDefault();
});
$("#initial-cash").bind("blur", function () {
var price = (accounting.unformat($("#financing_value_vehicles").val(), ",")) || 0;
var initialCash = (accounting.unformat($("#initial-cash").val(), ",")) || 0;
var finance = price - initialCash;
var formattedValue = accounting.formatMoney(finance, "", "2", ".", ",");
$("#amount-finance").val(formattedValue);
});
/** ------------ **/
/** BID CALCULATOR **/
$("input#calculate-bid").click(function(event){
var price = (accounting.unformat($("#bid-product-value").val(), ",")) || 0;
var rate = (accounting.unformat($("#bid-tax").val(), ",") / 100) || 0;
var initialCash = (accounting.unformat($("#bid-initial-cash").val(), ",")) || 0;
var value = (accounting.unformat($("#bid-amount-finance").val(), ",")) || 0;
var finance = price - initialCash;
var months = (accounting.unformat($("#bid-prize_parcela").val(), ",")) || 0;
var tax = parseFloat(rate);
var nominator = (Math.pow(1 + tax, months));
var denominator = ((Math.pow(1 + tax, months)) - 1);
var formattedFinance = accounting.formatMoney(finance, "", "2", ".", ",");
$("#bid-amount-finance").val(formattedFinance);
var result = accounting.formatMoney(((finance*nominator*tax/denominator)), "R$ ", "2", ".", ",");
$(".calculator_bid li.result p.value").text(result);
event.preventDefault();
});
$("#bid-initial-cash").bind("blur", function () {
var price = (accounting.unformat($("#bid-product-value").val(), ",")) || 0;
var initialCash = (accounting.unformat($("#bid-initial-cash").val(), ",")) || 0;
var finance = price - initialCash;
var formattedValue = accounting.formatMoney(finance, "", "2", ".", ",");
$("#bid-amount-finance").val(formattedValue);
});
/** ------------ **/
$('.state-active').each(function(i){
active_tab = $(this).attr('href')
$(this).parents('section').find('div' + active_tab).addClass('tab-active')
});
$('.tooltip').hide();
if ($("html").is(".lt-ie9")) {
$('a').hover(
function(){
$(this).siblings('.tooltip').show();
},
function(){
$(this).siblings('.tooltip').hide();
}
);
} else {
$('a').hover(
function(){
$(this).siblings('.tooltip').fadeIn();
},
function(){
$(this).siblings('.tooltip').fadeOut();
}
);
}
tab.live('click', function(event){
event.preventDefault();
link = $(this).attr('href')
el = $(this).parents('.tabs')
el.find('div').removeClass('tab-active');
el.find('a').removeClass('state-active');
$(this).addClass('state-active')
el.find('div' + link).addClass('tab-active');
});
$('a').unbind('click').hasClass('state-active');
$('a.state-active').unbind('click');
$("#schedule nav a").live("click", function(event){
$('#schedule nav a').removeClass('state-active')
$(this).addClass('state-active')
$(".window div").animate({
top: "" + ($(this).hasClass("prev") ? 0 : -210) + "px"
});
event.preventDefault()
});
app.advertisementNewForm();
},
advertisementNewForm: function(){
$('span.select-image').bind('click', function(){
$(this).parent('li').find('input[type="file"]').click();
});
}
});
$().ready(app.init);
}).call(this);
Page load
jQuery load
jQuery plugins
application.js
if ($("#my-tabs").length) {
// tabs code
}
if ($("#my-gallery").length) {
// gallery code
}
if ($("#my-map").length) {
// map code
}
✗
Without a flow control, it’s
difficult separating code
execution per page/need.
Single entry points control the
flow of the application.
Page load
Vendor code
Application modules
sectionInitializer
section
module1 module2 module3 module4
Page load
Vendor code
Application modules
sectionInitializer
section
module1 module2 module3 module4
<body data-section='profile'>
define('myapp.core.sectionInitializer', function() {
var section = document.querySelector('body').dataset.section;
require('myapp.section.' + section);
});
// No logic, only modules bootstrapping
define('myapp.section.profile',
[
'myapp.components.photoGallery',
'myapp.components.activityFeed',
'myapp.ui.Tabs'
], function(photoGallery, activityFeed, Tabs) {
photoGallery.init($('[data-user-photo-gallery]'));
activityFeed.init($('[data-user-activity-feed]'));
new Tabs($('[data-user-section-tabs]'));
new Tabs($(‘[data-user-report-type-tabs]'));
});
Those initializers contain no
logic, they only init modules.
Self-registered Modules
Page load
Vendor code
Application modules
moduleInitializer
module1 module2 module3 module4
module3 HTML
module4 HTML
module1 HTML
module2 HTML
<div data-module="photoGallery">
<!-- gallery markup -->
</div>
<div data-module="wishlistMap">
<!-- map markup -->
</div>
// moduleInitializer
$("[data-module]").each(function () {
var module = $(this).data("module");
require("myapp.modules." + module).init(this);
});
Each module
“initializes itself”.
Action/section free,
global use.
EVENTS
Observer Pattern
Observable (server)
“When a new episode is
available, I’ll notify all pirat—I
mean—clients."
Observer (client/pirate)
“Whenever the server notifies
me about a new episode, I’ll
download it.”
OBSERVER OBSERVABLE
Yo, can you give me a
shout out whenever a new
GoT episode comes out?
Sure, my good sire!
YO
"THE RAINS OF
CASTAMERE" IS OUT GET
IT WHILE IT’S HOT
Cool, then I’ll download
it! It’ll surely by a very
happy episode <3
// Pirate observes torrent server
torrentServer.on("new-got-episode", function (name) {
this.download(name);
});
// Torrent server publishes that it has a new GoT episode
this.trigger("new-got-episode", "The Rains of Castamere");
Mediator
Facilitates the
communication
between modules.
MEDIATOR
All modules have no
knowledge about each other,
except for the Mediator.
MEDIATOR
Mediator, please tell me
when a new The Walking
Dead episode comes out
Sure thing
MEDIATOR
Mediator, please tell me
when a new Mythbusters
episode comes out
Groovy.
Hey, I’ll want that
as well!
Jammin'.
MEDIATOR
Mediator, there’s a new
The Walking Dead episode!
Here’s the link!
Yo folks, there’s a new
The Walking Dead
episode! Here’s the link!
Oh yeah, I’ll get it
right now!
MEDIATOR
Mediator, there’s a new
Mythbusters episode!
Here’s the link!
Yo everyone, there’s a
new Mythbusters
episode! Here’s the link!
Cool, I’ll download
it!
Tnx yo!
// Pirate 1 subscribes to mediator
mediator.on("new-twd-episode", function (data) {
console.log("Downloading " + data.name + " from " + data.link);
});
mediator.on("new-mythbusters-episode", function (data) {
console.log("Downloading " + data.name + " from " + data.link);
});
// Pirate 2 subscribes to mediator
mediator.on("new-mythbusters-episode", function (data) {
console.log("Downloading " + data.name + " from " + data.link);
});
// Torrent server 1 publishes on mediator
mediator.trigger("new-twd-episode", {
link : "http://foo.bar",
name : "The Suicide King"
});
// Torrent server 2 publishes on mediator
mediator.trigger("new-mythbusters-episode", {
link : "http://theillegalbay.br",
name : "Hollywood Myths"
});
Everyone knows only
the Mediator.
jQuery
MyApp.mediator = $({});
Mixin
// MyApp.myModule now has the `on`, `off` and `trigger` methods
$.extend(MyApp.myModule, EventEmitter.prototype);
MyApp.components.myModule.trigger("my-event", "my-data");
GETTING REAL
AMD
vs.
CommonJS
vs.
Plain Objects
vs.
ES6
How does your
product work?
Synchronous or
asynchronous?
Do you have a
build process?
Will you use client-side
code on the server-side?
Are you feeling lucky?
Events
vs.
Promises
vs.
Dependency Injection
vs.
ES6
¯_(ツ)_/¯
In the end, there’s no
unique solution.
Choose whatever makes
you and your team more
comfortable.
If you do it right,
JavaScript can be fun.
THANKS!slideshare.net/eshiota
github.com/eshiota
@shiota

Mais conteúdo relacionado

Mais procurados

Enjoy the vue.js
Enjoy the vue.jsEnjoy the vue.js
Enjoy the vue.jsTechExeter
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.jsJay Phelps
 
Dependency Management with RequireJS
Dependency Management with RequireJSDependency Management with RequireJS
Dependency Management with RequireJSAaronius
 
An introduction to Ember.js
An introduction to Ember.jsAn introduction to Ember.js
An introduction to Ember.jscodeofficer
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceParashuram N
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Chris Alfano
 
Survey of Front End Topics in Rails
Survey of Front End Topics in RailsSurvey of Front End Topics in Rails
Survey of Front End Topics in RailsBenjamin Vandgrift
 
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013GetSource
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 
JavaScript for Flex Devs
JavaScript for Flex DevsJavaScript for Flex Devs
JavaScript for Flex DevsAaronius
 
[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법Jeado Ko
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS DirectivesEyal Vardi
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS InternalEyal Vardi
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowVrann Tulika
 
Building a dashboard using AngularJS
Building a dashboard using AngularJSBuilding a dashboard using AngularJS
Building a dashboard using AngularJSRajthilakMCA
 
iPhone Appleless Apps
iPhone Appleless AppsiPhone Appleless Apps
iPhone Appleless AppsRemy Sharp
 
Laravel 로 배우는 서버사이드 #5
Laravel 로 배우는 서버사이드 #5Laravel 로 배우는 서버사이드 #5
Laravel 로 배우는 서버사이드 #5성일 한
 
Ionic으로 모바일앱 만들기 #4
Ionic으로 모바일앱 만들기 #4Ionic으로 모바일앱 만들기 #4
Ionic으로 모바일앱 만들기 #4성일 한
 

Mais procurados (20)

Enjoy the vue.js
Enjoy the vue.jsEnjoy the vue.js
Enjoy the vue.js
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.js
 
Dependency Management with RequireJS
Dependency Management with RequireJSDependency Management with RequireJS
Dependency Management with RequireJS
 
An introduction to Ember.js
An introduction to Ember.jsAn introduction to Ember.js
An introduction to Ember.js
 
Intro to Ember.JS 2016
Intro to Ember.JS 2016Intro to Ember.JS 2016
Intro to Ember.JS 2016
 
IndexedDB - Querying and Performance
IndexedDB - Querying and PerformanceIndexedDB - Querying and Performance
IndexedDB - Querying and Performance
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
Survey of Front End Topics in Rails
Survey of Front End Topics in RailsSurvey of Front End Topics in Rails
Survey of Front End Topics in Rails
 
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
Image Manipulation in WordPress 3.5 - WordCamp Phoenix 2013
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 
JavaScript for Flex Devs
JavaScript for Flex DevsJavaScript for Flex Devs
JavaScript for Flex Devs
 
[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법[FEConf Korea 2017]Angular 컴포넌트 대화법
[FEConf Korea 2017]Angular 컴포넌트 대화법
 
AngularJS Directives
AngularJS DirectivesAngularJS Directives
AngularJS Directives
 
AngularJS Internal
AngularJS InternalAngularJS Internal
AngularJS Internal
 
Magento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request FlowMagento Live Australia 2016: Request Flow
Magento Live Australia 2016: Request Flow
 
Building a dashboard using AngularJS
Building a dashboard using AngularJSBuilding a dashboard using AngularJS
Building a dashboard using AngularJS
 
iPhone Appleless Apps
iPhone Appleless AppsiPhone Appleless Apps
iPhone Appleless Apps
 
Laravel 로 배우는 서버사이드 #5
Laravel 로 배우는 서버사이드 #5Laravel 로 배우는 서버사이드 #5
Laravel 로 배우는 서버사이드 #5
 
Jquery ui
Jquery uiJquery ui
Jquery ui
 
Ionic으로 모바일앱 만들기 #4
Ionic으로 모바일앱 만들기 #4Ionic으로 모바일앱 만들기 #4
Ionic으로 모바일앱 만들기 #4
 

Semelhante a Modular and Event-Driven JavaScript

Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery ApplicationsRebecca Murphey
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScriptAndrew Dupont
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuerysergioafp
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretssmueller_sandsmedia
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsJarod Ferguson
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5arajivmordani
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of usOSCON Byrum
 
JQuery In Drupal
JQuery In DrupalJQuery In Drupal
JQuery In Drupalkatbailey
 
Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Fabio Biondi
 
Building Robust jQuery Plugins
Building Robust jQuery PluginsBuilding Robust jQuery Plugins
Building Robust jQuery PluginsJörn Zaefferer
 
Secrets of JavaScript Libraries
Secrets of JavaScript LibrariesSecrets of JavaScript Libraries
Secrets of JavaScript Librariesjeresig
 
JavaScript on Rails 튜토리얼
JavaScript on Rails 튜토리얼JavaScript on Rails 튜토리얼
JavaScript on Rails 튜토리얼Sukjoon Kim
 

Semelhante a Modular and Event-Driven JavaScript (20)

Building Large jQuery Applications
Building Large jQuery ApplicationsBuilding Large jQuery Applications
Building Large jQuery Applications
 
JQuery Flot
JQuery FlotJQuery Flot
JQuery Flot
 
Writing Maintainable JavaScript
Writing Maintainable JavaScriptWriting Maintainable JavaScript
Writing Maintainable JavaScript
 
jQuery secrets
jQuery secretsjQuery secrets
jQuery secrets
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
international PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secretsinternational PHP2011_Bastian Feder_jQuery's Secrets
international PHP2011_Bastian Feder_jQuery's Secrets
 
Taming that client side mess with Backbone.js
Taming that client side mess with Backbone.jsTaming that client side mess with Backbone.js
Taming that client side mess with Backbone.js
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
The Beauty Of Java Script V5a
The Beauty Of Java Script V5aThe Beauty Of Java Script V5a
The Beauty Of Java Script V5a
 
The Beauty of Java Script
The Beauty of Java ScriptThe Beauty of Java Script
The Beauty of Java Script
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
G* on GAE/J 挑戦編
G* on GAE/J 挑戦編G* on GAE/J 挑戦編
G* on GAE/J 挑戦編
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of us
 
jQuery
jQueryjQuery
jQuery
 
JQuery In Drupal
JQuery In DrupalJQuery In Drupal
JQuery In Drupal
 
Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)Single Page Applications in Angular (italiano)
Single Page Applications in Angular (italiano)
 
Building Robust jQuery Plugins
Building Robust jQuery PluginsBuilding Robust jQuery Plugins
Building Robust jQuery Plugins
 
Secrets of JavaScript Libraries
Secrets of JavaScript LibrariesSecrets of JavaScript Libraries
Secrets of JavaScript Libraries
 
JavaScript on Rails 튜토리얼
JavaScript on Rails 튜토리얼JavaScript on Rails 튜토리얼
JavaScript on Rails 튜토리얼
 

Mais de Eduardo Shiota Yasuda

The anatomy of an A/B Test - JSConf Colombia Workshop
The anatomy of an A/B Test - JSConf Colombia WorkshopThe anatomy of an A/B Test - JSConf Colombia Workshop
The anatomy of an A/B Test - JSConf Colombia WorkshopEduardo Shiota Yasuda
 
Internationalisation: 2200+ different ways to view a website
Internationalisation: 2200+ different ways to view a websiteInternationalisation: 2200+ different ways to view a website
Internationalisation: 2200+ different ways to view a websiteEduardo Shiota Yasuda
 
Web Audio Band - Playing with a band in your browser
Web Audio Band - Playing with a band in your browserWeb Audio Band - Playing with a band in your browser
Web Audio Band - Playing with a band in your browserEduardo Shiota Yasuda
 
RetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio API
RetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio APIRetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio API
RetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio APIEduardo Shiota Yasuda
 
Criando uma arquitetura de front-end do zero
Criando uma arquitetura de front-end do zeroCriando uma arquitetura de front-end do zero
Criando uma arquitetura de front-end do zeroEduardo Shiota Yasuda
 
Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...
Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...
Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...Eduardo Shiota Yasuda
 
Desafios do Desenvolvimento de Front-end em um e-commerce
Desafios do Desenvolvimento de Front-end em um e-commerceDesafios do Desenvolvimento de Front-end em um e-commerce
Desafios do Desenvolvimento de Front-end em um e-commerceEduardo Shiota Yasuda
 
Sushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire Japan
Sushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire JapanSushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire Japan
Sushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire JapanEduardo Shiota Yasuda
 
O Design e a Interface no mundo da Programação
O Design e a Interface no mundo da ProgramaçãoO Design e a Interface no mundo da Programação
O Design e a Interface no mundo da ProgramaçãoEduardo Shiota Yasuda
 

Mais de Eduardo Shiota Yasuda (12)

Front-end Culture @ Booking.com
Front-end Culture @ Booking.comFront-end Culture @ Booking.com
Front-end Culture @ Booking.com
 
The anatomy of an A/B Test - JSConf Colombia Workshop
The anatomy of an A/B Test - JSConf Colombia WorkshopThe anatomy of an A/B Test - JSConf Colombia Workshop
The anatomy of an A/B Test - JSConf Colombia Workshop
 
Dominating the Web Typography
Dominating the Web TypographyDominating the Web Typography
Dominating the Web Typography
 
Internationalisation: 2200+ different ways to view a website
Internationalisation: 2200+ different ways to view a websiteInternationalisation: 2200+ different ways to view a website
Internationalisation: 2200+ different ways to view a website
 
Web Audio Band - Playing with a band in your browser
Web Audio Band - Playing with a band in your browserWeb Audio Band - Playing with a band in your browser
Web Audio Band - Playing with a band in your browser
 
RetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio API
RetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio APIRetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio API
RetroJS - Escrevendo músicas da era 8-bits com JavaScript e Web Audio API
 
Criando uma arquitetura de front-end do zero
Criando uma arquitetura de front-end do zeroCriando uma arquitetura de front-end do zero
Criando uma arquitetura de front-end do zero
 
Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...
Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...
Baby.com.br: Analisando, adaptando e melhorando a arquitetura da informação e...
 
Desafios do Desenvolvimento de Front-end em um e-commerce
Desafios do Desenvolvimento de Front-end em um e-commerceDesafios do Desenvolvimento de Front-end em um e-commerce
Desafios do Desenvolvimento de Front-end em um e-commerce
 
User Experience para Developers
User Experience para DevelopersUser Experience para Developers
User Experience para Developers
 
Sushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire Japan
Sushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire JapanSushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire Japan
Sushi e Interfaces - PechaKucha São Paulo Vol. 8 + Inspire Japan
 
O Design e a Interface no mundo da Programação
O Design e a Interface no mundo da ProgramaçãoO Design e a Interface no mundo da Programação
O Design e a Interface no mundo da Programação
 

Último

Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfhans926745
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 

Último (20)

Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 

Modular and Event-Driven JavaScript