김재현

Bootstrap 설치

1 var express = require('express'); 1 var express = require('express');
2 +var mysql = require('mysql');
2 var path = require('path'); 3 var path = require('path');
3 var favicon = require('serve-favicon'); 4 var favicon = require('serve-favicon');
4 var logger = require('morgan'); 5 var logger = require('morgan');
...@@ -10,6 +11,12 @@ var index = require('./routes/index'); ...@@ -10,6 +11,12 @@ var index = require('./routes/index');
10 var users = require('./routes/users'); 11 var users = require('./routes/users');
11 12
12 var app = express(); 13 var app = express();
14 +var connection = mysql.createConnection({
15 + host : 'localhost',
16 + user : 'admin',
17 + password : 'admin',
18 + database : 'ossprojectdb'
19 +});
13 20
14 // view engine setup 21 // view engine setup
15 app.set('views', path.join(__dirname, 'views')); 22 app.set('views', path.join(__dirname, 'views'));
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
5 "main": "app.js", 5 "main": "app.js",
6 "private": true, 6 "private": true,
7 "scripts": { 7 "scripts": {
8 - "start": "node ./bin/www", 8 + "start": "nodemon ./bin/www",
9 "test": "echo \"Error: no test specified\" && exit 1" 9 "test": "echo \"Error: no test specified\" && exit 1"
10 }, 10 },
11 "repository": { 11 "repository": {
......
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
No preview for this file type
1 +/*!
2 + * Bootstrap v3.3.2 (http://getbootstrap.com)
3 + * Copyright 2011-2015 Twitter, Inc.
4 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 + */
6 +
7 +if (typeof jQuery === 'undefined') {
8 + throw new Error('Bootstrap\'s JavaScript requires jQuery')
9 +}
10 +
11 ++function ($) {
12 + 'use strict';
13 + var version = $.fn.jquery.split(' ')[0].split('.')
14 + if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
15 + throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
16 + }
17 +}(jQuery);
18 +
19 +/* ========================================================================
20 + * Bootstrap: transition.js v3.3.2
21 + * http://getbootstrap.com/javascript/#transitions
22 + * ========================================================================
23 + * Copyright 2011-2015 Twitter, Inc.
24 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
25 + * ======================================================================== */
26 +
27 +
28 ++function ($) {
29 + 'use strict';
30 +
31 + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
32 + // ============================================================
33 +
34 + function transitionEnd() {
35 + var el = document.createElement('bootstrap')
36 +
37 + var transEndEventNames = {
38 + WebkitTransition : 'webkitTransitionEnd',
39 + MozTransition : 'transitionend',
40 + OTransition : 'oTransitionEnd otransitionend',
41 + transition : 'transitionend'
42 + }
43 +
44 + for (var name in transEndEventNames) {
45 + if (el.style[name] !== undefined) {
46 + return { end: transEndEventNames[name] }
47 + }
48 + }
49 +
50 + return false // explicit for ie8 ( ._.)
51 + }
52 +
53 + // http://blog.alexmaccaw.com/css-transitions
54 + $.fn.emulateTransitionEnd = function (duration) {
55 + var called = false
56 + var $el = this
57 + $(this).one('bsTransitionEnd', function () { called = true })
58 + var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
59 + setTimeout(callback, duration)
60 + return this
61 + }
62 +
63 + $(function () {
64 + $.support.transition = transitionEnd()
65 +
66 + if (!$.support.transition) return
67 +
68 + $.event.special.bsTransitionEnd = {
69 + bindType: $.support.transition.end,
70 + delegateType: $.support.transition.end,
71 + handle: function (e) {
72 + if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
73 + }
74 + }
75 + })
76 +
77 +}(jQuery);
78 +
79 +/* ========================================================================
80 + * Bootstrap: alert.js v3.3.2
81 + * http://getbootstrap.com/javascript/#alerts
82 + * ========================================================================
83 + * Copyright 2011-2015 Twitter, Inc.
84 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
85 + * ======================================================================== */
86 +
87 +
88 ++function ($) {
89 + 'use strict';
90 +
91 + // ALERT CLASS DEFINITION
92 + // ======================
93 +
94 + var dismiss = '[data-dismiss="alert"]'
95 + var Alert = function (el) {
96 + $(el).on('click', dismiss, this.close)
97 + }
98 +
99 + Alert.VERSION = '3.3.2'
100 +
101 + Alert.TRANSITION_DURATION = 150
102 +
103 + Alert.prototype.close = function (e) {
104 + var $this = $(this)
105 + var selector = $this.attr('data-target')
106 +
107 + if (!selector) {
108 + selector = $this.attr('href')
109 + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
110 + }
111 +
112 + var $parent = $(selector)
113 +
114 + if (e) e.preventDefault()
115 +
116 + if (!$parent.length) {
117 + $parent = $this.closest('.alert')
118 + }
119 +
120 + $parent.trigger(e = $.Event('close.bs.alert'))
121 +
122 + if (e.isDefaultPrevented()) return
123 +
124 + $parent.removeClass('in')
125 +
126 + function removeElement() {
127 + // detach from parent, fire event then clean up data
128 + $parent.detach().trigger('closed.bs.alert').remove()
129 + }
130 +
131 + $.support.transition && $parent.hasClass('fade') ?
132 + $parent
133 + .one('bsTransitionEnd', removeElement)
134 + .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
135 + removeElement()
136 + }
137 +
138 +
139 + // ALERT PLUGIN DEFINITION
140 + // =======================
141 +
142 + function Plugin(option) {
143 + return this.each(function () {
144 + var $this = $(this)
145 + var data = $this.data('bs.alert')
146 +
147 + if (!data) $this.data('bs.alert', (data = new Alert(this)))
148 + if (typeof option == 'string') data[option].call($this)
149 + })
150 + }
151 +
152 + var old = $.fn.alert
153 +
154 + $.fn.alert = Plugin
155 + $.fn.alert.Constructor = Alert
156 +
157 +
158 + // ALERT NO CONFLICT
159 + // =================
160 +
161 + $.fn.alert.noConflict = function () {
162 + $.fn.alert = old
163 + return this
164 + }
165 +
166 +
167 + // ALERT DATA-API
168 + // ==============
169 +
170 + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
171 +
172 +}(jQuery);
173 +
174 +/* ========================================================================
175 + * Bootstrap: button.js v3.3.2
176 + * http://getbootstrap.com/javascript/#buttons
177 + * ========================================================================
178 + * Copyright 2011-2015 Twitter, Inc.
179 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
180 + * ======================================================================== */
181 +
182 +
183 ++function ($) {
184 + 'use strict';
185 +
186 + // BUTTON PUBLIC CLASS DEFINITION
187 + // ==============================
188 +
189 + var Button = function (element, options) {
190 + this.$element = $(element)
191 + this.options = $.extend({}, Button.DEFAULTS, options)
192 + this.isLoading = false
193 + }
194 +
195 + Button.VERSION = '3.3.2'
196 +
197 + Button.DEFAULTS = {
198 + loadingText: 'loading...'
199 + }
200 +
201 + Button.prototype.setState = function (state) {
202 + var d = 'disabled'
203 + var $el = this.$element
204 + var val = $el.is('input') ? 'val' : 'html'
205 + var data = $el.data()
206 +
207 + state = state + 'Text'
208 +
209 + if (data.resetText == null) $el.data('resetText', $el[val]())
210 +
211 + // push to event loop to allow forms to submit
212 + setTimeout($.proxy(function () {
213 + $el[val](data[state] == null ? this.options[state] : data[state])
214 +
215 + if (state == 'loadingText') {
216 + this.isLoading = true
217 + $el.addClass(d).attr(d, d)
218 + } else if (this.isLoading) {
219 + this.isLoading = false
220 + $el.removeClass(d).removeAttr(d)
221 + }
222 + }, this), 0)
223 + }
224 +
225 + Button.prototype.toggle = function () {
226 + var changed = true
227 + var $parent = this.$element.closest('[data-toggle="buttons"]')
228 +
229 + if ($parent.length) {
230 + var $input = this.$element.find('input')
231 + if ($input.prop('type') == 'radio') {
232 + if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
233 + else $parent.find('.active').removeClass('active')
234 + }
235 + if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
236 + } else {
237 + this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
238 + }
239 +
240 + if (changed) this.$element.toggleClass('active')
241 + }
242 +
243 +
244 + // BUTTON PLUGIN DEFINITION
245 + // ========================
246 +
247 + function Plugin(option) {
248 + return this.each(function () {
249 + var $this = $(this)
250 + var data = $this.data('bs.button')
251 + var options = typeof option == 'object' && option
252 +
253 + if (!data) $this.data('bs.button', (data = new Button(this, options)))
254 +
255 + if (option == 'toggle') data.toggle()
256 + else if (option) data.setState(option)
257 + })
258 + }
259 +
260 + var old = $.fn.button
261 +
262 + $.fn.button = Plugin
263 + $.fn.button.Constructor = Button
264 +
265 +
266 + // BUTTON NO CONFLICT
267 + // ==================
268 +
269 + $.fn.button.noConflict = function () {
270 + $.fn.button = old
271 + return this
272 + }
273 +
274 +
275 + // BUTTON DATA-API
276 + // ===============
277 +
278 + $(document)
279 + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
280 + var $btn = $(e.target)
281 + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
282 + Plugin.call($btn, 'toggle')
283 + e.preventDefault()
284 + })
285 + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
286 + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
287 + })
288 +
289 +}(jQuery);
290 +
291 +/* ========================================================================
292 + * Bootstrap: carousel.js v3.3.2
293 + * http://getbootstrap.com/javascript/#carousel
294 + * ========================================================================
295 + * Copyright 2011-2015 Twitter, Inc.
296 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
297 + * ======================================================================== */
298 +
299 +
300 ++function ($) {
301 + 'use strict';
302 +
303 + // CAROUSEL CLASS DEFINITION
304 + // =========================
305 +
306 + var Carousel = function (element, options) {
307 + this.$element = $(element)
308 + this.$indicators = this.$element.find('.carousel-indicators')
309 + this.options = options
310 + this.paused =
311 + this.sliding =
312 + this.interval =
313 + this.$active =
314 + this.$items = null
315 +
316 + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
317 +
318 + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
319 + .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
320 + .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
321 + }
322 +
323 + Carousel.VERSION = '3.3.2'
324 +
325 + Carousel.TRANSITION_DURATION = 600
326 +
327 + Carousel.DEFAULTS = {
328 + interval: 5000,
329 + pause: 'hover',
330 + wrap: true,
331 + keyboard: true
332 + }
333 +
334 + Carousel.prototype.keydown = function (e) {
335 + if (/input|textarea/i.test(e.target.tagName)) return
336 + switch (e.which) {
337 + case 37: this.prev(); break
338 + case 39: this.next(); break
339 + default: return
340 + }
341 +
342 + e.preventDefault()
343 + }
344 +
345 + Carousel.prototype.cycle = function (e) {
346 + e || (this.paused = false)
347 +
348 + this.interval && clearInterval(this.interval)
349 +
350 + this.options.interval
351 + && !this.paused
352 + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
353 +
354 + return this
355 + }
356 +
357 + Carousel.prototype.getItemIndex = function (item) {
358 + this.$items = item.parent().children('.item')
359 + return this.$items.index(item || this.$active)
360 + }
361 +
362 + Carousel.prototype.getItemForDirection = function (direction, active) {
363 + var activeIndex = this.getItemIndex(active)
364 + var willWrap = (direction == 'prev' && activeIndex === 0)
365 + || (direction == 'next' && activeIndex == (this.$items.length - 1))
366 + if (willWrap && !this.options.wrap) return active
367 + var delta = direction == 'prev' ? -1 : 1
368 + var itemIndex = (activeIndex + delta) % this.$items.length
369 + return this.$items.eq(itemIndex)
370 + }
371 +
372 + Carousel.prototype.to = function (pos) {
373 + var that = this
374 + var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
375 +
376 + if (pos > (this.$items.length - 1) || pos < 0) return
377 +
378 + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
379 + if (activeIndex == pos) return this.pause().cycle()
380 +
381 + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
382 + }
383 +
384 + Carousel.prototype.pause = function (e) {
385 + e || (this.paused = true)
386 +
387 + if (this.$element.find('.next, .prev').length && $.support.transition) {
388 + this.$element.trigger($.support.transition.end)
389 + this.cycle(true)
390 + }
391 +
392 + this.interval = clearInterval(this.interval)
393 +
394 + return this
395 + }
396 +
397 + Carousel.prototype.next = function () {
398 + if (this.sliding) return
399 + return this.slide('next')
400 + }
401 +
402 + Carousel.prototype.prev = function () {
403 + if (this.sliding) return
404 + return this.slide('prev')
405 + }
406 +
407 + Carousel.prototype.slide = function (type, next) {
408 + var $active = this.$element.find('.item.active')
409 + var $next = next || this.getItemForDirection(type, $active)
410 + var isCycling = this.interval
411 + var direction = type == 'next' ? 'left' : 'right'
412 + var that = this
413 +
414 + if ($next.hasClass('active')) return (this.sliding = false)
415 +
416 + var relatedTarget = $next[0]
417 + var slideEvent = $.Event('slide.bs.carousel', {
418 + relatedTarget: relatedTarget,
419 + direction: direction
420 + })
421 + this.$element.trigger(slideEvent)
422 + if (slideEvent.isDefaultPrevented()) return
423 +
424 + this.sliding = true
425 +
426 + isCycling && this.pause()
427 +
428 + if (this.$indicators.length) {
429 + this.$indicators.find('.active').removeClass('active')
430 + var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
431 + $nextIndicator && $nextIndicator.addClass('active')
432 + }
433 +
434 + var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
435 + if ($.support.transition && this.$element.hasClass('slide')) {
436 + $next.addClass(type)
437 + $next[0].offsetWidth // force reflow
438 + $active.addClass(direction)
439 + $next.addClass(direction)
440 + $active
441 + .one('bsTransitionEnd', function () {
442 + $next.removeClass([type, direction].join(' ')).addClass('active')
443 + $active.removeClass(['active', direction].join(' '))
444 + that.sliding = false
445 + setTimeout(function () {
446 + that.$element.trigger(slidEvent)
447 + }, 0)
448 + })
449 + .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
450 + } else {
451 + $active.removeClass('active')
452 + $next.addClass('active')
453 + this.sliding = false
454 + this.$element.trigger(slidEvent)
455 + }
456 +
457 + isCycling && this.cycle()
458 +
459 + return this
460 + }
461 +
462 +
463 + // CAROUSEL PLUGIN DEFINITION
464 + // ==========================
465 +
466 + function Plugin(option) {
467 + return this.each(function () {
468 + var $this = $(this)
469 + var data = $this.data('bs.carousel')
470 + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
471 + var action = typeof option == 'string' ? option : options.slide
472 +
473 + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
474 + if (typeof option == 'number') data.to(option)
475 + else if (action) data[action]()
476 + else if (options.interval) data.pause().cycle()
477 + })
478 + }
479 +
480 + var old = $.fn.carousel
481 +
482 + $.fn.carousel = Plugin
483 + $.fn.carousel.Constructor = Carousel
484 +
485 +
486 + // CAROUSEL NO CONFLICT
487 + // ====================
488 +
489 + $.fn.carousel.noConflict = function () {
490 + $.fn.carousel = old
491 + return this
492 + }
493 +
494 +
495 + // CAROUSEL DATA-API
496 + // =================
497 +
498 + var clickHandler = function (e) {
499 + var href
500 + var $this = $(this)
501 + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
502 + if (!$target.hasClass('carousel')) return
503 + var options = $.extend({}, $target.data(), $this.data())
504 + var slideIndex = $this.attr('data-slide-to')
505 + if (slideIndex) options.interval = false
506 +
507 + Plugin.call($target, options)
508 +
509 + if (slideIndex) {
510 + $target.data('bs.carousel').to(slideIndex)
511 + }
512 +
513 + e.preventDefault()
514 + }
515 +
516 + $(document)
517 + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
518 + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
519 +
520 + $(window).on('load', function () {
521 + $('[data-ride="carousel"]').each(function () {
522 + var $carousel = $(this)
523 + Plugin.call($carousel, $carousel.data())
524 + })
525 + })
526 +
527 +}(jQuery);
528 +
529 +/* ========================================================================
530 + * Bootstrap: collapse.js v3.3.2
531 + * http://getbootstrap.com/javascript/#collapse
532 + * ========================================================================
533 + * Copyright 2011-2015 Twitter, Inc.
534 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
535 + * ======================================================================== */
536 +
537 +
538 ++function ($) {
539 + 'use strict';
540 +
541 + // COLLAPSE PUBLIC CLASS DEFINITION
542 + // ================================
543 +
544 + var Collapse = function (element, options) {
545 + this.$element = $(element)
546 + this.options = $.extend({}, Collapse.DEFAULTS, options)
547 + this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
548 + this.transitioning = null
549 +
550 + if (this.options.parent) {
551 + this.$parent = this.getParent()
552 + } else {
553 + this.addAriaAndCollapsedClass(this.$element, this.$trigger)
554 + }
555 +
556 + if (this.options.toggle) this.toggle()
557 + }
558 +
559 + Collapse.VERSION = '3.3.2'
560 +
561 + Collapse.TRANSITION_DURATION = 350
562 +
563 + Collapse.DEFAULTS = {
564 + toggle: true,
565 + trigger: '[data-toggle="collapse"]'
566 + }
567 +
568 + Collapse.prototype.dimension = function () {
569 + var hasWidth = this.$element.hasClass('width')
570 + return hasWidth ? 'width' : 'height'
571 + }
572 +
573 + Collapse.prototype.show = function () {
574 + if (this.transitioning || this.$element.hasClass('in')) return
575 +
576 + var activesData
577 + var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
578 +
579 + if (actives && actives.length) {
580 + activesData = actives.data('bs.collapse')
581 + if (activesData && activesData.transitioning) return
582 + }
583 +
584 + var startEvent = $.Event('show.bs.collapse')
585 + this.$element.trigger(startEvent)
586 + if (startEvent.isDefaultPrevented()) return
587 +
588 + if (actives && actives.length) {
589 + Plugin.call(actives, 'hide')
590 + activesData || actives.data('bs.collapse', null)
591 + }
592 +
593 + var dimension = this.dimension()
594 +
595 + this.$element
596 + .removeClass('collapse')
597 + .addClass('collapsing')[dimension](0)
598 + .attr('aria-expanded', true)
599 +
600 + this.$trigger
601 + .removeClass('collapsed')
602 + .attr('aria-expanded', true)
603 +
604 + this.transitioning = 1
605 +
606 + var complete = function () {
607 + this.$element
608 + .removeClass('collapsing')
609 + .addClass('collapse in')[dimension]('')
610 + this.transitioning = 0
611 + this.$element
612 + .trigger('shown.bs.collapse')
613 + }
614 +
615 + if (!$.support.transition) return complete.call(this)
616 +
617 + var scrollSize = $.camelCase(['scroll', dimension].join('-'))
618 +
619 + this.$element
620 + .one('bsTransitionEnd', $.proxy(complete, this))
621 + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
622 + }
623 +
624 + Collapse.prototype.hide = function () {
625 + if (this.transitioning || !this.$element.hasClass('in')) return
626 +
627 + var startEvent = $.Event('hide.bs.collapse')
628 + this.$element.trigger(startEvent)
629 + if (startEvent.isDefaultPrevented()) return
630 +
631 + var dimension = this.dimension()
632 +
633 + this.$element[dimension](this.$element[dimension]())[0].offsetHeight
634 +
635 + this.$element
636 + .addClass('collapsing')
637 + .removeClass('collapse in')
638 + .attr('aria-expanded', false)
639 +
640 + this.$trigger
641 + .addClass('collapsed')
642 + .attr('aria-expanded', false)
643 +
644 + this.transitioning = 1
645 +
646 + var complete = function () {
647 + this.transitioning = 0
648 + this.$element
649 + .removeClass('collapsing')
650 + .addClass('collapse')
651 + .trigger('hidden.bs.collapse')
652 + }
653 +
654 + if (!$.support.transition) return complete.call(this)
655 +
656 + this.$element
657 + [dimension](0)
658 + .one('bsTransitionEnd', $.proxy(complete, this))
659 + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
660 + }
661 +
662 + Collapse.prototype.toggle = function () {
663 + this[this.$element.hasClass('in') ? 'hide' : 'show']()
664 + }
665 +
666 + Collapse.prototype.getParent = function () {
667 + return $(this.options.parent)
668 + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
669 + .each($.proxy(function (i, element) {
670 + var $element = $(element)
671 + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
672 + }, this))
673 + .end()
674 + }
675 +
676 + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
677 + var isOpen = $element.hasClass('in')
678 +
679 + $element.attr('aria-expanded', isOpen)
680 + $trigger
681 + .toggleClass('collapsed', !isOpen)
682 + .attr('aria-expanded', isOpen)
683 + }
684 +
685 + function getTargetFromTrigger($trigger) {
686 + var href
687 + var target = $trigger.attr('data-target')
688 + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
689 +
690 + return $(target)
691 + }
692 +
693 +
694 + // COLLAPSE PLUGIN DEFINITION
695 + // ==========================
696 +
697 + function Plugin(option) {
698 + return this.each(function () {
699 + var $this = $(this)
700 + var data = $this.data('bs.collapse')
701 + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
702 +
703 + if (!data && options.toggle && option == 'show') options.toggle = false
704 + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
705 + if (typeof option == 'string') data[option]()
706 + })
707 + }
708 +
709 + var old = $.fn.collapse
710 +
711 + $.fn.collapse = Plugin
712 + $.fn.collapse.Constructor = Collapse
713 +
714 +
715 + // COLLAPSE NO CONFLICT
716 + // ====================
717 +
718 + $.fn.collapse.noConflict = function () {
719 + $.fn.collapse = old
720 + return this
721 + }
722 +
723 +
724 + // COLLAPSE DATA-API
725 + // =================
726 +
727 + $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
728 + var $this = $(this)
729 +
730 + if (!$this.attr('data-target')) e.preventDefault()
731 +
732 + var $target = getTargetFromTrigger($this)
733 + var data = $target.data('bs.collapse')
734 + var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
735 +
736 + Plugin.call($target, option)
737 + })
738 +
739 +}(jQuery);
740 +
741 +/* ========================================================================
742 + * Bootstrap: dropdown.js v3.3.2
743 + * http://getbootstrap.com/javascript/#dropdowns
744 + * ========================================================================
745 + * Copyright 2011-2015 Twitter, Inc.
746 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
747 + * ======================================================================== */
748 +
749 +
750 ++function ($) {
751 + 'use strict';
752 +
753 + // DROPDOWN CLASS DEFINITION
754 + // =========================
755 +
756 + var backdrop = '.dropdown-backdrop'
757 + var toggle = '[data-toggle="dropdown"]'
758 + var Dropdown = function (element) {
759 + $(element).on('click.bs.dropdown', this.toggle)
760 + }
761 +
762 + Dropdown.VERSION = '3.3.2'
763 +
764 + Dropdown.prototype.toggle = function (e) {
765 + var $this = $(this)
766 +
767 + if ($this.is('.disabled, :disabled')) return
768 +
769 + var $parent = getParent($this)
770 + var isActive = $parent.hasClass('open')
771 +
772 + clearMenus()
773 +
774 + if (!isActive) {
775 + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
776 + // if mobile we use a backdrop because click events don't delegate
777 + $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
778 + }
779 +
780 + var relatedTarget = { relatedTarget: this }
781 + $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
782 +
783 + if (e.isDefaultPrevented()) return
784 +
785 + $this
786 + .trigger('focus')
787 + .attr('aria-expanded', 'true')
788 +
789 + $parent
790 + .toggleClass('open')
791 + .trigger('shown.bs.dropdown', relatedTarget)
792 + }
793 +
794 + return false
795 + }
796 +
797 + Dropdown.prototype.keydown = function (e) {
798 + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
799 +
800 + var $this = $(this)
801 +
802 + e.preventDefault()
803 + e.stopPropagation()
804 +
805 + if ($this.is('.disabled, :disabled')) return
806 +
807 + var $parent = getParent($this)
808 + var isActive = $parent.hasClass('open')
809 +
810 + if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
811 + if (e.which == 27) $parent.find(toggle).trigger('focus')
812 + return $this.trigger('click')
813 + }
814 +
815 + var desc = ' li:not(.divider):visible a'
816 + var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
817 +
818 + if (!$items.length) return
819 +
820 + var index = $items.index(e.target)
821 +
822 + if (e.which == 38 && index > 0) index-- // up
823 + if (e.which == 40 && index < $items.length - 1) index++ // down
824 + if (!~index) index = 0
825 +
826 + $items.eq(index).trigger('focus')
827 + }
828 +
829 + function clearMenus(e) {
830 + if (e && e.which === 3) return
831 + $(backdrop).remove()
832 + $(toggle).each(function () {
833 + var $this = $(this)
834 + var $parent = getParent($this)
835 + var relatedTarget = { relatedTarget: this }
836 +
837 + if (!$parent.hasClass('open')) return
838 +
839 + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
840 +
841 + if (e.isDefaultPrevented()) return
842 +
843 + $this.attr('aria-expanded', 'false')
844 + $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
845 + })
846 + }
847 +
848 + function getParent($this) {
849 + var selector = $this.attr('data-target')
850 +
851 + if (!selector) {
852 + selector = $this.attr('href')
853 + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
854 + }
855 +
856 + var $parent = selector && $(selector)
857 +
858 + return $parent && $parent.length ? $parent : $this.parent()
859 + }
860 +
861 +
862 + // DROPDOWN PLUGIN DEFINITION
863 + // ==========================
864 +
865 + function Plugin(option) {
866 + return this.each(function () {
867 + var $this = $(this)
868 + var data = $this.data('bs.dropdown')
869 +
870 + if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
871 + if (typeof option == 'string') data[option].call($this)
872 + })
873 + }
874 +
875 + var old = $.fn.dropdown
876 +
877 + $.fn.dropdown = Plugin
878 + $.fn.dropdown.Constructor = Dropdown
879 +
880 +
881 + // DROPDOWN NO CONFLICT
882 + // ====================
883 +
884 + $.fn.dropdown.noConflict = function () {
885 + $.fn.dropdown = old
886 + return this
887 + }
888 +
889 +
890 + // APPLY TO STANDARD DROPDOWN ELEMENTS
891 + // ===================================
892 +
893 + $(document)
894 + .on('click.bs.dropdown.data-api', clearMenus)
895 + .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
896 + .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
897 + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
898 + .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
899 + .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
900 +
901 +}(jQuery);
902 +
903 +/* ========================================================================
904 + * Bootstrap: modal.js v3.3.2
905 + * http://getbootstrap.com/javascript/#modals
906 + * ========================================================================
907 + * Copyright 2011-2015 Twitter, Inc.
908 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
909 + * ======================================================================== */
910 +
911 +
912 ++function ($) {
913 + 'use strict';
914 +
915 + // MODAL CLASS DEFINITION
916 + // ======================
917 +
918 + var Modal = function (element, options) {
919 + this.options = options
920 + this.$body = $(document.body)
921 + this.$element = $(element)
922 + this.$backdrop =
923 + this.isShown = null
924 + this.scrollbarWidth = 0
925 +
926 + if (this.options.remote) {
927 + this.$element
928 + .find('.modal-content')
929 + .load(this.options.remote, $.proxy(function () {
930 + this.$element.trigger('loaded.bs.modal')
931 + }, this))
932 + }
933 + }
934 +
935 + Modal.VERSION = '3.3.2'
936 +
937 + Modal.TRANSITION_DURATION = 300
938 + Modal.BACKDROP_TRANSITION_DURATION = 150
939 +
940 + Modal.DEFAULTS = {
941 + backdrop: true,
942 + keyboard: true,
943 + show: true
944 + }
945 +
946 + Modal.prototype.toggle = function (_relatedTarget) {
947 + return this.isShown ? this.hide() : this.show(_relatedTarget)
948 + }
949 +
950 + Modal.prototype.show = function (_relatedTarget) {
951 + var that = this
952 + var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
953 +
954 + this.$element.trigger(e)
955 +
956 + if (this.isShown || e.isDefaultPrevented()) return
957 +
958 + this.isShown = true
959 +
960 + this.checkScrollbar()
961 + this.setScrollbar()
962 + this.$body.addClass('modal-open')
963 +
964 + this.escape()
965 + this.resize()
966 +
967 + this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
968 +
969 + this.backdrop(function () {
970 + var transition = $.support.transition && that.$element.hasClass('fade')
971 +
972 + if (!that.$element.parent().length) {
973 + that.$element.appendTo(that.$body) // don't move modals dom position
974 + }
975 +
976 + that.$element
977 + .show()
978 + .scrollTop(0)
979 +
980 + if (that.options.backdrop) that.adjustBackdrop()
981 + that.adjustDialog()
982 +
983 + if (transition) {
984 + that.$element[0].offsetWidth // force reflow
985 + }
986 +
987 + that.$element
988 + .addClass('in')
989 + .attr('aria-hidden', false)
990 +
991 + that.enforceFocus()
992 +
993 + var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
994 +
995 + transition ?
996 + that.$element.find('.modal-dialog') // wait for modal to slide in
997 + .one('bsTransitionEnd', function () {
998 + that.$element.trigger('focus').trigger(e)
999 + })
1000 + .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1001 + that.$element.trigger('focus').trigger(e)
1002 + })
1003 + }
1004 +
1005 + Modal.prototype.hide = function (e) {
1006 + if (e) e.preventDefault()
1007 +
1008 + e = $.Event('hide.bs.modal')
1009 +
1010 + this.$element.trigger(e)
1011 +
1012 + if (!this.isShown || e.isDefaultPrevented()) return
1013 +
1014 + this.isShown = false
1015 +
1016 + this.escape()
1017 + this.resize()
1018 +
1019 + $(document).off('focusin.bs.modal')
1020 +
1021 + this.$element
1022 + .removeClass('in')
1023 + .attr('aria-hidden', true)
1024 + .off('click.dismiss.bs.modal')
1025 +
1026 + $.support.transition && this.$element.hasClass('fade') ?
1027 + this.$element
1028 + .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1029 + .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1030 + this.hideModal()
1031 + }
1032 +
1033 + Modal.prototype.enforceFocus = function () {
1034 + $(document)
1035 + .off('focusin.bs.modal') // guard against infinite focus loop
1036 + .on('focusin.bs.modal', $.proxy(function (e) {
1037 + if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
1038 + this.$element.trigger('focus')
1039 + }
1040 + }, this))
1041 + }
1042 +
1043 + Modal.prototype.escape = function () {
1044 + if (this.isShown && this.options.keyboard) {
1045 + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
1046 + e.which == 27 && this.hide()
1047 + }, this))
1048 + } else if (!this.isShown) {
1049 + this.$element.off('keydown.dismiss.bs.modal')
1050 + }
1051 + }
1052 +
1053 + Modal.prototype.resize = function () {
1054 + if (this.isShown) {
1055 + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
1056 + } else {
1057 + $(window).off('resize.bs.modal')
1058 + }
1059 + }
1060 +
1061 + Modal.prototype.hideModal = function () {
1062 + var that = this
1063 + this.$element.hide()
1064 + this.backdrop(function () {
1065 + that.$body.removeClass('modal-open')
1066 + that.resetAdjustments()
1067 + that.resetScrollbar()
1068 + that.$element.trigger('hidden.bs.modal')
1069 + })
1070 + }
1071 +
1072 + Modal.prototype.removeBackdrop = function () {
1073 + this.$backdrop && this.$backdrop.remove()
1074 + this.$backdrop = null
1075 + }
1076 +
1077 + Modal.prototype.backdrop = function (callback) {
1078 + var that = this
1079 + var animate = this.$element.hasClass('fade') ? 'fade' : ''
1080 +
1081 + if (this.isShown && this.options.backdrop) {
1082 + var doAnimate = $.support.transition && animate
1083 +
1084 + this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
1085 + .prependTo(this.$element)
1086 + .on('click.dismiss.bs.modal', $.proxy(function (e) {
1087 + if (e.target !== e.currentTarget) return
1088 + this.options.backdrop == 'static'
1089 + ? this.$element[0].focus.call(this.$element[0])
1090 + : this.hide.call(this)
1091 + }, this))
1092 +
1093 + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
1094 +
1095 + this.$backdrop.addClass('in')
1096 +
1097 + if (!callback) return
1098 +
1099 + doAnimate ?
1100 + this.$backdrop
1101 + .one('bsTransitionEnd', callback)
1102 + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1103 + callback()
1104 +
1105 + } else if (!this.isShown && this.$backdrop) {
1106 + this.$backdrop.removeClass('in')
1107 +
1108 + var callbackRemove = function () {
1109 + that.removeBackdrop()
1110 + callback && callback()
1111 + }
1112 + $.support.transition && this.$element.hasClass('fade') ?
1113 + this.$backdrop
1114 + .one('bsTransitionEnd', callbackRemove)
1115 + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1116 + callbackRemove()
1117 +
1118 + } else if (callback) {
1119 + callback()
1120 + }
1121 + }
1122 +
1123 + // these following methods are used to handle overflowing modals
1124 +
1125 + Modal.prototype.handleUpdate = function () {
1126 + if (this.options.backdrop) this.adjustBackdrop()
1127 + this.adjustDialog()
1128 + }
1129 +
1130 + Modal.prototype.adjustBackdrop = function () {
1131 + this.$backdrop
1132 + .css('height', 0)
1133 + .css('height', this.$element[0].scrollHeight)
1134 + }
1135 +
1136 + Modal.prototype.adjustDialog = function () {
1137 + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
1138 +
1139 + this.$element.css({
1140 + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1141 + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
1142 + })
1143 + }
1144 +
1145 + Modal.prototype.resetAdjustments = function () {
1146 + this.$element.css({
1147 + paddingLeft: '',
1148 + paddingRight: ''
1149 + })
1150 + }
1151 +
1152 + Modal.prototype.checkScrollbar = function () {
1153 + this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
1154 + this.scrollbarWidth = this.measureScrollbar()
1155 + }
1156 +
1157 + Modal.prototype.setScrollbar = function () {
1158 + var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1159 + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1160 + }
1161 +
1162 + Modal.prototype.resetScrollbar = function () {
1163 + this.$body.css('padding-right', '')
1164 + }
1165 +
1166 + Modal.prototype.measureScrollbar = function () { // thx walsh
1167 + var scrollDiv = document.createElement('div')
1168 + scrollDiv.className = 'modal-scrollbar-measure'
1169 + this.$body.append(scrollDiv)
1170 + var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
1171 + this.$body[0].removeChild(scrollDiv)
1172 + return scrollbarWidth
1173 + }
1174 +
1175 +
1176 + // MODAL PLUGIN DEFINITION
1177 + // =======================
1178 +
1179 + function Plugin(option, _relatedTarget) {
1180 + return this.each(function () {
1181 + var $this = $(this)
1182 + var data = $this.data('bs.modal')
1183 + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1184 +
1185 + if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1186 + if (typeof option == 'string') data[option](_relatedTarget)
1187 + else if (options.show) data.show(_relatedTarget)
1188 + })
1189 + }
1190 +
1191 + var old = $.fn.modal
1192 +
1193 + $.fn.modal = Plugin
1194 + $.fn.modal.Constructor = Modal
1195 +
1196 +
1197 + // MODAL NO CONFLICT
1198 + // =================
1199 +
1200 + $.fn.modal.noConflict = function () {
1201 + $.fn.modal = old
1202 + return this
1203 + }
1204 +
1205 +
1206 + // MODAL DATA-API
1207 + // ==============
1208 +
1209 + $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1210 + var $this = $(this)
1211 + var href = $this.attr('href')
1212 + var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
1213 + var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1214 +
1215 + if ($this.is('a')) e.preventDefault()
1216 +
1217 + $target.one('show.bs.modal', function (showEvent) {
1218 + if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
1219 + $target.one('hidden.bs.modal', function () {
1220 + $this.is(':visible') && $this.trigger('focus')
1221 + })
1222 + })
1223 + Plugin.call($target, option, this)
1224 + })
1225 +
1226 +}(jQuery);
1227 +
1228 +/* ========================================================================
1229 + * Bootstrap: tooltip.js v3.3.2
1230 + * http://getbootstrap.com/javascript/#tooltip
1231 + * Inspired by the original jQuery.tipsy by Jason Frame
1232 + * ========================================================================
1233 + * Copyright 2011-2015 Twitter, Inc.
1234 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1235 + * ======================================================================== */
1236 +
1237 +
1238 ++function ($) {
1239 + 'use strict';
1240 +
1241 + // TOOLTIP PUBLIC CLASS DEFINITION
1242 + // ===============================
1243 +
1244 + var Tooltip = function (element, options) {
1245 + this.type =
1246 + this.options =
1247 + this.enabled =
1248 + this.timeout =
1249 + this.hoverState =
1250 + this.$element = null
1251 +
1252 + this.init('tooltip', element, options)
1253 + }
1254 +
1255 + Tooltip.VERSION = '3.3.2'
1256 +
1257 + Tooltip.TRANSITION_DURATION = 150
1258 +
1259 + Tooltip.DEFAULTS = {
1260 + animation: true,
1261 + placement: 'top',
1262 + selector: false,
1263 + template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
1264 + trigger: 'hover focus',
1265 + title: '',
1266 + delay: 0,
1267 + html: false,
1268 + container: false,
1269 + viewport: {
1270 + selector: 'body',
1271 + padding: 0
1272 + }
1273 + }
1274 +
1275 + Tooltip.prototype.init = function (type, element, options) {
1276 + this.enabled = true
1277 + this.type = type
1278 + this.$element = $(element)
1279 + this.options = this.getOptions(options)
1280 + this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
1281 +
1282 + var triggers = this.options.trigger.split(' ')
1283 +
1284 + for (var i = triggers.length; i--;) {
1285 + var trigger = triggers[i]
1286 +
1287 + if (trigger == 'click') {
1288 + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1289 + } else if (trigger != 'manual') {
1290 + var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
1291 + var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
1292 +
1293 + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1294 + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1295 + }
1296 + }
1297 +
1298 + this.options.selector ?
1299 + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1300 + this.fixTitle()
1301 + }
1302 +
1303 + Tooltip.prototype.getDefaults = function () {
1304 + return Tooltip.DEFAULTS
1305 + }
1306 +
1307 + Tooltip.prototype.getOptions = function (options) {
1308 + options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1309 +
1310 + if (options.delay && typeof options.delay == 'number') {
1311 + options.delay = {
1312 + show: options.delay,
1313 + hide: options.delay
1314 + }
1315 + }
1316 +
1317 + return options
1318 + }
1319 +
1320 + Tooltip.prototype.getDelegateOptions = function () {
1321 + var options = {}
1322 + var defaults = this.getDefaults()
1323 +
1324 + this._options && $.each(this._options, function (key, value) {
1325 + if (defaults[key] != value) options[key] = value
1326 + })
1327 +
1328 + return options
1329 + }
1330 +
1331 + Tooltip.prototype.enter = function (obj) {
1332 + var self = obj instanceof this.constructor ?
1333 + obj : $(obj.currentTarget).data('bs.' + this.type)
1334 +
1335 + if (self && self.$tip && self.$tip.is(':visible')) {
1336 + self.hoverState = 'in'
1337 + return
1338 + }
1339 +
1340 + if (!self) {
1341 + self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1342 + $(obj.currentTarget).data('bs.' + this.type, self)
1343 + }
1344 +
1345 + clearTimeout(self.timeout)
1346 +
1347 + self.hoverState = 'in'
1348 +
1349 + if (!self.options.delay || !self.options.delay.show) return self.show()
1350 +
1351 + self.timeout = setTimeout(function () {
1352 + if (self.hoverState == 'in') self.show()
1353 + }, self.options.delay.show)
1354 + }
1355 +
1356 + Tooltip.prototype.leave = function (obj) {
1357 + var self = obj instanceof this.constructor ?
1358 + obj : $(obj.currentTarget).data('bs.' + this.type)
1359 +
1360 + if (!self) {
1361 + self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1362 + $(obj.currentTarget).data('bs.' + this.type, self)
1363 + }
1364 +
1365 + clearTimeout(self.timeout)
1366 +
1367 + self.hoverState = 'out'
1368 +
1369 + if (!self.options.delay || !self.options.delay.hide) return self.hide()
1370 +
1371 + self.timeout = setTimeout(function () {
1372 + if (self.hoverState == 'out') self.hide()
1373 + }, self.options.delay.hide)
1374 + }
1375 +
1376 + Tooltip.prototype.show = function () {
1377 + var e = $.Event('show.bs.' + this.type)
1378 +
1379 + if (this.hasContent() && this.enabled) {
1380 + this.$element.trigger(e)
1381 +
1382 + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1383 + if (e.isDefaultPrevented() || !inDom) return
1384 + var that = this
1385 +
1386 + var $tip = this.tip()
1387 +
1388 + var tipId = this.getUID(this.type)
1389 +
1390 + this.setContent()
1391 + $tip.attr('id', tipId)
1392 + this.$element.attr('aria-describedby', tipId)
1393 +
1394 + if (this.options.animation) $tip.addClass('fade')
1395 +
1396 + var placement = typeof this.options.placement == 'function' ?
1397 + this.options.placement.call(this, $tip[0], this.$element[0]) :
1398 + this.options.placement
1399 +
1400 + var autoToken = /\s?auto?\s?/i
1401 + var autoPlace = autoToken.test(placement)
1402 + if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1403 +
1404 + $tip
1405 + .detach()
1406 + .css({ top: 0, left: 0, display: 'block' })
1407 + .addClass(placement)
1408 + .data('bs.' + this.type, this)
1409 +
1410 + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1411 +
1412 + var pos = this.getPosition()
1413 + var actualWidth = $tip[0].offsetWidth
1414 + var actualHeight = $tip[0].offsetHeight
1415 +
1416 + if (autoPlace) {
1417 + var orgPlacement = placement
1418 + var $container = this.options.container ? $(this.options.container) : this.$element.parent()
1419 + var containerDim = this.getPosition($container)
1420 +
1421 + placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
1422 + placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
1423 + placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
1424 + placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
1425 + placement
1426 +
1427 + $tip
1428 + .removeClass(orgPlacement)
1429 + .addClass(placement)
1430 + }
1431 +
1432 + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1433 +
1434 + this.applyPlacement(calculatedOffset, placement)
1435 +
1436 + var complete = function () {
1437 + var prevHoverState = that.hoverState
1438 + that.$element.trigger('shown.bs.' + that.type)
1439 + that.hoverState = null
1440 +
1441 + if (prevHoverState == 'out') that.leave(that)
1442 + }
1443 +
1444 + $.support.transition && this.$tip.hasClass('fade') ?
1445 + $tip
1446 + .one('bsTransitionEnd', complete)
1447 + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1448 + complete()
1449 + }
1450 + }
1451 +
1452 + Tooltip.prototype.applyPlacement = function (offset, placement) {
1453 + var $tip = this.tip()
1454 + var width = $tip[0].offsetWidth
1455 + var height = $tip[0].offsetHeight
1456 +
1457 + // manually read margins because getBoundingClientRect includes difference
1458 + var marginTop = parseInt($tip.css('margin-top'), 10)
1459 + var marginLeft = parseInt($tip.css('margin-left'), 10)
1460 +
1461 + // we must check for NaN for ie 8/9
1462 + if (isNaN(marginTop)) marginTop = 0
1463 + if (isNaN(marginLeft)) marginLeft = 0
1464 +
1465 + offset.top = offset.top + marginTop
1466 + offset.left = offset.left + marginLeft
1467 +
1468 + // $.fn.offset doesn't round pixel values
1469 + // so we use setOffset directly with our own function B-0
1470 + $.offset.setOffset($tip[0], $.extend({
1471 + using: function (props) {
1472 + $tip.css({
1473 + top: Math.round(props.top),
1474 + left: Math.round(props.left)
1475 + })
1476 + }
1477 + }, offset), 0)
1478 +
1479 + $tip.addClass('in')
1480 +
1481 + // check to see if placing tip in new offset caused the tip to resize itself
1482 + var actualWidth = $tip[0].offsetWidth
1483 + var actualHeight = $tip[0].offsetHeight
1484 +
1485 + if (placement == 'top' && actualHeight != height) {
1486 + offset.top = offset.top + height - actualHeight
1487 + }
1488 +
1489 + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1490 +
1491 + if (delta.left) offset.left += delta.left
1492 + else offset.top += delta.top
1493 +
1494 + var isVertical = /top|bottom/.test(placement)
1495 + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1496 + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1497 +
1498 + $tip.offset(offset)
1499 + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1500 + }
1501 +
1502 + Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
1503 + this.arrow()
1504 + .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
1505 + .css(isHorizontal ? 'top' : 'left', '')
1506 + }
1507 +
1508 + Tooltip.prototype.setContent = function () {
1509 + var $tip = this.tip()
1510 + var title = this.getTitle()
1511 +
1512 + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1513 + $tip.removeClass('fade in top bottom left right')
1514 + }
1515 +
1516 + Tooltip.prototype.hide = function (callback) {
1517 + var that = this
1518 + var $tip = this.tip()
1519 + var e = $.Event('hide.bs.' + this.type)
1520 +
1521 + function complete() {
1522 + if (that.hoverState != 'in') $tip.detach()
1523 + that.$element
1524 + .removeAttr('aria-describedby')
1525 + .trigger('hidden.bs.' + that.type)
1526 + callback && callback()
1527 + }
1528 +
1529 + this.$element.trigger(e)
1530 +
1531 + if (e.isDefaultPrevented()) return
1532 +
1533 + $tip.removeClass('in')
1534 +
1535 + $.support.transition && this.$tip.hasClass('fade') ?
1536 + $tip
1537 + .one('bsTransitionEnd', complete)
1538 + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1539 + complete()
1540 +
1541 + this.hoverState = null
1542 +
1543 + return this
1544 + }
1545 +
1546 + Tooltip.prototype.fixTitle = function () {
1547 + var $e = this.$element
1548 + if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
1549 + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1550 + }
1551 + }
1552 +
1553 + Tooltip.prototype.hasContent = function () {
1554 + return this.getTitle()
1555 + }
1556 +
1557 + Tooltip.prototype.getPosition = function ($element) {
1558 + $element = $element || this.$element
1559 +
1560 + var el = $element[0]
1561 + var isBody = el.tagName == 'BODY'
1562 +
1563 + var elRect = el.getBoundingClientRect()
1564 + if (elRect.width == null) {
1565 + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1566 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
1567 + }
1568 + var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
1569 + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
1570 + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1571 +
1572 + return $.extend({}, elRect, scroll, outerDims, elOffset)
1573 + }
1574 +
1575 + Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1576 + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1577 + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1578 + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1579 + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1580 +
1581 + }
1582 +
1583 + Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1584 + var delta = { top: 0, left: 0 }
1585 + if (!this.$viewport) return delta
1586 +
1587 + var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1588 + var viewportDimensions = this.getPosition(this.$viewport)
1589 +
1590 + if (/right|left/.test(placement)) {
1591 + var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
1592 + var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1593 + if (topEdgeOffset < viewportDimensions.top) { // top overflow
1594 + delta.top = viewportDimensions.top - topEdgeOffset
1595 + } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1596 + delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1597 + }
1598 + } else {
1599 + var leftEdgeOffset = pos.left - viewportPadding
1600 + var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1601 + if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1602 + delta.left = viewportDimensions.left - leftEdgeOffset
1603 + } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
1604 + delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1605 + }
1606 + }
1607 +
1608 + return delta
1609 + }
1610 +
1611 + Tooltip.prototype.getTitle = function () {
1612 + var title
1613 + var $e = this.$element
1614 + var o = this.options
1615 +
1616 + title = $e.attr('data-original-title')
1617 + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
1618 +
1619 + return title
1620 + }
1621 +
1622 + Tooltip.prototype.getUID = function (prefix) {
1623 + do prefix += ~~(Math.random() * 1000000)
1624 + while (document.getElementById(prefix))
1625 + return prefix
1626 + }
1627 +
1628 + Tooltip.prototype.tip = function () {
1629 + return (this.$tip = this.$tip || $(this.options.template))
1630 + }
1631 +
1632 + Tooltip.prototype.arrow = function () {
1633 + return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1634 + }
1635 +
1636 + Tooltip.prototype.enable = function () {
1637 + this.enabled = true
1638 + }
1639 +
1640 + Tooltip.prototype.disable = function () {
1641 + this.enabled = false
1642 + }
1643 +
1644 + Tooltip.prototype.toggleEnabled = function () {
1645 + this.enabled = !this.enabled
1646 + }
1647 +
1648 + Tooltip.prototype.toggle = function (e) {
1649 + var self = this
1650 + if (e) {
1651 + self = $(e.currentTarget).data('bs.' + this.type)
1652 + if (!self) {
1653 + self = new this.constructor(e.currentTarget, this.getDelegateOptions())
1654 + $(e.currentTarget).data('bs.' + this.type, self)
1655 + }
1656 + }
1657 +
1658 + self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1659 + }
1660 +
1661 + Tooltip.prototype.destroy = function () {
1662 + var that = this
1663 + clearTimeout(this.timeout)
1664 + this.hide(function () {
1665 + that.$element.off('.' + that.type).removeData('bs.' + that.type)
1666 + })
1667 + }
1668 +
1669 +
1670 + // TOOLTIP PLUGIN DEFINITION
1671 + // =========================
1672 +
1673 + function Plugin(option) {
1674 + return this.each(function () {
1675 + var $this = $(this)
1676 + var data = $this.data('bs.tooltip')
1677 + var options = typeof option == 'object' && option
1678 +
1679 + if (!data && option == 'destroy') return
1680 + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1681 + if (typeof option == 'string') data[option]()
1682 + })
1683 + }
1684 +
1685 + var old = $.fn.tooltip
1686 +
1687 + $.fn.tooltip = Plugin
1688 + $.fn.tooltip.Constructor = Tooltip
1689 +
1690 +
1691 + // TOOLTIP NO CONFLICT
1692 + // ===================
1693 +
1694 + $.fn.tooltip.noConflict = function () {
1695 + $.fn.tooltip = old
1696 + return this
1697 + }
1698 +
1699 +}(jQuery);
1700 +
1701 +/* ========================================================================
1702 + * Bootstrap: popover.js v3.3.2
1703 + * http://getbootstrap.com/javascript/#popovers
1704 + * ========================================================================
1705 + * Copyright 2011-2015 Twitter, Inc.
1706 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1707 + * ======================================================================== */
1708 +
1709 +
1710 ++function ($) {
1711 + 'use strict';
1712 +
1713 + // POPOVER PUBLIC CLASS DEFINITION
1714 + // ===============================
1715 +
1716 + var Popover = function (element, options) {
1717 + this.init('popover', element, options)
1718 + }
1719 +
1720 + if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1721 +
1722 + Popover.VERSION = '3.3.2'
1723 +
1724 + Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1725 + placement: 'right',
1726 + trigger: 'click',
1727 + content: '',
1728 + template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1729 + })
1730 +
1731 +
1732 + // NOTE: POPOVER EXTENDS tooltip.js
1733 + // ================================
1734 +
1735 + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1736 +
1737 + Popover.prototype.constructor = Popover
1738 +
1739 + Popover.prototype.getDefaults = function () {
1740 + return Popover.DEFAULTS
1741 + }
1742 +
1743 + Popover.prototype.setContent = function () {
1744 + var $tip = this.tip()
1745 + var title = this.getTitle()
1746 + var content = this.getContent()
1747 +
1748 + $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1749 + $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1750 + this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1751 + ](content)
1752 +
1753 + $tip.removeClass('fade top bottom left right in')
1754 +
1755 + // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1756 + // this manually by checking the contents.
1757 + if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1758 + }
1759 +
1760 + Popover.prototype.hasContent = function () {
1761 + return this.getTitle() || this.getContent()
1762 + }
1763 +
1764 + Popover.prototype.getContent = function () {
1765 + var $e = this.$element
1766 + var o = this.options
1767 +
1768 + return $e.attr('data-content')
1769 + || (typeof o.content == 'function' ?
1770 + o.content.call($e[0]) :
1771 + o.content)
1772 + }
1773 +
1774 + Popover.prototype.arrow = function () {
1775 + return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1776 + }
1777 +
1778 + Popover.prototype.tip = function () {
1779 + if (!this.$tip) this.$tip = $(this.options.template)
1780 + return this.$tip
1781 + }
1782 +
1783 +
1784 + // POPOVER PLUGIN DEFINITION
1785 + // =========================
1786 +
1787 + function Plugin(option) {
1788 + return this.each(function () {
1789 + var $this = $(this)
1790 + var data = $this.data('bs.popover')
1791 + var options = typeof option == 'object' && option
1792 +
1793 + if (!data && option == 'destroy') return
1794 + if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1795 + if (typeof option == 'string') data[option]()
1796 + })
1797 + }
1798 +
1799 + var old = $.fn.popover
1800 +
1801 + $.fn.popover = Plugin
1802 + $.fn.popover.Constructor = Popover
1803 +
1804 +
1805 + // POPOVER NO CONFLICT
1806 + // ===================
1807 +
1808 + $.fn.popover.noConflict = function () {
1809 + $.fn.popover = old
1810 + return this
1811 + }
1812 +
1813 +}(jQuery);
1814 +
1815 +/* ========================================================================
1816 + * Bootstrap: scrollspy.js v3.3.2
1817 + * http://getbootstrap.com/javascript/#scrollspy
1818 + * ========================================================================
1819 + * Copyright 2011-2015 Twitter, Inc.
1820 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1821 + * ======================================================================== */
1822 +
1823 +
1824 ++function ($) {
1825 + 'use strict';
1826 +
1827 + // SCROLLSPY CLASS DEFINITION
1828 + // ==========================
1829 +
1830 + function ScrollSpy(element, options) {
1831 + var process = $.proxy(this.process, this)
1832 +
1833 + this.$body = $('body')
1834 + this.$scrollElement = $(element).is('body') ? $(window) : $(element)
1835 + this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1836 + this.selector = (this.options.target || '') + ' .nav li > a'
1837 + this.offsets = []
1838 + this.targets = []
1839 + this.activeTarget = null
1840 + this.scrollHeight = 0
1841 +
1842 + this.$scrollElement.on('scroll.bs.scrollspy', process)
1843 + this.refresh()
1844 + this.process()
1845 + }
1846 +
1847 + ScrollSpy.VERSION = '3.3.2'
1848 +
1849 + ScrollSpy.DEFAULTS = {
1850 + offset: 10
1851 + }
1852 +
1853 + ScrollSpy.prototype.getScrollHeight = function () {
1854 + return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
1855 + }
1856 +
1857 + ScrollSpy.prototype.refresh = function () {
1858 + var offsetMethod = 'offset'
1859 + var offsetBase = 0
1860 +
1861 + if (!$.isWindow(this.$scrollElement[0])) {
1862 + offsetMethod = 'position'
1863 + offsetBase = this.$scrollElement.scrollTop()
1864 + }
1865 +
1866 + this.offsets = []
1867 + this.targets = []
1868 + this.scrollHeight = this.getScrollHeight()
1869 +
1870 + var self = this
1871 +
1872 + this.$body
1873 + .find(this.selector)
1874 + .map(function () {
1875 + var $el = $(this)
1876 + var href = $el.data('target') || $el.attr('href')
1877 + var $href = /^#./.test(href) && $(href)
1878 +
1879 + return ($href
1880 + && $href.length
1881 + && $href.is(':visible')
1882 + && [[$href[offsetMethod]().top + offsetBase, href]]) || null
1883 + })
1884 + .sort(function (a, b) { return a[0] - b[0] })
1885 + .each(function () {
1886 + self.offsets.push(this[0])
1887 + self.targets.push(this[1])
1888 + })
1889 + }
1890 +
1891 + ScrollSpy.prototype.process = function () {
1892 + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1893 + var scrollHeight = this.getScrollHeight()
1894 + var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
1895 + var offsets = this.offsets
1896 + var targets = this.targets
1897 + var activeTarget = this.activeTarget
1898 + var i
1899 +
1900 + if (this.scrollHeight != scrollHeight) {
1901 + this.refresh()
1902 + }
1903 +
1904 + if (scrollTop >= maxScroll) {
1905 + return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1906 + }
1907 +
1908 + if (activeTarget && scrollTop < offsets[0]) {
1909 + this.activeTarget = null
1910 + return this.clear()
1911 + }
1912 +
1913 + for (i = offsets.length; i--;) {
1914 + activeTarget != targets[i]
1915 + && scrollTop >= offsets[i]
1916 + && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
1917 + && this.activate(targets[i])
1918 + }
1919 + }
1920 +
1921 + ScrollSpy.prototype.activate = function (target) {
1922 + this.activeTarget = target
1923 +
1924 + this.clear()
1925 +
1926 + var selector = this.selector +
1927 + '[data-target="' + target + '"],' +
1928 + this.selector + '[href="' + target + '"]'
1929 +
1930 + var active = $(selector)
1931 + .parents('li')
1932 + .addClass('active')
1933 +
1934 + if (active.parent('.dropdown-menu').length) {
1935 + active = active
1936 + .closest('li.dropdown')
1937 + .addClass('active')
1938 + }
1939 +
1940 + active.trigger('activate.bs.scrollspy')
1941 + }
1942 +
1943 + ScrollSpy.prototype.clear = function () {
1944 + $(this.selector)
1945 + .parentsUntil(this.options.target, '.active')
1946 + .removeClass('active')
1947 + }
1948 +
1949 +
1950 + // SCROLLSPY PLUGIN DEFINITION
1951 + // ===========================
1952 +
1953 + function Plugin(option) {
1954 + return this.each(function () {
1955 + var $this = $(this)
1956 + var data = $this.data('bs.scrollspy')
1957 + var options = typeof option == 'object' && option
1958 +
1959 + if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
1960 + if (typeof option == 'string') data[option]()
1961 + })
1962 + }
1963 +
1964 + var old = $.fn.scrollspy
1965 +
1966 + $.fn.scrollspy = Plugin
1967 + $.fn.scrollspy.Constructor = ScrollSpy
1968 +
1969 +
1970 + // SCROLLSPY NO CONFLICT
1971 + // =====================
1972 +
1973 + $.fn.scrollspy.noConflict = function () {
1974 + $.fn.scrollspy = old
1975 + return this
1976 + }
1977 +
1978 +
1979 + // SCROLLSPY DATA-API
1980 + // ==================
1981 +
1982 + $(window).on('load.bs.scrollspy.data-api', function () {
1983 + $('[data-spy="scroll"]').each(function () {
1984 + var $spy = $(this)
1985 + Plugin.call($spy, $spy.data())
1986 + })
1987 + })
1988 +
1989 +}(jQuery);
1990 +
1991 +/* ========================================================================
1992 + * Bootstrap: tab.js v3.3.2
1993 + * http://getbootstrap.com/javascript/#tabs
1994 + * ========================================================================
1995 + * Copyright 2011-2015 Twitter, Inc.
1996 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1997 + * ======================================================================== */
1998 +
1999 +
2000 ++function ($) {
2001 + 'use strict';
2002 +
2003 + // TAB CLASS DEFINITION
2004 + // ====================
2005 +
2006 + var Tab = function (element) {
2007 + this.element = $(element)
2008 + }
2009 +
2010 + Tab.VERSION = '3.3.2'
2011 +
2012 + Tab.TRANSITION_DURATION = 150
2013 +
2014 + Tab.prototype.show = function () {
2015 + var $this = this.element
2016 + var $ul = $this.closest('ul:not(.dropdown-menu)')
2017 + var selector = $this.data('target')
2018 +
2019 + if (!selector) {
2020 + selector = $this.attr('href')
2021 + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
2022 + }
2023 +
2024 + if ($this.parent('li').hasClass('active')) return
2025 +
2026 + var $previous = $ul.find('.active:last a')
2027 + var hideEvent = $.Event('hide.bs.tab', {
2028 + relatedTarget: $this[0]
2029 + })
2030 + var showEvent = $.Event('show.bs.tab', {
2031 + relatedTarget: $previous[0]
2032 + })
2033 +
2034 + $previous.trigger(hideEvent)
2035 + $this.trigger(showEvent)
2036 +
2037 + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
2038 +
2039 + var $target = $(selector)
2040 +
2041 + this.activate($this.closest('li'), $ul)
2042 + this.activate($target, $target.parent(), function () {
2043 + $previous.trigger({
2044 + type: 'hidden.bs.tab',
2045 + relatedTarget: $this[0]
2046 + })
2047 + $this.trigger({
2048 + type: 'shown.bs.tab',
2049 + relatedTarget: $previous[0]
2050 + })
2051 + })
2052 + }
2053 +
2054 + Tab.prototype.activate = function (element, container, callback) {
2055 + var $active = container.find('> .active')
2056 + var transition = callback
2057 + && $.support.transition
2058 + && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
2059 +
2060 + function next() {
2061 + $active
2062 + .removeClass('active')
2063 + .find('> .dropdown-menu > .active')
2064 + .removeClass('active')
2065 + .end()
2066 + .find('[data-toggle="tab"]')
2067 + .attr('aria-expanded', false)
2068 +
2069 + element
2070 + .addClass('active')
2071 + .find('[data-toggle="tab"]')
2072 + .attr('aria-expanded', true)
2073 +
2074 + if (transition) {
2075 + element[0].offsetWidth // reflow for transition
2076 + element.addClass('in')
2077 + } else {
2078 + element.removeClass('fade')
2079 + }
2080 +
2081 + if (element.parent('.dropdown-menu')) {
2082 + element
2083 + .closest('li.dropdown')
2084 + .addClass('active')
2085 + .end()
2086 + .find('[data-toggle="tab"]')
2087 + .attr('aria-expanded', true)
2088 + }
2089 +
2090 + callback && callback()
2091 + }
2092 +
2093 + $active.length && transition ?
2094 + $active
2095 + .one('bsTransitionEnd', next)
2096 + .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
2097 + next()
2098 +
2099 + $active.removeClass('in')
2100 + }
2101 +
2102 +
2103 + // TAB PLUGIN DEFINITION
2104 + // =====================
2105 +
2106 + function Plugin(option) {
2107 + return this.each(function () {
2108 + var $this = $(this)
2109 + var data = $this.data('bs.tab')
2110 +
2111 + if (!data) $this.data('bs.tab', (data = new Tab(this)))
2112 + if (typeof option == 'string') data[option]()
2113 + })
2114 + }
2115 +
2116 + var old = $.fn.tab
2117 +
2118 + $.fn.tab = Plugin
2119 + $.fn.tab.Constructor = Tab
2120 +
2121 +
2122 + // TAB NO CONFLICT
2123 + // ===============
2124 +
2125 + $.fn.tab.noConflict = function () {
2126 + $.fn.tab = old
2127 + return this
2128 + }
2129 +
2130 +
2131 + // TAB DATA-API
2132 + // ============
2133 +
2134 + var clickHandler = function (e) {
2135 + e.preventDefault()
2136 + Plugin.call($(this), 'show')
2137 + }
2138 +
2139 + $(document)
2140 + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
2141 + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
2142 +
2143 +}(jQuery);
2144 +
2145 +/* ========================================================================
2146 + * Bootstrap: affix.js v3.3.2
2147 + * http://getbootstrap.com/javascript/#affix
2148 + * ========================================================================
2149 + * Copyright 2011-2015 Twitter, Inc.
2150 + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2151 + * ======================================================================== */
2152 +
2153 +
2154 ++function ($) {
2155 + 'use strict';
2156 +
2157 + // AFFIX CLASS DEFINITION
2158 + // ======================
2159 +
2160 + var Affix = function (element, options) {
2161 + this.options = $.extend({}, Affix.DEFAULTS, options)
2162 +
2163 + this.$target = $(this.options.target)
2164 + .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
2165 + .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
2166 +
2167 + this.$element = $(element)
2168 + this.affixed =
2169 + this.unpin =
2170 + this.pinnedOffset = null
2171 +
2172 + this.checkPosition()
2173 + }
2174 +
2175 + Affix.VERSION = '3.3.2'
2176 +
2177 + Affix.RESET = 'affix affix-top affix-bottom'
2178 +
2179 + Affix.DEFAULTS = {
2180 + offset: 0,
2181 + target: window
2182 + }
2183 +
2184 + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
2185 + var scrollTop = this.$target.scrollTop()
2186 + var position = this.$element.offset()
2187 + var targetHeight = this.$target.height()
2188 +
2189 + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
2190 +
2191 + if (this.affixed == 'bottom') {
2192 + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
2193 + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
2194 + }
2195 +
2196 + var initializing = this.affixed == null
2197 + var colliderTop = initializing ? scrollTop : position.top
2198 + var colliderHeight = initializing ? targetHeight : height
2199 +
2200 + if (offsetTop != null && scrollTop <= offsetTop) return 'top'
2201 + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
2202 +
2203 + return false
2204 + }
2205 +
2206 + Affix.prototype.getPinnedOffset = function () {
2207 + if (this.pinnedOffset) return this.pinnedOffset
2208 + this.$element.removeClass(Affix.RESET).addClass('affix')
2209 + var scrollTop = this.$target.scrollTop()
2210 + var position = this.$element.offset()
2211 + return (this.pinnedOffset = position.top - scrollTop)
2212 + }
2213 +
2214 + Affix.prototype.checkPositionWithEventLoop = function () {
2215 + setTimeout($.proxy(this.checkPosition, this), 1)
2216 + }
2217 +
2218 + Affix.prototype.checkPosition = function () {
2219 + if (!this.$element.is(':visible')) return
2220 +
2221 + var height = this.$element.height()
2222 + var offset = this.options.offset
2223 + var offsetTop = offset.top
2224 + var offsetBottom = offset.bottom
2225 + var scrollHeight = $('body').height()
2226 +
2227 + if (typeof offset != 'object') offsetBottom = offsetTop = offset
2228 + if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
2229 + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
2230 +
2231 + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
2232 +
2233 + if (this.affixed != affix) {
2234 + if (this.unpin != null) this.$element.css('top', '')
2235 +
2236 + var affixType = 'affix' + (affix ? '-' + affix : '')
2237 + var e = $.Event(affixType + '.bs.affix')
2238 +
2239 + this.$element.trigger(e)
2240 +
2241 + if (e.isDefaultPrevented()) return
2242 +
2243 + this.affixed = affix
2244 + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
2245 +
2246 + this.$element
2247 + .removeClass(Affix.RESET)
2248 + .addClass(affixType)
2249 + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
2250 + }
2251 +
2252 + if (affix == 'bottom') {
2253 + this.$element.offset({
2254 + top: scrollHeight - height - offsetBottom
2255 + })
2256 + }
2257 + }
2258 +
2259 +
2260 + // AFFIX PLUGIN DEFINITION
2261 + // =======================
2262 +
2263 + function Plugin(option) {
2264 + return this.each(function () {
2265 + var $this = $(this)
2266 + var data = $this.data('bs.affix')
2267 + var options = typeof option == 'object' && option
2268 +
2269 + if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
2270 + if (typeof option == 'string') data[option]()
2271 + })
2272 + }
2273 +
2274 + var old = $.fn.affix
2275 +
2276 + $.fn.affix = Plugin
2277 + $.fn.affix.Constructor = Affix
2278 +
2279 +
2280 + // AFFIX NO CONFLICT
2281 + // =================
2282 +
2283 + $.fn.affix.noConflict = function () {
2284 + $.fn.affix = old
2285 + return this
2286 + }
2287 +
2288 +
2289 + // AFFIX DATA-API
2290 + // ==============
2291 +
2292 + $(window).on('load', function () {
2293 + $('[data-spy="affix"]').each(function () {
2294 + var $spy = $(this)
2295 + var data = $spy.data()
2296 +
2297 + data.offset = data.offset || {}
2298 +
2299 + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
2300 + if (data.offsetTop != null) data.offset.top = data.offsetTop
2301 +
2302 + Plugin.call($spy, data)
2303 + })
2304 + })
2305 +
2306 +}(jQuery);
1 +// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
2 +require('../../js/transition.js')
3 +require('../../js/alert.js')
4 +require('../../js/button.js')
5 +require('../../js/carousel.js')
6 +require('../../js/collapse.js')
7 +require('../../js/dropdown.js')
8 +require('../../js/modal.js')
9 +require('../../js/tooltip.js')
10 +require('../../js/popover.js')
11 +require('../../js/scrollspy.js')
12 +require('../../js/tab.js')
13 +require('../../js/affix.js')
...\ No newline at end of file ...\ No newline at end of file
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
...@@ -6,4 +6,8 @@ router.get('/', function(req, res, next) { ...@@ -6,4 +6,8 @@ router.get('/', function(req, res, next) {
6 res.render('index', { title: 'Express' }); 6 res.render('index', { title: 'Express' });
7 }); 7 });
8 8
9 +router.get('/test', function(req, res, next) {
10 + res.render('test', { title: '맛집 견문록' });
11 +});
12 +
9 module.exports = router; 13 module.exports = router;
......
1 +<!DOCTYPE html>
2 +<html>
3 + <head>
4 + <title><%= title %></title>
5 + <link rel='stylesheet' href='/stylesheets/style.css'/>
6 + </head>
7 + <body>
8 + <h1><%= title %></h1>
9 + <p>Welcome to <%= title %></p>
10 + </body>
11 +</html>