Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 127ed17e4513c6c2f7ae85b68de3e18c20766cb7 0 parents
@zlorfi authored
Showing with 16,853 additions and 0 deletions.
  1. +5 −0 .gitignore
  2. +13 −0 Gemfile
  3. +48 −0 Gemfile.lock
  4. +38 −0 app.rb
  5. +14 −0 config.ru
  6. BIN  public/favicon.ico
  7. BIN  public/images/Slider_1.gif
  8. BIN  public/images/arrow_small_blue.gif
  9. BIN  public/images/foundation/orbit/bullets.jpg
  10. BIN  public/images/foundation/orbit/left-arrow-small.png
  11. BIN  public/images/foundation/orbit/left-arrow.png
  12. BIN  public/images/foundation/orbit/loading.gif
  13. BIN  public/images/foundation/orbit/mask-black.png
  14. BIN  public/images/foundation/orbit/pause-black.png
  15. BIN  public/images/foundation/orbit/right-arrow-small.png
  16. BIN  public/images/foundation/orbit/right-arrow.png
  17. BIN  public/images/foundation/orbit/rotator-black.png
  18. BIN  public/images/foundation/orbit/timer-black.png
  19. BIN  public/images/head_logo.png
  20. BIN  public/images/spinner.gif
  21. +50 −0 public/javascripts/foundation/foundation.alerts.js
  22. +480 −0 public/javascripts/foundation/foundation.clearing.js
  23. +74 −0 public/javascripts/foundation/foundation.cookie.js
  24. +122 −0 public/javascripts/foundation/foundation.dropdown.js
  25. +395 −0 public/javascripts/foundation/foundation.forms.js
  26. +612 −0 public/javascripts/foundation/foundation.joyride.js
  27. +357 −0 public/javascripts/foundation/foundation.js
  28. +130 −0 public/javascripts/foundation/foundation.magellan.js
  29. +365 −0 public/javascripts/foundation/foundation.orbit.js
  30. +159 −0 public/javascripts/foundation/foundation.placeholder.js
  31. +276 −0 public/javascripts/foundation/foundation.reveal.js
  32. +252 −0 public/javascripts/foundation/foundation.section.js
  33. +195 −0 public/javascripts/foundation/foundation.tooltips.js
  34. +225 −0 public/javascripts/foundation/foundation.topbar.js
  35. +4 −0 public/javascripts/vendor/custom.modernizr.js
  36. +9,597 −0 public/javascripts/vendor/jquery.js
  37. +1,884 −0 public/javascripts/vendor/zepto.js
  38. BIN  views/images/foundation/orbit/bullets.jpg
  39. BIN  views/images/foundation/orbit/left-arrow-small.png
  40. BIN  views/images/foundation/orbit/left-arrow.png
  41. BIN  views/images/foundation/orbit/loading.gif
  42. BIN  views/images/foundation/orbit/mask-black.png
  43. BIN  views/images/foundation/orbit/pause-black.png
  44. BIN  views/images/foundation/orbit/right-arrow-small.png
  45. BIN  views/images/foundation/orbit/right-arrow.png
  46. BIN  views/images/foundation/orbit/rotator-black.png
  47. BIN  views/images/foundation/orbit/timer-black.png
  48. +52 −0 views/index.haml
  49. +46 −0 views/layout.haml
  50. +995 −0 views/sass/_settings.scss
  51. +46 −0 views/sass/app.scss
  52. +396 −0 views/sass/normalize.scss
  53. +23 −0 views/sidebar.haml
