zurb-foundation 4.1.5 → 4.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.md +4 -0
  3. data/docs/CHANGELOG.md +10 -0
  4. data/docs/components/block-grid.html.erb +1 -1
  5. data/docs/components/grid.html.erb +4 -4
  6. data/docs/components/inline-lists.html.erb +2 -2
  7. data/docs/components/panels.html.erb +2 -2
  8. data/docs/components/pricing-tables.html.erb +1 -1
  9. data/docs/components/progress-bars.html.erb +1 -1
  10. data/docs/components/reveal.html.erb +1 -1
  11. data/docs/components/section.html.erb +546 -19
  12. data/docs/components/split-buttons.html.erb +2 -2
  13. data/docs/components/thumbnails.html.erb +2 -2
  14. data/docs/components/top-bar.html.erb +2 -3
  15. data/docs/components/type.html.erb +5 -5
  16. data/docs/components/visibility.html.erb +1 -1
  17. data/docs/css/docs.scss +54 -0
  18. data/docs/sass.html.erb +3 -1
  19. data/js/foundation/foundation.forms.js +311 -227
  20. data/js/foundation/foundation.joyride.js +10 -8
  21. data/js/foundation/foundation.js +1 -1
  22. data/js/foundation/foundation.section.js +4 -4
  23. data/lib/foundation/version.rb +1 -1
  24. data/scss/foundation/_variables.scss +185 -171
  25. data/scss/foundation/components/_alert-boxes.scss +1 -0
  26. data/scss/foundation/components/_block-grid.scss +2 -4
  27. data/scss/foundation/components/_breadcrumbs.scss +1 -0
  28. data/scss/foundation/components/_button-groups.scss +1 -0
  29. data/scss/foundation/components/_buttons.scss +1 -0
  30. data/scss/foundation/components/_clearing.scss +154 -151
  31. data/scss/foundation/components/_custom-forms.scss +35 -21
  32. data/scss/foundation/components/_dropdown-buttons.scss +2 -1
  33. data/scss/foundation/components/_dropdown.scss +2 -1
  34. data/scss/foundation/components/_flex-video.scss +1 -0
  35. data/scss/foundation/components/_forms.scss +1 -0
  36. data/scss/foundation/components/_global.scss +75 -84
  37. data/scss/foundation/components/_grid.scss +9 -8
  38. data/scss/foundation/components/_inline-lists.scss +2 -1
  39. data/scss/foundation/components/_joyride.scss +165 -160
  40. data/scss/foundation/components/_keystrokes.scss +2 -1
  41. data/scss/foundation/components/_labels.scss +1 -0
  42. data/scss/foundation/components/_magellan.scss +2 -0
  43. data/scss/foundation/components/_orbit.scss +158 -154
  44. data/scss/foundation/components/_pagination.scss +1 -0
  45. data/scss/foundation/components/_panels.scss +1 -0
  46. data/scss/foundation/components/_pricing-tables.scss +1 -0
  47. data/scss/foundation/components/_progress-bars.scss +1 -0
  48. data/scss/foundation/components/_reveal.scss +2 -1
  49. data/scss/foundation/components/_section.scss +108 -93
  50. data/scss/foundation/components/_side-nav.scss +2 -1
  51. data/scss/foundation/components/_split-buttons.scss +1 -0
  52. data/scss/foundation/components/_sub-nav.scss +1 -0
  53. data/scss/foundation/components/_switch.scss +4 -2
  54. data/scss/foundation/components/_tables.scss +7 -3
  55. data/scss/foundation/components/_thumbs.scss +1 -0
  56. data/scss/foundation/components/_tooltips.scss +85 -81
  57. data/scss/foundation/components/_top-bar.scss +323 -318
  58. data/scss/foundation/components/_type.scss +290 -286
  59. data/scss/foundation/components/_visibility.scss +2 -0
  60. data/templates/project/index.html +0 -1
  61. data/templates/project/manifest.rb +0 -1
  62. data/templates/project/scss/app.scss +3 -0
  63. metadata +4 -4
@@ -143,7 +143,7 @@ $split-button-pip-left-lrg: emCalc(-9px);
143
143
  <hr>
144
144
 
145
145
  <h3>Using the JavaScript</h3>
146
- <p>You don't need ths JS to create dropdown button styles with Foundation. The only reason you'll need to include <code>foundation.dropdown.js</code> is if you want to add one of our dropdowns to the button. You'll also need to make sure to include <code>zepto.js</code> and <code>foundation.js</code> above the dropdown plugin.</p>
146
+ <p>You don't need this JS to create dropdown button styles with Foundation. The only reason you'll need to include <code>foundation.dropdown.js</code> is if you want to add one of our dropdowns to the button. You'll also need to make sure to include <code>zepto.js</code> and <code>foundation.js</code> above the dropdown plugin.</p>
147
147
  <p>Above your closing <code>&lt;/body&gt;</code> tag include the following line of code and make sure you have the JS file in your directory:</p>
148
148
 
149
149
  <p><a href="../javascript.html" title="How to install Foundation JavaScript">Read how to install Foundation JavaScript</a></p>
@@ -169,7 +169,7 @@ $split-button-pip-left-lrg: emCalc(-9px);
169
169
 
170
170
  <h5>Optional JavaScript Configuration</h5>
171
171
 
