text: /* ========================================================================
   * Bootstrap: affix.js v3.2.0
   * http://getbootstrap.com/javascript/#affix
   * ========================================================================
   * Copyright 2011-2014 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      =
      this.unpin        =
      this.pinnedOffset = null
  
      this.checkPosition()
    }
  
    Affix.VERSION  = '3.2.0'
  
    Affix.RESET    = 'affix affix-top affix-bottom'
  
    Affix.DEFAULTS = {
      offset: 0,
      target: window
    }
  
    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 scrollHeight = $(document).height()
      var scrollTop    = this.$target.scrollTop()
      var position     = this.$element.offset()
      var offset       = this.options.offset
      var offsetTop    = offset.top
      var offsetBottom = offset.bottom
  
      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.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
                  offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
                  offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false
  
      if (this.affixed === affix) return
      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($.Event(affixType.replace('affix', 'affixed')))
  
      if (affix == 'bottom') {
        this.$element.offset({
          top: scrollHeight - this.$element.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) data.offset.bottom = data.offsetBottom
        if (data.offsetTop)    data.offset.top    = data.offsetTop
  
        Plugin.call($spy, data)
      })
    })
  
  }(jQuery);
  /* ========================================================================
   * Bootstrap: alert.js v3.2.0
   * http://getbootstrap.com/javascript/#alerts
   * ========================================================================
   * Copyright 2011-2014 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.2.0'
  
    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.hasClass('alert') ? $this : $this.parent()
      }
  
      $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(150) :
        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.2.0
   * http://getbootstrap.com/javascript/#buttons
   * ========================================================================
   * Copyright 2011-2014 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.2.0'
  
    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 = state + 'Text'
  
      if (data.resetText == null) $el.data('resetText', $el[val]())
  
      $el[val](data[state] == null ? this.options[state] : data[state])
  
      // push to event loop to allow forms to submit
      setTimeout($.proxy(function () {
        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') && this.$element.hasClass('active')) changed = false
          else $parent.find('.active').removeClass('active')
        }
        if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
      }
  
      if (changed) 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')
      e.preventDefault()
    })
  
  }(jQuery);
  /* ========================================================================
   * Bootstrap: carousel.js v3.2.0
   * http://getbootstrap.com/javascript/#carousel
   * ========================================================================
   * Copyright 2011-2014 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).on('keydown.bs.carousel', $.proxy(this.keydown, this))
      this.$indicators = this.$element.find('.carousel-indicators')
      this.options     = options
      this.paused      =
      this.sliding     =
      this.interval    =
      this.$active     =
      this.$items      = null
  
      this.options.pause == 'hover' && this.$element
        .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
        .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
    }
  
    Carousel.VERSION  = '3.2.0'
  
    Carousel.DEFAULTS = {
      interval: 5000,
      pause: 'hover',
      wrap: true
    }
  
    Carousel.prototype.keydown = function (e) {
      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.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[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 || $active[type]()
      var isCycling = this.interval
      var direction = type == 'next' ? 'left' : 'right'
      var fallback  = type == 'next' ? 'first' : 'last'
      var that      = this
  
      if (!$next.length) {
        if (!this.options.wrap) return
        $next = this.$element.find('.item')[fallback]()
      }
  
      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($active.css('transition-duration').slice(0, -1) * 1000)
      } 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
    // =================
  
    $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', 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()
    })
  
    $(window).on('load', function () {
      $('[data-ride="carousel"]').each(function () {
        var $carousel = $(this)
        Plugin.call($carousel, $carousel.data())
      })
    })
  
  }(jQuery);
  /* ========================================================================
   * Bootstrap: collapse.js v3.2.0
   * http://getbootstrap.com/javascript/#collapse
   * ========================================================================
   * Copyright 2011-2014 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.transitioning = null
  
      if (this.options.parent) this.$parent = $(this.options.parent)
      if (this.options.toggle) this.toggle()
    }
  
    Collapse.VERSION  = '3.2.0'
  
    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 startEvent = $.Event('show.bs.collapse')
      this.$element.trigger(startEvent)
      if (startEvent.isDefaultPrevented()) return
  
      var actives = this.$parent && this.$parent.find('> .panel > .in')
  
      if (actives && actives.length) {
        var hasData = actives.data('bs.collapse')
        if (hasData && hasData.transitioning) return
        Plugin.call(actives, 'hide')
        hasData || actives.data('bs.collapse', null)
      }
  
      var dimension = this.dimension()
  
      this.$element
        .removeClass('collapse')
        .addClass('collapsing')[dimension](0)
  
      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(350)[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')
        .removeClass('in')
  
      this.transitioning = 1
  
      var complete = function () {
        this.transitioning = 0
        this.$element
          .trigger('hidden.bs.collapse')
          .removeClass('collapsing')
          .addClass('collapse')
      }
  
      if (!$.support.transition) return complete.call(this)
  
      this.$element
        [dimension](0)
        .one('bsTransitionEnd', $.proxy(complete, this))
        .emulateTransitionEnd(350)
    }
  
    Collapse.prototype.toggle = function () {
      this[this.$element.hasClass('in') ? 'hide' : 'show']()
    }
  
  
    // 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 && option == 'show') option = !option
        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 href
      var $this   = $(this)
      var target  = $this.attr('data-target')
          || e.preventDefault()
          || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
      var $target = $(target)
      var data    = $target.data('bs.collapse')
      var option  = data ? 'toggle' : $this.data()
      var parent  = $this.attr('data-parent')
      var $parent = parent && $(parent)
  
      if (!data || !data.transitioning) {
        if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
        $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
      }
  
      Plugin.call($target, option)
    })
  
  }(jQuery);
  /* ========================================================================
   * Bootstrap: dropdown.js v3.2.0
   * http://getbootstrap.com/javascript/#dropdowns
   * ========================================================================
   * Copyright 2011-2014 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.2.0'
  
    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
          $('<div class="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')
  
        $parent
          .toggleClass('open')
          .trigger('shown.bs.dropdown', relatedTarget)
      }
  
      return false
    }
  
    Dropdown.prototype.keydown = function (e) {
      if (!/(38|40|27)/.test(e.keyCode)) 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 || (isActive && e.keyCode == 27)) {
        if (e.which == 27) $parent.find(toggle).trigger('focus')
        return $this.trigger('click')
      }
  
      var desc = ' li:not(.divider):visible a'
      var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
  
      if (!$items.length) return
  
      var index = $items.index($items.filter(':focus'))
  
      if (e.keyCode == 38 && index > 0)                 index--                        // up
      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
      if (!~index)                                      index = 0
  
      $items.eq(index).trigger('focus')
    }
  
    function clearMenus(e) {
      if (e && e.which === 3) return
      $(backdrop).remove()
      $(toggle).each(function () {
        var $parent = getParent($(this))
        var relatedTarget = { relatedTarget: this }
        if (!$parent.hasClass('open')) return
        $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
        if (e.isDefaultPrevented()) return
        $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
      })
    }
  
    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()
    }
  
  
    // 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 + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
  
  }(jQuery);
  /* ========================================================================
   * Bootstrap: tab.js v3.2.0
   * http://getbootstrap.com/javascript/#tabs
   * ========================================================================
   * Copyright 2011-2014 Twitter, Inc.
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   * ======================================================================== */
  
  
  
  +function ($) {
    'use strict';
  
    // TAB CLASS DEFINITION
    // ====================
  
    var Tab = function (element) {
      this.element = $(element)
    }
  
    Tab.VERSION = '3.2.0'
  
    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')[0]
      var e        = $.Event('show.bs.tab', {
        relatedTarget: previous
      })
  
      $this.trigger(e)
  
      if (e.isDefaultPrevented()) return
  
      var $target = $(selector)
  
      this.activate($this.closest('li'), $ul)
      this.activate($target, $target.parent(), function () {
        $this.trigger({
          type: 'shown.bs.tab',
          relatedTarget: previous
        })
      })
    }
  
    Tab.prototype.activate = function (element, container, callback) {
      var $active    = container.find('> .active')
      var transition = callback
        && $.support.transition
        && $active.hasClass('fade')
  
      function next() {
        $active
          .removeClass('active')
          .find('> .dropdown-menu > .active')
          .removeClass('active')
  
        element.addClass('active')
  
        if (transition) {
          element[0].offsetWidth // reflow for transition
          element.addClass('in')
        } else {
          element.removeClass('fade')
        }
  
        if (element.parent('.dropdown-menu')) {
          element.closest('li.dropdown').addClass('active')
        }
  
        callback && callback()
      }
  
      transition ?
        $active
          .one('bsTransitionEnd', next)
          .emulateTransitionEnd(150) :
        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
    // ============
  
    $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
      e.preventDefault()
      Plugin.call($(this), 'show')
    })
  
  }(jQuery);
  /* ========================================================================
   * Bootstrap: transition.js v3.2.0
   * http://getbootstrap.com/javascript/#transitions
   * ========================================================================
   * Copyright 2011-2014 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: scrollspy.js v3.2.0
   * http://getbootstrap.com/javascript/#scrollspy
   * ========================================================================
   * Copyright 2011-2014 Twitter, Inc.
   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   * ======================================================================== */
  
  
  
  +function ($) {
    'use strict';
  
    // SCROLLSPY CLASS DEFINITION
    // ==========================
  
    function ScrollSpy(element, options) {
      var process  = $.proxy(this.process, this)
  
      this.$body          = $('body')
      this.$scrollElement = $(element).is('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', process)
      this.refresh()
      this.process()
    }
  
    ScrollSpy.VERSION  = '3.2.0'
  
    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 offsetMethod = 'offset'
      var offsetBase   = 0
  
      if (!$.isWindow(this.$scrollElement[0])) {
        offsetMethod = 'position'
        offsetBase   = this.$scrollElement.scrollTop()
      }
  
      this.offsets = []
      this.targets = []
      this.scrollHeight = this.getScrollHeight()
  
      var self     = this
  
      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 () {
          self.offsets.push(this[0])
          self.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]) {
        return activeTarget != (i = targets[0]) && this.activate(i)
      }
  
      for (i = offsets.length; i--;) {
        activeTarget != targets[i]
          && scrollTop >= offsets[i]
          && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
          && this.activate(targets[i])
      }
    }
  
    ScrollSpy.prototype.activate = function (target) {
      this.activeTarget = target
  
      $(this.selector)
        .parentsUntil(this.options.target, '.active')
        .removeClass('active')
  
      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 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: modal.js v3.2.0
   * http://getbootstrap.com/javascript/#modals
   * ========================================================================
   * Copyright 2011-2014 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.$backdrop      =
      this.isShown        = null
      this.scrollbarWidth = 0
  
      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.2.0'
  
    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.$body.addClass('modal-open')
  
      this.setScrollbar()
      this.escape()
  
      this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
  
      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)
  
        if (transition) {
          that.$element[0].offsetWidth // force reflow
        }
  
        that.$element
          .addClass('in')
          .attr('aria-hidden', false)
  
        that.enforceFocus()
  
        var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
  
        transition ?
          that.$element.find('.modal-dialog') // wait for modal to slide in
            .one('bsTransitionEnd', function () {
              that.$element.trigger('focus').trigger(e)
            })
            .emulateTransitionEnd(300) :
          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.$body.removeClass('modal-open')
  
      this.resetScrollbar()
      this.escape()
  
      $(document).off('focusin.bs.modal')
  
      this.$element
        .removeClass('in')
        .attr('aria-hidden', true)
        .off('click.dismiss.bs.modal')
  
      $.support.transition && this.$element.hasClass('fade') ?
        this.$element
          .one('bsTransitionEnd', $.proxy(this.hideModal, this))
          .emulateTransitionEnd(300) :
        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('keyup.dismiss.bs.modal', $.proxy(function (e) {
          e.which == 27 && this.hide()
        }, this))
      } else if (!this.isShown) {
        this.$element.off('keyup.dismiss.bs.modal')
      }
    }
  
    Modal.prototype.hideModal = function () {
      var that = this
      this.$element.hide()
      this.backdrop(function () {
        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 = $('<div class="modal-backdrop ' + animate + '" />')
          .appendTo(this.$body)
  
        this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
          if (e.target !== e.currentTarget) return
          this.options.backdrop == 'static'
            ? this.$element[0].focus.call(this.$element[0])
            : this.hide.call(this)
        }, this))
  
        if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
  
        this.$backdrop.addClass('in')
  
        if (!callback) return
  
        doAnimate ?
          this.$backdrop
            .one('bsTransitionEnd', callback)
            .emulateTransitionEnd(150) :
          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(150) :
          callbackRemove()
  
      } else if (callback) {
        callback()
      }
    }
  
    Modal.prototype.checkScrollbar = function () {
      if (document.body.clientWidth >= window.innerWidth) return
      this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
    }
  
    Modal.prototype.setScrollbar = function () {
      var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
      if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
    }
  
    Modal.prototype.resetScrollbar = function () {
      this.$body.css('padding-right', '')
    }
  
    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.2.0
   * http://getbootstrap.com/javascript/#tooltip
   * Inspired by the original jQuery.tipsy by Jason Frame
   * ========================================================================
   * Copyright 2011-2014 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       =
      this.options    =
      this.enabled    =
      this.timeout    =
      this.hoverState =
      this.$element   = null
  
      this.init('tooltip', element, options)
    }
  
    Tooltip.VERSION  = '3.2.0'
  
    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 && $(this.options.viewport.selector || this.options.viewport)
  
      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)
      }
  
      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.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)
      }
  
      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(document.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)
  
        var pos          = this.getPosition()
        var actualWidth  = $tip[0].offsetWidth
        var actualHeight = $tip[0].offsetHeight
  
        if (autoPlace) {
          var orgPlacement = placement
          var $parent      = this.$element.parent()
          var parentDim    = this.getPosition($parent)
  
          placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
                      placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
                      placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
                      placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
                      placement
  
          $tip
            .removeClass(orgPlacement)
            .addClass(placement)
        }
  
        var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
  
        this.applyPlacement(calculatedOffset, placement)
  
        var complete = function () {
          that.$element.trigger('shown.bs.' + that.type)
          that.hoverState = null
        }
  
        $.support.transition && this.$tip.hasClass('fade') ?
          $tip
            .one('bsTransitionEnd', complete)
            .emulateTransitionEnd(150) :
          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  = offset.top  + marginTop
      offset.left = 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 arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
      var arrowPosition       = delta.left ? 'left'        : 'top'
      var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
  
      $tip.offset(offset)
      this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
    }
  
    Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
      this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
    }
  
    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 () {
      var that = this
      var $tip = this.tip()
      var e    = $.Event('hide.bs.' + this.type)
  
      this.$element.removeAttr('aria-describedby')
  
      function complete() {
        if (that.hoverState != 'in') $tip.detach()
        that.$element.trigger('hidden.bs.' + that.type)
      }
  
      this.$element.trigger(e)
  
      if (e.isDefaultPrevented()) return
  
      $tip.removeClass('in')
  
      $.support.transition && this.$tip.hasClass('fade') ?
        $tip
          .one('bsTransitionEnd', complete)
          .emulateTransitionEnd(150) :
        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'
      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
        scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
        width:  isBody ? $(window).width()  : $element.outerWidth(),
        height: isBody ? $(window).height() : $element.outerHeight()
      }, isBody ? { top: 0, left: 0 } : $element.offset())
    }
  
    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.width) { // 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 () {
      return (this.$tip = this.$tip || $(this.options.template))
    }
  
    Tooltip.prototype.arrow = function () {
      return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
    }
  
    Tooltip.prototype.validate = function () {
      if (!this.$element[0].parentNode) {
        this.hide()
        this.$element = null
        this.options  = null
      }
    }
  
    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)
        }
      }
  
      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
    }
  
    Tooltip.prototype.destroy = function () {
      clearTimeout(this.timeout)
      this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
    }
  
  
    // 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 && option == 'destroy') 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.2.0
   * http://getbootstrap.com/javascript/#popovers
   * ========================================================================
   * Copyright 2011-2014 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.2.0'
  
    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').empty()[ // 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.prototype.tip = function () {
      if (!this.$tip) this.$tip = $(this.options.template)
      return this.$tip
    }
  
  
    // 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 && option == 'destroy') 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);
  (function() {
  
  
  }).call(this);
  /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
  /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */
  
  window.matchMedia=window.matchMedia||function(a){"use strict";var c,d=a.documentElement,e=d.firstElementChild||d.firstChild,f=a.createElement("body"),g=a.createElement("div");return g.id="mq-test-1",g.style.cssText="position:absolute;top:-100em",f.style.background="none",f.appendChild(g),function(a){return g.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',d.insertBefore(f,e),c=42===g.offsetWidth,d.removeChild(f),{matches:c,media:a}}}(document);
  
  /*! Respond.js v1.3.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs  */
  (function(a){"use strict";function x(){u(!0)}var b={};if(a.respond=b,b.update=function(){},b.mediaQueriesSupported=a.matchMedia&&a.matchMedia("only all").matches,!b.mediaQueriesSupported){var q,r,t,c=a.document,d=c.documentElement,e=[],f=[],g=[],h={},i=30,j=c.getElementsByTagName("head")[0]||d,k=c.getElementsByTagName("base")[0],l=j.getElementsByTagName("link"),m=[],n=function(){for(var b=0;l.length>b;b++){var c=l[b],d=c.href,e=c.media,f=c.rel&&"stylesheet"===c.rel.toLowerCase();d&&f&&!h[d]&&(c.styleSheet&&c.styleSheet.rawCssText?(p(c.styleSheet.rawCssText,d,e),h[d]=!0):(!/^([a-zA-Z:]*\/\/)/.test(d)&&!k||d.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&m.push({href:d,media:e}))}o()},o=function(){if(m.length){var b=m.shift();v(b.href,function(c){p(c,b.href,b.media),h[b.href]=!0,a.setTimeout(function(){o()},0)})}},p=function(a,b,c){var d=a.match(/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi),g=d&&d.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,"$1"+b+"$2$3")},i=!g&&c;b.length&&(b+="/"),i&&(g=1);for(var j=0;g>j;j++){var k,l,m,n;i?(k=c,f.push(h(a))):(k=d[j].match(/@media *([^\{]+)\{([\S\s]+?)$/)&&RegExp.$1,f.push(RegExp.$2&&h(RegExp.$2))),m=k.split(","),n=m.length;for(var o=0;n>o;o++)l=m[o],e.push({media:l.split("(")[0].match(/(only\s+)?([a-zA-Z]+)\s?/)&&RegExp.$2||"all",rules:f.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},s=function(){var a,b=c.createElement("div"),e=c.body,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",e||(e=f=c.createElement("body"),e.style.background="none"),e.appendChild(b),d.insertBefore(e,d.firstChild),a=b.offsetWidth,f?d.removeChild(e):e.removeChild(b),a=t=parseFloat(a)},u=function(b){var h="clientWidth",k=d[h],m="CSS1Compat"===c.compatMode&&k||c.body[h]||k,n={},o=l[l.length-1],p=(new Date).getTime();if(b&&q&&i>p-q)return a.clearTimeout(r),r=a.setTimeout(u,i),void 0;q=p;for(var v in e)if(e.hasOwnProperty(v)){var w=e[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?t||s():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?t||s():1)),w.hasquery&&(z&&A||!(z||m>=x)||!(A||y>=m))||(n[w.media]||(n[w.media]=[]),n[w.media].push(f[w.rules]))}for(var C in g)g.hasOwnProperty(C)&&g[C]&&g[C].parentNode===j&&j.removeChild(g[C]);for(var D in n)if(n.hasOwnProperty(D)){var E=c.createElement("style"),F=n[D].join("\n");E.type="text/css",E.media=D,j.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(c.createTextNode(F)),g.push(E)}},v=function(a,b){var c=w();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},w=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}();n(),b.update=n,a.addEventListener?a.addEventListener("resize",x,!1):a.attachEvent&&a.attachEvent("onresize",x)}})(this);
  (function() {
  
  
  }).call(this);
  /*!
   * jQuery JavaScript Library v2.0.3
   * http://jquery.com/
   *
   * Includes Sizzle.js
   * http://sizzlejs.com/
   *
   * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
   * Released under the MIT license
   * http://jquery.org/license
   *
   * Date: 2013-07-03T13:30Z
   */
  
  (function( window, undefined ) {
  
  // Can't do this because several apps including ASP.NET trace
  // the stack via arguments.caller.callee and Firefox dies if
  // you try to trace through "use strict" call chains. (#13335)
  // Support: Firefox 18+
  //"use strict";
  var
  	// A central reference to the root jQuery(document)
  	rootjQuery,
  
  	// The deferred used on DOM ready
  	readyList,
  
  	// Support: IE9
  	// For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`
  	core_strundefined = typeof undefined,
  
  	// Use the correct document accordingly with window argument (sandbox)
  	location = window.location,
  	document = window.document,
  	docElem = document.documentElement,
  
  	// Map over jQuery in case of overwrite
  	_jQuery = window.jQuery,
  
  	// Map over the $ in case of overwrite
  	_$ = window.$,
  
  	// [[Class]] -> type pairs
  	class2type = {},
  
  	// List of deleted data cache ids, so we can reuse them
  	core_deletedIds = [],
  
  	core_version = "2.0.3",
  
  	// Save a reference to some core methods
  	core_concat = core_deletedIds.concat,
  	core_push = core_deletedIds.push,
  	core_slice = core_deletedIds.slice,
  	core_indexOf = core_deletedIds.indexOf,
  	core_toString = class2type.toString,
  	core_hasOwn = class2type.hasOwnProperty,
  	core_trim = core_version.trim,
  
  	// Define a local copy of jQuery
  	jQuery = function( selector, context ) {
  		// The jQuery object is actually just the init constructor 'enhanced'
  		return new jQuery.fn.init( selector, context, rootjQuery );
  	},
  
  	// Used for matching numbers
  	core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
  
  	// Used for splitting on whitespace
  	core_rnotwhite = /\S+/g,
  
  	// A simple way to check for HTML strings
  	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
  	// Strict HTML recognition (#11290: must start with <)
  	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
  
  	// Match a standalone tag
  	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
  
  	// Matches dashed string for camelizing
  	rmsPrefix = /^-ms-/,
  	rdashAlpha = /-([\da-z])/gi,
  
  	// Used by jQuery.camelCase as callback to replace()
  	fcamelCase = function( all, letter ) {
  		return letter.toUpperCase();
  	},
  
  	// The ready event handler and self cleanup method
  	completed = function() {
  		document.removeEventListener( "DOMContentLoaded", completed, false );
  		window.removeEventListener( "load", completed, false );
  		jQuery.ready();
  	};
  
  jQuery.fn = jQuery.prototype = {
  	// The current version of jQuery being used
  	jquery: core_version,
  
  	constructor: jQuery,
  	init: function( selector, context, rootjQuery ) {
  		var match, elem;
  
  		// HANDLE: $(""), $(null), $(undefined), $(false)
  		if ( !selector ) {
  			return this;
  		}
  
  		// Handle HTML strings
  		if ( typeof selector === "string" ) {
  			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
  				// Assume that strings that start and end with <> are HTML and skip the regex check
  				match = [ null, selector, null ];
  
  			} else {
  				match = rquickExpr.exec( selector );
  			}
  
  			// Match html or make sure no context is specified for #id
  			if ( match && (match[1] || !context) ) {
  
  				// HANDLE: $(html) -> $(array)
  				if ( match[1] ) {
  					context = context instanceof jQuery ? context[0] : context;
  
  					// scripts is true for back-compat
  					jQuery.merge( this, jQuery.parseHTML(
  						match[1],
  						context && context.nodeType ? context.ownerDocument || context : document,
  						true
  					) );
  
  					// HANDLE: $(html, props)
  					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
  						for ( match in context ) {
  							// Properties of context are called as methods if possible
  							if ( jQuery.isFunction( this[ match ] ) ) {
  								this[ match ]( context[ match ] );
  
  							// ...and otherwise set as attributes
  							} else {
  								this.attr( match, context[ match ] );
  							}
  						}
  					}
  
  					return this;
  
  				// HANDLE: $(#id)
  				} else {
  					elem = document.getElementById( match[2] );
  
  					// Check parentNode to catch when Blackberry 4.6 returns
  					// nodes that are no longer in the document #6963
  					if ( elem && elem.parentNode ) {
  						// Inject the element directly into the jQuery object
  						this.length = 1;
  						this[0] = elem;
  					}
  
  					this.context = document;
  					this.selector = selector;
  					return this;
  				}
  
  			// HANDLE: $(expr, $(...))
  			} else if ( !context || context.jquery ) {
  				return ( context || rootjQuery ).find( selector );
  
  			// HANDLE: $(expr, context)
  			// (which is just equivalent to: $(context).find(expr)
  			} else {
  				return this.constructor( context ).find( selector );
  			}
  
  		// HANDLE: $(DOMElement)
  		} else if ( selector.nodeType ) {
  			this.context = this[0] = selector;
  			this.length = 1;
  			return this;
  
  		// HANDLE: $(function)
  		// Shortcut for document ready
  		} else if ( jQuery.isFunction( selector ) ) {
  			return rootjQuery.ready( selector );
  		}
  
  		if ( selector.selector !== undefined ) {
  			this.selector = selector.selector;
  			this.context = selector.context;
  		}
  
  		return jQuery.makeArray( selector, this );
  	},
  
  	// Start with an empty selector
  	selector: "",
  
  	// The default length of a jQuery object is 0
  	length: 0,
  
  	toArray: function() {
  		return core_slice.call( this );
  	},
  
  	// Get the Nth element in the matched element set OR
  	// Get the whole matched element set as a clean array
  	get: function( num ) {
  		return num == null ?
  
  			// Return a 'clean' array
  			this.toArray() :
  
  			// Return just the object
  			( num < 0 ? this[ this.length + num ] : this[ num ] );
  	},
  
  	// Take an array of elements and push it onto the stack
  	// (returning the new matched element set)
  	pushStack: function( elems ) {
  
  		// Build a new jQuery matched element set
  		var ret = jQuery.merge( this.constructor(), elems );
  
  		// Add the old object onto the stack (as a reference)
  		ret.prevObject = this;
  		ret.context = this.context;
  
  		// Return the newly-formed element set
  		return ret;
  	},
  
  	// Execute a callback for every element in the matched set.
  	// (You can seed the arguments with an array of args, but this is
  	// only used internally.)
  	each: function( callback, args ) {
  		return jQuery.each( this, callback, args );
  	},
  
  	ready: function( fn ) {
  		// Add the callback
  		jQuery.ready.promise().done( fn );
  
  		return this;
  	},
  
  	slice: function() {
  		return this.pushStack( core_slice.apply( this, arguments ) );
  	},
  
  	first: function() {
  		return this.eq( 0 );
  	},
  
  	last: function() {
  		return this.eq( -1 );
  	},
  
  	eq: function( i ) {
  		var len = this.length,
  			j = +i + ( i < 0 ? len : 0 );
  		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
  	},
  
  	map: function( callback ) {
  		return this.pushStack( jQuery.map(this, function( elem, i ) {
  			return callback.call( elem, i, elem );
  		}));
  	},
  
  	end: function() {
  		return this.prevObject || this.constructor(null);
  	},
  
  	// For internal use only.
  	// Behaves like an Array's method, not like a jQuery method.
  	push: core_push,
  	sort: [].sort,
  	splice: [].splice
  };
  
  // Give the init function the jQuery prototype for later instantiation
  jQuery.fn.init.prototype = jQuery.fn;
  
  jQuery.extend = jQuery.fn.extend = function() {
  	var options, name, src, copy, copyIsArray, clone,
  		target = arguments[0] || {},
  		i = 1,
  		length = arguments.length,
  		deep = false;
  
  	// Handle a deep copy situation
  	if ( typeof target === "boolean" ) {
  		deep = target;
  		target = arguments[1] || {};
  		// skip the boolean and the target
  		i = 2;
  	}
  
  	// Handle case when target is a string or something (possible in deep copy)
  	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
  		target = {};
  	}
  
  	// extend jQuery itself if only one argument is passed
  	if ( length === i ) {
  		target = this;
  		--i;
  	}
  
  	for ( ; i < length; i++ ) {
  		// Only deal with non-null/undefined values
  		if ( (options = arguments[ i ]) != null ) {
  			// Extend the base object
  			for ( name in options ) {
  				src = target[ name ];
  				copy = options[ name ];
  
  				// Prevent never-ending loop
  				if ( target === copy ) {
  					continue;
  				}
  
  				// Recurse if we're merging plain objects or arrays
  				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
  					if ( copyIsArray ) {
  						copyIsArray = false;
  						clone = src && jQuery.isArray(src) ? src : [];
  
  					} else {
  						clone = src && jQuery.isPlainObject(src) ? src : {};
  					}
  
  					// Never move original objects, clone them
  					target[ name ] = jQuery.extend( deep, clone, copy );
  
  				// Don't bring in undefined values
  				} else if ( copy !== undefined ) {
  					target[ name ] = copy;
  				}
  			}
  		}
  	}
  
  	// Return the modified object
  	return target;
  };
  
  jQuery.extend({
  	// Unique for each copy of jQuery on the page
  	expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
  
  	noConflict: function( deep ) {
  		if ( window.$ === jQuery ) {
  			window.$ = _$;
  		}
  
  		if ( deep && window.jQuery === jQuery ) {
  			window.jQuery = _jQuery;
  		}
  
  		return jQuery;
  	},
  
  	// Is the DOM ready to be used? Set to true once it occurs.
  	isReady: false,
  
  	// A counter to track how many items to wait for before
  	// the ready event fires. See #6781
  	readyWait: 1,
  
  	// Hold (or release) the ready event
  	holdReady: function( hold ) {
  		if ( hold ) {
  			jQuery.readyWait++;
  		} else {
  			jQuery.ready( true );
  		}
  	},
  
  	// Handle when the DOM is ready
  	ready: function( wait ) {
  
  		// Abort if there are pending holds or we're already ready
  		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
  			return;
  		}
  
  		// Remember that the DOM is ready
  		jQuery.isReady = true;
  
  		// If a normal DOM Ready event fired, decrement, and wait if need be
  		if ( wait !== true && --jQuery.readyWait > 0 ) {
  			return;
  		}
  
  		// If there are functions bound, to execute
  		readyList.resolveWith( document, [ jQuery ] );
  
  		// Trigger any bound ready events
  		if ( jQuery.fn.trigger ) {
  			jQuery( document ).trigger("ready").off("ready");
  		}
  	},
  
  	// See test/unit/core.js for details concerning isFunction.
  	// Since version 1.3, DOM methods and functions like alert
  	// aren't supported. They return false on IE (#2968).
  	isFunction: function( obj ) {
  		return jQuery.type(obj) === "function";
  	},
  
  	isArray: Array.isArray,
  
  	isWindow: function( obj ) {
  		return obj != null && obj === obj.window;
  	},
  
  	isNumeric: function( obj ) {
  		return !isNaN( parseFloat(obj) ) && isFinite( obj );
  	},
  
  	type: function( obj ) {
  		if ( obj == null ) {
  			return String( obj );
  		}
  		// Support: Safari <= 5.1 (functionish RegExp)
  		return typeof obj === "object" || typeof obj === "function" ?
  			class2type[ core_toString.call(obj) ] || "object" :
  			typeof obj;
  	},
  
  	isPlainObject: function( obj ) {
  		// Not plain objects:
  		// - Any object or value whose internal [[Class]] property is not "[object Object]"
  		// - DOM nodes
  		// - window
  		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
  			return false;
  		}
  
  		// Support: Firefox <20
  		// The try/catch suppresses exceptions thrown when attempting to access
  		// the "constructor" property of certain host objects, ie. |window.location|
  		// https://bugzilla.mozilla.org/show_bug.cgi?id=814622
  		try {
  			if ( obj.constructor &&
  					!core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
  				return false;
  			}
  		} catch ( e ) {
  			return false;
  		}
  
  		// If the function hasn't returned already, we're confident that
  		// |obj| is a plain object, created by {} or constructed with new Object
  		return true;
  	},
  
  	isEmptyObject: function( obj ) {
  		var name;
  		for ( name in obj ) {
  			return false;
  		}
  		return true;
  	},
  
  	error: function( msg ) {
  		throw new Error( msg );
  	},
  
  	// data: string of html
  	// context (optional): If specified, the fragment will be created in this context, defaults to document
  	// keepScripts (optional): If true, will include scripts passed in the html string
  	parseHTML: function( data, context, keepScripts ) {
  		if ( !data || typeof data !== "string" ) {
  			return null;
  		}
  		if ( typeof context === "boolean" ) {
  			keepScripts = context;
  			context = false;
  		}
  		context = context || document;
  
  		var parsed = rsingleTag.exec( data ),
  			scripts = !keepScripts && [];
  
  		// Single tag
  		if ( parsed ) {
  			return [ context.createElement( parsed[1] ) ];
  		}
  
  		parsed = jQuery.buildFragment( [ data ], context, scripts );
  
  		if ( scripts ) {
  			jQuery( scripts ).remove();
  		}
  
  		return jQuery.merge( [], parsed.childNodes );
  	},
  
  	parseJSON: JSON.parse,
  
  	// Cross-browser xml parsing
  	parseXML: function( data ) {
  		var xml, tmp;
  		if ( !data || typeof data !== "string" ) {
  			return null;
  		}
  
  		// Support: IE9
  		try {
  			tmp = new DOMParser();
  			xml = tmp.parseFromString( data , "text/xml" );
  		} catch ( e ) {
  			xml = undefined;
  		}
  
  		if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
  			jQuery.error( "Invalid XML: " + data );
  		}
  		return xml;
  	},
  
  	noop: function() {},
  
  	// Evaluates a script in a global context
  	globalEval: function( code ) {
  		var script,
  				indirect = eval;
  
  		code = jQuery.trim( code );
  
  		if ( code ) {
  			// If the code includes a valid, prologue position
  			// strict mode pragma, execute code by injecting a
  			// script tag into the document.
  			if ( code.indexOf("use strict") === 1 ) {
  				script = document.createElement("script");
  				script.text = code;
  				document.head.appendChild( script ).parentNode.removeChild( script );
  			} else {
  			// Otherwise, avoid the DOM node creation, insertion
  			// and removal by using an indirect global eval
  				indirect( code );
  			}
  		}
  	},
  
  	// Convert dashed to camelCase; used by the css and data modules
  	// Microsoft forgot to hump their vendor prefix (#9572)
  	camelCase: function( string ) {
  		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
  	},
  
  	nodeName: function( elem, name ) {
  		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
  	},
  
  	// args is for internal usage only
  	each: function( obj, callback, args ) {
  		var value,
  			i = 0,
  			length = obj.length,
  			isArray = isArraylike( obj );
  
  		if ( args ) {
  			if ( isArray ) {
  				for ( ; i < length; i++ ) {
  					value = callback.apply( obj[ i ], args );
  
  					if ( value === false ) {
  						break;
  					}
  				}
  			} else {
  				for ( i in obj ) {
  					value = callback.apply( obj[ i ], args );
  
  					if ( value === false ) {
  						break;
  					}
  				}
  			}
  
  		// A special, fast, case for the most common use of each
  		} else {
  			if ( isArray ) {
  				for ( ; i < length; i++ ) {
  					value = callback.call( obj[ i ], i, obj[ i ] );
  
  					if ( value === false ) {
  						break;
  					}
  				}
  			} else {
  				for ( i in obj ) {
  					value = callback.call( obj[ i ], i, obj[ i ] );
  
  					if ( value === false ) {
  						break;
  					}
  				}
  			}
  		}
  
  		return obj;
  	},
  
  	trim: function( text ) {
  		return text == null ? "" : core_trim.call( text );
  	},
  
  	// results is for internal usage only
  	makeArray: function( arr, results ) {
  		var ret = results || [];
  
  		if ( arr != null ) {
  			if ( isArraylike( Object(arr) ) ) {
  				jQuery.merge( ret,
  					typeof arr === "string" ?
  					[ arr ] : arr
  				);
  			} else {
  				core_push.call( ret, arr );
  			}
  		}
  
  		return ret;
  	},
  
  	inArray: function( elem, arr, i ) {
  		return arr == null ? -1 : core_indexOf.call( arr, elem, i );
  	},
  
  	merge: function( first, second ) {
  		var l = second.length,
  			i = first.length,
  			j = 0;
  
  		if ( typeof l === "number" ) {
  			for ( ; j < l; j++ ) {
  				first[ i++ ] = second[ j ];
  			}
  		} else {
  			while ( second[j] !== undefined ) {
  				first[ i++ ] = second[ j++ ];
  			}
  		}
  
  		first.length = i;
  
  		return first;
  	},
  
  	grep: function( elems, callback, inv ) {
  		var retVal,
  			ret = [],
  			i = 0,
  			length = elems.length;
  		inv = !!inv;
  
  		// Go through the array, only saving the items
  		// that pass the validator function
  		for ( ; i < length; i++ ) {
  			retVal = !!callback( elems[ i ], i );
  			if ( inv !== retVal ) {
  				ret.push( elems[ i ] );
  			}
  		}
  
  		return ret;
  	},
  
  	// arg is for internal usage only
  	map: function( elems, callback, arg ) {
  		var value,
  			i = 0,
  			length = elems.length,
  			isArray = isArraylike( elems ),
  			ret = [];
  
  		// Go through the array, translating each of the items to their
  		if ( isArray ) {
  			for ( ; i < length; i++ ) {
  				value = callback( elems[ i ], i, arg );
  
  				if ( value != null ) {
  					ret[ ret.length ] = value;
  				}
  			}
  
  		// Go through every key on the object,
  		} else {
  			for ( i in elems ) {
  				value = callback( elems[ i ], i, arg );
  
  				if ( value != null ) {
  					ret[ ret.length ] = value;
  				}
  			}
  		}
  
  		// Flatten any nested arrays
  		return core_concat.apply( [], ret );
  	},
  
  	// A global GUID counter for objects
  	guid: 1,
  
  	// Bind a function to a context, optionally partially applying any
  	// arguments.
  	proxy: function( fn, context ) {
  		var tmp, args, proxy;
  
  		if ( typeof context === "string" ) {
  			tmp = fn[ context ];
  			context = fn;
  			fn = tmp;
  		}
  
  		// Quick check to determine if target is callable, in the spec
  		// this throws a TypeError, but we will just return undefined.
  		if ( !jQuery.isFunction( fn ) ) {
  			return undefined;
  		}
  
  		// Simulated bind
  		args = core_slice.call( arguments, 2 );
  		proxy = function() {
  			return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
  		};
  
  		// Set the guid of unique handler to the same of original handler, so it can be removed
  		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
  
  		return proxy;
  	},
  
  	// Multifunctional method to get and set values of a collection
  	// The value/s can optionally be executed if it's a function
  	access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
  		var i = 0,
  			length = elems.length,
  			bulk = key == null;
  
  		// Sets many values
  		if ( jQuery.type( key ) === "object" ) {
  			chainable = true;
  			for ( i in key ) {
  				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
  			}
  
  		// Sets one value
  		} else if ( value !== undefined ) {
  			chainable = true;
  
  			if ( !jQuery.isFunction( value ) ) {
  				raw = true;
  			}
  
  			if ( bulk ) {
  				// Bulk operations run against the entire set
  				if ( raw ) {
  					fn.call( elems, value );
  					fn = null;
  
  				// ...except when executing function values
  				} else {
  					bulk = fn;
  					fn = function( elem, key, value ) {
  						return bulk.call( jQuery( elem ), value );
  					};
  				}
  			}
  
  			if ( fn ) {
  				for ( ; i < length; i++ ) {
  					fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
  				}
  			}
  		}
  
  		return chainable ?
  			elems :
  
  			// Gets
  			bulk ?
  				fn.call( elems ) :
  				length ? fn( elems[0], key ) : emptyGet;
  	},
  
  	now: Date.now,
  
  	// A method for quickly swapping in/out CSS properties to get correct calculations.
  	// Note: this method belongs to the css module but it's needed here for the support module.
  	// If support gets modularized, this method should be moved back to the css module.
  	swap: function( elem, options, callback, args ) {
  		var ret, name,
  			old = {};
  
  		// Remember the old values, and insert the new ones
  		for ( name in options ) {
  			old[ name ] = elem.style[ name ];
  			elem.style[ name ] = options[ name ];
  		}
  
  		ret = callback.apply( elem, args || [] );
  
  		// Revert the old values
  		for ( name in options ) {
  			elem.style[ name ] = old[ name ];
  		}
  
  		return ret;
  	}
  });
  
  jQuery.ready.promise = function( obj ) {
  	if ( !readyList ) {
  
  		readyList = jQuery.Deferred();
  
  		// Catch cases where $(document).ready() is called after the browser event has already occurred.
  		// we once tried to use readyState "interactive" here, but it caused issues like the one
  		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
  		if ( document.readyState === "complete" ) {
  			// Handle it asynchronously to allow scripts the opportunity to delay ready
  			setTimeout( jQuery.ready );
  
  		} else {
  
  			// Use the handy event callback
  			document.addEventListener( "DOMContentLoaded", completed, false );
  
  			// A fallback to window.onload, that will always work
  			window.addEventListener( "load", completed, false );
  		}
  	}
  	return readyList.promise( obj );
  };
  
  // Populate the class2type map
  jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
  	class2type[ "[object " + name + "]" ] = name.toLowerCase();
  });
  
  function isArraylike( obj ) {
  	var length = obj.length,
  		type = jQuery.type( obj );
  
  	if ( jQuery.isWindow( obj ) ) {
  		return false;
  	}
  
  	if ( obj.nodeType === 1 && length ) {
  		return true;
  	}
  
  	return type === "array" || type !== "function" &&
  		( length === 0 ||
  		typeof length === "number" && length > 0 && ( length - 1 ) in obj );
  }
  
  // All jQuery objects should point back to these
  rootjQuery = jQuery(document);
  /*!
   * Sizzle CSS Selector Engine v1.9.4-pre
   * http://sizzlejs.com/
   *
   * Copyright 2013 jQuery Foundation, Inc. and other contributors
   * Released under the MIT license
   * http://jquery.org/license
   *
   * Date: 2013-06-03
   */
  (function( window, undefined ) {
  
  var i,
  	support,
  	cachedruns,
  	Expr,
  	getText,
  	isXML,
  	compile,
  	outermostContext,
  	sortInput,
  
  	// Local document vars
  	setDocument,
  	document,
  	docElem,
  	documentIsHTML,
  	rbuggyQSA,
  	rbuggyMatches,
  	matches,
  	contains,
  
  	// Instance-specific data
  	expando = "sizzle" + -(new Date()),
  	preferredDoc = window.document,
  	dirruns = 0,
  	done = 0,
  	classCache = createCache(),
  	tokenCache = createCache(),
  	compilerCache = createCache(),
  	hasDuplicate = false,
  	sortOrder = function( a, b ) {
  		if ( a === b ) {
  			hasDuplicate = true;
  			return 0;
  		}
  		return 0;
  	},
  
  	// General-purpose constants
  	strundefined = typeof undefined,
  	MAX_NEGATIVE = 1 << 31,
  
  	// Instance methods
  	hasOwn = ({}).hasOwnProperty,
  	arr = [],
  	pop = arr.pop,
  	push_native = arr.push,
  	push = arr.push,
  	slice = arr.slice,
  	// Use a stripped-down indexOf if we can't use a native one
  	indexOf = arr.indexOf || function( elem ) {
  		var i = 0,
  			len = this.length;
  		for ( ; i < len; i++ ) {
  			if ( this[i] === elem ) {
  				return i;
  			}
  		}
  		return -1;
  	},
  
  	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
  
  	// Regular expressions
  
  	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
  	whitespace = "[\\x20\\t\\r\\n\\f]",
  	// http://www.w3.org/TR/css3-syntax/#characters
  	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
  
  	// Loosely modeled on CSS identifier characters
  	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
  	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
  	identifier = characterEncoding.replace( "w", "w#" ),
  
  	// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
  	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
  		"*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
  
  	// Prefer arguments quoted,
  	//   then not containing pseudos/brackets,
  	//   then attribute selectors/non-parenthetical expressions,
  	//   then anything else
  	// These preferences are here to reduce the number of selectors
  	//   needing tokenize in the PSEUDO preFilter
  	pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
  
  	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
  	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
  
  	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
  	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
  
  	rsibling = new RegExp( whitespace + "*[+~]" ),
  	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ),
  
  	rpseudo = new RegExp( pseudos ),
  	ridentifier = new RegExp( "^" + identifier + "$" ),
  
  	matchExpr = {
  		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
  		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
  		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
  		"ATTR": new RegExp( "^" + attributes ),
  		"PSEUDO": new RegExp( "^" + pseudos ),
  		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
  			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
  			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
  		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
  		// For use in libraries implementing .is()
  		// We use this for POS matching in `select`
  		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
  			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
  	},
  
  	rnative = /^[^{]+\{\s*\[native \w/,
  
  	// Easily-parseable/retrievable ID or TAG or CLASS selectors
  	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
  
  	rinputs = /^(?:input|select|textarea|button)$/i,
  	rheader = /^h\d$/i,
  
  	rescape = /'|\\/g,
  
  	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
  	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
  	funescape = function( _, escaped, escapedWhitespace ) {
  		var high = "0x" + escaped - 0x10000;
  		// NaN means non-codepoint
  		// Support: Firefox
  		// Workaround erroneous numeric interpretation of +"0x"
  		return high !== high || escapedWhitespace ?
  			escaped :
  			// BMP codepoint
  			high < 0 ?
  				String.fromCharCode( high + 0x10000 ) :
  				// Supplemental Plane codepoint (surrogate pair)
  				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
  	};
  
  // Optimize for push.apply( _, NodeList )
  try {
  	push.apply(
  		(arr = slice.call( preferredDoc.childNodes )),
  		preferredDoc.childNodes
  	);
  	// Support: Android<4.0
  	// Detect silently failing push.apply
  	arr[ preferredDoc.childNodes.length ].nodeType;
  } catch ( e ) {
  	push = { apply: arr.length ?
  
  		// Leverage slice if possible
  		function( target, els ) {
  			push_native.apply( target, slice.call(els) );
  		} :
  
  		// Support: IE<9
  		// Otherwise append directly
  		function( target, els ) {
  			var j = target.length,
  				i = 0;
  			// Can't trust NodeList.length
  			while ( (target[j++] = els[i++]) ) {}
  			target.length = j - 1;
  		}
  	};
  }
  
  function Sizzle( selector, context, results, seed ) {
  	var match, elem, m, nodeType,
  		// QSA vars
  		i, groups, old, nid, newContext, newSelector;
  
  	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
  		setDocument( context );
  	}
  
  	context = context || document;
  	results = results || [];
  
  	if ( !selector || typeof selector !== "string" ) {
  		return results;
  	}
  
  	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
  		return [];
  	}
  
  	if ( documentIsHTML && !seed ) {
  
  		// Shortcuts
  		if ( (match = rquickExpr.exec( selector )) ) {
  			// Speed-up: Sizzle("#ID")
  			if ( (m = match[1]) ) {
  				if ( nodeType === 9 ) {
  					elem = context.getElementById( m );
  					// Check parentNode to catch when Blackberry 4.6 returns
  					// nodes that are no longer in the document #6963
  					if ( elem && elem.parentNode ) {
  						// Handle the case where IE, Opera, and Webkit return items
  						// by name instead of ID
  						if ( elem.id === m ) {
  							results.push( elem );
  							return results;
  						}
  					} else {
  						return results;
  					}
  				} else {
  					// Context is not a document
  					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
  						contains( context, elem ) && elem.id === m ) {
  						results.push( elem );
  						return results;
  					}
  				}
  
  			// Speed-up: Sizzle("TAG")
  			} else if ( match[2] ) {
  				push.apply( results, context.getElementsByTagName( selector ) );
  				return results;
  
  			// Speed-up: Sizzle(".CLASS")
  			} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
  				push.apply( results, context.getElementsByClassName( m ) );
  				return results;
  			}
  		}
  
  		// QSA path
  		if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
  			nid = old = expando;
  			newContext = context;
  			newSelector = nodeType === 9 && selector;
  
  			// qSA works strangely on Element-rooted queries
  			// We can work around this by specifying an extra ID on the root
  			// and working up from there (Thanks to Andrew Dupont for the technique)
  			// IE 8 doesn't work on object elements
  			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
  				groups = tokenize( selector );
  
  				if ( (old = context.getAttribute("id")) ) {
  					nid = old.replace( rescape, "\\$&" );
  				} else {
  					context.setAttribute( "id", nid );
  				}
  				nid = "[id='" + nid + "'] ";
  
  				i = groups.length;
  				while ( i-- ) {
  					groups[i] = nid + toSelector( groups[i] );
  				}
  				newContext = rsibling.test( selector ) && context.parentNode || context;
  				newSelector = groups.join(",");
  			}
  
  			if ( newSelector ) {
  				try {
  					push.apply( results,
  						newContext.querySelectorAll( newSelector )
  					);
  					return results;
  				} catch(qsaError) {
  				} finally {
  					if ( !old ) {
  						context.removeAttribute("id");
  					}
  				}
  			}
  		}
  	}
  
  	// All others
  	return select( selector.replace( rtrim, "$1" ), context, results, seed );
  }
  
  /**
   * Create key-value caches of limited size
   * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
   *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
   *	deleting the oldest entry
   */
  function createCache() {
  	var keys = [];
  
  	function cache( key, value ) {
  		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
  		if ( keys.push( key += " " ) > Expr.cacheLength ) {
  			// Only keep the most recent entries
  			delete cache[ keys.shift() ];
  		}
  		return (cache[ key ] = value);
  	}
  	return cache;
  }
  
  /**
   * Mark a function for special use by Sizzle
   * @param {Function} fn The function to mark
   */
  function markFunction( fn ) {
  	fn[ expando ] = true;
  	return fn;
  }
  
  /**
   * Support testing using an element
   * @param {Function} fn Passed the created div and expects a boolean result
   */
  function assert( fn ) {
  	var div = document.createElement("div");
  
  	try {
  		return !!fn( div );
  	} catch (e) {
  		return false;
  	} finally {
  		// Remove from its parent by default
  		if ( div.parentNode ) {
  			div.parentNode.removeChild( div );
  		}
  		// release memory in IE
  		div = null;
  	}
  }
  
  /**
   * Adds the same handler for all of the specified attrs
   * @param {String} attrs Pipe-separated list of attributes
   * @param {Function} handler The method that will be applied
   */
  function addHandle( attrs, handler ) {
  	var arr = attrs.split("|"),
  		i = attrs.length;
  
  	while ( i-- ) {
  		Expr.attrHandle[ arr[i] ] = handler;
  	}
  }
  
  /**
   * Checks document order of two siblings
   * @param {Element} a
   * @param {Element} b
   * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
   */
  function siblingCheck( a, b ) {
  	var cur = b && a,
  		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
  			( ~b.sourceIndex || MAX_NEGATIVE ) -
  			( ~a.sourceIndex || MAX_NEGATIVE );
  
  	// Use IE sourceIndex if available on both nodes
  	if ( diff ) {
  		return diff;
  	}
  
  	// Check if b follows a
  	if ( cur ) {
  		while ( (cur = cur.nextSibling) ) {
  			if ( cur === b ) {
  				return -1;
  			}
  		}
  	}
  
  	return a ? 1 : -1;
  }
  
  /**
   * Returns a function to use in pseudos for input types
   * @param {String} type
   */
  function createInputPseudo( type ) {
  	return function( elem ) {
  		var name = elem.nodeName.toLowerCase();
  		return name === "input" && elem.type === type;
  	};
  }
  
  /**
   * Returns a function to use in pseudos for buttons
   * @param {String} type
   */
  function createButtonPseudo( type ) {
  	return function( elem ) {
  		var name = elem.nodeName.toLowerCase();
  		return (name === "input" || name === "button") && elem.type === type;
  	};
  }
  
  /**
   * Returns a function to use in pseudos for positionals
   * @param {Function} fn
   */
  function createPositionalPseudo( fn ) {
  	return markFunction(function( argument ) {
  		argument = +argument;
  		return markFunction(function( seed, matches ) {
  			var j,
  				matchIndexes = fn( [], seed.length, argument ),
  				i = matchIndexes.length;
  
  			// Match elements found at the specified indexes
  			while ( i-- ) {
  				if ( seed[ (j = matchIndexes[i]) ] ) {
  					seed[j] = !(matches[j] = seed[j]);
  				}
  			}
  		});
  	});
  }
  
  /**
   * Detect xml
   * @param {Element|Object} elem An element or a document
   */
  isXML = Sizzle.isXML = function( elem ) {
  	// documentElement is verified for cases where it doesn't yet exist
  	// (such as loading iframes in IE - #4833)
  	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
  	return documentElement ? documentElement.nodeName !== "HTML" : false;
  };
  
  // Expose support vars for convenience
  support = Sizzle.support = {};
  
  /**
   * Sets document-related variables once based on the current document
   * @param {Element|Object} [doc] An element or document object to use to set the document
   * @returns {Object} Returns the current document
   */
  setDocument = Sizzle.setDocument = function( node ) {
  	var doc = node ? node.ownerDocument || node : preferredDoc,
  		parent = doc.defaultView;
  
  	// If no document and documentElement is available, return
  	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  		return document;
  	}
  
  	// Set our document
  	document = doc;
  	docElem = doc.documentElement;
  
  	// Support tests
  	documentIsHTML = !isXML( doc );
  
  	// Support: IE>8
  	// If iframe document is assigned to "document" variable and if iframe has been reloaded,
  	// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
  	// IE6-8 do not support the defaultView property so parent will be undefined
  	if ( parent && parent.attachEvent && parent !== parent.top ) {
  		parent.attachEvent( "onbeforeunload", function() {
  			setDocument();
  		});
  	}
  
  	/* Attributes
  	---------------------------------------------------------------------- */
  
  	// Support: IE<8
  	// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
  	support.attributes = assert(function( div ) {
  		div.className = "i";
  		return !div.getAttribute("className");
  	});
  
  	/* getElement(s)By*
  	---------------------------------------------------------------------- */
  
  	// Check if getElementsByTagName("*") returns only elements
  	support.getElementsByTagName = assert(function( div ) {
  		div.appendChild( doc.createComment("") );
  		return !div.getElementsByTagName("*").length;
  	});
  
  	// Check if getElementsByClassName can be trusted
  	support.getElementsByClassName = assert(function( div ) {
  		div.innerHTML = "<div class='a'></div><div class='a i'></div>";
  
  		// Support: Safari<4
  		// Catch class over-caching
  		div.firstChild.className = "i";
  		// Support: Opera<10
  		// Catch gEBCN failure to find non-leading classes
  		return div.getElementsByClassName("i").length === 2;
  	});
  
  	// Support: IE<10
  	// Check if getElementById returns elements by name
  	// The broken getElementById methods don't pick up programatically-set names,
  	// so use a roundabout getElementsByName test
  	support.getById = assert(function( div ) {
  		docElem.appendChild( div ).id = expando;
  		return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
  	});
  
  	// ID find and filter
  	if ( support.getById ) {
  		Expr.find["ID"] = function( id, context ) {
  			if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
  				var m = context.getElementById( id );
  				// Check parentNode to catch when Blackberry 4.6 returns
  				// nodes that are no longer in the document #6963
  				return m && m.parentNode ? [m] : [];
  			}
  		};
  		Expr.filter["ID"] = function( id ) {
  			var attrId = id.replace( runescape, funescape );
  			return function( elem ) {
  				return elem.getAttribute("id") === attrId;
  			};
  		};
  	} else {
  		// Support: IE6/7
  		// getElementById is not reliable as a find shortcut
  		delete Expr.find["ID"];
  
  		Expr.filter["ID"] =  function( id ) {
  			var attrId = id.replace( runescape, funescape );
  			return function( elem ) {
  				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
  				return node && node.value === attrId;
  			};
  		};
  	}
  
  	// Tag
  	Expr.find["TAG"] = support.getElementsByTagName ?
  		function( tag, context ) {
  			if ( typeof context.getElementsByTagName !== strundefined ) {
  				return context.getElementsByTagName( tag );
  			}
  		} :
  		function( tag, context ) {
  			var elem,
  				tmp = [],
  				i = 0,
  				results = context.getElementsByTagName( tag );
  
  			// Filter out possible comments
  			if ( tag === "*" ) {
  				while ( (elem = results[i++]) ) {
  					if ( elem.nodeType === 1 ) {
  						tmp.push( elem );
  					}
  				}
  
  				return tmp;
  			}
  			return results;
  		};
  
  	// Class
  	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  		if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
  			return context.getElementsByClassName( className );
  		}
  	};
  
  	/* QSA/matchesSelector
  	---------------------------------------------------------------------- */
  
  	// QSA and matchesSelector support
  
  	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
  	rbuggyMatches = [];
  
  	// qSa(:focus) reports false when true (Chrome 21)
  	// We allow this because of a bug in IE8/9 that throws an error
  	// whenever `document.activeElement` is accessed on an iframe
  	// So, we allow :focus to pass through QSA all the time to avoid the IE error
  	// See http://bugs.jquery.com/ticket/13378
  	rbuggyQSA = [];
  
  	if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
  		// Build QSA regex
  		// Regex strategy adopted from Diego Perini
  		assert(function( div ) {
  			// Select is set to empty string on purpose
  			// This is to test IE's treatment of not explicitly
  			// setting a boolean content attribute,
  			// since its presence should be enough
  			// http://bugs.jquery.com/ticket/12359
  			div.innerHTML = "<select><option selected=''></option></select>";
  
  			// Support: IE8
  			// Boolean attributes and "value" are not treated correctly
  			if ( !div.querySelectorAll("[selected]").length ) {
  				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  			}
  
  			// Webkit/Opera - :checked should return selected option elements
  			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  			// IE8 throws error here and will not see later tests
  			if ( !div.querySelectorAll(":checked").length ) {
  				rbuggyQSA.push(":checked");
  			}
  		});
  
  		assert(function( div ) {
  
  			// Support: Opera 10-12/IE8
  			// ^= $= *= and empty values
  			// Should not select anything
  			// Support: Windows 8 Native Apps
  			// The type attribute is restricted during .innerHTML assignment
  			var input = doc.createElement("input");
  			input.setAttribute( "type", "hidden" );
  			div.appendChild( input ).setAttribute( "t", "" );
  
  			if ( div.querySelectorAll("[t^='']").length ) {
  				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  			}
  
  			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
  			// IE8 throws error here and will not see later tests
  			if ( !div.querySelectorAll(":enabled").length ) {
  				rbuggyQSA.push( ":enabled", ":disabled" );
  			}
  
  			// Opera 10-11 does not throw on post-comma invalid pseudos
  			div.querySelectorAll("*,:x");
  			rbuggyQSA.push(",.*:");
  		});
  	}
  
  	if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
  		docElem.mozMatchesSelector ||
  		docElem.oMatchesSelector ||
  		docElem.msMatchesSelector) )) ) {
  
  		assert(function( div ) {
  			// Check to see if it's possible to do matchesSelector
  			// on a disconnected node (IE 9)
  			support.disconnectedMatch = matches.call( div, "div" );
  
  			// This should fail with an exception
  			// Gecko does not error, returns false instead
  			matches.call( div, "[s!='']:x" );
  			rbuggyMatches.push( "!=", pseudos );
  		});
  	}
  
  	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
  	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
  
  	/* Contains
  	---------------------------------------------------------------------- */
  
  	// Element contains another
  	// Purposefully does not implement inclusive descendent
  	// As in, an element does not contain itself
  	contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ?
  		function( a, b ) {
  			var adown = a.nodeType === 9 ? a.documentElement : a,
  				bup = b && b.parentNode;
  			return a === bup || !!( bup && bup.nodeType === 1 && (
  				adown.contains ?
  					adown.contains( bup ) :
  					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
  			));
  		} :
  		function( a, b ) {
  			if ( b ) {
  				while ( (b = b.parentNode) ) {
  					if ( b === a ) {
  						return true;
  					}
  				}
  			}
  			return false;
  		};
  
  	/* Sorting
  	---------------------------------------------------------------------- */
  
  	// Document order sorting
  	sortOrder = docElem.compareDocumentPosition ?
  	function( a, b ) {
  
  		// Flag for duplicate removal
  		if ( a === b ) {
  			hasDuplicate = true;
  			return 0;
  		}
  
  		var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );
  
  		if ( compare ) {
  			// Disconnected nodes
  			if ( compare & 1 ||
  				(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
  
  				// Choose the first element that is related to our preferred document
  				if ( a === doc || contains(preferredDoc, a) ) {
  					return -1;
  				}
  				if ( b === doc || contains(preferredDoc, b) ) {
  					return 1;
  				}
  
  				// Maintain original order
  				return sortInput ?
  					( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
  					0;
  			}
  
  			return compare & 4 ? -1 : 1;
  		}
  
  		// Not directly comparable, sort on existence of method
  		return a.compareDocumentPosition ? -1 : 1;
  	} :
  	function( a, b ) {
  		var cur,
  			i = 0,
  			aup = a.parentNode,
  			bup = b.parentNode,
  			ap = [ a ],
  			bp = [ b ];
  
  		// Exit early if the nodes are identical
  		if ( a === b ) {
  			hasDuplicate = true;
  			return 0;
  
  		// Parentless nodes are either documents or disconnected
  		} else if ( !aup || !bup ) {
  			return a === doc ? -1 :
  				b === doc ? 1 :
  				aup ? -1 :
  				bup ? 1 :
  				sortInput ?
  				( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
  				0;
  
  		// If the nodes are siblings, we can do a quick check
  		} else if ( aup === bup ) {
  			return siblingCheck( a, b );
  		}
  
  		// Otherwise we need full lists of their ancestors for comparison
  		cur = a;
  		while ( (cur = cur.parentNode) ) {
  			ap.unshift( cur );
  		}
  		cur = b;
  		while ( (cur = cur.parentNode) ) {
  			bp.unshift( cur );
  		}
  
  		// Walk down the tree looking for a discrepancy
  		while ( ap[i] === bp[i] ) {
  			i++;
  		}
  
  		return i ?
  			// Do a sibling check if the nodes have a common ancestor
  			siblingCheck( ap[i], bp[i] ) :
  
  			// Otherwise nodes in our document sort first
  			ap[i] === preferredDoc ? -1 :
  			bp[i] === preferredDoc ? 1 :
  			0;
  	};
  
  	return doc;
  };
  
  Sizzle.matches = function( expr, elements ) {
  	return Sizzle( expr, null, null, elements );
  };
  
  Sizzle.matchesSelector = function( elem, expr ) {
  	// Set document vars if needed
  	if ( ( elem.ownerDocument || elem ) !== document ) {
  		setDocument( elem );
  	}
  
  	// Make sure that attribute selectors are quoted
  	expr = expr.replace( rattributeQuotes, "='$1']" );
  
  	if ( support.matchesSelector && documentIsHTML &&
  		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
  		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
  
  		try {
  			var ret = matches.call( elem, expr );
  
  			// IE 9's matchesSelector returns false on disconnected nodes
  			if ( ret || support.disconnectedMatch ||
  					// As well, disconnected nodes are said to be in a document
  					// fragment in IE 9
  					elem.document && elem.document.nodeType !== 11 ) {
  				return ret;
  			}
  		} catch(e) {}
  	}
  
  	return Sizzle( expr, document, null, [elem] ).length > 0;
  };
  
  Sizzle.contains = function( context, elem ) {
  	// Set document vars if needed
  	if ( ( context.ownerDocument || context ) !== document ) {
  		setDocument( context );
  	}
  	return contains( context, elem );
  };
  
  Sizzle.attr = function( elem, name ) {
  	// Set document vars if needed
  	if ( ( elem.ownerDocument || elem ) !== document ) {
  		setDocument( elem );
  	}
  
  	var fn = Expr.attrHandle[ name.toLowerCase() ],
  		// Don't get fooled by Object.prototype properties (jQuery #13807)
  		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
  			fn( elem, name, !documentIsHTML ) :
  			undefined;
  
  	return val === undefined ?
  		support.attributes || !documentIsHTML ?
  			elem.getAttribute( name ) :
  			(val = elem.getAttributeNode(name)) && val.specified ?
  				val.value :
  				null :
  		val;
  };
  
  Sizzle.error = function( msg ) {
  	throw new Error( "Syntax error, unrecognized expression: " + msg );
  };
  
  /**
   * Document sorting and removing duplicates
   * @param {ArrayLike} results
   */
  Sizzle.uniqueSort = function( results ) {
  	var elem,
  		duplicates = [],
  		j = 0,
  		i = 0;
  
  	// Unless we *know* we can detect duplicates, assume their presence
  	hasDuplicate = !support.detectDuplicates;
  	sortInput = !support.sortStable && results.slice( 0 );
  	results.sort( sortOrder );
  
  	if ( hasDuplicate ) {
  		while ( (elem = results[i++]) ) {
  			if ( elem === results[ i ] ) {
  				j = duplicates.push( i );
  			}
  		}
  		while ( j-- ) {
  			results.splice( duplicates[ j ], 1 );
  		}
  	}
  
  	return results;
  };
  
  /**
   * Utility function for retrieving the text value of an array of DOM nodes
   * @param {Array|Element} elem
   */
  getText = Sizzle.getText = function( elem ) {
  	var node,
  		ret = "",
  		i = 0,
  		nodeType = elem.nodeType;
  
  	if ( !nodeType ) {
  		// If no nodeType, this is expected to be an array
  		for ( ; (node = elem[i]); i++ ) {
  			// Do not traverse comment nodes
  			ret += getText( node );
  		}
  	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
  		// Use textContent for elements
  		// innerText usage removed for consistency of new lines (see #11153)
  		if ( typeof elem.textContent === "string" ) {
  			return elem.textContent;
  		} else {
  			// Traverse its children
  			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  				ret += getText( elem );
  			}
  		}
  	} else if ( nodeType === 3 || nodeType === 4 ) {
  		return elem.nodeValue;
  	}
  	// Do not include comment or processing instruction nodes
  
  	return ret;
  };
  
  Expr = Sizzle.selectors = {
  
  	// Can be adjusted by the user
  	cacheLength: 50,
  
  	createPseudo: markFunction,
  
  	match: matchExpr,
  
  	attrHandle: {},
  
  	find: {},
  
  	relative: {
  		">": { dir: "parentNode", first: true },
  		" ": { dir: "parentNode" },
  		"+": { dir: "previousSibling", first: true },
  		"~": { dir: "previousSibling" }
  	},
  
  	preFilter: {
  		"ATTR": function( match ) {
  			match[1] = match[1].replace( runescape, funescape );
  
  			// Move the given value to match[3] whether quoted or unquoted
  			match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
  
  			if ( match[2] === "~=" ) {
  				match[3] = " " + match[3] + " ";
  			}
  
  			return match.slice( 0, 4 );
  		},
  
  		"CHILD": function( match ) {
  			/* matches from matchExpr["CHILD"]
  				1 type (only|nth|...)
  				2 what (child|of-type)
  				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
  				4 xn-component of xn+y argument ([+-]?\d*n|)
  				5 sign of xn-component
  				6 x of xn-component
  				7 sign of y-component
  				8 y of y-component
  			*/
  			match[1] = match[1].toLowerCase();
  
  			if ( match[1].slice( 0, 3 ) === "nth" ) {
  				// nth-* requires argument
  				if ( !match[3] ) {
  					Sizzle.error( match[0] );
  				}
  
  				// numeric x and y parameters for Expr.filter.CHILD
  				// remember that false/true cast respectively to 0/1
  				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
  				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
  
  			// other types prohibit arguments
  			} else if ( match[3] ) {
  				Sizzle.error( match[0] );
  			}
  
  			return match;
  		},
  
  		"PSEUDO": function( match ) {
  			var excess,
  				unquoted = !match[5] && match[2];
  
  			if ( matchExpr["CHILD"].test( match[0] ) ) {
  				return null;
  			}
  
  			// Accept quoted arguments as-is
  			if ( match[3] && match[4] !== undefined ) {
  				match[2] = match[4];
  
  			// Strip excess characters from unquoted arguments
  			} else if ( unquoted && rpseudo.test( unquoted ) &&
  				// Get excess from tokenize (recursively)
  				(excess = tokenize( unquoted, true )) &&
  				// advance to the next closing parenthesis
  				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
  
  				// excess is a negative index
  				match[0] = match[0].slice( 0, excess );
  				match[2] = unquoted.slice( 0, excess );
  			}
  
  			// Return only captures needed by the pseudo filter method (type and argument)
  			return match.slice( 0, 3 );
  		}
  	},
  
  	filter: {
  
  		"TAG": function( nodeNameSelector ) {
  			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
  			return nodeNameSelector === "*" ?
  				function() { return true; } :
  				function( elem ) {
  					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
  				};
  		},
  
  		"CLASS": function( className ) {
  			var pattern = classCache[ className + " " ];
  
  			return pattern ||
  				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  				classCache( className, function( elem ) {
  					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
  				});
  		},
  
  		"ATTR": function( name, operator, check ) {
  			return function( elem ) {
  				var result = Sizzle.attr( elem, name );
  
  				if ( result == null ) {
  					return operator === "!=";
  				}
  				if ( !operator ) {
  					return true;
  				}
  
  				result += "";
  
  				return operator === "=" ? result === check :
  					operator === "!=" ? result !== check :
  					operator === "^=" ? check && result.indexOf( check ) === 0 :
  					operator === "*=" ? check && result.indexOf( check ) > -1 :
  					operator === "$=" ? check && result.slice( -check.length ) === check :
  					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
  					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  					false;
  			};
  		},
  
  		"CHILD": function( type, what, argument, first, last ) {
  			var simple = type.slice( 0, 3 ) !== "nth",
  				forward = type.slice( -4 ) !== "last",
  				ofType = what === "of-type";
  
  			return first === 1 && last === 0 ?
  
  				// Shortcut for :nth-*(n)
  				function( elem ) {
  					return !!elem.parentNode;
  				} :
  
  				function( elem, context, xml ) {
  					var cache, outerCache, node, diff, nodeIndex, start,
  						dir = simple !== forward ? "nextSibling" : "previousSibling",
  						parent = elem.parentNode,
  						name = ofType && elem.nodeName.toLowerCase(),
  						useCache = !xml && !ofType;
  
  					if ( parent ) {
  
  						// :(first|last|only)-(child|of-type)
  						if ( simple ) {
  							while ( dir ) {
  								node = elem;
  								while ( (node = node[ dir ]) ) {
  									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
  										return false;
  									}
  								}
  								// Reverse direction for :only-* (if we haven't yet done so)
  								start = dir = type === "only" && !start && "nextSibling";
  							}
  							return true;
  						}
  
  						start = [ forward ? parent.firstChild : parent.lastChild ];
  
  						// non-xml :nth-child(...) stores cache data on `parent`
  						if ( forward && useCache ) {
  							// Seek `elem` from a previously-cached index
  							outerCache = parent[ expando ] || (parent[ expando ] = {});
  							cache = outerCache[ type ] || [];
  							nodeIndex = cache[0] === dirruns && cache[1];
  							diff = cache[0] === dirruns && cache[2];
  							node = nodeIndex && parent.childNodes[ nodeIndex ];
  
  							while ( (node = ++nodeIndex && node && node[ dir ] ||
  
  								// Fallback to seeking `elem` from the start
  								(diff = nodeIndex = 0) || start.pop()) ) {
  
  								// When found, cache indexes on `parent` and break
  								if ( node.nodeType === 1 && ++diff && node === elem ) {
  									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
  									break;
  								}
  							}
  
  						// Use previously-cached element index if available
  						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
  							diff = cache[1];
  
  						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
  						} else {
  							// Use the same loop as above to seek `elem` from the start
  							while ( (node = ++nodeIndex && node && node[ dir ] ||
  								(diff = nodeIndex = 0) || start.pop()) ) {
  
  								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
  									// Cache the index of each encountered element
  									if ( useCache ) {
  										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
  									}
  
  									if ( node === elem ) {
  										break;
  									}
  								}
  							}
  						}
  
  						// Incorporate the offset, then check against cycle size
  						diff -= last;
  						return diff === first || ( diff % first === 0 && diff / first >= 0 );
  					}
  				};
  		},
  
  		"PSEUDO": function( pseudo, argument ) {
  			// pseudo-class names are case-insensitive
  			// http://www.w3.org/TR/selectors/#pseudo-classes
  			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
  			// Remember that setFilters inherits from pseudos
  			var args,
  				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
  					Sizzle.error( "unsupported pseudo: " + pseudo );
  
  			// The user may use createPseudo to indicate that
  			// arguments are needed to create the filter function
  			// just as Sizzle does
  			if ( fn[ expando ] ) {
  				return fn( argument );
  			}
  
  			// But maintain support for old signatures
  			if ( fn.length > 1 ) {
  				args = [ pseudo, pseudo, "", argument ];
  				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
  					markFunction(function( seed, matches ) {
  						var idx,
  							matched = fn( seed, argument ),
  							i = matched.length;
  						while ( i-- ) {
  							idx = indexOf.call( seed, matched[i] );
  							seed[ idx ] = !( matches[ idx ] = matched[i] );
  						}
  					}) :
  					function( elem ) {
  						return fn( elem, 0, args );
  					};
  			}
  
  			return fn;
  		}
  	},
  
  	pseudos: {
  		// Potentially complex pseudos
  		"not": markFunction(function( selector ) {
  			// Trim the selector passed to compile
  			// to avoid treating leading and trailing
  			// spaces as combinators
  			var input = [],
  				results = [],
  				matcher = compile( selector.replace( rtrim, "$1" ) );
  
  			return matcher[ expando ] ?
  				markFunction(function( seed, matches, context, xml ) {
  					var elem,
  						unmatched = matcher( seed, null, xml, [] ),
  						i = seed.length;
  
  					// Match elements unmatched by `matcher`
  					while ( i-- ) {
  						if ( (elem = unmatched[i]) ) {
  							seed[i] = !(matches[i] = elem);
  						}
  					}
  				}) :
  				function( elem, context, xml ) {
  					input[0] = elem;
  					matcher( input, null, xml, results );
  					return !results.pop();
  				};
  		}),
  
  		"has": markFunction(function( selector ) {
  			return function( elem ) {
  				return Sizzle( selector, elem ).length > 0;
  			};
  		}),
  
  		"contains": markFunction(function( text ) {
  			return function( elem ) {
  				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  			};
  		}),
  
  		// "Whether an element is represented by a :lang() selector
  		// is based solely on the element's language value
  		// being equal to the identifier C,
  		// or beginning with the identifier C immediately followed by "-".
  		// The matching of C against the element's language value is performed case-insensitively.
  		// The identifier C does not have to be a valid language name."
  		// http://www.w3.org/TR/selectors/#lang-pseudo
  		"lang": markFunction( function( lang ) {
  			// lang value must be a valid identifier
  			if ( !ridentifier.test(lang || "") ) {
  				Sizzle.error( "unsupported lang: " + lang );
  			}
  			lang = lang.replace( runescape, funescape ).toLowerCase();
  			return function( elem ) {
  				var elemLang;
  				do {
  					if ( (elemLang = documentIsHTML ?
  						elem.lang :
  						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
  
  						elemLang = elemLang.toLowerCase();
  						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
  					}
  				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
  				return false;
  			};
  		}),
  
  		// Miscellaneous
  		"target": function( elem ) {
  			var hash = window.location && window.location.hash;
  			return hash && hash.slice( 1 ) === elem.id;
  		},
  
  		"root": function( elem ) {
  			return elem === docElem;
  		},
  
  		"focus": function( elem ) {
  			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
  		},
  
  		// Boolean properties
  		"enabled": function( elem ) {
  			return elem.disabled === false;
  		},
  
  		"disabled": function( elem ) {
  			return elem.disabled === true;
  		},
  
  		"checked": function( elem ) {
  			// In CSS3, :checked should return both checked and selected elements
  			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  			var nodeName = elem.nodeName.toLowerCase();
  			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
  		},
  
  		"selected": function( elem ) {
  			// Accessing this property makes selected-by-default
  			// options in Safari work properly
  			if ( elem.parentNode ) {
  				elem.parentNode.selectedIndex;
  			}
  
  			return elem.selected === true;
  		},
  
  		// Contents
  		"empty": function( elem ) {
  			// http://www.w3.org/TR/selectors/#empty-pseudo
  			// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
  			//   not comment, processing instructions, or others
  			// Thanks to Diego Perini for the nodeName shortcut
  			//   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
  			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  				if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
  					return false;
  				}
  			}
  			return true;
  		},
  
  		"parent": function( elem ) {
  			return !Expr.pseudos["empty"]( elem );
  		},
  
  		// Element/input types
  		"header": function( elem ) {
  			return rheader.test( elem.nodeName );
  		},
  
  		"input": function( elem ) {
  			return rinputs.test( elem.nodeName );
  		},
  
  		"button": function( elem ) {
  			var name = elem.nodeName.toLowerCase();
  			return name === "input" && elem.type === "button" || name === "button";
  		},
  
  		"text": function( elem ) {
  			var attr;
  			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
  			// use getAttribute instead to test this case
  			return elem.nodeName.toLowerCase() === "input" &&
  				elem.type === "text" &&
  				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
  		},
  
  		// Position-in-collection
  		"first": createPositionalPseudo(function() {
  			return [ 0 ];
  		}),
  
  		"last": createPositionalPseudo(function( matchIndexes, length ) {
  			return [ length - 1 ];
  		}),
  
  		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
  			return [ argument < 0 ? argument + length : argument ];
  		}),
  
  		"even": createPositionalPseudo(function( matchIndexes, length ) {
  			var i = 0;
  			for ( ; i < length; i += 2 ) {
  				matchIndexes.push( i );
  			}
  			return matchIndexes;
  		}),
  
  		"odd": createPositionalPseudo(function( matchIndexes, length ) {
  			var i = 1;
  			for ( ; i < length; i += 2 ) {
  				matchIndexes.push( i );
  			}
  			return matchIndexes;
  		}),
  
  		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  			var i = argument < 0 ? argument + length : argument;
  			for ( ; --i >= 0; ) {
  				matchIndexes.push( i );
  			}
  			return matchIndexes;
  		}),
  
  		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  			var i = argument < 0 ? argument + length : argument;
  			for ( ; ++i < length; ) {
  				matchIndexes.push( i );
  			}
  			return matchIndexes;
  		})
  	}
  };
  
  Expr.pseudos["nth"] = Expr.pseudos["eq"];
  
  // Add button/input type pseudos
  for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
  	Expr.pseudos[ i ] = createInputPseudo( i );
  }
  for ( i in { submit: true, reset: true } ) {
  	Expr.pseudos[ i ] = createButtonPseudo( i );
  }
  
  // Easy API for creating new setFilters
  function setFilters() {}
  setFilters.prototype = Expr.filters = Expr.pseudos;
  Expr.setFilters = new setFilters();
  
  function tokenize( selector, parseOnly ) {
  	var matched, match, tokens, type,
  		soFar, groups, preFilters,
  		cached = tokenCache[ selector + " " ];
  
  	if ( cached ) {
  		return parseOnly ? 0 : cached.slice( 0 );
  	}
  
  	soFar = selector;
  	groups = [];
  	preFilters = Expr.preFilter;
  
  	while ( soFar ) {
  
  		// Comma and first run
  		if ( !matched || (match = rcomma.exec( soFar )) ) {
  			if ( match ) {
  				// Don't consume trailing commas as valid
  				soFar = soFar.slice( match[0].length ) || soFar;
  			}
  			groups.push( tokens = [] );
  		}
  
  		matched = false;
  
  		// Combinators
  		if ( (match = rcombinators.exec( soFar )) ) {
  			matched = match.shift();
  			tokens.push({
  				value: matched,
  				// Cast descendant combinators to space
  				type: match[0].replace( rtrim, " " )
  			});
  			soFar = soFar.slice( matched.length );
  		}
  
  		// Filters
  		for ( type in Expr.filter ) {
  			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
  				(match = preFilters[ type ]( match ))) ) {
  				matched = match.shift();
  				tokens.push({
  					value: matched,
  					type: type,
  					matches: match
  				});
  				soFar = soFar.slice( matched.length );
  			}
  		}
  
  		if ( !matched ) {
  			break;
  		}
  	}
  
  	// Return the length of the invalid excess
  	// if we're just parsing
  	// Otherwise, throw an error or return tokens
  	return parseOnly ?
  		soFar.length :
  		soFar ?
  			Sizzle.error( selector ) :
  			// Cache the tokens
  			tokenCache( selector, groups ).slice( 0 );
  }
  
  function toSelector( tokens ) {
  	var i = 0,
  		len = tokens.length,
  		selector = "";
  	for ( ; i < len; i++ ) {
  		selector += tokens[i].value;
  	}
  	return selector;
  }
  
  function addCombinator( matcher, combinator, base ) {
  	var dir = combinator.dir,
  		checkNonElements = base && dir === "parentNode",
  		doneName = done++;
  
  	return combinator.first ?
  		// Check against closest ancestor/preceding element
  		function( elem, context, xml ) {
  			while ( (elem = elem[ dir ]) ) {
  				if ( elem.nodeType === 1 || checkNonElements ) {
  					return matcher( elem, context, xml );
  				}
  			}
  		} :
  
  		// Check against all ancestor/preceding elements
  		function( elem, context, xml ) {
  			var data, cache, outerCache,
  				dirkey = dirruns + " " + doneName;
  
  			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
  			if ( xml ) {
  				while ( (elem = elem[ dir ]) ) {
  					if ( elem.nodeType === 1 || checkNonElements ) {
  						if ( matcher( elem, context, xml ) ) {
  							return true;
  						}
  					}
  				}
  			} else {
  				while ( (elem = elem[ dir ]) ) {
  					if ( elem.nodeType === 1 || checkNonElements ) {
  						outerCache = elem[ expando ] || (elem[ expando ] = {});
  						if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
  							if ( (data = cache[1]) === true || data === cachedruns ) {
  								return data === true;
  							}
  						} else {
  							cache = outerCache[ dir ] = [ dirkey ];
  							cache[1] = matcher( elem, context, xml ) || cachedruns;
  							if ( cache[1] === true ) {
  								return true;
  							}
  						}
  					}
  				}
  			}
  		};
  }
  
  function elementMatcher( matchers ) {
  	return matchers.length > 1 ?
  		function( elem, context, xml ) {
  			var i = matchers.length;
  			while ( i-- ) {
  				if ( !matchers[i]( elem, context, xml ) ) {
  					return false;
  				}
  			}
  			return true;
  		} :
  		matchers[0];
  }
  
  function condense( unmatched, map, filter, context, xml ) {
  	var elem,
  		newUnmatched = [],
  		i = 0,
  		len = unmatched.length,
  		mapped = map != null;
  
  	for ( ; i < len; i++ ) {
  		if ( (elem = unmatched[i]) ) {
  			if ( !filter || filter( elem, context, xml ) ) {
  				newUnmatched.push( elem );
  				if ( mapped ) {
  					map.push( i );
  				}
  			}
  		}
  	}
  
  	return newUnmatched;
  }
  
  function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
  	if ( postFilter && !postFilter[ expando ] ) {
  		postFilter = setMatcher( postFilter );
  	}
  	if ( postFinder && !postFinder[ expando ] ) {
  		postFinder = setMatcher( postFinder, postSelector );
  	}
  	return markFunction(function( seed, results, context, xml ) {
  		var temp, i, elem,
  			preMap = [],
  			postMap = [],
  			preexisting = results.length,
  
  			// Get initial elements from seed or context
  			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
  
  			// Prefilter to get matcher input, preserving a map for seed-results synchronization
  			matcherIn = preFilter && ( seed || !selector ) ?
  				condense( elems, preMap, preFilter, context, xml ) :
  				elems,
  
  			matcherOut = matcher ?
  				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
  				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
  
  					// ...intermediate processing is necessary
  					[] :
  
  					// ...otherwise use results directly
  					results :
  				matcherIn;
  
  		// Find primary matches
  		if ( matcher ) {
  			matcher( matcherIn, matcherOut, context, xml );
  		}
  
  		// Apply postFilter
  		if ( postFilter ) {
  			temp = condense( matcherOut, postMap );
  			postFilter( temp, [], context, xml );
  
  			// Un-match failing elements by moving them back to matcherIn
  			i = temp.length;
  			while ( i-- ) {
  				if ( (elem = temp[i]) ) {
  					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
  				}
  			}
  		}
  
  		if ( seed ) {
  			if ( postFinder || preFilter ) {
  				if ( postFinder ) {
  					// Get the final matcherOut by condensing this intermediate into postFinder contexts
  					temp = [];
  					i = matcherOut.length;
  					while ( i-- ) {
  						if ( (elem = matcherOut[i]) ) {
  							// Restore matcherIn since elem is not yet a final match
  							temp.push( (matcherIn[i] = elem) );
  						}
  					}
  					postFinder( null, (matcherOut = []), temp, xml );
  				}
  
  				// Move matched elements from seed to results to keep them synchronized
  				i = matcherOut.length;
  				while ( i-- ) {
  					if ( (elem = matcherOut[i]) &&
  						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
  
  						seed[temp] = !(results[temp] = elem);
  					}
  				}
  			}
  
  		// Add elements to results, through postFinder if defined
  		} else {
  			matcherOut = condense(
  				matcherOut === results ?
  					matcherOut.splice( preexisting, matcherOut.length ) :
  					matcherOut
  			);
  			if ( postFinder ) {
  				postFinder( null, results, matcherOut, xml );
  			} else {
  				push.apply( results, matcherOut );
  			}
  		}
  	});
  }
  
  function matcherFromTokens( tokens ) {
  	var checkContext, matcher, j,
  		len = tokens.length,
  		leadingRelative = Expr.relative[ tokens[0].type ],
  		implicitRelative = leadingRelative || Expr.relative[" "],
  		i = leadingRelative ? 1 : 0,
  
  		// The foundational matcher ensures that elements are reachable from top-level context(s)
  		matchContext = addCombinator( function( elem ) {
  			return elem === checkContext;
  		}, implicitRelative, true ),
  		matchAnyContext = addCombinator( function( elem ) {
  			return indexOf.call( checkContext, elem ) > -1;
  		}, implicitRelative, true ),
  		matchers = [ function( elem, context, xml ) {
  			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  				(checkContext = context).nodeType ?
  					matchContext( elem, context, xml ) :
  					matchAnyContext( elem, context, xml ) );
  		} ];
  
  	for ( ; i < len; i++ ) {
  		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  		} else {
  			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
  
  			// Return special upon seeing a positional matcher
  			if ( matcher[ expando ] ) {
  				// Find the next relative operator (if any) for proper handling
  				j = ++i;
  				for ( ; j < len; j++ ) {
  					if ( Expr.relative[ tokens[j].type ] ) {
  						break;
  					}
  				}
  				return setMatcher(
  					i > 1 && elementMatcher( matchers ),
  					i > 1 && toSelector(
  						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
  						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
  					).replace( rtrim, "$1" ),
  					matcher,
  					i < j && matcherFromTokens( tokens.slice( i, j ) ),
  					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
  					j < len && toSelector( tokens )
  				);
  			}
  			matchers.push( matcher );
  		}
  	}
  
  	return elementMatcher( matchers );
  }
  
  function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  	// A counter to specify which element is currently being matched
  	var matcherCachedRuns = 0,
  		bySet = setMatchers.length > 0,
  		byElement = elementMatchers.length > 0,
  		superMatcher = function( seed, context, xml, results, expandContext ) {
  			var elem, j, matcher,
  				setMatched = [],
  				matchedCount = 0,
  				i = "0",
  				unmatched = seed && [],
  				outermost = expandContext != null,
  				contextBackup = outermostContext,
  				// We must always have either seed elements or context
  				elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
  				// Use integer dirruns iff this is the outermost matcher
  				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
  
  			if ( outermost ) {
  				outermostContext = context !== document && context;
  				cachedruns = matcherCachedRuns;
  			}
  
  			// Add elements passing elementMatchers directly to results
  			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
  			for ( ; (elem = elems[i]) != null; i++ ) {
  				if ( byElement && elem ) {
  					j = 0;
  					while ( (matcher = elementMatchers[j++]) ) {
  						if ( matcher( elem, context, xml ) ) {
  							results.push( elem );
  							break;
  						}
  					}
  					if ( outermost ) {
  						dirruns = dirrunsUnique;
  						cachedruns = ++matcherCachedRuns;
  					}
  				}
  
  				// Track unmatched elements for set filters
  				if ( bySet ) {
  					// They will have gone through all possible matchers
  					if ( (elem = !matcher && elem) ) {
  						matchedCount--;
  					}
  
  					// Lengthen the array for every element, matched or not
  					if ( seed ) {
  						unmatched.push( elem );
  					}
  				}
  			}
  
  			// Apply set filters to unmatched elements
  			matchedCount += i;
  			if ( bySet && i !== matchedCount ) {
  				j = 0;
  				while ( (matcher = setMatchers[j++]) ) {
  					matcher( unmatched, setMatched, context, xml );
  				}
  
  				if ( seed ) {
  					// Reintegrate element matches to eliminate the need for sorting
  					if ( matchedCount > 0 ) {
  						while ( i-- ) {
  							if ( !(unmatched[i] || setMatched[i]) ) {
  								setMatched[i] = pop.call( results );
  							}
  						}
  					}
  
  					// Discard index placeholder values to get only actual matches
  					setMatched = condense( setMatched );
  				}
  
  				// Add matches to results
  				push.apply( results, setMatched );
  
  				// Seedless set matches succeeding multiple successful matchers stipulate sorting
  				if ( outermost && !seed && setMatched.length > 0 &&
  					( matchedCount + setMatchers.length ) > 1 ) {
  
  					Sizzle.uniqueSort( results );
  				}
  			}
  
  			// Override manipulation of globals by nested matchers
  			if ( outermost ) {
  				dirruns = dirrunsUnique;
  				outermostContext = contextBackup;
  			}
  
  			return unmatched;
  		};
  
  	return bySet ?
  		markFunction( superMatcher ) :
  		superMatcher;
  }
  
  compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
  	var i,
  		setMatchers = [],
  		elementMatchers = [],
  		cached = compilerCache[ selector + " " ];
  
  	if ( !cached ) {
  		// Generate a function of recursive functions that can be used to check each element
  		if ( !group ) {
  			group = tokenize( selector );
  		}
  		i = group.length;
  		while ( i-- ) {
  			cached = matcherFromTokens( group[i] );
  			if ( cached[ expando ] ) {
  				setMatchers.push( cached );
  			} else {
  				elementMatchers.push( cached );
  			}
  		}
  
  		// Cache the compiled function
  		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
  	}
  	return cached;
  };
  
  function multipleContexts( selector, contexts, results ) {
  	var i = 0,
  		len = contexts.length;
  	for ( ; i < len; i++ ) {
  		Sizzle( selector, contexts[i], results );
  	}
  	return results;
  }
  
  function select( selector, context, results, seed ) {
  	var i, tokens, token, type, find,
  		match = tokenize( selector );
  
  	if ( !seed ) {
  		// Try to minimize operations if there is only one group
  		if ( match.length === 1 ) {
  
  			// Take a shortcut and set the context if the root selector is an ID
  			tokens = match[0] = match[0].slice( 0 );
  			if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
  					support.getById && context.nodeType === 9 && documentIsHTML &&
  					Expr.relative[ tokens[1].type ] ) {
  
  				context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
  				if ( !context ) {
  					return results;
  				}
  				selector = selector.slice( tokens.shift().value.length );
  			}
  
  			// Fetch a seed set for right-to-left matching
  			i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
  			while ( i-- ) {
  				token = tokens[i];
  
  				// Abort if we hit a combinator
  				if ( Expr.relative[ (type = token.type) ] ) {
  					break;
  				}
  				if ( (find = Expr.find[ type ]) ) {
  					// Search, expanding context for leading sibling combinators
  					if ( (seed = find(
  						token.matches[0].replace( runescape, funescape ),
  						rsibling.test( tokens[0].type ) && context.parentNode || context
  					)) ) {
  
  						// If seed is empty or no tokens remain, we can return early
  						tokens.splice( i, 1 );
  						selector = seed.length && toSelector( tokens );
  						if ( !selector ) {
  							push.apply( results, seed );
  							return results;
  						}
  
  						break;
  					}
  				}
  			}
  		}
  	}
  
  	// Compile and execute a filtering function
  	// Provide `match` to avoid retokenization if we modified the selector above
  	compile( selector, match )(
  		seed,
  		context,
  		!documentIsHTML,
  		results,
  		rsibling.test( selector )
  	);
  	return results;
  }
  
  // One-time assignments
  
  // Sort stability
  support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  
  // Support: Chrome<14
  // Always assume duplicates if they aren't passed to the comparison function
  support.detectDuplicates = hasDuplicate;
  
  // Initialize against the default document
  setDocument();
  
  // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
  // Detached nodes confoundingly follow *each other*
  support.sortDetached = assert(function( div1 ) {
  	// Should return 1, but returns 4 (following)
  	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
  });
  
  // Support: IE<8
  // Prevent attribute/property "interpolation"
  // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
  if ( !assert(function( div ) {
  	div.innerHTML = "<a href='#'></a>";
  	return div.firstChild.getAttribute("href") === "#" ;
  }) ) {
  	addHandle( "type|href|height|width", function( elem, name, isXML ) {
  		if ( !isXML ) {
  			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
  		}
  	});
  }
  
  // Support: IE<9
  // Use defaultValue in place of getAttribute("value")
  if ( !support.attributes || !assert(function( div ) {
  	div.innerHTML = "<input/>";
  	div.firstChild.setAttribute( "value", "" );
  	return div.firstChild.getAttribute( "value" ) === "";
  }) ) {
  	addHandle( "value", function( elem, name, isXML ) {
  		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
  			return elem.defaultValue;
  		}
  	});
  }
  
  // Support: IE<9
  // Use getAttributeNode to fetch booleans when getAttribute lies
  if ( !assert(function( div ) {
  	return div.getAttribute("disabled") == null;
  }) ) {
  	addHandle( booleans, function( elem, name, isXML ) {
  		var val;
  		if ( !isXML ) {
  			return (val = elem.getAttributeNode( name )) && val.specified ?
  				val.value :
  				elem[ name ] === true ? name.toLowerCase() : null;
  		}
  	});
  }
  
  jQuery.find = Sizzle;
  jQuery.expr = Sizzle.selectors;
  jQuery.expr[":"] = jQuery.expr.pseudos;
  jQuery.unique = Sizzle.uniqueSort;
  jQuery.text = Sizzle.getText;
  jQuery.isXMLDoc = Sizzle.isXML;
  jQuery.contains = Sizzle.contains;
  
  
  })( window );
  // String to Object options format cache
  var optionsCache = {};
  
  // Convert String-formatted options into Object-formatted ones and store in cache
  function createOptions( options ) {
  	var object = optionsCache[ options ] = {};
  	jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
  		object[ flag ] = true;
  	});
  	return object;
  }
  
  /*
   * Create a callback list using the following parameters:
   *
   *	options: an optional list of space-separated options that will change how
   *			the callback list behaves or a more traditional option object
   *
   * By default a callback list will act like an event callback list and can be
   * "fired" multiple times.
   *
   * Possible options:
   *
   *	once:			will ensure the callback list can only be fired once (like a Deferred)
   *
   *	memory:			will keep track of previous values and will call any callback added
   *					after the list has been fired right away with the latest "memorized"
   *					values (like a Deferred)
   *
   *	unique:			will ensure a callback can only be added once (no duplicate in the list)
   *
   *	stopOnFalse:	interrupt callings when a callback returns false
   *
   */
  jQuery.Callbacks = function( options ) {
  
  	// Convert options from String-formatted to Object-formatted if needed
  	// (we check in cache first)
  	options = typeof options === "string" ?
  		( optionsCache[ options ] || createOptions( options ) ) :
  		jQuery.extend( {}, options );
  
  	var // Last fire value (for non-forgettable lists)
  		memory,
  		// Flag to know if list was already fired
  		fired,
  		// Flag to know if list is currently firing
  		firing,
  		// First callback to fire (used internally by add and fireWith)
  		firingStart,
  		// End of the loop when firing
  		firingLength,
  		// Index of currently firing callback (modified by remove if needed)
  		firingIndex,
  		// Actual callback list
  		list = [],
  		// Stack of fire calls for repeatable lists
  		stack = !options.once && [],
  		// Fire callbacks
  		fire = function( data ) {
  			memory = options.memory && data;
  			fired = true;
  			firingIndex = firingStart || 0;
  			firingStart = 0;
  			firingLength = list.length;
  			firing = true;
  			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
  				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
  					memory = false; // To prevent further calls using add
  					break;
  				}
  			}
  			firing = false;
  			if ( list ) {
  				if ( stack ) {
  					if ( stack.length ) {
  						fire( stack.shift() );
  					}
  				} else if ( memory ) {
  					list = [];
  				} else {
  					self.disable();
  				}
  			}
  		},
  		// Actual Callbacks object
  		self = {
  			// Add a callback or a collection of callbacks to the list
  			add: function() {
  				if ( list ) {
  					// First, we save the current length
  					var start = list.length;
  					(function add( args ) {
  						jQuery.each( args, function( _, arg ) {
  							var type = jQuery.type( arg );
  							if ( type === "function" ) {
  								if ( !options.unique || !self.has( arg ) ) {
  									list.push( arg );
  								}
  							} else if ( arg && arg.length && type !== "string" ) {
  								// Inspect recursively
  								add( arg );
  							}
  						});
  					})( arguments );
  					// Do we need to add the callbacks to the
  					// current firing batch?
  					if ( firing ) {
  						firingLength = list.length;
  					// With memory, if we're not firing then
  					// we should call right away
  					} else if ( memory ) {
  						firingStart = start;
  						fire( memory );
  					}
  				}
  				return this;
  			},
  			// Remove a callback from the list
  			remove: function() {
  				if ( list ) {
  					jQuery.each( arguments, function( _, arg ) {
  						var index;
  						while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
  							list.splice( index, 1 );
  							// Handle firing indexes
  							if ( firing ) {
  								if ( index <= firingLength ) {
  									firingLength--;
  								}
  								if ( index <= firingIndex ) {
  									firingIndex--;
  								}
  							}
  						}
  					});
  				}
  				return this;
  			},
  			// Check if a given callback is in the list.
  			// If no argument is given, return whether or not list has callbacks attached.
  			has: function( fn ) {
  				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
  			},
  			// Remove all callbacks from the list
  			empty: function() {
  				list = [];
  				firingLength = 0;
  				return this;
  			},
  			// Have the list do nothing anymore
  			disable: function() {
  				list = stack = memory = undefined;
  				return this;
  			},
  			// Is it disabled?
  			disabled: function() {
  				return !list;
  			},
  			// Lock the list in its current state
  			lock: function() {
  				stack = undefined;
  				if ( !memory ) {
  					self.disable();
  				}
  				return this;
  			},
  			// Is it locked?
  			locked: function() {
  				return !stack;
  			},
  			// Call all callbacks with the given context and arguments
  			fireWith: function( context, args ) {
  				if ( list && ( !fired || stack ) ) {
  					args = args || [];
  					args = [ context, args.slice ? args.slice() : args ];
  					if ( firing ) {
  						stack.push( args );
  					} else {
  						fire( args );
  					}
  				}
  				return this;
  			},
  			// Call all the callbacks with the given arguments
  			fire: function() {
  				self.fireWith( this, arguments );
  				return this;
  			},
  			// To know if the callbacks have already been called at least once
  			fired: function() {
  				return !!fired;
  			}
  		};
  
  	return self;
  };
  jQuery.extend({
  
  	Deferred: function( func ) {
  		var tuples = [
  				// action, add listener, listener list, final state
  				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
  				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
  				[ "notify", "progress", jQuery.Callbacks("memory") ]
  			],
  			state = "pending",
  			promise = {
  				state: function() {
  					return state;
  				},
  				always: function() {
  					deferred.done( arguments ).fail( arguments );
  					return this;
  				},
  				then: function( /* fnDone, fnFail, fnProgress */ ) {
  					var fns = arguments;
  					return jQuery.Deferred(function( newDefer ) {
  						jQuery.each( tuples, function( i, tuple ) {
  							var action = tuple[ 0 ],
  								fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
  							// deferred[ done | fail | progress ] for forwarding actions to newDefer
  							deferred[ tuple[1] ](function() {
  								var returned = fn && fn.apply( this, arguments );
  								if ( returned && jQuery.isFunction( returned.promise ) ) {
  									returned.promise()
  										.done( newDefer.resolve )
  										.fail( newDefer.reject )
  										.progress( newDefer.notify );
  								} else {
  									newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
  								}
  							});
  						});
  						fns = null;
  					}).promise();
  				},
  				// Get a promise for this deferred
  				// If obj is provided, the promise aspect is added to the object
  				promise: function( obj ) {
  					return obj != null ? jQuery.extend( obj, promise ) : promise;
  				}
  			},
  			deferred = {};
  
  		// Keep pipe for back-compat
  		promise.pipe = promise.then;
  
  		// Add list-specific methods
  		jQuery.each( tuples, function( i, tuple ) {
  			var list = tuple[ 2 ],
  				stateString = tuple[ 3 ];
  
  			// promise[ done | fail | progress ] = list.add
  			promise[ tuple[1] ] = list.add;
  
  			// Handle state
  			if ( stateString ) {
  				list.add(function() {
  					// state = [ resolved | rejected ]
  					state = stateString;
  
  				// [ reject_list | resolve_list ].disable; progress_list.lock
  				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
  			}
  
  			// deferred[ resolve | reject | notify ]
  			deferred[ tuple[0] ] = function() {
  				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
  				return this;
  			};
  			deferred[ tuple[0] + "With" ] = list.fireWith;
  		});
  
  		// Make the deferred a promise
  		promise.promise( deferred );
  
  		// Call given func if any
  		if ( func ) {
  			func.call( deferred, deferred );
  		}
  
  		// All done!
  		return deferred;
  	},
  
  	// Deferred helper
  	when: function( subordinate /* , ..., subordinateN */ ) {
  		var i = 0,
  			resolveValues = core_slice.call( arguments ),
  			length = resolveValues.length,
  
  			// the count of uncompleted subordinates
  			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
  
  			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
  			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
  
  			// Update function for both resolve and progress values
  			updateFunc = function( i, contexts, values ) {
  				return function( value ) {
  					contexts[ i ] = this;
  					values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
  					if( values === progressValues ) {
  						deferred.notifyWith( contexts, values );
  					} else if ( !( --remaining ) ) {
  						deferred.resolveWith( contexts, values );
  					}
  				};
  			},
  
  			progressValues, progressContexts, resolveContexts;
  
  		// add listeners to Deferred subordinates; treat others as resolved
  		if ( length > 1 ) {
  			progressValues = new Array( length );
  			progressContexts = new Array( length );
  			resolveContexts = new Array( length );
  			for ( ; i < length; i++ ) {
  				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
  					resolveValues[ i ].promise()
  						.done( updateFunc( i, resolveContexts, resolveValues ) )
  						.fail( deferred.reject )
  						.progress( updateFunc( i, progressContexts, progressValues ) );
  				} else {
  					--remaining;
  				}
  			}
  		}
  
  		// if we're not waiting on anything, resolve the master
  		if ( !remaining ) {
  			deferred.resolveWith( resolveContexts, resolveValues );
  		}
  
  		return deferred.promise();
  	}
  });
  jQuery.support = (function( support ) {
  	var input = document.createElement("input"),
  		fragment = document.createDocumentFragment(),
  		div = document.createElement("div"),
  		select = document.createElement("select"),
  		opt = select.appendChild( document.createElement("option") );
  
  	// Finish early in limited environments
  	if ( !input.type ) {
  		return support;
  	}
  
  	input.type = "checkbox";
  
  	// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
  	// Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)
  	support.checkOn = input.value !== "";
  
  	// Must access the parent to make an option select properly
  	// Support: IE9, IE10
  	support.optSelected = opt.selected;
  
  	// Will be defined later
  	support.reliableMarginRight = true;
  	support.boxSizingReliable = true;
  	support.pixelPosition = false;
  
  	// Make sure checked status is properly cloned
  	// Support: IE9, IE10
  	input.checked = true;
  	support.noCloneChecked = input.cloneNode( true ).checked;
  
  	// Make sure that the options inside disabled selects aren't marked as disabled
  	// (WebKit marks them as disabled)
  	select.disabled = true;
  	support.optDisabled = !opt.disabled;
  
  	// Check if an input maintains its value after becoming a radio
  	// Support: IE9, IE10
  	input = document.createElement("input");
  	input.value = "t";
  	input.type = "radio";
  	support.radioValue = input.value === "t";
  
  	// #11217 - WebKit loses check when the name is after the checked attribute
  	input.setAttribute( "checked", "t" );
  	input.setAttribute( "name", "t" );
  
  	fragment.appendChild( input );
  
  	// Support: Safari 5.1, Android 4.x, Android 2.3
  	// old WebKit doesn't clone checked state correctly in fragments
  	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
  
  	// Support: Firefox, Chrome, Safari
  	// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
  	support.focusinBubbles = "onfocusin" in window;
  
  	div.style.backgroundClip = "content-box";
  	div.cloneNode( true ).style.backgroundClip = "";
  	support.clearCloneStyle = div.style.backgroundClip === "content-box";
  
  	// Run tests that need a body at doc ready
  	jQuery(function() {
  		var container, marginDiv,
  			// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).
  			divReset = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",
  			body = document.getElementsByTagName("body")[ 0 ];
  
  		if ( !body ) {
  			// Return for frameset docs that don't have a body
  			return;
  		}
  
  		container = document.createElement("div");
  		container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
  
  		// Check box-sizing and margin behavior.
  		body.appendChild( container ).appendChild( div );
  		div.innerHTML = "";
  		// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).
  		div.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%";
  
  		// Workaround failing boxSizing test due to offsetWidth returning wrong value
  		// with some non-1 values of body zoom, ticket #13543
  		jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {
  			support.boxSizing = div.offsetWidth === 4;
  		});
  
  		// Use window.getComputedStyle because jsdom on node.js will break without it.
  		if ( window.getComputedStyle ) {
  			support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
  			support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
  
  			// Support: Android 2.3
  			// Check if div with explicit width and no margin-right incorrectly
  			// gets computed margin-right based on width of container. (#3333)
  			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  			marginDiv = div.appendChild( document.createElement("div") );
  			marginDiv.style.cssText = div.style.cssText = divReset;
  			marginDiv.style.marginRight = marginDiv.style.width = "0";
  			div.style.width = "1px";
  
  			support.reliableMarginRight =
  				!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
  		}
  
  		body.removeChild( container );
  	});
  
  	return support;
  })( {} );
  
  /*
  	Implementation Summary
  
  	1. Enforce API surface and semantic compatibility with 1.9.x branch
  	2. Improve the module's maintainability by reducing the storage
  		paths to a single mechanism.
  	3. Use the same single mechanism to support "private" and "user" data.
  	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
  	5. Avoid exposing implementation details on user objects (eg. expando properties)
  	6. Provide a clear path for implementation upgrade to WeakMap in 2014
  */
  var data_user, data_priv,
  	rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
  	rmultiDash = /([A-Z])/g;
  
  function Data() {
  	// Support: Android < 4,
  	// Old WebKit does not have Object.preventExtensions/freeze method,
  	// return new empty object instead with no [[set]] accessor
  	Object.defineProperty( this.cache = {}, 0, {
  		get: function() {
  			return {};
  		}
  	});
  
  	this.expando = jQuery.expando + Math.random();
  }
  
  Data.uid = 1;
  
  Data.accepts = function( owner ) {
  	// Accepts only:
  	//  - Node
  	//    - Node.ELEMENT_NODE
  	//    - Node.DOCUMENT_NODE
  	//  - Object
  	//    - Any
  	return owner.nodeType ?
  		owner.nodeType === 1 || owner.nodeType === 9 : true;
  };
  
  Data.prototype = {
  	key: function( owner ) {
  		// We can accept data for non-element nodes in modern browsers,
  		// but we should not, see #8335.
  		// Always return the key for a frozen object.
  		if ( !Data.accepts( owner ) ) {
  			return 0;
  		}
  
  		var descriptor = {},
  			// Check if the owner object already has a cache key
  			unlock = owner[ this.expando ];
  
  		// If not, create one
  		if ( !unlock ) {
  			unlock = Data.uid++;
  
  			// Secure it in a non-enumerable, non-writable property
  			try {
  				descriptor[ this.expando ] = { value: unlock };
  				Object.defineProperties( owner, descriptor );
  
  			// Support: Android < 4
  			// Fallback to a less secure definition
  			} catch ( e ) {
  				descriptor[ this.expando ] = unlock;
  				jQuery.extend( owner, descriptor );
  			}
  		}
  
  		// Ensure the cache object
  		if ( !this.cache[ unlock ] ) {
  			this.cache[ unlock ] = {};
  		}
  
  		return unlock;
  	},
  	set: function( owner, data, value ) {
  		var prop,
  			// There may be an unlock assigned to this node,
  			// if there is no entry for this "owner", create one inline
  			// and set the unlock as though an owner entry had always existed
  			unlock = this.key( owner ),
  			cache = this.cache[ unlock ];
  
  		// Handle: [ owner, key, value ] args
  		if ( typeof data === "string" ) {
  			cache[ data ] = value;
  
  		// Handle: [ owner, { properties } ] args
  		} else {
  			// Fresh assignments by object are shallow copied
  			if ( jQuery.isEmptyObject( cache ) ) {
  				jQuery.extend( this.cache[ unlock ], data );
  			// Otherwise, copy the properties one-by-one to the cache object
  			} else {
  				for ( prop in data ) {
  					cache[ prop ] = data[ prop ];
  				}
  			}
  		}
  		return cache;
  	},
  	get: function( owner, key ) {
  		// Either a valid cache is found, or will be created.
  		// New caches will be created and the unlock returned,
  		// allowing direct access to the newly created
  		// empty data object. A valid owner object must be provided.
  		var cache = this.cache[ this.key( owner ) ];
  
  		return key === undefined ?
  			cache : cache[ key ];
  	},
  	access: function( owner, key, value ) {
  		var stored;
  		// In cases where either:
  		//
  		//   1. No key was specified
  		//   2. A string key was specified, but no value provided
  		//
  		// Take the "read" path and allow the get method to determine
  		// which value to return, respectively either:
  		//
  		//   1. The entire cache object
  		//   2. The data stored at the key
  		//
  		if ( key === undefined ||
  				((key && typeof key === "string") && value === undefined) ) {
  
  			stored = this.get( owner, key );
  
  			return stored !== undefined ?
  				stored : this.get( owner, jQuery.camelCase(key) );
  		}
  
  		// [*]When the key is not a string, or both a key and value
  		// are specified, set or extend (existing objects) with either:
  		//
  		//   1. An object of properties
  		//   2. A key and value
  		//
  		this.set( owner, key, value );
  
  		// Since the "set" path can have two possible entry points
  		// return the expected data based on which path was taken[*]
  		return value !== undefined ? value : key;
  	},
  	remove: function( owner, key ) {
  		var i, name, camel,
  			unlock = this.key( owner ),
  			cache = this.cache[ unlock ];
  
  		if ( key === undefined ) {
  			this.cache[ unlock ] = {};
  
  		} else {
  			// Support array or space separated string of keys
  			if ( jQuery.isArray( key ) ) {
  				// If "name" is an array of keys...
  				// When data is initially created, via ("key", "val") signature,
  				// keys will be converted to camelCase.
  				// Since there is no way to tell _how_ a key was added, remove
  				// both plain key and camelCase key. #12786
  				// This will only penalize the array argument path.
  				name = key.concat( key.map( jQuery.camelCase ) );
  			} else {
  				camel = jQuery.camelCase( key );
  				// Try the string as a key before any manipulation
  				if ( key in cache ) {
  					name = [ key, camel ];
  				} else {
  					// If a key with the spaces exists, use it.
  					// Otherwise, create an array by matching non-whitespace
  					name = camel;
  					name = name in cache ?
  						[ name ] : ( name.match( core_rnotwhite ) || [] );
  				}
  			}
  
  			i = name.length;
  			while ( i-- ) {
  				delete cache[ name[ i ] ];
  			}
  		}
  	},
  	hasData: function( owner ) {
  		return !jQuery.isEmptyObject(
  			this.cache[ owner[ this.expando ] ] || {}
  		);
  	},
  	discard: function( owner ) {
  		if ( owner[ this.expando ] ) {
  			delete this.cache[ owner[ this.expando ] ];
  		}
  	}
  };
  
  // These may be used throughout the jQuery core codebase
  data_user = new Data();
  data_priv = new Data();
  
  
  jQuery.extend({
  	acceptData: Data.accepts,
  
  	hasData: function( elem ) {
  		return data_user.hasData( elem ) || data_priv.hasData( elem );
  	},
  
  	data: function( elem, name, data ) {
  		return data_user.access( elem, name, data );
  	},
  
  	removeData: function( elem, name ) {
  		data_user.remove( elem, name );
  	},
  
  	// TODO: Now that all calls to _data and _removeData have been replaced
  	// with direct calls to data_priv methods, these can be deprecated.
  	_data: function( elem, name, data ) {
  		return data_priv.access( elem, name, data );
  	},
  
  	_removeData: function( elem, name ) {
  		data_priv.remove( elem, name );
  	}
  });
  
  jQuery.fn.extend({
  	data: function( key, value ) {
  		var attrs, name,
  			elem = this[ 0 ],
  			i = 0,
  			data = null;
  
  		// Gets all values
  		if ( key === undefined ) {
  			if ( this.length ) {
  				data = data_user.get( elem );
  
  				if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
  					attrs = elem.attributes;
  					for ( ; i < attrs.length; i++ ) {
  						name = attrs[ i ].name;
  
  						if ( name.indexOf( "data-" ) === 0 ) {
  							name = jQuery.camelCase( name.slice(5) );
  							dataAttr( elem, name, data[ name ] );
  						}
  					}
  					data_priv.set( elem, "hasDataAttrs", true );
  				}
  			}
  
  			return data;
  		}
  
  		// Sets multiple values
  		if ( typeof key === "object" ) {
  			return this.each(function() {
  				data_user.set( this, key );
  			});
  		}
  
  		return jQuery.access( this, function( value ) {
  			var data,
  				camelKey = jQuery.camelCase( key );
  
  			// The calling jQuery object (element matches) is not empty
  			// (and therefore has an element appears at this[ 0 ]) and the
  			// `value` parameter was not undefined. An empty jQuery object
  			// will result in `undefined` for elem = this[ 0 ] which will
  			// throw an exception if an attempt to read a data cache is made.
  			if ( elem && value === undefined ) {
  				// Attempt to get data from the cache
  				// with the key as-is
  				data = data_user.get( elem, key );
  				if ( data !== undefined ) {
  					return data;
  				}
  
  				// Attempt to get data from the cache
  				// with the key camelized
  				data = data_user.get( elem, camelKey );
  				if ( data !== undefined ) {
  					return data;
  				}
  
  				// Attempt to "discover" the data in
  				// HTML5 custom data-* attrs
  				data = dataAttr( elem, camelKey, undefined );
  				if ( data !== undefined ) {
  					return data;
  				}
  
  				// We tried really hard, but the data doesn't exist.
  				return;
  			}
  
  			// Set the data...
  			this.each(function() {
  				// First, attempt to store a copy or reference of any
  				// data that might've been store with a camelCased key.
  				var data = data_user.get( this, camelKey );
  
  				// For HTML5 data-* attribute interop, we have to
  				// store property names with dashes in a camelCase form.
  				// This might not apply to all properties...*
  				data_user.set( this, camelKey, value );
  
  				// *... In the case of properties that might _actually_
  				// have dashes, we need to also store a copy of that
  				// unchanged property.
  				if ( key.indexOf("-") !== -1 && data !== undefined ) {
  					data_user.set( this, key, value );
  				}
  			});
  		}, null, value, arguments.length > 1, null, true );
  	},
  
  	removeData: function( key ) {
  		return this.each(function() {
  			data_user.remove( this, key );
  		});
  	}
  });
  
  function dataAttr( elem, key, data ) {
  	var name;
  
  	// If nothing was found internally, try to fetch any
  	// data from the HTML5 data-* attribute
  	if ( data === undefined && elem.nodeType === 1 ) {
  		name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
  		data = elem.getAttribute( name );
  
  		if ( typeof data === "string" ) {
  			try {
  				data = data === "true" ? true :
  					data === "false" ? false :
  					data === "null" ? null :
  					// Only convert to a number if it doesn't change the string
  					+data + "" === data ? +data :
  					rbrace.test( data ) ? JSON.parse( data ) :
  					data;
  			} catch( e ) {}
  
  			// Make sure we set the data so it isn't changed later
  			data_user.set( elem, key, data );
  		} else {
  			data = undefined;
  		}
  	}
  	return data;
  }
  jQuery.extend({
  	queue: function( elem, type, data ) {
  		var queue;
  
  		if ( elem ) {
  			type = ( type || "fx" ) + "queue";
  			queue = data_priv.get( elem, type );
  
  			// Speed up dequeue by getting out quickly if this is just a lookup
  			if ( data ) {
  				if ( !queue || jQuery.isArray( data ) ) {
  					queue = data_priv.access( elem, type, jQuery.makeArray(data) );
  				} else {
  					queue.push( data );
  				}
  			}
  			return queue || [];
  		}
  	},
  
  	dequeue: function( elem, type ) {
  		type = type || "fx";
  
  		var queue = jQuery.queue( elem, type ),
  			startLength = queue.length,
  			fn = queue.shift(),
  			hooks = jQuery._queueHooks( elem, type ),
  			next = function() {
  				jQuery.dequeue( elem, type );
  			};
  
  		// If the fx queue is dequeued, always remove the progress sentinel
  		if ( fn === "inprogress" ) {
  			fn = queue.shift();
  			startLength--;
  		}
  
  		if ( fn ) {
  
  			// Add a progress sentinel to prevent the fx queue from being
  			// automatically dequeued
  			if ( type === "fx" ) {
  				queue.unshift( "inprogress" );
  			}
  
  			// clear up the last queue stop function
  			delete hooks.stop;
  			fn.call( elem, next, hooks );
  		}
  
  		if ( !startLength && hooks ) {
  			hooks.empty.fire();
  		}
  	},
  
  	// not intended for public consumption - generates a queueHooks object, or returns the current one
  	_queueHooks: function( elem, type ) {
  		var key = type + "queueHooks";
  		return data_priv.get( elem, key ) || data_priv.access( elem, key, {
  			empty: jQuery.Callbacks("once memory").add(function() {
  				data_priv.remove( elem, [ type + "queue", key ] );
  			})
  		});
  	}
  });
  
  jQuery.fn.extend({
  	queue: function( type, data ) {
  		var setter = 2;
  
  		if ( typeof type !== "string" ) {
  			data = type;
  			type = "fx";
  			setter--;
  		}
  
  		if ( arguments.length < setter ) {
  			return jQuery.queue( this[0], type );
  		}
  
  		return data === undefined ?
  			this :
  			this.each(function() {
  				var queue = jQuery.queue( this, type, data );
  
  				// ensure a hooks for this queue
  				jQuery._queueHooks( this, type );
  
  				if ( type === "fx" && queue[0] !== "inprogress" ) {
  					jQuery.dequeue( this, type );
  				}
  			});
  	},
  	dequeue: function( type ) {
  		return this.each(function() {
  			jQuery.dequeue( this, type );
  		});
  	},
  	// Based off of the plugin by Clint Helfers, with permission.
  	// http://blindsignals.com/index.php/2009/07/jquery-delay/
  	delay: function( time, type ) {
  		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
  		type = type || "fx";
  
  		return this.queue( type, function( next, hooks ) {
  			var timeout = setTimeout( next, time );
  			hooks.stop = function() {
  				clearTimeout( timeout );
  			};
  		});
  	},
  	clearQueue: function( type ) {
  		return this.queue( type || "fx", [] );
  	},
  	// Get a promise resolved when queues of a certain type
  	// are emptied (fx is the type by default)
  	promise: function( type, obj ) {
  		var tmp,
  			count = 1,
  			defer = jQuery.Deferred(),
  			elements = this,
  			i = this.length,
  			resolve = function() {
  				if ( !( --count ) ) {
  					defer.resolveWith( elements, [ elements ] );
  				}
  			};
  
  		if ( typeof type !== "string" ) {
  			obj = type;
  			type = undefined;
  		}
  		type = type || "fx";
  
  		while( i-- ) {
  			tmp = data_priv.get( elements[ i ], type + "queueHooks" );
  			if ( tmp && tmp.empty ) {
  				count++;
  				tmp.empty.add( resolve );
  			}
  		}
  		resolve();
  		return defer.promise( obj );
  	}
  });
  var nodeHook, boolHook,
  	rclass = /[\t\r\n\f]/g,
  	rreturn = /\r/g,
  	rfocusable = /^(?:input|select|textarea|button)$/i;
  
  jQuery.fn.extend({
  	attr: function( name, value ) {
  		return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
  	},
  
  	removeAttr: function( name ) {
  		return this.each(function() {
  			jQuery.removeAttr( this, name );
  		});
  	},
  
  	prop: function( name, value ) {
  		return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
  	},
  
  	removeProp: function( name ) {
  		return this.each(function() {
  			delete this[ jQuery.propFix[ name ] || name ];
  		});
  	},
  
  	addClass: function( value ) {
  		var classes, elem, cur, clazz, j,
  			i = 0,
  			len = this.length,
  			proceed = typeof value === "string" && value;
  
  		if ( jQuery.isFunction( value ) ) {
  			return this.each(function( j ) {
  				jQuery( this ).addClass( value.call( this, j, this.className ) );
  			});
  		}
  
  		if ( proceed ) {
  			// The disjunction here is for better compressibility (see removeClass)
  			classes = ( value || "" ).match( core_rnotwhite ) || [];
  
  			for ( ; i < len; i++ ) {
  				elem = this[ i ];
  				cur = elem.nodeType === 1 && ( elem.className ?
  					( " " + elem.className + " " ).replace( rclass, " " ) :
  					" "
  				);
  
  				if ( cur ) {
  					j = 0;
  					while ( (clazz = classes[j++]) ) {
  						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
  							cur += clazz + " ";
  						}
  					}
  					elem.className = jQuery.trim( cur );
  
  				}
  			}
  		}
  
  		return this;
  	},
  
  	removeClass: function( value ) {
  		var classes, elem, cur, clazz, j,
  			i = 0,
  			len = this.length,
  			proceed = arguments.length === 0 || typeof value === "string" && value;
  
  		if ( jQuery.isFunction( value ) ) {
  			return this.each(function( j ) {
  				jQuery( this ).removeClass( value.call( this, j, this.className ) );
  			});
  		}
  		if ( proceed ) {
  			classes = ( value || "" ).match( core_rnotwhite ) || [];
  
  			for ( ; i < len; i++ ) {
  				elem = this[ i ];
  				// This expression is here for better compressibility (see addClass)
  				cur = elem.nodeType === 1 && ( elem.className ?
  					( " " + elem.className + " " ).replace( rclass, " " ) :
  					""
  				);
  
  				if ( cur ) {
  					j = 0;
  					while ( (clazz = classes[j++]) ) {
  						// Remove *all* instances
  						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
  							cur = cur.replace( " " + clazz + " ", " " );
  						}
  					}
  					elem.className = value ? jQuery.trim( cur ) : "";
  				}
  			}
  		}
  
  		return this;
  	},
  
  	toggleClass: function( value, stateVal ) {
  		var type = typeof value;
  
  		if ( typeof stateVal === "boolean" && type === "string" ) {
  			return stateVal ? this.addClass( value ) : this.removeClass( value );
  		}
  
  		if ( jQuery.isFunction( value ) ) {
  			return this.each(function( i ) {
  				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
  			});
  		}
  
  		return this.each(function() {
  			if ( type === "string" ) {
  				// toggle individual class names
  				var className,
  					i = 0,
  					self = jQuery( this ),
  					classNames = value.match( core_rnotwhite ) || [];
  
  				while ( (className = classNames[ i++ ]) ) {
  					// check each className given, space separated list
  					if ( self.hasClass( className ) ) {
  						self.removeClass( className );
  					} else {
  						self.addClass( className );
  					}
  				}
  
  			// Toggle whole class name
  			} else if ( type === core_strundefined || type === "boolean" ) {
  				if ( this.className ) {
  					// store className if set
  					data_priv.set( this, "__className__", this.className );
  				}
  
  				// If the element has a class name or if we're passed "false",
  				// then remove the whole classname (if there was one, the above saved it).
  				// Otherwise bring back whatever was previously saved (if anything),
  				// falling back to the empty string if nothing was stored.
  				this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
  			}
  		});
  	},
  
  	hasClass: function( selector ) {
  		var className = " " + selector + " ",
  			i = 0,
  			l = this.length;
  		for ( ; i < l; i++ ) {
  			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
  				return true;
  			}
  		}
  
  		return false;
  	},
  
  	val: function( value ) {
  		var hooks, ret, isFunction,
  			elem = this[0];
  
  		if ( !arguments.length ) {
  			if ( elem ) {
  				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
  
  				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
  					return ret;
  				}
  
  				ret = elem.value;
  
  				return typeof ret === "string" ?
  					// handle most common string cases
  					ret.replace(rreturn, "") :
  					// handle cases where value is null/undef or number
  					ret == null ? "" : ret;
  			}
  
  			return;
  		}
  
  		isFunction = jQuery.isFunction( value );
  
  		return this.each(function( i ) {
  			var val;
  
  			if ( this.nodeType !== 1 ) {
  				return;
  			}
  
  			if ( isFunction ) {
  				val = value.call( this, i, jQuery( this ).val() );
  			} else {
  				val = value;
  			}
  
  			// Treat null/undefined as ""; convert numbers to string
  			if ( val == null ) {
  				val = "";
  			} else if ( typeof val === "number" ) {
  				val += "";
  			} else if ( jQuery.isArray( val ) ) {
  				val = jQuery.map(val, function ( value ) {
  					return value == null ? "" : value + "";
  				});
  			}
  
  			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
  
  			// If set returns undefined, fall back to normal setting
  			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
  				this.value = val;
  			}
  		});
  	}
  });
  
  jQuery.extend({
  	valHooks: {
  		option: {
  			get: function( elem ) {
  				// attributes.value is undefined in Blackberry 4.7 but
  				// uses .value. See #6932
  				var val = elem.attributes.value;
  				return !val || val.specified ? elem.value : elem.text;
  			}
  		},
  		select: {
  			get: function( elem ) {
  				var value, option,
  					options = elem.options,
  					index = elem.selectedIndex,
  					one = elem.type === "select-one" || index < 0,
  					values = one ? null : [],
  					max = one ? index + 1 : options.length,
  					i = index < 0 ?
  						max :
  						one ? index : 0;
  
  				// Loop through all the selected options
  				for ( ; i < max; i++ ) {
  					option = options[ i ];
  
  					// IE6-9 doesn't update selected after form reset (#2551)
  					if ( ( option.selected || i === index ) &&
  							// Don't return options that are disabled or in a disabled optgroup
  							( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
  							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
  
  						// Get the specific value for the option
  						value = jQuery( option ).val();
  
  						// We don't need an array for one selects
  						if ( one ) {
  							return value;
  						}
  
  						// Multi-Selects return an array
  						values.push( value );
  					}
  				}
  
  				return values;
  			},
  
  			set: function( elem, value ) {
  				var optionSet, option,
  					options = elem.options,
  					values = jQuery.makeArray( value ),
  					i = options.length;
  
  				while ( i-- ) {
  					option = options[ i ];
  					if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {
  						optionSet = true;
  					}
  				}
  
  				// force browsers to behave consistently when non-matching value is set
  				if ( !optionSet ) {
  					elem.selectedIndex = -1;
  				}
  				return values;
  			}
  		}
  	},
  
  	attr: function( elem, name, value ) {
  		var hooks, ret,
  			nType = elem.nodeType;
  
  		// don't get/set attributes on text, comment and attribute nodes
  		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  			return;
  		}
  
  		// Fallback to prop when attributes are not supported
  		if ( typeof elem.getAttribute === core_strundefined ) {
  			return jQuery.prop( elem, name, value );
  		}
  
  		// All attributes are lowercase
  		// Grab necessary hook if one is defined
  		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
  			name = name.toLowerCase();
  			hooks = jQuery.attrHooks[ name ] ||
  				( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
  		}
  
  		if ( value !== undefined ) {
  
  			if ( value === null ) {
  				jQuery.removeAttr( elem, name );
  
  			} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
  				return ret;
  
  			} else {
  				elem.setAttribute( name, value + "" );
  				return value;
  			}
  
  		} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
  			return ret;
  
  		} else {
  			ret = jQuery.find.attr( elem, name );
  
  			// Non-existent attributes return null, we normalize to undefined
  			return ret == null ?
  				undefined :
  				ret;
  		}
  	},
  
  	removeAttr: function( elem, value ) {
  		var name, propName,
  			i = 0,
  			attrNames = value && value.match( core_rnotwhite );
  
  		if ( attrNames && elem.nodeType === 1 ) {
  			while ( (name = attrNames[i++]) ) {
  				propName = jQuery.propFix[ name ] || name;
  
  				// Boolean attributes get special treatment (#10870)
  				if ( jQuery.expr.match.bool.test( name ) ) {
  					// Set corresponding property to false
  					elem[ propName ] = false;
  				}
  
  				elem.removeAttribute( name );
  			}
  		}
  	},
  
  	attrHooks: {
  		type: {
  			set: function( elem, value ) {
  				if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
  					// Setting the type on a radio button after the value resets the value in IE6-9
  					// Reset value to default in case type is set after value during creation
  					var val = elem.value;
  					elem.setAttribute( "type", value );
  					if ( val ) {
  						elem.value = val;
  					}
  					return value;
  				}
  			}
  		}
  	},
  
  	propFix: {
  		"for": "htmlFor",
  		"class": "className"
  	},
  
  	prop: function( elem, name, value ) {
  		var ret, hooks, notxml,
  			nType = elem.nodeType;
  
  		// don't get/set properties on text, comment and attribute nodes
  		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
  			return;
  		}
  
  		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
  
  		if ( notxml ) {
  			// Fix name and attach hooks
  			name = jQuery.propFix[ name ] || name;
  			hooks = jQuery.propHooks[ name ];
  		}
  
  		if ( value !== undefined ) {
  			return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
  				ret :
  				( elem[ name ] = value );
  
  		} else {
  			return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
  				ret :
  				elem[ name ];
  		}
  	},
  
  	propHooks: {
  		tabIndex: {
  			get: function( elem ) {
  				return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
  					elem.tabIndex :
  					-1;
  			}
  		}
  	}
  });
  
  // Hooks for boolean attributes
  boolHook = {
  	set: function( elem, value, name ) {
  		if ( value === false ) {
  			// Remove boolean attributes when set to false
  			jQuery.removeAttr( elem, name );
  		} else {
  			elem.setAttribute( name, name );
  		}
  		return name;
  	}
  };
  jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
  	var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;
  
  	jQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) {
  		var fn = jQuery.expr.attrHandle[ name ],
  			ret = isXML ?
  				undefined :
  				/* jshint eqeqeq: false */
  				// Temporarily disable this handler to check existence
  				(jQuery.expr.attrHandle[ name ] = undefined) !=
  					getter( elem, name, isXML ) ?
  
  					name.toLowerCase() :
  					null;
  
  		// Restore handler
  		jQuery.expr.attrHandle[ name ] = fn;
  
  		return ret;
  	};
  });
  
  // Support: IE9+
  // Selectedness for an option in an optgroup can be inaccurate
  if ( !jQuery.support.optSelected ) {
  	jQuery.propHooks.selected = {
  		get: function( elem ) {
  			var parent = elem.parentNode;
  			if ( parent && parent.parentNode ) {
  				parent.parentNode.selectedIndex;
  			}
  			return null;
  		}
  	};
  }
  
  jQuery.each([
  	"tabIndex",
  	"readOnly",
  	"maxLength",
  	"cellSpacing",
  	"cellPadding",
  	"rowSpan",
  	"colSpan",
  	"useMap",
  	"frameBorder",
  	"contentEditable"
  ], function() {
  	jQuery.propFix[ this.toLowerCase() ] = this;
  });
  
  // Radios and checkboxes getter/setter
  jQuery.each([ "radio", "checkbox" ], function() {
  	jQuery.valHooks[ this ] = {
  		set: function( elem, value ) {
  			if ( jQuery.isArray( value ) ) {
  				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
  			}
  		}
  	};
  	if ( !jQuery.support.checkOn ) {
  		jQuery.valHooks[ this ].get = function( elem ) {
  			// Support: Webkit
  			// "" is returned instead of "on" if a value isn't specified
  			return elem.getAttribute("value") === null ? "on" : elem.value;
  		};
  	}
  });
  var rkeyEvent = /^key/,
  	rmouseEvent = /^(?:mouse|contextmenu)|click/,
  	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
  	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
  
  function returnTrue() {
  	return true;
  }
  
  function returnFalse() {
  	return false;
  }
  
  function safeActiveElement() {
  	try {
  		return document.activeElement;
  	} catch ( err ) { }
  }
  
  /*
   * Helper functions for managing events -- not part of the public interface.
   * Props to Dean Edwards' addEvent library for many of the ideas.
   */
  jQuery.event = {
  
  	global: {},
  
  	add: function( elem, types, handler, data, selector ) {
  
  		var handleObjIn, eventHandle, tmp,
  			events, t, handleObj,
  			special, handlers, type, namespaces, origType,
  			elemData = data_priv.get( elem );
  
  		// Don't attach events to noData or text/comment nodes (but allow plain objects)
  		if ( !elemData ) {
  			return;
  		}
  
  		// Caller can pass in an object of custom data in lieu of the handler
  		if ( handler.handler ) {
  			handleObjIn = handler;
  			handler = handleObjIn.handler;
  			selector = handleObjIn.selector;
  		}
  
  		// Make sure that the handler has a unique ID, used to find/remove it later
  		if ( !handler.guid ) {
  			handler.guid = jQuery.guid++;
  		}
  
  		// Init the element's event structure and main handler, if this is the first
  		if ( !(events = elemData.events) ) {
  			events = elemData.events = {};
  		}
  		if ( !(eventHandle = elemData.handle) ) {
  			eventHandle = elemData.handle = function( e ) {
  				// Discard the second event of a jQuery.event.trigger() and
  				// when an event is called after a page has unloaded
  				return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
  					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
  					undefined;
  			};
  			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
  			eventHandle.elem = elem;
  		}
  
  		// Handle multiple events separated by a space
  		types = ( types || "" ).match( core_rnotwhite ) || [""];
  		t = types.length;
  		while ( t-- ) {
  			tmp = rtypenamespace.exec( types[t] ) || [];
  			type = origType = tmp[1];
  			namespaces = ( tmp[2] || "" ).split( "." ).sort();
  
  			// There *must* be a type, no attaching namespace-only handlers
  			if ( !type ) {
  				continue;
  			}
  
  			// If event changes its type, use the special event handlers for the changed type
  			special = jQuery.event.special[ type ] || {};
  
  			// If selector defined, determine special event api type, otherwise given type
  			type = ( selector ? special.delegateType : special.bindType ) || type;
  
  			// Update special based on newly reset type
  			special = jQuery.event.special[ type ] || {};
  
  			// handleObj is passed to all event handlers
  			handleObj = jQuery.extend({
  				type: type,
  				origType: origType,
  				data: data,
  				handler: handler,
  				guid: handler.guid,
  				selector: selector,
  				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
  				namespace: namespaces.join(".")
  			}, handleObjIn );
  
  			// Init the event handler queue if we're the first
  			if ( !(handlers = events[ type ]) ) {
  				handlers = events[ type ] = [];
  				handlers.delegateCount = 0;
  
  				// Only use addEventListener if the special events handler returns false
  				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
  					if ( elem.addEventListener ) {
  						elem.addEventListener( type, eventHandle, false );
  					}
  				}
  			}
  
  			if ( special.add ) {
  				special.add.call( elem, handleObj );
  
  				if ( !handleObj.handler.guid ) {
  					handleObj.handler.guid = handler.guid;
  				}
  			}
  
  			// Add to the element's handler list, delegates in front
  			if ( selector ) {
  				handlers.splice( handlers.delegateCount++, 0, handleObj );
  			} else {
  				handlers.push( handleObj );
  			}
  
  			// Keep track of which events have ever been used, for event optimization
  			jQuery.event.global[ type ] = true;
  		}
  
  		// Nullify elem to prevent memory leaks in IE
  		elem = null;
  	},
  
  	// Detach an event or set of events from an element
  	remove: function( elem, types, handler, selector, mappedTypes ) {
  
  		var j, origCount, tmp,
  			events, t, handleObj,
  			special, handlers, type, namespaces, origType,
  			elemData = data_priv.hasData( elem ) && data_priv.get( elem );
  
  		if ( !elemData || !(events = elemData.events) ) {
  			return;
  		}
  
  		// Once for each type.namespace in types; type may be omitted
  		types = ( types || "" ).match( core_rnotwhite ) || [""];
  		t = types.length;
  		while ( t-- ) {
  			tmp = rtypenamespace.exec( types[t] ) || [];
  			type = origType = tmp[1];
  			namespaces = ( tmp[2] || "" ).split( "." ).sort();
  
  			// Unbind all events (on this namespace, if provided) for the element
  			if ( !type ) {
  				for ( type in events ) {
  					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
  				}
  				continue;
  			}
  
  			special = jQuery.event.special[ type ] || {};
  			type = ( selector ? special.delegateType : special.bindType ) || type;
  			handlers = events[ type ] || [];
  			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
  
  			// Remove matching events
  			origCount = j = handlers.length;
  			while ( j-- ) {
  				handleObj = handlers[ j ];
  
  				if ( ( mappedTypes || origType === handleObj.origType ) &&
  					( !handler || handler.guid === handleObj.guid ) &&
  					( !tmp || tmp.test( handleObj.namespace ) ) &&
  					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
  					handlers.splice( j, 1 );
  
  					if ( handleObj.selector ) {
  						handlers.delegateCount--;
  					}
  					if ( special.remove ) {
  						special.remove.call( elem, handleObj );
  					}
  				}
  			}
  
  			// Remove generic event handler if we removed something and no more handlers exist
  			// (avoids potential for endless recursion during removal of special event handlers)
  			if ( origCount && !handlers.length ) {
  				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
  					jQuery.removeEvent( elem, type, elemData.handle );
  				}
  
  				delete events[ type ];
  			}
  		}
  
  		// Remove the expando if it's no longer used
  		if ( jQuery.isEmptyObject( events ) ) {
  			delete elemData.handle;
  			data_priv.remove( elem, "events" );
  		}
  	},
  
  	trigger: function( event, data, elem, onlyHandlers ) {
  
  		var i, cur, tmp, bubbleType, ontype, handle, special,
  			eventPath = [ elem || document ],
  			type = core_hasOwn.call( event, "type" ) ? event.type : event,
  			namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
  
  		cur = tmp = elem = elem || document;
  
  		// Don't do events on text and comment nodes
  		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
  			return;
  		}
  
  		// focus/blur morphs to focusin/out; ensure we're not firing them right now
  		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
  			return;
  		}
  
  		if ( type.indexOf(".") >= 0 ) {
  			// Namespaced trigger; create a regexp to match event type in handle()
  			namespaces = type.split(".");
  			type = namespaces.shift();
  			namespaces.sort();
  		}
  		ontype = type.indexOf(":") < 0 && "on" + type;
  
  		// Caller can pass in a jQuery.Event object, Object, or just an event type string
  		event = event[ jQuery.expando ] ?
  			event :
  			new jQuery.Event( type, typeof event === "object" && event );
  
  		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
  		event.isTrigger = onlyHandlers ? 2 : 3;
  		event.namespace = namespaces.join(".");
  		event.namespace_re = event.namespace ?
  			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
  			null;
  
  		// Clean up the event in case it is being reused
  		event.result = undefined;
  		if ( !event.target ) {
  			event.target = elem;
  		}
  
  		// Clone any incoming data and prepend the event, creating the handler arg list
  		data = data == null ?
  			[ event ] :
  			jQuery.makeArray( data, [ event ] );
  
  		// Allow special events to draw outside the lines
  		special = jQuery.event.special[ type ] || {};
  		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
  			return;
  		}
  
  		// Determine event propagation path in advance, per W3C events spec (#9951)
  		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
  		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
  
  			bubbleType = special.delegateType || type;
  			if ( !rfocusMorph.test( bubbleType + type ) ) {
  				cur = cur.parentNode;
  			}
  			for ( ; cur; cur = cur.parentNode ) {
  				eventPath.push( cur );
  				tmp = cur;
  			}
  
  			// Only add window if we got to document (e.g., not plain obj or detached DOM)
  			if ( tmp === (elem.ownerDocument || document) ) {
  				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
  			}
  		}
  
  		// Fire handlers on the event path
  		i = 0;
  		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
  
  			event.type = i > 1 ?
  				bubbleType :
  				special.bindType || type;
  
  			// jQuery handler
  			handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
  			if ( handle ) {
  				handle.apply( cur, data );
  			}
  
  			// Native handler
  			handle = ontype && cur[ ontype ];
  			if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
  				event.preventDefault();
  			}
  		}
  		event.type = type;
  
  		// If nobody prevented the default action, do it now
  		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
  
  			if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
  				jQuery.acceptData( elem ) ) {
  
  				// Call a native DOM method on the target with the same name name as the event.
  				// Don't do default actions on window, that's where global variables be (#6170)
  				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
  
  					// Don't re-trigger an onFOO event when we call its FOO() method
  					tmp = elem[ ontype ];
  
  					if ( tmp ) {
  						elem[ ontype ] = null;
  					}
  
  					// Prevent re-triggering of the same event, since we already bubbled it above
  					jQuery.event.triggered = type;
  					elem[ type ]();
  					jQuery.event.triggered = undefined;
  
  					if ( tmp ) {
  						elem[ ontype ] = tmp;
  					}
  				}
  			}
  		}
  
  		return event.result;
  	},
  
  	dispatch: function( event ) {
  
  		// Make a writable jQuery.Event from the native event object
  		event = jQuery.event.fix( event );
  
  		var i, j, ret, matched, handleObj,
  			handlerQueue = [],
  			args = core_slice.call( arguments ),
  			handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
  			special = jQuery.event.special[ event.type ] || {};
  
  		// Use the fix-ed jQuery.Event rather than the (read-only) native event
  		args[0] = event;
  		event.delegateTarget = this;
  
  		// Call the preDispatch hook for the mapped type, and let it bail if desired
  		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
  			return;
  		}
  
  		// Determine handlers
  		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
  
  		// Run delegates first; they may want to stop propagation beneath us
  		i = 0;
  		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
  			event.currentTarget = matched.elem;
  
  			j = 0;
  			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
  
  				// Triggered event must either 1) have no namespace, or
  				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
  				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
  
  					event.handleObj = handleObj;
  					event.data = handleObj.data;
  
  					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
  							.apply( matched.elem, args );
  
  					if ( ret !== undefined ) {
  						if ( (event.result = ret) === false ) {
  							event.preventDefault();
  							event.stopPropagation();
  						}
  					}
  				}
  			}
  		}
  
  		// Call the postDispatch hook for the mapped type
  		if ( special.postDispatch ) {
  			special.postDispatch.call( this, event );
  		}
  
  		return event.result;
  	},
  
  	handlers: function( event, handlers ) {
  		var i, matches, sel, handleObj,
  			handlerQueue = [],
  			delegateCount = handlers.delegateCount,
  			cur = event.target;
  
  		// Find delegate handlers
  		// Black-hole SVG <use> instance trees (#13180)
  		// Avoid non-left-click bubbling in Firefox (#3861)
  		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
  
  			for ( ; cur !== this; cur = cur.parentNode || this ) {
  
  				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
  				if ( cur.disabled !== true || event.type !== "click" ) {
  					matches = [];
  					for ( i = 0; i < delegateCount; i++ ) {
  						handleObj = handlers[ i ];
  
  						// Don't conflict with Object.prototype properties (#13203)
  						sel = handleObj.selector + " ";
  
  						if ( matches[ sel ] === undefined ) {
  							matches[ sel ] = handleObj.needsContext ?
  								jQuery( sel, this ).index( cur ) >= 0 :
  								jQuery.find( sel, this, null, [ cur ] ).length;
  						}
  						if ( matches[ sel ] ) {
  							matches.push( handleObj );
  						}
  					}
  					if ( matches.length ) {
  						handlerQueue.push({ elem: cur, handlers: matches });
  					}
  				}
  			}
  		}
  
  		// Add the remaining (directly-bound) handlers
  		if ( delegateCount < handlers.length ) {
  			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
  		}
  
  		return handlerQueue;
  	},
  
  	// Includes some event props shared by KeyEvent and MouseEvent
  	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
  
  	fixHooks: {},
  
  	keyHooks: {
  		props: "char charCode key keyCode".split(" "),
  		filter: function( event, original ) {
  
  			// Add which for key events
  			if ( event.which == null ) {
  				event.which = original.charCode != null ? original.charCode : original.keyCode;
  			}
  
  			return event;
  		}
  	},
  
  	mouseHooks: {
  		props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
  		filter: function( event, original ) {
  			var eventDoc, doc, body,
  				button = original.button;
  
  			// Calculate pageX/Y if missing and clientX/Y available
  			if ( event.pageX == null && original.clientX != null ) {
  				eventDoc = event.target.ownerDocument || document;
  				doc = eventDoc.documentElement;
  				body = eventDoc.body;
  
  				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
  				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
  			}
  
  			// Add which for click: 1 === left; 2 === middle; 3 === right
  			// Note: button is not normalized, so don't use it
  			if ( !event.which && button !== undefined ) {
  				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
  			}
  
  			return event;
  		}
  	},
  
  	fix: function( event ) {
  		if ( event[ jQuery.expando ] ) {
  			return event;
  		}
  
  		// Create a writable copy of the event object and normalize some properties
  		var i, prop, copy,
  			type = event.type,
  			originalEvent = event,
  			fixHook = this.fixHooks[ type ];
  
  		if ( !fixHook ) {
  			this.fixHooks[ type ] = fixHook =
  				rmouseEvent.test( type ) ? this.mouseHooks :
  				rkeyEvent.test( type ) ? this.keyHooks :
  				{};
  		}
  		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
  
  		event = new jQuery.Event( originalEvent );
  
  		i = copy.length;
  		while ( i-- ) {
  			prop = copy[ i ];
  			event[ prop ] = originalEvent[ prop ];
  		}
  
  		// Support: Cordova 2.5 (WebKit) (#13255)
  		// All events should have a target; Cordova deviceready doesn't
  		if ( !event.target ) {
  			event.target = document;
  		}
  
  		// Support: Safari 6.0+, Chrome < 28
  		// Target should not be a text node (#504, #13143)
  		if ( event.target.nodeType === 3 ) {
  			event.target = event.target.parentNode;
  		}
  
  		return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
  	},
  
  	special: {
  		load: {
  			// Prevent triggered image.load events from bubbling to window.load
  			noBubble: true
  		},
  		focus: {
  			// Fire native event if possible so blur/focus sequence is correct
  			trigger: function() {
  				if ( this !== safeActiveElement() && this.focus ) {
  					this.focus();
  					return false;
  				}
  			},
  			delegateType: "focusin"
  		},
  		blur: {
  			trigger: function() {
  				if ( this === safeActiveElement() && this.blur ) {
  					this.blur();
  					return false;
  				}
  			},
  			delegateType: "focusout"
  		},
  		click: {
  			// For checkbox, fire native event so checked state will be right
  			trigger: function() {
  				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
  					this.click();
  					return false;
  				}
  			},
  
  			// For cross-browser consistency, don't fire native .click() on links
  			_default: function( event ) {
  				return jQuery.nodeName( event.target, "a" );
  			}
  		},
  
  		beforeunload: {
  			postDispatch: function( event ) {
  
  				// Support: Firefox 20+
  				// Firefox doesn't alert if the returnValue field is not set.
  				if ( event.result !== undefined ) {
  					event.originalEvent.returnValue = event.result;
  				}
  			}
  		}
  	},
  
  	simulate: function( type, elem, event, bubble ) {
  		// Piggyback on a donor event to simulate a different one.
  		// Fake originalEvent to avoid donor's stopPropagation, but if the
  		// simulated event prevents default then we do the same on the donor.
  		var e = jQuery.extend(
  			new jQuery.Event(),
  			event,
  			{
  				type: type,
  				isSimulated: true,
  				originalEvent: {}
  			}
  		);
  		if ( bubble ) {
  			jQuery.event.trigger( e, null, elem );
  		} else {
  			jQuery.event.dispatch.call( elem, e );
  		}
  		if ( e.isDefaultPrevented() ) {
  			event.preventDefault();
  		}
  	}
  };
  
  jQuery.removeEvent = function( elem, type, handle ) {
  	if ( elem.removeEventListener ) {
  		elem.removeEventListener( type, handle, false );
  	}
  };
  
  jQuery.Event = function( src, props ) {
  	// Allow instantiation without the 'new' keyword
  	if ( !(this instanceof jQuery.Event) ) {
  		return new jQuery.Event( src, props );
  	}
  
  	// Event object
  	if ( src && src.type ) {
  		this.originalEvent = src;
  		this.type = src.type;
  
  		// Events bubbling up the document may have been marked as prevented
  		// by a handler lower down the tree; reflect the correct value.
  		this.isDefaultPrevented = ( src.defaultPrevented ||
  			src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
  
  	// Event type
  	} else {
  		this.type = src;
  	}
  
  	// Put explicitly provided properties onto the event object
  	if ( props ) {
  		jQuery.extend( this, props );
  	}
  
  	// Create a timestamp if incoming event doesn't have one
  	this.timeStamp = src && src.timeStamp || jQuery.now();
  
  	// Mark it as fixed
  	this[ jQuery.expando ] = true;
  };
  
  // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
  // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  jQuery.Event.prototype = {
  	isDefaultPrevented: returnFalse,
  	isPropagationStopped: returnFalse,
  	isImmediatePropagationStopped: returnFalse,
  
  	preventDefault: function() {
  		var e = this.originalEvent;
  
  		this.isDefaultPrevented = returnTrue;
  
  		if ( e && e.preventDefault ) {
  			e.preventDefault();
  		}
  	},
  	stopPropagation: function() {
  		var e = this.originalEvent;
  
  		this.isPropagationStopped = returnTrue;
  
  		if ( e && e.stopPropagation ) {
  			e.stopPropagation();
  		}
  	},
  	stopImmediatePropagation: function() {
  		this.isImmediatePropagationStopped = returnTrue;
  		this.stopPropagation();
  	}
  };
  
  // Create mouseenter/leave events using mouseover/out and event-time checks
  // Support: Chrome 15+
  jQuery.each({
  	mouseenter: "mouseover",
  	mouseleave: "mouseout"
  }, function( orig, fix ) {
  	jQuery.event.special[ orig ] = {
  		delegateType: fix,
  		bindType: fix,
  
  		handle: function( event ) {
  			var ret,
  				target = this,
  				related = event.relatedTarget,
  				handleObj = event.handleObj;
  
  			// For mousenter/leave call the handler if related is outside the target.
  			// NB: No relatedTarget if the mouse left/entered the browser window
  			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
  				event.type = handleObj.origType;
  				ret = handleObj.handler.apply( this, arguments );
  				event.type = fix;
  			}
  			return ret;
  		}
  	};
  });
  
  // Create "bubbling" focus and blur events
  // Support: Firefox, Chrome, Safari
  if ( !jQuery.support.focusinBubbles ) {
  	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
  
  		// Attach a single capturing handler while someone wants focusin/focusout
  		var attaches = 0,
  			handler = function( event ) {
  				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
  			};
  
  		jQuery.event.special[ fix ] = {
  			setup: function() {
  				if ( attaches++ === 0 ) {
  					document.addEventListener( orig, handler, true );
  				}
  			},
  			teardown: function() {
  				if ( --attaches === 0 ) {
  					document.removeEventListener( orig, handler, true );
  				}
  			}
  		};
  	});
  }
  
  jQuery.fn.extend({
  
  	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
  		var origFn, type;
  
  		// Types can be a map of types/handlers
  		if ( typeof types === "object" ) {
  			// ( types-Object, selector, data )
  			if ( typeof selector !== "string" ) {
  				// ( types-Object, data )
  				data = data || selector;
  				selector = undefined;
  			}
  			for ( type in types ) {
  				this.on( type, selector, data, types[ type ], one );
  			}
  			return this;
  		}
  
  		if ( data == null && fn == null ) {
  			// ( types, fn )
  			fn = selector;
  			data = selector = undefined;
  		} else if ( fn == null ) {
  			if ( typeof selector === "string" ) {
  				// ( types, selector, fn )
  				fn = data;
  				data = undefined;
  			} else {
  				// ( types, data, fn )
  				fn = data;
  				data = selector;
  				selector = undefined;
  			}
  		}
  		if ( fn === false ) {
  			fn = returnFalse;
  		} else if ( !fn ) {
  			return this;
  		}
  
  		if ( one === 1 ) {
  			origFn = fn;
  			fn = function( event ) {
  				// Can use an empty set, since event contains the info
  				jQuery().off( event );
  				return origFn.apply( this, arguments );
  			};
  			// Use same guid so caller can remove using origFn
  			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
  		}
  		return this.each( function() {
  			jQuery.event.add( this, types, fn, data, selector );
  		});
  	},
  	one: function( types, selector, data, fn ) {
  		return this.on( types, selector, data, fn, 1 );
  	},
  	off: function( types, selector, fn ) {
  		var handleObj, type;
  		if ( types && types.preventDefault && types.handleObj ) {
  			// ( event )  dispatched jQuery.Event
  			handleObj = types.handleObj;
  			jQuery( types.delegateTarget ).off(
  				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
  				handleObj.selector,
  				handleObj.handler
  			);
  			return this;
  		}
  		if ( typeof types === "object" ) {
  			// ( types-object [, selector] )
  			for ( type in types ) {
  				this.off( type, selector, types[ type ] );
  			}
  			return this;
  		}
  		if ( selector === false || typeof selector === "function" ) {
  			// ( types [, fn] )
  			fn = selector;
  			selector = undefined;
  		}
  		if ( fn === false ) {
  			fn = returnFalse;
  		}
  		return this.each(function() {
  			jQuery.event.remove( this, types, fn, selector );
  		});
  	},
  
  	trigger: function( type, data ) {
  		return this.each(function() {
  			jQuery.event.trigger( type, data, this );
  		});
  	},
  	triggerHandler: function( type, data ) {
  		var elem = this[0];
  		if ( elem ) {
  			return jQuery.event.trigger( type, data, elem, true );
  		}
  	}
  });
  var isSimple = /^.[^:#\[\.,]*$/,
  	rparentsprev = /^(?:parents|prev(?:Until|All))/,
  	rneedsContext = jQuery.expr.match.needsContext,
  	// methods guaranteed to produce a unique set when starting from a unique set
  	guaranteedUnique = {
  		children: true,
  		contents: true,
  		next: true,
  		prev: true
  	};
  
  jQuery.fn.extend({
  	find: function( selector ) {
  		var i,
  			ret = [],
  			self = this,
  			len = self.length;
  
  		if ( typeof selector !== "string" ) {
  			return this.pushStack( jQuery( selector ).filter(function() {
  				for ( i = 0; i < len; i++ ) {
  					if ( jQuery.contains( self[ i ], this ) ) {
  						return true;
  					}
  				}
  			}) );
  		}
  
  		for ( i = 0; i < len; i++ ) {
  			jQuery.find( selector, self[ i ], ret );
  		}
  
  		// Needed because $( selector, context ) becomes $( context ).find( selector )
  		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
  		ret.selector = this.selector ? this.selector + " " + selector : selector;
  		return ret;
  	},
  
  	has: function( target ) {
  		var targets = jQuery( target, this ),
  			l = targets.length;
  
  		return this.filter(function() {
  			var i = 0;
  			for ( ; i < l; i++ ) {
  				if ( jQuery.contains( this, targets[i] ) ) {
  					return true;
  				}
  			}
  		});
  	},
  
  	not: function( selector ) {
  		return this.pushStack( winnow(this, selector || [], true) );
  	},
  
  	filter: function( selector ) {
  		return this.pushStack( winnow(this, selector || [], false) );
  	},
  
  	is: function( selector ) {
  		return !!winnow(
  			this,
  
  			// If this is a positional/relative selector, check membership in the returned set
  			// so $("p:first").is("p:last") won't return true for a doc with two "p".
  			typeof selector === "string" && rneedsContext.test( selector ) ?
  				jQuery( selector ) :
  				selector || [],
  			false
  		).length;
  	},
  
  	closest: function( selectors, context ) {
  		var cur,
  			i = 0,
  			l = this.length,
  			matched = [],
  			pos = ( rneedsContext.test( selectors ) || typeof selectors !== "string" ) ?
  				jQuery( selectors, context || this.context ) :
  				0;
  
  		for ( ; i < l; i++ ) {
  			for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
  				// Always skip document fragments
  				if ( cur.nodeType < 11 && (pos ?
  					pos.index(cur) > -1 :
  
  					// Don't pass non-elements to Sizzle
  					cur.nodeType === 1 &&
  						jQuery.find.matchesSelector(cur, selectors)) ) {
  
  					cur = matched.push( cur );
  					break;
  				}
  			}
  		}
  
  		return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
  	},
  
  	// Determine the position of an element within
  	// the matched set of elements
  	index: function( elem ) {
  
  		// No argument, return index in parent
  		if ( !elem ) {
  			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
  		}
  
  		// index in selector
  		if ( typeof elem === "string" ) {
  			return core_indexOf.call( jQuery( elem ), this[ 0 ] );
  		}
  
  		// Locate the position of the desired element
  		return core_indexOf.call( this,
  
  			// If it receives a jQuery object, the first element is used
  			elem.jquery ? elem[ 0 ] : elem
  		);
  	},
  
  	add: function( selector, context ) {
  		var set = typeof selector === "string" ?
  				jQuery( selector, context ) :
  				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
  			all = jQuery.merge( this.get(), set );
  
  		return this.pushStack( jQuery.unique(all) );
  	},
  
  	addBack: function( selector ) {
  		return this.add( selector == null ?
  			this.prevObject : this.prevObject.filter(selector)
  		);
  	}
  });
  
  function sibling( cur, dir ) {
  	while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
  
  	return cur;
  }
  
  jQuery.each({
  	parent: function( elem ) {
  		var parent = elem.parentNode;
  		return parent && parent.nodeType !== 11 ? parent : null;
  	},
  	parents: function( elem ) {
  		return jQuery.dir( elem, "parentNode" );
  	},
  	parentsUntil: function( elem, i, until ) {
  		return jQuery.dir( elem, "parentNode", until );
  	},
  	next: function( elem ) {
  		return sibling( elem, "nextSibling" );
  	},
  	prev: function( elem ) {
  		return sibling( elem, "previousSibling" );
  	},
  	nextAll: function( elem ) {
  		return jQuery.dir( elem, "nextSibling" );
  	},
  	prevAll: function( elem ) {
  		return jQuery.dir( elem, "previousSibling" );
  	},
  	nextUntil: function( elem, i, until ) {
  		return jQuery.dir( elem, "nextSibling", until );
  	},
  	prevUntil: function( elem, i, until ) {
  		return jQuery.dir( elem, "previousSibling", until );
  	},
  	siblings: function( elem ) {
  		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
  	},
  	children: function( elem ) {
  		return jQuery.sibling( elem.firstChild );
  	},
  	contents: function( elem ) {
  		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
  	}
  }, function( name, fn ) {
  	jQuery.fn[ name ] = function( until, selector ) {
  		var matched = jQuery.map( this, fn, until );
  
  		if ( name.slice( -5 ) !== "Until" ) {
  			selector = until;
  		}
  
  		if ( selector && typeof selector === "string" ) {
  			matched = jQuery.filter( selector, matched );
  		}
  
  		if ( this.length > 1 ) {
  			// Remove duplicates
  			if ( !guaranteedUnique[ name ] ) {
  				jQuery.unique( matched );
  			}
  
  			// Reverse order for parents* and prev-derivatives
  			if ( rparentsprev.test( name ) ) {
  				matched.reverse();
  			}
  		}
  
  		return this.pushStack( matched );
  	};
  });
  
  jQuery.extend({
  	filter: function( expr, elems, not ) {
  		var elem = elems[ 0 ];
  
  		if ( not ) {
  			expr = ":not(" + expr + ")";
  		}
  
  		return elems.length === 1 && elem.nodeType === 1 ?
  			jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
  			jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
  				return elem.nodeType === 1;
  			}));
  	},
  
  	dir: function( elem, dir, until ) {
  		var matched = [],
  			truncate = until !== undefined;
  
  		while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
  			if ( elem.nodeType === 1 ) {
  				if ( truncate && jQuery( elem ).is( until ) ) {
  					break;
  				}
  				matched.push( elem );
  			}
  		}
  		return matched;
  	},
  
  	sibling: function( n, elem ) {
  		var matched = [];
  
  		for ( ; n; n = n.nextSibling ) {
  			if ( n.nodeType === 1 && n !== elem ) {
  				matched.push( n );
  			}
  		}
  
  		return matched;
  	}
  });
  
  // Implement the identical functionality for filter and not
  function winnow( elements, qualifier, not ) {
  	if ( jQuery.isFunction( qualifier ) ) {
  		return jQuery.grep( elements, function( elem, i ) {
  			/* jshint -W018 */
  			return !!qualifier.call( elem, i, elem ) !== not;
  		});
  
  	}
  
  	if ( qualifier.nodeType ) {
  		return jQuery.grep( elements, function( elem ) {
  			return ( elem === qualifier ) !== not;
  		});
  
  	}
  
  	if ( typeof qualifier === "string" ) {
  		if ( isSimple.test( qualifier ) ) {
  			return jQuery.filter( qualifier, elements, not );
  		}
  
  		qualifier = jQuery.filter( qualifier, elements );
  	}
  
  	return jQuery.grep( elements, function( elem ) {
  		return ( core_indexOf.call( qualifier, elem ) >= 0 ) !== not;
  	});
  }
  var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
  	rtagName = /<([\w:]+)/,
  	rhtml = /<|&#?\w+;/,
  	rnoInnerhtml = /<(?:script|style|link)/i,
  	manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
  	// checked="checked" or checked
  	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
  	rscriptType = /^$|\/(?:java|ecma)script/i,
  	rscriptTypeMasked = /^true\/(.*)/,
  	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
  
  	// We have to close these tags to support XHTML (#13200)
  	wrapMap = {
  
  		// Support: IE 9
  		option: [ 1, "<select multiple='multiple'>", "</select>" ],
  
  		thead: [ 1, "<table>", "</table>" ],
  		col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
  		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
  		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
  
  		_default: [ 0, "", "" ]
  	};
  
  // Support: IE 9
  wrapMap.optgroup = wrapMap.option;
  
  wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  wrapMap.th = wrapMap.td;
  
  jQuery.fn.extend({
  	text: function( value ) {
  		return jQuery.access( this, function( value ) {
  			return value === undefined ?
  				jQuery.text( this ) :
  				this.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) );
  		}, null, value, arguments.length );
  	},
  
  	append: function() {
  		return this.domManip( arguments, function( elem ) {
  			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  				var target = manipulationTarget( this, elem );
  				target.appendChild( elem );
  			}
  		});
  	},
  
  	prepend: function() {
  		return this.domManip( arguments, function( elem ) {
  			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
  				var target = manipulationTarget( this, elem );
  				target.insertBefore( elem, target.firstChild );
  			}
  		});
  	},
  
  	before: function() {
  		return this.domManip( arguments, function( elem ) {
  			if ( this.parentNode ) {
  				this.parentNode.insertBefore( elem, this );
  			}
  		});
  	},
  
  	after: function() {
  		return this.domManip( arguments, function( elem ) {
  			if ( this.parentNode ) {
  				this.parentNode.insertBefore( elem, this.nextSibling );
  			}
  		});
  	},
  
  	// keepData is for internal use only--do not document
  	remove: function( selector, keepData ) {
  		var elem,
  			elems = selector ? jQuery.filter( selector, this ) : this,
  			i = 0;
  
  		for ( ; (elem = elems[i]) != null; i++ ) {
  			if ( !keepData && elem.nodeType === 1 ) {
  				jQuery.cleanData( getAll( elem ) );
  			}
  
  			if ( elem.parentNode ) {
  				if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
  					setGlobalEval( getAll( elem, "script" ) );
  				}
  				elem.parentNode.removeChild( elem );
  			}
  		}
  
  		return this;
  	},
  
  	empty: function() {
  		var elem,
  			i = 0;
  
  		for ( ; (elem = this[i]) != null; i++ ) {
  			if ( elem.nodeType === 1 ) {
  
  				// Prevent memory leaks
  				jQuery.cleanData( getAll( elem, false ) );
  
  				// Remove any remaining nodes
  				elem.textContent = "";
  			}
  		}
  
  		return this;
  	},
  
  	clone: function( dataAndEvents, deepDataAndEvents ) {
  		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
  		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
  
  		return this.map( function () {
  			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
  		});
  	},
  
  	html: function( value ) {
  		return jQuery.access( this, function( value ) {
  			var elem = this[ 0 ] || {},
  				i = 0,
  				l = this.length;
  
  			if ( value === undefined && elem.nodeType === 1 ) {
  				return elem.innerHTML;
  			}
  
  			// See if we can take a shortcut and just use innerHTML
  			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
  				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
  
  				value = value.replace( rxhtmlTag, "<$1></$2>" );
  
  				try {
  					for ( ; i < l; i++ ) {
  						elem = this[ i ] || {};
  
  						// Remove element nodes and prevent memory leaks
  						if ( elem.nodeType === 1 ) {
  							jQuery.cleanData( getAll( elem, false ) );
  							elem.innerHTML = value;
  						}
  					}
  
  					elem = 0;
  
  				// If using innerHTML throws an exception, use the fallback method
  				} catch( e ) {}
  			}
  
  			if ( elem ) {
  				this.empty().append( value );
  			}
  		}, null, value, arguments.length );
  	},
  
  	replaceWith: function() {
  		var
  			// Snapshot the DOM in case .domManip sweeps something relevant into its fragment
  			args = jQuery.map( this, function( elem ) {
  				return [ elem.nextSibling, elem.parentNode ];
  			}),
  			i = 0;
  
  		// Make the changes, replacing each context element with the new content
  		this.domManip( arguments, function( elem ) {
  			var next = args[ i++ ],
  				parent = args[ i++ ];
  
  			if ( parent ) {
  				// Don't use the snapshot next if it has moved (#13810)
  				if ( next && next.parentNode !== parent ) {
  					next = this.nextSibling;
  				}
  				jQuery( this ).remove();
  				parent.insertBefore( elem, next );
  			}
  		// Allow new content to include elements from the context set
  		}, true );
  
  		// Force removal if there was no new content (e.g., from empty arguments)
  		return i ? this : this.remove();
  	},
  
  	detach: function( selector ) {
  		return this.remove( selector, true );
  	},
  
  	domManip: function( args, callback, allowIntersection ) {
  
  		// Flatten any nested arrays
  		args = core_concat.apply( [], args );
  
  		var fragment, first, scripts, hasScripts, node, doc,
  			i = 0,
  			l = this.length,
  			set = this,
  			iNoClone = l - 1,
  			value = args[ 0 ],
  			isFunction = jQuery.isFunction( value );
  
  		// We can't cloneNode fragments that contain checked, in WebKit
  		if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
  			return this.each(function( index ) {
  				var self = set.eq( index );
  				if ( isFunction ) {
  					args[ 0 ] = value.call( this, index, self.html() );
  				}
  				self.domManip( args, callback, allowIntersection );
  			});
  		}
  
  		if ( l ) {
  			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this );
  			first = fragment.firstChild;
  
  			if ( fragment.childNodes.length === 1 ) {
  				fragment = first;
  			}
  
  			if ( first ) {
  				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
  				hasScripts = scripts.length;
  
  				// Use the original fragment for the last item instead of the first because it can end up
  				// being emptied incorrectly in certain situations (#8070).
  				for ( ; i < l; i++ ) {
  					node = fragment;
  
  					if ( i !== iNoClone ) {
  						node = jQuery.clone( node, true, true );
  
  						// Keep references to cloned scripts for later restoration
  						if ( hasScripts ) {
  							// Support: QtWebKit
  							// jQuery.merge because core_push.apply(_, arraylike) throws
  							jQuery.merge( scripts, getAll( node, "script" ) );
  						}
  					}
  
  					callback.call( this[ i ], node, i );
  				}
  
  				if ( hasScripts ) {
  					doc = scripts[ scripts.length - 1 ].ownerDocument;
  
  					// Reenable scripts
  					jQuery.map( scripts, restoreScript );
  
  					// Evaluate executable scripts on first document insertion
  					for ( i = 0; i < hasScripts; i++ ) {
  						node = scripts[ i ];
  						if ( rscriptType.test( node.type || "" ) &&
  							!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
  
  							if ( node.src ) {
  								// Hope ajax is available...
  								jQuery._evalUrl( node.src );
  							} else {
  								jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
  							}
  						}
  					}
  				}
  			}
  		}
  
  		return this;
  	}
  });
  
  jQuery.each({
  	appendTo: "append",
  	prependTo: "prepend",
  	insertBefore: "before",
  	insertAfter: "after",
  	replaceAll: "replaceWith"
  }, function( name, original ) {
  	jQuery.fn[ name ] = function( selector ) {
  		var elems,
  			ret = [],
  			insert = jQuery( selector ),
  			last = insert.length - 1,
  			i = 0;
  
  		for ( ; i <= last; i++ ) {
  			elems = i === last ? this : this.clone( true );
  			jQuery( insert[ i ] )[ original ]( elems );
  
  			// Support: QtWebKit
  			// .get() because core_push.apply(_, arraylike) throws
  			core_push.apply( ret, elems.get() );
  		}
  
  		return this.pushStack( ret );
  	};
  });
  
  jQuery.extend({
  	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
  		var i, l, srcElements, destElements,
  			clone = elem.cloneNode( true ),
  			inPage = jQuery.contains( elem.ownerDocument, elem );
  
  		// Support: IE >= 9
  		// Fix Cloning issues
  		if ( !jQuery.support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) {
  
  			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
  			destElements = getAll( clone );
  			srcElements = getAll( elem );
  
  			for ( i = 0, l = srcElements.length; i < l; i++ ) {
  				fixInput( srcElements[ i ], destElements[ i ] );
  			}
  		}
  
  		// Copy the events from the original to the clone
  		if ( dataAndEvents ) {
  			if ( deepDataAndEvents ) {
  				srcElements = srcElements || getAll( elem );
  				destElements = destElements || getAll( clone );
  
  				for ( i = 0, l = srcElements.length; i < l; i++ ) {
  					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
  				}
  			} else {
  				cloneCopyEvent( elem, clone );
  			}
  		}
  
  		// Preserve script evaluation history
  		destElements = getAll( clone, "script" );
  		if ( destElements.length > 0 ) {
  			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
  		}
  
  		// Return the cloned set
  		return clone;
  	},
  
  	buildFragment: function( elems, context, scripts, selection ) {
  		var elem, tmp, tag, wrap, contains, j,
  			i = 0,
  			l = elems.length,
  			fragment = context.createDocumentFragment(),
  			nodes = [];
  
  		for ( ; i < l; i++ ) {
  			elem = elems[ i ];
  
  			if ( elem || elem === 0 ) {
  
  				// Add nodes directly
  				if ( jQuery.type( elem ) === "object" ) {
  					// Support: QtWebKit
  					// jQuery.merge because core_push.apply(_, arraylike) throws
  					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
  
  				// Convert non-html into a text node
  				} else if ( !rhtml.test( elem ) ) {
  					nodes.push( context.createTextNode( elem ) );
  
  				// Convert html into DOM nodes
  				} else {
  					tmp = tmp || fragment.appendChild( context.createElement("div") );
  
  					// Deserialize a standard representation
  					tag = ( rtagName.exec( elem ) || ["", ""] )[ 1 ].toLowerCase();
  					wrap = wrapMap[ tag ] || wrapMap._default;
  					tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
  
  					// Descend through wrappers to the right content
  					j = wrap[ 0 ];
  					while ( j-- ) {
  						tmp = tmp.lastChild;
  					}
  
  					// Support: QtWebKit
  					// jQuery.merge because core_push.apply(_, arraylike) throws
  					jQuery.merge( nodes, tmp.childNodes );
  
  					// Remember the top-level container
  					tmp = fragment.firstChild;
  
  					// Fixes #12346
  					// Support: Webkit, IE
  					tmp.textContent = "";
  				}
  			}
  		}
  
  		// Remove wrapper from fragment
  		fragment.textContent = "";
  
  		i = 0;
  		while ( (elem = nodes[ i++ ]) ) {
  
  			// #4087 - If origin and destination elements are the same, and this is
  			// that element, do not do anything
  			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
  				continue;
  			}
  
  			contains = jQuery.contains( elem.ownerDocument, elem );
  
  			// Append to fragment
  			tmp = getAll( fragment.appendChild( elem ), "script" );
  
  			// Preserve script evaluation history
  			if ( contains ) {
  				setGlobalEval( tmp );
  			}
  
  			// Capture executables
  			if ( scripts ) {
  				j = 0;
  				while ( (elem = tmp[ j++ ]) ) {
  					if ( rscriptType.test( elem.type || "" ) ) {
  						scripts.push( elem );
  					}
  				}
  			}
  		}
  
  		return fragment;
  	},
  
  	cleanData: function( elems ) {
  		var data, elem, events, type, key, j,
  			special = jQuery.event.special,
  			i = 0;
  
  		for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
  			if ( Data.accepts( elem ) ) {
  				key = elem[ data_priv.expando ];
  
  				if ( key && (data = data_priv.cache[ key ]) ) {
  					events = Object.keys( data.events || {} );
  					if ( events.length ) {
  						for ( j = 0; (type = events[j]) !== undefined; j++ ) {
  							if ( special[ type ] ) {
  								jQuery.event.remove( elem, type );
  
  							// This is a shortcut to avoid jQuery.event.remove's overhead
  							} else {
  								jQuery.removeEvent( elem, type, data.handle );
  							}
  						}
  					}
  					if ( data_priv.cache[ key ] ) {
  						// Discard any remaining `private` data
  						delete data_priv.cache[ key ];
  					}
  				}
  			}
  			// Discard any remaining `user` data
  			delete data_user.cache[ elem[ data_user.expando ] ];
  		}
  	},
  
  	_evalUrl: function( url ) {
  		return jQuery.ajax({
  			url: url,
  			type: "GET",
  			dataType: "script",
  			async: false,
  			global: false,
  			"throws": true
  		});
  	}
  });
  
  // Support: 1.x compatibility
  // Manipulating tables requires a tbody
  function manipulationTarget( elem, content ) {
  	return jQuery.nodeName( elem, "table" ) &&
  		jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ?
  
  		elem.getElementsByTagName("tbody")[0] ||
  			elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
  		elem;
  }
  
  // Replace/restore the type attribute of script elements for safe DOM manipulation
  function disableScript( elem ) {
  	elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
  	return elem;
  }
  function restoreScript( elem ) {
  	var match = rscriptTypeMasked.exec( elem.type );
  
  	if ( match ) {
  		elem.type = match[ 1 ];
  	} else {
  		elem.removeAttribute("type");
  	}
  
  	return elem;
  }
  
  // Mark scripts as having already been evaluated
  function setGlobalEval( elems, refElements ) {
  	var l = elems.length,
  		i = 0;
  
  	for ( ; i < l; i++ ) {
  		data_priv.set(
  			elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
  		);
  	}
  }
  
  function cloneCopyEvent( src, dest ) {
  	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
  
  	if ( dest.nodeType !== 1 ) {
  		return;
  	}
  
  	// 1. Copy private data: events, handlers, etc.
  	if ( data_priv.hasData( src ) ) {
  		pdataOld = data_priv.access( src );
  		pdataCur = data_priv.set( dest, pdataOld );
  		events = pdataOld.events;
  
  		if ( events ) {
  			delete pdataCur.handle;
  			pdataCur.events = {};
  
  			for ( type in events ) {
  				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
  					jQuery.event.add( dest, type, events[ type ][ i ] );
  				}
  			}
  		}
  	}
  
  	// 2. Copy user data
  	if ( data_user.hasData( src ) ) {
  		udataOld = data_user.access( src );
  		udataCur = jQuery.extend( {}, udataOld );
  
  		data_user.set( dest, udataCur );
  	}
  }
  
  
  function getAll( context, tag ) {
  	var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
  			context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
  			[];
  
  	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
  		jQuery.merge( [ context ], ret ) :
  		ret;
  }
  
  // Support: IE >= 9
  function fixInput( src, dest ) {
  	var nodeName = dest.nodeName.toLowerCase();
  
  	// Fails to persist the checked state of a cloned checkbox or radio button.
  	if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
  		dest.checked = src.checked;
  
  	// Fails to return the selected option to the default selected state when cloning options
  	} else if ( nodeName === "input" || nodeName === "textarea" ) {
  		dest.defaultValue = src.defaultValue;
  	}
  }
  jQuery.fn.extend({
  	wrapAll: function( html ) {
  		var wrap;
  
  		if ( jQuery.isFunction( html ) ) {
  			return this.each(function( i ) {
  				jQuery( this ).wrapAll( html.call(this, i) );
  			});
  		}
  
  		if ( this[ 0 ] ) {
  
  			// The elements to wrap the target around
  			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
  
  			if ( this[ 0 ].parentNode ) {
  				wrap.insertBefore( this[ 0 ] );
  			}
  
  			wrap.map(function() {
  				var elem = this;
  
  				while ( elem.firstElementChild ) {
  					elem = elem.firstElementChild;
  				}
  
  				return elem;
  			}).append( this );
  		}
  
  		return this;
  	},
  
  	wrapInner: function( html ) {
  		if ( jQuery.isFunction( html ) ) {
  			return this.each(function( i ) {
  				jQuery( this ).wrapInner( html.call(this, i) );
  			});
  		}
  
  		return this.each(function() {
  			var self = jQuery( this ),
  				contents = self.contents();
  
  			if ( contents.length ) {
  				contents.wrapAll( html );
  
  			} else {
  				self.append( html );
  			}
  		});
  	},
  
  	wrap: function( html ) {
  		var isFunction = jQuery.isFunction( html );
  
  		return this.each(function( i ) {
  			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
  		});
  	},
  
  	unwrap: function() {
  		return this.parent().each(function() {
  			if ( !jQuery.nodeName( this, "body" ) ) {
  				jQuery( this ).replaceWith( this.childNodes );
  			}
  		}).end();
  	}
  });
  var curCSS, iframe,
  	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
  	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
  	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
  	rmargin = /^margin/,
  	rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
  	rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
  	rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
  	elemdisplay = { BODY: "block" },
  
  	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
  	cssNormalTransform = {
  		letterSpacing: 0,
  		fontWeight: 400
  	},
  
  	cssExpand = [ "Top", "Right", "Bottom", "Left" ],
  	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
  
  // return a css property mapped to a potentially vendor prefixed property
  function vendorPropName( style, name ) {
  
  	// shortcut for names that are not vendor prefixed
  	if ( name in style ) {
  		return name;
  	}
  
  	// check for vendor prefixed names
  	var capName = name.charAt(0).toUpperCase() + name.slice(1),
  		origName = name,
  		i = cssPrefixes.length;
  
  	while ( i-- ) {
  		name = cssPrefixes[ i ] + capName;
  		if ( name in style ) {
  			return name;
  		}
  	}
  
  	return origName;
  }
  
  function isHidden( elem, el ) {
  	// isHidden might be called from jQuery#filter function;
  	// in that case, element will be second argument
  	elem = el || elem;
  	return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
  }
  
  // NOTE: we've included the "window" in window.getComputedStyle
  // because jsdom on node.js will break without it.
  function getStyles( elem ) {
  	return window.getComputedStyle( elem, null );
  }
  
  function showHide( elements, show ) {
  	var display, elem, hidden,
  		values = [],
  		index = 0,
  		length = elements.length;
  
  	for ( ; index < length; index++ ) {
  		elem = elements[ index ];
  		if ( !elem.style ) {
  			continue;
  		}
  
  		values[ index ] = data_priv.get( elem, "olddisplay" );
  		display = elem.style.display;
  		if ( show ) {
  			// Reset the inline display of this element to learn if it is
  			// being hidden by cascaded rules or not
  			if ( !values[ index ] && display === "none" ) {
  				elem.style.display = "";
  			}
  
  			// Set elements which have been overridden with display: none
  			// in a stylesheet to whatever the default browser style is
  			// for such an element
  			if ( elem.style.display === "" && isHidden( elem ) ) {
  				values[ index ] = data_priv.access( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
  			}
  		} else {
  
  			if ( !values[ index ] ) {
  				hidden = isHidden( elem );
  
  				if ( display && display !== "none" || !hidden ) {
  					data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css(elem, "display") );
  				}
  			}
  		}
  	}
  
  	// Set the display of most of the elements in a second loop
  	// to avoid the constant reflow
  	for ( index = 0; index < length; index++ ) {
  		elem = elements[ index ];
  		if ( !elem.style ) {
  			continue;
  		}
  		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
  			elem.style.display = show ? values[ index ] || "" : "none";
  		}
  	}
  
  	return elements;
  }
  
  jQuery.fn.extend({
  	css: function( name, value ) {
  		return jQuery.access( this, function( elem, name, value ) {
  			var styles, len,
  				map = {},
  				i = 0;
  
  			if ( jQuery.isArray( name ) ) {
  				styles = getStyles( elem );
  				len = name.length;
  
  				for ( ; i < len; i++ ) {
  					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
  				}
  
  				return map;
  			}
  
  			return value !== undefined ?
  				jQuery.style( elem, name, value ) :
  				jQuery.css( elem, name );
  		}, name, value, arguments.length > 1 );
  	},
  	show: function() {
  		return showHide( this, true );
  	},
  	hide: function() {
  		return showHide( this );
  	},
  	toggle: function( state ) {
  		if ( typeof state === "boolean" ) {
  			return state ? this.show() : this.hide();
  		}
  
  		return this.each(function() {
  			if ( isHidden( this ) ) {
  				jQuery( this ).show();
  			} else {
  				jQuery( this ).hide();
  			}
  		});
  	}
  });
  
  jQuery.extend({
  	// Add in style property hooks for overriding the default
  	// behavior of getting and setting a style property
  	cssHooks: {
  		opacity: {
  			get: function( elem, computed ) {
  				if ( computed ) {
  					// We should always get a number back from opacity
  					var ret = curCSS( elem, "opacity" );
  					return ret === "" ? "1" : ret;
  				}
  			}
  		}
  	},
  
  	// Don't automatically add "px" to these possibly-unitless properties
  	cssNumber: {
  		"columnCount": true,
  		"fillOpacity": true,
  		"fontWeight": true,
  		"lineHeight": true,
  		"opacity": true,
  		"order": true,
  		"orphans": true,
  		"widows": true,
  		"zIndex": true,
  		"zoom": true
  	},
  
  	// Add in properties whose names you wish to fix before
  	// setting or getting the value
  	cssProps: {
  		// normalize float css property
  		"float": "cssFloat"
  	},
  
  	// Get and set the style property on a DOM Node
  	style: function( elem, name, value, extra ) {
  		// Don't set styles on text and comment nodes
  		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
  			return;
  		}
  
  		// Make sure that we're working with the right name
  		var ret, type, hooks,
  			origName = jQuery.camelCase( name ),
  			style = elem.style;
  
  		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
  
  		// gets hook for the prefixed version
  		// followed by the unprefixed version
  		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  
  		// Check if we're setting a value
  		if ( value !== undefined ) {
  			type = typeof value;
  
  			// convert relative number strings (+= or -=) to relative numbers. #7345
  			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
  				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
  				// Fixes bug #9237
  				type = "number";
  			}
  
  			// Make sure that NaN and null values aren't set. See: #7116
  			if ( value == null || type === "number" && isNaN( value ) ) {
  				return;
  			}
  
  			// If a number was passed in, add 'px' to the (except for certain CSS properties)
  			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
  				value += "px";
  			}
  
  			// Fixes #8908, it can be done more correctly by specifying setters in cssHooks,
  			// but it would mean to define eight (for every problematic property) identical functions
  			if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
  				style[ name ] = "inherit";
  			}
  
  			// If a hook was provided, use that value, otherwise just set the specified value
  			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
  				style[ name ] = value;
  			}
  
  		} else {
  			// If a hook was provided get the non-computed value from there
  			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
  				return ret;
  			}
  
  			// Otherwise just get the value from the style object
  			return style[ name ];
  		}
  	},
  
  	css: function( elem, name, extra, styles ) {
  		var val, num, hooks,
  			origName = jQuery.camelCase( name );
  
  		// Make sure that we're working with the right name
  		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
  
  		// gets hook for the prefixed version
  		// followed by the unprefixed version
  		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
  
  		// If a hook was provided get the computed value from there
  		if ( hooks && "get" in hooks ) {
  			val = hooks.get( elem, true, extra );
  		}
  
  		// Otherwise, if a way to get the computed value exists, use that
  		if ( val === undefined ) {
  			val = curCSS( elem, name, styles );
  		}
  
  		//convert "normal" to computed value
  		if ( val === "normal" && name in cssNormalTransform ) {
  			val = cssNormalTransform[ name ];
  		}
  
  		// Return, converting to number if forced or a qualifier was provided and val looks numeric
  		if ( extra === "" || extra ) {
  			num = parseFloat( val );
  			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
  		}
  		return val;
  	}
  });
  
  curCSS = function( elem, name, _computed ) {
  	var width, minWidth, maxWidth,
  		computed = _computed || getStyles( elem ),
  
  		// Support: IE9
  		// getPropertyValue is only needed for .css('filter') in IE9, see #12537
  		ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
  		style = elem.style;
  
  	if ( computed ) {
  
  		if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
  			ret = jQuery.style( elem, name );
  		}
  
  		// Support: Safari 5.1
  		// A tribute to the "awesome hack by Dean Edwards"
  		// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
  		// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
  		if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
  
  			// Remember the original values
  			width = style.width;
  			minWidth = style.minWidth;
  			maxWidth = style.maxWidth;
  
  			// Put in the new values to get a computed value out
  			style.minWidth = style.maxWidth = style.width = ret;
  			ret = computed.width;
  
  			// Revert the changed values
  			style.width = width;
  			style.minWidth = minWidth;
  			style.maxWidth = maxWidth;
  		}
  	}
  
  	return ret;
  };
  
  
  function setPositiveNumber( elem, value, subtract ) {
  	var matches = rnumsplit.exec( value );
  	return matches ?
  		// Guard against undefined "subtract", e.g., when used as in cssHooks
  		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
  		value;
  }
  
  function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
  	var i = extra === ( isBorderBox ? "border" : "content" ) ?
  		// If we already have the right measurement, avoid augmentation
  		4 :
  		// Otherwise initialize for horizontal or vertical properties
  		name === "width" ? 1 : 0,
  
  		val = 0;
  
  	for ( ; i < 4; i += 2 ) {
  		// both box models exclude margin, so add it if we want it
  		if ( extra === "margin" ) {
  			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
  		}
  
  		if ( isBorderBox ) {
  			// border-box includes padding, so remove it if we want content
  			if ( extra === "content" ) {
  				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  			}
  
  			// at this point, extra isn't border nor margin, so remove border
  			if ( extra !== "margin" ) {
  				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  			}
  		} else {
  			// at this point, extra isn't content, so add padding
  			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
  
  			// at this point, extra isn't content nor padding, so add border
  			if ( extra !== "padding" ) {
  				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
  			}
  		}
  	}
  
  	return val;
  }
  
  function getWidthOrHeight( elem, name, extra ) {
  
  	// Start with offset property, which is equivalent to the border-box value
  	var valueIsBorderBox = true,
  		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
  		styles = getStyles( elem ),
  		isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
  
  	// some non-html elements return undefined for offsetWidth, so check for null/undefined
  	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
  	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
  	if ( val <= 0 || val == null ) {
  		// Fall back to computed then uncomputed css if necessary
  		val = curCSS( elem, name, styles );
  		if ( val < 0 || val == null ) {
  			val = elem.style[ name ];
  		}
  
  		// Computed unit is not pixels. Stop here and return.
  		if ( rnumnonpx.test(val) ) {
  			return val;
  		}
  
  		// we need the check for style in case a browser which returns unreliable values
  		// for getComputedStyle silently falls back to the reliable elem.style
  		valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
  
  		// Normalize "", auto, and prepare for extra
  		val = parseFloat( val ) || 0;
  	}
  
  	// use the active box-sizing model to add/subtract irrelevant styles
  	return ( val +
  		augmentWidthOrHeight(
  			elem,
  			name,
  			extra || ( isBorderBox ? "border" : "content" ),
  			valueIsBorderBox,
  			styles
  		)
  	) + "px";
  }
  
  // Try to determine the default display value of an element
  function css_defaultDisplay( nodeName ) {
  	var doc = document,
  		display = elemdisplay[ nodeName ];
  
  	if ( !display ) {
  		display = actualDisplay( nodeName, doc );
  
  		// If the simple way fails, read from inside an iframe
  		if ( display === "none" || !display ) {
  			// Use the already-created iframe if possible
  			iframe = ( iframe ||
  				jQuery("<iframe frameborder='0' width='0' height='0'/>")
  				.css( "cssText", "display:block !important" )
  			).appendTo( doc.documentElement );
  
  			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
  			doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
  			doc.write("<!doctype html><html><body>");
  			doc.close();
  
  			display = actualDisplay( nodeName, doc );
  			iframe.detach();
  		}
  
  		// Store the correct default display
  		elemdisplay[ nodeName ] = display;
  	}
  
  	return display;
  }
  
  // Called ONLY from within css_defaultDisplay
  function actualDisplay( name, doc ) {
  	var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
  		display = jQuery.css( elem[0], "display" );
  	elem.remove();
  	return display;
  }
  
  jQuery.each([ "height", "width" ], function( i, name ) {
  	jQuery.cssHooks[ name ] = {
  		get: function( elem, computed, extra ) {
  			if ( computed ) {
  				// certain elements can have dimension info if we invisibly show them
  				// however, it must have a current display style that would benefit from this
  				return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
  					jQuery.swap( elem, cssShow, function() {
  						return getWidthOrHeight( elem, name, extra );
  					}) :
  					getWidthOrHeight( elem, name, extra );
  			}
  		},
  
  		set: function( elem, value, extra ) {
  			var styles = extra && getStyles( elem );
  			return setPositiveNumber( elem, value, extra ?
  				augmentWidthOrHeight(
  					elem,
  					name,
  					extra,
  					jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
  					styles
  				) : 0
  			);
  		}
  	};
  });
  
  // These hooks cannot be added until DOM ready because the support test
  // for it is not run until after DOM ready
  jQuery(function() {
  	// Support: Android 2.3
  	if ( !jQuery.support.reliableMarginRight ) {
  		jQuery.cssHooks.marginRight = {
  			get: function( elem, computed ) {
  				if ( computed ) {
  					// Support: Android 2.3
  					// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
  					// Work around by temporarily setting element display to inline-block
  					return jQuery.swap( elem, { "display": "inline-block" },
  						curCSS, [ elem, "marginRight" ] );
  				}
  			}
  		};
  	}
  
  	// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
  	// getComputedStyle returns percent when specified for top/left/bottom/right
  	// rather than make the css module depend on the offset module, we just check for it here
  	if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
  		jQuery.each( [ "top", "left" ], function( i, prop ) {
  			jQuery.cssHooks[ prop ] = {
  				get: function( elem, computed ) {
  					if ( computed ) {
  						computed = curCSS( elem, prop );
  						// if curCSS returns percentage, fallback to offset
  						return rnumnonpx.test( computed ) ?
  							jQuery( elem ).position()[ prop ] + "px" :
  							computed;
  					}
  				}
  			};
  		});
  	}
  
  });
  
  if ( jQuery.expr && jQuery.expr.filters ) {
  	jQuery.expr.filters.hidden = function( elem ) {
  		// Support: Opera <= 12.12
  		// Opera reports offsetWidths and offsetHeights less than zero on some elements
  		return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
  	};
  
  	jQuery.expr.filters.visible = function( elem ) {
  		return !jQuery.expr.filters.hidden( elem );
  	};
  }
  
  // These hooks are used by animate to expand properties
  jQuery.each({
  	margin: "",
  	padding: "",
  	border: "Width"
  }, function( prefix, suffix ) {
  	jQuery.cssHooks[ prefix + suffix ] = {
  		expand: function( value ) {
  			var i = 0,
  				expanded = {},
  
  				// assumes a single number if not a string
  				parts = typeof value === "string" ? value.split(" ") : [ value ];
  
  			for ( ; i < 4; i++ ) {
  				expanded[ prefix + cssExpand[ i ] + suffix ] =
  					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
  			}
  
  			return expanded;
  		}
  	};
  
  	if ( !rmargin.test( prefix ) ) {
  		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
  	}
  });
  var r20 = /%20/g,
  	rbracket = /\[\]$/,
  	rCRLF = /\r?\n/g,
  	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
  	rsubmittable = /^(?:input|select|textarea|keygen)/i;
  
  jQuery.fn.extend({
  	serialize: function() {
  		return jQuery.param( this.serializeArray() );
  	},
  	serializeArray: function() {
  		return this.map(function(){
  			// Can add propHook for "elements" to filter or add form elements
  			var elements = jQuery.prop( this, "elements" );
  			return elements ? jQuery.makeArray( elements ) : this;
  		})
  		.filter(function(){
  			var type = this.type;
  			// Use .is(":disabled") so that fieldset[disabled] works
  			return this.name && !jQuery( this ).is( ":disabled" ) &&
  				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
  				( this.checked || !manipulation_rcheckableType.test( type ) );
  		})
  		.map(function( i, elem ){
  			var val = jQuery( this ).val();
  
  			return val == null ?
  				null :
  				jQuery.isArray( val ) ?
  					jQuery.map( val, function( val ){
  						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  					}) :
  					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
  		}).get();
  	}
  });
  
  //Serialize an array of form elements or a set of
  //key/values into a query string
  jQuery.param = function( a, traditional ) {
  	var prefix,
  		s = [],
  		add = function( key, value ) {
  			// If value is a function, invoke it and return its value
  			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
  			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
  		};
  
  	// Set traditional to true for jQuery <= 1.3.2 behavior.
  	if ( traditional === undefined ) {
  		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
  	}
  
  	// If an array was passed in, assume that it is an array of form elements.
  	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
  		// Serialize the form elements
  		jQuery.each( a, function() {
  			add( this.name, this.value );
  		});
  
  	} else {
  		// If traditional, encode the "old" way (the way 1.3.2 or older
  		// did it), otherwise encode params recursively.
  		for ( prefix in a ) {
  			buildParams( prefix, a[ prefix ], traditional, add );
  		}
  	}
  
  	// Return the resulting serialization
  	return s.join( "&" ).replace( r20, "+" );
  };
  
  function buildParams( prefix, obj, traditional, add ) {
  	var name;
  
  	if ( jQuery.isArray( obj ) ) {
  		// Serialize array item.
  		jQuery.each( obj, function( i, v ) {
  			if ( traditional || rbracket.test( prefix ) ) {
  				// Treat each array item as a scalar.
  				add( prefix, v );
  
  			} else {
  				// Item is non-scalar (array or object), encode its numeric index.
  				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
  			}
  		});
  
  	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
  		// Serialize object item.
  		for ( name in obj ) {
  			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
  		}
  
  	} else {
  		// Serialize scalar item.
  		add( prefix, obj );
  	}
  }
  jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
  	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
  	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
  
  	// Handle event binding
  	jQuery.fn[ name ] = function( data, fn ) {
  		return arguments.length > 0 ?
  			this.on( name, null, data, fn ) :
  			this.trigger( name );
  	};
  });
  
  jQuery.fn.extend({
  	hover: function( fnOver, fnOut ) {
  		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
  	},
  
  	bind: function( types, data, fn ) {
  		return this.on( types, null, data, fn );
  	},
  	unbind: function( types, fn ) {
  		return this.off( types, null, fn );
  	},
  
  	delegate: function( selector, types, data, fn ) {
  		return this.on( types, selector, data, fn );
  	},
  	undelegate: function( selector, types, fn ) {
  		// ( namespace ) or ( selector, types [, fn] )
  		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
  	}
  });
  var
  	// Document location
  	ajaxLocParts,
  	ajaxLocation,
  
  	ajax_nonce = jQuery.now(),
  
  	ajax_rquery = /\?/,
  	rhash = /#.*$/,
  	rts = /([?&])_=[^&]*/,
  	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
  	// #7653, #8125, #8152: local protocol detection
  	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
  	rnoContent = /^(?:GET|HEAD)$/,
  	rprotocol = /^\/\//,
  	rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
  
  	// Keep a copy of the old load method
  	_load = jQuery.fn.load,
  
  	/* Prefilters
  	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
  	 * 2) These are called:
  	 *    - BEFORE asking for a transport
  	 *    - AFTER param serialization (s.data is a string if s.processData is true)
  	 * 3) key is the dataType
  	 * 4) the catchall symbol "*" can be used
  	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
  	 */
  	prefilters = {},
  
  	/* Transports bindings
  	 * 1) key is the dataType
  	 * 2) the catchall symbol "*" can be used
  	 * 3) selection will start with transport dataType and THEN go to "*" if needed
  	 */
  	transports = {},
  
  	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
  	allTypes = "*/".concat("*");
  
  // #8138, IE may throw an exception when accessing
  // a field from window.location if document.domain has been set
  try {
  	ajaxLocation = location.href;
  } catch( e ) {
  	// Use the href attribute of an A element
  	// since IE will modify it given document.location
  	ajaxLocation = document.createElement( "a" );
  	ajaxLocation.href = "";
  	ajaxLocation = ajaxLocation.href;
  }
  
  // Segment location into parts
  ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
  
  // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
  function addToPrefiltersOrTransports( structure ) {
  
  	// dataTypeExpression is optional and defaults to "*"
  	return function( dataTypeExpression, func ) {
  
  		if ( typeof dataTypeExpression !== "string" ) {
  			func = dataTypeExpression;
  			dataTypeExpression = "*";
  		}
  
  		var dataType,
  			i = 0,
  			dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
  
  		if ( jQuery.isFunction( func ) ) {
  			// For each dataType in the dataTypeExpression
  			while ( (dataType = dataTypes[i++]) ) {
  				// Prepend if requested
  				if ( dataType[0] === "+" ) {
  					dataType = dataType.slice( 1 ) || "*";
  					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
  
  				// Otherwise append
  				} else {
  					(structure[ dataType ] = structure[ dataType ] || []).push( func );
  				}
  			}
  		}
  	};
  }
  
  // Base inspection function for prefilters and transports
  function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
  
  	var inspected = {},
  		seekingTransport = ( structure === transports );
  
  	function inspect( dataType ) {
  		var selected;
  		inspected[ dataType ] = true;
  		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
  			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
  			if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
  				options.dataTypes.unshift( dataTypeOrTransport );
  				inspect( dataTypeOrTransport );
  				return false;
  			} else if ( seekingTransport ) {
  				return !( selected = dataTypeOrTransport );
  			}
  		});
  		return selected;
  	}
  
  	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
  }
  
  // A special extend for ajax options
  // that takes "flat" options (not to be deep extended)
  // Fixes #9887
  function ajaxExtend( target, src ) {
  	var key, deep,
  		flatOptions = jQuery.ajaxSettings.flatOptions || {};
  
  	for ( key in src ) {
  		if ( src[ key ] !== undefined ) {
  			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
  		}
  	}
  	if ( deep ) {
  		jQuery.extend( true, target, deep );
  	}
  
  	return target;
  }
  
  jQuery.fn.load = function( url, params, callback ) {
  	if ( typeof url !== "string" && _load ) {
  		return _load.apply( this, arguments );
  	}
  
  	var selector, type, response,
  		self = this,
  		off = url.indexOf(" ");
  
  	if ( off >= 0 ) {
  		selector = url.slice( off );
  		url = url.slice( 0, off );
  	}
  
  	// If it's a function
  	if ( jQuery.isFunction( params ) ) {
  
  		// We assume that it's the callback
  		callback = params;
  		params = undefined;
  
  	// Otherwise, build a param string
  	} else if ( params && typeof params === "object" ) {
  		type = "POST";
  	}
  
  	// If we have elements to modify, make the request
  	if ( self.length > 0 ) {
  		jQuery.ajax({
  			url: url,
  
  			// if "type" variable is undefined, then "GET" method will be used
  			type: type,
  			dataType: "html",
  			data: params
  		}).done(function( responseText ) {
  
  			// Save response for use in complete callback
  			response = arguments;
  
  			self.html( selector ?
  
  				// If a selector was specified, locate the right elements in a dummy div
  				// Exclude scripts to avoid IE 'Permission Denied' errors
  				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
  
  				// Otherwise use the full result
  				responseText );
  
  		}).complete( callback && function( jqXHR, status ) {
  			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
  		});
  	}
  
  	return this;
  };
  
  // Attach a bunch of functions for handling common AJAX events
  jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
  	jQuery.fn[ type ] = function( fn ){
  		return this.on( type, fn );
  	};
  });
  
  jQuery.extend({
  
  	// Counter for holding the number of active queries
  	active: 0,
  
  	// Last-Modified header cache for next request
  	lastModified: {},
  	etag: {},
  
  	ajaxSettings: {
  		url: ajaxLocation,
  		type: "GET",
  		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
  		global: true,
  		processData: true,
  		async: true,
  		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
  		/*
  		timeout: 0,
  		data: null,
  		dataType: null,
  		username: null,
  		password: null,
  		cache: null,
  		throws: false,
  		traditional: false,
  		headers: {},
  		*/
  
  		accepts: {
  			"*": allTypes,
  			text: "text/plain",
  			html: "text/html",
  			xml: "application/xml, text/xml",
  			json: "application/json, text/javascript"
  		},
  
  		contents: {
  			xml: /xml/,
  			html: /html/,
  			json: /json/
  		},
  
  		responseFields: {
  			xml: "responseXML",
  			text: "responseText",
  			json: "responseJSON"
  		},
  
  		// Data converters
  		// Keys separate source (or catchall "*") and destination types with a single space
  		converters: {
  
  			// Convert anything to text
  			"* text": String,
  
  			// Text to html (true = no transformation)
  			"text html": true,
  
  			// Evaluate text as a json expression
  			"text json": jQuery.parseJSON,
  
  			// Parse text as xml
  			"text xml": jQuery.parseXML
  		},
  
  		// For options that shouldn't be deep extended:
  		// you can add your own custom options here if
  		// and when you create one that shouldn't be
  		// deep extended (see ajaxExtend)
  		flatOptions: {
  			url: true,
  			context: true
  		}
  	},
  
  	// Creates a full fledged settings object into target
  	// with both ajaxSettings and settings fields.
  	// If target is omitted, writes into ajaxSettings.
  	ajaxSetup: function( target, settings ) {
  		return settings ?
  
  			// Building a settings object
  			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
  
  			// Extending ajaxSettings
  			ajaxExtend( jQuery.ajaxSettings, target );
  	},
  
  	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
  	ajaxTransport: addToPrefiltersOrTransports( transports ),
  
  	// Main method
  	ajax: function( url, options ) {
  
  		// If url is an object, simulate pre-1.5 signature
  		if ( typeof url === "object" ) {
  			options = url;
  			url = undefined;
  		}
  
  		// Force options to be an object
  		options = options || {};
  
  		var transport,
  			// URL without anti-cache param
  			cacheURL,
  			// Response headers
  			responseHeadersString,
  			responseHeaders,
  			// timeout handle
  			timeoutTimer,
  			// Cross-domain detection vars
  			parts,
  			// To know if global events are to be dispatched
  			fireGlobals,
  			// Loop variable
  			i,
  			// Create the final options object
  			s = jQuery.ajaxSetup( {}, options ),
  			// Callbacks context
  			callbackContext = s.context || s,
  			// Context for global events is callbackContext if it is a DOM node or jQuery collection
  			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
  				jQuery( callbackContext ) :
  				jQuery.event,
  			// Deferreds
  			deferred = jQuery.Deferred(),
  			completeDeferred = jQuery.Callbacks("once memory"),
  			// Status-dependent callbacks
  			statusCode = s.statusCode || {},
  			// Headers (they are sent all at once)
  			requestHeaders = {},
  			requestHeadersNames = {},
  			// The jqXHR state
  			state = 0,
  			// Default abort message
  			strAbort = "canceled",
  			// Fake xhr
  			jqXHR = {
  				readyState: 0,
  
  				// Builds headers hashtable if needed
  				getResponseHeader: function( key ) {
  					var match;
  					if ( state === 2 ) {
  						if ( !responseHeaders ) {
  							responseHeaders = {};
  							while ( (match = rheaders.exec( responseHeadersString )) ) {
  								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
  							}
  						}
  						match = responseHeaders[ key.toLowerCase() ];
  					}
  					return match == null ? null : match;
  				},
  
  				// Raw string
  				getAllResponseHeaders: function() {
  					return state === 2 ? responseHeadersString : null;
  				},
  
  				// Caches the header
  				setRequestHeader: function( name, value ) {
  					var lname = name.toLowerCase();
  					if ( !state ) {
  						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
  						requestHeaders[ name ] = value;
  					}
  					return this;
  				},
  
  				// Overrides response content-type header
  				overrideMimeType: function( type ) {
  					if ( !state ) {
  						s.mimeType = type;
  					}
  					return this;
  				},
  
  				// Status-dependent callbacks
  				statusCode: function( map ) {
  					var code;
  					if ( map ) {
  						if ( state < 2 ) {
  							for ( code in map ) {
  								// Lazy-add the new callback in a way that preserves old ones
  								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
  							}
  						} else {
  							// Execute the appropriate callbacks
  							jqXHR.always( map[ jqXHR.status ] );
  						}
  					}
  					return this;
  				},
  
  				// Cancel the request
  				abort: function( statusText ) {
  					var finalText = statusText || strAbort;
  					if ( transport ) {
  						transport.abort( finalText );
  					}
  					done( 0, finalText );
  					return this;
  				}
  			};
  
  		// Attach deferreds
  		deferred.promise( jqXHR ).complete = completeDeferred.add;
  		jqXHR.success = jqXHR.done;
  		jqXHR.error = jqXHR.fail;
  
  		// Remove hash character (#7531: and string promotion)
  		// Add protocol if not provided (prefilters might expect it)
  		// Handle falsy url in the settings object (#10093: consistency with old signature)
  		// We also use the url parameter if available
  		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
  			.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
  
  		// Alias method option to type as per ticket #12004
  		s.type = options.method || options.type || s.method || s.type;
  
  		// Extract dataTypes list
  		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
  
  		// A cross-domain request is in order when we have a protocol:host:port mismatch
  		if ( s.crossDomain == null ) {
  			parts = rurl.exec( s.url.toLowerCase() );
  			s.crossDomain = !!( parts &&
  				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
  					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
  						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
  			);
  		}
  
  		// Convert data if not already a string
  		if ( s.data && s.processData && typeof s.data !== "string" ) {
  			s.data = jQuery.param( s.data, s.traditional );
  		}
  
  		// Apply prefilters
  		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
  
  		// If request was aborted inside a prefilter, stop there
  		if ( state === 2 ) {
  			return jqXHR;
  		}
  
  		// We can fire global events as of now if asked to
  		fireGlobals = s.global;
  
  		// Watch for a new set of requests
  		if ( fireGlobals && jQuery.active++ === 0 ) {
  			jQuery.event.trigger("ajaxStart");
  		}
  
  		// Uppercase the type
  		s.type = s.type.toUpperCase();
  
  		// Determine if request has content
  		s.hasContent = !rnoContent.test( s.type );
  
  		// Save the URL in case we're toying with the If-Modified-Since
  		// and/or If-None-Match header later on
  		cacheURL = s.url;
  
  		// More options handling for requests with no content
  		if ( !s.hasContent ) {
  
  			// If data is available, append data to url
  			if ( s.data ) {
  				cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
  				// #9682: remove data so that it's not used in an eventual retry
  				delete s.data;
  			}
  
  			// Add anti-cache in url if needed
  			if ( s.cache === false ) {
  				s.url = rts.test( cacheURL ) ?
  
  					// If there is already a '_' parameter, set its value
  					cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
  
  					// Otherwise add one to the end
  					cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
  			}
  		}
  
  		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  		if ( s.ifModified ) {
  			if ( jQuery.lastModified[ cacheURL ] ) {
  				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
  			}
  			if ( jQuery.etag[ cacheURL ] ) {
  				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
  			}
  		}
  
  		// Set the correct header, if data is being sent
  		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
  			jqXHR.setRequestHeader( "Content-Type", s.contentType );
  		}
  
  		// Set the Accepts header for the server, depending on the dataType
  		jqXHR.setRequestHeader(
  			"Accept",
  			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
  				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
  				s.accepts[ "*" ]
  		);
  
  		// Check for headers option
  		for ( i in s.headers ) {
  			jqXHR.setRequestHeader( i, s.headers[ i ] );
  		}
  
  		// Allow custom headers/mimetypes and early abort
  		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
  			// Abort if not done already and return
  			return jqXHR.abort();
  		}
  
  		// aborting is no longer a cancellation
  		strAbort = "abort";
  
  		// Install callbacks on deferreds
  		for ( i in { success: 1, error: 1, complete: 1 } ) {
  			jqXHR[ i ]( s[ i ] );
  		}
  
  		// Get transport
  		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
  
  		// If no transport, we auto-abort
  		if ( !transport ) {
  			done( -1, "No Transport" );
  		} else {
  			jqXHR.readyState = 1;
  
  			// Send global event
  			if ( fireGlobals ) {
  				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
  			}
  			// Timeout
  			if ( s.async && s.timeout > 0 ) {
  				timeoutTimer = setTimeout(function() {
  					jqXHR.abort("timeout");
  				}, s.timeout );
  			}
  
  			try {
  				state = 1;
  				transport.send( requestHeaders, done );
  			} catch ( e ) {
  				// Propagate exception as error if not done
  				if ( state < 2 ) {
  					done( -1, e );
  				// Simply rethrow otherwise
  				} else {
  					throw e;
  				}
  			}
  		}
  
  		// Callback for when everything is done
  		function done( status, nativeStatusText, responses, headers ) {
  			var isSuccess, success, error, response, modified,
  				statusText = nativeStatusText;
  
  			// Called once
  			if ( state === 2 ) {
  				return;
  			}
  
  			// State is "done" now
  			state = 2;
  
  			// Clear timeout if it exists
  			if ( timeoutTimer ) {
  				clearTimeout( timeoutTimer );
  			}
  
  			// Dereference transport for early garbage collection
  			// (no matter how long the jqXHR object will be used)
  			transport = undefined;
  
  			// Cache response headers
  			responseHeadersString = headers || "";
  
  			// Set readyState
  			jqXHR.readyState = status > 0 ? 4 : 0;
  
  			// Determine if successful
  			isSuccess = status >= 200 && status < 300 || status === 304;
  
  			// Get response data
  			if ( responses ) {
  				response = ajaxHandleResponses( s, jqXHR, responses );
  			}
  
  			// Convert no matter what (that way responseXXX fields are always set)
  			response = ajaxConvert( s, response, jqXHR, isSuccess );
  
  			// If successful, handle type chaining
  			if ( isSuccess ) {
  
  				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
  				if ( s.ifModified ) {
  					modified = jqXHR.getResponseHeader("Last-Modified");
  					if ( modified ) {
  						jQuery.lastModified[ cacheURL ] = modified;
  					}
  					modified = jqXHR.getResponseHeader("etag");
  					if ( modified ) {
  						jQuery.etag[ cacheURL ] = modified;
  					}
  				}
  
  				// if no content
  				if ( status === 204 || s.type === "HEAD" ) {
  					statusText = "nocontent";
  
  				// if not modified
  				} else if ( status === 304 ) {
  					statusText = "notmodified";
  
  				// If we have data, let's convert it
  				} else {
  					statusText = response.state;
  					success = response.data;
  					error = response.error;
  					isSuccess = !error;
  				}
  			} else {
  				// We extract error from statusText
  				// then normalize statusText and status for non-aborts
  				error = statusText;
  				if ( status || !statusText ) {
  					statusText = "error";
  					if ( status < 0 ) {
  						status = 0;
  					}
  				}
  			}
  
  			// Set data for the fake xhr object
  			jqXHR.status = status;
  			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
  
  			// Success/Error
  			if ( isSuccess ) {
  				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
  			} else {
  				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
  			}
  
  			// Status-dependent callbacks
  			jqXHR.statusCode( statusCode );
  			statusCode = undefined;
  
  			if ( fireGlobals ) {
  				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
  					[ jqXHR, s, isSuccess ? success : error ] );
  			}
  
  			// Complete
  			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
  
  			if ( fireGlobals ) {
  				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
  				// Handle the global AJAX counter
  				if ( !( --jQuery.active ) ) {
  					jQuery.event.trigger("ajaxStop");
  				}
  			}
  		}
  
  		return jqXHR;
  	},
  
  	getJSON: function( url, data, callback ) {
  		return jQuery.get( url, data, callback, "json" );
  	},
  
  	getScript: function( url, callback ) {
  		return jQuery.get( url, undefined, callback, "script" );
  	}
  });
  
  jQuery.each( [ "get", "post" ], function( i, method ) {
  	jQuery[ method ] = function( url, data, callback, type ) {
  		// shift arguments if data argument was omitted
  		if ( jQuery.isFunction( data ) ) {
  			type = type || callback;
  			callback = data;
  			data = undefined;
  		}
  
  		return jQuery.ajax({
  			url: url,
  			type: method,
  			dataType: type,
  			data: data,
  			success: callback
  		});
  	};
  });
  
  /* Handles responses to an ajax request:
   * - finds the right dataType (mediates between content-type and expected dataType)
   * - returns the corresponding response
   */
  function ajaxHandleResponses( s, jqXHR, responses ) {
  
  	var ct, type, finalDataType, firstDataType,
  		contents = s.contents,
  		dataTypes = s.dataTypes;
  
  	// Remove auto dataType and get content-type in the process
  	while( dataTypes[ 0 ] === "*" ) {
  		dataTypes.shift();
  		if ( ct === undefined ) {
  			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
  		}
  	}
  
  	// Check if we're dealing with a known content-type
  	if ( ct ) {
  		for ( type in contents ) {
  			if ( contents[ type ] && contents[ type ].test( ct ) ) {
  				dataTypes.unshift( type );
  				break;
  			}
  		}
  	}
  
  	// Check to see if we have a response for the expected dataType
  	if ( dataTypes[ 0 ] in responses ) {
  		finalDataType = dataTypes[ 0 ];
  	} else {
  		// Try convertible dataTypes
  		for ( type in responses ) {
  			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
  				finalDataType = type;
  				break;
  			}
  			if ( !firstDataType ) {
  				firstDataType = type;
  			}
  		}
  		// Or just use first one
  		finalDataType = finalDataType || firstDataType;
  	}
  
  	// If we found a dataType
  	// We add the dataType to the list if needed
  	// and return the corresponding response
  	if ( finalDataType ) {
  		if ( finalDataType !== dataTypes[ 0 ] ) {
  			dataTypes.unshift( finalDataType );
  		}
  		return responses[ finalDataType ];
  	}
  }
  
  /* Chain conversions given the request and the original response
   * Also sets the responseXXX fields on the jqXHR instance
   */
  function ajaxConvert( s, response, jqXHR, isSuccess ) {
  	var conv2, current, conv, tmp, prev,
  		converters = {},
  		// Work with a copy of dataTypes in case we need to modify it for conversion
  		dataTypes = s.dataTypes.slice();
  
  	// Create converters map with lowercased keys
  	if ( dataTypes[ 1 ] ) {
  		for ( conv in s.converters ) {
  			converters[ conv.toLowerCase() ] = s.converters[ conv ];
  		}
  	}
  
  	current = dataTypes.shift();
  
  	// Convert to each sequential dataType
  	while ( current ) {
  
  		if ( s.responseFields[ current ] ) {
  			jqXHR[ s.responseFields[ current ] ] = response;
  		}
  
  		// Apply the dataFilter if provided
  		if ( !prev && isSuccess && s.dataFilter ) {
  			response = s.dataFilter( response, s.dataType );
  		}
  
  		prev = current;
  		current = dataTypes.shift();
  
  		if ( current ) {
  
  		// There's only work to do if current dataType is non-auto
  			if ( current === "*" ) {
  
  				current = prev;
  
  			// Convert response if prev dataType is non-auto and differs from current
  			} else if ( prev !== "*" && prev !== current ) {
  
  				// Seek a direct converter
  				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
  
  				// If none found, seek a pair
  				if ( !conv ) {
  					for ( conv2 in converters ) {
  
  						// If conv2 outputs current
  						tmp = conv2.split( " " );
  						if ( tmp[ 1 ] === current ) {
  
  							// If prev can be converted to accepted input
  							conv = converters[ prev + " " + tmp[ 0 ] ] ||
  								converters[ "* " + tmp[ 0 ] ];
  							if ( conv ) {
  								// Condense equivalence converters
  								if ( conv === true ) {
  									conv = converters[ conv2 ];
  
  								// Otherwise, insert the intermediate dataType
  								} else if ( converters[ conv2 ] !== true ) {
  									current = tmp[ 0 ];
  									dataTypes.unshift( tmp[ 1 ] );
  								}
  								break;
  							}
  						}
  					}
  				}
  
  				// Apply converter (if not an equivalence)
  				if ( conv !== true ) {
  
  					// Unless errors are allowed to bubble, catch and return them
  					if ( conv && s[ "throws" ] ) {
  						response = conv( response );
  					} else {
  						try {
  							response = conv( response );
  						} catch ( e ) {
  							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
  						}
  					}
  				}
  			}
  		}
  	}
  
  	return { state: "success", data: response };
  }
  // Install script dataType
  jQuery.ajaxSetup({
  	accepts: {
  		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
  	},
  	contents: {
  		script: /(?:java|ecma)script/
  	},
  	converters: {
  		"text script": function( text ) {
  			jQuery.globalEval( text );
  			return text;
  		}
  	}
  });
  
  // Handle cache's special case and crossDomain
  jQuery.ajaxPrefilter( "script", function( s ) {
  	if ( s.cache === undefined ) {
  		s.cache = false;
  	}
  	if ( s.crossDomain ) {
  		s.type = "GET";
  	}
  });
  
  // Bind script tag hack transport
  jQuery.ajaxTransport( "script", function( s ) {
  	// This transport only deals with cross domain requests
  	if ( s.crossDomain ) {
  		var script, callback;
  		return {
  			send: function( _, complete ) {
  				script = jQuery("<script>").prop({
  					async: true,
  					charset: s.scriptCharset,
  					src: s.url
  				}).on(
  					"load error",
  					callback = function( evt ) {
  						script.remove();
  						callback = null;
  						if ( evt ) {
  							complete( evt.type === "error" ? 404 : 200, evt.type );
  						}
  					}
  				);
  				document.head.appendChild( script[ 0 ] );
  			},
  			abort: function() {
  				if ( callback ) {
  					callback();
  				}
  			}
  		};
  	}
  });
  var oldCallbacks = [],
  	rjsonp = /(=)\?(?=&|$)|\?\?/;
  
  // Default jsonp settings
  jQuery.ajaxSetup({
  	jsonp: "callback",
  	jsonpCallback: function() {
  		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
  		this[ callback ] = true;
  		return callback;
  	}
  });
  
  // Detect, normalize options and install callbacks for jsonp requests
  jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
  
  	var callbackName, overwritten, responseContainer,
  		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
  			"url" :
  			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
  		);
  
  	// Handle iff the expected data type is "jsonp" or we have a parameter to set
  	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
  
  		// Get callback name, remembering preexisting value associated with it
  		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
  			s.jsonpCallback() :
  			s.jsonpCallback;
  
  		// Insert callback into url or form data
  		if ( jsonProp ) {
  			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
  		} else if ( s.jsonp !== false ) {
  			s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
  		}
  
  		// Use data converter to retrieve json after script execution
  		s.converters["script json"] = function() {
  			if ( !responseContainer ) {
  				jQuery.error( callbackName + " was not called" );
  			}
  			return responseContainer[ 0 ];
  		};
  
  		// force json dataType
  		s.dataTypes[ 0 ] = "json";
  
  		// Install callback
  		overwritten = window[ callbackName ];
  		window[ callbackName ] = function() {
  			responseContainer = arguments;
  		};
  
  		// Clean-up function (fires after converters)
  		jqXHR.always(function() {
  			// Restore preexisting value
  			window[ callbackName ] = overwritten;
  
  			// Save back as free
  			if ( s[ callbackName ] ) {
  				// make sure that re-using the options doesn't screw things around
  				s.jsonpCallback = originalSettings.jsonpCallback;
  
  				// save the callback name for future use
  				oldCallbacks.push( callbackName );
  			}
  
  			// Call if it was a function and we have a response
  			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
  				overwritten( responseContainer[ 0 ] );
  			}
  
  			responseContainer = overwritten = undefined;
  		});
  
  		// Delegate to script
  		return "script";
  	}
  });
  jQuery.ajaxSettings.xhr = function() {
  	try {
  		return new XMLHttpRequest();
  	} catch( e ) {}
  };
  
  var xhrSupported = jQuery.ajaxSettings.xhr(),
  	xhrSuccessStatus = {
  		// file protocol always yields status code 0, assume 200
  		0: 200,
  		// Support: IE9
  		// #1450: sometimes IE returns 1223 when it should be 204
  		1223: 204
  	},
  	// Support: IE9
  	// We need to keep track of outbound xhr and abort them manually
  	// because IE is not smart enough to do it all by itself
  	xhrId = 0,
  	xhrCallbacks = {};
  
  if ( window.ActiveXObject ) {
  	jQuery( window ).on( "unload", function() {
  		for( var key in xhrCallbacks ) {
  			xhrCallbacks[ key ]();
  		}
  		xhrCallbacks = undefined;
  	});
  }
  
  jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
  jQuery.support.ajax = xhrSupported = !!xhrSupported;
  
  jQuery.ajaxTransport(function( options ) {
  	var callback;
  	// Cross domain only allowed if supported through XMLHttpRequest
  	if ( jQuery.support.cors || xhrSupported && !options.crossDomain ) {
  		return {
  			send: function( headers, complete ) {
  				var i, id,
  					xhr = options.xhr();
  				xhr.open( options.type, options.url, options.async, options.username, options.password );
  				// Apply custom fields if provided
  				if ( options.xhrFields ) {
  					for ( i in options.xhrFields ) {
  						xhr[ i ] = options.xhrFields[ i ];
  					}
  				}
  				// Override mime type if needed
  				if ( options.mimeType && xhr.overrideMimeType ) {
  					xhr.overrideMimeType( options.mimeType );
  				}
  				// X-Requested-With header
  				// For cross-domain requests, seeing as conditions for a preflight are
  				// akin to a jigsaw puzzle, we simply never set it to be sure.
  				// (it can always be set on a per-request basis or even using ajaxSetup)
  				// For same-domain requests, won't change header if already provided.
  				if ( !options.crossDomain && !headers["X-Requested-With"] ) {
  					headers["X-Requested-With"] = "XMLHttpRequest";
  				}
  				// Set headers
  				for ( i in headers ) {
  					xhr.setRequestHeader( i, headers[ i ] );
  				}
  				// Callback
  				callback = function( type ) {
  					return function() {
  						if ( callback ) {
  							delete xhrCallbacks[ id ];
  							callback = xhr.onload = xhr.onerror = null;
  							if ( type === "abort" ) {
  								xhr.abort();
  							} else if ( type === "error" ) {
  								complete(
  									// file protocol always yields status 0, assume 404
  									xhr.status || 404,
  									xhr.statusText
  								);
  							} else {
  								complete(
  									xhrSuccessStatus[ xhr.status ] || xhr.status,
  									xhr.statusText,
  									// Support: IE9
  									// #11426: When requesting binary data, IE9 will throw an exception
  									// on any attempt to access responseText
  									typeof xhr.responseText === "string" ? {
  										text: xhr.responseText
  									} : undefined,
  									xhr.getAllResponseHeaders()
  								);
  							}
  						}
  					};
  				};
  				// Listen to events
  				xhr.onload = callback();
  				xhr.onerror = callback("error");
  				// Create the abort callback
  				callback = xhrCallbacks[( id = xhrId++ )] = callback("abort");
  				// Do send the request
  				// This may raise an exception which is actually
  				// handled in jQuery.ajax (so no try/catch here)
  				xhr.send( options.hasContent && options.data || null );
  			},
  			abort: function() {
  				if ( callback ) {
  					callback();
  				}
  			}
  		};
  	}
  });
  var fxNow, timerId,
  	rfxtypes = /^(?:toggle|show|hide)$/,
  	rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
  	rrun = /queueHooks$/,
  	animationPrefilters = [ defaultPrefilter ],
  	tweeners = {
  		"*": [function( prop, value ) {
  			var tween = this.createTween( prop, value ),
  				target = tween.cur(),
  				parts = rfxnum.exec( value ),
  				unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
  
  				// Starting value computation is required for potential unit mismatches
  				start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
  					rfxnum.exec( jQuery.css( tween.elem, prop ) ),
  				scale = 1,
  				maxIterations = 20;
  
  			if ( start && start[ 3 ] !== unit ) {
  				// Trust units reported by jQuery.css
  				unit = unit || start[ 3 ];
  
  				// Make sure we update the tween properties later on
  				parts = parts || [];
  
  				// Iteratively approximate from a nonzero starting point
  				start = +target || 1;
  
  				do {
  					// If previous iteration zeroed out, double until we get *something*
  					// Use a string for doubling factor so we don't accidentally see scale as unchanged below
  					scale = scale || ".5";
  
  					// Adjust and apply
  					start = start / scale;
  					jQuery.style( tween.elem, prop, start + unit );
  
  				// Update scale, tolerating zero or NaN from tween.cur()
  				// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
  				} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
  			}
  
  			// Update tween properties
  			if ( parts ) {
  				start = tween.start = +start || +target || 0;
  				tween.unit = unit;
  				// If a +=/-= token was provided, we're doing a relative animation
  				tween.end = parts[ 1 ] ?
  					start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
  					+parts[ 2 ];
  			}
  
  			return tween;
  		}]
  	};
  
  // Animations created synchronously will run synchronously
  function createFxNow() {
  	setTimeout(function() {
  		fxNow = undefined;
  	});
  	return ( fxNow = jQuery.now() );
  }
  
  function createTween( value, prop, animation ) {
  	var tween,
  		collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
  		index = 0,
  		length = collection.length;
  	for ( ; index < length; index++ ) {
  		if ( (tween = collection[ index ].call( animation, prop, value )) ) {
  
  			// we're done with this property
  			return tween;
  		}
  	}
  }
  
  function Animation( elem, properties, options ) {
  	var result,
  		stopped,
  		index = 0,
  		length = animationPrefilters.length,
  		deferred = jQuery.Deferred().always( function() {
  			// don't match elem in the :animated selector
  			delete tick.elem;
  		}),
  		tick = function() {
  			if ( stopped ) {
  				return false;
  			}
  			var currentTime = fxNow || createFxNow(),
  				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
  				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
  				temp = remaining / animation.duration || 0,
  				percent = 1 - temp,
  				index = 0,
  				length = animation.tweens.length;
  
  			for ( ; index < length ; index++ ) {
  				animation.tweens[ index ].run( percent );
  			}
  
  			deferred.notifyWith( elem, [ animation, percent, remaining ]);
  
  			if ( percent < 1 && length ) {
  				return remaining;
  			} else {
  				deferred.resolveWith( elem, [ animation ] );
  				return false;
  			}
  		},
  		animation = deferred.promise({
  			elem: elem,
  			props: jQuery.extend( {}, properties ),
  			opts: jQuery.extend( true, { specialEasing: {} }, options ),
  			originalProperties: properties,
  			originalOptions: options,
  			startTime: fxNow || createFxNow(),
  			duration: options.duration,
  			tweens: [],
  			createTween: function( prop, end ) {
  				var tween = jQuery.Tween( elem, animation.opts, prop, end,
  						animation.opts.specialEasing[ prop ] || animation.opts.easing );
  				animation.tweens.push( tween );
  				return tween;
  			},
  			stop: function( gotoEnd ) {
  				var index = 0,
  					// if we are going to the end, we want to run all the tweens
  					// otherwise we skip this part
  					length = gotoEnd ? animation.tweens.length : 0;
  				if ( stopped ) {
  					return this;
  				}
  				stopped = true;
  				for ( ; index < length ; index++ ) {
  					animation.tweens[ index ].run( 1 );
  				}
  
  				// resolve when we played the last frame
  				// otherwise, reject
  				if ( gotoEnd ) {
  					deferred.resolveWith( elem, [ animation, gotoEnd ] );
  				} else {
  					deferred.rejectWith( elem, [ animation, gotoEnd ] );
  				}
  				return this;
  			}
  		}),
  		props = animation.props;
  
  	propFilter( props, animation.opts.specialEasing );
  
  	for ( ; index < length ; index++ ) {
  		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
  		if ( result ) {
  			return result;
  		}
  	}
  
  	jQuery.map( props, createTween, animation );
  
  	if ( jQuery.isFunction( animation.opts.start ) ) {
  		animation.opts.start.call( elem, animation );
  	}
  
  	jQuery.fx.timer(
  		jQuery.extend( tick, {
  			elem: elem,
  			anim: animation,
  			queue: animation.opts.queue
  		})
  	);
  
  	// attach callbacks from options
  	return animation.progress( animation.opts.progress )
  		.done( animation.opts.done, animation.opts.complete )
  		.fail( animation.opts.fail )
  		.always( animation.opts.always );
  }
  
  function propFilter( props, specialEasing ) {
  	var index, name, easing, value, hooks;
  
  	// camelCase, specialEasing and expand cssHook pass
  	for ( index in props ) {
  		name = jQuery.camelCase( index );
  		easing = specialEasing[ name ];
  		value = props[ index ];
  		if ( jQuery.isArray( value ) ) {
  			easing = value[ 1 ];
  			value = props[ index ] = value[ 0 ];
  		}
  
  		if ( index !== name ) {
  			props[ name ] = value;
  			delete props[ index ];
  		}
  
  		hooks = jQuery.cssHooks[ name ];
  		if ( hooks && "expand" in hooks ) {
  			value = hooks.expand( value );
  			delete props[ name ];
  
  			// not quite $.extend, this wont overwrite keys already present.
  			// also - reusing 'index' from above because we have the correct "name"
  			for ( index in value ) {
  				if ( !( index in props ) ) {
  					props[ index ] = value[ index ];
  					specialEasing[ index ] = easing;
  				}
  			}
  		} else {
  			specialEasing[ name ] = easing;
  		}
  	}
  }
  
  jQuery.Animation = jQuery.extend( Animation, {
  
  	tweener: function( props, callback ) {
  		if ( jQuery.isFunction( props ) ) {
  			callback = props;
  			props = [ "*" ];
  		} else {
  			props = props.split(" ");
  		}
  
  		var prop,
  			index = 0,
  			length = props.length;
  
  		for ( ; index < length ; index++ ) {
  			prop = props[ index ];
  			tweeners[ prop ] = tweeners[ prop ] || [];
  			tweeners[ prop ].unshift( callback );
  		}
  	},
  
  	prefilter: function( callback, prepend ) {
  		if ( prepend ) {
  			animationPrefilters.unshift( callback );
  		} else {
  			animationPrefilters.push( callback );
  		}
  	}
  });
  
  function defaultPrefilter( elem, props, opts ) {
  	/* jshint validthis: true */
  	var prop, value, toggle, tween, hooks, oldfire,
  		anim = this,
  		orig = {},
  		style = elem.style,
  		hidden = elem.nodeType && isHidden( elem ),
  		dataShow = data_priv.get( elem, "fxshow" );
  
  	// handle queue: false promises
  	if ( !opts.queue ) {
  		hooks = jQuery._queueHooks( elem, "fx" );
  		if ( hooks.unqueued == null ) {
  			hooks.unqueued = 0;
  			oldfire = hooks.empty.fire;
  			hooks.empty.fire = function() {
  				if ( !hooks.unqueued ) {
  					oldfire();
  				}
  			};
  		}
  		hooks.unqueued++;
  
  		anim.always(function() {
  			// doing this makes sure that the complete handler will be called
  			// before this completes
  			anim.always(function() {
  				hooks.unqueued--;
  				if ( !jQuery.queue( elem, "fx" ).length ) {
  					hooks.empty.fire();
  				}
  			});
  		});
  	}
  
  	// height/width overflow pass
  	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
  		// Make sure that nothing sneaks out
  		// Record all 3 overflow attributes because IE9-10 do not
  		// change the overflow attribute when overflowX and
  		// overflowY are set to the same value
  		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
  
  		// Set display property to inline-block for height/width
  		// animations on inline elements that are having width/height animated
  		if ( jQuery.css( elem, "display" ) === "inline" &&
  				jQuery.css( elem, "float" ) === "none" ) {
  
  			style.display = "inline-block";
  		}
  	}
  
  	if ( opts.overflow ) {
  		style.overflow = "hidden";
  		anim.always(function() {
  			style.overflow = opts.overflow[ 0 ];
  			style.overflowX = opts.overflow[ 1 ];
  			style.overflowY = opts.overflow[ 2 ];
  		});
  	}
  
  
  	// show/hide pass
  	for ( prop in props ) {
  		value = props[ prop ];
  		if ( rfxtypes.exec( value ) ) {
  			delete props[ prop ];
  			toggle = toggle || value === "toggle";
  			if ( value === ( hidden ? "hide" : "show" ) ) {
  
  				// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
  				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
  					hidden = true;
  				} else {
  					continue;
  				}
  			}
  			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
  		}
  	}
  
  	if ( !jQuery.isEmptyObject( orig ) ) {
  		if ( dataShow ) {
  			if ( "hidden" in dataShow ) {
  				hidden = dataShow.hidden;
  			}
  		} else {
  			dataShow = data_priv.access( elem, "fxshow", {} );
  		}
  
  		// store state if its toggle - enables .stop().toggle() to "reverse"
  		if ( toggle ) {
  			dataShow.hidden = !hidden;
  		}
  		if ( hidden ) {
  			jQuery( elem ).show();
  		} else {
  			anim.done(function() {
  				jQuery( elem ).hide();
  			});
  		}
  		anim.done(function() {
  			var prop;
  
  			data_priv.remove( elem, "fxshow" );
  			for ( prop in orig ) {
  				jQuery.style( elem, prop, orig[ prop ] );
  			}
  		});
  		for ( prop in orig ) {
  			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
  
  			if ( !( prop in dataShow ) ) {
  				dataShow[ prop ] = tween.start;
  				if ( hidden ) {
  					tween.end = tween.start;
  					tween.start = prop === "width" || prop === "height" ? 1 : 0;
  				}
  			}
  		}
  	}
  }
  
  function Tween( elem, options, prop, end, easing ) {
  	return new Tween.prototype.init( elem, options, prop, end, easing );
  }
  jQuery.Tween = Tween;
  
  Tween.prototype = {
  	constructor: Tween,
  	init: function( elem, options, prop, end, easing, unit ) {
  		this.elem = elem;
  		this.prop = prop;
  		this.easing = easing || "swing";
  		this.options = options;
  		this.start = this.now = this.cur();
  		this.end = end;
  		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
  	},
  	cur: function() {
  		var hooks = Tween.propHooks[ this.prop ];
  
  		return hooks && hooks.get ?
  			hooks.get( this ) :
  			Tween.propHooks._default.get( this );
  	},
  	run: function( percent ) {
  		var eased,
  			hooks = Tween.propHooks[ this.prop ];
  
  		if ( this.options.duration ) {
  			this.pos = eased = jQuery.easing[ this.easing ](
  				percent, this.options.duration * percent, 0, 1, this.options.duration
  			);
  		} else {
  			this.pos = eased = percent;
  		}
  		this.now = ( this.end - this.start ) * eased + this.start;
  
  		if ( this.options.step ) {
  			this.options.step.call( this.elem, this.now, this );
  		}
  
  		if ( hooks && hooks.set ) {
  			hooks.set( this );
  		} else {
  			Tween.propHooks._default.set( this );
  		}
  		return this;
  	}
  };
  
  Tween.prototype.init.prototype = Tween.prototype;
  
  Tween.propHooks = {
  	_default: {
  		get: function( tween ) {
  			var result;
  
  			if ( tween.elem[ tween.prop ] != null &&
  				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
  				return tween.elem[ tween.prop ];
  			}
  
  			// passing an empty string as a 3rd parameter to .css will automatically
  			// attempt a parseFloat and fallback to a string if the parse fails
  			// so, simple values such as "10px" are parsed to Float.
  			// complex values such as "rotate(1rad)" are returned as is.
  			result = jQuery.css( tween.elem, tween.prop, "" );
  			// Empty strings, null, undefined and "auto" are converted to 0.
  			return !result || result === "auto" ? 0 : result;
  		},
  		set: function( tween ) {
  			// use step hook for back compat - use cssHook if its there - use .style if its
  			// available and use plain properties where available
  			if ( jQuery.fx.step[ tween.prop ] ) {
  				jQuery.fx.step[ tween.prop ]( tween );
  			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
  				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
  			} else {
  				tween.elem[ tween.prop ] = tween.now;
  			}
  		}
  	}
  };
  
  // Support: IE9
  // Panic based approach to setting things on disconnected nodes
  
  Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
  	set: function( tween ) {
  		if ( tween.elem.nodeType && tween.elem.parentNode ) {
  			tween.elem[ tween.prop ] = tween.now;
  		}
  	}
  };
  
  jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
  	var cssFn = jQuery.fn[ name ];
  	jQuery.fn[ name ] = function( speed, easing, callback ) {
  		return speed == null || typeof speed === "boolean" ?
  			cssFn.apply( this, arguments ) :
  			this.animate( genFx( name, true ), speed, easing, callback );
  	};
  });
  
  jQuery.fn.extend({
  	fadeTo: function( speed, to, easing, callback ) {
  
  		// show any hidden elements after setting opacity to 0
  		return this.filter( isHidden ).css( "opacity", 0 ).show()
  
  			// animate to the value specified
  			.end().animate({ opacity: to }, speed, easing, callback );
  	},
  	animate: function( prop, speed, easing, callback ) {
  		var empty = jQuery.isEmptyObject( prop ),
  			optall = jQuery.speed( speed, easing, callback ),
  			doAnimation = function() {
  				// Operate on a copy of prop so per-property easing won't be lost
  				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
  
  				// Empty animations, or finishing resolves immediately
  				if ( empty || data_priv.get( this, "finish" ) ) {
  					anim.stop( true );
  				}
  			};
  			doAnimation.finish = doAnimation;
  
  		return empty || optall.queue === false ?
  			this.each( doAnimation ) :
  			this.queue( optall.queue, doAnimation );
  	},
  	stop: function( type, clearQueue, gotoEnd ) {
  		var stopQueue = function( hooks ) {
  			var stop = hooks.stop;
  			delete hooks.stop;
  			stop( gotoEnd );
  		};
  
  		if ( typeof type !== "string" ) {
  			gotoEnd = clearQueue;
  			clearQueue = type;
  			type = undefined;
  		}
  		if ( clearQueue && type !== false ) {
  			this.queue( type || "fx", [] );
  		}
  
  		return this.each(function() {
  			var dequeue = true,
  				index = type != null && type + "queueHooks",
  				timers = jQuery.timers,
  				data = data_priv.get( this );
  
  			if ( index ) {
  				if ( data[ index ] && data[ index ].stop ) {
  					stopQueue( data[ index ] );
  				}
  			} else {
  				for ( index in data ) {
  					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
  						stopQueue( data[ index ] );
  					}
  				}
  			}
  
  			for ( index = timers.length; index--; ) {
  				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
  					timers[ index ].anim.stop( gotoEnd );
  					dequeue = false;
  					timers.splice( index, 1 );
  				}
  			}
  
  			// start the next in the queue if the last step wasn't forced
  			// timers currently will call their complete callbacks, which will dequeue
  			// but only if they were gotoEnd
  			if ( dequeue || !gotoEnd ) {
  				jQuery.dequeue( this, type );
  			}
  		});
  	},
  	finish: function( type ) {
  		if ( type !== false ) {
  			type = type || "fx";
  		}
  		return this.each(function() {
  			var index,
  				data = data_priv.get( this ),
  				queue = data[ type + "queue" ],
  				hooks = data[ type + "queueHooks" ],
  				timers = jQuery.timers,
  				length = queue ? queue.length : 0;
  
  			// enable finishing flag on private data
  			data.finish = true;
  
  			// empty the queue first
  			jQuery.queue( this, type, [] );
  
  			if ( hooks && hooks.stop ) {
  				hooks.stop.call( this, true );
  			}
  
  			// look for any active animations, and finish them
  			for ( index = timers.length; index--; ) {
  				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
  					timers[ index ].anim.stop( true );
  					timers.splice( index, 1 );
  				}
  			}
  
  			// look for any animations in the old queue and finish them
  			for ( index = 0; index < length; index++ ) {
  				if ( queue[ index ] && queue[ index ].finish ) {
  					queue[ index ].finish.call( this );
  				}
  			}
  
  			// turn off finishing flag
  			delete data.finish;
  		});
  	}
  });
  
  // Generate parameters to create a standard animation
  function genFx( type, includeWidth ) {
  	var which,
  		attrs = { height: type },
  		i = 0;
  
  	// if we include width, step value is 1 to do all cssExpand values,
  	// if we don't include width, step value is 2 to skip over Left and Right
  	includeWidth = includeWidth? 1 : 0;
  	for( ; i < 4 ; i += 2 - includeWidth ) {
  		which = cssExpand[ i ];
  		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
  	}
  
  	if ( includeWidth ) {
  		attrs.opacity = attrs.width = type;
  	}
  
  	return attrs;
  }
  
  // Generate shortcuts for custom animations
  jQuery.each({
  	slideDown: genFx("show"),
  	slideUp: genFx("hide"),
  	slideToggle: genFx("toggle"),
  	fadeIn: { opacity: "show" },
  	fadeOut: { opacity: "hide" },
  	fadeToggle: { opacity: "toggle" }
  }, function( name, props ) {
  	jQuery.fn[ name ] = function( speed, easing, callback ) {
  		return this.animate( props, speed, easing, callback );
  	};
  });
  
  jQuery.speed = function( speed, easing, fn ) {
  	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
  		complete: fn || !fn && easing ||
  			jQuery.isFunction( speed ) && speed,
  		duration: speed,
  		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
  	};
  
  	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
  		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
  
  	// normalize opt.queue - true/undefined/null -> "fx"
  	if ( opt.queue == null || opt.queue === true ) {
  		opt.queue = "fx";
  	}
  
  	// Queueing
  	opt.old = opt.complete;
  
  	opt.complete = function() {
  		if ( jQuery.isFunction( opt.old ) ) {
  			opt.old.call( this );
  		}
  
  		if ( opt.queue ) {
  			jQuery.dequeue( this, opt.queue );
  		}
  	};
  
  	return opt;
  };
  
  jQuery.easing = {
  	linear: function( p ) {
  		return p;
  	},
  	swing: function( p ) {
  		return 0.5 - Math.cos( p*Math.PI ) / 2;
  	}
  };
  
  jQuery.timers = [];
  jQuery.fx = Tween.prototype.init;
  jQuery.fx.tick = function() {
  	var timer,
  		timers = jQuery.timers,
  		i = 0;
  
  	fxNow = jQuery.now();
  
  	for ( ; i < timers.length; i++ ) {
  		timer = timers[ i ];
  		// Checks the timer has not already been removed
  		if ( !timer() && timers[ i ] === timer ) {
  			timers.splice( i--, 1 );
  		}
  	}
  
  	if ( !timers.length ) {
  		jQuery.fx.stop();
  	}
  	fxNow = undefined;
  };
  
  jQuery.fx.timer = function( timer ) {
  	if ( timer() && jQuery.timers.push( timer ) ) {
  		jQuery.fx.start();
  	}
  };
  
  jQuery.fx.interval = 13;
  
  jQuery.fx.start = function() {
  	if ( !timerId ) {
  		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
  	}
  };
  
  jQuery.fx.stop = function() {
  	clearInterval( timerId );
  	timerId = null;
  };
  
  jQuery.fx.speeds = {
  	slow: 600,
  	fast: 200,
  	// Default speed
  	_default: 400
  };
  
  // Back Compat <1.8 extension point
  jQuery.fx.step = {};
  
  if ( jQuery.expr && jQuery.expr.filters ) {
  	jQuery.expr.filters.animated = function( elem ) {
  		return jQuery.grep(jQuery.timers, function( fn ) {
  			return elem === fn.elem;
  		}).length;
  	};
  }
  jQuery.fn.offset = function( options ) {
  	if ( arguments.length ) {
  		return options === undefined ?
  			this :
  			this.each(function( i ) {
  				jQuery.offset.setOffset( this, options, i );
  			});
  	}
  
  	var docElem, win,
  		elem = this[ 0 ],
  		box = { top: 0, left: 0 },
  		doc = elem && elem.ownerDocument;
  
  	if ( !doc ) {
  		return;
  	}
  
  	docElem = doc.documentElement;
  
  	// Make sure it's not a disconnected DOM node
  	if ( !jQuery.contains( docElem, elem ) ) {
  		return box;
  	}
  
  	// If we don't have gBCR, just use 0,0 rather than error
  	// BlackBerry 5, iOS 3 (original iPhone)
  	if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
  		box = elem.getBoundingClientRect();
  	}
  	win = getWindow( doc );
  	return {
  		top: box.top + win.pageYOffset - docElem.clientTop,
  		left: box.left + win.pageXOffset - docElem.clientLeft
  	};
  };
  
  jQuery.offset = {
  
  	setOffset: function( elem, options, i ) {
  		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
  			position = jQuery.css( elem, "position" ),
  			curElem = jQuery( elem ),
  			props = {};
  
  		// Set position first, in-case top/left are set even on static elem
  		if ( position === "static" ) {
  			elem.style.position = "relative";
  		}
  
  		curOffset = curElem.offset();
  		curCSSTop = jQuery.css( elem, "top" );
  		curCSSLeft = jQuery.css( elem, "left" );
  		calculatePosition = ( position === "absolute" || position === "fixed" ) && ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
  
  		// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
  		if ( calculatePosition ) {
  			curPosition = curElem.position();
  			curTop = curPosition.top;
  			curLeft = curPosition.left;
  
  		} else {
  			curTop = parseFloat( curCSSTop ) || 0;
  			curLeft = parseFloat( curCSSLeft ) || 0;
  		}
  
  		if ( jQuery.isFunction( options ) ) {
  			options = options.call( elem, i, curOffset );
  		}
  
  		if ( options.top != null ) {
  			props.top = ( options.top - curOffset.top ) + curTop;
  		}
  		if ( options.left != null ) {
  			props.left = ( options.left - curOffset.left ) + curLeft;
  		}
  
  		if ( "using" in options ) {
  			options.using.call( elem, props );
  
  		} else {
  			curElem.css( props );
  		}
  	}
  };
  
  
  jQuery.fn.extend({
  
  	position: function() {
  		if ( !this[ 0 ] ) {
  			return;
  		}
  
  		var offsetParent, offset,
  			elem = this[ 0 ],
  			parentOffset = { top: 0, left: 0 };
  
  		// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
  		if ( jQuery.css( elem, "position" ) === "fixed" ) {
  			// We assume that getBoundingClientRect is available when computed position is fixed
  			offset = elem.getBoundingClientRect();
  
  		} else {
  			// Get *real* offsetParent
  			offsetParent = this.offsetParent();
  
  			// Get correct offsets
  			offset = this.offset();
  			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
  				parentOffset = offsetParent.offset();
  			}
  
  			// Add offsetParent borders
  			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
  			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
  		}
  
  		// Subtract parent offsets and element margins
  		return {
  			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
  			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
  		};
  	},
  
  	offsetParent: function() {
  		return this.map(function() {
  			var offsetParent = this.offsetParent || docElem;
  
  			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
  				offsetParent = offsetParent.offsetParent;
  			}
  
  			return offsetParent || docElem;
  		});
  	}
  });
  
  
  // Create scrollLeft and scrollTop methods
  jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
  	var top = "pageYOffset" === prop;
  
  	jQuery.fn[ method ] = function( val ) {
  		return jQuery.access( this, function( elem, method, val ) {
  			var win = getWindow( elem );
  
  			if ( val === undefined ) {
  				return win ? win[ prop ] : elem[ method ];
  			}
  
  			if ( win ) {
  				win.scrollTo(
  					!top ? val : window.pageXOffset,
  					top ? val : window.pageYOffset
  				);
  
  			} else {
  				elem[ method ] = val;
  			}
  		}, method, val, arguments.length, null );
  	};
  });
  
  function getWindow( elem ) {
  	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
  }
  // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
  jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
  	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
  		// margin is only for outerHeight, outerWidth
  		jQuery.fn[ funcName ] = function( margin, value ) {
  			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
  				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
  
  			return jQuery.access( this, function( elem, type, value ) {
  				var doc;
  
  				if ( jQuery.isWindow( elem ) ) {
  					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
  					// isn't a whole lot we can do. See pull request at this URL for discussion:
  					// https://github.com/jquery/jquery/pull/764
  					return elem.document.documentElement[ "client" + name ];
  				}
  
  				// Get document width or height
  				if ( elem.nodeType === 9 ) {
  					doc = elem.documentElement;
  
  					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
  					// whichever is greatest
  					return Math.max(
  						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
  						elem.body[ "offset" + name ], doc[ "offset" + name ],
  						doc[ "client" + name ]
  					);
  				}
  
  				return value === undefined ?
  					// Get width or height on the element, requesting but not forcing parseFloat
  					jQuery.css( elem, type, extra ) :
  
  					// Set width or height on the element
  					jQuery.style( elem, type, value, extra );
  			}, type, chainable ? margin : undefined, chainable, null );
  		};
  	});
  });
  // Limit scope pollution from any deprecated API
  // (function() {
  
  // The number of elements contained in the matched element set
  jQuery.fn.size = function() {
  	return this.length;
  };
  
  jQuery.fn.andSelf = jQuery.fn.addBack;
  
  // })();
  if ( typeof module === "object" && module && typeof module.exports === "object" ) {
  	// Expose jQuery as module.exports in loaders that implement the Node
  	// module pattern (including browserify). Do not create the global, since
  	// the user will be storing it themselves locally, and globals are frowned
  	// upon in the Node module world.
  	module.exports = jQuery;
  } else {
  	// Register as a named AMD module, since jQuery can be concatenated with other
  	// files that may use define, but not via a proper concatenation script that
  	// understands anonymous AMD modules. A named AMD is safest and most robust
  	// way to register. Lowercase jquery is used because AMD module names are
  	// derived from file names, and jQuery is normally delivered in a lowercase
  	// file name. Do this after creating the global so that if an AMD module wants
  	// to call noConflict to hide this version of jQuery, it will work.
  	if ( typeof define === "function" && define.amd ) {
  		define( "jquery", [], function () { return jQuery; } );
  	}
  }
  
  // If there is a window object, that at least has a document property,
  // define jQuery and $ identifiers
  if ( typeof window === "object" && typeof window.document === "object" ) {
  	window.jQuery = window.$ = jQuery;
  }
  
  })( window );
  (function($, undefined) {
  
  /**
   * Unobtrusive scripting adapter for jQuery
   * https://github.com/rails/jquery-ujs
   *
   * Requires jQuery 1.8.0 or later.
   *
   * Released under the MIT license
   *
   */
  
    // Cut down on the number of issues from people inadvertently including jquery_ujs twice
    // by detecting and raising an error when it happens.
    if ( $.rails !== undefined ) {
      $.error('jquery-ujs has already been loaded!');
    }
  
    // Shorthand to make it a little easier to call public rails functions from within rails.js
    var rails;
    var $document = $(document);
  
    $.rails = rails = {
      // Link elements bound by jquery-ujs
      linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with], a[data-disable]',
  
      // Button elements bound by jquery-ujs
      buttonClickSelector: 'button[data-remote]:not(form button), button[data-confirm]:not(form button)',
  
      // Select elements bound by jquery-ujs
      inputChangeSelector: 'select[data-remote], input[data-remote], textarea[data-remote]',
  
      // Form elements bound by jquery-ujs
      formSubmitSelector: 'form',
  
      // Form input elements bound by jquery-ujs
      formInputClickSelector: 'form input[type=submit], form input[type=image], form button[type=submit], form button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])',
  
      // Form input elements disabled during form submission
      disableSelector: 'input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled',
  
      // Form input elements re-enabled after form submission
      enableSelector: 'input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled',
  
      // Form required input elements
      requiredInputSelector: 'input[name][required]:not([disabled]),textarea[name][required]:not([disabled])',
  
      // Form file input elements
      fileInputSelector: 'input[type=file]',
  
      // Link onClick disable selector with possible reenable after remote submission
      linkDisableSelector: 'a[data-disable-with], a[data-disable]',
  
      // Button onClick disable selector with possible reenable after remote submission
      buttonDisableSelector: 'button[data-remote][data-disable-with], button[data-remote][data-disable]',
  
      // Make sure that every Ajax request sends the CSRF token
      CSRFProtection: function(xhr) {
        var token = $('meta[name="csrf-token"]').attr('content');
        if (token) xhr.setRequestHeader('X-CSRF-Token', token);
      },
  
      // making sure that all forms have actual up-to-date token(cached forms contain old one)
      refreshCSRFTokens: function(){
        var csrfToken = $('meta[name=csrf-token]').attr('content');
        var csrfParam = $('meta[name=csrf-param]').attr('content');
        $('form input[name="' + csrfParam + '"]').val(csrfToken);
      },
  
      // Triggers an event on an element and returns false if the event result is false
      fire: function(obj, name, data) {
        var event = $.Event(name);
        obj.trigger(event, data);
        return event.result !== false;
      },
  
      // Default confirm dialog, may be overridden with custom confirm dialog in $.rails.confirm
      confirm: function(message) {
        return confirm(message);
      },
  
      // Default ajax function, may be overridden with custom function in $.rails.ajax
      ajax: function(options) {
        return $.ajax(options);
      },
  
      // Default way to get an element's href. May be overridden at $.rails.href.
      href: function(element) {
        return element.attr('href');
      },
  
      // Submits "remote" forms and links with ajax
      handleRemote: function(element) {
        var method, url, data, elCrossDomain, crossDomain, withCredentials, dataType, options;
  
        if (rails.fire(element, 'ajax:before')) {
          elCrossDomain = element.data('cross-domain');
          crossDomain = elCrossDomain === undefined ? null : elCrossDomain;
          withCredentials = element.data('with-credentials') || null;
          dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);
  
          if (element.is('form')) {
            method = element.attr('method');
            url = element.attr('action');
            data = element.serializeArray();
            // memoized value from clicked submit button
            var button = element.data('ujs:submit-button');
            if (button) {
              data.push(button);
              element.data('ujs:submit-button', null);
            }
          } else if (element.is(rails.inputChangeSelector)) {
            method = element.data('method');
            url = element.data('url');
            data = element.serialize();
            if (element.data('params')) data = data + "&" + element.data('params');
          } else if (element.is(rails.buttonClickSelector)) {
            method = element.data('method') || 'get';
            url = element.data('url');
            data = element.serialize();
            if (element.data('params')) data = data + "&" + element.data('params');
          } else {
            method = element.data('method');
            url = rails.href(element);
            data = element.data('params') || null;
          }
  
          options = {
            type: method || 'GET', data: data, dataType: dataType,
            // stopping the "ajax:beforeSend" event will cancel the ajax request
            beforeSend: function(xhr, settings) {
              if (settings.dataType === undefined) {
                xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
              }
              if (rails.fire(element, 'ajax:beforeSend', [xhr, settings])) {
                element.trigger('ajax:send', xhr);
              } else {
                return false;
              }
            },
            success: function(data, status, xhr) {
              element.trigger('ajax:success', [data, status, xhr]);
            },
            complete: function(xhr, status) {
              element.trigger('ajax:complete', [xhr, status]);
            },
            error: function(xhr, status, error) {
              element.trigger('ajax:error', [xhr, status, error]);
            },
            crossDomain: crossDomain
          };
  
          // There is no withCredentials for IE6-8 when
          // "Enable native XMLHTTP support" is disabled
          if (withCredentials) {
            options.xhrFields = {
              withCredentials: withCredentials
            };
          }
  
          // Only pass url to `ajax` options if not blank
          if (url) { options.url = url; }
  
          return rails.ajax(options);
        } else {
          return false;
        }
      },
  
      // Handles "data-method" on links such as:
      // <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a>
      handleMethod: function(link) {
        var href = rails.href(link),
          method = link.data('method'),
          target = link.attr('target'),
          csrfToken = $('meta[name=csrf-token]').attr('content'),
          csrfParam = $('meta[name=csrf-param]').attr('content'),
          form = $('<form method="post" action="' + href + '"></form>'),
          metadataInput = '<input name="_method" value="' + method + '" type="hidden" />';
  
        if (csrfParam !== undefined && csrfToken !== undefined) {
          metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />';
        }
  
        if (target) { form.attr('target', target); }
  
        form.hide().append(metadataInput).appendTo('body');
        form.submit();
      },
  
      // Helper function that returns form elements that match the specified CSS selector
      // If form is actually a "form" element this will return associated elements outside the from that have
      // the html form attribute set
      formElements: function(form, selector) {
        return form.is('form') ? $(form[0].elements).filter(selector) : form.find(selector);
      },
  
      /* Disables form elements:
        - Caches element value in 'ujs:enable-with' data store
        - Replaces element text with value of 'data-disable-with' attribute
        - Sets disabled property to true
      */
      disableFormElements: function(form) {
        rails.formElements(form, rails.disableSelector).each(function() {
          rails.disableFormElement($(this));
        });
      },
  
      disableFormElement: function(element) {
        var method, replacement;
  
        method = element.is('button') ? 'html' : 'val';
        replacement = element.data('disable-with');
  
        element.data('ujs:enable-with', element[method]());
        if (replacement !== undefined) {
          element[method](replacement);
        }
  
        element.prop('disabled', true);
      },
  
      /* Re-enables disabled form elements:
        - Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
        - Sets disabled property to false
      */
      enableFormElements: function(form) {
        rails.formElements(form, rails.enableSelector).each(function() {
          rails.enableFormElement($(this));
        });
      },
  
      enableFormElement: function(element) {
        var method = element.is('button') ? 'html' : 'val';
        if (element.data('ujs:enable-with')) element[method](element.data('ujs:enable-with'));
        element.prop('disabled', false);
      },
  
     /* For 'data-confirm' attribute:
        - Fires `confirm` event
        - Shows the confirmation dialog
        - Fires the `confirm:complete` event
  
        Returns `true` if no function stops the chain and user chose yes; `false` otherwise.
        Attaching a handler to the element's `confirm` event that returns a `falsy` value cancels the confirmation dialog.
        Attaching a handler to the element's `confirm:complete` event that returns a `falsy` value makes this function
        return false. The `confirm:complete` event is fired whether or not the user answered true or false to the dialog.
     */
      allowAction: function(element) {
        var message = element.data('confirm'),
            answer = false, callback;
        if (!message) { return true; }
  
        if (rails.fire(element, 'confirm')) {
          answer = rails.confirm(message);
          callback = rails.fire(element, 'confirm:complete', [answer]);
        }
        return answer && callback;
      },
  
      // Helper function which checks for blank inputs in a form that match the specified CSS selector
      blankInputs: function(form, specifiedSelector, nonBlank) {
        var inputs = $(), input, valueToCheck,
            selector = specifiedSelector || 'input,textarea',
            allInputs = form.find(selector);
  
        allInputs.each(function() {
          input = $(this);
          valueToCheck = input.is('input[type=checkbox],input[type=radio]') ? input.is(':checked') : input.val();
          // If nonBlank and valueToCheck are both truthy, or nonBlank and valueToCheck are both falsey
          if (!valueToCheck === !nonBlank) {
  
            // Don't count unchecked required radio if other radio with same name is checked
            if (input.is('input[type=radio]') && allInputs.filter('input[type=radio]:checked[name="' + input.attr('name') + '"]').length) {
              return true; // Skip to next input
            }
  
            inputs = inputs.add(input);
          }
        });
        return inputs.length ? inputs : false;
      },
  
      // Helper function which checks for non-blank inputs in a form that match the specified CSS selector
      nonBlankInputs: function(form, specifiedSelector) {
        return rails.blankInputs(form, specifiedSelector, true); // true specifies nonBlank
      },
  
      // Helper function, needed to provide consistent behavior in IE
      stopEverything: function(e) {
        $(e.target).trigger('ujs:everythingStopped');
        e.stopImmediatePropagation();
        return false;
      },
  
      //  replace element's html with the 'data-disable-with' after storing original html
      //  and prevent clicking on it
      disableElement: function(element) {
        var replacement = element.data('disable-with');
  
        element.data('ujs:enable-with', element.html()); // store enabled state
        if (replacement !== undefined) {
          element.html(replacement);
        }
  
        element.bind('click.railsDisable', function(e) { // prevent further clicking
          return rails.stopEverything(e);
        });
      },
  
      // restore element to its original state which was disabled by 'disableElement' above
      enableElement: function(element) {
        if (element.data('ujs:enable-with') !== undefined) {
          element.html(element.data('ujs:enable-with')); // set to old enabled state
          element.removeData('ujs:enable-with'); // clean up cache
        }
        element.unbind('click.railsDisable'); // enable element
      }
    };
  
    if (rails.fire($document, 'rails:attachBindings')) {
  
      $.ajaxPrefilter(function(options, originalOptions, xhr){ if ( !options.crossDomain ) { rails.CSRFProtection(xhr); }});
  
      $document.delegate(rails.linkDisableSelector, 'ajax:complete', function() {
          rails.enableElement($(this));
      });
  
      $document.delegate(rails.buttonDisableSelector, 'ajax:complete', function() {
          rails.enableFormElement($(this));
      });
  
      $document.delegate(rails.linkClickSelector, 'click.rails', function(e) {
        var link = $(this), method = link.data('method'), data = link.data('params'), metaClick = e.metaKey || e.ctrlKey;
        if (!rails.allowAction(link)) return rails.stopEverything(e);
  
        if (!metaClick && link.is(rails.linkDisableSelector)) rails.disableElement(link);
  
        if (link.data('remote') !== undefined) {
          if (metaClick && (!method || method === 'GET') && !data) { return true; }
  
          var handleRemote = rails.handleRemote(link);
          // response from rails.handleRemote() will either be false or a deferred object promise.
          if (handleRemote === false) {
            rails.enableElement(link);
          } else {
            handleRemote.error( function() { rails.enableElement(link); } );
          }
          return false;
  
        } else if (link.data('method')) {
          rails.handleMethod(link);
          return false;
        }
      });
  
      $document.delegate(rails.buttonClickSelector, 'click.rails', function(e) {
        var button = $(this);
  
        if (!rails.allowAction(button)) return rails.stopEverything(e);
  
        if (button.is(rails.buttonDisableSelector)) rails.disableFormElement(button);
  
        var handleRemote = rails.handleRemote(button);
        // response from rails.handleRemote() will either be false or a deferred object promise.
        if (handleRemote === false) {
          rails.enableFormElement(button);
        } else {
          handleRemote.error( function() { rails.enableFormElement(button); } );
        }
        return false;
      });
  
      $document.delegate(rails.inputChangeSelector, 'change.rails', function(e) {
        var link = $(this);
        if (!rails.allowAction(link)) return rails.stopEverything(e);
  
        rails.handleRemote(link);
        return false;
      });
  
      $document.delegate(rails.formSubmitSelector, 'submit.rails', function(e) {
        var form = $(this),
          remote = form.data('remote') !== undefined,
          blankRequiredInputs,
          nonBlankFileInputs;
  
        if (!rails.allowAction(form)) return rails.stopEverything(e);
  
        // skip other logic when required values are missing or file upload is present
        if (form.attr('novalidate') == undefined) {
          blankRequiredInputs = rails.blankInputs(form, rails.requiredInputSelector);
          if (blankRequiredInputs && rails.fire(form, 'ajax:aborted:required', [blankRequiredInputs])) {
            return rails.stopEverything(e);
          }
        }
  
        if (remote) {
          nonBlankFileInputs = rails.nonBlankInputs(form, rails.fileInputSelector);
          if (nonBlankFileInputs) {
            // slight timeout so that the submit button gets properly serialized
            // (make it easy for event handler to serialize form without disabled values)
            setTimeout(function(){ rails.disableFormElements(form); }, 13);
            var aborted = rails.fire(form, 'ajax:aborted:file', [nonBlankFileInputs]);
  
            // re-enable form elements if event bindings return false (canceling normal form submission)
            if (!aborted) { setTimeout(function(){ rails.enableFormElements(form); }, 13); }
  
            return aborted;
          }
  
          rails.handleRemote(form);
          return false;
  
        } else {
          // slight timeout so that the submit button gets properly serialized
          setTimeout(function(){ rails.disableFormElements(form); }, 13);
        }
      });
  
      $document.delegate(rails.formInputClickSelector, 'click.rails', function(event) {
        var button = $(this);
  
        if (!rails.allowAction(button)) return rails.stopEverything(event);
  
        // register the pressed submit button
        var name = button.attr('name'),
          data = name ? {name:name, value:button.val()} : null;
  
        button.closest('form').data('ujs:submit-button', data);
      });
  
      $document.delegate(rails.formSubmitSelector, 'ajax:send.rails', function(event) {
        if (this == event.target) rails.disableFormElements($(this));
      });
  
      $document.delegate(rails.formSubmitSelector, 'ajax:complete.rails', function(event) {
        if (this == event.target) rails.enableFormElements($(this));
      });
  
      $(function(){
        rails.refreshCSRFTokens();
      });
    }
  
  })( jQuery );
  /* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
   * @license MIT */
  
  
  ;(function(root, factory) {
  
    if (typeof define === 'function' && define.amd) {
      define(factory);
    } else if (typeof exports === 'object') {
      module.exports = factory();
    } else {
      root.NProgress = factory();
    }
  
  })(this, function() {
    var NProgress = {};
  
    NProgress.version = '0.1.6';
  
    var Settings = NProgress.settings = {
      minimum: 0.08,
      easing: 'ease',
      positionUsing: '',
      speed: 200,
      trickle: true,
      trickleRate: 0.02,
      trickleSpeed: 800,
      showSpinner: true,
      barSelector: '[role="bar"]',
      spinnerSelector: '[role="spinner"]',
      parent: 'body',
      template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
    };
  
    /**
     * Updates configuration.
     *
     *     NProgress.configure({
     *       minimum: 0.1
     *     });
     */
    NProgress.configure = function(options) {
      var key, value;
      for (key in options) {
        value = options[key];
        if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;
      }
  
      return this;
    };
  
    /**
     * Last number.
     */
  
    NProgress.status = null;
  
    /**
     * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
     *
     *     NProgress.set(0.4);
     *     NProgress.set(1.0);
     */
  
    NProgress.set = function(n) {
      var started = NProgress.isStarted();
  
      n = clamp(n, Settings.minimum, 1);
      NProgress.status = (n === 1 ? null : n);
  
      var progress = NProgress.render(!started),
          bar      = progress.querySelector(Settings.barSelector),
          speed    = Settings.speed,
          ease     = Settings.easing;
  
      progress.offsetWidth; /* Repaint */
  
      queue(function(next) {
        // Set positionUsing if it hasn't already been set
        if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();
  
        // Add transition
        css(bar, barPositionCSS(n, speed, ease));
  
        if (n === 1) {
          // Fade out
          css(progress, { 
            transition: 'none', 
            opacity: 1 
          });
          progress.offsetWidth; /* Repaint */
  
          setTimeout(function() {
            css(progress, { 
              transition: 'all ' + speed + 'ms linear', 
              opacity: 0 
            });
            setTimeout(function() {
              NProgress.remove();
              next();
            }, speed);
          }, speed);
        } else {
          setTimeout(next, speed);
        }
      });
  
      return this;
    };
  
    NProgress.isStarted = function() {
      return typeof NProgress.status === 'number';
    };
  
    /**
     * Shows the progress bar.
     * This is the same as setting the status to 0%, except that it doesn't go backwards.
     *
     *     NProgress.start();
     *
     */
    NProgress.start = function() {
      if (!NProgress.status) NProgress.set(0);
  
      var work = function() {
        setTimeout(function() {
          if (!NProgress.status) return;
          NProgress.trickle();
          work();
        }, Settings.trickleSpeed);
      };
  
      if (Settings.trickle) work();
  
      return this;
    };
  
    /**
     * Hides the progress bar.
     * This is the *sort of* the same as setting the status to 100%, with the
     * difference being `done()` makes some placebo effect of some realistic motion.
     *
     *     NProgress.done();
     *
     * If `true` is passed, it will show the progress bar even if its hidden.
     *
     *     NProgress.done(true);
     */
  
    NProgress.done = function(force) {
      if (!force && !NProgress.status) return this;
  
      return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
    };
  
    /**
     * Increments by a random amount.
     */
  
    NProgress.inc = function(amount) {
      var n = NProgress.status;
  
      if (!n) {
        return NProgress.start();
      } else {
        if (typeof amount !== 'number') {
          amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
        }
  
        n = clamp(n + amount, 0, 0.994);
        return NProgress.set(n);
      }
    };
  
    NProgress.trickle = function() {
      return NProgress.inc(Math.random() * Settings.trickleRate);
    };
  
    /**
     * Waits for all supplied jQuery promises and
     * increases the progress as the promises resolve.
     * 
     * @param $promise jQUery Promise
     */
    (function() {
      var initial = 0, current = 0;
      
      NProgress.promise = function($promise) {
        if (!$promise || $promise.state() == "resolved") {
          return this;
        }
        
        if (current == 0) {
          NProgress.start();
        }
        
        initial++;
        current++;
        
        $promise.always(function() {
          current--;
          if (current == 0) {
              initial = 0;
              NProgress.done();
          } else {
              NProgress.set((initial - current) / initial);
          }
        });
        
        return this;
      };
      
    })();
  
    /**
     * (Internal) renders the progress bar markup based on the `template`
     * setting.
     */
  
    NProgress.render = function(fromStart) {
      if (NProgress.isRendered()) return document.getElementById('nprogress');
  
      addClass(document.documentElement, 'nprogress-busy');
      
      var progress = document.createElement('div');
      progress.id = 'nprogress';
      progress.innerHTML = Settings.template;
  
      var bar      = progress.querySelector(Settings.barSelector),
          perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),
          parent   = document.querySelector(Settings.parent),
          spinner;
      
      css(bar, {
        transition: 'all 0 linear',
        transform: 'translate3d(' + perc + '%,0,0)'
      });
  
      if (!Settings.showSpinner) {
        spinner = progress.querySelector(Settings.spinnerSelector);
        spinner && removeElement(spinner);
      }
  
      if (parent != document.body) {
        addClass(parent, 'nprogress-custom-parent');
      }
  
      parent.appendChild(progress);
      return progress;
    };
  
    /**
     * Removes the element. Opposite of render().
     */
  
    NProgress.remove = function() {
      removeClass(document.documentElement, 'nprogress-busy');
      removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent')
      var progress = document.getElementById('nprogress');
      progress && removeElement(progress);
    };
  
    /**
     * Checks if the progress bar is rendered.
     */
  
    NProgress.isRendered = function() {
      return !!document.getElementById('nprogress');
    };
  
    /**
     * Determine which positioning CSS rule to use.
     */
  
    NProgress.getPositioningCSS = function() {
      // Sniff on document.body.style
      var bodyStyle = document.body.style;
  
      // Sniff prefixes
      var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
                         ('MozTransform' in bodyStyle) ? 'Moz' :
                         ('msTransform' in bodyStyle) ? 'ms' :
                         ('OTransform' in bodyStyle) ? 'O' : '';
  
      if (vendorPrefix + 'Perspective' in bodyStyle) {
        // Modern browsers with 3D support, e.g. Webkit, IE10
        return 'translate3d';
      } else if (vendorPrefix + 'Transform' in bodyStyle) {
        // Browsers without 3D support, e.g. IE9
        return 'translate';
      } else {
        // Browsers without translate() support, e.g. IE7-8
        return 'margin';
      }
    };
  
    /**
     * Helpers
     */
  
    function clamp(n, min, max) {
      if (n < min) return min;
      if (n > max) return max;
      return n;
    }
  
    /**
     * (Internal) converts a percentage (`0..1`) to a bar translateX
     * percentage (`-100%..0%`).
     */
  
    function toBarPerc(n) {
      return (-1 + n) * 100;
    }
  
  
    /**
     * (Internal) returns the correct CSS for changing the bar's
     * position given an n percentage, and speed and ease from Settings
     */
  
    function barPositionCSS(n, speed, ease) {
      var barCSS;
  
      if (Settings.positionUsing === 'translate3d') {
        barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
      } else if (Settings.positionUsing === 'translate') {
        barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
      } else {
        barCSS = { 'margin-left': toBarPerc(n)+'%' };
      }
  
      barCSS.transition = 'all '+speed+'ms '+ease;
  
      return barCSS;
    }
  
    /**
     * (Internal) Queues a function to be executed.
     */
  
    var queue = (function() {
      var pending = [];
      
      function next() {
        var fn = pending.shift();
        if (fn) {
          fn(next);
        }
      }
  
      return function(fn) {
        pending.push(fn);
        if (pending.length == 1) next();
      };
    })();
  
    /**
     * (Internal) Applies css properties to an element, similar to the jQuery 
     * css method.
     *
     * While this helper does assist with vendor prefixed property names, it 
     * does not perform any manipulation of values prior to setting styles.
     */
  
    var css = (function() {
      var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],
          cssProps    = {};
  
      function camelCase(string) {
        return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) {
          return letter.toUpperCase();
        });
      }
  
      function getVendorProp(name) {
        var style = document.body.style;
        if (name in style) return name;
  
        var i = cssPrefixes.length,
            capName = name.charAt(0).toUpperCase() + name.slice(1),
            vendorName;
        while (i--) {
          vendorName = cssPrefixes[i] + capName;
          if (vendorName in style) return vendorName;
        }
  
        return name;
      }
  
      function getStyleProp(name) {
        name = camelCase(name);
        return cssProps[name] || (cssProps[name] = getVendorProp(name));
      }
  
      function applyCss(element, prop, value) {
        prop = getStyleProp(prop);
        element.style[prop] = value;
      }
  
      return function(element, properties) {
        var args = arguments,
            prop, 
            value;
  
        if (args.length == 2) {
          for (prop in properties) {
            value = properties[prop];
            if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);
          }
        } else {
          applyCss(element, args[1], args[2]);
        }
      }
    })();
  
    /**
     * (Internal) Determines if an element or space separated list of class names contains a class name.
     */
  
    function hasClass(element, name) {
      var list = typeof element == 'string' ? element : classList(element);
      return list.indexOf(' ' + name + ' ') >= 0;
    }
  
    /**
     * (Internal) Adds a class to an element.
     */
  
    function addClass(element, name) {
      var oldList = classList(element),
          newList = oldList + name;
  
      if (hasClass(oldList, name)) return; 
  
      // Trim the opening space.
      element.className = newList.substring(1);
    }
  
    /**
     * (Internal) Removes a class from an element.
     */
  
    function removeClass(element, name) {
      var oldList = classList(element),
          newList;
  
      if (!hasClass(element, name)) return;
  
      // Replace the class name.
      newList = oldList.replace(' ' + name + ' ', ' ');
  
      // Trim the opening and closing spaces.
      element.className = newList.substring(1, newList.length - 1);
    }
  
    /**
     * (Internal) Gets a space separated list of the class names on the element. 
     * The list is wrapped with a single space on each end to facilitate finding 
     * matches within the list.
     */
  
    function classList(element) {
      return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' ');
    }
  
    /**
     * (Internal) Removes an element from the DOM.
     */
  
    function removeElement(element) {
      element && element.parentNode && element.parentNode.removeChild(element);
    }
  
    return NProgress;
  });
  /*!
   * imagesLoaded PACKAGED v3.0.4
   * JavaScript is all like "You images are done yet or what?"
   * MIT License
   */
  
  /*!
   * EventEmitter v4.2.4 - git.io/ee
   * Oliver Caldwell
   * MIT license
   * @preserve
   */
  
  
  (function () {
  	'use strict';
  
  	/**
  	 * Class for managing events.
  	 * Can be extended to provide event functionality in other classes.
  	 *
  	 * @class EventEmitter Manages event registering and emitting.
  	 */
  	function EventEmitter() {}
  
  	// Shortcuts to improve speed and size
  
  	// Easy access to the prototype
  	var proto = EventEmitter.prototype;
  
  	/**
  	 * Finds the index of the listener for the event in it's storage array.
  	 *
  	 * @param {Function[]} listeners Array of listeners to search through.
  	 * @param {Function} listener Method to look for.
  	 * @return {Number} Index of the specified listener, -1 if not found
  	 * @api private
  	 */
  	function indexOfListener(listeners, listener) {
  		var i = listeners.length;
  		while (i--) {
  			if (listeners[i].listener === listener) {
  				return i;
  			}
  		}
  
  		return -1;
  	}
  
  	/**
  	 * Alias a method while keeping the context correct, to allow for overwriting of target method.
  	 *
  	 * @param {String} name The name of the target method.
  	 * @return {Function} The aliased method
  	 * @api private
  	 */
  	function alias(name) {
  		return function aliasClosure() {
  			return this[name].apply(this, arguments);
  		};
  	}
  
  	/**
  	 * Returns the listener array for the specified event.
  	 * Will initialise the event object and listener arrays if required.
  	 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them.
  	 * Each property in the object response is an array of listener functions.
  	 *
  	 * @param {String|RegExp} evt Name of the event to return the listeners from.
  	 * @return {Function[]|Object} All listener functions for the event.
  	 */
  	proto.getListeners = function getListeners(evt) {
  		var events = this._getEvents();
  		var response;
  		var key;
  
  		// Return a concatenated array of all matching events if
  		// the selector is a regular expression.
  		if (typeof evt === 'object') {
  			response = {};
  			for (key in events) {
  				if (events.hasOwnProperty(key) && evt.test(key)) {
  					response[key] = events[key];
  				}
  			}
  		}
  		else {
  			response = events[evt] || (events[evt] = []);
  		}
  
  		return response;
  	};
  
  	/**
  	 * Takes a list of listener objects and flattens it into a list of listener functions.
  	 *
  	 * @param {Object[]} listeners Raw listener objects.
  	 * @return {Function[]} Just the listener functions.
  	 */
  	proto.flattenListeners = function flattenListeners(listeners) {
  		var flatListeners = [];
  		var i;
  
  		for (i = 0; i < listeners.length; i += 1) {
  			flatListeners.push(listeners[i].listener);
  		}
  
  		return flatListeners;
  	};
  
  	/**
  	 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful.
  	 *
  	 * @param {String|RegExp} evt Name of the event to return the listeners from.
  	 * @return {Object} All listener functions for an event in an object.
  	 */
  	proto.getListenersAsObject = function getListenersAsObject(evt) {
  		var listeners = this.getListeners(evt);
  		var response;
  
  		if (listeners instanceof Array) {
  			response = {};
  			response[evt] = listeners;
  		}
  
  		return response || listeners;
  	};
  
  	/**
  	 * Adds a listener function to the specified event.
  	 * The listener will not be added if it is a duplicate.
  	 * If the listener returns true then it will be removed after it is called.
  	 * If you pass a regular expression as the event name then the listener will be added to all events that match it.
  	 *
  	 * @param {String|RegExp} evt Name of the event to attach the listener to.
  	 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.addListener = function addListener(evt, listener) {
  		var listeners = this.getListenersAsObject(evt);
  		var listenerIsWrapped = typeof listener === 'object';
  		var key;
  
  		for (key in listeners) {
  			if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
  				listeners[key].push(listenerIsWrapped ? listener : {
  					listener: listener,
  					once: false
  				});
  			}
  		}
  
  		return this;
  	};
  
  	/**
  	 * Alias of addListener
  	 */
  	proto.on = alias('addListener');
  
  	/**
  	 * Semi-alias of addListener. It will add a listener that will be
  	 * automatically removed after it's first execution.
  	 *
  	 * @param {String|RegExp} evt Name of the event to attach the listener to.
  	 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.addOnceListener = function addOnceListener(evt, listener) {
  		return this.addListener(evt, {
  			listener: listener,
  			once: true
  		});
  	};
  
  	/**
  	 * Alias of addOnceListener.
  	 */
  	proto.once = alias('addOnceListener');
  
  	/**
  	 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad.
  	 * You need to tell it what event names should be matched by a regex.
  	 *
  	 * @param {String} evt Name of the event to create.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.defineEvent = function defineEvent(evt) {
  		this.getListeners(evt);
  		return this;
  	};
  
  	/**
  	 * Uses defineEvent to define multiple events.
  	 *
  	 * @param {String[]} evts An array of event names to define.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.defineEvents = function defineEvents(evts) {
  		for (var i = 0; i < evts.length; i += 1) {
  			this.defineEvent(evts[i]);
  		}
  		return this;
  	};
  
  	/**
  	 * Removes a listener function from the specified event.
  	 * When passed a regular expression as the event name, it will remove the listener from all events that match it.
  	 *
  	 * @param {String|RegExp} evt Name of the event to remove the listener from.
  	 * @param {Function} listener Method to remove from the event.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.removeListener = function removeListener(evt, listener) {
  		var listeners = this.getListenersAsObject(evt);
  		var index;
  		var key;
  
  		for (key in listeners) {
  			if (listeners.hasOwnProperty(key)) {
  				index = indexOfListener(listeners[key], listener);
  
  				if (index !== -1) {
  					listeners[key].splice(index, 1);
  				}
  			}
  		}
  
  		return this;
  	};
  
  	/**
  	 * Alias of removeListener
  	 */
  	proto.off = alias('removeListener');
  
  	/**
  	 * Adds listeners in bulk using the manipulateListeners method.
  	 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added.
  	 * You can also pass it a regular expression to add the array of listeners to all events that match it.
  	 * Yeah, this function does quite a bit. That's probably a bad thing.
  	 *
  	 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once.
  	 * @param {Function[]} [listeners] An optional array of listener functions to add.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.addListeners = function addListeners(evt, listeners) {
  		// Pass through to manipulateListeners
  		return this.manipulateListeners(false, evt, listeners);
  	};
  
  	/**
  	 * Removes listeners in bulk using the manipulateListeners method.
  	 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
  	 * You can also pass it an event name and an array of listeners to be removed.
  	 * You can also pass it a regular expression to remove the listeners from all events that match it.
  	 *
  	 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once.
  	 * @param {Function[]} [listeners] An optional array of listener functions to remove.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.removeListeners = function removeListeners(evt, listeners) {
  		// Pass through to manipulateListeners
  		return this.manipulateListeners(true, evt, listeners);
  	};
  
  	/**
  	 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level.
  	 * The first argument will determine if the listeners are removed (true) or added (false).
  	 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays.
  	 * You can also pass it an event name and an array of listeners to be added/removed.
  	 * You can also pass it a regular expression to manipulate the listeners of all events that match it.
  	 *
  	 * @param {Boolean} remove True if you want to remove listeners, false if you want to add.
  	 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once.
  	 * @param {Function[]} [listeners] An optional array of listener functions to add/remove.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) {
  		var i;
  		var value;
  		var single = remove ? this.removeListener : this.addListener;
  		var multiple = remove ? this.removeListeners : this.addListeners;
  
  		// If evt is an object then pass each of it's properties to this method
  		if (typeof evt === 'object' && !(evt instanceof RegExp)) {
  			for (i in evt) {
  				if (evt.hasOwnProperty(i) && (value = evt[i])) {
  					// Pass the single listener straight through to the singular method
  					if (typeof value === 'function') {
  						single.call(this, i, value);
  					}
  					else {
  						// Otherwise pass back to the multiple function
  						multiple.call(this, i, value);
  					}
  				}
  			}
  		}
  		else {
  			// So evt must be a string
  			// And listeners must be an array of listeners
  			// Loop over it and pass each one to the multiple method
  			i = listeners.length;
  			while (i--) {
  				single.call(this, evt, listeners[i]);
  			}
  		}
  
  		return this;
  	};
  
  	/**
  	 * Removes all listeners from a specified event.
  	 * If you do not specify an event then all listeners will be removed.
  	 * That means every event will be emptied.
  	 * You can also pass a regex to remove all events that match it.
  	 *
  	 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.removeEvent = function removeEvent(evt) {
  		var type = typeof evt;
  		var events = this._getEvents();
  		var key;
  
  		// Remove different things depending on the state of evt
  		if (type === 'string') {
  			// Remove all listeners for the specified event
  			delete events[evt];
  		}
  		else if (type === 'object') {
  			// Remove all events matching the regex.
  			for (key in events) {
  				if (events.hasOwnProperty(key) && evt.test(key)) {
  					delete events[key];
  				}
  			}
  		}
  		else {
  			// Remove all listeners in all events
  			delete this._events;
  		}
  
  		return this;
  	};
  
  	/**
  	 * Alias of removeEvent.
  	 *
  	 * Added to mirror the node API.
  	 */
  	proto.removeAllListeners = alias('removeEvent');
  
  	/**
  	 * Emits an event of your choice.
  	 * When emitted, every listener attached to that event will be executed.
  	 * If you pass the optional argument array then those arguments will be passed to every listener upon execution.
  	 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately.
  	 * So they will not arrive within the array on the other side, they will be separate.
  	 * You can also pass a regular expression to emit to all events that match it.
  	 *
  	 * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
  	 * @param {Array} [args] Optional array of arguments to be passed to each listener.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.emitEvent = function emitEvent(evt, args) {
  		var listeners = this.getListenersAsObject(evt);
  		var listener;
  		var i;
  		var key;
  		var response;
  
  		for (key in listeners) {
  			if (listeners.hasOwnProperty(key)) {
  				i = listeners[key].length;
  
  				while (i--) {
  					// If the listener returns true then it shall be removed from the event
  					// The function is executed either with a basic call or an apply if there is an args array
  					listener = listeners[key][i];
  
  					if (listener.once === true) {
  						this.removeListener(evt, listener.listener);
  					}
  
  					response = listener.listener.apply(this, args || []);
  
  					if (response === this._getOnceReturnValue()) {
  						this.removeListener(evt, listener.listener);
  					}
  				}
  			}
  		}
  
  		return this;
  	};
  
  	/**
  	 * Alias of emitEvent
  	 */
  	proto.trigger = alias('emitEvent');
  
  	/**
  	 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on.
  	 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it.
  	 *
  	 * @param {String|RegExp} evt Name of the event to emit and execute listeners for.
  	 * @param {...*} Optional additional arguments to be passed to each listener.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.emit = function emit(evt) {
  		var args = Array.prototype.slice.call(arguments, 1);
  		return this.emitEvent(evt, args);
  	};
  
  	/**
  	 * Sets the current value to check against when executing listeners. If a
  	 * listeners return value matches the one set here then it will be removed
  	 * after execution. This value defaults to true.
  	 *
  	 * @param {*} value The new value to check for when executing listeners.
  	 * @return {Object} Current instance of EventEmitter for chaining.
  	 */
  	proto.setOnceReturnValue = function setOnceReturnValue(value) {
  		this._onceReturnValue = value;
  		return this;
  	};
  
  	/**
  	 * Fetches the current value to check against when executing listeners. If
  	 * the listeners return value matches this one then it should be removed
  	 * automatically. It will return true by default.
  	 *
  	 * @return {*|Boolean} The current value to check for or the default, true.
  	 * @api private
  	 */
  	proto._getOnceReturnValue = function _getOnceReturnValue() {
  		if (this.hasOwnProperty('_onceReturnValue')) {
  			return this._onceReturnValue;
  		}
  		else {
  			return true;
  		}
  	};
  
  	/**
  	 * Fetches the events object and creates one if required.
  	 *
  	 * @return {Object} The events storage object.
  	 * @api private
  	 */
  	proto._getEvents = function _getEvents() {
  		return this._events || (this._events = {});
  	};
  
  	// Expose the class either via AMD, CommonJS or the global object
  	if (typeof define === 'function' && define.amd) {
  		define(function () {
  			return EventEmitter;
  		});
  	}
  	else if (typeof module === 'object' && module.exports){
  		module.exports = EventEmitter;
  	}
  	else {
  		this.EventEmitter = EventEmitter;
  	}
  }.call(this));
  
  /*!
   * eventie v1.0.3
   * event binding helper
   *   eventie.bind( elem, 'click', myFn )
   *   eventie.unbind( elem, 'click', myFn )
   */
  
  /*jshint browser: true, undef: true, unused: true */
  /*global define: false */
  
  ( function( window ) {
  
  'use strict';
  
  var docElem = document.documentElement;
  
  var bind = function() {};
  
  if ( docElem.addEventListener ) {
    bind = function( obj, type, fn ) {
      obj.addEventListener( type, fn, false );
    };
  } else if ( docElem.attachEvent ) {
    bind = function( obj, type, fn ) {
      obj[ type + fn ] = fn.handleEvent ?
        function() {
          var event = window.event;
          // add event.target
          event.target = event.target || event.srcElement;
          fn.handleEvent.call( fn, event );
        } :
        function() {
          var event = window.event;
          // add event.target
          event.target = event.target || event.srcElement;
          fn.call( obj, event );
        };
      obj.attachEvent( "on" + type, obj[ type + fn ] );
    };
  }
  
  var unbind = function() {};
  
  if ( docElem.removeEventListener ) {
    unbind = function( obj, type, fn ) {
      obj.removeEventListener( type, fn, false );
    };
  } else if ( docElem.detachEvent ) {
    unbind = function( obj, type, fn ) {
      obj.detachEvent( "on" + type, obj[ type + fn ] );
      try {
        delete obj[ type + fn ];
      } catch ( err ) {
        // can't delete window object properties
        obj[ type + fn ] = undefined;
      }
    };
  }
  
  var eventie = {
    bind: bind,
    unbind: unbind
  };
  
  // transport
  if ( typeof define === 'function' && define.amd ) {
    // AMD
    define( eventie );
  } else {
    // browser global
    window.eventie = eventie;
  }
  
  })( this );
  
  /*!
   * imagesLoaded v3.0.4
   * JavaScript is all like "You images are done yet or what?"
   * MIT License
   */
  
  ( function( window ) {
  
  'use strict';
  
  var $ = window.jQuery;
  var console = window.console;
  var hasConsole = typeof console !== 'undefined';
  
  // -------------------------- helpers -------------------------- //
  
  // extend objects
  function extend( a, b ) {
    for ( var prop in b ) {
      a[ prop ] = b[ prop ];
    }
    return a;
  }
  
  var objToString = Object.prototype.toString;
  function isArray( obj ) {
    return objToString.call( obj ) === '[object Array]';
  }
  
  // turn element or nodeList into an array
  function makeArray( obj ) {
    var ary = [];
    if ( isArray( obj ) ) {
      // use object if already an array
      ary = obj;
    } else if ( typeof obj.length === 'number' ) {
      // convert nodeList to array
      for ( var i=0, len = obj.length; i < len; i++ ) {
        ary.push( obj[i] );
      }
    } else {
      // array of single index
      ary.push( obj );
    }
    return ary;
  }
  
  // --------------------------  -------------------------- //
  
  function defineImagesLoaded( EventEmitter, eventie ) {
  
    /**
     * @param {Array, Element, NodeList, String} elem
     * @param {Object or Function} options - if function, use as callback
     * @param {Function} onAlways - callback function
     */
    function ImagesLoaded( elem, options, onAlways ) {
      // coerce ImagesLoaded() without new, to be new ImagesLoaded()
      if ( !( this instanceof ImagesLoaded ) ) {
        return new ImagesLoaded( elem, options );
      }
      // use elem as selector string
      if ( typeof elem === 'string' ) {
        elem = document.querySelectorAll( elem );
      }
  
      this.elements = makeArray( elem );
      this.options = extend( {}, this.options );
  
      if ( typeof options === 'function' ) {
        onAlways = options;
      } else {
        extend( this.options, options );
      }
  
      if ( onAlways ) {
        this.on( 'always', onAlways );
      }
  
      this.getImages();
  
      if ( $ ) {
        // add jQuery Deferred object
        this.jqDeferred = new $.Deferred();
      }
  
      // HACK check async to allow time to bind listeners
      var _this = this;
      setTimeout( function() {
        _this.check();
      });
    }
  
    ImagesLoaded.prototype = new EventEmitter();
  
    ImagesLoaded.prototype.options = {};
  
    ImagesLoaded.prototype.getImages = function() {
      this.images = [];
  
      // filter & find items if we have an item selector
      for ( var i=0, len = this.elements.length; i < len; i++ ) {
        var elem = this.elements[i];
        // filter siblings
        if ( elem.nodeName === 'IMG' ) {
          this.addImage( elem );
        }
        // find children
        var childElems = elem.querySelectorAll('img');
        // concat childElems to filterFound array
        for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
          var img = childElems[j];
          this.addImage( img );
        }
      }
    };
  
    /**
     * @param {Image} img
     */
    ImagesLoaded.prototype.addImage = function( img ) {
      var loadingImage = new LoadingImage( img );
      this.images.push( loadingImage );
    };
  
    ImagesLoaded.prototype.check = function() {
      var _this = this;
      var checkedCount = 0;
      var length = this.images.length;
      this.hasAnyBroken = false;
      // complete if no images
      if ( !length ) {
        this.complete();
        return;
      }
  
      function onConfirm( image, message ) {
        if ( _this.options.debug && hasConsole ) {
          console.log( 'confirm', image, message );
        }
  
        _this.progress( image );
        checkedCount++;
        if ( checkedCount === length ) {
          _this.complete();
        }
        return true; // bind once
      }
  
      for ( var i=0; i < length; i++ ) {
        var loadingImage = this.images[i];
        loadingImage.on( 'confirm', onConfirm );
        loadingImage.check();
      }
    };
  
    ImagesLoaded.prototype.progress = function( image ) {
      this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
      // HACK - Chrome triggers event before object properties have changed. #83
      var _this = this;
      setTimeout( function() {
        _this.emit( 'progress', _this, image );
        if ( _this.jqDeferred ) {
          _this.jqDeferred.notify( _this, image );
        }
      });
    };
  
    ImagesLoaded.prototype.complete = function() {
      var eventName = this.hasAnyBroken ? 'fail' : 'done';
      this.isComplete = true;
      var _this = this;
      // HACK - another setTimeout so that confirm happens after progress
      setTimeout( function() {
        _this.emit( eventName, _this );
        _this.emit( 'always', _this );
        if ( _this.jqDeferred ) {
          var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve';
          _this.jqDeferred[ jqMethod ]( _this );
        }
      });
    };
  
    // -------------------------- jquery -------------------------- //
  
    if ( $ ) {
      $.fn.imagesLoaded = function( options, callback ) {
        var instance = new ImagesLoaded( this, options, callback );
        return instance.jqDeferred.promise( $(this) );
      };
    }
  
  
    // --------------------------  -------------------------- //
  
    var cache = {};
  
    function LoadingImage( img ) {
      this.img = img;
    }
  
    LoadingImage.prototype = new EventEmitter();
  
    LoadingImage.prototype.check = function() {
      // first check cached any previous images that have same src
      var cached = cache[ this.img.src ];
      if ( cached ) {
        this.useCached( cached );
        return;
      }
      // add this to cache
      cache[ this.img.src ] = this;
  
      // If complete is true and browser supports natural sizes,
      // try to check for image status manually.
      if ( this.img.complete && this.img.naturalWidth !== undefined ) {
        // report based on naturalWidth
        this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
        return;
      }
  
      // If none of the checks above matched, simulate loading on detached element.
      var proxyImage = this.proxyImage = new Image();
      eventie.bind( proxyImage, 'load', this );
      eventie.bind( proxyImage, 'error', this );
      proxyImage.src = this.img.src;
    };
  
    LoadingImage.prototype.useCached = function( cached ) {
      if ( cached.isConfirmed ) {
        this.confirm( cached.isLoaded, 'cached was confirmed' );
      } else {
        var _this = this;
        cached.on( 'confirm', function( image ) {
          _this.confirm( image.isLoaded, 'cache emitted confirmed' );
          return true; // bind once
        });
      }
    };
  
    LoadingImage.prototype.confirm = function( isLoaded, message ) {
      this.isConfirmed = true;
      this.isLoaded = isLoaded;
      this.emit( 'confirm', this, message );
    };
  
    // trigger specified handler for event type
    LoadingImage.prototype.handleEvent = function( event ) {
      var method = 'on' + event.type;
      if ( this[ method ] ) {
        this[ method ]( event );
      }
    };
  
    LoadingImage.prototype.onload = function() {
      this.confirm( true, 'onload' );
      this.unbindProxyEvents();
    };
  
    LoadingImage.prototype.onerror = function() {
      this.confirm( false, 'onerror' );
      this.unbindProxyEvents();
    };
  
    LoadingImage.prototype.unbindProxyEvents = function() {
      eventie.unbind( this.proxyImage, 'load', this );
      eventie.unbind( this.proxyImage, 'error', this );
    };
  
    // -----  ----- //
  
    return ImagesLoaded;
  }
  
  // -------------------------- transport -------------------------- //
  
  if ( typeof define === 'function' && define.amd ) {
    // AMD
    define( [
        'eventEmitter/EventEmitter',
        'eventie/eventie'
      ],
      defineImagesLoaded );
  } else {
    // browser global
    window.imagesLoaded = defineImagesLoaded(
      window.EventEmitter,
      window.eventie
    );
  }
  
  })( window );
  (function() {
    var initAvatarImages;
  
    initAvatarImages = function() {
      return $('.avatar').imagesLoaded().fail(function(imgs) {
        var img, _i, _len, _ref, _results;
        _ref = imgs.images;
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          img = _ref[_i];
          if (img.isConfirmed && !img.isLoaded) {
            _results.push($(img.img).closest('.avatar').addClass('error'));
          } else {
            _results.push(void 0);
          }
        }
        return _results;
      });
    };
  
    $(document).on('ready page:load', function() {
      return initAvatarImages();
    });
  
  }).call(this);
  (function() {
    var Confirm;
  
    Confirm = {
      initRailsHook: function() {
        return $.rails.allowAction = (function(_this) {
          return function(elem) {
            return _this.allowAction(elem);
          };
        })(this);
      },
      allowAction: function(elem) {
        var $modal, modal;
        modal = elem.data('confirm-modal');
        if (!modal) {
          return true;
        }
        $modal = $(modal);
        if ($modal && $.rails.fire(elem, 'confirm')) {
          this.showModal($modal, elem);
        }
        return false;
      },
      confirmed: function(elem) {
        if ($.rails.fire(elem, 'confirm:complete', [true])) {
          $.rails.allowAction = function() {
            return true;
          };
          elem.trigger('click');
          return $.rails.allowAction = this.allowAction;
        }
      },
      showModal: function($modal, elem) {
        if ($modal.hasClass('reveal-modal')) {
          $modal.foundation('reveal', 'open');
          $modal.find('[data-dismiss]').on('click', (function(_this) {
            return function() {
              return $modal.foundation('reveal', 'close');
            };
          })(this));
        } else {
          $modal.modal();
        }
        return $modal.find('[data-confirm]').on('click', (function(_this) {
          return function() {
            return _this.confirmed(elem);
          };
        })(this));
      }
    };
  
    $(function() {
      return Confirm.initRailsHook();
    });
  
  }).call(this);
  /*!
   * jQuery.ScrollTo
   * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
   * Licensed under MIT
   * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
   * @projectDescription Easy element scrolling using jQuery.
   * @author Ariel Flesler
   * @version 1.4.11
   */
  
  
  ;(function(plugin) {
      // AMD Support
      if (typeof define === 'function' && define.amd) {
          define(['jquery'], plugin);
      } else {
          plugin(jQuery);
      }
  }(function($) {
  
    var $scrollTo = $.scrollTo = function( target, duration, settings ) {
      return $(window).scrollTo( target, duration, settings );
    };
  
    $scrollTo.defaults = {
      axis:'xy',
      duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1,
      limit:true
    };
  
    // Returns the element that needs to be animated to scroll the window.
    // Kept for backwards compatibility (specially for localScroll & serialScroll)
    $scrollTo.window = function( scope ) {
      return $(window)._scrollable();
    };
  
    // Hack, hack, hack :)
    // Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
    $.fn._scrollable = function() {
      return this.map(function() {
        var elem = this,
          isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1;
  
          if (!isWin)
            return elem;
  
        var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem;
  
        return /webkit/i.test(navigator.userAgent) || doc.compatMode == 'BackCompat' ?
          doc.body :
          doc.documentElement;
      });
    };
  
    $.fn.scrollTo = function( target, duration, settings ) {
      if (typeof duration == 'object') {
        settings = duration;
        duration = 0;
      }
      if (typeof settings == 'function')
        settings = { onAfter:settings };
  
      if (target == 'max')
        target = 9e9;
  
      settings = $.extend( {}, $scrollTo.defaults, settings );
      // Speed is still recognized for backwards compatibility
      duration = duration || settings.duration;
      // Make sure the settings are given right
      settings.queue = settings.queue && settings.axis.length > 1;
  
      if (settings.queue)
        // Let's keep the overall duration
        duration /= 2;
      settings.offset = both( settings.offset );
      settings.over = both( settings.over );
  
      return this._scrollable().each(function() {
        // Null target yields nothing, just like jQuery does
        if (target == null) return;
  
        var elem = this,
          $elem = $(elem),
          targ = target, toff, attr = {},
          win = $elem.is('html,body');
  
        switch (typeof targ) {
          // A number will pass the regex
          case 'number':
          case 'string':
            if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) {
              targ = both( targ );
              // We are done
              break;
            }
            // Relative selector, no break!
            targ = $(targ,this);
            if (!targ.length) return;
          case 'object':
            // DOMElement / jQuery
            if (targ.is || targ.style)
              // Get the real position of the target
              toff = (targ = $(targ)).offset();
        }
  
        var offset = $.isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset;
  
        $.each( settings.axis.split(''), function( i, axis ) {
          var Pos = axis == 'x' ? 'Left' : 'Top',
            pos = Pos.toLowerCase(),
            key = 'scroll' + Pos,
            old = elem[key],
            max = $scrollTo.max(elem, axis);
  
          if (toff) {// jQuery / DOMElement
            attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );
  
            // If it's a dom element, reduce the margin
            if (settings.margin) {
              attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
              attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
            }
  
            attr[key] += offset[pos] || 0;
  
            if(settings.over[pos])
              // Scroll to a fraction of its width/height
              attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos];
          } else {
            var val = targ[pos];
            // Handle percentage values
            attr[key] = val.slice && val.slice(-1) == '%' ?
              parseFloat(val) / 100 * max
              : val;
          }
  
          // Number or 'number'
          if (settings.limit && /^\d+$/.test(attr[key]))
            // Check the limits
            attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max );
  
          // Queueing axes
          if (!i && settings.queue) {
            // Don't waste time animating, if there's no need.
            if (old != attr[key])
              // Intermediate animation
              animate( settings.onAfterFirst );
            // Don't animate this axis again in the next iteration.
            delete attr[key];
          }
        });
  
        animate( settings.onAfter );
  
        function animate( callback ) {
          $elem.animate( attr, duration, settings.easing, callback && function() {
            callback.call(this, targ, settings);
          });
        };
  
      }).end();
    };
  
    // Max scrolling position, works on quirks mode
    // It only fails (not too badly) on IE, quirks mode.
    $scrollTo.max = function( elem, axis ) {
      var Dim = axis == 'x' ? 'Width' : 'Height',
        scroll = 'scroll'+Dim;
  
      if (!$(elem).is('html,body'))
        return elem[scroll] - $(elem)[Dim.toLowerCase()]();
  
      var size = 'client' + Dim,
        html = elem.ownerDocument.documentElement,
        body = elem.ownerDocument.body;
  
      return Math.max( html[scroll], body[scroll] )
         - Math.min( html[size]  , body[size]   );
    };
  
    function both( val ) {
      return $.isFunction(val) || typeof val == 'object' ? val : { top:val, left:val };
    };
  
      // AMD requirement
      return $scrollTo;
  }));
  (function() {
  
  
  }).call(this);
  