scaffold_markup 0.0.1

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 (47) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +4 -0
  3. data/README.md +41 -0
  4. data/Rakefile +2 -0
  5. data/app/helpers/scaffold_markup_helper.rb +15 -0
  6. data/app/views/application/_form.html.haml +5 -0
  7. data/app/views/application/_form_actions.html.haml +3 -0
  8. data/app/views/application/_form_attributes.html.haml +5 -0
  9. data/app/views/application/_index_actions.html.haml +2 -0
  10. data/app/views/application/_index_table.html.haml +3 -0
  11. data/app/views/application/_page_title.html.haml +2 -0
  12. data/app/views/application/_show_actions.html.haml +3 -0
  13. data/app/views/application/_show_attributes.html.haml +2 -0
  14. data/app/views/application/edit.html.haml +3 -0
  15. data/app/views/application/index.html.haml +4 -0
  16. data/app/views/application/new.html.haml +3 -0
  17. data/app/views/application/show.html.haml +7 -0
  18. data/app/views/kaminari/twitter_bootstrap/_first_page.html.haml +15 -0
  19. data/app/views/kaminari/twitter_bootstrap/_gap.html.haml +9 -0
  20. data/app/views/kaminari/twitter_bootstrap/_last_page.html.haml +13 -0
  21. data/app/views/kaminari/twitter_bootstrap/_next_page.html.haml +13 -0
  22. data/app/views/kaminari/twitter_bootstrap/_page.html.haml +15 -0
  23. data/app/views/kaminari/twitter_bootstrap/_paginator.html.haml +20 -0
  24. data/app/views/kaminari/twitter_bootstrap/_prev_page.html.haml +13 -0
  25. data/lib/scaffold_markup.rb +21 -0
  26. data/lib/scaffold_markup/builders/base_builder.rb +22 -0
  27. data/lib/scaffold_markup/builders/form_builder.rb +77 -0
  28. data/lib/scaffold_markup/builders/nav_bar_builder.rb +26 -0
  29. data/lib/scaffold_markup/builders/nav_container_builder.rb +25 -0
  30. data/lib/scaffold_markup/builders/page_builder.rb +63 -0
  31. data/lib/scaffold_markup/controllers/base.rb +70 -0
  32. data/lib/scaffold_markup/engine.rb +4 -0
  33. data/lib/scaffold_markup/extensions/active_model_extension.rb +6 -0
  34. data/lib/scaffold_markup/extensions/active_record_extension.rb +14 -0
  35. data/lib/scaffold_markup/extensions/twitter_bootstrap_markup_extension.rb +5 -0
  36. data/lib/scaffold_markup/helpers/link_button_helper.rb +32 -0
  37. data/lib/scaffold_markup/helpers/table_helper.rb +83 -0
  38. data/lib/scaffold_markup/helpers/url_helper.rb +28 -0
  39. data/lib/scaffold_markup/version.rb +3 -0
  40. data/scaffold_markup.gemspec +26 -0
  41. data/vendor/assets/images/glyphicons-halflings-white.png +0 -0
  42. data/vendor/assets/images/glyphicons-halflings.png +0 -0
  43. data/vendor/assets/javascripts/bootstrap.js +1792 -0
  44. data/vendor/assets/javascripts/jquery.livequery.js +226 -0
  45. data/vendor/assets/stylesheets/bootstrap.css +5580 -0
  46. data/vendor/assets/stylesheets/scaffold_markup.css +24 -0
  47. metadata +146 -0
