Skip to content

Instantly share code, notes, and snippets.

@Rich-Harris
Last active August 29, 2015 14:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rich-Harris/b8df60d7eacebde205c0 to your computer and use it in GitHub Desktop.
Save Rich-Harris/b8df60d7eacebde205c0 to your computer and use it in GitHub Desktop.
Backbone adaptor

Ractive isn't an MVC framework, because MVC isn't the only way to build apps. Rather than dressing up your data with dedicated Model classes, you can use plain old JavaScript objects - POJOs.

That's handy, but sometimes it's not enough - maybe you want to use Backbone (for example) Models and Collections in your app, but you still want to use Ractive to render your interface.

In these situations, we use adaptors. Adaptors are small plugins that allow Ractive to communicate seamlessly with third-party model libraries. In the example above, we're using the Backbone adaptor. We have a variety of model types (Film, Actor and Director) and a collection type (Films).

As Ractive builds up the view, any time it encounters an instance of a Backbone Model, it does two things. Firstly, it wraps the object so that you can do film.title in your template (rather than film.get('title') or film.attributes.title). Secondly, it adds a handler to the model's change event, so that changes in the model are reflected in the view. This binding works in both directions - changes in the view will also be reflected in the model, where appropriate.

Later, if the model is no longer in use, the event handler will be removed automatically.

This means we have the best of both worlds - we have Ractive's simplicity, but with the power of Backbone's helper methods. For example when you roll over the actor or director name in the top left, you see a list of credits constructed using the collection's pluck method:

<div class='credits-list'>;Credits: {{ credits.pluck( 'title' ).join( ', ' ) }}</div>

This is possible because each Actor and Director instance has a credits property, which is an instance of the Films collection type.

Notice also that within the highlight event handler, we're using the set event on the Backbone object rather than on Ractive, which is a more object-oriented approach if that's your bag.

You'll find more information about adaptors, including how to create your own, on the docs.

