helios 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +93 -71
  3. data/README.md +150 -127
  4. data/helios.gemspec +5 -4
  5. data/lib/helios/backend/push-notification.rb +1 -0
  6. data/lib/helios/commands/link.rb +2 -0
  7. data/lib/helios/commands/new.rb +1 -0
  8. data/lib/helios/frontend/javascripts/vendor/foundation.js +163 -47
  9. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.alerts.js +6 -4
  10. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.clearing.js +70 -32
  11. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.dropdown.js +87 -31
  12. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.forms.js +360 -238
  13. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.interchange.js +271 -0
  14. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.joyride.js +279 -48
  15. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.magellan.js +8 -4
  16. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.orbit.js +59 -24
  17. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.placeholder.js +21 -1
  18. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.reveal.js +100 -42
  19. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.section.js +299 -60
  20. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.tooltips.js +26 -13
  21. data/lib/helios/frontend/javascripts/vendor/foundation/foundation.topbar.js +154 -59
  22. data/lib/helios/frontend/javascripts/vendor/foundation/index.js +17 -0
  23. data/lib/helios/frontend/stylesheets/screen.sass +0 -1
  24. data/lib/helios/frontend/templates/push-notification/devices.jst.tpl +0 -3
  25. data/lib/helios/templates/.gitignore.erb +32 -0
  26. data/lib/helios/version.rb +1 -1
  27. metadata +31 -14