172
- <p>Dropdwon button options can only be passed in during initialization at this time.</p>
172
+ <p>Dropdown button options can only be passed in during initialization at this time.</p>
173
173
 
174
174
  <%= code_example "
175
175
  {
@@ -52,7 +52,7 @@
52
52
  /* Using the available options */
53
53
  .your-class-name { @include thumb($border-width, $box-shadow, $box-shadow-hover); }
54
54
 
55
- /* Control the width of the white area around the thumnails */
55
+ /* Control the width of the white area around the thumbnails */
56
56
  $border-width: $thumb-border-width
57
57
 
58
58
  /* Control the default box-shadow that looks like a 1px border */
@@ -86,4 +86,4 @@ $thumb-transition-speed: 200ms;', :css %>
86
86
  <div class="large-3 pull-9 columns">
87
87
  <%= render "_sidebar-components.html.erb" %>
88
88
  </div>
89
- </div>
89
+ </div>
@@ -1,5 +1,4 @@
1
1
  <% @side_nav = "nav" %>
2
-
3
2
  <div class="row">
4
3
  <div class="large-9 push-3 columns">
5
4
 
@@ -86,7 +85,7 @@
86
85
  <p>The top bar is built with a single <code>nav</code> element with a class of <code>top-bar</code>. It will take on full-browser width by default. To make the top bar stay fixed as you scroll, wrap it in <code>div class="fixed"</code>. If you want your navigation to be set to your grid width, wrap it in <code>div class="contain-to-grid"</code>. You may use <code>fixed</code> and <code>contain-to-grid</code> together.</p>
87
86
 
88
87
  <h5>Building the Nav</h5>
89
- <p>When building your bar it is good to be aware of how many links your're going to need in it so you can customize your responsive breakpoint accordingly. Build your navigation with <code>ul.left</code> and/or <code>ul.right</code> depending where you want links. To add items, simply include <code>li</code> elements with and anchor inside them for your top-level. To build a dropdown menu, you'll need to add <code>has-dropdown</code> to the <code>li</code> and include <code>ul.dropdown</code> after that anchor. Add a class of <code>active</code> to mark the current page.</p>
88
+ <p>When building your bar it is good to be aware of how many links you're going to need in it so you can customize your responsive breakpoint accordingly. Build your navigation with <code>ul.left</code> and/or <code>ul.right</code> depending where you want links. To add items, simply include <code>li</code> elements with and anchor inside them for your top-level. To build a dropdown menu, you'll need to add <code>has-dropdown</code> to the <code>li</code> and include <code>ul.dropdown</code> after that anchor. Add a class of <code>active</code> to mark the current page.</p>
90
89
 
91
90
  <h5>Other Elements</h5>
92
91
  <p>To make this navigation nice and flexible, we've included patterns for elements like buttons, inputs and dividers. To create dividers between your navigation, just add an empty <code>li.divider</code> and you'll get some separation. You can use a small Foundation button in the nav, just include <code>has-form</code> as a class for its parent li. You can include two different input types: search and text. To use these, add a class of search to the parent li.</p>
@@ -280,4 +279,4 @@ $topbar-breakpoint: emCalc(940px); // Change to 9999px for always mobile layout'
280
279
  <div class="large-3 pull-9 columns">
281
280
  <%= render "_sidebar-components.html.erb" %>
282
281
  </div>
283
- </div>
282
+ </div>
@@ -23,16 +23,16 @@
23
23
  <h2>h2. This is a large header.</h2>
24
24
  <h3>h3. This is a medium header.</h3>
25
25
  <h4>h4. This is a moderate header.</h4>
26
- <h5>h5. This is a small header. h1.</h5>
27
- <h6>h6. This is a tiny header. h1.</h6>
26
+ <h5>h5. This is a small header.</h5>
27
+ <h6>h6. This is a tiny header.</h6>
28
28
 
29
29
  <%= code_example '
30
30
  <h1>h1. This is a very large header.</h1>
31
31
  <h2>h2. This is a large header.</h2>
32
32
  <h3>h3. This is a medium header.</h3>
33
33
  <h4>h4. This is a moderate header.</h4>
34
- <h5>h5. This is a small header. h1.</h5>
35
- <h6>h6. This is a tiny header. h1.</h6>
34
+ <h5>h5. This is a small header.</h5>
35
+ <h6>h6. This is a tiny header.</h6>
36
36
  ', :html %>
37
37
 
38
38
  <hr>
@@ -181,7 +181,7 @@
181
181
  </ol>
182
182
  </div>
183
183
  <div class="large-4 columns">
184
- <h6>Defition Lists</h6>
184
+ <h6>Definition Lists</h6>
185
185
  <dl>
186
186
  <dt>Definition Title</dt>
187
187
  <dd>Definition Cras justo odio, dapibus ac facilisis in, egestas eget quam. Nullam id dolor id nibh ultricies vehicula ut id elit.</dd>
@@ -90,7 +90,7 @@
90
90
  .hide-for-touch /* Hidden for touch enabled devices */
91
91
  ', :css %>
92
92
 
93
- <p><strong>Note:</strong> We've also included specific table hide/show visilibity classes that follow the same structure, just prepended with table, thead, th, tbody, tr or td. The display property will go from 'none' to whatever its default display should be.</p>
93
+ <p><strong>Note:</strong> We've also included specific table hide/show visibility classes that follow the same structure, just prepended with table, thead, th, tbody, tr or td. The display property will go from 'none' to whatever its default display should be.</p>
94
94
 
95
95
  <hr>
96
96
 
@@ -175,6 +175,60 @@ input[type="text"].attached-input {
175
175
  }
176
176
  }
