Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

test app

  • Loading branch information...
commit 7875fc52b4486960d484a7674821513b845f73da 1 parent 1db2a43
@whito authored
Showing with 6,947 additions and 0 deletions.
  1. +19 −0 .gitignore
  2. +1 −0  Procfile
  3. +25 −0 README
  4. +6 −0 app/controllers/application_controller.js
  5. +18 −0 app/controllers/users_controller.js
  6. +2 −0  app/helpers/posts_helper.js
  7. +2 −0  app/helpers/users_helper.js
  8. 0  app/models/user.js
  9. +41 −0 app/views/layouts/application_layout.ejs
  10. +21 −0 app/views/layouts/login_layout.ejs
  11. +41 −0 app/views/layouts/posts_layout.ejs
  12. 0  app/views/layouts/users_layout.ejs
  13. 0  app/views/login/index.ejs
  14. +13 −0 app/views/users/_form.ejs
  15. +9 −0 app/views/users/edit.ejs
  16. +39 −0 app/views/users/index.ejs
  17. +11 −0 app/views/users/new.ejs
  18. +18 −0 app/views/users/show.ejs
  19. +10 −0 config/database.json
  20. +25 −0 config/environment.js
  21. +9 −0 config/environments/development.js
  22. +11 −0 config/environments/production.js
  23. +8 −0 config/environments/test.js
  24. +51 −0 config/initializers/db-tools.js
  25. +5 −0 config/passport.yml
  26. +14 −0 config/routes.js
  27. +30 −0 db/schema.js
  28. +3 −0  npmfile.js
  29. +25 −0 package.json
  30. BIN  public/favicon.ico
  31. BIN  public/images/glyphicons-halflings-white.png
  32. BIN  public/images/glyphicons-halflings.png
  33. +96 −0 public/index.html
  34. +1 −0  public/javascripts/application.js
  35. +1,720 −0 public/javascripts/bootstrap.js
  36. +139 −0 public/javascripts/rails.js
  37. +581 −0 public/stylesheets/bootstrap-responsive.css
  38. +3,496 −0 public/stylesheets/bootstrap.css
  39. 0  public/stylesheets/style.css
  40. +11 −0 server.js
  41. +121 −0 test/controllers/posts_controller_test.js
  42. +121 −0 test/controllers/users_controller_test.js
  43. +204 −0 test/test_helper.js
