Browse Source

Add content and demo for Foundation 5

Last part of the m-js-css-intermediate course
tags/v0.5.0^2
Peter J. Jones 1 year ago
parent
commit
3d4a514e7e
Signed by: Peter Jones <pjones@devalot.com> GPG Key ID: 9DAFAA8D01941E49
47 changed files with 13999 additions and 58 deletions
  1. 96
    13
      content/css/frameworks/foundation.md
  2. 1
    1
      content/css/style.md
  3. 1
    1
      content/js/ajax.md
  4. 1
    3
      content/js/alternatives.md
  5. 1
    1
      content/js/basic-functions.md
  6. 1
    1
      content/js/basic-objects.md
  7. 1
    1
      content/js/closures.md
  8. 1
    1
      content/js/es6.md
  9. 1
    1
      content/js/oop/context.md
  10. 0
    2
      content/js/testing.md
  11. 1
    15
      content/js/tools.md
  12. 4
    1
      courses/javascript-intermediate.md
  13. 50
    17
      courses/m-js-css-intermediate.md
  14. BIN
      diagrams/css/foundation-button.png
  15. BIN
      diagrams/css/foundation-slider.png
  16. BIN
      diagrams/css/foundation-split.png
  17. BIN
      diagrams/css/foundation-switch.png
  18. 29
    0
      src/www/css/frameworks/foundation5/css/app.css
  19. 6579
    0
      src/www/css/frameworks/foundation5/css/foundation.css
  20. 1
    0
      src/www/css/frameworks/foundation5/css/foundation.min.css
  21. 424
    0
      src/www/css/frameworks/foundation5/css/normalize.css
  22. 148
    0
      src/www/css/frameworks/foundation5/index.html
  23. 15
    0
      src/www/css/frameworks/foundation5/js/app.js
  24. 20
    0
      src/www/css/frameworks/foundation5/js/foundation.min.js
  25. 426
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.abide.js
  26. 125
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.accordion.js
  27. 43
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.alert.js
  28. 586
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.clearing.js
  29. 468
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.dropdown.js
  30. 104
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.equalizer.js
  31. 360
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.interchange.js
  32. 935
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.joyride.js
  33. 732
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.js
  34. 214
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.magellan.js
  35. 225
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.offcanvas.js
  36. 476
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.orbit.js
  37. 522
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.reveal.js
  38. 296
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.slider.js
  39. 247
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.tab.js
  40. 348
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.tooltip.js
  41. 458
    0
      src/www/css/frameworks/foundation5/js/foundation/foundation.topbar.js
  42. 8
    0
      src/www/css/frameworks/foundation5/js/vendor/fastclick.js
  43. 8
    0
      src/www/css/frameworks/foundation5/js/vendor/jquery.cookie.js
  44. 26
    0
      src/www/css/frameworks/foundation5/js/vendor/jquery.js
  45. 8
    0
      src/www/css/frameworks/foundation5/js/vendor/modernizr.js
  46. 2
    0
      src/www/css/frameworks/foundation5/js/vendor/placeholder.js
  47. 7
    0
      src/www/css/index.html

+ 96
- 13
content/css/frameworks/foundation.md View File

@@ -19,33 +19,116 @@ clean web site by default.

* Configurable via Sass, HTML, and JavaScript

### Adding Foundation to a Project
### The Foundation Grid

TBD
The main grid system in Foundation `<=` 5.

### The Foundation Grid
~~~ {.html}
<div class="row">
<div class="large-4 columns">
Column with 4 Units.
</div>
<div class="large-8 columns">
Column with 8 Units.
</div>
</div>
~~~

(Internally implemented with Floating or Flexbox.)

### The XY Grid

The main grid system in Foundation `>=` 6.

~~~ {.html}
<div class="grid-container">
<div class="grid-x">
<div class="cell small-4">A Cell</div>
<div class="cell small-4">A Cell</div>
<div class="cell small-4">A Cell</div>
</div>
</div>
~~~

(Internally implemented with Flexbox.)

### User Interface Controls

Foundation provides a variety of user interface elements:

* Buttons

* Switches

* Sliders

* Menus

* Navigation bars

* Breadcrumbs

TDB
* etc.

### Controls
### Buttons

TBD (buttons, sliders, etc)
![](../../../diagrams/css/foundation-button.png)\
<!-- Placeholder -->

### Navigation
~~~ {.html insert="../../../src/www/css/frameworks/foundation5/index.html" token="button"}
~~~

TBD
### Split Buttons

### Containers
![](../../../diagrams/css/foundation-split.png)\
<!-- Placeholder -->

TBD
~~~ {.html insert="../../../src/www/css/frameworks/foundation5/index.html" token="split"}
~~~

### Switches

![](../../../diagrams/css/foundation-switch.png)\
<!-- Placeholder -->

~~~ {.html insert="../../../src/www/css/frameworks/foundation5/index.html" token="switch"}
~~~

### Sliders

![](../../../diagrams/css/foundation-slider.png)\
<!-- Placeholder -->

~~~ {.html insert="../../../src/www/css/frameworks/foundation5/index.html" token="slider"}
~~~

(There are also progress bars in Foundation.)

### Foundation and Sass

TBD
Foundation is written in Sass and JavaScript. With the full Sass
distribution of Foundation you can:

* Change settings and colors (`_settings.scss`)

* Recompile with Grunt, Gulp, Webpack, etc.

* Have more control over which parts of Foundation you include in
your project (i.e. reduce its size)

### Experimenting with Foundation

Let's take a look at a Foundation demonstration application:

#. Open the following folder in your text editor:

src/www/css/frameworks/foundation5

### The Foundation XY Grid
#. Review the `index.html` file

TBD
If you are running your Node.js server you can access this
application [using this link][foundation5-demo].

<!-- === Links === -->
[foundation]: https://foundation.zurb.com
[foundation5-demo]: http://localhost:3000/css/frameworks/foundation5/

+ 1
- 1
content/css/style.md View File

@@ -1,4 +1,4 @@
## Advanced Font Tricks
## Advanced Font Tricks ## {#fonts}

### Specifying Fonts


+ 1
- 1
content/js/ajax.md View File

@@ -125,7 +125,7 @@ More work to extract data from XML:

## Putting It All Together

### Exercise: Making Ajax Requests
### Exercise: Making Ajax Requests ### {#lab}

#. Open the following files:


+ 1
- 3
content/js/alternatives.md View File

@@ -1,6 +1,4 @@
# Alternatives and Extensions to JavaScript

## Overview
## Alternatives and Extensions to JavaScript

### Languages that Compile to JavaScript


+ 1
- 1
content/js/basic-functions.md View File

@@ -59,7 +59,7 @@ var result = add(1, 2); // 3

- Missing arguments will be `undefined`

### Function Invocation (Example)
### Function Invocation (Example) ### {#wrong-args}

