road to mobile w/ sinatra, jquery mobile, spine.js and mustache
DESCRIPTION
Ruby is powerful server-side language with great collection of libraries and frameworks but to create a full mobile offering, Ruby developers need to become masters of many a craft. In this talk we'll walk through the design and development of a full stack HTML5 mobile application using Sinatra to create a robust RESTful API, Spine.js to bring MVC order to the client and jQuery Mobile to style and structure the application for the mobile world.TRANSCRIPT
![Page 1: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/1.jpg)
By Brian Sam-Bodden
with jqm, spine.mvc, sinatra and mustache
The Road to Mobile Web Development
1
![Page 2: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/2.jpg)
WHAT I HAVE FOR YOU...
2
• A possible path to mobile web applications:
• Sinatra + Mustache for a Simpler Server-Side• jQuery Mobile for Out-of-the-box Mobile• Spine.js for MVC goodness on the Client-Side• Where to start? Front-to-Back or Back-to-Front?
2
![Page 3: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/3.jpg)
THE MOBILE WEBAGENT COMPUTING COMES OF AGE
3
![Page 4: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/4.jpg)
“...the future of computing is mobile... businesses should have their best developers working on their mobile
applications”Google’s Eric Schmidt Interview on TechCrunch, April 2010
4
MOBILE WEBAGENT COMPUTING COMES OF AGE
4
![Page 5: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/5.jpg)
• 20%: decline of home PC usage since 2008 (1)
• 74%: increase of smart phones sold from 2010 to 2011(2)
• 261%: increase in smart tablets sold from 2010 to 2011(3)
• $9 billion: predicted US mobile shopping sales in 2011 (4)
• 10.8%: people who used a mobile device to visit a retailer’s site on Cyber Monday (up from 3.9% in 2010) (4)
MOBILE WEBSOME STATISTICS
5
5
![Page 6: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/6.jpg)
“Manufacturers shipped more smartphones than personal
computers in the fourth quarter of 2010... crowning
mobile devices as the computing platform of choice.
Financial Times Article, February 2011
6
MOBILE WEBMOVE OVER PCS
6
![Page 7: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/7.jpg)
• In a Mall Kiosk in Ft. Lauderdale, Florida:
7
MOBILE WEBSEEN IN UNUSUAL PLACES
7
![Page 8: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/8.jpg)
8
![Page 9: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/9.jpg)
9
HTML5WHAT YOU NEED TO KNOW
Big Picture: Canvas, Video, Geolocation and Offline Web Apps
9
![Page 10: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/10.jpg)
10
HTML5WHAT YOU NEED TO KNOW
Big Picture: IE Still Sucks! Who owns a windows phone anyways? :-)
10
![Page 11: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/11.jpg)
• Simplified header and doctype: <!DOCTYPE html>
• Script tag doesn’t need type attribute
• Many more semantic tags added like header, nav, section, article, aside, footer, details, summary, address, figure, output, time, pubdate, nav, first, last, next, prev, menu, command, mark, strong, progress, meter and many, many more
• Data attributes (data-*)
• Media Tags
HTML5WHAT YOU NEED TO KNOW
11
11
![Page 12: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/12.jpg)
• Native GeoLocation API for Mobile Browsers
• 2D Graphics with Canvas
• Many new form input types
• Datalist
• Markup-driven form validation
• Local Storage, Web Sockets, Web Workers
HTML5WHAT YOU NEED TO KNOW
12
12
![Page 13: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/13.jpg)
THE ROAD TO MOBILEBROWSER-BASED OR NATIVE?
13
![Page 14: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/14.jpg)
WEB OR NATIVE?MAKING AN INFORM DECISION
14
• Number of Mobile Web Apps have quickly surpassed their native counterparts
14
![Page 15: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/15.jpg)
WEB OR NATIVE?MAKING AN INFORM DECISION
15
Taptu predicts that "the Mobile Touch Web will grow... and will approach the quality .. of [Native] Apps across all the
app categories except for games."
From “Mobile App or Browser-Based Site? Report Says The Browser Will Win on Mobile”February 2010, ReadWriteWeb.com
15
![Page 16: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/16.jpg)
WEB OR NATIVE?MAKING AN INFORM DECISION
16
Factor Native Web
# of target devices
More Devices == More Projects, Inconsistencies between products
One codebase (with small tweaks) to rule them all
distribution Application Stores Processes/Charge Upfront :-) Instant
time to market Slow! Faster for simpler applications
developer skills Specialized UI developer skills: iOS, Android, etc. HTML/JavaScript/CSS + Frameworks
multimedia Audio/Video/ 2D and 3D graphics more accessible from native APIs
HTML 5 Video / Canvas coming along, WebGL future uncertain(1)
device integrationTouch Gestures / Accelerometer / Gyroscope / Camera / Geo-
location / File System / System Alerts more/only accessible from native APIs
Hacks abound to make some of these work
audiencegamers, selective downloaders (only download if app provides significant advantages of others) and the “only if I can have an
icon for it” crowd
anybody with a browser that it is inclined to use it!
16
![Page 17: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/17.jpg)
• If your application core relies on 3D, File System, Camera, Mobile Security, System Alerts, Marketplace, Performance go Native
• If your application success hinges on ease of deployment and distribution, deeply linked pages, social media and constant updates/changes then go Web
• Factors that are improving and/or are close to match their native counterparts include audio, video, 2D graphics, input and gestures, accelerometer and gyroscope, geolocation and native-like application launcher
WEB OR NATIVE?MAKING AN INFORM DECISION
17
17
![Page 18: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/18.jpg)
WEB OR NATIVE?MAKING AN INFORM DECISION
18
... and there is always the hybrid approach!
build it for the Web, convert it to Native
http://rhomobile.com/https://webmynd.com/http://phonegap.com/http://appcelerator.com/
18
![Page 19: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/19.jpg)
DEVELOPMENT APPROACHWHERE TO START?
19
![Page 20: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/20.jpg)
• Server-side developers gravitate to fleshing out the API first
• Client-side developers start with the look and feel
• After trying both I’ve decided that it is best to start at both ends and meet in the middle :-)
APPROACHWHERE TO START?
20
20
![Page 21: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/21.jpg)
SINATRATHE LIGHTWEIGHT HTTP RUBY DSL
21
![Page 22: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/22.jpg)
• Why?
• Rails might be too heavy for our purposes
• You will/might need to support native clients
• API-driven and JSON is the payload
SINATRAA LIGHTWEIGHT SERVER SIDE ALTERNATIVE
22
22
![Page 23: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/23.jpg)
• Multiple mini-apps in one process...
SINATRAA LIGHTWEIGHT SERVER SIDE ALTERNATIVE
23
map '/' do run Comida::ComidaWebAppend
map '/api' do run Comida::ComidaApiend
module Comida # # The Web App # class ComidaWebApp < Sinatra::Base ... end # # The API # class ComidaApi < Sinatra::Base ... endend
23
![Page 24: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/24.jpg)
• I wanted simple templates that I could render on the client and on the server
• No Ruby in my views, no markup in my Ruby!
MUSTACHELOGIC-LESS TEMPLATES
24
24
![Page 25: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/25.jpg)
• Classy with logic less templates...
SINATRA W/ MUSTACHEA LIGHTWEIGHT SERVER SIDE ALTERNATIVE
25
25
![Page 26: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/26.jpg)
• Render a mustache template (with a layout too).
26
class ComidaWebApp < Sinatra::Base register Mustache::Sinatra require './views/layout'
get '/' do mustache :search end
{{> search_page}}
{{> search_results_page}}
<script type="text/javascript" src="javascripts/search.js"></script>
template/search.mustache
<section data-role="page" id="search_results"> <header data-role="header"> <h1>Resturants</h1> <nav data-role="navbar"> <ul> <li><a href="#home" class="ui-btn-active">Search</a></li> <li><a href="#menu">Menus</a></li> <li><a href="#order">Order</a></li> </ul> </nav> </header> <div data-role="content" id="content_main"> <form action="/api/menus.json" method="get" data-ajax="false" id="restaurant_selection_form"> <div id="restaurants_found"></div> <button type="submit" data-theme="a">Submit</button> </form> </div></section><!-- /page -->
SINATRA W/ MUSTACHEA LIGHTWEIGHT SERVER SIDE ALTERNATIVE
template/search_result_page.mustache
26
![Page 27: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/27.jpg)
• Simple API with Sinatra...
SINATRAA LIGHTWEIGHT SERVER SIDE ALTERNATIVE
27
get '/search.json' do response = {} response[:restaurants] = restaurants content_type :json response.to_jsonend
• Let’s explore the sample’s app API with IRB and CURL
27
![Page 28: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/28.jpg)
JQUERY MOBILEA JQUERY-DRIVEN USER INTERFACE FRAMEWORK
28
![Page 29: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/29.jpg)
• A lightweight markup-driven User Interface (UI) framework for mobile web applications
• Build on JavaScript and making extensive use of the jQuery JavaScript Library (about 12K minified)
• Promotes the use of clean, semantic HTML that gets enhanced progressively and degrades gracefully if needed
• Supports a large variety of hardware and device features
• Supports Accessible Rich Internet Applications (WAI-ARIA)
• Theme-able following the ThemeRoller philosophy of jQuery UI
29
JQUERY MOBILEINTRODUCTION
29
![Page 30: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/30.jpg)
• To start on your path to web development for mobile devices you’ll need:
• Editor: An editor capable of dealing with HTML, CSS and JavaScript and potentially with your server-side language/platform/framework of choice
• Emulation/Simulation: A way to emulate the different devices and resolutions that your application/website wants to target
• Debugging: For more complex applications the ability to debug, trace and analyze JavaScript code
30
JQUERY MOBILESETTING YOUR DEVELOPMENT ENVIRONMENT
30
![Page 31: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/31.jpg)
SIMULATION, EMULATION & LIVE TESTING
WHAT TO DO WHEN
31
![Page 32: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/32.jpg)
• The Mobile Web Development cycle involves coding, previewing often on a regular desktop/laptop web browser and interspersed testing on a particular device emulator or on the target device itself* (particularly to test the feel of any gesture based interaction, device orientation changes and
other features that can only be experienced on the device itself)
• The simplest way to test is to run a local Web Server on your development machine and access the application over a WIFI network
32
JQUERY MOBILEEMULATION CHOICES
32
![Page 33: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/33.jpg)
• The Android SDK (http://developer.android.com) includes a device emulator that can support many Android Virtual Devices (AVDs).
33
JQUERY MOBILETHE ANDROID EMULATOR
33
![Page 34: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/34.jpg)
• The iOS Simulator (http://developer.apple.com/programs/ios/) is tucked away in Apple’s free iPhone Software Development Kit
34
JQUERY MOBILETHE ANDROID EMULATOR
The iOS simulator can be found under /Developer/Platforms/iPhoneSimulator.platform/Developer/Applications and it is aptly named “iOS Simulator”
34
![Page 35: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/35.jpg)
PAGESTHE BUILDING BLOCKS OF A MOBILE APPLICATION
35
![Page 36: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/36.jpg)
• Let’s open the example_1.html page in Safari (5.1.2 shown below) at 1024x768:
36
part_1/example_1.html
jQuery Mobile applications can also be
used on desktop, laptops and tablets
JQUERY MOBILEEMULATING A DEVICE
36
![Page 37: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/37.jpg)
• In Safari (5.1.2) at 640x960 (iPhone 4 resolution):
37
part_1/example_1.html
The iPhone, iPad and iPods use a mobile version of Safari so desktop Safari at iPhone/
iPad resolutions is a perfect browser for rapid development
JQUERY MOBILEEMULATING A DEVICE
37
![Page 38: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/38.jpg)
• On the Android Emulator :
38
part_1/example_1.html
JQUERY MOBILEEMULATING A DEVICE
38
![Page 39: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/39.jpg)
• On the iOS Emulator :
39
part_1/example_1.html
JQUERY MOBILEEMULATING A DEVICE
39
![Page 40: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/40.jpg)
• On the iPhone 4:
40
part_1/example_1.html
JQUERY MOBILEEMULATING A DEVICE
40
![Page 41: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/41.jpg)
• On the iPad
41
part_1/example_1.html
JQUERY MOBILEEMULATING A DEVICE
41
![Page 42: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/42.jpg)
• The basic document contains a single Page with a Title and a Body showing some simple content
• jQuery Mobile Documents can contain one or more mobile pages as well explore later in the course
42
part_1/example_1.html
JQUERY MOBILEEMULATING A DEVICE
42
![Page 43: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/43.jpg)
• The HTML document source is shown below:
43
JQUERY MOBILEGETTING STARTED
<!DOCTYPE html> <html> <head> <title>Browser Page Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" /> <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script> <script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script></head> <body>
<div data-role="page">
<div data-role="header"> <h1>Page Title</h1> </div><!-- /header -->
<div data-role="content"> <p>This is the content</p> </div><!-- /content -->
</div><!-- /page -->
</body></html>
part_1/example_1.html
43
![Page 44: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/44.jpg)
• The body of the document consists of several div elements
• The div are decorated with HTML5 data-role attributes
• The outer div has a role of page and contains two stacked inner divs with the roles header and content
44
JQUERY MOBILEGETTING STARTED
<body> <div data-role="page">
<div data-role="header"> <h1>Page Title</h1> </div><!-- /header -->
<div data-role="content"> <p>This is the content</p> </div><!-- /content -->
</div><!-- /page -->
</body></html>
part_1/example_1.html
44
![Page 45: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/45.jpg)
45
part_1/example_1.html
JQUERY MOBILEEMULATING A DEVICE
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css" />
• The link tag applies the jQuery Mobile CSS stylesheet to the document
• Commenting out the CSS reveals the simplicity of the underlying markup
45
![Page 46: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/46.jpg)
MULTI-PAGE DOCUMENTSINLINE PAGES
46
![Page 47: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/47.jpg)
47
MULTI-PAGE DOCSA DOCUMENT WITH A COUPLE OF PAGES
<div data-role="page" id="home">
<div data-role="header"> <h1>Home</h1> </div><!-- /header -->
<div data-role="content"> <p>This is the home page</p> </div><!-- /content --> <div data-role="footer" data-position="fixed"> <h4>The Footer</h4> </div><!-- /footer -->
</div><!-- /page -->
<div data-role="page" id="other">
<div data-role="header"> <h1>Other</h1> </div><!-- /header -->
<div data-role="content"> <p>This is another page</p> </div><!-- /content --> <div data-role="footer" data-position="fixed"> <h4>The Footer</h4> </div><!-- /footer -->
</div><!-- /page -->part_1/example_2.html
47
![Page 48: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/48.jpg)
48
MULTI-PAGE DOCSLOCATION HASH BASED NAVIGATION
http://.../part_1/example_2.html http://.../part_1/example_2.html#other
• HTML5 provides the window.location.hash which is exploited by jQuery Mobile to provide navigation to individual pages within a multi-page document
• Adding #other to the URL will navigate to the “other” page using the default transition (slide)
48
![Page 49: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/49.jpg)
49
MULTI-PAGE DOCSLINKING PAGES
<div data-role="page" id="home">
<div data-role="header"> <h1>Home</h1> </div><!-- /header -->
<div data-role="content"> <p>This is the home page</p> <p>Check out this <a href="#other">other</a> page</p> </div><!-- /content --> <div data-role="footer" data-position="fixed"> <h4>The Footer</h4> </div><!-- /footer -->
</div><!-- /page -->
• Let’s fill add navigation links to the other page from the home page and vice-versa:
part_1/example_2.html
<div data-role="page" id="other">
<div data-role="header"> <h1>Other</h1> </div><!-- /header -->
<div data-role="content"> <p>This is another page</p> <p>Take me <a href="#home">back!</a></p> </div><!-- /content --> <div data-role="footer" data-position="fixed"> <h4>The Footer</h4> </div><!-- /footer -->
</div><!-- /page -->
49
![Page 50: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/50.jpg)
50
MULTI-PAGE DOCSBACK LINKS
• A generic way to create a link to the previous page (without adding a new entry to the browser history) is to use the data-rel= “back” attribute as shown below:
part_1/example_2.html
<div data-role="page" id="other">
<div data-role="header"> <h1>Other</h1> </div><!-- /header -->
<div data-role="content"> <p>This is another page</p> <p>Take me <a href="#home" data-rel="back">back!</a></p> </div><!-- /content --> <div data-role="footer" data-position="fixed"> <h4>The Footer</h4> </div><!-- /footer -->
</div><!-- /page -->
50
![Page 51: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/51.jpg)
51
MULTI-PAGE DOCSA DOCUMENT WITH A COUPLE OF PAGES
• We can now navigate from #home to #other and back:
part_1/example_2.html
51
![Page 52: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/52.jpg)
52
PAGE TRANSITIONSANIMATION BASED NAVIGATION
<div data-role="content"> <p>This is the home page</p> <p>Check out this <a href="#other" data-transition="flip">other</a> page</p> </div><!-- /content -->
• So far we have seen the default ‘slide’ transition when navigating from page to page
• jQuery Mobile provides several transitions that we can apply via the data-transition attribute
• Let’s modify the link to the “other” page to use the “flip” transition animation
part_1/example_2.html
52
![Page 53: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/53.jpg)
53
PAGE TRANSITIONSANIMATION BASED NAVIGATION
• The ‘flip’ transition animation in action:
part_1/example_2.html
53
![Page 54: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/54.jpg)
54
BUTTONSSTYLIZED BUTTONS
<div data-role="page" id="other">
<div data-role="header"> <a href="#home" data-role="button" data-rel="back" data-icon="back" >Back</a> <h1>Other</h1> </div><!-- /header -->
part_1/example_2.html
• jQuery Mobile provides a “button” data-role attribute that can be applied to a link to turn it into a nicely styled button
• Let’s add a back button link to our “other” page
54
![Page 55: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/55.jpg)
55
BUTTONSSTYLIZED BUTTONS
• The newly added back button:
55
![Page 56: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/56.jpg)
56
LIST VIEWSSTYLING ORDERED OR UNORDERED LISTS
<div data-role="page" id="other"> ... <div data-role="content"> <h3>Unordered List</h3> <ul data-role="listview"> <li>Apples</li> <li>Oranges</li> <li>Peaches</li> </ul> <h3>Ordered List</h3> <ol data-role="listview"> <li>Woke up</li> <li>Fell out of bed</li> <li>Dragged a comb across my head</li> </ol> </div><!-- /content --> ...</div><!-- /page -->
part_1/example_2.html
• jQuery Mobile provides a “listview” data-role attribute that can turn an ordered or unordered list into a nicely styled native looking list
• Let’s modify the “other” page to show a couple of lists
56
![Page 57: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/57.jpg)
57
• The styled lists on the ‘other’ page:
LIST VIEWSSTYLING ORDERED OR UNORDERED LISTS
57
![Page 58: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/58.jpg)
• The beginnings of a mobile website for a restaurant
• On the home page we want to display the restaurant’s name and a logo alongside some welcome text and a button link to a “menu” page
• On the menu page we will display a list of menu items and a back button to the home page
58
DEMO 1.0LAUNCHING THE RESTAURANT MOBILE SITE
58
![Page 59: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/59.jpg)
APPLICATION INITIALIZATION
USING THE JQUERY PLUGIN PATTERN
59
![Page 60: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/60.jpg)
60
INITIALIZATIONUSING THE JQUERY PLUGIN PATTERN WITH JQUERY MOBILE
(function($) { var methods = { initPageOne : function(options) { }, initPageTwo : function(options) { }, initAllPages : function(options) { $().initApp("initPageOne"); $().initApp("initPageTwo"); } } $.fn.initApp = function(method) { // Method calling logic if ( methods[method] ) { return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if ( typeof method === 'object' || ! method ) { return methods.initAllPages.apply( this, arguments ); } else { $.error( 'Method ' + method + ' does not exist' ); } }})(jQuery);
60
![Page 61: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/61.jpg)
• Finally we can initialize the application by calling the initApp function from within a document ready handler function:
61
INITIALIZATIONUSING THE JQUERY PLUGIN PATTERN WITH JQUERY MOBILE
<script>$(document).ready(function() { $().initApp();})</script>
61
![Page 62: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/62.jpg)
MVC IN JAVASCRIPTINTRODUCING SPINE.JS
62
![Page 63: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/63.jpg)
SPINE.JSMVC FOR JAVASCRIPT
63
![Page 64: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/64.jpg)
• Spine.js is a small library provides a micro-MVC framework for your JavaScript applications
• It allow you to create a separation between the model (business JavaScript code) and the view (which renders the DOM)
• When models change their associated views are re-rendered without tightly coupling them to the DOM
• Spine.js keeps state/model in a single space, model changes propagate automatically to the views with very little glue code
64
SPINE.JSMVC FOR JAVASCRIPT
64
![Page 65: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/65.jpg)
JQUERY SHOPPING CART
65
![Page 66: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/66.jpg)
• Let’s walk through the code of a jQuery powered shopping cart from the ground up
• The markup consists of two lists styled to appear side-by-side and an element showing the total amount of the items in the shopping cart
• Each retail item will be represented by a div containing an image (drag handle), encode the item price in the div
• As items are dragged into the cart, use an effect to alert the user of the cart total amount changes
• The non-visual JS code uses the prototype pattern to separate the UI interactions from the business interactions
• As items are dropped into the cart, add controls to the items to increase the quantity
66
JQUERY SHOPPING CARTDRAG AND DROP SHOPPING CART
66
![Page 67: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/67.jpg)
• The jQuery powered Shopping Cart project structure is shown below:
67
JQUERY SHOPPING CARTDRAG AND DROP SHOPPING CART
67
![Page 68: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/68.jpg)
• jQuery Shopping Cart in action:
68
JQUERY SHOPPING CARTDRAG AND DROP SHOPPING CART
68
![Page 69: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/69.jpg)
• At first glance the implementation of the shopping cart seems to work as advertised and even seems well thought- out. That is, until we start asking the hard questions.
• Shortcoming of the jQuery Shopping Cart:
• From the usability point of view, the first thing that jumps to mind is, what happens when the user clicks the refresh button?
• Since everything is just being kept in memory the answer is that it simply goes away
69
JQUERY SHOPPING CARTDRAG AND DROP SHOPPING CART
69
![Page 70: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/70.jpg)
• Shortcoming of the jQuery Shopping Cart (cont.):
• For anything more complex we would end up with an unmanageable mess of UI callbacks all of which are currently living in the global JavaScript scope.
• Another problem glaring problem is the coupling of the concepts of the shopping cart and the items in the shopping cart.
• The items are simple JavaScript objects with no behavior, their reflection on the UI is controlled by the decorateForCart function
70
JQUERY SHOPPING CARTDRAG AND DROP SHOPPING CART
70
![Page 71: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/71.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• Spine.js is partly based on Backbone’s API yet Spine’s take on the MVC pattern is slightly different
• I used Spine.js to refactor the jQuery Shopping Cart
• Problems I wanted to fix on the shopping cart solution:
• Using the back button or the refresh button loses the carts contents
• UI callbacks and manual event handling and triggering can quickly get out of hand
71
71
![Page 72: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/72.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• Models: In Spine, models are created using the setup method of Spine.Model, which takes the name of the model and an array of properties
72
// Create the Item model.var Item = Spine.Model.sub();Item.configure("Item", "name", "pid", "price", "quantity");
part_2/examples/jquery-spine-shopping-cart/app/models/item.js
72
![Page 73: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/73.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• To make the model persists between page reloads we extend the Item with the Spine.Model.Local module
73
// Persist model between page reloads.Item.extend(Spine.Model.Local);
part_2/examples/jquery-spine-shopping-cart/app/models/item.js
• The extend method adds class properties to the model. We now have an object that can be created, saved and retrieved from the browser local storage.
73
![Page 74: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/74.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• To add behavior to our model we use the include method which adds instance properties
• The four methods that we need for our Item model; increase, decrease, total and label
74
// Instance methodsItem.include({ // total: function() { return (this.price * this.quantity); }, // increase: function(quantity) { quantity = (typeof(quantity) != 'undefined') ? quantity : 1; this.quantity = this.quantity + quantity; this.save(); }, // decrease: function(quantity) { quantity = (typeof(quantity) != 'undefined') ? quantity : 1; if (this.quantity >= quantity) { this.quantity = this.quantity - quantity; } else { this.quantity = 0; } this.save(); }, // label: function() { return (this.name + " - $" + this.price); } });
part_2/examples/jquery-spine-shopping-cart/app/models/item.js
74
![Page 75: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/75.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• To instantiate an Item we use the create method which takes an object literal for the parameters. A new model can be persisted using the save method. When a model is saved it is assigned an identifier that can be retrieved via the id property.
75
var item = new Item({name: "Product 1", pid: "0001" , price: 100.0, quantity: 1});item.save();alert("Just saved Item with id => " + item.id);
75
![Page 76: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/76.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• Controllers: Controllers in Spine are a combination of a traditional MVC controller and a view. Therefore controllers are in charge of rendering and manipulating one or more models in the context of controller’s functionality
• Our first Spine controller will deal with the rendering and manipulation of an individual Item. The CartItem controller will deal with user interface events to increase and decrease the quantity of a Item while keeping the user abreast of the changes.
76
76
![Page 77: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/77.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• Spine controllers like the CartItem are created using the create method of Spine.Controller, which takes an object literal that a wide variety of properties
77
jQuery(function($){ window.CartItem = Spine.Controller.sub({ init: function(){ var cartItem = this; this.item.bind("quantityChanged", function() { cartItem.updateQty() }); $('#item_' + this.item.pid + ' .add').live('click', function(e) { cartItem.add(); e.preventDefault(); }); $('#item_' + this.item.pid + ' .remove').live('click', function(e) { cartItem.remove(); e.preventDefault(); }); },
part_2/examples/jquery-spine-shopping-cart/app/controllers/cart_item.js
77
![Page 78: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/78.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• ... cont.
78
render: function(){ this.el = $.mustache($("#cartItem").html(), this.item); return this; }, // event handlers add: function(e) { this.item.increase(); }, remove: function(e) { this.item.decrease(); }, // ui methods updateQty: function() { $('#item_' + this.item.pid + ' #qty') .text(this.item.quantity) .effect("highlight", {}, 1500); } });})
part_2/examples/jquery-spine-shopping-cart/app/controllers/cart_item.js
78
![Page 79: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/79.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• The cartItem template is a Mustache.js Template that enables the creation of markup templates containing binding expressions. The mustache method clones the template contents and replaces the binding expressions ({{exp}}) with the values of the object passed, in our case the controller’s enclosed Item model.
79
<!-- Mustache :-{)~ Template for CartItem --><script type="text/x-mustache-tmpl" id="cartItem"> <li class="product ui-state-default" id="item_{{pid}}" price="{{price}}"> {{label}} (<span id="qty">{{quantity}}</span>) <a href="#" class="add">+</a> <a href="#" class="remove">-</a> </li></script>
part_2/examples/jquery-spine-shopping-cart/shopping_cart.html
79
![Page 80: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/80.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• To test our controller we need to instantiate an Item model and use it to instantiate the controller. We can then render the controller on the DOM of an HTML page
80
var item = new Item({name: "Product 1", pid: "0001" , price: 100.0, quantity: 1});var view = new CartItem({item: item});$("#item").html(view.render().el);
part_2/examples/jquery-spine-shopping-cart/tests/cart_item_test.html
80
![Page 81: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/81.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• The ShoppingCart controller which will manage a collection of Item models. Internally the ShoppingCart keeps the items dropped in the items property
• The clear, total, isEmpty and itemsCount methods fulfill the business functionality of the cart
81
jQuery(function($){ window.ShoppingCart = Spine.Controller.sub({ el: $("#theCart"), init: function() { var cart = this; this.items = {}; $.each(Item.all(), function(){ cart.addItem(this); }); this.el.droppable({ accept: '.product', drop: this.proxy(this.drop) }); $('#dump', this.el).live('click', function() { cart.clear(); }); }, // removes all items from the cart clear: function() { $.each(this.items, function(){ this.destroy(); }); this.items = {}; this.updateCartTotal(); }, total: function() { var sum = 0.0; $.each(this.items, function(){ sum += this.total(); });
return sum; }, isEmpty: function() { return this.itemsCount() == 0; }, itemsCount: function() { var size = 0; var items = this.items; $.each(items, function(){ if (items.hasOwnProperty(this)) size++; });
return size; }, ...
part_2/examples/jquery-spine-shopping-cart/app/controllers/shopping_cart.js
81
![Page 82: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/82.jpg)
SPINE.JSMVC FOR JAVASCRIPT
82
...drop: function(ev, ui) { var item_dropped = ui.draggable; var pid = item_dropped.attr('id'); var price = item_dropped.attr('price'); var name = item_dropped.attr('name');
if (this.items.hasOwnProperty(pid)) { this.items[pid].increase(); } else { var item = Item.create({name: name, pid: pid, price: price, quantity: 1}); this.addItem(item); $(".items").append(CartItem.init({item: item}).render().el); }},
part_2/examples/jquery-spine-shopping-cart/app/controllers/shopping_cart.js
• The drop method handles drop events; it either creates a new item or increases the quantity of an existing item. It creates an Item model that is then rendered using the CartItem controller
82
![Page 83: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/83.jpg)
SPINE.JSMVC FOR JAVASCRIPT
83
...render: function() { this.el.html($.mustache($("#shoppingCart").html(), {})); $('#dump').button();
$.each(this.items, function(){ $(".items").append(CartItem.init({item: this}).render().el); }); this.updateCartTotal();},
part_2/examples/jquery-spine-shopping-cart/app/controllers/shopping_cart.js
• The render method render the #shoppingCart template, decorates the #dump button and loops through the contained Items creating a CartItem for each and rendering them in the .items
83
![Page 84: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/84.jpg)
SPINE.JSMVC FOR JAVASCRIPT
• The removeItem, updateCartTotal, removeIfQuantityZero and addItem deal with responding to UI events and updating the UI
84
...removeItem: function(item) { $('#item_' + item.pid).effect("puff", {}, "slow", function(){ $(this).remove(); });},
updateCartTotal: function() { $('#total').text(this.total()).effect("highlight", {}, 1500);},
removeIfQuantityZero: function(item) { if (item.quantity == 0) { this.removeItem(item); delete this.items[item.pid]; item.destroy(); }},
addItem: function(item) { this.items[item.pid] = item; item.bind("quantityChanged", this.proxy(this.updateCartTotal)); item.bind("quantityChanged", this.proxy(this.removeIfQuantityZero));item.bind("quantityChanged", function() { item.save() }); item.bind("destroy", this.proxy(this.removeItem)); item.save(); this.updateCartTotal();}
part_2/examples/jquery-spine-shopping-cart/app/controllers/shopping_cart.js
84
![Page 85: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/85.jpg)
SPINE.JSMVC FOR JAVASCRIPT
85
part_4/examples/jquery-spine-shopping-cart/app/application.js
• Finally to kick everything in motion the file application.js file begins by fetching any previously stored Item records, making the sample products draggable, creating a cart and rendering it.
jQuery(function($){ Item.fetch(); $(".product").draggable({ helper: 'clone', opacity: "0.5" }); var cart = new ShoppingCart(); cart.render();});
85
![Page 86: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/86.jpg)
RESOURCES
86
![Page 87: Road to mobile w/ Sinatra, jQuery Mobile, Spine.js and Mustache](https://reader033.vdocument.in/reader033/viewer/2022061113/545b42f3b1af9fcf338b60b0/html5/thumbnails/87.jpg)
RESOURCES• Sinatra: http://www.sinatrarb.com/
• jQuery Mobile: http://jquerymobile.com
• Spine.js: http://spinejs.com
• Example Code:
• https://github.com/bsbodden/jquery-shopping-cart
• https://github.com/bsbodden/jquery-spine-shopping-cart
• https://github.com/integrallis/jqm-spine-sinatra-demo
87
87