summaryrefslogtreecommitdiffstats
path: root/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js
diff options
context:
space:
mode:
Diffstat (limited to 'import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js')
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.js2363
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.min.js11
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js36
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js219
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/jsrender.min.js4
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js4
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerDepsModal.js16
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js218
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js282
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js180
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js99
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js232
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js11
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js191
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/tests/test.js16
-rw-r--r--import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js1551
16 files changed, 4869 insertions, 564 deletions
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.js
new file mode 100644
index 000000000..d47d640fe
--- /dev/null
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.js
@@ -0,0 +1,2363 @@
+/*!
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+
+if (typeof jQuery === 'undefined') {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+ 'use strict';
+ var version = $.fn.jquery.split(' ')[0].split('.')
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 2)) {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3')
+ }
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.3.6
+ * http://getbootstrap.com/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
+ // ============================================================
+
+ function transitionEnd() {
+ var el = document.createElement('bootstrap')
+
+ var transEndEventNames = {
+ WebkitTransition : 'webkitTransitionEnd',
+ MozTransition : 'transitionend',
+ OTransition : 'oTransitionEnd otransitionend',
+ transition : 'transitionend'
+ }
+
+ for (var name in transEndEventNames) {
+ if (el.style[name] !== undefined) {
+ return { end: transEndEventNames[name] }
+ }
+ }
+
+ return false // explicit for ie8 ( ._.)
+ }
+
+ // http://blog.alexmaccaw.com/css-transitions
+ $.fn.emulateTransitionEnd = function (duration) {
+ var called = false
+ var $el = this
+ $(this).one('bsTransitionEnd', function () { called = true })
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+ setTimeout(callback, duration)
+ return this
+ }
+
+ $(function () {
+ $.support.transition = transitionEnd()
+
+ if (!$.support.transition) return
+
+ $.event.special.bsTransitionEnd = {
+ bindType: $.support.transition.end,
+ delegateType: $.support.transition.end,
+ handle: function (e) {
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+ }
+ }
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.3.6
+ * http://getbootstrap.com/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // ALERT CLASS DEFINITION
+ // ======================
+
+ var dismiss = '[data-dismiss="alert"]'
+ var Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.VERSION = '3.3.6'
+
+ Alert.TRANSITION_DURATION = 150
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = $(selector)
+
+ if (e) e.preventDefault()
+
+ if (!$parent.length) {
+ $parent = $this.closest('.alert')
+ }
+
+ $parent.trigger(e = $.Event('close.bs.alert'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ // detach from parent, fire event then clean up data
+ $parent.detach().trigger('closed.bs.alert').remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent
+ .one('bsTransitionEnd', removeElement)
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
+ removeElement()
+ }
+
+
+ // ALERT PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.alert')
+
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.alert
+
+ $.fn.alert = Plugin
+ $.fn.alert.Constructor = Alert
+
+
+ // ALERT NO CONFLICT
+ // =================
+
+ $.fn.alert.noConflict = function () {
+ $.fn.alert = old
+ return this
+ }
+
+
+ // ALERT DATA-API
+ // ==============
+
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.3.6
+ * http://getbootstrap.com/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // BUTTON PUBLIC CLASS DEFINITION
+ // ==============================
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Button.DEFAULTS, options)
+ this.isLoading = false
+ }
+
+ Button.VERSION = '3.3.6'
+
+ Button.DEFAULTS = {
+ loadingText: 'loading...'
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ var $el = this.$element
+ var val = $el.is('input') ? 'val' : 'html'
+ var data = $el.data()
+
+ state += 'Text'
+
+ if (data.resetText == null) $el.data('resetText', $el[val]())
+
+ // push to event loop to allow forms to submit
+ setTimeout($.proxy(function () {
+ $el[val](data[state] == null ? this.options[state] : data[state])
+
+ if (state == 'loadingText') {
+ this.isLoading = true
+ $el.addClass(d).attr(d, d)
+ } else if (this.isLoading) {
+ this.isLoading = false
+ $el.removeClass(d).removeAttr(d)
+ }
+ }, this), 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var changed = true
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+ if ($parent.length) {
+ var $input = this.$element.find('input')
+ if ($input.prop('type') == 'radio') {
+ if ($input.prop('checked')) changed = false
+ $parent.find('.active').removeClass('active')
+ this.$element.addClass('active')
+ } else if ($input.prop('type') == 'checkbox') {
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
+ this.$element.toggleClass('active')
+ }
+ $input.prop('checked', this.$element.hasClass('active'))
+ if (changed) $input.trigger('change')
+ } else {
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
+ this.$element.toggleClass('active')
+ }
+ }
+
+
+ // BUTTON PLUGIN DEFINITION
+ // ========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.button')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ var old = $.fn.button
+
+ $.fn.button = Plugin
+ $.fn.button.Constructor = Button
+
+
+ // BUTTON NO CONFLICT
+ // ==================
+
+ $.fn.button.noConflict = function () {
+ $.fn.button = old
+ return this
+ }
+
+
+ // BUTTON DATA-API
+ // ===============
+
+ $(document)
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ var $btn = $(e.target)
+ if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ Plugin.call($btn, 'toggle')
+ if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault()
+ })
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.3.6
+ * http://getbootstrap.com/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CAROUSEL CLASS DEFINITION
+ // =========================
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.$indicators = this.$element.find('.carousel-indicators')
+ this.options = options
+ this.paused = null
+ this.sliding = null
+ this.interval = null
+ this.$active = null
+ this.$items = null
+
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
+ .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+ .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+ }
+
+ Carousel.VERSION = '3.3.6'
+
+ Carousel.TRANSITION_DURATION = 600
+
+ Carousel.DEFAULTS = {
+ interval: 5000,
+ pause: 'hover',
+ wrap: true,
+ keyboard: true
+ }
+
+ Carousel.prototype.keydown = function (e) {
+ if (/input|textarea/i.test(e.target.tagName)) return
+ switch (e.which) {
+ case 37: this.prev(); break
+ case 39: this.next(); break
+ default: return
+ }
+
+ e.preventDefault()
+ }
+
+ Carousel.prototype.cycle = function (e) {
+ e || (this.paused = false)
+
+ this.interval && clearInterval(this.interval)
+
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+ return this
+ }
+
+ Carousel.prototype.getItemIndex = function (item) {
+ this.$items = item.parent().children('.item')
+ return this.$items.index(item || this.$active)
+ }
+
+ Carousel.prototype.getItemForDirection = function (direction, active) {
+ var activeIndex = this.getItemIndex(active)
+ var willWrap = (direction == 'prev' && activeIndex === 0)
+ || (direction == 'next' && activeIndex == (this.$items.length - 1))
+ if (willWrap && !this.options.wrap) return active
+ var delta = direction == 'prev' ? -1 : 1
+ var itemIndex = (activeIndex + delta) % this.$items.length
+ return this.$items.eq(itemIndex)
+ }
+
+ Carousel.prototype.to = function (pos) {
+ var that = this
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+ if (pos > (this.$items.length - 1) || pos < 0) return
+
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+ if (activeIndex == pos) return this.pause().cycle()
+
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
+ }
+
+ Carousel.prototype.pause = function (e) {
+ e || (this.paused = true)
+
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
+ this.$element.trigger($.support.transition.end)
+ this.cycle(true)
+ }
+
+ this.interval = clearInterval(this.interval)
+
+ return this
+ }
+
+ Carousel.prototype.next = function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ Carousel.prototype.prev = function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ Carousel.prototype.slide = function (type, next) {
+ var $active = this.$element.find('.item.active')
+ var $next = next || this.getItemForDirection(type, $active)
+ var isCycling = this.interval
+ var direction = type == 'next' ? 'left' : 'right'
+ var that = this
+
+ if ($next.hasClass('active')) return (this.sliding = false)
+
+ var relatedTarget = $next[0]
+ var slideEvent = $.Event('slide.bs.carousel', {
+ relatedTarget: relatedTarget,
+ direction: direction
+ })
+ this.$element.trigger(slideEvent)
+ if (slideEvent.isDefaultPrevented()) return
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ if (this.$indicators.length) {
+ this.$indicators.find('.active').removeClass('active')
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+ $nextIndicator && $nextIndicator.addClass('active')
+ }
+
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ $active
+ .one('bsTransitionEnd', function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () {
+ that.$element.trigger(slidEvent)
+ }, 0)
+ })
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
+ } else {
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger(slidEvent)
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+
+ // CAROUSEL PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.carousel')
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+ var action = typeof option == 'string' ? option : options.slide
+
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (action) data[action]()
+ else if (options.interval) data.pause().cycle()
+ })
+ }
+
+ var old = $.fn.carousel
+
+ $.fn.carousel = Plugin
+ $.fn.carousel.Constructor = Carousel
+
+
+ // CAROUSEL NO CONFLICT
+ // ====================
+
+ $.fn.carousel.noConflict = function () {
+ $.fn.carousel = old
+ return this
+ }
+
+
+ // CAROUSEL DATA-API
+ // =================
+
+ var clickHandler = function (e) {
+ var href
+ var $this = $(this)
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+ if (!$target.hasClass('carousel')) return
+ var options = $.extend({}, $target.data(), $this.data())
+ var slideIndex = $this.attr('data-slide-to')
+ if (slideIndex) options.interval = false
+
+ Plugin.call($target, options)
+
+ if (slideIndex) {
+ $target.data('bs.carousel').to(slideIndex)
+ }
+
+ e.preventDefault()
+ }
+
+ $(document)
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
+
+ $(window).on('load', function () {
+ $('[data-ride="carousel"]').each(function () {
+ var $carousel = $(this)
+ Plugin.call($carousel, $carousel.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.3.6
+ * http://getbootstrap.com/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // COLLAPSE PUBLIC CLASS DEFINITION
+ // ================================
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
+ this.transitioning = null
+
+ if (this.options.parent) {
+ this.$parent = this.getParent()
+ } else {
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+ }
+
+ if (this.options.toggle) this.toggle()
+ }
+
+ Collapse.VERSION = '3.3.6'
+
+ Collapse.TRANSITION_DURATION = 350
+
+ Collapse.DEFAULTS = {
+ toggle: true
+ }
+
+ Collapse.prototype.dimension = function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ Collapse.prototype.show = function () {
+ if (this.transitioning || this.$element.hasClass('in')) return
+
+ var activesData
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
+
+ if (actives && actives.length) {
+ activesData = actives.data('bs.collapse')
+ if (activesData && activesData.transitioning) return
+ }
+
+ var startEvent = $.Event('show.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ if (actives && actives.length) {
+ Plugin.call(actives, 'hide')
+ activesData || actives.data('bs.collapse', null)
+ }
+
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ .addClass('collapsing')[dimension](0)
+ .attr('aria-expanded', true)
+
+ this.$trigger
+ .removeClass('collapsed')
+ .attr('aria-expanded', true)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse in')[dimension]('')
+ this.transitioning = 0
+ this.$element
+ .trigger('shown.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+ this.$element
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
+ }
+
+ Collapse.prototype.hide = function () {
+ if (this.transitioning || !this.$element.hasClass('in')) return
+
+ var startEvent = $.Event('hide.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ var dimension = this.dimension()
+
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+ this.$element
+ .addClass('collapsing')
+ .removeClass('collapse in')
+ .attr('aria-expanded', false)
+
+ this.$trigger
+ .addClass('collapsed')
+ .attr('aria-expanded', false)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.transitioning = 0
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse')
+ .trigger('hidden.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ this.$element
+ [dimension](0)
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
+ }
+
+ Collapse.prototype.toggle = function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ Collapse.prototype.getParent = function () {
+ return $(this.options.parent)
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+ .each($.proxy(function (i, element) {
+ var $element = $(element)
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+ }, this))
+ .end()
+ }
+
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+ var isOpen = $element.hasClass('in')
+
+ $element.attr('aria-expanded', isOpen)
+ $trigger
+ .toggleClass('collapsed', !isOpen)
+ .attr('aria-expanded', isOpen)
+ }
+
+ function getTargetFromTrigger($trigger) {
+ var href
+ var target = $trigger.attr('data-target')
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+ return $(target)
+ }
+
+
+ // COLLAPSE PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.collapse')
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.collapse
+
+ $.fn.collapse = Plugin
+ $.fn.collapse.Constructor = Collapse
+
+
+ // COLLAPSE NO CONFLICT
+ // ====================
+
+ $.fn.collapse.noConflict = function () {
+ $.fn.collapse = old
+ return this
+ }
+
+
+ // COLLAPSE DATA-API
+ // =================
+
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+ var $this = $(this)
+
+ if (!$this.attr('data-target')) e.preventDefault()
+
+ var $target = getTargetFromTrigger($this)
+ var data = $target.data('bs.collapse')
+ var option = data ? 'toggle' : $this.data()
+
+ Plugin.call($target, option)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.3.6
+ * http://getbootstrap.com/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // DROPDOWN CLASS DEFINITION
+ // =========================
+
+ var backdrop = '.dropdown-backdrop'
+ var toggle = '[data-toggle="dropdown"]'
+ var Dropdown = function (element) {
+ $(element).on('click.bs.dropdown', this.toggle)
+ }
+
+ Dropdown.VERSION = '3.3.6'
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = selector && $(selector)
+
+ return $parent && $parent.length ? $parent : $this.parent()
+ }
+
+ function clearMenus(e) {
+ if (e && e.which === 3) return
+ $(backdrop).remove()
+ $(toggle).each(function () {
+ var $this = $(this)
+ var $parent = getParent($this)
+ var relatedTarget = { relatedTarget: this }
+
+ if (!$parent.hasClass('open')) return
+
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
+
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
+ $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
+ })
+ }
+
+ Dropdown.prototype.toggle = function (e) {
+ var $this = $(this)
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) {
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+ // if mobile we use a backdrop because click events don't delegate
+ $(document.createElement('div'))
+ .addClass('dropdown-backdrop')
+ .insertAfter($(this))
+ .on('click', clearMenus)
+ }
+
+ var relatedTarget = { relatedTarget: this }
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this
+ .trigger('focus')
+ .attr('aria-expanded', 'true')
+
+ $parent
+ .toggleClass('open')
+ .trigger($.Event('shown.bs.dropdown', relatedTarget))
+ }
+
+ return false
+ }
+
+ Dropdown.prototype.keydown = function (e) {
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
+
+ var $this = $(this)
+
+ e.preventDefault()
+ e.stopPropagation()
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
+ return $this.trigger('click')
+ }
+
+ var desc = ' li:not(.disabled):visible a'
+ var $items = $parent.find('.dropdown-menu' + desc)
+
+ if (!$items.length) return
+
+ var index = $items.index(e.target)
+
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
+
+ $items.eq(index).trigger('focus')
+ }
+
+
+ // DROPDOWN PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.dropdown')
+
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.dropdown
+
+ $.fn.dropdown = Plugin
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ // DROPDOWN NO CONFLICT
+ // ====================
+
+ $.fn.dropdown.noConflict = function () {
+ $.fn.dropdown = old
+ return this
+ }
+
+
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
+ // ===================================
+
+ $(document)
+ .on('click.bs.dropdown.data-api', clearMenus)
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.3.6
+ * http://getbootstrap.com/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // MODAL CLASS DEFINITION
+ // ======================
+
+ var Modal = function (element, options) {
+ this.options = options
+ this.$body = $(document.body)
+ this.$element = $(element)
+ this.$dialog = this.$element.find('.modal-dialog')
+ this.$backdrop = null
+ this.isShown = null
+ this.originalBodyPad = null
+ this.scrollbarWidth = 0
+ this.ignoreBackdropClick = false
+
+ if (this.options.remote) {
+ this.$element
+ .find('.modal-content')
+ .load(this.options.remote, $.proxy(function () {
+ this.$element.trigger('loaded.bs.modal')
+ }, this))
+ }
+ }
+
+ Modal.VERSION = '3.3.6'
+
+ Modal.TRANSITION_DURATION = 300
+ Modal.BACKDROP_TRANSITION_DURATION = 150
+
+ Modal.DEFAULTS = {
+ backdrop: true,
+ keyboard: true,
+ show: true
+ }
+
+ Modal.prototype.toggle = function (_relatedTarget) {
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
+ }
+
+ Modal.prototype.show = function (_relatedTarget) {
+ var that = this
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = true
+
+ this.checkScrollbar()
+ this.setScrollbar()
+ this.$body.addClass('modal-open')
+
+ this.escape()
+ this.resize()
+
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+ this.$dialog.on('mousedown.dismiss.bs.modal', function () {
+ that.$element.one('mouseup.dismiss.bs.modal', function (e) {
+ if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
+ })
+ })
+
+ this.backdrop(function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(that.$body) // don't move modals dom position
+ }
+
+ that.$element
+ .show()
+ .scrollTop(0)
+
+ that.adjustDialog()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ that.enforceFocus()
+
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+ transition ?
+ that.$dialog // wait for modal to slide in
+ .one('bsTransitionEnd', function () {
+ that.$element.trigger('focus').trigger(e)
+ })
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ that.$element.trigger('focus').trigger(e)
+ })
+ }
+
+ Modal.prototype.hide = function (e) {
+ if (e) e.preventDefault()
+
+ e = $.Event('hide.bs.modal')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ this.escape()
+ this.resize()
+
+ $(document).off('focusin.bs.modal')
+
+ this.$element
+ .removeClass('in')
+ .off('click.dismiss.bs.modal')
+ .off('mouseup.dismiss.bs.modal')
+
+ this.$dialog.off('mousedown.dismiss.bs.modal')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$element
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ this.hideModal()
+ }
+
+ Modal.prototype.enforceFocus = function () {
+ $(document)
+ .off('focusin.bs.modal') // guard against infinite focus loop
+ .on('focusin.bs.modal', $.proxy(function (e) {
+ if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
+ this.$element.trigger('focus')
+ }
+ }, this))
+ }
+
+ Modal.prototype.escape = function () {
+ if (this.isShown && this.options.keyboard) {
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
+ e.which == 27 && this.hide()
+ }, this))
+ } else if (!this.isShown) {
+ this.$element.off('keydown.dismiss.bs.modal')
+ }
+ }
+
+ Modal.prototype.resize = function () {
+ if (this.isShown) {
+ $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
+ } else {
+ $(window).off('resize.bs.modal')
+ }
+ }
+
+ Modal.prototype.hideModal = function () {
+ var that = this
+ this.$element.hide()
+ this.backdrop(function () {
+ that.$body.removeClass('modal-open')
+ that.resetAdjustments()
+ that.resetScrollbar()
+ that.$element.trigger('hidden.bs.modal')
+ })
+ }
+
+ Modal.prototype.removeBackdrop = function () {
+ this.$backdrop && this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ Modal.prototype.backdrop = function (callback) {
+ var that = this
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $(document.createElement('div'))
+ .addClass('modal-backdrop ' + animate)
+ .appendTo(this.$body)
+
+ this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+ if (this.ignoreBackdropClick) {
+ this.ignoreBackdropClick = false
+ return
+ }
+ if (e.target !== e.currentTarget) return
+ this.options.backdrop == 'static'
+ ? this.$element[0].focus()
+ : this.hide()
+ }, this))
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ if (!callback) return
+
+ doAnimate ?
+ this.$backdrop
+ .one('bsTransitionEnd', callback)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ var callbackRemove = function () {
+ that.removeBackdrop()
+ callback && callback()
+ }
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$backdrop
+ .one('bsTransitionEnd', callbackRemove)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callbackRemove()
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ // these following methods are used to handle overflowing modals
+
+ Modal.prototype.handleUpdate = function () {
+ this.adjustDialog()
+ }
+
+ Modal.prototype.adjustDialog = function () {
+ var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
+
+ this.$element.css({
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
+ paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
+ })
+ }
+
+ Modal.prototype.resetAdjustments = function () {
+ this.$element.css({
+ paddingLeft: '',
+ paddingRight: ''
+ })
+ }
+
+ Modal.prototype.checkScrollbar = function () {
+ var fullWindowWidth = window.innerWidth
+ if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
+ var documentElementRect = document.documentElement.getBoundingClientRect()
+ fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
+ }
+ this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
+ this.scrollbarWidth = this.measureScrollbar()
+ }
+
+ Modal.prototype.setScrollbar = function () {
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+ this.originalBodyPad = document.body.style.paddingRight || ''
+ if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
+ }
+
+ Modal.prototype.resetScrollbar = function () {
+ this.$body.css('padding-right', this.originalBodyPad)
+ }
+
+ Modal.prototype.measureScrollbar = function () { // thx walsh
+ var scrollDiv = document.createElement('div')
+ scrollDiv.className = 'modal-scrollbar-measure'
+ this.$body.append(scrollDiv)
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+ this.$body[0].removeChild(scrollDiv)
+ return scrollbarWidth
+ }
+
+
+ // MODAL PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option, _relatedTarget) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.modal')
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option](_relatedTarget)
+ else if (options.show) data.show(_relatedTarget)
+ })
+ }
+
+ var old = $.fn.modal
+
+ $.fn.modal = Plugin
+ $.fn.modal.Constructor = Modal
+
+
+ // MODAL NO CONFLICT
+ // =================
+
+ $.fn.modal.noConflict = function () {
+ $.fn.modal = old
+ return this
+ }
+
+
+ // MODAL DATA-API
+ // ==============
+
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+ var $this = $(this)
+ var href = $this.attr('href')
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+ if ($this.is('a')) e.preventDefault()
+
+ $target.one('show.bs.modal', function (showEvent) {
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+ $target.one('hidden.bs.modal', function () {
+ $this.is(':visible') && $this.trigger('focus')
+ })
+ })
+ Plugin.call($target, option, this)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.3.6
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TOOLTIP PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Tooltip = function (element, options) {
+ this.type = null
+ this.options = null
+ this.enabled = null
+ this.timeout = null
+ this.hoverState = null
+ this.$element = null
+ this.inState = null
+
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.VERSION = '3.3.6'
+
+ Tooltip.TRANSITION_DURATION = 150
+
+ Tooltip.DEFAULTS = {
+ animation: true,
+ placement: 'top',
+ selector: false,
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+ trigger: 'hover focus',
+ title: '',
+ delay: 0,
+ html: false,
+ container: false,
+ viewport: {
+ selector: 'body',
+ padding: 0
+ }
+ }
+
+ Tooltip.prototype.init = function (type, element, options) {
+ this.enabled = true
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
+ this.inState = { click: false, hover: false, focus: false }
+
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
+ }
+
+ var triggers = this.options.trigger.split(' ')
+
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i]
+
+ if (trigger == 'click') {
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+ } else if (trigger != 'manual') {
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+ }
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ Tooltip.prototype.getDefaults = function () {
+ return Tooltip.DEFAULTS
+ }
+
+ Tooltip.prototype.getOptions = function (options) {
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay,
+ hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ Tooltip.prototype.getDelegateOptions = function () {
+ var options = {}
+ var defaults = this.getDefaults()
+
+ this._options && $.each(this._options, function (key, value) {
+ if (defaults[key] != value) options[key] = value
+ })
+
+ return options
+ }
+
+ Tooltip.prototype.enter = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
+ }
+
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
+ self.hoverState = 'in'
+ return
+ }
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'in'
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ Tooltip.prototype.isInStateTrue = function () {
+ for (var key in this.inState) {
+ if (this.inState[key]) return true
+ }
+
+ return false
+ }
+
+ Tooltip.prototype.leave = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
+ }
+
+ if (self.isInStateTrue()) return
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'out'
+
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ Tooltip.prototype.show = function () {
+ var e = $.Event('show.bs.' + this.type)
+
+ if (this.hasContent() && this.enabled) {
+ this.$element.trigger(e)
+
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
+ if (e.isDefaultPrevented() || !inDom) return
+ var that = this
+
+ var $tip = this.tip()
+
+ var tipId = this.getUID(this.type)
+
+ this.setContent()
+ $tip.attr('id', tipId)
+ this.$element.attr('aria-describedby', tipId)
+
+ if (this.options.animation) $tip.addClass('fade')
+
+ var placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ var autoToken = /\s?auto?\s?/i
+ var autoPlace = autoToken.test(placement)
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+ $tip
+ .detach()
+ .css({ top: 0, left: 0, display: 'block' })
+ .addClass(placement)
+ .data('bs.' + this.type, this)
+
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+ this.$element.trigger('inserted.bs.' + this.type)
+
+ var pos = this.getPosition()
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (autoPlace) {
+ var orgPlacement = placement
+ var viewportDim = this.getPosition(this.$viewport)
+
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
+ placement
+
+ $tip
+ .removeClass(orgPlacement)
+ .addClass(placement)
+ }
+
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+ this.applyPlacement(calculatedOffset, placement)
+
+ var complete = function () {
+ var prevHoverState = that.hoverState
+ that.$element.trigger('shown.bs.' + that.type)
+ that.hoverState = null
+
+ if (prevHoverState == 'out') that.leave(that)
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+ }
+ }
+
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
+ var $tip = this.tip()
+ var width = $tip[0].offsetWidth
+ var height = $tip[0].offsetHeight
+
+ // manually read margins because getBoundingClientRect includes difference
+ var marginTop = parseInt($tip.css('margin-top'), 10)
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+ // we must check for NaN for ie 8/9
+ if (isNaN(marginTop)) marginTop = 0
+ if (isNaN(marginLeft)) marginLeft = 0
+
+ offset.top += marginTop
+ offset.left += marginLeft
+
+ // $.fn.offset doesn't round pixel values
+ // so we use setOffset directly with our own function B-0
+ $.offset.setOffset($tip[0], $.extend({
+ using: function (props) {
+ $tip.css({
+ top: Math.round(props.top),
+ left: Math.round(props.left)
+ })
+ }
+ }, offset), 0)
+
+ $tip.addClass('in')
+
+ // check to see if placing tip in new offset caused the tip to resize itself
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (placement == 'top' && actualHeight != height) {
+ offset.top = offset.top + height - actualHeight
+ }
+
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+ if (delta.left) offset.left += delta.left
+ else offset.top += delta.top
+
+ var isVertical = /top|bottom/.test(placement)
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
+
+ $tip.offset(offset)
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
+ }
+
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
+ this.arrow()
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isVertical ? 'top' : 'left', '')
+ }
+
+ Tooltip.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ Tooltip.prototype.hide = function (callback) {
+ var that = this
+ var $tip = $(this.$tip)
+ var e = $.Event('hide.bs.' + this.type)
+
+ function complete() {
+ if (that.hoverState != 'in') $tip.detach()
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ callback && callback()
+ }
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $tip.removeClass('in')
+
+ $.support.transition && $tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+
+ this.hoverState = null
+
+ return this
+ }
+
+ Tooltip.prototype.fixTitle = function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+ }
+ }
+
+ Tooltip.prototype.hasContent = function () {
+ return this.getTitle()
+ }
+
+ Tooltip.prototype.getPosition = function ($element) {
+ $element = $element || this.$element
+
+ var el = $element[0]
+ var isBody = el.tagName == 'BODY'
+
+ var elRect = el.getBoundingClientRect()
+ if (elRect.width == null) {
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+ }
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
+ }
+
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
+
+ }
+
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+ var delta = { top: 0, left: 0 }
+ if (!this.$viewport) return delta
+
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+ var viewportDimensions = this.getPosition(this.$viewport)
+
+ if (/right|left/.test(placement)) {
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
+ delta.top = viewportDimensions.top - topEdgeOffset
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+ }
+ } else {
+ var leftEdgeOffset = pos.left - viewportPadding
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+ delta.left = viewportDimensions.left - leftEdgeOffset
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+ }
+ }
+
+ return delta
+ }
+
+ Tooltip.prototype.getTitle = function () {
+ var title
+ var $e = this.$element
+ var o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ Tooltip.prototype.getUID = function (prefix) {
+ do prefix += ~~(Math.random() * 1000000)
+ while (document.getElementById(prefix))
+ return prefix
+ }
+
+ Tooltip.prototype.tip = function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ if (this.$tip.length != 1) {
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
+ }
+ }
+ return this.$tip
+ }
+
+ Tooltip.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+ }
+
+ Tooltip.prototype.enable = function () {
+ this.enabled = true
+ }
+
+ Tooltip.prototype.disable = function () {
+ this.enabled = false
+ }
+
+ Tooltip.prototype.toggleEnabled = function () {
+ this.enabled = !this.enabled
+ }
+
+ Tooltip.prototype.toggle = function (e) {
+ var self = this
+ if (e) {
+ self = $(e.currentTarget).data('bs.' + this.type)
+ if (!self) {
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+ $(e.currentTarget).data('bs.' + this.type, self)
+ }
+ }
+
+ if (e) {
+ self.inState.click = !self.inState.click
+ if (self.isInStateTrue()) self.enter(self)
+ else self.leave(self)
+ } else {
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+ }
+ }
+
+ Tooltip.prototype.destroy = function () {
+ var that = this
+ clearTimeout(this.timeout)
+ this.hide(function () {
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ if (that.$tip) {
+ that.$tip.detach()
+ }
+ that.$tip = null
+ that.$arrow = null
+ that.$viewport = null
+ })
+ }
+
+
+ // TOOLTIP PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tooltip')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tooltip
+
+ $.fn.tooltip = Plugin
+ $.fn.tooltip.Constructor = Tooltip
+
+
+ // TOOLTIP NO CONFLICT
+ // ===================
+
+ $.fn.tooltip.noConflict = function () {
+ $.fn.tooltip = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.3.6
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // POPOVER PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+ Popover.VERSION = '3.3.6'
+
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+ placement: 'right',
+ trigger: 'click',
+ content: '',
+ template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ })
+
+
+ // NOTE: POPOVER EXTENDS tooltip.js
+ // ================================
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+ Popover.prototype.constructor = Popover
+
+ Popover.prototype.getDefaults = function () {
+ return Popover.DEFAULTS
+ }
+
+ Popover.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+ var content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+ ](content)
+
+ $tip.removeClass('fade top bottom left right in')
+
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+ // this manually by checking the contents.
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+ }
+
+ Popover.prototype.hasContent = function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ Popover.prototype.getContent = function () {
+ var $e = this.$element
+ var o = this.options
+
+ return $e.attr('data-content')
+ || (typeof o.content == 'function' ?
+ o.content.call($e[0]) :
+ o.content)
+ }
+
+ Popover.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+ }
+
+
+ // POPOVER PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.popover
+
+ $.fn.popover = Plugin
+ $.fn.popover.Constructor = Popover
+
+
+ // POPOVER NO CONFLICT
+ // ===================
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.3.6
+ * http://getbootstrap.com/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // SCROLLSPY CLASS DEFINITION
+ // ==========================
+
+ function ScrollSpy(element, options) {
+ this.$body = $(document.body)
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
+ this.selector = (this.options.target || '') + ' .nav li > a'
+ this.offsets = []
+ this.targets = []
+ this.activeTarget = null
+ this.scrollHeight = 0
+
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.VERSION = '3.3.6'
+
+ ScrollSpy.DEFAULTS = {
+ offset: 10
+ }
+
+ ScrollSpy.prototype.getScrollHeight = function () {
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+ }
+
+ ScrollSpy.prototype.refresh = function () {
+ var that = this
+ var offsetMethod = 'offset'
+ var offsetBase = 0
+
+ this.offsets = []
+ this.targets = []
+ this.scrollHeight = this.getScrollHeight()
+
+ if (!$.isWindow(this.$scrollElement[0])) {
+ offsetMethod = 'position'
+ offsetBase = this.$scrollElement.scrollTop()
+ }
+
+ this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ var href = $el.data('target') || $el.attr('href')
+ var $href = /^#./.test(href) && $(href)
+
+ return ($href
+ && $href.length
+ && $href.is(':visible')
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ that.offsets.push(this[0])
+ that.targets.push(this[1])
+ })
+ }
+
+ ScrollSpy.prototype.process = function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ var scrollHeight = this.getScrollHeight()
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
+ var offsets = this.offsets
+ var targets = this.targets
+ var activeTarget = this.activeTarget
+ var i
+
+ if (this.scrollHeight != scrollHeight) {
+ this.refresh()
+ }
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+ }
+
+ if (activeTarget && scrollTop < offsets[0]) {
+ this.activeTarget = null
+ return this.clear()
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
+ && this.activate(targets[i])
+ }
+ }
+
+ ScrollSpy.prototype.activate = function (target) {
+ this.activeTarget = target
+
+ this.clear()
+
+ var selector = this.selector +
+ '[data-target="' + target + '"],' +
+ this.selector + '[href="' + target + '"]'
+
+ var active = $(selector)
+ .parents('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active
+ .closest('li.dropdown')
+ .addClass('active')
+ }
+
+ active.trigger('activate.bs.scrollspy')
+ }
+
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
+
+ // SCROLLSPY PLUGIN DEFINITION
+ // ===========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.scrollspy')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.scrollspy
+
+ $.fn.scrollspy = Plugin
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+
+ // SCROLLSPY NO CONFLICT
+ // =====================
+
+ $.fn.scrollspy.noConflict = function () {
+ $.fn.scrollspy = old
+ return this
+ }
+
+
+ // SCROLLSPY DATA-API
+ // ==================
+
+ $(window).on('load.bs.scrollspy.data-api', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ Plugin.call($spy, $spy.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.3.6
+ * http://getbootstrap.com/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TAB CLASS DEFINITION
+ // ====================
+
+ var Tab = function (element) {
+ // jscs:disable requireDollarBeforejQueryAssignment
+ this.element = $(element)
+ // jscs:enable requireDollarBeforejQueryAssignment
+ }
+
+ Tab.VERSION = '3.3.6'
+
+ Tab.TRANSITION_DURATION = 150
+
+ Tab.prototype.show = function () {
+ var $this = this.element
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
+ var selector = $this.data('target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ if ($this.parent('li').hasClass('active')) return
+
+ var $previous = $ul.find('.active:last a')
+ var hideEvent = $.Event('hide.bs.tab', {
+ relatedTarget: $this[0]
+ })
+ var showEvent = $.Event('show.bs.tab', {
+ relatedTarget: $previous[0]
+ })
+
+ $previous.trigger(hideEvent)
+ $this.trigger(showEvent)
+
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
+
+ var $target = $(selector)
+
+ this.activate($this.closest('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $previous.trigger({
+ type: 'hidden.bs.tab',
+ relatedTarget: $this[0]
+ })
+ $this.trigger({
+ type: 'shown.bs.tab',
+ relatedTarget: $previous[0]
+ })
+ })
+ }
+
+ Tab.prototype.activate = function (element, container, callback) {
+ var $active = container.find('> .active')
+ var transition = callback
+ && $.support.transition
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', false)
+
+ element
+ .addClass('active')
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if (element.parent('.dropdown-menu').length) {
+ element
+ .closest('li.dropdown')
+ .addClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+ }
+
+ callback && callback()
+ }
+
+ $active.length && transition ?
+ $active
+ .one('bsTransitionEnd', next)
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
+ next()
+
+ $active.removeClass('in')
+ }
+
+
+ // TAB PLUGIN DEFINITION
+ // =====================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tab')
+
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tab
+
+ $.fn.tab = Plugin
+ $.fn.tab.Constructor = Tab
+
+
+ // TAB NO CONFLICT
+ // ===============
+
+ $.fn.tab.noConflict = function () {
+ $.fn.tab = old
+ return this
+ }
+
+
+ // TAB DATA-API
+ // ============
+
+ var clickHandler = function (e) {
+ e.preventDefault()
+ Plugin.call($(this), 'show')
+ }
+
+ $(document)
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.3.6
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // AFFIX CLASS DEFINITION
+ // ======================
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, Affix.DEFAULTS, options)
+
+ this.$target = $(this.options.target)
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
+
+ this.$element = $(element)
+ this.affixed = null
+ this.unpin = null
+ this.pinnedOffset = null
+
+ this.checkPosition()
+ }
+
+ Affix.VERSION = '3.3.6'
+
+ Affix.RESET = 'affix affix-top affix-bottom'
+
+ Affix.DEFAULTS = {
+ offset: 0,
+ target: window
+ }
+
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
+ Affix.prototype.getPinnedOffset = function () {
+ if (this.pinnedOffset) return this.pinnedOffset
+ this.$element.removeClass(Affix.RESET).addClass('affix')
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ return (this.pinnedOffset = position.top - scrollTop)
+ }
+
+ Affix.prototype.checkPositionWithEventLoop = function () {
+ setTimeout($.proxy(this.checkPosition, this), 1)
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var height = this.$element.height()
+ var offset = this.options.offset
+ var offsetTop = offset.top
+ var offsetBottom = offset.bottom
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
+
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
+
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
+
+ if (affix == 'bottom') {
+ this.$element.offset({
+ top: scrollHeight - height - offsetBottom
+ })
+ }
+ }
+
+
+ // AFFIX PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.affix')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.affix
+
+ $.fn.affix = Plugin
+ $.fn.affix.Constructor = Affix
+
+
+ // AFFIX NO CONFLICT
+ // =================
+
+ $.fn.affix.noConflict = function () {
+ $.fn.affix = old
+ return this
+ }
+
+
+ // AFFIX DATA-API
+ // ==============
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ var data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
+
+ Plugin.call($spy, data)
+ })
+ })
+
+}(jQuery);
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.min.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.min.js
index 848258d38..c4a924160 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.min.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/bootstrap.min.js
@@ -1,6 +1,7 @@
/*!
-* Bootstrap.js by @fat & @mdo
-* Copyright 2013 Twitter, Inc.
-* http://www.apache.org/licenses/LICENSE-2.0.txt
-*/
-!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>this.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children()[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(".dropdown-backdrop").remove(),e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||("ontouchstart"in document.documentElement&&e('<div class="dropdown-backdrop"/>').insertBefore(e(this)).on("click",r),s.toggleClass("open")),n.focus(),!1},keydown:function(n){var r,s,o,u,a,f;if(!/(38|40|27)/.test(n.keyCode))return;r=e(this),n.preventDefault(),n.stopPropagation();if(r.is(".disabled, :disabled"))return;u=i(r),a=u.hasClass("open");if(!a||a&&n.keyCode==27)return n.which==27&&u.find(t).focus(),r.click();s=e("[role=menu] li:not(.divider):visible a",u);if(!s.length)return;f=s.index(s.filter(":focus")),n.keyCode==38&&f>0&&f--,n.keyCode==40&&f<s.length-1&&f++,~f||(f=0),s.eq(f).focus()}};var s=e.fn.dropdown;e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e.fn.dropdown.noConflict=function(){return e.fn.dropdown=s,this},e(document).on("click.dropdown.data-api",r).on("click.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$element[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.$element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(){var e=this;this.$element.hide(),this.backdrop(function(){e.removeBackdrop(),e.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!t)return;i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,t):t()):t&&t()}};var n=e.fn.modal;e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e.fn.modal.noConflict=function(){return e.fn.modal=n,this},e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s,o,u,a;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,o=this.options.trigger.split(" ");for(a=o.length;a--;)u=o[a],u=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):u!="manual"&&(i=u=="hover"?"mouseenter":"focus",s=u=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this)));this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,this.$element.data(),t),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e.fn[this.type].defaults,r={},i;this._options&&e.each(this._options,function(e,t){n[e]!=t&&(r[e]=t)},this),i=e(t.currentTarget)[this.type](r).data(this.type);if(!i.options.delay||!i.options.delay.show)return i.show();clearTimeout(this.timeout),i.hoverState="in",this.timeout=setTimeout(function(){i.hoverState=="in"&&i.show()},i.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var t,n,r,i,s,o,u=e.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(u);if(u.isDefaultPrevented())return;t=this.tip(),this.setContent(),this.options.animation&&t.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,t[0],this.$element[0]):this.options.placement,t.detach().css({top:0,left:0,display:"block"}),this.options.container?t.appendTo(this.options.container):t.insertAfter(this.$element),n=this.getPosition(),r=t[0].offsetWidth,i=t[0].offsetHeight;switch(s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}this.applyPlacement(o,s),this.$element.trigger("shown")}},applyPlacement:function(e,t){var n=this.tip(),r=n[0].offsetWidth,i=n[0].offsetHeight,s,o,u,a;n.offset(e).addClass(t).addClass("in"),s=n[0].offsetWidth,o=n[0].offsetHeight,t=="top"&&o!=i&&(e.top=e.top+i-o,a=!0),t=="bottom"||t=="top"?(u=0,e.left<0&&(u=e.left*-2,e.left=0,n.offset(e),s=n[0].offsetWidth,o=n[0].offsetHeight),this.replaceArrow(u-r+s,s,"left")):this.replaceArrow(o-i,o,"top"),a&&n.offset(e)},replaceArrow:function(e,t,n){this.arrow().css(n,e?50*(1-e/t)+"%":"")},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function i(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip(),r=e.Event("hide");this.$element.trigger(r);if(r.isDefaultPrevented())return;return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?i():n.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var t=this.$element[0];return e.extend({},typeof t.getBoundingClientRect=="function"?t.getBoundingClientRect():{width:t.offsetWidth,height:t.offsetHeight},this.$element.offset())},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=t?e(t.currentTarget)[this.type](this._options).data(this.type):this;n.tip().hasClass("in")?n.hide():n.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var n=e.fn.tooltip;e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},e.fn.tooltip.noConflict=function(){return e.fn.tooltip=n,this}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=(typeof n.content=="function"?n.content.call(t[0]):n.content)||t.attr("data-content"),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var n=e.fn.popover;e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),e.fn.popover.noConflict=function(){return e.fn.popover=n,this}}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var n=e(this),r=n.data("target")||n.attr("href"),i=/^#\w/.test(r)&&e(r);return i&&i.length&&[[i.position().top+(!e.isWindow(t.$scrollElement.get(0))&&t.$scrollElement.scrollTop()),r]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}};var n=e.fn.scrollspy;e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=n,this},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}};var n=e.fn.tab;e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e.fn.tab.noConflict=function(){return e.fn.tab=n,this},e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=e(this.options.menu),this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery); \ No newline at end of file
+ * Bootstrap v3.3.6 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>2)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 3")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.6",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.6",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),a(c.target).is('input[type="radio"]')||a(c.target).is('input[type="checkbox"]')||c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.6",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.6",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.6",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.6",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),c.isInStateTrue()?void 0:(clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide())},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);return this.$element.trigger(g),g.isDefaultPrevented()?void 0:(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this)},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=d?{top:0,left:0}:b.offset(),g={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},h=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,g,h,f)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.6",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.6",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),
+d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.6",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.6",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); \ No newline at end of file
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
index 1c0ef9e37..9ea960288 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
@@ -158,7 +158,7 @@ function customRecipePageInit(ctx) {
msg += " <strong>" + dep.name + "</strong>";
/* Add any cells currently in view to the list of cells which get
- * an inline notification inside them and which change add/rm state
+ * an list-inline notification inside them and which change add/rm state
*/
depBtnCell = $("#package-btn-cell-" + dep.pk);
btnCell = btnCell.add(depBtnCell);
@@ -208,7 +208,7 @@ function customRecipePageInit(ctx) {
}
/* Add any cells currently in view to the list of cells which get
- * an inline notification inside them and which change add/rm state
+ * an list-inline notification inside them and which change add/rm state
*/
depBtnCell = $("#package-btn-cell-" + dep.pk);
btnCell = btnCell.add(depBtnCell);
@@ -281,4 +281,36 @@ function customRecipePageInit(ctx) {
window.location.replace(libtoaster.ctx.projectBuildsUrl);
});
});
+
+ $("#delete-custom-recipe-confirmed").click(function(e){
+ e.preventDefault();
+ libtoaster.disableAjaxLoadingTimer();
+ $(this).find('[data-role="submit-state"]').hide();
+ $(this).find('[data-role="loading-state"]').show();
+ $(this).attr("disabled", "disabled");
+
+ $.ajax({
+ type: 'DELETE',
+ url: ctx.recipe.xhrCustomRecipeUrl,
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function (data) {
+ if (data.error !== "ok") {
+ console.warn(data.error);
+ } else {
+ var msg = $('<span>You have deleted <strong>1</strong> custom image: <strong id="deleted-custom-image-name"></strong></span>');
+ msg.find("#deleted-custom-image-name").text(ctx.recipe.name);
+
+ libtoaster.setNotification("custom-image-recipe-deleted",
+ msg.html());
+
+ window.location.replace(data.gotoUrl);
+ }
+ },
+ error: function (data) {
+ console.warn(data);
+ }
+ });
+ });
+
+
}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js
index 5a59799bc..30dc28280 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/importlayer.js
@@ -10,45 +10,31 @@ function importLayerPageInit (ctx) {
var layerDepInput = $("#layer-dependency");
var layerNameCtrl = $("#layer-name-ctrl");
var duplicatedLayerName = $("#duplicated-layer-name-hint");
+ var localDirPath = $("#local-dir-path");
var layerDeps = {};
var layerDepsDeps = {};
var currentLayerDepSelection;
var validLayerName = /^(\w|-)+$/;
- libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.layersTypeAheadUrl, { include_added: "true" }, function(item){
+ libtoaster.makeTypeahead(layerDepInput,
+ libtoaster.ctx.layersTypeAheadUrl,
+ { include_added: "true" }, function(item){
currentLayerDepSelection = item;
+ layerDepBtn.removeAttr("disabled");
});
- // choices available in the typeahead
- var layerDepsChoices = {};
-
- // when the typeahead choices change, store an array of the available layer
- // choices locally, to use for enabling/disabling the "Add layer" button
- layerDepInput.on("typeahead-choices-change", function (event, data) {
- layerDepsChoices = {};
-
- if (data.choices) {
- data.choices.forEach(function (item) {
- layerDepsChoices[item.name] = item;
- });
- }
+ layerDepInput.on("typeahead:select", function(event, data){
+ currentLayerDepSelection = data;
});
+ // Disable local dir repo when page is loaded.
+ $('#local-dir').hide();
+
// disable the "Add layer" button when the layer input typeahead is empty
// or not in the typeahead choices
- layerDepInput.on("input change", function () {
- // get the choices from the typeahead
- var choice = layerDepsChoices[$(this).val()];
-
- if (choice) {
- layerDepBtn.removeAttr("disabled");
- currentLayerDepSelection = choice;
- }
- else {
- layerDepBtn.attr("disabled", "disabled");
- currentLayerDepSelection = undefined;
- }
+ layerDepInput.on("input change", function(){
+ layerDepBtn.attr("disabled","disabled");
});
/* We automatically add "openembedded-core" layer for convenience as a
@@ -70,7 +56,7 @@ function importLayerPageInit (ctx) {
layerDeps[currentLayerDepSelection.id] = currentLayerDepSelection;
/* Make a list item for the new layer dependency */
- var newLayerDep = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>");
+ var newLayerDep = $("<li><a></a><span class=\"glyphicon glyphicon-trash\" data-toggle=\"tooltip\" title=\"Remove\"></span></li>");
newLayerDep.data('layer-id', currentLayerDepSelection.id);
newLayerDep.children("span").tooltip();
@@ -91,7 +77,8 @@ function importLayerPageInit (ctx) {
$("#layer-deps-list").append(newLayerDep);
- libtoaster.getLayerDepsForProject(currentLayerDepSelection.layerdetailurl, function (data){
+ libtoaster.getLayerDepsForProject(currentLayerDepSelection.layerdetailurl,
+ function (data){
/* These are the dependencies of the layer added as a dependency */
if (data.list.length > 0) {
currentLayerDepSelection.url = currentLayerDepSelection.layerdetailurl;
@@ -105,7 +92,8 @@ function importLayerPageInit (ctx) {
}, null);
});
- importAndAddBtn.click(function(){
+ importAndAddBtn.click(function(e){
+ e.preventDefault();
/* This is a list of the names from layerDeps for the layer deps
* modal dialog body
*/
@@ -145,7 +133,9 @@ function importLayerPageInit (ctx) {
var body = "<strong>"+layer.name+"</strong>'s dependencies ("+
depNames.join(", ")+"</span>) require some layers that are not added to your project. Select the ones you want to add:</p>";
- showLayerDepsModal(layer, depDepsArray, title, body, false, function(layerObsList){
+ showLayerDepsModal(layer,
+ depDepsArray,
+ title, body, false, function(layerObsList){
/* Add the accepted layer dependencies' ids to the allDeps array */
for (var key in layerObsList){
allDeps.push(layerObsList[key].id);
@@ -167,8 +157,16 @@ function importLayerPageInit (ctx) {
dir_path: $("#layer-subdir").val(),
project_id: libtoaster.ctx.projectId,
layer_deps: layerDepsCsv,
+ local_source_dir: $('#local-dir-path').val(),
};
+ if ($('input[name=repo]:checked').val() == "git") {
+ layerData.local_source_dir = "";
+ } else {
+ layerData.vcs_url = "";
+ layerData.git_ref = "";
+ }
+
$.ajax({
type: "POST",
url: ctx.xhrImportLayerUrl,
@@ -178,9 +176,8 @@ function importLayerPageInit (ctx) {
if (data.error != "ok") {
console.log(data.error);
} else {
- /* Success layer import now go to the project page */
- $.cookie('layer-imported-alert', JSON.stringify(data), { path: '/'});
- window.location.replace(libtoaster.ctx.projectPageUrl+'?notify=layer-imported');
+ createImportedNotification(data);
+ window.location.replace(libtoaster.ctx.projectPageUrl);
}
},
error: function (data) {
@@ -191,6 +188,30 @@ function importLayerPageInit (ctx) {
}
});
+ /* Layer imported notification */
+ function createImportedNotification(imported){
+ var message = "Layer imported";
+
+ if (imported.deps_added.length === 0) {
+ message = "You have imported <strong><a class=\"alert-link\" href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a></strong> and added it to your project.";
+ } else {
+
+ var links = "<a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a>, ";
+
+ imported.deps_added.map (function(item, index){
+ links +='<a href="'+item.layerdetailurl+'">'+item.name+'</a>';
+ /*If we're at the last element we don't want the trailing comma */
+ if (imported.deps_added[index+1] !== undefined)
+ links += ', ';
+ });
+
+ /* Length + 1 here to do deps + the imported layer */
+ message = 'You have imported <strong><a href="'+imported.imported_layer.layerdetailurl+'">'+imported.imported_layer.name+'</a></strong> and added <strong>'+(imported.deps_added.length+1)+'</strong> layers to your project: <strong>'+links+'</strong>';
+ }
+
+ libtoaster.setNotification("layer-imported", message);
+ }
+
function enable_import_btn(enabled) {
var importAndAddHint = $("#import-and-add-hint");
@@ -207,25 +228,48 @@ function importLayerPageInit (ctx) {
function check_form() {
var valid = false;
var inputs = $("input:required");
+ var inputStr = inputs.val().split("");
- for (var i=0; i<inputs.length; i++){
- if (!(valid = inputs[i].value)){
+ for (var i=0; i<inputs.val().length; i++){
+ if (!(valid = inputStr[i])){
enable_import_btn(false);
break;
}
}
- if (valid)
- enable_import_btn(true);
+ if (valid) {
+ if ($("#local-dir-radio").prop("checked") &&
+ localDirPath.val().length > 0) {
+ enable_import_btn(true);
+ }
+
+ if ($("#git-repo-radio").prop("checked") &&
+ vcsURLInput.val().length > 0 && gitRefInput.val().length > 0) {
+ enable_import_btn(true);
+ }
+ }
+
+ if (inputs.val().length == 0)
+ enable_import_btn(false);
}
function layerExistsError(layer){
var dupLayerInfo = $("#duplicate-layer-info");
- dupLayerInfo.find(".dup-layer-name").text(layer.name);
- dupLayerInfo.find(".dup-layer-link").attr("href", layer.layerdetailurl);
- dupLayerInfo.find("#dup-layer-vcs-url").text(layer.vcs_url);
- dupLayerInfo.find("#dup-layer-revision").text(layer.vcs_reference);
+ if (layer.local_source_dir) {
+ $("#git-layer-dup").hide();
+ $("#local-layer-dup").fadeIn();
+ dupLayerInfo.find(".dup-layer-name").text(layer.name);
+ dupLayerInfo.find(".dup-layer-link").attr("href", layer.layerdetailurl);
+ dupLayerInfo.find("#dup-local-source-dir-name").text(layer.local_source_dir);
+ } else {
+ $("#git-layer-dup").fadeIn();
+ $("#local-layer-dup").hide();
+ dupLayerInfo.find(".dup-layer-name").text(layer.name);
+ dupLayerInfo.find(".dup-layer-link").attr("href", layer.layerdetailurl);
+ dupLayerInfo.find("#dup-layer-vcs-url").text(layer.vcs_url);
+ dupLayerInfo.find("#dup-layer-revision").text(layer.vcs_reference);
+ }
$(".fields-apart-from-layer-name").fadeOut(function(){
dupLayerInfo.fadeIn();
@@ -233,13 +277,13 @@ function importLayerPageInit (ctx) {
}
layerNameInput.on('blur', function() {
- if (!$(this).val()){
- return;
- }
- var name = $(this).val();
+ if (!$(this).val()){
+ return;
+ }
+ var name = $(this).val();
- /* Check if the layer name exists */
- $.getJSON(libtoaster.ctx.layersTypeAheadUrl,
+ /* Check if the layer name exists */
+ $.getJSON(libtoaster.ctx.layersTypeAheadUrl,
{ include_added: "true" , search: name, format: "json" },
function(layer) {
if (layer.results.length > 0) {
@@ -262,7 +306,7 @@ function importLayerPageInit (ctx) {
layerNameInput.on('input', function() {
if ($(this).val() && !validLayerName.test($(this).val())){
- layerNameCtrl.addClass("error")
+ layerNameCtrl.addClass("has-error")
$("#invalid-layer-name-hint").show();
enable_import_btn(false);
return;
@@ -270,16 +314,19 @@ function importLayerPageInit (ctx) {
if ($("#duplicate-layer-info").css("display") != "None"){
$("#duplicate-layer-info").fadeOut(function(){
- $(".fields-apart-from-layer-name").show();
- });
+ $(".fields-apart-from-layer-name").show();
+ radioDisplay();
+ });
- }
+ }
+
+ radioDisplay();
/* Don't remove the error class if we're displaying the error for another
* reason.
*/
if (!duplicatedLayerName.is(":visible"))
- layerNameCtrl.removeClass("error")
+ layerNameCtrl.removeClass("has-error")
$("#invalid-layer-name-hint").hide();
check_form();
@@ -300,4 +347,72 @@ function importLayerPageInit (ctx) {
}
});
+ function radioDisplay() {
+ if ($('input[name=repo]:checked').val() == "local") {
+ $('#git-repo').hide();
+ $('#import-git-layer-and-add-hint').hide();
+ $('#local-dir').fadeIn();
+ $('#import-local-dir-and-add-hint').fadeIn();
+ } else {
+ $('#local-dir').hide();
+ $('#import-local-dir-and-add-hint').hide();
+ $('#git-repo').fadeIn();
+ $('#import-git-layer-and-add-hint').fadeIn();
+ }
+ }
+
+ $('input:radio[name="repo"]').change(function() {
+ radioDisplay();
+ if ($("#local-dir-radio").prop("checked")) {
+ if (localDirPath.val().length > 0) {
+ enable_import_btn(true);
+ } else {
+ enable_import_btn(false);
+ }
+ }
+ if ($("#git-repo-radio").prop("checked")) {
+ if (vcsURLInput.val().length > 0 && gitRefInput.val().length > 0) {
+ enable_import_btn(true);
+ } else {
+ enable_import_btn(false);
+ }
+ }
+ });
+
+ localDirPath.on('input', function(){
+ if ($(this).val().trim().length == 0) {
+ $('#import-and-add-btn').attr("disabled","disabled");
+ $('#local-dir').addClass('has-error');
+ $('#hintError-dir-abs-path').show();
+ $('#hintError-dir-path-starts-with-slash').show();
+ } else {
+ var input = $(this);
+ var reBeginWithSlash = /^\//;
+ var reCheckVariable = /^\$/;
+ var re = /([ <>\\|":\.%\?\*]+)/;
+
+ var invalidDir = re.test(input.val());
+ var invalidSlash = reBeginWithSlash.test(input.val());
+ var invalidVar = reCheckVariable.test(input.val());
+
+ if (!invalidSlash && !invalidVar) {
+ $('#local-dir').addClass('has-error');
+ $('#import-and-add-btn').attr("disabled","disabled");
+ $('#hintError-dir-abs-path').show();
+ $('#hintError-dir-path-starts-with-slash').show();
+ } else if (invalidDir) {
+ $('#local-dir').addClass('has-error');
+ $('#import-and-add-btn').attr("disabled","disabled");
+ $('#hintError-dir-path').show();
+ } else {
+ $('#local-dir').removeClass('has-error');
+ if (layerNameInput.val().length > 0) {
+ $('#import-and-add-btn').removeAttr("disabled");
+ }
+ $('#hintError-dir-abs-path').hide();
+ $('#hintError-dir-path-starts-with-slash').hide();
+ $('#hintError-dir-path').hide();
+ }
+ }
+ });
}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/jsrender.min.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/jsrender.min.js
new file mode 100644
index 000000000..87cac4eb3
--- /dev/null
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/jsrender.min.js
@@ -0,0 +1,4 @@
+/*! JsRender v0.9.78 (Beta): http://jsviews.com/#jsrender */
+/*! **VERSION FOR WEB** (For NODE.JS see http://jsviews.com/download/jsrender-node.js) */
+!function(e,t){var n=t.jQuery;"object"==typeof exports?module.exports=n?e(t,n):function(n){if(n&&!n.fn)throw"Provide jQuery or null";return e(t,n)}:"function"==typeof define&&define.amd?define(function(){return e(t)}):e(t,!1)}(function(e,t){"use strict";function n(e,t){return function(){var n,r=this,i=r.base;return r.base=e,n=t.apply(r,arguments),r.base=i,n}}function r(e,t){return te(t)&&(t=n(e?e._d?e:n(s,e):s,t),t._d=1),t}function i(e,t){for(var n in t.props)Re.test(n)&&(e[n]=r(e[n],t.props[n]))}function o(e){return e}function s(){return""}function a(e){try{throw console.log("JsRender dbg breakpoint: "+e),"dbg breakpoint"}catch(t){}return this.base?this.baseApply(arguments):e}function d(e){this.name=(t.link?"JsViews":"JsRender")+" Error",this.message=e||this.name}function u(e,t){for(var n in t)e[n]=t[n];return e}function l(e,t,n){return e?(de.delimiters=[e,t,ve=n?n.charAt(0):ve],pe=e.charAt(0),ce=e.charAt(1),fe=t.charAt(0),ge=t.charAt(1),e="\\"+pe+"(\\"+ve+")?\\"+ce,t="\\"+fe+"\\"+ge,G="(?:(\\w+(?=[\\/\\s\\"+fe+"]))|(\\w+)?(:)|(>)|(\\*))\\s*((?:[^\\"+fe+"]|\\"+fe+"(?!\\"+ge+"))*?)",ae.rTag="(?:"+G+")",G=new RegExp("(?:"+e+G+"(\\/)?|\\"+pe+"(\\"+ve+")?\\"+ce+"(?:(?:\\/(\\w+))\\s*|!--[\\s\\S]*?--))"+t,"g"),W=new RegExp("<.*>|([^\\\\]|^)[{}]|"+e+".*"+t),le):de.delimiters}function p(e,t){t||e===!0||(t=e,e=void 0);var n,r,i,o,s=this,a=!t||"root"===t;if(e){if(o=t&&s.type===t&&s,!o)if(n=s.views,s._.useKey){for(r in n)if(o=t?n[r].get(e,t):n[r])break}else for(r=0,i=n.length;!o&&i>r;r++)o=t?n[r].get(e,t):n[r]}else if(a)for(;s.parent;)o=s,s=s.parent;else for(;s&&!o;)o=s.type===t?s:void 0,s=s.parent;return o}function c(){var e=this.get("item");return e?e.index:void 0}function f(){return this.index}function g(t){var n,r=this,i=r.linkCtx,o=(r.ctx||{})[t];return void 0===o&&i&&i.ctx&&(o=i.ctx[t]),void 0===o&&(o=oe[t]),o&&te(o)&&!o._wrp&&(n=function(){return o.apply(this&&this!==e?this:r,arguments)},n._wrp=r,u(n,o)),n||o}function v(e){return e&&(e.fn?e:this.getRsc("templates",e)||re(e))}function h(e,t,n,r){var o,s,a="number"==typeof n&&t.tmpl.bnds[n-1],d=t.linkCtx;return void 0!==r?n=r={props:{},args:[r]}:a&&(n=a(t.data,t,ae)),s=n.args[0],(e||a)&&(o=d&&d.tag,o||(o=u(new ae._tg,{_:{inline:!d,bnd:a,unlinked:!0},tagName:":",cvt:e,flow:!0,tagCtx:n}),d&&(d.tag=o,o.linkCtx=d),n.ctx=L(n.ctx,(d?d.view:t).ctx)),o._er=r&&s,i(o,n),n.view=t,o.ctx=n.ctx||o.ctx||{},n.ctx=void 0,s=o.cvtArgs("true"!==e&&e)[0],s=a&&t._.onRender?t._.onRender(s,t,o):s),void 0!=s?s:""}function m(e){var t=this,n=t.tagCtx,r=n.view,i=n.args;return e=e||t.convert,e=e&&(""+e===e?r.getRsc("converters",e)||S("Unknown converter: '"+e+"'"):e),i=i.length||n.index?e?i.slice():i:[r.data],e&&(e.depends&&(t.depends=ae.getDeps(t.depends,t,e.depends,e)),i[0]=e.apply(t,i)),i}function w(e,t){for(var n,r,i=this;void 0===n&&i;)r=i.tmpl&&i.tmpl[e],n=r&&r[t],i=i.parent;return n||Y[e][t]}function x(e,t,n,r,o,s){t=t||X;var a,d,u,l,p,c,f,g,v,h,m,w,x,b,_,y,k,j,C,A="",T=t.linkCtx||0,V=t.ctx,R=n||t.tmpl,M="number"==typeof r&&t.tmpl.bnds[r-1];for("tag"===e._is?(a=e,e=a.tagName,r=a.tagCtxs,u=a.template):(d=t.getRsc("tags",e)||S("Unknown tag: {{"+e+"}} "),u=d.template),void 0!==s?(A+=s,r=s=[{props:{},args:[]}]):M&&(r=M(t.data,t,ae)),g=r.length,f=0;g>f;f++)h=r[f],(!T||!T.tag||f&&!T.tag._.inline||a._er)&&((w=R.tmpls&&h.tmpl)&&(w=h.content=R.tmpls[w-1]),h.index=f,h.tmpl=w,h.render=N,h.view=t,h.ctx=L(h.ctx,V)),(n=h.props.tmpl)&&(h.tmpl=t.getTmpl(n)),a||(a=new d._ctr,x=!!a.init,a.parent=c=V&&V.tag,a.tagCtxs=r,C=a.dataMap,T&&(a._.inline=!1,T.tag=a,a.linkCtx=T),(a._.bnd=M||T.fn)?a._.arrVws={}:a.dataBoundOnly&&S("{^{"+e+"}} tag must be data-bound")),r=a.tagCtxs,C=a.dataMap,h.tag=a,C&&r&&(h.map=r[f].map),a.flow||(m=h.ctx=h.ctx||{},l=a.parents=m.parentTags=V&&L(m.parentTags,V.parentTags)||{},c&&(l[c.tagName]=c),l[a.tagName]=m.tag=a);if(!(a._er=s)){for(i(a,r[0]),a.rendering={},f=0;g>f;f++)h=a.tagCtx=r[f],k=h.props,y=a.cvtArgs(),(b=k.dataMap||C)&&(y.length||k.dataMap)&&(_=h.map,_&&_.src===y[0]&&!o||(_&&_.src&&_.unmap(),_=h.map=b.map(y[0],k,void 0,!a._.bnd)),y=[_.tgt]),a.ctx=h.ctx,f||(x&&(j=a.template,a.init(h,T,a.ctx),x=void 0),T&&(T.attr=a.attr=T.attr||a.attr),p=a.attr,a._.noVws=p&&p!==Ee),v=void 0,a.render&&(v=a.render.apply(a,y)),y.length||(y=[t]),void 0===v&&(v=h.render(y[0],!0)||(o?void 0:"")),A=A?A+(v||""):v;a.rendering=void 0}return a.tagCtx=r[0],a.ctx=a.tagCtx.ctx,a._.noVws&&a._.inline&&(A="text"===p?ie.html(A):""),M&&t._.onRender?t._.onRender(A,t,a):A}function b(e,t,n,r,i,o,s,a){var d,u,l,p=this,f="array"===t;p.content=a,p.views=f?[]:{},p.parent=n,p.type=t||"top",p.data=r,p.tmpl=i,l=p._={key:0,useKey:f?0:1,id:""+$e++,onRender:s,bnds:{}},p.linked=!!s,n?(d=n.views,u=n._,u.useKey?(d[l.key="_"+u.useKey++]=p,p.index=Ue,p.getIndex=c):d.length===(l.key=p.index=o)?d.push(p):d.splice(o,0,p),p.ctx=e||n.ctx):p.ctx=e}function _(e){var t,n,r,i,o,s,a;for(t in Oe)if(o=Oe[t],(s=o.compile)&&(n=e[t+"s"]))for(r in n)i=n[r]=s(r,n[r],e,0),i._is=t,i&&(a=ae.onStore[t])&&a(r,i,s)}function y(e,t,n){function i(){var t=this;t._={inline:!0,unlinked:!0},t.tagName=e}var o,s,a,d=new ae._tg;if(te(t)?t={depends:t.depends,render:t}:""+t===t&&(t={template:t}),s=t.baseTag){t.flow=!!t.flow,t.baseTag=s=""+s===s?n&&n.tags[s]||se[s]:s,d=u(d,s);for(a in t)d[a]=r(s[a],t[a])}else d=u(d,t);return void 0!==(o=d.template)&&(d.template=""+o===o?re[o]||re(o):o),d.init!==!1&&((i.prototype=d).constructor=d._ctr=i),n&&(d._parentTmpl=n),d}function k(e){return this.base.apply(this,e)}function j(e,n,r,i){function o(n){var o,a;if(""+n===n||n.nodeType>0&&(s=n)){if(!s)if(/^\.\/[^\\:*?"<>]*$/.test(n))(a=re[e=e||n])?n=a:s=document.getElementById(n);else if(t.fn&&!W.test(n))try{s=t(document).find(n)[0]}catch(d){}s&&(i?n=s.innerHTML:(o=s.getAttribute(Se),o?o!==Ie?(n=re[o],delete re[o]):t.fn&&(n=t.data(s)[Ie]):(e=e||(t.fn?Ie:n),n=j(e,s.innerHTML,r,i)),n.tmplName=e=e||o,e!==Ie&&(re[e]=n),s.setAttribute(Se,e),t.fn&&t.data(s,Ie,n))),s=void 0}else n.fn||(n=void 0);return n}var s,a,d=n=n||"";return 0===i&&(i=void 0,d=o(d)),i=i||(n.markup?n:{}),i.tmplName=e,r&&(i._parentTmpl=r),!d&&n.markup&&(d=o(n.markup))&&d.fn&&(d=d.markup),void 0!==d?(d.fn||n.fn?d.fn&&(a=d):(n=V(d,i),U(d.replace(ke,"\\$&"),n)),a||(_(i),a=u(function(){return n.render.apply(n,arguments)},n)),e&&!r&&e!==Ie&&(qe[e]=a),a):void 0}function C(e,n){return t.isFunction(e)?e.call(n):e}function A(e){var t,n=[],r=e.length;for(t=0;r>t;t++)n.push(e[t].unmap());return n}function T(e,n){function r(e){l.apply(this,e)}function i(){return new r(arguments)}function o(e,t){var n,r,i,o,s,a=c.length;for(n=0;a>n;n++)o=c[n],r=void 0,o+""!==o&&(r=o,o=r.getter),void 0===(s=e[o])&&r&&void 0!==(i=r.defaultVal)&&(s=C(i,e)),t(s,r&&p[r.type],o)}function s(n){n=n+""===n?JSON.parse(n):n;var r,i,s,u=n,l=[];if(t.isArray(n)){for(n=n||[],i=n.length,r=0;i>r;r++)l.push(this.map(n[r]));return l._is=e,l.unmap=d,l.merge=a,l}if(n){o(n,function(e,t){t&&(e=t.map(e)),l.push(e)}),u=this.apply(this,l);for(s in n)s===ee||b[s]||(u[s]=n[s])}return u}function a(e){e=e+""===e?JSON.parse(e):e;var n,r,s,a,d,u,l,p,c,f,v=this;if(t.isArray(v)){for(p={},f=[],s=e.length,a=v.length,n=0;s>n;n++){for(c=e[n],l=!1,r=0;a>r&&!l;r++)p[r]||(u=v[r],g&&(p[r]=l=g+""===g?c[g]&&(b[g]?u[g]():u[g])===c[g]:g(u,c)));l?(u.merge(c),f.push(u)):f.push(i.map(c))}return void(x?x(v).refresh(f,!0):v.splice.apply(v,[0,v.length].concat(f)))}o(e,function(e,t,n){t?v[n]().merge(e):v[n](e)});for(d in e)d===ee||b[d]||(v[d]=e[d])}function d(){var e,n,r,i,o,s,a=this;if(t.isArray(a))return A(a);for(e={},i=c.length,r=0;i>r;r++)n=c[r],o=void 0,n+""!==n&&(o=n,n=o.getter),s=a[n](),e[n]=o&&s&&p[o.type]?t.isArray(s)?A(s):s.unmap():s;for(n in a)"_is"===n||b[n]||n===ee||"_"===n.charAt(0)&&b[n.slice(1)]||t.isFunction(a[n])||(e[n]=a[n]);return e}var u,l,p=this,c=n.getters,f=n.extend,g=n.id,v=t.extend({_is:e||"unnamed",unmap:d,merge:a},f),h="",m="",w=c?c.length:0,x=t.observable,b={};for(r.prototype=v,u=0;w>u;u++)!function(e){e=e.getter||e,b[e]=u+1;var t="_"+e;h+=(h?",":"")+e,m+="this."+t+" = "+e+";\n",v[e]=v[e]||function(n){return arguments.length?void(x?x(this).setProperty(e,n):this[t]=n):this[t]},x&&(v[e].set=v[e].set||function(e){this[t]=e})}(c[u]);return l=new Function(h,m.slice(0,-1)),l.prototype=v,v.constructor=l,i.map=s,i.getters=c,i.extend=f,i.id=g,i}function V(e,n){var r,i=ue._wm||{},o=u({tmpls:[],links:{},bnds:[],_is:"template",render:N},n);return o.markup=e,n.htmlTag||(r=Ae.exec(e),o.htmlTag=r?r[1].toLowerCase():""),r=i[o.htmlTag],r&&r!==i.div&&(o.markup=t.trim(o.markup)),o}function R(e,t){function n(i,o,s){var a,d,u,l;if(i&&typeof i===Fe&&!i.nodeType&&!i.markup&&!i.getTgt&&!("viewModel"===e&&i.getters||i.extend)){for(u in i)n(u,i[u],o);return o||Y}return void 0===o&&(o=i,i=void 0),i&&""+i!==i&&(s=o,o=i,i=void 0),l=s?"viewModel"===e?s:s[r]=s[r]||{}:n,d=t.compile,null===o?i&&delete l[i]:(o=d?d.call(l,i,o,s,0):o,i&&(l[i]=o)),d&&o&&(o._is=e),o&&(a=ae.onStore[e])&&a(i,o,d),o}var r=e+"s";Y[r]=n}function M(e){le[e]=function(t){return arguments.length?(de[e]=t,le):de[e]}}function $(e){function t(t,n){this.tgt=e.getTgt(t,n)}return te(e)&&(e={getTgt:e}),e.baseMap&&(e=u(u({},e.baseMap),e)),e.map=function(e,n){return new t(e,n)},e}function N(e,t,n,r,i,o){var s,a,d,u,l,p,c,f,g=r,v="";if(t===!0?(n=t,t=void 0):typeof t!==Fe&&(t=void 0),(d=this.tag)?(l=this,g=g||l.view,u=g.getTmpl(d.template||l.tmpl),arguments.length||(e=g)):u=this,u){if(!g&&e&&"view"===e._is&&(g=e),g&&e===g&&(e=g.data),p=!g,me=me||p,g||((t=t||{}).root=e),!me||ue.useViews||u.useViews||g&&g!==X)v=E(u,e,t,n,g,i,o,d);else{if(g?(c=g.data,f=g.index,g.index=Ue):(g=X,g.data=e,g.ctx=t),ne(e)&&!n)for(s=0,a=e.length;a>s;s++)g.index=s,g.data=e[s],v+=u.fn(e[s],g,ae);else g.data=e,v+=u.fn(e,g,ae);g.data=c,g.index=f}p&&(me=void 0)}return v}function E(e,t,n,r,i,o,s,a){function d(e){_=u({},n),_[x]=e}var l,p,c,f,g,v,h,m,w,x,_,y,k="";if(a&&(w=a.tagName,y=a.tagCtx,n=n?L(n,a.ctx):a.ctx,e===i.content?h=e!==i.ctx._wrp?i.ctx._wrp:void 0:e!==y.content?e===a.template?(h=y.tmpl,n._wrp=y.content):h=y.content||i.content:h=i.content,y.props.link===!1&&(n=n||{},n.link=!1),(x=y.props.itemVar)&&("~"!==x.charAt(0)&&I("Use itemVar='~myItem'"),x=x.slice(1))),i&&(s=s||i._.onRender,n=L(n,i.ctx)),o===!0&&(v=!0,o=0),s&&(n&&n.link===!1||a&&a._.noVws)&&(s=void 0),m=s,s===!0&&(m=void 0,s=i._.onRender),n=e.helpers?L(e.helpers,n):n,_=n,ne(t)&&!r)for(c=v?i:void 0!==o&&i||new b(n,"array",i,t,e,o,s),i&&i._.useKey&&(c._.bnd=!a||a._.bnd&&a),x&&(c.it=x),x=c.it,l=0,p=t.length;p>l;l++)x&&d(t[l]),f=new b(_,"item",c,t[l],e,(o||0)+l,s,h),g=e.fn(t[l],f,ae),k+=c._.onRender?c._.onRender(g,f):g;else x&&d(t),c=v?i:new b(_,w||"data",i,t,e,o,s,h),a&&!a.flow&&(c.tag=a),k+=e.fn(t,c,ae);return m?m(k,c):k}function F(e,t,n){var r=void 0!==n?te(n)?n.call(t.data,e,t):n||"":"{Error: "+e.message+"}";return de.onError&&void 0!==(n=de.onError.call(t.data,e,n&&r,t))&&(r=n),t&&!t.linkCtx?ie.html(r):r}function S(e){throw new ae.Err(e)}function I(e){S("Syntax error\n"+e)}function U(e,t,n,r,i){function o(t){t-=v,t&&m.push(e.substr(v,t).replace(_e,"\\n"))}function s(t,n){t&&(t+="}}",I((n?"{{"+n+"}} block has {{/"+t+" without {{"+t:"Unmatched or missing {{/"+t)+", in template:\n"+e))}function a(a,d,u,c,g,x,b,_,y,k,j,C){(b&&d||y&&!u||_&&":"===_.slice(-1)||k)&&I(a),x&&(g=":",c=Ee),y=y||n&&!i;var A=(d||n)&&[[]],T="",V="",R="",M="",$="",N="",E="",F="",S=!y&&!g;u=u||(_=_||"#data",g),o(C),v=C+a.length,b?f&&m.push(["*","\n"+_.replace(/^:/,"ret+= ").replace(ye,"$1")+";\n"]):u?("else"===u&&(Ce.test(_)&&I('for "{{else if expr}}" use "{{else expr}}"'),A=w[7]&&[[]],w[8]=e.substring(w[8],C),w=h.pop(),m=w[2],S=!0),_&&O(_.replace(_e," "),A,t).replace(je,function(e,t,n,r,i,o,s,a){return r="'"+i+"':",s?(V+=o+",",M+="'"+a+"',"):n?(R+=r+o+",",N+=r+"'"+a+"',"):t?E+=o:("trigger"===i&&(F+=o),T+=r+o+",",$+=r+"'"+a+"',",p=p||Re.test(i)),""}).slice(0,-1),A&&A[0]&&A.pop(),l=[u,c||!!r||p||"",S&&[],J(M||(":"===u?"'#data',":""),$,N),J(V||(":"===u?"data,":""),T,R),E,F,A||0],m.push(l),S&&(h.push(w),w=l,w[8]=v)):j&&(s(j!==w[0]&&"else"!==w[0]&&j,w[0]),w[8]=e.substring(w[8],C),w=h.pop()),s(!w&&j),m=w[2]}var d,u,l,p,c,f=de.allowCode||t&&t.allowCode||le.allowCode===!0,g=[],v=0,h=[],m=g,w=[,,g];if(f&&(t.allowCode=f),n&&(void 0!==r&&(e=e.slice(0,-r.length-2)+ge),e=pe+e+ge),s(h[0]&&h[0][2].pop()[0]),e.replace(G,a),o(e.length),(v=g[g.length-1])&&s(""+v!==v&&+v[8]===v[8]&&v[0]),n){for(u=B(g,e,n),c=[],d=g.length;d--;)c.unshift(g[d][7]);q(u,c)}else u=B(g,t);return u}function q(e,t){var n,r,i=0,o=t.length;for(e.deps=[];o>i;i++){r=t[i];for(n in r)"_jsvto"!==n&&r[n].length&&(e.deps=e.deps.concat(r[n]))}e.paths=r}function J(e,t,n){return[e.slice(0,-1),t.slice(0,-1),n.slice(0,-1)]}function K(e,t){return"\n "+(t?t+":{":"")+"args:["+e[0]+"]"+(e[1]||!t?",\n props:{"+e[1]+"}":"")+(e[2]?",\n ctx:{"+e[2]+"}":"")}function O(e,t,n){function r(r,m,w,x,b,_,y,k,j,C,A,T,V,R,M,$,N,E,F,S){function q(e,n,r,s,a,d,p,c){var f="."===r;if(r&&(b=b.slice(n.length),/^\.?constructor$/.test(c||b)&&I(e),f||(e=(s?'view.hlp("'+s+'")':a?"view":"data")+(c?(d?"."+d:s?"":a?"":"."+r)+(p||""):(c=s?"":a?d||"":r,"")),e+=c?"."+c:"",e=n+("view.data"===e.slice(0,9)?e.slice(5):e)),u)){if(O="linkTo"===i?o=t._jsvto=t._jsvto||[]:l.bd,B=f&&O[O.length-1]){if(B._jsv){for(;B.sb;)B=B.sb;B.bnd&&(b="^"+b.slice(1)),B.sb=b,B.bnd=B.bnd||"^"===b.charAt(0)}}else O.push(b);h[g]=F+(f?1:0)}return e}x=u&&x,x&&!k&&(b=x+b),_=_||"",w=w||m||T,b=b||j,C=C||N||"";var J,K,O,B,L,Q=")";if("["===C&&(C="[j._sq(",Q=")]"),!y||d||a){if(u&&$&&!d&&!a&&(!i||s||o)&&(J=h[g-1],S.length-1>F-(J||0))){if(J=S.slice(J,F+r.length),K!==!0)if(O=o||p[g-1].bd,B=O[O.length-1],B&&B.prm){for(;B.sb&&B.sb.prm;)B=B.sb;L=B.sb={path:B.sb,bnd:B.bnd}}else O.push(L={path:O.pop()});$=ce+":"+J+" onerror=''"+fe,K=f[$],K||(f[$]=!0,f[$]=K=U($,n,!0)),K!==!0&&L&&(L._jsv=K,L.prm=l.bd,L.bnd=L.bnd||L.path&&L.path.indexOf("^")>=0)}return d?(d=!V,d?r:T+'"'):a?(a=!R,a?r:T+'"'):(w?(h[g]=F++,l=p[++g]={bd:[]},w):"")+(E?g?"":(c=S.slice(c,F),(i?(i=s=o=!1,"\b"):"\b,")+c+(c=F+r.length,u&&t.push(l.bd=[]),"\b")):k?(g&&I(e),u&&t.pop(),i=b,s=x,c=F+r.length,x&&(u=l.bd=t[i]=[]),b+":"):b?b.split("^").join(".").replace(xe,q)+(C?(l=p[++g]={bd:[]},v[g]=Q,C):_):_?_:M?(M=v[g]||M,v[g]=!1,l=p[--g],M+(C?(l=p[++g],v[g]=Q,C):"")):A?(v[g]||I(e),","):m?"":(d=V,a=R,'"'))}I(e)}var i,o,s,a,d,u=t&&t[0],l={bd:u},p={0:l},c=0,f=n?n.links:u&&(u.links=u.links||{}),g=0,v={},h={},m=(e+(n?" ":"")).replace(be,r);return!g&&m||I(e)}function B(e,t,n){var r,i,o,s,a,d,u,l,p,c,f,g,v,h,m,w,x,b,_,y,k,j,C,A,T,R,M,$,N,E,F=0,S=ue.useViews||t.useViews||t.tags||t.templates||t.helpers||t.converters,U="",J={},O=e.length;for(""+t===t?(b=n?'data-link="'+t.replace(_e," ").slice(1,-1)+'"':t,t=0):(b=t.tmplName||"unnamed",t.allowCode&&(J.allowCode=!0),t.debug&&(J.debug=!0),f=t.bnds,x=t.tmpls),r=0;O>r;r++)if(i=e[r],""+i===i)U+='\n+"'+i+'"';else if(o=i[0],"*"===o)U+=";\n"+i[1]+"\nret=ret";else{if(s=i[1],k=!n&&i[2],a=K(i[3],"params")+"},"+K(v=i[4]),$=i[5],E=i[6],j=i[8]&&i[8].replace(ye,"$1"),(T="else"===o)?g&&g.push(i[7]):(F=0,f&&(g=i[7])&&(g=[g],F=f.push(1))),S=S||v[1]||v[2]||g||/view.(?!index)/.test(v[0]),(R=":"===o)?s&&(o=s===Ee?">":s+o):(k&&(_=V(j,J),_.tmplName=b+"/"+o,_.useViews=_.useViews||S,B(k,_),S=_.useViews,x.push(_)),T||(y=o,S=S||o&&(!se[o]||!se[o].flow),A=U,U=""),C=e[r+1],C=C&&"else"===C[0]),N=$?";\ntry{\nret+=":"\n+",h="",m="",R&&(g||E||s&&s!==Ee)){if(M=new Function("data,view,j,u"," // "+b+" "+F+" "+o+"\nreturn {"+a+"};"),M._er=$,M._tag=o,n)return M;q(M,g),w='c("'+s+'",view,',c=!0,h=w+F+",",m=")"}if(U+=R?(n?($?"try{\n":"")+"return ":N)+(c?(c=void 0,S=p=!0,w+(g?(f[F-1]=M,F):"{"+a+"}")+")"):">"===o?(u=!0,"h("+v[0]+")"):(l=!0,"((v="+v[0]+")!=null?v:"+(n?"null)":'"")'))):(d=!0,"\n{view:view,tmpl:"+(k?x.length:"0")+","+a+"},"),y&&!C){if(U="["+U.slice(0,-1)+"]",w='t("'+y+'",view,this,',n||g){if(U=new Function("data,view,j,u"," // "+b+" "+F+" "+y+"\nreturn "+U+";"),U._er=$,U._tag=y,g&&q(f[F-1]=U,g),n)return U;h=w+F+",undefined,",m=")"}U=A+N+w+(F||U)+")",g=0,y=0}$&&(S=!0,U+=";\n}catch(e){ret"+(n?"urn ":"+=")+h+"j._err(e,view,"+$+")"+m+";}"+(n?"":"ret=ret"))}U="// "+b+"\nvar v"+(d?",t=j._tag":"")+(p?",c=j._cnvt":"")+(u?",h=j._html":"")+(n?";\n":',ret=""\n')+(J.debug?"debugger;":"")+U+(n?"\n":";\nreturn ret;"),de.debugMode!==!1&&(U="try {\n"+U+"\n}catch(e){\nreturn j._err(e, view);\n}");try{U=new Function("data,view,j,u",U)}catch(L){I("Compiled template code:\n\n"+U+'\n: "'+L.message+'"')}return t&&(t.fn=U,t.useViews=!!S),U}function L(e,t){return e&&e!==t?t?u(u({},t),e):e:t&&u({},t)}function Q(e){return Ne[e]||(Ne[e]="&#"+e.charCodeAt(0)+";")}function H(e){var t,n,r=[];if(typeof e===Fe)for(t in e)n=e[t],t===ee||te(n)||r.push({key:t,prop:n});return r}function P(e,n,r){var i=this.jquery&&(this[0]||S('Unknown template: "'+this.selector+'"')),o=i.getAttribute(Se);return N.call(o?t.data(i)[Ie]:re(i),e,n,r)}function D(e){return void 0!=e?Ve.test(e)&&(""+e).replace(Me,Q)||e:""}var Z=t===!1;t=t&&t.fn?t:e.jQuery;var z,G,W,X,Y,ee,te,ne,re,ie,oe,se,ae,de,ue,le,pe,ce,fe,ge,ve,he,me,we="v0.9.78",xe=/^(!*?)(?:null|true|false|\d[\d.]*|([\w$]+|\.|~([\w$]+)|#(view|([\w$]+))?)([\w$.^]*?)(?:[.[^]([\w$]+)\]?)?)$/g,be=/(\()(?=\s*\()|(?:([([])\s*)?(?:(\^?)(!*?[#~]?[\w$.^]+)?\s*((\+\+|--)|\+|-|&&|\|\||===|!==|==|!=|<=|>=|[<>%*:?\/]|(=))\s*|(!*?[#~]?[\w$.^]+)([([])?)|(,\s*)|(\(?)\\?(?:(')|("))|(?:\s*(([)\]])(?=\s*[.^]|\s*$|[^([])|[)\]])([([]?))|(\s+)/g,_e=/[ \t]*(\r\n|\n|\r)/g,ye=/\\(['"])/g,ke=/['"\\]/g,je=/(?:\x08|^)(onerror:)?(?:(~?)(([\w$_\.]+):)?([^\x08]+))\x08(,)?([^\x08]+)/gi,Ce=/^if\s/,Ae=/<(\w+)[>\s]/,Te=/[\x00`><"'&=]/g,Ve=/[\x00`><\"'&=]/,Re=/^on[A-Z]|^convert(Back)?$/,Me=Te,$e=0,Ne={"&":"&amp;","<":"&lt;",">":"&gt;","\x00":"&#0;","'":"&#39;",'"':"&#34;","`":"&#96;","=":"&#61;"},Ee="html",Fe="object",Se="data-jsv-tmpl",Ie="jsvTmpl",Ue="For #index in nested block use #getIndex().",qe={},Je=e.jsrender,Ke=Je&&t&&!t.render,Oe={template:{compile:j},tag:{compile:y},viewModel:{compile:T},helper:{},converter:{}};if(Y={jsviews:we,sub:{View:b,Err:d,tmplFn:U,parse:O,extend:u,extendCtx:L,syntaxErr:I,onStore:{},addSetting:M,settings:{allowCode:!1},advSet:s,_ths:i,_tg:function(){},_cnvt:h,_tag:x,_er:S,_err:F,_html:D,_sq:function(e){return"constructor"===e&&I(""),e}},settings:{delimiters:l,advanced:function(e){return e?(u(ue,e),ae.advSet(),le):ue}},map:$},(d.prototype=new Error).constructor=d,c.depends=function(){return[this.get("item"),"index"]},f.depends="index",b.prototype={get:p,getIndex:f,getRsc:w,getTmpl:v,hlp:g,_is:"view"},ae=Y.sub,le=Y.settings,!(Je||t&&t.render)){for(z in Oe)R(z,Oe[z]);ie=Y.converters,oe=Y.helpers,se=Y.tags,ae._tg.prototype={baseApply:k,cvtArgs:m},X=ae.topView=new b,t?(t.fn.render=P,ee=t.expando,t.observable&&(u(ae,t.views.sub),Y.map=t.views.map)):(t={},Z&&(e.jsrender=t),t.renderFile=t.__express=t.compile=function(){throw"Node.js: use npm jsrender, or jsrender-node.js"},t.isFunction=function(e){return"function"==typeof e},t.isArray=Array.isArray||function(e){return"[object Array]"==={}.toString.call(e)},ae._jq=function(e){e!==t&&(u(e,t),t=e,t.fn.render=P,delete t.jsrender,ee=t.expando)},t.jsrender=we),de=ae.settings,de.allowCode=!1,te=t.isFunction,ne=t.isArray,t.render=qe,t.views=Y,t.templates=re=Y.templates;for(he in de)M(he);(le.debugMode=function(e){return void 0===e?de.debugMode:(de.debugMode=e,de.onError=e+""===e?new Function("","return '"+e+"';"):te(e)?e:void 0,le)})(!1),ue=de.advanced={useViews:!1,_jsv:!1},se({"if":{render:function(e){var t=this,n=t.tagCtx,r=t.rendering.done||!e&&(arguments.length||!n.index)?"":(t.rendering.done=!0,t.selected=n.index,n.render(n.view,!0));return r},flow:!0},"for":{render:function(e){var t,n=!arguments.length,r=this,i=r.tagCtx,o="",s=0;return r.rendering.done||(t=n?i.view.data:e,void 0!==t&&(o+=i.render(t,n),s+=ne(t)?t.length:1),(r.rendering.done=s)&&(r.selected=i.index)),o},flow:!0},props:{baseTag:"for",dataMap:$(H),flow:!0},include:{flow:!0},"*":{render:o,flow:!0},":*":{render:o,flow:!0},dbg:oe.dbg=ie.dbg=a}),ie({html:D,attr:D,url:function(e){return void 0!=e?encodeURI(""+e):null===e?e:""}})}return de=ae.settings,le.delimiters("{{","}}","^"),Ke&&Je.views.sub._jq(t),t||Je},window);
+//# sourceMappingURL=jsrender.min.js.map
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
index 259271df3..9f9eda1e1 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
@@ -55,8 +55,8 @@ function layerBtnsInit() {
});
});
- $(".build-recipe-btn").unbind('click');
- $(".build-recipe-btn").click(function(e){
+ $("td .build-recipe-btn").unbind('click');
+ $("td .build-recipe-btn").click(function(e){
e.preventDefault();
var recipe = $(this).data('recipe-name');
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerDepsModal.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerDepsModal.js
index 825f9dccd..e9622243a 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerDepsModal.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerDepsModal.js
@@ -6,7 +6,12 @@
* addToProject: Whether to add layers to project on accept
* successAdd: function to run on success
*/
-function showLayerDepsModal(layer, dependencies, title, body, addToProject, successAdd) {
+function showLayerDepsModal(layer,
+ dependencies,
+ title,
+ body,
+ addToProject,
+ successAdd) {
if ($("#dependencies-modal").length === 0) {
$.get(libtoaster.ctx.htmlUrl + "/layer_deps_modal.html", function(html){
@@ -33,17 +38,20 @@ function showLayerDepsModal(layer, dependencies, title, body, addToProject, succ
var deplistHtml = "";
for (var i = 0; i < dependencies.length; i++) {
- deplistHtml += "<li><label class=\"checkbox\"><input name=\"dependencies\" value=\"";
+ deplistHtml += "<li><div class=\"checkbox\"><label><input name=\"dependencies\" value=\"";
deplistHtml += dependencies[i].id;
deplistHtml +="\" type=\"checkbox\" checked=\"checked\"/>";
deplistHtml += dependencies[i].name;
- deplistHtml += "</label></li>";
+ deplistHtml += "</label></div></li>";
}
$('#dependencies-list').html(deplistHtml);
$("#dependencies-modal").data("deps", dependencies);
- $('#dependencies-modal').modal('show');
+ /* Clear any alert notifications before showing the modal */
+ $(".alert").fadeOut(function(){
+ $('#dependencies-modal').modal('show');
+ });
/* Discard the old submission function */
$("#dependencies-modal-form").unbind('submit');
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
index d54540626..9ead393cb 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/layerdetails.js
@@ -10,25 +10,27 @@ function layerDetailsPageInit (ctx) {
var targetTab = $("#targets-tab");
var machineTab = $("#machines-tab");
var detailsTab = $("#details-tab");
+ var editLayerSource = $("#edit-layer-source");
+ var saveSourceChangesBtn = $("#save-changes-for-switch");
+ var layerGitRefInput = $("#layer-git-ref");
+ var layerSubDirInput = $('#layer-subdir');
+
+ targetTab.on('show.bs.tab', targetsTabShow);
+ detailsTab.on('show.bs.tab', detailsTabShow);
+ machineTab.on('show.bs.tab', machinesTabShow);
/* setup the dependencies typeahead */
- libtoaster.makeTypeahead(layerDepInput, libtoaster.ctx.layersTypeAheadUrl, { include_added: "true" }, function(item){
+ libtoaster.makeTypeahead(layerDepInput,
+ libtoaster.ctx.layersTypeAheadUrl,
+ { include_added: "true" }, function(item){
currentLayerDepSelection = item;
-
layerDepBtn.removeAttr("disabled");
});
- $(window).on('hashchange', function(e){
- switch(window.location.hash){
- case '#machines':
- machineTab.tab('show');
- break;
- case '#recipes':
- targetTab.tab('show');
- break;
- default:
- detailsTab.tab('show');
- break;
+ /* disable the add layer button if its input field is empty */
+ layerDepInput.on("keyup",function(){
+ if ($(this).val().length === 0) {
+ layerDepBtn.attr("disabled", "disabled");
}
});
@@ -76,7 +78,7 @@ function layerDetailsPageInit (ctx) {
addRemoveDep(currentLayerDepSelection.id, true, function(){
/* Make a list item for the new layer dependency */
- var newLayerDep = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>");
+ var newLayerDep = $("<li><a></a><span class=\"glyphicon glyphicon-trash\" data-toggle=\"tooltip\" title=\"Delete\"></span></li>");
newLayerDep.data('layer-id', currentLayerDepSelection.id);
newLayerDep.children("span").tooltip();
@@ -94,11 +96,11 @@ function layerDetailsPageInit (ctx) {
/* Clear the current selection */
layerDepInput.val("");
currentLayerDepSelection = undefined;
- layerDepBtn.attr("disabled","disabled");
+ layerDepBtn.attr("disabled", "disabled");
});
});
- $(".icon-pencil").click(function (){
+ $(".glyphicon-edit").click(function (){
var mParent = $(this).parent("dd");
mParent.prev().css("margin-top", "10px");
mParent.children("form").slideDown();
@@ -106,8 +108,12 @@ function layerDetailsPageInit (ctx) {
currentVal.hide();
/* Set the current value to the input field */
mParent.find("textarea,input").val(currentVal.text());
+ /* If the input field is empty, disable the submit button */
+ if ( mParent.find("textarea,input").val().length == 0 ) {
+ mParent.find(".change-btn").attr("disabled", "disabled");
+ }
/* Hides the "Not set" text */
- mParent.children(".muted").hide();
+ mParent.children(".text-muted").hide();
/* We're editing so hide the delete icon */
mParent.children(".delete-current-value").hide();
mParent.find(".cancel").show();
@@ -128,30 +134,31 @@ function layerDetailsPageInit (ctx) {
mParent.children(".current-value").show();
/* Show the "Not set" text if we ended up with no value */
if (!mParent.children(".current-value").html()){
- mParent.children(".muted").fadeIn();
+ mParent.children(".text-muted").fadeIn();
mParent.children(".delete-current-value").hide();
} else {
mParent.children(".delete-current-value").show();
}
- mParent.children(".icon-pencil").show();
- mParent.prev().css("margin-top", "0px");
+ mParent.children(".glyphicon-edit").show();
+ mParent.prev().css("margin-top", "0");
});
});
+
function defaultAddBtnText(){
var text = " Add the "+ctx.layerVersion.name+" layer to your project";
addRmLayerBtn.text(text);
- addRmLayerBtn.prepend("<span class=\"icon-plus\"></span>");
+ addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>");
addRmLayerBtn.removeClass("btn-danger");
}
- detailsTab.on('show', function(){
+ function detailsTabShow(){
if (!ctx.layerVersion.inCurrentPrj)
defaultAddBtnText();
- window.location.hash = "details";
- });
+ window.location.hash = "information";
+ }
function targetsTabShow(){
if (!ctx.layerVersion.inCurrentPrj){
@@ -159,7 +166,7 @@ function layerDetailsPageInit (ctx) {
var text = " Add the "+ctx.layerVersion.name+" layer to your project "+
"to enable these recipes";
addRmLayerBtn.text(text);
- addRmLayerBtn.prepend("<span class=\"icon-plus\"></span>");
+ addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>");
} else {
defaultAddBtnText();
}
@@ -177,7 +184,7 @@ function layerDetailsPageInit (ctx) {
$("#no-recipes-yet").hide();
}
- targetTab.removeClass("muted");
+ targetTab.removeClass("text-muted");
if (window.location.hash === "#recipes"){
/* re run the machinesTabShow to update the text */
targetsTabShow();
@@ -192,20 +199,19 @@ function layerDetailsPageInit (ctx) {
else
$("#no-machines-yet").hide();
- machineTab.removeClass("muted");
+ machineTab.removeClass("text-muted");
if (window.location.hash === "#machines"){
/* re run the machinesTabShow to update the text */
machinesTabShow();
}
$(".select-machine-btn").click(function(e){
- if ($(this).attr("disabled") === "disabled")
+ if ($(this).hasClass("disabled"))
e.preventDefault();
});
});
- targetTab.on('show', targetsTabShow);
function machinesTabShow(){
if (!ctx.layerVersion.inCurrentPrj) {
@@ -213,7 +219,7 @@ function layerDetailsPageInit (ctx) {
var text = " Add the "+ctx.layerVersion.name+" layer to your project " +
"to enable these machines";
addRmLayerBtn.text(text);
- addRmLayerBtn.prepend("<span class=\"icon-plus\"></span>");
+ addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-plus\"></span>");
} else {
defaultAddBtnText();
}
@@ -222,8 +228,6 @@ function layerDetailsPageInit (ctx) {
window.location.hash = "machines";
}
- machineTab.on('show', machinesTabShow);
-
$(".pagesize").change(function(){
var search = libtoaster.parseUrlParams();
search.limit = this.value;
@@ -239,17 +243,17 @@ function layerDetailsPageInit (ctx) {
if (added){
/* enable and switch all the button states */
- $(".build-recipe-btn").removeAttr("disabled");
- $(".select-machine-btn").removeAttr("disabled");
+ $(".build-recipe-btn").removeClass("disabled");
+ $(".select-machine-btn").removeClass("disabled");
addRmLayerBtn.addClass("btn-danger");
addRmLayerBtn.data('directive', "remove");
addRmLayerBtn.text(" Remove the "+ctx.layerVersion.name+" layer from your project");
- addRmLayerBtn.prepend("<span class=\"icon-trash\"></span>");
+ addRmLayerBtn.prepend("<span class=\"glyphicon glyphicon-trash\"></span>");
} else {
/* disable and switch all the button states */
- $(".build-recipe-btn").attr("disabled","disabled");
- $(".select-machine-btn").attr("disabled", "disabled");
+ $(".build-recipe-btn").addClass("disabled");
+ $(".select-machine-btn").addClass("disabled");
addRmLayerBtn.removeClass("btn-danger");
addRmLayerBtn.data('directive', "add");
@@ -257,7 +261,7 @@ function layerDetailsPageInit (ctx) {
* on which tab is currently visible. Unfortunately we can't just call
* tab('show') as if it's already visible it doesn't run the event.
*/
- switch ($(".nav-pills .active a").prop('id')){
+ switch ($(".nav-tabs .active a").prop('id')){
case 'machines-tab':
machinesTabShow();
break;
@@ -286,7 +290,7 @@ function layerDetailsPageInit (ctx) {
setLayerInCurrentPrj(add);
- $("#alert-area").show();
+ libtoaster.showChangeNotification(alertMsg);
});
});
@@ -325,7 +329,7 @@ function layerDetailsPageInit (ctx) {
text = entryElement.val();
/* Hide the "Not set" text if it's visible */
- inputArea.find(".muted").hide();
+ inputArea.find(".text-muted").hide();
inputArea.find(".current-value").text(text);
/* Same behaviour as cancel in that we hide the form/show current
* value.
@@ -343,9 +347,9 @@ function layerDetailsPageInit (ctx) {
/* Disable the change button when we have no data in the input */
$("dl input, dl textarea").on("input",function() {
if ($(this).val().length === 0)
- $(this).parent().children(".change-btn").attr("disabled", "disabled");
+ $(this).parent().next(".change-btn").attr("disabled", "disabled");
else
- $(this).parent().children(".change-btn").removeAttr("disabled");
+ $(this).parent().next(".change-btn").removeAttr("disabled");
});
/* This checks to see if the dt's dd has data in it or if the change data
@@ -355,11 +359,11 @@ function layerDetailsPageInit (ctx) {
if ($(this).is("dt")) {
var dd = $(this).next("dd");
if (!dd.children("form:visible")|| !dd.find(".current-value").html()){
- if (ctx.layerVersion.sourceId == 3){
+ if (ctx.layerVersion.layer_source == ctx.layerSourceTypes.TYPE_IMPORTED){
/* There's no current value and the layer is editable
* so show the "Not set" and hide the delete icon
*/
- dd.find(".muted").show();
+ dd.find(".text-muted").show();
dd.find(".delete-current-value").hide();
} else {
/* We're not viewing an editable layer so hide the empty dd/dl pair */
@@ -386,10 +390,132 @@ function layerDetailsPageInit (ctx) {
$(this).parents("form").submit();
});
+ $("#layer-delete-confirmed").click(function(){
+
+ $("#delete-layer-modal button[data-dismiss='modal']").hide();
+
+ var message = $('<span>You have deleted <strong>1</strong> layer from your project: <strong id="deleted-layer-name"></strong>');
+ message.find("#deleted-layer-name").text(ctx.layerVersion.name);
- layerDepsList.find(".icon-trash").click(layerDepRemoveClick);
+ $.ajax({
+ type: "DELETE",
+ url: ctx.xhrUpdateLayerUrl,
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function(data) {
+ if (data.error != "ok") {
+ console.warn(data.error);
+ } else {
+ libtoaster.setNotification("layer-deleted", message.html());
+ window.location.replace(data.gotoUrl);
+ }
+ },
+ error: function(data) {
+ console.warn("Call failed");
+ console.warn(data);
+ }
+ });
+ });
+
+ layerDepsList.find(".glyphicon-trash").click(layerDepRemoveClick);
layerDepsList.find("a").tooltip();
- $(".icon-trash").tooltip();
+ $(".glyphicon-trash").tooltip();
$(".commit").tooltip();
+ editLayerSource.click(function() {
+ /* Kindly bring the git layers imported from layerindex to normal page
+ * and not this new page :(
+ */
+ $(this).hide();
+ saveSourceChangesBtn.attr("disabled", "disabled");
+
+ $("#git-repo-info, #directory-info").hide();
+ $("#edit-layer-source-form").fadeIn();
+ if ($("#layer-dir-path-in-details").val() == "") {
+ //Local dir path is empty...
+ $("#repo").prop("checked", true);
+ $("#layer-git").fadeIn();
+ $("#layer-dir").hide();
+ } else {
+ $("#layer-git").hide();
+ $("#layer-dir").fadeIn();
+ }
+ });
+
+ $('input:radio[name="source-location"]').change(function() {
+ if ($('input[name=source-location]:checked').val() == "repo") {
+ $("#layer-git").fadeIn();
+ $("#layer-dir").hide();
+ if ($("#layer-git-repo-url").val().length === 0 && layerGitRefInput.val().length === 0) {
+ saveSourceChangesBtn.attr("disabled", "disabled");
+ }
+ } else {
+ $("#layer-dir").fadeIn();
+ $("#layer-git").hide();
+ }
+ });
+
+ $("#layer-dir-path-in-details").keyup(function() {
+ saveSourceChangesBtn.removeAttr("disabled");
+ });
+
+ $("#layer-git-repo-url").keyup(function() {
+ if ($("#layer-git-repo-url").val().length > 0 && layerGitRefInput.val().length > 0) {
+ saveSourceChangesBtn.removeAttr("disabled");
+ }
+ });
+
+ layerGitRefInput.keyup(function() {
+ if ($("#layer-git-repo-url").val().length > 0 && layerGitRefInput.val().length > 0) {
+ saveSourceChangesBtn.removeAttr("disabled");
+ }
+ });
+
+
+ layerSubDirInput.keyup(function(){
+ if ($(this).val().length > 0){
+ saveSourceChangesBtn.removeAttr("disabled");
+ }
+ });
+
+ $('#cancel-changes-for-switch').click(function() {
+ $("#edit-layer-source-form").hide();
+ $("#directory-info, #git-repo-info").fadeIn();
+ editLayerSource.show();
+ });
+
+ saveSourceChangesBtn.click(function() {
+
+ var layerData = {
+ vcs_url: $('#layer-git-repo-url').val(),
+ commit: layerGitRefInput.val(),
+ dirpath: layerSubDirInput.val(),
+ local_source_dir: $('#layer-dir-path-in-details').val(),
+ };
+
+ if ($('input[name=source-location]:checked').val() == "repo") {
+ layerData.local_source_dir = "";
+ } else {
+ layerData.vcs_url = "";
+ layerData.git_ref = "";
+ }
+
+ $.ajax({
+ type: "POST",
+ url: ctx.xhrUpdateLayerUrl,
+ data: layerData,
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function (data) {
+ if (data.error != "ok") {
+ console.warn(data.error);
+ } else {
+ /* success layer property changed */
+ window.location.reload();
+ }
+ },
+ error: function (data) {
+ console.warn("Call failed");
+ console.warn(data);
+ }
+ });
+ });
}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
index 43930a2c3..86662b7a6 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
@@ -3,96 +3,82 @@
* This object really just helps readability since we can then have
* a traceable namespace.
*/
-var libtoaster = (function (){
-
- /* makeTypeahead parameters
- * elementSelector: JQuery elementSelector string
- * xhrUrl: the url to get the JSON from expects JSON in the form:
- * { "list": [ { "name": "test", "detail" : "a test thing" }, .... ] }
+var libtoaster = (function () {
+ // prevent conflicts with Bootstrap 2's typeahead (required during
+ // transition from v2 to v3)
+ var typeahead = jQuery.fn.typeahead.noConflict();
+ jQuery.fn._typeahead = typeahead;
+
+ /* Make a typeahead from an input element
+ *
+ * _makeTypeahead parameters
+ * jQElement: input element as selected by $('selector')
+ * xhrUrl: the url to get the JSON from; this URL should return JSON in the
+ * format:
+ * { "results": [ { "name": "test", "detail" : "a test thing" }, ... ] }
* xhrParams: the data/parameters to pass to the getJSON url e.g.
- * { 'type' : 'projects' } the text typed will be passed as 'search'.
- * selectedCB: function to call once an item has been selected one
- * arg of the item.
+ * { 'type' : 'projects' }; the text typed will be passed as 'search'.
+ * selectedCB: function to call once an item has been selected; has
+ * signature selectedCB(item), where item is an item in the format shown
+ * in the JSON list above, i.e.
+ * { "name": "name", "detail": "detail" }.
*/
- function _makeTypeahead (jQElement, xhrUrl, xhrParams, selectedCB) {
- if (!xhrUrl || xhrUrl.length === 0)
- throw("No url to typeahead supplied");
+ function _makeTypeahead(jQElement, xhrUrl, xhrParams, selectedCB) {
+ if (!xhrUrl || xhrUrl.length === 0) {
+ throw("No url supplied for typeahead");
+ }
var xhrReq;
- jQElement.typeahead({
- // each time the typeahead's choices change, a
- // "typeahead-choices-change" event is fired with an object
- // containing the available choices in a "choices" property
- source: function(query, process){
+ jQElement._typeahead(
+ {
+ highlight: true,
+ classNames: {
+ open: "dropdown-menu",
+ cursor: "active"
+ }
+ },
+ {
+ source: function (query, syncResults, asyncResults) {
xhrParams.search = query;
- /* If we have a request in progress don't fire off another one*/
- if (xhrReq)
+ // if we have a request in progress, cancel it and start another
+ if (xhrReq) {
xhrReq.abort();
+ }
- xhrReq = $.getJSON(xhrUrl, this.options.xhrParams, function(data){
+ xhrReq = $.getJSON(xhrUrl, xhrParams, function (data) {
if (data.error !== "ok") {
- console.log("Error getting data from server "+data.error);
+ console.error("Error getting data from server: " + data.error);
return;
}
xhrReq = null;
- jQElement.trigger("typeahead-choices-change", {choices: data.results});
-
- return process(data.results);
+ asyncResults(data.results);
});
},
- updater: function(item) {
- var itemObj = this.$menu.find('.active').data('itemObject');
- selectedCB(itemObj);
- return item;
- },
- matcher: function(item) {
- if (!item.hasOwnProperty('name')) {
- console.log("Name property missing in data");
- return 0;
- }
-
- if (this.$element.val().length === 0)
- return 0;
- return 1;
- },
- highlighter: function (item) {
- /* Use jquery to escape the item name and detail */
- var current = $("<span></span>").text(item.name + ' '+item.detail);
- current = current.html();
-
- var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
- return current.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
- return '<strong>' + match + '</strong>'
- })
+ // how the selected item is shown in the input
+ display: function (item) {
+ return item.name;
},
- sorter: function (items) { return items; },
- xhrUrl: xhrUrl,
- xhrParams: xhrParams,
- xhrReq: xhrReq,
- });
-
-
- /* Copy of bootstrap's render func but sets selectedObject value */
- function customRenderFunc (items) {
- var that = this;
- items = $(items).map(function (i, item) {
- i = $(that.options.item).attr('data-value', item.name).data('itemObject', item);
- i.find('a').html(that.highlighter(item));
- return i[0];
- });
-
- items.first().addClass('active');
- this.$menu.html(items);
- return this;
- }
+ templates: {
+ // how the item is displayed in the dropdown
+ suggestion: function (item) {
+ var elt = document.createElement("div");
+ elt.innerHTML = item.name + " " + item.detail;
+ return elt;
+ }
+ }
+ }
+ );
- jQElement.data('typeahead').render = customRenderFunc;
+ // when an item is selected using the typeahead, invoke the callback
+ jQElement.on("typeahead:select", function (event, item) {
+ selectedCB(item);
+ });
}
/* startABuild:
@@ -162,11 +148,25 @@ var libtoaster = (function (){
});
}
+ function _getMostRecentBuilds(url, onsuccess, onfail) {
+ $.ajax({
+ url: url,
+ type: 'GET',
+ data : {format: 'json'},
+ headers: {'X-CSRFToken': $.cookie('csrftoken')},
+ success: function (data) {
+ onsuccess ? onsuccess(data) : console.log(data);
+ },
+ error: function (data) {
+ onfail ? onfail(data) : console.error(data);
+ }
+ });
+ }
+
/* Get a project's configuration info */
function _getProjectInfo(url, onsuccess, onfail){
$.ajax({
type: "GET",
- data : { format: "json" },
url: url,
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
success: function (_data) {
@@ -193,7 +193,7 @@ var libtoaster = (function (){
function _editCurrentProject(data, onSuccess, onFail){
$.ajax({
type: "POST",
- url: libtoaster.ctx.projectPageUrl + "?format=json",
+ url: libtoaster.ctx.xhrProjectUrl,
data: data,
headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
success: function (data) {
@@ -314,11 +314,11 @@ var libtoaster = (function (){
var alertMsg;
if (layerDepsList.length > 0 && add === true) {
- alertMsg = $("<span>You have added <strong>"+(layerDepsList.length+1)+"</strong> layers to your project: <a id=\"layer-affected-name\"></a> and its dependencies </span>");
+ alertMsg = $("<span>You have added <strong>"+(layerDepsList.length+1)+"</strong> layers to your project: <a class=\"alert-link\" id=\"layer-affected-name\"></a> and its dependencies </span>");
/* Build the layer deps list */
layerDepsList.map(function(layer, i){
- var link = $("<a></a>");
+ var link = $("<a class=\"alert-link\"></a>");
link.attr("href", layer.layerdetailurl);
link.text(layer.name);
@@ -330,9 +330,9 @@ var libtoaster = (function (){
alertMsg.append(link);
});
} else if (layerDepsList.length === 0 && add === true) {
- alertMsg = $("<span>You have added <strong>1</strong> layer to your project: <a id=\"layer-affected-name\"></a></span></span>");
+ alertMsg = $("<span>You have added <strong>1</strong> layer to your project: <a class=\"alert-link\" id=\"layer-affected-name\"></a></span></span>");
} else if (add === false) {
- alertMsg = $("<span>You have removed <strong>1</strong> layer from your project: <a id=\"layer-affected-name\"></a></span>");
+ alertMsg = $("<span>You have removed <strong>1</strong> layer from your project: <a class=\"alert-link\" id=\"layer-affected-name\"></a></span>");
}
alertMsg.children("#layer-affected-name").text(layer.name);
@@ -342,10 +342,12 @@ var libtoaster = (function (){
}
function _showChangeNotification(message){
- var alertMsg = $("#change-notification-msg");
+ $(".alert-dismissible").fadeOut().promise().done(function(){
+ var alertMsg = $("#change-notification-msg");
- alertMsg.html(message);
- $("#change-notification, #change-notification *").fadeIn();
+ alertMsg.html(message);
+ $("#change-notification, #change-notification *").fadeIn();
+ });
}
function _createCustomRecipe(name, baseRecipeId, doneCb){
@@ -374,11 +376,98 @@ var libtoaster = (function (){
});
}
+ /* Validate project names. Use unique project names
+
+ All arguments accepted by this function are JQeury objects.
+
+ For example if the HTML element has "hint-error-project-name", then
+ it is passed to this function as $("#hint-error-project-name").
+
+ Arg1 - projectName : This is a string object. In the HTML, project name will be entered here.
+ Arg2 - hintEerror : This is a jquery object which will accept span which throws error for
+ duplicate project
+ Arg3 - ctrlGrpValidateProjectName : This object holds the div with class "control-group"
+ Arg4 - enableOrDisableBtn : This object will help the API to enable or disable the form.
+ For example in the new project the create project button will be hidden if the
+ duplicate project exist. Similarly in the projecttopbar the save button will be
+ disabled if the project name already exist.
+
+ Return - This function doesn't return anything. It sets/unsets the behavior of the elements.
+ */
+
+ function _makeProjectNameValidation(projectName, hintError,
+ ctrlGrpValidateProjectName, enableOrDisableBtn ) {
+
+ function checkProjectName(projectName){
+ $.ajax({
+ type: "GET",
+ url: libtoaster.ctx.projectsTypeAheadUrl,
+ data: { 'search' : projectName },
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function(data){
+ if (data.results.length > 0 &&
+ data.results[0].name === projectName) {
+ // This project name exists hence show the error and disable
+ // the save button
+ ctrlGrpValidateProjectName.addClass('has-error');
+ hintError.show();
+ enableOrDisableBtn.attr('disabled', 'disabled');
+ } else {
+ ctrlGrpValidateProjectName.removeClass('has-error');
+ hintError.hide();
+ enableOrDisableBtn.removeAttr('disabled');
+ }
+ },
+ error: function (data) {
+ console.log(data);
+ },
+ });
+ }
+
+ /* The moment user types project name remove the error */
+ projectName.on("input", function() {
+ var projectName = $(this).val();
+ checkProjectName(projectName)
+ });
+
+ /* Validate new project name */
+ projectName.on("blur", function(){
+ var projectName = $(this).val();
+ checkProjectName(projectName)
+ });
+ }
+
+ // if true, the loading spinner for Ajax requests will be displayed
+ // if requests take more than 1200ms
+ var ajaxLoadingTimerEnabled = true;
+
+ // turn on the page-level loading spinner for Ajax requests
+ function _enableAjaxLoadingTimer() {
+ ajaxLoadingTimerEnabled = true;
+ }
+
+ // turn off the page-level loading spinner for Ajax requests
+ function _disableAjaxLoadingTimer() {
+ ajaxLoadingTimerEnabled = false;
+ }
+
+ /* Utility function to set a notification for the next page load */
+ function _setNotification(name, message){
+ var data = {
+ name: name,
+ message: message
+ };
+
+ $.cookie('toaster-notification', JSON.stringify(data), { path: '/'});
+ }
return {
+ enableAjaxLoadingTimer: _enableAjaxLoadingTimer,
+ disableAjaxLoadingTimer: _disableAjaxLoadingTimer,
reload_params : reload_params,
startABuild : _startABuild,
cancelABuild : _cancelABuild,
+ getMostRecentBuilds: _getMostRecentBuilds,
makeTypeahead : _makeTypeahead,
getProjectInfo: _getProjectInfo,
getLayerDepsForProject : _getLayerDepsForProject,
@@ -390,6 +479,8 @@ var libtoaster = (function (){
makeLayerAddRmAlertMsg : _makeLayerAddRmAlertMsg,
showChangeNotification : _showChangeNotification,
createCustomRecipe: _createCustomRecipe,
+ makeProjectNameValidation: _makeProjectNameValidation,
+ setNotification: _setNotification,
};
})();
@@ -421,10 +512,24 @@ function reload_params(params) {
window.location.href = url+"?"+callparams.join('&');
}
-
/* Things that happen for all pages */
$(document).ready(function() {
+ (function showNotificationRequest(){
+ var cookie = $.cookie('toaster-notification');
+
+ if (!cookie)
+ return;
+
+ var notificationData = JSON.parse(cookie);
+
+ libtoaster.showChangeNotification(notificationData.message);
+
+ $.removeCookie('toaster-notification', { path: "/"});
+ })();
+
+
+
var ajaxLoadingTimer;
/* If we don't have a console object which might be the case in some
@@ -493,9 +598,7 @@ $(document).ready(function() {
delay: { show : 300 }
});
- // show help bubble only on hover inside tables
- $(".hover-help").css("visibility","hidden");
-
+ // show help bubble on hover inside tables
$("table").on("mouseover", "th, td", function () {
$(this).find(".hover-help").css("visibility","visible");
});
@@ -509,14 +612,14 @@ $(document).ready(function() {
// show task type and outcome in task details pages
$(".task-info").tooltip({ container: 'body', html: true, delay: {show: 200}, placement: 'right' });
- // initialise the tooltips for the icon-pencil icons
- $(".icon-pencil").tooltip({ container: 'body', html: true, delay: {show: 400}, title: "Change" });
+ // initialise the tooltips for the edit icons
+ $(".glyphicon-edit").tooltip({ container: 'body', html: true, delay: {show: 400}, title: "Change" });
// initialise the tooltips for the download icons
$(".icon-download-alt").tooltip({ container: 'body', html: true, delay: { show: 200 } });
// initialise popover for debug information
- $(".icon-info-sign").popover( { placement: 'bottom', html: true, container: 'body' });
+ $(".glyphicon-info-sign").popover( { placement: 'bottom', html: true, container: 'body' });
// linking directly to tabs
$(function(){
@@ -582,7 +685,9 @@ $(document).ready(function() {
window.clearTimeout(ajaxLoadingTimer);
ajaxLoadingTimer = window.setTimeout(function() {
- $("#loading-notification").fadeIn();
+ if (libtoaster.ajaxLoadingTimerEnabled) {
+ $("#loading-notification").fadeIn();
+ }
}, 1200);
});
@@ -613,6 +718,11 @@ $(document).ready(function() {
});
}
+ /* Make sure we don't have a notification overlay a modal */
+ $(".modal").on('show.bs.modal', function(){
+ $(".alert-dismissible").fadeOut();
+ });
+
if (libtoaster.debug) {
check_for_duplicate_ids();
} else {
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js
index 09117e1da..73d0935fa 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/mrbsection.js
@@ -1,33 +1,19 @@
function mrbSectionInit(ctx){
-
- var projectBuilds;
-
- if (ctx.mrbType === 'project')
- projectBuilds = true;
-
- $(".cancel-build-btn").click(function(e){
+ $('#latest-builds').on('click', '.cancel-build-btn', function(e){
+ e.stopImmediatePropagation();
e.preventDefault();
var url = $(this).data('request-url');
var buildReqIds = $(this).data('buildrequest-id');
- var banner = $(this).parents(".alert");
-
- banner.find(".progress-info").fadeOut().promise().done(function(){
- $("#cancelling-msg-" + buildReqIds).show();
- console.log("cancel build");
- libtoaster.cancelABuild(url, buildReqIds, function(){
- if (projectBuilds == false){
- /* the all builds page is not 'self updating' like thei
- * project Builds
- */
- window.location.reload();
- }
- }, null);
- });
+
+ libtoaster.cancelABuild(url, buildReqIds, function () {
+ window.location.reload();
+ }, null);
});
- $(".run-again-btn").click(function(e){
+ $('#latest-builds').on('click', '.rebuild-btn', function(e){
+ e.stopImmediatePropagation();
e.preventDefault();
var url = $(this).data('request-url');
@@ -38,58 +24,112 @@ function mrbSectionInit(ctx){
}, null);
});
+ // cached version of buildData, so we can determine whether a build has
+ // changed since it was last fetched, and update the DOM appropriately
+ var buildData = {};
- var progressTimer;
-
- if (projectBuilds === true){
- progressTimer = window.setInterval(function() {
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,
- function(prjInfo){
- /* These two are needed because a build can be 100% and still
- * in progress due to the fact that the % done is updated at the
- * start of a task so it can be doing the last task at 100%
- */
- var inProgress = 0;
- var allPercentDone = 0;
- if (prjInfo.builds.length === 0)
- return
-
- for (var i in prjInfo.builds){
- var build = prjInfo.builds[i];
-
- if (build.outcome === "In Progress" ||
- $(".progress .bar").length > 0){
- /* Update the build progress */
- var percentDone;
-
- if (build.outcome !== "In Progress"){
- /* We have to ignore the value when it's Succeeded because it
- * goes back to 0
- */
- percentDone = 100;
- } else {
- percentDone = build.percentDone;
- inProgress++;
- }
-
- $("#build-pc-done-" + build.id).text(percentDone);
- $("#build-pc-done-title-" + build.id).attr("title", percentDone);
- $("#build-pc-done-bar-" + build.id).css("width",
- String(percentDone) + "%");
-
- allPercentDone += percentDone;
- }
- }
+ // returns the cached version of this build, or {} is there isn't a cached one
+ function getCached(build) {
+ return buildData[build.id] || {};
+ }
+
+ // returns true if a build's state changed to "Succeeded", "Failed"
+ // or "Cancelled" from some other value
+ function buildFinished(build) {
+ var cached = getCached(build);
+ return cached.state &&
+ cached.state !== build.state &&
+ (build.state == 'Succeeded' || build.state == 'Failed' ||
+ build.state == 'Cancelled');
+ }
+
+ // returns true if the state changed
+ function stateChanged(build) {
+ var cached = getCached(build);
+ return (cached.state !== build.state);
+ }
+
+ // returns true if the tasks_complete_percentage changed
+ function tasksProgressChanged(build) {
+ var cached = getCached(build);
+ return (cached.tasks_complete_percentage !== build.tasks_complete_percentage);
+ }
- if (allPercentDone === (100 * prjInfo.builds.length) && !inProgress)
+ // returns true if the number of recipes parsed/to parse changed
+ function recipeProgressChanged(build) {
+ var cached = getCached(build);
+ return (cached.recipes_parsed_percentage !== build.recipes_parsed_percentage);
+ }
+
+ function refreshMostRecentBuilds(){
+ libtoaster.getMostRecentBuilds(
+ libtoaster.ctx.mostRecentBuildsUrl,
+
+ // success callback
+ function (data) {
+ var build;
+ var tmpl;
+ var container;
+ var selector;
+ var colourClass;
+ var elements;
+
+ for (var i = 0; i < data.length; i++) {
+ build = data[i];
+
+ if (buildFinished(build)) {
+ // a build finished: reload the whole page so that the build
+ // shows up in the builds table
window.location.reload();
+ }
+ else if (stateChanged(build)) {
+ // update the whole template
+ build.warnings_pluralise = (build.warnings !== 1 ? 's' : '');
+ build.errors_pluralise = (build.errors !== 1 ? 's' : '');
+
+ tmpl = $.templates("#build-template");
+
+ html = $(tmpl.render(build));
+
+ selector = '[data-latest-build-result="' + build.id + '"] ' +
+ '[data-role="build-status-container"]';
+ container = $(selector);
+
+ // initialize bootstrap tooltips in the new HTML
+ html.find('span.glyphicon-question-sign').tooltip();
- /* Our progress bar is not still showing so shutdown the polling. */
- if ($(".progress .bar").length === 0)
- window.clearInterval(progressTimer);
+ container.html(html);
+ }
+ else if (tasksProgressChanged(build)) {
+ // update the task progress text
+ selector = '#build-pc-done-' + build.id;
+ $(selector).html(build.tasks_complete_percentage);
+
+ // update the task progress bar
+ selector = '#build-pc-done-bar-' + build.id;
+ $(selector).width(build.tasks_complete_percentage + '%');
+ }
+ else if (recipeProgressChanged(build)) {
+ // update the recipe progress text
+ selector = '#recipes-parsed-percentage-' + build.id;
+ $(selector).html(build.recipes_parsed_percentage);
+
+ // update the recipe progress bar
+ selector = '#recipes-parsed-percentage-bar-' + build.id;
+ $(selector).width(build.recipes_parsed_percentage + '%');
+ }
- });
- }, 1500);
+ buildData[build.id] = build;
+ }
+ },
+
+ // fail callback
+ function (data) {
+ console.error(data);
+ }
+ );
}
-}
+ window.setInterval(refreshMostRecentBuilds, 1500);
+ refreshMostRecentBuilds();
+}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js
index cb9ed4da0..dace8e325 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/newcustomimage_modal.js
@@ -22,26 +22,40 @@ function newCustomImageModalInit(){
var nameInput = imgCustomModal.find('input');
var invalidNameMsg = "Image names cannot contain spaces or capital letters. The only allowed special character is dash (-).";
- var duplicateNameMsg = "A recipe with this name already exists. Image names must be unique.";
+ var duplicateNameMsg = "An image with this name already exists. Image names must be unique.";
var duplicateImageInProjectMsg = "An image with this name already exists in this project."
var invalidBaseRecipeIdMsg = "Please select an image to customise.";
- // capture clicks on radio buttons inside the modal; when one is selected,
- // set the recipe on the modal
- imgCustomModal.on("click", "[name='select-image']", function (e) {
+ // set button to "submit" state and enable text entry so user can
+ // enter the custom recipe name
+ showSubmitState();
+
+ /* capture clicks on radio buttons inside the modal; when one is selected,
+ * set the recipe on the modal
+ */
+ imgCustomModal.on("click", "[name='select-image']", function(e) {
clearRecipeError();
+ $(".radio").each(function(){
+ $(this).removeClass("has-error");
+ });
var recipeId = $(e.target).attr('data-recipe');
imgCustomModal.data('recipe', recipeId);
});
newCustomImgBtn.click(function(e){
+ // disable the button and text entry
+ showLoadingState();
+
e.preventDefault();
var baseRecipeId = imgCustomModal.data('recipe');
if (!baseRecipeId) {
showRecipeError(invalidBaseRecipeIdMsg);
+ $(".radio").each(function(){
+ $(this).addClass("has-error");
+ });
return;
}
@@ -62,16 +76,37 @@ function newCustomImageModalInit(){
}
} else {
imgCustomModal.modal('hide');
+ imgCustomModal.one('hidden.bs.modal', showSubmitState);
window.location.replace(ret.url + '?notify=new');
}
});
}
});
+ // enable text entry, show "Create image" button text
+ function showSubmitState() {
+ libtoaster.enableAjaxLoadingTimer();
+ newCustomImgBtn.find('[data-role="loading-state"]').hide();
+ newCustomImgBtn.find('[data-role="submit-state"]').show();
+ newCustomImgBtn.removeAttr('disabled');
+ nameInput.removeAttr('disabled');
+ }
+
+ // disable text entry, show "Creating image..." button text;
+ // we also disabled the page-level ajax loading spinner while this spinner
+ // is active
+ function showLoadingState() {
+ libtoaster.disableAjaxLoadingTimer();
+ newCustomImgBtn.find('[data-role="submit-state"]').hide();
+ newCustomImgBtn.find('[data-role="loading-state"]').show();
+ newCustomImgBtn.attr('disabled', 'disabled');
+ nameInput.attr('disabled', 'disabled');
+ }
+
function showNameError(text){
invalidNameHelp.text(text);
invalidNameHelp.show();
- nameInput.parent().addClass('error');
+ nameInput.parent().addClass('has-error');
}
function showRecipeError(text){
@@ -92,26 +127,26 @@ function newCustomImageModalInit(){
if (nameInput.val().search(/[^a-z|0-9|-]/) != -1){
showNameError(invalidNameMsg);
newCustomImgBtn.prop("disabled", true);
- nameInput.parent().addClass('error');
+ nameInput.parent().addClass('has-error');
} else {
invalidNameHelp.hide();
newCustomImgBtn.prop("disabled", false);
- nameInput.parent().removeClass('error');
+ nameInput.parent().removeClass('has-error');
}
});
}
-// Set the image recipes which can used as the basis for the custom
-// image recipe the user is creating
-//
-// baseRecipes: a list of one or more recipes which can be
-// used as the base for the new custom image recipe in the format:
-// [{'id': <recipe ID>, 'name': <recipe name>'}, ...]
-//
-// if recipes is a single recipe, just show the text box to set the
-// name for the new custom image; if recipes contains multiple recipe objects,
-// show a set of radio buttons so the user can decide which to use as the
-// basis for the new custom image
+/* Set the image recipes which can used as the basis for the custom
+ * image recipe the user is creating
+ * baseRecipes: a list of one or more recipes which can be
+ * used as the base for the new custom image recipe in the format:
+ * [{'id': <recipe ID>, 'name': <recipe name>'}, ...]
+ *
+ * if recipes is a single recipe, just show the text box to set the
+ * name for the new custom image; if recipes contains multiple recipe objects,
+ * show a set of radio buttons so the user can decide which to use as the
+ * basis for the new custom image
+ */
function newCustomImageModalSetRecipes(baseRecipes) {
var imgCustomModal = $("#new-custom-image-modal");
var imageSelector = $('#new-custom-image-modal [data-role="image-selector"]');
@@ -124,8 +159,9 @@ function newCustomImageModalSetRecipes(baseRecipes) {
// hide the radio button container
imageSelector.hide();
- // set the single recipe ID on the modal as it's the only one
- // we can build from
+ /* set the single recipe ID on the modal as it's the only one
+ * we can build from.
+ */
imgCustomModal.data('recipe', baseRecipes[0].id);
}
else {
@@ -134,14 +170,29 @@ function newCustomImageModalSetRecipes(baseRecipes) {
for (var i = 0; i < baseRecipes.length; i++) {
var recipe = baseRecipes[i];
imageSelectRadiosContainer.append(
- '<label class="radio" data-role="image-radio">' +
- recipe.name +
- '<input type="radio" class="form-control" name="select-image" ' +
+ '<div class="radio"><label data-role="image-radio">' +
+ '<input type="radio" name="select-image" ' +
'data-recipe="' + recipe.id + '">' +
- '</label>'
+ recipe.name +
+ '</label></div>'
);
}
+ /* select the first radio button as default selection. Radio button
+ * groups should always display with an option checked
+ */
+ imageSelectRadiosContainer.find("input:radio:first").attr("checked", "checked");
+
+ /* check which radio button is selected by default inside the modal,
+ * and set the recipe on the modal accordingly
+ */
+ imageSelectRadiosContainer.find("input:radio").each(function(){
+ if ( $(this).is(":checked") ) {
+ var recipeId = $(this).attr("data-recipe");
+ imgCustomModal.data("recipe", recipeId);
+ }
+ });
+
// show the radio button container
imageSelector.show();
}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js
index 3013416dd..453670364 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projectpage.js
@@ -27,11 +27,10 @@ function projectPageInit(ctx) {
var urlParams = libtoaster.parseUrlParams();
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+ libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){
updateProjectLayers(prjInfo.layers);
updateFreqBuildRecipes(prjInfo.freqtargets);
updateProjectRelease(prjInfo.release);
- updateProjectReleases(prjInfo.releases, prjInfo.release);
/* If we're receiving a machine set from the url and it's different from
* our current machine then activate set machine sequence.
@@ -46,54 +45,13 @@ function projectPageInit(ctx) {
/* Now we're really ready show the page */
$("#project-page").show();
- });
-
- (function notificationRequest(){
-
- if (urlParams.hasOwnProperty('notify')){
- switch (urlParams.notify){
- case 'new-project':
- $("#project-created-notification").show();
- break;
- case 'layer-imported':
- layerImportedNotification();
- break;
- default:
- break;
- }
- }
- })();
-
- /* Layer imported notification */
- function layerImportedNotification(){
- var imported = $.cookie("layer-imported-alert");
- var message = "Layer imported";
-
- if (!imported)
- return;
- else
- imported = JSON.parse(imported);
-
- if (imported.deps_added.length === 0) {
- message = "You have imported <strong><a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a></strong> and added it to your project.";
- } else {
- var links = "<a href=\""+imported.imported_layer.layerdetailurl+"\">"+imported.imported_layer.name+"</a>, ";
-
- imported.deps_added.map (function(item, index){
- links +='<a href="'+item.layerdetailurl+'">'+item.name+'</a>';
- /*If we're at the last element we don't want the trailing comma */
- if (imported.deps_added[index+1] !== undefined)
- links += ', ';
- });
-
- /* Length + 1 here to do deps + the imported layer */
- message = 'You have imported <strong><a href="'+imported.imported_layer.layerdetailurl+'">'+imported.imported_layer.name+'</a></strong> and added <strong>'+(imported.deps_added.length+1)+'</strong> layers to your project: <strong>'+links+'</strong>';
- }
-
- libtoaster.showChangeNotification(message);
+ /* Set the project name in the delete modal */
+ $("#delete-project-modal .project-name").text(prjInfo.name);
+ });
- $.removeCookie("layer-imported-alert", { path: "/"});
+ if (urlParams.hasOwnProperty('notify') && urlParams.notify === 'new-project'){
+ $("#project-created-notification").show();
}
/* Add/Rm layer functionality */
@@ -145,7 +103,7 @@ function projectPageInit(ctx) {
for (var i in layers){
var layerObj = layers[i];
- var projectLayer = $("<li><a></a><span class=\"icon-trash\" data-toggle=\"tooltip\" title=\"Remove\"></span></li>");
+ var projectLayer = $("<li><a></a><span class=\"glyphicon glyphicon-trash\" data-toggle=\"tooltip\" title=\"Remove\"></span></li>");
projectLayer.data('layer', layerObj);
projectLayer.children("span").tooltip();
@@ -154,7 +112,12 @@ function projectPageInit(ctx) {
link.attr("href", layerObj.layerdetailurl);
link.text(layerObj.name);
- link.tooltip({title: layerObj.vcs_url + " | "+ layerObj.vcs_reference, placement: "right"});
+
+ if (layerObj.local_source_dir) {
+ link.tooltip({title: layerObj.local_source_dir, placement: "right"});
+ } else {
+ link.tooltip({title: layerObj.vcs_url + " | "+ layerObj.vcs_reference, placement: "right"});
+ }
var trashItem = projectLayer.children("span");
trashItem.click(function (e) {
@@ -208,7 +171,7 @@ function projectPageInit(ctx) {
}
for (var i in recipes){
- var freqTargetCheck = $('<li><label class="checkbox"><input type="checkbox" /><span class="freq-target-name"></span></label></li>');
+ var freqTargetCheck = $('<li><div class="checkbox"><label><input type="checkbox" /><span class="freq-target-name"></span></label></li>');
freqTargetCheck.find(".freq-target-name").text(recipes[i]);
freqTargetCheck.find("input").val(recipes[i]);
freqTargetCheck.click(function(){
@@ -264,7 +227,9 @@ function projectPageInit(ctx) {
machineNameTitle.text(machineName);
}
- libtoaster.makeTypeahead(machineChangeInput, libtoaster.ctx.machinesTypeAheadUrl, { }, function(item){
+ libtoaster.makeTypeahead(machineChangeInput,
+ libtoaster.ctx.machinesTypeAheadUrl,
+ { }, function(item){
currentMachineAddSelection = item.name;
machineChangeBtn.removeAttr("disabled");
});
@@ -285,7 +250,7 @@ function projectPageInit(ctx) {
machineChangeCancel.click();
/* Show the alert message */
- var message = $('<span class="lead">You have changed the machine to: <strong><span id="notify-machine-name"></span></strong></span>');
+ var message = $('<span>You have changed the machine to: <strong><span id="notify-machine-name"></span></strong></span>');
message.find("#notify-machine-name").text(currentMachineAddSelection);
libtoaster.showChangeNotification(message);
},
@@ -301,146 +266,35 @@ function projectPageInit(ctx) {
releaseTitle.text(release.description);
}
- function updateProjectReleases(releases, current){
- for (var i in releases){
- var releaseOption = $("<option></option>");
- releaseOption.val(releases[i].id);
- releaseOption.text(releases[i].description);
- releaseOption.data('release', releases[i]);
-
- if (releases[i].id == current.id)
- releaseOption.attr("selected", "selected");
-
- releaseForm.children("select").append(releaseOption);
- }
- }
-
- releaseChangeFormToggle.click(function(){
- releaseForm.slideDown();
- releaseTitle.hide();
- $(this).hide();
- });
-
- cancelReleaseChange.click(function(e){
+ $("#delete-project-confirmed").click(function(e){
e.preventDefault();
- releaseForm.slideUp(function(){
- releaseTitle.show();
- releaseChangeFormToggle.show();
- });
- });
-
- function changeProjectRelease(release, layersToRm){
- libtoaster.editCurrentProject({ projectVersion : release.id },
- function(){
- /* Success */
- /* Update layers list with new layers */
- layersInPrjList.addClass('muted');
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,
- function(prjInfo){
- layersInPrjList.children().remove();
- updateProjectLayers(prjInfo.layers);
- layersInPrjList.removeClass('muted');
- releaseChangedNotification(release, prjInfo.layers, layersToRm);
- });
- updateProjectRelease(release);
- cancelReleaseChange.click();
- });
- }
-
- /* Create a notification to show the changes to the layer configuration
- * caused by changing a release.
- */
-
- function releaseChangedNotification(release, layers, layersToRm){
-
- var message;
-
- if (layers.length === 0 && layersToRm.length === 0){
- message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>.');
- message.find("#notify-release-name").text(release.description);
- libtoaster.showChangeNotification(message);
- return;
- }
-
- /* Create the whitespace separated list of layers removed */
- var layersDelList = "";
-
- layersToRm.map(function(layer, i){
- layersDelList += layer.name;
- if (layersToRm[i+1] !== undefined)
- layersDelList += ', ';
- });
-
- message = $('<span><span class="lead">You have changed the project release to: <strong><span id="notify-release-name"></span></strong>. This has caused the following changes in your project layers:</span><ul id="notify-layers-changed-list"></ul></span>');
-
- var changedList = message.find("#notify-layers-changed-list");
-
- message.find("#notify-release-name").text(release.description);
-
- /* Manually construct the list item for changed layers */
- var li = '<li><strong>'+layers.length+'</strong> layers changed to the <strong>'+release.name+'</strong> release: ';
- for (var i in layers){
- li += '<a href='+layers[i].layerdetailurl+'>'+layers[i].name+'</a>';
- if (i !== 0)
- li += ', ';
- }
-
- changedList.append($(li));
-
- /* Layers removed */
- if (layersToRm && layersToRm.length > 0){
- if (layersToRm.length == 1)
- li = '<li><strong>1</strong> layer removed: '+layersToRm[0].name+'</li>';
- else
- li = '<li><strong>'+layersToRm.length+'</strong> layers deleted: '+layersDelList+'</li>';
-
- changedList.append($(li));
- }
-
- libtoaster.showChangeNotification(message);
- }
-
- /* Show the modal dialog which gives the option to remove layers which
- * aren't compatible with the proposed release
- */
- function showReleaseLayerChangeModal(release, layers){
- var layersToRmList = releaseModal.find("#layers-to-remove-list");
- layersToRmList.text("");
-
- releaseModal.find(".proposed-release-change-name").text(release.description);
- releaseModal.data("layers", layers);
- releaseModal.data("release", release);
-
- for (var i in layers){
- layersToRmList.append($("<li></li>").text(layers[i].name));
- }
- releaseModal.modal('show');
- }
-
- $("#change-release-btn").click(function(e){
- e.preventDefault();
-
- var newRelease = releaseForm.find("option:selected").data('release');
-
- $.getJSON(ctx.testReleaseChangeUrl,
- { new_release_id: newRelease.id },
- function(layers) {
- if (layers.rows.length === 0){
- /* No layers to change for this release */
- changeProjectRelease(newRelease, []);
- } else {
- showReleaseLayerChangeModal(newRelease, layers.rows);
+ libtoaster.disableAjaxLoadingTimer();
+ $(this).find('[data-role="submit-state"]').hide();
+ $(this).find('[data-role="loading-state"]').show();
+ $(this).attr("disabled", "disabled");
+ $('#delete-project-modal [data-dismiss="modal"]').hide();
+
+ $.ajax({
+ type: 'DELETE',
+ url: libtoaster.ctx.xhrProjectUrl,
+ headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
+ success: function (data) {
+ if (data.error !== "ok") {
+ console.warn(data.error);
+ } else {
+ var msg = $('<span>You have deleted <strong>1</strong> project: <strong id="project-deleted"></strong></span>');
+
+ msg.find("#project-deleted").text(libtoaster.ctx.projectName);
+ libtoaster.setNotification("project-deleted", msg.html());
+
+ window.location.replace(data.gotoUrl);
+ }
+ },
+ error: function (data) {
+ console.warn(data);
}
});
});
- /* Release change modal accept */
- $("#change-release-and-rm-layers").click(function(){
- var layers = releaseModal.data("layers");
- var release = releaseModal.data("release");
-
- changeProjectRelease(release, layers);
- });
-
}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
index b09f974e4..92ab2d67f 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
@@ -4,7 +4,7 @@ function projectTopBarInit(ctx) {
var projectNameForm = $("#project-name-change-form");
var projectNameContainer = $("#project-name-container");
- var projectName = $("#project-name");
+ var projectName = $(".project-name");
var projectNameFormToggle = $("#project-change-form-toggle");
var projectNameChangeCancel = $("#project-name-change-cancel");
@@ -25,13 +25,14 @@ function projectTopBarInit(ctx) {
e.preventDefault();
projectNameForm.hide();
projectNameContainer.fadeIn();
+ $("#project-name-change-input").val(projectName.first().text());
});
$("#project-name-change-btn").click(function(){
var newProjectName = $("#project-name-change-input").val();
libtoaster.editCurrentProject({ projectName: newProjectName }, function (){
- projectName.html(newProjectName);
+ projectName.text(newProjectName);
libtoaster.ctx.projectName = newProjectName;
projectNameChangeCancel.click();
});
@@ -87,4 +88,10 @@ function projectTopBarInit(ctx) {
window.location.replace(libtoaster.ctx.projectBuildsUrl);
}, null);
});
+
+ /* Call makeProjectNameValidation function */
+ libtoaster.makeProjectNameValidation($("#project-name-change-input"),
+ $("#hint-error-project-name"), $("#validate-project-name"),
+ $("#project-name-change-btn"));
+
}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js
index f738144ae..176ce579f 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/table.js
@@ -15,6 +15,7 @@ function tableInit(ctx){
orderby : null,
filter : null,
search : null,
+ default_orderby: null,
};
var defaultHiddenCols = [];
@@ -75,14 +76,21 @@ function tableInit(ctx){
if (tableData.total === 0){
tableContainer.hide();
- if ($("#no-results-special-"+ctx.tableName).length > 0) {
- /* use this page's special no-results form instead of the default */
- $("#no-results-search-input-"+ctx.tableName).val(tableParams.search);
- $("#no-results-special-"+ctx.tableName).show();
- $("#results-found-"+ctx.tableName).hide();
- } else {
- $("#new-search-input-"+ctx.tableName).val(tableParams.search);
- $("#no-results-"+ctx.tableName).show();
+ /* No results caused by a search returning nothing */
+ if (tableParams.search) {
+ if ($("#no-results-special-"+ctx.tableName).length > 0) {
+ /* use this page's special no-results form instead of the default */
+ $("#no-results-search-input-"+ctx.tableName).val(tableParams.search);
+ $("#no-results-special-"+ctx.tableName).show();
+ $("#results-found-"+ctx.tableName).hide();
+ } else {
+ $("#new-search-input-"+ctx.tableName).val(tableParams.search);
+ $("#no-results-"+ctx.tableName).show();
+ }
+ }
+ else {
+ /* No results caused by there being no data */
+ $("#empty-state-"+ctx.tableName).show();
}
table.trigger("table-done", [tableData.total, tableParams]);
@@ -90,6 +98,7 @@ function tableInit(ctx){
} else {
tableContainer.show();
$("#no-results-"+ctx.tableName).hide();
+ $("#empty-state-"+ctx.tableName).hide();
}
setupTableChrome(tableData);
@@ -101,27 +110,8 @@ function tableInit(ctx){
var row = $("<tr></tr>");
column_index = -1;
for (var key_j in tableData.rows[i]){
-
- /* if we have a static: version of a key, prefer the static: version for rendering */
- var orig_key_j = key_j;
-
- if (key_j.indexOf("static:") === 0) {
- if (key_j.substr("static:".length) in tableData.rows[i]) {
- continue;
- }
- orig_key_j = key_j.substr("static:".length)
- } else if (("static:" + key_j) in tableData.rows[i]) {
- key_j = "static:" + key_j;
- }
-
- /* we skip over un-displayable column entries */
- column_index += 1;
- if (! tableData.columns[column_index].displayable) {
- continue;
- }
-
var td = $("<td></td>");
- td.prop("class", orig_key_j);
+ td.prop("class", key_j);
if (tableData.rows[i][key_j]){
td.html(tableData.rows[i][key_j]);
}
@@ -181,6 +171,15 @@ function tableInit(ctx){
table.css("padding-bottom", 0);
tableContainer.css("visibility", "visible");
+ /* If we have a hash in the url try and highlight that item in the table */
+ if (window.location.hash){
+ var highlight = $("table a[name="+window.location.hash.replace('#',''));
+ if (highlight.length > 0){
+ highlight.parents("tr").addClass('highlight');
+ window.scroll(0, highlight.position().top - 50);
+ }
+ }
+
table.trigger("table-done", [tableData.total, tableParams]);
}
@@ -188,12 +187,14 @@ function tableInit(ctx){
if (tableChromeDone === true)
return;
- var tableHeadRow = table.find("thead");
+ var tableHeadRow = table.find("thead > tr");
var editColMenu = $("#table-chrome-"+ctx.tableName).find(".editcol");
tableHeadRow.html("");
editColMenu.html("");
+ tableParams.default_orderby = tableData.default_orderby;
+
if (!tableParams.orderby && tableData.default_orderby){
tableParams.orderby = tableData.default_orderby;
}
@@ -209,7 +210,7 @@ function tableInit(ctx){
/* Setup the help text */
if (col.help_text.length > 0) {
- var help_text = $('<i class="icon-question-sign get-help"> </i>');
+ var help_text = $('<span class="glyphicon glyphicon-question-sign get-help"> </span>');
help_text.tooltip({title: col.help_text});
header.append(help_text);
}
@@ -219,6 +220,7 @@ function tableInit(ctx){
var title = $('<a href=\"#\" ></a>');
title.data('field-name', col.field_name);
+ title.attr('data-sort-field', col.field_name);
title.text(col.title);
title.click(sortColumnClicked);
@@ -246,12 +248,12 @@ function tableInit(ctx){
} else {
/* Not orderable */
header.css("font-weight", "normal");
- header.append('<span class="muted">' + col.title + '</span> ');
+ header.append('<span class="text-muted">' + col.title + '</span> ');
}
/* Setup the filter button */
if (col.filter_name){
- var filterBtn = $('<a href="#" role="button" data-filter-on="' + col.filter_name + '" class="pull-right btn btn-mini" data-toggle="modal"><i class="icon-filter filtered"></i></a>');
+ var filterBtn = $('<a href="#" role="button" data-filter-on="' + col.filter_name + '" class="pull-right btn btn-link btn-xs" data-toggle="modal"><i class="glyphicon glyphicon-filter filtered"></i></a>');
filterBtn.data('filter-name', col.filter_name);
filterBtn.prop('id', col.filter_name);
@@ -270,7 +272,7 @@ function tableInit(ctx){
tableHeadRow.append(header);
/* Now setup the checkbox state and click handler */
- var toggler = $('<li><label class="checkbox">'+col.title+'<input type="checkbox" id="checkbox-'+ col.field_name +'" class="col-toggle" value="'+col.field_name+'" /></label></li>');
+ var toggler = $('<li><div class="checkbox"><label><input type="checkbox" id="checkbox-'+ col.field_name +'" class="col-toggle" value="'+col.field_name+'" />'+col.title+'</label></div></li>');
var togglerInput = toggler.find("input");
@@ -280,7 +282,8 @@ function tableInit(ctx){
if (col.hideable){
togglerInput.click(colToggleClicked);
} else {
- toggler.find("label").addClass("muted");
+ toggler.find("label").addClass("text-muted");
+ toggler.find("label").parent().addClass("disabled");
togglerInput.attr("disabled", "disabled");
}
@@ -297,11 +300,12 @@ function tableInit(ctx){
/* Toggles the active state of the filter button */
function filterBtnActive(filterBtn, active){
if (active) {
+ filterBtn.removeClass("btn-link");
filterBtn.addClass("btn-primary");
filterBtn.tooltip({
html: true,
- title: '<button class="btn btn-small btn-primary" onClick=\'$("#clear-filter-btn-'+ ctx.tableName +'").click();\'>Clear filter</button>',
+ title: '<button class="btn btn-sm btn-primary" onClick=\'$("#clear-filter-btn-'+ ctx.tableName +'").click();\'>Clear filter</button>',
placement: 'bottom',
delay: {
hide: 1500,
@@ -310,6 +314,7 @@ function tableInit(ctx){
});
} else {
filterBtn.removeClass("btn-primary");
+ filterBtn.addClass("btn-link");
filterBtn.tooltip('destroy');
}
}
@@ -343,29 +348,65 @@ function tableInit(ctx){
}
}
- function sortColumnClicked(e){
- e.preventDefault();
+ /* Apply an ordering to the current table.
+ *
+ * 1. Find the column heading matching the sortSpecifier
+ * 2. Set its up/down arrow and add .sorted
+ *
+ * orderby: e.g. "-started_on", "completed_on"
+ * colHeading: column heading element to activate (by showing the caret
+ * up/down, depending on sort order); if not set, the correct column
+ * heading is selected from the DOM using orderby as a key
+ */
+ function applyOrderby(orderby, colHeading) {
+ if (!orderby) {
+ return;
+ }
+
+ // We only have one sort at a time so remove existing sort indicators
+ $("#" + ctx.tableName + " th .icon-caret-down").hide();
+ $("#" + ctx.tableName + " th .icon-caret-up").hide();
+ $("#" + ctx.tableName + " th a").removeClass("sorted");
- /* We only have one sort at a time so remove any existing sort indicators */
- $("#"+ctx.tableName+" th .icon-caret-down").hide();
- $("#"+ctx.tableName+" th .icon-caret-up").hide();
- $("#"+ctx.tableName+" th a").removeClass("sorted");
+ // normalise the orderby so we can use it to find the link we want
+ // to style
+ var fieldName = orderby;
+ if (fieldName.indexOf('-') === 0) {
+ fieldName = fieldName.slice(1);
+ }
+
+ // find the table header element which corresponds to the sort field
+ // (if we don't already have it)
+ if (!colHeading) {
+ colHeading = $('[data-sort-field="' + fieldName + '"]');
+ }
+
+ colHeading.addClass("sorted");
+
+ var parent = colHeading.parent();
+
+ if (orderby.indexOf('-') === 0) {
+ parent.children('.icon-caret-up').show();
+ }
+ else {
+ parent.children('.icon-caret-down').show();
+ }
+
+ tableParams.orderby = orderby;
+ loadData(tableParams);
+ }
- var fieldName = $(this).data('field-name');
+ function sortColumnClicked(e){
+ e.preventDefault();
/* if we're already sorted sort the other way */
- if (tableParams.orderby === fieldName &&
+ var orderby = $(this).data('field-name');
+ if (tableParams.orderby === orderby &&
tableParams.orderby.indexOf('-') === -1) {
- tableParams.orderby = '-' + $(this).data('field-name');
- $(this).parent().children('.icon-caret-up').show();
- } else {
- tableParams.orderby = $(this).data('field-name');
- $(this).parent().children('.icon-caret-down').show();
+ orderby = '-' + orderby;
}
- $(this).addClass("sorted");
-
- loadData(tableParams);
+ applyOrderby(orderby, $(this));
}
function pageButtonClicked(e) {
@@ -384,11 +425,13 @@ function tableInit(ctx){
table.find("."+col).show();
} else {
table.find("."+col).hide();
- /* If we're ordered by the column we're hiding remove the order by */
+ // If we're ordered by the column we're hiding remove the order by
+ // and apply the default one instead
if (col === tableParams.orderby ||
'-' + col === tableParams.orderby){
tableParams.orderby = null;
- $("#"+ctx.tableName +" .default-orderby").click();
+
+ applyOrderby(tableParams.default_orderby);
}
}
@@ -415,23 +458,23 @@ function tableInit(ctx){
var hasNoRecords = (Number(filterActionData.count) == 0);
var actionStr = '<div class="radio">' +
- '<input type="radio" name="filter"' +
- ' value="' + filterName + '"';
+ '<label class="filter-title' +
+ (hasNoRecords ? ' text-muted' : '') + '"' +
+ ' for="' + filterName + '">' +
+ '<input type="radio" name="filter"' +
+ ' value="' + filterName + '"';
if (hasNoRecords) {
actionStr += ' disabled="disabled"';
}
actionStr += ' id="' + filterName + '">' +
- '<input type="hidden" name="filter_value" value="on"' +
- ' data-value-for="' + filterName + '">' +
- '<label class="filter-title' +
- (hasNoRecords ? ' muted' : '') + '"' +
- ' for="' + filterName + '">' +
- filterActionData.title +
- ' (' + filterActionData.count + ')' +
- '</label>' +
- '</div>';
+ '<input type="hidden" name="filter_value" value="on"' +
+ ' data-value-for="' + filterName + '">' +
+ filterActionData.title +
+ ' (' + filterActionData.count + ')' +
+ '</label>' +
+ '</div>';
var action = $(actionStr);
@@ -465,22 +508,23 @@ function tableInit(ctx){
*/
function createActionDateRange(filterName, filterValue, filterActionData) {
var action = $('<div class="radio">' +
+ '<label class="filter-title"' +
+ ' for="' + filterName + '">' +
'<input type="radio" name="filter"' +
' value="' + filterName + '" ' +
' id="' + filterName + '">' +
'<input type="hidden" name="filter_value" value=""' +
' data-value-for="' + filterName + '">' +
- '<label class="filter-title"' +
- ' for="' + filterName + '">' +
filterActionData.title +
'</label>' +
- '<input type="text" maxlength="10" class="input-small"' +
+ '<div class="form-inline form-group date-filter-controls">' +
+ '<input type="text" maxlength="10" class="form-control"' +
' data-date-from-for="' + filterName + '">' +
- '<span class="help-inline">to</span>' +
- '<input type="text" maxlength="10" class="input-small"' +
+ '<span>to</span>' +
+ '<input type="text" maxlength="10" class="form-control"' +
' data-date-to-for="' + filterName + '">' +
'<span class="help-inline get-help">(yyyy-mm-dd)</span>' +
- '</div>');
+ '</div></div>');
var radio = action.find('[type="radio"]');
var value = action.find('[data-value-for]');
@@ -621,7 +665,7 @@ function tableInit(ctx){
queryset on the table
*/
var filterActionRadios = $('#filter-actions-' + ctx.tableName);
- var filterApplyBtn = $('[data-role="filter-apply"]');
+ var filterApplyBtn = $('[data-cat="filter-apply"]');
var setApplyButtonState = function (e, filterActionValue) {
if (filterActionValue !== undefined) {
@@ -662,7 +706,7 @@ function tableInit(ctx){
if (action) {
// Setup the current selected filter; default to 'all' if
// no current filter selected
- var radioInput = action.children('input[name="filter"]');
+ var radioInput = action.find('input[name="filter"]');
if ((tableParams.filter &&
tableParams.filter === radioInput.val()) ||
filterActionData.action_name == 'all') {
@@ -788,6 +832,7 @@ function tableInit(ctx){
loadData(tableParams);
- $(this).parent().modal('hide');
+
+ $('#filter-modal-'+ctx.tableName).modal('hide');
});
}
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/tests/test.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/tests/test.js
index aac0ba60a..d7953de44 100644
--- a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/tests/test.js
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/tests/test.js
@@ -2,7 +2,6 @@
/* Unit tests for Toaster's JS */
/* libtoaster tests */
-
QUnit.test("Layer alert notification", function(assert) {
var layer = {
"layerdetailurl":"/toastergui/project/1/layer/22",
@@ -43,9 +42,8 @@ QUnit.test("Layer alert notification", function(assert) {
QUnit.test("Project info", function(assert){
var done = assert.async();
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+ libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){
assert.ok(prjInfo.machine.name);
- assert.ok(prjInfo.releases.length > 0);
assert.ok(prjInfo.layers.length > 0);
assert.ok(prjInfo.freqtargets);
assert.ok(prjInfo.release);
@@ -83,11 +81,11 @@ QUnit.test("Add layer", function(assert){
}, 200);
/* Compare the number of layers before and after the add in the project */
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl, function(prjInfo){
+ libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl, function(prjInfo){
var origNumLayers = prjInfo.layers.length;
libtoaster.addRmLayer(layer, true, function(deps){
- libtoaster.getProjectInfo(libtoaster.ctx.projectPageUrl,
+ libtoaster.getProjectInfo(libtoaster.ctx.xhrProjectUrl,
function(prjInfo){
assert.ok(prjInfo.layers.length > origNumLayers,
"Layer not added to project");
@@ -135,10 +133,10 @@ QUnit.test("Make typeaheads", function(assert){
libtoaster.makeTypeahead(recipesT,
libtoaster.ctx.recipesTypeAheadUrl, {}, function(){});
- assert.ok(recipesT.data('typeahead'));
- assert.ok(layersT.data('typeahead'));
- assert.ok(projectsT.data('typeahead'));
- assert.ok(recipesT.data('typeahead'));
+ assert.ok(recipesT.data('ttTypeahead'));
+ assert.ok(layersT.data('ttTypeahead'));
+ assert.ok(projectsT.data('ttTypeahead'));
+ assert.ok(recipesT.data('ttTypeahead'));
});
diff --git a/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js
new file mode 100644
index 000000000..f3efd80cb
--- /dev/null
+++ b/import-layers/yocto-poky/bitbake/lib/toaster/toastergui/static/js/typeahead.jquery.js
@@ -0,0 +1,1551 @@
+/*!
+ * typeahead.js 0.11.1
+ * https://github.com/twitter/typeahead.js
+ * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
+ */
+
+(function(root, factory) {
+ if (typeof define === "function" && define.amd) {
+ define("typeahead.js", [ "jquery" ], function(a0) {
+ return factory(a0);
+ });
+ } else if (typeof exports === "object") {
+ module.exports = factory(require("jquery"));
+ } else {
+ factory(jQuery);
+ }
+})(this, function($) {
+ var _ = function() {
+ "use strict";
+ return {
+ isMsie: function() {
+ return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
+ },
+ isBlankString: function(str) {
+ return !str || /^\s*$/.test(str);
+ },
+ escapeRegExChars: function(str) {
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+ },
+ isString: function(obj) {
+ return typeof obj === "string";
+ },
+ isNumber: function(obj) {
+ return typeof obj === "number";
+ },
+ isArray: $.isArray,
+ isFunction: $.isFunction,
+ isObject: $.isPlainObject,
+ isUndefined: function(obj) {
+ return typeof obj === "undefined";
+ },
+ isElement: function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ },
+ isJQuery: function(obj) {
+ return obj instanceof $;
+ },
+ toStr: function toStr(s) {
+ return _.isUndefined(s) || s === null ? "" : s + "";
+ },
+ bind: $.proxy,
+ each: function(collection, cb) {
+ $.each(collection, reverseArgs);
+ function reverseArgs(index, value) {
+ return cb(value, index);
+ }
+ },
+ map: $.map,
+ filter: $.grep,
+ every: function(obj, test) {
+ var result = true;
+ if (!obj) {
+ return result;
+ }
+ $.each(obj, function(key, val) {
+ if (!(result = test.call(null, val, key, obj))) {
+ return false;
+ }
+ });
+ return !!result;
+ },
+ some: function(obj, test) {
+ var result = false;
+ if (!obj) {
+ return result;
+ }
+ $.each(obj, function(key, val) {
+ if (result = test.call(null, val, key, obj)) {
+ return false;
+ }
+ });
+ return !!result;
+ },
+ mixin: $.extend,
+ identity: function(x) {
+ return x;
+ },
+ clone: function(obj) {
+ return $.extend(true, {}, obj);
+ },
+ getIdGenerator: function() {
+ var counter = 0;
+ return function() {
+ return counter++;
+ };
+ },
+ templatify: function templatify(obj) {
+ return $.isFunction(obj) ? obj : template;
+ function template() {
+ return String(obj);
+ }
+ },
+ defer: function(fn) {
+ setTimeout(fn, 0);
+ },
+ debounce: function(func, wait, immediate) {
+ var timeout, result;
+ return function() {
+ var context = this, args = arguments, later, callNow;
+ later = function() {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ }
+ };
+ callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ }
+ return result;
+ };
+ },
+ throttle: function(func, wait) {
+ var context, args, timeout, result, previous, later;
+ previous = 0;
+ later = function() {
+ previous = new Date();
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function() {
+ var now = new Date(), remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ },
+ stringify: function(val) {
+ return _.isString(val) ? val : JSON.stringify(val);
+ },
+ noop: function() {}
+ };
+ }();
+ var WWW = function() {
+ "use strict";
+ var defaultClassNames = {
+ wrapper: "twitter-typeahead",
+ input: "tt-input",
+ hint: "tt-hint",
+ menu: "tt-menu",
+ dataset: "tt-dataset",
+ suggestion: "tt-suggestion",
+ selectable: "tt-selectable",
+ empty: "tt-empty",
+ open: "tt-open",
+ cursor: "tt-cursor",
+ highlight: "tt-highlight"
+ };
+ return build;
+ function build(o) {
+ var www, classes;
+ classes = _.mixin({}, defaultClassNames, o);
+ www = {
+ css: buildCss(),
+ classes: classes,
+ html: buildHtml(classes),
+ selectors: buildSelectors(classes)
+ };
+ return {
+ css: www.css,
+ html: www.html,
+ classes: www.classes,
+ selectors: www.selectors,
+ mixin: function(o) {
+ _.mixin(o, www);
+ }
+ };
+ }
+ function buildHtml(c) {
+ return {
+ wrapper: '<span class="' + c.wrapper + '"></span>',
+ menu: '<div class="' + c.menu + '"></div>'
+ };
+ }
+ function buildSelectors(classes) {
+ var selectors = {};
+ _.each(classes, function(v, k) {
+ selectors[k] = "." + v;
+ });
+ return selectors;
+ }
+ function buildCss() {
+ var css = {
+ wrapper: {
+ position: "relative",
+ display: "inline-block"
+ },
+ hint: {
+ position: "absolute",
+ top: "0",
+ left: "0",
+ borderColor: "transparent",
+ boxShadow: "none",
+ opacity: "1"
+ },
+ input: {
+ position: "relative",
+ verticalAlign: "top",
+ backgroundColor: "transparent"
+ },
+ inputWithNoHint: {
+ position: "relative",
+ verticalAlign: "top"
+ },
+ menu: {
+ position: "absolute",
+ top: "100%",
+ left: "0",
+ zIndex: "100",
+ display: "none"
+ },
+ ltr: {
+ left: "0",
+ right: "auto"
+ },
+ rtl: {
+ left: "auto",
+ right: " 0"
+ }
+ };
+ if (_.isMsie()) {
+ _.mixin(css.input, {
+ backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
+ });
+ }
+ return css;
+ }
+ }();
+ var EventBus = function() {
+ "use strict";
+ var namespace, deprecationMap;
+ namespace = "typeahead:";
+ deprecationMap = {
+ render: "rendered",
+ cursorchange: "cursorchanged",
+ select: "selected",
+ autocomplete: "autocompleted"
+ };
+ function EventBus(o) {
+ if (!o || !o.el) {
+ $.error("EventBus initialized without el");
+ }
+ this.$el = $(o.el);
+ }
+ _.mixin(EventBus.prototype, {
+ _trigger: function(type, args) {
+ var $e;
+ $e = $.Event(namespace + type);
+ (args = args || []).unshift($e);
+ this.$el.trigger.apply(this.$el, args);
+ return $e;
+ },
+ before: function(type) {
+ var args, $e;
+ args = [].slice.call(arguments, 1);
+ $e = this._trigger("before" + type, args);
+ return $e.isDefaultPrevented();
+ },
+ trigger: function(type) {
+ var deprecatedType;
+ this._trigger(type, [].slice.call(arguments, 1));
+ if (deprecatedType = deprecationMap[type]) {
+ this._trigger(deprecatedType, [].slice.call(arguments, 1));
+ }
+ }
+ });
+ return EventBus;
+ }();
+ var EventEmitter = function() {
+ "use strict";
+ var splitter = /\s+/, nextTick = getNextTick();
+ return {
+ onSync: onSync,
+ onAsync: onAsync,
+ off: off,
+ trigger: trigger
+ };
+ function on(method, types, cb, context) {
+ var type;
+ if (!cb) {
+ return this;
+ }
+ types = types.split(splitter);
+ cb = context ? bindContext(cb, context) : cb;
+ this._callbacks = this._callbacks || {};
+ while (type = types.shift()) {
+ this._callbacks[type] = this._callbacks[type] || {
+ sync: [],
+ async: []
+ };
+ this._callbacks[type][method].push(cb);
+ }
+ return this;
+ }
+ function onAsync(types, cb, context) {
+ return on.call(this, "async", types, cb, context);
+ }
+ function onSync(types, cb, context) {
+ return on.call(this, "sync", types, cb, context);
+ }
+ function off(types) {
+ var type;
+ if (!this._callbacks) {
+ return this;
+ }
+ types = types.split(splitter);
+ while (type = types.shift()) {
+ delete this._callbacks[type];
+ }
+ return this;
+ }
+ function trigger(types) {
+ var type, callbacks, args, syncFlush, asyncFlush;
+ if (!this._callbacks) {
+ return this;
+ }
+ types = types.split(splitter);
+ args = [].slice.call(arguments, 1);
+ while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
+ syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
+ asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
+ syncFlush() && nextTick(asyncFlush);
+ }
+ return this;
+ }
+ function getFlush(callbacks, context, args) {
+ return flush;
+ function flush() {
+ var cancelled;
+ for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
+ cancelled = callbacks[i].apply(context, args) === false;
+ }
+ return !cancelled;
+ }
+ }
+ function getNextTick() {
+ var nextTickFn;
+ if (window.setImmediate) {
+ nextTickFn = function nextTickSetImmediate(fn) {
+ setImmediate(function() {
+ fn();
+ });
+ };
+ } else {
+ nextTickFn = function nextTickSetTimeout(fn) {
+ setTimeout(function() {
+ fn();
+ }, 0);
+ };
+ }
+ return nextTickFn;
+ }
+ function bindContext(fn, context) {
+ return fn.bind ? fn.bind(context) : function() {
+ fn.apply(context, [].slice.call(arguments, 0));
+ };
+ }
+ }();
+ var highlight = function(doc) {
+ "use strict";
+ var defaults = {
+ node: null,
+ pattern: null,
+ tagName: "strong",
+ className: null,
+ wordsOnly: false,
+ caseSensitive: false
+ };
+ return function hightlight(o) {
+ var regex;
+ o = _.mixin({}, defaults, o);
+ if (!o.node || !o.pattern) {
+ return;
+ }
+ o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
+ regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
+ traverse(o.node, hightlightTextNode);
+ function hightlightTextNode(textNode) {
+ var match, patternNode, wrapperNode;
+ if (match = regex.exec(textNode.data)) {
+ wrapperNode = doc.createElement(o.tagName);
+ o.className && (wrapperNode.className = o.className);
+ patternNode = textNode.splitText(match.index);
+ patternNode.splitText(match[0].length);
+ wrapperNode.appendChild(patternNode.cloneNode(true));
+ textNode.parentNode.replaceChild(wrapperNode, patternNode);
+ }
+ return !!match;
+ }
+ function traverse(el, hightlightTextNode) {
+ var childNode, TEXT_NODE_TYPE = 3;
+ for (var i = 0; i < el.childNodes.length; i++) {
+ childNode = el.childNodes[i];
+ if (childNode.nodeType === TEXT_NODE_TYPE) {
+ i += hightlightTextNode(childNode) ? 1 : 0;
+ } else {
+ traverse(childNode, hightlightTextNode);
+ }
+ }
+ }
+ };
+ function getRegex(patterns, caseSensitive, wordsOnly) {
+ var escapedPatterns = [], regexStr;
+ for (var i = 0, len = patterns.length; i < len; i++) {
+ escapedPatterns.push(_.escapeRegExChars(patterns[i]));
+ }
+ regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
+ return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
+ }
+ }(window.document);
+ var Input = function() {
+ "use strict";
+ var specialKeyCodeMap;
+ specialKeyCodeMap = {
+ 9: "tab",
+ 27: "esc",
+ 37: "left",
+ 39: "right",
+ 13: "enter",
+ 38: "up",
+ 40: "down"
+ };
+ function Input(o, www) {
+ o = o || {};
+ if (!o.input) {
+ $.error("input is missing");
+ }
+ www.mixin(this);
+ this.$hint = $(o.hint);
+ this.$input = $(o.input);
+ this.query = this.$input.val();
+ this.queryWhenFocused = this.hasFocus() ? this.query : null;
+ this.$overflowHelper = buildOverflowHelper(this.$input);
+ this._checkLanguageDirection();
+ if (this.$hint.length === 0) {
+ this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
+ }
+ }
+ Input.normalizeQuery = function(str) {
+ return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
+ };
+ _.mixin(Input.prototype, EventEmitter, {
+ _onBlur: function onBlur() {
+ this.resetInputValue();
+ this.trigger("blurred");
+ },
+ _onFocus: function onFocus() {
+ this.queryWhenFocused = this.query;
+ this.trigger("focused");
+ },
+ _onKeydown: function onKeydown($e) {
+ var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
+ this._managePreventDefault(keyName, $e);
+ if (keyName && this._shouldTrigger(keyName, $e)) {
+ this.trigger(keyName + "Keyed", $e);
+ }
+ },
+ _onInput: function onInput() {
+ this._setQuery(this.getInputValue());
+ this.clearHintIfInvalid();
+ this._checkLanguageDirection();
+ },
+ _managePreventDefault: function managePreventDefault(keyName, $e) {
+ var preventDefault;
+ switch (keyName) {
+ case "up":
+ case "down":
+ preventDefault = !withModifier($e);
+ break;
+
+ default:
+ preventDefault = false;
+ }
+ preventDefault && $e.preventDefault();
+ },
+ _shouldTrigger: function shouldTrigger(keyName, $e) {
+ var trigger;
+ switch (keyName) {
+ case "tab":
+ trigger = !withModifier($e);
+ break;
+
+ default:
+ trigger = true;
+ }
+ return trigger;
+ },
+ _checkLanguageDirection: function checkLanguageDirection() {
+ var dir = (this.$input.css("direction") || "ltr").toLowerCase();
+ if (this.dir !== dir) {
+ this.dir = dir;
+ this.$hint.attr("dir", dir);
+ this.trigger("langDirChanged", dir);
+ }
+ },
+ _setQuery: function setQuery(val, silent) {
+ var areEquivalent, hasDifferentWhitespace;
+ areEquivalent = areQueriesEquivalent(val, this.query);
+ hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
+ this.query = val;
+ if (!silent && !areEquivalent) {
+ this.trigger("queryChanged", this.query);
+ } else if (!silent && hasDifferentWhitespace) {
+ this.trigger("whitespaceChanged", this.query);
+ }
+ },
+ bind: function() {
+ var that = this, onBlur, onFocus, onKeydown, onInput;
+ onBlur = _.bind(this._onBlur, this);
+ onFocus = _.bind(this._onFocus, this);
+ onKeydown = _.bind(this._onKeydown, this);
+ onInput = _.bind(this._onInput, this);
+ this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
+ if (!_.isMsie() || _.isMsie() > 9) {
+ this.$input.on("input.tt", onInput);
+ } else {
+ this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
+ if (specialKeyCodeMap[$e.which || $e.keyCode]) {
+ return;
+ }
+ _.defer(_.bind(that._onInput, that, $e));
+ });
+ }
+ return this;
+ },
+ focus: function focus() {
+ this.$input.focus();
+ },
+ blur: function blur() {
+ this.$input.blur();
+ },
+ getLangDir: function getLangDir() {
+ return this.dir;
+ },
+ getQuery: function getQuery() {
+ return this.query || "";
+ },
+ setQuery: function setQuery(val, silent) {
+ this.setInputValue(val);
+ this._setQuery(val, silent);
+ },
+ hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
+ return this.query !== this.queryWhenFocused;
+ },
+ getInputValue: function getInputValue() {
+ return this.$input.val();
+ },
+ setInputValue: function setInputValue(value) {
+ this.$input.val(value);
+ this.clearHintIfInvalid();
+ this._checkLanguageDirection();
+ },
+ resetInputValue: function resetInputValue() {
+ this.setInputValue(this.query);
+ },
+ getHint: function getHint() {
+ return this.$hint.val();
+ },
+ setHint: function setHint(value) {
+ this.$hint.val(value);
+ },
+ clearHint: function clearHint() {
+ this.setHint("");
+ },
+ clearHintIfInvalid: function clearHintIfInvalid() {
+ var val, hint, valIsPrefixOfHint, isValid;
+ val = this.getInputValue();
+ hint = this.getHint();
+ valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
+ isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
+ !isValid && this.clearHint();
+ },
+ hasFocus: function hasFocus() {
+ return this.$input.is(":focus");
+ },
+ hasOverflow: function hasOverflow() {
+ var constraint = this.$input.width() - 2;
+ this.$overflowHelper.text(this.getInputValue());
+ return this.$overflowHelper.width() >= constraint;
+ },
+ isCursorAtEnd: function() {
+ var valueLength, selectionStart, range;
+ valueLength = this.$input.val().length;
+ selectionStart = this.$input[0].selectionStart;
+ if (_.isNumber(selectionStart)) {
+ return selectionStart === valueLength;
+ } else if (document.selection) {
+ range = document.selection.createRange();
+ range.moveStart("character", -valueLength);
+ return valueLength === range.text.length;
+ }
+ return true;
+ },
+ destroy: function destroy() {
+ this.$hint.off(".tt");
+ this.$input.off(".tt");
+ this.$overflowHelper.remove();
+ this.$hint = this.$input = this.$overflowHelper = $("<div>");
+ }
+ });
+ return Input;
+ function buildOverflowHelper($input) {
+ return $('<pre aria-hidden="true"></pre>').css({
+ position: "absolute",
+ visibility: "hidden",
+ whiteSpace: "pre",
+ fontFamily: $input.css("font-family"),
+ fontSize: $input.css("font-size"),
+ fontStyle: $input.css("font-style"),
+ fontVariant: $input.css("font-variant"),
+ fontWeight: $input.css("font-weight"),
+ wordSpacing: $input.css("word-spacing"),
+ letterSpacing: $input.css("letter-spacing"),
+ textIndent: $input.css("text-indent"),
+ textRendering: $input.css("text-rendering"),
+ textTransform: $input.css("text-transform")
+ }).insertAfter($input);
+ }
+ function areQueriesEquivalent(a, b) {
+ return Input.normalizeQuery(a) === Input.normalizeQuery(b);
+ }
+ function withModifier($e) {
+ return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
+ }
+ }();
+ var Dataset = function() {
+ "use strict";
+ var keys, nameGenerator;
+ keys = {
+ val: "tt-selectable-display",
+ obj: "tt-selectable-object"
+ };
+ nameGenerator = _.getIdGenerator();
+ function Dataset(o, www) {
+ o = o || {};
+ o.templates = o.templates || {};
+ o.templates.notFound = o.templates.notFound || o.templates.empty;
+ if (!o.source) {
+ $.error("missing source");
+ }
+ if (!o.node) {
+ $.error("missing node");
+ }
+ if (o.name && !isValidName(o.name)) {
+ $.error("invalid dataset name: " + o.name);
+ }
+ www.mixin(this);
+ this.highlight = !!o.highlight;
+ this.name = o.name || nameGenerator();
+ this.limit = o.limit || 5;
+ this.displayFn = getDisplayFn(o.display || o.displayKey);
+ this.templates = getTemplates(o.templates, this.displayFn);
+ this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
+ this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
+ this._resetLastSuggestion();
+ this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
+ }
+ Dataset.extractData = function extractData(el) {
+ var $el = $(el);
+ if ($el.data(keys.obj)) {
+ return {
+ val: $el.data(keys.val) || "",
+ obj: $el.data(keys.obj) || null
+ };
+ }
+ return null;
+ };
+ _.mixin(Dataset.prototype, EventEmitter, {
+ _overwrite: function overwrite(query, suggestions) {
+ suggestions = suggestions || [];
+ if (suggestions.length) {
+ this._renderSuggestions(query, suggestions);
+ } else if (this.async && this.templates.pending) {
+ this._renderPending(query);
+ } else if (!this.async && this.templates.notFound) {
+ this._renderNotFound(query);
+ } else {
+ this._empty();
+ }
+ this.trigger("rendered", this.name, suggestions, false);
+ },
+ _append: function append(query, suggestions) {
+ suggestions = suggestions || [];
+ if (suggestions.length && this.$lastSuggestion.length) {
+ this._appendSuggestions(query, suggestions);
+ } else if (suggestions.length) {
+ this._renderSuggestions(query, suggestions);
+ } else if (!this.$lastSuggestion.length && this.templates.notFound) {
+ this._renderNotFound(query);
+ }
+ this.trigger("rendered", this.name, suggestions, true);
+ },
+ _renderSuggestions: function renderSuggestions(query, suggestions) {
+ var $fragment;
+ $fragment = this._getSuggestionsFragment(query, suggestions);
+ this.$lastSuggestion = $fragment.children().last();
+ this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
+ },
+ _appendSuggestions: function appendSuggestions(query, suggestions) {
+ var $fragment, $lastSuggestion;
+ $fragment = this._getSuggestionsFragment(query, suggestions);
+ $lastSuggestion = $fragment.children().last();
+ this.$lastSuggestion.after($fragment);
+ this.$lastSuggestion = $lastSuggestion;
+ },
+ _renderPending: function renderPending(query) {
+ var template = this.templates.pending;
+ this._resetLastSuggestion();
+ template && this.$el.html(template({
+ query: query,
+ dataset: this.name
+ }));
+ },
+ _renderNotFound: function renderNotFound(query) {
+ var template = this.templates.notFound;
+ this._resetLastSuggestion();
+ template && this.$el.html(template({
+ query: query,
+ dataset: this.name
+ }));
+ },
+ _empty: function empty() {
+ this.$el.empty();
+ this._resetLastSuggestion();
+ },
+ _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
+ var that = this, fragment;
+ fragment = document.createDocumentFragment();
+ _.each(suggestions, function getSuggestionNode(suggestion) {
+ var $el, context;
+ context = that._injectQuery(query, suggestion);
+ $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
+ fragment.appendChild($el[0]);
+ });
+ this.highlight && highlight({
+ className: this.classes.highlight,
+ node: fragment,
+ pattern: query
+ });
+ return $(fragment);
+ },
+ _getFooter: function getFooter(query, suggestions) {
+ return this.templates.footer ? this.templates.footer({
+ query: query,
+ suggestions: suggestions,
+ dataset: this.name
+ }) : null;
+ },
+ _getHeader: function getHeader(query, suggestions) {
+ return this.templates.header ? this.templates.header({
+ query: query,
+ suggestions: suggestions,
+ dataset: this.name
+ }) : null;
+ },
+ _resetLastSuggestion: function resetLastSuggestion() {
+ this.$lastSuggestion = $();
+ },
+ _injectQuery: function injectQuery(query, obj) {
+ return _.isObject(obj) ? _.mixin({
+ _query: query
+ }, obj) : obj;
+ },
+ update: function update(query) {
+ var that = this, canceled = false, syncCalled = false, rendered = 0;
+ this.cancel();
+ this.cancel = function cancel() {
+ canceled = true;
+ that.cancel = $.noop;
+ that.async && that.trigger("asyncCanceled", query);
+ };
+ this.source(query, sync, async);
+ !syncCalled && sync([]);
+ function sync(suggestions) {
+ if (syncCalled) {
+ return;
+ }
+ syncCalled = true;
+ suggestions = (suggestions || []).slice(0, that.limit);
+ rendered = suggestions.length;
+ that._overwrite(query, suggestions);
+ if (rendered < that.limit && that.async) {
+ that.trigger("asyncRequested", query);
+ }
+ }
+ function async(suggestions) {
+ suggestions = suggestions || [];
+ if (!canceled && rendered < that.limit) {
+ that.cancel = $.noop;
+ rendered += suggestions.length;
+
+ // HACK: because we don't have a synchronous way of
+ // retrieving results, we use the async function every
+ // time we update the drop-down; however, the typeahead
+ // does some internal book-keeping which means that we
+ // only get the additional items in the drop-down when
+ // the next set of results is fetched, instead of all
+ // of them (it appears to implicitly track which
+ // results have already been shown in the drop-down); by
+ // forcing an overwrite, we see all of the new results
+ // every time we fetch a set of suggestions
+ //that._append(query, suggestions.slice(0, that.limit - rendered));
+ that._overwrite(query, suggestions);
+
+ that.async && that.trigger("asyncReceived", query);
+ }
+ }
+ },
+ cancel: $.noop,
+ clear: function clear() {
+ this._empty();
+ this.cancel();
+ this.trigger("cleared");
+ },
+ isEmpty: function isEmpty() {
+ return this.$el.is(":empty");
+ },
+ destroy: function destroy() {
+ this.$el = $("<div>");
+ }
+ });
+ return Dataset;
+ function getDisplayFn(display) {
+ display = display || _.stringify;
+ return _.isFunction(display) ? display : displayFn;
+ function displayFn(obj) {
+ return obj[display];
+ }
+ }
+ function getTemplates(templates, displayFn) {
+ return {
+ notFound: templates.notFound && _.templatify(templates.notFound),
+ pending: templates.pending && _.templatify(templates.pending),
+ header: templates.header && _.templatify(templates.header),
+ footer: templates.footer && _.templatify(templates.footer),
+ suggestion: templates.suggestion || suggestionTemplate
+ };
+ function suggestionTemplate(context) {
+ return $("<div>").text(displayFn(context));
+ }
+ }
+ function isValidName(str) {
+ return /^[_a-zA-Z0-9-]+$/.test(str);
+ }
+ }();
+ var Menu = function() {
+ "use strict";
+ function Menu(o, www) {
+ var that = this;
+ o = o || {};
+ if (!o.node) {
+ $.error("node is required");
+ }
+ www.mixin(this);
+ this.$node = $(o.node);
+ this.query = null;
+ this.datasets = _.map(o.datasets, initializeDataset);
+ function initializeDataset(oDataset) {
+ var node = that.$node.find(oDataset.node).first();
+ oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
+ return new Dataset(oDataset, www);
+ }
+ }
+ _.mixin(Menu.prototype, EventEmitter, {
+ _onSelectableClick: function onSelectableClick($e) {
+ this.trigger("selectableClicked", $($e.currentTarget));
+ },
+ _onRendered: function onRendered(type, dataset, suggestions, async) {
+ this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
+ this.trigger("datasetRendered", dataset, suggestions, async);
+ },
+ _onCleared: function onCleared() {
+ this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
+ this.trigger("datasetCleared");
+ },
+ _propagate: function propagate() {
+ this.trigger.apply(this, arguments);
+ },
+ _allDatasetsEmpty: function allDatasetsEmpty() {
+ return _.every(this.datasets, isDatasetEmpty);
+ function isDatasetEmpty(dataset) {
+ return dataset.isEmpty();
+ }
+ },
+ _getSelectables: function getSelectables() {
+ return this.$node.find(this.selectors.selectable);
+ },
+ _removeCursor: function _removeCursor() {
+ var $selectable = this.getActiveSelectable();
+ $selectable && $selectable.removeClass(this.classes.cursor);
+ },
+ _ensureVisible: function ensureVisible($el) {
+ var elTop, elBottom, nodeScrollTop, nodeHeight;
+ elTop = $el.position().top;
+ elBottom = elTop + $el.outerHeight(true);
+ nodeScrollTop = this.$node.scrollTop();
+ nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
+ if (elTop < 0) {
+ this.$node.scrollTop(nodeScrollTop + elTop);
+ } else if (nodeHeight < elBottom) {
+ this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
+ }
+ },
+ bind: function() {
+ var that = this, onSelectableClick;
+ onSelectableClick = _.bind(this._onSelectableClick, this);
+ this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
+ _.each(this.datasets, function(dataset) {
+ dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
+ });
+ return this;
+ },
+ isOpen: function isOpen() {
+ return this.$node.hasClass(this.classes.open);
+ },
+ open: function open() {
+ this.$node.addClass(this.classes.open);
+ },
+ close: function close() {
+ this.$node.removeClass(this.classes.open);
+ this._removeCursor();
+ },
+ setLanguageDirection: function setLanguageDirection(dir) {
+ this.$node.attr("dir", dir);
+ },
+ selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
+ var $selectables, $oldCursor, oldIndex, newIndex;
+ $oldCursor = this.getActiveSelectable();
+ $selectables = this._getSelectables();
+ oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
+ newIndex = oldIndex + delta;
+ newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
+ newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
+ return newIndex === -1 ? null : $selectables.eq(newIndex);
+ },
+ setCursor: function setCursor($selectable) {
+ this._removeCursor();
+ if ($selectable = $selectable && $selectable.first()) {
+ $selectable.addClass(this.classes.cursor);
+ this._ensureVisible($selectable);
+ }
+ },
+ getSelectableData: function getSelectableData($el) {
+ return $el && $el.length ? Dataset.extractData($el) : null;
+ },
+ getActiveSelectable: function getActiveSelectable() {
+ var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
+ return $selectable.length ? $selectable : null;
+ },
+ getTopSelectable: function getTopSelectable() {
+ var $selectable = this._getSelectables().first();
+ return $selectable.length ? $selectable : null;
+ },
+ update: function update(query) {
+ var isValidUpdate = query !== this.query;
+ if (isValidUpdate) {
+ this.query = query;
+ _.each(this.datasets, updateDataset);
+ }
+ return isValidUpdate;
+ function updateDataset(dataset) {
+ dataset.update(query);
+ }
+ },
+ empty: function empty() {
+ _.each(this.datasets, clearDataset);
+ this.query = null;
+ this.$node.addClass(this.classes.empty);
+ function clearDataset(dataset) {
+ dataset.clear();
+ }
+ },
+ destroy: function destroy() {
+ this.$node.off(".tt");
+ this.$node = $("<div>");
+ _.each(this.datasets, destroyDataset);
+ function destroyDataset(dataset) {
+ dataset.destroy();
+ }
+ }
+ });
+ return Menu;
+ }();
+ var DefaultMenu = function() {
+ "use strict";
+ var s = Menu.prototype;
+ function DefaultMenu() {
+ Menu.apply(this, [].slice.call(arguments, 0));
+ }
+ _.mixin(DefaultMenu.prototype, Menu.prototype, {
+ open: function open() {
+ !this._allDatasetsEmpty() && this._show();
+ return s.open.apply(this, [].slice.call(arguments, 0));
+ },
+ close: function close() {
+ this._hide();
+ return s.close.apply(this, [].slice.call(arguments, 0));
+ },
+ _onRendered: function onRendered() {
+ if (this._allDatasetsEmpty()) {
+ this._hide();
+ } else {
+ this.isOpen() && this._show();
+ }
+ return s._onRendered.apply(this, [].slice.call(arguments, 0));
+ },
+ _onCleared: function onCleared() {
+ if (this._allDatasetsEmpty()) {
+ this._hide();
+ } else {
+ this.isOpen() && this._show();
+ }
+ return s._onCleared.apply(this, [].slice.call(arguments, 0));
+ },
+ setLanguageDirection: function setLanguageDirection(dir) {
+ this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
+ return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
+ },
+ _hide: function hide() {
+ this.$node.hide();
+ },
+ _show: function show() {
+ this.$node.css("display", "block");
+ }
+ });
+ return DefaultMenu;
+ }();
+ var Typeahead = function() {
+ "use strict";
+ function Typeahead(o, www) {
+ var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
+ o = o || {};
+ if (!o.input) {
+ $.error("missing input");
+ }
+ if (!o.menu) {
+ $.error("missing menu");
+ }
+ if (!o.eventBus) {
+ $.error("missing event bus");
+ }
+ www.mixin(this);
+ this.eventBus = o.eventBus;
+ this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
+ this.input = o.input;
+ this.menu = o.menu;
+ this.enabled = true;
+ this.active = false;
+ this.input.hasFocus() && this.activate();
+ this.dir = this.input.getLangDir();
+ this._hacks();
+ this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
+ onFocused = c(this, "activate", "open", "_onFocused");
+ onBlurred = c(this, "deactivate", "_onBlurred");
+ onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
+ onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
+ onEscKeyed = c(this, "isActive", "_onEscKeyed");
+ onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
+ onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
+ onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
+ onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
+ onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
+ onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
+ this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this);
+ }
+ _.mixin(Typeahead.prototype, {
+ _hacks: function hacks() {
+ var $input, $menu;
+ $input = this.input.$input || $("<div>");
+ $menu = this.menu.$node || $("<div>");
+ $input.on("blur.tt", function($e) {
+ var active, isActive, hasActive;
+ active = document.activeElement;
+ isActive = $menu.is(active);
+ hasActive = $menu.has(active).length > 0;
+ if (_.isMsie() && (isActive || hasActive)) {
+ $e.preventDefault();
+ $e.stopImmediatePropagation();
+ _.defer(function() {
+ $input.focus();
+ });
+ }
+ });
+ $menu.on("mousedown.tt", function($e) {
+ $e.preventDefault();
+ });
+ },
+ _onSelectableClicked: function onSelectableClicked(type, $el) {
+ this.select($el);
+ },
+ _onDatasetCleared: function onDatasetCleared() {
+ this._updateHint();
+ },
+ _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
+ this._updateHint();
+ this.eventBus.trigger("render", suggestions, async, dataset);
+ },
+ _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
+ this.eventBus.trigger("asyncrequest", query, dataset);
+ },
+ _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
+ this.eventBus.trigger("asynccancel", query, dataset);
+ },
+ _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
+ this.eventBus.trigger("asyncreceive", query, dataset);
+ },
+ _onFocused: function onFocused() {
+ this._minLengthMet() && this.menu.update(this.input.getQuery());
+ },
+ _onBlurred: function onBlurred() {
+ if (this.input.hasQueryChangedSinceLastFocus()) {
+ this.eventBus.trigger("change", this.input.getQuery());
+ }
+ },
+ _onEnterKeyed: function onEnterKeyed(type, $e) {
+ var $selectable;
+ if ($selectable = this.menu.getActiveSelectable()) {
+ this.select($selectable) && $e.preventDefault();
+ }
+ },
+ _onTabKeyed: function onTabKeyed(type, $e) {
+ var $selectable;
+ if ($selectable = this.menu.getActiveSelectable()) {
+ this.select($selectable) && $e.preventDefault();
+ } else if ($selectable = this.menu.getTopSelectable()) {
+ this.autocomplete($selectable) && $e.preventDefault();
+ }
+ },
+ _onEscKeyed: function onEscKeyed() {
+ this.close();
+ },
+ _onUpKeyed: function onUpKeyed() {
+ this.moveCursor(-1);
+ },
+ _onDownKeyed: function onDownKeyed() {
+ this.moveCursor(+1);
+ },
+ _onLeftKeyed: function onLeftKeyed() {
+ if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
+ this.autocomplete(this.menu.getTopSelectable());
+ }
+ },
+ _onRightKeyed: function onRightKeyed() {
+ if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
+ this.autocomplete(this.menu.getTopSelectable());
+ }
+ },
+ _onQueryChanged: function onQueryChanged(e, query) {
+ this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
+ },
+ _onWhitespaceChanged: function onWhitespaceChanged() {
+ this._updateHint();
+ },
+ _onLangDirChanged: function onLangDirChanged(e, dir) {
+ if (this.dir !== dir) {
+ this.dir = dir;
+ this.menu.setLanguageDirection(dir);
+ }
+ },
+ _openIfActive: function openIfActive() {
+ this.isActive() && this.open();
+ },
+ _minLengthMet: function minLengthMet(query) {
+ query = _.isString(query) ? query : this.input.getQuery() || "";
+ return query.length >= this.minLength;
+ },
+ _updateHint: function updateHint() {
+ var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
+ $selectable = this.menu.getTopSelectable();
+ data = this.menu.getSelectableData($selectable);
+ val = this.input.getInputValue();
+ if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
+ query = Input.normalizeQuery(val);
+ escapedQuery = _.escapeRegExChars(query);
+ frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
+ match = frontMatchRegEx.exec(data.val);
+ match && this.input.setHint(val + match[1]);
+ } else {
+ this.input.clearHint();
+ }
+ },
+ isEnabled: function isEnabled() {
+ return this.enabled;
+ },
+ enable: function enable() {
+ this.enabled = true;
+ },
+ disable: function disable() {
+ this.enabled = false;
+ },
+ isActive: function isActive() {
+ return this.active;
+ },
+ activate: function activate() {
+ if (this.isActive()) {
+ return true;
+ } else if (!this.isEnabled() || this.eventBus.before("active")) {
+ return false;
+ } else {
+ this.active = true;
+ this.eventBus.trigger("active");
+ return true;
+ }
+ },
+ deactivate: function deactivate() {
+ if (!this.isActive()) {
+ return true;
+ } else if (this.eventBus.before("idle")) {
+ return false;
+ } else {
+ this.active = false;
+ this.close();
+ this.eventBus.trigger("idle");
+ return true;
+ }
+ },
+ isOpen: function isOpen() {
+ return this.menu.isOpen();
+ },
+ open: function open() {
+ if (!this.isOpen() && !this.eventBus.before("open")) {
+ this.menu.open();
+ this._updateHint();
+ this.eventBus.trigger("open");
+ }
+ return this.isOpen();
+ },
+ close: function close() {
+ if (this.isOpen() && !this.eventBus.before("close")) {
+ this.menu.close();
+ this.input.clearHint();
+ this.input.resetInputValue();
+ this.eventBus.trigger("close");
+ }
+ return !this.isOpen();
+ },
+ setVal: function setVal(val) {
+ this.input.setQuery(_.toStr(val));
+ },
+ getVal: function getVal() {
+ return this.input.getQuery();
+ },
+ select: function select($selectable) {
+ var data = this.menu.getSelectableData($selectable);
+ if (data && !this.eventBus.before("select", data.obj)) {
+ this.input.setQuery(data.val, true);
+ this.eventBus.trigger("select", data.obj);
+ this.close();
+ return true;
+ }
+ return false;
+ },
+ autocomplete: function autocomplete($selectable) {
+ var query, data, isValid;
+ query = this.input.getQuery();
+ data = this.menu.getSelectableData($selectable);
+ isValid = data && query !== data.val;
+ if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
+ this.input.setQuery(data.val);
+ this.eventBus.trigger("autocomplete", data.obj);
+ return true;
+ }
+ return false;
+ },
+ moveCursor: function moveCursor(delta) {
+ var query, $candidate, data, payload, cancelMove;
+ query = this.input.getQuery();
+ $candidate = this.menu.selectableRelativeToCursor(delta);
+ data = this.menu.getSelectableData($candidate);
+ payload = data ? data.obj : null;
+ cancelMove = this._minLengthMet() && this.menu.update(query);
+ if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
+ this.menu.setCursor($candidate);
+ if (data) {
+ this.input.setInputValue(data.val);
+ } else {
+ this.input.resetInputValue();
+ this._updateHint();
+ }
+ this.eventBus.trigger("cursorchange", payload);
+ return true;
+ }
+ return false;
+ },
+ destroy: function destroy() {
+ this.input.destroy();
+ this.menu.destroy();
+ }
+ });
+ return Typeahead;
+ function c(ctx) {
+ var methods = [].slice.call(arguments, 1);
+ return function() {
+ var args = [].slice.call(arguments);
+ _.each(methods, function(method) {
+ return ctx[method].apply(ctx, args);
+ });
+ };
+ }
+ }();
+ (function() {
+ "use strict";
+ var old, keys, methods;
+ old = $.fn.typeahead;
+ keys = {
+ www: "tt-www",
+ attrs: "tt-attrs",
+ typeahead: "tt-typeahead"
+ };
+ methods = {
+ initialize: function initialize(o, datasets) {
+ var www;
+ datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
+ o = o || {};
+ www = WWW(o.classNames);
+ return this.each(attach);
+ function attach() {
+ var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
+ _.each(datasets, function(d) {
+ d.highlight = !!o.highlight;
+ });
+ $input = $(this);
+ $wrapper = $(www.html.wrapper);
+ $hint = $elOrNull(o.hint);
+ $menu = $elOrNull(o.menu);
+ defaultHint = o.hint !== false && !$hint;
+ defaultMenu = o.menu !== false && !$menu;
+ defaultHint && ($hint = buildHintFromInput($input, www));
+ defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
+ $hint && $hint.val("");
+ $input = prepInput($input, www);
+ if (defaultHint || defaultMenu) {
+ $wrapper.css(www.css.wrapper);
+ $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
+ $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
+ }
+ MenuConstructor = defaultMenu ? DefaultMenu : Menu;
+ eventBus = new EventBus({
+ el: $input
+ });
+ input = new Input({
+ hint: $hint,
+ input: $input
+ }, www);
+ menu = new MenuConstructor({
+ node: $menu,
+ datasets: datasets
+ }, www);
+ typeahead = new Typeahead({
+ input: input,
+ menu: menu,
+ eventBus: eventBus,
+ minLength: o.minLength
+ }, www);
+ $input.data(keys.www, www);
+ $input.data(keys.typeahead, typeahead);
+ }
+ },
+ isEnabled: function isEnabled() {
+ var enabled;
+ ttEach(this.first(), function(t) {
+ enabled = t.isEnabled();
+ });
+ return enabled;
+ },
+ enable: function enable() {
+ ttEach(this, function(t) {
+ t.enable();
+ });
+ return this;
+ },
+ disable: function disable() {
+ ttEach(this, function(t) {
+ t.disable();
+ });
+ return this;
+ },
+ isActive: function isActive() {
+ var active;
+ ttEach(this.first(), function(t) {
+ active = t.isActive();
+ });
+ return active;
+ },
+ activate: function activate() {
+ ttEach(this, function(t) {
+ t.activate();
+ });
+ return this;
+ },
+ deactivate: function deactivate() {
+ ttEach(this, function(t) {
+ t.deactivate();
+ });
+ return this;
+ },
+ isOpen: function isOpen() {
+ var open;
+ ttEach(this.first(), function(t) {
+ open = t.isOpen();
+ });
+ return open;
+ },
+ open: function open() {
+ ttEach(this, function(t) {
+ t.open();
+ });
+ return this;
+ },
+ close: function close() {
+ ttEach(this, function(t) {
+ t.close();
+ });
+ return this;
+ },
+ select: function select(el) {
+ var success = false, $el = $(el);
+ ttEach(this.first(), function(t) {
+ success = t.select($el);
+ });
+ return success;
+ },
+ autocomplete: function autocomplete(el) {
+ var success = false, $el = $(el);
+ ttEach(this.first(), function(t) {
+ success = t.autocomplete($el);
+ });
+ return success;
+ },
+ moveCursor: function moveCursoe(delta) {
+ var success = false;
+ ttEach(this.first(), function(t) {
+ success = t.moveCursor(delta);
+ });
+ return success;
+ },
+ val: function val(newVal) {
+ var query;
+ if (!arguments.length) {
+ ttEach(this.first(), function(t) {
+ query = t.getVal();
+ });
+ return query;
+ } else {
+ ttEach(this, function(t) {
+ t.setVal(newVal);
+ });
+ return this;
+ }
+ },
+ destroy: function destroy() {
+ ttEach(this, function(typeahead, $input) {
+ revert($input);
+ typeahead.destroy();
+ });
+ return this;
+ }
+ };
+ $.fn.typeahead = function(method) {
+ if (methods[method]) {
+ return methods[method].apply(this, [].slice.call(arguments, 1));
+ } else {
+ return methods.initialize.apply(this, arguments);
+ }
+ };
+ $.fn.typeahead.noConflict = function noConflict() {
+ $.fn.typeahead = old;
+ return this;
+ };
+ function ttEach($els, fn) {
+ $els.each(function() {
+ var $input = $(this), typeahead;
+ (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
+ });
+ }
+ function buildHintFromInput($input, www) {
+ return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
+ autocomplete: "off",
+ spellcheck: "false",
+ tabindex: -1
+ });
+ }
+ function prepInput($input, www) {
+ $input.data(keys.attrs, {
+ dir: $input.attr("dir"),
+ autocomplete: $input.attr("autocomplete"),
+ spellcheck: $input.attr("spellcheck"),
+ style: $input.attr("style")
+ });
+ $input.addClass(www.classes.input).attr({
+ autocomplete: "off",
+ spellcheck: false
+ });
+ try {
+ !$input.attr("dir") && $input.attr("dir", "auto");
+ } catch (e) {}
+ return $input;
+ }
+ function getBackgroundStyles($el) {
+ return {
+ backgroundAttachment: $el.css("background-attachment"),
+ backgroundClip: $el.css("background-clip"),
+ backgroundColor: $el.css("background-color"),
+ backgroundImage: $el.css("background-image"),
+ backgroundOrigin: $el.css("background-origin"),
+ backgroundPosition: $el.css("background-position"),
+ backgroundRepeat: $el.css("background-repeat"),
+ backgroundSize: $el.css("background-size")
+ };
+ }
+ function revert($input) {
+ var www, $wrapper;
+ www = $input.data(keys.www);
+ $wrapper = $input.parent().filter(www.selectors.wrapper);
+ _.each($input.data(keys.attrs), function(val, key) {
+ _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
+ });
+ $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
+ if ($wrapper.length) {
+ $input.detach().insertAfter($wrapper);
+ $wrapper.remove();
+ }
+ }
+ function $elOrNull(obj) {
+ var isValid, $el;
+ isValid = _.isJQuery(obj) || _.isElement(obj);
+ $el = isValid ? $(obj).first() : [];
+ return $el.length ? $el : null;
+ }
+ })();
+}); \ No newline at end of file
OpenPOWER on IntegriCloud