~~~ {.javascript}
var add = function(a, b) {

+ 1
- 1
content/js/basic-objects.md View File

@@ -1,6 +1,6 @@
## Objects

### A Collection of Key/Value Pairs
### A Collection of Key/Value Pairs ### {#key-value}

- Built up from the core types


+ 1
- 1
content/js/closures.md View File

@@ -30,7 +30,7 @@

See: `src/examples/js/closure.html`

### Closures: Practical Example
### Closures: Practical Example ### {#private}

~~~ {.javascript}
var Foo = function() {

+ 1
- 1
content/js/es6.md View File

@@ -247,7 +247,7 @@ Produces this output:

(This function first appeared in ECMAScript Edition 6, 2015.)

## ES2015 Modules ## {#modules}
## JavaScript Modules ## {#modules}

### Exporting and Importing ### {#modules-export}


+ 1
- 1
content/js/oop/context.md View File

@@ -11,7 +11,7 @@
- Dynamic, defined at runtime
- Context is accessible as the `this` variable

### Context Example
### Context Example ### {#example-this}

~~~ {.javascript insert="../../../src/examples/js/this.js"}
~~~

+ 0
- 2
content/js/testing.md View File

@@ -1,5 +1,3 @@
# Testing in JavaScript

## General Testing Overview

### Testing in the Browser

+ 1
- 15
content/js/tools.md View File

@@ -1,18 +1,4 @@
# Development Tools

## Inside the Browser

### Debugging

* Complete debugging with breakpoints and watch variables

* Built into all of the major browsers

* The `console` and `debugger` objects

* WebSockets API for working with the debugger remotely

## Outside of the Browser
## Development Tools

### Node.js


+ 4
- 1
courses/javascript-intermediate.md View File

@@ -62,7 +62,8 @@ This JavaScript course is delivered during two days.
<!-- Advanced OOP -->
<<(../content/js/adv-oop.md)

<!-- Testing -->
# Testing in JavaScript

<<(../content/js/testing.md)

<!-- The runtime and promises -->
@@ -77,6 +78,8 @@ This JavaScript course is delivered during two days.
<<(../content/js/popular-apis.md)
<<(../content/js/frameworks.md)

# Real World JavaScript Development

<<(../content/js/alternatives.md)
<<(../content/js/tools.md)
<<(../content/js/resources.md)

+ 50
- 17
courses/m-js-css-intermediate.md View File

@@ -31,8 +31,12 @@ This course is delivered over three days.

### What's In Store {.unnumbered}

Day 1 Day 2 Day 3
------------------------- ----------------- ------------------
| Day 1 | Day 2 | Day 3 |
|-------------------+-----------------+--------------------|
| JavaScript Review | Promises | Responsive Design |
| DOM Manipulation | ES2015--ES2017 | Designing w/ Grids |
| Event Handling | Testing | Foundation |
| Ajax and JSON | Selector Review | Webpack |

<!-- ====================================================================== -->
<!-- And now, the content... -->
@@ -42,20 +46,35 @@ This course is delivered over three days.

# JavaScript Review (Warming Up)

<<(../content/js/basic-functions.md#a5d15bd6258111e8a686cf157ebd8e95)
<<(../content/js/basic-functions.md#a706548258211e8a1a73f1bc7dcefa25)
<<(../content/js/closures.md#e926298a258211e8abc83b6fee9937e9)
<<(../content/js/values-types.md#ec9075fc36c911e8bf5bdbeceee344b0)
<<(../content/js/values-types.md#ec9075fc36c911e8bf5bdbeceee344b0)

## Document Object Model Review
## Objects ##

<<(../content/js/dom/fetch.md#c90768f0258511e8b89193e5afe59cab)
<<(../content/js/dom/traversal.md#e8f42bd0258511e8936dbfa61311da9e)
<<(../content/js/dom/create.md#f89dbf4c258511e8952d0b8f8af2f634)
<<(../content/js/dom/create.md#a5306c0a258611e8bfa2af6ab5c5b3cc)
<<(../content/js/dom/text.md#a3af8004258611e88aa2efbe26ab52d0)
<<(../content/js/dom/events.md#a6c1d41c258611e89ac42bb59fa4b75e)
<<(../content/js/dom/warmup-ex.md)
<<(../content/js/basic-objects.md#key-value)

## Functions ##

<<(../content/js/basic-functions.md#wrong-args)
<<(../content/js/oop/context.md#example-this)
<<(../content/js/closures.md#private)

# The Document Object Model

<<(../content/js/dom/intro.md)
<<(../content/js/dom/fetch.md)
<<(../content/js/dom/traversal.md)
<<(../content/js/dom/types.md)
<<(../content/js/dom/create.md)
<<(../content/js/dom/text.md)
<<(../content/js/dom/flags.md)
<<(../content/js/jquery/intro.md)
<<(../content/js/jquery/dom.md)

# Event Handling

<<(../content/js/dom/events.md)
<<(../content/js/jquery/events.md)
<<(../content/js/dom/warmup-ex.md)

# Asynchronous JavaScript and XML

@@ -64,21 +83,35 @@ This course is delivered over three days.
<<(../content/js/apis/fetch.md)
<<(../content/js/adv-async.md#promises)
<<(../content/js/mvc.md#a67c1f10257c11e89c00134983c63ac9)
<<(../content/js/ajax.md#lab)

<!-- * Observables -->
<!-- === ES2015--ES2017 === -->

<<(../content/js/es6.md)
<<(../content/js/es7.md)
<<(../content/js/es8.md)

# Testing in JavaScript

<<(../content/js/testing.md)

# Intermediate CSS

<!-- Icons and Web Fonts -->
<<(../content/css/style.md#fonts)
<<(../content/css/layout/responsive.md)
<!-- Grids -->
<<(../content/css/layout/grid.md)
<<(../content/css/selectors/basic.md)
<<(../content/css/selectors/relation.md)
<<(../content/css/selectors/basic-pseudo.md)
<<(../content/css/selectors/pseudo-chlid.md)
<<(../content/css/selectors/pseudo-funcs.md)
<<(../content/css/selectors/not.md)
<<(../content/css/selectors/attribute.md)

# Web Development: Frameworks and Tools

<<(../content/js/alternatives.md)
<<(../content/js/tools.md)
<<(../content/css/tools/preprocessors.md)
<<(../content/css/frameworks/foundation.md)
<<(../content/js/tools/webpack.md)

BIN
diagrams/css/foundation-button.png View File


BIN
diagrams/css/foundation-slider.png View File


BIN
diagrams/css/foundation-split.png View File


BIN
diagrams/css/foundation-switch.png View File


+ 29
- 0
src/www/css/frameworks/foundation5/css/app.css View File

@@ -0,0 +1,29 @@
.row {
padding: 1em 0;
}

.alt {
background-color: #eee;
border-bottom: 2px solid #ddd;
}

.artists {
min-height: 10em;
}

.artists li {
font-size: 1.2em;
}

footer {
background: #555;
color: #fff;
}

footer p, footer li {
font-size: 0.9em;
}

main {
height: 100vh;
}

+ 6579
- 0
src/www/css/frameworks/foundation5/css/foundation.css
File diff suppressed because it is too large
View File


+ 1
- 0
src/www/css/frameworks/foundation5/css/foundation.min.css
File diff suppressed because it is too large
View File


+ 424
- 0
src/www/css/frameworks/foundation5/css/normalize.css View File

@@ -0,0 +1,424 @@
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */

/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS and IE text size adjust after device orientation change,
* without disabling user zoom.
*/

html {
font-family: sans-serif; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}

/**
* Remove default margin.
*/

body {
margin: 0;
}

/* HTML5 display definitions
========================================================================== */

/**
* Correct `block` display not defined for any HTML5 element in IE 8/9.
* Correct `block` display not defined for `details` or `summary` in IE 10/11
* and Firefox.
* Correct `block` display not defined for `main` in IE 11.
*/

article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
display: block;
}

/**
* 1. Correct `inline-block` display not defined in IE 8/9.
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
*/

audio,
canvas,
progress,
video {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}

/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/

audio:not([controls]) {
display: none;
height: 0;
}

/**
* Address `[hidden]` styling not present in IE 8/9/10.
* Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
*/

[hidden],
template {
display: none;
}

/* Links
========================================================================== */

/**
* Remove the gray background color from active links in IE 10.
*/

a {
background-color: transparent;
}

/**
* Improve readability of focused elements when they are also in an
* active/hover state.
*/

a:active,
a:hover {
outline: 0;
}

/* Text-level semantics
========================================================================== */

/**
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
*/

abbr[title] {
border-bottom: 1px dotted;
}

/**
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
*/

b,
strong {
font-weight: bold;
}

/**
* Address styling not present in Safari and Chrome.
*/

dfn {
font-style: italic;
}

/**
* Address variable `h1` font-size and margin within `section` and `article`
* contexts in Firefox 4+, Safari, and Chrome.
*/

h1 {
font-size: 2em;
margin: 0.67em 0;
}

/**
* Address styling not present in IE 8/9.
*/

mark {
background: #ff0;
color: #000;
}

/**
* Address inconsistent and variable font size in all browsers.
*/

small {
font-size: 80%;
}

/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/

sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}

sup {
top: -0.5em;
}

sub {
bottom: -0.25em;
}

/* Embedded content
========================================================================== */

/**
* Remove border when inside `a` element in IE 8/9/10.
*/

img {
border: 0;
}

/**
* Correct overflow not hidden in IE 9/10/11.
*/

svg:not(:root) {
overflow: hidden;
}

/* Grouping content
========================================================================== */

/**
* Address margin not present in IE 8/9 and Safari.
*/

figure {
margin: 1em 40px;
}

/**
* Address differences between Firefox and other browsers.
*/

hr {
box-sizing: content-box;
height: 0;
}

/**
* Contain overflow in all browsers.
*/

pre {
overflow: auto;
}

/**
* Address odd `em`-unit font size rendering in all browsers.
*/

code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}

/* Forms
========================================================================== */

/**
* Known limitation: by default, Chrome and Safari on OS X allow very limited
* styling of `select`, unless a `border` property is set.
*/

/**
* 1. Correct color not being inherited.
* Known issue: affects color of disabled elements.
* 2. Correct font properties not being inherited.
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
*/

button,
input,
optgroup,
select,
textarea {
color: inherit; /* 1 */
font: inherit; /* 2 */
margin: 0; /* 3 */
}

/**
* Address `overflow` set to `hidden` in IE 8/9/10/11.
*/

button {
overflow: visible;
}

/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
* Correct `select` style inheritance in Firefox.
*/

button,
select {
text-transform: none;
}

/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/

button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}

/**
* Re-set default cursor for disabled elements.
*/

button[disabled],
html input[disabled] {
cursor: default;
}

/**
* Remove inner padding and border in Firefox 4+.
*/

button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}

/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/

input {
line-height: normal;
}

/**
* It's recommended that you don't attempt to style these elements.
* Firefox's implementation doesn't respect box-sizing, padding, or width.
*
* 1. Address box sizing set to `content-box` in IE 8/9/10.
* 2. Remove excess padding in IE 8/9/10.
*/

input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}

/**
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
* `font-size` values of the `input`, it causes the cursor style of the
* decrement button to change from `default` to `text`.
*/

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
height: auto;
}

/**
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
*/

input[type="search"] {
-webkit-appearance: textfield; /* 1 */
box-sizing: content-box; /* 2 */
}

/**
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
* Safari (but not Chrome) clips the cancel button when the search input has
* padding (and `textfield` appearance).
*/

input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}

/**
* Define consistent border, margin, and padding.
*/

fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}

/**
* 1. Correct `color` not being inherited in IE 8/9/10/11.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/

legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}

/**
* Remove default vertical scrollbar in IE 8/9/10/11.
*/

textarea {
overflow: auto;
}

/**
* Don't inherit the `font-weight` (applied by a rule above).
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
*/

optgroup {
font-weight: bold;
}

/* Tables
========================================================================== */

/**
* Remove most spacing between table cells.
*/

table {
border-collapse: collapse;
border-spacing: 0;
}

td,
th {
padding: 0;
}

+ 148
- 0
src/www/css/frameworks/foundation5/index.html View File

@@ -0,0 +1,148 @@
<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Foundation Demo</title>
<link rel="stylesheet" href="css/app.css" />
<link rel="stylesheet" href="css/foundation.css" />
<script src="js/vendor/modernizr.js"></script>
</head>
<body>
<main>
<nav class="top-bar" data-topbar>
<ul class="title-area">
<li class="name"><h1><a href="#">Foundation Demo</h1></a>
</ul>

<section class="top-bar-section">
<ul class="right">
<li class="active"><a href="#">Home</a>
<li><a href="#">Artists</a>
</ul>
</section>
</nav>

<div class="alt">
<div class="row">
<div class="medium-4 columns">
<h2>Our Artists</h2>
</div>

<div class="medium-8 columns">
<p>
Aliquam erat volutpat. Nunc eleifend leo vitae magna. In
id erat non orci commodo lobortis. Proin neque massa,
cursus ut, gravida ut, lobortis eget, lacus. Sed diam.
Praesent fermentum tempor tellus. Nullam tempus. Mauris ac
felis vel velit tristique imperdiet. Donec at pede. Etiam
vel neque nec dui dignissim bibendum. Vivamus id enim.
Phasellus neque orci, porta a, aliquet quis, semper a,
massa. Phasellus purus. Pellentesque tristique imperdiet
tortor. Nam euismod tellus id erat.
</p>
</div>
</div>
</div>

<section class="artists row">
<div id="view" class="medium-9 columns">
<ul>
<li>Hey there, click the button!
</ul>
</div>

<div class="medium-3 columns">
<a href="#" id="load" class="button round">Load</a>
</div>
</section>

<div>
<div class="row">
<div class="small-6 columns">
<!-- <<: button -->
<a href="#" class="button">Go!</a>
<!-- :>> -->
</div>
<div class="small-6 columns">
<!-- <<: split -->
<a href="#" class="button split">Reload<span data-dropdown="drop"></span></a><br>
<ul id="drop" class="f-dropdown" data-dropdown-content>
<li><a href="#">Delete Cache</a></li>
<li><a href="#">Delete Cache and Reload</a></li>
<li><a href="#">Launch Missiles</a></li>
</ul>
<!-- :>> -->
</div>
</div>

<div class="row">
<div class="small-6 columns">
<!-- <<: switch -->
<div class="switch">
<input id="checkbox" type="checkbox">
<label for="checkbox">Checkbox</label>
</div>
<!-- :>> -->
</div>
<div class="small-6 columns">
<!-- <<: slider -->
<div class="range-slider" data-slider>
<span class="range-slider-handle"></span>
<span class="range-slider-active-segment"></span>
<input type="hidden">
</div>
<!-- :>> -->
</div>
</div>
</div>

<footer>
<div class="row">
<section class="medium-6 columns">
<p class="copyright">
Copyright &#169; 2016 Awesome Company, All Rights Reserved.
</p>

<p>
Aliquam erat volutpat. Nunc eleifend leo vitae magna. In id
erat non orci commodo lobortis. Proin neque massa, cursus ut,
gravida ut, lobortis eget, lacus. Sed diam. Praesent
fermentum tempor tellus. Nullam tempus. Mauris ac felis vel
velit tristique imperdiet. Donec at pede. Etiam vel neque
nec dui dignissim bibendum. Vivamus id enim. Phasellus neque
orci, porta a, aliquet quis, semper a, massa. Phasellus
purus. Pellentesque tristique imperdiet tortor. Nam euismod
tellus id erat.
</p>
</section>

<section class="medium-6 columns">
<ul>
<li><a href="#">Mauris mollis tincidunt felis.</a></li>
<li><a href="#">Nunc rutrum turpis sed pede.</a></li>
<li><a href="#">Phasellus purus.</a></li>
<li><a href="#">Nulla posuere.</a></li>
</ul>
</section>
</div>
</footer>

<script id="template" type="x-tmpl-mustache">
<ul>
{{#artists}}
<li>{{name}} ({{formation_year}})</li>
{{/artists}}
</ul>
</script>

<script src="js/vendor/jquery.js"></script>
<script src="js/foundation.min.js"></script>
<script src="../../../js/discography/js/vendor/mustache.min.js"></script>
<script src="js/app.js"></script>
<script>
$(document).foundation();
</script>
</main>
</body>
</html>

+ 15
- 0
src/www/css/frameworks/foundation5/js/app.js View File

@@ -0,0 +1,15 @@
$(function() {
function load() {
$.getJSON("/api/artists")
.then(function(artists) {
var template = $("#template").html();
var view = Mustache.render(template, {artists: artists});
$("#view").html(view);
})
.fail(function(error) {
console.error("bloody hell: ", error);
});
}

$("#load").click(load);
});

+ 20
- 0
src/www/css/frameworks/foundation5/js/foundation.min.js
File diff suppressed because it is too large
View File


+ 426
- 0
src/www/css/frameworks/foundation5/js/foundation/foundation.abide.js View File

@@ -0,0 +1,426 @@
;(function ($, window, document, undefined) {
'use strict';

Foundation.libs.abide = {
name : 'abide',

version : '5.5.3',

settings : {
live_validate : true, // validate the form as you go
validate_on_blur : true, // validate whenever you focus/blur on an input field
// validate_on: 'tab', // tab (when user tabs between fields), change (input changes), manual (call custom events)

focus_on_invalid : true, // automatically bring the focus to an invalid input field
error_labels : true, // labels with a for="inputId" will receive an `error` class
error_class : 'error', // labels with a for="inputId" will receive an `error` class
// the amount of time Abide will take before it validates the form (in ms).
// smaller time will result in faster validation
timeout : 1000,
patterns : {
alpha : /^[a-zA-Z]+$/,
alpha_numeric : /^[a-zA-Z0-9]+$/,
integer : /^[-+]?\d+$/,
number : /^[-+]?\d*(?:[\.\,]\d+)?$/,

// amex, visa, diners
card : /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/,
cvv : /^([0-9]){3,4}$/,

// http://www.whatwg.org/specs/web-apps/current-work/multipage/states-of-the-type-attribute.html#valid-e-mail-address
email : /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$/,

// http://blogs.lse.ac.uk/lti/2008/04/23/a-regular-expression-to-match-any-url/
url: /^(https?|ftp|file|ssh):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+~%\/\.\w]+)?\??([-\+=&;%@\.\w]+)?#?([\w]+)?)?/,
// abc.de
domain : /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,8}$/,

datetime : /^([0-2][0-9]{3})\-([0-1][0-9])\-([0-3][0-9])T([0-5][0-9])\:([0-5][0-9])\:([0-5][0-9])(Z|([\-\+]([0-1][0-9])\:00))$/,
// YYYY-MM-DD
date : /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))$/,
// HH:MM:SS
time : /^(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]){2}$/,
dateISO : /^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/,
// MM/DD/YYYY
month_day_year : /^(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.]\d{4}$/,
// DD/MM/YYYY
day_month_year : /^(0[1-9]|[12][0-9]|3[01])[- \/.](0[1-9]|1[012])[- \/.]\d{4}$/,

// #FFF or #FFFFFF
color : /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/
},
validators : {
equalTo : function (el, required, parent) {
var from = document.getElementById(el.getAttribute(this.add_namespace('data-equalto'))).value,
to = el.value,
valid = (from === to);

return valid;
}
}
},

timer : null,

init : function (scope, method, options) {
this.bindings(method, options);
},

events : function (scope) {
var self = this,
form = self.S(scope).attr('novalidate', 'novalidate'),
settings = form.data(this.attr_name(true) + '-init') || {};

this.invalid_attr = this.add_namespace('data-invalid');

function validate(originalSelf, e) {
clearTimeout(self.timer);
self.timer = setTimeout(function () {
self.validate([originalSelf], e);
}.bind(originalSelf), settings.timeout);
}

form
.off('.abide')
.on('submit.fndtn.abide', function (e) {
var is_ajax = /ajax/i.test(self.S(this).attr(self.attr_name()));
return self.validate(self.S(this).find('input, textarea, select').not(":hidden, [data-abide-ignore]").get(), e, is_ajax);
})
.on('validate.fndtn.abide', function (e) {
if (settings.validate_on === 'manual') {
self.validate([e.target], e);
}
})
.on('reset', function (e) {
return self.reset($(this), e);
})
.find('input, textarea, select').not(":hidden, [data-abide-ignore]")
.off('.abide')
.on('blur.fndtn.abide change.fndtn.abide', function (e) {
var id = this.getAttribute('id'),
eqTo = form.find('[data-equalto="'+ id +'"]');
// old settings fallback
// will be deprecated with F6 release
if (settings.validate_on_blur && settings.validate_on_blur === true) {
validate(this, e);
}
// checks if there is an equalTo equivalent related by id
if(typeof eqTo.get(0) !== "undefined" && eqTo.val().length){
validate(eqTo.get(0),e);
}
// new settings combining validate options into one setting
if (settings.validate_on === 'change') {
validate(this, e);
}
})
.on('keydown.fndtn.abide', function (e) {
var id = this.getAttribute('id'),
eqTo = form.find('[data-equalto="'+ id +'"]');
// old settings fallback
// will be deprecated with F6 release
if (settings.live_validate && settings.live_validate === true && e.which != 9) {
validate(this, e);
}
// checks if there is an equalTo equivalent related by id
if(typeof eqTo.get(0) !== "undefined" && eqTo.val().length){
validate(eqTo.get(0),e);
}
// new settings combining validate options into one setting
if (settings.validate_on === 'tab' && e.which === 9) {
validate(this, e);
}
else if (settings.validate_on === 'change') {
validate(this, e);
}
})
.on('focus', function (e) {
if (navigator.userAgent.match(/iPad|iPhone|Android|BlackBerry|Windows Phone|webOS/i)) {
$('html, body').animate({
scrollTop: $(e.target).offset().top
}, 100);
}
});
},

reset : function (form, e) {
var self = this;
form.removeAttr(self.invalid_attr);

$('[' + self.invalid_attr + ']', form).removeAttr(self.invalid_attr);
$('.' + self.settings.error_class, form).not('small').removeClass(self.settings.error_class);
$(':input', form).not(':button, :submit, :reset, :hidden, [data-abide-ignore]').val('').removeAttr(self.invalid_attr);
},

validate : function (els, e, is_ajax) {
var validations = this.parse_patterns(els),
validation_count = validations.length,
form = this.S(els[0]).closest('form'),
submit_event = /submit/.test(e.type);

// Has to count up to make sure the focus gets applied to the top error
for (var i = 0; i < validation_count; i++) {
if (!validations[i] && (submit_event || is_ajax)) {
if (this.settings.focus_on_invalid) {
els[i].focus();
}
form.trigger('invalid.fndtn.abide');
this.S(els[i]).closest('form').attr(this.invalid_attr, '');
return false;
}
}

if (submit_event || is_ajax) {
form.trigger('valid.fndtn.abide');
}

form.removeAttr(this.invalid_attr);

if (is_ajax) {
return false;
}

return true;
},

parse_patterns : function (els) {
var i = els.length,
el_patterns = [];

while (i--) {
el_patterns.push(this.pattern(els[i]));
}

return this.check_validation_and_apply_styles(el_patterns);
},

pattern : function (el) {
var type = el.getAttribute('type'),
required = typeof el.getAttribute('required') === 'string';

var pattern = el.getAttribute('pattern') || '';

if (this.settings.patterns.hasOwnProperty(pattern) && pattern.length > 0) {
return [el, this.settings.patterns[pattern], required];
} else if (pattern.length > 0) {
return [el, new RegExp(pattern), required];
}

if (this.settings.patterns.hasOwnProperty(type)) {
return [el, this.settings.patterns[type], required];
}

pattern = /.*/;

return [el, pattern, required];
},

// TODO: Break this up into smaller methods, getting hard to read.
check_validation_and_apply_styles : function (el_patterns) {
var i = el_patterns.length,
validations = [];
if (i == 0) {
return validations;
}
var form = this.S(el_patterns[0][0]).closest('[data-' + this.attr_name(true) + ']'),
settings = form.data(this.attr_name(true) + '-init') || {};
while (i--) {
var el = el_patterns[i][0],
required = el_patterns[i][2],
value = el.value.trim(),
direct_parent = this.S(el).parent(),
validator = el.getAttribute(this.add_namespace('data-abide-validator')),
is_radio = el.type === 'radio',
is_checkbox = el.type === 'checkbox',
label = this.S('label[for="' + el.getAttribute('id') + '"]'),
valid_length = (required) ? (el.value.length > 0) : true,
el_validations = [];

var parent, valid;

// support old way to do equalTo validations
if (el.getAttribute(this.add_namespace('data-equalto'))) { validator = 'equalTo' }

if (!direct_parent.is('label')) {
parent = direct_parent;
} else {
parent = direct_parent.parent();
}

if (is_radio && required) {
el_validations.push(this.valid_radio(el, required));
} else if (is_checkbox && required) {
el_validations.push(this.valid_checkbox(el, required));

} else if (validator) {
// Validate using each of the specified (space-delimited) validators.
var validators = validator.split(' ');
var last_valid = true, all_valid = true;
for (var iv = 0; iv < validators.length; iv++) {
valid = this.settings.validators[validators[iv]].apply(this, [el, required, parent])
el_validations.push(valid);
all_valid = valid && last_valid;
last_valid = valid;
}
if (all_valid) {
this.S(el).removeAttr(this.invalid_attr);
parent.removeClass('error');
if (label.length > 0 && this.settings.error_labels) {
label.removeClass(this.settings.error_class).removeAttr('role');
}
$(el).triggerHandler('valid');
} else {
this.S(el).attr(this.invalid_attr, '');
parent.addClass('error');
if (label.length > 0 && this.settings.error_labels) {
label.addClass(this.settings.error_class).attr('role', 'alert');
}
$(el).triggerHandler('invalid');
}
} else {

if (el_patterns[i][1].test(value) && valid_length ||
!required && el.value.length < 1 || $(el).attr('disabled')) {
el_validations.push(true);
} else {
el_validations.push(false);
}

el_validations = [el_validations.every(function (valid) {return valid;})];
if (el_validations[0]) {
this.S(el).removeAttr(this.invalid_attr);
el.setAttribute('aria-invalid', 'false');
el.removeAttribute('aria-describedby');
parent.removeClass(this.settings.error_class);
if (label.length > 0 && this.settings.error_labels) {
label.removeClass(this.settings.error_class).removeAttr('role');
}
$(el).triggerHandler('valid');
} else {
this.S(el).attr(this.invalid_attr, '');
el.setAttribute('aria-invalid', 'true');

// Try to find the error associated with the input
var errorElem = parent.find('small.' + this.settings.error_class, 'span.' + this.settings.error_class);
var errorID = errorElem.length > 0 ? errorElem[0].id : '';
if (errorID.length > 0) {
el.setAttribute('aria-describedby', errorID);
}

// el.setAttribute('aria-describedby', $(el).find('.error')[0].id);
parent.addClass(this.settings.error_class);
if (label.length > 0 && this.settings.error_labels) {
label.addClass(this.settings.error_class).attr('role', 'alert');
}
$(el).triggerHandler('invalid');
}
}
validations = validations.concat(el_validations);
}

return validations;
},

valid_checkbox : function (el, required) {
var el = this.S(el),
valid = (el.is(':checked') || !required || el.get(0).getAttribute('disabled'));

if (valid) {
el.removeAttr(this.invalid_attr).parent().removeClass(this.settings.error_class);
$(el).triggerHandler('valid');
} else {
el.attr(this.invalid_attr, '').parent().addClass(this.settings.error_class);
$(el).triggerHandler('invalid');
}

return valid;
},

valid_radio : function (el, required) {
var name = el.getAttribute('name'),
group = this.S(el).closest('[data-' + this.attr_name(true) + ']').find("[name='" + name + "']"),
count = group.length,
valid = false,
disabled = false;

// Has to count up to make sure the focus gets applied to the top error
for (var i=0; i < count; i++) {
if( group[i].getAttribute('disabled') ){
disabled=true;
valid=true;
} else {
if (group[i].checked){
valid = true;
} else {
if( disabled ){
valid = false;
}
}
}
}

// Has to count up to make sure the focus gets applied to the top error
for (var i = 0; i < count; i++) {
if (valid) {
this.S(group[i]).removeAttr(this.invalid_attr).parent().removeClass(this.settings.error_class);
$(group[i]).triggerHandler('valid');
} else {
this.S(group[i]).attr(this.invalid_attr, '').parent().addClass(this.settings.error_class);
$(group[i]).triggerHandler('invalid');
}
}

return valid;
},

valid_equal : function (el, required, parent) {
var from = document.getElementById(el.getAttribute(this.add_namespace('data-equalto'))).value,
to = el.value,
valid = (from === to);

if (valid) {
this.S(el).removeAttr(this.invalid_attr);
parent.removeClass(this.settings.error_class);
if (label.length > 0 && settings.error_labels) {
label.removeClass(this.settings.error_class);
}
} else {
this.S(el).attr(this.invalid_attr, '');
parent.addClass(this.settings.error_class);
if (label.length > 0 && settings.error_labels) {
label.addClass(this.settings.error_class);
}
}

return valid;
},

valid_oneof : function (el, required, parent, doNotValidateOthers) {
var el = this.S(el),
others = this.S('[' + this.add_namespace('data-oneof') + ']'),
valid = others.filter(':checked').length > 0;

if (valid) {
el.removeAttr(this.invalid_attr).parent().removeClass(this.settings.error_class);
} else {
el.attr(this.invalid_attr, '').parent().addClass(this.settings.error_class);
}

if (!doNotValidateOthers) {
var _this = this;
others.each(function () {
_this.valid_oneof.call(_this, this, null, null, true);
});
}

return valid;
},

reflow : function(scope, options) {
var self = this,
form = self.S('[' + this.attr_name() + ']').attr('novalidate', 'novalidate');
self.S(form).each(function (idx, el) {
self.events(el);
});
}
};
}(jQuery, window, window.document));

+ 125
- 0
src/www/css/frameworks/foundation5/js/foundation/foundation.accordion.js View File

@@ -0,0 +1,125 @@
;(function ($, window, document, undefined) {
'use strict';

Foundation.libs.accordion = {
name : 'accordion',

version : '5.5.3',

settings : {
content_class : 'content',
active_class : 'active',
multi_expand : false,
toggleable : true,
callback : function () {}
},

init : function (scope, method, options) {
this.bindings(method, options);
},

events : function (instance) {
var self = this;
var S = this.S;
self.create(this.S(instance));

S(this.scope)
.off('.fndtn.accordion')
.on('click.fndtn.accordion', '[' + this.attr_name() + '] > dd > a, [' + this.attr_name() + '] > li > a', function (e) {
var accordion = S(this).closest('[' + self.attr_name() + ']'),
groupSelector = self.attr_name() + '=' + accordion.attr(self.attr_name()),
settings = accordion.data(self.attr_name(true) + '-init') || self.settings,
target = S('#' + this.href.split('#')[1]),
aunts = $('> dd, > li', accordion),
siblings = aunts.children('.' + settings.content_class),
active_content = siblings.filter('.' + settings.active_class);

e.preventDefault();

if (accordion.attr(self.attr_name())) {
siblings = siblings.add('[' + groupSelector + '] dd > ' + '.' + settings.content_class + ', [' + groupSelector + '] li > ' + '.' + settings.content_class);
aunts = aunts.add('[' + groupSelector + '] dd, [' + groupSelector + '] li');
}

if (settings.toggleable && target.is(active_content)) {
target.parent('dd, li').toggleClass(settings.active_class, false);
target.toggleClass(settings.active_class, false);
S(this).attr('aria-expanded', function(i, attr){
return attr === 'true' ? 'false' : 'true';
});
settings.callback(target);
target.triggerHandler('toggled', [accordion]);
accordion.triggerHandler('toggled', [target]);
return;
}

if (!settings.multi_expand) {
siblings.removeClass(settings.active_class);
aunts.removeClass(settings.active_class);
aunts.children('a').attr('aria-expanded','false');
}

target.addClass(settings.active_class).parent().addClass(settings.active_class);
settings.callback(target);
target.triggerHandler('toggled', [accordion]);
accordion.triggerHandler('toggled', [target]);
S(this).attr('aria-expanded','true');
});
},

create: function($instance) {
var self = this,
accordion = $instance,
aunts = $('> .accordion-navigation', accordion),
settings = accordion.data(self.attr_name(true) + '-init') || self.settings;

aunts.children('a').attr('aria-expanded','false');
aunts.has('.' + settings.content_class + '.' + settings.active_class).addClass(settings.active_class).children('a').attr('aria-expanded','true');

if (settings.multi_expand) {
$instance.attr('aria-multiselectable','true');
}
},
toggle : function(options) {
var options = typeof options !== 'undefined' ? options : {};
var selector = typeof options.selector !== 'undefined' ? options.selector : '';
var toggle_state = typeof options.toggle_state !== 'undefined' ? options.toggle_state : '';
var $accordion = typeof options.$accordion !== 'undefined' ? options.$accordion : this.S(this.scope).closest('[' + this.attr_name() + ']');
var $items = $accordion.find('> dd' + selector + ', > li' + selector);
if ( $items.length < 1 ) {
if ( window.console ) {
console.error('Selection not found.', selector);
}
return false;
}
var S = this.S;
var active_class = this.settings.active_class;
$items.each(function() {
var $item = S(this);
var is_active = $item.hasClass(active_class);
if ( ( is_active && toggle_state === 'close' ) || ( !is_active && toggle_state === 'open' ) || toggle_state === '' ) {
$item.find('> a').trigger('click.fndtn.accordion');
}
});
},
open : function(options) {
var options = typeof options !== 'undefined' ? options : {};
options.toggle_state = 'open';
this.toggle(options);
},
close : function(options) {
var options = typeof options !== 'undefined' ? options : {};
options.toggle_state = 'close';
this.toggle(options);
},

off : function () {},

reflow : function () {}
};
}(jQuery, window, window.document));

+ 43
- 0
src/www/css/frameworks/foundation5/js/foundation/foundation.alert.js View File

@@ -0,0 +1,43 @@
;(function ($, window, document, undefined) {
'use strict';

Foundation.libs.alert = {
name : 'alert',

version : '5.5.3',

settings : {
callback : function () {}
},

init : function (scope, method, options) {
this.bindings(method, options);
},

events : function () {
var self = this,
S = this.S;

$(this.scope).off('.alert').on('click.fndtn.alert', '[' + this.attr_name() + '] .close', function (e) {
var alertBox = S(this).closest('[' + self.attr_name() + ']'),
settings = alertBox.data(self.attr_name(true) + '-init') || self.settings;

e.preventDefault();
if (Modernizr.csstransitions) {
alertBox.addClass('alert-close');
alertBox.on('transitionend webkitTransitionEnd oTransitionEnd', function (e) {
S(this).trigger('close.fndtn.alert').remove();
settings.callback();
});
} else {
alertBox.fadeOut(300, function () {
S(this).trigger('close.fndtn.alert').remove();
settings.callback();
});
}
});
},

reflow : function () {}
};
}(jQuery, window, window.document));

+ 586
- 0
src/www/css/frameworks/foundation5/js/foundation/foundation.clearing.js View File

@@ -0,0 +1,586 @@
;(function ($, window, document, undefined) {
'use strict';

Foundation.libs.clearing = {
name : 'clearing',

version : '5.5.3',

settings : {
templates : {
viewing : '<a href="#" class="clearing-close">&times;</a>' +
'<div class="visible-img" style="display: none"><div class="clearing-touch-label"></div><img src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="" />' +
'<p class="clearing-caption"></p><a href="#" class="clearing-main-prev"><span></span></a>' +
'<a href="#" class="clearing-main-next"><span></span></a></div>' +
'<img class="clearing-preload-next" style="display: none" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="" />' +
'<img class="clearing-preload-prev" style="display: none" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" alt="" />'
},

// 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, div.clearing-blackout',

// Default to the entire li element.
open_selectors : '',

// Image will be skipped in carousel.
skip_selector : '',

touch_label : '',

// event initializer and locks
init : false,
locked : false
},

init : function (scope, method, options) {
var self = this;
Foundation.inherit(this, 'throttle image_loaded');

this.bindings(method, options);

if (self.S(this.scope).is('[' + this.attr_name() + ']')) {
this.assemble(self.S('li', this.scope));
} else {
self.S('[' + this.attr_name() + ']', this.scope).each(function () {
self.assemble(self.S('li', this));
});
}
},

events : function (scope) {
var self = this,
S = self.S,
$scroll_container = $('.scroll-container');

if ($scroll_container.length > 0) {
this.scope = $scroll_container;
}

S(this.scope)
.off('.clearing')
.on('click.fndtn.clearing', 'ul[' + this.attr_name() + '] li ' + this.settings.open_selectors,
function (e, current, target) {
var current = current || S(this),
target = target || current,
next = current.next('li'),
settings = current.closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init'),
image = S(e.target);

e.preventDefault();

if (!settings) {
self.init();
settings = current.closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init');
}

// if clearing is open and the current image is
// clicked, go to the next image in sequence
if (target.hasClass('visible') &&
current[0] === target[0] &&
next.length > 0 && self.is_open(current)) {
target = next;
image = S('img', target);
}

// set current and target to the clicked li if not otherwise defined.
self.open(image, current, target);
self.update_paddles(target);
})

.on('click.fndtn.clearing', '.clearing-main-next',
function (e) { self.nav(e, 'next') })
.on('click.fndtn.clearing', '.clearing-main-prev',
function (e) { self.nav(e, 'prev') })
.on('click.fndtn.clearing', this.settings.close_selectors,
function (e) { Foundation.libs.clearing.close(e, this) });

$(document).on('keydown.fndtn.clearing',
function (e) { self.keydown(e) });

S(window).off('.clearing').on('resize.fndtn.clearing',
function () { self.resize() });

this.swipe_events(scope);
},

swipe_events : function (scope) {
var self = this,
S = self.S;

S(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
};

S(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 = S(this).data('swipe-transition');

if (typeof data === 'undefined') {
data = {};
}

data.delta_x = e.touches[0].pageX - data.start_page_x;

if (Foundation.rtl) {
data.delta_x = -data.delta_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) {
S(this).data('swipe-transition', {});
e.stopPropagation();
});
},

assemble : function ($li) {
var $el = $li.parent();

if ($el.parent().hasClass('carousel')) {
return;
}

$el.after('<div id="foundationClearingHolder"></div>');

var grid = $el.detach(),
grid_outerHTML = '';

if (grid[0] == null) {
return;
} else {
grid_outerHTML = grid[0].outerHTML;
}

var holder = this.S('#foundationClearingHolder'),
settings = $el.data(this.attr_name(true) + '-init'),
data = {
grid : '<div class="carousel">' + grid_outerHTML + '</div>',
viewing : settings.templates.viewing
},
wrapper = '<div class="clearing-assembled"><div>' + data.viewing +
data.grid + '</div></div>',
touch_label = this.settings.touch_label;

if (Modernizr.touch) {
wrapper = $(wrapper).find('.clearing-touch-label').html(touch_label).end();
}

holder.after(wrapper).remove();
},

open : function ($image, current, target) {
var self = this,
body = $(document.body),
root = target.closest('.clearing-assembled'),
container = self.S('div', root).first(),
visible_image = self.S('.visible-img', container),
image = self.S('img', visible_image).not($image),
label = self.S('.clearing-touch-label', container),
error = false,
loaded = {};

// Event to disable scrolling on touch devices when Clearing is activated
$('body').on('touchmove', function (e) {
e.preventDefault();
});

image.error(function () {
error = true;
});

function startLoad() {
setTimeout(function () {
this.image_loaded(image, function () {
if (image.outerWidth() === 1 && !error) {
startLoad.call(this);
} else {
cb.call(this, image);
}
}.bind(this));
}.bind(this), 100);
}

function cb (image) {
var $image = $(image);
$image.css('visibility', 'visible');
$image.trigger('imageVisible');
// toggle the gallery
body.css('overflow', 'hidden');
root.addClass('clearing-blackout');
container.addClass('clearing-container');
visible_image.show();
this.fix_height(target)
.caption(self.S('.clearing-caption', visible_image), self.S('img', target))
.center_and_label(image, label)
.shift(current, target, function () {
target.closest('li').siblings().removeClass('visible');
target.closest('li').addClass('visible');
});
visible_image.trigger('opened.fndtn.clearing')
}

if (!this.locked()) {
visible_image.trigger('open.fndtn.clearing');
// set the image to the selected thumbnail
loaded = this.load($image);
if (loaded.interchange) {
image
.attr('data-interchange', loaded.interchange)
.foundation('interchange', 'reflow');
} else {
image
.attr('src', loaded.src)
.attr('data-interchange', '');
}
image.css('visibility', 'hidden');

startLoad.call(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))),
body = $(document.body), container, visible_image;

if (el === e.target && root) {
body.css('overflow', '');
container = $('div', root).first();
visible_image = $('.visible-img', container);
visible_image.trigger('close.fndtn.clearing');
this.settings.prev_index = 0;
$('ul[' + this.attr_name() + ']', root)
.attr('style', '').closest('.clearing-blackout')
.removeClass('clearing-blackout');
container.removeClass('clearing-container');
visible_image.hide();
visible_image.trigger('closed.fndtn.clearing');
}

// Event to re-enable scrolling on touch devices
$('body').off('touchmove');

return false;
},

is_open : function (current) {
return current.parent().prop('style').length > 0;
},

keydown : function (e) {
var clearing = $('.clearing-blackout ul[' + this.attr_name() + ']'),
NEXT_KEY = this.rtl ? 37 : 39,
PREV_KEY = this.rtl ? 39 : 37,
ESC_KEY = 27;

if (e.which === NEXT_KEY) {
this.go(clearing, 'next');
}
if (e.which === PREV_KEY) {
this.go(clearing, 'prev');
}
if (e.which === ESC_KEY) {
this.S('a.clearing-close').trigger('click.fndtn.clearing');
}
},

nav : function (e, direction) {
var clearing = $('ul[' + this.attr_name() + ']', '.clearing-blackout');

e.preventDefault();
this.go(clearing, direction);
},

resize : function () {
var image = $('img', '.clearing-blackout .visible-img'),
label = $('.clearing-touch-label', '.clearing-blackout');

if (image.length) {
this.center_and_label(image, label);
image.trigger('resized.fndtn.clearing')
}
},

// visual adjustments
fix_height : function (target) {
var lis = target.parent().children(),
self = this;

lis.each(function () {
var li = self.S(this),
image = li.find('img');

if (li.height() > image.outerHeight()) {
li.addClass('fix-height');
}
})
.closest('ul')
.width(lis.length * 100 + '%');

return this;
},

update_paddles : function (target) {
target = target.closest('li');
var visible_image = target
.closest('.carousel')
.siblings('.visible-img');

if (target.next().length > 0) {
this.S('.clearing-main-next', visible_image).removeClass('disabled');
} else {
this.S('.clearing-main-next', visible_image).addClass('disabled');
}

if (target.prev().length > 0) {
this.S('.clearing-main-prev', visible_image).removeClass('disabled');
} else {
this.S('.clearing-main-prev', visible_image).addClass('disabled');
}
},

center_and_label : function (target, label) {
if (!this.rtl && label.length > 0) {
label.css({
marginLeft : -(label.outerWidth() / 2),
marginTop : -(target.outerHeight() / 2)-label.outerHeight()-10
});
} else {
label.css({
marginRight : -(label.outerWidth() / 2),
marginTop : -(target.outerHeight() / 2)-label.outerHeight()-10,
left: 'auto',
right: '50%'
});
}
return this;
},

// image loading and preloading

load : function ($image) {
var href,
interchange,
closest_a;

if ($image[0].nodeName === 'A') {
href = $image.attr('href');
interchange = $image.data('clearing-interchange');
} else {
closest_a = $image.closest('a');
href = closest_a.attr('href');
interchange = closest_a.data('clearing-interchange');
}

this.preload($image);

return {
'src': href ? href : $image.attr('src'),
'interchange': href ? interchange : $image.data('clearing-interchange')
}
},

preload : function ($image) {
this
.img($image.closest('li').next(), 'next')
.img($image.closest('li').prev(), 'prev');
},

img : function (img, sibling_type) {
if (img.length) {
var preload_img = $('.clearing-preload-' + sibling_type),
new_a = this.S('a', img),
src,
interchange,
image;

if (new_a.length) {
src = new_a.attr('href');
interchange = new_a.data('clearing-interchange');
} else {
image = this.S('img', img);
src = image.attr('src');
interchange = image.data('clearing-interchange');
}

if (interchange) {
preload_img.attr('data-interchange', interchange);
} else {
preload_img.attr('src', src);
preload_img.attr('data-interchange', '');
}
}
return this;
},

// image caption

caption : function (container, $image) {
var caption = $image.attr('data-caption');

if (caption) {
var containerPlain = container.get(0);
containerPlain.innerHTML = caption;
container.show();
} else {
container
.text('')
.hide();
}
return this;
},

// directional methods

go : function ($ul, direction) {
var current = this.S('.visible', $ul),
target = current[direction]();

// Check for skip selector.
if (this.settings.skip_selector && target.find(this.settings.skip_selector).length != 0) {
target = target[direction]();
}

if (target.length) {
this.S('img', target)
.trigger('click.fndtn.clearing', [current, target])
.trigger('change.fndtn.clearing');
}
},

shift : function (current, target, callback) {
var clearing = target.parent(),
old_index = this.settings.prev_index || target.index(),
direction = this.direction(clearing, current, target),
dir = this.rtl ? 'right' : 'left',
left = parseInt(clearing.css('left'), 10),
width = target.outerWidth(),
skip_shift;

var dir_obj = {};

// we use jQuery animate instead of CSS transitions because we
// need a callback to unlock the next animation
// needs support for RTL **
if (target.index() !== old_index && !/skip/.test(direction)) {
if (/left/.test(direction)) {
this.lock();
dir_obj[dir] = left + width;
clearing.animate(dir_obj, 300, this.unlock());
} else if (/right/.test(direction)) {
this.lock();
dir_obj[dir] = left - width;
clearing.animate(dir_obj, 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) {
dir_obj[dir] = -(skip_shift * width);
clearing.animate(dir_obj, 300, this.unlock());
} else {
dir_obj[dir] = 0;
clearing.animate(dir_obj, 300, this.unlock());
}
}

callback();
},

direction : function ($el, current, target) {
var lis = this.S('li', $el),
li_width = lis.outerWidth() + (lis.outerWidth() / 4),
up_count = Math.floor(this.S('.clearing-container').outerWidth() / li_width) - 1,