View
19 .gitignore
@@ -0,0 +1,19 @@
+dump.rdb
+lib-cov
+*.log
+*.csv
+*.out
+*.pid
+pids
+logs
+results
+node_modules
+npm-debug.log
+.idea
+.DS_Store
+log/*.log
+.c9revisions
+coverage.html
+.settings
+doc
+
View
1  Procfile
@@ -0,0 +1 @@
+web: node server.js
View
25 README
@@ -0,0 +1,25 @@
+
+NPM install
+
+node server.js
+
+got to http://localhost:3000/login
+
+see that the GET calls the custom route to the login action of the users_controller
+
+submit the form
+
+see that the POST calls the custom testpost action defined in the users_controller
+
+check out environment.js and uncomment the section:
+
+// Passport ---------------------
+//rwps.init();
+// hook up user model
+//process.nextTick(function () {
+// rwps.loadUser(User);
+//});
+//------------------------------
+
+run it again and see that the POST doesn't happen
+
View
6 app/controllers/application_controller.js
@@ -0,0 +1,6 @@
+//before('protect from forgery', function () {
+// protectFromForgery('c46b3908cb5c9fc33b344fc49947c3db17a8c4a4');
+//});
+function test(){
+ console.log('test function in th application controller');
+}
View
18 app/controllers/users_controller.js
@@ -0,0 +1,18 @@
+load('application');
+
+
+// CRUD actions removed for test
+
+action(function login() {
+ console.log("GET called for custom login action");
+ this.title= "Login Page";
+ layout("login");
+ render({
+ title: this.title
+ });
+});
+
+action(function testpost() {
+ console.log("-------------> Test POST was called");
+ send(200);
+});
View
2  app/helpers/posts_helper.js
@@ -0,0 +1,2 @@
+module.exports = {
+};
View
2  app/helpers/users_helper.js
@@ -0,0 +1,2 @@
+module.exports = {
+};
View
0  app/models/user.js
No changes.
View
41 app/views/layouts/application_layout.ejs
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title><%= title %></title>
+ <%- stylesheet_link_tag('bootstrap', 'style', 'bootstrap-responsive') %>
+ <%- javascript_include_tag('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', 'bootstrap', 'rails', 'application') %>
+ <%- csrf_meta_tag() %>
+ </head>
+ <body>
+ <div class="navbar">
+ <div class="navbar-inner">
+ <div class="container">
+ <a class="brand" href="#">Project name</a>
+ </div>
+ </div>
+ </div>
+
+ <div class="container">
+ <% var flash = request.flash('info').pop(); if (flash) { %>
+ <div class="alert alert-info">
+ <a class="close" data-dismiss="alert">×</a>
+ <%- flash %>
+ </div>
+ <% } %>
+
+ <% flash = request.flash('error').pop(); if (flash) { %>
+ <div class="alert alert-error">
+ <a class="close" data-dismiss="alert">×</a>
+ <%- flash %>
+ </div>
+ <% }; %>
+
+ <%- body %>
+
+ <hr />
+ <footer>
+ <p>&copy; Company 2012</p>
+ </footer>
+ </div>
+ </body>
+</html>
View
21 app/views/layouts/login_layout.ejs
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title><%= title %></title>
+ <%- stylesheet_link_tag( 'style') %>
+
+ </head>
+ <body>
+ <form action='/login' method='post' id='login'>
+ <fieldset>
+ <label>Username</label>
+ <input type='text' name='login' id='username' required autofocus>
+ <label>Password</label>
+ <input type='password' name='password' id='password'>
+ </fieldset>
+ <fieldset>
+ <input type='submit' class='button' value='Login'>
+ </fieldset>
+ </form>
+ </body>
+</html>
View
41 app/views/layouts/posts_layout.ejs
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <title><%= title %></title>
+ <%- stylesheet_link_tag('bootstrap', 'style', 'bootstrap-responsive') %>
+ <%- javascript_include_tag('http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', 'bootstrap', 'rails', 'application') %>
+ <%- csrf_meta_tag() %>
+ </head>
+ <body>
+ <div class="navbar">
+ <div class="navbar-inner">
+ <div class="container">
+ <a class="brand" href="#">Project name</a>
+ </div>
+ </div>
+ </div>
+
+ <div class="container">
+ <% var flash = request.flash('info').pop(); if (flash) { %>
+ <div class="alert alert-info">
+ <a class="close" data-dismiss="alert">×</a>
+ <%- flash %>
+ </div>
+ <% } %>
+
+ <% flash = request.flash('error').pop(); if (flash) { %>
+ <div class="alert alert-error">
+ <a class="close" data-dismiss="alert">×</a>
+ <%- flash %>
+ </div>
+ <% }; %>
+
+ <%- body %>
+
+ <hr />
+ <footer>
+ <p>&copy; Company 2012</p>
+ </footer>
+ </div>
+ </body>
+</html>
View
0  app/views/layouts/users_layout.ejs
No changes.
View
0  app/views/login/index.ejs
No changes.
View
13 app/views/users/_form.ejs
@@ -0,0 +1,13 @@
+<%- errorMessagesFor(user) %>
+<div class="control-group">
+ <%- form.label("login", false, {class: "control-label"}) %>
+ <div class="controls">
+ <%- form.input("login") %>
+ </div>
+</div>
+<div class="control-group">
+ <%- form.label("password", false, {class: "control-label"}) %>
+ <div class="controls">
+ <%- form.input("password") %>
+ </div>
+</div>
View
9 app/views/users/edit.ejs
@@ -0,0 +1,9 @@
+<div class="page-header"><h1>Edit user</h1></div>
+
+<% form_for(user, {action: path_to.user(user), method: 'PUT', id: "user_form", class: 'form-horizontal'}, function (form) { %>
+ <%- partial('users/form.ejs', {locals: {form: form, user: user}}) %>
+ <div class="form-actions">
+ <%- form.submit('<i class="icon-ok icon-white"></i> Update user', {class: 'btn btn-primary'}) %> or
+ <%- link_to('Cancel', path_to.user(user), {class: 'btn'}) %>
+ </div>
+<% });%>
View
39 app/views/users/index.ejs
@@ -0,0 +1,39 @@
+<div class="page-header">
+ <h1>Index of user</h1>
+</div>
+
+<div class="row">
+ <div class="span12">
+ <p><%- link_to('<i class="icon-plus icon-white"></i> New user', path_to.new_user(), {class: 'btn btn-primary'}) %></>
+ </div>
+</div>
+
+<div class="row">
+ <div class="span12">
+ <% if (users.length > 0) { %>
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th>ID</th>
+ <th>Actions</th>
+ </tr>
+ </thead>
+ <tbody>
+ <% users.forEach(function (user) { %>
+ <tr>
+ <td><strong><%- link_to('user #' + user.id, path_to.user(user)) %></strong></td>
+ <td>
+ <%- link_to('<i class="icon-edit"></i> Edit', path_to.edit_user(user), {class: 'btn btn-mini'}) %>
+ <%- link_to('<i class="icon-remove icon-white"></i> Delete', path_to.user(user), {class: 'btn btn-mini btn-danger', method: 'delete', remote: true, jsonp: '(function (u) {location.href = u;})'}) %>
+ </td>
+ </tr>
+ <% }); %>
+ </tbody>
+ </table>
+ <% } else { %>
+ <p class="alert alert-block alert-info">
+ <strong>No users were found.</strong>
+ </p>
+ <% } %>
+ </div>
+</div>
View
11 app/views/users/new.ejs
@@ -0,0 +1,11 @@
+<div class="page-header">
+ <h1>New user</h1>
+</div>
+
+<% form_for(user, {action: path_to.users(), method: 'POST', id: "user_form", class: 'form-horizontal'}, function (form) { %>
+ <%- partial('users/form.ejs', {locals: {form: form, user: user}}) %>
+ <div class="form-actions">
+ <%- form.submit('<i class="icon-ok icon-white"></i> Create user', {class: 'btn btn-primary'}) %> or
+ <%- link_to('Cancel', path_to.users(), {class: 'btn'}) %>
+ </div>
+<% });%>
View
18 app/views/users/show.ejs
@@ -0,0 +1,18 @@
+<div class="page-header">
+ <h1>Details of user</h1>
+</div>
+
+
+<table class="table table-bordered">
+ <tbody>
+ <tr><th>login</th><td><%= user.login %></td></tr>
+ <tr><th>password</th><td><%= user.password %></td></tr>
+ </tbody>
+</table>
+
+<div class="well">
+ <%- link_to('<i class="icon-edit icon-white"></i> Edit', path_to.edit_user(user), {class: 'btn btn-primary'}) %>
+ <%- link_to('<i class="icon-remove icon-white"></i> Delete', path_to.user(user), {class: 'btn btn-danger', method: 'delete', remote: true, jsonp: '(function (u) { location.href = u; })'}) %>
+ or
+ <%- link_to('Back to index', path_to.users()) %>
+</div>
View
10 config/database.json
@@ -0,0 +1,10 @@
+{ "development":
+ { "driver": "memory"
+ }
+, "test":
+ { "driver": "memory"
+ }
+, "production":
+ { "driver": "memory"
+ }
+}
View
25 config/environment.js
@@ -0,0 +1,25 @@
+var express = require('express');
+var rwps = require('railway-passport');
+
+app.configure(function(){
+ var cwd = process.cwd();
+
+ app.use(express.static(cwd + '/public', {maxAge: 86400000}));
+ app.set('view engine', 'ejs');
+ app.set('view options', {complexNames: true});
+ app.set('jsDirectory', '/javascripts/');
+ app.set('cssDirectory', '/stylesheets/');
+ app.use(express.bodyParser());
+ app.use(express.cookieParser('secret'));
+ app.use(express.session({secret: 'secret'}));
+ app.use(express.methodOverride());
+ // Passport ---------------------
+ //rwps.init();
+ // hook up user model
+ //process.nextTick(function () {
+ // rwps.loadUser(User);
+ //});
+ //------------------------------
+ app.use(app.router);
+});
+
View
9 config/environments/development.js
@@ -0,0 +1,9 @@
+app.configure('development', function () {
+ app.disable('view cache');
+ app.disable('model cache');
+ app.disable('eval cache');
+ app.enable('log actions');
+ app.enable('env info');
+ app.use(require('express').errorHandler({ dumpExceptions: true, showStack: true }));
+});
+
View
11 config/environments/production.js
@@ -0,0 +1,11 @@
+app.configure('production', function () {
+ app.enable('view cache');
+ app.enable('model cache');
+ app.enable('eval cache');
+ app.enable('merge javascripts');
+ app.enable('merge stylesheets');
+ app.disable('assets timestamps');
+ app.use(require('express').errorHandler());
+ app.settings.quiet = true;
+});
+
View
8 config/environments/test.js
@@ -0,0 +1,8 @@
+app.configure('test', function(){
+ app.use(require('express').errorHandler({ dumpExceptions: true, showStack: true }));
+ app.settings.quiet = true;
+ app.enable('view cache');
+ app.enable('model cache');
+ app.enable('eval cache');
+});
+
View
51 config/initializers/db-tools.js
@@ -0,0 +1,51 @@
+railway.tools.database = function db() {
+ var action = process.argv[3];
+ switch (action) {
+ case 'migrate':
+ case 'update':
+ perform(action, process.exit);
+ break;
+ default:
+ console.log('Unknown action', action);
+ break;
+ }
+};
+
+railway.tools.database.help = {
+ shortcut: 'db',
+ usage: 'db [migrate|update]',
+ description: 'Migrate or update database(s)'
+};
+
+function getUniqueSchemas() {
+ var schemas = [];
+ Object.keys(app.models).forEach(function (modelName) {
+ var Model = app.models[modelName];
+ var schema = Model.schema;
+ if (!~schemas.indexOf(schema)) {
+ schemas.push(schema);
+ }
+ });
+ return schemas;
+}
+
+function perform(action, callback) {
+ console.log('Perform', action, 'on');
+ var wait = 0;
+ getUniqueSchemas().forEach(function (schema) {
+ if (schema['auto' + action]) {
+ console.log(' - ' + schema.name);
+ wait += 1;
+ process.nextTick(function () {
+ schema['auto' + action](done);
+ });
+ }
+ });
+
+ if (wait === 0) done(); else console.log(wait);
+
+ function done() {
+ if (--wait === 0) callback();
+ }
+}
+
View
5 config/passport.yml
@@ -0,0 +1,5 @@
+development:
+ baseURL: "http://localhost:3000/"
+ local:
+ usernameField: "login"
+ passwordField: "password"
View
14 config/routes.js
@@ -0,0 +1,14 @@
+exports.routes = function (map) {
+
+ map.resources('users');
+
+ // Generic routes. Add all your routes below this line
+ // feel free to remove generic routes
+ //map.all(':controller/:action');
+ //map.all(':controller/:action/:id');
+
+ // test routes
+ map.get('login', 'users#login');
+ map.post('login', 'users#testpost');
+
+};
View
30 db/schema.js
@@ -0,0 +1,30 @@
+/*
+ db/schema.js contains database schema description for application models
+ by default (when using jugglingdb as ORM) this file uses database connection
+ described in config/database.json. But it's possible to use another database
+ connections and multiple different schemas, docs available at
+
+ http://railwayjs.com/orm.html
+
+ Example of model definition:
+
+ define('User', function () {
+ property('email', String, { index: true });
+ property('password', String);
+ property('activated', Boolean, {default: false});
+ });
+
+ Example of schema configured without config/database.json (heroku redistogo addon):
+ schema('redis', {url: process.env.REDISTOGO_URL}, function () {
+ // model definitions here
+ });
+
+*/
+
+var User = describe('User', function () {
+ property('login', String);
+ property('password', String);
+});var Post = describe('Post', function () {
+ property('name', String);
+ property('content', String);
+});
View
3  npmfile.js
@@ -0,0 +1,3 @@
+require('ejs-ext');
+require('jugglingdb');
+require('seedjs');
View
25 package.json
@@ -0,0 +1,25 @@
+{ "name": "test"
+, "version": "0.0.1"
+, "engines": ["node >= 0.4.0"]
+, "main": "server.js"
+, "dependencies":
+ { "ejs": "*"
+ , "ejs-ext": "*"
+ , "express": "~2.x"
+ , "railway": ">= 0.2.6"
+ , "jugglingdb": ">= 0.1.0"
+ , "coffee-script": ">= 1.1.1"
+ , "railway-passport": "*"
+ , "passport": "*"
+ , "passport-local": "*"
+
+ },
+ "devDependencies":
+ { "nodeunit": "*"
+ , "sinon": "*"
+ , "semicov": "*"
+ }
+, "scripts":
+ { "test": "nodeunit test/*/*"
+ }
+}
View
BIN  public/favicon.ico
Binary file not shown
View
BIN  public/images/glyphicons-halflings-white.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  public/images/glyphicons-halflings.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
96 public/index.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Welcome to Railway</title>
+ <link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.3.0/bootstrap.min.css">
+ <meta name="viewport" content="width=500, initial-scale=0.5">
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
+ <script type="text/javascript" src="/javascripts/rails.js"></script>
+ </head>
+ <body>
+ <div class="container">
+ <div class="page-header">
+ <h1 style="text-align: center; padding: 35px;">Welcome to Railway</h1>
+ </div>
+ <h6 style="text-align: center;">
+ <a href="/railway/environment.json" id="show-env-info-link" data-remote="true" data-jsonp="load">Information about application environment</a>
+ </h6>
+ <div id="env-info"></div>
+ <hr />
+ <div class="row">
+ <div class="span8 offset4">
+ <a href="http://github.com/1602/express-on-railway"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://d3nwyuy0nl342s.cloudfront.net/img/e6bef7a091f5f3138b8cd40bc3e114258dd68ddf/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f7265645f6161303030302e706e67" alt="Fork me on GitHub"></a>
+ <div class="content">
+ <h6>1. Start with <a href="http://railwayjs.com/#generators">generators</a></h6>
+ <p> this is a fastest way to create application:</p>
+ <pre>railway g crud post title content date:date published:boolean</pre>
+ <h6>2. Then describe <a href="http://railwayjs.com/#routing">routes</a></h6>
+ <p>in <code>config/routes.js</code> and remove this file (<code>public/index.html</code>)</p>
+ <pre>exports.routes = function (map) {
+ map.get('/', 'posts#index');
+};</pre>
+ <h6>3. Design your <a href="http://railwayjs.com/#orm">database</a></h6>
+ <p>in <code>db/schema.js</code> and describe models in <code>app/models/*</code></p>
+ <h6>4. Keep you <a href="http://railwayjs.com/#controllers">controllers</a> thin</h6>
+ <p>write tests, and good luck.<br> If you have any questions feel free to ask at <a href="http://groups.google.com/group/railwayjs">RailwayJS Google Group</a>.</p>
+ <p>Track RailwayJS project state on <a href="https://trello.com/board/railwayjs/4f0a0d49128365065e008a1d">trello board</a>, vote for features, discuss. Help us to get better!</p>
+ </div>
+ </div>
+
+ <div class="span4">
+ <p>
+ <h6>5. Links in sidebar</h6>
+ <ul style="padding-left: 0px;">
+ <li><a href="http://railwayjs.com">RailwayJS project docs</a></li>
+ <li><a href="http://modules.node-js.ru">NodeJS modules rating</a></li>
+ <li><a href="http://expressjs.com">ExpressJS project homepage</a></li>
+ <li><a href="http://mongoosejs.com">MongooseJS ORM project homepage</a></li>
+ <li><a href="http://railwayjs.com/juggling.html">Try JugglingDB in your browser, docs</a></li>
+ </ul>
+ </p>
+ </div>
+
+ </div>
+ <footer>
+ </footer>
+ <script>
+ function load(data) {
+ $('#show-env-info-link').hide();
+ if (data.forbidden) {
+ return '';
+ }
+ var html = '<table class=".zebra-striped">';
+ html += makeList('Versions', data.versions);
+ html += makeList('Settings', data.settings);
+ html += makeList('Application', data.application);
+ html += makeList('ENV', data.env);
+ html += '</table>';
+
+ $('#env-info').html(html);
+ }
+
+ function makeList(title, obj) {
+ var res = '<tr><td colspan="2"><h6>' + title + '</h6></td></tr>';
+ for (var i in obj) {
+ res += '<tr><td>' + i + '</td><td>' + toS(obj[i]) + '</td></tr>';
+ }
+ return res;
+ }
+
+ function toS(obj) {
+ if (obj instanceof Array) {
+ return obj.join('<br />');
+ } else if (typeof obj === 'object') {
+ var s = [];
+ for (var i in obj) {
+ s.push(i + ': ' + obj[i]);
+ }
+ return s.join(', ');
+ } else {
+ return obj;
+ }
+ }
+ </script>
+ </div>
+ </body>
+</html>
View
1  public/javascripts/application.js
@@ -0,0 +1 @@
+// place your application-wide javascripts here
View
1,720 public/javascripts/bootstrap.js
@@ -0,0 +1,1720 @@
+/* ===================================================
+ * bootstrap-transition.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
+ * ===================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function( $ ) {
+
+ $(function () {
+
+ "use strict"
+
+ /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
+ * ======================================================= */
+
+ $.support.transition = (function () {
+ var thisBody = document.body || document.documentElement
+ , thisStyle = thisBody.style
+ , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
+
+ return support && {
+ end: (function () {
+ var transitionEnd = "TransitionEnd"
+ if ( $.browser.webkit ) {
+ transitionEnd = "webkitTransitionEnd"
+ } else if ( $.browser.mozilla ) {
+ transitionEnd = "transitionend"
+ } else if ( $.browser.opera ) {
+ transitionEnd = "oTransitionEnd"
+ }
+ return transitionEnd
+ }())
+ }
+ })()
+
+ })
+
+}( window.jQuery );/* ==========================================================
+ * bootstrap-alert.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* ALERT CLASS DEFINITION
+ * ====================== */
+
+ var dismiss = '[data-dismiss="alert"]'
+ , Alert = function ( el ) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.prototype = {
+
+ constructor: Alert
+
+ , close: function ( e ) {
+ var $this = $(this)
+ , selector = $this.attr('data-target')
+ , $parent
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+ $parent.trigger('close')
+
+ e && e.preventDefault()
+
+ $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
+
+ $parent
+ .trigger('close')
+ .removeClass('in')
+
+ function removeElement() {
+ $parent
+ .trigger('closed')
+ .remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent.on($.support.transition.end, removeElement) :
+ removeElement()
+ }
+
+ }
+
+
+ /* ALERT PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.alert = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('alert')
+ if (!data) $this.data('alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.alert.Constructor = Alert
+
+
+ /* ALERT DATA-API
+ * ============== */
+
+ $(function () {
+ $('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
+ })
+
+}( window.jQuery );/* ============================================================
+ * bootstrap-button.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+!function( $ ){
+
+ "use strict"
+
+ /* BUTTON PUBLIC CLASS DEFINITION
+ * ============================== */
+
+ var Button = function ( element, options ) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.button.defaults, options)
+ }
+
+ Button.prototype = {
+
+ constructor: Button
+
+ , setState: function ( state ) {
+ var d = 'disabled'
+ , $el = this.$element
+ , data = $el.data()
+ , val = $el.is('input') ? 'val' : 'html'
+
+ state = state + 'Text'
+ data.resetText || $el.data('resetText', $el[val]())
+
+ $el[val](data[state] || this.options[state])
+
+ // push to event loop to allow forms to submit
+ setTimeout(function () {
+ state == 'loadingText' ?
+ $el.addClass(d).attr(d, d) :
+ $el.removeClass(d).removeAttr(d)
+ }, 0)
+ }
+
+ , toggle: function () {
+ var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
+
+ $parent && $parent
+ .find('.active')
+ .removeClass('active')
+
+ this.$element.toggleClass('active')
+ }
+
+ }
+
+
+ /* BUTTON PLUGIN DEFINITION
+ * ======================== */
+
+ $.fn.button = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('button')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('button', (data = new Button(this, options)))
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ $.fn.button.defaults = {
+ loadingText: 'loading...'
+ }
+
+ $.fn.button.Constructor = Button
+
+
+ /* BUTTON DATA-API
+ * =============== */
+
+ $(function () {
+ $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ $btn.button('toggle')
+ })
+ })
+
+}( window.jQuery );/* ==========================================================
+ * bootstrap-carousel.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
+ * ==========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* CAROUSEL CLASS DEFINITION
+ * ========================= */
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.carousel.defaults, options)
+ this.options.slide && this.slide(this.options.slide)
+ }
+
+ Carousel.prototype = {
+
+ cycle: function () {
+ this.interval = setInterval($.proxy(this.next, this), this.options.interval)
+ return this
+ }
+
+ , to: function (pos) {
+ var $active = this.$element.find('.active')
+ , children = $active.parent().children()
+ , activePos = children.index($active)
+ , that = this
+
+ if (pos > (children.length - 1) || pos < 0) return
+
+ if (this.sliding) {
+ return this.$element.one('slid', function () {
+ that.to(pos)
+ })
+ }
+
+ if (activePos == pos) {
+ return this.pause().cycle()
+ }
+
+ return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
+ }
+
+ , pause: function () {
+ clearInterval(this.interval)
+ this.interval = null
+ return this
+ }
+
+ , next: function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ , prev: function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ , slide: function (type, next) {
+ var $active = this.$element.find('.active')
+ , $next = next || $active[type]()
+ , isCycling = this.interval
+ , direction = type == 'next' ? 'left' : 'right'
+ , fallback = type == 'next' ? 'first' : 'last'
+ , that = this
+
+ if (!$next.length) return
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ $next = $next.length ? $next : this.$element.find('.item')[fallback]()
+
+ if (!$.support.transition && this.$element.hasClass('slide')) {
+ this.$element.trigger('slide')
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger('slid')
+ } else {
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ this.$element.trigger('slide')
+ this.$element.one($.support.transition.end, function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
+ })
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+ }
+
+
+ /* CAROUSEL PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.carousel = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('carousel')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (typeof option == 'string' || (option = options.slide)) data[option]()
+ else data.cycle()
+ })
+ }
+
+ $.fn.carousel.defaults = {
+ interval: 5000
+ }
+
+ $.fn.carousel.Constructor = Carousel
+
+
+ /* CAROUSEL DATA-API
+ * ================= */
+
+ $(function () {
+ $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data())
+ $target.carousel(options)
+ e.preventDefault()
+ })
+ })
+
+}( window.jQuery );/* =============================================================
+ * bootstrap-collapse.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+!function( $ ){
+
+ "use strict"
+
+ var Collapse = function ( element, options ) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.collapse.defaults, options)
+
+ if (this.options["parent"]) {
+ this.$parent = $(this.options["parent"])
+ }
+
+ this.options.toggle && this.toggle()
+ }
+
+ Collapse.prototype = {
+
+ constructor: Collapse
+
+ , dimension: function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ , show: function () {
+ var dimension = this.dimension()
+ , scroll = $.camelCase(['scroll', dimension].join('-'))
+ , actives = this.$parent && this.$parent.find('.in')
+ , hasData
+
+ if (actives && actives.length) {
+ hasData = actives.data('collapse')
+ actives.collapse('hide')
+ hasData || actives.data('collapse', null)
+ }
+
+ this.$element[dimension](0)
+ this.transition('addClass', 'show', 'shown')
+ this.$element[dimension](this.$element[0][scroll])
+
+ }
+
+ , hide: function () {
+ var dimension = this.dimension()
+ this.reset(this.$element[dimension]())
+ this.transition('removeClass', 'hide', 'hidden')
+ this.$element[dimension](0)
+ }
+
+ , reset: function ( size ) {
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ [dimension](size || 'auto')
+ [0].offsetWidth
+
+ this.$element.addClass('collapse')
+ }
+
+ , transition: function ( method, startEvent, completeEvent ) {
+ var that = this
+ , complete = function () {
+ if (startEvent == 'show') that.reset()
+ that.$element.trigger(completeEvent)
+ }
+
+ this.$element
+ .trigger(startEvent)
+ [method]('in')
+
+ $.support.transition && this.$element.hasClass('collapse') ?
+ this.$element.one($.support.transition.end, complete) :
+ complete()
+ }
+
+ , toggle: function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+ /* COLLAPSIBLE PLUGIN DEFINITION
+ * ============================== */
+
+ $.fn.collapse = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('collapse')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.collapse.defaults = {
+ toggle: true
+ }
+
+ $.fn.collapse.Constructor = Collapse
+
+
+ /* COLLAPSIBLE DATA-API
+ * ==================== */
+
+ $(function () {
+ $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
+ var $this = $(this), href
+ , target = $this.attr('data-target')
+ || e.preventDefault()
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
+ $(target).collapse(option)
+ })
+ })
+
+}( window.jQuery );/* ============================================================
+ * bootstrap-dropdown.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
+ * ============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* DROPDOWN CLASS DEFINITION
+ * ========================= */
+
+ var toggle = '[data-toggle="dropdown"]'
+ , Dropdown = function ( element ) {
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
+ $('html').on('click.dropdown.data-api', function () {
+ $el.parent().removeClass('open')
+ })
+ }
+
+ Dropdown.prototype = {
+
+ constructor: Dropdown
+
+ , toggle: function ( e ) {
+ var $this = $(this)
+ , selector = $this.attr('data-target')
+ , $parent
+ , isActive
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ $parent = $(selector)
+ $parent.length || ($parent = $this.parent())
+
+ isActive = $parent.hasClass('open')
+
+ clearMenus()
+ !isActive && $parent.toggleClass('open')
+
+ return false
+ }
+
+ }
+
+ function clearMenus() {
+ $(toggle).parent().removeClass('open')
+ }
+
+
+ /* DROPDOWN PLUGIN DEFINITION
+ * ========================== */
+
+ $.fn.dropdown = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('dropdown')
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
+ * =================================== */
+
+ $(function () {
+ $('html').on('click.dropdown.data-api', clearMenus)
+ $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ })
+
+}( window.jQuery );/* =========================================================
+ * bootstrap-modal.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#modals
+ * =========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================= */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* MODAL CLASS DEFINITION
+ * ====================== */
+
+ var Modal = function ( content, options ) {
+ this.options = options
+ this.$element = $(content)
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
+ }
+
+ Modal.prototype = {
+
+ constructor: Modal
+
+ , toggle: function () {
+ return this[!this.isShown ? 'show' : 'hide']()
+ }
+
+ , show: function () {
+ var that = this
+
+ if (this.isShown) return
+
+ $('body').addClass('modal-open')
+
+ this.isShown = true
+ this.$element.trigger('show')
+
+ escape.call(this)
+ backdrop.call(this, function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position
+
+ that.$element
+ .show()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ transition ?
+ that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
+ that.$element.trigger('shown')
+
+ })
+ }
+
+ , hide: function ( e ) {
+ e && e.preventDefault()
+
+ if (!this.isShown) return
+
+ var that = this
+ this.isShown = false
+
+ $('body').removeClass('modal-open')
+
+ escape.call(this)
+
+ this.$element
+ .trigger('hide')
+ .removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ hideWithTransition.call(this) :
+ hideModal.call(this)
+ }
+
+ }
+
+
+ /* MODAL PRIVATE METHODS
+ * ===================== */
+
+ function hideWithTransition() {
+ var that = this
+ , timeout = setTimeout(function () {
+ that.$element.off($.support.transition.end)
+ hideModal.call(that)
+ }, 500)
+
+ this.$element.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ hideModal.call(that)
+ })
+ }
+
+ function hideModal( that ) {
+ this.$element
+ .hide()
+ .trigger('hidden')
+
+ backdrop.call(this)
+ }
+
+ function backdrop( callback ) {
+ var that = this
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
+ .appendTo(document.body)
+
+ if (this.options.backdrop != 'static') {
+ this.$backdrop.click($.proxy(this.hide, this))
+ }
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ doAnimate ?
+ this.$backdrop.one($.support.transition.end, callback) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ $.support.transition && this.$element.hasClass('fade')?
+ this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
+ removeBackdrop.call(this)
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ function removeBackdrop() {
+ this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ function escape() {
+ var that = this
+ if (this.isShown && this.options.keyboard) {
+ $(document).on('keyup.dismiss.modal', function ( e ) {
+ e.which == 27 && that.hide()
+ })
+ } else if (!this.isShown) {
+ $(document).off('keyup.dismiss.modal')
+ }
+ }
+
+
+ /* MODAL PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.modal = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('modal')
+ , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option]()
+ else if (options.show) data.show()
+ })
+ }
+
+ $.fn.modal.defaults = {
+ backdrop: true
+ , keyboard: true
+ , show: true
+ }
+
+ $.fn.modal.Constructor = Modal
+
+
+ /* MODAL DATA-API
+ * ============== */
+
+ $(function () {
+ $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
+ var $this = $(this), href
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ , option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
+
+ e.preventDefault()
+ $target.modal(option)
+ })
+ })
+
+}( window.jQuery );/* ===========================================================
+ * bootstrap-tooltip.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ========================================================== */
+
+!function( $ ) {
+
+ "use strict"
+
+ /* TOOLTIP PUBLIC CLASS DEFINITION
+ * =============================== */
+
+ var Tooltip = function ( element, options ) {
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.prototype = {
+
+ constructor: Tooltip
+
+ , init: function ( type, element, options ) {
+ var eventIn
+ , eventOut
+
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.enabled = true
+
+ if (this.options.trigger != 'manual') {
+ eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
+ eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
+ this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ , getOptions: function ( options ) {
+ options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay
+ , hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ , enter: function ( e ) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.show) {
+ self.show()
+ } else {
+ self.hoverState = 'in'
+ setTimeout(function() {
+ if (self.hoverState == 'in') {
+ self.show()
+ }
+ }, self.options.delay.show)
+ }
+ }
+
+ , leave: function ( e ) {
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
+
+ if (!self.options.delay || !self.options.delay.hide) {
+ self.hide()
+ } else {
+ self.hoverState = 'out'
+ setTimeout(function() {
+ if (self.hoverState == 'out') {
+ self.hide()
+ }
+ }, self.options.delay.hide)
+ }
+ }
+
+ , show: function () {
+ var $tip
+ , inside
+ , pos
+ , actualWidth
+ , actualHeight
+ , placement
+ , tp
+
+ if (this.hasContent() && this.enabled) {
+ $tip = this.tip()
+ this.setContent()
+
+ if (this.options.animation) {
+ $tip.addClass('fade')
+ }
+
+ placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ inside = /in/.test(placement)
+
+ $tip
+ .remove()
+ .css({ top: 0, left: 0, display: 'block' })
+ .appendTo(inside ? this.$element : document.body)
+
+ pos = this.getPosition(inside)
+
+ actualWidth = $tip[0].offsetWidth
+ actualHeight = $tip[0].offsetHeight
+
+ switch (inside ? placement.split(' ')[1] : placement) {
+ case 'bottom':
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'top':
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
+ break
+ case 'left':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
+ break
+ case 'right':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
+ break
+ }
+
+ $tip
+ .css(tp)
+ .addClass(placement)
+ .addClass('in')
+ }
+ }
+
+ , setContent: function () {
+ var $tip = this.tip()
+ $tip.find('.tooltip-inner').html(this.getTitle())
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ , hide: function () {
+ var that = this
+ , $tip = this.tip()
+
+ $tip.removeClass('in')
+
+ function removeWithAnimation() {
+ var timeout = setTimeout(function () {
+ $tip.off($.support.transition.end).remove()
+ }, 500)
+
+ $tip.one($.support.transition.end, function () {
+ clearTimeout(timeout)
+ $tip.remove()
+ })
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ removeWithAnimation() :
+ $tip.remove()
+ }
+
+ , fixTitle: function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
+ }
+ }
+
+ , hasContent: function () {
+ return this.getTitle()
+ }
+
+ , getPosition: function (inside) {
+ return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
+ width: this.$element[0].offsetWidth
+ , height: this.$element[0].offsetHeight
+ })
+ }
+
+ , getTitle: function () {
+ var title
+ , $e = this.$element
+ , o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ title = title.toString().replace(/(^\s*|\s*$)/, "")
+
+ return title
+ }
+
+ , tip: function () {
+ return this.$tip = this.$tip || $(this.options.template)
+ }
+
+ , validate: function () {
+ if (!this.$element[0].parentNode) {
+ this.hide()
+ this.$element = null
+ this.options = null
+ }
+ }
+
+ , enable: function () {
+ this.enabled = true
+ }
+
+ , disable: function () {
+ this.enabled = false
+ }
+
+ , toggleEnabled: function () {
+ this.enabled = !this.enabled
+ }
+
+ , toggle: function () {
+ this[this.tip().hasClass('in') ? 'hide' : 'show']()
+ }
+
+ }
+
+
+ /* TOOLTIP PLUGIN DEFINITION
+ * ========================= */
+
+ $.fn.tooltip = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tooltip')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tooltip.Constructor = Tooltip
+
+ $.fn.tooltip.defaults = {
+ animation: true
+ , delay: 0
+ , selector: false
+ , placement: 'top'
+ , trigger: 'hover'
+ , title: ''
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
+ }
+
+}( window.jQuery );/* ===========================================================
+ * bootstrap-popover.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
+ * ===========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * =========================================================== */
+
+
+!function( $ ) {
+
+ "use strict"
+
+ var Popover = function ( element, options ) {
+ this.init('popover', element, options)
+ }
+
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
+ ========================================== */
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
+
+ constructor: Popover
+
+ , setContent: function () {
+ var $tip = this.tip()
+ , title = this.getTitle()
+ , content = this.getContent()
+
+ $tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
+ $tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content)
+
+ $tip.removeClass('fade top bottom left right in')
+ }
+
+ , hasContent: function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ , getContent: function () {
+ var content
+ , $e = this.$element
+ , o = this.options
+
+ content = $e.attr('data-content')
+ || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
+
+ content = content.toString().replace(/(^\s*|\s*$)/, "")
+
+ return content
+ }
+
+ , tip: function() {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ }
+ return this.$tip
+ }
+
+ })
+
+
+ /* POPOVER PLUGIN DEFINITION
+ * ======================= */
+
+ $.fn.popover = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('popover')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.popover.Constructor = Popover
+
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
+ placement: 'right'
+ , content: ''
+ , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
+ })
+
+}( window.jQuery );/* =============================================================
+ * bootstrap-scrollspy.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================== */
+
+!function ( $ ) {
+
+ "use strict"
+
+ /* SCROLLSPY CLASS DEFINITION
+ * ========================== */
+
+ function ScrollSpy( element, options) {
+ var process = $.proxy(this.process, this)
+ , $element = $(element).is('body') ? $(window) : $(element)
+ , href
+ this.options = $.extend({}, $.fn.scrollspy.defaults, options)
+ this.$scrollElement = $element.on('scroll.scroll.data-api', process)
+ this.selector = (this.options.target
+ || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
+ || '') + ' .nav li > a'
+ this.$body = $('body').on('click.scroll.data-api', this.selector, process)
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.prototype = {
+
+ constructor: ScrollSpy
+
+ , refresh: function () {
+ this.targets = this.$body
+ .find(this.selector)
+ .map(function () {
+ var href = $(this).attr('href')
+ return /^#\w/.test(href) && $(href).length ? href : null
+ })
+
+ this.offsets = $.map(this.targets, function (id) {
+ return $(id).position().top
+ })
+ }
+
+ , process: function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ , offsets = this.offsets
+ , targets = this.targets
+ , activeTarget = this.activeTarget
+ , i
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+ && this.activate( targets[i] )
+ }
+ }
+
+ , activate: function (target) {
+ var active
+
+ this.activeTarget = target
+
+ this.$body
+ .find(this.selector).parent('.active')
+ .removeClass('active')
+
+ active = this.$body
+ .find(this.selector + '[href="' + target + '"]')
+ .parent('li')
+ .addClass('active')
+
+ if ( active.parent('.dropdown-menu') ) {
+ active.closest('li.dropdown').addClass('active')
+ }
+ }
+
+ }
+
+
+ /* SCROLLSPY PLUGIN DEFINITION
+ * =========================== */
+
+ $.fn.scrollspy = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('scrollspy')
+ , options = typeof option == 'object' && option
+ if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+ $.fn.scrollspy.defaults = {
+ offset: 10
+ }
+
+
+ /* SCROLLSPY DATA-API
+ * ================== */
+
+ $(function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ $spy.scrollspy($spy.data())
+ })
+ })
+
+}( window.jQuery );/* ========================================================
+ * bootstrap-tab.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
+ * ========================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ======================================================== */
+
+
+!function( $ ){
+
+ "use strict"
+
+ /* TAB CLASS DEFINITION
+ * ==================== */
+
+ var Tab = function ( element ) {
+ this.element = $(element)
+ }
+
+ Tab.prototype = {
+
+ constructor: Tab
+
+ , show: function () {
+ var $this = this.element
+ , $ul = $this.closest('ul:not(.dropdown-menu)')
+ , selector = $this.attr('data-target')
+ , previous
+ , $target
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
+ }
+
+ if ( $this.parent('li').hasClass('active') ) return
+
+ previous = $ul.find('.active a').last()[0]
+
+ $this.trigger({
+ type: 'show'
+ , relatedTarget: previous
+ })
+
+ $target = $(selector)
+
+ this.activate($this.parent('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $this.trigger({
+ type: 'shown'
+ , relatedTarget: previous
+ })
+ })
+ }
+
+ , activate: function ( element, container, callback) {
+ var $active = container.find('> .active')
+ , transition = callback
+ && $.support.transition
+ && $active.hasClass('fade')
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+
+ element.addClass('active')
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if ( element.parent('.dropdown-menu') ) {
+ element.closest('li.dropdown').addClass('active')
+ }
+
+ callback && callback()
+ }
+
+ transition ?
+ $active.one($.support.transition.end, next) :
+ next()
+
+ $active.removeClass('in')
+ }
+ }
+
+
+ /* TAB PLUGIN DEFINITION
+ * ===================== */
+
+ $.fn.tab = function ( option ) {
+ return this.each(function () {
+ var $this = $(this)
+ , data = $this.data('tab')
+ if (!data) $this.data('tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ $.fn.tab.Constructor = Tab
+
+
+ /* TAB DATA-API
+ * ============ */
+
+ $(function () {
+ $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
+ e.preventDefault()
+ $(this).tab('show')
+ })
+ })
+
+}( window.jQuery );/* =============================================================
+ * bootstrap-typeahead.js v2.0.1
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
+ * =============================================================
+ * Copyright 2012 Twitter, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============================================================ */
+
+!function( $ ){
+
+ "use strict"
+
+ var Typeahead = function ( element, options ) {
+ this.$element = $(element)
+ this.options = $.extend({}, $.fn.typeahead.defaults, options)
+ this.matcher = this.options.matcher || this.matcher
+ this.sorter = this.options.sorter || this.sorter
+ this.highlighter = this.options.highlighter || this.highlighter
+ this.$menu = $(this.options.menu).appendTo('body')
+ this.source = this.options.source
+ this.shown = false
+ this.listen()
+ }
+
+ Typeahead.prototype = {
+
+ constructor: Typeahead
+
+ , select: function () {
+ var val = this.$menu.find('.active').attr('data-value')
+ this.$element.val(val)
+ return this.hide()
+ }
+
+ , show: function () {
+ var pos = $.extend({}, this.$element.offset(), {
+ height: this.$element[0].offsetHeight
+ })
+
+ this.$menu.css({
+ top: pos.top + pos.height
+ , left: pos.left
+ })
+
+ this.$menu.show()
+ this.shown = true
+ return this
+ }
+
+ , hide: function () {
+ this.$menu.hide()
+ this.shown = false
+ return this
+ }
+
+ , lookup: function (event) {
+ var that = this
+ , items
+ , q
+
+ this.query = this.$element.val()
+
+ if (!this.query) {
+ return this.shown ? this.hide() : this
+ }
+
+ items = $.grep(this.source, function (item) {
+ if (that.matcher(item)) return item
+ })
+
+ items = this.sorter(items)
+
+ if (!items.length) {
+ return this.shown ? this.hide() : this
+ }
+
+ return this.render(items.slice(0, this.options.items)).show()
+ }
+
+ , matcher: function (item) {
+ return ~item.toLowerCase().indexOf(this.query.toLowerCase())
+ }
+
+ , sorter: function (items) {
+ var beginswith = []
+ , caseSensitive = []
+ , caseInsensitive = []
+ , item
+
+ while (item = items.shift()) {
+ if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
+ else if (~item.indexOf(this.query)) caseSensitive.push(item)
+ else caseInsensitive.push(item)
+ }
+
+ return beginswith.concat(caseSensitive, caseInsensitive)
+ }
+
+ , highlighter: function (item) {
+ return item.replace(new RegExp('(' + this.query + ')', 'ig'), function ($1, match) {
+ return '<strong>' + match + '</strong>'
+ })
+ }
+
+ , render: function (items) {
+ var that = this
+
+ items = $(items).map(function (i, item) {
+ i = $(that.options.item).attr('data-value', item)
+ i.find('a').html(that.highlighter(item))
+ return i[0]
+ })
+
+ items.first().addClass('active')
+ this.$menu.html(items)
+ return this
+ }
+
+ , next: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , next = active.next()
+
+ if (!next.length) {
+ next = $(this.$menu.find('li')[0])
+ }
+
+ next.addClass('active')
+ }
+
+ , prev: function (event) {
+ var active = this.$menu.find('.active').removeClass('active')
+ , prev = active.prev()
+
+ if (!prev.length) {
+ prev = this.$menu.find('li').last()
+ }
+
+ prev.addClass('active')
+ }
+
+ , listen: function () {
+ this.$element
+ .on('blur', $.proxy(this.blur, this))
+ .on('keypress', $.proxy(this.keypress, this))
+ .on('keyup', $.proxy(this.keyup, this))
+
+ if ($.browser.webkit || $.browser.msie) {
+ this.$element.on('keydown', $.proxy(this.keypress, this))
+ }
+
+ this.$menu
+ .on('click', $.proxy(this.click, this))
+ .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
+ }
+
+ , keyup: function (e) {
+ e.stopPropagation()
+ e.preventDefault()
+
+ switch(e.keyCode) {
+ case 40: // down arrow
+ case 38: // up arrow
+ break
+
+ case 9: // tab
+ case 13: // enter
+ if (!this.shown) return
+ this.select()
+ break
+
+ case 27: // escape
+ this.hide()
+ break
+
+ default:
+ this.lookup()
+ }
+
+ }
+
+ , keypress: function (e) {
+ e.stopPropagation()
+ if (!this.shown) return
+
+ switch(e.keyCode) {
+ case 9: // tab
+ case 13: // enter
+ case 27: // escape
+ e.preventDefault()
+ break
+
+ case 38: // up arrow
+ e.preventDefault()
+ this.prev()
+ break
+
+ case 40: // down arrow
+ e.preventDefault()
+ this.next()
+ break
+ }
+ }
+
+ , blur: function (e) {
+ var that = this
+ e.stopPropagation()
+ e.preventDefault()
+ setTimeout(function () { that.hide() }, 150)
+ }
+
+ , click: function (e) {
+ e.stopPropagation()
+ e.preventDefault()
+ this.select()
+ }
+
+ , mouseenter: function (e) {
+ this.$menu.find('.active').removeClass('active')
+ $(e.currentTarget).addClass('active')
+ }
+
+ }
+
+