Showing preview only (298K chars total). Download the full file or copy to clipboard to get everything.
Repository: jpotts18/mean-stack-relational
Branch: master
Commit: 14458849606d
Files: 75
Total size: 277.6 KB
Directory structure:
gitextract__zeyph8s/
├── .gitignore
├── .jshintrc
├── .travis.yml
├── LICENSE
├── Procfile
├── README.md
├── app/
│ ├── controllers/
│ │ ├── articles.js
│ │ ├── index.js
│ │ └── users.js
│ ├── models/
│ │ ├── article.js
│ │ └── user.js
│ ├── routes/
│ │ ├── articles.js
│ │ ├── index.js
│ │ └── users.js
│ └── views/
│ ├── 404.jade
│ ├── 500.jade
│ ├── includes/
│ │ ├── foot.jade
│ │ └── head.jade
│ ├── index.jade
│ └── layouts/
│ └── default.jade
├── app.js
├── app.json
├── bower.json
├── config/
│ ├── config.js
│ ├── env/
│ │ ├── all.json5
│ │ ├── development.json5.sample
│ │ ├── production.json5.sample
│ │ ├── test.json5.sample
│ │ └── travis.json
│ ├── express.js
│ ├── middlewares/
│ │ └── session.js
│ ├── passport.js
│ ├── sequelize.js
│ └── winston.js
├── gruntfile.js
├── package.json
├── pm2-ecosystem.json
├── pm2-main.js
├── public/
│ ├── css/
│ │ ├── common.css
│ │ └── views/
│ │ └── articles.css
│ ├── humans.txt
│ ├── img/
│ │ └── .gitignore
│ ├── js/
│ │ ├── FbSdk.js
│ │ ├── app.js
│ │ ├── config.js
│ │ ├── controllers/
│ │ │ ├── articles.js
│ │ │ ├── header.js
│ │ │ ├── index.js
│ │ │ └── users/
│ │ │ ├── auth.js
│ │ │ ├── signIn.js
│ │ │ └── signUp.js
│ │ ├── directives.js
│ │ ├── filters.js
│ │ ├── init.js
│ │ └── services/
│ │ ├── articles.js
│ │ ├── authenticate.js
│ │ └── global.js
│ ├── robots.txt
│ └── views/
│ ├── 404.html
│ ├── articles/
│ │ ├── create.html
│ │ ├── edit.html
│ │ ├── list.html
│ │ └── view.html
│ ├── header.html
│ ├── index.html
│ └── users/
│ ├── auth.html
│ ├── signin.html
│ └── signup.html
└── test/
├── karma/
│ ├── karma.conf.js
│ └── unit/
│ └── controllers/
│ ├── articles.spec.js
│ ├── headers.spec.js
│ └── index.spec.js
└── mocha/
├── controllers/
│ ├── articleControllerSpec.js
│ └── usersControllerSpec.js
└── models/
└── userModelSpec.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Github Node Default
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
pids
logs
results
npm-debug.log
node_modules
# From Mean Stack
bower_components/
.DS_Store
.nodemonignore
.sass-cache/
node_modules/
public/lib
test/coverage/
migrations/
# Configuration Files
/config/env/development.json5
/config/env/production.json5
/config/env/test.json5
*.local
# IDE files
.idea
/.*.md.html
.settings
.project
.classpath
*~
*.swp
*.swo
================================================
FILE: .jshintrc
================================================
{
// JSHint Default Configuration File (as on JSHint website)
// See http://jshint.com/docs/ for more details
"maxerr" : 50, // {int} Maximum error before stopping
// Enforcing
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
"camelcase" : false, // true: Identifiers must be in camelCase
"curly" : true, // true: Require {} for every new block or scope
"eqeqeq" : true, // true: Require triple equals (===) for comparison
"forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
"freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
"indent" : 4, // {int} Number of spaces to use for indentation
"latedef" : false, // true: Require variables/functions to be defined before being used
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
"noempty" : true, // true: Prohibit use of empty blocks
"nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters.
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
"plusplus" : false, // true: Prohibit use of `++` and `--`
"quotmark" : false, // Quotation mark consistency:
// false : do nothing (default)
// true : ensure whatever is used is consistent
// "single" : require single quotes
// "double" : require double quotes
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
"unused" : false, // Unused variables:
// true : all variables, last function parameter
// "vars" : all variables only
// "strict" : all variables, all function parameters
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
"maxparams" : false, // {int} Max number of formal params allowed per function
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
"maxstatements" : false, // {int} Max number statements per function
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
"maxlen" : false, // {int} Max number of characters per line
"varstmt" : false, // true: Disallow any var statements. Only `let` and `const` are allowed.
// Relaxing
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
"boss" : false, // true: Tolerate assignments where comparisons would be expected
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
"eqnull" : true, // true: Tolerate use of `== null`
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
"esnext" : true, // true: Allow ES.next (ES6) syntax (ex: `const`)
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
// (ex: `for each`, multiple try/catch, function expression…)
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
"funcscope" : true, // true: Tolerate defining variables inside control statements
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
"iterator" : false, // true: Tolerate using the `__iterator__` property
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
"laxcomma" : false, // true: Tolerate comma-first style coding
"loopfunc" : false, // true: Tolerate functions being defined in loops
"multistr" : false, // true: Tolerate multi-line strings
"noyield" : false, // true: Tolerate generator functions with no yield statement in them.
"notypeof" : false, // true: Tolerate invalid typeof operator values
"proto" : false, // true: Tolerate using the `__proto__` property
"scripturl" : false, // true: Tolerate script-targeted URLs
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
"validthis" : false, // true: Tolerate using this in a non-constructor function
// Environments
"browser" : true, // Web Browser (window, document, etc)
"browserify" : false, // Browserify (node.js code in the browser)
"couch" : false, // CouchDB
"devel" : true, // Development/debugging (alert, confirm, etc)
"dojo" : false, // Dojo Toolkit
"jasmine" : true, // Jasmine
"jquery" : false, // jQuery
"mocha" : true, // Mocha
"mootools" : false, // MooTools
"node" : true, // Node.js
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
"phantom" : false, // PhantomJS
"prototypejs" : false, // Prototype and Scriptaculous
"qunit" : false, // QUnit
"rhino" : false, // Rhino
"shelljs" : false, // ShellJS
"typed" : false, // Globals for typed array constructions
"worker" : false, // Web Workers
"wsh" : false, // Windows Scripting Host
"yui" : false, // Yahoo User Interface
// Custom Globals
"globals" : {
"angular": true,
"describe": true,
"it": true,
"expect": true,
"beforeEach": true,
"afterEach": true,
"module": true,
"inject": true
} // additional predefined global variables
}
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "0.10"
env:
- NODE_ENV=travis
services:
- mongodb
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2013-2015 Jeff Potter, Chaudhry Junaid
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: Procfile
================================================
web: node pm2-main.js
================================================
FILE: README.md
================================================
MEAN Stack Relational 
=====================
### Please use for reference only! No support or updates planned.
The main idea for this repository is shamelessly stolen from [http://mean.io](http://mean.io). It says:
> MEAN is a boilerplate that provides a nice starting point for [MySQL], Express, Node.js, and AngularJS based applications. It is designed to give you quick and organized way to start developing of MEAN based web apps with useful modules like sequelize and passport pre-bundled and configured. We mainly try to take care of the connection points between existing popular frameworks and solve common integration problems.
The MongoDB ORM, [Mongoose](http://mongoosejs.com/), has been replaced with [Sequelize](http://sequelizejs.com/). Switching from mongoose to sequelize allows developers easy access to MySQL, MariaDB, SQLite or PostgreSQL databases by mapping database entries to objects and vice versa.
[Addy Osmani's Blog](http://addyosmani.com/blog/full-stack-javascript-with-mean-and-yeoman/) explains SQL databases, being strongly typed in nature are great at enforcing a level of consistency, ensuring many kinds of bad data simply don’t get recorded. By using SQL databases MEAN Stack Relational favors reliability over the performance gains of NoSQL databases.
# Demo
Deploy to your Heroku account for a demo:
[](https://heroku.com/deploy)
Note: Deploy from main repository view to avoid missing app.json error.
# Getting Started
Alright now the fun begins. First clone or download the repo to your computer.
1. Clone the repository ```git clone git@github.com:jpotts18/mean-stack-relational.git```.
1. Go into the repository ```cd mean-stack-relational/```.
1. Install dependencies with NPM ```npm install```. This will copy development.json5, and production.json5 from respective sample files in the config/env folder and run the grunt copy task to copy frontend lib files to their destination.
1. Plug in your private and public keys for working with FB and Twitter into ```/config/env/development.json5``` and/or ```/config/env/production.json5```.
1. Wire up the database connection found in ```/config/env/development.json5``` and/or ```/config/env/production.json5```.
1. Run in production mode with: ```pm2 start pm2-ecosystem.json --env production``` (Run ```sudo npm install -g pm2``` if it's not installed.), or
1. Run in development mode with grunt: ```grunt```
1. Make something awesome!
Thats all! Now go and open up your browser at [http://localhost:3000](http://localhost:3000), and tweet [@jpotts18](http://twitter.com/jpotts18) to say thanks!
## Prerequisites
- Node.js - Download and Install Node.js. You can also follow [this gist](https://gist.github.com/isaacs/579814) for a quick and easy way to install Node.js and npm
- MySQL - Download and Install MySQL - Make sure it's running on the default port (3306).
### Tool Prerequisites
- NPM - Node.js package manager, should be installed when you install node.js. NPM (Node Package Manager) will look at the [package.json](https://github.com/jpotts18/mean-stack-relational/blob/master/package.json) file in the root of the project and download all of the necessary dependencies and put them in a folder called ```node_modules```
- Bower - Web package manager, installing Bower is simple when you have npm:
``` npm install -g bower ```
### NPM Modules Used
- [Passport](http://passportjs.org/) - Passport is authentication middleware for Node.js. Extremely flexible and modular, Passport can be unobtrusively dropped in to any Express-based web application. A comprehensive set of strategies support authentication using a username and password, Facebook, Twitter, and more.
- [Express](http://expressjs.com/) - Express is a minimal and flexible node.js web application framework, providing a robust set of features for building single and multi-page, and hybrid web applications.
- [Sequelize](http://sequelizejs.com/) - The Sequelize library provides easy access to MySQL, MariaDB, SQLite or PostgreSQL databases by mapping database entries to objects and vice versa. To put it in a nutshell, it's an ORM (Object-Relational-Mapper). The library is written entirely in JavaScript and can be used in the Node.JS environment.
### Javascript Tools Used
- [Grunt](http://gruntjs.com/) - In one word: automation. The less work you have to do when performing repetitive tasks like minification, compilation, unit testing, linting, etc, the easier your job becomes. After you've configured it, a Grunt can do most of that mundane work for you—and your team—with basically zero effort.
1. It [watches](https://github.com/jpotts18/mean-stack-relational/blob/master/gruntfile.js#L5) your filesystem and when it detects a change it will livereload your changes.
2. It runs [jshint](https://github.com/jpotts18/mean-stack-relational/blob/master/gruntfile.js#L32) which looks through your javascript files and ensures coding standards.
3. It runs [nodemon](https://github.com/jpotts18/mean-stack-relational/blob/master/gruntfile.js#L35) which watches changes in specific folders and recompiles the app when necessary. No running ```node app.js``` every 2 minutes.
4. It can also run tests like mocha and karma for you.
- [Bower](http://bower.io/) - Bower is a package manager for the web. It offers a generic, unopinionated solution to the problem of front-end package management, while exposing the package dependency model via an API that can be consumed by a more opinionated build stack. There are no system wide dependencies, no dependencies are shared between different apps, and the dependency tree is flat.
### Front-End Tools Used
- [Angular.js](http://angularjs.org) - AngularJS is an open-source JavaScript framework, maintained by Google, that assists with running single-page applications. Its goal is to augment browser-based applications with model–view–controller (MVC) capability, in an effort to make both development and testing easier.
- [Twitter Bootstrap](http://getbootstrap.com/) - Sleek, intuitive, and powerful mobile first front-end framework for faster and easier web development.
- [UI Bootstrap](http://angular-ui.github.io/bootstrap/) - Bootstrap components written in pure AngularJS by the AngularUI Team
# Project Roadmap
Following is a list of items detailing future direction for MEAN Stack Relational:
## Purpose
- Demonstrate several login strategies using passport.js
- Demonstrate environment configuration best practices
- Demonstrate how to use Sequelize to query a single table and to accomplish a join.
## Additions
- Demonstrate testing for Express routes and javascript classes using Mocha, Sinon, Proxyquire and more
- Demonstrating modularity by using javascript classes for complex backend functionality
- Yeoman generator to compete with MEAN
# Troubleshooting and Contact
During install some of you may encounter some issues feel free to contact me (jpotts18) or the co-contributor (chaudhryjunaid), via the repository issue tracker or the links provided below. I am also available on twitter at [@jpotts18](http://twitter.com/jpotts18) and Junaid at [@chjunaidanwar](http://twitter.com/chjunaidanwar).
================================================
FILE: app/controllers/articles.js
================================================
'use strict';
/**
* Module dependencies.
*/
var StandardError = require('standard-error');
var db = require('../../config/sequelize');
/**
* Find article by id
* Note: This is called every time that the parameter :articleId is used in a URL.
* Its purpose is to preload the article on the req object then call the next function.
*/
exports.article = function(req, res, next, id) {
console.log('id => ' + id);
db.Article.find({where: {id: id}, include: [{model:db.User, attributes:['id', 'username', 'name']}]}).then(function(article){
if(!article) {
return next(new Error('Failed to load article ' + id));
} else {
req.article = article;
return next();
}
}).catch(function(err){
return next(err);
});
};
/**
* Create a article
*/
exports.create = function(req, res) {
// augment the article by adding the UserId
req.body.UserId = req.user.id;
// save and return and instance of article on the res object.
db.Article.create(req.body).then(function(article){
if(!article){
return res.send('users/signup', {errors: new StandardError('Article could not be created')});
} else {
return res.jsonp(article);
}
}).catch(function(err){
return res.send('users/signup', {
errors: err,
status: 500
});
});
};
/**
* Update a article
*/
exports.update = function(req, res) {
// create a new variable to hold the article that was placed on the req object.
var article = req.article;
article.updateAttributes({
title: req.body.title,
content: req.body.content
}).then(function(a){
return res.jsonp(a);
}).catch(function(err){
return res.render('error', {
error: err,
status: 500
});
});
};
/**
* Delete an article
*/
exports.destroy = function(req, res) {
// create a new variable to hold the article that was placed on the req object.
var article = req.article;
article.destroy().then(function(){
return res.jsonp(article);
}).catch(function(err){
return res.render('error', {
error: err,
status: 500
});
});
};
/**
* Show an article
*/
exports.show = function(req, res) {
// Sending down the article that was just preloaded by the articles.article function
// and saves article on the req object.
return res.jsonp(req.article);
};
/**
* List of Articles
*/
exports.all = function(req, res) {
db.Article.findAll({include: [{model:db.User, attributes: ['id', 'username', 'name']}]}).then(function(articles){
return res.jsonp(articles);
}).catch(function(err){
return res.render('error', {
error: err,
status: 500
});
});
};
/**
* Article authorizations routing middleware
*/
exports.hasAuthorization = function(req, res, next) {
if (req.article.User.id !== req.user.id) {
return res.send(401, 'User is not authorized');
}
next();
};
================================================
FILE: app/controllers/index.js
================================================
'use strict';
/**
* Module dependencies.
*/
var _ = require('lodash');
exports.render = function(req, res) {
res.render('index', {
user: req.user ? JSON.stringify(req.user) : "null"
});
};
================================================
FILE: app/controllers/users.js
================================================
'use strict';
/**
* Module dependencies.
*/
var db = require('../../config/sequelize'),
request = require('request'),
qs = require('querystring'),
config = require('../../config/config'),
passport = require('passport');
/**
* Auth callback
*/
exports.authCallback = function (req, res, next) {
res.redirect('/');
};
/**
* Show login form
*/
exports.signin = function (req, res) {
res.render('users/signin', {
title: 'Signin',
message: req.flash('error')
});
};
/**
* Show sign up form
*/
exports.signup = function (req, res) {
res.render('users/signup', {
title: 'Sign up',
});
};
/**
* Logout
*/
exports.signout = function (req, res) {
console.log('Logout: { id: ' + req.user.id + ', username: ' + req.user.username + '}');
req.logout();
return res.send({status: 'success', message: 'User logout successfully.'});
};
/**
* Session
*/
exports.session = function (req, res) {
return res.send({status: 'success', message: 'User login successfully.'})
// res.redirect('/');
};
/**
* Create user
*/
exports.create = function (req, res, next) {
var message = null;
var user = db.User.build(req.body);
user.provider = 'local';
user.salt = user.makeSalt();
user.hashedPassword = user.encryptPassword(req.body.password, user.salt);
console.log('New User (local) : { id: ' + user.id + ' username: ' + user.username + ' }');
user.save().then(function () {
req.login(user, function (err) {
if (err) {
return next(err);
}
return res.send({status: 'success', message: 'User signup successfully.'})
// res.redirect('/');
});
}).catch(function (err) {
res.render('users/signup', {
message: message,
user: user
});
});
};
/**
* Send User
*/
exports.me = function (req, res) {
res.jsonp(req.user || null);
};
/**
* Find user by id
*/
exports.user = function (req, res, next, id) {
db.User.find({where: {id: id}}).then(function (user) {
if (!user) {
return next(new Error('Failed to load User ' + id));
}
req.profile = user;
next();
}).catch(function (err) {
next(err);
});
};
/**
* Generic require login routing middleware
*/
exports.requiresLogin = function (req, res, next) {
if (!req.isAuthenticated()) {
return res.status(401).send('User is not authorized');
}
next();
};
/**
* User authorizations routing middleware
*/
exports.hasAuthorization = function (req, res, next) {
if (req.profile.id !== req.user.id) {
return res.status(401).send('User is not authorized');
}
next();
};
// function to authenticate and create user
function authenticateSocialUser(profile, done) {
var searchQuery = {
email: profile.email
};
if (profile.name) {
searchQuery = {
twitterKey: profile.id
}
}
db.User.find({where: searchQuery}).then(function (user) {
if (!user) {
var userObj = {};
if (profile.name) {
userObj = {
name: profile.name || '',
username: profile.name || '',
provider: 'twitter',
twitterKey: profile.id,
email: profile.id + "@twitter.com"
}
} else {
userObj = {
name: profile.given_name || '',
email: profile.email,
username: profile.given_name || profile.name || '',
provider: 'google',
googleUserId: profile.sub
};
}
db.User.create(userObj).then(function (u) {
done(null, u);
})
} else {
done(null, user);
}
}).catch(function (err) {
done(err, null, err);
});
}
exports.facebookUser = function (req, res, next) {
function sendResponse(err, user, info) {
if (err) {
return res.send({status: "error", error: err});
}
if (!user) {
return res.send({status: "error", error: info});
}
req.login(user, function (err) {
if (err) {
return res.send({status: "error", error: {message: 'Login failed'}});
}
return res.send({status: "success", data: {user: user}});
});
}
passport.authenticate('facebook-token', {scope: ['email', 'user_about_me', 'phone']}, sendResponse)(req, res, next);
}
exports.twitterSocialUser = function (req, res) {
var requestTokenUrl = 'https://api.twitter.com/oauth/request_token';
var accessTokenUrl = 'https://api.twitter.com/oauth/access_token';
var profileUrl = 'https://api.twitter.com/1.1/account/verify_credentials.json';
function sendResponse(err, user, info) {
if (err) {
return res.send({status: "error", error: err});
}
if (!user) {
return res.send({status: "error", error: info});
}
req.login(user, function (err) {
if (err) {
return res.send({status: "error", error: {message: 'Login failed'}});
}
return res.send({status: "success", data: {user: user}});
});
}
function getUserProfile(err, response, profile) {
if (err) {
return res.send({status: "error", error: err});
}
// Step 5a. Link user accounts.
authenticateSocialUser(profile, sendResponse);
}
function verifyAccesToken(err, response, accessToken) {
accessToken = qs.parse(accessToken);
var profileOauth = {
consumer_key: config.twitter.clientID,
consumer_secret: config.twitter.clientSecret,
token: accessToken.oauth_token,
token_secret: accessToken.oauth_token_secret,
};
// Step 4. Retrieve user's profile information and email address.
request.get({
url: profileUrl,
qs: {include_email: true},
oauth: profileOauth,
json: true
}, getUserProfile);
}
function obtainRequestToken() {
var requestTokenOauth = {
consumer_key: config.twitter.clientID,
consumer_secret: config.twitter.clientSecret,
callback: req.body.redirectUri
};
// Step 1. Obtain request token for the authorization popup.
request.post({url: requestTokenUrl, oauth: requestTokenOauth}, function (err, response, body) {
var oauthToken = qs.parse(body);
// Step 2. Send OAuth token back to open the authorization screen.
res.send(oauthToken);
});
}
function exchangeOauthToken() {
var accessTokenOauth = {
consumer_key: config.twitter.clientID,
consumer_secret: config.twitter.clientSecret,
token: req.body.oauth_token,
verifier: req.body.oauth_verifier
};
// Step 3. Exchange oauth token and oauth verifier for access token.
request.post({url: accessTokenUrl, oauth: accessTokenOauth}, verifyAccesToken);
}
// Part 1 of 2: Initial request from Satellizer.
if (!req.body.oauth_token || !req.body.oauth_verifier) {
obtainRequestToken();
} else {
// Part 2 of 2: Second request after Authorize app is clicked.
exchangeOauthToken();
}
}
exports.googleSocailUser = function (req, res) {
var accessTokenUrl = 'https://accounts.google.com/o/oauth2/token';
var peopleApiUrl = 'https://www.googleapis.com/plus/v1/people/me/openIdConnect';
var params = {
code: req.body.code,
client_id: req.body.clientId,
client_secret: config.google.clientSecret,
redirect_uri: req.body.redirectUri,
grant_type: 'authorization_code'
};
function sendResponse(err, user, info) {
if (err) {
return res.send({status: "error", error: err});
}
if (!user) {
return res.send({status: "error", error: info});
}
req.login(user, function (err) {
if (err) {
return res.send({status: "error", error: {message: 'Login failed'}});
}
return res.send({status: "success", data: {user: user}});
});
}
function retrivedInfo(err, response, profile) {
if (profile.error) {
return res.status(500).send({message: profile.error.message});
}
// Authenticate User
authenticateSocialUser(profile, sendResponse);
}
function getAccessToken(err, response, token) {
var accessToken = token.access_token;
var headers = {Authorization: 'Bearer ' + accessToken};
// Step 2. Retrieve profile information about the current user.
request.get({url: peopleApiUrl, headers: headers, json: true}, retrivedInfo);
}
// Step 1. Exchange authorization code for access token.
request.post(accessTokenUrl, {json: true, form: params}, getAccessToken);
}
================================================
FILE: app/models/article.js
================================================
'use strict';
module.exports = function(sequelize, DataTypes) {
var Article = sequelize.define('Article', {
title: DataTypes.STRING,
content: DataTypes.TEXT
},
{
associate: function(models){
Article.belongsTo(models.User);
}
}
);
return Article;
};
================================================
FILE: app/models/user.js
================================================
'use strict';
/**
* User Model
*/
var crypto = require('crypto');
module.exports = function(sequelize, DataTypes) {
var User = sequelize.define('User',
{
name: DataTypes.STRING,
email: DataTypes.STRING,
username: DataTypes.STRING,
hashedPassword: DataTypes.STRING,
provider: DataTypes.STRING,
salt: DataTypes.STRING,
facebookUserId: DataTypes.INTEGER,
twitterUserId: DataTypes.INTEGER,
twitterKey: DataTypes.STRING,
twitterSecret: DataTypes.STRING,
github: DataTypes.STRING,
openId: DataTypes.STRING
},
{
instanceMethods: {
toJSON: function () {
var values = this.get();
delete values.hashedPassword;
delete values.salt;
return values;
},
makeSalt: function() {
return crypto.randomBytes(16).toString('base64');
},
authenticate: function(plainText){
return this.encryptPassword(plainText, this.salt) === this.hashedPassword;
},
encryptPassword: function(password, salt) {
if (!password || !salt) {
return '';
}
salt = new Buffer(salt, 'base64');
return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64');
}
},
associate: function(models) {
User.hasMany(models.Article);
}
}
);
return User;
};
================================================
FILE: app/routes/articles.js
================================================
'use strict';
/**
* Module dependencies.
*/
var users = require('../../app/controllers/users'),
articles = require('../../app/controllers/articles');
module.exports = function(app) {
// Article Routes
app.route('/articles')
.get(articles.all)
.post(users.requiresLogin, articles.create);
app.route('/articles/:articleId')
.get(articles.show)
.put(users.requiresLogin, articles.hasAuthorization, articles.update)
.delete(users.requiresLogin, articles.hasAuthorization, articles.destroy);
// Finish with setting up the articleId param
// Note: the articles.article function will be called everytime then it will call the next function.
app.param('articleId', articles.article);
};
================================================
FILE: app/routes/index.js
================================================
'use strict';
module.exports = function(app) {
// Home route
var index = require('../../app/controllers/index');
app.get('/', index.render);
};
================================================
FILE: app/routes/users.js
================================================
'use strict';
/**
* Module dependencies.
*/
var passport = require('passport');
module.exports = function (app) {
// User Routes
var users = require('../../app/controllers/users');
// User Routes
app.get('/signout', users.signout);
app.get('/users/me', users.me);
// Setting up the users api
app.post('/users', users.create);
// Setting the local strategy route
app.post('/users/session', passport.authenticate('local', {
failureRedirect: '/signin',
failureFlash: true
}), users.session);
// Setting social authentication routes
// Setting the facebook oauth route
app.post('/auth/facebook/token', users.facebookUser);
app.post('/auth/google', users.googleSocailUser);
// Setting the twitter oauth route
app.post('/auth/twitter', users.twitterSocialUser);
// Finish with setting up the userId param
app.param('userId', users.user);
};
================================================
FILE: app/views/404.jade
================================================
extends layouts/default
block main
h1 Oops something went wrong
br
span 404
block content
#error-message-box
#error-stack-trace
pre
code!= error
================================================
FILE: app/views/500.jade
================================================
extends layouts/default
block main
h1 Oops something went wrong
br
span 500
block content
#error-message-box
#error-stack-trace
pre
code!= error
================================================
FILE: app/views/includes/foot.jade
================================================
//AngularJS
script(type='text/javascript', src='/lib/angular/angular.js')
script(type='text/javascript', src='/lib/angular-cookies/angular-cookies.js')
script(type='text/javascript', src='/lib/angular-resource/angular-resource.js')
script(type='text/javascript', src='/lib/angular-ui-router/release/angular-ui-router.min.js')
//Angular UI
script(type='text/javascript', src='/lib/angular-bootstrap/ui-bootstrap.js')
script(type='text/javascript', src='/lib/angular-bootstrap/ui-bootstrap-tpls.js')
script(type='text/javascript', src='/lib/angular-ui-utils/modules/route/route.js')
script(type='text/javascript', src='/lib/satellizer/satellizer.min.js')
script(type='text/javascript', src='/js/FbSdk.js')
script(type='text/javascript', src='/lib/social/angular-fblogin.js')
//Application Init
script(type='text/javascript', src='/js/app.js')
script(type='text/javascript', src='/js/config.js')
script(type='text/javascript', src='/js/directives.js')
script(type='text/javascript', src='/js/filters.js')
//Application Services
script(type='text/javascript', src='/js/services/global.js')
script(type='text/javascript', src='/js/services/articles.js')
script(type='text/javascript', src='/js/services/authenticate.js')
//Application Controllers
script(type='text/javascript', src='/js/controllers/articles.js')
script(type='text/javascript', src='/js/controllers/index.js')
script(type='text/javascript', src='/js/controllers/header.js')
script(type='text/javascript', src='/js/controllers/users/auth.js')
script(type='text/javascript', src='/js/controllers/users/signIn.js')
script(type='text/javascript', src='/js/controllers/users/signUp.js')
script(type='text/javascript', src='/js/init.js')
if (process.env.NODE_ENV == 'development')
//Livereload script rendered
script(type='text/javascript', src='http://localhost:35729/livereload.js')
================================================
FILE: app/views/includes/head.jade
================================================
head
meta(charset='utf-8')
meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
meta(name='viewport', content='width=device-width,initial-scale=1')
title= appName+' - '+title
meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
meta(name="keywords", content="node.js, express, mongoose, mongodb, angularjs")
meta(name="description", content="MEAN - A Modern Stack: MongoDB, ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).")
link(href='/img/icons/favicon.ico', rel='shortcut icon', type='image/x-icon')
meta(property='fb:app_id', content='APP_ID')
meta(property='og:title', content='#{appName} - #{title}')
meta(property='og:description', content='MEAN - A Modern Stack: MongoDB, ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).')
meta(property='og:type', content='website')
meta(property='og:url', content='APP_URL')
meta(property='og:image', content='APP_LOGO')
meta(property='og:site_name', content='MEAN - A Modern Stack')
meta(property='fb:admins', content='APP_ADMIN')
link(rel='stylesheet', href='/lib/bootstrap/docs/assets/css/bootstrap.css')
//- link(rel='stylesheet', href='/lib/bootstrap/dist/css/bootstrap-responsive.css')
link(rel='stylesheet', href='/css/common.css')
link(rel='stylesheet', href='/css/views/articles.css')
//if lt IE 9
script(src='http://html5shim.googlecode.com/svn/trunk/html5.js')
================================================
FILE: app/views/index.jade
================================================
extends layouts/default
block content
section(ui-view)
script(type="text/javascript").
window.user = !{user};
================================================
FILE: app/views/layouts/default.jade
================================================
doctype html
html(lang='en', xmlns='http://www.w3.org/1999/xhtml', xmlns:fb='https://www.facebook.com/2008/fbml', itemscope='itemscope', itemtype='http://schema.org/Product')
base(href='/')
include ../includes/head
body
.navbar.navbar-inverse.navbar-fixed-top(data-ng-include="'views/header.html'", data-role="navigation")
section.content
section.container
block content
include ../includes/foot
================================================
FILE: app.js
================================================
'use strict';
/**
* Module dependencies.
*/
var express = require('express');
var fs = require('fs');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Load Configurations
var config = require('./config/config');
var winston = require('./config/winston');
winston.info('Starting '+config.app.name+'...');
winston.info('Config loaded: '+config.NODE_ENV);
winston.debug('Accepted Config:',config);
var db = require('./config/sequelize');
var passport = require('./config/passport');
var app = express();
//Initialize Express
require('./config/express')(app, passport);
//Start the app by listening on <port>
app.listen(config.PORT);
winston.info('Express app started on port ' + config.PORT);
//expose app
module.exports = app;
================================================
FILE: app.json
================================================
{
"name": "mean-stack-relational",
"description": "M*EAN - A Modern Stack: MySQL(Postgres for Heroku), ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).",
"repository": "https://github.com/jpotts18/mean-stack-relational.git",
"logo": "https://raw.githubusercontent.com/jpotts18/mean-stack-relational/master/public/img/m_logo.png",
"keywords": ["node", "express", "static"],
"env": {
"WEB_CONCURRENCY": {
"description": "The number of processes to run.",
"value": "1"
}
},
"addons": [
"heroku-postgresql:hobby-dev"
]
}
================================================
FILE: bower.json
================================================
{
"name": "mean",
"version": "0.1.0",
"dependencies": {
"angular": "latest",
"angular-resource": "latest",
"angular-cookies": "latest",
"angular-mocks": "latest",
"angular-route": "latest",
"bootstrap": "2.3.2",
"angular-bootstrap": "0.7.0",
"angular-ui-utils": "0.0.4",
"angular-ui-router": "~0.3.1",
"satellizer": "^0.15.5",
"bower": "*",
"install": "^1.0.4",
"angular-fblogin": "*"
}
}
================================================
FILE: config/config.js
================================================
'use strict';
var nconf = require('nconf'),
json5 = require('json5'),
_ = require('lodash'),
glob = require('glob'),
path = require('path'),
fs = require('fs'),
StandardError = require('standard-error');
var rootPath = path.normalize(__dirname + '/..');
// Load app configuration
var computedConfig = {
root: rootPath,
modelsDir : rootPath + '/app/models'
};
//
// Setup nconf to use (in-order):
// 1. Locally computed config
// 2. Command-line arguments
// 3. Some Environment variables
// 4. Some defaults
// 5. Environment specific config file located at './env/<NODE_ENV>.json'
// 6. Shared config file located at './env/all.json'
//
nconf.argv()
.env(['PORT','NODE_ENV','FORCE_DB_SYNC','forceSequelizeSync'])// Load select environment variables
.defaults({store:{
NODE_ENV:'development'
}});
var envConfigPath = rootPath + '/config/env/'+nconf.get('NODE_ENV')+'.json5';
try{
if(!fs.statSync(envConfigPath).isFile()){
throw new Error(); // throw error to trigger catch
}
}
catch(err){
throw new StandardError('Environment specific config file not found! Throwing up! (NODE_ENV='
+nconf.get('NODE_ENV')+')');
}
nconf.file(nconf.get('NODE_ENV'),{ file: envConfigPath, type:'file', format:json5 })
.file('shared',{ file: rootPath+ '/config/env/all.json5', type:'file', format:json5 })
.add('base-defaults',{type:'literal', store:{
PORT:5555
}})
.overrides({store:computedConfig});
module.exports = nconf.get();
/**
* Get files by glob patterns
*/
module.exports.getGlobbedFiles = function(globPatterns, removeRoot) {
// For context switching
var _this = this;
// URL paths regex
var urlRegex = new RegExp('^(?:[a-z]+:)?\/\/', 'i');
// The output array
var output = [];
// If glob pattern is array so we use each pattern in a recursive way, otherwise we use glob
if (_.isArray(globPatterns)) {
globPatterns.forEach(function(globPattern) {
output = _.union(output, _this.getGlobbedFiles(globPattern, removeRoot));
});
} else if (_.isString(globPatterns)) {
if (urlRegex.test(globPatterns)) {
output.push(globPatterns);
} else {
var files = glob(globPatterns, { sync: true });
if (removeRoot) {
files = files.map(function(file) {
return file.replace(removeRoot, '');
});
}
output = _.union(output, files);
}
}
return output;
};
/**
* Get the modules JavaScript files
*/
module.exports.getJavaScriptAssets = function(includeTests) {
var output = this.getGlobbedFiles(this.assets.lib.js.concat(this.assets.js), 'public/');
// To include tests
if (includeTests) {
output = _.union(output, this.getGlobbedFiles(this.assets.tests));
}
return output;
};
/**
* Get the modules CSS files
*/
module.exports.getCSSAssets = function() {
var output = this.getGlobbedFiles(this.assets.lib.css.concat(this.assets.css), 'public/');
return output;
};
================================================
FILE: config/env/all.json5
================================================
{
PORT: 3000, // capital PORT allows auto override by common env variable if it exists
FORCE_DB_SYNC: "false", // must be string to allow environment variable override
enableSequelizeLog: "true", // type chosen as string for no particular reason
expressSessionSecret: '$uper$ecret$e$$ionKey' // replace with your own in production
}
================================================
FILE: config/env/development.json5.sample
================================================
{
// This is your MYSQL Database configuration
db: {
name: "mean_relational",
password: "",
username: "root",
host: "localhost",
port: 3306
},
app: {
name: "M*EAN Stack Relational - Development"
},
// You will need to get your own client id's before this will work properly
facebook: {
clientID: "<CLIENT ID>",
clientSecret: "<CLIENT SECRET>",
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
twitter: {
clientID: "<CLIENT ID>",
clientSecret: "<CLIENT SECRET>",
callbackURL: "http://localhost:3000/auth/twitter/callback"
},
google: {
realm: "http://localhost:3000/",
callbackURL: "http://localhost:3000/auth/google/callback"
}
}
================================================
FILE: config/env/production.json5.sample
================================================
{
// This is your MYSQL Database configuration
db: {
name: "mean_relational",
password: "",
username: "root",
host:"localhost",
port:3306
},
app: {
name: "M*EAN Stack Relational - Production"
},
// You will need to get your own client id's before this will work properly
facebook: {
clientID: "<CLIENT ID>",
clientSecret: "<CLIENT SECRET>",
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
twitter: {
clientID: "<CLIENT ID>",
clientSecret: "<CLIENT SECRET>",
callbackURL: "http://localhost:3000/auth/twitter/callback"
},
google: {
realm: "http://localhost:3000/",
callbackURL: "http://localhost:3000/auth/google/callback"
}
}
================================================
FILE: config/env/test.json5.sample
================================================
{
PORT: 3001,
// This is your MYSQL test database configuration
db: {
name: "mean_relational_test",
password: "",
username: "root",
host: "localhost",
port: 3306
},
app: {
name: "M*EAN Stack Relational - Test"
},
// You will need to get your own client id's before this will work properly
facebook: {
clientID: "<CLIENT ID>",
clientSecret: "<CLIENT SECRET>",
callbackURL: "http://localhost:3000/auth/facebook/callback"
},
twitter: {
clientID: "<CLIENT ID>",
clientSecret: "<CLIENT SECRET>",
callbackURL: "http://localhost:3000/auth/twitter/callback"
},
google: {
realm: "http://localhost:3000/",
callbackURL: "http://localhost:3000/auth/google/callback"
}
}
================================================
FILE: config/env/travis.json
================================================
{
"db": "mongodb://localhost/mean-travis",
"port": 3001,
"app": {
"name": "MEAN - A Modern Stack - Test on travis"
},
"facebook": {
"clientID": "APP_ID",
"clientSecret": "APP_SECRET",
"callbackURL": "http://localhost:3000/auth/facebook/callback"
},
"twitter": {
"clientID": "CONSUMER_KEY",
"clientSecret": "CONSUMER_SECRET",
"callbackURL": "http://localhost:3000/auth/twitter/callback"
},
"github": {
"clientID": "APP_ID",
"clientSecret": "APP_SECRET",
"callbackURL": "http://localhost:3000/auth/github/callback"
},
"google": {
"clientID": "APP_ID",
"clientSecret": "APP_SECRET",
"callbackURL": "http://localhost:3000/auth/google/callback"
}
}
================================================
FILE: config/express.js
================================================
'use strict';
/**
* Module dependencies.
*/
var express = require('express');
var flash = require('connect-flash');
var helpers = require('view-helpers');
var compression = require('compression');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var path = require('path');
var sessionMiddleware = require('./middlewares/session');
var config = require('./config');
var winston = require('./winston');
module.exports = function(app, passport) {
winston.info('Initializing Express');
app.set('showStackError', true);
//Prettify HTML
app.locals.pretty = true;
//Should be placed before express.static
app.use(compression({
filter: function(req, res) {
return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
},
level: 9
}));
//Setting the fav icon and static folder
app.use(favicon(config.root + '/public/img/icons/favicon.ico'));
app.use(express.static(config.root + '/public'));
//Don't use logger for test env
if (config.NODE_ENV !== 'test') {
app.use(logger('dev', { "stream": winston.stream }));
}
//Set views path, template engine and default layout
app.set('views', config.root + '/app/views');
app.set('view engine', 'jade');
//Enable jsonp
app.enable("jsonp callback");
//cookieParser should be above session
app.use(cookieParser());
// request body parsing middleware should be above methodOverride
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(methodOverride());
//express session configuration
app.use(sessionMiddleware);
//connect flash for flash messages
app.use(flash());
//dynamic helpers
app.use(helpers(config.app.name));
//use passport session
app.use(passport.initialize());
app.use(passport.session());
// Globbing routing files
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
app.get('*', function (req, res, next) {
res.render('index');
});
app.use(function(err, req, res, next) {
//Log it
winston.error(err);
//Error page
res.status(500).render('500', {
error: err.stack
});
});
};
================================================
FILE: config/middlewares/session.js
================================================
'use strict';
var config = require('./../config'),
session = require('express-session'),
db = require('./../sequelize') ;
var sequelizeStore = require('express-sequelize-session')(session.Store);
var sessionMiddleware = session({
resave: true,
saveUninitialized: true,
store: new sequelizeStore(db.sequelize),
cookie:{maxAge:1000*3600*24*7}, //remember for 7 days
secret: config.expressSessionSecret/*||'$uper$ecret$e$$ionKey'*/
});
module.exports = sessionMiddleware;
================================================
FILE: config/passport.js
================================================
'use strict';
var passport = require('passport'),
_ = require('lodash');
// These are different types of authentication strategies that can be used with Passport.
var LocalStrategy = require('passport-local').Strategy,
FacebookTokenStrategy = require('passport-facebook-token'),
config = require('./config'),
db = require('./sequelize'),
winston = require('./winston');
//Serialize sessions
passport.serializeUser(function(user, done) {
done(null, user.id);
});
passport.deserializeUser(function(id, done) {
db.User.find({where: {id: id}}).then(function(user){
if(!user){
winston.warn('Logged in user not in database, user possibly deleted post-login');
return done(null, false);
}
winston.info('Session: { id: ' + user.id + ', username: ' + user.username + ' }');
done(null, user);
}).catch(function(err){
done(err, null);
});
});
//Use local strategy
passport.use(new LocalStrategy({
usernameField: 'email',
passwordField: 'password'
},
function(email, password, done) {
db.User.find({ where: { email: email }}).then(function(user) {
if (!user) {
done(null, false, { message: 'Unknown user' });
} else if (!user.authenticate(password)) {
done(null, false, { message: 'Invalid password'});
} else {
winston.info('Login (local) : { id: ' + user.id + ', username: ' + user.username + ' }');
done(null, user);
}
}).catch(function(err){
done(err);
});
}
));
passport.use(new FacebookTokenStrategy({
clientID: config.facebook.clientID,
clientSecret: config.facebook.clientSecret,
profileFields: ['id', 'first_name', 'last_name', 'email', 'photos']
}, function (accessToken, refreshToken, profile, done) {
db.User.find({where : {email: profile.emails[0].value}}).then(function(user){
if(!user){
db.User.create({
name: profile.name.givenName || '',
email: profile.emails[0].value,
username: profile.name.givenName || '',
provider: 'facebook',
facebookUserId: profile.id
}).then(function(u){
winston.info('New User (facebook) : { id: ' + u.id + ', username: ' + u.username + ' }');
done(null, u);
})
} else {
winston.info('Login (facebook) : { id: ' + user.id + ', username: ' + user.username + ' }');
done(null, user);
}
}).catch(function(err){
done(err, null);
});
}
));
module.exports = passport;
================================================
FILE: config/sequelize.js
================================================
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var _ = require('lodash');
var config = require('./config');
var winston = require('./winston');
var db = {};
winston.info('Initializing Sequelize...');
// create your instance of sequelize
var onHeroku = !!process.env.DYNO;
winston.info('Checking if running on Heroku: ',onHeroku);
var sequelize = onHeroku ?
new Sequelize(process.env.DATABASE_URL, {
dialect: 'postgres',
protocol: 'postgres',
dialectOptions: {
ssl: true
}
})
:
new Sequelize(config.db.name, config.db.username, config.db.password, {
host: config.db.host,
port: config.db.port,
dialect: 'mysql',
storage: config.db.storage,
logging: config.enableSequelizeLog === 'true' ? winston.verbose : false
});
// loop through all files in models directory ignoring hidden files and this file
fs.readdirSync(config.modelsDir)
.filter(function (file) {
return (file.indexOf('.') !== 0) && (file !== 'index.js')
})
// import model files and save model names
.forEach(function (file) {
winston.info('Loading model file ' + file);
var model = sequelize.import(path.join(config.modelsDir, file));
db[model.name] = model;
});
// invoke associations on each of the models
Object.keys(db).forEach(function (modelName) {
if (db[modelName].options.hasOwnProperty('associate')) {
db[modelName].options.associate(db)
}
});
// Synchronizing any model changes with database.
// set FORCE_DB_SYNC=true in the environment, or the program parameters to drop the database,
// and force model changes into it, if required;
// Caution: Do not set FORCE_DB_SYNC to true for every run to avoid losing data with restarts
sequelize
.sync({
force: config.FORCE_DB_SYNC === 'true',
logging: config.enableSequelizeLog === 'true' ? winston.verbose : false
})
.then(function () {
winston.info("Database " + (config.FORCE_DB_SYNC === 'true' ? "*DROPPED* and " : "") + "synchronized");
}).catch(function (err) {
winston.error("An error occurred: ", err);
});
// assign the sequelize variables to the db object and returning the db.
module.exports = _.extend({
sequelize: sequelize,
Sequelize: Sequelize
}, db);
================================================
FILE: config/winston.js
================================================
'use strict';
/**
* Created by Junaid Anwar on 5/28/15.
*/
var winston = require('winston');
var logger = new (winston.Logger)();
logger.add(winston.transports.Console, {
level: 'verbose',
prettyPrint: true,
colorize: true,
silent: false,
timestamp: false
});
logger.stream = {
write: function(message, encoding){
logger.info(message);
}
};
module.exports = logger;
================================================
FILE: gruntfile.js
================================================
'use strict';
module.exports = function(grunt) {
// Project Configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
jade: {
files: ['app/views/**'],
options: {
livereload: true,
},
},
js: {
files: ['public/js/**', 'app/**/*.js', 'config/**/*.js'],
tasks: ['jshint'],
options: {
livereload: true,
},
},
html: {
files: ['public/views/**'],
options: {
livereload: true,
},
},
css: {
files: ['public/css/**'],
options: {
livereload: true
}
}
},
jshint: {
all:['gruntfile.js', 'public/js/**/*.js', 'test/mocha/**/*.js', 'test/karma/**/*.js', 'app/**/*.js'],
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
}
},
copy: {
options: {
punctuation: ''
},
js: {
files: [
{cwd: 'bower_components/angular-bootstrap', src: ['**/*.js'], dest: 'public/lib/angular-bootstrap', expand: true},
{cwd: 'bower_components/angular-cookies', src: ['angular-cookies*'], dest: 'public/lib/angular-cookies', expand: true},
{cwd: 'bower_components/angular-mocks', src: ['**/*.js'], dest: 'public/lib/angular-mocks', expand: true},
{cwd: 'bower_components/angular-resource', src: ['angular-resource*'], dest: 'public/lib/angular-resource', expand: true},
{cwd: 'bower_components/angular-route', src: ['angular-route*'], dest: 'public/lib/angular-route', expand: true},
{cwd: 'bower_components/angular', src: ['angular*'], dest: 'public/lib/angular', expand: true},
{cwd: 'bower_components/angular-ui-utils/demo', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/demo', expand: true},
{cwd: 'bower_components/angular-ui-utils/test', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/test', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/event', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/event', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/format', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/format', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/highlight', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/highlight', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/ie-shiv', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/ie-shiv', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/indeterminate', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/indeterminate', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/inflector', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/inflector', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/jq', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/jq', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/keypress', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/keypress', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/mask', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/mask', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/reset', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/reset', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/reset/stylesheets', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/reset/stylesheets', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/route', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/route', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/scrollfix', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/scrollfix', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/showhide', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/showhide', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/unique', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/unique', expand: true},
{cwd: 'bower_components/angular-ui-utils/modules/validate', src: ['**/*.js'], dest: 'public/lib/angular-ui-utils/modules/validate', expand: true},
{cwd: 'bower_components/bootstrap/js', src: ['*.js'], dest: 'public/lib/bootstrap/js', expand: true},
{cwd: 'bower_components/bootstrap/less', src: ['*.less'], dest: 'public/lib/bootstrap/less', expand: true},
{cwd: 'bower_components/bootstrap/docs/assets/css', src: ['*.*'], dest: 'public/lib/bootstrap/docs/assets/css', expand: true},
{cwd: 'bower_components/bootstrap/docs/assets/ico', src: ['*.*'], dest: 'public/lib/bootstrap/docs/assets/ico', expand: true},
{cwd: 'bower_components/bootstrap/docs/assets/img', src: ['*.*'], dest: 'public/lib/bootstrap/docs/assets/img', expand: true},
{cwd: 'bower_components/bootstrap/docs/assets/js', src: ['*.*'], dest: 'public/lib/bootstrap/docs/assets/js', expand: true},
{cwd: 'bower_components/satellizer/dist', src: ['**/*.js'], dest: 'public/lib/satellizer', expand: true},
{cwd: 'bower_components/angular-fblogin/dist', src: ['**/*.js'], dest: 'public/lib/social', expand: true},
{cwd: 'bower_components/jquery', src: ['jquery*'], dest: 'public/lib/jquery', expand: true},
{cwd: 'bower_components/angular-ui-router', src: ['release/*.js'], dest: 'public/lib/angular-ui-router', expand: true}
]
}
},
nodemon: {
dev: {
script: 'app.js',
options: {
args: ['--color'],
ignore: ['README.md', 'node_modules/**', '.DS_Store'],
ext: 'js',
watch: ['app', 'config', 'app.js', 'gruntfile.js'],
delay: 1000,
env: {
PORT: 3000
},
cwd: __dirname
}
}
},
concurrent: {
tasks: ['nodemon', 'watch'],
options: {
logConcurrentOutput: true
}
},
mochaTest: {
options: {
reporter: 'spec'
},
src: ['test/mocha/**/*.js']
},
env: {
test: {
NODE_ENV: 'test'
}
},
karma: {
unit: {
configFile: 'test/karma/karma.conf.js'
}
}
});
//Load NPM tasks
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-nodemon');
grunt.loadNpmTasks('grunt-concurrent');
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-env');
grunt.loadNpmTasks('grunt-copy');
//Making grunt default to force in order not to break the project.
grunt.option('force', true);
//Default task(s).
grunt.registerTask('default', ['copy', 'jshint', 'concurrent']);
//Test task.
grunt.registerTask('test', ['env:test', 'mochaTest', 'karma:unit']);
};
================================================
FILE: package.json
================================================
{
"name": "mean-stack-relational",
"description": "M*EAN - A Modern Stack: MySQL(Postgres for Heroku), ExpressJS, AngularJS, NodeJS. (BONUS: Passport User Support).",
"version": "0.2.2",
"private": false,
"author": "Jeff Potter",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/jpotts18/mean-stack-relational.git"
},
"engines": {
"node": "4.2.x",
"npm": "2.14.x"
},
"scripts": {
"start": "node node_modules/grunt-cli/bin/grunt",
"test": "node node_modules/grunt-cli/bin/grunt test",
"postinstall": "bower install && cp config/env/development.json5.sample config/env/development.json5 && cp config/env/production.json5.sample config/env/production.json5 && node node_modules/grunt-cli/bin/grunt copy"
},
"dependencies": {
"async": "latest",
"body-parser": "^1.14.1",
"bower": "latest",
"compression": "^1.6.0",
"connect-flash": "^0.1.1",
"cookie-parser": "^1.4.0",
"express": "^4.13.3",
"express-sequelize-session": "^0.4.0",
"express-session": "^1.12.1",
"glob": "^6.0.1",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"grunt-copy": "latest",
"grunt-env": "latest",
"jade": "^1.11.0",
"jshint-stylish": "^2.1.0",
"json5": "^0.4.0",
"lodash": "latest",
"method-override": "^2.3.5",
"morgan": "^1.6.1",
"mysql": "^2.9.0",
"nconf": "^0.8.2",
"passport": "^0.3.2",
"passport-facebook": "^2.0.0",
"passport-google": "latest",
"passport-local": "^1.0.0",
"passport-twitter": "^1.0.3",
"pg": "^4.4.3",
"pm2": "^1.0.0",
"proxyquire": "^1.7.3",
"sequelize": "^3.13.0",
"serve-favicon": "^2.3.0",
"standard-error": "^1.1.0",
"view-helpers": "latest",
"winston": "latest",
"request": "2.75.0",
"qs": "6.2.1",
"passport-facebook-token": "3.3.0"
},
"devDependencies": {
"chai": "^3.2.0",
"grunt-concurrent": "latest",
"grunt-contrib-jshint": "latest",
"grunt-contrib-nodemon": "^0.5.2",
"grunt-contrib-watch": "latest",
"grunt-karma": "~0.6.2",
"grunt-mocha-test": "latest",
"karma": "~0.10.4",
"karma-chrome-launcher": "~0.1.0",
"karma-coffee-preprocessor": "~0.1.0",
"karma-coverage": "~0.1.0",
"karma-firefox-launcher": "~0.1.0",
"karma-html2js-preprocessor": "~0.1.0",
"karma-jasmine": "~0.1.3",
"karma-phantomjs-launcher": "~0.1.0",
"karma-requirejs": "~0.2.0",
"karma-script-launcher": "~0.1.0",
"mocha": "^2.2.5",
"supertest": "latest"
}
}
================================================
FILE: pm2-ecosystem.json
================================================
{
"apps" : [{
// mean-stack-relational app
"name" : "msr",
"script" : "app.js",
// by default, the app runs in fork mode, uncomment below to run in cluster mode
//"instances" : 4,
//"exec_mode" : "cluster_mode", // defaults to fork
"args" : ["--color"],
"watch" : true,
"ignore_watch" : ["pids", "logs", "node_modules", "bower_components"],
"merge_logs" : true, // merge logs from all instances in cluster mode
"cwd" : ".",
"error_file" : "./logs/msr.log",
"out_file" : "./logs/msr.log",
"pid_file" : "./pids/msr.pid",
"min_uptime" : "30s", // defaults to 1000s
"max_restarts" : 30, // defaults to 15
"restart_delay" : 1000,
"max_memory_restart" : "8G", // restart app if it reaches an 8GB memory footprint
"env": {
"NODE_ENV": "development"
},
"env_production" : {
"NODE_ENV": "production"
}
}]
}
================================================
FILE: pm2-main.js
================================================
var pm2 = require('pm2');
var instances = process.env.WEB_CONCURRENCY || 1; // Set by Heroku or 1 (set -1 to scale to max cpu core - 1)
var maxMemory = process.env.WEB_MEMORY || 512; // 512 is the maximum free Dyno memory on Heroku
pm2.connect(function() {
pm2.start({
script : 'app.js',
name : 'msr', // ----> THESE ATTRIBUTES ARE OPTIONAL:
exec_mode : 'cluster', // set to 'cluster' for cluster execution
instances : instances,
max_memory_restart : maxMemory + 'M', // Auto restart if process taking more than XXmo
env: { // If needed declare some environment variables
"NODE_ENV": "production"
}
}, function(err) {
if (err) return console.error('Error while launching applications', err.stack || err);
console.log('PM2 and application has been successfully started');
// Display logs in standard output
pm2.launchBus(function(err, bus) {
console.log('[PM2] Log streaming started');
bus.on('log:out', function(packet) {
console.log('[App:%s] %s', packet.process.name, packet.data);
});
bus.on('log:err', function(packet) {
console.error('[App:%s][Err] %s', packet.process.name, packet.data);
});
});
});
});
================================================
FILE: public/css/common.css
================================================
.navbar .nav>li>a.brand {
padding-left:20px;
margin-left:0
}
.content {
margin-top:50px;
width:100%
}
footer {
position:fixed;
left:0px;
bottom:0px;
height:30px;
width:100%;
background:#ddd;
-webkit-box-shadow:0 8px 6px 6px black;
-moz-box-shadow:0 8px 6px 6px black;
box-shadow:0 8px 6px 6px black
}
footer p {
padding:5px 0 12px 10px
}
================================================
FILE: public/css/views/articles.css
================================================
h1 {
text-align:center
}
ul.articles li:not(:last-child) {
border-bottom:1px solid #ccc
}
================================================
FILE: public/humans.txt
================================================
# humanstxt.org/
# The humans responsible & technology colophon
# TEAM
<name> -- <role> -- <twitter>
# THANKS
<name>
# TECHNOLOGY COLOPHON
HTML5, CSS3
jQuery, Modernizr
================================================
FILE: public/img/.gitignore
================================================
================================================
FILE: public/js/FbSdk.js
================================================
/*1453279404,,JIT Construction: v2136283,en_US*/
/**
* Copyright Facebook Inc.
*
* Licensed under the Apache License, Version 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*/
try {
window.FB || (function (window, fb_fif_window) {
var apply = Function.prototype.apply;
function bindContext(fn, thisArg) {
return function _sdkBound() {
return apply.call(fn, thisArg, arguments);
};
}
var global = {__type: 'JS_SDK_SANDBOX', window: window, document: window.document};
var sandboxWhitelist = ['setTimeout', 'setInterval', 'clearTimeout', 'clearInterval'];
for (var i = 0; i < sandboxWhitelist.length; i++) {
global[sandboxWhitelist[i]] = bindContext(window[sandboxWhitelist[i]], window);
}
(function () {
var self = window;
var __DEV__ = 0;
function emptyFunction() {
}
var __transform_includes = {};
var __annotator, __bodyWrapper;
var __w, __t;
var undefined;
with (this) {
(function () {
var a = {}, b = function (i, j) {
if (!i && !j)return null;
var k = {};
if (typeof i !== 'undefined')k.type = i;
if (typeof j !== 'undefined')k.signature = j;
return k;
}, c = function (i, j) {
return b(i && /^[A-Z]/.test(i) ? i : undefined, j && (j.params && j.params.length || j.returns) ? 'function(' + (j.params ? j.params.map(function (k) {
return (/\?/.test(k) ? '?' + k.replace('?', '') : k);
}).join(',') : '') + ')' + (j.returns ? ':' + j.returns : '') : undefined);
}, d = function (i, j, k) {
return i;
}, e = function (i, j, k) {
if ('sourcemeta' in __transform_includes)i.__SMmeta = j;
if ('typechecks' in __transform_includes) {
var l = c(j ? j.name : undefined, k);
if (l)__w(i, l);
}
return i;
}, f = function (i, j, k) {
return k.apply(i, j);
}, g = function (i, j, k, l) {
if (l && l.params)__t.apply(i, l.params);
var m = k.apply(i, j);
if (l && l.returns)__t([m, l.returns]);
return m;
}, h = function (i, j, k, l, m) {
if (m) {
if (!m.callId)m.callId = m.module + ':' + (m.line || 0) + ':' + (m.column || 0);
var n = m.callId;
a[n] = (a[n] || 0) + 1;
}
return k.apply(i, j);
};
if (typeof __transform_includes === 'undefined') {
__annotator = d;
__bodyWrapper = f;
} else {
__annotator = e;
if ('codeusage' in __transform_includes) {
__annotator = d;
__bodyWrapper = h;
__bodyWrapper.getCodeUsage = function () {
return a;
};
__bodyWrapper.clearCodeUsage = function () {
a = {};
};
} else if ('typechecks' in __transform_includes) {
__bodyWrapper = g;
} else __bodyWrapper = f;
}
})();
__t=function(a){return a[0];};__w=function(a){return a;};
var require,__d;(function(a){var b={},c={},d=['global','require','requireDynamic','requireLazy','module','exports'];require=function(e,f){if(c.hasOwnProperty(e))return c[e];if(!b.hasOwnProperty(e)){if(f)return null;throw new Error('Module '+e+' has not been defined');}var g=b[e],h=g.deps,i=g.factory.length,j,k=[];for(var l=0;l<i;l++){switch(h[l]){case 'module':j=g;break;case 'exports':j=g.exports;break;case 'global':j=a;break;case 'require':j=require;break;case 'requireDynamic':j=require;break;case 'requireLazy':j=null;break;default:j=require.call(null,h[l]);}k.push(j);}g.factory.apply(a,k);c[e]=g.exports;return g.exports;};require.__markCompiled=function(){};__d=function(e,f,g,h){if(typeof g=='function'){b[e]={factory:g,deps:d.concat(f),exports:{}};if(h===3)require.call(null,e);}else c[e]=g;};})(this);
__d('ES5Array',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};h.isArray=function(i){return Object.prototype.toString.call(i)=='[object Array]';};f.exports=h;},null);
__d('ES5ArrayPrototype',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};h.map=function(i,j){if(typeof i!='function')throw new TypeError();var k,l=this.length,m=new Array(l);for(k=0;k<l;++k)if(k in this)m[k]=i.call(j,this[k],k,this);return m;};h.forEach=function(i,j){h.map.call(this,i,j);};h.filter=function(i,j){if(typeof i!='function')throw new TypeError();var k,l,m=this.length,n=[];for(k=0;k<m;++k)if(k in this){l=this[k];if(i.call(j,l,k,this))n.push(l);}return n;};h.every=function(i,j){if(typeof i!='function')throw new TypeError();var k=new Object(this),l=k.length;for(var m=0;m<l;m++)if(m in k)if(!i.call(j,k[m],m,k))return false;return true;};h.some=function(i,j){if(typeof i!='function')throw new TypeError();var k=new Object(this),l=k.length;for(var m=0;m<l;m++)if(m in k)if(i.call(j,k[m],m,k))return true;return false;};h.indexOf=function(i,j){var k=this.length;j|=0;if(j<0)j+=k;for(;j<k;j++)if(j in this&&this[j]===i)return j;return -1;};f.exports=h;},null);
__d("ES5Date",[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};h.now=function(){return new Date().getTime();};f.exports=h;},null);
__d('ES5FunctionPrototype',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};h.bind=function(i){if(typeof this!='function')throw new TypeError('Bind must be called on a function');var j=this,k=Array.prototype.slice.call(arguments,1);function l(){return j.apply(i,k.concat(Array.prototype.slice.call(arguments)));}l.displayName='bound:'+(j.displayName||j.name||'(?)');l.toString=function m(){return 'bound: '+j;};return l;};f.exports=h;},null);
__d('ie8DontEnum',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=['toString','toLocaleString','valueOf','hasOwnProperty','isPrototypeOf','prototypeIsEnumerable','constructor'],i=({}).hasOwnProperty,j=function(){};if(({toString:true}).propertyIsEnumerable('toString'))j=function(k,l){for(var m=0;m<h.length;m++){var n=h[m];if(i.call(k,n))l(n);}};f.exports=j;},null);
__d('ES5Object',['ie8DontEnum'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i=({}).hasOwnProperty,j={};function k(){}j.create=function(l){var m=typeof l;if(m!='object'&&m!='function')throw new TypeError('Object prototype may only be a Object or null');k.prototype=l;return new k();};j.keys=function(l){var m=typeof l;if(m!='object'&&m!='function'||l===null)throw new TypeError('Object.keys called on non-object');var n=[];for(var o in l)if(i.call(l,o))n.push(o);h(l,function(p){return n.push(p);});return n;};f.exports=j;},null);
__d('ES5StringPrototype',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};h.trim=function(){if(this==null)throw new TypeError('String.prototype.trim called on null or undefined');return String.prototype.replace.call(this,/^\s+|\s+$/g,'');};h.startsWith=function(i){var j=String(this);if(this==null)throw new TypeError('String.prototype.startsWith called on null or undefined');var k=arguments.length>1?Number(arguments[1]):0;if(isNaN(k))k=0;var l=Math.min(Math.max(k,0),j.length);return j.indexOf(String(i),k)==l;};h.endsWith=function(i){var j=String(this);if(this==null)throw new TypeError('String.prototype.endsWith called on null or undefined');var k=j.length,l=String(i),m=arguments.length>1?Number(arguments[1]):k;if(isNaN(m))m=0;var n=Math.min(Math.max(m,0),k),o=n-l.length;if(o<0)return false;return j.lastIndexOf(l,o)==o;};h.contains=function(i){if(this==null)throw new TypeError('String.prototype.contains called on null or undefined');var j=String(this),k=arguments.length>1?Number(arguments[1]):0;if(isNaN(k))k=0;return j.indexOf(String(i),k)!=-1;};h.repeat=function(i){if(this==null)throw new TypeError('String.prototype.repeat called on null or undefined');var j=String(this),k=i?Number(i):0;if(isNaN(k))k=0;if(k<0||k===Infinity)throw RangeError();if(k===1)return j;if(k===0)return '';var l='';while(k){if(k&1)l+=j;if(k>>=1)j+=j;}return l;};f.exports=h;},null);
__d('ES6Array',[],function a(b,c,d,e,f,g){'use strict';if(c.__markCompiled)c.__markCompiled();var h={from:function(i){if(i==null)throw new TypeError('Object is null or undefined');var j=arguments[1],k=arguments[2],l=this,m=Object(i),n=typeof Symbol==='function'?typeof Symbol==='function'?Symbol.iterator:'@@iterator':'@@iterator',o=typeof j==='function',p=typeof m[n]==='function',q=0,r,s;if(p){r=typeof l==='function'?new l():[];var t=m[n](),u;while(!(u=t.next()).done){s=u.value;if(o)s=j.call(k,s,q);r[q]=s;q+=1;}r.length=q;return r;}var v=m.length;if(isNaN(v)||v<0)v=0;r=typeof l==='function'?new l(v):new Array(v);while(q<v){s=m[q];if(o)s=j.call(k,s,q);r[q]=s;q+=1;}r.length=q;return r;}};f.exports=h;},null);
__d('ES6ArrayPrototype',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={find:function(i,j){if(this==null)throw new TypeError('Array.prototype.find called on null or undefined');if(typeof i!=='function')throw new TypeError('predicate must be a function');var k=h.findIndex.call(this,i,j);return k===-1?void 0:this[k];},findIndex:function(i,j){if(this==null)throw new TypeError('Array.prototype.findIndex called on null or undefined');if(typeof i!=='function')throw new TypeError('predicate must be a function');var k=Object(this),l=k.length>>>0;for(var m=0;m<l;m++)if(i.call(j,k[m],m,k))return m;return -1;},fill:function(i){if(this==null)throw new TypeError('Array.prototype.fill called on null or undefined');var j=Object(this),k=j.length>>>0,l=arguments[1],m=l>>0,n=m<0?Math.max(k+m,0):Math.min(m,k),o=arguments[2],p=o===undefined?k:o>>0,q=p<0?Math.max(k+p,0):Math.min(p,k);while(n<q){j[n]=i;n++;}return j;}};f.exports=h;},null);
__d('ES6DatePrototype',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(j){return (j<10?'0':'')+j;}var i={toISOString:function(){if(!isFinite(this))throw new Error('Invalid time value');var j=this.getUTCFullYear();j=(j<0?'-':j>9999?'+':'')+('00000'+Math.abs(j)).slice(0<=j&&j<=9999?-4:-6);return j+'-'+h(this.getUTCMonth()+1)+'-'+h(this.getUTCDate())+'T'+h(this.getUTCHours())+':'+h(this.getUTCMinutes())+':'+h(this.getUTCSeconds())+'.'+(this.getUTCMilliseconds()/1000).toFixed(3).slice(2,5)+'Z';}};f.exports=i;},null);
__d('ES6Number',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=Math.pow(2,-52),i=Math.pow(2,53)-1,j=-1*i,k={isFinite:function(l){return typeof l=='number'&&isFinite(l);},isNaN:function(l){return typeof l=='number'&&isNaN(l);},isInteger:function(l){return this.isFinite(l)&&Math.floor(l)===l;},isSafeInteger:function(l){return this.isFinite(l)&&l>=this.MIN_SAFE_INTEGER&&l<=this.MAX_SAFE_INTEGER&&Math.floor(l)===l;},EPSILON:h,MAX_SAFE_INTEGER:i,MIN_SAFE_INTEGER:j};f.exports=k;},null);
__d('ES6Object',['ie8DontEnum'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i=({}).hasOwnProperty,j={assign:function(k){if(k==null)throw new TypeError('Object.assign target cannot be null or undefined');k=Object(k);for(var l=arguments.length,m=Array(l>1?l-1:0),n=1;n<l;n++)m[n-1]=arguments[n];for(var o=0;o<m.length;o++){var p=m[o];if(p==null)continue;p=Object(p);for(var q in p)if(i.call(p,q))k[q]=p[q];h(p,function(r){return k[r]=p[r];});}return k;},is:function(k,l){if(k===l){return k!==0||1/k===1/l;}else return k!==k&&l!==l;}};f.exports=j;},null);
__d('ES7StringPrototype',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};h.trimLeft=function(){return this.replace(/^\s+/,'');};h.trimRight=function(){return this.replace(/\s+$/,'');};f.exports=h;},null);
/**
* @providesModule JSON3
* @preserve-header
*
*! JSON v3.2.3 | http://bestiejs.github.com/json3 | Copyright 2012, Kit Cambridge | http://kit.mit-license.org
*/__d("JSON3",[],function a(b,c,d,e,f,g){c.__markCompiled&&c.__markCompiled();(function(){var h={}.toString,i,j,k,l=f.exports={},m='{"A":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}',n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ba,ca=new Date(-3509827334573292),da,ea,fa;try{ca=ca.getUTCFullYear()==-109252&&ca.getUTCMonth()===0&&ca.getUTCDate()==1&&ca.getUTCHours()==10&&ca.getUTCMinutes()==37&&ca.getUTCSeconds()==6&&ca.getUTCMilliseconds()==708;}catch(ga){}if(!ca){da=Math.floor;ea=[0,31,59,90,120,151,181,212,243,273,304,334];fa=function(ha,ia){return ea[ia]+365*(ha-1970)+da((ha-1969+(ia=+(ia>1)))/4)-da((ha-1901+ia)/100)+da((ha-1601+ia)/400);};}if(typeof JSON=="object"&&JSON){l.stringify=JSON.stringify;l.parse=JSON.parse;}if((n=typeof l.stringify=="function"&&!fa)){(ca=function(){return 1;}).toJSON=ca;try{n=l.stringify(0)==="0"&&l.stringify(Number())==="0"&&l.stringify(String())=='""'&&l.stringify(h)===k&&l.stringify(k)===k&&l.stringify()===k&&l.stringify(ca)==="1"&&l.stringify([ca])=="[1]"&&l.stringify([k])=="[null]"&&l.stringify(null)=="null"&&l.stringify([k,h,null])=="[null,null,null]"&&l.stringify({result:[ca,true,false,null,"\0\b\n\f\r\t"]})==m&&l.stringify(null,ca)==="1"&&l.stringify([1,2],null,1)=="[\n 1,\n 2\n]"&&l.stringify(new Date(-8.64e+15))=='"-271821-04-20T00:00:00.000Z"'&&l.stringify(new Date(8.64e+15))=='"+275760-09-13T00:00:00.000Z"'&&l.stringify(new Date(-62198755200000))=='"-000001-01-01T00:00:00.000Z"'&&l.stringify(new Date(-1))=='"1969-12-31T23:59:59.999Z"';}catch(ga){n=false;}}if(typeof l.parse=="function")try{if(l.parse("0")===0&&!l.parse(false)){ca=l.parse(m);if((s=ca.A.length==5&&ca.A[0]==1)){try{s=!l.parse('"\t"');}catch(ga){}if(s)try{s=l.parse("01")!=1;}catch(ga){}}}}catch(ga){s=false;}ca=m=null;if(!n||!s){if(!(i={}.hasOwnProperty))i=function(ha){var ia={},ja;if((ia.__proto__=null,ia.__proto__={toString:1},ia).toString!=h){i=function(ka){var la=this.__proto__,ma=ka in (this.__proto__=null,this);this.__proto__=la;return ma;};}else{ja=ia.constructor;i=function(ka){var la=(this.constructor||ja).prototype;return ka in this&&!(ka in la&&this[ka]===la[ka]);};}ia=null;return i.call(this,ha);};j=function(ha,ia){var ja=0,ka,la,ma,na;(ka=function(){this.valueOf=0;}).prototype.valueOf=0;la=new ka();for(ma in la)if(i.call(la,ma))ja++;ka=la=null;if(!ja){la=["valueOf","toString","toLocaleString","propertyIsEnumerable","isPrototypeOf","hasOwnProperty","constructor"];na=function(oa,pa){var qa=h.call(oa)=="[object Function]",ra,sa;for(ra in oa)if(!(qa&&ra=="prototype")&&i.call(oa,ra))pa(ra);for(sa=la.length;ra=la[--sa];i.call(oa,ra)&&pa(ra));};}else if(ja==2){na=function(oa,pa){var qa={},ra=h.call(oa)=="[object Function]",sa;for(sa in oa)if(!(ra&&sa=="prototype")&&!i.call(qa,sa)&&(qa[sa]=1)&&i.call(oa,sa))pa(sa);};}else na=function(oa,pa){var qa=h.call(oa)=="[object Function]",ra,sa;for(ra in oa)if(!(qa&&ra=="prototype")&&i.call(oa,ra)&&!(sa=ra==="constructor"))pa(ra);if(sa||i.call(oa,(ra="constructor")))pa(ra);};return na(ha,ia);};if(!n){o={"\\":"\\\\",'"':'\\"',"\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r","\t":"\\t"};p=function(ha,ia){return ("000000"+(ia||0)).slice(-ha);};q=function(ha){var ia='"',ja=0,ka;for(;ka=ha.charAt(ja);ja++)ia+='\\"\b\f\n\r\t'.indexOf(ka)>-1?o[ka]:ka<" "?"\\u00"+p(2,ka.charCodeAt(0).toString(16)):ka;return ia+'"';};r=function(ha,ia,ja,ka,la,ma,na){var oa=ia[ha],pa,qa,ra,sa,ta,ua,va,wa,xa,ya,za,ab,bb,cb,db;if(typeof oa=="object"&&oa){pa=h.call(oa);if(pa=="[object Date]"&&!i.call(oa,"toJSON")){if(oa>-1/0&&oa<1/0){if(fa){sa=da(oa/86400000);for(qa=da(sa/365.2425)+1970-1;fa(qa+1,0)<=sa;qa++);for(ra=da((sa-fa(qa,0))/30.42);fa(qa,ra+1)<=sa;ra++);sa=1+sa-fa(qa,ra);ta=(oa%86400000+86400000)%86400000;ua=da(ta/3600000)%24;va=da(ta/60000)%60;wa=da(ta/1000)%60;xa=ta%1000;}else{qa=oa.getUTCFullYear();ra=oa.getUTCMonth();sa=oa.getUTCDate();ua=oa.getUTCHours();va=oa.getUTCMinutes();wa=oa.getUTCSeconds();xa=oa.getUTCMilliseconds();}oa=(qa<=0||qa>=10000?(qa<0?"-":"+")+p(6,qa<0?-qa:qa):p(4,qa))+"-"+p(2,ra+1)+"-"+p(2,sa)+"T"+p(2,ua)+":"+p(2,va)+":"+p(2,wa)+"."+p(3,xa)+"Z";}else oa=null;}else if(typeof oa.toJSON=="function"&&((pa!="[object Number]"&&pa!="[object String]"&&pa!="[object Array]")||i.call(oa,"toJSON")))oa=oa.toJSON(ha);}if(ja)oa=ja.call(ia,ha,oa);if(oa===null)return "null";pa=h.call(oa);if(pa=="[object Boolean]"){return ""+oa;}else if(pa=="[object Number]"){return oa>-1/0&&oa<1/0?""+oa:"null";}else if(pa=="[object String]")return q(oa);if(typeof oa=="object"){for(bb=na.length;bb--;)if(na[bb]===oa)throw TypeError();na.push(oa);ya=[];cb=ma;ma+=la;if(pa=="[object Array]"){for(ab=0,bb=oa.length;ab<bb;db||(db=true),ab++){za=r(ab,oa,ja,ka,la,ma,na);ya.push(za===k?"null":za);}return db?(la?"[\n"+ma+ya.join(",\n"+ma)+"\n"+cb+"]":("["+ya.join(",")+"]")):"[]";}else{j(ka||oa,function(eb){var fb=r(eb,oa,ja,ka,la,ma,na);if(fb!==k)ya.push(q(eb)+":"+(la?" ":"")+fb);db||(db=true);});return db?(la?"{\n"+ma+ya.join(",\n"+ma)+"\n"+cb+"}":("{"+ya.join(",")+"}")):"{}";}na.pop();}};l.stringify=function(ha,ia,ja){var ka,la,ma,na,oa,pa;if(typeof ia=="function"||typeof ia=="object"&&ia)if(h.call(ia)=="[object Function]"){la=ia;}else if(h.call(ia)=="[object Array]"){ma={};for(na=0,oa=ia.length;na<oa;pa=ia[na++],((h.call(pa)=="[object String]"||h.call(pa)=="[object Number]")&&(ma[pa]=1)));}if(ja)if(h.call(ja)=="[object Number]"){if((ja-=ja%1)>0)for(ka="",ja>10&&(ja=10);ka.length<ja;ka+=" ");}else if(h.call(ja)=="[object String]")ka=ja.length<=10?ja:ja.slice(0,10);return r("",(pa={},pa[""]=ha,pa),la,ma,ka,"",[]);};}if(!s){t=String.fromCharCode;u={"\\":"\\",'"':'"',"/":"/",b:"\b",t:"\t",n:"\n",f:"\f",r:"\r"};v=function(){aa=ba=null;throw SyntaxError();};w=function(){var ha=ba,ia=ha.length,ja,ka,la,ma,na;while(aa<ia){ja=ha.charAt(aa);if("\t\r\n ".indexOf(ja)>-1){aa++;}else if("{}[]:,".indexOf(ja)>-1){aa++;return ja;}else if(ja=='"'){for(ka="@",aa++;aa<ia;){ja=ha.charAt(aa);if(ja<" "){v();}else if(ja=="\\"){ja=ha.charAt(++aa);if('\\"/btnfr'.indexOf(ja)>-1){ka+=u[ja];aa++;}else if(ja=="u"){la=++aa;for(ma=aa+4;aa<ma;aa++){ja=ha.charAt(aa);if(!(ja>="0"&&ja<="9"||ja>="a"&&ja<="f"||ja>="A"&&ja<="F"))v();}ka+=t("0x"+ha.slice(la,aa));}else v();}else{if(ja=='"')break;ka+=ja;aa++;}}if(ha.charAt(aa)=='"'){aa++;return ka;}v();}else{la=aa;if(ja=="-"){na=true;ja=ha.charAt(++aa);}if(ja>="0"&&ja<="9"){if(ja=="0"&&(ja=ha.charAt(aa+1),ja>="0"&&ja<="9"))v();na=false;for(;aa<ia&&(ja=ha.charAt(aa),ja>="0"&&ja<="9");aa++);if(ha.charAt(aa)=="."){ma=++aa;for(;ma<ia&&(ja=ha.charAt(ma),ja>="0"&&ja<="9");ma++);if(ma==aa)v();aa=ma;}ja=ha.charAt(aa);if(ja=="e"||ja=="E"){ja=ha.charAt(++aa);if(ja=="+"||ja=="-")aa++;for(ma=aa;ma<ia&&(ja=ha.charAt(ma),ja>="0"&&ja<="9");ma++);if(ma==aa)v();aa=ma;}return +ha.slice(la,aa);}if(na)v();if(ha.slice(aa,aa+4)=="true"){aa+=4;return true;}else if(ha.slice(aa,aa+5)=="false"){aa+=5;return false;}else if(ha.slice(aa,aa+4)=="null"){aa+=4;return null;}v();}}return "$";};x=function(ha){var ia,ja,ka;if(ha=="$")v();if(typeof ha=="string"){if(ha.charAt(0)=="@")return ha.slice(1);if(ha=="["){ia=[];for(;;ja||(ja=true)){ha=w();if(ha=="]")break;if(ja)if(ha==","){ha=w();if(ha=="]")v();}else v();if(ha==",")v();ia.push(x(ha));}return ia;}else if(ha=="{"){ia={};for(;;ja||(ja=true)){ha=w();if(ha=="}")break;if(ja)if(ha==","){ha=w();if(ha=="}")v();}else v();if(ha==","||typeof ha!="string"||ha.charAt(0)!="@"||w()!=":")v();ia[ha.slice(1)]=x(w());}return ia;}v();}return ha;};z=function(ha,ia,ja){var ka=y(ha,ia,ja);if(ka===k){delete ha[ia];}else ha[ia]=ka;};y=function(ha,ia,ja){var ka=ha[ia],la;if(typeof ka=="object"&&ka)if(h.call(ka)=="[object Array]"){for(la=ka.length;la--;)z(ka,la,ja);}else j(ka,function(ma){z(ka,ma,ja);});return ja.call(ha,ia,ka);};l.parse=function(ha,ia){aa=0;ba=ha;var ja=x(w());if(w()!="$")v();aa=ba=null;return ia&&h.call(ia)=="[object Function]"?y((ca={},ca[""]=ja,ca),"",ia):ja;};}}}).call(this);},null);
__d('ES',['ES5ArrayPrototype','ES5FunctionPrototype','ES5StringPrototype','ES5Array','ES5Object','ES5Date','JSON3','ES6Array','ES6Object','ES6ArrayPrototype','ES6DatePrototype','ES6Number','ES7StringPrototype'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t){if(c.__markCompiled)c.__markCompiled();var u=({}).toString,v={'JSON.stringify':n.stringify,'JSON.parse':n.parse},w={'Array.prototype':h,'Function.prototype':i,'String.prototype':j,Object:l,Array:k,Date:m},x={Object:p,'Array.prototype':q,'Date.prototype':r,Number:s,Array:o},y={'String.prototype':t};function z(ba){for(var ca in ba){if(!ba.hasOwnProperty(ca))continue;var da=ba[ca],ea=ca.split('.'),fa=ea.length==2?window[ea[0]][ea[1]]:window[ca];for(var ga in da){if(!da.hasOwnProperty(ga))continue;if(typeof da[ga]!=='function'){v[ca+'.'+ga]=da[ga];continue;}var ha=fa[ga];v[ca+'.'+ga]=ha&&/\{\s+\[native code\]\s\}/.test(ha)?ha:da[ga];}}}z(w);z(x);z(y);function aa(ba,ca,da){var ea=da?u.call(ba).slice(8,-1)+'.prototype':ba,fa=v[ea+'.'+ca]||ba[ca];if(typeof fa==='function'){for(var ga=arguments.length,ha=Array(ga>3?ga-3:0),ia=3;ia<ga;ia++)ha[ia-3]=arguments[ia];return fa.apply(ba,ha);}else if(fa)return fa;throw new Error('Polyfill '+ea+' does not have implementation of '+ca);}f.exports=aa;},null);
__d('sdk.babelHelpers',['ES5FunctionPrototype','ES5Object','ES6Object'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();var k={},l=Object.prototype.hasOwnProperty;k.inherits=function(m,n){j.assign(m,n);m.prototype=i.create(n&&n.prototype);m.prototype.constructor=m;m.__superConstructor__=n;return n;};k._extends=j.assign;k.objectWithoutProperties=function(m,n){var o={};for(var p in m){if(!l.call(m,p)||n.indexOf(p)>=0)continue;o[p]=m[p];}return o;};k.taggedTemplateLiteralLoose=function(m,n){m.raw=n;return m;};k.bind=h.bind;f.exports=k;},null); var ES = require('ES'); var babelHelpers = require('sdk.babelHelpers'); __d("UrlMapConfig",[],{"www":"www.facebook.com","m":"m.facebook.com","connect":"connect.facebook.net","business":"business.facebook.com","api_https":"api.facebook.com","api_read_https":"api-read.facebook.com","graph_https":"graph.facebook.com","fbcdn_http":"fbstatic-a.akamaihd.net","fbcdn_https":"fbstatic-a.akamaihd.net","cdn_http":"staticxx.facebook.com","cdn_https":"staticxx.facebook.com"});__d("JSSDKRuntimeConfig",[],{"locale":"en_US","rtl":false,"revision":"2136283"});__d("JSSDKConfig",[],{"bustCache":true,"tagCountLogRate":0.01,"errorHandling":{"rate":4},"usePluginPipe":true,"features":{"dialog_resize_refactor":true,"one_comment_controller":true,"allow_non_canvas_app_events":false,"event_subscriptions_log":{"rate":0.01,"value":10000},"should_force_single_dialog_instance":true,"js_sdk_force_status_on_load":true,"kill_fragment":true,"xfbml_profile_pic_server":true,"error_handling":{"rate":4},"e2e_ping_tracking":{"rate":1.0e-6},"getloginstatus_tracking":{"rate":0.001},"xd_timeout":{"rate":4,"value":30000},"use_bundle":false,"launch_payment_dialog_via_pac":{"rate":100},"plugin_tags_blacklist":["recommendations_bar","registration","activity","recommendations","facepile"],"should_log_response_error":true},"api":{"mode":"warn","whitelist":["AppEvents","AppEvents.EventNames","AppEvents.ParameterNames","AppEvents.activateApp","AppEvents.logEvent","AppEvents.logPurchase","Canvas","Canvas.Prefetcher","Canvas.Prefetcher.addStaticResource","Canvas.Prefetcher.setCollectionMode","Canvas.getPageInfo","Canvas.hideFlashElement","Canvas.scrollTo","Canvas.setAutoGrow","Canvas.setDoneLoading","Canvas.setSize","Canvas.setUrlHandler","Canvas.showFlashElement","Canvas.startTimer","Canvas.stopTimer","Event","Event.subscribe","Event.unsubscribe","Music.flashCallback","Music.init","Music.send","Payment","Payment.cancelFlow","Payment.continueFlow","Payment.init","Payment.lockForProcessing","Payment.parse","Payment.setSize","Payment.unlockForProcessing","ThirdPartyProvider","ThirdPartyProvider.init","ThirdPartyProvider.sendData","UA","UA.nativeApp","XFBML","XFBML.RecommendationsBar","XFBML.RecommendationsBar.markRead","XFBML.parse","addFriend","api","getAccessToken","getAuthResponse","getLoginStatus","getUserID","init","login","logout","publish","share","ui"]},"initSitevars":{"enableMobileComments":1,"iframePermissions":{"read_stream":false,"manage_mailbox":false,"manage_friendlists":false,"read_mailbox":false,"publish_checkins":true,"status_update":true,"photo_upload":true,"video_upload":true,"sms":false,"create_event":true,"rsvp_event":true,"offline_access":true,"email":true,"xmpp_login":false,"create_note":true,"share_item":true,"export_stream":false,"publish_stream":true,"publish_likes":true,"ads_management":false,"contact_email":true,"access_private_data":false,"read_insights":false,"read_requests":false,"read_friendlists":true,"manage_pages":false,"physical_login":false,"manage_groups":false,"read_deals":false}}});__d("JSSDKXDConfig",[],{"XdUrl":"\/connect\/xd_arbiter.php?version=42","XdBundleUrl":"\/connect\/xd_arbiter\/r\/MHETSQlw-F9.js?version=42","Flash":{"path":"https:\/\/connect.facebook.net\/rsrc.php\/v1\/yW\/r\/yOZN1vHw3Z_.swf"},"useCdn":true});__d("JSSDKCssConfig",[],{"rules":".fb_hidden{position:absolute;top:-10000px;z-index:10001}.fb_reposition{overflow-x:hidden;position:relative}.fb_invisible{display:none}.fb_reset{background:none;border:0;border-spacing:0;color:#000;cursor:auto;direction:ltr;font-family:\"lucida grande\", tahoma, verdana, arial, sans-serif;font-size:11px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:1;margin:0;overflow:visible;padding:0;text-align:left;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;visibility:visible;white-space:normal;word-spacing:normal}.fb_reset>div{overflow:hidden}.fb_link img{border:none}\n.fb_dialog{background:rgba(82, 82, 82, .7);position:absolute;top:-10000px;z-index:10001}.fb_reset .fb_dialog_legacy{overflow:visible}.fb_dialog_advanced{padding:10px;-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.fb_dialog_content{background:#fff;color:#333}.fb_dialog_close_icon{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yq\/r\/IE9JII6Z1Ys.png) no-repeat scroll 0 0 transparent;_background-image:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yL\/r\/s816eWC-2sl.gif);cursor:pointer;display:block;height:15px;position:absolute;right:18px;top:17px;width:15px}.fb_dialog_mobile .fb_dialog_close_icon{top:5px;left:5px;right:auto}.fb_dialog_padding{background-color:transparent;position:absolute;width:1px;z-index:-1}.fb_dialog_close_icon:hover{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yq\/r\/IE9JII6Z1Ys.png) no-repeat scroll 0 -15px transparent;_background-image:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yL\/r\/s816eWC-2sl.gif)}.fb_dialog_close_icon:active{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yq\/r\/IE9JII6Z1Ys.png) no-repeat scroll 0 -30px transparent;_background-image:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yL\/r\/s816eWC-2sl.gif)}.fb_dialog_loader{background-color:#f6f7f8;border:1px solid #606060;font-size:24px;padding:20px}.fb_dialog_top_left,.fb_dialog_top_right,.fb_dialog_bottom_left,.fb_dialog_bottom_right{height:10px;width:10px;overflow:hidden;position:absolute}.fb_dialog_top_left{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 0;left:-10px;top:-10px}.fb_dialog_top_right{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 -10px;right:-10px;top:-10px}.fb_dialog_bottom_left{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 -20px;bottom:-10px;left:-10px}.fb_dialog_bottom_right{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/ye\/r\/8YeTNIlTZjm.png) no-repeat 0 -30px;right:-10px;bottom:-10px}.fb_dialog_vert_left,.fb_dialog_vert_right,.fb_dialog_horiz_top,.fb_dialog_horiz_bottom{position:absolute;background:#525252;filter:alpha(opacity=70);opacity:.7}.fb_dialog_vert_left,.fb_dialog_vert_right{width:10px;height:100\u0025}.fb_dialog_vert_left{margin-left:-10px}.fb_dialog_vert_right{right:0;margin-right:-10px}.fb_dialog_horiz_top,.fb_dialog_horiz_bottom{width:100\u0025;height:10px}.fb_dialog_horiz_top{margin-top:-10px}.fb_dialog_horiz_bottom{bottom:0;margin-bottom:-10px}.fb_dialog_iframe{line-height:0}.fb_dialog_content .dialog_title{background:#6d84b4;border:1px solid #3a5795;color:#fff;font-size:14px;font-weight:bold;margin:0}.fb_dialog_content .dialog_title>span{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yd\/r\/Cou7n-nqK52.gif) no-repeat 5px 50\u0025;float:left;padding:5px 0 7px 26px}body.fb_hidden{-webkit-transform:none;height:100\u0025;margin:0;overflow:visible;position:absolute;top:-10000px;left:0;width:100\u0025}.fb_dialog.fb_dialog_mobile.loading{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/ya\/r\/3rhSv5V8j3o.gif) white no-repeat 50\u0025 50\u0025;min-height:100\u0025;min-width:100\u0025;overflow:hidden;position:absolute;top:0;z-index:10001}.fb_dialog.fb_dialog_mobile.loading.centered{width:auto;height:auto;min-height:initial;min-width:initial;background:none}.fb_dialog.fb_dialog_mobile.loading.centered #fb_dialog_loader_spinner{width:100\u0025}.fb_dialog.fb_dialog_mobile.loading.centered .fb_dialog_content{background:none}.loading.centered #fb_dialog_loader_close{color:#fff;display:block;padding-top:20px;clear:both;font-size:18px}#fb-root #fb_dialog_ipad_overlay{background:rgba(0, 0, 0, .45);position:absolute;left:0;top:0;width:100\u0025;min-height:100\u0025;z-index:10000}#fb-root #fb_dialog_ipad_overlay.hidden{display:none}.fb_dialog.fb_dialog_mobile.loading iframe{visibility:hidden}.fb_dialog_content .dialog_header{-webkit-box-shadow:white 0 1px 1px -1px inset;background:-webkit-gradient(linear, 0\u0025 0\u0025, 0\u0025 100\u0025, from(#738ABA), to(#2C4987));border-bottom:1px solid;border-color:#1d4088;color:#fff;font:14px Helvetica, sans-serif;font-weight:bold;text-overflow:ellipsis;text-shadow:rgba(0, 30, 84, .296875) 0 -1px 0;vertical-align:middle;white-space:nowrap}.fb_dialog_content .dialog_header table{-webkit-font-smoothing:subpixel-antialiased;height:43px;width:100\u0025}.fb_dialog_content .dialog_header td.header_left{font-size:12px;padding-left:5px;vertical-align:middle;width:60px}.fb_dialog_content .dialog_header td.header_right{font-size:12px;padding-right:5px;vertical-align:middle;width:60px}.fb_dialog_content .touchable_button{background:-webkit-gradient(linear, 0\u0025 0\u0025, 0\u0025 100\u0025, from(#4966A6), color-stop(.5, #355492), to(#2A4887));border:1px solid #2f477a;-webkit-background-clip:padding-box;-webkit-border-radius:3px;-webkit-box-shadow:rgba(0, 0, 0, .117188) 0 1px 1px inset, rgba(255, 255, 255, .167969) 0 1px 0;display:inline-block;margin-top:3px;max-width:85px;line-height:18px;padding:4px 12px;position:relative}.fb_dialog_content .dialog_header .touchable_button input{border:none;background:none;color:#fff;font:12px Helvetica, sans-serif;font-weight:bold;margin:2px -12px;padding:2px 6px 3px 6px;text-shadow:rgba(0, 30, 84, .296875) 0 -1px 0}.fb_dialog_content .dialog_header .header_center{color:#fff;font-size:16px;font-weight:bold;line-height:18px;text-align:center;vertical-align:middle}.fb_dialog_content .dialog_content{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/y9\/r\/jKEcVPZFk-2.gif) no-repeat 50\u0025 50\u0025;border:1px solid #555;border-bottom:0;border-top:0;height:150px}.fb_dialog_content .dialog_footer{background:#f6f7f8;border:1px solid #555;border-top-color:#ccc;height:40px}#fb_dialog_loader_close{float:left}.fb_dialog.fb_dialog_mobile .fb_dialog_close_button{text-shadow:rgba(0, 30, 84, .296875) 0 -1px 0}.fb_dialog.fb_dialog_mobile .fb_dialog_close_icon{visibility:hidden}#fb_dialog_loader_spinner{animation:rotateSpinner 1.2s linear infinite;background-color:transparent;background-image:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/yD\/r\/t-wz8gw1xG1.png);background-repeat:no-repeat;background-position:50\u0025 50\u0025;height:24px;width:24px}\u0040keyframes rotateSpinner{0\u0025{transform:rotate(0deg)}100\u0025{transform:rotate(360deg)}}\n.fb_iframe_widget{display:inline-block;position:relative}.fb_iframe_widget span{display:inline-block;position:relative;text-align:justify}.fb_iframe_widget iframe{position:absolute}.fb_iframe_widget_fluid_desktop,.fb_iframe_widget_fluid_desktop span,.fb_iframe_widget_fluid_desktop iframe{max-width:100\u0025}.fb_iframe_widget_fluid_desktop iframe{min-width:220px;position:relative}.fb_iframe_widget_lift{z-index:1}.fb_hide_iframes iframe{position:relative;left:-10000px}.fb_iframe_widget_loader{position:relative;display:inline-block}.fb_iframe_widget_fluid{display:inline}.fb_iframe_widget_fluid span{width:100\u0025}.fb_iframe_widget_loader iframe{min-height:32px;z-index:2;zoom:1}.fb_iframe_widget_loader .FB_Loader{background:url(https:\/\/fbstatic-a.akamaihd.net\/rsrc.php\/v2\/y9\/r\/jKEcVPZFk-2.gif) no-repeat;height:32px;width:32px;margin-left:-16px;position:absolute;left:50\u0025;z-index:4}","components":["css:fb.css.base","css:fb.css.dialog","css:fb.css.iframewidget"]});__d("ApiClientConfig",[],{"FlashRequest":{"swfUrl":"https:\/\/connect.facebook.net\/rsrc.php\/v1\/yd\/r\/mxzow1Sdmxr.swf"}});__d("JSSDKCanvasPrefetcherConfig",[],{"blacklist":[144959615576466],"sampleRate":500});__d("JSSDKPluginPipeConfig",[],{"threshold":0,"enabledApps":{"209753825810663":1,"187288694643718":1}}); __d("DOMWrapper",[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h,i,j={setRoot:function(k){h=k;},getRoot:function(){return h||document.body;},setWindow:function(k){i=k;},getWindow:function(){return i||self;}};f.exports=j;},null);
__d('dotAccess',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(i,j,k){var l=j.split('.');do{var m=l.shift();i=i[m]||k&&(i[m]={});}while(l.length&&i);return i;}f.exports=h;},null);
__d('guid',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(){return 'f'+(Math.random()*(1<<30)).toString(16).replace('.','');}f.exports=h;},null);
__d('wrapFunction',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};function i(j,k,l){k=k||'default';return function(){var m=k in h?h[k](j,l):j;return m.apply(this,arguments);};}i.setWrapper=function(j,k){k=k||'default';h[k]=j;};f.exports=i;},null);
__d('GlobalCallback',['DOMWrapper','dotAccess','guid','wrapFunction'],function a(b,c,d,e,f,g,h,i,j,k){if(c.__markCompiled)c.__markCompiled();var l,m,n={setPrefix:function(o){l=i(h.getWindow(),o,true);m=o;},create:function(o,p){if(!l)this.setPrefix('__globalCallbacks');var q=j();l[q]=k(o,'entry',p||'GlobalCallback');return m+'.'+q;},remove:function(o){var p=o.substring(m.length+1);delete l[p];}};f.exports=n;},null);
__d("sprintf",[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(i){for(var j=arguments.length,k=Array(j>1?j-1:0),l=1;l<j;l++)k[l-1]=arguments[l];var m=0;return i.replace(/%s/g,function(n){return k[m++];});}f.exports=h;},null);
__d('Log',['sprintf'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i={DEBUG:3,INFO:2,WARNING:1,ERROR:0};function j(l,m){var n=Array.prototype.slice.call(arguments,2),o=h.apply(null,n),p=window.console;if(p&&k.level>=m)p[l in p?l:'log'](o);}var k={level:-1,Level:i,debug:ES(j,'bind',true,null,'debug',i.DEBUG),info:ES(j,'bind',true,null,'info',i.INFO),warn:ES(j,'bind',true,null,'warn',i.WARNING),error:ES(j,'bind',true,null,'error',i.ERROR)};f.exports=k;},null);
__d("ObservableMixin",[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(){this.__observableEvents={};}h.prototype={inform:function(i){var j=Array.prototype.slice.call(arguments,1),k=Array.prototype.slice.call(this.getSubscribers(i));for(var l=0;l<k.length;l++){if(k[l]===null)continue;try{k[l].apply(this,j);}catch(m){setTimeout(function(){throw m;},0);}}return this;},getSubscribers:function(i){return this.__observableEvents[i]||(this.__observableEvents[i]=[]);},clearSubscribers:function(i){if(i)this.__observableEvents[i]=[];return this;},clearAllSubscribers:function(){this.__observableEvents={};return this;},subscribe:function(i,j){var k=this.getSubscribers(i);k.push(j);return this;},unsubscribe:function(i,j){var k=this.getSubscribers(i);for(var l=0;l<k.length;l++)if(k[l]===j){k.splice(l,1);break;}return this;},monitor:function(i,j){if(!j()){var k=ES(function(l){if(j.apply(j,arguments))this.unsubscribe(i,k);},"bind",true,this);this.subscribe(i,k);}return this;}};f.exports=h;},null);
__d('UrlMap',['UrlMapConfig'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i={resolve:function(j,k){var l=typeof k=='undefined'?location.protocol.replace(':',''):k?'https':'http';if(j in h)return l+'://'+h[j];if(typeof k=='undefined'&&j+'_'+l in h)return l+'://'+h[j+'_'+l];if(k!==true&&j+'_http' in h)return 'http://'+h[j+'_http'];if(k!==false&&j+'_https' in h)return 'https://'+h[j+'_https'];}};f.exports=i;},null);
__d('QueryString',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(l){var m=[];ES(ES('Object','keys',false,l).sort(),'forEach',true,function(n){var o=l[n];if(typeof o==='undefined')return;if(o===null){m.push(n);return;}m.push(encodeURIComponent(n)+'='+encodeURIComponent(o));});return m.join('&');}function i(l,m){var n={};if(l==='')return n;var o=l.split('&');for(var p=0;p<o.length;p++){var q=o[p].split('=',2),r=decodeURIComponent(q[0]);if(m&&n.hasOwnProperty(r))throw new URIError('Duplicate key: '+r);n[r]=q.length===2?decodeURIComponent(q[1]):null;}return n;}function j(l,m){return l+(ES(l,'indexOf',true,'?')!==-1?'&':'?')+(typeof m==='string'?m:k.encode(m));}var k={encode:h,decode:i,appendToUrl:j};f.exports=k;},null);
__d("ManagedError",[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(i,j){Error.prototype.constructor.call(this,i);this.message=i;this.innerError=j;}h.prototype=new Error();h.prototype.constructor=h;f.exports=h;},null);
__d('AssertionError',['ManagedError'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();function i(j){h.prototype.constructor.apply(this,arguments);}i.prototype=new h();i.prototype.constructor=i;f.exports=i;},null);
__d('Assert',['AssertionError','sprintf'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();function j(o,p){if(typeof o!=='boolean'||!o)throw new h(p);return o;}function k(o,p,q){var r;if(p===undefined){r='undefined';}else if(p===null){r='null';}else{var s=Object.prototype.toString.call(p);r=/\s(\w*)/.exec(s)[1].toLowerCase();}j(ES(o,'indexOf',true,r)!==-1,q||i('Expression is of type %s, not %s',r,o));return p;}function l(o,p,q){j(p instanceof o,q||'Expression not instance of type');return p;}function m(o,p){n['is'+o]=p;n['maybe'+o]=function(q,r){if(q!=null)p(q,r);};}var n={isInstanceOf:l,isTrue:j,isTruthy:function(o,p){return j(!!o,p);},type:k,define:function(o,p){o=o.substring(0,1).toUpperCase()+o.substring(1).toLowerCase();m(o,function(q,r){j(p(q),r);});}};ES(['Array','Boolean','Date','Function','Null','Number','Object','Regexp','String','Undefined'],'forEach',true,function(o){m(o,ES(k,'bind',true,null,o.toLowerCase()));});f.exports=n;},null);
__d('Type',['Assert'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();function i(){var m=this.__mixins;if(m)for(var n=0;n<m.length;n++)m[n].apply(this,arguments);}function j(m,n){if(n instanceof m)return true;if(n instanceof i)for(var o=0;o<n.__mixins.length;o++)if(n.__mixins[o]==m)return true;return false;}function k(m,n){var o=m.prototype;if(!ES('Array','isArray',false,n))n=[n];for(var p=0;p<n.length;p++){var q=n[p];if(typeof q=='function'){o.__mixins.push(q);q=q.prototype;}ES(ES('Object','keys',false,q),'forEach',true,function(r){o[r]=q[r];});}}function l(m,n,o){var p=n&&n.hasOwnProperty('constructor')?n.constructor:function(){this.parent.apply(this,arguments);};h.isFunction(p);if(m&&m.prototype instanceof i===false)throw new Error('parent type does not inherit from Type');m=m||i;function q(){}q.prototype=m.prototype;p.prototype=new q();if(n)ES('Object','assign',false,p.prototype,n);p.prototype.constructor=p;p.parent=m;p.prototype.__mixins=m.prototype.__mixins?Array.prototype.slice.call(m.prototype.__mixins):[];if(o)k(p,o);p.prototype.parent=function(){this.parent=m.prototype.parent;m.apply(this,arguments);};p.prototype.parentCall=function(r){return m.prototype[r].apply(this,Array.prototype.slice.call(arguments,1));};p.extend=function(r,s){return l(this,r,s);};return p;}ES('Object','assign',false,i.prototype,{instanceOf:function(m){return j(m,this);}});ES('Object','assign',false,i,{extend:function(m,n){return typeof m==='function'?l.apply(null,arguments):l(null,m,n);},instanceOf:j});f.exports=i;},null);
__d('sdk.Model',['Type','ObservableMixin'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();var j=h.extend({constructor:function(k){this.parent();var l={},m=this;ES(ES('Object','keys',false,k),'forEach',true,function(n){l[n]=k[n];m['set'+n]=function(o){if(o===l[n])return this;l[n]=o;m.inform(n+'.change',o);return m;};m['get'+n]=function(){return l[n];};});}},i);f.exports=j;},null);
__d('sdk.Runtime',['sdk.Model','JSSDKRuntimeConfig'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();var j={UNKNOWN:0,PAGETAB:1,CANVAS:2,PLATFORM:4},k=new h({AccessToken:'',ClientID:'',CookieUserID:'',Environment:j.UNKNOWN,Initialized:false,IsVersioned:false,KidDirectedSite:undefined,Locale:i.locale,LoggedIntoFacebook:undefined,LoginStatus:undefined,Revision:i.revision,Rtl:i.rtl,Scope:undefined,Secure:undefined,UseCookie:false,UserID:'',Version:undefined});ES('Object','assign',false,k,{ENVIRONMENTS:j,isEnvironment:function(l){var m=this.getEnvironment();return (l|m)===m;},isCanvasEnvironment:function(){return this.isEnvironment(j.CANVAS)||this.isEnvironment(j.PAGETAB);}});(function(){var l=/app_runner/.test(window.name)?j.PAGETAB:/iframe_canvas/.test(window.name)?j.CANVAS:j.UNKNOWN;if((l|j.PAGETAB)===l)l=l|j.CANVAS;k.setEnvironment(l);})();f.exports=k;},null);
__d('sdk.Cookie',['QueryString','sdk.Runtime'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();var j=null;function k(n,o,p){n=n+i.getClientID();var q=j&&j!=='.';if(q){document.cookie=n+'=; expires=Wed, 04 Feb 2004 08:00:00 GMT;';document.cookie=n+'=; expires=Wed, 04 Feb 2004 08:00:00 GMT;'+'domain='+location.hostname+';';}var r=new Date(p).toGMTString();document.cookie=n+'='+o+(o&&p===0?'':'; expires='+r)+'; path=/'+(q?'; domain='+j:'');}function l(n){n=n+i.getClientID();var o=new RegExp('\\b'+n+'=([^;]*)\\b');return o.test(document.cookie)?RegExp.$1:null;}var m={setDomain:function(n){j=n;var o=h.encode({base_domain:j&&j!=='.'?j:''}),p=new Date();p.setFullYear(p.getFullYear()+1);k('fbm_',o,p.getTime());},getDomain:function(){return j;},loadMeta:function(){var n=l('fbm_');if(n){var o=h.decode(n);if(!j)j=o.base_domain;return o;}},loadSignedRequest:function(){return l('fbsr_');},setSignedRequestCookie:function(n,o){if(!n)throw new Error('Value passed to Cookie.setSignedRequestCookie '+'was empty.');k('fbsr_',n,o);},clearSignedRequestCookie:function(){k('fbsr_','',0);},setRaw:k,getRaw:l};f.exports=m;},null);
__d('Miny',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h='Miny1',i='wxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'.split(''),j={encode:function(k){if(/^$|[~\\]|__proto__/.test(k))return k;var l=k.match(/\w+|\W+/g),m,n=ES('Object','create',false,null);for(m=0;m<l.length;m++)n[l[m]]=(n[l[m]]||0)+1;var o=ES('Object','keys',false,n);o.sort(function(r,s){return n[s]-n[r];});for(m=0;m<o.length;m++){var p=(m-m%32)/32;n[o[m]]=p?p.toString(32)+i[m%32]:i[m%32];}var q='';for(m=0;m<l.length;m++)q+=n[l[m]];o.unshift(h,o.length);o.push(q);return o.join('~');}};f.exports=j;},null);
__d('sdk.UA',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=navigator.userAgent,i={iphone:/\b(iPhone|iP[ao]d)/.test(h),ipad:/\b(iP[ao]d)/.test(h),android:/Android/i.test(h),nativeApp:/FBAN\/\w+;/i.test(h)},j=/Mobile/i.test(h),k={ie:'',firefox:'',chrome:'',webkit:'',osx:''},l=/(?:MSIE.(\d+\.\d+))|(?:(?:Firefox|GranParadiso|Iceweasel).(\d+\.\d+))|(?:AppleWebKit.(\d+(?:\.\d+)?))|(?:Trident\/\d+\.\d+.*rv:(\d+\.\d+))/.exec(h);if(l){k.ie=l[1]?parseFloat(l[1]):l[4]?parseFloat(l[4]):'';k.firefox=l[2]||'';k.webkit=l[3]||'';if(l[3]){var m=/(?:Chrome\/(\d+\.\d+))/.exec(h);k.chrome=m?m[1]:'';}}var n=/(?:Mac OS X (\d+(?:[._]\d+)?))/.exec(h);if(n)k.osx=n[1];function o(q){return ES(q.split('.'),'map',true,function(r){return parseFloat(r);});}var p={};ES(ES('Object','keys',false,k),'map',true,function(q){p[q]=function(){return parseFloat(k[q]);};p[q].getVersionParts=function(){return o(k[q]);};});ES(ES('Object','keys',false,i),'map',true,function(q){p[q]=function(){return i[q];};});p.mobile=function(){return i.iphone||i.ipad||i.android||j;};f.exports=p;},null);
__d('getBlankIframeSrc',['sdk.UA'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();function i(){return h.ie()<10?'javascript:false':'about:blank';}f.exports=i;},null);
__d('insertIframe',['GlobalCallback','getBlankIframeSrc','guid'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();function k(l){l.id=l.id||j();l.name=l.name||j();var m=false,n=false,o=function(){if(m&&!n){n=true;l.onload&&l.onload(l.root.firstChild);}},p=h.create(o);if(document.attachEvent){var q='<iframe'+' id="'+l.id+'"'+' name="'+l.name+'"'+(l.title?' title="'+l.title+'"':'')+(l.className?' class="'+l.className+'"':'')+' style="border:none;'+(l.width?'width:'+l.width+'px;':'')+(l.height?'height:'+l.height+'px;':'')+'"'+' src="'+i()+'"'+' frameborder="0"'+' scrolling="no"'+' allowtransparency="true"'+' onload="'+p+'()"'+'></iframe>';l.root.innerHTML='<iframe src="'+i()+'"'+' frameborder="0"'+' scrolling="no"'+' style="height:1px"></iframe>';m=true;setTimeout(function(){l.root.innerHTML=q;l.root.firstChild.src=l.url;l.onInsert&&l.onInsert(l.root.firstChild);},0);}else{var r=document.createElement('iframe');r.id=l.id;r.name=l.name;r.onload=o;r.scrolling='no';r.style.border='none';r.style.overflow='hidden';if(l.title)r.title=l.title;if(l.className)r.className=l.className;if(l.height!==undefined)r.style.height=l.height+'px';if(l.width!==undefined)if(l.width=='100%'){r.style.width=l.width;}else r.style.width=l.width+'px';l.root.appendChild(r);m=true;r.src=l.url;l.onInsert&&l.onInsert(r);}}f.exports=k;},null);
__d('sdk.domReady',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h,i="readyState" in document?/loaded|complete/.test(document.readyState):!!document.body;function j(){if(!h)return;var m;while(m=h.shift())m();h=null;}function k(m){if(h){h.push(m);}else m();}if(!i){h=[];if(document.addEventListener){document.addEventListener('DOMContentLoaded',j,false);window.addEventListener('load',j,false);}else if(document.attachEvent){document.attachEvent('onreadystatechange',j);window.attachEvent('onload',j);}if(document.documentElement.doScroll&&window==window.top){var l=function(){try{document.documentElement.doScroll('left');}catch(m){setTimeout(l,0);return;}j();};l();}}f.exports=k;},3);
__d('sdk.Content',['Log','sdk.UA','sdk.domReady'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();var k,l,m={append:function(n,o){if(!o)if(!k){k=o=document.getElementById('fb-root');if(!o){h.warn('The "fb-root" div has not been created, auto-creating');k=o=document.createElement('div');o.id='fb-root';if(i.ie()||!document.body){j(function(){document.body.appendChild(o);});}else document.body.appendChild(o);}o.className+=' fb_reset';}else o=k;if(typeof n=='string'){var p=document.createElement('div');o.appendChild(p).innerHTML=n;return p;}else return o.appendChild(n);},appendHidden:function(n){if(!o){var o=document.createElement('div'),p=o.style;p.position='absolute';p.top='-10000px';p.width=p.height=0;o=m.append(o);}return m.append(n,o);},submitToTarget:function(n,o){var p=document.createElement('form');p.action=n.url;p.target=n.target;p.method=o?'GET':'POST';m.appendHidden(p);for(var q in n.params)if(n.params.hasOwnProperty(q)){var r=n.params[q];if(r!==null&&r!==undefined){var s=document.createElement('input');s.name=q;s.value=r;p.appendChild(s);}}p.submit();p.parentNode.removeChild(p);}};f.exports=m;},null);
__d('sdk.Impressions',['sdk.Content','Miny','QueryString','sdk.Runtime','UrlMap','getBlankIframeSrc','guid','insertIframe'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o){if(c.__markCompiled)c.__markCompiled();function p(r){var s=k.getClientID();if(!r.api_key&&s)r.api_key=s;r.kid_directed_site=k.getKidDirectedSite();var t=l.resolve('www',true)+'/impression.php/'+n()+'/',u=j.appendToUrl(t,r);if(u.length>2000)if(r.payload&&typeof r.payload==='string'){var v=i.encode(r.payload);if(v&&v.length<r.payload.length){r.payload=v;u=j.appendToUrl(t,r);}}if(u.length<=2000){var w=new Image();w.src=u;}else{var x=n(),y=h.appendHidden('');o({url:m(),root:y,name:x,className:'fb_hidden fb_invisible',onload:function(){y.parentNode.removeChild(y);}});h.submitToTarget({url:t,target:x,params:r});}}var q={log:function(r,s){if(!s.source)s.source='jssdk';p({lid:r,payload:ES('JSON','stringify',false,s)});},impression:p};f.exports=q;},null);
__d('Base64',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';function i(m){m=m.charCodeAt(0)<<16|m.charCodeAt(1)<<8|m.charCodeAt(2);return String.fromCharCode(h.charCodeAt(m>>>18),h.charCodeAt(m>>>12&63),h.charCodeAt(m>>>6&63),h.charCodeAt(m&63));}var j='>___?456789:;<=_______'+'\x00\x01\x02\x03\x04\x05\x06\x07\b\t\n\x0b\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19'+'______\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123';function k(m){m=j.charCodeAt(m.charCodeAt(0)-43)<<18|j.charCodeAt(m.charCodeAt(1)-43)<<12|j.charCodeAt(m.charCodeAt(2)-43)<<6|j.charCodeAt(m.charCodeAt(3)-43);return String.fromCharCode(m>>>16,m>>>8&255,m&255);}var l={encode:function(m){m=unescape(encodeURI(m));var n=(m.length+2)%3;m=(m+'\0\0'.slice(n)).replace(/[\s\S]{3}/g,i);return m.slice(0,m.length+n-2)+'=='.slice(n);},decode:function(m){m=m.replace(/[^A-Za-z0-9+\/]/g,'');var n=m.length+3&3;m=(m+'AAA'.slice(n)).replace(/..../g,k);m=m.slice(0,m.length+n-3);try{return decodeURIComponent(escape(m));}catch(o){throw new Error('Not valid UTF-8');}},encodeObject:function(m){return l.encode(ES('JSON','stringify',false,m));},decodeObject:function(m){return ES('JSON','parse',false,l.decode(m));},encodeNums:function(m){return String.fromCharCode.apply(String,ES(m,'map',true,function(n){return h.charCodeAt((n|-(n>63))&-(n>0)&63);}));}};f.exports=l;},null);
__d('sdk.SignedRequest',['Base64'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();function i(k){if(!k)return null;var l=k.split('.',2)[1].replace(/\-/g,'+').replace(/\_/g,'/');return h.decodeObject(l);}var j={parse:i};f.exports=j;},null);
__d('URIRFC3986',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=new RegExp('^'+'([^:/?#]+:)?'+'(//'+'([^\\\\/?#@]*@)?'+'('+'\\[[A-Fa-f0-9:.]+\\]|'+'[^\\/?#:]*'+')'+'(:[0-9]*)?'+')?'+'([^?#]*)'+'(\\?[^#]*)?'+'(#.*)?'),i={parse:function(j){if(ES(j,'trim',true)==='')return null;var k=j.match(h),l={};l.uri=k[0]?k[0]:null;l.scheme=k[1]?k[1].substr(0,k[1].length-1):null;l.authority=k[2]?k[2].substr(2):null;l.userinfo=k[3]?k[3].substr(0,k[3].length-1):null;l.host=k[2]?k[4]:null;l.port=k[5]?k[5].substr(1)?parseInt(k[5].substr(1),10):null:null;l.path=k[6]?k[6]:null;l.query=k[7]?k[7].substr(1):null;l.fragment=k[8]?k[8].substr(1):null;l.isGenericURI=l.authority===null&&!!l.scheme;return l;}};f.exports=i;},null);
__d('createObjectFrom',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(i,j){var k={},l=ES('Array','isArray',false,j);if(j===undefined)j=true;for(var m=i.length-1;m>=0;m--)k[i[m]]=l?j[m]:j;return k;}f.exports=h;},null);
__d('URISchemes',['createObjectFrom'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i=h(['blob','fb','fb-ama','fb-messenger','fbcf','fbconnect','fbmobilehome','fbrpc','file','ftp','http','https','mailto','ms-app','intent','itms','itms-apps','itms-services','market','svn+ssh','fbstaging','tel','sms','pebblejs','sftp']),j={isAllowed:function(k){if(!k)return true;return i.hasOwnProperty(k.toLowerCase());}};f.exports=j;},null);
__d('eprintf',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=function(i){var j=ES(Array.prototype.slice.call(arguments),'map',true,function(m){return String(m);}),k=i.split('%s').length-1;if(k!==j.length-1)return h('eprintf args number mismatch: %s',ES('JSON','stringify',false,j));var l=1;return i.replace(/%s/g,function(m){return String(j[l++]);});};f.exports=h;},null);
__d('ex',['eprintf'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i=function(){for(var j=arguments.length,k=Array(j),l=0;l<j;l++)k[l]=arguments[l];k=ES(k,'map',true,function(m){return String(m);});if(k[0].split('%s').length!==k.length)return i('ex args number mismatch: %s',ES('JSON','stringify',false,k));return i._prefix+ES('JSON','stringify',false,k)+i._suffix;};i._prefix='<![EX[';i._suffix=']]>';f.exports=i;},null);
__d('invariant',['ex','sprintf'],function a(b,c,d,e,f,g,h,i){'use strict';if(c.__markCompiled)c.__markCompiled();var j=h;function k(l,m){if(!l){var n;if(m===undefined){n=new Error('Minified exception occurred; use the non-minified dev environment '+'for the full error message and additional helpful warnings.');}else{var o=[m];for(var p=2,q=arguments.length;p<q;p++)o.push(arguments[p]);n=new Error(j.apply(null,o));n.name='Invariant Violation';n.messageWithParams=o;}n.framesToPop=1;throw n;}}f.exports=k;},null);
__d('URIBase',['URIRFC3986','URISchemes','ex','invariant'],function a(b,c,d,e,f,g,h,i,j,k){if(c.__markCompiled)c.__markCompiled();var l=new RegExp('[\\x00-\\x2c\\x2f\\x3b-\\x40\\x5c\\x5e\\x60\\x7b-\\x7f'+'\\uFDD0-\\uFDEF\\uFFF0-\\uFFFF'+'\\u2047\\u2048\\uFE56\\uFE5F\\uFF03\\uFF0F\\uFF1F]'),m=new RegExp('^(?:[^/]*:|'+'[\\x00-\\x1f]*/[\\x00-\\x1f]*/)');function n(q,r,s,t){if(!r)return true;if(r instanceof p){q.setProtocol(r.getProtocol());q.setDomain(r.getDomain());q.setPort(r.getPort());q.setPath(r.getPath());q.setQueryData(t.deserialize(t.serialize(r.getQueryData())));q.setFragment(r.getFragment());q.setForceFragmentSeparator(r.getForceFragmentSeparator());return true;}r=ES(r.toString(),'trim',true);var u=h.parse(r)||{};if(!s&&!i.isAllowed(u.scheme))return false;q.setProtocol(u.scheme||'');if(!s&&l.test(u.host))return false;q.setDomain(u.host||'');q.setPort(u.port||'');q.setPath(u.path||'');if(s){q.setQueryData(t.deserialize(u.query)||{});}else try{q.setQueryData(t.deserialize(u.query)||{});}catch(v){return false;}q.setFragment(u.fragment||'');if(u.fragment==='')q.setForceFragmentSeparator(true);if(u.userinfo!==null)if(s){throw new Error(j('URI.parse: invalid URI (userinfo is not allowed in a URI): %s',q.toString()));}else return false;if(!q.getDomain()&&ES(q.getPath(),'indexOf',true,'\\')!==-1)if(s){throw new Error(j('URI.parse: invalid URI (no domain but multiple back-slashes): %s',q.toString()));}else return false;if(!q.getProtocol()&&m.test(r))if(s){throw new Error(j('URI.parse: invalid URI (unsafe protocol-relative URLs): %s',q.toString()));}else return false;return true;}var o=[];function p(q,r){'use strict';!r?k(0):undefined;this.$URIBase1=r;this.$URIBase2='';this.$URIBase3='';this.$URIBase4='';this.$URIBase5='';this.$URIBase6='';this.$URIBase7={};this.$URIBase8=false;n(this,q,true,r);}p.prototype.setProtocol=function(q){'use strict';!i.isAllowed(q)?k(0):undefined;this.$URIBase2=q;return this;};p.prototype.getProtocol=function(q){'use strict';return this.$URIBase2;};p.prototype.setSecure=function(q){'use strict';return this.setProtocol(q?'https':'http');};p.prototype.isSecure=function(){'use strict';return this.getProtocol()==='https';};p.prototype.setDomain=function(q){'use strict';if(l.test(q))throw new Error(j('URI.setDomain: unsafe domain specified: %s for url %s',q,this.toString()));this.$URIBase3=q;return this;};p.prototype.getDomain=function(){'use strict';return this.$URIBase3;};p.prototype.setPort=function(q){'use strict';this.$URIBase4=q;return this;};p.prototype.getPort=function(){'use strict';return this.$URIBase4;};p.prototype.setPath=function(q){'use strict';this.$URIBase5=q;return this;};p.prototype.getPath=function(){'use strict';return this.$URIBase5;};p.prototype.addQueryData=function(q,r){'use strict';if(Object.prototype.toString.call(q)==='[object Object]'){ES('Object','assign',false,this.$URIBase7,q);}else this.$URIBase7[q]=r;return this;};p.prototype.setQueryData=function(q){'use strict';this.$URIBase7=q;return this;};p.prototype.getQueryData=function(){'use strict';return this.$URIBase7;};p.prototype.removeQueryData=function(q){'use strict';if(!ES('Array','isArray',false,q))q=[q];for(var r=0,s=q.length;r<s;++r)delete this.$URIBase7[q[r]];return this;};p.prototype.setFragment=function(q){'use strict';this.$URIBase6=q;this.setForceFragmentSeparator(false);return this;};p.prototype.getFragment=function(){'use strict';return this.$URIBase6;};p.prototype.setForceFragmentSeparator=function(q){'use strict';this.$URIBase8=q;return this;};p.prototype.getForceFragmentSeparator=function(){'use strict';return this.$URIBase8;};p.prototype.isEmpty=function(){'use strict';return !(this.getPath()||this.getProtocol()||this.getDomain()||this.getPort()||ES('Object','keys',false,this.getQueryData()).length>0||this.getFragment());};p.prototype.toString=function(){'use strict';var q=this;for(var r=0;r<o.length;r++)q=o[r](q);return q.$URIBase9();};p.prototype.$URIBase9=function(){'use strict';var q='',r=this.getProtocol();if(r)q+=r+'://';var s=this.getDomain();if(s)q+=s;var t=this.getPort();if(t)q+=':'+t;var u=this.getPath();if(u){q+=u;}else if(q)q+='/';var v=this.$URIBase1.serialize(this.getQueryData());if(v)q+='?'+v;var w=this.getFragment();if(w){q+='#'+w;}else if(this.getForceFragmentSeparator())q+='#';return q;};p.registerFilter=function(q){'use strict';o.push(q);};p.prototype.getOrigin=function(){'use strict';var q=this.getPort();return this.getProtocol()+'://'+this.getDomain()+(q?':'+q:'');};p.isValidURI=function(q,r){return n(new p(null,r),q,false,r);};f.exports=p;},null);
__d('sdk.URI',['Assert','QueryString','URIBase'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();var k,l,m=/\.facebook\.com$/,n={serialize:function(p){return p?i.encode(p):'';},deserialize:function(p){return p?i.decode(p):{};}};k=babelHelpers.inherits(o,j);l=k&&k.prototype;function o(p){'use strict';h.isString(p,'The passed argument was of invalid type.');l.constructor.call(this,p,n);}o.prototype.isFacebookURI=function(){'use strict';return m.test(this.getDomain());};o.prototype.valueOf=function(){'use strict';return this.toString();};f.exports=o;},null);
__d('Queue',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={};function i(j){'use strict';this._opts=babelHelpers._extends({interval:0,processor:null},j);this._queue=[];this._stopped=true;}i.prototype._dispatch=function(j){'use strict';if(this._stopped||this._queue.length===0)return;if(!this._opts.processor){this._stopped=true;throw new Error('No processor available');}if(this._opts.interval){this._opts.processor.call(this,this._queue.shift());this._timeout=setTimeout(ES(this._dispatch,'bind',true,this),this._opts.interval);}else while(this._queue.length)this._opts.processor.call(this,this._queue.shift());};i.prototype.enqueue=function(j){'use strict';if(this._opts.processor&&!this._stopped){this._opts.processor.call(this,j);}else this._queue.push(j);return this;};i.prototype.start=function(j){'use strict';if(j)this._opts.processor=j;this._stopped=false;this._dispatch();return this;};i.prototype.isStarted=function(){'use strict';return !this._stopped;};i.prototype.dispatch=function(){'use strict';this._dispatch(true);};i.prototype.stop=function(j){'use strict';this._stopped=true;if(j)clearTimeout(this._timeout);return this;};i.prototype.merge=function(j,k){'use strict';this._queue[k?'unshift':'push'].apply(this._queue,j._queue);j._queue=[];this._dispatch();return this;};i.prototype.getLength=function(){'use strict';return this._queue.length;};i.get=function(j,k){'use strict';var l;if(j in h){l=h[j];}else l=h[j]=new i(k);return l;};i.exists=function(j){'use strict';return j in h;};i.remove=function(j){'use strict';return delete h[j];};f.exports=i;},null);
__d('DOMEventListener',['wrapFunction'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i,j;if(window.addEventListener){i=function(l,m,n){n.wrapper=h(n,'entry','DOMEventListener.add '+m);l.addEventListener(m,n.wrapper,false);};j=function(l,m,n){l.removeEventListener(m,n.wrapper,false);};}else if(window.attachEvent){i=function(l,m,n){n.wrapper=h(n,'entry','DOMEventListener.add '+m);l.attachEvent('on'+m,n.wrapper);};j=function(l,m,n){l.detachEvent('on'+m,n.wrapper);};}else j=i=function(){};var k={add:function(l,m,n){i(l,m,n);return {remove:function(){j(l,m,n);l=null;}};},remove:j};f.exports=k;},null);
__d('UserAgent_DEPRECATED',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=false,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w;function x(){if(h)return;h=true;var z=navigator.userAgent,aa=/(?:MSIE.(\d+\.\d+))|(?:(?:Firefox|GranParadiso|Iceweasel).(\d+\.\d+))|(?:Opera(?:.+Version.|.)(\d+\.\d+))|(?:AppleWebKit.(\d+(?:\.\d+)?))|(?:Trident\/\d+\.\d+.*rv:(\d+\.\d+))/.exec(z),ba=/(Mac OS X)|(Windows)|(Linux)/.exec(z);t=/\b(iPhone|iP[ao]d)/.exec(z);u=/\b(iP[ao]d)/.exec(z);r=/Android/i.exec(z);v=/FBAN\/\w+;/i.exec(z);w=/Mobile/i.exec(z);s=!!/Win64/.exec(z);if(aa){i=aa[1]?parseFloat(aa[1]):aa[5]?parseFloat(aa[5]):NaN;if(i&&document&&document.documentMode)i=document.documentMode;var ca=/(?:Trident\/(\d+.\d+))/.exec(z);n=ca?parseFloat(ca[1])+4:i;j=aa[2]?parseFloat(aa[2]):NaN;k=aa[3]?parseFloat(aa[3]):NaN;l=aa[4]?parseFloat(aa[4]):NaN;if(l){aa=/(?:Chrome\/(\d+\.\d+))/.exec(z);m=aa&&aa[1]?parseFloat(aa[1]):NaN;}else m=NaN;}else i=j=k=m=l=NaN;if(ba){if(ba[1]){var da=/(?:Mac OS X (\d+(?:[._]\d+)?))/.exec(z);o=da?parseFloat(da[1].replace('_','.')):true;}else o=false;p=!!ba[2];q=!!ba[3];}else o=p=q=false;}var y={ie:function(){return x()||i;},ieCompatibilityMode:function(){return x()||n>i;},ie64:function(){return y.ie()&&s;},firefox:function(){return x()||j;},opera:function(){return x()||k;},webkit:function(){return x()||l;},safari:function(){return y.webkit();},chrome:function(){return x()||m;},windows:function(){return x()||p;},osx:function(){return x()||o;},linux:function(){return x()||q;},iphone:function(){return x()||t;},mobile:function(){return x()||(t||u||r||w);},nativeApp:function(){return x()||v;},android:function(){return x()||r;},ipad:function(){return x()||u;}};f.exports=y;},null);
__d('htmlSpecialChars',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=/&/g,i=/</g,j=/>/g,k=/"/g,l=/'/g;function m(n){if(typeof n=='undefined'||n===null||!n.toString)return '';if(n===false){return '0';}else if(n===true)return '1';return n.toString().replace(h,'&').replace(k,'"').replace(l,''').replace(i,'<').replace(j,'>');}f.exports=m;},null);
__d('Flash',['DOMEventListener','DOMWrapper','QueryString','UserAgent_DEPRECATED','guid','htmlSpecialChars'],function a(b,c,d,e,f,g,h,i,j,k,l,m){if(c.__markCompiled)c.__markCompiled();var n={},o,p=i.getWindow().document;function q(v){var w=p.getElementById(v);if(w)w.parentNode.removeChild(w);delete n[v];}function r(){for(var v in n)if(n.hasOwnProperty(v))q(v);}function s(v){return v.replace(/\d+/g,function(w){return '000'.substring(w.length)+w;});}function t(v){if(!o){if(k.ie()>=9)h.add(window,'unload',r);o=true;}n[v]=v;}var u={embed:function(v,w,x,y){var z=l();v=m(v).replace(/&/g,'&');x=babelHelpers._extends({allowscriptaccess:'always',flashvars:y,movie:v},x);if(typeof x.flashvars=='object')x.flashvars=j.encode(x.flashvars);var aa=[];for(var ba in x)if(x.hasOwnProperty(ba)&&x[ba])aa.push('<param name="'+m(ba)+'" value="'+m(x[ba])+'">');var ca=w.appendChild(p.createElement('span')),da='<object '+(k.ie()?'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ':'type="application/x-shockwave-flash"')+'data="'+v+'" '+(x.height?'height="'+x.height+'" ':'')+(x.width?'width="'+x.width+'" ':'')+'id="'+z+'">'+aa.join('')+'</object>';ca.innerHTML=da;var ea=ca.firstChild;t(z);return ea;},remove:q,getVersion:function(){var v='Shockwave Flash',w='application/x-shockwave-flash',x='ShockwaveFlash.ShockwaveFlash',y;if(navigator.plugins&&typeof navigator.plugins[v]=='object'){var z=navigator.plugins[v].description;if(z&&navigator.mimeTypes&&navigator.mimeTypes[w]&&navigator.mimeTypes[w].enabledPlugin)y=z.match(/\d+/g);}if(!y)try{y=new ActiveXObject(x).GetVariable('$version').match(/(\d+),(\d+),(\d+),(\d+)/);y=Array.prototype.slice.call(y,1);}catch(aa){}return y;},getVersionString:function(){var v=u.getVersion();return v?v.join('.'):'';},checkMinVersion:function(v){var w=u.getVersion();if(!w)return false;return s(w.join('.'))>=s(v);},isAvailable:function(){return !!u.getVersion();}};f.exports=u;},null);
__d("emptyFunction",[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(j){return function(){return j;};}function i(){}i.thatReturns=h;i.thatReturnsFalse=h(false);i.thatReturnsTrue=h(true);i.thatReturnsNull=h(null);i.thatReturnsThis=function(){return this;};i.thatReturnsArgument=function(j){return j;};f.exports=i;},null);
__d('XDM',['DOMEventListener','DOMWrapper','emptyFunction','Flash','GlobalCallback','guid','Log','UserAgent_DEPRECATED','wrapFunction'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p){if(c.__markCompiled)c.__markCompiled();var q={},r={transports:[]},s=i.getWindow();function t(w){var x={},y=w.length,z=r.transports;while(y--)x[w[y]]=1;y=z.length;while(y--){var aa=z[y],ba=q[aa];if(!x[aa]&&ba.isAvailable())return aa;}}var u={register:function(w,x){n.debug('Registering %s as XDM provider',w);r.transports.push(w);q[w]=x;},create:function(w){if(!w.whenReady&&!w.onMessage){n.error('An instance without whenReady or onMessage makes no sense');throw new Error('An instance without whenReady or '+'onMessage makes no sense');}if(!w.channel){n.warn('Missing channel name, selecting at random');w.channel=m();}if(!w.whenReady)w.whenReady=j;if(!w.onMessage)w.onMessage=j;var x=w.transport||t(w.blacklist||[]),y=q[x];if(y&&y.isAvailable()){n.debug('%s is available',x);y.init(w);return x;}}};u.register('flash',(function(){var w=false,x,y=false,z=15000,aa;return {isAvailable:function(){return k.checkMinVersion('8.0.24');},init:function(ba){n.debug('init flash: '+ba.channel);var ca={send:function(fa,ga,ha,ia){n.debug('sending to: %s (%s)',ga,ia);x.postMessage(fa,ga,ia);}};if(w){ba.whenReady(ca);return;}var da=ba.root.appendChild(s.document.createElement('div')),ea=l.create(function(){l.remove(ea);clearTimeout(aa);n.info('xdm.swf called the callback');var fa=l.create(function(ga,ha){ga=decodeURIComponent(ga);ha=decodeURIComponent(ha);n.debug('received message %s from %s',ga,ha);ba.onMessage(ga,ha);},'xdm.swf:onMessage');x.init(ba.channel,fa);ba.whenReady(ca);},'xdm.swf:load');x=k.embed(ba.flashUrl,da,null,{protocol:location.protocol.replace(':',''),host:location.host,callback:ea,log:y});aa=setTimeout(function(){n.warn('The Flash component did not load within %s ms - '+'verify that the container is not set to hidden or invisible '+'using CSS as this will cause some browsers to not load '+'the components',z);},z);w=true;}};})());var v=/\.facebook\.com(\/|$)/;u.register('postmessage',(function(){var w=false;return {isAvailable:function(){return !!s.postMessage;},init:function(x){n.debug('init postMessage: '+x.channel);var y='_FB_'+x.channel,z={send:function(aa,ba,ca,da){if(s===ca){n.error('Invalid windowref, equal to window (self)');throw new Error();}n.debug('sending to: %s (%s)',ba,da);var ea=function(){ca.postMessage('_FB_'+da+aa,ba);};if(o.ie()==8||o.ieCompatibilityMode()){setTimeout(ea,0);}else ea();}};if(w){x.whenReady(z);return;}h.add(s,'message',p(function(event){var aa=event.data,ba=event.origin||'native';if(!/^(https?:\/\/|native$)/.test(ba)){n.debug('Received message from invalid origin type: %s',ba);return;}if(ba!=='native'&&!(v.test(location.hostname)||v.test(event.origin)))return;if(typeof aa!='string'){n.warn('Received message of type %s from %s, expected a string',typeof aa,ba);return;}n.debug('received message %s from %s',aa,ba);if(aa.substring(0,y.length)==y)aa=aa.substring(y.length);x.onMessage(aa,ba);},'entry','onMessage'));x.whenReady(z);w=true;}};})());f.exports=u;},null);
__d('isFacebookURI',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h=null,i=['http','https'];function j(k){if(!h)h=new RegExp('(^|\\.)facebook\\.com$','i');if(k.isEmpty()&&k.toString()!=='#')return false;if(!k.getDomain()&&!k.getProtocol())return true;return ES(i,'indexOf',true,k.getProtocol())!==-1&&h.test(k.getDomain());}j.setRegex=function(k){h=k;};f.exports=j;},null);
__d('sdk.Event',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={SUBSCRIBE:'event.subscribe',UNSUBSCRIBE:'event.unsubscribe',subscribers:function(){if(!this._subscribersMap)this._subscribersMap={};return this._subscribersMap;},subscribe:function(i,j){var k=this.subscribers();if(!k[i]){k[i]=[j];}else if(ES(k[i],'indexOf',true,j)==-1)k[i].push(j);if(i!=this.SUBSCRIBE&&i!=this.UNSUBSCRIBE)this.fire(this.SUBSCRIBE,i,k[i]);},unsubscribe:function(i,j){var k=this.subscribers()[i];if(k)ES(k,'forEach',true,function(l,m){if(l==j)k.splice(m,1);});if(i!=this.SUBSCRIBE&&i!=this.UNSUBSCRIBE)this.fire(this.UNSUBSCRIBE,i,k);},monitor:function(i,j){if(!j()){var k=this,l=function(){if(j.apply(j,arguments))k.unsubscribe(i,l);};this.subscribe(i,l);}},clear:function(i){delete this.subscribers()[i];},fire:function(i){var j=Array.prototype.slice.call(arguments,1),k=this.subscribers()[i];if(k)ES(k,'forEach',true,function(l){if(l)l.apply(this,j);});}};f.exports=h;},null);
__d('JSONRPC',['Log'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();function i(j){'use strict';this.$JSONRPC1=0;this.$JSONRPC2={};this.remote=ES(function(k){this.$JSONRPC3=k;return this.remote;},'bind',true,this);this.local={};this.$JSONRPC4=j;}i.prototype.stub=function(j){'use strict';this.remote[j]=ES(function(){var k={jsonrpc:'2.0',method:j};for(var l=arguments.length,m=Array(l),n=0;n<l;n++)m[n]=arguments[n];if(typeof m[m.length-1]=='function'){k.id=++this.$JSONRPC1;this.$JSONRPC2[k.id]=m.pop();}k.params=m;this.$JSONRPC4(ES('JSON','stringify',false,k),this.$JSONRPC3||{method:j});},'bind',true,this);};i.prototype.read=function(j,k){'use strict';var l=ES('JSON','parse',false,j),m=l.id;if(!l.method){if(!this.$JSONRPC2[m]){h.warn('Could not find callback %s',m);return;}var n=this.$JSONRPC2[m];delete this.$JSONRPC2[m];delete l.id;delete l.jsonrpc;n(l);return;}var o=this,p=this.local[l.method],q;if(m){q=function(t,u){var v={jsonrpc:'2.0',id:m};v[t]=u;setTimeout(function(){o.$JSONRPC4(ES('JSON','stringify',false,v),k);},0);};}else q=function(){};if(!p){h.error('Method "%s" has not been defined',l.method);q('error',{code:-32601,message:'Method not found',data:l.method});return;}l.params.push(ES(q,'bind',true,null,'result'));l.params.push(ES(q,'bind',true,null,'error'));try{var s=p.apply(k||null,l.params);if(typeof s!=='undefined')q('result',s);}catch(r){h.error('Invokation of RPC method %s resulted in the error: %s',l.method,r.message);q('error',{code:-32603,message:'Internal error',data:r.message});}};f.exports=i;},null);
__d('sdk.RPC',['Assert','JSONRPC','Queue'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();var k=new j(),l=new i(function(n){k.enqueue(n);}),m={local:l.local,remote:l.remote,stub:ES(l.stub,'bind',true,l),setInQueue:function(n){h.isInstanceOf(j,n);n.start(function(o){l.read(o);});},getOutQueue:function(){return k;}};f.exports=m;},null);
__d('sdk.Scribe',['QueryString','sdk.Runtime','UrlMap'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();function k(m,n){if(typeof n.extra=='object')n.extra.revision=i.getRevision();new Image().src=h.appendToUrl(j.resolve('www',true)+'/common/scribe_endpoint.php',{c:m,m:ES('JSON','stringify',false,n)});}var l={log:k};f.exports=l;},null);
__d('hasNamePropertyBug',['guid','UserAgent_DEPRECATED'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();var j=i.ie()?undefined:false;function k(){var m=document.createElement("form"),n=m.appendChild(document.createElement("input"));n.name=h();j=n!==m.elements[n.name];m=n=null;return j;}function l(){return typeof j==='undefined'?k():j;}f.exports=l;},null);
__d('sdk.createIframe',['DOMEventListener','getBlankIframeSrc','guid','hasNamePropertyBug'],function a(b,c,d,e,f,g,h,i,j,k){if(c.__markCompiled)c.__markCompiled();function l(m){m=ES('Object','assign',false,{},m);var n,o=m.name||j(),p=m.root,q=m.style||{border:'none'},r=m.url,s=m.onload,t=m.onerror;if(k()){n=document.createElement('<iframe name="'+o+'"/>');}else{n=document.createElement("iframe");n.name=o;}delete m.style;delete m.name;delete m.url;delete m.root;delete m.onload;delete m.onerror;var u=ES('Object','assign',false,{frameBorder:0,allowTransparency:true,allowFullscreen:true,scrolling:'no'},m);if(u.width)n.width=u.width+'px';if(u.height)n.height=u.height+'px';delete u.height;delete u.width;for(var v in u)if(u.hasOwnProperty(v))n.setAttribute(v,u[v]);ES('Object','assign',false,n.style,q);n.src=i();p.appendChild(n);if(s)var w=h.add(n,'load',function(){w.remove();s();});if(t)var x=h.add(n,'error',function(){x.remove();t();});n.src=r;return n;}f.exports=l;},null);
__d('sdk.feature',['JSSDKConfig','invariant'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();function j(k,l){!(arguments.length>=2)?i(0):undefined;if(h.features&&k in h.features){var m=h.features[k];if(typeof m==='object'&&typeof m.rate==='number'){if(m.rate&&Math.random()*100<=m.rate){return m.value||true;}else return m.value?null:false;}else return m;}return l;}f.exports=j;},null);
__d('sdk.XD',['sdk.Content','sdk.Event','Log','QueryString','Queue','sdk.RPC','sdk.Runtime','sdk.Scribe','sdk.URI','UrlMap','JSSDKXDConfig','XDM','isFacebookURI','sdk.createIframe','sdk.feature','guid'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w){if(c.__markCompiled)c.__markCompiled();var x=new l(),y=new l(),z=new l(),aa,ba,ca=w(),da=r.useCdn?'cdn':'www',ea=v('use_bundle',false)?r.XdBundleUrl:r.XdUrl,fa=q.resolve(da,false)+ea,ga=q.resolve(da,true)+ea,ha=w(),ia=location.protocol+'//'+location.host,ja,ka=false,la='Facebook Cross Domain Communication Frame',ma={},na=new l();m.setInQueue(na);function oa(ua){j.info('Remote XD can talk to facebook.com (%s)',ua);n.setEnvironment(ua==='canvas'?n.ENVIRONMENTS.CANVAS:n.ENVIRONMENTS.PAGETAB);}function pa(ua,va){if(!va){j.error('No senderOrigin');throw new Error();}var wa=/^https?/.exec(va)[0];switch(ua.xd_action){case 'proxy_ready':var xa,ya;if(wa=='https'){xa=z;ya=ba;n.setLoggedIntoFacebook(ua.logged_in==='true');}else{xa=y;ya=aa;}if(ua.registered){oa(ua.registered);x=xa.merge(x);}j.info('Proxy ready, starting queue %s containing %s messages',wa+'ProxyQueue',xa.getLength());xa.start(function(ab){ja.send(typeof ab==='string'?ab:k.encode(ab),va,ya.contentWindow,ha+'_'+wa);});break;case 'plugin_ready':j.info('Plugin %s ready, protocol: %s',ua.name,wa);ma[ua.name]={protocol:wa};if(l.exists(ua.name)){var za=l.get(ua.name);j.debug('Enqueuing %s messages for %s in %s',za.getLength(),ua.name,wa+'ProxyQueue');(wa=='https'?z:y).merge(za);}break;}if(ua.data)qa(ua.data,va);}function qa(ua,va){if(va&&va!=='native'&&!t(new p(va)))return;if(typeof ua=='string'){if(/^FB_RPC:/.test(ua)){na.enqueue(ua.substring(7));return;}if(ua.substring(0,1)=='{'){try{ua=ES('JSON','parse',false,ua);}catch(wa){j.warn('Failed to decode %s as JSON',ua);return;}}else ua=k.decode(ua);}if(!va)if(ua.xd_sig==ca)va=ua.xd_origin;if(ua.xd_action){pa(ua,va);return;}if(ua.access_token)n.setSecure(/^https/.test(ia));if(ua.cb){var xa=ta._callbacks[ua.cb];if(!ta._forever[ua.cb])delete ta._callbacks[ua.cb];if(xa)xa(ua);}}function ra(ua,va){if(ua=='facebook'){va.relation='parent.parent';x.enqueue(va);}else{va.relation='parent.frames["'+ua+'"]';var wa=ma[ua];if(wa){j.debug('Enqueuing message for plugin %s in %s',ua,wa.protocol+'ProxyQueue');(wa.protocol=='https'?z:y).enqueue(va);}else{j.debug('Buffering message for plugin %s',ua);l.get(ua).enqueue(va);}}}m.getOutQueue().start(function(ua){ra('facebook','FB_RPC:'+ua);});function sa(ua){if(ka)return;var va=h.appendHidden(document.createElement('div')),wa=s.create({blacklist:null,root:va,channel:ha,flashUrl:r.Flash.path,whenReady:function(xa){ja=xa;var ya={channel:ha,origin:location.protocol+'//'+location.host,transport:wa,xd_name:ua},za='#'+k.encode(ya);if(n.getSecure()!==true)aa=u({url:fa+za,name:'fb_xdm_frame_http',id:'fb_xdm_frame_http',root:va,'aria-hidden':true,title:la,tabindex:-1});ba=u({url:ga+za,name:'fb_xdm_frame_https',id:'fb_xdm_frame_https',root:va,'aria-hidden':true,title:la,tabindex:-1});},onMessage:qa});if(!wa)o.log('jssdk_error',{appId:n.getClientID(),error:'XD_TRANSPORT',extra:{message:'Failed to create a valid transport'}});ka=true;}var ta={rpc:m,_callbacks:{},_forever:{},_channel:ha,_origin:ia,onMessage:qa,recv:qa,init:sa,sendToFacebook:ra,inform:function(ua,va,wa,xa){ra('facebook',{method:ua,params:ES('JSON','stringify',false,va||{}),behavior:xa||'p',relation:wa});},handler:function(ua,va,wa,xa){var ya='#'+k.encode({cb:this.registerCallback(ua,wa,xa),origin:ia+'/'+ha,domain:location.hostname,relation:va||'opener'});return (location.protocol=='https:'?ga:fa)+ya;},registerCallback:function(ua,va,wa){wa=wa||w();if(va)ta._forever[wa]=true;ta._callbacks[wa]=ua;return wa;}};i.subscribe('init:post',function(ua){sa(ua.xdProxyName);var va=v('xd_timeout',false);if(va)setTimeout(function(){var wa=ba&&(!!aa==y.isStarted()&&!!ba==z.isStarted());if(!wa)o.log('jssdk_error',{appId:n.getClientID(),error:'XD_INITIALIZATION',extra:{message:'Failed to initialize in '+va+'ms'}});},va);});f.exports=ta;},null);
__d('sdk.getContextType',['sdk.Runtime','sdk.UA'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();function j(){if(i.nativeApp())return 3;if(i.mobile())return 2;if(h.isEnvironment(h.ENVIRONMENTS.CANVAS))return 5;return 1;}f.exports=j;},null);
__d('sdk.Auth',['sdk.Cookie','sdk.createIframe','DOMWrapper','sdk.feature','sdk.getContextType','guid','sdk.Impressions','Log','ObservableMixin','sdk.Runtime','sdk.SignedRequest','UrlMap','sdk.URI','sdk.XD'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u){if(c.__markCompiled)c.__markCompiled();var v='fblo_',w=365*24*60*60*1000,x,y,z=new p();function aa(ga,ha){var ia=q.getUserID(),ja='';if(ga)if(ga.userID){ja=ga.userID;}else if(ga.signedRequest){var ka=r.parse(ga.signedRequest);if(ka&&ka.user_id)ja=ka.user_id;}var la=q.getLoginStatus(),ma=la==='unknown'&&ga||q.getUseCookie()&&q.getCookieUserID()!==ja,na=ia&&!ga,oa=ga&&ia&&ia!=ja,pa=ga!=x,qa=ha!=(la||'unknown');q.setLoginStatus(ha);q.setAccessToken(ga&&ga.accessToken||null);q.setUserID(ja);x=ga;var ra={authResponse:ga,status:ha};if(na||oa)z.inform('logout',ra);if(ma||oa)z.inform('login',ra);if(pa)z.inform('authresponse.change',ra);if(qa)z.inform('status.change',ra);return ra;}function ba(){return x;}function ca(ga,ha,ia){return function(ja){var ka;if(ja&&ja.access_token){var la=r.parse(ja.signed_request);ha={accessToken:ja.access_token,userID:la.user_id,expiresIn:parseInt(ja.expires_in,10),signedRequest:ja.signed_request};if(ja.granted_scopes)ha.grantedScopes=ja.granted_scopes;if(q.getUseCookie()){var ma=ha.expiresIn===0?0:ES('Date','now',false)+ha.expiresIn*1000,na=h.getDomain();if(!na&&ja.base_domain)h.setDomain('.'+ja.base_domain);h.setSignedRequestCookie(ja.signed_request,ma);h.setRaw(v,'',0);}ka='connected';aa(ha,ka);}else if(ia==='logout'||ia==='login_status'){if(ja.error&&ja.error==='not_authorized'){ka='not_authorized';}else ka='unknown';aa(null,ka);if(q.getUseCookie())h.clearSignedRequestCookie();if(ia==='logout')h.setRaw(v,'y',ES('Date','now',false)+w);}if(ja&&ja.https==1)q.setSecure(true);if(ga)ga({authResponse:ha,status:q.getLoginStatus()});return ha;};}function da(ga){var ha,ia=ES('Date','now',false);if(y){clearTimeout(y);y=null;}if(h.getRaw(v)==='y'){var ja='unknown';aa(null,ja);if(ga)ga({authResponse:null,status:ja});return;}var ka=ca(ga,x,'login_status'),la=new t(s.resolve('www',true)+'/connect/ping').setQueryData({client_id:q.getClientID(),response_type:'token,signed_request,code',domain:location.hostname,origin:l(),redirect_uri:u.handler(function(ma){if(k('e2e_ping_tracking',true)){var na={init:ia,close:ES('Date','now',false),method:'ping'};o.debug('e2e: %s',ES('JSON','stringify',false,na));n.log(114,{payload:na});}ha.parentNode.removeChild(ha);if(ka(ma))y=setTimeout(function(){da(function(){});},1200000);},'parent'),sdk:'joey',kid_directed_site:q.getKidDirectedSite()});ha=i({root:j.getRoot(),name:m(),url:la.toString(),style:{display:'none'}});}var ea;function fa(ga,ha){if(!q.getClientID()){o.warn('FB.getLoginStatus() called before calling FB.init().');return;}if(ga)if(!ha&&ea=='loaded'){ga({status:q.getLoginStatus(),authResponse:ba()});return;}else z.subscribe('FB.loginStatus',ga);if(!ha&&ea=='loading')return;ea='loading';var ia=function(ja){ea='loaded';z.inform('FB.loginStatus',ja);z.clearSubscribers('FB.loginStatus');};da(ia);}ES('Object','assign',false,z,{getLoginStatus:fa,fetchLoginStatus:da,setAuthResponse:aa,getAuthResponse:ba,parseSignedRequest:r.parse,xdResponseWrapper:ca});f.exports=z;},null);
__d('sdk.DOM',['Assert','sdk.UA','sdk.domReady'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();var k={};function l(z,aa){var ba=z.getAttribute(aa)||z.getAttribute(aa.replace(/_/g,'-'))||z.getAttribute(aa.replace(/-/g,'_'))||z.getAttribute(aa.replace(/-/g,''))||z.getAttribute(aa.replace(/_/g,''))||z.getAttribute('data-'+aa)||z.getAttribute('data-'+aa.replace(/_/g,'-'))||z.getAttribute('data-'+aa.replace(/-/g,'_'))||z.getAttribute('data-'+aa.replace(/-/g,''))||z.getAttribute('data-'+aa.replace(/_/g,''));return ba?String(ba):null;}function m(z,aa){var ba=l(z,aa);return ba?/^(true|1|yes|on)$/.test(ba):null;}function n(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);try{return String(z[aa]);}catch(ba){throw new Error('Could not read property '+aa+' : '+ba.message);}}function o(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);try{z.innerHTML=aa;}catch(ba){throw new Error('Could not set innerHTML : '+ba.message);}}function p(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);var ba=' '+n(z,'className')+' ';return ES(ba,'indexOf',true,' '+aa+' ')>=0;}function q(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);if(!p(z,aa))z.className=n(z,'className')+' '+aa;}function r(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);var ba=new RegExp('\\s*'+aa,'g');z.className=ES(n(z,'className').replace(ba,''),'trim',true);}function s(z,aa,ba){h.isString(z);aa=aa||document.body;ba=ba||'*';if(aa.querySelectorAll)return ES('Array','from',false,aa.querySelectorAll(ba+'.'+z));var ca=aa.getElementsByTagName(ba),da=[];for(var ea=0,fa=ca.length;ea<fa;ea++)if(p(ca[ea],z))da[da.length]=ca[ea];return da;}function t(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);aa=aa.replace(/-(\w)/g,function(da,ea){return ea.toUpperCase();});var ba=z.currentStyle||document.defaultView.getComputedStyle(z,null),ca=ba[aa];if(/backgroundPosition?/.test(aa)&&/top|left/.test(ca))ca='0%';return ca;}function u(z,aa,ba){h.isTruthy(z,'element not specified');h.isString(aa);aa=aa.replace(/-(\w)/g,function(ca,da){return da.toUpperCase();});z.style[aa]=ba;}function v(z,aa){var ba=true;for(var ca=0,da;da=aa[ca++];)if(!(da in k)){ba=false;k[da]=true;}if(ba)return;if(i.ie()<11){try{document.createStyleSheet().cssText=z;}catch(ea){if(document.styleSheets[0])document.styleSheets[0].cssText+=z;}}else{var fa=document.createElement('style');fa.type='text/css';fa.textContent=z;document.getElementsByTagName('head')[0].appendChild(fa);}}function w(){var z=document.documentElement&&document.compatMode=='CSS1Compat'?document.documentElement:document.body;return {scrollTop:z.scrollTop||document.body.scrollTop,scrollLeft:z.scrollLeft||document.body.scrollLeft,width:window.innerWidth?window.innerWidth:z.clientWidth,height:window.innerHeight?window.innerHeight:z.clientHeight};}function x(z){h.isTruthy(z,'element not specified');var aa=0,ba=0;do{aa+=z.offsetLeft;ba+=z.offsetTop;}while(z=z.offsetParent);return {x:aa,y:ba};}var y={containsCss:p,addCss:q,removeCss:r,getByClass:s,getStyle:t,setStyle:u,getAttr:l,getBoolAttr:m,getProp:n,html:o,addCssRules:v,getViewportInfo:w,getPosition:x,ready:j};f.exports=y;},null);
__d('sdk.ErrorHandling',['ManagedError','sdk.Runtime','sdk.Scribe','sdk.UA','sdk.feature','wrapFunction'],function a(b,c,d,e,f,g,h,i,j,k,l,m){if(c.__markCompiled)c.__markCompiled();var n=l('error_handling',false),o='';function p(v){var w=v._originalError;delete v._originalError;j.log('jssdk_error',{appId:i.getClientID(),error:v.name||v.message,extra:v});throw w;}function q(v){var w={line:v.lineNumber||v.line,message:v.message,name:v.name,script:v.fileName||v.sourceURL||v.script,stack:v.stackTrace||v.stack};w._originalError=v;if(k.chrome()&&/([\w:\.\/]+\.js):(\d+)/.test(v.stack)){w.script=RegExp.$1;w.line=parseInt(RegExp.$2,10);}for(var x in w)w[x]==null&&delete w[x];return w;}function r(v,w){return function(){if(!n)return v.apply(this,arguments);try{o=w;return v.apply(this,arguments);}catch(x){if(x instanceof h)throw x;var y=q(x);y.entry=w;var z=ES(Array.prototype.slice.call(arguments),'map',true,function(aa){var ba=Object.prototype.toString.call(aa);return (/^\[object (String|Number|Boolean|Object|Date)\]$/.test(ba)?aa:aa.toString());});y.args=ES('JSON','stringify',false,z).substring(0,200);p(y);}finally{o='';}};}function s(v){if(!v.__wrapper)v.__wrapper=function(){try{return v.apply(this,arguments);}catch(w){window.setTimeout(function(){throw w;},0);return false;}};return v.__wrapper;}function t(v,w){return function(x,y){var z=w+':'+(o||'[global]')+':'+(x.name||'[anonymous]'+(arguments.callee.caller.name?'('+arguments.callee.caller.name+')':''));return v(m(x,'entry',z),y);};}if(n){setTimeout=t(setTimeout,'setTimeout');setInterval=t(setInterval,'setInterval');m.setWrapper(r,'entry');}var u={guard:r,unguard:s};f.exports=u;},null);
__d('sdk.Insights',['sdk.Impressions'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();var i={TYPE:{NOTICE:'notice',WARNING:'warn',ERROR:'error'},CATEGORY:{DEPRECATED:'deprecated',APIERROR:'apierror'},log:function(j,k,l){var m={source:'jssdk',type:j,category:k,payload:l};h.log(113,m);},impression:h.impression};f.exports=i;},null);
__d('FB',['sdk.Auth','JSSDKCssConfig','dotAccess','sdk.domReady','sdk.DOM','sdk.ErrorHandling','sdk.Content','DOMWrapper','GlobalCallback','sdk.Insights','Log','sdk.Runtime','sdk.Scribe','JSSDKConfig'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u){if(c.__markCompiled)c.__markCompiled();var v,w,x=j(u,'api.mode'),y={};v=window.FB={};var z={};r.level=0;p.setPrefix('FB.__globalCallbacks');var aa=document.createElement('div');o.setRoot(aa);k(function(){r.info('domReady');n.appendHidden(aa);if(i.rules)l.addCssRules(i.rules,i.components);});s.subscribe('AccessToken.change',function(da){if(!da&&s.getLoginStatus()==='connected')h.getLoginStatus(null,true);});if(j(u,'api.whitelist.length')){w={};ES(u.api.whitelist,'forEach',true,function(da){w[da]=1;});}function ba(da,ea,fa,ga){var ha;if(/^_/.test(fa)){ha='hide';}else if(w&&!w[ea])ha=x;switch(ha){case 'hide':return;case 'stub':return function(){r.warn('The method FB.%s has been removed from the JS SDK.',ea);};default:return m.guard(function(){if(ha==='warn'){r.warn('The method FB.%s is not officially supported by '+'Facebook and access to it will soon be removed.',ea);if(!y.hasOwnProperty(ea)){q.log(q.TYPE.WARNING,q.CATEGORY.DEPRECATED,'FB.'+ea);t.log('jssdk_error',{appId:s.getClientID(),error:'Private method used',extra:{args:ea}});y[ea]=true;}}function ia(pa){if(ES('Array','isArray',false,pa))return ES(pa,'map',true,ia);if(pa&&typeof pa==='object'&&pa.__wrapped)return pa.__wrapped;return typeof pa==='function'&&/^function/.test(pa.toString())?m.unguard(pa):pa;}var ja=ES(Array.prototype.slice.call(arguments),'map',true,ia),ka=da.apply(ga,ja),la,ma=true;if(ka&&typeof ka==='object'){la=ES('Object','create',false,ka);la.__wrapped=ka;for(var na in ka){var oa=ka[na];if(typeof oa!=='function'||na==='constructor')continue;ma=false;la[na]=ba(oa,ea+':'+na,na,ka);}}if(!ma)return la;return ma?ka:la;},ea);}}function ca(da,ea){var fa=da?j(v,da,true):v;ES(ES('Object','keys',false,ea),'forEach',true,function(ga){var ha=ea[ga];if(typeof ha==='function'){var ia=(da?da+'.':'')+ga,ja=ba(ha,ia,ga,ea);if(ja)fa[ga]=ja;}else if(typeof ha==='object'){ia=(da?da+'.':'')+ga;if(w&&w[ia])fa[ga]=ha;}});}s.setSecure((function(){var da=/iframe_canvas|app_runner/.test(window.name),ea=/dialog/.test(window.name);if(location.protocol=='https:'&&(window==top||!(da||ea)))return true;if(/_fb_https?/.test(window.name))return ES(window.name,'indexOf',true,'_fb_https')!=-1;})());ES('Object','assign',false,z,{provide:ca});f.exports=z;},null);
__d('ArgumentError',['ManagedError'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();function i(j,k){h.prototype.constructor.apply(this,arguments);}i.prototype=new h();i.prototype.constructor=i;f.exports=i;},null);
__d('CORSRequest',['wrapFunction','QueryString'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();function j(m,n){if(!self.XMLHttpRequest)return null;var o=new XMLHttpRequest(),p=function(){};if('withCredentials' in o){o.open(m,n,true);o.setRequestHeader('Content-type','application/x-www-form-urlencoded');}else if(self.XDomainRequest){o=new XDomainRequest();try{o.open(m,n);o.onprogress=o.ontimeout=p;}catch(q){return null;}}else return null;var r={send:function(u){o.send(u);}},s=h(function(){s=p;if('onload' in r)r.onload(o);},'entry','XMLHttpRequest:load'),t=h(function(){t=p;if('onerror' in r)r.onerror(o);},'entry','XMLHttpRequest:error');o.onload=function(){s();};o.onerror=function(){t();};o.onreadystatechange=function(){if(o.readyState==4)if(o.status==200){s();}else t();};return r;}function k(m,n,o,p){o.suppress_http_code=1;var q=i.encode(o);if(n!='post'){m=i.appendToUrl(m,q);q='';}var r=j(n,m);if(!r)return false;r.onload=function(s){p(ES('JSON','parse',false,s.responseText));};r.onerror=function(s){if(s.responseText){p(ES('JSON','parse',false,s.responseText));}else p({error:{type:'http',message:'unknown error',status:s.status}});};r.send(q);return true;}var l={execute:k};f.exports=l;},null);
__d('FlashRequest',['DOMWrapper','Flash','GlobalCallback','QueryString','Queue'],function a(b,c,d,e,f,g,h,i,j,k,l){if(c.__markCompiled)c.__markCompiled();var m,n={},o,p;function q(){if(!o)throw new Error('swfUrl has not been set');var t=j.create(function(){m.start(function(v){var w=p.execute(v.method,v.url,v.body);if(!w)throw new Error('Could create request');n[w]=v.callback;});}),u=j.create(function(v,w,x){var y;try{y=ES('JSON','parse',false,decodeURIComponent(x));}catch(z){y={error:{type:'SyntaxError',message:z.message,status:w,raw:x}};}n[v](y);delete n[v];});p=i.embed(o,h.getRoot(),null,{log:false,initCallback:t,requestCallback:u});}function r(t,u,v,w){v.suppress_http_code=1;if(!v.method)v.method=u;var x=k.encode(v);if(u==='get'&&t.length+x.length<2000){t=k.appendToUrl(t,x);x='';}else u='post';if(!m){if(!i.isAvailable())return false;m=new l();q();}m.enqueue({method:u,url:t,body:x,callback:w});return true;}var s={setSwfUrl:function(t){o=t;},execute:r};f.exports=s;},null);
__d('JSONPRequest',['DOMWrapper','GlobalCallback','QueryString'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();var k=2000;function l(n,o,p,q){var r=document.createElement('script'),s=function(u){s=function(){};i.remove(p.callback);q(u);r.parentNode.removeChild(r);};p.callback=i.create(s);if(!p.method)p.method=o;n=j.appendToUrl(n,p);if(n.length>k){i.remove(p.callback);return false;}r.onerror=function(){s({error:{type:'http',message:'unknown error'}});};var t=function(){setTimeout(function(){s({error:{type:'http',message:'unknown error'}});},0);};if(r.addEventListener){r.addEventListener('load',t,false);}else r.onreadystatechange=function(){if(/loaded|complete/.test(this.readyState))t();};r.src=n;h.getRoot().appendChild(r);return true;}var m={execute:l,MAX_QUERYSTRING_LENGTH:k};f.exports=m;},null);
__d('flattenObject',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(i){var j={};for(var k in i)if(i.hasOwnProperty(k)){var l=i[k];if(null===l||undefined===l){}else if(typeof l=='string'){j[k]=l;}else j[k]=ES('JSON','stringify',false,l);}return j;}f.exports=h;},null);
__d('ApiClient',['ArgumentError','Assert','CORSRequest','FlashRequest','flattenObject','JSONPRequest','Log','ObservableMixin','QueryString','sprintf','sdk.URI','UrlMap','ApiClientConfig','invariant'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u){if(c.__markCompiled)c.__markCompiled();var v,w,x,y=m.MAX_QUERYSTRING_LENGTH,z={get:true,post:true,'delete':true,put:true},aa={fql_query:true,fql_multiquery:true,friends_get:true,notifications_get:true,stream_get:true,users_getinfo:true},ba=['jsonp','cors','flash'],ca=[],da=[],ea=null,fa=0,ga=[],ha=0,ia=50,ja=105440539523;function ka(ua,va,wa,xa){var ya=ha!==0&&fa>=ha;if(ya){ga.push(function(){return ka(ua,va,wa,xa);});sa.inform('request.queued',ua,va,wa);return;}fa++;if(x)wa=ES('Object','assign',false,{},x,wa);wa.access_token=wa.access_token||v;wa.pretty=wa.pretty||0;wa=l(wa);var za={jsonp:m,cors:j,flash:k},ab;if(wa.transport){ab=[wa.transport];delete wa.transport;}else ab=ba;for(var bb=0;bb<ab.length;bb++){var cb=za[ab[bb]],db=ES('Object','assign',false,{},wa);if(cb.execute(ua,va,db,xa))return;}xa({error:{type:'no-transport',message:'Could not find a usable transport for request'}});}function la(ua,va,wa,xa,ya,za){if(za&&za.error)sa.inform('request.error',va,wa,xa,za,ES('Date','now',false)-ya);sa.inform('request.complete',va,wa,xa,za,ES('Date','now',false)-ya);fa--;if(ua)ua(za);var ab=ga.length>0&&fa<ha;if(ab){var bb=ga.shift();bb();}}function ma(ua){var va=ua.shift();i.isString(va,'Invalid path');if(!/^https?/.test(va)&&va.charAt(0)!=='/')va='/'+va;var wa,xa={};try{wa=new r(va);}catch(ya){throw new h(ya.message,ya);}ES(ua,'forEach',true,function(cb){return xa[typeof cb]=cb;});var za=(xa.string||'get').toLowerCase();i.isTrue(z.hasOwnProperty(za),q('Invalid method passed to ApiClient: %s',za));var ab=xa['function'];if(!ab)n.warn('No callback passed to the ApiClient');if(xa.object)wa.addQueryData(l(xa.object));var bb=wa.getQueryData();bb.method=za;return {uri:wa,callback:ab,params:bb};}function na(){for(var ua=arguments.length,va=Array(ua),wa=0;wa<ua;wa++)va[wa]=arguments[wa];var xa=ma(va),ya=xa.uri,za=xa.callback,ab=xa.params,bb=ab.method;if(ta(ya,bb))bb='post';var cb=ya.getProtocol()&&ya.getDomain()?ya.setQueryData({}).toString():s.resolve('graph')+ya.getPath();sa.inform('request.prepare',cb,ab);ka(cb,bb=='get'?'get':'post',ab,ES(la,'bind',true,null,za,ya.getPath(),bb,ab,ES('Date','now',false)));}function oa(ua){var va=ma(ua),wa=va.uri,xa=va.callback,ya=va.params.method,za,ab=wa.removeQueryData('method').toString();if(ya.toLowerCase()=='post'){za=p.encode(wa.getQueryData());ab=wa.setQueryData({}).toString();}return {body:za,callback:xa,method:ya,relative_url:ab};}function pa(){for(var ua=arguments.length,va=Array(ua),wa=0;wa<ua;wa++)va[wa]=arguments[wa];var xa=oa(va),ya=xa.body,za=xa.callback,ab=xa.method,bb=xa.relative_url,cb={method:ab,relative_url:bb};if(ya)cb.body=ya;ca.push(cb);da.push(za);if(ca.length==ia){if(ea)clearTimeout(ea);qa();}else if(!ea)ea=setTimeout(qa,0);}function qa(){!(ca.length>0)?u(0):undefined;!(ca.length===da.length)?u(0):undefined;var ua=ca,va=da;ca=[];da=[];ea=null;if(ua.length===1){var wa=ua[0],xa=va[0],ya=wa.body?p.decode(wa.body):null;na(wa.relative_url,wa.method,ya,xa);return;}na('/','POST',{batch:ua,include_headers:false,batch_app_id:w||ja},function(za){if(ES('Array','isArray',false,za)){ES(za,'forEach',true,function(ab,bb){va[bb](ES('JSON','parse',false,ab.body));});}else ES(va,'forEach',true,function(ab){return (ab({error:{message:'Fatal: batch call failed.'}}));});});}function ra(ua,va){i.isObject(ua);i.isString(ua.method,'method missing');if(!va)n.warn('No callback passed to the ApiClient');var wa=ua.method.toLowerCase().replace('.','_');ua.format='json-strings';ua.api_key=w;var xa=wa in aa?'api_read':'api',ya=s.resolve(xa)+'/restserver.php',za=ES(la,'bind',true,null,va,'/restserver.php','get',ua,ES('Date','now',false));ka(ya,'get',ua,za);}var sa=ES('Object','assign',false,new o(),{setAccessToken:function(ua){v=ua;},setAccessTokenForClientID:function(ua,va){if(!(v&&w&&w!==va))v=ua;},getAccessToken:function(){return v;},setClientID:function(ua){w=ua;},setDefaultParams:function(ua){x=ua;},setDefaultTransports:function(ua){ba=ua;},setMaxConcurrentRequests:function(ua){ha=ua;},getCurrentlyExecutingRequestCount:function(){return fa;},getQueuedRequestCount:function(){return ga.length;},rest:ra,graph:na,scheduleBatchCall:pa,prepareBatchParams:oa});function ta(ua,va){return ua.toString().length>y&&va==='get';}k.setSwfUrl(t.FlashRequest.swfUrl);f.exports=sa;},null);
__d('sdk.PlatformVersioning',['sdk.Runtime','ManagedError'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();var j=/^v\d+\.\d\d?$/,k={REGEX:j,assertVersionIsSet:function(){if(!h.getVersion())throw new i('init not called with valid version');},assertValidVersion:function(l){if(!j.test(l))throw new i('invalid version specified');}};f.exports=k;},null);
__d('sdk.api',['ApiClient','sdk.PlatformVersioning','sdk.Runtime','sdk.Scribe','sdk.URI','sdk.feature'],function a(b,c,d,e,f,g,h,i,j,k,l,m){if(c.__markCompiled)c.__markCompiled();var n=m('should_log_response_error',false),o;j.subscribe('ClientID.change',function(q){return h.setClientID(q);});j.subscribe('AccessToken.change',function(q){o=q;h.setAccessToken(q);});h.setDefaultParams({sdk:'joey'});h.subscribe('request.complete',function(q,r,s,t){var u=false;if(t&&typeof t=='object')if(t.error){if(t.error=='invalid_token'||t.error.type=='OAuthException'&&t.error.code==190)u=true;}else if(t.error_code)if(t.error_code=='190')u=true;if(u&&o===j.getAccessToken())j.setAccessToken(null);});h.subscribe('request.complete',function(q,r,s,t){if((q=='/me/permissions'&&r==='delete'||q=='/restserver.php'&&s.method=='Auth.revokeAuthorization')&&t===true)j.setAccessToken(null);});h.subscribe('request.error',function(q,r,s,t){if(n&&t.error.type==='http')k.log('jssdk_error',{appId:j.getClientID(),error:'transport',extra:{name:'transport',message:ES('JSON','stringify',false,t.error)}});});function p(q){if(typeof q==='string'){if(j.getIsVersioned()){i.assertVersionIsSet();if(!/https?/.test(q)&&q.charAt(0)!=='/')q='/'+q;q=new l(q).setDomain(null).setProtocol(null).toString();if(!i.REGEX.test(q.substring(1,ES(q,'indexOf',true,'/',1))))q='/'+j.getVersion()+q;var r=[q].concat(Array.prototype.slice.call(arguments,1));h.graph.apply(h,r);}else h.graph.apply(h,arguments);}else h.rest.apply(h,arguments);}f.exports=p;},null);
__d('legacy:fb.api',['FB','sdk.api'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();h.provide('',{api:i});},3);
__d('sdk.AppEvents',['Assert','sdk.Impressions','sdk.Runtime'],function a(b,c,d,e,f,g,h,i,j){if(c.__markCompiled)c.__markCompiled();var k={COMPLETED_REGISTRATION:'fb_mobile_complete_registration',VIEWED_CONTENT:'fb_mobile_content_view',SEARCHED:'fb_mobile_search',RATED:'fb_mobile_rate',COMPLETED_TUTORIAL:'fb_mobile_tutorial_completion',ADDED_TO_CART:'fb_mobile_add_to_cart',ADDED_TO_WISHLIST:'fb_mobile_add_to_wishlist',INITIATED_CHECKOUT:'fb_mobile_initiated_checkout',ADDED_PAYMENT_INFO:'fb_mobile_add_payment_info',ACHIEVED_LEVEL:'fb_mobile_level_achieved',UNLOCKED_ACHIEVEMENT:'fb_mobile_achievement_unlocked',SPENT_CREDITS:'fb_mobile_spent_credits'},l={ACTIVATED_APP:'fb_mobile_activate_app',PURCHASED:'fb_mobile_purchase'},m={CURRENCY:'fb_currency',REGISTRATION_METHOD:'fb_registration_method',CONTENT_TYPE:'fb_content_type',CONTENT_ID:'fb_content_id',SEARCH_STRING:'fb_search_string',SUCCESS:'fb_success',MAX_RATING_VALUE:'fb_max_rating_value',PAYMENT_INFO_AVAILABLE:'fb_payment_info_available',NUM_ITEMS:'fb_num_items',LEVEL:'fb_level',DESCRIPTION:'fb_description'},n=40,o='^[0-9a-zA-Z_]+[0-9a-zA-Z _-]*$';function p(t,u,v,w){h.isTrue(q(u),'Invalid event name: '+u+'. '+'It must be between 1 and '+n+' characters, '+'and must be contain only alphanumerics, _, - or spaces, '+'starting with alphanumeric or _.');var x={ae:1,ev:u,vts:v,canvas:j.isCanvasEnvironment()?1:0};if(w)x.cd=w;i.impression({api_key:t,payload:ES('JSON','stringify',false,x)});}function q(t){if(t===null||t.length===0||t.length>n||!new RegExp(o).test(t))return false;return true;}function r(t,u,v,w){var x={};x[m.CURRENCY]=v;p(t,l.PURCHASED,u,babelHelpers._extends({},w,x));}function s(t){p(t,l.ACTIVATED_APP);}f.exports={activateApp:s,logEvent:p,logPurchase:r,isValidEventName:q,EventNames:k,ParameterNames:m};},null);
__d('legacy:fb.appevents',['Assert','sdk.AppEvents','FB','sdk.feature','sdk.Runtime'],function a(b,c,d,e,f,g,h,i,j,k,l){if(c.__markCompiled)c.__markCompiled();j.provide('AppEvents',{logEvent:function(m,n,o){h.isTrue(k('allow_non_canvas_app_events',false)||l.isCanvasEnvironment(),'You can only use this function in Facebook Canvas environment');h.isString(m,'Invalid eventName');h.maybeNumber(n,'Invalid valueToSum');h.maybeObject(o,'Invalid params');var p=l.getClientID();h.isTrue(p!==null&&p.length>0,'You need to call FB.init() with App ID first.');i.logEvent(p,m,n,o);},logPurchase:function(m,n,o){h.isTrue(k('allow_non_canvas_app_events',false)||l.isCanvasEnvironment(),'You can only use this function in Facebook Canvas environment');h.isNumber(m,'Invalid purchaseAmount');h.isString(n,'Invalid currency');h.maybeObject(o,'Invalid params');var p=l.getClientID();h.isTrue(p!==null&&p.length>0,'You need to call FB.init() with App ID first.');i.logPurchase(p,m,n,o);},activateApp:function(){h.isTrue(k('allow_non_canvas_app_events',false)||l.isCanvasEnvironment(),'You can only use this function in Facebook Canvas environment');var m=l.getClientID();h.isTrue(m!==null&&m.length>0,'You need to call FB.init() with App ID first.');i.activateApp(m);},EventNames:i.EventNames,ParameterNames:i.ParameterNames});},3);
__d('resolveURI',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();function h(i){if(!i)return window.location.href;i=i.replace(/&/g,'&').replace(/"/g,'"');var j=document.createElement('div');j.innerHTML='<a href="'+i+'"></a>';return j.firstChild.href;}f.exports=h;},null);
__d('sdk.Canvas.Environment',['sdk.RPC'],function a(b,c,d,e,f,g,h){if(c.__markCompiled)c.__markCompiled();function i(l){h.remote.getPageInfo(function(m){l(m.result);});}function j(l,m){h.remote.scrollTo({x:l||0,y:m||0});}h.stub('getPageInfo');h.stub('scrollTo');var k={getPageInfo:i,scrollTo:j};f.exports=k;},null);
__d('sdk.fbt',[],function a(b,c,d,e,f,g){if(c.__markCompiled)c.__markCompiled();var h={_:function(i){return typeof i==='string'?i:i[0];}};f.exports=h;},null);
__d('sdk.Dialog',['sdk.Canvas.Environment','sdk.Content','sdk.DOM','DOMEventListener','ObservableMixin','sdk.Runtime','Type','sdk.UA','sdk.fbt','sdk.feature'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q){if(c.__markCompiled)c.__markCompiled();var r=30,s=590,t=500,u=240,v=575;function w(){if(q('dialog_resize_refactor',false)){var z=j.getViewportInfo();if(z.height&&z.width)return {width:Math.min(z.width,t),height:Math.min(z.height,s)};}return null;}var x=n.extend({constructor:function z(aa,ba){this.parent();this.id=aa;this.display=ba;this._e2e={};if(!y._dialogs){y._dialogs={};y._addOrientationHandler();}y._dialogs[aa]=this;this.trackEvent('init');},trackEvent:function(z,aa){if(this._e2e[z])return this;this._e2e[z]=aa||ES('Date','now',false);if(z=='close')this.inform('e2e:end',this._e2e);return this;},trackEvents:function(z){if(typeof z==='string')z=ES('JSON','parse',false,z);for(var aa in z)if(z.hasOwnProperty(aa))this.trackEvent(aa,z[aa]);return this;}},l),y={newInstance:function(z,aa){return new x(z,aa);},_dialogs:null,_lastYOffset:0,_overlayListeners:[],_loaderEl:null,_overlayEl:null,_stack:[],_active:null,_forceTabletStyle:null,_closeOnOverlayTap:null,get:function(z){return y._dialogs[z];},_findRoot:function(z){while(z){if(j.containsCss(z,'fb_dialog'))return z;z=z.parentNode;}},_createWWWLoader:function(z){z=z?z:460;return y.create({content:'<div class="dialog_title">'+' <a id="fb_dialog_loader_close">'+' <div class="fb_dialog_close_icon"></div>'+' </a>'+' <span>Facebook</span>'+' <div style="clear:both;"></div>'+'</div>'+'<div class="dialog_content"></div>'+'<div class="dialog_footer"></div>',width:z});},_createMobileLoader:function(){var z;if(o.nativeApp()){z='<div class="dialog_header"></div>';}else if(y.isTabletStyle()){z='<div class="overlayLoader">'+'<div id="fb_dialog_loader_spinner"></div>'+'<a id="fb_dialog_loader_close" href="#">'+p._("Cancel")+'</a>'+'</div>';}else z='<div class="dialog_header">'+'<table>'+' <tbody>'+' <tr>'+' <td class="header_left">'+' <label class="touchable_button">'+' <input type="submit" value="'+p._("Cancel")+'"'+' id="fb_dialog_loader_close"/>'+' </label>'+' </td>'+' <td class="header_center">'+' <div>'+' '+p._("Loading...")+' </div>'+' </td>'+' <td class="header_right">'+' </td>'+' </tr>'+' </tbody>'+'</table>'+'</div>';return y.create({classes:'loading'+(y.isTabletStyle()?' centered':''),content:z});},_restoreBodyPosition:function(){var z=document.body;if(y.isTabletStyle()){j.removeCss(z,'fb_reposition');}else j.removeCss(z,'fb_hidden');},_setDialogOverlayStyle:function(){if(!y._overlayEl)return;var z=j.getViewportInfo();y._overlayEl.style.minHeight=z.height||z.width?z.height+'px':null;y._overlayEl.style.top=z.scrollTop?z.scrollTop+'px':null;},_showTabletOverlay:function(z){if(!y.isTabletStyle())return;if(!y._overlayEl){y._overlayEl=document.createElement('div');y._overlayEl.setAttribute('id','fb_dialog_ipad_overlay');i.append(y._overlayEl,null);}y._setDialogOverlayStyle();if(y._closeOnOverlayTap){var aa=false;setTimeout(function(){return aa=true;},3000);var ba=k.add(y._overlayEl,'click',function(){if(aa)z();});y._overlayListeners.push(ba);}y._overlayEl.className='';},_hideTabletOverlay:function(){if(y.isTabletStyle()){y._overlayEl.className='hidden';ES(y._overlayListeners,'forEach',true,function(z){return z.remove();});y._overlayListeners=[];}},showLoader:function(z,aa){if(!z)z=function(){};var ba=function(){y._hideLoader();y._restoreBodyPosition();y._hideTabletOverlay();z();};y._showTabletOverlay(ba);if(!y._loaderEl)y._loaderEl=y._findRoot(o.mobile()?y._createMobileLoader():y._createWWWLoader(aa));var ca=document.getElementById('fb_dialog_loader_close');if(ca){j.removeCss(ca,'fb_hidden');var da=k.add(ca,'click',ba);y._overlayListeners.push(da);}y._makeActive(y._loaderEl);},setCloseOnOverlayTap:function(z){y._closeOnOverlayTap=!!z;},_hideLoader:function(){if(y._loaderEl&&y._loaderEl==y._active)y._loaderEl.style.top='-10000px';},_makeActive:function(z){y._setDialogSizes();y._lowerActive();y._active=z;if(m.isEnvironment(m.ENVIRONMENTS.CANVAS))h.getPageInfo(function(aa){y._centerActive(aa);});y._centerActive();},_lowerActive:function(){if(!y._active)return;y._active.style.top='-10000px';y._active=null;},_removeStacked:function(z){y._stack=ES(y._stack,'filter',true,function(aa){return aa!=z;});},_centerActive:function(z){var aa=y._active;if(!aa)return;var ba=j.getViewportInfo(),ca=parseInt(aa.offsetWidth,10),da=parseInt(aa.offsetHeight,10),ea=ba.scrollLeft+(ba.width-ca)/2,fa=(ba.height-da)/2.5;if(ea<fa)fa=ea;var ga=ba.height-da-fa,ha=(ba.height-da)/2;if(z)ha=z.scrollTop-z.offsetTop+(z.clientHeight-da)/2;if(ha<fa){ha=fa;}else if(ha>ga)ha=ga;ha+=ba.scrollTop;if(o.mobile()){var ia=100,ja=document.body;if(y.isTabletStyle()){ia+=(ba.height-da)/2;j.addCss(ja,'fb_reposition');}else{j.addCss(ja,'fb_hidden');if(q('dialog_resize_refactor',false))ja.style.width='auto';ha=10000;}var ka=j.getByClass('fb_dialog_padding',aa);if(ka.length)ka[0].style.height=ia+'px';}aa.style.left=(ea>0?ea:0)+'px';aa.style.top=(ha>0?ha:0)+'px';},_setDialogSizes:function(){var z=arguments.length<=0||arguments[0]===undefined?false:arguments[0];if(!o.mobile())return;for(var aa in y._dialogs)if(y._dialogs.hasOwnProperty(aa)){var ba=document.getElementById(aa);if(ba){ba.style.width=y.getDefaultSize().width+'px';if(!z)ba.style.height=y.getDefaultSize().height+'px';}}},getDefaultSize:function(){if(o.mobile()){var z=w();if(z){if(j.getViewportInfo().width<=z.width)z.width=j.getViewportInfo().width-r;if(j.getViewportInfo().height<=z.height)z.height=j.getViewportInfo().height-r;return z;}if(o.ipad())return {width:t,height:s};if(o.android()){return {width:screen.availWidth,height:screen.availHeight};}else{var aa=window.innerWidth,ba=window.innerHeight,ca=aa/ba>1.2;return {width:aa,height:Math.max(ba,ca?screen.width:screen.height)};}}return {width:v,height:u};},_handleOrientationChange:function(){var z=q('dialog_resize_refactor',false)?j.getViewportInfo().width:screen.availWidth;y._availScreenWidth=z;if(y.isTabletStyle()){y._setDialogSizes(true);y._centerActive();y._setDialogOverlayStyle();}else{var aa=y.getDefaultSize().width;for(var ba in y._dialogs)if(y._dialogs.hasOwnProperty(ba)){var ca=document.getElementById(ba);if(ca)ca.style.width=aa+'px';}}},_addOrientationHandler:function(){if(!o.mobile())return;var z="onorientationchange" in window?'orientationchange':'resize';y._availScreenWidth=q('dialog_resize_refactor',false)?j.getViewportInfo().width:screen.availWidth;k.add(window,z,function(aa){return setTimeout(y._handleOrientationChange,50);});},create:function(z){z=z||{};var aa=document.createElement('div'),ba=document.createElement('div'),ca='fb_dialog';if(z.closeIcon&&z.onClose){var da=document.createElement('a');da.className='fb_dialog_close_icon';da.onclick=z.onClose;aa.appendChild(da);}ca+=' '+(z.classes||'');if(o.ie()){ca+=' fb_dialog_legacy';ES(['vert_left','vert_right','horiz_top','horiz_bottom','top_left','top_right','bottom_left','bottom_right'],'forEach',true,function(ga){var ha=document.createElement('span');ha.className='fb_dialog_'+ga;aa.appendChild(ha);});}else ca+=o.mobile()?' fb_dialog_mobile':' fb_dialog_advanced';if(z.content)i.append(z.content,ba);aa.className=ca;var ea=parseInt(z.width,10);if(!isNaN(ea))aa.style.width=ea+'px';ba.className='fb_dialog_content';aa.appendChild(ba);if(o.mobile()){var fa=document.createElement('div');fa.className='fb_dialog_padding';aa.appendChild(fa);}i.append(aa);if(z.visible)y.show(aa);return ba;},show:function(z){var aa=y._findRoot(z);if(aa){y._removeStacked(aa);y._hideLoader();y._makeActive(aa);y._stack.push(aa);if('fbCallID' in z)y.get(z.fbCallID).inform('iframe_show').trackEvent('show');}},hide:function(z){var aa=y._findRoot(z);y._hideLoader();if(aa==y._active){y._lowerActive();y._restoreBodyPosition();y._hideTabletOverlay();if('fbCallID' in z)y.get(z.fbCallID).inform('iframe_hide').trackEvent('hide');}},remove:function(z){z=y._findRoot(z);if(z){var aa=y._active==z;y._removeStacked(z);if(aa){y._hideLoader();if(y._stack.length>0){y.show(y._stack.pop());}else{y._lowerActive();y._restoreBodyPosition();y._hideTabletOverlay();}}else if(y._active===null&&y._stack.length>0)y.show(y._stack.pop());setTimeout(function(){z.parentNode.removeChild(z);},3000);}},isActive:function(z){var aa=y._findRoot(z);return aa&&aa===y._active;},setForceTabletStyle:function(z){y._forceTabletStyle=!!z;},isTabletStyle:function(){var z;if(!o.mobile())return false;if(y._forceTabletStyle)return true;if(q('dialog_resize_refactor',false)){var aa=w();z=aa&&(aa.height>=s||aa.width>=t);}else z=!!o.ipad();return z;}};f.exports=y;},null);
__d('sdk.Frictionless',['sdk.Auth','sdk.api','sdk.Event','sdk.Dialog'],function a(b,c,d,e,f,g,h,i,j,k){if(c.__markCompiled)c.__markCompiled();var l={_allowedRecipients:{},_useFrictionless:false,_updateRecipients:function(){l._allowedRecipients={};i('/me/apprequestformerrecipients',function(m){if(!m||m.error)return;ES(m.data,'forEach',true,function(n){l._allowedRecipients[n.recipient_id]=true;});});},init:function(){l._useFrictionless=true;h.getLoginStatus(function(m){if(m.status=='connected')l._updateRecipients();});j.subscribe('auth.login',function(m){if(m.authResponse)l._updateRecipients();});},_processRequestResponse:function(m,n){return function(o){var p=o&&o.updated_frictionless;if(l._useFrictionless&&p)l._updateRecipients();if(o){if(!n&&o.frictionless){k._hideLoader();k._restoreBodyPosition();k._hideIPadOverlay();}delete o.frictionless;delete o.updated_frictionless;}m&&m(o);};},isAllowed:function(m){if(!m)return false;if(typeof m==='number')return m in l._allowedRecipients;if(typeof m==='string')m=m.split(',');m=ES(m,'map',true,function(p){return ES(String(p),'trim',true);});var n=true,o=false;ES(m,'forEach',true,function(p){n=n&&p in l._allowedRecipients;o=true;});return n&&o;}};j.subscribe('init:post',function(m){if(m.frictionlessRequests)l.init();});f.exports=l;},null);
__d('sdk.Native',['Log','sdk.UA'],function a(b,c,d,e,f,g,h,i){if(c.__markCompiled)c.__markCompiled();var j='fbNativeReady',k={onready:function(l){if(!i.nativeApp()){h.error('FB.Native.onready only works when the page is rendered '+'in a WebView of the native Facebook app. Test if this is the '+'case calling FB.UA.nativeApp()');return;}if(window.__fbNative&&!this.nativeReady)ES('Object','assign',false,this,window.__fbNative);if(this.nativeReady){l();}else{var m=function(n){window.removeEventListener(j,m);this.onready(l);};window.addEventListener(j,m,false);}}};f.exports=k;},null);
__d('sdk.UIServer',['sdk.Auth','sdk.Content','sdk.DOM','sdk.Dialog','sdk.Event','sdk.Frictionless','Log','sdk.Native','QueryString','sdk.RPC','sdk.Runtime','JSSDKConfig','sdk.UA','UrlMap','sdk.XD','createObjectFrom','sdk.feature','sdk.fbt','flattenObject','sdk.getContextType','guid','insertIframe','resolveURI'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa,ba,ca,da){if(c.__markCompiled)c.__markCompiled();var ea={transform:function(ka){if(ka.params.display==='touch'&&ja.canIframe(ka.params)&&window.postMessage){ka.params.channel=ja._xdChannelHandler(ka.id,'parent');if(!t.nativeApp())ka.params.in_iframe=1;return ka;}else return ja.genericTransform(ka);},getXdRelation:function(ka){var la=ka.display;if(la==='touch'&&window.postMessage&&ka.in_iframe)return 'parent';return ja.getXdRelation(ka);}},fa={'stream.share':{size:{width:670,height:340},url:'sharer.php',transform:function(ka){if(!ka.params.u)ka.params.u=window.location.toString();ka.params.display='popup';return ka;}},apprequests:{transform:function(ka){ka=ea.transform(ka);ka.params.frictionless=m&&m._useFrictionless;if(ka.params.frictionless){if(m.isAllowed(ka.params.to)){ka.params.display='iframe';ka.params.in_iframe=true;ka.hideLoader=true;}ka.cb=m._processRequestResponse(ka.cb,ka.hideLoader);}ka.closeIcon=false;return ka;},getXdRelation:ea.getXdRelation},feed:ea,'permissions.oauth':{url:'dialog/oauth',size:{width:t.mobile()?null:475,height:t.mobile()?null:183},transform:function(ka){if(!r.getClientID()){n.error('FB.login() called before FB.init().');return;}if(h.getAuthResponse()&&!ka.params.scope&&!ka.params.auth_type){n.error('FB.login() called when user is already connected.');ka.cb&&ka.cb({status:r.getLoginStatus(),authResponse:h.getAuthResponse()});return;}var la=ka.cb,ma=ka.id;delete ka.cb;var na=ES('Object','keys',false,ES('Object','assign',false,ka.params.response_type?w(ka.params.response_type.split(',')):{},{token:true,signed_request:true})).join(',');if(ka.params.display==='async'){ES('Object','assign',false,ka.params,{client_id:r.getClientID(),origin:aa(),response_type:na,domain:location.hostname});ka.cb=h.xdResponseWrapper(la,h.getAuthResponse(),'permissions.oauth');}else ES('Object','assign',false,ka.params,{client_id:r.getClientID(),redirect_uri:da(ja.xdHandler(la,ma,'opener',h.getAuthResponse(),'permissions.oauth')),origin:aa(),response_type:na,domain:location.hostname});return ka;}},'auth.logout':{url:'logout.php',transform:function(ka){if(!r.getClientID()){n.error('FB.logout() called before calling FB.init().');}else if(!h.getAuthResponse()){n.error('FB.logout() called without an access token.');}else{ka.params.next=ja.xdHandler(ka.cb,ka.id,'parent',h.getAuthResponse(),'logout');return ka;}}},'login.status':{url:'dialog/oauth',transform:function(ka){var la=ka.cb,ma=ka.id;delete ka.cb;ES('Object','assign',false,ka.params,{client_id:r.getClientID(),redirect_uri:ja.xdHandler(la,ma,'parent',h.getAuthResponse(),'login_status'),origin:aa(),response_type:'token,signed_request,code',domain:location.hostname});return ka;}},pay:{size:{width:555,height:120},connectDisplay:'popup'}},ga={};function ha(ka,la){ga[la]=true;return function(ma){delete ga[la];ka(ma);};}function ia(ka){if(!x('should_force_single_dialog_instance',true))return false;var la=ka.method.toLowerCase();if(la==='pay'&&ka.display==='async')return true;return false;}var ja={Methods:fa,_loadedNodes:{},_defaultCb:{},_resultToken:'"xxRESULTTOKENxx"',genericTransform:function(ka){if(ka.params.display=='dialog'||ka.params.display=='iframe')ES('Object','assign',false,ka.params,{display:'iframe',channel:ja._xdChannelHandler(ka.id,'parent.parent')},true);return ka;},checkOauthDisplay:function(ka){var la=ka.scope||ka.perms||r.getScope();if(!la)return ka.display;var ma=la.split(/\s|,/g);for(var na=0;na<ma.length;na++)if(!s.initSitevars.iframePermissions[ES(ma[na],'trim',true)])return 'popup';return ka.display;},prepareCall:function(ka,la){var ma=ka.method.toLowerCase(),na=ja.Methods.hasOwnProperty(ma)?ES('Object','assign',false,{},ja.Methods[ma]):{},oa=ba(),pa=r.getSecure()||ma!=='auth.status'&&ma!='login.status';ES('Object','assign',false,ka,{app_id:r.getClientID(),locale:r.getLocale(),sdk:'joey',access_token:pa&&r.getAccessToken()||undefined});if(ma==='share'||ma==='share_open_graph')if(ka.iframe_test)na=ES('Object','assign',false,{},ea);ka.display=ja.getDisplayMode(na,ka);if(!na.url)na.url='dialog/'+ma;if((na.url=='dialog/oauth'||na.url=='dialog/permissions.request')&&(ka.display=='iframe'||ka.display=='touch'&&ka.in_iframe))ka.display=ja.checkOauthDisplay(ka);if(ka.display=='popup')delete ka.access_token;if(r.getIsVersioned()&&na.url.substring(0,7)==='dialog/')na.url=ka.version+'/'+na.url;if(ia(ka)){if(ga[ma]){var qa='Dialog "'+ma+'" is trying to run more than once.';n.warn(qa);la({error_code:-100,error_message:qa});return;}la=ha(la,ma);}var ra={cb:la,id:oa,size:na.size||ja.getDefaultSize(),url:u.resolve(ka.display=='touch'?'m':'www',pa)+'/'+na.url,params:ka,name:ma,dialog:k.newInstance(oa,ka.display)},sa=na.transform?na.transform:ja.genericTransform;if(sa){ra=sa(ra);if(!ra)return;}if(ka.display==='touch'&&ka.in_iframe)ra.params.parent_height=window.innerHeight;var ta=na.getXdRelation||ja.getXdRelation,ua=ta(ra.params);if(!(ra.id in ja._defaultCb)&&!('next' in ra.params)&&!('redirect_uri' in ra.params))ra.params.next=ja._xdResult(ra.cb,ra.id,ua,true);if(ua==='parent')ES('Object','assign',false,ra.params,{channel_url:ja._xdChannelHandler(oa,'parent.parent')},true);ra=ja.prepareParams(ra);return ra;},prepareParams:function(ka){if(ka.params.display!=='async')delete ka.params.method;ka.params=z(ka.params);var la=p.encode(ka.params);if(!t.nativeApp()&&ja.urlTooLongForIE(ka.url+'?'+la)){ka.post=true;}else if(la)ka.url+='?'+la;return ka;},urlTooLongForIE:function(ka){return t.ie()&&t.ie()<=8&&ka.length>2048;},getDisplayMode:function(ka,la){if(la.display==='hidden'||la.display==='none')return la.display;var ma=r.isEnvironment(r.ENVIRONMENTS.CANVAS)||r.isEnvironment(r.ENVIRONMENTS.PAGETAB);if(ma&&!la.display)return 'async';if(t.mobile()&&la.method!=='feed'||la.display==='touch')return 'touch';if(la.display=='iframe'||la.display=='dialog')if(!ja.canIframe(la)){n.error('"dialog" mode can only be used when the user is connected.');return 'popup';}if(ka.connectDisplay&&!ma)return ka.connectDisplay;return la.display||(ja.canIframe(la)?'dialog':'popup');},canIframe:function(ka){if(r.getAccessToken())return true;if(t.mobile()&&r.getLoggedIntoFacebook())return !!ka.iframe_test;return false;},getXdRelation:function(ka){var la=ka.display;if(la==='popup'||la==='touch')return 'opener';if(la==='dialog'||la==='iframe'||la==='hidden'||la==='none')return 'parent';if(la==='async')return 'parent.frames['+window.name+']';},popup:function(ka){var la=typeof window.screenX!='undefined'?window.screenX:window.screenLeft,ma=typeof window.screenY!='undefined'?window.screenY:window.screenTop,na=typeof window.outerWidth!='undefined'?window.outerWidth:document.documentElement.clientWidth,oa=typeof window.outerHeight!='undefined'?window.outerHeight:document.documentElement.clientHeight-22,pa=t.mobile()?null:ka.size.width,qa=t.mobile()?null:ka.size.height,ra=la<0?window.screen.width+la:la,sa=parseInt(ra+(na-pa)/2,10),ta=parseInt(ma+(oa-qa)/2.5,10),ua=[];if(pa!==null)ua.push('width='+pa);if(qa!==null)ua.push('height='+qa);ua.push('left='+sa);ua.push('top='+ta);ua.push('scrollbars=1');if(ka.name=='permissions.request'||ka.name=='permissions.oauth')ua.push('location=1,toolbar=0');ua=ua.join(',');var va;if(ka.post){va=window.open('about:blank',ka.id,ua);if(va){ja.setLoadedNode(ka,va,'popup');i.submitToTarget({url:ka.url,target:ka.id,params:ka.params});}}else{va=window.open(ka.url,ka.id,ua);if(va)ja.setLoadedNode(ka,va,'popup');}if(!va)return;if(ka.id in ja._defaultCb)ja._popupMonitor();},setLoadedNode:function(ka,la,ma){if(ma==='iframe')la.fbCallID=ka.id;la={node:la,type:ma,fbCallID:ka.id};ja._loadedNodes[ka.id]=la;},getLoadedNode:function(ka){var la=typeof ka=='object'?ka.id:ka,ma=ja._loadedNodes[la];return ma?ma.node:null;},hidden:function(ka){ka.className='FB_UI_Hidden';ka.root=i.appendHidden('');ja._insertIframe(ka);},iframe:function(ka){ka.className='FB_UI_Dialog';if(ka.params.iframe_test){k.setForceTabletStyle(true);k.setCloseOnOverlayTap(true);}var la=function(){var ma=ES('JSON','stringify',false,{error_code:4201,error_message:y._("User canceled the Dialog flow")});ja._triggerDefault(ka.id,ma);};ka.root=k.create({onClose:la,closeIcon:ka.closeIcon===undefined?true:ka.closeIcon,classes:k.isTabletStyle()?'centered':''});if(!ka.hideLoader)k.showLoader(la,ka.size.width);j.addCss(ka.root,'fb_dialog_iframe');ja._insertIframe(ka);},touch:function(ka){if(ka.params&&ka.params.in_iframe){if(ka.ui_created){k.showLoader(function(){ja._triggerDefault(ka.id,null);},0);}else ja.iframe(ka);}else if(t.nativeApp()&&!ka.ui_created){ka.frame=ka.id;o.onready(function(){ja.setLoadedNode(ka,o.open(ka.url+'#cb='+ka.frameName),'native');});ja._popupMonitor();}else if(!ka.ui_created)ja.popup(ka);},async:function(ka){ka.params.redirect_uri=location.protocol+'//'+location.host+location.pathname;delete ka.params.access_token;q.remote.showDialog(ka.params,function(la){var ma=la.result;if(ma&&ma.e2e){var na=k.get(ka.id);na.trackEvents(ma.e2e);na.trackEvent('close');delete ma.e2e;}ka.cb(ma);});},getDefaultSize:function(){return k.getDefaultSize();},_insertIframe:function(ka){ja._loadedNodes[ka.id]=false;var la=function(ma){if(ka.id in ja._loadedNodes)ja.setLoadedNode(ka,ma,'iframe');};if(ka.post){ca({url:'about:blank',root:ka.root,className:ka.className,width:ka.size.width,height:ka.size.height,id:ka.id,onInsert:la,onload:function(ma){i.submitToTarget({url:ka.url,target:ma.name,params:ka.params});}});}else ca({url:ka.url,root:ka.root,className:ka.className,width:ka.size.width,height:ka.size.height,id:ka.id,name:ka.frameName,onInsert:la});},_handleResizeMessage:function(ka,la){var ma=ja.getLoadedNode(ka);if(!ma)return;if(la.height)ma.style.height=la.height+'px';if(la.width)ma.style.width=la.width+'px';v.inform('resize.ack',la||{},'parent.frames['+ma.name+']');if(!k.isActive(ma)){k.show(ma);}else k._centerActive();},_triggerDefault:function(ka,la){var ma={frame:ka};if(la)ma.result=la;ja._xdRecv(ma,ja._defaultCb[ka]||function(){});},_popupMonitor:function(){var ka;for(var la in ja._loadedNodes)if(ja._loadedNodes.hasOwnProperty(la)&&la in ja._defaultCb){var ma=ja._loadedNodes[la];if(ma.type!='popup'&&ma.type!='native')continue;var na=ma.node;try{if(na.closed){ja._triggerDefault(la,null);}else ka=true;}catch(oa){}}if(ka&&!ja._popupInterval){ja._popupInterval=setInterval(ja._popupMonitor,100);}else if(!ka&&ja._popupInterval){clearInterval(ja._popupInterval);ja._popupInterval=null;}},_xdChannelHandler:function(ka,la){return v.handler(function(ma){var na=ja.getLoadedNode(ka);if(!na)return;if(ma.type=='resize'){ja._handleResizeMessage(ka,ma);}else if(ma.type=='hide'){k.hide(na);}else if(ma.type=='rendered'){var oa=k._findRoot(na);k.show(oa);}else if(ma.type=='fireevent')l.fire(ma.event);},la,true,null);},_xdNextHandler:function(ka,la,ma,na){if(na)ja._defaultCb[la]=ka;return v.handler(function(oa){ja._xdRecv(oa,ka);},ma)+'&frame='+la;},_xdRecv:function(ka,la){var ma=ja.getLoadedNode(ka.frame);if(ma)if(ma.close){try{ma.close();if(/iPhone.*Version\/(5|6)/.test(navigator.userAgent)&&RegExp.$1!=='5')window.focus();ja._popupCount--;}catch(na){}}else if(j.containsCss(ma,'FB_UI_Hidden')){setTimeout(function(){ma.parentNode.parentNode.removeChild(ma.parentNode);},3000);}else if(j.containsCss(ma,'FB_UI_Dialog'))k.remove(ma);delete ja._loadedNodes[ka.frame];delete ja._defaultCb[ka.frame];if(ka.e2e){var oa=k.get(ka.frame);oa.trackEvents(ka.e2e);oa.trackEvent('close');delete ka.e2e;}la(ka);},_xdResult:function(ka,la,ma,na){return (ja._xdNextHandler(function(oa){ka&&ka(oa.result&&oa.result!=ja._resultToken&&ES('JSON','parse',false,oa.result));},la,ma,na)+'&result='+encodeURIComponent(ja._resultToken));},xdHandler:function(ka,la,ma,na,oa){return ja._xdNextHandler(h.xdResponseWrapper(ka,na,oa),la,ma,true);}};q.stub('showDialog');f.exports=ja;},null);
__d('sdk.ui',['Assert','sdk.Impressions','Log','sdk.PlatformVersioning','sdk.Runtime','sdk.UIServer','sdk.feature'],function a(b,c,d,e,f,g,h,i,j,k,l,m,n){if(c.__markCompiled)c.__markCompiled();function o(p,q){h.isObject(p);h.maybeFunction(q);if(l.getIsVersioned()){k.assertVersionIsSet();if(p.version){k.assertValidVersion(p.version);}else p.version=l.getVersion();}p=ES('Object','assign',false,{},p);if(!p.method){j.error('"method" is a required parameter for FB.ui().');return null;}if(p.method=='pay.prompt')p.method='pay';var r=p.method;if(p.redirect_uri){j.warn('When using FB.ui, you should not specify a redirect_uri.');delete p.redir
gitextract__zeyph8s/
├── .gitignore
├── .jshintrc
├── .travis.yml
├── LICENSE
├── Procfile
├── README.md
├── app/
│ ├── controllers/
│ │ ├── articles.js
│ │ ├── index.js
│ │ └── users.js
│ ├── models/
│ │ ├── article.js
│ │ └── user.js
│ ├── routes/
│ │ ├── articles.js
│ │ ├── index.js
│ │ └── users.js
│ └── views/
│ ├── 404.jade
│ ├── 500.jade
│ ├── includes/
│ │ ├── foot.jade
│ │ └── head.jade
│ ├── index.jade
│ └── layouts/
│ └── default.jade
├── app.js
├── app.json
├── bower.json
├── config/
│ ├── config.js
│ ├── env/
│ │ ├── all.json5
│ │ ├── development.json5.sample
│ │ ├── production.json5.sample
│ │ ├── test.json5.sample
│ │ └── travis.json
│ ├── express.js
│ ├── middlewares/
│ │ └── session.js
│ ├── passport.js
│ ├── sequelize.js
│ └── winston.js
├── gruntfile.js
├── package.json
├── pm2-ecosystem.json
├── pm2-main.js
├── public/
│ ├── css/
│ │ ├── common.css
│ │ └── views/
│ │ └── articles.css
│ ├── humans.txt
│ ├── img/
│ │ └── .gitignore
│ ├── js/
│ │ ├── FbSdk.js
│ │ ├── app.js
│ │ ├── config.js
│ │ ├── controllers/
│ │ │ ├── articles.js
│ │ │ ├── header.js
│ │ │ ├── index.js
│ │ │ └── users/
│ │ │ ├── auth.js
│ │ │ ├── signIn.js
│ │ │ └── signUp.js
│ │ ├── directives.js
│ │ ├── filters.js
│ │ ├── init.js
│ │ └── services/
│ │ ├── articles.js
│ │ ├── authenticate.js
│ │ └── global.js
│ ├── robots.txt
│ └── views/
│ ├── 404.html
│ ├── articles/
│ │ ├── create.html
│ │ ├── edit.html
│ │ ├── list.html
│ │ └── view.html
│ ├── header.html
│ ├── index.html
│ └── users/
│ ├── auth.html
│ ├── signin.html
│ └── signup.html
└── test/
├── karma/
│ ├── karma.conf.js
│ └── unit/
│ └── controllers/
│ ├── articles.spec.js
│ ├── headers.spec.js
│ └── index.spec.js
└── mocha/
├── controllers/
│ ├── articleControllerSpec.js
│ └── usersControllerSpec.js
└── models/
└── userModelSpec.js
SYMBOL INDEX (176 symbols across 2 files)
FILE: app/controllers/users.js
function authenticateSocialUser (line 127) | function authenticateSocialUser(profile, done) {
function sendResponse (line 171) | function sendResponse(err, user, info) {
function sendResponse (line 195) | function sendResponse(err, user, info) {
function getUserProfile (line 212) | function getUserProfile(err, response, profile) {
function verifyAccesToken (line 221) | function verifyAccesToken(err, response, accessToken) {
function obtainRequestToken (line 241) | function obtainRequestToken() {
function exchangeOauthToken (line 255) | function exchangeOauthToken() {
function sendResponse (line 286) | function sendResponse(err, user, info) {
function retrivedInfo (line 301) | function retrivedInfo(err, response, profile) {
function getAccessToken (line 309) | function getAccessToken(err, response, token) {
FILE: public/js/FbSdk.js
function bindContext (line 12) | function bindContext(fn, thisArg) {
function emptyFunction (line 25) | function emptyFunction() {
function l (line 91) | function l(){return j.apply(i,k.concat(Array.prototype.slice.call(argume...
function k (line 93) | function k(){}
function h (line 97) | function h(j){return (j<10?'0':'')+j;}
function z (line 107) | function z(ba){for(var ca in ba){if(!ba.hasOwnProperty(ca))continue;var ...
function aa (line 107) | function aa(ba,ca,da){var ea=da?u.call(ba).slice(8,-1)+'.prototype':ba,f...
function h (line 109) | function h(i,j,k){var l=j.split('.');do{var m=l.shift();i=i[m]||k&&(i[m]...
function h (line 110) | function h(){return 'f'+(Math.random()*(1<<30)).toString(16).replace('.'...
function i (line 111) | function i(j,k,l){k=k||'default';return function(){var m=k in h?h[k](j,l...
function h (line 113) | function h(i){for(var j=arguments.length,k=Array(j>1?j-1:0),l=1;l<j;l++)...
function j (line 114) | function j(l,m){var n=Array.prototype.slice.call(arguments,2),o=h.apply(...
function h (line 115) | function h(){this.__observableEvents={};}
function h (line 117) | function h(l){var m=[];ES(ES('Object','keys',false,l).sort(),'forEach',t...
function i (line 117) | function i(l,m){var n={};if(l==='')return n;var o=l.split('&');for(var p...
function j (line 117) | function j(l,m){return l+(ES(l,'indexOf',true,'?')!==-1?'&':'?')+(typeof...
function h (line 118) | function h(i,j){Error.prototype.constructor.call(this,i);this.message=i;...
function i (line 119) | function i(j){h.prototype.constructor.apply(this,arguments);}
function j (line 120) | function j(o,p){if(typeof o!=='boolean'||!o)throw new h(p);return o;}
function k (line 120) | function k(o,p,q){var r;if(p===undefined){r='undefined';}else if(p===nul...
function l (line 120) | function l(o,p,q){j(p instanceof o,q||'Expression not instance of type')...
function m (line 120) | function m(o,p){n['is'+o]=p;n['maybe'+o]=function(q,r){if(q!=null)p(q,r)...
function i (line 121) | function i(){var m=this.__mixins;if(m)for(var n=0;n<m.length;n++)m[n].ap...
function j (line 121) | function j(m,n){if(n instanceof m)return true;if(n instanceof i)for(var ...
function k (line 121) | function k(m,n){var o=m.prototype;if(!ES('Array','isArray',false,n))n=[n...
function l (line 121) | function l(m,n,o){var p=n&&n.hasOwnProperty('constructor')?n.constructor...
function k (line 124) | function k(n,o,p){n=n+i.getClientID();var q=j&&j!=='.';if(q){document.co...
function l (line 124) | function l(n){n=n+i.getClientID();var o=new RegExp('\\b'+n+'=([^;]*)\\b'...
function o (line 126) | function o(q){return ES(q.split('.'),'map',true,function(r){return parse...
function i (line 127) | function i(){return h.ie()<10?'javascript:false':'about:blank';}
function k (line 128) | function k(l){l.id=l.id||j();l.name=l.name||j();var m=false,n=false,o=fu...
function j (line 129) | function j(){if(!h)return;var m;while(m=h.shift())m();h=null;}
function k (line 129) | function k(m){if(h){h.push(m);}else m();}
function p (line 131) | function p(r){var s=k.getClientID();if(!r.api_key&&s)r.api_key=s;r.kid_d...
function i (line 132) | function i(m){m=m.charCodeAt(0)<<16|m.charCodeAt(1)<<8|m.charCodeAt(2);r...
function k (line 132) | function k(m){m=j.charCodeAt(m.charCodeAt(0)-43)<<18|j.charCodeAt(m.char...
function i (line 133) | function i(k){if(!k)return null;var l=k.split('.',2)[1].replace(/\-/g,'+...
function h (line 135) | function h(i,j){var k={},l=ES('Array','isArray',false,j);if(j===undefine...
function k (line 139) | function k(l,m){if(!l){var n;if(m===undefined){n=new Error('Minified exc...
function n (line 140) | function n(q,r,s,t){if(!r)return true;if(r instanceof p){q.setProtocol(r...
function p (line 140) | function p(q,r){'use strict';!r?k(0):undefined;this.$URIBase1=r;this.$UR...
function o (line 141) | function o(p){'use strict';h.isString(p,'The passed argument was of inva...
function i (line 142) | function i(j){'use strict';this._opts=babelHelpers._extends({interval:0,...
function x (line 144) | function x(){if(h)return;h=true;var z=navigator.userAgent,aa=/(?:MSIE.(\...
function m (line 145) | function m(n){if(typeof n=='undefined'||n===null||!n.toString)return '';...
function q (line 146) | function q(v){var w=p.getElementById(v);if(w)w.parentNode.removeChild(w)...
function r (line 146) | function r(){for(var v in n)if(n.hasOwnProperty(v))q(v);}
function s (line 146) | function s(v){return v.replace(/\d+/g,function(w){return '000'.substring...
function t (line 146) | function t(v){if(!o){if(k.ie()>=9)h.add(window,'unload',r);o=true;}n[v]=v;}
function h (line 147) | function h(j){return function(){return j;};}
function i (line 147) | function i(){}
function t (line 148) | function t(w){var x={},y=w.length,z=r.transports;while(y--)x[w[y]]=1;y=z...
function j (line 149) | function j(k){if(!h)h=new RegExp('(^|\\.)facebook\\.com$','i');if(k.isEm...
function i (line 151) | function i(j){'use strict';this.$JSONRPC1=0;this.$JSONRPC2={};this.remot...
function k (line 153) | function k(m,n){if(typeof n.extra=='object')n.extra.revision=i.getRevisi...
function k (line 154) | function k(){var m=document.createElement("form"),n=m.appendChild(docume...
function l (line 154) | function l(){return typeof j==='undefined'?k():j;}
function l (line 155) | function l(m){m=ES('Object','assign',false,{},m);var n,o=m.name||j(),p=m...
function j (line 156) | function j(k,l){!(arguments.length>=2)?i(0):undefined;if(h.features&&k i...
function oa (line 157) | function oa(ua){j.info('Remote XD can talk to facebook.com (%s)',ua);n.s...
function pa (line 157) | function pa(ua,va){if(!va){j.error('No senderOrigin');throw new Error();...
function qa (line 157) | function qa(ua,va){if(va&&va!=='native'&&!t(new p(va)))return;if(typeof ...
function ra (line 157) | function ra(ua,va){if(ua=='facebook'){va.relation='parent.parent';x.enqu...
function sa (line 157) | function sa(ua){if(ka)return;var va=h.appendHidden(document.createElemen...
function j (line 158) | function j(){if(i.nativeApp())return 3;if(i.mobile())return 2;if(h.isEnv...
function aa (line 159) | function aa(ga,ha){var ia=q.getUserID(),ja='';if(ga)if(ga.userID){ja=ga....
function ba (line 159) | function ba(){return x;}
function ca (line 159) | function ca(ga,ha,ia){return function(ja){var ka;if(ja&&ja.access_token)...
function da (line 159) | function da(ga){var ha,ia=ES('Date','now',false);if(y){clearTimeout(y);y...
function fa (line 159) | function fa(ga,ha){if(!q.getClientID()){o.warn('FB.getLoginStatus() call...
function l (line 160) | function l(z,aa){var ba=z.getAttribute(aa)||z.getAttribute(aa.replace(/_...
function m (line 160) | function m(z,aa){var ba=l(z,aa);return ba?/^(true|1|yes|on)$/.test(ba):n...
function n (line 160) | function n(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);tr...
function o (line 160) | function o(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);tr...
function p (line 160) | function p(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);va...
function q (line 160) | function q(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);if...
function r (line 160) | function r(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);va...
function s (line 160) | function s(z,aa,ba){h.isString(z);aa=aa||document.body;ba=ba||'*';if(aa....
function t (line 160) | function t(z,aa){h.isTruthy(z,'element not specified');h.isString(aa);aa...
function u (line 160) | function u(z,aa,ba){h.isTruthy(z,'element not specified');h.isString(aa)...
function v (line 160) | function v(z,aa){var ba=true;for(var ca=0,da;da=aa[ca++];)if(!(da in k))...
function w (line 160) | function w(){var z=document.documentElement&&document.compatMode=='CSS1C...
function x (line 160) | function x(z){h.isTruthy(z,'element not specified');var aa=0,ba=0;do{aa+...
function p (line 161) | function p(v){var w=v._originalError;delete v._originalError;j.log('jssd...
function q (line 161) | function q(v){var w={line:v.lineNumber||v.line,message:v.message,name:v....
function r (line 161) | function r(v,w){return function(){if(!n)return v.apply(this,arguments);t...
function s (line 161) | function s(v){if(!v.__wrapper)v.__wrapper=function(){try{return v.apply(...
function t (line 161) | function t(v,w){return function(x,y){var z=w+':'+(o||'[global]')+':'+(x....
function ba (line 163) | function ba(da,ea,fa,ga){var ha;if(/^_/.test(fa)){ha='hide';}else if(w&&...
function ca (line 163) | function ca(da,ea){var fa=da?j(v,da,true):v;ES(ES('Object','keys',false,...
function i (line 164) | function i(j,k){h.prototype.constructor.apply(this,arguments);}
function j (line 165) | function j(m,n){if(!self.XMLHttpRequest)return null;var o=new XMLHttpReq...
function k (line 165) | function k(m,n,o,p){o.suppress_http_code=1;var q=i.encode(o);if(n!='post...
function q (line 166) | function q(){if(!o)throw new Error('swfUrl has not been set');var t=j.cr...
function r (line 166) | function r(t,u,v,w){v.suppress_http_code=1;if(!v.method)v.method=u;var x...
function l (line 167) | function l(n,o,p,q){var r=document.createElement('script'),s=function(u)...
function h (line 168) | function h(i){var j={};for(var k in i)if(i.hasOwnProperty(k)){var l=i[k]...
function ka (line 169) | function ka(ua,va,wa,xa){var ya=ha!==0&&fa>=ha;if(ya){ga.push(function()...
function la (line 169) | function la(ua,va,wa,xa,ya,za){if(za&&za.error)sa.inform('request.error'...
function ma (line 169) | function ma(ua){var va=ua.shift();i.isString(va,'Invalid path');if(!/^ht...
function na (line 169) | function na(){for(var ua=arguments.length,va=Array(ua),wa=0;wa<ua;wa++)v...
function oa (line 169) | function oa(ua){var va=ma(ua),wa=va.uri,xa=va.callback,ya=va.params.meth...
function pa (line 169) | function pa(){for(var ua=arguments.length,va=Array(ua),wa=0;wa<ua;wa++)v...
function qa (line 169) | function qa(){!(ca.length>0)?u(0):undefined;!(ca.length===da.length)?u(0...
function ra (line 169) | function ra(ua,va){i.isObject(ua);i.isString(ua.method,'method missing')...
function ta (line 169) | function ta(ua,va){return ua.toString().length>y&&va==='get';}
function p (line 171) | function p(q){if(typeof q==='string'){if(j.getIsVersioned()){i.assertVer...
function p (line 173) | function p(t,u,v,w){h.isTrue(q(u),'Invalid event name: '+u+'. '+'It must...
function q (line 173) | function q(t){if(t===null||t.length===0||t.length>n||!new RegExp(o).test...
function r (line 173) | function r(t,u,v,w){var x={};x[m.CURRENCY]=v;p(t,l.PURCHASED,u,babelHelp...
function s (line 173) | function s(t){p(t,l.ACTIVATED_APP);}
function h (line 175) | function h(i){if(!i)return window.location.href;i=i.replace(/&/g,'&'...
function i (line 176) | function i(l){h.remote.getPageInfo(function(m){l(m.result);});}
function j (line 176) | function j(l,m){h.remote.scrollTo({x:l||0,y:m||0});}
function w (line 178) | function w(){if(q('dialog_resize_refactor',false)){var z=j.getViewportIn...
function ha (line 181) | function ha(ka,la){ga[la]=true;return function(ma){delete ga[la];ka(ma);};}
function ia (line 181) | function ia(ka){if(!x('should_force_single_dialog_instance',true))return...
function o (line 182) | function o(p,q){h.isObject(p);h.maybeFunction(q);if(l.getIsVersioned()){...
function l (line 184) | function l(){var p=h.getWindow().document,q=p.body,r=p.documentElement,s...
function m (line 184) | function m(p){if(typeof p!='object')p={};var q=0,r=0;if(!p.height){p.hei...
function n (line 184) | function n(p,q){if(q===undefined&&typeof p==='number'){q=p;p=true;}if(p|...
function i (line 185) | function i(k){h.local.navigate=function(l){k({path:l});};h.remote.setNav...
function r (line 186) | function r(ba){ba._hideunity_savedstyle={};ba._hideunity_savedstyle.left...
function s (line 186) | function s(ba){if(ba._hideunity_savedstyle){ba.style.left=ba._hideunity_...
function t (line 186) | function t(ba){ba._old_visibility=ba.style.visibility;ba.style.visibilit...
function u (line 186) | function u(ba){ba.style.visibility=ba._old_visibility||'';delete ba._old...
function v (line 186) | function v(ba){var ca=ba.type?ba.type.toLowerCase():null,da=ca==='applic...
function w (line 186) | function w(ba){var ca=ba.type?ba.type.toLowerCase():null;return ca==='ap...
function x (line 186) | function x(ba){var ca=ES('Array','from',false,window.document.getElement...
function y (line 186) | function y(){t();r();}
function z (line 186) | function z(){u();s();}
function j (line 187) | function j(o,p){var q={appId:i.getClientID(),time:ES('Date','now',false)...
function k (line 187) | function k(){j(null,'StartIframeAppTtiTimer');}
function l (line 187) | function l(o){j(o,'StopIframeAppTtiTimer');}
function m (line 187) | function m(o){j(o,'RecordIframeAppTti');}
function p (line 189) | function p(){var u={object:'data',link:'href',script:'src'};if(n==k.AUTO...
function q (line 189) | function q(){if(!i.isEnvironment(i.ENVIRONMENTS.CANVAS)||!i.getClientID(...
function r (line 189) | function r(u){n=u;}
function s (line 189) | function s(u){o.push(u);}
function j (line 191) | function j(l,m){if(l!='canvas.friendsOnlineUpdated')return;if(m.length==...
function k (line 191) | function k(l,m){if(l!='canvas.friendsOnlineUpdated')return;if(m.length==...
function j (line 192) | function j(k,l){if(k!='canvas.syncRequestUpdated')return;h.remote.initPe...
function s (line 195) | function s(u){var v=typeof u=='number'&&u>0||typeof u=='string'&&/^[0-9a...
function t (line 195) | function t(u){if(p.getInitialized())l.warn('FB.init has already been cal...
function h (line 199) | function h(i){var j,k;return function(){if(!j){j=true;k=i();}return k;};}
function r (line 200) | function r(y,z){return ES(y[z]+'','trim',true);}
function s (line 200) | function s(y){return y.scopeName?y.scopeName+':'+y.nodeName:'';}
function t (line 200) | function t(y){return n[r(y,'nodeName').toLowerCase()]||n[s(y).toLowerCas...
function u (line 200) | function u(y){var z=ES(r(y,'className').split(/\s+/),'filter',true,funct...
function v (line 200) | function v(y){var z={};ES(ES('Array','from',false,y.attributes),'forEach...
function w (line 200) | function w(y,z,aa){var ba=document.createElement('div');i.addCss(y,z+'-'...
function x (line 200) | function x(y,z,aa){h.isTrue(y&&y.nodeType&&y.nodeType===1&&!!y.getElemen...
function v (line 201) | function v(){return !!(i('plugin_pipe',false)&&o.getSecure()!==undefined...
function w (line 201) | function w(){var y=u;u=[];if(y.length<=t){ES(y,'forEach',true,function(b...
function x (line 201) | function x(y){var z=document.createElement('span');h.appendHidden(z);var...
function aa (line 202) | function aa(ia,ja,ka){if(ja||ja===0)if(ja==='100%'){ia.style.width='100%...
function ba (line 202) | function ba(ia){return function(ja){var ka={width:ja.width,height:ja.hei...
function da (line 202) | function da(ia,ja){var ka=ia[ja]||ia[ja.replace(/_/g,'-')]||ia[ja.replac...
function ea (line 202) | function ea(ia,ja,ka,la){ES(ES('Object','keys',false,ia),'forEach',true,...
function fa (line 202) | function fa(ia){if(ia==='100%')return '100%';return ia||ia==='0'||ia===0...
function ga (line 202) | function ga(ia){if(ia)aa(ia,0,0);}
function x (line 207) | function x(){var y={};for(var z in w){var aa=w[z];y[z]={widget:aa.getUrl...
function h (line 210) | function h(i,j){if(i===null||typeof i==='undefined')return;if(typeof i!=...
function j (line 213) | function j(k){return k.replace(h,function(l){return i[l];});}
function m (line 216) | function m(p){'use strict';this.$VideoCache1=p.isMuted;this.$VideoCache2...
function n (line 216) | function n(p,q,r){'use strict';this.$VideoController1=p;this.$VideoContr...
Condensed preview — 75 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (295K chars).
[
{
"path": ".gitignore",
"chars": 437,
"preview": "# Github Node Default\n\nlib-cov\n*.seed\n*.log\n*.csv\n*.dat\n*.out\n*.pid\n*.gz\n\npids\nlogs\nresults\n\nnpm-debug.log\nnode_modules\n"
},
{
"path": ".jshintrc",
"chars": 6504,
"preview": "{\n // JSHint Default Configuration File (as on JSHint website)\n // See http://jshint.com/docs/ for more details\n\n "
},
{
"path": ".travis.yml",
"chars": 85,
"preview": "language: node_js\nnode_js:\n - \"0.10\"\nenv:\n - NODE_ENV=travis\nservices:\n - mongodb\n"
},
{
"path": "LICENSE",
"chars": 1100,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2013-2015 Jeff Potter, Chaudhry Junaid\n\nPermission is hereby granted, free of charg"
},
{
"path": "Procfile",
"chars": 22,
"preview": "web: node pm2-main.js\n"
},
{
"path": "README.md",
"chars": 7322,
"preview": "MEAN Stack Relational \n============="
},
{
"path": "app/controllers/articles.js",
"chars": 3106,
"preview": "'use strict';\n\n/**\n * Module dependencies.\n */\nvar StandardError = require('standard-error');\nvar db = require('../../co"
},
{
"path": "app/controllers/index.js",
"chars": 210,
"preview": "'use strict';\n\n/**\n * Module dependencies.\n */\nvar _ = require('lodash');\n\n\nexports.render = function(req, res) {\n re"
},
{
"path": "app/controllers/users.js",
"chars": 9208,
"preview": "'use strict';\n\n/**\n * Module dependencies.\n */\nvar db = require('../../config/sequelize'),\n request = require('reques"
},
{
"path": "app/models/article.js",
"chars": 277,
"preview": "'use strict';\n\nmodule.exports = function(sequelize, DataTypes) {\n\n\tvar Article = sequelize.define('Article', {\n\t\t\ttitle:"
},
{
"path": "app/models/user.js",
"chars": 1300,
"preview": "'use strict';\n\n/**\n\t* User Model\n\t*/\n\nvar crypto = require('crypto');\n\nmodule.exports = function(sequelize, DataTypes) {"
},
{
"path": "app/routes/articles.js",
"chars": 703,
"preview": "'use strict';\n\n/**\n* Module dependencies.\n*/\nvar users = require('../../app/controllers/users'),\narticles = require('../"
},
{
"path": "app/routes/index.js",
"chars": 146,
"preview": "'use strict';\n\nmodule.exports = function(app) {\n// Home route\nvar index = require('../../app/controllers/index');\napp.ge"
},
{
"path": "app/routes/users.js",
"chars": 921,
"preview": "'use strict';\n\n/**\n * Module dependencies.\n */\nvar passport = require('passport');\n\nmodule.exports = function (app) {\n//"
},
{
"path": "app/views/404.jade",
"chars": 174,
"preview": "extends layouts/default\n\nblock main\n h1 Oops something went wrong\n br\n span 404\n\nblock content\n #error-message-box\n "
},
{
"path": "app/views/500.jade",
"chars": 173,
"preview": "extends layouts/default\n\nblock main\n h1 Oops something went wrong\n br\n span 500\n\nblock content\n #error-message-box\n "
},
{
"path": "app/views/includes/foot.jade",
"chars": 1855,
"preview": "//AngularJS\nscript(type='text/javascript', src='/lib/angular/angular.js')\nscript(type='text/javascript', src='/lib/angul"
},
{
"path": "app/views/includes/head.jade",
"chars": 1419,
"preview": "head\n meta(charset='utf-8')\n meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')\n meta(name='viewport', co"
},
{
"path": "app/views/index.jade",
"chars": 119,
"preview": "extends layouts/default\n\nblock content\n section(ui-view)\n script(type=\"text/javascript\").\n window.user = !{user};\n"
},
{
"path": "app/views/layouts/default.jade",
"chars": 428,
"preview": "doctype html\nhtml(lang='en', xmlns='http://www.w3.org/1999/xhtml', xmlns:fb='https://www.facebook.com/2008/fbml', itemsc"
},
{
"path": "app.js",
"chars": 835,
"preview": "'use strict';\n\n/**\n * Module dependencies.\n */\nvar express = require('express');\nvar fs = require('fs');\n\n/"
},
{
"path": "app.json",
"chars": 614,
"preview": "{\n \"name\": \"mean-stack-relational\",\n \"description\": \"M*EAN - A Modern Stack: MySQL(Postgres for Heroku), ExpressJS"
},
{
"path": "bower.json",
"chars": 449,
"preview": "{\n \"name\": \"mean\",\n \"version\": \"0.1.0\",\n \"dependencies\": {\n \"angular\": \"latest\",\n \"angular-resource\": \"latest\","
},
{
"path": "config/config.js",
"chars": 2937,
"preview": "'use strict';\n\nvar nconf = require('nconf'),\n json5 = require('json5'),\n _ = require('lodash'),\n glob = require"
},
{
"path": "config/env/all.json5",
"chars": 343,
"preview": "{\n\tPORT: 3000, // capital PORT allows auto override by common env variable if it exists\n\tFORCE_DB_SYNC: \"false\", // must"
},
{
"path": "config/env/development.json5.sample",
"chars": 803,
"preview": "{\n // This is your MYSQL Database configuration\n db: {\n name: \"mean_relational\",\n password: \"\",\n "
},
{
"path": "config/env/production.json5.sample",
"chars": 799,
"preview": "{\n // This is your MYSQL Database configuration\n db: {\n name: \"mean_relational\",\n password: \"\",\n "
},
{
"path": "config/env/test.json5.sample",
"chars": 821,
"preview": "{\n PORT: 3001,\n // This is your MYSQL test database configuration\n db: {\n name: \"mean_relational_test\",\n"
},
{
"path": "config/env/travis.json",
"chars": 795,
"preview": "{\n \"db\": \"mongodb://localhost/mean-travis\",\n \"port\": 3001,\n \"app\": {\n \"name\": \"MEAN - A Modern Stack - T"
},
{
"path": "config/express.js",
"chars": 2500,
"preview": "'use strict';\n\n/**\n * Module dependencies.\n */\nvar express = require('express');\nvar flash = require('connect-flash');\nv"
},
{
"path": "config/middlewares/session.js",
"chars": 501,
"preview": "'use strict';\n\nvar config = require('./../config'),\n session = require('express-session'),\n db = require('./../seq"
},
{
"path": "config/passport.js",
"chars": 2710,
"preview": "'use strict';\n\nvar passport = require('passport'),\n _ = require('lodash');\n// These are different types of authentica"
},
{
"path": "config/sequelize.js",
"chars": 2386,
"preview": "'use strict';\n\nvar fs = require('fs');\nvar path = require('path');\nvar Sequelize = require('sequelize');\nvar _ = require"
},
{
"path": "config/winston.js",
"chars": 408,
"preview": "'use strict';\n\n/**\n * Created by Junaid Anwar on 5/28/15.\n */\nvar winston = require('winston');\nvar logger = new (winsto"
},
{
"path": "gruntfile.js",
"chars": 9036,
"preview": "'use strict';\n\nmodule.exports = function(grunt) {\n // Project Configuration\n grunt.initConfig({\n pkg: grunt"
},
{
"path": "package.json",
"chars": 2547,
"preview": "{\n \"name\": \"mean-stack-relational\",\n \"description\": \"M*EAN - A Modern Stack: MySQL(Postgres for Heroku), ExpressJS, An"
},
{
"path": "pm2-ecosystem.json",
"chars": 947,
"preview": "{\n \"apps\" : [{\n // mean-stack-relational app\n \"name\" : \"msr\",\n \"script\" : \"app.js\",\n // by defaul"
},
{
"path": "pm2-main.js",
"chars": 1398,
"preview": "var pm2 = require('pm2');\n\nvar instances = process.env.WEB_CONCURRENCY || 1; // Set by Heroku or 1 (set -1 to scale to m"
},
{
"path": "public/css/common.css",
"chars": 396,
"preview": ".navbar .nav>li>a.brand {\n padding-left:20px;\n margin-left:0\n}\n\n.content {\n margin-top:50px;\n width:100%\n}\n\n"
},
{
"path": "public/css/views/articles.css",
"chars": 98,
"preview": "h1 {\n text-align:center\n}\n\nul.articles li:not(:last-child) {\n border-bottom:1px solid #ccc\n}"
},
{
"path": "public/humans.txt",
"chars": 191,
"preview": "# humanstxt.org/\n# The humans responsible & technology colophon\n\n# TEAM\n\n <name> -- <role> -- <twitter>\n\n# THANKS\n\n "
},
{
"path": "public/img/.gitignore",
"chars": 0,
"preview": ""
},
{
"path": "public/js/FbSdk.js",
"chars": 176337,
"preview": "/*1453279404,,JIT Construction: v2136283,en_US*/\n\n/**\n * Copyright Facebook Inc.\n *\n * Licensed under the Apache License"
},
{
"path": "public/js/app.js",
"chars": 801,
"preview": "angular.module('mean', ['ngCookies', 'ngResource', 'ui.router', 'ui.bootstrap', 'ui.route', 'mean.system', 'mean.article"
},
{
"path": "public/js/config.js",
"chars": 1668,
"preview": "//Setting up route\nangular.module('mean').config(['$stateProvider','$urlRouterProvider', function($stateProvider,$urlRou"
},
{
"path": "public/js/controllers/articles.js",
"chars": 1716,
"preview": "angular.module('mean.articles').controller('ArticlesController', ['$scope', '$stateParams', 'Global', 'Articles', '$stat"
},
{
"path": "public/js/controllers/header.js",
"chars": 613,
"preview": "angular.module('mean.system').controller('HeaderController', ['$scope', 'Global', 'SignOut', '$state', function ($scope,"
},
{
"path": "public/js/controllers/index.js",
"chars": 141,
"preview": "angular.module('mean.system').controller('IndexController', ['$scope', 'Global', function ($scope, Global) {\n $scope."
},
{
"path": "public/js/controllers/users/auth.js",
"chars": 1444,
"preview": "angular.module('mean.auth').controller('socialAuth', ['$scope', 'Global','$state', '$fblogin', 'SocialAuth','$window','$"
},
{
"path": "public/js/controllers/users/signIn.js",
"chars": 504,
"preview": "angular.module('mean.auth').controller('signIn', ['$scope', '$window', 'Global', '$state', 'LogIn', function ($scope, $w"
},
{
"path": "public/js/controllers/users/signUp.js",
"chars": 576,
"preview": "angular.module('mean.auth').controller('signUp', ['$scope', '$window', 'Global','$state', 'SignUp', function ($scope, $w"
},
{
"path": "public/js/directives.js",
"chars": 0,
"preview": ""
},
{
"path": "public/js/filters.js",
"chars": 0,
"preview": ""
},
{
"path": "public/js/init.js",
"chars": 242,
"preview": "angular.element(document).ready(function() {\n //Fixing facebook bug with redirect\n if (window.location.hash === \"#"
},
{
"path": "public/js/services/articles.js",
"chars": 285,
"preview": "//Articles service used for articles REST endpoint\nangular.module('mean.articles').factory(\"Articles\", ['$resource', fun"
},
{
"path": "public/js/services/authenticate.js",
"chars": 698,
"preview": "\nangular.module('mean.auth').factory(\"SocialAuth\", ['$http', function ($http) {\n return {\n FbLogin: function ("
},
{
"path": "public/js/services/global.js",
"chars": 277,
"preview": "//Global service for global variables\nangular.module('mean.system').factory(\"Global\", [\n function() {\n var _th"
},
{
"path": "public/robots.txt",
"chars": 32,
"preview": "# robotstxt.org/\n\nUser-agent: *\n"
},
{
"path": "public/views/404.html",
"chars": 129,
"preview": "<section>\n <h1>ERROR #404</h1>\n <h3>The link you followed may be broken, or the page may have been removed.</h3>\n<"
},
{
"path": "public/views/articles/create.html",
"chars": 661,
"preview": "<section>\n\t<form class=\"form-horizontal\" data-ng-submit=\"create()\">\n\t\t<div class=\"control-group\">\n\t\t\t<label class=\"contr"
},
{
"path": "public/views/articles/edit.html",
"chars": 722,
"preview": "<section data-ng-init=\"findOne()\">\n\t<form class=\"form-horizontal\" data-ng-submit=\"update()\">\n\t\t<div class=\"control-group"
},
{
"path": "public/views/articles/list.html",
"chars": 479,
"preview": "<section data-ng-init=\"find()\">\n\t<ul class=\"articles unstyled\">\n\t\t<li data-ng-repeat=\"article in articles\">\n\t\t\t<span>{{a"
},
{
"path": "public/views/articles/view.html",
"chars": 418,
"preview": "<section data-ng-init=\"findOne()\">\n <span>{{article.updatedAt | date:'medium'}}</span>/\n <span>{{article.User.name"
},
{
"path": "public/views/header.html",
"chars": 1008,
"preview": "<div class=\"navbar-inner\" data-ng-controller=\"HeaderController\">\n <ul class=\"nav\">\n <li>\n <a class="
},
{
"path": "public/views/index.html",
"chars": 52,
"preview": "<section>\n\t<h1>This is the home view</h1>\n</section>"
},
{
"path": "public/views/users/auth.html",
"chars": 319,
"preview": "<div class=\"row\" data-ng-controller=\"socialAuth\">\n <div class=\"span6\"><a ng-click=\"fbAuth();\"><img src=\"/img/icons/fa"
},
{
"path": "public/views/users/signin.html",
"chars": 983,
"preview": "\n<span ng-include=\"'../views/users/auth.html'\"></span>\n<span ng-controller=\"signIn\">\n <form ng-submit=\"signIn(user)\" "
},
{
"path": "public/views/users/signup.html",
"chars": 1530,
"preview": "<div ng-include=\"'../views/users/auth.html'\"></div>\n<div ng-controller=\"signUp\">\n <form ng-submit=\"signUp(user)\" cla"
},
{
"path": "test/karma/karma.conf.js",
"chars": 2958,
"preview": "// Karma configuration\n// Generated on Sat Oct 05 2013 22:00:14 GMT+0700 (ICT)\n\nmodule.exports = function(config) {\n "
},
{
"path": "test/karma/unit/controllers/articles.spec.js",
"chars": 7893,
"preview": "(function() {\n 'use strict';\n\n // Articles Controller Spec\n describe('MEAN controllers', function() {\n\n "
},
{
"path": "test/karma/unit/controllers/headers.spec.js",
"chars": 684,
"preview": "(function() {\n 'use strict';\n\n describe('MEAN controllers', function() {\n\n describe('HeaderController', fun"
},
{
"path": "test/karma/unit/controllers/index.spec.js",
"chars": 680,
"preview": "(function() {\n 'use strict';\n\n describe('MEAN controllers', function() {\n\n describe('IndexController', func"
},
{
"path": "test/mocha/controllers/articleControllerSpec.js",
"chars": 9478,
"preview": "/**\n * Created by Ahmed Hassan on 12/11/15.\n * Set of tests demonstrating how controllers can be tested by stubbing out "
},
{
"path": "test/mocha/controllers/usersControllerSpec.js",
"chars": 43,
"preview": "'use strict';\n\n/* Users controller tests */"
},
{
"path": "test/mocha/models/userModelSpec.js",
"chars": 3916,
"preview": "'use strict';\n\n/**\n * Module dependencies.\n */\nvar chai = require('chai'),\n expect = chai.expect,\n _ = require('lo"
}
]
About this extraction
This page contains the full source code of the jpotts18/mean-stack-relational GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 75 files (277.6 KB), approximately 80.8k tokens, and a symbol index with 176 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.