• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Functional widgets in Rails
 

Functional widgets in Rails

on

  • 1,388 views

 

Statistics

Views

Total Views
1,388
Views on SlideShare
1,388
Embed Views
0

Actions

Likes
0
Downloads
4
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Functional widgets in Rails Functional widgets in Rails Presentation Transcript

    • Functional widgets in Rails Sebastian Sito
    • Co to jest widget? mała aplikacja wbudowana w stronę WWW może być funkcjonalna lub statyczna
    • Przykład? AlleWidget Google Gadgets Facebook like buttons
    • Na początek statyczny content<script type="text/javascript" src="http://hostapp.com/api/widget/main"></script>
    • Uwaga na Operę!<script type="text/javascript" src="http://hostapp.com/api/widget/main.js"></script>
    • Po stronie aplikacjiapp/controllers/widget_controller.rbclass Api::WidgetController < ApplicationController layout :nil def main respond_to do |format| format.js end endend
    • Po stronie aplikacjiapp/views/api/widget/main.js.erbdocument.write(<div id="widget">);<%= @title %>document.write(</div>);
    • Personalizacja widgetuapp/controllers/widget_controller.rbclass Api::WidgetController < ApplicationController layout :nil before_filter :validate_api_key def main respond_to do |format| format.js end endend
    • Personalizacja widgetuconfig/routes.rbnamespace :api do match /widget/:action/:api_key, :controller => widget, :api_key => /.*/endapp/controllers/api/widget_controller.rbdef validate_api_key render :text => Invalid API key unless params[:api_key] and return render :text => Wrong API credentials if not User.find_by_key(params[:api_key]) and returnend
    • Personalizacja widgetu<script type="text/javascript"> var __apiKey = "qcg35cgwhojpm839v5";</script><script type="text/javascript" src="http://hostapp.com/api/widget/main"></script>
    • Widget funkcjonalnyMamy problem: aplikacja i widget to dwie różne domeny!
    • JSONP z pomocąCzęsto używany, żeby obejść problemy związane zkomunikacją między domenami.JSONvar xhr = new XMLHttpRequest();xhr.onreadystatechange = function () { if (xhr.readyState == 4 && xhr.status == 200) { // success };};xhr.open("GET", "http://somewhere", true);xhr.send();
    • JSONP z pomocąJSONPvar tag = document.createElement("script");tag.src = http://somewhere?callback=foo;document.getElementsByTagName("head")[0].appendChild(tag);
    • Jaka jest różnica?Różnica w zapytaniu JSONP polega na tym, że odpowiedź jestprzekazywana jako argument wywołania funkcji - stąd parametrcallback.WAŻNE!W odróżnieniu od zwykłego zapytania XHR w zapytaniuJSONP nie można wyłapać błędów - dostajemy poprostuParseError
    • Jaka jest różnica?Różnica w zapytaniu JSONP polega na tym, że odpowiedź jestprzekazywana jako argument wywołania funkcji - stąd parametrcallback.WAŻNE!W odróżnieniu od zwykłego zapytania XHR w zapytaniuJSONP nie można wyłapać błędów - dostajemy poprostuParseError Na szczęście jQuery robi to za nas!
    • JSONP i Rails 3Musimy obsłużyć:http://hostapp.com/api/widget/action?callback=foo
    • JSONP i Rails 3Musimy obsłużyć:http://hostapp.com/api/widget/action?callback=fooOdpowiedź można sformułować tak:render :json => @items.to_json, :callback => params[:callback]
    • JSONP i Rails 3Musimy obsłużyć:http://hostapp.com/api/widget/action?callback=fooOdpowiedź można sformułować tak:render :json => @items.to_json, :callback => params[:callback]Otrzymujemy błędy z powodu innej domeny z którą chcemy siępołączyć?
    • SameOriginPolicyclass Api::WidgetController < ApplicationController after_filter :set_access_control_headersend
    • SameOriginPolicyclass Api::WidgetController < ApplicationController after_filter :set_access_control_headersenddef set_access_control_headers headers[Access-Control-Allow-Origin] = * headers[Access-Control-Request-Method] = *end
    • Wszystko razemJeśli widget ma wiele funkcji, trzeba jakoś sprytnie ustalićsposób komunikacji.
    • Wszystko razemJeśli widget ma wiele funkcji, trzeba jakoś sprytnie ustalićsposób komunikacji.
    • Ładowanie widgetuPomysł polega na umieszczeniu całej logiki komunikacji iwidoku w samym widgecie, dzięki czemu zaoszczędzimy narequestach (będziemy wysyłać i odbierać tylko dane)<script type="text/javascript" src="http://hostapp.com/api/widget/main"></script>app/views/api/widget/main.js.erbif(window.Widget == undefined) { window.Widget = { // logic here}}
    • Logika widgetuif(window.Widget == undefined) { window.Widget = { Settings: {}, API: {}, Handlers: {}, GUI: {} }}$(document).ready(function() {Widget.API.call(init, {});});
    • UstawieniaSettings: { api: { url: "http://hostapp.com/api/widget" }}
    • APIAPI: { call: function(action, data) { var url = Widget.Settings.api.url + / + action; data[api_key] = __apiKey; $.ajax({url: url,data: data,crossDomain: true, dataType: "jsonp", success: Widget.API.responseHandler });}
    • Rails responsedef widget_response(action, data) response_hash = {:action => action, :data => data} render :json => response_hash.to_json, :callback => params[:callback]end
    • APIAPI: { responseHandler: function() { Widget.Handlers[action](response.data) }}
    • HandlersHandlers: { init: function(data) { // populate widget with data // and draw some GUI Widget.GUI.render(data); }}
    • Jeszcze ciekawiej: IFRAME w widgecieCo jeśli w swoim widgecie uruchomimy jeszcze inną stronę wIFRAME i będziemy chcieli mieć możliwość odpowiedzieć zniego na pewne zdarzenie w IFRAME?
    • Jeszcze ciekawiej: IFRAME w widgecieCo jeśli w swoim widgecie uruchomimy jeszcze inną stronę wIFRAME i będziemy chcieli mieć możliwość odpowiedzieć zniego na pewne zdarzenie w IFRAME? Hash pooling
    • Jeszcze ciekawiej: IFRAME w widgecieCo jeśli w swoim widgecie uruchomimy jeszcze inną stronę wIFRAME i będziemy chcieli mieć możliwość odpowiedzieć zniego na pewne zdarzenie w IFRAME? Hash poolingWidget.interval = setInterval(handleWindowHash, 1000)teraz z wewnątrz IFRAME zmieniamy hash okna nadrzędnegowindow.location.hash = "trigger_sth"
    • PrzykładHost Apphttp://rails-widget-example.heroku.comWidget<!doctype html><html><head><title>Widget Client</title> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> var __userSecret = 8102260836164404; </script> <script type="text/javascript" src="http:// rails-widget-example.heroku.com/api/widget/main.js"> </script></head> <body><div><h1>Widget example</h1></div><div id="widget_placeholder"></div> </body></html>
    • Dzięki :)E-mail sebastian@emaire.comTwitter @sebastiandreakeKod aplikacji live https://github.com/dreake/widget