diff --git a/.gitignore b/.gitignore index 4b6a7b1d40..547ad2481a 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,7 @@ _testmain.go *.test bin/ .vagrant/ + + +website/npm-debug.log + diff --git a/website/source/Gruntfile.js b/website/source/Gruntfile.js index dafb62430e..41f6d6660c 100644 --- a/website/source/Gruntfile.js +++ b/website/source/Gruntfile.js @@ -3,17 +3,24 @@ module.exports = function(grunt) { // Configuration goes here grunt.initConfig({ + less: { + development:{ + files: { + "stylesheets/main.css": "stylesheets/main.less" + } + } + }, + concat: { options: { separator: ';' }, - site: { - src: [ + src: [ 'javascripts/app/app.js', 'javascripts/app/util.js', - 'javascripts/app/home.js', - 'javascripts/app/nodes.js' + 'javascripts/app/homepage.js' + ], dest: 'javascripts/app/deploy/site.js' @@ -23,12 +30,16 @@ module.exports = function(grunt) { uglify: { app: { files: { - 'javascripts/app/deploy/site.min.js': ['javascripts/app/deploy/site.js'] + 'javascripts/app/deploy/site.min.js': ['javascripts/app/deploy/site.js'] } } }, watch: { + less: { + files: 'stylesheets/*.less', + tasks: ['less'] + }, js: { files: 'javascripts/app/*.js', tasks: ['concat', 'uglify'] @@ -37,8 +48,8 @@ module.exports = function(grunt) { }); - // Load plugins here + grunt.loadNpmTasks('grunt-contrib-less'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-connect'); @@ -51,6 +62,8 @@ module.exports = function(grunt) { grunt.registerTask('dist-js', ['concat', 'uglify']); // Full distribution task. - grunt.registerTask('dist', ['dist-js']); + grunt.registerTask('dist', ['dist-js']); -}; \ No newline at end of file + grunt.registerTask('default', ['watch']); + +}; diff --git a/website/source/images/consul-footer-logo.png b/website/source/images/consul-footer-logo.png new file mode 100644 index 0000000000..066c92e828 Binary files /dev/null and b/website/source/images/consul-footer-logo.png differ diff --git a/website/source/images/consul-footer-logo@2x.png b/website/source/images/consul-footer-logo@2x.png new file mode 100644 index 0000000000..e0537e3b28 Binary files /dev/null and b/website/source/images/consul-footer-logo@2x.png differ diff --git a/website/source/images/consul-header-logo.png b/website/source/images/consul-header-logo.png new file mode 100644 index 0000000000..804275a2e1 Binary files /dev/null and b/website/source/images/consul-header-logo.png differ diff --git a/website/source/images/consul-header-logo@2x.png b/website/source/images/consul-header-logo@2x.png new file mode 100644 index 0000000000..4ba6ea05f0 Binary files /dev/null and b/website/source/images/consul-header-logo@2x.png differ diff --git a/website/source/images/consul-hero-logo.png b/website/source/images/consul-hero-logo.png new file mode 100644 index 0000000000..9252d5638a Binary files /dev/null and b/website/source/images/consul-hero-logo.png differ diff --git a/website/source/images/consul-hero-logo@2x.png b/website/source/images/consul-hero-logo@2x.png new file mode 100644 index 0000000000..b3ff43f905 Binary files /dev/null and b/website/source/images/consul-hero-logo@2x.png differ diff --git a/website/source/images/custom-event-icon.png b/website/source/images/custom-event-icon.png deleted file mode 100644 index d8757cbcb5..0000000000 Binary files a/website/source/images/custom-event-icon.png and /dev/null differ diff --git a/website/source/images/custom-event-icon@2x.png b/website/source/images/custom-event-icon@2x.png deleted file mode 100644 index ebbf02f38a..0000000000 Binary files a/website/source/images/custom-event-icon@2x.png and /dev/null differ diff --git a/website/source/images/failure-detect-icon.png b/website/source/images/failure-detect-icon.png deleted file mode 100644 index abeb9c9ba1..0000000000 Binary files a/website/source/images/failure-detect-icon.png and /dev/null differ diff --git a/website/source/images/failure-detect-icon@2x.png b/website/source/images/failure-detect-icon@2x.png deleted file mode 100644 index 54136c0dfa..0000000000 Binary files a/website/source/images/failure-detect-icon@2x.png and /dev/null differ diff --git a/website/source/images/feature-config.png b/website/source/images/feature-config.png new file mode 100644 index 0000000000..9a513e7cda Binary files /dev/null and b/website/source/images/feature-config.png differ diff --git a/website/source/images/feature-config@2x.png b/website/source/images/feature-config@2x.png new file mode 100644 index 0000000000..da0ac0489d Binary files /dev/null and b/website/source/images/feature-config@2x.png differ diff --git a/website/source/images/feature-discovery.png b/website/source/images/feature-discovery.png new file mode 100644 index 0000000000..12ed354c08 Binary files /dev/null and b/website/source/images/feature-discovery.png differ diff --git a/website/source/images/feature-discovery@2x.png b/website/source/images/feature-discovery@2x.png new file mode 100644 index 0000000000..dd722bdb2d Binary files /dev/null and b/website/source/images/feature-discovery@2x.png differ diff --git a/website/source/images/feature-health.png b/website/source/images/feature-health.png new file mode 100644 index 0000000000..fbbb5f977e Binary files /dev/null and b/website/source/images/feature-health.png differ diff --git a/website/source/images/feature-health@2x.png b/website/source/images/feature-health@2x.png new file mode 100644 index 0000000000..e2a4e94c1b Binary files /dev/null and b/website/source/images/feature-health@2x.png differ diff --git a/website/source/images/feature-multi.png b/website/source/images/feature-multi.png new file mode 100644 index 0000000000..90d9253950 Binary files /dev/null and b/website/source/images/feature-multi.png differ diff --git a/website/source/images/feature-multi@2x.png b/website/source/images/feature-multi@2x.png new file mode 100644 index 0000000000..dc07d515cf Binary files /dev/null and b/website/source/images/feature-multi@2x.png differ diff --git a/website/source/images/footer-hashicorp-logo.png b/website/source/images/footer-hashicorp-logo.png new file mode 100644 index 0000000000..90d1aa9e3c Binary files /dev/null and b/website/source/images/footer-hashicorp-logo.png differ diff --git a/website/source/images/footer-hashicorp-logo@2x.png b/website/source/images/footer-hashicorp-logo@2x.png new file mode 100644 index 0000000000..82f68a9034 Binary files /dev/null and b/website/source/images/footer-hashicorp-logo@2x.png differ diff --git a/website/source/images/footer-pattern.jpg b/website/source/images/footer-pattern.jpg deleted file mode 100644 index 4c506b382e..0000000000 Binary files a/website/source/images/footer-pattern.jpg and /dev/null differ diff --git a/website/source/images/gossip-proto-icon.png b/website/source/images/gossip-proto-icon.png deleted file mode 100644 index 9276ea0714..0000000000 Binary files a/website/source/images/gossip-proto-icon.png and /dev/null differ diff --git a/website/source/images/gossip-proto-icon@2x.png b/website/source/images/gossip-proto-icon@2x.png deleted file mode 100644 index 97826050c9..0000000000 Binary files a/website/source/images/gossip-proto-icon@2x.png and /dev/null differ diff --git a/website/source/images/hashi-logo-s.png b/website/source/images/hashi-logo-s.png deleted file mode 100644 index 696c582bb8..0000000000 Binary files a/website/source/images/hashi-logo-s.png and /dev/null differ diff --git a/website/source/images/hero-dots-below.png b/website/source/images/hero-dots-below.png new file mode 100644 index 0000000000..4b18811b3d Binary files /dev/null and b/website/source/images/hero-dots-below.png differ diff --git a/website/source/images/hero-dots-below@2x.png b/website/source/images/hero-dots-below@2x.png new file mode 100644 index 0000000000..0a82b7eb71 Binary files /dev/null and b/website/source/images/hero-dots-below@2x.png differ diff --git a/website/source/images/hero-dots.png b/website/source/images/hero-dots.png new file mode 100644 index 0000000000..bbaa6541e3 Binary files /dev/null and b/website/source/images/hero-dots.png differ diff --git a/website/source/images/hero-dots@2x.png b/website/source/images/hero-dots@2x.png new file mode 100644 index 0000000000..700c88cac7 Binary files /dev/null and b/website/source/images/hero-dots@2x.png differ diff --git a/website/source/images/icon-download-purple.png b/website/source/images/icon-download-purple.png new file mode 100644 index 0000000000..0e67c1cfeb Binary files /dev/null and b/website/source/images/icon-download-purple.png differ diff --git a/website/source/images/icon-download-purple@2x.png b/website/source/images/icon-download-purple@2x.png new file mode 100644 index 0000000000..2e01d9583c Binary files /dev/null and b/website/source/images/icon-download-purple@2x.png differ diff --git a/website/source/images/icon-download.png b/website/source/images/icon-download.png new file mode 100644 index 0000000000..3f02f426c4 Binary files /dev/null and b/website/source/images/icon-download.png differ diff --git a/website/source/images/icon-download@2x.png b/website/source/images/icon-download@2x.png new file mode 100644 index 0000000000..0528dfed4f Binary files /dev/null and b/website/source/images/icon-download@2x.png differ diff --git a/website/source/images/icon-github-purple.png b/website/source/images/icon-github-purple.png new file mode 100644 index 0000000000..3c03018ea7 Binary files /dev/null and b/website/source/images/icon-github-purple.png differ diff --git a/website/source/images/icon-github-purple@2x.png b/website/source/images/icon-github-purple@2x.png new file mode 100644 index 0000000000..55b692b845 Binary files /dev/null and b/website/source/images/icon-github-purple@2x.png differ diff --git a/website/source/images/icon-github.png b/website/source/images/icon-github.png new file mode 100644 index 0000000000..0708f44a92 Binary files /dev/null and b/website/source/images/icon-github.png differ diff --git a/website/source/images/icon-github@2x.png b/website/source/images/icon-github@2x.png new file mode 100644 index 0000000000..26a1e75377 Binary files /dev/null and b/website/source/images/icon-github@2x.png differ diff --git a/website/source/images/logo-circle-logo.png b/website/source/images/logo-circle-logo.png deleted file mode 100644 index 5823d37909..0000000000 Binary files a/website/source/images/logo-circle-logo.png and /dev/null differ diff --git a/website/source/images/logo-circle-logo@2x.png b/website/source/images/logo-circle-logo@2x.png deleted file mode 100644 index 410ed083b2..0000000000 Binary files a/website/source/images/logo-circle-logo@2x.png and /dev/null differ diff --git a/website/source/images/logo-type-medium.png b/website/source/images/logo-type-medium.png deleted file mode 100644 index 3e5e183a40..0000000000 Binary files a/website/source/images/logo-type-medium.png and /dev/null differ diff --git a/website/source/images/logo-type-medium@2x.png b/website/source/images/logo-type-medium@2x.png deleted file mode 100644 index d9c0c89b19..0000000000 Binary files a/website/source/images/logo-type-medium@2x.png and /dev/null differ diff --git a/website/source/images/logo-type-small.png b/website/source/images/logo-type-small.png deleted file mode 100644 index 44997415d9..0000000000 Binary files a/website/source/images/logo-type-small.png and /dev/null differ diff --git a/website/source/images/logo-type-small@2x.png b/website/source/images/logo-type-small@2x.png deleted file mode 100644 index 8fcda9cf45..0000000000 Binary files a/website/source/images/logo-type-small@2x.png and /dev/null differ diff --git a/website/source/images/nav-dotpipes.png b/website/source/images/nav-dotpipes.png new file mode 100644 index 0000000000..095eaf673e Binary files /dev/null and b/website/source/images/nav-dotpipes.png differ diff --git a/website/source/images/nav-dotpipes@2x.png b/website/source/images/nav-dotpipes@2x.png new file mode 100644 index 0000000000..13419820fd Binary files /dev/null and b/website/source/images/nav-dotpipes@2x.png differ diff --git a/website/source/images/node-hero-pattern.jpg b/website/source/images/node-hero-pattern.jpg deleted file mode 100644 index 0514498712..0000000000 Binary files a/website/source/images/node-hero-pattern.jpg and /dev/null differ diff --git a/website/source/images/node-hero-pattern@2x.jpg b/website/source/images/node-hero-pattern@2x.jpg deleted file mode 100644 index 1d80e4e5ed..0000000000 Binary files a/website/source/images/node-hero-pattern@2x.jpg and /dev/null differ diff --git a/website/source/index.html.erb b/website/source/index.html.erb index b521794bad..e25c735538 100644 --- a/website/source/index.html.erb +++ b/website/source/index.html.erb @@ -1,43 +1,71 @@ -
-
- -
-

Consul is a decentralized solution for service discovery and orchestration that is lightweight, highly available, and fault tolerant.

-
- +
+
+
+
+

Create and configure lightweight, reproducible, and portable development environments.

+
+ + +
+
- -
-
- + +
+
+
+
+ +
+
+

Service Discovery

+

Consul makes it simple for services to register themselves, and to discover other service

+
+
-
-

Gossip-based Membership

-

Consul relies on an efficient and lightweight gossip protocol to communicate with nodes. The Serf agents periodically exchange messages with each other in much the same way that a zombie apocalypse would occur: it starts with one zombie but soon infects everyone. In practice, the gossip is very fast and extremely efficient.

+
+
+
+ +
+
+

Failure Detection

+

Pairing service discovery with health checking prevents routing requests to unhealthy hosts, and enables services to easily provide circuit breakers.

+
+
-
-
-

Failure Detection

-

Consul is able to quickly detect failed members and notify the rest of the cluster. This failure detection is built into the heart of the gossip protocol used by Serf. Like humans in a zombie apocalypse, everybody checks their peers for infection and quickly alerts the other living humans. Serf relies on a random probing technique which is proven to efficiently scale to clusters of any size.

+ +
+
+
+
+ +
+
+

Multi Datacenter

+

Consul scales to multiple datacenters out of the box, with no complicated configuration.

+
+
-
- -
-
-
-
- -
-
-

Custom Events

-

In addition to managing membership, Consul can broadcast custom events. These can be used to trigger deploys, restart processes, spread tales of human heroism, and anything else you may want. The event system is flexible and lightweight, making it easy for application developers and sysadmins alike to leverage.

+
+
+
+ +
+
+

Shared Configuration

+

Store hierarchical key/value configuration data for services.

+
+
+
diff --git a/website/source/javascripts/app/app.js b/website/source/javascripts/app/app.js index 75d3896c0a..c75c3614ef 100644 --- a/website/source/javascripts/app/app.js +++ b/website/source/javascripts/app/app.js @@ -1,25 +1,20 @@ // -// home.js +// app.js // -var Serf = (function() { +var APP = (function() { function initialize (){ - Serf.Util.runIfClassNamePresent('page-home', initHome); + APP.Utils.runIfClassNamePresent('page-home', initHome); } function initHome() { - if(!Serf.Util.isMobile){ - Serf.Nodes.init(); - }else{ - Serf.Home.mobileHero(); - } - + APP.Homepage.init(); } - + //api return { initialize: initialize } -})(); \ No newline at end of file +})(); diff --git a/website/source/javascripts/app/deploy/site.js b/website/source/javascripts/app/deploy/site.js index c5ece5b0c7..50f04f090e 100644 --- a/website/source/javascripts/app/deploy/site.js +++ b/website/source/javascripts/app/deploy/site.js @@ -1,239 +1,97 @@ // -// home.js +// app.js // -var Serf = (function() { +var APP = (function() { function initialize (){ - Serf.Util.runIfClassNamePresent('page-home', initHome); + APP.Utils.runIfClassNamePresent('page-home', initHome); } function initHome() { - if(!Serf.Util.isMobile){ - Serf.Nodes.init(); - }else{ - Serf.Home.mobileHero(); - } - + APP.Homepage.init(); } - + //api return { initialize: initialize } -})();// +})(); +;// // util.js // -var Serf = Serf || {}; - -(function () { +var APP = APP || {}; +APP.Utils = (function () { + return { //check for mobile user agents - var isMobile = (function(){ - if( navigator.userAgent.match(/Android/i) - || navigator.userAgent.match(/webOS/i) - || navigator.userAgent.match(/iPhone/i) - //|| navigator.userAgent.match(/iPad/i) - || navigator.userAgent.match(/iPod/i) - || navigator.userAgent.match(/BlackBerry/i) - || navigator.userAgent.match(/Windows Phone/i) - ){ - return true; - } - else { - return false; - } - })() + isMobile : (function(){ + if( navigator.userAgent.match(/Android/i) + || navigator.userAgent.match(/webOS/i) + || navigator.userAgent.match(/iPhone/i) + //|| navigator.userAgent.match(/iPad/i) + || navigator.userAgent.match(/iPod/i) + || navigator.userAgent.match(/BlackBerry/i) + || navigator.userAgent.match(/Windows Phone/i) + ){ + return true; + } + else { + return false; + } + })(), - // calls the given function if the given classname is found - function runIfClassNamePresent(selector, initFunction) { - var elms = document.getElementsByClassName(selector); - if (elms.length > 0) { - initFunction(); - } - } - - Serf.Util = {}; - Serf.Util.isMobile = isMobile; - Serf.Util.runIfClassNamePresent = runIfClassNamePresent; - -})();// -// home.js -// -var Serf = Serf || {}; - -(function () { - - // calls the given function if the given classname is found - function mobileHero() { - var jumbo = document.getElementById('jumbotron'); - jumbo.className = jumbo.className + ' mobile-hero'; - } - - Serf.Home = {}; - Serf.Home.mobileHero = mobileHero; - -})();// -// node.js -// animation on the home page -// - -var Serf = Serf || {}; - -(function () { - - var width = 1400, - height = 490, - border = 50, - numberNodes = 128, - linkGroup = 0; - //nodeLinks = []; - - var nodes = []; - for (i=0; i 0) { + initFunction(); + } + } } - var fill = d3.scale.category20(); +}());;//homepage.js - var force = d3.layout.force() - .size([width, height]) - .nodes(nodes) - .linkDistance(60) - .charge(-1) - .gravity(0.0004) - .on("tick", tick); +var APP = APP || {}; - var svg = d3.select("#jumbotron").append("svg") - .attr('id', 'node-canvas') - .attr("width", width) - .attr("height", height) +(function () { + APP.Homepage = (function () { + return { - //set left value after adding to dom - resize(); + ui : null, - svg.append("rect") - .attr("width", width) - .attr("height", height); + init: function () { + var _this = this; - var nodes = force.nodes(), - links = force.links(), - node = svg.selectAll(".node"), - link = svg.selectAll(".link"); + //cache elements + this.ui = { + $doc: $(window), + $hero: $('#jumbotron'), + $pagination: null + } + + this.addEventListeners(); - var cursor = svg.append("circle") - .attr("r", 30) - .attr("transform", "translate(-100,-100)") - .attr("class", "cursor"); + }, + addEventListeners: function(){ + var _this = this; - function createLink(index) { - var node = nodes[index]; - var nodeSelected = svg.select("#id_" + node.index).classed("active linkgroup_"+ linkGroup, true); + if(APP.Utils.isMobile) + return; + + _this.ui.$doc.scroll(function() { + var top = _this.ui.$doc.scrollTop(), + speedAdj = (top*0.8), + speedAdjOffset = speedAdj - top; - var distMap = {}; - var distances = []; - - for (var i=0; i0&&b()}}}();var APP=APP||{};!function(){APP.Homepage=function(){return{ui:null,init:function(){this.ui={$doc:$(window),$hero:$("#jumbotron"),$pagination:null},this.addEventListeners()},addEventListeners:function(){var a=this;APP.Utils.isMobile||a.ui.$doc.scroll(function(){var b=a.ui.$doc.scrollTop(),c=.8*b,d=c-b;a.ui.$hero.css("webkitTransform","translate(0, "+c+"px)"),a.ui.$hero.find(".container").css("webkitTransform","translate(0, "+d+"px)")})}}}()}(jQuery,this); \ No newline at end of file diff --git a/website/source/javascripts/app/home.js b/website/source/javascripts/app/home.js deleted file mode 100644 index 50103e327b..0000000000 --- a/website/source/javascripts/app/home.js +++ /dev/null @@ -1,17 +0,0 @@ -// -// home.js -// -var Serf = Serf || {}; - -(function () { - - // calls the given function if the given classname is found - function mobileHero() { - var jumbo = document.getElementById('jumbotron'); - jumbo.className = jumbo.className + ' mobile-hero'; - } - - Serf.Home = {}; - Serf.Home.mobileHero = mobileHero; - -})(); \ No newline at end of file diff --git a/website/source/javascripts/app/homepage.js b/website/source/javascripts/app/homepage.js new file mode 100644 index 0000000000..ff66839479 --- /dev/null +++ b/website/source/javascripts/app/homepage.js @@ -0,0 +1,45 @@ +//homepage.js + +var APP = APP || {}; + +(function () { + APP.Homepage = (function () { + return { + + ui : null, + + init: function () { + var _this = this; + + //cache elements + this.ui = { + $doc: $(window), + $hero: $('#jumbotron'), + $pagination: null + } + + this.addEventListeners(); + + }, + + addEventListeners: function(){ + var _this = this; + + if(APP.Utils.isMobile) + return; + + _this.ui.$doc.scroll(function() { + var top = _this.ui.$doc.scrollTop(), + speedAdj = (top*0.8), + speedAdjOffset = speedAdj - top; + + _this.ui.$hero.css('webkitTransform', 'translate(0, '+ speedAdj +'px)'); + _this.ui.$hero.find('.container').css('webkitTransform', 'translate(0, '+ speedAdjOffset +'px)'); + //_this.ui.$pagination.css('webkitTransform', 'translate(0, '+ speedAdjOffset +'px)'); + }) + } + } + }()); + +}(jQuery, this)); + diff --git a/website/source/javascripts/app/nodes.js b/website/source/javascripts/app/nodes.js deleted file mode 100644 index 803d9093a1..0000000000 --- a/website/source/javascripts/app/nodes.js +++ /dev/null @@ -1,163 +0,0 @@ -// -// node.js -// animation on the home page -// - -var Serf = Serf || {}; - -(function () { - - var width = 1400, - height = 490, - border = 50, - numberNodes = 128, - linkGroup = 0; - //nodeLinks = []; - - var nodes = []; - for (i=0; i 0) { - initFunction(); - } - } + runIfClassNamePresent: function(selector, initFunction) { + var elms = document.getElementsByClassName(selector); + if (elms.length > 0) { + initFunction(); + } + } + } - Serf.Util = {}; - Serf.Util.isMobile = isMobile; - Serf.Util.runIfClassNamePresent = runIfClassNamePresent; - -})(); \ No newline at end of file +}()); \ No newline at end of file diff --git a/website/source/javascripts/bootstrap.min.js b/website/source/javascripts/lib/_old/bootstrap.min.js similarity index 100% rename from website/source/javascripts/bootstrap.min.js rename to website/source/javascripts/lib/_old/bootstrap.min.js diff --git a/website/source/javascripts/lib/bootstrap.js b/website/source/javascripts/lib/bootstrap.js new file mode 100644 index 0000000000..8ae571b6da --- /dev/null +++ b/website/source/javascripts/lib/bootstrap.js @@ -0,0 +1,1951 @@ +/*! + * Bootstrap v3.1.1 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } + +/* ======================================================================== + * Bootstrap: transition.js v3.1.1 + * http://getbootstrap.com/javascript/#transitions + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd', + 'MozTransition' : 'transitionend', + 'OTransition' : 'oTransitionEnd otransitionend', + 'transition' : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + + return false // explicit for ie8 ( ._.) + } + + // http://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false, $el = this + $(this).one($.support.transition.end, function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: alert.js v3.1.1 + * http://getbootstrap.com/javascript/#alerts + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // ALERT CLASS DEFINITION + // ====================== + + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = $(selector) + + if (e) e.preventDefault() + + if (!$parent.length) { + $parent = $this.hasClass('alert') ? $this : $this.parent() + } + + $parent.trigger(e = $.Event('close.bs.alert')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent.trigger('closed.bs.alert').remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent + .one($.support.transition.end, removeElement) + .emulateTransitionEnd(150) : + removeElement() + } + + + // ALERT PLUGIN DEFINITION + // ======================= + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') + + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + // ALERT NO CONFLICT + // ================= + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + // ALERT DATA-API + // ============== + + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: button.js v3.1.1 + * http://getbootstrap.com/javascript/#buttons + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state = state + 'Text' + + if (!data.resetText) $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d) + } + }, this), 0) + } + + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked') && this.$element.hasClass('active')) changed = false + else $parent.find('.active').removeClass('active') + } + if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + } + + if (changed) this.$element.toggleClass('active') + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + e.preventDefault() + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: carousel.js v3.1.1 + * http://getbootstrap.com/javascript/#carousel + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = + this.sliding = + this.interval = + this.$active = + this.$items = null + + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true + } + + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) + + this.interval && clearInterval(this.interval) + + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + + return this + } + + Carousel.prototype.getActiveIndex = function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + + return this.$items.index(this.$active) + } + + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getActiveIndex() + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || $active[type]() + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var fallback = type == 'next' ? 'first' : 'last' + var that = this + + if (!$next.length) { + if (!this.options.wrap) return + $next = this.$element.find('.item')[fallback]() + } + + if ($next.hasClass('active')) return this.sliding = false + + var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + + this.sliding = true + + isCycling && this.pause() + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid.bs.carousel', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .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.bs.carousel') }, 0) + }) + .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid.bs.carousel') + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + }) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + $carousel.carousel($carousel.data()) + }) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.1.1 + * http://getbootstrap.com/javascript/#collapse + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.transitioning = null + + if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.toggle) this.toggle() + } + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var actives = this.$parent && this.$parent.find('> .panel > .in') + + if (actives && actives.length) { + var hasData = actives.data('bs.collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing') + [dimension](0) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in') + [dimension]('auto') + this.transitioning = 0 + this.$element.trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + [dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element + [dimension](this.$element[dimension]()) + [0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse') + .removeClass('in') + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .trigger('hidden.bs.collapse') + .removeClass('collapsing') + .addClass('collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data && options.toggle && option == 'show') option = !option + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + var target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + var $target = $(target) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + var parent = $this.attr('data-parent') + var $parent = parent && $(parent) + + if (!data || !data.transitioning) { + if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') + $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + } + + $target.collapse(option) + }) + +}(jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.1.1 + * http://getbootstrap.com/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle=dropdown]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $('
- + + diff --git a/website/source/layouts/_header.erb b/website/source/layouts/_header.erb index 74e7860ce9..1e7a5b32ab 100644 --- a/website/source/layouts/_header.erb +++ b/website/source/layouts/_header.erb @@ -7,15 +7,20 @@ -<%= current_page.data.page_title ? "#{current_page.data.page_title} - " : "" %>Serf +<%= current_page.data.page_title ? "#{current_page.data.page_title} - " : "" %>Consul <%= stylesheet_link_tag "bootstrap.min" %> <%= stylesheet_link_tag "main" %> - + + + + +