5 .gitignore
@@ -0,0 +1,5 @@
+.sass-cache
+.bundle
+body
+meta
+.DS_Store
13 Gemfile
@@ -0,0 +1,13 @@
+source :rubygems
+
+gem 'sinatra', "~> 1.3"
+gem 'compass'
+gem 'zurb-foundation'
+gem 'puma'
+gem 'haml'
+gem 'rack-cache'
+
+group :development do
+ gem 'shotgun'
+ gem 'pry'
+end
48 Gemfile.lock
@@ -0,0 +1,48 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ chunky_png (1.2.7)
+ coderay (1.0.9)
+ compass (0.12.2)
+ chunky_png (~> 1.2)
+ fssm (>= 0.2.7)
+ sass (~> 3.1)
+ fssm (0.2.10)
+ haml (4.0.0)
+ tilt
+ method_source (0.8.1)
+ pry (0.9.12)
+ coderay (~> 1.0.5)
+ method_source (~> 0.8)
+ slop (~> 3.4)
+ puma (1.6.3)
+ rack (~> 1.2)
+ rack (1.5.2)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-protection (1.5.0)
+ rack
+ sass (3.2.7)
+ shotgun (0.9)
+ rack (>= 1.0)
+ sinatra (1.4.1)
+ rack (~> 1.5, >= 1.5.2)
+ rack-protection (~> 1.4)
+ tilt (~> 1.3, >= 1.3.4)
+ slop (3.4.4)
+ tilt (1.3.5)
+ zurb-foundation (4.0.7)
+ sass (>= 3.2.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ compass
+ haml
+ pry
+ puma
+ rack-cache
+ shotgun
+ sinatra (~> 1.3)
+ zurb-foundation
38 app.rb
@@ -0,0 +1,38 @@
+require 'rubygems' unless RUBY_VERSION >= '1.9'
+require "bundler/setup"
+require "sinatra/base"
+require 'compass'
+require "zurb-foundation"
+require 'haml'
+
+#configure { set :server, :puma }
+
+class App < Sinatra::Base
+ configure :production, :development do
+ enable :logging
+ end
+
+ configure do
+ Compass.configuration do |config|
+ config.project_path = File.dirname __FILE__
+ config.sass_dir = File.join "views", "scss"
+ config.images_dir = File.join "views", "images"
+ config.http_path = "/"
+ config.http_images_path = "/images"
+ config.http_stylesheets_path = "/stylesheets"
+ end
+
+ set :scss, Compass.sass_engine_options
+ set :server, :puma
+ end
+
+ get "/stylesheets/*.css" do |path|
+ content_type "text/css", charset: "utf-8"
+ scss :"sass/#{path}"
+ end
+
+ get "/" do
+ haml :index
+ end
+
+end
14 config.ru
@@ -0,0 +1,14 @@
+require 'rubygems' unless RUBY_VERSION >= '1.9'
+require 'sinatra'
+require 'rack/cache'
+require "./app"
+
+use Rack::Cache,
+ :metastore => 'file:./tmp/meta',
+ :entitystore => 'file:./tmp/body',
+ #:metastore => 'memcached://localhost:11211/meta',
+ #:entitystore => 'memcached://localhost:11211/body',
+ :verbose => true
+
+#run Sinatra::Application
+run App
BIN  public/favicon.ico
Binary file not shown
BIN  public/images/Slider_1.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/arrow_small_blue.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/bullets.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/left-arrow-small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/left-arrow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/loading.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/mask-black.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/pause-black.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/right-arrow-small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/right-arrow.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/rotator-black.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/foundation/orbit/timer-black.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/head_logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  public/images/spinner.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 public/javascripts/foundation/foundation.alerts.js
@@ -0,0 +1,50 @@
+/*jslint unparam: true, browser: true, indent: 2 */
+
+;(function ($, window, document, undefined) {
+ 'use strict';
+
+ Foundation.libs.alerts = {
+ name : 'alerts',
+
+ version : '4.0.0',
+
+ settings : {
+ speed: 300, // fade out speed
+ callback: function (){}
+ },
+
+ init : function (scope, method, options) {
+ this.scope = scope || this.scope;
+
+ if (typeof method === 'object') {
+ $.extend(true, this.settings, method);
+ }
+
+ if (typeof method != 'string') {
+ if (!this.settings.init) this.events();
+
+ return this.settings.init;
+ } else {
+ return this[method].call(this, options);
+ }
+ },
+
+ events : function () {
+ var self = this;
+
+ $(this.scope).on('click.fndtn.alerts', '[data-alert] a.close', function (e) {
+ e.preventDefault();
+ $(this).closest("[data-alert]").fadeOut(self.speed, function () {
+ $(this).remove();
+ self.settings.callback();
+ });
+ });
+
+ this.settings.init = true;
+ },
+
+ off : function () {
+ $(this.scope).off('.fndtn.alerts');
+ }
+ };
+}(Foundation.zj, this, this.document));
480 public/javascripts/foundation/foundation.clearing.js
@@ -0,0 +1,480 @@
+/*jslint unparam: true, browser: true, indent: 2 */
+
+;(function ($, window, document, undefined) {
+ 'use strict';
+
+ Foundation.libs.clearing = {
+ name : 'clearing',
+
+ version : '4.0.0',
+
+ settings : {
+ templates : {
+ viewing : '<a href="#" class="clearing-close">&times;</a>' +
+ '<div class="visible-img" style="display: none"><img src="//:0">' +
+ '<p class="clearing-caption"></p><a href="#" class="clearing-main-left"><span></span></a>' +
+ '<a href="#" class="clearing-main-right"><span></span></a></div>'
+ },
+
+ // comma delimited list of selectors that, on click, will close clearing,
+ // add 'div.clearing-blackout, div.visible-img' to close on background click
+ close_selectors : '.clearing-close',
+
+ // event initializers and locks
+ init : false,
+ locked : false
+ },
+
+ init : function (scope, method, options) {
+ this.scope = this.scope || scope;
+ Foundation.inherit(this, 'set_data get_data remove_data throttle');
+
+ if (typeof method === 'object') {
+ options = $.extend(true, this.settings, method);
+ }
+
+ if (typeof method != 'string') {
+ $(this.scope).find('ul[data-clearing]').each(function () {
+ var self = Foundation.libs.clearing,
+ $el = $(this),
+ options = options || {},
+ settings = self.get_data($el);
+
+ if (!settings) {
+ options.$parent = $el.parent();
+
+ self.set_data($el, $.extend(true, self.settings, options));
+
+ self.assemble($el.find('li'));
+
+ if (!self.settings.init) {
+ self.events().swipe_events();
+ }
+ }
+ });
+
+ return this.settings.init;
+ } else {
+ // fire method
+ return this[method].call(this, options);
+ }
+ },
+
+ // event binding and initial setup
+
+ events : function () {
+ var self = this;
+
+ $(this.scope)
+ .on('click.fndtn.clearing', 'ul[data-clearing] li',
+ function (e, current, target) {
+ var current = current || $(this),
+ target = target || current,
+ settings = self.get_data(current.parent());
+
+ e.preventDefault();
+ if (!settings) self.init();
+
+ // set current and target to the clicked li if not otherwise defined.
+ self.open($(e.target), current, target);
+ self.update_paddles(target);
+ })
+
+ .on('click.fndtn.clearing', '.clearing-main-right',
+ function (e) { this.nav(e, 'next') }.bind(this))
+ .on('click.fndtn.clearing', '.clearing-main-left',
+ function (e) { this.nav(e, 'prev') }.bind(this))
+ .on('click.fndtn.clearing', this.settings.close_selectors,
+ function (e) { Foundation.libs.clearing.close(e, this) })
+ .on('keydown.fndtn.clearing',
+ function (e) { this.keydown(e) }.bind(this));
+
+ $(window).on('resize.fndtn.clearing',
+ function (e) { this.resize() }.bind(this));
+
+ this.settings.init = true;
+ return this;
+ },
+
+ swipe_events : function () {
+ var self = this;
+
+ $(this.scope)
+ .on('touchstart.fndtn.clearing', '.visible-img', function(e) {
+ if (!e.touches) { e = e.originalEvent; }
+ var data = {
+ start_page_x: e.touches[0].pageX,
+ start_page_y: e.touches[0].pageY,
+ start_time: (new Date()).getTime(),
+ delta_x: 0,
+ is_scrolling: undefined
+ };
+
+ $(this).data('swipe-transition', data);
+ e.stopPropagation();
+ })
+ .on('touchmove.fndtn.clearing', '.visible-img', function(e) {
+ if (!e.touches) { e = e.originalEvent; }
+ // Ignore pinch/zoom events
+ if(e.touches.length > 1 || e.scale && e.scale !== 1) return;
+
+ var data = $(this).data('swipe-transition');
+
+ if (typeof data === 'undefined') {
+ data = {};
+ }
+
+ data.delta_x = e.touches[0].pageX - data.start_page_x;
+
+ if ( typeof data.is_scrolling === 'undefined') {
+ data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
+ }
+
+ if (!data.is_scrolling && !data.active) {
+ e.preventDefault();
+ var direction = (data.delta_x < 0) ? 'next' : 'prev';
+ data.active = true;
+ self.nav(e, direction);
+ }
+ })
+ .on('touchend.fndtn.clearing', '.visible-img', function(e) {
+ $(this).data('swipe-transition', {});
+ e.stopPropagation();
+ });
+ },
+
+ assemble : function ($li) {
+ var $el = $li.parent(),
+ settings = this.get_data($el),
+ grid = $el.detach(),
+ data = {
+ grid: '<div class="carousel">' + this.outerHTML(grid[0]) + '</div>',
+ viewing: settings.templates.viewing
+ },
+ wrapper = '<div class="clearing-assembled"><div>' + data.viewing +
+ data.grid + '</div></div>';
+
+ return settings.$parent.append(wrapper);
+ },
+
+ // event callbacks
+
+ open : function ($image, current, target) {
+ var root = target.closest('.clearing-assembled'),
+ container = root.find('div').first(),
+ visible_image = container.find('.visible-img'),
+ image = visible_image.find('img').not($image);
+
+ if (!this.locked()) {
+ // set the image to the selected thumbnail
+ image.attr('src', this.load($image));
+
+ this.loaded(image, function () {
+ // toggle the gallery
+ root.addClass('clearing-blackout');
+ container.addClass('clearing-container');
+ visible_image.show();
+ this.fix_height(target)
+ .caption(visible_image.find('.clearing-caption'), $image)
+ .center(image)
+ .shift(current, target, function () {
+ target.siblings().removeClass('visible');
+ target.addClass('visible');
+ });
+ }.bind(this));
+ }
+ },
+
+ close : function (e, el) {
+ e.preventDefault();
+
+ var root = (function (target) {
+ if (/blackout/.test(target.selector)) {
+ return target;
+ } else {
+ return target.closest('.clearing-blackout');
+ }
+ }($(el))), container, visible_image;
+
+ if (el === e.target && root) {
+ container = root.find('div').first(),
+ visible_image = container.find('.visible-img');
+ this.settings.prev_index = 0;
+ root.find('ul[data-clearing]')
+ .attr('style', '').closest('.clearing-blackout')
+ .removeClass('clearing-blackout');
+ container.removeClass('clearing-container');
+ visible_image.hide();
+ }
+
+ return false;
+ },
+
+ keydown : function (e) {
+ var clearing = $('.clearing-blackout').find('ul[data-clearing]');
+
+ if (e.which === 39) this.go(clearing, 'next');
+ if (e.which === 37) this.go(clearing, 'prev');
+ if (e.which === 27) $('a.clearing-close').trigger('click');
+ },
+
+ nav : function (e, direction) {
+ var clearing = $('.clearing-blackout').find('ul[data-clearing]');
+
+ e.preventDefault();
+ this.go(clearing, direction);
+ },
+
+ resize : function () {
+ var image = $('.clearing-blackout .visible-img').find('img');
+
+ if (image.length) {
+ this.center(image);
+ }
+ },
+
+ // visual adjustments
+ fix_height : function (target) {
+ var lis = target.parent().children(),
+ self = this;
+
+ lis.each(function () {
+ var li = $(this),
+ image = li.find('img');
+
+ if (li.height() > self.outerHeight(image)) {
+ li.addClass('fix-height');
+ }
+ })
+ .closest('ul')
+ .width(lis.length * 100 + '%');
+
+ return this;
+ },
+
+ update_paddles : function (target) {
+ var visible_image = target
+ .closest('.carousel')
+ .siblings('.visible-img');
+
+ if (target.next().length) {
+ visible_image
+ .find('.clearing-main-right')
+ .removeClass('disabled');
+ } else {
+ visible_image
+ .find('.clearing-main-right')
+ .addClass('disabled');
+ }
+
+ if (target.prev().length) {
+ visible_image
+ .find('.clearing-main-left')
+ .removeClass('disabled');
+ } else {
+ visible_image
+ .find('.clearing-main-left')
+ .addClass('disabled');
+ }
+ },
+
+ center : function (target) {
+ target.css({
+ marginLeft : -(this.outerWidth(target) / 2),
+ marginTop : -(this.outerHeight(target) / 2)
+ });
+ return this;
+ },
+
+ // image loading and preloading
+
+ load : function ($image) {
+ var href = $image.parent().attr('href');
+
+ this.preload($image);
+
+ if (href) return href;
+ return $image.attr('src');
+ },
+
+ preload : function ($image) {
+ this
+ .img($image.closest('li').next())
+ .img($image.closest('li').prev());
+ },
+
+ loaded : function (image, callback) {
+ // based on jquery.imageready.js
+ // @weblinc, @jsantell, (c) 2012
+
+ function loaded () {
+ callback();
+ }
+
+ function bindLoad () {
+ this.one('load', loaded);
+
+ if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
+ var src = this.attr( 'src' ),
+ param = src.match( /\?/ ) ? '&' : '?';
+
+ param += 'random=' + (new Date()).getTime();
+ this.attr('src', src + param);
+ }
+ }
+
+ if (!image.attr('src')) {
+ loaded();
+ return;
+ }
+
+ if (this.complete || this.readyState === 4) {
+ loaded();
+ } else {
+ bindLoad.call(image);
+ }
+ },
+
+ img : function (img) {
+ if (img.length) {
+ var new_img = new Image(),
+ new_a = img.find('a');
+
+ if (new_a.length) {
+ new_img.src = new_a.attr('href');
+ } else {
+ new_img.src = img.find('img').attr('src');
+ }
+ }
+ return this;
+ },
+
+ // image caption
+
+ caption : function (container, $image) {
+ var caption = $image.data('caption');
+
+ if (caption) {
+ container
+ .text(caption)
+ .show();
+ } else {
+ container
+ .text('')
+ .hide();
+ }
+ return this;
+ },
+
+ // directional methods
+
+ go : function ($ul, direction) {
+ var current = $ul.find('.visible'),
+ target = current[direction]();
+
+ if (target.length) {
+ target
+ .find('img')
+ .trigger('click', [current, target]);
+ }
+ },
+
+ shift : function (current, target, callback) {
+ var clearing = target.parent(),
+ old_index = this.settings.prev_index || target.index(),
+ direction = this.direction(clearing, current, target),
+ left = parseInt(clearing.css('left'), 10),
+ width = this.outerWidth(target),
+ skip_shift;
+
+ // we use jQuery animate instead of CSS transitions because we
+ // need a callback to unlock the next animation
+ if (target.index() !== old_index && !/skip/.test(direction)){
+ if (/left/.test(direction)) {
+ this.lock();
+ clearing.animate({left : left + width}, 300, this.unlock());
+ } else if (/right/.test(direction)) {
+ this.lock();
+ clearing.animate({left : left - width}, 300, this.unlock());
+ }
+ } else if (/skip/.test(direction)) {
+ // the target image is not adjacent to the current image, so
+ // do we scroll right or not
+ skip_shift = target.index() - this.settings.up_count;
+ this.lock();
+
+ if (skip_shift > 0) {
+ clearing.animate({left : -(skip_shift * width)}, 300, this.unlock());
+ } else {
+ clearing.animate({left : 0}, 300, this.unlock());
+ }
+ }
+
+ callback();
+ },
+
+ direction : function ($el, current, target) {
+ var lis = $el.find('li'),
+ li_width = this.outerWidth(lis) + (this.outerWidth(lis) / 4),
+ up_count = Math.floor(this.outerWidth($('.clearing-container')) / li_width) - 1,
+ target_index = lis.index(target),
+ response;
+
+ this.settings.up_count = up_count;
+
+ if (this.adjacent(this.settings.prev_index, target_index)) {
+ if ((target_index > up_count)
+ && target_index > this.settings.prev_index) {
+ response = 'right';
+ } else if ((target_index > up_count - 1)
+ && target_index <= this.settings.prev_index) {
+ response = 'left';
+ } else {
+ response = false;
+ }
+ } else {
+ response = 'skip';
+ }
+
+ this.settings.prev_index = target_index;
+
+ return response;
+ },
+
+ adjacent : function (current_index, target_index) {
+ for (var i = target_index + 1; i >= target_index - 1; i--) {
+ if (i === current_index) return true;
+ }
+ return false;
+ },
+
+ // lock management
+
+ lock : function () {
+ this.settings.locked = true;
+ },
+
+ unlock : function () {
+ this.settings.locked = false;
+ },
+
+ locked : function () {
+ return this.settings.locked;
+ },
+
+ // plugin management/browser quirks
+
+ outerHTML : function (el) {
+ // support FireFox < 11
+ return el.outerHTML || new XMLSerializer().serializeToString(el);
+ },
+
+ off : function () {
+ $(this.scope).off('.fndtn.clearing');
+ $(window).off('.fndtn.clearing');
+ this.remove_data(); // empty settings cache
+ this.settings.init = false;
+ }
+ };
+
+}(Foundation.zj, this, this.document));
74 public/javascripts/foundation/foundation.cookie.js
@@ -0,0 +1,74 @@
+/*!
+ * jQuery Cookie Plugin v1.3
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright 2011, Klaus Hartl
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.opensource.org/licenses/GPL-2.0
+ *
+ * Modified to work with Zepto.js by ZURB
+ */
+(function ($, document, undefined) {
+
+ var pluses = /\+/g;
+
+ function raw(s) {
+ return s;
+ }
+
+ function decoded(s) {
+ return decodeURIComponent(s.replace(pluses, ' '));
+ }
+
+ var config = $.cookie = function (key, value, options) {
+
+ // write
+ if (value !== undefined) {
+ options = $.extend({}, config.defaults, options);
+
+ if (value === null) {
+ options.expires = -1;
+ }
+
+ if (typeof options.expires === 'number') {
+ var days = options.expires, t = options.expires = new Date();
+ t.setDate(t.getDate() + days);
+ }
+
+ value = config.json ? JSON.stringify(value) : String(value);
+
+ return (document.cookie = [
+ encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+ options.path ? '; path=' + options.path : '',
+ options.domain ? '; domain=' + options.domain : '',
+ options.secure ? '; secure' : ''
+ ].join(''));
+ }
+
+ // read
+ var decode = config.raw ? raw : decoded;
+ var cookies = document.cookie.split('; ');
+ for (var i = 0, l = cookies.length; i < l; i++) {
+ var parts = cookies[i].split('=');
+ if (decode(parts.shift()) === key) {
+ var cookie = decode(parts.join('='));
+ return config.json ? JSON.parse(cookie) : cookie;
+ }
+ }
+
+ return null;
+ };
+
+ config.defaults = {};
+
+ $.removeCookie = function (key, options) {
+ if ($.cookie(key) !== null) {
+ $.cookie(key, null, options);
+ return true;
+ }
+ return false;
+ };
+
+})(Foundation.zj, document);
122 public/javascripts/foundation/foundation.dropdown.js
@@ -0,0 +1,122 @@
+/*jslint unparam: true, browser: true, indent: 2 */
+
+;(function ($, window, document, undefined) {
+ 'use strict';
+
+ Foundation.libs.dropdown = {
+ name : 'dropdown',
+
+ version : '4.0.6',
+
+ settings : {
+ activeClass: 'open'
+ },
+
+ init : function (scope, method, options) {
+ this.scope = scope || this.scope;
+ Foundation.inherit(this, 'throttle');
+
+ if (typeof method === 'object') {
+ $.extend(true, this.settings, method);
+ }
+
+ if (typeof method != 'string') {
+
+ if (!this.settings.init) {
+ this.events();
+ }
+
+ return this.settings.init;
+ } else {
+ return this[method].call(this, options);
+ }
+ },
+
+ events : function () {
+ var self = this;
+
+ $(this.scope).on('click.fndtn.dropdown', '[data-dropdown]', function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.toggle($(this));
+ });
+
+ $('*, html, body').on('click.fndtn.dropdown', function (e) {
+ if (!$(e.target).data('dropdown')) {
+ $('[data-dropdown-content]')
+ .css('left', '-99999px')
+ .removeClass(self.settings.activeClass);
+ }
+ });
+
+ $(window).on('resize.fndtn.dropdown', self.throttle(function () {
+ self.resize.call(self);
+ }, 50)).trigger('resize');
+
+ this.settings.init = true;
+ },
+
+ toggle : function (target, resize) {
+ var dropdown = $('#' + target.data('dropdown'));
+
+ $('[data-dropdown-content]').not(dropdown).css('left', '-99999px').removeClass(this.settings.activeClass);
+
+ if (dropdown.hasClass(this.settings.activeClass)) {
+ dropdown
+ .css('left', '-99999px')
+ .removeClass(this.settings.activeClass);
+ } else {
+ this
+ .css(dropdown
+ .addClass(this.settings.activeClass), target);
+ }
+ },
+
+ resize : function () {
+ var dropdown = $('[data-dropdown-content].open'),
+ target = $("[data-dropdown='" + dropdown.attr('id') + "']");
+
+ if (dropdown.length && target.length) {
+ this.css(dropdown, target);
+ }
+ },
+
+ css : function (dropdown, target) {
+ if (dropdown.parent()[0] === $('body')[0]) {
+ var position = target.offset();
+ } else {
+ var position = target.position();
+ }
+
+ if (this.small()) {
+ dropdown.css({
+ position : 'absolute',
+ width: '95%',
+ left: '2.5%',
+ 'max-width': 'none',
+ top: position.top + this.outerHeight(target)
+ });
+ } else {
+ dropdown.attr('style', '').css({
+ position : 'absolute',
+ top: position.top + this.outerHeight(target),
+ left: position.left
+ });
+ }
+
+ return dropdown;
+ },
+
+ small : function () {
+ return $(window).width() < 768 || $('html').hasClass('lt-ie9');
+ },
+
+ off: function () {
+ $(this.scope).off('.fndtn.dropdown');
+ $('html, body').off('.fndtn.dropdown');
+ $(window).off('.fndtn.dropdown');
+ $('[data-dropdown-content]').off('.fndtn.dropdown');
+ this.settings.init = false;
+ }
+ };
+}(Foundation.zj, this, this.document));
395 public/javascripts/foundation/foundation.forms.js
@@ -0,0 +1,395 @@
+/*jslint unparam: true, browser: true, indent: 2 */
+
+;(function ($, window, document, undefined) {
+ 'use strict';
+
+ Foundation.libs.forms = {
+ name : 'forms',
+
+ version : '4.0.4',
+
+ settings : {
+ disable_class: 'no-custom'
+ },
+
+ init : function (scope, method, options) {
+ this.scope = scope || this.scope;
+
+ if (typeof method === 'object') {
+ $.extend(true, this.settings, method);
+ }
+
+ if (typeof method != 'string') {
+ if (!this.settings.init) {
+ this.events();
+ }
+
+ this.assemble();
+
+ return this.settings.init;
+ } else {
+ return this[method].call(this, options);
+ }
+ },
+
+ assemble : function () {
+ $('form.custom input[type="radio"]', $(this.scope)).not('[data-customforms="disabled"]')
+ .each(this.append_custom_markup);
+ $('form.custom input[type="checkbox"]', $(this.scope)).not('[data-customforms="disabled"]')
+ .each(this.append_custom_markup);
+ $('form.custom select', $(this.scope)).not('[data-customforms="disabled"]')
+ .each(this.append_custom_select);
+ },
+
+ events : function () {
+ var self = this;
+
+ $(this.scope)
+ .on('change.fndtn.forms', 'form.custom select:not([data-customforms="disabled"])', function (e) {
+ self.refresh_custom_select($(this));
+ })
+ .on('click.fndtn.forms', 'form.custom label', function (e) {
+ var $associatedElement = $('#' + self.escape($(this).attr('for')) + ':not([data-customforms="disabled"])'),
+ $customCheckbox,
+ $customRadio;
+ if ($associatedElement.length !== 0) {
+ if ($associatedElement.attr('type') === 'checkbox') {
+ e.preventDefault();
+ $customCheckbox = $(this).find('span.custom.checkbox');
+
+ //the checkbox might be outside after the label
+ if ($customCheckbox.length == 0) {
+ $customCheckbox = $(this).next('span.custom.checkbox');
+ }
+ //the checkbox might be outside before the label
+ if ($customCheckbox.length == 0) {
+ $customCheckbox = $(this).prev('span.custom.checkbox');
+ }
+ self.toggle_checkbox($customCheckbox);
+ } else if ($associatedElement.attr('type') === 'radio') {
+ e.preventDefault();
+ $customRadio = $(this).find('span.custom.radio');
+ //the radio might be outside after the label
+ if ($customRadio.length == 0) {
+ $customRadio = $(this).next('span.custom.radio');
+ }
+ //the radio might be outside before the label
+ if ($customRadio.length == 0) {
+ $customRadio = $(this).prev('span.custom.radio');
+ }
+ self.toggle_radio($customRadio);
+ }
+ }
+ })
+ .on('click.fndtn.forms', 'form.custom div.custom.dropdown a.current, form.custom div.custom.dropdown a.selector', function (e) {
+ var $this = $(this),
+ $dropdown = $this.closest('div.custom.dropdown'),
+ $select = $dropdown.prev();
+
+ // make sure other dropdowns close
+ if(!$dropdown.hasClass('open'))
+ $(self.scope).trigger('click');
+
+ e.preventDefault();
+ if (false === $select.is(':disabled')) {
+ $dropdown.toggleClass('open');
+
+ if ($dropdown.hasClass('open')) {
+ $(self.scope).on('click.fndtn.forms.customdropdown', function () {
+ $dropdown.removeClass('open');
+ $(self.scope).off('.fndtn.forms.customdropdown');
+ });
+ } else {
+ $(self.scope).on('.fndtn.forms.customdropdown');
+ }
+ return false;
+ }
+ })
+ .on('click.fndtn.forms touchend.fndtn.forms', 'form.custom div.custom.dropdown li', function (e) {
+ var $this = $(this),
+ $customDropdown = $this.closest('div.custom.dropdown'),
+ $select = $customDropdown.prev(),
+ selectedIndex = 0;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ if ( ! $(this).hasClass('disabled')) {
+ $('div.dropdown').not($customDropdown).removeClass('open');
+
+ var $oldThis= $this
+ .closest('ul')
+ .find('li.selected');
+ $oldThis.removeClass('selected');
+
+ $this.addClass('selected');
+
+ $customDropdown
+ .removeClass('open')
+ .find('a.current')
+ .html($this.html());
+
+ $this.closest('ul').find('li').each(function (index) {
+ if ($this[0] == this) {
+ selectedIndex = index;
+ }
+
+ });
+ $select[0].selectedIndex = selectedIndex;
+
+ //store the old value in data
+ $select.data('prevalue', $oldThis.html());
+ $select.trigger('change');
+ }
+ });
+
+ this.settings.init = true;
+ },
+
+ append_custom_markup : function (idx, sel) {
+ var $this = $(sel).hide(),
+ type = $this.attr('type'),
+ $span = $this.next('span.custom.' + type);
+
+ if ($span.length === 0) {
+ $span = $('<span class="custom ' + type + '"></span>').insertAfter($this);
+ }
+
+ $span.toggleClass('checked', $this.is(':checked'));
+ $span.toggleClass('disabled', $this.is(':disabled'));
+ },
+
+ append_custom_select : function (idx, sel) {
+ var self = Foundation.libs.forms,
+ $this = $( sel ),
+ $customSelect = $this.next( 'div.custom.dropdown' ),
+ $customList = $customSelect.find( 'ul' ),
+ $selectCurrent = $customSelect.find( ".current" ),
+ $selector = $customSelect.find( ".selector" ),
+ $options = $this.find( 'option' ),
+ $selectedOption = $options.filter( ':selected' ),
+ copyClasses = $this.attr('class') ? $this.attr('class').split(' ') : [],
+ maxWidth = 0,
+ liHtml = '',
+ $listItems,
+ $currentSelect = false;
+
+ if ($this.hasClass(self.settings.disable_class)) return;
+
+ if ($customSelect.length === 0) {
+ var customSelectSize = $this.hasClass( 'small' ) ? 'small' :
+ $this.hasClass( 'medium' ) ? 'medium' :
+ $this.hasClass( 'large' ) ? 'large' :
+ $this.hasClass( 'expand' ) ? 'expand' : '';
+
+ $customSelect = $('<div class="' + ['custom', 'dropdown', customSelectSize ].concat(copyClasses).filter(function(item, idx,arr){ if(item == '') return false; return arr.indexOf(item) == idx; }).join( ' ' ) + '"><a href="#" class="selector"></a><ul /></div>');
+ $selector = $customSelect.find(".selector");
+ $customList = $customSelect.find("ul");
+ liHtml = $options.map(function() { return "<li>" + $( this ).html() + "</li>"; } ).get().join( '' );
+ $customList.append(liHtml);
+ $currentSelect = $customSelect.prepend('<a href="#" class="current">' + $selectedOption.html() + '</a>' ).find( ".current" );
+ $this
+ .after( $customSelect )
+ .hide();
+
+ } else {
+ liHtml = $options.map(function() {
+ return "<li>" + $( this ).html() + "</li>";
+ })
+ .get().join('');
+ $customList
+ .html('')
+ .append(liHtml);
+
+ } // endif $customSelect.length === 0
+ $customSelect.toggleClass('disabled', $this.is( ':disabled' ) );
+ $listItems = $customList.find( 'li' );
+
+ $options.each( function ( index ) {
+ if ( this.selected ) {
+ $listItems.eq( index ).addClass( 'selected' );
+
+ if ($currentSelect) {
+ $currentSelect.html( $( this ).html() );
+ }
+
+ }
+ if ($(this).is(':disabled')) {
+ $listItems.eq( index ).addClass( 'disabled' );
+ }
+ });
+
+ //
+ // If we're not specifying a predetermined form size.
+ //
+ if (!$customSelect.is('.small, .medium, .large, .expand')) {
+
+ // ------------------------------------------------------------------------------------
+ // This is a work-around for when elements are contained within hidden parents.
+ // For example, when custom-form elements are inside of a hidden reveal modal.
+ //
+ // We need to display the current custom list element as well as hidden parent elements
+ // in order to properly calculate the list item element's width property.
+ // -------------------------------------------------------------------------------------
+
+ $customSelect.addClass( 'open' );
+ //
+ // Quickly, display all parent elements.
+ // This should help us calcualate the width of the list item's within the drop down.
+ //
+ var self = Foundation.libs.forms;
+ self.hidden_fix.adjust( $customList );
+
+ maxWidth = ( self.outerWidth($listItems) > maxWidth ) ? self.outerWidth($listItems) : maxWidth;
+
+ Foundation.libs.forms.hidden_fix.reset();
+
+ $customSelect.removeClass( 'open' );
+
+ } // endif
+
+ },
+
+ refresh_custom_select : function ($select) {
+ var self = this;
+ var maxWidth = 0,
+ $customSelect = $select.next(),
+ $options = $select.find('option');
+
+ $customSelect.find('ul').html('');
+
+ $options.each(function () {
+ var $li = $('<li>' + $(this).html() + '</li>');
+ $customSelect.find('ul').append($li);
+ });
+
+ // re-populate
+ $options.each(function (index) {
+ if (this.selected) {
+ $customSelect.find('li').eq(index).addClass('selected');
+ $customSelect.find('.current').html($(this).html());
+ }
+ if ($(this).is(':disabled')) {
+ $customSelect.find('li').eq(index).addClass('disabled');
+ }
+ });
+
+ // fix width
+ $customSelect.removeAttr('style')
+ .find('ul').removeAttr('style');
+ $customSelect.find('li').each(function () {
+ $customSelect.addClass('open');
+ if (self.outerWidth($(this)) > maxWidth) {
+ maxWidth = self.outerWidth($(this));
+ }
+ $customSelect.removeClass('open');
+ });
+ },
+
+ toggle_checkbox : function ($element) {
+ var $input = $element.prev(),
+ input = $input[0];
+
+ if (false === $input.is(':disabled')) {
+ input.checked = ((input.checked) ? false : true);
+ $element.toggleClass('checked');
+
+ $input.trigger('change');
+ }
+ },
+
+ toggle_radio : function ($element) {
+ var $input = $element.prev(),
+ $form = $input.closest('form.custom'),
+ input = $input[0];
+
+ if (false === $input.is(':disabled')) {
+ $form.find('input[type="radio"][name="' + this.escape($input.attr('name')) + '"]').next().not($element).removeClass('checked');
+ if ( !$element.hasClass('checked') ) {
+ $element.toggleClass('checked');
+ }
+ input.checked = $element.hasClass('checked');
+
+ $input.trigger('change');
+ }
+ },
+
+ escape : function (text) {
+ return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+ },
+
+ hidden_fix : {
+ /**
+ * Sets all hidden parent elements and self to visibile.
+ *
+ * @method adjust
+ * @param {jQuery Object} $child
+ */
+
+ // We'll use this to temporarily store style properties.
+ tmp : [],
+
+ // We'll use this to set hidden parent elements.
+ hidden : null,
+
+ adjust : function( $child ) {
+ // Internal reference.
+ var _self = this;
+
+ // Set all hidden parent elements, including this element.
+ _self.hidden = $child.parents().andSelf().filter( ":hidden" );
+
+ // Loop through all hidden elements.
+ _self.hidden.each( function() {
+
+ // Cache the element.
+ var $elem = $( this );
+
+ // Store the style attribute.
+ // Undefined if element doesn't have a style attribute.
+ _self.tmp.push( $elem.attr( 'style' ) );
+
+ // Set the element's display property to block,
+ // but ensure it's visibility is hidden.
+ $elem.css( { 'visibility' : 'hidden', 'display' : 'block' } );
+ });
+
+ }, // end adjust
+
+ /**
+ * Resets the elements previous state.
+ *
+ * @method reset
+ */
+ reset : function() {
+ // Internal reference.
+ var _self = this;
+ // Loop through our hidden element collection.
+ _self.hidden.each( function( i ) {
+ // Cache this element.
+ var $elem = $( this ),
+ _tmp = _self.tmp[ i ]; // Get the stored 'style' value for this element.
+
+ // If the stored value is undefined.
+ if( _tmp === undefined )
+ // Remove the style attribute.
+ $elem.removeAttr( 'style' );
+ else
+ // Otherwise, reset the element style attribute.
+ $elem.attr( 'style', _tmp );
+
+ });
+ // Reset the tmp array.
+ _self.tmp = [];
+ // Reset the hidden elements variable.
+ _self.hidden = null;
+
+ } // end reset
+
+ },
+
+ off : function () {
+ $(this.scope).off('.fndtn.forms');
+ }
+ };
+}(Foundation.zj, this, this.document));
612 public/javascripts/foundation/foundation.joyride.js
@@ -0,0 +1,612 @@
+/*jslint unparam: true, browser: true, indent: 2 */
+
+;(function ($, window, document, undefined) {
+ 'use strict';
+
+ Foundation.libs.joyride = {
+ name: 'joyride',
+
+ version : '4.0.0',
+
+ defaults : {
+ tipLocation : 'bottom', // 'top' or 'bottom' in relation to parent
+ nubPosition : 'auto', // override on a per tooltip bases
+ scrollSpeed : 300, // Page scrolling speed in milliseconds
+ timer : 0, // 0 = no timer , all other numbers = timer in milliseconds
+ startTimerOnClick : true, // true or false - true requires clicking the first button start the timer
+ startOffset : 0, // the index of the tooltip you want to start on (index of the li)
+ nextButton : true, // true or false to control whether a next button is used
+ tipAnimation : 'fade', // 'pop' or 'fade' in each tip
+ pauseAfter : [], // array of indexes where to pause the tour after
+ tipAnimationFadeSpeed: 300, // when tipAnimation = 'fade' this is speed in milliseconds for the transition
+ cookieMonster : false, // true or false to control whether cookies are used
+ cookieName : 'joyride', // Name the cookie you'll use
+ cookieDomain : false, // Will this cookie be attached to a domain, ie. '.notableapp.com'
+ cookieExpires : 365, // set when you would like the cookie to expire.
+ tipContainer : 'body', // Where will the tip be attached
+ postRideCallback : function (){}, // A method to call once the tour closes (canceled or complete)
+ postStepCallback : function (){}, // A method to call after each step
+ template : { // HTML segments for tip layout
+ link : '<a href="#close" class="joyride-close-tip">&times;</a>',
+ timer : '<div class="joyride-timer-indicator-wrap"><span class="joyride-timer-indicator"></span></div>',
+ tip : '<div class="joyride-tip-guide"><span class="joyride-nub"></span></div>',
+ wrapper : '<div class="joyride-content-wrapper"></div>',
+ button : '<a href="#" class="small button joyride-next-tip"></a>'
+ }
+ },
+
+ settings : {},
+
+ init : function (scope, method, options) {
+ this.scope = scope || this.scope;
+ Foundation.inherit(this, 'throttle data_options scrollTo scrollLeft delay');
+
+ if (typeof method === 'object') {
+ $.extend(true, this.settings, this.defaults, method);
+ } else {
+ $.extend(true, this.settings, this.defaults, options);
+ }
+
+ if (typeof method != 'string') {
+ if (!this.settings.init) this.events();
+
+ return this.settings.init;
+ } else {
+ return this[method].call(this, options);
+ }
+ },
+
+ events : function () {
+ var self = this;
+
+ $(this.scope)
+ .on('click.joyride', '.joyride-next-tip, .joyride-modal-bg', function (e) {
+ e.preventDefault();
+
+ if (this.settings.$li.next().length < 1) {
+ this.end();
+ } else if (this.settings.timer > 0) {
+ clearTimeout(this.settings.automate);
+ this.hide();
+ this.show();
+ this.startTimer();
+ } else {
+ this.hide();
+ this.show();
+ }
+
+ }.bind(this))
+
+ .on('click.joyride', '.joyride-close-tip', function (e) {
+ e.preventDefault();
+ this.end();
+ }.bind(this));
+
+ $(window).on('resize.fndtn.joyride', self.throttle(function () {
+ if ($('[data-joyride]').length > 0 && self.settings.$next_tip) {
+ if (self.is_phone()) {
+ self.pos_phone();
+ } else {
+ self.pos_default();
+ }
+ }
+ }, 100));
+
+ this.settings.init = true;
+ },
+
+ start : function () {
+ var self = this,
+ $this = $(this.scope).find('[data-joyride]'),
+ integer_settings = ['timer', 'scrollSpeed', 'startOffset', 'tipAnimationFadeSpeed', 'cookieExpires'],
+ int_settings_count = integer_settings.length;
+
+ if (!this.settings.init) this.init();
+
+ // non configureable settings
+ this.settings.$content_el = $this;
+ this.settings.body_offset = $(this.settings.tipContainer).position();
+ this.settings.$tip_content = this.settings.$content_el.find('> li');
+ this.settings.paused = false;
+ this.settings.attempts = 0;
+
+ this.settings.tipLocationPatterns = {
+ top: ['bottom'],
+ bottom: [], // bottom should not need to be repositioned
+ left: ['right', 'top', 'bottom'],
+ right: ['left', 'top', 'bottom']
+ };
+
+ // can we create cookies?
+ if (typeof $.cookie !== 'function') {
+ this.settings.cookieMonster = false;
+ }
+
+ // generate the tips and insert into dom.
+ if (!this.settings.cookieMonster || this.settings.cookieMonster && $.cookie(this.settings.cookieName) === null) {
+ this.settings.$tip_content.each(function (index) {
+ var $this = $(this);
+ $.extend(true, self.settings, self.data_options($this));
+ // Make sure that settings parsed from data_options are integers where necessary
+ for (var i = int_settings_count - 1; i >= 0; i--) {
+ self.settings[integer_settings[i]] = parseInt(self.settings[integer_settings[i]], 10);
+ }
+ self.create({$li : $this, index : index});
+ });
+
+ // show first tip
+ if (!this.settings.startTimerOnClick && this.settings.timer > 0) {
+ this.show('init');
+ this.startTimer();
+ } else {
+ this.show('init');
+ }
+
+ }
+ },
+
+ resume : function () {
+ this.set_li();
+ this.show();
+ },
+
+ tip_template : function (opts) {
+ var $blank, content;
+
+ opts.tip_class = opts.tip_class || '';
+
+ $blank = $(this.settings.template.tip).addClass(opts.tip_class);
+ content = $.trim($(opts.li).html()) +
+ this.button_text(opts.button_text) +
+ this.settings.template.link +
+ this.timer_instance(opts.index);
+
+ $blank.append($(this.settings.template.wrapper));
+ $blank.first().attr('data-index', opts.index);
+ $('.joyride-content-wrapper', $blank).append(content);
+
+ return $blank[0];
+ },
+
+ timer_instance : function (index) {
+ var txt;
+
+ if ((index === 0 && this.settings.startTimerOnClick && this.settings.timer > 0) || this.settings.timer === 0) {
+ txt = '';
+ } else {
+ txt = this.outerHTML($(this.settings.template.timer)[0]);
+ }
+ return txt;
+ },
+
+ button_text : function (txt) {
+ if (this.settings.nextButton) {
+ txt = $.trim(txt) || 'Next';
+ txt = this.outerHTML($(this.settings.template.button).append(txt)[0]);
+ } else {
+ txt = '';
+ }
+ return txt;
+ },
+
+ create : function (opts) {
+ var buttonText = opts.$li.attr('data-button') || opts.$li.attr('data-text'),
+ tipClass = opts.$li.attr('class'),
+ $tip_content = $(this.tip_template({
+ tip_class : tipClass,
+ index : opts.index,
+ button_text : buttonText,
+ li : opts.$li
+ }));
+
+ $(this.settings.tipContainer).append($tip_content);
+ },
+
+ show : function (init) {
+ var $timer = null;
+
+ // are we paused?
+ if (this.settings.$li === undefined
+ || ($.inArray(this.settings.$li.index(), this.settings.pauseAfter) === -1)) {
+
+ // don't go to the next li if the tour was paused
+ if (this.settings.paused) {
+ this.settings.paused = false;
+ } else {
+ this.set_li(init);
+ }
+
+ this.settings.attempts = 0;
+
+ if (this.settings.$li.length && this.settings.$target.length > 0) {
+
+ this.settings.tipSettings = $.extend(this.settings, this.data_options(this.settings.$li));
+
+ this.settings.timer = parseInt(this.settings.timer, 10);
+
+ this.settings.tipSettings.tipLocationPattern = this.settings.tipLocationPatterns[this.settings.tipSettings.tipLocation];
+
+ // scroll if not modal
+ if (!/body/i.test(this.settings.$target.selector)) {
+ this.scroll_to();
+ }
+
+ if (this.is_phone()) {
+ this.pos_phone(true);
+ } else {
+ this.pos_default(true);
+ }
+
+ $timer = this.settings.$next_tip.find('.joyride-timer-indicator');
+
+ if (/pop/i.test(this.settings.tipAnimation)) {
+
+ $timer.width(0);
+
+ if (thsi.settings.timer > 0) {
+
+ this.settings.$next_tip.show();
+
+ this.delay(function () {
+ $timer.animate({
+ width: $timer.parent().width()
+ }, this.settings.timer, 'linear');
+ }.bind(this), this.settings.tipAnimationFadeSpeed);
+
+ } else {
+ this.settings.$next_tip.show();
+
+ }
+
+
+ } else if (/fade/i.test(this.settings.tipAnimation)) {
+
+ $timer.width(0);
+
+ if (this.settings.timer > 0) {
+
+ this.settings.$next_tip
+ .fadeIn(this.settings.tipAnimationFadeSpeed)
+ .show();
+
+ this.delay(function () {
+ $timer.animate({
+ width: $timer.parent().width()
+ }, this.settings.timer, 'linear');
+ }.bind(this), this.settings.tipAnimationFadeSpeed);
+
+ } else {
+ this.settings.$next_tip.fadeIn(this.settings.tipAnimationFadeSpeed);
+
+ }
+ }
+
+ this.settings.$current_tip = this.settings.$next_tip;
+
+ // skip non-existant targets
+ } else if (this.settings.$li && this.settings.$target.length < 1) {
+
+ this.show();
+
+ } else {
+
+ this.end();
+
+ }
+ } else {
+
+ this.settings.paused = true;
+
+ }
+
+ },
+
+ is_phone : function () {
+ if (Modernizr) {
+ return Modernizr.mq('only screen and (max-width: 767px)') || $('.lt-ie9').length > 0;
+ }
+
+ return (this.settings.$window.width() < 767) ? true : false;
+ },
+
+ hide : function () {
+ this.settings.postStepCallback(this.settings.$li.index(),
+ this.settings.$current_tip);
+ $('.joyride-modal-bg').hide();
+ this.settings.$current_tip.hide();
+ },
+
+ set_li : function (init) {
+ if (init) {
+ this.settings.$li = this.settings.$tip_content.eq(this.settings.startOffset);
+ this.set_next_tip();
+ this.settings.$current_tip = this.settings.$next_tip;
+ } else {
+ this.settings.$li = this.settings.$li.next();
+ this.set_next_tip();
+ }
+
+ this.set_target();
+ },
+
+ set_next_tip : function () {
+ this.settings.$next_tip = $(".joyride-tip-guide[data-index='" + this.settings.$li.index() + "']");
+ this.settings.$next_tip.data('closed', '');
+ },
+
+ set_target : function () {
+ var cl = this.settings.$li.attr('data-class'),
+ id = this.settings.$li.attr('data-id'),
+ $sel = function () {
+ if (id) {
+ return $(document.getElementById(id));
+ } else if (cl) {
+ return $('.' + cl).first();
+ } else {
+ return $('body');
+ }
+ };
+
+ this.settings.$target = $sel();
+ },
+
+ scroll_to : function () {
+ var window_half, tipOffset;
+
+ window_half = $(window).height() / 2;
+ tipOffset = Math.ceil(this.settings.$target.offset().top - window_half + this.outerHeight(this.settings.$next_tip));
+ if (tipOffset > 0) {
+ this.scrollTo($('html, body'), tipOffset, this.settings.scrollSpeed);
+ }
+ },
+
+ paused : function () {
+ if (($.inArray((this.settings.$li.index() + 1), this.settings.pauseAfter) === -1)) {
+ return true;
+ }
+
+ return false;
+ },
+
+ restart : function () {
+ this.hide();
+ this.settings.$li = undefined;
+ this.show('init');
+ },
+
+ pos_default : function (init) {
+ var half_fold = Math.ceil($(window).height() / 2),
+ tip_position = this.settings.$next_tip.offset(),
+ $nub = this.settings.$next_tip.find('.joyride-nub'),
+ nub_height = Math.ceil(this.outerHeight($nub) / 2),
+ toggle = init || false;
+
+ // tip must not be "display: none" to calculate position
+ if (toggle) {
+ this.settings.$next_tip.css('visibility', 'hidden');
+ this.settings.$next_tip.show();
+ }
+
+ if (!/body/i.test(this.settings.$target.selector)) {
+
+ if (this.bottom()) {
+ this.settings.$next_tip.css({
+ top: (this.settings.$target.offset().top + nub_height + this.outerHeight(this.settings.$target)),
+ left: this.settings.$target.offset().left});
+
+ this.nub_position($nub, this.settings.tipSettings.nubPosition, 'top');
+
+ } else if (this.top()) {
+
+ this.settings.$next_tip.css({
+ top: (this.settings.$target.offset().top - this.outerHeight(this.settings.$next_tip) - nub_height),
+ left: this.settings.$target.offset().left});
+
+ this.nub_position($nub, this.settings.tipSettings.nubPosition, 'bottom');
+
+ } else if (this.right()) {
+
+ this.settings.$next_tip.css({
+ top: this.settings.$target.offset().top,
+ left: (this.outerWidth(this.settings.$target) + this.settings.$target.offset().left)});
+
+ this.nub_position($nub, this.settings.tipSettings.nubPosition, 'left');
+
+ } else if (this.left()) {
+
+ this.settings.$next_tip.css({
+ top: this.settings.$target.offset().top,
+ left: (this.settings.$target.offset().left - this.outerWidth(this.settings.$next_tip) - nub_height)});
+
+ this.nub_position($nub, this.settings.tipSettings.nubPosition, 'right');
+
+ }
+
+ if (!this.visible(this.corners(this.settings.$next_tip)) && this.settings.attempts < this.settings.tipSettings.tipLocationPattern.length) {
+
+ $nub.removeClass('bottom')
+ .removeClass('top')
+ .removeClass('right')
+ .removeClass('left');
+
+ this.settings.tipSettings.tipLocation = this.settings.tipSettings.tipLocationPattern[this.settings.attempts];
+
+ this.settings.attempts++;
+
+ this.pos_default(true);
+
+ }
+
+ } else if (this.settings.$li.length) {
+
+ this.pos_modal($nub);
+
+ }
+
+ if (toggle) {
+ this.settings.$next_tip.hide();
+ this.settings.$next_tip.css('visibility', 'visible');
+ }
+
+ },
+
+ pos_phone : function (init) {
+ var tip_height = this.outerHeight(this.settings.$next_tip),
+ tip_offset = this.settings.$next_tip.offset(),
+ target_height = this.outerHeight(this.settings.$target),
+ $nub = $('.joyride-nub', this.settings.$next_tip),
+ nub_height = Math.ceil(this.outerHeight($nub) / 2),
+ toggle = init || false;
+
+ $nub.removeClass('bottom')
+ .removeClass('top')
+ .removeClass('right')
+ .removeClass('left');
+
+ if (toggle) {
+ this.settings.$next_tip.css('visibility', 'hidden');
+ this.settings.$next_tip.show();
+ }
+
+ if (!/body/i.test(this.settings.$target.selector)) {
+
+ if (this.top()) {
+
+ this.settings.$next_tip.offset({top: this.settings.$target.offset().top - tip_height - nub_height});
+ $nub.addClass('bottom');
+
+ } else {
+
+ this.settings.$next_tip.offset({top: this.settings.$target.offset().top + target_height + nub_height});
+ $nub.addClass('top');
+
+ }
+
+ } else if (this.settings.$li.length) {
+ this.pos_modal($nub);
+ }
+
+ if (toggle) {
+ this.settings.$next_tip.hide();
+ this.settings.$next_tip.css('visibility', 'visible');
+ }
+ },
+
+ pos_modal : function ($nub) {
+ this.center();
+ $nub.hide();
+ if (!this.settings.$next_tip.data('closed')) {
+ if ($('.joyride-modal-bg').length < 1) {
+ $('body').append('<div class="joyride-modal-bg">').show();
+ }
+
+ if (/pop/i.test(this.settings.tipAnimation)) {
+ $('.joyride-modal-bg').show();
+ } else {
+ $('.joyride-modal-bg').fadeIn(this.settings.tipAnimationFadeSpeed);
+ }
+ }
+ },
+
+ center : function () {
+ var $w = $(window);
+
+ this.settings.$next_tip.css({
+ top : ((($w.height() - this.outerHeight(this.settings.$next_tip)) / 2) + $w.scrollTop()),
+ left : ((($w.width() - this.outerWidth(this.settings.$next_tip)) / 2) + this.scrollLeft($w))
+ });
+
+ return true;
+ },
+
+ bottom : function () {
+ return /bottom/i.test(this.settings.tipSettings.tipLocation);
+ },
+
+ top : function () {
+ return /top/i.test(this.settings.tipSettings.tipLocation);
+ },
+
+ right : function () {
+ return /right/i.test(this.settings.tipSettings.tipLocation);
+ },
+
+ left : function () {
+ return /left/i.test(this.settings.tipSettings.tipLocation);
+ },
+
+ corners : function (el) {
+ var w = $(window),
+ right = w.width() + this.scrollLeft(w),
+ bottom = w.width() + w.scrollTop();
+
+ return [
+ el.offset().top <= w.scrollTop(),
+ right <= el.offset().left + this.outerWidth(el),
+ bottom <= el.offset().top + this.outerHeight(el),
+ this.scrollLeft(w) >= el.offset().left
+ ];
+ },
+
+ visible : function (hidden_corners) {
+ var i = hidden_corners.length;
+
+ while (i--) {
+ if (hidden_corners[i]) return false;
+ }
+
+ return true;
+ },
+
+ nub_position : function (nub, pos, def) {
+ if (pos === 'auto') {
+ nub.addClass(def);
+ } else {
+ nub.addClass(pos);
+ }
+ },
+
+ startTimer : function () {
+ if (this.settings.$li.length) {
+ this.settings.automate = setTimeout(function () {
+ this.hide();
+ this.show();
+ this.startTimer();
+ }.bind(this), this.settings.timer);
+ } else {
+ clearTimeout(this.settings.automate);
+ }
+ },
+
+ end : function () {
+ if (this.settings.cookieMonster) {
+ $.cookie(this.settings.cookieName, 'ridden', { expires: this.settings.cookieExpires, domain: this.settings.cookieDomain });
+ }
+
+ if (this.settings.timer > 0) {
+ clearTimeout(this.settings.automate);
+ }
+
+ this.settings.$next_tip.data('closed', true);
+
+ $('.joyride-modal-bg').hide();
+ this.settings.$current_tip.hide();
+ this.settings.postStepCallback(this.settings.$li.index(), this.settings.$current_tip);
+ this.settings.postRideCallback(this.settings.$li.index(), this.settings.$current_tip);
+ },
+
+ outerHTML : function (el) {
+ // support FireFox < 11
+ return el.outerHTML || new XMLSerializer().serializeToString(el);
+ },
+
+ off : function () {
+ $(this.scope).off('.joyride');
+ $(window).off('.joyride');
+ $('.joyride-close-tip, .joyride-next-tip, .joyride-modal-bg').off('.joyride');
+ $('.joyride-tip-guide, .joyride-modal-bg').remove();
+ clearTimeout(this.settings.automate);
+ this.settings = {};
+ }
+ };
+}(Foundation.zj, this, this.document));
357 public/javascripts/foundation/foundation.js
@@ -0,0 +1,357 @@
+/*
+ * Foundation Responsive Library
+ * http://foundation.zurb.com
+ * Copyright 2013, ZURB
+ * Free to use under the MIT license.
+ * http://www.opensource.org/licenses/mit-license.php
+*/
+
+/*jslint unparam: true, browser: true, indent: 2 */
+
+// Accommodate running jQuery or Zepto in noConflict() mode by
+// using an anonymous function to redefine the $ shorthand name.
+// See http://docs.jquery.com/Using_jQuery_with_Other_Libraries
+// and http://zeptojs.com/
+var libFuncName = null;
+if (typeof jQuery === "undefined" &&
+ typeof Zepto === "undefined" &&
+ typeof $ === "function") {
+ libFuncName = $;
+} else if (typeof jQuery === "function") {
+ libFuncName = jQuery;
+} else if (typeof Zepto === "function") {
+ libFuncName = Zepto;
+} else {
+ throw new TypeError();
+}
+
+(function ($) {
+
+(function () {
+ // add dusty browser stuff
+ if (!Array.prototype.filter) {
+ Array.prototype.filter = function(fun /*, thisp */) {
+ "use strict";
+
+ if (this == null) {
+ throw new TypeError();
+ }
+
+ var t = Object(this),
+ len = t.length >>> 0;
+ if (typeof fun != "function") {
+ try {
+ throw new TypeError();
+ } catch (e) {
+ return;
+ }
+ }
+
+ var res = [],
+ thisp = arguments[1];
+ for (var i = 0; i < len; i++) {
+ if (i in t) {
+ var val = t[i]; // in case fun mutates this
+ if (fun && fun.call(thisp, val, i, t)) {
+ res.push(val);
+ }
+ }
+ }
+
+ return res;
+ };
+
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function (oThis) {
+ if (typeof this !== "function") {
+ // closest thing possible to the ECMAScript 5 internal IsCallable function
+ throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
+ }
+
+ var aArgs = Array.prototype.slice.call(arguments, 1),
+ fToBind = this,
+ fNOP = function () {},
+ fBound = function () {
+ return fToBind.apply(this instanceof fNOP && oThis
+ ? this
+ : oThis,
+ aArgs.concat(Array.prototype.slice.call(arguments)));
+ };
+
+ fNOP.prototype = this.prototype;
+ fBound.prototype = new fNOP();
+
+ return fBound;
+ };
+ }
+ }
+
+ // fake stop() for zepto.
+ $.fn.stop = $.fn.stop || function() {
+ return this;
+ };
+}());
+
+;(function (window, document, undefined) {
+ 'use strict';
+
+ window.Foundation = {
+ name : 'Foundation',
+
+ version : '4.0.0',
+
+ // global Foundation cache object
+ cache : {},
+
+ init : function (scope, libraries, method, options, response, /* internal */ nc) {
+ var library_arr,
+ args = [scope, method, options, response],
+ responses = [],
+ nc = nc || false;
+
+ // disable library error catching,
+ // used for development only
+ if (nc) this.nc = nc;
+
+ // set foundation global scope
+ this.scope = scope || this.scope;
+
+ if (libraries && typeof libraries === 'string') {
+ if (/off/i.test(libraries)) return this.off();
+
+ library_arr = libraries.split(' ');
+
+ if (library_arr.length > 0) {
+ for (var i = library_arr.length - 1; i >= 0; i--) {
+ responses.push(this.init_lib(library_arr[i], args));
+ }
+ }
+ } else {
+ for (var lib in this.libs) {
+ responses.push(this.init_lib(lib, args));
+ }
+ }
+
+ // if first argument is callback, add to args
+ if (typeof libraries === 'function') {
+ args.unshift(libraries);
+ }
+
+ return this.response_obj(responses, args);
+ },
+
+ response_obj : function (response_arr, args) {
+ for (var callback in args) {
+ if (typeof args[callback] === 'function') {
+ return args[callback]({
+ errors: response_arr.filter(function (s) {
+ if (typeof s === 'string') return s;
+ })
+ });
+ }
+ }
+
+ return response_arr;
+ },
+
+ init_lib : function (lib, args) {
+ return this.trap(function () {
+ if (this.libs.hasOwnProperty(lib)) {
+ this.patch(this.libs[lib]);
+ return this.libs[lib].init.apply(this.libs[lib], args);
+ }
+ }.bind(this), lib);
+ },
+
+ trap : function (fun, lib) {
+ if (!this.nc) {
+ try {
+ return fun();
+ } catch (e) {
+ return this.error({name: lib, message: 'could not be initialized', more: e.name + ' ' + e.message});
+ }
+ }
+
+ return fun();
+ },
+
+ patch : function (lib) {
+ this.fix_outer(lib);
+ },
+
+ inherit : function (scope, methods) {
+ var methods_arr = methods.split(' ');
+
+ for (var i = methods_arr.length - 1; i >= 0; i--) {
+ if (this.lib_methods.hasOwnProperty(methods_arr[i])) {
+ this.libs[scope.name][methods_arr[i]] = this.lib_methods[methods_arr[i]];
+ }
+ }
+ },
+
+ libs : {},
+
+ // methods that can be inherited in libraries
+ lib_methods : {
+ set_data : function (node, data) {
+ // this.name references the name of the library calling this method
+ var id = this.name + (+new Date());
+
+ Foundation.cache[id] = data;
+ node.attr('data-' + this.name + '-id', id);
+ },
+
+ get_data : function (node) {
+ return Foundation.cache[node.attr('data-' + this.name + '-id')];
+ },
+
+ remove_data : function (node) {
+ if (node) {
+ delete Foundation.cache[node.attr('data-' + this.name + '-id')];
+ node.attr('data-' + this.name + '-id', '');
+ } else {
+ $('[data-' + this.name + '-id]').each(function () {
+ delete Foundation.cache[$(this).attr('data-' + this.name + '-id')];
+ $(this).attr('data-' + this.name + '-id', '');
+ });
+ }
+ },
+
+ throttle : function(fun, delay) {
+ var timer = null;
+ return function () {
+ var context = this, args = arguments;
+ clearTimeout(timer);
+ timer = setTimeout(function () {
+ fun.apply(context, args);
+ }, delay);
+ };
+ },
+
+ // parses data-options attribute on page nodes and turns
+ // them into an object
+ data_options : function (el) {
+ var opts = {}, ii, p,
+ opts_arr = (el.attr('data-options') || ':').split(';'),
+ opts_len = opts_arr.length;
+
+ function isNumber (o) {
+ return ! isNaN (o-0) && o !== null && o !== "" && o !== false;
+ }
+
+ function trim(str) {
+ if (typeof str === 'string') return $.trim(str);
+ return str;
+ }
+
+ // parse options
+ for (ii = opts_len - 1; ii >= 0; ii--) {
+ p = opts_arr[ii].split(':');
+
+ if (/true/i.test(p[1])) p[1] = true;
+ if (/false/i.test(p[1])) p[1] = false;
+ if (isNumber(p[1])) p[1] = parseInt(p[1], 10);
+
+ if (p.length === 2) {
+ opts[trim(p[0])] = trim(p[1]);
+ }
+ }
+
+ return opts;
+ },
+
+ delay : function (fun, delay) {
+ return setTimeout(fun, delay);
+ },
+
+ // animated scrolling
+ scrollTo : function (el, to, duration) {
+ if (duration < 0) return;
+ var difference = to - $(window).scrollTop();
+ var perTick = difference / duration * 10;
+
+ this.scrollToTimerCache = setTimeout(function() {
+ if (!isNaN(parseInt(perTick, 10))) {
+ window.scrollTo(0, $(window).scrollTop() + perTick);
+ this.scrollTo(el, to, duration - 10);
+ }
+ }.bind(this), 10);
+ },
+
+ // not supported in core Zepto
+ scrollLeft : function (el) {
+ if (!el.length) return;
+ return ('scrollLeft' in el[0]) ? el[0].scrollLeft : el[0].pageXOffset;
+ },
+
+ // test for empty object or array
+ empty : function (obj) {
+ if (obj.length && obj.length > 0) return false;
+ if (obj.length && obj.length === 0) return true;
+
+ for (var key in obj) {
+ if (hasOwnProperty.call(obj, key)) return false;
+ }
+
+ return true;
+ }
+ },
+
+ fix_outer : function (lib) {
+ lib.outerHeight = function (el, bool) {
+ if (typeof Zepto === 'function') {
+ return el.height();
+ }
+
+ if (typeof bool !== 'undefined') {
+ return el.outerHeight(bool);
+ }
+
+ return el.outerHeight();
+ };
+
+ lib.outerWidth = function (el) {
+ if (typeof Zepto === 'function') {
+ return el.width();
+ }
+
+ if (typeof bool !== 'undefined') {
+ return el.outerWidth(bool);
+ }
+
+ return el.outerWidth();
+ };
+ },
+
+ error : function (error) {
+ return error.name + ' ' + error.message + '; ' + error.more;
+ },
+
+ // remove all foundation events.
+ off: function () {
+ $(this.scope).off('.fndtn');
+ $(window).off('.fndtn');
+ return true;
+ },
+
+ zj : function () {
+ try {
+ return Zepto;
+ } catch (e) {
+ return jQuery;
+ }
+ }()
+ },
+
+ $.fn.foundation = function () {
+ var args = Array.prototype.slice.call(arguments, 0);
+
+ return this.each(function () {
+ Foundation.init.apply(Foundation, [this].concat(args));
+ return this;
+ });
+ };
+
+}(this, this.document));
+
+})(libFuncName);
130 public/javascripts/foundation/foundation.magellan.js
@@ -0,0 +1,130 @@
+/*jslint unparam: true, browser: true, indent: 2 */
+
+;(function ($, window, document, undefined) {
+ 'use strict';
+
+ Foundation.libs.magellan = {
+ name : 'magellan',
+
+ version : '4.0.0',
+
+ settings : {
+ activeClass: 'active'
+ },
+
+ init : function (scope, method, options) {
+ this.scope = scope || this.scope;
+ Foundation.inherit(this, 'data_options');
+
+ if (typeof method === 'object') {
+ $.extend(true, this.settings, method);
+ }
+
+ if (typeof method != 'string') {
+ if (!this.settings.init) {
+ this.fixed_magellan = $("[data-magellan-expedition]");
+ this.set_threshold();
+ this.last_destination = $('[data-magellan-destination]').last();
+ this.events();
+ }
+
+ return this.settings.init;
+ } else {
+ return this[method].call(this, options);
+ }
+ },
+
+ events : function () {
+ var self = this;
+ $(this.scope).on('arrival.fndtn.magellan', '[data-magellan-arrival]', function (e) {
+ var $destination = $(this),
+ $expedition = $destination.closest('[data-magellan-expedition]'),
+ activeClass = $expedition.attr('data-magellan-active-class')
+ || self.settings.activeClass;
+
+ $destination