Académique Documents
Professionnel Documents
Culture Documents
@shiota
2013
ol!
slideshare.net/eshiota github.com/eshiota @shiota
projeto greeneld
(a.k.a. o sonho de todo desenvolvedor)
* veja http://simplebits.com/publications/bulletproof/
latest
latest
5+ iOS 6+
8+
u mad?
latest
latest
5+ iOS 6+
8+
CSS
pre-processors: sass
@import "compass/css3";!
!
@import @import @import @import "base/variables";! "base/functions";! "base/mixins";! "base/helpers";! "core/reset";! "core/basic";! "core/forms";! "core/tables";! "core/typography";! "core/icons";! "core/buttons";!
!
@import @import @import @import @import @import @import
!
@import "layout/main";! @import "layout/header";! @import "layout/footer";!
!
@import @import @import @import "ui/loader";! "ui/loaderBar";! "ui/flashMessage";! "ui/breadcrumb";
app/! assets/! stylesheets/! base/! _functions.scss! _mixins.scss! _variables.scss! ui/! _breadcrumb.scss! _carousel.scss! _dentedBox.scss! _flashMessage.scss
/*********************************************************************! *! * Variables Module! *! * All constants that will be used through the styles must be! * defined here.! *! *********************************************************************/!
!
/*********************************************************************! * =Dimensions! *********************************************************************/!
!
$SITE_WIDTH: 978px;! $FOOTER_HEIGHT : 812px;! $DEFAULT_FONT_SIZE : 16px;!
!
/*********************************************************************! * =Colors! *********************************************************************/!
!
$TEXT_COLOR: #555;! $LINK_COLOR: #447f87;!
!
$PURPLE: #905194;! $LIGHT: #fefefa;! $ORANGE: #fbb100;! $YELLOW: #fffd7d;
/*********************************************************************! * =Image replacement! *! * `display` property may be overridden by the element.! *********************************************************************/!
!
%image_replacement {! text-indent: 101%;! overflow: hidden;! white-space: nowrap;! display: block;! }
.my-logo {! text-indent: 100%;! overflow: hidden;! white-space: nowrap;! display: block;! width: 200px;! height: 280px;! background: url("mylogo.png");! }! ! .my-other-logo {! text-indent: 100%;! overflow: hidden;! white-space: nowrap;! display: block;! width: 100px;! height: 150px;! background: url("myotherlogo.png");! }
.my-logo {! @extend %image_replacement;! width: 200px;! height: 280px;! background: url("mylogo.png");! }! ! .my-other-logo {! @extend %image_replacement;! width: 100px;! height: 150px;! background: url("myotherlogo.png");! }
!
.section-header {! width: 100%;! height: 15em;! color: #fff;! background-color: #905194;! background-position: center center;! background-repeat: no-repeat;! background-image: url("themes/default_bg.jpg");! text-align: center;! }!
!
.my-theme1 {! background-color: #fbb100;! color: #fff;! background-image: url("themes/theme1_bg.jpg");! }!
!
.my-theme2 {! background-color: #fefefa;! color: #333;! background-image: url("themes/theme2_bg.jpg");! }
@mixin header_theme($background_color: #905194, $text_color: #fff, $image: "default_bg.jpg") {! background-color: $background_color;! color: $text_color;! background-image: url("themes/#{$image}");! }
!
.section-header {! @include header_theme;! width: 100%;! height: 15em;! background-position: center center;! background-repeat: no-repeat;! text-align: center;! }!
!
.my-theme1 {! @include header_theme(#fefefa, #333, "theme2_bg.jpg");! }!
!
.my-theme2 {! @include header_theme(#fefefa, #333, "theme2_bg.jpg");! }
! !
@if $unit == "px" { $one: 1px; }! @if $unit == "em" { $one: 1em; }! @if $unit == "%" { $one: 1%; }! @return $number / $one;!
}!
// Returns flexible value using `target "context` formula.! // Returns `em` by default, accepts `%` as format.! @function flex($target, $context, $unit: "em") {! $size: remove-unit($target) / remove-unit($context);!
! !
@if $unit == "em" { @return #{$size}em; }! @if $unit == "%" { @return percentage($size); }!
}! // Alias to `flex` function, using `%` as format.! @function perc($target, $context: $DEFAULT_FONT_SIZE) {! @return flex($target, $context, "%");! }!
// Alias to `flex` function, using `em` as format.! @function em($target, $context: $DEFAULT_FONT_SIZE) {! @return flex($target, $context, "em");! }
modularizao
/*****************************************************************************! *! * UI "Flyout! *! * Flyouts are those UI components that look like tooltip, and! * are activated when the user clicks on a link. The flyout window! * opens text to the link, like those present on the iPad.! *! * **Usage**! *! * <div class="flyout-container">! * <div class="flyout [vertical-position]-[horizontal-position]-flyout">! * Flyout content! * </div>! * </div>! *! *****************************************************************************/!
! !
.flyout-container {! position: relative;! z-index: 100; // may be adjusted as needed through a context! }! .flyout {! @include box-sizing(border-box);! background: #f9f9f9;! border-radius: 2px;! border: 1px solid #d5d5d5;! box-shadow: 0 2px 0 rgba(0, 0, 0, .1);! display: none;! position: absolute;!
// tip! &:after {! content: "";! display: block;! width: 40px;! height: 22px;! background: sprite($icon-sprite, tooltip_top_large_gray) no-repeat;! position: absolute;! }!
}!
...
Open/close Principle
Mdulos de CSS devem poder ser extendidos sem modicar sua denio core.
! !
@mixin loader_sprite_position($xoffset, $yoffset) {! background-position: sprite-position($icon-sprite, loader_sprite, $xoffset, $yoffset);! }! .loader {! width: 25px;! height: 25px;! display: none;! }!
{ { { { { { { {
loader_sprite_position(-10px, -10px); }! loader_sprite_position(-45px, -10px); }! loader_sprite_position(-80px, -10px); }! loader_sprite_position(-115px, -10px); }! loader_sprite_position(-150px, -10px); }! loader_sprite_position(-185px, -10px); }! loader_sprite_position(-220px, -10px); }! loader_sprite_position(-255px, -10px); }
// On ui/_buttons.scss!
!
.bt-wrapper .loader {! position: absolute;! z-index: 4;! right: 20px;! top: 50%;! margin-top: -9px;! }!
!
// On modules/_checkoutAddressForm.scss!
!
.address-form .cep-input .loader {! position: absolute;! right: -33px;! top: em(29px);! }
.yout
guias de estilo
#cheat #wip
JavaScript
Voc precisa de uma soluo pronta pra fazer bind entre view e dados?
Voc precisa de uma estrutura pronta e fechada para manter a consistncia do cdigo?
decises de arquitetura
(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);!
beforeCommand
controllerCommand
actionCommand
afterCommand
beforeCommand
controllerCommand
actionCommand
afterCommand
<body data-dispatcher="products#show">
dispatcher.js
products#show
beforeCommand() productsControllerCommand()
afterCommand()
productsShowCommand()
namespaces
window.MYAPP = {! commands : {! productsShowCommand : function () {! console.log("Execute code from products#show page");! }! }! };! ! MYAPP.commands.productsShowCommand();
;(function (root) {! root.ns = function (name, obj, scope) {! var parts = name.split(".")! , curScope = scope || root! , curPart! , curObj! ;!
!
obj = obj || {};!
!
while (typeof (curPart = parts.shift()) !== "undefined") {! curObj = (parts.length > 0)! ? ((typeof curScope[curPart] !== "undefined") ? curScope[curPart] : {})! : obj;!
!
curScope[curPart] = curObj;!
!
curScope = curScope[curPart];! }!
!
return curScope;! };! })(this);
ns("MYAPP.commands.productsShowCommand", function () {! console.log("Execute code from products#show page");! });! ! // Same as:! ! window.MYAPP = {! commands : {! productsShowCommand : function () {! console.log("Execute code from products#show page");! }! }! };
module.js
!
EDEN.forms.AddressForm = function (el) {! this.element = $(el);! this.init();! }!
!
$.extend(EDEN.forms.AddressForm.prototype, {!
!
// Public methods! // --------------!
!
// Inits the instance! init : function () {! // Do something! }!
!
});!
!
var shippingAddressForm = new EDEN.forms.AddressForm($("#shipping-address"));
! ! ! ! ! !
});! var shippingAddressForm = Module.run("EDEN.forms.AddressForm", $("#shipping-address"));! // or! var shippingAddressForm = new EDEN.forms.AddressForm($("#shipping-address"));
MEDIATOR
Blz
MEDIATOR
nish.
MEDIATOR
MEDIATOR
MEDIATOR
!
_registerInterests : function () {! this.element.find(".cep-input")! .on("keyup paste cut", this._onCepModification.bind(this)); },! !
!
_onCepModification : function (event) {! if (this.isCepFilled()) {! EDEN.mediator.trigger("shipping-cep-change", event.target.value);! } else {! EDEN.mediator.trigger("shipping-cep-incomplete", event.target.value);! }! }
!
_registerInterests : function () {! EDEN.mediator.on("shipping-cep-change", this._onShippingCepChange, this);! this.shippingService.on("get-success", this._onShippingGetSuccess, this);! },!
!
_onShippingCepChange : function (cep) {! this.shippingService.get(cep);! }!
!
_onShippingGetSuccess : function (data) {! EDEN.mediator.trigger("shipping-rate-change", data.rate);! EDEN.mediator.trigger("delivery-estimate-change", data.estimate);! }
! ! ! ! ! ! ! !
_onShippingRateChange : function (rate) {! this.updateShippingRate(rate);! },! _onDeliveryEstimateChange : function (days) {! this.updateDeliveryEstimate(days);! },! updateShippingRate : function (rate) {! var formatter = EDEN.currency.formatter;! this.element.find(".shipping-rate").text(formatter(rate));! this.shippingRate = rate;!
this.updateTotal();! },! updateTotal : function () {! var total = this.subtotal + this.shippingRate,! formatter = EDEN.currency.formatter;! this.element.find(".total").text(formatter(total));! EDEN.mediator.trigger("cart-total-change", total);!
!
_registerInterests : function () {! EDEN.mediator.on("cart-total-change", this._onCartTotalChange, this);! },!
!
_onCartTotalChange : function (total) {! this.updateInstallments(total);! },!
!
updateInstallments : function (total) {! // Updates the values! }
testes
! ! ! ! ! ! !
beforeEach(function () {! loadFixtures("loader.html");! });! afterEach(function () {! $("body").find(".loader").remove();! });! it("accepts instance creation without new operator", function () {! var newLoader = Loader();! expect(newLoader).toBeInstanceOf(Loader);! });! it("appends the loader to body as a default", function () {! var loader = new Loader();! expect($("body").find(".loader").length).toEqual(1);! });! it("appends the loader through an argument function", function () {! var loader = new Loader(function ($loader) {! $("#loader-placeholder").append($loader);! });!
HTML
sintaxe: erb
<% product.foreach_variant(current_cart) do |variant, size, i| %>! <label class="variant">! <input value="<%= size.value %>" name="product_size" type="radio"! data-price="<%= variant.price.to_f %>" data-variant-sku="<%= variant.sku %>"! class="<%= "disabled" unless variant.has_stock? %>" />! <span class="variant-name"><%= size.value %></span>! </label>! <% end %>
classes semnticas
<div class="column-left">! <!-- Dropdown Categoria -->! <!-- Dropdown Marca -->! </div>!
!
<div class="column-right">! <!-- Product Navigation -->! <!-- Products List -->! </div>
column-left?
column-right?
<div class="products-search-filters">! <!-- Dropdown Categoria -->! <!-- Dropdown Marca -->! </div>!
!
<div class="products-search-filtered-results">! <!-- Product Navigation -->! <!-- Products List -->! </div>
products-search-lters
products-search-ltered-results
data-attributes
contentDropdown.js
<div class="size-selector">! <div class="size-selector-header" data-dropdown-header>! <!-- some title, could be anything -->! </div>!
!
<div class="size-selector-content" data-dropdown-content>! <!-- content here -->! </div>! </div>!
!
<div class="filter-selector">! <div class="filter-selector-header" data-dropdown-header>! <!-- some title, could be anything -->! </div>!
!
<div class="filter-selector-content" data-dropdown-content>! <!-- content here -->! </div>! </div>
// Inits the `ContentDropdown` instance! //! // * `el`: jQuery selector! init : function (el) {! this.element = $(el);! this.content = this.element.byData("dropdown-content");! this.selection = this.element.byData("dropdown-selection");! }
dicas adicionais
performance client-side
/* Compass sprite function receives the map variable and image as arguments */!
!
background: sprite($icon-sprite, arrow_dropdown) no-repeat;
!
background: url(/assets/icon-s5dab8c2901.png) -40px -158px no-repeat;
Use inline images para imagens < 1KB que estaro apenas em um lugar do CSS.
!
background: #f5f3eb inline-image("bg_dots.png") repeat;
!
background: #f5f3fb url('data:image/ png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAQCAMAAAAcVM5PAAAAGXRFWHRTb2Z0d2FyZQBBZG9 iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRF5+TW////////4qZUpQAAAAN0Uk5T// 8A18oNQQAAACBJREFUeNpiYGBgAgMGBkYog4mJXAbILAiDkVxzAAIMAEMOAPMId2OWAAAAAElFTkSuQmCC ') repeat;
code standards
"O cdigo deve parecer que foi escrito pela mesma pessoa, independente de quem o escreveu."
TL;DR
Alta performance client-side Interface facilmente modicvel Componentes portveis entre diferentes aplicaes Bulletproof web design Tipograa e grids exveis, responsive-ready Baixa barreira de entrada para outros desenvolvedores
obrigado!
slideshare.net/eshiota github.com/eshiota @shiota