mui-sass 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +11 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +119 -0
  9. data/Rakefile +1 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +7 -0
  12. data/lib/mui-sass.rb +60 -0
  13. data/lib/mui/sass/engine.rb +13 -0
  14. data/lib/mui/sass/version.rb +5 -0
  15. data/mui-sass.gemspec +29 -0
  16. data/templates/project/manifest.rb +2 -0
  17. data/templates/project/styles.sass +1 -0
  18. data/vendor/assets/javascripts/mui.js +1593 -0
  19. data/vendor/assets/stylesheets/_mui.scss +27 -0
  20. data/vendor/assets/stylesheets/bootstrap-3.3.1/.bower.json +59 -0
  21. data/vendor/assets/stylesheets/bootstrap-3.3.1/LICENSE +21 -0
  22. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_alerts.scss +14 -0
  23. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_background-variant.scss +11 -0
  24. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_border-radius.scss +18 -0
  25. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_buttons.scss +52 -0
  26. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_center-block.scss +7 -0
  27. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_clearfix.scss +22 -0
  28. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_forms.scss +88 -0
  29. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_gradients.scss +58 -0
  30. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +81 -0
  31. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_grid.scss +122 -0
  32. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_hide-text.scss +21 -0
  33. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_image.scss +33 -0
  34. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_labels.scss +12 -0
  35. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_list-group.scss +31 -0
  36. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +10 -0
  37. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  38. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_opacity.scss +8 -0
  39. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_pagination.scss +23 -0
  40. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_panels.scss +24 -0
  41. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_progress-bar.scss +10 -0
  42. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_reset-filter.scss +8 -0
  43. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_resize.scss +6 -0
  44. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +21 -0
  45. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_size.scss +10 -0
  46. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_tab-focus.scss +9 -0
  47. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_table-row.scss +28 -0
  48. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +11 -0
  49. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_text-overflow.scss +8 -0
  50. data/vendor/assets/stylesheets/bootstrap-3.3.1/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +222 -0
  51. data/vendor/assets/stylesheets/mui/_appbar.scss +72 -0
  52. data/vendor/assets/stylesheets/mui/_buttons.scss +201 -0
  53. data/vendor/assets/stylesheets/mui/_colors.scss +348 -0
  54. data/vendor/assets/stylesheets/mui/_dividers.scss +25 -0
  55. data/vendor/assets/stylesheets/mui/_dropdowns.scss +90 -0
  56. data/vendor/assets/stylesheets/mui/_forms.scss +467 -0
  57. data/vendor/assets/stylesheets/mui/_grid.scss +29 -0
  58. data/vendor/assets/stylesheets/mui/_helpers.scss +284 -0
  59. data/vendor/assets/stylesheets/mui/_layout.scss +21 -0
  60. data/vendor/assets/stylesheets/mui/_mixins.scss +17 -0
  61. data/vendor/assets/stylesheets/mui/_overlay.scss +19 -0
  62. data/vendor/assets/stylesheets/mui/_panel.scss +14 -0
  63. data/vendor/assets/stylesheets/mui/_ripple.scss +55 -0
  64. data/vendor/assets/stylesheets/mui/_scaffolding.scss +110 -0
  65. data/vendor/assets/stylesheets/mui/_semantic-markup.scss +45 -0
  66. data/vendor/assets/stylesheets/mui/_tables.scss +44 -0
  67. data/vendor/assets/stylesheets/mui/_tabs.scss +75 -0
  68. data/vendor/assets/stylesheets/mui/_typography.scss +51 -0
  69. data/vendor/assets/stylesheets/mui/_variables.scss +256 -0
  70. data/vendor/assets/stylesheets/mui/mixins/_buttons.scss +58 -0
  71. data/vendor/assets/stylesheets/mui/mixins/_grid-framework.scss +61 -0
  72. data/vendor/assets/stylesheets/mui/mixins/_typography.scss +132 -0
  73. data/vendor/assets/stylesheets/mui/mixins/_util.scss +4 -0
  74. data/vendor/assets/stylesheets/mui/normalize-3.0.2.scss +427 -0
  75. metadata +173 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 2fd0efddb4858bf77210c5234be75b7501a53757