177
177
 
178
+ /* Section Docs */
179
+ .section-auto-sample {
180
+ @include section-container($section-type:accordion);
181
+ & > section { @include section($section-type:accordion, $title-selector:".title-sample", $content-selector:".content-sample"); }
182
+
183
+ @media #{$small} {
184
+ @include section-container(false,$section-type:tabs);
185
+ & > section { @include section($section-type:tabs, $title-selector:".title-sample", $content-selector:".content-sample"); }
186
+ }
187
+ }
188
+
189
+ .section-auto-sample-accordion {
190
+ @include section-container($section-type:accordion);
191
+ & > section { @include section($section-type:accordion, $title-selector:".title-sample", $content-selector:".content-sample"); }
192
+ }
193
+
194
+ .section-auto-sample-tabs {
195
+ @include section-container($section-type:tabs);
196
+ & > section { @include section($section-type:tabs, $title-selector:".title-sample", $content-selector:".content-sample"); }
197
+ }
198
+
199
+ .section-auto-sample-vtabs,
200
+ .section-auto-sample-vnav,
201
+ .section-auto-sample-hnav {
202
+ @include section-container($section-type:accordion);
203
+ & > section { @include section($section-type:accordion, $title-selector:".title-sample", $content-selector:".content-sample"); }
204
+ }
205
+
206
+ @media #{$small} {
207
+ .section-auto-sample-vtabs {
208
+ @include section-container($section-type:vertical-tabs);
209
+ & > section { @include section($section-type:vertical-tabs, $title-selector:".title-sample", $content-selector:".content-sample"); }
210
+ }
211
+
212
+ .nav-container { @include grid-row($behavior:nest);
213
+ > nav { @include grid-column($columns:4); }
214
+ }
215
+
216
+ .section-auto-sample-vnav {
217
+ @include section-container($section-type:vertical-nav);
218
+ & > section { @include section($section-type:vertical-nav, $title-selector:".title-sample", $content-selector:".content-sample"); }
219
+ }
220
+
221
+ .section-auto-sample-hnav {
222
+ @include section-container($section-type:horizontal-nav);
223
+ & > section { @include section($section-type:horizontal-nav, $title-selector:".title-sample", $content-selector:".content-sample"); }
224
+ }
225
+
226
+ }
227
+ .section-auto-sample-custom {
228
+ @include section-container($section-type:tabs);
229
+ & > section { @include section($section-type:tabs, $title-selector:".title-sample", $content-selector:".content-sample", $title-padding: 10px 50px, $title-color:#000, $title-bg:pink, $title-bg-hover:darken(pink,5%), $title-bg-active: #fff, $title-color-active: darken(pink,10%)); }
230
+ }
231
+
178
232
  @media only screen and (min-width: 800px) {
179
233
  .docs.header { float: $default-float; }
180
234
 
@@ -32,9 +32,10 @@
32
32
 
33
33
  <a name="create-compass"></a>
34
34
  <h2>Creating your first project</h2>
35
- <h5 class="subheader">Compass makes it really easy to start a new project. Since you've installed the Foundation gem by now, you now have Compass, Sass and a few other necessary dependencies available at your fingertips.</h5>
35
+ <h5 class="subheader">Compass makes it really easy to start a new project. Since you've installed the Foundation gem by now, you just need to install Compass to get going.</h5>
36
36
  <p>Follow these two steps to get going:</p>
37
37
  <ol style="margin-left: 20px;">
38
+ <li><span class="keystroke">[sudo] gem install compass</span></li>
38
39
  <li><span class="keystroke">cd path/to/where-you-want-your-project</span></li>
39
40
  <li>run <span class="keystroke">compass create &lt;project-name&gt; -r zurb-foundation --using foundation</span></li>
40
41
  </ol>
@@ -267,6 +268,7 @@ $em-base: 16px !default;
267
268
  // $include-html-visibility-classes: $include-html-classes;
268
269
  // $include-html-button-classes: $include-html-classes;
269
270
  // $include-html-form-classes: $include-html-classes;
271
+ // $include-html-custom-form-classes: $include-html-classes;
270
272
  // $include-html-media-classes: $include-html-classes;
271
273
  // $include-html-section-classes: $include-html-classes;
272
274
  // $include-html-reveal-classes: $include-html-classes;
@@ -1,19 +1,19 @@
1
- /*jslint unparam: true, browser: true, indent: 2 */
2
-
3
- ;(function ($, window, document, undefined) {
1
+ (function ($, window, document, undefined) {
4
2
  'use strict';
5
3
 
6
4
  Foundation.libs.forms = {
7
- name : 'forms',
5
+ name: 'forms',
6
+
7
+ version: '4.1.6',
8
8
 
9
- version : '4.0.4',
9
+ cache: {},
10
10
 
11
- settings : {
12
- disable_class: 'no-custom'
11
+ settings: {
12
+ disable_class: 'no-custom',
13
+ last_combo : null
13
14
  },
14
15
 
15
- init : function (scope, method, options) {
16
- this.scope = scope || this.scope;
16
+ init: function (scope, method, options) {
17
17
 
18
18
  if (typeof method === 'object') {
19
19
  $.extend(true, this.settings, method);
@@ -32,18 +32,18 @@
32
32
  }
33
33
  },
34
34
 
35
- assemble : function () {
35
+ assemble: function () {
36
36
  $('form.custom input[type="radio"]', $(this.scope)).not('[data-customforms="disabled"]')
37
37
  .each(this.append_custom_markup);
38
38
  $('form.custom input[type="checkbox"]', $(this.scope)).not('[data-customforms="disabled"]')
39
39
  .each(this.append_custom_markup);
40
40
  $('form.custom select', $(this.scope))
41
- .not('[data-customforms="disabled"]')
42
- .not('[multiple=multiple]')
41
+ .not('[data-customforms="disabled"]')
42
+ .not('[multiple=multiple]')
43
43
  .each(this.append_custom_select);
44
44
  },
45
45
 
46
- events : function () {
46
+ events: function () {
47
47
  var self = this;
48
48
 
49
49
  $(this.scope)
@@ -57,41 +57,43 @@
57
57
  e.stopPropagation();
58
58
  self.toggle_radio($(this));
59
59
  })
60
- .on('change.fndtn.forms', 'form.custom select:not([data-customforms="disabled"])', function (e) {
61
- self.refresh_custom_select($(this));
60
+ .on('change.fndtn.forms', 'form.custom select:not([data-customforms="disabled"])', function (e, force_refresh) {
61
+ self.refresh_custom_select($(this), force_refresh);
62
62
  })
63
63
  .on('click.fndtn.forms', 'form.custom label', function (e) {
64
- var $associatedElement = $('#' + self.escape($(this).attr('for')) + ':not([data-customforms="disabled"])'),
64
+ if ($(e.target).is('label')) {
65
+ var $associatedElement = $('#' + self.escape($(this).attr('for')) + ':not([data-customforms="disabled"])'),
65
66
  $customCheckbox,
66
67
  $customRadio;
67
- if ($associatedElement.length !== 0) {
68
- if ($associatedElement.attr('type') === 'checkbox') {
69
- e.preventDefault();
70
- $customCheckbox = $(this).find('span.custom.checkbox');
71
- //the checkbox might be outside after the label or inside of another element
72
- if ($customCheckbox.length == 0) {
73
- $customCheckbox = $associatedElement.add(this).siblings('span.custom.checkbox').first();
74
- }
75
- self.toggle_checkbox($customCheckbox);
76
- } else if ($associatedElement.attr('type') === 'radio') {
77
- e.preventDefault();
78
- $customRadio = $(this).find('span.custom.radio');
79
- //the radio might be outside after the label or inside of another element
80
- if ($customRadio.length == 0) {
81
- $customRadio = $associatedElement.add(this).siblings('span.custom.radio').first();
68
+
69
+ if ($associatedElement.length !== 0) {
70
+ if ($associatedElement.attr('type') === 'checkbox') {
71
+ e.preventDefault();
72
+ $customCheckbox = $(this).find('span.custom.checkbox');
73
+ //the checkbox might be outside after the label or inside of another element
74
+ if ($customCheckbox.length == 0) {
75
+ $customCheckbox = $associatedElement.add(this).siblings('span.custom.checkbox').first();
76
+ }
77
+ self.toggle_checkbox($customCheckbox);
78
+ } else if ($associatedElement.attr('type') === 'radio') {
79
+ e.preventDefault();
80
+ $customRadio = $(this).find('span.custom.radio');
81
+ //the radio might be outside after the label or inside of another element
82
+ if ($customRadio.length == 0) {
83
+ $customRadio = $associatedElement.add(this).siblings('span.custom.radio').first();
84
+ }
85
+ self.toggle_radio($customRadio);
82
86
  }
83
- self.toggle_radio($customRadio);
84
87
  }
85
88
  }
86
89
  })
87
90
  .on('click.fndtn.forms', 'form.custom div.custom.dropdown a.current, form.custom div.custom.dropdown a.selector', function (e) {
88
91
  var $this = $(this),
89
92
  $dropdown = $this.closest('div.custom.dropdown'),
90
- $select = $dropdown.prev();
93
+ $select = getFirstPrevSibling($dropdown, 'select');
91
94
 
92
95
  // make sure other dropdowns close
93
- if(!$dropdown.hasClass('open'))
94
- $(self.scope).trigger('click');
96
+ if (!$dropdown.hasClass('open')) $(self.scope).trigger('click');
95
97
 
96
98
  e.preventDefault();
97
99
  if (false === $select.is(':disabled')) {
@@ -111,32 +113,29 @@
111
113
  .on('click.fndtn.forms touchend.fndtn.forms', 'form.custom div.custom.dropdown li', function (e) {
112
114
  var $this = $(this),
113
115
  $customDropdown = $this.closest('div.custom.dropdown'),
114
- $select = $customDropdown.prev(),
116
+ $select = getFirstPrevSibling($customDropdown, 'select'),
115
117
  selectedIndex = 0;
116
118
 
117
119
  e.preventDefault();
118
120
  e.stopPropagation();
119
121
 
120
- if ( ! $(this).hasClass('disabled')) {
122
+ if (!$(this).hasClass('disabled')) {
121
123
  $('div.dropdown').not($customDropdown).removeClass('open');
122
124
 
123
- var $oldThis= $this
124
- .closest('ul')
125
+ var $oldThis = $this.closest('ul')
125
126
  .find('li.selected');
126
127
  $oldThis.removeClass('selected');
127
128
 
128
129
  $this.addClass('selected');
129
130
 
130
- $customDropdown
131
- .removeClass('open')
131
+ $customDropdown.removeClass('open')
132
132
  .find('a.current')
133
- .html($this.html());
133
+ .text($this.text());
134
134
 
135
135
  $this.closest('ul').find('li').each(function (index) {
136
136
  if ($this[0] == this) {
137
137
  selectedIndex = index;
138
138
  }
139
-
140
139
  });
141
140
  $select[0].selectedIndex = selectedIndex;
142
141
 
@@ -144,10 +143,11 @@
144
143
  $select.data('prevalue', $oldThis.html());
145
144
  $select.trigger('change');
146
145
  }
147
- });
146
+ });
148
147
 
149
148
  $(window).on('keydown', function (e) {
150
149
  var focus = document.activeElement,
150
+ self = Foundation.libs.forms,
151
151
  dropdown = $('.custom.dropdown.open');
152
152
 
153
153
  if (dropdown.length > 0) {
@@ -156,12 +156,27 @@
156
156
  if (e.which === 13) {
157
157
  dropdown.find('li.selected').trigger('click');
158
158
  }
159
+
160
+ if (e.which === 27) {
161
+ dropdown.removeClass('open');
162
+ }
163
+
164
+ if (e.which >= 65 && e.which <= 90) {
165
+ var next = self.go_to(dropdown, e.which),
166
+ current = dropdown.find('li.selected');
167
+
168
+ if (next) {
169
+ current.removeClass('selected');
170
+ self.scrollTo(next.addClass('selected'), 300);
171
+ }
172
+ }
159
173
 
160
174
  if (e.which === 38) {
161
175
  var current = dropdown.find('li.selected'),
162
176
  prev = current.prev(':not(.disabled)');
163
177
 
164
178
  if (prev.length > 0) {
179
+ prev.parent()[0].scrollTop = prev.parent().scrollTop() - self.outerHeight(prev);
165
180
  current.removeClass('selected');
166
181
  prev.addClass('selected');
167
182
  }
@@ -170,6 +185,7 @@
170
185
  next = current.next(':not(.disabled)');
171
186
 
172
187
  if (next.length > 0) {
188
+ next.parent()[0].scrollTop = next.parent().scrollTop() + self.outerHeight(next);
173
189
  current.removeClass('selected');
174
190
  next.addClass('selected');
175
191
  }
@@ -180,11 +196,42 @@
180
196
  this.settings.init = true;
181
197
  },
182
198
 
183
- append_custom_markup : function (idx, sel) {
184
- var $this = $(sel).addClass('hidden-field'),
185
- type = $this.attr('type'),
199
+ go_to: function (dropdown, char) {
200
+ var lis = dropdown.find('li'),
201
+ count = lis.length;
202
+
203
+ if (count > 0) {
204
+ for (var i = 0; i < count; i++) {
205
+ var first_letter = lis.eq(i).text().charAt(0).toLowerCase();
206
+ if (first_letter === String.fromCharCode(char).toLowerCase()) return lis.eq(i);
207
+ }
208
+ }
209
+ },
210
+
211
+ scrollTo: function (el, duration) {
212
+ if (duration < 0) return;
213
+ var parent = el.parent();
214
+ var li_height = this.outerHeight(el);
215
+ var difference = (li_height * (el.index())) - parent.scrollTop();
216
+ var perTick = difference / duration * 10;
217
+
218
+ this.scrollToTimerCache = setTimeout(function () {
219
+ if (!isNaN(parseInt(perTick, 10))) {
220
+ parent[0].scrollTop = parent.scrollTop() + perTick;
221
+ this.scrollTo(el, duration - 10);
222
+ }
223
+ }.bind(this), 10);
224
+ },
225
+
226
+ append_custom_markup: function (idx, sel) {
227
+ var $this = $(sel),
228
+ type = $this.attr('type'),
186
229
  $span = $this.next('span.custom.' + type);
187
230
 
231
+ if (!$this.parent().hasClass('switch')) {
232
+ $this.addClass('hidden-field');
233
+ }
234
+
188
235
  if ($span.length === 0) {
189
236
  $span = $('<span class="custom ' + type + '"></span>').insertAfter($this);
190
237
  }
@@ -193,134 +240,158 @@
193
240
  $span.toggleClass('disabled', $this.is(':disabled'));
194
241
  },
195
242
 
196
- append_custom_select : function (idx, sel) {
197
- var self = Foundation.libs.forms,
198
- $this = $( sel ),
199
- $customSelect = $this.next( 'div.custom.dropdown' ),
200
- $customList = $customSelect.find( 'ul' ),
201
- $selectCurrent = $customSelect.find( ".current" ),
202
- $selector = $customSelect.find( ".selector" ),
203
- $options = $this.find( 'option' ),
204
- $selectedOption = $options.filter( ':selected' ),
205
- copyClasses = $this.attr('class') ? $this.attr('class').split(' ') : [],
206
- maxWidth = 0,
207
- liHtml = '',
208
- $listItems,
209
- $currentSelect = false;
210
-
211
- if ($this.hasClass(self.settings.disable_class)) return;
212
-
213
- if ($customSelect.length === 0) {
214
- var customSelectSize = $this.hasClass( 'small' ) ? 'small' :
215
- $this.hasClass( 'medium' ) ? 'medium' :
216
- $this.hasClass( 'large' ) ? 'large' :
217
- $this.hasClass( 'expand' ) ? 'expand' : '';
218
-
219
- $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>');
220
- $selector = $customSelect.find(".selector");
221
- $customList = $customSelect.find("ul");
222
- liHtml = $options.map(function() { return "<li>" + $( this ).html() + "</li>"; } ).get().join( '' );
223
- $customList.append(liHtml);
224
- $currentSelect = $customSelect.prepend('<a href="#" class="current">' + $selectedOption.html() + '</a>' ).find( ".current" );
225
- $this
226
- .after( $customSelect )
227
- .addClass('hidden-field');
228
-
229
- } else {
230
- liHtml = $options.map(function() {
231
- return "<li>" + $( this ).html() + "</li>";
232
- })
233
- .get().join('');
234
- $customList
235
- .html('')
236
- .append(liHtml);
237
-
238
- } // endif $customSelect.length === 0
239
- $customSelect.toggleClass('disabled', $this.is( ':disabled' ) );
240
- $listItems = $customList.find( 'li' );
241
-
242
- $options.each( function ( index ) {
243
- if ( this.selected ) {
244
- $listItems.eq( index ).addClass( 'selected' );
245
-
246
- if ($currentSelect) {
247
- $currentSelect.html( $( this ).html() );
243
+ append_custom_select: function (idx, sel) {
244
+ var self = Foundation.libs.forms,
245
+ $this = $(sel),
246
+ $customSelect = $this.next('div.custom.dropdown'),
247
+ $customList = $customSelect.find('ul'),
248
+ $selectCurrent = $customSelect.find(".current"),
249
+ $selector = $customSelect.find(".selector"),
250
+ $options = $this.find('option'),
251
+ $selectedOption = $options.filter(':selected'),
252
+ copyClasses = $this.attr('class') ? $this.attr('class').split(' ') : [],
253
+ maxWidth = 0,
254
+ liHtml = '',
255
+ $listItems,
256
+ $currentSelect = false;
257
+
258
+ if ($this.hasClass(self.settings.disable_class)) return;
259
+
260
+ if ($customSelect.length === 0) {
261
+ var customSelectSize = $this.hasClass('small') ? 'small' : $this.hasClass('medium') ? 'medium' : $this.hasClass('large') ? 'large' : $this.hasClass('expand') ? 'expand' : '';
262
+
263
+ $customSelect = $('<div class="' + ['custom', 'dropdown', customSelectSize].concat(copyClasses).filter(function (item, idx, arr) {
264
+ if (item == '') return false;
265
+ return arr.indexOf(item) == idx;
266
+ }).join(' ') + '"><a href="#" class="selector"></a><ul /></div>');
267
+
268
+ $selector = $customSelect.find(".selector");
269
+ $customList = $customSelect.find("ul");
270
+
271
+ liHtml = $options.map(function () {
272
+ return "<li>" + $(this).html() + "</li>";
273
+ }).get().join('');
274
+
275
+ $customList.append(liHtml);
276
+
277
+ $currentSelect = $customSelect
278
+ .prepend('<a href="#" class="current">' + $selectedOption.html() + '</a>')
279
+ .find(".current");
280
+
281
+ $this.after($customSelect)
282
+ .addClass('hidden-field');
283
+ } else {
284
+ liHtml = $options.map(function () {
285
+ return "<li>" + $(this).html() + "</li>";
286
+ })
287
+ .get().join('');
288
+
289
+ $customList.html('')
290
+ .append(liHtml);
291
+
292
+ } // endif $customSelect.length === 0
293
+
294
+ self.assign_id($this, $customSelect);
295
+ $customSelect.toggleClass('disabled', $this.is(':disabled'));
296
+ $listItems = $customList.find('li');
297
+
298
+ // cache list length
299
+ self.cache[$customSelect.data('id')] = $listItems.length;
300
+
301
+ $options.each(function (index) {
302
+ if (this.selected) {
303
+ $listItems.eq(index).addClass('selected');
304
+
305
+ if ($currentSelect) {
306
+ $currentSelect.html($(this).html());
307
+ }
308
+ }
309
+ if ($(this).is(':disabled')) {
310
+ $listItems.eq(index).addClass('disabled');
248
311
  }
312
+ });
249
313
 
250
- }
251
- if ($(this).is(':disabled')) {
252
- $listItems.eq( index ).addClass( 'disabled' );
253
- }
254
- });
314
+ //
315
+ // If we're not specifying a predetermined form size.
316
+ //
317
+ if (!$customSelect.is('.small, .medium, .large, .expand')) {
255
318
 
256
- //
257
- // If we're not specifying a predetermined form size.
258
- //
259
- if (!$customSelect.is('.small, .medium, .large, .expand')) {
319
+ // ------------------------------------------------------------------------------------
320
+ // This is a work-around for when elements are contained within hidden parents.
321
+ // For example, when custom-form elements are inside of a hidden reveal modal.
322
+ //
323
+ // We need to display the current custom list element as well as hidden parent elements
324
+ // in order to properly calculate the list item element's width property.
325
+ // -------------------------------------------------------------------------------------
260
326
 
261
- // ------------------------------------------------------------------------------------
262
- // This is a work-around for when elements are contained within hidden parents.
263
- // For example, when custom-form elements are inside of a hidden reveal modal.
264
- //
265
- // We need to display the current custom list element as well as hidden parent elements
266
- // in order to properly calculate the list item element's width property.
267
- // -------------------------------------------------------------------------------------
327
+ $customSelect.addClass('open');
328
+ //
329
+ // Quickly, display all parent elements.
330
+ // This should help us calcualate the width of the list item's within the drop down.
331
+ //
332
+ var self = Foundation.libs.forms;
333
+ self.hidden_fix.adjust($customList);
268
334
 
269
- $customSelect.addClass( 'open' );
270
- //
271
- // Quickly, display all parent elements.
272
- // This should help us calcualate the width of the list item's within the drop down.
273
- //
274
- var self = Foundation.libs.forms;
275
- self.hidden_fix.adjust( $customList );
335
+ maxWidth = (self.outerWidth($listItems) > maxWidth) ? self.outerWidth($listItems) : maxWidth;
276
336
 
277
- maxWidth = ( self.outerWidth($listItems) > maxWidth ) ? self.outerWidth($listItems) : maxWidth;
337
+ Foundation.libs.forms.hidden_fix.reset();
278
338
 
279
- Foundation.libs.forms.hidden_fix.reset();
339
+ $customSelect.removeClass('open');
280
340
 
281
- $customSelect.removeClass( 'open' );
341
+ } // endif
282
342
 
283
- } // endif
343
+ },
284
344
 
345
+ assign_id: function ($select, $customSelect) {
346
+ var id = [+new Date(), Foundation.random_str(5)].join('-');
347
+ $select.attr('data-id', id);
348
+ $customSelect.attr('data-id', id);
285
349
  },
286
350
 
287
- refresh_custom_select : function ($select) {
351
+ refresh_custom_select: function ($select, force_refresh) {
288
352
  var self = this;
289
353
  var maxWidth = 0,
290
- $customSelect = $select.next(),
291
- $options = $select.find('option');
354
+ $customSelect = $select.next(),
355
+ $options = $select.find('option'),
356
+ $listItems = $customSelect.find('li');
292
357
 
293
- $customSelect.find('ul').html('');
358
+ if ($listItems.length != this.cache[$customSelect.data('id')] || force_refresh) {
359
+ $customSelect.find('ul').html('');
294
360
 
295
- $options.each(function () {
296
- var $li = $('<li>' + $(this).html() + '</li>');
297
- $customSelect.find('ul').append($li);
298
- });
361
+ $options.each(function () {
362
+ var $li = $('<li>' + $(this).html() + '</li>');
363
+ $customSelect.find('ul').append($li);
364
+ });
299
365
 
300
- // re-populate
301
- $options.each(function (index) {
302
- if (this.selected) {
303
- $customSelect.find('li').eq(index).addClass('selected');
304
- $customSelect.find('.current').html($(this).html());
305
- }
306
- if ($(this).is(':disabled')) {
307
- $customSelect.find('li').eq(index).addClass('disabled');
308
- }
309
- });
366
+ // re-populate
367
+ $options.each(function (index) {
368
+ if (this.selected) {
369
+ $customSelect.find('li').eq(index).addClass('selected');
370
+ $customSelect.find('.current').html($(this).html());
371
+ }
372
+ if ($(this).is(':disabled')) {
373
+ $customSelect.find('li').eq(index).addClass('disabled');
374
+ }
375
+ });
310
376
 
311
- // fix width
312
- $customSelect.removeAttr('style')
313
- .find('ul').removeAttr('style');
314
- $customSelect.find('li').each(function () {
315
- $customSelect.addClass('open');
316
- if (self.outerWidth($(this)) > maxWidth) {
317
- maxWidth = self.outerWidth($(this));
318
- }
319
- $customSelect.removeClass('open');
320
- });
377
+ // fix width
378
+ $customSelect.removeAttr('style')
379
+ .find('ul').removeAttr('style');
380
+ $customSelect.find('li').each(function () {
381
+ $customSelect.addClass('open');
382
+ if (self.outerWidth($(this)) > maxWidth) {
383
+ maxWidth = self.outerWidth($(this));
384
+ }
385
+ $customSelect.removeClass('open');
386
+ });
387
+
388
+ $listItems = $customSelect.find('li');
389
+ // cache list length
390
+ this.cache[$customSelect.data('id')] = $listItems.length;
391
+ }
321
392
  },
322
393
 
323
- toggle_checkbox : function ($element) {
394
+ toggle_checkbox: function ($element) {
324
395
  var $input = $element.prev(),
325
396
  input = $input[0];
326
397
 
@@ -332,98 +403,111 @@
332
403
  }
333
404
  },
334
405
 
335
- toggle_radio : function ($element) {
336
- var $input = $element.prev(),
337
- $form = $input.closest('form.custom'),
338
- input = $input[0];
406
+ toggle_radio: function ($element) {
407
+ var $input = $element.prev(),
408
+ $form = $input.closest('form.custom'),
409
+ input = $input[0];
339
410
 
340
- if (false === $input.is(':disabled')) {
341
- $form.find('input[type="radio"][name="' + this.escape($input.attr('name')) + '"]').next().not($element).removeClass('checked');
342
- if ( !$element.hasClass('checked') ) {
343
- $element.toggleClass('checked');
344
- }
345
- input.checked = $element.hasClass('checked');
411
+ if (false === $input.is(':disabled')) {
412
+ $form.find('input[type="radio"][name="' + this.escape($input.attr('name')) + '"]')
413
+ .next().not($element).removeClass('checked');
346
414
 
347
- $input.trigger('change');
348
- }
415
+ if (!$element.hasClass('checked')) {
416
+ $element.toggleClass('checked');
417
+ }
418
+
419
+ input.checked = $element.hasClass('checked');
420
+
421
+ $input.trigger('change');
422
+ }
349
423
  },
350
424
 
351
- escape : function (text) {
425
+ escape: function (text) {
352
426
  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
353
427
  },
354
428
 
355
- hidden_fix : {
356
- /**
357
- * Sets all hidden parent elements and self to visibile.
358
- *
359
- * @method adjust
360
- * @param {jQuery Object} $child
361
- */
429
+ hidden_fix: {
430
+ /**
431
+ * Sets all hidden parent elements and self to visibile.
432
+ *
433
+ * @method adjust
434
+ * @param {jQuery Object} $child
435
+ */
362
436
 
363
- // We'll use this to temporarily store style properties.
364
- tmp : [],
437
+ // We'll use this to temporarily store style properties.
438
+ tmp: [],
365
439
 
366
- // We'll use this to set hidden parent elements.
367
- hidden : null,
440
+ // We'll use this to set hidden parent elements.
441
+ hidden: null,
368
442
 
369
- adjust : function( $child ) {
370
- // Internal reference.
371
- var _self = this;
443
+ adjust: function ($child) {
444
+ // Internal reference.
445
+ var _self = this;
372
446
 
373
- // Set all hidden parent elements, including this element.
374
- _self.hidden = $child.parents().andSelf().filter( ":hidden" );
447
+ // Set all hidden parent elements, including this element.
448
+ _self.hidden = $child.parents().andSelf().filter(":hidden");
375
449
 
376
- // Loop through all hidden elements.
377
- _self.hidden.each( function() {
450
+ // Loop through all hidden elements.
451
+ _self.hidden.each(function () {
378
452
 
379
- // Cache the element.
380
- var $elem = $( this );
453
+ // Cache the element.
454
+ var $elem = $(this);
381
455
 
382
- // Store the style attribute.
383
- // Undefined if element doesn't have a style attribute.
384
- _self.tmp.push( $elem.attr( 'style' ) );
385
-
386
- // Set the element's display property to block,
387
- // but ensure it's visibility is hidden.
388
- $elem.css( { 'visibility' : 'hidden', 'display' : 'block' } );
389
- });
456
+ // Store the style attribute.
457
+ // Undefined if element doesn't have a style attribute.
458
+ _self.tmp.push($elem.attr('style'));
390
459
 
391
- }, // end adjust
392
-
393
- /**
394
- * Resets the elements previous state.
395
- *
396
- * @method reset
397
- */
398
- reset : function() {
399
- // Internal reference.
400
- var _self = this;
401
- // Loop through our hidden element collection.
402
- _self.hidden.each( function( i ) {
403
- // Cache this element.
404
- var $elem = $( this ),
405
- _tmp = _self.tmp[ i ]; // Get the stored 'style' value for this element.
406
-
407
- // If the stored value is undefined.
408
- if( _tmp === undefined )
460
+ // Set the element's display property to block,
461
+ // but ensure it's visibility is hidden.
462
+ $elem.css({
463
+ 'visibility': 'hidden',
464
+ 'display': 'block'
465
+ });
466
+ });
467
+
468
+ }, // end adjust
469
+
470
+ /**
471
+ * Resets the elements previous state.
472
+ *
473
+ * @method reset
474
+ */
475
+ reset: function () {
476
+ // Internal reference.
477
+ var _self = this;
478
+ // Loop through our hidden element collection.
479
+ _self.hidden.each(function (i) {
480
+ // Cache this element.
481
+ var $elem = $(this),
482
+ _tmp = _self.tmp[i]; // Get the stored 'style' value for this element.
483
+
484
+ // If the stored value is undefined.
485
+ if (_tmp === undefined)
409
486
  // Remove the style attribute.
410
- $elem.removeAttr( 'style' );
411
- else
487
+ $elem.removeAttr('style');
488
+ else
412
489
  // Otherwise, reset the element style attribute.
413
- $elem.attr( 'style', _tmp );
414
-
415
- });
416
- // Reset the tmp array.
417
- _self.tmp = [];
418
- // Reset the hidden elements variable.
419
- _self.hidden = null;
420
-
421
- } // end reset
422
-
490
+ $elem.attr('style', _tmp);
491
+ });
492
+ // Reset the tmp array.
493
+ _self.tmp = [];
494
+ // Reset the hidden elements variable.
495
+ _self.hidden = null;
496
+
497
+ } // end reset
423
498
  },
424
499
 
425
- off : function () {
500
+ off: function () {
426
501
  $(this.scope).off('.fndtn.forms');
427
502
  }
428
503
  };
504
+
505
+ var getFirstPrevSibling = function($el, selector) {
506
+ var $el = $el.prev();
507
+ while ($el.length) {
508
+ if ($el.is(selector)) return $el;
509
+ $el = $el.prev();
510
+ }
511
+ return $();
512
+ };
429
513
  }(Foundation.zj, this, this.document));