scaffold_markup 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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 );