4
+ data.tar.gz: f5e4ad14d40016269391859ba7c43526e042a12e
5
+ SHA512:
6
+ metadata.gz: ebb593ac163b5dfb8d8779034a293f0cd1d8ae0e2d97c00be618c0f31a6faa026b7e92fb5e867066125a5ceafd83c54616c0413f6a8d5ea892e60f5f0a9d6ca9
7
+ data.tar.gz: 3a575d3b24fabab3624382463a7774bca6871d2b9fd1c598cb7664d5727a9991a15200ccbca6e956ef29616b9675b7038eda2261454995a10eae97161ea1cd13
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.sass-cache/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/support/dummy_rails_app/log/
10
+ /spec/support/dummy_rails_app/tmp/
11
+ /spec/reports/
12
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.6
7
+ - 2.2.2
8
+
9
+ before_install: gem install bundler
10
+
11
+ sudo: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## 0.1.19 (2015-07-28)
2
+
3
+ - Initial release
4
+
5
+ Framework version: MUI v0.1.19
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mui-sass.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Dmitriy Tarasov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # MUI for Sass
2
+
3
+ `mui-sass` is a Sass-powered version of [MUI framework](https://www.muicss.com/) for your Ruby applications. It works with Ruby on Rails, Compass, Sprockets, etc.
4
+
5
+ ## Installation
6
+
7
+ This package provides MUI framework CSS and JavaScript components. HTML Email, React, WebComponents and Design Files are not included.
8
+
9
+ ## Installation
10
+
11
+ * [Ruby on Rails](#ruby-on-rails)
12
+ * [Compass](#compass)
13
+
14
+ ### Ruby on Rails
15
+
16
+ Add this line to your Rails application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'mui-sass'
20
+ ```
21
+
22
+ And then execute `bundle` command to install.
23
+
24
+ Import `mui` in `app/assets/stylesheets/application.scss`:
25
+
26
+ ```scss
27
+ @import 'mui';
28
+ ```
29
+
30
+ Default Rails installation comes with `.css` file extension for stylesheet assests files, make sure you change it to `.scss` and remove all the `//= require` and `//= require_tree` statements from file.
31
+
32
+ Alternatively, to keep original `application.css` file, you can create `custom.scss` file in same folder and import `mui` there.
33
+
34
+ Require `mui` javascript in `app/assets/javascripts/application.js`:
35
+
36
+ ````
37
+ //= require mui
38
+ ````
39
+
40
+ ### Compass
41
+
42
+ To use Compass extension you'll need to install `mui-sass` gem:
43
+
44
+ ```
45
+ gem install mui-sass
46
+ ```
47
+
48
+ #### Existing Compass project
49
+
50
+ If you have an existing Compass project, open `config.rb` file and require `mui-sass` there:
51
+
52
+ ```ruby
53
+ require 'mui-sass'
54
+ ```
55
+
56
+ Navigate to your project's folder and run command:
57
+
58
+ ```
59
+ compass install mui -r mui-sass
60
+ ```
61
+
62
+ This will create new file `styles.scss`, that imports MUI components.
63
+
64
+ Instead of the install command provided above, you can manually import `mui`:
65
+
66
+ ```
67
+ @import 'mui';
68
+ ```
69
+
70
+ #### New Compass project
71
+
72
+ If you are creating a new Compass project and wish to include `mui-sass` run command:
73
+
74
+ ```
75
+ compass create project-name -r mui-sass --using mui
76
+ ```
77
+
78
+ This command will create a new Compass project with `styles.scss` file, which imports MUI components.
79
+
80
+ ## Usage
81
+
82
+ By default, using `@import 'mui';` and `//= require mui`, all of MUI components are imported.
83
+
84
+ You can import individual `scss` components like this:
85
+
86
+ First you need to include core components:
87
+
88
+ ```scss
89
+ @import 'mui/normalize-3.0.2';
90
+ @import 'mui/colors';
91
+ @import 'mui/variables';
92
+ @import 'mui/mixins';
93
+ ```
94
+
95
+ Then add component:
96
+ ```scss
97
+ @import 'mui/appbar';
98
+ @import 'mui/buttons';
99
+ @import 'mui/dividers';
100
+ @import 'mui/dropdowns';
101
+ @import 'mui/forms';
102
+ @import 'mui/grid';
103
+ @import 'mui/helpers';
104
+ @import 'mui/layout';
105
+ @import 'mui/overlay';
106
+ @import 'mui/panel';
107
+ @import 'mui/ripple';
108
+ @import 'mui/scaffolding';
109
+ @import 'mui/semantic-markup';
110
+ @import 'mui/tables';
111
+ @import 'mui/tabs';
112
+ @import 'mui/typography';
113
+ ```
114
+
115
+ The full set of MUI variables can be found [here](https://github.com/rubysamurai/mui-sass/blob/master/vendor/assets/stylesheets/mui/_variables.scss)
116
+
117
+ ## Contributing
118
+
119
+ Fork the project and submit a pull request.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'mui-sass'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/lib/mui-sass.rb ADDED
@@ -0,0 +1,60 @@
1
+ module Mui
2
+ module Sass
3
+ class << self
4
+ def load!
5
+ if defined?(::Compass::Frameworks)
6
+ register_compass_extension
7
+ elsif defined?(::Rails)
8
+ register_rails_engine
9
+ elsif defined?(::Sprockets)
10
+ register_sprockets
11
+ end
12
+
13
+ configure_sass
14
+ end
15
+
16
+ def gem_path
17
+ @gem_path ||= File.expand_path('..', File.dirname(__FILE__))
18
+ end
19
+
20
+ def stylesheets_path
21
+ File.join(gem_path, 'vendor/assets/stylesheets')
22
+ end
23
+
24
+ def javascripts_path
25
+ File.join(gem_path, 'vendor/assets/javascripts')
26
+ end
27
+
28
+ private
29
+
30
+ def configure_sass
31
+ require 'sass'
32
+
33
+ ::Sass.load_paths << stylesheets_path
34
+ end
35
+
36
+ def register_compass_extension
37
+ require 'mui/sass/version'
38
+
39
+ ::Compass::Frameworks.register(
40
+ 'mui',
41
+ version: Mui::Sass::VERSION,
42
+ path: gem_path,
43
+ stylesheets_directory: stylesheets_path,
44
+ templates_directory: File.join(gem_path, 'templates')
45
+ )
46
+ end
47
+
48
+ def register_rails_engine
49
+ require 'mui/sass/engine'
50
+ end
51
+
52
+ def register_sprockets
53
+ Sprockets.append_path(stylesheets_path)
54
+ Sprockets.append_path(javascripts_path)
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ Mui::Sass.load!
@@ -0,0 +1,13 @@
1
+ module Mui
2
+ module Sass
3
+ module Rails
4
+ class Engine < ::Rails::Engine
5
+ initializer 'mui-sass.assets.precompile' do |app|
6
+ %w(stylesheets javascripts).each do |sub|
7
+ app.config.assets.paths << root.join('vendor/assets', sub).to_s
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module Mui
2
+ module Sass
3
+ VERSION = '0.1.19'
4
+ end
5
+ end
data/mui-sass.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mui/sass/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'mui-sass'
8
+ spec.version = Mui::Sass::VERSION
9
+ spec.authors = ['Dmitriy Tarasov']
10
+ spec.email = ['info@rubysamurai.com']
11
+
12
+ spec.summary = 'MUI framework, powered by Sass and ready to use in Ruby projects'
13
+ spec.description = 'MUI framework, powered by Sass and ready to use in Ruby projects'
14
+ spec.homepage = 'https://github.com/rubysamurai/mui-sass'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.required_ruby_version = '>= 1.9.3'
23
+
24
+ spec.add_runtime_dependency 'sass', '~> 3.3'
25
+
26
+ spec.add_development_dependency 'rspec', '~> 3.3'
27
+ spec.add_development_dependency 'compass', '~> 1.0'
28
+ spec.add_development_dependency 'rails', '~> 4.0'
29
+ end
@@ -0,0 +1,2 @@
1
+ description 'MUI CSS for Sass'
2
+ stylesheet 'styles.sass'
@@ -0,0 +1 @@
1
+ @import 'mui'
@@ -0,0 +1,1593 @@
1
+ (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
+ /**
3
+ * MUI config module
4
+ * @module config
5
+ */
6
+
7
+ /** Define module API */
8
+ module.exports = {
9
+ /** Use debug mode */
10
+ debug: true
11
+ };
12
+
13
+ },{}],2:[function(require,module,exports){
14
+ /**
15
+ * MUI CSS/JS dropdown module
16
+ * @module dropdowns
17
+ */
18
+
19
+ 'use strict';
20
+
21
+
22
+ var jqLite = require('./lib/jqLite.js'),
23
+ util = require('./lib/util.js'),
24
+ attrKey = 'data-mui-toggle',
25
+ attrSelector = '[data-mui-toggle="dropdown"]',
26
+ openClass = 'mui-open',
27
+ menuClass = 'mui-dropdown-menu';
28
+
29
+
30
+ /**
31
+ * Initialize toggle element.
32
+ * @param {Element} toggleEl - The toggle element.
33
+ */
34
+ function initialize(toggleEl) {
35
+ // check flag
36
+ if (toggleEl._muiDropdown === true) return;
37
+ else toggleEl._muiDropdown = true;
38
+
39
+ // attach click handler
40
+ jqLite.on(toggleEl, 'click', clickHandler);
41
+ }
42
+
43
+
44
+ /**
45
+ * Handle click events on dropdown toggle element.
46
+ * @param {Event} ev - The DOM event
47
+ */
48
+ function clickHandler(ev) {
49
+ // only left clicks
50
+ if (ev.button !== 0) return;
51
+
52
+ var toggleEl = this;
53
+
54
+ // exit if toggle button is disabled
55
+ if (toggleEl.getAttribute('disabled') !== null) return;
56
+
57
+ // prevent form submission
58
+ ev.preventDefault();
59
+ ev.stopPropagation();
60
+
61
+ // toggle dropdown
62
+ toggleDropdown(toggleEl);
63
+ }
64
+
65
+
66
+ /**
67
+ * Toggle the dropdown.
68
+ * @param {Element} toggleEl - The dropdown toggle element.
69
+ */
70
+ function toggleDropdown(toggleEl) {
71
+ var wrapperEl = toggleEl.parentNode,
72
+ menuEl = toggleEl.nextElementSibling,
73
+ doc = wrapperEl.ownerDocument;
74
+
75
+ // exit if no menu element
76
+ if (!menuEl || !jqLite.hasClass(menuEl, menuClass)) {
77
+ return util.raiseError('Dropdown menu element not found');
78
+ }
79
+
80
+ // method to close dropdown
81
+ function closeDropdownFn() {
82
+ jqLite.removeClass(menuEl, openClass);
83
+
84
+ // remove event handlers
85
+ jqLite.off(doc, 'click', closeDropdownFn);
86
+ }
87
+
88
+ // method to open dropdown
89
+ function openDropdownFn() {
90
+ // position menu element below toggle button
91
+ var wrapperRect = wrapperEl.getBoundingClientRect(),
92
+ toggleRect = toggleEl.getBoundingClientRect();
93
+
94
+ var top = toggleRect.top - wrapperRect.top + toggleRect.height;
95
+ jqLite.css(menuEl, 'top', top + 'px');
96
+
97
+ // add open class to wrapper
98
+ jqLite.addClass(menuEl, openClass);
99
+
100
+ // close dropdown when user clicks outside of menu
101
+ jqLite.on(doc, 'click', closeDropdownFn);
102
+ }
103
+
104
+ // toggle dropdown
105
+ if (jqLite.hasClass(menuEl, openClass)) closeDropdownFn();
106
+ else openDropdownFn();
107
+ }
108
+
109
+
110
+ /** Define module API */
111
+ module.exports = {
112
+ /** Initialize module listeners */
113
+ initListeners: function() {
114
+ var doc = document;
115
+
116
+ // markup elements available when method is called
117
+ var elList = doc.querySelectorAll(attrSelector);
118
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
119
+
120
+ // listen for new elements
121
+ util.onNodeInserted(function(el) {
122
+ if (el.getAttribute(attrKey) === 'dropdown') initialize(el);
123
+ });
124
+ }
125
+ };
126
+
127
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}],3:[function(require,module,exports){
128
+ /**
129
+ * MUI CSS/JS form-control module
130
+ * @module forms/form-control
131
+ */
132
+
133
+ 'use strict';
134
+
135
+
136
+ var jqLite = require('../lib/jqLite.js'),
137
+ util = require('../lib/util.js'),
138
+ cssSelector = '.mui-form-control',
139
+ emptyClass = 'mui-empty',
140
+ notEmptyClass = 'mui-not-empty',
141
+ dirtyClass = 'mui-dirty',
142
+ formControlClass = 'mui-form-control',
143
+ floatingLabelClass = 'mui-form-floating-label';
144
+
145
+
146
+ /**
147
+ * Initialize input element.
148
+ * @param {Element} inputEl - The input element.
149
+ */
150
+ function initialize(inputEl) {
151
+ // check flag
152
+ if (inputEl._muiFormControl === true) return;
153
+ else inputEl._muiFormControl = true;
154
+
155
+ if (inputEl.value.length) jqLite.addClass(inputEl, notEmptyClass);
156
+ else jqLite.addClass(inputEl, emptyClass);
157
+
158
+ jqLite.on(inputEl, 'input', inputHandler);
159
+
160
+ // add dirty class on focus
161
+ jqLite.on(inputEl, 'focus', function(){jqLite.addClass(this, dirtyClass);});
162
+ }
163
+
164
+
165
+ /**
166
+ * Handle input events.
167
+ */
168
+ function inputHandler() {
169
+ var inputEl = this;
170
+
171
+ if (inputEl.value.length) {
172
+ jqLite.removeClass(inputEl, emptyClass);
173
+ jqLite.addClass(inputEl, notEmptyClass);
174
+ } else {
175
+ jqLite.removeClass(inputEl, notEmptyClass);
176
+ jqLite.addClass(inputEl, emptyClass)
177
+ }
178
+
179
+ jqLite.addClass(inputEl, dirtyClass);
180
+ }
181
+
182
+
183
+ /** Define module API */
184
+ module.exports = {
185
+ /** Initialize input elements */
186
+ initialize: initialize,
187
+
188
+ /** Initialize module listeners */
189
+ initListeners: function() {
190
+ var doc = document;
191
+
192
+ // markup elements available when method is called
193
+ var elList = doc.querySelectorAll(cssSelector);
194
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
195
+
196
+ // listen for new elements
197
+ util.onNodeInserted(function(el) {
198
+ if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') initialize(el);
199
+ });
200
+
201
+ // add transition css for floating labels
202
+ setTimeout(function() {
203
+ var css = '.' + floatingLabelClass + '{' + [
204
+ '-webkit-transition',
205
+ '-moz-transition',
206
+ '-o-transition',
207
+ 'transition',
208
+ ''
209
+ ].join(':all .15s ease-out;') + '}';
210
+
211
+ util.loadStyle(css);
212
+ }, 150);
213
+
214
+ // pointer-events shim for floating labels
215
+ if (util.supportsPointerEvents() === false) {
216
+ jqLite.on(document, 'click', function(ev) {
217
+ var targetEl = ev.target;
218
+
219
+ if (targetEl.tagName === 'LABEL' &&
220
+ jqLite.hasClass(targetEl, floatingLabelClass)) {
221
+ var inputEl = targetEl.previousElementSibling;
222
+ if (jqLite.hasClass(inputEl, formControlClass)) inputEl.focus();
223
+ }
224
+ });
225
+ }
226
+ }
227
+ };
228
+
229
+ },{"../lib/jqLite.js":5,"../lib/util.js":6}],4:[function(require,module,exports){
230
+ /**
231
+ * MUI CSS/JS select module
232
+ * @module forms/select
233
+ */
234
+
235
+ 'use strict';
236
+
237
+
238
+ var jqLite = require('../lib/jqLite.js'),
239
+ util = require('../lib/util.js'),
240
+ wrapperClass = 'mui-select',
241
+ cssSelector = '.mui-select > select',
242
+ menuClass = 'mui-select-menu',
243
+ optionHeight = 42, // from CSS
244
+ menuPadding = 8; // from CSS
245
+
246
+
247
+ /**
248
+ * Initialize select element.
249
+ * @param {Element} selectEl - The select element.
250
+ */
251
+ function initialize(selectEl) {
252
+ // check flag
253
+ if (selectEl._muiSelect === true) return;
254
+ else selectEl._muiSelect = true;
255
+
256
+ // initialize element
257
+ new Select(selectEl);
258
+ }
259
+
260
+
261
+ /**
262
+ * Creates a new Select object
263
+ * @class
264
+ */
265
+ function Select(selectEl) {
266
+ // instance variables
267
+ this.selectEl = selectEl;
268
+ this.wrapperEl = selectEl.parentNode;
269
+ this.useDefault = false;
270
+
271
+ // attach event handlers
272
+ jqLite.on(selectEl, 'touchstart', util.callback(this, 'touchstartHandler'));
273
+ jqLite.on(selectEl, 'mousedown', util.callback(this, 'mousedownHandler'));
274
+ jqLite.on(selectEl, 'focus', util.callback(this, 'focusHandler'));
275
+ jqLite.on(selectEl, 'click', util.callback(this, 'clickHandler'));
276
+
277
+ // make wrapper focusable and fix firefox bug
278
+ this.wrapperEl.tabIndex = -1;
279
+ var callbackFn = util.callback(this, 'wrapperFocusHandler');
280
+ jqLite.on(this.wrapperEl, 'focus', callbackFn);
281
+ }
282
+
283
+
284
+ /**
285
+ * Use default on touch devices.
286
+ */
287
+ Select.prototype.touchstartHandler = function() {
288
+ // set flag
289
+ this.useDefault = true;
290
+ }
291
+
292
+
293
+ /**
294
+ * Disable default dropdown on mousedown.
295
+ * @param {Event} ev - The DOM event
296
+ */
297
+ Select.prototype.mousedownHandler = function(ev) {
298
+ if (ev.button !== 0 || this.useDefault === true) return;
299
+ ev.preventDefault();
300
+ }
301
+
302
+
303
+ /**
304
+ * Handle focus event on select element.
305
+ * @param {Event} ev - The DOM event
306
+ */
307
+ Select.prototype.focusHandler = function(ev) {
308
+ // check flag
309
+ if (this.useDefault === true) return;
310
+
311
+ var selectEl = this.selectEl,
312
+ wrapperEl = this.wrapperEl,
313
+ origIndex = selectEl.tabIndex,
314
+ keydownFn = util.callback(this, 'keydownHandler');
315
+
316
+ // attach keydown handler
317
+ jqLite.on(document, 'keydown', keydownFn);
318
+
319
+ // disable tabfocus once
320
+ selectEl.tabIndex = -1;
321
+ jqLite.one(wrapperEl, 'blur', function() {
322
+ selectEl.tabIndex = origIndex;
323
+ jqLite.off(document, 'keydown', keydownFn);
324
+ });
325
+
326
+ // defer focus to parent
327
+ wrapperEl.focus();
328
+ }
329
+
330
+
331
+ /**
332
+ * Handle keydown events on document
333
+ **/
334
+ Select.prototype.keydownHandler = function(ev) {
335
+ // spacebar, down, up
336
+ if (ev.keyCode === 32 || ev.keyCode === 38 || ev.keyCode === 40) {
337
+ // prevent window scroll
338
+ ev.preventDefault();
339
+
340
+ if (this.selectEl.disabled !== true) this.renderMenu();
341
+ }
342
+ }
343
+
344
+
345
+ /**
346
+ * Handle focus event on wrapper element.
347
+ */
348
+ Select.prototype.wrapperFocusHandler = function() {
349
+ // firefox bugfix
350
+ if (this.selectEl.disabled) return this.wrapperEl.blur();
351
+ }
352
+
353
+
354
+ /**
355
+ * Handle click events on select element.
356
+ * @param {Event} ev - The DOM event
357
+ */
358
+ Select.prototype.clickHandler = function(ev) {
359
+ // only left clicks
360
+ if (ev.button !== 0) return;
361
+ this.renderMenu();
362
+ }
363
+
364
+
365
+ /**
366
+ * Render options dropdown.
367
+ */
368
+ Select.prototype.renderMenu = function() {
369
+ // check and reset flag
370
+ if (this.useDefault === true) return this.useDefault = false;
371
+
372
+ new Menu(this.selectEl);
373
+ }
374
+
375
+
376
+ /**
377
+ * Creates a new Menu
378
+ * @class
379
+ */
380
+ function Menu(selectEl) {
381
+ // instance variables
382
+ this.origIndex = null;
383
+ this.currentIndex = null;
384
+ this.selectEl = selectEl;
385
+ this.menuEl = this._createMenuEl(selectEl);
386
+ this.clickCallbackFn = util.callback(this, 'clickHandler');
387
+ this.keydownCallbackFn = util.callback(this, 'keydownHandler');
388
+ this.destroyCallbackFn = util.callback(this, 'destroy');
389
+
390
+ // add to DOM
391
+ selectEl.parentNode.appendChild(this.menuEl);
392
+
393
+ // blur active element
394
+ setTimeout(function() {
395
+ // ie10 bugfix
396
+ if (document.activeElement.nodeName.toLowerCase() !== "body") {
397
+ document.activeElement.blur();
398
+ }
399
+ }, 0);
400
+
401
+ // attach event handlers
402
+ jqLite.on(this.menuEl, 'click', this.clickCallbackFn);
403
+ jqLite.on(document, 'keydown', this.keydownCallbackFn);
404
+ jqLite.on(window, 'resize', this.destroyCallbackFn);
405
+
406
+ // attach event handler after current event loop exits
407
+ var fn = this.destroyCallbackFn;
408
+ setTimeout(function() {jqLite.on(document, 'click', fn);}, 0);
409
+ }
410
+
411
+
412
+ /**
413
+ * Create menu element
414
+ * @param {Element} selectEl - The select element
415
+ */
416
+ Menu.prototype._createMenuEl = function(selectEl) {
417
+ var optionEl, itemEl, i, minTop, maxTop, top;
418
+
419
+ var menuEl = document.createElement('div'),
420
+ optionList = selectEl.children,
421
+ m = optionList.length,
422
+ selectedPos = 0,
423
+ idealTop = 13;
424
+
425
+
426
+ // create element
427
+ menuEl.className = menuClass;
428
+
429
+ // add options
430
+ for (i=0; i < m; i++) {
431
+ optionEl = optionList[i];
432
+
433
+ itemEl = document.createElement('div');
434
+ itemEl.textContent = optionEl.textContent;
435
+ itemEl._muiPos = i;
436
+
437
+ if (optionEl.selected) selectedPos = i;
438
+
439
+ menuEl.appendChild(itemEl);
440
+ }
441
+
442
+ // add selected attribute
443
+ menuEl.children[selectedPos].setAttribute('selected', true);
444
+
445
+ // save indices
446
+ this.origIndex = selectedPos;
447
+ this.currentIndex = selectedPos;
448
+
449
+ var viewHeight = document.documentElement.clientHeight;
450
+
451
+ // set height (use viewport as maximum height)
452
+ var height = m * optionHeight + 2 * menuPadding;
453
+ height = Math.min(height, viewHeight);
454
+ jqLite.css(menuEl, 'height', height + 'px');
455
+
456
+ // ideal position
457
+ idealTop += selectedPos * optionHeight;
458
+ idealTop = -1 * idealTop;
459
+
460
+ // minimum position
461
+ minTop = -1 * selectEl.getBoundingClientRect().top;
462
+
463
+ // maximium position
464
+ maxTop = (viewHeight - height) + minTop;
465
+
466
+ // prevent overflow-y
467
+ top = Math.max(idealTop, minTop);
468
+ top = Math.min(top, maxTop);
469
+
470
+ jqLite.css(menuEl, 'top', top + 'px');
471
+
472
+ return menuEl;
473
+ }
474
+
475
+
476
+ /**
477
+ * Handle keydown events on document element.
478
+ * @param {Event} ev - The DOM event
479
+ */
480
+ Menu.prototype.keydownHandler = function(ev) {
481
+ var keyCode = ev.keyCode;
482
+
483
+ // tab
484
+ if (keyCode === 9) return this.destroy();
485
+
486
+ // escape | up | down | enter
487
+ if (keyCode === 27 || keyCode === 40 || keyCode === 38 || keyCode === 13) {
488
+ ev.preventDefault();
489
+ }
490
+
491
+ if (keyCode === 27) {
492
+ this.destroy();
493
+ } else if (keyCode === 40) {
494
+ this.increment();
495
+ } else if (keyCode === 38) {
496
+ this.decrement();
497
+ } else if (keyCode === 13) {
498
+ this.selectCurrent();
499
+ this.destroy();
500
+ }
501
+ }
502
+
503
+
504
+ /**
505
+ * Handle click events on menu element.
506
+ * @param {Event} ev - The DOM event
507
+ */
508
+ Menu.prototype.clickHandler = function(ev) {
509
+ // don't allow events to bubble
510
+ ev.stopPropagation();
511
+
512
+ var pos = ev.target._muiPos;
513
+
514
+ // ignore clicks on non-items
515
+ if (pos === undefined) return;
516
+
517
+ // select option
518
+ this.currentIndex = pos;
519
+ this.selectCurrent();
520
+
521
+ // destroy menu
522
+ this.destroy();
523
+ }
524
+
525
+
526
+ /**
527
+ * Increment selected item
528
+ */
529
+ Menu.prototype.increment = function() {
530
+ if (this.currentIndex === this.menuEl.children.length - 1) return;
531
+
532
+ this.menuEl.children[this.currentIndex].removeAttribute('selected');
533
+ this.currentIndex += 1;
534
+ this.menuEl.children[this.currentIndex].setAttribute('selected', true);
535
+ }
536
+
537
+
538
+ /**
539
+ * Decrement selected item
540
+ */
541
+ Menu.prototype.decrement = function() {
542
+ if (this.currentIndex === 0) return;
543
+
544
+ this.menuEl.children[this.currentIndex].removeAttribute('selected');
545
+ this.currentIndex -= 1;
546
+ this.menuEl.children[this.currentIndex].setAttribute('selected', true);
547
+ }
548
+
549
+
550
+ /**
551
+ * Select current item
552
+ */
553
+ Menu.prototype.selectCurrent = function() {
554
+ if (this.currentIndex !== this.origIndex) {
555
+ this.selectEl.children[this.origIndex].selected = false;
556
+ this.selectEl.children[this.currentIndex].selected = true;
557
+
558
+ // trigger change event
559
+ util.dispatchEvent(this.selectEl, 'change');
560
+ }
561
+ }
562
+
563
+
564
+ /**
565
+ * Destroy menu and detach event handlers
566
+ */
567
+ Menu.prototype.destroy = function() {
568
+ // remove element and focus element
569
+ this.menuEl.parentNode.removeChild(this.menuEl);
570
+ this.selectEl.focus();
571
+
572
+ // remove event handlers
573
+ jqLite.off(this.menuEl, 'click', this.clickCallbackFn);
574
+ jqLite.off(document, 'keydown', this.keydownCallbackFn);
575
+ jqLite.off(document, 'click', this.destroyCallbackFn);
576
+ jqLite.off(window, 'resize', this.destroyCallbackFn);
577
+ }
578
+
579
+
580
+ /** Define module API */
581
+ module.exports = {
582
+ /** Initialize module listeners */
583
+ initListeners: function() {
584
+ var doc = document;
585
+
586
+ // markup elements available when method is called
587
+ var elList = doc.querySelectorAll(cssSelector);
588
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
589
+
590
+ // listen for new elements
591
+ util.onNodeInserted(function(el) {
592
+ if (el.tagName === 'SELECT' &&
593
+ jqLite.hasClass(el.parentNode, wrapperClass)) {
594
+ initialize(el);
595
+ }
596
+ });
597
+ }
598
+ };
599
+
600
+ },{"../lib/jqLite.js":5,"../lib/util.js":6}],5:[function(require,module,exports){
601
+ /**
602
+ * MUI CSS/JS jqLite module
603
+ * @module lib/jqLite
604
+ */
605
+
606
+ 'use strict';
607
+
608
+
609
+ /**
610
+ * Add a class to an element.
611
+ * @param {Element} element - The DOM element.
612
+ * @param {string} cssClasses - Space separated list of class names.
613
+ */
614
+ function jqLiteAddClass(element, cssClasses) {
615
+ if (!cssClasses || !element.setAttribute) return;
616
+
617
+ var existingClasses = _getExistingClasses(element),
618
+ splitClasses = cssClasses.split(' '),
619
+ cssClass;
620
+
621
+ for (var i=0; i < splitClasses.length; i++) {
622
+ cssClass = splitClasses[i].trim();
623
+ if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
624
+ existingClasses += cssClass + ' ';
625
+ }
626
+ }
627
+
628
+ element.setAttribute('class', existingClasses.trim());
629
+ }
630
+
631
+
632
+ /**
633
+ * Get or set CSS properties.
634
+ * @param {Element} element - The DOM element.
635
+ * @param {string} [name] - The property name.
636
+ * @param {string} [value] - The property value.
637
+ */
638
+ function jqLiteCss(element, name, value) {
639
+ // Return full style object
640
+ if (name === undefined) {
641
+ return getComputedStyle(element);
642
+ }
643
+
644
+ var nameType = jqLiteType(name);
645
+
646
+ // Set multiple values
647
+ if (nameType === 'object') {
648
+ for (var key in name) element.style[_camelCase(key)] = name[key];
649
+ return;
650
+ }
651
+
652
+ // Set a single value
653
+ if (nameType === 'string' && value !== undefined) {
654
+ element.style[_camelCase(name)] = value;
655
+ }
656
+
657
+ var styleObj = getComputedStyle(element),
658
+ isArray = (jqLiteType(name) === 'array');
659
+
660
+ // Read single value
661
+ if (!isArray) return _getCurrCssProp(element, name, styleObj);
662
+
663
+ // Read multiple values
664
+ var outObj = {},
665
+ key;
666
+
667
+ for (var i=0; i < name.length; i++) {
668
+ key = name[i];
669
+ outObj[key] = _getCurrCssProp(element, key, styleObj);
670
+ }
671
+
672
+ return outObj;
673
+ }
674
+
675
+
676
+ /**
677
+ * Check if element has class.
678
+ * @param {Element} element - The DOM element.
679
+ * @param {string} cls - The class name string.
680
+ */
681
+ function jqLiteHasClass(element, cls) {
682
+ if (!cls || !element.getAttribute) return false;
683
+ return (_getExistingClasses(element).indexOf(' ' + cls + ' ') > -1);
684
+ }
685
+
686
+
687
+ /**
688
+ * Return the type of a variable.
689
+ * @param {} somevar - The JavaScript variable.
690
+ */
691
+ function jqLiteType(somevar) {
692
+ // handle undefined
693
+ if (somevar === undefined) return 'undefined';
694
+
695
+ // handle others (of type [object <Type>])
696
+ var typeStr = Object.prototype.toString.call(somevar);
697
+ if (typeStr.indexOf('[object ') === 0) {
698
+ return typeStr.slice(8, -1).toLowerCase();
699
+ } else {
700
+ throw "Could not understand type: " + typeStr;
701
+ }
702
+ }
703
+
704
+
705
+ /**
706
+ * Attach an event handler to a DOM element
707
+ * @param {Element} element - The DOM element.
708
+ * @param {string} type - The event type name.
709
+ * @param {Function} callback - The callback function.
710
+ * @param {Boolean} useCapture - Use capture flag.
711
+ */
712
+ function jqLiteOn(element, type, callback, useCapture) {
713
+ useCapture = (useCapture === undefined) ? false : useCapture;
714
+
715
+ // add to DOM
716
+ element.addEventListener(type, callback, useCapture);
717
+
718
+ // add to cache
719
+ var cache = element._muiEventCache = element._muiEventCache || {};
720
+ cache[type] = cache[type] || [];
721
+ cache[type].push([callback, useCapture]);
722
+ }
723
+
724
+
725
+ /**
726
+ * Remove an event handler from a DOM element
727
+ * @param {Element} element - The DOM element.
728
+ * @param {string} type - The event type name.
729
+ * @param {Function} callback - The callback function.
730
+ * @param {Boolean} useCapture - Use capture flag.
731
+ */
732
+ function jqLiteOff(element, type, callback, useCapture) {
733
+ useCapture = (useCapture === undefined) ? false : useCapture;
734
+
735
+ // remove from cache
736
+ var cache = element._muiEventCache = element._muiEventCache || {},
737
+ argsList = cache[type] || [],
738
+ args,
739
+ i;
740
+
741
+ i = argsList.length;
742
+ while (i--) {
743
+ args = argsList[i];
744
+
745
+ // remove all events if callback is undefined
746
+ if (callback === undefined ||
747
+ (args[0] === callback && args[1] === useCapture)) {
748
+
749
+ // remove from cache
750
+ argsList.splice(i, 1);
751
+
752
+ // remove from DOM
753
+ element.removeEventListener(type, args[0], args[1]);
754
+ }
755
+ }
756
+ }
757
+
758
+
759
+ /**
760
+ * Attach an event hander which will only execute once
761
+ * @param {Element} element - The DOM element.
762
+ * @param {string} type - The event type name.
763
+ * @param {Function} callback - The callback function.
764
+ * @param {Boolean} useCapture - Use capture flag.
765
+ */
766
+ function jqLiteOne(element, type, callback, useCapture) {
767
+ jqLiteOn(element, type, function onFn(ev) {
768
+ // execute callback
769
+ if (callback) callback.apply(this, arguments);
770
+
771
+ // remove wrapper
772
+ jqLiteOff(element, type, onFn);
773
+ }, useCapture);
774
+ }
775
+
776
+
777
+ /**
778
+ * Return object representing top/left offset and element height/width.
779
+ * @param {Element} element - The DOM element.
780
+ */
781
+ function jqLiteOffset(element) {
782
+ var win = window,
783
+ docEl = document.documentElement,
784
+ rect = element.getBoundingClientRect(),
785
+ viewLeft,
786
+ viewTop;
787
+
788
+ viewLeft = (win.pageXOffset || docEl.scrollLeft) - (docEl.clientLeft || 0);
789
+ viewTop = (win.pageYOffset || docEl.scrollTop) - (docEl.clientTop || 0);
790
+
791
+ return {
792
+ top: rect.top + viewTop,
793
+ left: rect.left + viewLeft,
794
+ height: rect.height,
795
+ width: rect.width
796
+ };
797
+ }
798
+
799
+
800
+ /**
801
+ * Attach a callback to the DOM ready event listener
802
+ * @param {Function} fn - The callback function.
803
+ */
804
+ function jqLiteReady(fn) {
805
+ var done = false,
806
+ top = true,
807
+ doc = document,
808
+ win = doc.defaultView,
809
+ root = doc.documentElement,
810
+ add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
811
+ rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
812
+ pre = doc.addEventListener ? '' : 'on';
813
+
814
+ var init = function(e) {
815
+ if (e.type == 'readystatechange' && doc.readyState != 'complete') {
816
+ return;
817
+ }
818
+
819
+ (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
820
+ if (!done && (done = true)) fn.call(win, e.type || e);
821
+ };
822
+
823
+ var poll = function() {
824
+ try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
825
+ init('poll');
826
+ };
827
+
828
+ if (doc.readyState == 'complete') {
829
+ fn.call(win, 'lazy');
830
+ } else {
831
+ if (doc.createEventObject && root.doScroll) {
832
+ try { top = !win.frameElement; } catch(e) { }
833
+ if (top) poll();
834
+ }
835
+ doc[add](pre + 'DOMContentLoaded', init, false);
836
+ doc[add](pre + 'readystatechange', init, false);
837
+ win[add](pre + 'load', init, false);
838
+ }
839
+ }
840
+
841
+
842
+ /**
843
+ * Remove classes from a DOM element
844
+ * @param {Element} element - The DOM element.
845
+ * @param {string} cssClasses - Space separated list of class names.
846
+ */
847
+ function jqLiteRemoveClass(element, cssClasses) {
848
+ if (!cssClasses || !element.setAttribute) return;
849
+
850
+ var existingClasses = _getExistingClasses(element),
851
+ splitClasses = cssClasses.split(' '),
852
+ cssClass;
853
+
854
+ for (var i=0; i < splitClasses.length; i++) {
855
+ cssClass = splitClasses[i].trim();
856
+ while (existingClasses.indexOf(' ' + cssClass + ' ') >= 0) {
857
+ existingClasses = existingClasses.replace(' ' + cssClass + ' ', ' ');
858
+ }
859
+ }
860
+
861
+ element.setAttribute('class', existingClasses.trim());
862
+ }
863
+
864
+
865
+ // ------------------------------
866
+ // Utilities
867
+ // ------------------------------
868
+ var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g,
869
+ MOZ_HACK_REGEXP = /^moz([A-Z])/,
870
+ ESCAPE_REGEXP = /([.*+?^=!:${}()|\[\]\/\\])/g,
871
+ BOOLEAN_ATTRS;
872
+
873
+
874
+ BOOLEAN_ATTRS = {
875
+ multiple: true,
876
+ selected: true,
877
+ checked: true,
878
+ disabled: true,
879
+ readonly: true,
880
+ required: true,
881
+ open: true
882
+ }
883
+
884
+
885
+ function _getExistingClasses(element) {
886
+ var classes = (element.getAttribute('class') || '').replace(/[\n\t]/g, '');
887
+ return ' ' + classes + ' ';
888
+ }
889
+
890
+
891
+ function _camelCase(name) {
892
+ return name.
893
+ replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
894
+ return offset ? letter.toUpperCase() : letter;
895
+ }).
896
+ replace(MOZ_HACK_REGEXP, 'Moz$1');
897
+ }
898
+
899
+
900
+ function _escapeRegExp(string) {
901
+ return string.replace(ESCAPE_REGEXP, "\\$1");
902
+ }
903
+
904
+
905
+ function _getCurrCssProp(elem, name, computed) {
906
+ var ret;
907
+
908
+ // try computed style
909
+ ret = computed.getPropertyValue(name);
910
+
911
+ // try style attribute (if element is not attached to document)
912
+ if (ret === '' && !elem.ownerDocument) ret = elem.style[_camelCase(name)];
913
+
914
+ return ret;
915
+ }
916
+
917
+
918
+ /**
919
+ * Module API
920
+ */
921
+ module.exports = {
922
+ /** Add classes */
923
+ addClass: jqLiteAddClass,
924
+
925
+ /** Get or set CSS properties */
926
+ css: jqLiteCss,
927
+
928
+ /** Check for class */
929
+ hasClass: jqLiteHasClass,
930
+
931
+ /** Remove event handlers */
932
+ off: jqLiteOff,
933
+
934
+ /** Return offset values */
935
+ offset: jqLiteOffset,
936
+
937
+ /** Add event handlers */
938
+ on: jqLiteOn,
939
+
940
+ /** Add an execute-once event handler */
941
+ one: jqLiteOne,
942
+
943
+ /** DOM ready event handler */
944
+ ready: jqLiteReady,
945
+
946
+ /** Remove classes */
947
+ removeClass: jqLiteRemoveClass,
948
+
949
+ /** Check JavaScript variable instance type */
950
+ type: jqLiteType
951
+ };
952
+
953
+ },{}],6:[function(require,module,exports){
954
+ /**
955
+ * MUI CSS/JS utilities module
956
+ * @module lib/util
957
+ */
958
+
959
+ 'use strict';
960
+
961
+
962
+ var config = require('../config.js'),
963
+ jqLite = require('./jqLite.js'),
964
+ win = window,
965
+ doc = window.document,
966
+ nodeInsertedCallbacks = [],
967
+ head,
968
+ _supportsPointerEvents;
969
+
970
+
971
+ head = doc.head || doc.getElementsByTagName('head')[0] || doc.documentElement;
972
+
973
+
974
+ /**
975
+ * Logging function
976
+ */
977
+ function logFn() {
978
+ if (config.debug && typeof win.console !== "undefined") {
979
+ try {
980
+ win.console.log.apply(win.console, arguments);
981
+ } catch (a) {
982
+ var e = Array.prototype.slice.call(arguments);
983
+ win.console.log(e.join("\n"));
984
+ }
985
+ }
986
+ }
987
+
988
+
989
+ /**
990
+ * Load CSS text in new stylesheet
991
+ * @param {string} cssText - The css text.
992
+ */
993
+ function loadStyleFn(cssText) {
994
+ if (doc.createStyleSheet) {
995
+ doc.createStyleSheet().cssText = cssText;
996
+ } else {
997
+ var e = doc.createElement('style');
998
+ e.type = 'text/css';
999
+
1000
+ if (e.styleSheet) e.styleSheet.cssText = cssText;
1001
+ else e.appendChild(doc.createTextNode(cssText));
1002
+
1003
+ // add to document
1004
+ head.insertBefore(e, head.firstChild);
1005
+ }
1006
+ }
1007
+
1008
+
1009
+ /**
1010
+ * Raise an error
1011
+ * @param {string} msg - The error message.
1012
+ */
1013
+ function raiseErrorFn(msg) {
1014
+ throw "MUI Error: " + msg;
1015
+ }
1016
+
1017
+
1018
+ /**
1019
+ * Register callbacks on muiNodeInserted event
1020
+ * @param {function} callbackFn - The callback function.
1021
+ */
1022
+ function onNodeInsertedFn(callbackFn) {
1023
+ nodeInsertedCallbacks.push(callbackFn);
1024
+
1025
+ // initalize listeners
1026
+ if (nodeInsertedCallbacks._initialized === undefined) {
1027
+ jqLite.on(doc, 'animationstart', animationHandlerFn);
1028
+ jqLite.on(doc, 'mozAnimationStart', animationHandlerFn);
1029
+ jqLite.on(doc, 'webkitAnimationStart', animationHandlerFn);
1030
+
1031
+ nodeInsertedCallbacks._initialized = true;
1032
+ }
1033
+ }
1034
+
1035
+
1036
+ /**
1037
+ * Execute muiNodeInserted callbacks
1038
+ * @param {Event} ev - The DOM event.
1039
+ */
1040
+ function animationHandlerFn(ev) {
1041
+ // check animation name
1042
+ if (ev.animationName !== 'mui-node-inserted') return;
1043
+
1044
+ var el = ev.target;
1045
+
1046
+ // iterate through callbacks
1047
+ for (var i=nodeInsertedCallbacks.length - 1; i >= 0; i--) {
1048
+ nodeInsertedCallbacks[i](el);
1049
+ }
1050
+ }
1051
+
1052
+
1053
+ /**
1054
+ * Convert Classname object, with class as key and true/false as value, to an
1055
+ * class string.
1056
+ * @param {Object} classes The classes
1057
+ * @return {String} class string
1058
+ */
1059
+ function classNamesFn(classes) {
1060
+ var cs = '';
1061
+ for (var i in classes) {
1062
+ cs += (classes[i]) ? i + ' ' : '';
1063
+ }
1064
+ return cs.trim();
1065
+ }
1066
+
1067
+
1068
+ /**
1069
+ * Check if client supports pointer events.
1070
+ */
1071
+ function supportsPointerEventsFn() {
1072
+ // check cache
1073
+ if (_supportsPointerEvents !== undefined) return _supportsPointerEvents;
1074
+
1075
+ var element = document.createElement('x');
1076
+ element.style.cssText = 'pointer-events:auto';
1077
+ _supportsPointerEvents = (element.style.pointerEvents === 'auto');
1078
+ return _supportsPointerEvents;
1079
+ }
1080
+
1081
+
1082
+ /**
1083
+ * Create callback closure.
1084
+ * @param {Object} instance - The object instance.
1085
+ * @param {String} funcName - The name of the callback function.
1086
+ */
1087
+ function callbackFn(instance, funcName) {
1088
+ return function() {instance[funcName].apply(instance, arguments);};
1089
+ }
1090
+
1091
+
1092
+ /**
1093
+ * Dispatch event.
1094
+ * @param {Element} element - The DOM element.
1095
+ * @param {String} eventType - The event type.
1096
+ * @param {Boolean} bubbles=true - If true, event bubbles.
1097
+ * @param {Boolean} cancelable=true = If true, event is cancelable
1098
+ */
1099
+ function dispatchEventFn(element, eventType, bubbles, cancelable) {
1100
+ var ev = document.createEvent('HTMLEvents'),
1101
+ bubbles = (bubbles !== undefined) ? bubbles : true,
1102
+ cancelable = (cancelable !== undefined) ? cancelable : true;
1103
+
1104
+ ev.initEvent(eventType, bubbles, cancelable);
1105
+ element.dispatchEvent(ev);
1106
+ }
1107
+
1108
+
1109
+ /**
1110
+ * Define the module API
1111
+ */
1112
+ module.exports = {
1113
+ /** Create callback closures */
1114
+ callback: callbackFn,
1115
+
1116
+ /** Classnames object to string */
1117
+ classNames: classNamesFn,
1118
+
1119
+ /** Dispatch event */
1120
+ dispatchEvent: dispatchEventFn,
1121
+
1122
+ /** Log messages to the console when debug is turned on */
1123
+ log: logFn,
1124
+
1125
+ /** Load CSS text as new stylesheet */
1126
+ loadStyle: loadStyleFn,
1127
+
1128
+ /** Register muiNodeInserted handler */
1129
+ onNodeInserted: onNodeInsertedFn,
1130
+
1131
+ /** Raise MUI error */
1132
+ raiseError: raiseErrorFn,
1133
+
1134
+ /** Support Pointer Events check */
1135
+ supportsPointerEvents: supportsPointerEventsFn
1136
+ };
1137
+
1138
+ },{"../config.js":1,"./jqLite.js":5}],7:[function(require,module,exports){
1139
+ /**
1140
+ * MUI CSS/JS main module
1141
+ * @module main
1142
+ */
1143
+
1144
+ (function(win) {
1145
+ 'use strict';
1146
+
1147
+ // return if library has been loaded already
1148
+ if (win._muiLoadedJS) return;
1149
+ else win._muiLoadedJS = true;
1150
+
1151
+ // load dependencies
1152
+ var jqLite = require('./lib/jqLite.js'),
1153
+ util = require('./lib/util.js'),
1154
+ formControl = require('./forms/form-control.js'),
1155
+ select = require('./forms/select.js'),
1156
+ ripple = require('./ripple.js'),
1157
+ dropdowns = require('./dropdowns.js'),
1158
+ tabs = require('./tabs.js'),
1159
+ overlay = require('./overlay.js');
1160
+
1161
+ // expose api
1162
+ win.mui = {
1163
+ overlay: overlay,
1164
+ tabs: tabs.api
1165
+ };
1166
+
1167
+ // init libraries
1168
+ jqLite.ready(function() {
1169
+ formControl.initListeners();
1170
+ select.initListeners();
1171
+ ripple.initListeners();
1172
+ dropdowns.initListeners();
1173
+ tabs.initListeners();
1174
+ });
1175
+ })(window);
1176
+
1177
+ },{"./dropdowns.js":2,"./forms/form-control.js":3,"./forms/select.js":4,"./lib/jqLite.js":5,"./lib/util.js":6,"./overlay.js":8,"./ripple.js":9,"./tabs.js":10}],8:[function(require,module,exports){
1178
+ /**
1179
+ * MUI CSS/JS overlay module
1180
+ * @module overlay
1181
+ */
1182
+
1183
+ 'use strict';
1184
+
1185
+
1186
+ var util = require('./lib/util.js'),
1187
+ jqLite = require('./lib/jqLite.js'),
1188
+ bodyClass = 'mui-overlay-on',
1189
+ overlayId = 'mui-overlay',
1190
+ iosRegex = /(iPad|iPhone|iPod)/g;
1191
+
1192
+
1193
+ /**
1194
+ * Turn overlay on/off.
1195
+ * @param {string} action - Turn overlay "on"/"off".
1196
+ * @param {object} [options]
1197
+ * @config {boolean} [keyboard] - If true, close when escape key is pressed.
1198
+ * @config {boolean} [static] - If false, close when backdrop is clicked.
1199
+ * @config {Function} [onclose] - Callback function to execute on close
1200
+ * @param {Element} [childElement] - Child element to add to overlay.
1201
+ */
1202
+ function overlayFn(action) {
1203
+ var overlayEl;
1204
+
1205
+ if (action === 'on') {
1206
+ // extract arguments
1207
+ var arg, options, childElement;
1208
+
1209
+ // pull options and childElement from arguments
1210
+ for (var i=arguments.length - 1; i > 0; i--) {
1211
+ arg = arguments[i];
1212
+
1213
+ if (jqLite.type(arg) === 'object') options = arg;
1214
+ if (arg instanceof Element && arg.nodeType === 1) childElement = arg;
1215
+ }
1216
+
1217
+ // option defaults
1218
+ options = options || {};
1219
+ if (options.keyboard === undefined) options.keyboard = true;
1220
+ if (options.static === undefined) options.static = false;
1221
+
1222
+ // execute method
1223
+ overlayEl = overlayOn(options, childElement);
1224
+
1225
+ } else if (action === 'off') {
1226
+ overlayEl = overlayOff();
1227
+
1228
+ } else {
1229
+ // raise error
1230
+ util.raiseError("Expecting 'on' or 'off'");
1231
+ }
1232
+
1233
+ return overlayEl;
1234
+ }
1235
+
1236
+
1237
+ /**
1238
+ * Turn on overlay.
1239
+ * @param {object} options - Overlay options.
1240
+ * @param {Element} childElement - The child element.
1241
+ */
1242
+ function overlayOn(options, childElement) {
1243
+ var bodyEl = document.body,
1244
+ overlayEl = document.getElementById(overlayId);
1245
+
1246
+ // add overlay
1247
+ jqLite.addClass(bodyEl, bodyClass);
1248
+
1249
+ if (!overlayEl) {
1250
+ // create overlayEl
1251
+ overlayEl = document.createElement('div');
1252
+ overlayEl.setAttribute('id', overlayId);
1253
+
1254
+ // add child element
1255
+ if (childElement) overlayEl.appendChild(childElement);
1256
+
1257
+ bodyEl.appendChild(overlayEl);
1258
+
1259
+ } else {
1260
+ // remove existing children
1261
+ while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
1262
+
1263
+ // add child element
1264
+ if (childElement) overlayEl.appendChild(childElement);
1265
+ }
1266
+
1267
+ // iOS bugfix
1268
+ if (iosRegex.test(navigator.userAgent)) {
1269
+ jqLite.css(overlayEl, 'cursor', 'pointer');
1270
+ }
1271
+
1272
+ // handle options
1273
+ if (options.keyboard) addKeyupHandler();
1274
+ else removeKeyupHandler();
1275
+
1276
+ if (options.static) removeClickHandler(overlayEl);
1277
+ else addClickHandler(overlayEl);
1278
+
1279
+ // attach options
1280
+ overlayEl.muiOptions = options;
1281
+
1282
+ return overlayEl;
1283
+ }
1284
+
1285
+
1286
+ /**
1287
+ * Turn off overlay.
1288
+ */
1289
+ function overlayOff() {
1290
+ var overlayEl = document.getElementById(overlayId),
1291
+ callbackFn;
1292
+
1293
+ if (overlayEl) {
1294
+ // remove children
1295
+ while (overlayEl.firstChild) overlayEl.removeChild(overlayEl.firstChild);
1296
+
1297
+ // remove overlay element
1298
+ overlayEl.parentNode.removeChild(overlayEl);
1299
+
1300
+ // callback reference
1301
+ callbackFn = overlayEl.muiOptions.onclose;
1302
+ }
1303
+
1304
+ jqLite.removeClass(document.body, bodyClass);
1305
+
1306
+ // remove option handlers
1307
+ removeKeyupHandler();
1308
+ removeClickHandler(overlayEl);
1309
+
1310
+ // execute callback
1311
+ if (callbackFn) callbackFn();
1312
+
1313
+ return overlayEl;
1314
+ }
1315
+
1316
+
1317
+ /**
1318
+ * Add keyup handler.
1319
+ */
1320
+ function addKeyupHandler() {
1321
+ jqLite.on(document, 'keyup', onKeyup);
1322
+ }
1323
+
1324
+
1325
+ /**
1326
+ * Remove keyup handler.
1327
+ */
1328
+ function removeKeyupHandler() {
1329
+ jqLite.off(document, 'keyup', onKeyup);
1330
+ }
1331
+
1332
+
1333
+ /**
1334
+ * Teardown overlay when escape key is pressed.
1335
+ */
1336
+ function onKeyup(ev) {
1337
+ if (ev.keyCode === 27) overlayOff();
1338
+ }
1339
+
1340
+
1341
+ /**
1342
+ * Add click handler.
1343
+ */
1344
+ function addClickHandler(overlayEl) {
1345
+ jqLite.on(overlayEl, 'click', onClick);
1346
+ }
1347
+
1348
+
1349
+ /**
1350
+ * Remove click handler.
1351
+ */
1352
+ function removeClickHandler(overlayEl) {
1353
+ jqLite.off(overlayEl, 'click', onClick);
1354
+ }
1355
+
1356
+
1357
+ /**
1358
+ * Teardown overlay when backdrop is clicked.
1359
+ */
1360
+ function onClick(ev) {
1361
+ if (ev.target.id === overlayId) overlayOff();
1362
+ }
1363
+
1364
+
1365
+ /** Define module API */
1366
+ module.exports = overlayFn;
1367
+
1368
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}],9:[function(require,module,exports){
1369
+ /**
1370
+ * MUI CSS/JS ripple module
1371
+ * @module ripple
1372
+ */
1373
+
1374
+ 'use strict';
1375
+
1376
+
1377
+ var jqLite = require('./lib/jqLite.js'),
1378
+ util = require('./lib/util.js'),
1379
+ btnClass = 'mui-btn',
1380
+ btnFlatClass = 'mui-btn-flat',
1381
+ btnFloatingClass = 'mui-btn-floating',
1382
+ rippleClass = 'mui-ripple-effect',
1383
+ animationName = 'mui-btn-inserted';
1384
+
1385
+
1386
+ /**
1387
+ * Add ripple effects to button element.
1388
+ * @param {Element} buttonEl - The button element.
1389
+ */
1390
+ function initialize(buttonEl) {
1391
+ // check flag
1392
+ if (buttonEl._muiRipple === true) return;
1393
+ else buttonEl._muiRipple = true;
1394
+
1395
+ // exit if element is INPUT (doesn't support absolute positioned children)
1396
+ if (buttonEl.tagName === 'INPUT') return;
1397
+
1398
+ // attach event handler
1399
+ jqLite.on(buttonEl, 'touchstart', eventHandler);
1400
+ jqLite.on(buttonEl, 'mousedown', eventHandler);
1401
+ }
1402
+
1403
+
1404
+ /**
1405
+ * Event handler
1406
+ * @param {Event} ev - The DOM event
1407
+ */
1408
+ function eventHandler(ev) {
1409
+ // only left clicks
1410
+ if (ev.button !== 0) return;
1411
+
1412
+ var buttonEl = this;
1413
+
1414
+ // exit if button is disabled
1415
+ if (buttonEl.disabled === true) return;
1416
+
1417
+ // de-dupe touchstart and mousedown with 100msec flag
1418
+ if (buttonEl.touchFlag === true) {
1419
+ return;
1420
+ } else {
1421
+ buttonEl.touchFlag = true;
1422
+ setTimeout(function() {
1423
+ buttonEl.touchFlag = false;
1424
+ }, 100);
1425
+ }
1426
+
1427
+ var rippleEl = document.createElement('div');
1428
+ rippleEl.className = rippleClass;
1429
+
1430
+ var offset = jqLite.offset(buttonEl),
1431
+ xPos = ev.pageX - offset.left,
1432
+ yPos = ev.pageY - offset.top,
1433
+ diameter,
1434
+ radius;
1435
+
1436
+ // get height
1437
+ if (jqLite.hasClass(buttonEl, btnFloatingClass)) {
1438
+ diameter = offset.height / 2;
1439
+ } else {
1440
+ diameter = offset.height;
1441
+ }
1442
+
1443
+ radius = diameter / 2;
1444
+
1445
+ jqLite.css(rippleEl, {
1446
+ height: diameter + 'px',
1447
+ width: diameter + 'px',
1448
+ top: yPos - radius + 'px',
1449
+ left: xPos - radius + 'px'
1450
+ });
1451
+
1452
+ buttonEl.appendChild(rippleEl);
1453
+
1454
+ window.setTimeout(function() {
1455
+ buttonEl.removeChild(rippleEl);
1456
+ }, 2000);
1457
+ }
1458
+
1459
+
1460
+ /** Define module API */
1461
+ module.exports = {
1462
+ /** Initialize module listeners */
1463
+ initListeners: function() {
1464
+ var doc = document;
1465
+
1466
+ // markup elements available when method is called
1467
+ var elList = doc.getElementsByClassName(btnClass);
1468
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1469
+
1470
+ // listen for new elements
1471
+ util.onNodeInserted(function(el) {
1472
+ if (jqLite.hasClass(el, btnClass)) initialize(el);
1473
+ });
1474
+ }
1475
+ };
1476
+
1477
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}],10:[function(require,module,exports){
1478
+ /**
1479
+ * MUI CSS/JS tabs module
1480
+ * @module tabs
1481
+ */
1482
+
1483
+ 'use strict';
1484
+
1485
+
1486
+ var jqLite = require('./lib/jqLite.js'),
1487
+ util = require('./lib/util.js'),
1488
+ attrKey = 'data-mui-toggle',
1489
+ attrSelector = '[' + attrKey + '="tab"]',
1490
+ controlsAttrKey = 'data-mui-controls',
1491
+ activeClass = 'mui-active';
1492
+
1493
+
1494
+ /**
1495
+ * Initialize the toggle element
1496
+ * @param {Element} toggleEl - The toggle element.
1497
+ */
1498
+ function initialize(toggleEl) {
1499
+ // check flag
1500
+ if (toggleEl._muiTabs === true) return;
1501
+ else toggleEl._muiTabs = true;
1502
+
1503
+ // attach click handler
1504
+ jqLite.on(toggleEl, 'click', clickHandler);
1505
+ }
1506
+
1507
+
1508
+ /**
1509
+ * Handle clicks on the toggle element.
1510
+ * @param {Event} ev - The DOM event.
1511
+ */
1512
+ function clickHandler(ev) {
1513
+ // only left clicks
1514
+ if (ev.button !== 0) return;
1515
+
1516
+ var toggleEl = this;
1517
+
1518
+ // exit if toggle element is disabled
1519
+ if (toggleEl.getAttribute('disabled') !== null) return;
1520
+
1521
+ // let event bubble before toggling tab
1522
+ setTimeout(function() {
1523
+ if (!ev.defaultPrevented) activateTab(toggleEl);
1524
+ }, 0);
1525
+ }
1526
+
1527
+
1528
+ /**
1529
+ * Activate the tab controlled by the toggle element.
1530
+ * @param {Element} toggleEl - The toggle element.
1531
+ */
1532
+ function activateTab(toggleEl) {
1533
+ var tabEl = toggleEl.parentNode,
1534
+ paneId = toggleEl.getAttribute(controlsAttrKey),
1535
+ paneEl = document.getElementById(paneId),
1536
+ tabs,
1537
+ panes,
1538
+ el,
1539
+ i;
1540
+
1541
+ // raise error if pane doesn't exist
1542
+ if (!paneEl) util.raiseError('Tab pane "' + paneId + '" not found');
1543
+
1544
+ // de-activate tab siblings
1545
+ tabs = tabEl.parentNode.children;
1546
+ for (i=tabs.length - 1; i >= 0; i--) {
1547
+ el = tabs[i];
1548
+ if (el !== tabEl) jqLite.removeClass(el, activeClass);
1549
+ }
1550
+
1551
+ // de-activate pane siblings
1552
+ panes = paneEl.parentNode.children;
1553
+ for (i=panes.length - 1; i >= 0; i--) {
1554
+ el = panes[i];
1555
+ if (el !== paneEl) jqLite.removeClass(el, activeClass);
1556
+ }
1557
+
1558
+ // activate tab and pane
1559
+ jqLite.addClass(tabEl, activeClass);
1560
+ jqLite.addClass(paneEl, activeClass);
1561
+ }
1562
+
1563
+
1564
+ /** Define module API */
1565
+ module.exports = {
1566
+ /** Initialize module listeners */
1567
+ initListeners: function() {
1568
+ // markup elements available when method is called
1569
+ var elList = document.querySelectorAll(attrSelector);
1570
+ for (var i=elList.length - 1; i >= 0; i--) initialize(elList[i]);
1571
+
1572
+ // TODO: listen for new elements
1573
+ util.onNodeInserted(function(el) {
1574
+ if (el.getAttribute(attrKey) === 'tab') initialize(el);
1575
+ });
1576
+ },
1577
+
1578
+ /** External API */
1579
+ api: {
1580
+ activate: function(paneId) {
1581
+ var cssSelector = '[' + controlsAttrKey + '=' + paneId + ']',
1582
+ toggleEl = document.querySelectorAll(cssSelector);
1583
+
1584
+ if (!toggleEl.length) {
1585
+ util.raiseError('Tab control for pane "' + paneId + '" not found');
1586
+ }
1587
+
1588
+ activateTab(toggleEl[0]);
1589
+ }
1590
+ }
1591
+ };
1592
+
1593
+ },{"./lib/jqLite.js":5,"./lib/util.js":6}]},{},[7]);