@@ -6,21 +6,24 @@
6
6
  Foundation.libs.dropdown = {
7
7
  name : 'dropdown',
8
8
 
9
- version : '4.0.0',
9
+ version : '4.2.0',
10
10
 
11
11
  settings : {
12
- activeClass: 'open'
12
+ activeClass: 'open',
13
+ is_hover: false,
14
+ opened: function(){},
15
+ closed: function(){}
13
16
  },
14
17
 
15
18
  init : function (scope, method, options) {
16
19
  this.scope = scope || this.scope;
17
- Foundation.inherit(this, 'throttle');
20
+ Foundation.inherit(this, 'throttle scrollLeft data_options');
18
21
 
19
22
  if (typeof method === 'object') {
20
23
  $.extend(true, this.settings, method);
21
24
  }
22
25
 
23
- if (typeof method != 'string') {
26
+ if (typeof method !== 'string') {
24
27
 
25
28
  if (!this.settings.init) {
26
29
  this.events();
@@ -35,22 +38,37 @@
35
38
  events : function () {
36
39
  var self = this;
37
40
 
38
- $(this.scope).on('click.fndtn.dropdown', '[data-dropdown]', function (e) {
39
- e.preventDefault();
40
- e.stopPropagation();
41
- self.toggle($(this));
42
- });
43
-
44
- $('*, html, body').on('click.fndtn.dropdown', function (e) {
45
- if (!$(e.target).data('dropdown')) {
46
- $('[data-dropdown-content]')
47
- .css('left', '-99999px')
48
- .removeClass(self.settings.activeClass);
41
+ $(this.scope)
42
+ .on('click.fndtn.dropdown', '[data-dropdown]', function (e) {
43
+ var settings = $.extend({}, self.settings, self.data_options($(this)));
44
+ e.preventDefault();
45
+
46
+ if (!settings.is_hover) self.toggle($(this));
47
+ })
48
+ .on('mouseenter', '[data-dropdown]', function (e) {
49
+ var settings = $.extend({}, self.settings, self.data_options($(this)));
50
+ if (settings.is_hover) self.toggle($(this));
51
+ })
52
+ .on('mouseleave', '[data-dropdown-content]', function (e) {
53
+ var target = $('[data-dropdown="' + $(this).attr('id') + '"]'),
54
+ settings = $.extend({}, self.settings, self.data_options(target));
55
+ if (settings.is_hover) self.close.call(self, $(this));
56
+ })
57
+ .on('opened.fndtn.dropdown', '[data-dropdown-content]', this.settings.opened)
58
+ .on('closed.fndtn.dropdown', '[data-dropdown-content]', this.settings.closed);
59
+
60
+ $('body').on('click.fndtn.dropdown', function (e) {
61
+ var parent = $(e.target).closest('[data-dropdown-content]');
62
+
63
+ if ($(e.target).data('dropdown')) {
64
+ return;
65
+ }
66
+ if (parent.length > 0 && ($(e.target).is('[data-dropdown-content]') || $.contains(parent.first()[0], e.target))) {
67
+ e.stopPropagation();
68
+ return;
49
69
  }
50
- });
51
70
 
52
- $('[data-dropdown-content]').on('click.fndtn.dropdown', function (e) {
53
- e.stopPropagation();
71
+ self.close.call(self, $('[data-dropdown-content]'));
54
72
  });
55
73
 
56
74
  $(window).on('resize.fndtn.dropdown', self.throttle(function () {
@@ -60,19 +78,35 @@
60
78
  this.settings.init = true;
61
79
  },
62
80
 
63
- toggle : function (target, resize) {
81
+ close: function (dropdown) {
82
+ var self = this;
83
+ dropdown.each(function () {
84
+ if ($(this).hasClass(self.settings.activeClass)) {
85
+ $(this)
86
+ .css(Foundation.rtl ? 'right':'left', '-99999px')
87
+ .removeClass(self.settings.activeClass);
88
+ $(this).trigger('closed');
89
+ }
90
+ });
91
+ },
92
+
93
+ open: function (dropdown, target) {
94
+ this
95
+ .css(dropdown
96
+ .addClass(this.settings.activeClass), target);
97
+ dropdown.trigger('opened');
98
+ },
99
+
100
+ toggle : function (target) {
64
101
  var dropdown = $('#' + target.data('dropdown'));
65
102
 
66
- $('[data-dropdown-content]').not(dropdown).css('left', '-99999px');
103
+ this.close.call(this, $('[data-dropdown-content]').not(dropdown));
67
104
 
68
105
  if (dropdown.hasClass(this.settings.activeClass)) {
69
- dropdown
70
- .css('left', '-99999px')
71
- .removeClass(this.settings.activeClass);
106
+ this.close.call(this, dropdown);
72
107
  } else {
73
- this
74
- .css(dropdown
75
- .addClass(this.settings.activeClass), target);
108
+ this.close.call(this, $('[data-dropdown-content]'))
109
+ this.open.call(this, dropdown, target);
76
110
  }
77
111
  },
78
112
 
@@ -86,7 +120,15 @@
86
120
  },
87
121
 
88
122
  css : function (dropdown, target) {
89
- var offset = target.offset();
123
+ var offset_parent = dropdown.offsetParent();
124
+ // temporary workaround until 4.2
125
+ if (offset_parent.length > 0 && /body/i.test(dropdown.offsetParent()[0].nodeName)) {
126
+ var position = target.offset();
127
+ position.top -= dropdown.offsetParent().offset().top;
128
+ position.left -= dropdown.offsetParent().offset().left;
129
+ } else {
130
+ var position = target.position();
131
+ }
90
132
 
91
133
  if (this.small()) {
92
134
  dropdown.css({
@@ -94,13 +136,25 @@
94
136
  width: '95%',
95
137
  left: '2.5%',
96
138
  'max-width': 'none',
97
- top: offset.top + this.outerHeight(target)
139
+ top: position.top + this.outerHeight(target)
98
140
  });
99
141
  } else {
142
+ if (!Foundation.rtl && $(window).width() > this.outerWidth(dropdown) + target.offset().left) {
143
+ var left = position.left;
144
+ if (dropdown.hasClass('right')) {
145
+ dropdown.removeClass('right');
146
+ }
147
+ } else {
148
+ if (!dropdown.hasClass('right')) {
149
+ dropdown.addClass('right');
150
+ }
151
+ var left = position.left - (this.outerWidth(dropdown) - this.outerWidth(target));
152
+ }
153
+
100
154
  dropdown.attr('style', '').css({
101
155
  position : 'absolute',
102
- top: offset.top + this.outerHeight(target),
103
- left: offset.left
156
+ top: position.top + this.outerHeight(target),
157
+ left: left
104
158
  });
105
159
  }
106
160
 
@@ -117,6 +171,8 @@
117
171
  $(window).off('.fndtn.dropdown');
118
172
  $('[data-dropdown-content]').off('.fndtn.dropdown');
119
173
  this.settings.init = false;
120
- }
174
+ },
175
+
176
+ reflow : function () {}
121
177
  };
122
178
  }(Foundation.zj, this, this.document));
@@ -1,25 +1,25 @@
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.2.3',
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);
20
20
  }
21
21
 
22
- if (typeof method != 'string') {
22
+ if (typeof method !== 'string') {
23
23
  if (!this.settings.init) {
24
24
  this.events();
25
25
  }
@@ -32,16 +32,23 @@
32
32
  }
33
33
  },
34
34
 
35
- assemble : function () {
36
- $('form.custom input[type="radio"]').not('[data-customforms="disabled"]')
35
+ assemble: function () {
36
+ $('form.custom input[type="radio"]', $(this.scope))
37
+ .not('[data-customforms="disabled"]')
38
+ .not('.' + this.settings.disable_class)
37
39
  .each(this.append_custom_markup);
38
- $('form.custom input[type="checkbox"]').not('[data-customforms="disabled"]')
40
+ $('form.custom input[type="checkbox"]', $(this.scope))
41
+ .not('[data-customforms="disabled"]')
42
+ .not('.' + this.settings.disable_class)
39
43
  .each(this.append_custom_markup);
40
- $('form.custom select').not('[data-customforms="disabled"]')
44
+ $('form.custom select', $(this.scope))
45
+ .not('[data-customforms="disabled"]')
46
+ .not('.' + this.settings.disable_class)
47
+ .not('[multiple=multiple]')
41
48
  .each(this.append_custom_select);
42
49
  },
43
50
 
44
- events : function () {
51
+ events: function () {
45
52
  var self = this;
46
53
 
47
54
  $(this.scope)
@@ -55,49 +62,47 @@
55
62
  e.stopPropagation();
56
63
  self.toggle_radio($(this));
57
64
  })
58
- .on('change.fndtn.forms', 'form.custom select:not([data-customforms="disabled"])', function (e) {
59
- self.refresh_custom_select($(this));
65
+ .on('change.fndtn.forms', 'form.custom select', function (e, force_refresh) {
66
+ if ($(this).is('[data-customforms="disabled"]')) return;
67
+ self.refresh_custom_select($(this), force_refresh);
60
68
  })
61
69
  .on('click.fndtn.forms', 'form.custom label', function (e) {
62
- var $associatedElement = $('#' + self.escape($(this).attr('for')) + ':not([data-customforms="disabled"])'),
70
+ if ($(e.target).is('label')) {
71
+ var $associatedElement = $('#' + self.escape($(this).attr('for'))).not('[data-customforms="disabled"]'),
63
72
  $customCheckbox,
64
73
  $customRadio;
65
- if ($associatedElement.length !== 0) {
66
- if ($associatedElement.attr('type') === 'checkbox') {
67
- e.preventDefault();
68
- $customCheckbox = $(this).find('span.custom.checkbox');
69
- //the checkbox might be outside after the label
70
- if ($customCheckbox.length == 0) {
71
- $customCheckbox = $(this).next('span.custom.checkbox');
72
- }
73
- //the checkbox might be outside before the label
74
- if ($customCheckbox.length == 0) {
75
- $customCheckbox = $(this).prev('span.custom.checkbox');
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
82
- if ($customRadio.length == 0) {
83
- $customRadio = $(this).next('span.custom.radio');
84
- }
85
- //the radio might be outside before the label
86
- if ($customRadio.length == 0) {
87
- $customRadio = $(this).prev('span.custom.radio');
74
+
75
+ if ($associatedElement.length !== 0) {
76
+ if ($associatedElement.attr('type') === 'checkbox') {
77
+ e.preventDefault();
78
+ $customCheckbox = $(this).find('span.custom.checkbox');
79
+ //the checkbox might be outside after the label or inside of another element
80
+ if ($customCheckbox.length === 0) {
81
+ $customCheckbox = $associatedElement.add(this).siblings('span.custom.checkbox').first();
82
+ }
83
+ self.toggle_checkbox($customCheckbox);
84
+ } else if ($associatedElement.attr('type') === 'radio') {
85
+ e.preventDefault();
86
+ $customRadio = $(this).find('span.custom.radio');
87
+ //the radio might be outside after the label or inside of another element
88
+ if ($customRadio.length === 0) {
89
+ $customRadio = $associatedElement.add(this).siblings('span.custom.radio').first();
90
+ }
91
+ self.toggle_radio($customRadio);
88
92
  }
89
- self.toggle_radio($customRadio);
90
93
  }
91
94
  }
92
95
  })
96
+ .on('mousedown.fndtn.forms', 'form.custom div.custom.dropdown', function () {
97
+ return false;
98
+ })
93
99
  .on('click.fndtn.forms', 'form.custom div.custom.dropdown a.current, form.custom div.custom.dropdown a.selector', function (e) {
94
100
  var $this = $(this),
95
101
  $dropdown = $this.closest('div.custom.dropdown'),
96
- $select = $dropdown.prev();
102
+ $select = getFirstPrevSibling($dropdown, 'select');
97
103
 
98
104
  // make sure other dropdowns close
99
- if(!$dropdown.hasClass('open'))
100
- $(self.scope).trigger('click');
105
+ if (!$dropdown.hasClass('open')) $(self.scope).trigger('click');
101
106
 
102
107
  e.preventDefault();
103
108
  if (false === $select.is(':disabled')) {
@@ -117,32 +122,29 @@
117
122
  .on('click.fndtn.forms touchend.fndtn.forms', 'form.custom div.custom.dropdown li', function (e) {
118
123
  var $this = $(this),
119
124
  $customDropdown = $this.closest('div.custom.dropdown'),
120
- $select = $customDropdown.prev(),
125
+ $select = getFirstPrevSibling($customDropdown, 'select'),
121
126
  selectedIndex = 0;
122
127
 
123
128
  e.preventDefault();
124
129
  e.stopPropagation();
125
130
 
126
- if ( ! $(this).hasClass('disabled')) {
131
+ if (!$(this).hasClass('disabled')) {
127
132
  $('div.dropdown').not($customDropdown).removeClass('open');
128
133
 
129
- var $oldThis= $this
130
- .closest('ul')
134
+ var $oldThis = $this.closest('ul')
131
135
  .find('li.selected');
132
136
  $oldThis.removeClass('selected');
133
137
 
134
138
  $this.addClass('selected');
135
139
 
136
- $customDropdown
137
- .removeClass('open')
140
+ $customDropdown.removeClass('open')
138
141
  .find('a.current')
139
- .html($this.html());
142
+ .text($this.text());
140
143
 
141
144
  $this.closest('ul').find('li').each(function (index) {
142
- if ($this[0] == this) {
145
+ if ($this[0] === this) {
143
146
  selectedIndex = index;
144
147
  }
145
-
146
148
  });
147
149
  $select[0].selectedIndex = selectedIndex;
148
150
 
@@ -150,15 +152,94 @@
150
152
  $select.data('prevalue', $oldThis.html());
151
153
  $select.trigger('change');
152
154
  }
153
- });
155
+ });
156
+
157
+ $(window).on('keydown', function (e) {
158
+ var focus = document.activeElement,
159
+ self = Foundation.libs.forms,
160
+ dropdown = $('.custom.dropdown.open');
161
+
162
+ if (dropdown.length > 0) {
163
+ e.preventDefault();
164
+
165
+ if (e.which === 13) {
166
+ dropdown.find('li.selected').trigger('click');
167
+ }
168
+
169
+ if (e.which === 27) {
170
+ dropdown.removeClass('open');
171
+ }
172
+
173
+ if (e.which >= 65 && e.which <= 90) {
174
+ var next = self.go_to(dropdown, e.which),
175
+ current = dropdown.find('li.selected');
176
+
177
+ if (next) {
178
+ current.removeClass('selected');
179
+ self.scrollTo(next.addClass('selected'), 300);
180
+ }
181
+ }
182
+
183
+ if (e.which === 38) {
184
+ var current = dropdown.find('li.selected'),
185
+ prev = current.prev(':not(.disabled)');
186
+
187
+ if (prev.length > 0) {
188
+ prev.parent()[0].scrollTop = prev.parent().scrollTop() - self.outerHeight(prev);
189
+ current.removeClass('selected');
190
+ prev.addClass('selected');
191
+ }
192
+ } else if (e.which === 40) {
193
+ var current = dropdown.find('li.selected'),
194
+ next = current.next(':not(.disabled)');
195
+
196
+ if (next.length > 0) {
197
+ next.parent()[0].scrollTop = next.parent().scrollTop() + self.outerHeight(next);
198
+ current.removeClass('selected');
199
+ next.addClass('selected');
200
+ }
201
+ }
202
+ }
203
+ });
154
204
 
155
205
  this.settings.init = true;
156
206
  },
157
207
 
158
- append_custom_markup : function (idx, sel) {
159
- var $this = $(sel).hide(),
160
- type = $this.attr('type'),
208
+ go_to: function (dropdown, character) {
209
+ var lis = dropdown.find('li'),
210
+ count = lis.length;
211
+
212
+ if (count > 0) {
213
+ for (var i = 0; i < count; i++) {
214
+ var first_letter = lis.eq(i).text().charAt(0).toLowerCase();
215
+ if (first_letter === String.fromCharCode(character).toLowerCase()) return lis.eq(i);
216
+ }
217
+ }
218
+ },
219
+
220
+ scrollTo: function (el, duration) {
221
+ if (duration < 0) return;
222
+ var parent = el.parent();
223
+ var li_height = this.outerHeight(el);
224
+ var difference = (li_height * (el.index())) - parent.scrollTop();
225
+ var perTick = difference / duration * 10;
226
+
227
+ this.scrollToTimerCache = setTimeout(function () {
228
+ if (!isNaN(parseInt(perTick, 10))) {
229
+ parent[0].scrollTop = parent.scrollTop() + perTick;
230
+ this.scrollTo(el, duration - 10);
231
+ }
232
+ }.bind(this), 10);
233
+ },
234
+
235
+ append_custom_markup: function (idx, sel) {
236
+ var $this = $(sel),
237
+ type = $this.attr('type'),
161
238
  $span = $this.next('span.custom.' + type);
239
+
240
+ if (!$this.parent().hasClass('switch')) {
241
+ $this.addClass('hidden-field');
242
+ }
162
243
 
163
244
  if ($span.length === 0) {
164
245
  $span = $('<span class="custom ' + type + '"></span>').insertAfter($this);
@@ -168,133 +249,157 @@
168
249
  $span.toggleClass('disabled', $this.is(':disabled'));
169
250
  },
170
251
 
171
- append_custom_select : function (idx, sel) {
172
- var self = Foundation.libs.forms,
173
- $this = $( sel ),
174
- $customSelect = $this.next( 'div.custom.dropdown' ),
175
- $customList = $customSelect.find( 'ul' ),
176
- $selectCurrent = $customSelect.find( ".current" ),
177
- $selector = $customSelect.find( ".selector" ),
178
- $options = $this.find( 'option' ),
179
- $selectedOption = $options.filter( ':selected' ),
180
- maxWidth = 0,
181
- liHtml = '',
182
- $listItems,
183
- $currentSelect = false;
184
-
185
- if ($this.hasClass(self.settings.disable_class)) return;
186
-
187
- if ($customSelect.length === 0) {
188
- var customSelectSize = $this.hasClass( 'small' ) ? 'small' :
189
- $this.hasClass( 'medium' ) ? 'medium' :
190
- $this.hasClass( 'large' ) ? 'large' :
191
- $this.hasClass( 'expand' ) ? 'expand' : '';
192
-
193
- $customSelect = $('<div class="' + ['custom', 'dropdown', customSelectSize ].join( ' ' ) + '"><a href="#" class="selector"></a><ul /></div>');
194
- $selector = $customSelect.find(".selector");
195
- $customList = $customSelect.find("ul");
196
- liHtml = $options.map(function() { return "<li>" + $( this ).html() + "</li>"; } ).get().join( '' );
197
- $customList.append(liHtml);
198
- $currentSelect = $customSelect.prepend('<a href="#" class="current">' + $selectedOption.html() + '</a>' ).find( ".current" );
199
- $this
200
- .after( $customSelect )
201
- .hide();
202
-
203
- } else {
204
- liHtml = $options.map(function() {
205
- return "<li>" + $( this ).html() + "</li>";
206
- })
207
- .get().join('');
208
- $customList
209
- .html('')
210
- .append(liHtml);
211
-
212
- } // endif $customSelect.length === 0
213
- $customSelect.toggleClass('disabled', $this.is( ':disabled' ) );
214
- $listItems = $customList.find( 'li' );
215
-
216
- $options.each( function ( index ) {
217
- if ( this.selected ) {
218
- $listItems.eq( index ).addClass( 'selected' );
219
-
220
- if ($currentSelect) {
221
- $currentSelect.html( $( this ).html() );
252
+ append_custom_select: function (idx, sel) {
253
+ var self = Foundation.libs.forms,
254
+ $this = $(sel),
255
+ $customSelect = $this.next('div.custom.dropdown'),
256
+ $customList = $customSelect.find('ul'),
257
+ $selectCurrent = $customSelect.find(".current"),
258
+ $selector = $customSelect.find(".selector"),
259
+ $options = $this.find('option'),
260
+ $selectedOption = $options.filter(':selected'),
261
+ copyClasses = $this.attr('class') ? $this.attr('class').split(' ') : [],
262
+ maxWidth = 0,
263
+ liHtml = '',
264
+ $listItems,
265
+ $currentSelect = false;
266
+
267
+ if ($customSelect.length === 0) {
268
+ var customSelectSize = $this.hasClass('small') ? 'small' : $this.hasClass('medium') ? 'medium' : $this.hasClass('large') ? 'large' : $this.hasClass('expand') ? 'expand' : '';
269
+
270
+ $customSelect = $('<div class="' + ['custom', 'dropdown', customSelectSize].concat(copyClasses).filter(function (item, idx, arr) {
271
+ if (item === '') return false;
272
+ return arr.indexOf(item) === idx;
273
+ }).join(' ') + '"><a href="#" class="selector"></a><ul /></div>');
274
+
275
+ $selector = $customSelect.find(".selector");
276
+ $customList = $customSelect.find("ul");
277
+
278
+ liHtml = $options.map(function () {
279
+ var copyClasses = $(this).attr('class') ? $(this).attr('class') : '';
280
+ return "<li class='" + copyClasses + "'>" + $(this).html() + "</li>";
281
+ }).get().join('');
282
+
283
+ $customList.append(liHtml);
284
+
285
+ $currentSelect = $customSelect
286
+ .prepend('<a href="#" class="current">' + $selectedOption.html() + '</a>')
287
+ .find(".current");
288
+
289
+ $this.after($customSelect)
290
+ .addClass('hidden-field');
291
+ } else {
292
+ liHtml = $options.map(function () {
293
+ return "<li>" + $(this).html() + "</li>";
294
+ })
295
+ .get().join('');
296
+
297
+ $customList.html('')
298
+ .append(liHtml);
299
+
300
+ } // endif $customSelect.length === 0
301
+
302
+ self.assign_id($this, $customSelect);
303
+ $customSelect.toggleClass('disabled', $this.is(':disabled'));
304
+ $listItems = $customList.find('li');
305
+
306
+ // cache list length
307
+ self.cache[$customSelect.data('id')] = $listItems.length;
308
+
309
+ $options.each(function (index) {
310
+ if (this.selected) {
311
+ $listItems.eq(index).addClass('selected');
312
+
313
+ if ($currentSelect) {
314
+ $currentSelect.html($(this).html());
315
+ }
316
+ }
317
+ if ($(this).is(':disabled')) {
318
+ $listItems.eq(index).addClass('disabled');
222
319
  }
320
+ });
223
321
 
224
- }
225
- if ($(this).is(':disabled')) {
226
- $listItems.eq( index ).addClass( 'disabled' );
227
- }
228
- });
322
+ //
323
+ // If we're not specifying a predetermined form size.
324
+ //
325
+ if (!$customSelect.is('.small, .medium, .large, .expand')) {
229
326
 
230
- //
231
- // If we're not specifying a predetermined form size.
232
- //
233
- if (!$customSelect.is('.small, .medium, .large, .expand')) {
327
+ // ------------------------------------------------------------------------------------
328
+ // This is a work-around for when elements are contained within hidden parents.
329
+ // For example, when custom-form elements are inside of a hidden reveal modal.
330
+ //
331
+ // We need to display the current custom list element as well as hidden parent elements
332
+ // in order to properly calculate the list item element's width property.
333
+ // -------------------------------------------------------------------------------------
234
334
 
235
- // ------------------------------------------------------------------------------------
236
- // This is a work-around for when elements are contained within hidden parents.
237
- // For example, when custom-form elements are inside of a hidden reveal modal.
238
- //
239
- // We need to display the current custom list element as well as hidden parent elements
240
- // in order to properly calculate the list item element's width property.
241
- // -------------------------------------------------------------------------------------
335
+ $customSelect.addClass('open');
336
+ //
337
+ // Quickly, display all parent elements.
338
+ // This should help us calcualate the width of the list item's within the drop down.
339
+ //
340
+ var self = Foundation.libs.forms;
341
+ self.hidden_fix.adjust($customList);
242
342
 
243
- $customSelect.addClass( 'open' );
244
- //
245
- // Quickly, display all parent elements.
246
- // This should help us calcualate the width of the list item's within the drop down.
247
- //
248
- var self = Foundation.libs.forms;
249
- self.hidden_fix.adjust( $customList );
343
+ maxWidth = (self.outerWidth($listItems) > maxWidth) ? self.outerWidth($listItems) : maxWidth;
250
344
 
251
- maxWidth = ( self.outerWidth($listItems) > maxWidth ) ? self.outerWidth($listItems) : maxWidth;
345
+ Foundation.libs.forms.hidden_fix.reset();
252
346
 
253
- Foundation.libs.forms.hidden_fix.reset();
347
+ $customSelect.removeClass('open');
254
348
 
255
- $customSelect.removeClass( 'open' );
349
+ } // endif
256
350
 
257
- } // endif
351
+ },
258
352
 
353
+ assign_id: function ($select, $customSelect) {
354
+ var id = [+new Date(), Foundation.random_str(5)].join('-');
355
+ $select.attr('data-id', id);
356
+ $customSelect.attr('data-id', id);
259
357
  },
260
358
 
261
- refresh_custom_select : function ($select) {
359
+ refresh_custom_select: function ($select, force_refresh) {
262
360
  var self = this;
263
361
  var maxWidth = 0,
264
- $customSelect = $select.next(),
265
- $options = $select.find('option');
362
+ $customSelect = $select.next(),
363
+ $options = $select.find('option'),
364
+ $listItems = $customSelect.find('li');
266
365
 
267
- $customSelect.find('ul').html('');
366
+ if ($listItems.length !== this.cache[$customSelect.data('id')] || force_refresh) {
367
+ $customSelect.find('ul').html('');
268
368
 
269
- $options.each(function () {
270
- var $li = $('<li>' + $(this).html() + '</li>');
271
- $customSelect.find('ul').append($li);
272
- });
369
+ $options.each(function () {
370
+ var $li = $('<li>' + $(this).html() + '</li>');
371
+ $customSelect.find('ul').append($li);
372
+ });
273
373
 
274
- // re-populate
275
- $options.each(function (index) {
276
- if (this.selected) {
277
- $customSelect.find('li').eq(index).addClass('selected');
278
- $customSelect.find('.current').html($(this).html());
279
- }
280
- if ($(this).is(':disabled')) {
281
- $customSelect.find('li').eq(index).addClass('disabled');
282
- }
283
- });
374
+ // re-populate
375
+ $options.each(function (index) {
376
+ if (this.selected) {
377
+ $customSelect.find('li').eq(index).addClass('selected');
378
+ $customSelect.find('.current').html($(this).html());
379
+ }
380
+ if ($(this).is(':disabled')) {
381
+ $customSelect.find('li').eq(index).addClass('disabled');
382
+ }
383
+ });
284
384
 
285
- // fix width
286
- $customSelect.removeAttr('style')
287
- .find('ul').removeAttr('style');
288
- $customSelect.find('li').each(function () {
289
- $customSelect.addClass('open');
290
- if (self.outerWidth($(this)) > maxWidth) {
291
- maxWidth = self.outerWidth($(this));
292
- }
293
- $customSelect.removeClass('open');
294
- });
385
+ // fix width
386
+ $customSelect.removeAttr('style')
387
+ .find('ul').removeAttr('style');
388
+ $customSelect.find('li').each(function () {
389
+ $customSelect.addClass('open');
390
+ if (self.outerWidth($(this)) > maxWidth) {
391
+ maxWidth = self.outerWidth($(this));
392
+ }
393
+ $customSelect.removeClass('open');
394
+ });
395
+
396
+ $listItems = $customSelect.find('li');
397
+ // cache list length
398
+ this.cache[$customSelect.data('id')] = $listItems.length;
399
+ }
295
400
  },
296
401
 
297
- toggle_checkbox : function ($element) {
402
+ toggle_checkbox: function ($element) {
298
403
  var $input = $element.prev(),
299
404
  input = $input[0];
300
405
 
@@ -306,98 +411,115 @@
306
411
  }
307
412
  },
308
413
 
309
- toggle_radio : function ($element) {
310
- var $input = $element.prev(),
311
- $form = $input.closest('form.custom'),
312
- input = $input[0];
414
+ toggle_radio: function ($element) {
415
+ var $input = $element.prev(),
416
+ $form = $input.closest('form.custom'),
417
+ input = $input[0];
313
418
 
314
- if (false === $input.is(':disabled')) {
315
- $form.find('input[type="radio"][name="' + this.escape($input.attr('name')) + '"]').next().not($element).removeClass('checked');
316
- if ( !$element.hasClass('checked') ) {
317
- $element.toggleClass('checked');
318
- }
319
- input.checked = $element.hasClass('checked');
419
+ if (false === $input.is(':disabled')) {
420
+ $form.find('input[type="radio"][name="' + this.escape($input.attr('name')) + '"]')
421
+ .next().not($element).removeClass('checked');
320
422
 
321
- $input.trigger('change');
322
- }
423
+ if (!$element.hasClass('checked')) {
424
+ $element.toggleClass('checked');
425
+ }
426
+
427
+ input.checked = $element.hasClass('checked');
428
+
429
+ $input.trigger('change');
430
+ }
323
431
  },
324
432
 
325
- escape : function (text) {
433
+ escape: function (text) {
434
+ if (!text) return '';
326
435
  return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
327
436
  },
328
437
 
329
- hidden_fix : {
330
- /**
331
- * Sets all hidden parent elements and self to visibile.
332
- *
333
- * @method adjust
334
- * @param {jQuery Object} $child
335
- */
438
+ hidden_fix: {
439
+ /**
440
+ * Sets all hidden parent elements and self to visibile.
441
+ *
442
+ * @method adjust
443
+ * @param {jQuery Object} $child
444
+ */
336
445
 
337
- // We'll use this to temporarily store style properties.
338
- tmp : [],
446
+ // We'll use this to temporarily store style properties.
447
+ tmp: [],
339
448
 
340
- // We'll use this to set hidden parent elements.
341
- hidden : null,
449
+ // We'll use this to set hidden parent elements.
450
+ hidden: null,
342
451
 
343
- adjust : function( $child ) {
344
- // Internal reference.
345
- var _self = this;
452
+ adjust: function ($child) {
453
+ // Internal reference.
454
+ var _self = this;
346
455
 
347
- // Set all hidden parent elements, including this element.
348
- _self.hidden = $child.parents().andSelf().filter( ":hidden" );
456
+ // Set all hidden parent elements, including this element.
457
+ _self.hidden = $child.parents();
458
+ _self.hidden = _self.hidden.add($child).filter(":hidden");
349
459
 
350
- // Loop through all hidden elements.
351
- _self.hidden.each( function() {
460
+ // Loop through all hidden elements.
461
+ _self.hidden.each(function () {
352
462
 
353
- // Cache the element.
354
- var $elem = $( this );
463
+ // Cache the element.
464
+ var $elem = $(this);
355
465
 
356
- // Store the style attribute.
357
- // Undefined if element doesn't have a style attribute.
358
- _self.tmp.push( $elem.attr( 'style' ) );
466
+ // Store the style attribute.
467
+ // Undefined if element doesn't have a style attribute.
468
+ _self.tmp.push($elem.attr('style'));
359
469
 
360
- // Set the element's display property to block,
361
- // but ensure it's visibility is hidden.
362
- $elem.css( { 'visibility' : 'hidden', 'display' : 'block' } );
363
- });
364
-
365
- }, // end adjust
366
-
367
- /**
368
- * Resets the elements previous state.
369
- *
370
- * @method reset
371
- */
372
- reset : function() {
373
- // Internal reference.
374
- var _self = this;
375
- // Loop through our hidden element collection.
376
- _self.hidden.each( function( i ) {
377
- // Cache this element.
378
- var $elem = $( this ),
379
- _tmp = _self.tmp[ i ]; // Get the stored 'style' value for this element.
380
-
381
- // If the stored value is undefined.
382
- if( _tmp === undefined )
470
+ // Set the element's display property to block,
471
+ // but ensure it's visibility is hidden.
472
+ $elem.css({
473
+ 'visibility': 'hidden',
474
+ 'display': 'block'
475
+ });
476
+ });
477
+
478
+ }, // end adjust
479
+
480
+ /**
481
+ * Resets the elements previous state.
482
+ *
483
+ * @method reset
484
+ */
485
+ reset: function () {
486
+ // Internal reference.
487
+ var _self = this;
488
+ // Loop through our hidden element collection.
489
+ _self.hidden.each(function (i) {
490
+ // Cache this element.
491
+ var $elem = $(this),
492
+ _tmp = _self.tmp[i]; // Get the stored 'style' value for this element.
493
+
494
+ // If the stored value is undefined.
495
+ if (_tmp === undefined)
383
496
  // Remove the style attribute.
384
- $elem.removeAttr( 'style' );
385
- else
497
+ $elem.removeAttr('style');
498
+ else
386
499
  // Otherwise, reset the element style attribute.
387
- $elem.attr( 'style', _tmp );
388
-
389
- });
390
- // Reset the tmp array.
391
- _self.tmp = [];
392
- // Reset the hidden elements variable.
393
- _self.hidden = null;
394
-
395
- } // end reset
396
-
500
+ $elem.attr('style', _tmp);
501
+ });
502
+ // Reset the tmp array.
503
+ _self.tmp = [];
504
+ // Reset the hidden elements variable.
505
+ _self.hidden = null;
506
+
507
+ } // end reset
397
508
  },
398
509
 
399
- off : function () {
510
+ off: function () {
400
511
  $(this.scope).off('.fndtn.forms');
512
+ },
513
+
514
+ reflow : function () {}
515
+ };
516
+
517
+ var getFirstPrevSibling = function($el, selector) {
518
+ var $el = $el.prev();
519
+ while ($el.length) {
520
+ if ($el.is(selector)) return $el;
521
+ $el = $el.prev();
401
522
  }
523
+ return $();
402
524
  };
403
- }(Foundation.zj, this, this.document));
525
+ }(Foundation.zj, this, this.document));