@@ -0,0 +1,70 @@
1
+ module ScaffoldMarkup
2
+ module Controllers
3
+ module Base
4
+ attr_reader :resource_class
5
+
6
+ def self.included(base)
7
+ base.before_filter :identify_resource
8
+ end
9
+
10
+ def index
11
+ @collection = resource_class.page(params[:page])
12
+ end
13
+
14
+ def show
15
+ @model = resource_class.find(params[:id])
16
+ end
17
+
18
+ def new
19
+ @model = resource_class.new
20
+ end
21
+
22
+ def edit
23
+ @model = resource_class.find(params[:id])
24
+ end
25
+
26
+ def create
27
+ @model = resource_class.new(params[resource_class.model_name.underscore])
28
+ if @model.save
29
+ flash_message = "#{resource_class.model_name.human} successfully created"
30
+ if params[:save_and_new]
31
+ flash[:success] = flash_message
32
+ redirect_to :action => :new
33
+ else
34
+ flash.now[:success] = flash_message
35
+ render :show
36
+ end
37
+ else
38
+ render :new
39
+ end
40
+ end
41
+
42
+ def update
43
+ @model = resource_class.find(params[:id])
44
+ if @model.update_attributes(params[resource_class.model_name.underscore])
45
+ flash.now[:success] = "#{resource_class.model_name.human} successfully updated"
46
+ render :show
47
+ else
48
+ render :edit
49
+ end
50
+ end
51
+
52
+ def destroy
53
+ @model = resource_class.find(params[:id])
54
+ if @model.destroy
55
+ flash[:warning] = "#{resource_class.model_name.human} successfully removed"
56
+ else
57
+ flash[:danger] = "#{resource_class.model_name.human} could not be deleted"
58
+ end
59
+ redirect_to :action => :index
60
+ end
61
+
62
+ private
63
+
64
+ def identify_resource
65
+ @resource_class = params[:controller].classify.constantize
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,4 @@
1
+ module ScaffoldMarkup
2
+ class Engine < ::Rails::Engine #:nodoc:
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ class ActiveModel::Name
2
+ def human_plural
3
+ plural = human(:count => 2)
4
+ human == plural ? human.pluralize : plural
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ class ActiveRecord::Base
2
+ def self.reflected_association(attribute)
3
+ reflections.map { |k, v| v }.select { |e| e.foreign_key == attribute.to_s }.first
4
+ end
5
+
6
+ def self.accessible_attribute_names
7
+ accessible_attributes.to_a.select { |a| a.present? }
8
+ end
9
+
10
+ def self.validates_presence?(attribute)
11
+ validator = validators.select { |v| v.is_a?(ActiveModel::Validations::PresenceValidator) }.first
12
+ validator && (validator.attributes.include?(attribute.to_sym) || validator.attributes.include?(attribute.to_s))
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ class TwitterBootstrapMarkup::Tag
2
+ def html_safe
3
+ to_s.html_safe
4
+ end
5
+ end
@@ -0,0 +1,32 @@
1
+ module ScaffoldMarkup
2
+ module Helpers
3
+ module LinkButtonHelper
4
+ include TwitterBootstrapMarkup
5
+
6
+ def link_button(*args, &block)
7
+ LinkButton.new(*args, &block).html_safe
8
+ end
9
+
10
+ ButtonBase::TYPES.each do |type|
11
+ define_method("link_button_#{type}") do |*args, &block|
12
+ LinkButton.send(type, *args, &block).html_safe
13
+ end
14
+ end
15
+
16
+ ButtonBase::SIZES.each do |size|
17
+ define_method("link_button_#{size}") do |*args, &block|
18
+ LinkButton.send(size, *args, &block).html_safe
19
+ end
20
+ end
21
+
22
+ ButtonBase::TYPES.each do |type|
23
+ ButtonBase::SIZES.each do |size|
24
+ define_method("link_button_#{type}_#{size}") do |*args, &block|
25
+ LinkButton.send("#{type}_#{size}", *args, &block).html_safe
26
+ end
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,83 @@
1
+ module ScaffoldMarkup
2
+ module Helpers
3
+ module TableHelper
4
+ include TwitterBootstrapMarkup
5
+
6
+ def table(collection, attributes, options={})
7
+ _self = self
8
+
9
+ column_names = collection.is_a?(ActiveRecord::Relation) ? attributes.map { |a| collection.klass.human_attribute_name(a) } : attributes
10
+ column_names.insert(0, '') if options[:actions]
11
+
12
+ html = Table.striped.condensed do
13
+ append _self.table_head(column_names)
14
+ append _self.table_body(collection, attributes, options[:actions] || [])
15
+ end.to_s
16
+
17
+ if collection.respond_to?(:current_page)
18
+ html << Tag.new(:div, template.paginate(collection, :theme => 'twitter_bootstrap')).pull_right.to_s
19
+ end
20
+
21
+ html.html_safe
22
+ end
23
+
24
+ def table_head(attribute_names)
25
+ Tag.new(:thead) do
26
+ append do
27
+ Tag.new(:tr) do
28
+ attribute_names.each do |name|
29
+ append Tag.new(:th, name)
30
+ end
31
+ end
32
+ end
33
+ end.html_safe
34
+ end
35
+
36
+ def table_body(collection, attributes, actions=[])
37
+ _self = self
38
+ Tag.new(:tbody) do
39
+ collection.each do |element|
40
+ append do
41
+ Tag.new(:tr) do
42
+ append Tag.new(:td, _self.table_actions(actions, element), :class => 'actions')
43
+ attributes.each do |attribute|
44
+ append Tag.new(:td, element.send(attribute))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end.html_safe
50
+ end
51
+
52
+ def table_actions(actions, element)
53
+ _self = self
54
+ #TODO: DropdownButton tiene que soportar no recibir texto y dejar en blanco por default
55
+ DropdownButton.mini('') do
56
+ actions.each do |action|
57
+ case action
58
+ when :show
59
+ #TODO: El append de DropdownButton tiene que soportar bloques como parametro
60
+ append(Link.new(_self.url.resource(element)) do
61
+ append Icon.new('list')
62
+ append '&nbsp;Show'
63
+ end)
64
+ when :edit
65
+ append(Link.new(_self.url.edit_resource(element)) do
66
+ append Icon.new('pencil')
67
+ append '&nbsp;Edit'
68
+ end)
69
+ when :remove
70
+ append(Link.new(_self.url.resource(element), 'data-confirm' => 'Are you sure?', 'data-method' => :delete) do
71
+ append Icon.new('trash')
72
+ append '&nbsp;Remove'
73
+ end)
74
+ else
75
+ append action
76
+ end
77
+ end
78
+ end.html_safe
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,28 @@
1
+ module ScaffoldMarkup
2
+ module Helpers
3
+ class UrlHelper
4
+ attr_reader :template
5
+
6
+ def initialize(template)
7
+ @template = template
8
+ end
9
+
10
+ def list_resource(model_class)
11
+ template.send "#{model_class.model_name.underscore.pluralize}_path"
12
+ end
13
+
14
+ def resource(model_instance)
15
+ template.send "#{model_instance.class.model_name.underscore}_path", model_instance.id
16
+ end
17
+
18
+ def new_resource(model_class)
19
+ template.send "new_#{model_class.model_name.underscore}_path"
20
+ end
21
+
22
+ def edit_resource(model_instance)
23
+ template.send "edit_#{model_instance.class.model_name.underscore}_path", model_instance.id
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module ScaffoldMarkup
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "scaffold_markup/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "scaffold_markup"
7
+ s.version = ScaffoldMarkup::VERSION
8
+ s.authors = ["Gabriel Naiman"]
9
+ s.email = %w(gabynaiman@gmail.com)
10
+ s.homepage = 'https://github.com/gabynaiman/scaffold_markup'
11
+ s.summary = 'Rails admin scaffolding'
12
+ s.description = 'Rails admin scaffolding'
13
+
14
+ s.rubyforge_project = "scaffold_markup"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency 'twitter_bootstrap_markup'
22
+ s.add_dependency 'kaminari'
23
+ s.add_dependency 'haml-rails'
24
+ s.add_dependency 'activesupport', ['>= 3.0.0']
25
+ s.add_dependency 'actionpack', ['>= 3.0.0']
26
+ end
@@ -0,0 +1,1792 @@
1
+ /* ===================================================
2
+ * bootstrap-transition.js v2.0.2
3
+ * http://twitter.github.com/bootstrap/javascript.html#transitions
4
+ * ===================================================
5
+ * Copyright 2012 Twitter, Inc.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the "License");
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ * ========================================================== */
19
+
20
+ !function( $ ) {
21
+
22
+ $(function () {
23
+
24
+ "use strict"
25
+
26
+ /* CSS TRANSITION SUPPORT (https://gist.github.com/373874)
27
+ * ======================================================= */
28
+
29
+ $.support.transition = (function () {
30
+ var thisBody = document.body || document.documentElement
31
+ , thisStyle = thisBody.style
32
+ , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined
33
+
34
+ return support && {
35
+ end: (function () {
36
+ var transitionEnd = "TransitionEnd"
37
+ if ( $.browser.webkit ) {
38
+ transitionEnd = "webkitTransitionEnd"
39
+ } else if ( $.browser.mozilla ) {
40
+ transitionEnd = "transitionend"
41
+ } else if ( $.browser.opera ) {
42
+ transitionEnd = "oTransitionEnd"
43
+ }
44
+ return transitionEnd
45
+ }())
46
+ }
47
+ })()
48
+
49
+ })
50
+
51
+ }( window.jQuery );
52
+ /* =========================================================
53
+ * bootstrap-modal.js v2.0.2
54
+ * http://twitter.github.com/bootstrap/javascript.html#modals
55
+ * =========================================================
56
+ * Copyright 2012 Twitter, Inc.
57
+ *
58
+ * Licensed under the Apache License, Version 2.0 (the "License");
59
+ * you may not use this file except in compliance with the License.
60
+ * You may obtain a copy of the License at
61
+ *
62
+ * http://www.apache.org/licenses/LICENSE-2.0
63
+ *
64
+ * Unless required by applicable law or agreed to in writing, software
65
+ * distributed under the License is distributed on an "AS IS" BASIS,
66
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67
+ * See the License for the specific language governing permissions and
68
+ * limitations under the License.
69
+ * ========================================================= */
70
+
71
+
72
+ !function( $ ){
73
+
74
+ "use strict"
75
+
76
+ /* MODAL CLASS DEFINITION
77
+ * ====================== */
78
+
79
+ var Modal = function ( content, options ) {
80
+ this.options = options
81
+ this.$element = $(content)
82
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this))
83
+ }
84
+
85
+ Modal.prototype = {
86
+
87
+ constructor: Modal
88
+
89
+ , toggle: function () {
90
+ return this[!this.isShown ? 'show' : 'hide']()
91
+ }
92
+
93
+ , show: function () {
94
+ var that = this
95
+
96
+ if (this.isShown) return
97
+
98
+ $('body').addClass('modal-open')
99
+
100
+ this.isShown = true
101
+ this.$element.trigger('show')
102
+
103
+ escape.call(this)
104
+ backdrop.call(this, function () {
105
+ var transition = $.support.transition && that.$element.hasClass('fade')
106
+
107
+ !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position
108
+
109
+ that.$element
110
+ .show()
111
+
112
+ if (transition) {
113
+ that.$element[0].offsetWidth // force reflow
114
+ }
115
+
116
+ that.$element.addClass('in')
117
+
118
+ transition ?
119
+ that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) :
120
+ that.$element.trigger('shown')
121
+
122
+ })
123
+ }
124
+
125
+ , hide: function ( e ) {
126
+ e && e.preventDefault()
127
+
128
+ if (!this.isShown) return
129
+
130
+ var that = this
131
+ this.isShown = false
132
+
133
+ $('body').removeClass('modal-open')
134
+
135
+ escape.call(this)
136
+
137
+ this.$element
138
+ .trigger('hide')
139
+ .removeClass('in')
140
+
141
+ $.support.transition && this.$element.hasClass('fade') ?
142
+ hideWithTransition.call(this) :
143
+ hideModal.call(this)
144
+ }
145
+
146
+ }
147
+
148
+
149
+ /* MODAL PRIVATE METHODS
150
+ * ===================== */
151
+
152
+ function hideWithTransition() {
153
+ var that = this
154
+ , timeout = setTimeout(function () {
155
+ that.$element.off($.support.transition.end)
156
+ hideModal.call(that)
157
+ }, 500)
158
+
159
+ this.$element.one($.support.transition.end, function () {
160
+ clearTimeout(timeout)
161
+ hideModal.call(that)
162
+ })
163
+ }
164
+
165
+ function hideModal( that ) {
166
+ this.$element
167
+ .hide()
168
+ .trigger('hidden')
169
+
170
+ backdrop.call(this)
171
+ }
172
+
173
+ function backdrop( callback ) {
174
+ var that = this
175
+ , animate = this.$element.hasClass('fade') ? 'fade' : ''
176
+
177
+ if (this.isShown && this.options.backdrop) {
178
+ var doAnimate = $.support.transition && animate
179
+
180
+ this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
181
+ .appendTo(document.body)
182
+
183
+ if (this.options.backdrop != 'static') {
184
+ this.$backdrop.click($.proxy(this.hide, this))
185
+ }
186
+
187
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
188
+
189
+ this.$backdrop.addClass('in')
190
+
191
+ doAnimate ?
192
+ this.$backdrop.one($.support.transition.end, callback) :
193
+ callback()
194
+
195
+ } else if (!this.isShown && this.$backdrop) {
196
+ this.$backdrop.removeClass('in')
197
+
198
+ $.support.transition && this.$element.hasClass('fade')?
199
+ this.$backdrop.one($.support.transition.end, $.proxy(removeBackdrop, this)) :
200
+ removeBackdrop.call(this)
201
+
202
+ } else if (callback) {
203
+ callback()
204
+ }
205
+ }
206
+
207
+ function removeBackdrop() {
208
+ this.$backdrop.remove()
209
+ this.$backdrop = null
210
+ }
211
+
212
+ function escape() {
213
+ var that = this
214
+ if (this.isShown && this.options.keyboard) {
215
+ $(document).on('keyup.dismiss.modal', function ( e ) {
216
+ e.which == 27 && that.hide()
217
+ })
218
+ } else if (!this.isShown) {
219
+ $(document).off('keyup.dismiss.modal')
220
+ }
221
+ }
222
+
223
+
224
+ /* MODAL PLUGIN DEFINITION
225
+ * ======================= */
226
+
227
+ $.fn.modal = function ( option ) {
228
+ return this.each(function () {
229
+ var $this = $(this)
230
+ , data = $this.data('modal')
231
+ , options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option)
232
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
233
+ if (typeof option == 'string') data[option]()
234
+ else if (options.show) data.show()
235
+ })
236
+ }
237
+
238
+ $.fn.modal.defaults = {
239
+ backdrop: true
240
+ , keyboard: true
241
+ , show: true
242
+ }
243
+
244
+ $.fn.modal.Constructor = Modal
245
+
246
+
247
+ /* MODAL DATA-API
248
+ * ============== */
249
+
250
+ $(function () {
251
+ $('body').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
252
+ var $this = $(this), href
253
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
254
+ , option = $target.data('modal') ? 'toggle' : $.extend({}, $target.data(), $this.data())
255
+
256
+ e.preventDefault()
257
+ $target.modal(option)
258
+ })
259
+ })
260
+
261
+ }( window.jQuery );
262
+ /* ============================================================
263
+ * bootstrap-dropdown.js v2.0.2
264
+ * http://twitter.github.com/bootstrap/javascript.html#dropdowns
265
+ * ============================================================
266
+ * Copyright 2012 Twitter, Inc.
267
+ *
268
+ * Licensed under the Apache License, Version 2.0 (the "License");
269
+ * you may not use this file except in compliance with the License.
270
+ * You may obtain a copy of the License at
271
+ *
272
+ * http://www.apache.org/licenses/LICENSE-2.0
273
+ *
274
+ * Unless required by applicable law or agreed to in writing, software
275
+ * distributed under the License is distributed on an "AS IS" BASIS,
276
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
277
+ * See the License for the specific language governing permissions and
278
+ * limitations under the License.
279
+ * ============================================================ */
280
+
281
+
282
+ !function( $ ){
283
+
284
+ "use strict"
285
+
286
+ /* DROPDOWN CLASS DEFINITION
287
+ * ========================= */
288
+
289
+ var toggle = '[data-toggle="dropdown"]'
290
+ , Dropdown = function ( element ) {
291
+ var $el = $(element).on('click.dropdown.data-api', this.toggle)
292
+ $('html').on('click.dropdown.data-api', function () {
293
+ $el.parent().removeClass('open')
294
+ })
295
+ }
296
+
297
+ Dropdown.prototype = {
298
+
299
+ constructor: Dropdown
300
+
301
+ , toggle: function ( e ) {
302
+ var $this = $(this)
303
+ , selector = $this.attr('data-target')
304
+ , $parent
305
+ , isActive
306
+
307
+ if (!selector) {
308
+ selector = $this.attr('href')
309
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
310
+ }
311
+
312
+ $parent = $(selector)
313
+ $parent.length || ($parent = $this.parent())
314
+
315
+ isActive = $parent.hasClass('open')
316
+
317
+ clearMenus()
318
+ !isActive && $parent.toggleClass('open')
319
+
320
+ return false
321
+ }
322
+
323
+ }
324
+
325
+ function clearMenus() {
326
+ $(toggle).parent().removeClass('open')
327
+ }
328
+
329
+
330
+ /* DROPDOWN PLUGIN DEFINITION
331
+ * ========================== */
332
+
333
+ $.fn.dropdown = function ( option ) {
334
+ return this.each(function () {
335
+ var $this = $(this)
336
+ , data = $this.data('dropdown')
337
+ if (!data) $this.data('dropdown', (data = new Dropdown(this)))
338
+ if (typeof option == 'string') data[option].call($this)
339
+ })
340
+ }
341
+
342
+ $.fn.dropdown.Constructor = Dropdown
343
+
344
+
345
+ /* APPLY TO STANDARD DROPDOWN ELEMENTS
346
+ * =================================== */
347
+
348
+ $(function () {
349
+ $('html').on('click.dropdown.data-api', clearMenus)
350
+ $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle)
351
+ })
352
+
353
+ }( window.jQuery );
354
+ /* =============================================================
355
+ * bootstrap-scrollspy.js v2.0.2
356
+ * http://twitter.github.com/bootstrap/javascript.html#scrollspy
357
+ * =============================================================
358
+ * Copyright 2012 Twitter, Inc.
359
+ *
360
+ * Licensed under the Apache License, Version 2.0 (the "License");
361
+ * you may not use this file except in compliance with the License.
362
+ * You may obtain a copy of the License at
363
+ *
364
+ * http://www.apache.org/licenses/LICENSE-2.0
365
+ *
366
+ * Unless required by applicable law or agreed to in writing, software
367
+ * distributed under the License is distributed on an "AS IS" BASIS,
368
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
369
+ * See the License for the specific language governing permissions and
370
+ * limitations under the License.
371
+ * ============================================================== */
372
+
373
+ !function ( $ ) {
374
+
375
+ "use strict"
376
+
377
+ /* SCROLLSPY CLASS DEFINITION
378
+ * ========================== */
379
+
380
+ function ScrollSpy( element, options) {
381
+ var process = $.proxy(this.process, this)
382
+ , $element = $(element).is('body') ? $(window) : $(element)
383
+ , href
384
+ this.options = $.extend({}, $.fn.scrollspy.defaults, options)
385
+ this.$scrollElement = $element.on('scroll.scroll.data-api', process)
386
+ this.selector = (this.options.target
387
+ || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
388
+ || '') + ' .nav li > a'
389
+ this.$body = $('body').on('click.scroll.data-api', this.selector, process)
390
+ this.refresh()
391
+ this.process()
392
+ }
393
+
394
+ ScrollSpy.prototype = {
395
+
396
+ constructor: ScrollSpy
397
+
398
+ , refresh: function () {
399
+ this.targets = this.$body
400
+ .find(this.selector)
401
+ .map(function () {
402
+ var href = $(this).attr('href')
403
+ return /^#\w/.test(href) && $(href).length ? href : null
404
+ })
405
+
406
+ this.offsets = $.map(this.targets, function (id) {
407
+ return $(id).position().top
408
+ })
409
+ }
410
+
411
+ , process: function () {
412
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
413
+ , offsets = this.offsets
414
+ , targets = this.targets
415
+ , activeTarget = this.activeTarget
416
+ , i
417
+
418
+ for (i = offsets.length; i--;) {
419
+ activeTarget != targets[i]
420
+ && scrollTop >= offsets[i]
421
+ && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
422
+ && this.activate( targets[i] )
423
+ }
424
+ }
425
+
426
+ , activate: function (target) {
427
+ var active
428
+
429
+ this.activeTarget = target
430
+
431
+ this.$body
432
+ .find(this.selector).parent('.active')
433
+ .removeClass('active')
434
+
435
+ active = this.$body
436
+ .find(this.selector + '[href="' + target + '"]')
437
+ .parent('li')
438
+ .addClass('active')
439
+
440
+ if ( active.parent('.dropdown-menu') ) {
441
+ active.closest('li.dropdown').addClass('active')
442
+ }
443
+ }
444
+
445
+ }
446
+
447
+
448
+ /* SCROLLSPY PLUGIN DEFINITION
449
+ * =========================== */
450
+
451
+ $.fn.scrollspy = function ( option ) {
452
+ return this.each(function () {
453
+ var $this = $(this)
454
+ , data = $this.data('scrollspy')
455
+ , options = typeof option == 'object' && option
456
+ if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
457
+ if (typeof option == 'string') data[option]()
458
+ })
459
+ }
460
+
461
+ $.fn.scrollspy.Constructor = ScrollSpy
462
+
463
+ $.fn.scrollspy.defaults = {
464
+ offset: 10
465
+ }
466
+
467
+
468
+ /* SCROLLSPY DATA-API
469
+ * ================== */
470
+
471
+ $(function () {
472
+ $('[data-spy="scroll"]').each(function () {
473
+ var $spy = $(this)
474
+ $spy.scrollspy($spy.data())
475
+ })
476
+ })
477
+
478
+ }( window.jQuery );
479
+ /* ========================================================
480
+ * bootstrap-tab.js v2.0.2
481
+ * http://twitter.github.com/bootstrap/javascript.html#tabs
482
+ * ========================================================
483
+ * Copyright 2012 Twitter, Inc.
484
+ *
485
+ * Licensed under the Apache License, Version 2.0 (the "License");
486
+ * you may not use this file except in compliance with the License.
487
+ * You may obtain a copy of the License at
488
+ *
489
+ * http://www.apache.org/licenses/LICENSE-2.0
490
+ *
491
+ * Unless required by applicable law or agreed to in writing, software
492
+ * distributed under the License is distributed on an "AS IS" BASIS,
493
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
494
+ * See the License for the specific language governing permissions and
495
+ * limitations under the License.
496
+ * ======================================================== */
497
+
498
+
499
+ !function( $ ){
500
+
501
+ "use strict"
502
+
503
+ /* TAB CLASS DEFINITION
504
+ * ==================== */
505
+
506
+ var Tab = function ( element ) {
507
+ this.element = $(element)
508
+ }
509
+
510
+ Tab.prototype = {
511
+
512
+ constructor: Tab
513
+
514
+ , show: function () {
515
+ var $this = this.element
516
+ , $ul = $this.closest('ul:not(.dropdown-menu)')
517
+ , selector = $this.attr('data-target')
518
+ , previous
519
+ , $target
520
+
521
+ if (!selector) {
522
+ selector = $this.attr('href')
523
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
524
+ }
525
+
526
+ if ( $this.parent('li').hasClass('active') ) return
527
+
528
+ previous = $ul.find('.active a').last()[0]
529
+
530
+ $this.trigger({
531
+ type: 'show'
532
+ , relatedTarget: previous
533
+ })
534
+
535
+ $target = $(selector)
536
+
537
+ this.activate($this.parent('li'), $ul)
538
+ this.activate($target, $target.parent(), function () {
539
+ $this.trigger({
540
+ type: 'shown'
541
+ , relatedTarget: previous
542
+ })
543
+ })
544
+ }
545
+
546
+ , activate: function ( element, container, callback) {
547
+ var $active = container.find('> .active')
548
+ , transition = callback
549
+ && $.support.transition
550
+ && $active.hasClass('fade')
551
+
552
+ function next() {
553
+ $active
554
+ .removeClass('active')
555
+ .find('> .dropdown-menu > .active')
556
+ .removeClass('active')
557
+
558
+ element.addClass('active')
559
+
560
+ if (transition) {
561
+ element[0].offsetWidth // reflow for transition
562
+ element.addClass('in')
563
+ } else {
564
+ element.removeClass('fade')
565
+ }
566
+
567
+ if ( element.parent('.dropdown-menu') ) {
568
+ element.closest('li.dropdown').addClass('active')
569
+ }
570
+
571
+ callback && callback()
572
+ }
573
+
574
+ transition ?
575
+ $active.one($.support.transition.end, next) :
576
+ next()
577
+
578
+ $active.removeClass('in')
579
+ }
580
+ }
581
+
582
+
583
+ /* TAB PLUGIN DEFINITION
584
+ * ===================== */
585
+
586
+ $.fn.tab = function ( option ) {
587
+ return this.each(function () {
588
+ var $this = $(this)
589
+ , data = $this.data('tab')
590
+ if (!data) $this.data('tab', (data = new Tab(this)))
591
+ if (typeof option == 'string') data[option]()
592
+ })
593
+ }
594
+
595
+ $.fn.tab.Constructor = Tab
596
+
597
+
598
+ /* TAB DATA-API
599
+ * ============ */
600
+
601
+ $(function () {
602
+ $('body').on('click.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
603
+ e.preventDefault()
604
+ $(this).tab('show')
605
+ })
606
+ })
607
+
608
+ }( window.jQuery );
609
+ /* ===========================================================
610
+ * bootstrap-tooltip.js v2.0.2
611
+ * http://twitter.github.com/bootstrap/javascript.html#tooltips
612
+ * Inspired by the original jQuery.tipsy by Jason Frame
613
+ * ===========================================================
614
+ * Copyright 2012 Twitter, Inc.
615
+ *
616
+ * Licensed under the Apache License, Version 2.0 (the "License");
617
+ * you may not use this file except in compliance with the License.
618
+ * You may obtain a copy of the License at
619
+ *
620
+ * http://www.apache.org/licenses/LICENSE-2.0
621
+ *
622
+ * Unless required by applicable law or agreed to in writing, software
623
+ * distributed under the License is distributed on an "AS IS" BASIS,
624
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
625
+ * See the License for the specific language governing permissions and
626
+ * limitations under the License.
627
+ * ========================================================== */
628
+
629
+ !function( $ ) {
630
+
631
+ "use strict"
632
+
633
+ /* TOOLTIP PUBLIC CLASS DEFINITION
634
+ * =============================== */
635
+
636
+ var Tooltip = function ( element, options ) {
637
+ this.init('tooltip', element, options)
638
+ }
639
+
640
+ Tooltip.prototype = {
641
+
642
+ constructor: Tooltip
643
+
644
+ , init: function ( type, element, options ) {
645
+ var eventIn
646
+ , eventOut
647
+
648
+ this.type = type
649
+ this.$element = $(element)
650
+ this.options = this.getOptions(options)
651
+ this.enabled = true
652
+
653
+ if (this.options.trigger != 'manual') {
654
+ eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
655
+ eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
656
+ this.$element.on(eventIn, this.options.selector, $.proxy(this.enter, this))
657
+ this.$element.on(eventOut, this.options.selector, $.proxy(this.leave, this))
658
+ }
659
+
660
+ this.options.selector ?
661
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
662
+ this.fixTitle()
663
+ }
664
+
665
+ , getOptions: function ( options ) {
666
+ options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
667
+
668
+ if (options.delay && typeof options.delay == 'number') {
669
+ options.delay = {
670
+ show: options.delay
671
+ , hide: options.delay
672
+ }
673
+ }
674
+
675
+ return options
676
+ }
677
+
678
+ , enter: function ( e ) {
679
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
680
+
681
+ if (!self.options.delay || !self.options.delay.show) {
682
+ self.show()
683
+ } else {
684
+ self.hoverState = 'in'
685
+ setTimeout(function() {
686
+ if (self.hoverState == 'in') {
687
+ self.show()
688
+ }
689
+ }, self.options.delay.show)
690
+ }
691
+ }
692
+
693
+ , leave: function ( e ) {
694
+ var self = $(e.currentTarget)[this.type](this._options).data(this.type)
695
+
696
+ if (!self.options.delay || !self.options.delay.hide) {
697
+ self.hide()
698
+ } else {
699
+ self.hoverState = 'out'
700
+ setTimeout(function() {
701
+ if (self.hoverState == 'out') {
702
+ self.hide()
703
+ }
704
+ }, self.options.delay.hide)
705
+ }
706
+ }
707
+
708
+ , show: function () {
709
+ var $tip
710
+ , inside
711
+ , pos
712
+ , actualWidth
713
+ , actualHeight
714
+ , placement
715
+ , tp
716
+
717
+ if (this.hasContent() && this.enabled) {
718
+ $tip = this.tip()
719
+ this.setContent()
720
+
721
+ if (this.options.animation) {
722
+ $tip.addClass('fade')
723
+ }
724
+
725
+ placement = typeof this.options.placement == 'function' ?
726
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
727
+ this.options.placement
728
+
729
+ inside = /in/.test(placement)
730
+
731
+ $tip
732
+ .remove()
733
+ .css({ top: 0, left: 0, display: 'block' })
734
+ .appendTo(inside ? this.$element : document.body)
735
+
736
+ pos = this.getPosition(inside)
737
+
738
+ actualWidth = $tip[0].offsetWidth
739
+ actualHeight = $tip[0].offsetHeight
740
+
741
+ switch (inside ? placement.split(' ')[1] : placement) {
742
+ case 'bottom':
743
+ tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
744
+ break
745
+ case 'top':
746
+ tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}
747
+ break
748
+ case 'left':
749
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}
750
+ break
751
+ case 'right':
752
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
753
+ break
754
+ }
755
+
756
+ $tip
757
+ .css(tp)
758
+ .addClass(placement)
759
+ .addClass('in')
760
+ }
761
+ }
762
+
763
+ , setContent: function () {
764
+ var $tip = this.tip()
765
+ $tip.find('.tooltip-inner').html(this.getTitle())
766
+ $tip.removeClass('fade in top bottom left right')
767
+ }
768
+
769
+ , hide: function () {
770
+ var that = this
771
+ , $tip = this.tip()
772
+
773
+ $tip.removeClass('in')
774
+
775
+ function removeWithAnimation() {
776
+ var timeout = setTimeout(function () {
777
+ $tip.off($.support.transition.end).remove()
778
+ }, 500)
779
+
780
+ $tip.one($.support.transition.end, function () {
781
+ clearTimeout(timeout)
782
+ $tip.remove()
783
+ })
784
+ }
785
+
786
+ $.support.transition && this.$tip.hasClass('fade') ?
787
+ removeWithAnimation() :
788
+ $tip.remove()
789
+ }
790
+
791
+ , fixTitle: function () {
792
+ var $e = this.$element
793
+ if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
794
+ $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
795
+ }
796
+ }
797
+
798
+ , hasContent: function () {
799
+ return this.getTitle()
800
+ }
801
+
802
+ , getPosition: function (inside) {
803
+ return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
804
+ width: this.$element[0].offsetWidth
805
+ , height: this.$element[0].offsetHeight
806
+ })
807
+ }
808
+
809
+ , getTitle: function () {
810
+ var title
811
+ , $e = this.$element
812
+ , o = this.options
813
+
814
+ title = $e.attr('data-original-title')
815
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
816
+
817
+ title = (title || '').toString().replace(/(^\s*|\s*$)/, "")
818
+
819
+ return title
820
+ }
821
+
822
+ , tip: function () {
823
+ return this.$tip = this.$tip || $(this.options.template)
824
+ }
825
+
826
+ , validate: function () {
827
+ if (!this.$element[0].parentNode) {
828
+ this.hide()
829
+ this.$element = null
830
+ this.options = null
831
+ }
832
+ }
833
+
834
+ , enable: function () {
835
+ this.enabled = true
836
+ }
837
+
838
+ , disable: function () {
839
+ this.enabled = false
840
+ }
841
+
842
+ , toggleEnabled: function () {
843
+ this.enabled = !this.enabled
844
+ }
845
+
846
+ , toggle: function () {
847
+ this[this.tip().hasClass('in') ? 'hide' : 'show']()
848
+ }
849
+
850
+ }
851
+
852
+
853
+ /* TOOLTIP PLUGIN DEFINITION
854
+ * ========================= */
855
+
856
+ $.fn.tooltip = function ( option ) {
857
+ return this.each(function () {
858
+ var $this = $(this)
859
+ , data = $this.data('tooltip')
860
+ , options = typeof option == 'object' && option
861
+ if (!data) $this.data('tooltip', (data = new Tooltip(this, options)))
862
+ if (typeof option == 'string') data[option]()
863
+ })
864
+ }
865
+
866
+ $.fn.tooltip.Constructor = Tooltip
867
+
868
+ $.fn.tooltip.defaults = {
869
+ animation: true
870
+ , delay: 0
871
+ , selector: false
872
+ , placement: 'top'
873
+ , trigger: 'hover'
874
+ , title: ''
875
+ , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
876
+ }
877
+
878
+ }( window.jQuery );
879
+ /* ===========================================================
880
+ * bootstrap-popover.js v2.0.2
881
+ * http://twitter.github.com/bootstrap/javascript.html#popovers
882
+ * ===========================================================
883
+ * Copyright 2012 Twitter, Inc.
884
+ *
885
+ * Licensed under the Apache License, Version 2.0 (the "License");
886
+ * you may not use this file except in compliance with the License.
887
+ * You may obtain a copy of the License at
888
+ *
889
+ * http://www.apache.org/licenses/LICENSE-2.0
890
+ *
891
+ * Unless required by applicable law or agreed to in writing, software
892
+ * distributed under the License is distributed on an "AS IS" BASIS,
893
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
894
+ * See the License for the specific language governing permissions and
895
+ * limitations under the License.
896
+ * =========================================================== */
897
+
898
+
899
+ !function( $ ) {
900
+
901
+ "use strict"
902
+
903
+ var Popover = function ( element, options ) {
904
+ this.init('popover', element, options)
905
+ }
906
+
907
+ /* NOTE: POPOVER EXTENDS BOOTSTRAP-TOOLTIP.js
908
+ ========================================== */
909
+
910
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {
911
+
912
+ constructor: Popover
913
+
914
+ , setContent: function () {
915
+ var $tip = this.tip()
916
+ , title = this.getTitle()
917
+ , content = this.getContent()
918
+
919
+ $tip.find('.popover-title')[ $.type(title) == 'object' ? 'append' : 'html' ](title)
920
+ $tip.find('.popover-content > *')[ $.type(content) == 'object' ? 'append' : 'html' ](content)
921
+
922
+ $tip.removeClass('fade top bottom left right in')
923
+ }
924
+
925
+ , hasContent: function () {
926
+ return this.getTitle() || this.getContent()
927
+ }
928
+
929
+ , getContent: function () {
930
+ var content
931
+ , $e = this.$element
932
+ , o = this.options
933
+
934
+ content = $e.attr('data-content')
935
+ || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
936
+
937
+ content = content.toString().replace(/(^\s*|\s*$)/, "")
938
+
939
+ return content
940
+ }
941
+
942
+ , tip: function() {
943
+ if (!this.$tip) {
944
+ this.$tip = $(this.options.template)
945
+ }
946
+ return this.$tip
947
+ }
948
+
949
+ })
950
+
951
+
952
+ /* POPOVER PLUGIN DEFINITION
953
+ * ======================= */
954
+
955
+ $.fn.popover = function ( option ) {
956
+ return this.each(function () {
957
+ var $this = $(this)
958
+ , data = $this.data('popover')
959
+ , options = typeof option == 'object' && option
960
+ if (!data) $this.data('popover', (data = new Popover(this, options)))
961
+ if (typeof option == 'string') data[option]()
962
+ })
963
+ }
964
+
965
+ $.fn.popover.Constructor = Popover
966
+
967
+ $.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
968
+ placement: 'right'
969
+ , content: ''
970
+ , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
971
+ })
972
+
973
+ $(document).ready(function() {
974
+ $("[rel=popover]").livequery(function() {
975
+ $(this).popover();
976
+ });
977
+ });
978
+
979
+ }( window.jQuery );
980
+ /* ==========================================================
981
+ * bootstrap-alert.js v2.0.2
982
+ * http://twitter.github.com/bootstrap/javascript.html#alerts
983
+ * ==========================================================
984
+ * Copyright 2012 Twitter, Inc.
985
+ *
986
+ * Licensed under the Apache License, Version 2.0 (the "License");
987
+ * you may not use this file except in compliance with the License.
988
+ * You may obtain a copy of the License at
989
+ *
990
+ * http://www.apache.org/licenses/LICENSE-2.0
991
+ *
992
+ * Unless required by applicable law or agreed to in writing, software
993
+ * distributed under the License is distributed on an "AS IS" BASIS,
994
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
995
+ * See the License for the specific language governing permissions and
996
+ * limitations under the License.
997
+ * ========================================================== */
998
+
999
+
1000
+ !function( $ ){
1001
+
1002
+ "use strict"
1003
+
1004
+ /* ALERT CLASS DEFINITION
1005
+ * ====================== */
1006
+
1007
+ var dismiss = '[data-dismiss="alert"]'
1008
+ , Alert = function ( el ) {
1009
+ $(el).on('click', dismiss, this.close)
1010
+ }
1011
+
1012
+ Alert.prototype = {
1013
+
1014
+ constructor: Alert
1015
+
1016
+ , close: function ( e ) {
1017
+ var $this = $(this)
1018
+ , selector = $this.attr('data-target')
1019
+ , $parent
1020
+
1021
+ if (!selector) {
1022
+ selector = $this.attr('href')
1023
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
1024
+ }
1025
+
1026
+ $parent = $(selector)
1027
+ $parent.trigger('close')
1028
+
1029
+ e && e.preventDefault()
1030
+
1031
+ $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent())
1032
+
1033
+ $parent
1034
+ .trigger('close')
1035
+ .removeClass('in')
1036
+
1037
+ function removeElement() {
1038
+ $parent
1039
+ .trigger('closed')
1040
+ .remove()
1041
+ }
1042
+
1043
+ $.support.transition && $parent.hasClass('fade') ?
1044
+ $parent.on($.support.transition.end, removeElement) :
1045
+ removeElement()
1046
+ }
1047
+
1048
+ }
1049
+
1050
+
1051
+ /* ALERT PLUGIN DEFINITION
1052
+ * ======================= */
1053
+
1054
+ $.fn.alert = function ( option ) {
1055
+ return this.each(function () {
1056
+ var $this = $(this)
1057
+ , data = $this.data('alert')
1058
+ if (!data) $this.data('alert', (data = new Alert(this)))
1059
+ if (typeof option == 'string') data[option].call($this)
1060
+ })
1061
+ }
1062
+
1063
+ $.fn.alert.Constructor = Alert
1064
+
1065
+
1066
+ /* ALERT DATA-API
1067
+ * ============== */
1068
+
1069
+ $(function () {
1070
+ $('body').on('click.alert.data-api', dismiss, Alert.prototype.close)
1071
+ })
1072
+
1073
+ }( window.jQuery );
1074
+ /* ============================================================
1075
+ * bootstrap-button.js v2.0.2
1076
+ * http://twitter.github.com/bootstrap/javascript.html#buttons
1077
+ * ============================================================
1078
+ * Copyright 2012 Twitter, Inc.
1079
+ *
1080
+ * Licensed under the Apache License, Version 2.0 (the "License");
1081
+ * you may not use this file except in compliance with the License.
1082
+ * You may obtain a copy of the License at
1083
+ *
1084
+ * http://www.apache.org/licenses/LICENSE-2.0
1085
+ *
1086
+ * Unless required by applicable law or agreed to in writing, software
1087
+ * distributed under the License is distributed on an "AS IS" BASIS,
1088
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1089
+ * See the License for the specific language governing permissions and
1090
+ * limitations under the License.
1091
+ * ============================================================ */
1092
+
1093
+ !function( $ ){
1094
+
1095
+ "use strict"
1096
+
1097
+ /* BUTTON PUBLIC CLASS DEFINITION
1098
+ * ============================== */
1099
+
1100
+ var Button = function ( element, options ) {
1101
+ this.$element = $(element)
1102
+ this.options = $.extend({}, $.fn.button.defaults, options)
1103
+ }
1104
+
1105
+ Button.prototype = {
1106
+
1107
+ constructor: Button
1108
+
1109
+ , setState: function ( state ) {
1110
+ var d = 'disabled'
1111
+ , $el = this.$element
1112
+ , data = $el.data()
1113
+ , val = $el.is('input') ? 'val' : 'html'
1114
+
1115
+ state = state + 'Text'
1116
+ data.resetText || $el.data('resetText', $el[val]())
1117
+
1118
+ $el[val](data[state] || this.options[state])
1119
+
1120
+ // push to event loop to allow forms to submit
1121
+ setTimeout(function () {
1122
+ state == 'loadingText' ?
1123
+ $el.addClass(d).attr(d, d) :
1124
+ $el.removeClass(d).removeAttr(d)
1125
+ }, 0)
1126
+ }
1127
+
1128
+ , toggle: function () {
1129
+ var $parent = this.$element.parent('[data-toggle="buttons-radio"]')
1130
+
1131
+ $parent && $parent
1132
+ .find('.active')
1133
+ .removeClass('active')
1134
+
1135
+ this.$element.toggleClass('active')
1136
+ }
1137
+
1138
+ }
1139
+
1140
+
1141
+ /* BUTTON PLUGIN DEFINITION
1142
+ * ======================== */
1143
+
1144
+ $.fn.button = function ( option ) {
1145
+ return this.each(function () {
1146
+ var $this = $(this)
1147
+ , data = $this.data('button')
1148
+ , options = typeof option == 'object' && option
1149
+ if (!data) $this.data('button', (data = new Button(this, options)))
1150
+ if (option == 'toggle') data.toggle()
1151
+ else if (option) data.setState(option)
1152
+ })
1153
+ }
1154
+
1155
+ $.fn.button.defaults = {
1156
+ loadingText: 'loading...'
1157
+ }
1158
+
1159
+ $.fn.button.Constructor = Button
1160
+
1161
+
1162
+ /* BUTTON DATA-API
1163
+ * =============== */
1164
+
1165
+ $(function () {
1166
+ $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) {
1167
+ var $btn = $(e.target)
1168
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
1169
+ $btn.button('toggle')
1170
+ })
1171
+ })
1172
+
1173
+ }( window.jQuery );
1174
+ /* =============================================================
1175
+ * bootstrap-collapse.js v2.0.2
1176
+ * http://twitter.github.com/bootstrap/javascript.html#collapse
1177
+ * =============================================================
1178
+ * Copyright 2012 Twitter, Inc.
1179
+ *
1180
+ * Licensed under the Apache License, Version 2.0 (the "License");
1181
+ * you may not use this file except in compliance with the License.
1182
+ * You may obtain a copy of the License at
1183
+ *
1184
+ * http://www.apache.org/licenses/LICENSE-2.0
1185
+ *
1186
+ * Unless required by applicable law or agreed to in writing, software
1187
+ * distributed under the License is distributed on an "AS IS" BASIS,
1188
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1189
+ * See the License for the specific language governing permissions and
1190
+ * limitations under the License.
1191
+ * ============================================================ */
1192
+
1193
+ !function( $ ){
1194
+
1195
+ "use strict"
1196
+
1197
+ var Collapse = function ( element, options ) {
1198
+ this.$element = $(element)
1199
+ this.options = $.extend({}, $.fn.collapse.defaults, options)
1200
+
1201
+ if (this.options["parent"]) {
1202
+ this.$parent = $(this.options["parent"])
1203
+ }
1204
+
1205
+ this.options.toggle && this.toggle()
1206
+ }
1207
+
1208
+ Collapse.prototype = {
1209
+
1210
+ constructor: Collapse
1211
+
1212
+ , dimension: function () {
1213
+ var hasWidth = this.$element.hasClass('width')
1214
+ return hasWidth ? 'width' : 'height'
1215
+ }
1216
+
1217
+ , show: function () {
1218
+ var dimension = this.dimension()
1219
+ , scroll = $.camelCase(['scroll', dimension].join('-'))
1220
+ , actives = this.$parent && this.$parent.find('.in')
1221
+ , hasData
1222
+
1223
+ if (actives && actives.length) {
1224
+ hasData = actives.data('collapse')
1225
+ actives.collapse('hide')
1226
+ hasData || actives.data('collapse', null)
1227
+ }
1228
+
1229
+ this.$element[dimension](0)
1230
+ this.transition('addClass', 'show', 'shown')
1231
+ this.$element[dimension](this.$element[0][scroll])
1232
+
1233
+ }
1234
+
1235
+ , hide: function () {
1236
+ var dimension = this.dimension()
1237
+ this.reset(this.$element[dimension]())
1238
+ this.transition('removeClass', 'hide', 'hidden')
1239
+ this.$element[dimension](0)
1240
+ }
1241
+
1242
+ , reset: function ( size ) {
1243
+ var dimension = this.dimension()
1244
+
1245
+ this.$element
1246
+ .removeClass('collapse')
1247
+ [dimension](size || 'auto')
1248
+ [0].offsetWidth
1249
+
1250
+ this.$element[size ? 'addClass' : 'removeClass']('collapse')
1251
+
1252
+ return this
1253
+ }
1254
+
1255
+ , transition: function ( method, startEvent, completeEvent ) {
1256
+ var that = this
1257
+ , complete = function () {
1258
+ if (startEvent == 'show') that.reset()
1259
+ that.$element.trigger(completeEvent)
1260
+ }
1261
+
1262
+ this.$element
1263
+ .trigger(startEvent)
1264
+ [method]('in')
1265
+
1266
+ $.support.transition && this.$element.hasClass('collapse') ?
1267
+ this.$element.one($.support.transition.end, complete) :
1268
+ complete()
1269
+ }
1270
+
1271
+ , toggle: function () {
1272
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
1273
+ }
1274
+
1275
+ }
1276
+
1277
+ /* COLLAPSIBLE PLUGIN DEFINITION
1278
+ * ============================== */
1279
+
1280
+ $.fn.collapse = function ( option ) {
1281
+ return this.each(function () {
1282
+ var $this = $(this)
1283
+ , data = $this.data('collapse')
1284
+ , options = typeof option == 'object' && option
1285
+ if (!data) $this.data('collapse', (data = new Collapse(this, options)))
1286
+ if (typeof option == 'string') data[option]()
1287
+ })
1288
+ }
1289
+
1290
+ $.fn.collapse.defaults = {
1291
+ toggle: true
1292
+ }
1293
+
1294
+ $.fn.collapse.Constructor = Collapse
1295
+
1296
+
1297
+ /* COLLAPSIBLE DATA-API
1298
+ * ==================== */
1299
+
1300
+ $(function () {
1301
+ $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) {
1302
+ var $this = $(this), href
1303
+ , target = $this.attr('data-target')
1304
+ || e.preventDefault()
1305
+ || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
1306
+ , option = $(target).data('collapse') ? 'toggle' : $this.data()
1307
+ $(target).collapse(option)
1308
+ })
1309
+ })
1310
+
1311
+ }( window.jQuery );
1312
+ /* ==========================================================
1313
+ * bootstrap-carousel.js v2.0.2
1314
+ * http://twitter.github.com/bootstrap/javascript.html#carousel
1315
+ * ==========================================================
1316
+ * Copyright 2012 Twitter, Inc.
1317
+ *
1318
+ * Licensed under the Apache License, Version 2.0 (the "License");
1319
+ * you may not use this file except in compliance with the License.
1320
+ * You may obtain a copy of the License at
1321
+ *
1322
+ * http://www.apache.org/licenses/LICENSE-2.0
1323
+ *
1324
+ * Unless required by applicable law or agreed to in writing, software
1325
+ * distributed under the License is distributed on an "AS IS" BASIS,
1326
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1327
+ * See the License for the specific language governing permissions and
1328
+ * limitations under the License.
1329
+ * ========================================================== */
1330
+
1331
+
1332
+ !function( $ ){
1333
+
1334
+ "use strict"
1335
+
1336
+ /* CAROUSEL CLASS DEFINITION
1337
+ * ========================= */
1338
+
1339
+ var Carousel = function (element, options) {
1340
+ this.$element = $(element)
1341
+ this.options = $.extend({}, $.fn.carousel.defaults, options)
1342
+ this.options.slide && this.slide(this.options.slide)
1343
+ this.options.pause == 'hover' && this.$element
1344
+ .on('mouseenter', $.proxy(this.pause, this))
1345
+ .on('mouseleave', $.proxy(this.cycle, this))
1346
+ }
1347
+
1348
+ Carousel.prototype = {
1349
+
1350
+ cycle: function () {
1351
+ this.interval = setInterval($.proxy(this.next, this), this.options.interval)
1352
+ return this
1353
+ }
1354
+
1355
+ , to: function (pos) {
1356
+ var $active = this.$element.find('.active')
1357
+ , children = $active.parent().children()
1358
+ , activePos = children.index($active)
1359
+ , that = this
1360
+
1361
+ if (pos > (children.length - 1) || pos < 0) return
1362
+
1363
+ if (this.sliding) {
1364
+ return this.$element.one('slid', function () {
1365
+ that.to(pos)
1366
+ })
1367
+ }
1368
+
1369
+ if (activePos == pos) {
1370
+ return this.pause().cycle()
1371
+ }
1372
+
1373
+ return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
1374
+ }
1375
+
1376
+ , pause: function () {
1377
+ clearInterval(this.interval)
1378
+ this.interval = null
1379
+ return this
1380
+ }
1381
+
1382
+ , next: function () {
1383
+ if (this.sliding) return
1384
+ return this.slide('next')
1385
+ }
1386
+
1387
+ , prev: function () {
1388
+ if (this.sliding) return
1389
+ return this.slide('prev')
1390
+ }
1391
+
1392
+ , slide: function (type, next) {
1393
+ var $active = this.$element.find('.active')
1394
+ , $next = next || $active[type]()
1395
+ , isCycling = this.interval
1396
+ , direction = type == 'next' ? 'left' : 'right'
1397
+ , fallback = type == 'next' ? 'first' : 'last'
1398
+ , that = this
1399
+
1400
+ this.sliding = true
1401
+
1402
+ isCycling && this.pause()
1403
+
1404
+ $next = $next.length ? $next : this.$element.find('.item')[fallback]()
1405
+
1406
+ if ($next.hasClass('active')) return
1407
+
1408
+ if (!$.support.transition && this.$element.hasClass('slide')) {
1409
+ this.$element.trigger('slide')
1410
+ $active.removeClass('active')
1411
+ $next.addClass('active')
1412
+ this.sliding = false
1413
+ this.$element.trigger('slid')
1414
+ } else {
1415
+ $next.addClass(type)
1416
+ $next[0].offsetWidth // force reflow
1417
+ $active.addClass(direction)
1418
+ $next.addClass(direction)
1419
+ this.$element.trigger('slide')
1420
+ this.$element.one($.support.transition.end, function () {
1421
+ $next.removeClass([type, direction].join(' ')).addClass('active')
1422
+ $active.removeClass(['active', direction].join(' '))
1423
+ that.sliding = false
1424
+ setTimeout(function () { that.$element.trigger('slid') }, 0)
1425
+ })
1426
+ }
1427
+
1428
+ isCycling && this.cycle()
1429
+
1430
+ return this
1431
+ }
1432
+
1433
+ }
1434
+
1435
+
1436
+ /* CAROUSEL PLUGIN DEFINITION
1437
+ * ========================== */
1438
+
1439
+ $.fn.carousel = function ( option ) {
1440
+ return this.each(function () {
1441
+ var $this = $(this)
1442
+ , data = $this.data('carousel')
1443
+ , options = typeof option == 'object' && option
1444
+ if (!data) $this.data('carousel', (data = new Carousel(this, options)))
1445
+ if (typeof option == 'number') data.to(option)
1446
+ else if (typeof option == 'string' || (option = options.slide)) data[option]()
1447
+ else data.cycle()
1448
+ })
1449
+ }
1450
+
1451
+ $.fn.carousel.defaults = {
1452
+ interval: 5000
1453
+ , pause: 'hover'
1454
+ }
1455
+
1456
+ $.fn.carousel.Constructor = Carousel
1457
+
1458
+
1459
+ /* CAROUSEL DATA-API
1460
+ * ================= */
1461
+
1462
+ $(function () {
1463
+ $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) {
1464
+ var $this = $(this), href
1465
+ , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
1466
+ , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data())
1467
+ $target.carousel(options)
1468
+ e.preventDefault()
1469
+ })
1470
+ })
1471
+
1472
+ }( window.jQuery );
1473
+
1474
+ /* =============================================================
1475
+ * bootstrap-typeahead.js v2.0.0
1476
+ * http://twitter.github.com/bootstrap/javascript.html#typeahead
1477
+ * FORKED: https://gist.github.com/1866577
1478
+ * =============================================================
1479
+ * Copyright 2012 Twitter, Inc.
1480
+ *
1481
+ * Licensed under the Apache License, Version 2.0 (the "License");
1482
+ * you may not use this file except in compliance with the License.
1483
+ * You may obtain a copy of the License at
1484
+ *
1485
+ * http://www.apache.org/licenses/LICENSE-2.0
1486
+ *
1487
+ * Unless required by applicable law or agreed to in writing, software
1488
+ * distributed under the License is distributed on an "AS IS" BASIS,
1489
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1490
+ * See the License for the specific language governing permissions and
1491
+ * limitations under the License.
1492
+ * ============================================================ */
1493
+
1494
+ !function( $ ){
1495
+
1496
+ "use strict"
1497
+
1498
+ var Typeahead = function ( element, options ) {
1499
+ this.$element = $(element)
1500
+ this.options = $.extend({}, $.fn.typeahead.defaults, options)
1501
+ this.assigner = this.options.assigner || this.assigner
1502
+ this.matcher = this.options.matcher || this.matcher
1503
+ this.sorter = this.options.sorter || this.sorter
1504
+ this.highlighter = this.options.highlighter || this.highlighter
1505
+ this.$menu = $(this.options.menu).appendTo('body')
1506
+ this.source = this.options.source
1507
+ this.onselect = this.options.onselect
1508
+ this.strings = true
1509
+ this.shown = false
1510
+ this.listen()
1511
+ }
1512
+
1513
+ Typeahead.prototype = {
1514
+
1515
+ constructor: Typeahead
1516
+
1517
+ , select: function () {
1518
+ var val = JSON.parse(this.$menu.find('.active').attr('data-value'))
1519
+ , text
1520
+
1521
+ if (!this.strings) text = val[this.options.property]
1522
+ else text = val
1523
+
1524
+ this.assigner(text, val)
1525
+
1526
+ if (typeof this.onselect == "function")
1527
+ this.onselect(val)
1528
+
1529
+ return this.hide()
1530
+ }
1531
+
1532
+ , assigner: function(text) {
1533
+ this.$element.val(text)
1534
+ }
1535
+
1536
+ , show: function () {
1537
+ var pos = $.extend({}, this.$element.offset(), {
1538
+ height: this.$element[0].offsetHeight
1539
+ })
1540
+
1541
+ this.$menu.css({
1542
+ top: pos.top + pos.height
1543
+ , left: pos.left
1544
+ })
1545
+
1546
+ this.$menu.show()
1547
+ this.shown = true
1548
+ return this
1549
+ }
1550
+
1551
+ , hide: function () {
1552
+ this.$menu.hide()
1553
+ this.shown = false
1554
+ return this
1555
+ }
1556
+
1557
+ , lookup: function (event) {
1558
+ var that = this
1559
+ , items
1560
+ , q
1561
+ , value
1562
+
1563
+ this.query = this.$element.val()
1564
+
1565
+ if (typeof this.source == "function") {
1566
+ value = this.source(this, this.query, event)
1567
+ if (value) this.process(value)
1568
+ } else {
1569
+ this.process(this.source)
1570
+ }
1571
+ }
1572
+
1573
+ , process: function (results) {
1574
+ var that = this
1575
+ , items
1576
+ , q
1577
+
1578
+ if (results.length && typeof results[0] != "string")
1579
+ this.strings = false
1580
+
1581
+ this.query = this.$element.val()
1582
+
1583
+ if (!this.query) {
1584
+ return this.shown ? this.hide() : this
1585
+ }
1586
+
1587
+ items = $.grep(results, function (item) {
1588
+ if (!that.strings)
1589
+ item = item[that.options.property]
1590
+ if (that.matcher(item)) return item
1591
+ })
1592
+
1593
+ items = this.sorter(items)
1594
+
1595
+ if (!items.length) {
1596
+ return this.shown ? this.hide() : this
1597
+ }
1598
+
1599
+ return this.render(items.slice(0, this.options.items)).show()
1600
+ }
1601
+
1602
+ , matcher: function (item) {
1603
+ return ~item.toLowerCase().indexOf(this.query.toLowerCase())
1604
+ }
1605
+
1606
+ , sorter: function (items) {
1607
+ var beginswith = []
1608
+ , caseSensitive = []
1609
+ , caseInsensitive = []
1610
+ , item
1611
+ , sortby
1612
+
1613
+ while (item = items.shift()) {
1614
+ if (this.strings) sortby = item
1615
+ else sortby = item[this.options.property]
1616
+
1617
+ if (!sortby.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item)
1618
+ else if (~sortby.indexOf(this.query)) caseSensitive.push(item)
1619
+ else caseInsensitive.push(item)
1620
+ }
1621
+
1622
+ return beginswith.concat(caseSensitive, caseInsensitive)
1623
+ }
1624
+
1625
+ , highlighter: function (item) {
1626
+ return item.replace(('(' + this.query + ')').toRegExp('ig'), function ($1, match) {
1627
+ return '<strong>' + match + '</strong>'
1628
+ })
1629
+ }
1630
+
1631
+ , render: function (items) {
1632
+ var that = this
1633
+
1634
+ items = $(items).map(function (i, item) {
1635
+ i = $(that.options.item).attr('data-value', JSON.stringify(item))
1636
+ if (!that.strings)
1637
+ item = item[that.options.property]
1638
+ i.find('a').html(that.highlighter(item))
1639
+ return i[0]
1640
+ })
1641
+
1642
+ items.first().addClass('active')
1643
+ this.$menu.html(items)
1644
+ return this
1645
+ }
1646
+
1647
+ , next: function (event) {
1648
+ var active = this.$menu.find('.active').removeClass('active')
1649
+ , next = active.next()
1650
+
1651
+ if (!next.length) {
1652
+ next = $(this.$menu.find('li')[0])
1653
+ }
1654
+
1655
+ next.addClass('active')
1656
+ }
1657
+
1658
+ , prev: function (event) {
1659
+ var active = this.$menu.find('.active').removeClass('active')
1660
+ , prev = active.prev()
1661
+
1662
+ if (!prev.length) {
1663
+ prev = this.$menu.find('li').last()
1664
+ }
1665
+
1666
+ prev.addClass('active')
1667
+ }
1668
+
1669
+ , listen: function () {
1670
+ this.$element
1671
+ .on('blur', $.proxy(this.blur, this))
1672
+ .on('keypress', $.proxy(this.keypress, this))
1673
+ .on('keyup', $.proxy(this.keyup, this))
1674
+
1675
+ if ($.browser.webkit || $.browser.msie) {
1676
+ this.$element.on('keydown', $.proxy(this.keypress, this))
1677
+ }
1678
+
1679
+ this.$menu
1680
+ .on('click', $.proxy(this.click, this))
1681
+ .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
1682
+ }
1683
+
1684
+ , keyup: function (e) {
1685
+ e.stopPropagation()
1686
+ e.preventDefault()
1687
+
1688
+ switch(e.keyCode) {
1689
+ case 40: // down arrow
1690
+ case 38: // up arrow
1691
+ break
1692
+
1693
+ case 9: // tab
1694
+ case 13: // enter
1695
+ if (!this.shown) return
1696
+ this.select()
1697
+ break
1698
+
1699
+ case 27: // escape
1700
+ this.hide()
1701
+ break
1702
+
1703
+ default:
1704
+ this.lookup(e)
1705
+ }
1706
+
1707
+ }
1708
+
1709
+ , keypress: function (e) {
1710
+ e.stopPropagation()
1711
+ if (!this.shown) return
1712
+
1713
+ switch(e.keyCode) {
1714
+ case 9: // tab
1715
+ case 13: // enter
1716
+ case 27: // escape
1717
+ e.preventDefault()
1718
+ break
1719
+
1720
+ case 38: // up arrow
1721
+ e.preventDefault()
1722
+ this.prev()
1723
+ break
1724
+
1725
+ case 40: // down arrow
1726
+ e.preventDefault()
1727
+ this.next()
1728
+ break
1729
+ }
1730
+ }
1731
+
1732
+ , blur: function (e) {
1733
+ var that = this
1734
+ e.stopPropagation()
1735
+ e.preventDefault()
1736
+ setTimeout(function () { that.hide() }, 150)
1737
+ }
1738
+
1739
+ , click: function (e) {
1740
+ e.stopPropagation()
1741
+ e.preventDefault()
1742
+ this.select()
1743
+ }
1744
+
1745
+ , mouseenter: function (e) {
1746
+ this.$menu.find('.active').removeClass('active')
1747
+ $(e.currentTarget).addClass('active')
1748
+ }
1749
+
1750
+ }
1751
+
1752
+
1753
+ /* TYPEAHEAD PLUGIN DEFINITION
1754
+ * =========================== */
1755
+
1756
+ $.fn.typeahead = function ( option ) {
1757
+ return this.each(function () {
1758
+ var $this = $(this)
1759
+ , data = $this.data('typeahead')
1760
+ , options = typeof option == 'object' && option
1761
+ if (!data) $this.data('typeahead', (data = new Typeahead(this, options)))
1762
+ if (typeof option == 'string') data[option]()
1763
+ //FIX: hide browser default autocomplete
1764
+ $this.attr('autocomplete', 'off')
1765
+ })
1766
+ }
1767
+
1768
+ $.fn.typeahead.defaults = {
1769
+ source: []
1770
+ , items: 8
1771
+ , menu: '<ul class="typeahead dropdown-menu"></ul>'
1772
+ , item: '<li><a href="#"></a></li>'
1773
+ , onselect: null
1774
+ , property: 'value'
1775
+ }
1776
+
1777
+ $.fn.typeahead.Constructor = Typeahead
1778
+
1779
+
1780
+ /* TYPEAHEAD DATA-API
1781
+ * ================== */
1782
+
1783
+ $(function () {
1784
+ $('body').on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
1785
+ var $this = $(this)
1786
+ if ($this.data('typeahead')) return
1787
+ e.preventDefault()
1788
+ $this.typeahead($this.data())
1789
+ })
1790
+ })
1791
+
1792
+ }( window.jQuery );