<div class='info'>
{{#selectedFilm}}
<!-- roll over the actor/director name to reveal credits -->
<div class='credits'>
{{#actor}}
<div class='actor' on-hover='highlight:{{this}}'>
<span>{{name}}</span>
{{#highlighted}}
<div class='credits-list'>Credits: {{ credits.pluck( 'title' ).join( ', ' ) }}</div>
{{/highlighted}}
</div>
{{/actor}}
{{#director}}
<div class='director' on-hover='highlight:{{this}}'>
<span>{{name}}</span>
{{#highlighted}}
<div class='credits-list'>Credits: {{ credits.pluck( 'title' ).join( ', ' ) }}</div>
{{/highlighted}}
</div>
{{/director}}
</div>
<!-- info about the selected film -->
<h3>{{title}} <small>({{year}})</small></h3>
<h4>{{tagline}}</h4>
<img src='assets/bond/images/{{poster}}'>
<p>{{synopsis}}</p>
<!-- thanks, themoviedb.org! -->
<p class='source'>Source: <a href='http://www.themoviedb.org/movie/{{source}}'>themoviedb.org</a></p>
{{/selectedFilm}}
</div>
<ul class='thumbnails'>
{{#films}}
<li
on-tap='select:{{this}}'
class='thumbnail {{ this === selectedFilm || actor.highlighted || director.highlighted ? "highlighted" : "" }}'
>
<img src='assets/bond/images/{{poster}}'>
</li>
{{/films}}
</ul>
[
{
"id": "dr-no",
"source": "646-dr-no",
"title": "Dr. No",
"poster": "dr-no.jpg",
"year": 1962,
"director": "Terence Young",
"actor": "Sean Connery",
"tagline": "NOW meet the most extraordinary gentleman spy in all fiction!",
"synopsis": "When Strangways, the British SIS Station Chief in Jamaica goes missing, MI6 send James Bond - Agent 007 to investigate. His investigation leads him to the mysterious Crab Key; the secret base of Dr No who he suspects is trying to sabotage the American space program using a radio beam. With the assistance of local fisherman Quarrel, who had been helping Strangways, Bond sneaks onto Crab Key where he meets the beautiful Honey Ryder. Can the three of them defeat an army of henchmen and a \"fire breathing dragon\" in order to stop Dr No, save the space program and get revenge for Strangways? Dr. No is the first film of legendary James Bond series starring Sean Connery in the role of Fleming's British super agent."
},
{
"id": "from-russia-with-love",
"source": "657-from-russia-with-love",
"title": "From Russia With Love",
"poster": "from-russia-with-love.jpg",
"year": 1963,
"director": "Terence Young",
"actor": "Sean Connery",
"tagline": "The world's masters of murder pull out all the stops to destroy Agent 007!",
"synopsis": "Bond is back and on the loose in exotic Istanbul looking for a super-secret coding machine. He's involved with a beautiful Russian spy and has the SPECTRE organization after him, including villainess Rosa Klebb (she of the killer shoe). Lots of exciting escapes but not an overreliance on the gadgetry of the later films. The second Bond feature, thought by many to be the best."
},
{
"id": "goldfinger",
"source": "658-goldfinger",
"title": "Goldfinger",
"poster": "goldfinger.jpg",
"year": 1964,
"director": "Guy Hamilton",
"actor": "Sean Connery",
"tagline": "Everything he touches turns into excitement!",
"synopsis": "Bond is in Miami on holiday when M tells him to observe Auric Goldfinger. Bond steals Goldfinger's girlfriend, Jill Masterson, but after being knocked out, he awakes to find her dead and covered in gold paint. Upon returning to London, Bond is told to further investigate Goldfinger who is believed to be smuggling gold out of Britain, but warned he will be replaced if he turns the mission into a personal vendetta. After failing to befriend Goldfinger, Bond is caught spying and taken to America as a captive. Bond learns of Goldfinger's plan, codenamed Operation Grand Slam, which involves attacking Fort Knox to increase his gold riches. Can 007 find a way to stop Goldfinger despite being held prisoner? This is the third film from the legendary James Bond series starring Sean Connery as the British super agent."
},
{
"id": "thunderball",
"source": "660-thunderball",
"title": "Thunderball",
"poster": "thunderball.jpg",
"year": 1965,
"director": "Terence Young",
"actor": "Sean Connery",
"tagline": "Look up! Look down! Look out!",
"synopsis": "A criminal organization has obtained two nuclear bombs and are asking for a 100 million pound ransom in the form of diamonds in seven days or they will use the weapons. The secret service sends James Bond to the Bahamas to once again save the world."
},
{
"id": "casino-royale-a",
"source": "12208-casino-royale",
"title": "Casino Royale",
"poster": "casino-royale-a.jpg",
"year": 1967,
"director": "Val Guest",
"actor": "David Niven",
"synopsis": "Sir James Bond is called back out of retirement to stop SMERSH. In order to trick SMERSH, Bond thinks up the ultimate plan. That every agent will be named James Bond. One of the Bonds, whose real name is Evelyn Tremble is sent to take on Le Chiffre in a game of baccarat, but all the Bonds get more than they can handle, especially when the ultimate villain turns out to be Bonds nephew."
},
{
"id": "you-only-live-twice",
"source": "667-you-only-live-twice",
"title": "You Only Live Twice",
"poster": "you-only-live-twice.jpg",
"year": 1967,
"director": "Lewis Gilbert",
"actor": "Sean Connery",
"tagline": "You Only Live Twice...and \"TWICE\" is the only way to live!",
"synopsis": "A mysterious space craft kidnaps a Russian and American space capsule and brings the world on the verge of another World War. James Bond investigates the case in Japan and meets with his archenemy Blofeld. The fifth film from the legendary James Bond series starring Sean Connery as the British super agent."
},
{
"id": "on-her-majestys-secret-service",
"source": "668-on-her-majesty-s-secret-service",
"title": "On Her Majesty's Secret Service",
"poster": "on-her-majestys-secret-service.jpg",
"year": 1969,
"director": "Peter R. Hunt",
"actor": "George Lazenby",
"tagline": "Far up! Far out! Far more! James Bond 007 is back!",
"synopsis": "Bond tracks archnemesis Ernst Blofeld to a mountaintop retreat where he's training an army of beautiful but lethal women. Along the way, Bond falls for Italian contessa Tracy Draco -- and marries her in order to get closer to Blofeld. Meanwhile, he locates Blofeld in the Alps and embarks on a classic ski chase."
},
{
"id": "diamonds-are-forever",
"source": "681-diamonds-are-forever",
"title": "Diamonds Are Forever",
"poster": "diamonds-are-forever.jpg",
"year": 1971,
"director": "Guy Hamilton",
"actor": "Sean Connery",
"tagline": "Bond is back...with the girls",
"synopsis": "Diamonds are stolen only to be sold again in the international market. James Bond infiltrates a smuggling mission to find out who’s guilty. The mission takes him to Las Vegas where Bond meets his archenemy Blofeld. The seventh film from the Legendary James Bond series starring Sean Connery as a British super agent."
},
{
"id": "live-and-let-die",
"source": "253-live-and-let-die",
"title": "Live and Let Die",
"poster": "live-and-let-die.jpg",
"year": 1973,
"director": "Guy Hamilton",
"actor": "Roger Moore",
"tagline": "Roger M007re is James Bond.",
"synopsis": "James Bond must investigate a mysterious murder case of a British agent in New York. Soon he finds himself up against a big gangster boss named Mr. Big. This the eight film of the James Bond series and the first one to star Roger Moore as the British undercover agent 007."
},
{
"id": "the-man-with-the-golden-gun",
"source": "682-the-man-with-the-golden-gun",
"title": "The Man with the Golden Gun",
"poster": "the-man-with-the-golden-gun.jpg",
"year": 1974,
"director": "Guy Hamilton",
"actor": "Roger Moore",
"tagline": "The man with the golden gun is ready to assassinate James Bond.",
"synopsis": "A golden bullet has 007 engraved on it as it smashes into the secret service headquarters. The bullet came from the professional killer Scaramanga who has yet to miss a target and James Bond begins a mission to try and stop him. The ninth film from the Legendary James Bond series starring Roger Moore as a British super agent."
},
{
"id": "the-spy-who-loved-me",
"source": "691-the-spy-who-loved-me",
"title": "The Spy Who Loved Me",
"poster": "the-spy-who-loved-me.jpg",
"year": 1977,
"director": "Lewis Gilbert",
"actor": "Roger Moore",
"tagline": "It's the BIGGEST. It's the BEST. It's BOND. And B-E-Y-O-N-D.",
"synopsis": "Russian and American submarines with nuclear missels on board both vanish from sight without a trace. America and Russia both blame each other as James Bond tries to solve the riddle of the disappearing ships. But the KGB also has an agent on the case. The tenth film from the Legendary James Bond series starring Roger Moore as a British super agent."
},
{
"id": "moonraker",
"source": "698-moonraker",
"title": "Moonraker",
"poster": "moonraker.jpg",
"year": 1979,
"director": "Lewis Gilbert",
"actor": "Roger Moore",
"tagline": "Outer space now belongs to 007.",
"synopsis": "During the transportation of a Space Shuttle a Boeing 747 crashes in the Atlantic Ocean yet when they go to look for the destroyed shuttle it is not there. James bond investigates the missing mission space shuttle and soon learns that the shuttles owner Hugo Drax wants to kill all of mankind. The showdown is about to take place in outer space. The eleventh film from the Legendary James Bond series"
},
{
"id": "for-your-eyes-only",
"source": "699-for-your-eyes-only",
"title": "For Your Eyes Only",
"poster": "for-your-eyes-only.jpg",
"year": 1981,
"director": "John Glen",
"actor": "Roger Moore",
"tagline": "No one comes close to James Bond, 007.",
"synopsis": "A British spy ship has sunk and on board was a hi-tech encryption device. James Bond is sent to find the device that holds British launching instructions before the enemy Soviets get to it first. The twelfth film from the Legendary James Bond series starring Roger Moore as a British super agent."
},
{
"id": "never-say-never-again",
"source": "36670-never-say-never-again",
"title": "Never Say Never Again",
"poster": "never-say-never-again.jpg",
"year": 1983,
"director": "Irvin Kershner",
"actor": "Sean Connery",
"tagline": "Sean Connery is James Bond 007",
"synopsis": "James Bond returns as the secret agent 007 one more time to battle the evil organization SPECTRE. Bond must defeat Largo, who has stolen two atomic warheads for nuclear blackmail. But Bond has an ally in Largo's girlfriend, the willowy Domino, who falls for Bond and seeks revenge. This is the last time for Sean Connery as Her Majesty's Secret Agent 007."
},
{
"id": "octopussy",
"source": "700-octopussy",
"title": "Octopussy",
"poster": "octopussy.jpg",
"year": 1983,
"director": "John Glen",
"actor": "Roger Moore",
"tagline": "Nobody does him better.",
"synopsis": "James Bond is sent to investigate after a fellow “00” agent is found dead with a priceless Farberge egg. James bond follows the mystery and uncovers a smuggling scandal and a Russian General who wants to provoke a new World War. The 13th film from the Legendary James Bond series starring Roger Moore as a British super agent."
},
{
"id": "a-view-to-a-kill",
"source": "707-a-view-to-a-kill",
"title": "A View to a Kill",
"poster": "a-view-to-a-kill.jpg",
"year": 1985,
"director": "John Glen",
"actor": "Roger Moore",
"tagline": "Has James Bond finally met his match?",
"synopsis": "A newly developed microchip designed by Zorin Industries for the British Government that can survive the electromagnetic radiation caused by a nuclear explosion has landed in the hands of the KGB. James Bond must find out how and why. His suspicions soon lead him to big industry leader Max Zorin. The 14th film from the Legendary James Bond series starring Roger Moore as a British super agent."
},
{
"id": "the-living-daylights",
"source": "708-the-living-daylights",
"title": "The Living Daylights",
"poster": "the-living-daylights.jpg",
"year": 1987,
"director": "John Glen",
"actor": "Timothy Dalton",
"tagline": "Licensed to thrill.",
"synopsis": "James Bond helps a Russian General escape into the west. He soon finds out that the KGB wants to kill him for helping the General. A little while later the General is kidnapped from the Secret Service leading 007 to be suspicious. The 15th film from the Legendary James Bond series starring Timothy Dalton as a British super agent."
},
{
"id": "licence-to-kill",
"source": "709-licence-to-kill",
"title": "Licence to Kill",
"poster": "licence-to-kill.jpg",
"year": 1989,
"director": "John Glen",
"actor": "Timothy Dalton",
"tagline": "His bad side is a dangerous place to be.",
"synopsis": "James Bond and his American colleague Felix Leiter arrest the drug lord Sanchez who succeeds in escaping and takes revenge on Felix and his wife. Bond knows but just one thing: revenge. The 16th film from the Legendary James Bond series starring Timothy Dalton as a British super agent."
},
{
"id": "goldeneye",
"source": "710-goldeneye",
"title": "Goldeneye",
"poster": "goldeneye.jpg",
"year": 1995,
"director": "Martin Campbell",
"actor": "Pierce Brosnan",
"tagline": "When the world is the target and the threat is real, you can still depend on one man.",
"synopsis": "James Bond must unmask the mysterious head of the Janus Syndicate and prevent his one time ally - Alec Trevelyan Agent 006 - from utilising the GoldenEye weapons system to inflict devastating revenge on Britain. --- The 17th film from the legendary James Bond series and the first starring Pierce Brosnan."
},
{
"id": "tomorrow-never-dies",
"source": "714-tomorrow-never-dies",
"title": "Tomorrow Never Dies",
"poster": "tomorrow-never-dies.jpg",
"year": 1997,
"director": "Roger Spottiswoode",
"actor": "Pierce Brosnan",
"tagline": "The Man. The Number. The License...are all back.",
"synopsis": "A deranged media mogul is staging international incidents to pit the world's superpowers against each other. Now 007 must take on this evil mastermind in an adrenaline-charged battle to end his reign of terror and prevent global pandemonium. --- The 18th film from the legendary James Bond series, starring Pierce Brosnan."
},
{
"id": "the-world-is-not-enough",
"source": "36643-the-world-is-not-enough",
"title": "The World Is Not Enough",
"poster": "the-world-is-not-enough.jpg",
"year": 1999,
"director": "Michael Apted",
"actor": "Pierce Brosnan",
"tagline": "As the countdown begins for the new millennium there is still one number you can always count on.",
"synopsis": "Greed, revenge, world dominance, high-tech terrorism -- it's all in a day's work for cunning MI6 agent James Bond, who's on a mission to protect beautiful oil heiress Elektra King from a notorious terrorist. In a race against time that culminates in a dramatic submarine showdown, Bond works to defuse the international power struggle that has the world's oil supply hanging in the balance."
},
{
"id": "die-another-day",
"source": "36669-die-another-day",
"title": "Die Another Day",
"poster": "die-another-day.jpg",
"year": 2002,
"director": "Lee Tamahori",
"actor": "Pierce Brosnan",
"tagline": "Events don't get any bigger than...",
"synopsis": "The ever-daring James Bond taking on a North Korean leader who undergoes DNA replacement procedures that allow him to assume different identities. American agent Jinx Johnson assists Bond in thwarting the villain's plans to exploit a satellite that is powered by solar energy."
},
{
"id": "casino-royale-b",
"source": "36557-casino-royale",
"title": "Casino Royale",
"poster": "casino-royale-b.jpg",
"year": 2006,
"director": "Martin Campbell",
"actor": "Daniel Craig",
"tagline": "Everyone has a past. Every legend has a beginning.",
"synopsis": "In his first mission, James Bond must stop Le Chiffre, a banker to the world's terrorist organizations, from winning a high-stakes poker tournament at Casino Royale in Montenegro."
},
{
"id": "quantum-of-solace",
"source": "10764-quantum-of-solace",
"title": "Quantum of Solace",
"poster": "quantum-of-solace.jpg",
"year": 2008,
"director": "Marc Forster",
"actor": "Daniel Craig",
"tagline": "For love, for hate, for justice, for revenge.",
"synopsis": "Quantum of Solace continues the high octane adventures of James Bond in Casino Royale. Betrayed by Vesper, the woman he loved, 007 fights the urge to make his latest mission personal. Pursuing his determination to uncover the truth, Bond and M interrogate Mr White who reveals the organization which blackmailed Vesper is far more complex and dangerous than anyone had imagined."
},
{
"id": "skyfall",
"source": "37724-skyfall",
"title": "Skyfall",
"poster": "skyfall.jpg",
"year": 2012,
"director": "Sam Mendes",
"actor": "Daniel Craig",
"tagline": "Think on your sins.",
"synopsis": "Bond's loyalty to M is tested as her past comes back to haunt her. As MI6 comes under attack, 007 must track down and destroy the threat, no matter how personal the cost."
}
]
var ractive, Film, Actor, Director, Films, getCollectionFromData, xhr;
// First, we render our view
ractive = new BaseView({
el: demo,
// This is how we tell Ractive to keep an eye out for Backbone objects
adapt: [ 'Backbone' ]
});
ractive.on({
select: function ( event, film ) {
// `film` is a Backbone model
this.set( 'selectedFilm', film );
},
highlight: function ( event, talent ) {
// `talent` is a Backbone model (either an Actor or Director)
talent.set( 'highlighted', event.hover ); // true on mouseover, false on mouseout
}
});
// Next, we create some Backbone.Model subclasses. In this case they're very
// simple, and we could just use the unextended Backbone.Model, but it's
// important to note that the adaptor works equally well in either case
Film = Backbone.Model.extend();
Actor = Backbone.Model.extend({
initialize: function () {
this.set( 'credits', new Films() );
}
});
Director = Backbone.Model.extend({
initialize: function () {
this.set( 'credits', new Films() );
}
});
// Create a Backbone.Collection subclass. We'll use this several times.
Films = Backbone.Collection.extend({
model: Film,
comparator: function ( film ) {
return film.get( 'year' ); // sort chronologically
}
});
// We have some JSON data that we're about to load - here's how we turn it
// into a Backbone collection
getCollectionFromData = function ( data ) {
var films, actors, directors, mapped;
actors = {};
directors = {};
mapped = data.map( function ( record ) {
var film, actor, director;
if ( !actors[ record.actor ] ) {
actors[ record.actor ] = new Actor({ name: record.actor });
}
if ( !directors[ record.director ] ) {
directors[ record.director ] = new Director({ name: record.director });
}
// Overwrite the plain-text actor and director properties of the data
// with Backbone models representing them
record.actor = actors[ record.actor ];
record.director = directors[ record.director ];
film = new Film( record );
// Add this film to the actor's and director's credits
record.actor.get( 'credits' ).add( film );
record.director.get( 'credits' ).add( film );
return film;
});
return new Films( mapped );
};
// Load the data from a JSON file, then process it
xhr = new XMLHttpRequest();
xhr.open( 'get', 'https://gist.githubusercontent.com/Rich-Harris/b8df60d7eacebde205c0/raw/9e9dc817dba8d1abc2b9e3fcefcc73ac715c7c5d/data.json' );
xhr.onload = function () {
var data = JSON.parse( xhr.responseText ), films = getCollectionFromData( data );
ractive.set({
films: films,
selectedFilm: films.get( 'dr-no' )
});
};
xhr.send();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment