summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Weller <lhw@ring0.de>2017-01-26 12:38:12 +0000
committerLennart Weller <lhw@ring0.de>2017-01-26 12:38:12 +0000
commitddd4c2df4454614702d092ee9461f4b108048f28 (patch)
tree29ef10a0d966cfdc7aaaf434c75554e52b75c8de
parentmissed some js files (diff)
downloadnetdata-ddd4c2df4454614702d092ee9461f4b108048f28.tar.xz
netdata-ddd4c2df4454614702d092ee9461f4b108048f28.zip
include (hopefully) all missing-sources
-rw-r--r--debian/copyright17
-rw-r--r--debian/missing-sources/bootstrap-3.3.7.js2377
-rw-r--r--debian/missing-sources/bootstrap-table-1.11.0.js3019
-rw-r--r--debian/missing-sources/bootstrap-table-export-1.11.0.js121
-rw-r--r--debian/missing-sources/bootstrap-theme-3.3.7.css587
-rw-r--r--debian/missing-sources/bootstrap-toggle-2.2.2.css (renamed from debian/missing-sources/bootstrap-toggle.css)0
-rw-r--r--debian/missing-sources/bootstrap-toggle-2.2.2.js (renamed from debian/missing-sources/bootstrap-toggle.js)0
-rw-r--r--debian/missing-sources/bootstrap.slate.css7271
-rw-r--r--debian/missing-sources/c3-0.4.11.css (renamed from debian/missing-sources/c3.css)12
-rw-r--r--debian/missing-sources/c3-0.4.11.js (renamed from debian/missing-sources/c3.js)999
-rw-r--r--debian/missing-sources/d3-3.5.17.js9554
-rw-r--r--debian/missing-sources/dygraph-combined-dd74404.js6
-rw-r--r--debian/missing-sources/dygraph-combined.js11219
-rw-r--r--debian/missing-sources/gauge-d5260c3.coffee (renamed from debian/missing-sources/gauge.coffee)3
-rw-r--r--debian/missing-sources/jquery-2.2.4.js9814
-rw-r--r--debian/missing-sources/jquery.easypiechart-97b5824.js (renamed from debian/missing-sources/jquery.easypiechart.js)0
-rw-r--r--debian/missing-sources/jquery.nanoscroller.js1000
-rw-r--r--debian/missing-sources/jquery.peity-3.2.0.js (renamed from debian/missing-sources/jquery.peity.js)0
-rw-r--r--debian/missing-sources/jquery.sparkline-2.1.2.js (renamed from debian/missing-sources/jquery.sparkline.js)0
-rw-r--r--debian/missing-sources/morris-0.5.1.css (renamed from debian/missing-sources/morris.css)0
-rw-r--r--debian/missing-sources/morris-0.5.1.js (renamed from debian/missing-sources/morris.js)5
-rw-r--r--debian/missing-sources/perfect-scrollbar-0.6.15.js1552
-rw-r--r--debian/missing-sources/raphael-2.2.4.js8190
-rw-r--r--debian/missing-sources/tableExport-1.6.0.js1736
24 files changed, 37922 insertions, 19560 deletions
diff --git a/debian/copyright b/debian/copyright
index b31edf130..2f83af459 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -48,9 +48,11 @@ Copyright: 2015 Joseph Huckaby
License: Expat
Files:
- web/css/bootstrap-3.3.7.css
+ web/css/bootstrap-3.3.7.min.css
+ web/css/bootstrap-theme-3.3.7.min.css
web/lib/bootstrap-3.3.7.min.js
debian/missing-sources/bootstrap-3.3.7.js
+ debian/missing-sources/bootstrap-theme-3.3.7.css
Copyright: 2011-2016 Twitter, Inc
License: Expat
@@ -78,8 +80,8 @@ License: Expat
Files:
web/lib/c3-0.4.11.min.js
web/css/c3-0.4.11.min.css
- debian/missing-sources/c3-0.4.11.min.js
- debian/missing-sources/c3-0.4.11.min.css
+ debian/missing-sources/c3-0.4.11.js
+ debian/missing-sources/c3-0.4.11.css
Copyright: 2013 Masayuki Tanaka
License: Expat
@@ -123,7 +125,7 @@ License: BSD-3-clause
Files:
web/lib/morris-0.5.1.min.js
web/css/morris-0.5.1.css
- debian/missing-sources/morris-0.5.1.min.js
+ debian/missing-sources/morris-0.5.1.js
debian/missing-sources/morris-0.5.1.css
Copyright: 2014 Olly Smith
License: BSD-2-clause
@@ -155,6 +157,13 @@ Copyright: 2016 hhurz
2014 Giri Raj
License: Expat
+Files:
+ web/lib/raphael-2.2.4.min.js
+ debian/missing-sources/raphael-2.2.4.js
+Copyright: 2016 Dmitry Baranovskiy
+ 2016 Sencha Labs
+License: Expat
+
License: LGPL-3+
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
diff --git a/debian/missing-sources/bootstrap-3.3.7.js b/debian/missing-sources/bootstrap-3.3.7.js
new file mode 100644
index 000000000..8a2e99a53
--- /dev/null
+++ b/debian/missing-sources/bootstrap-3.3.7.js
@@ -0,0 +1,2377 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under the MIT license
+ */
+
+if (typeof jQuery === 'undefined') {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+ 'use strict';
+ var version = $.fn.jquery.split(' ')[0].split('.')
+ if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
+ }
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: transition.js v3.3.7
+ * http://getbootstrap.com/javascript/#transitions
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
+ // ============================================================
+
+ function transitionEnd() {
+ var el = document.createElement('bootstrap')
+
+ var transEndEventNames = {
+ WebkitTransition : 'webkitTransitionEnd',
+ MozTransition : 'transitionend',
+ OTransition : 'oTransitionEnd otransitionend',
+ transition : 'transitionend'
+ }
+
+ for (var name in transEndEventNames) {
+ if (el.style[name] !== undefined) {
+ return { end: transEndEventNames[name] }
+ }
+ }
+
+ return false // explicit for ie8 ( ._.)
+ }
+
+ // http://blog.alexmaccaw.com/css-transitions
+ $.fn.emulateTransitionEnd = function (duration) {
+ var called = false
+ var $el = this
+ $(this).one('bsTransitionEnd', function () { called = true })
+ var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
+ setTimeout(callback, duration)
+ return this
+ }
+
+ $(function () {
+ $.support.transition = transitionEnd()
+
+ if (!$.support.transition) return
+
+ $.event.special.bsTransitionEnd = {
+ bindType: $.support.transition.end,
+ delegateType: $.support.transition.end,
+ handle: function (e) {
+ if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
+ }
+ }
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: alert.js v3.3.7
+ * http://getbootstrap.com/javascript/#alerts
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // ALERT CLASS DEFINITION
+ // ======================
+
+ var dismiss = '[data-dismiss="alert"]'
+ var Alert = function (el) {
+ $(el).on('click', dismiss, this.close)
+ }
+
+ Alert.VERSION = '3.3.7'
+
+ Alert.TRANSITION_DURATION = 150
+
+ Alert.prototype.close = function (e) {
+ var $this = $(this)
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = $(selector === '#' ? [] : selector)
+
+ if (e) e.preventDefault()
+
+ if (!$parent.length) {
+ $parent = $this.closest('.alert')
+ }
+
+ $parent.trigger(e = $.Event('close.bs.alert'))
+
+ if (e.isDefaultPrevented()) return
+
+ $parent.removeClass('in')
+
+ function removeElement() {
+ // detach from parent, fire event then clean up data
+ $parent.detach().trigger('closed.bs.alert').remove()
+ }
+
+ $.support.transition && $parent.hasClass('fade') ?
+ $parent
+ .one('bsTransitionEnd', removeElement)
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
+ removeElement()
+ }
+
+
+ // ALERT PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.alert')
+
+ if (!data) $this.data('bs.alert', (data = new Alert(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.alert
+
+ $.fn.alert = Plugin
+ $.fn.alert.Constructor = Alert
+
+
+ // ALERT NO CONFLICT
+ // =================
+
+ $.fn.alert.noConflict = function () {
+ $.fn.alert = old
+ return this
+ }
+
+
+ // ALERT DATA-API
+ // ==============
+
+ $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: button.js v3.3.7
+ * http://getbootstrap.com/javascript/#buttons
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // BUTTON PUBLIC CLASS DEFINITION
+ // ==============================
+
+ var Button = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Button.DEFAULTS, options)
+ this.isLoading = false
+ }
+
+ Button.VERSION = '3.3.7'
+
+ Button.DEFAULTS = {
+ loadingText: 'loading...'
+ }
+
+ Button.prototype.setState = function (state) {
+ var d = 'disabled'
+ var $el = this.$element
+ var val = $el.is('input') ? 'val' : 'html'
+ var data = $el.data()
+
+ state += 'Text'
+
+ if (data.resetText == null) $el.data('resetText', $el[val]())
+
+ // push to event loop to allow forms to submit
+ setTimeout($.proxy(function () {
+ $el[val](data[state] == null ? this.options[state] : data[state])
+
+ if (state == 'loadingText') {
+ this.isLoading = true
+ $el.addClass(d).attr(d, d).prop(d, true)
+ } else if (this.isLoading) {
+ this.isLoading = false
+ $el.removeClass(d).removeAttr(d).prop(d, false)
+ }
+ }, this), 0)
+ }
+
+ Button.prototype.toggle = function () {
+ var changed = true
+ var $parent = this.$element.closest('[data-toggle="buttons"]')
+
+ if ($parent.length) {
+ var $input = this.$element.find('input')
+ if ($input.prop('type') == 'radio') {
+ if ($input.prop('checked')) changed = false
+ $parent.find('.active').removeClass('active')
+ this.$element.addClass('active')
+ } else if ($input.prop('type') == 'checkbox') {
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
+ this.$element.toggleClass('active')
+ }
+ $input.prop('checked', this.$element.hasClass('active'))
+ if (changed) $input.trigger('change')
+ } else {
+ this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
+ this.$element.toggleClass('active')
+ }
+ }
+
+
+ // BUTTON PLUGIN DEFINITION
+ // ========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.button')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.button', (data = new Button(this, options)))
+
+ if (option == 'toggle') data.toggle()
+ else if (option) data.setState(option)
+ })
+ }
+
+ var old = $.fn.button
+
+ $.fn.button = Plugin
+ $.fn.button.Constructor = Button
+
+
+ // BUTTON NO CONFLICT
+ // ==================
+
+ $.fn.button.noConflict = function () {
+ $.fn.button = old
+ return this
+ }
+
+
+ // BUTTON DATA-API
+ // ===============
+
+ $(document)
+ .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ var $btn = $(e.target).closest('.btn')
+ Plugin.call($btn, 'toggle')
+ if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
+ // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
+ e.preventDefault()
+ // The target component still receive the focus
+ if ($btn.is('input,button')) $btn.trigger('focus')
+ else $btn.find('input:visible,button:visible').first().trigger('focus')
+ }
+ })
+ .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
+ $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: carousel.js v3.3.7
+ * http://getbootstrap.com/javascript/#carousel
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // CAROUSEL CLASS DEFINITION
+ // =========================
+
+ var Carousel = function (element, options) {
+ this.$element = $(element)
+ this.$indicators = this.$element.find('.carousel-indicators')
+ this.options = options
+ this.paused = null
+ this.sliding = null
+ this.interval = null
+ this.$active = null
+ this.$items = null
+
+ this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
+
+ this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
+ .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
+ .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
+ }
+
+ Carousel.VERSION = '3.3.7'
+
+ Carousel.TRANSITION_DURATION = 600
+
+ Carousel.DEFAULTS = {
+ interval: 5000,
+ pause: 'hover',
+ wrap: true,
+ keyboard: true
+ }
+
+ Carousel.prototype.keydown = function (e) {
+ if (/input|textarea/i.test(e.target.tagName)) return
+ switch (e.which) {
+ case 37: this.prev(); break
+ case 39: this.next(); break
+ default: return
+ }
+
+ e.preventDefault()
+ }
+
+ Carousel.prototype.cycle = function (e) {
+ e || (this.paused = false)
+
+ this.interval && clearInterval(this.interval)
+
+ this.options.interval
+ && !this.paused
+ && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
+
+ return this
+ }
+
+ Carousel.prototype.getItemIndex = function (item) {
+ this.$items = item.parent().children('.item')
+ return this.$items.index(item || this.$active)
+ }
+
+ Carousel.prototype.getItemForDirection = function (direction, active) {
+ var activeIndex = this.getItemIndex(active)
+ var willWrap = (direction == 'prev' && activeIndex === 0)
+ || (direction == 'next' && activeIndex == (this.$items.length - 1))
+ if (willWrap && !this.options.wrap) return active
+ var delta = direction == 'prev' ? -1 : 1
+ var itemIndex = (activeIndex + delta) % this.$items.length
+ return this.$items.eq(itemIndex)
+ }
+
+ Carousel.prototype.to = function (pos) {
+ var that = this
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
+
+ if (pos > (this.$items.length - 1) || pos < 0) return
+
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
+ if (activeIndex == pos) return this.pause().cycle()
+
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
+ }
+
+ Carousel.prototype.pause = function (e) {
+ e || (this.paused = true)
+
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
+ this.$element.trigger($.support.transition.end)
+ this.cycle(true)
+ }
+
+ this.interval = clearInterval(this.interval)
+
+ return this
+ }
+
+ Carousel.prototype.next = function () {
+ if (this.sliding) return
+ return this.slide('next')
+ }
+
+ Carousel.prototype.prev = function () {
+ if (this.sliding) return
+ return this.slide('prev')
+ }
+
+ Carousel.prototype.slide = function (type, next) {
+ var $active = this.$element.find('.item.active')
+ var $next = next || this.getItemForDirection(type, $active)
+ var isCycling = this.interval
+ var direction = type == 'next' ? 'left' : 'right'
+ var that = this
+
+ if ($next.hasClass('active')) return (this.sliding = false)
+
+ var relatedTarget = $next[0]
+ var slideEvent = $.Event('slide.bs.carousel', {
+ relatedTarget: relatedTarget,
+ direction: direction
+ })
+ this.$element.trigger(slideEvent)
+ if (slideEvent.isDefaultPrevented()) return
+
+ this.sliding = true
+
+ isCycling && this.pause()
+
+ if (this.$indicators.length) {
+ this.$indicators.find('.active').removeClass('active')
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
+ $nextIndicator && $nextIndicator.addClass('active')
+ }
+
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
+ if ($.support.transition && this.$element.hasClass('slide')) {
+ $next.addClass(type)
+ $next[0].offsetWidth // force reflow
+ $active.addClass(direction)
+ $next.addClass(direction)
+ $active
+ .one('bsTransitionEnd', function () {
+ $next.removeClass([type, direction].join(' ')).addClass('active')
+ $active.removeClass(['active', direction].join(' '))
+ that.sliding = false
+ setTimeout(function () {
+ that.$element.trigger(slidEvent)
+ }, 0)
+ })
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
+ } else {
+ $active.removeClass('active')
+ $next.addClass('active')
+ this.sliding = false
+ this.$element.trigger(slidEvent)
+ }
+
+ isCycling && this.cycle()
+
+ return this
+ }
+
+
+ // CAROUSEL PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.carousel')
+ var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
+ var action = typeof option == 'string' ? option : options.slide
+
+ if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
+ if (typeof option == 'number') data.to(option)
+ else if (action) data[action]()
+ else if (options.interval) data.pause().cycle()
+ })
+ }
+
+ var old = $.fn.carousel
+
+ $.fn.carousel = Plugin
+ $.fn.carousel.Constructor = Carousel
+
+
+ // CAROUSEL NO CONFLICT
+ // ====================
+
+ $.fn.carousel.noConflict = function () {
+ $.fn.carousel = old
+ return this
+ }
+
+
+ // CAROUSEL DATA-API
+ // =================
+
+ var clickHandler = function (e) {
+ var href
+ var $this = $(this)
+ var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
+ if (!$target.hasClass('carousel')) return
+ var options = $.extend({}, $target.data(), $this.data())
+ var slideIndex = $this.attr('data-slide-to')
+ if (slideIndex) options.interval = false
+
+ Plugin.call($target, options)
+
+ if (slideIndex) {
+ $target.data('bs.carousel').to(slideIndex)
+ }
+
+ e.preventDefault()
+ }
+
+ $(document)
+ .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
+ .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
+
+ $(window).on('load', function () {
+ $('[data-ride="carousel"]').each(function () {
+ var $carousel = $(this)
+ Plugin.call($carousel, $carousel.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: collapse.js v3.3.7
+ * http://getbootstrap.com/javascript/#collapse
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+/* jshint latedef: false */
+
++function ($) {
+ 'use strict';
+
+ // COLLAPSE PUBLIC CLASS DEFINITION
+ // ================================
+
+ var Collapse = function (element, options) {
+ this.$element = $(element)
+ this.options = $.extend({}, Collapse.DEFAULTS, options)
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
+ this.transitioning = null
+
+ if (this.options.parent) {
+ this.$parent = this.getParent()
+ } else {
+ this.addAriaAndCollapsedClass(this.$element, this.$trigger)
+ }
+
+ if (this.options.toggle) this.toggle()
+ }
+
+ Collapse.VERSION = '3.3.7'
+
+ Collapse.TRANSITION_DURATION = 350
+
+ Collapse.DEFAULTS = {
+ toggle: true
+ }
+
+ Collapse.prototype.dimension = function () {
+ var hasWidth = this.$element.hasClass('width')
+ return hasWidth ? 'width' : 'height'
+ }
+
+ Collapse.prototype.show = function () {
+ if (this.transitioning || this.$element.hasClass('in')) return
+
+ var activesData
+ var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
+
+ if (actives && actives.length) {
+ activesData = actives.data('bs.collapse')
+ if (activesData && activesData.transitioning) return
+ }
+
+ var startEvent = $.Event('show.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ if (actives && actives.length) {
+ Plugin.call(actives, 'hide')
+ activesData || actives.data('bs.collapse', null)
+ }
+
+ var dimension = this.dimension()
+
+ this.$element
+ .removeClass('collapse')
+ .addClass('collapsing')[dimension](0)
+ .attr('aria-expanded', true)
+
+ this.$trigger
+ .removeClass('collapsed')
+ .attr('aria-expanded', true)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse in')[dimension]('')
+ this.transitioning = 0
+ this.$element
+ .trigger('shown.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ var scrollSize = $.camelCase(['scroll', dimension].join('-'))
+
+ this.$element
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
+ }
+
+ Collapse.prototype.hide = function () {
+ if (this.transitioning || !this.$element.hasClass('in')) return
+
+ var startEvent = $.Event('hide.bs.collapse')
+ this.$element.trigger(startEvent)
+ if (startEvent.isDefaultPrevented()) return
+
+ var dimension = this.dimension()
+
+ this.$element[dimension](this.$element[dimension]())[0].offsetHeight
+
+ this.$element
+ .addClass('collapsing')
+ .removeClass('collapse in')
+ .attr('aria-expanded', false)
+
+ this.$trigger
+ .addClass('collapsed')
+ .attr('aria-expanded', false)
+
+ this.transitioning = 1
+
+ var complete = function () {
+ this.transitioning = 0
+ this.$element
+ .removeClass('collapsing')
+ .addClass('collapse')
+ .trigger('hidden.bs.collapse')
+ }
+
+ if (!$.support.transition) return complete.call(this)
+
+ this.$element
+ [dimension](0)
+ .one('bsTransitionEnd', $.proxy(complete, this))
+ .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
+ }
+
+ Collapse.prototype.toggle = function () {
+ this[this.$element.hasClass('in') ? 'hide' : 'show']()
+ }
+
+ Collapse.prototype.getParent = function () {
+ return $(this.options.parent)
+ .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
+ .each($.proxy(function (i, element) {
+ var $element = $(element)
+ this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
+ }, this))
+ .end()
+ }
+
+ Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
+ var isOpen = $element.hasClass('in')
+
+ $element.attr('aria-expanded', isOpen)
+ $trigger
+ .toggleClass('collapsed', !isOpen)
+ .attr('aria-expanded', isOpen)
+ }
+
+ function getTargetFromTrigger($trigger) {
+ var href
+ var target = $trigger.attr('data-target')
+ || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
+
+ return $(target)
+ }
+
+
+ // COLLAPSE PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.collapse')
+ var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
+ if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.collapse
+
+ $.fn.collapse = Plugin
+ $.fn.collapse.Constructor = Collapse
+
+
+ // COLLAPSE NO CONFLICT
+ // ====================
+
+ $.fn.collapse.noConflict = function () {
+ $.fn.collapse = old
+ return this
+ }
+
+
+ // COLLAPSE DATA-API
+ // =================
+
+ $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
+ var $this = $(this)
+
+ if (!$this.attr('data-target')) e.preventDefault()
+
+ var $target = getTargetFromTrigger($this)
+ var data = $target.data('bs.collapse')
+ var option = data ? 'toggle' : $this.data()
+
+ Plugin.call($target, option)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: dropdown.js v3.3.7
+ * http://getbootstrap.com/javascript/#dropdowns
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // DROPDOWN CLASS DEFINITION
+ // =========================
+
+ var backdrop = '.dropdown-backdrop'
+ var toggle = '[data-toggle="dropdown"]'
+ var Dropdown = function (element) {
+ $(element).on('click.bs.dropdown', this.toggle)
+ }
+
+ Dropdown.VERSION = '3.3.7'
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = selector && $(selector)
+
+ return $parent && $parent.length ? $parent : $this.parent()
+ }
+
+ function clearMenus(e) {
+ if (e && e.which === 3) return
+ $(backdrop).remove()
+ $(toggle).each(function () {
+ var $this = $(this)
+ var $parent = getParent($this)
+ var relatedTarget = { relatedTarget: this }
+
+ if (!$parent.hasClass('open')) return
+
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
+
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
+ $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
+ })
+ }
+
+ Dropdown.prototype.toggle = function (e) {
+ var $this = $(this)
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ clearMenus()
+
+ if (!isActive) {
+ if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
+ // if mobile we use a backdrop because click events don't delegate
+ $(document.createElement('div'))
+ .addClass('dropdown-backdrop')
+ .insertAfter($(this))
+ .on('click', clearMenus)
+ }
+
+ var relatedTarget = { relatedTarget: this }
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this
+ .trigger('focus')
+ .attr('aria-expanded', 'true')
+
+ $parent
+ .toggleClass('open')
+ .trigger($.Event('shown.bs.dropdown', relatedTarget))
+ }
+
+ return false
+ }
+
+ Dropdown.prototype.keydown = function (e) {
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
+
+ var $this = $(this)
+
+ e.preventDefault()
+ e.stopPropagation()
+
+ if ($this.is('.disabled, :disabled')) return
+
+ var $parent = getParent($this)
+ var isActive = $parent.hasClass('open')
+
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
+ if (e.which == 27) $parent.find(toggle).trigger('focus')
+ return $this.trigger('click')
+ }
+
+ var desc = ' li:not(.disabled):visible a'
+ var $items = $parent.find('.dropdown-menu' + desc)
+
+ if (!$items.length) return
+
+ var index = $items.index(e.target)
+
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
+
+ $items.eq(index).trigger('focus')
+ }
+
+
+ // DROPDOWN PLUGIN DEFINITION
+ // ==========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.dropdown')
+
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
+ if (typeof option == 'string') data[option].call($this)
+ })
+ }
+
+ var old = $.fn.dropdown
+
+ $.fn.dropdown = Plugin
+ $.fn.dropdown.Constructor = Dropdown
+
+
+ // DROPDOWN NO CONFLICT
+ // ====================
+
+ $.fn.dropdown.noConflict = function () {
+ $.fn.dropdown = old
+ return this
+ }
+
+
+ // APPLY TO STANDARD DROPDOWN ELEMENTS
+ // ===================================
+
+ $(document)
+ .on('click.bs.dropdown.data-api', clearMenus)
+ .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
+ .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
+ .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: modal.js v3.3.7
+ * http://getbootstrap.com/javascript/#modals
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // MODAL CLASS DEFINITION
+ // ======================
+
+ var Modal = function (element, options) {
+ this.options = options
+ this.$body = $(document.body)
+ this.$element = $(element)
+ this.$dialog = this.$element.find('.modal-dialog')
+ this.$backdrop = null
+ this.isShown = null
+ this.originalBodyPad = null
+ this.scrollbarWidth = 0
+ this.ignoreBackdropClick = false
+
+ if (this.options.remote) {
+ this.$element
+ .find('.modal-content')
+ .load(this.options.remote, $.proxy(function () {
+ this.$element.trigger('loaded.bs.modal')
+ }, this))
+ }
+ }
+
+ Modal.VERSION = '3.3.7'
+
+ Modal.TRANSITION_DURATION = 300
+ Modal.BACKDROP_TRANSITION_DURATION = 150
+
+ Modal.DEFAULTS = {
+ backdrop: true,
+ keyboard: true,
+ show: true
+ }
+
+ Modal.prototype.toggle = function (_relatedTarget) {
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
+ }
+
+ Modal.prototype.show = function (_relatedTarget) {
+ var that = this
+ var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
+
+ this.$element.trigger(e)
+
+ if (this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = true
+
+ this.checkScrollbar()
+ this.setScrollbar()
+ this.$body.addClass('modal-open')
+
+ this.escape()
+ this.resize()
+
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
+
+ this.$dialog.on('mousedown.dismiss.bs.modal', function () {
+ that.$element.one('mouseup.dismiss.bs.modal', function (e) {
+ if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
+ })
+ })
+
+ this.backdrop(function () {
+ var transition = $.support.transition && that.$element.hasClass('fade')
+
+ if (!that.$element.parent().length) {
+ that.$element.appendTo(that.$body) // don't move modals dom position
+ }
+
+ that.$element
+ .show()
+ .scrollTop(0)
+
+ that.adjustDialog()
+
+ if (transition) {
+ that.$element[0].offsetWidth // force reflow
+ }
+
+ that.$element.addClass('in')
+
+ that.enforceFocus()
+
+ var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
+
+ transition ?
+ that.$dialog // wait for modal to slide in
+ .one('bsTransitionEnd', function () {
+ that.$element.trigger('focus').trigger(e)
+ })
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ that.$element.trigger('focus').trigger(e)
+ })
+ }
+
+ Modal.prototype.hide = function (e) {
+ if (e) e.preventDefault()
+
+ e = $.Event('hide.bs.modal')
+
+ this.$element.trigger(e)
+
+ if (!this.isShown || e.isDefaultPrevented()) return
+
+ this.isShown = false
+
+ this.escape()
+ this.resize()
+
+ $(document).off('focusin.bs.modal')
+
+ this.$element
+ .removeClass('in')
+ .off('click.dismiss.bs.modal')
+ .off('mouseup.dismiss.bs.modal')
+
+ this.$dialog.off('mousedown.dismiss.bs.modal')
+
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$element
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
+ this.hideModal()
+ }
+
+ Modal.prototype.enforceFocus = function () {
+ $(document)
+ .off('focusin.bs.modal') // guard against infinite focus loop
+ .on('focusin.bs.modal', $.proxy(function (e) {
+ if (document !== e.target &&
+ this.$element[0] !== e.target &&
+ !this.$element.has(e.target).length) {
+ this.$element.trigger('focus')
+ }
+ }, this))
+ }
+
+ Modal.prototype.escape = function () {
+ if (this.isShown && this.options.keyboard) {
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
+ e.which == 27 && this.hide()
+ }, this))
+ } else if (!this.isShown) {
+ this.$element.off('keydown.dismiss.bs.modal')
+ }
+ }
+
+ Modal.prototype.resize = function () {
+ if (this.isShown) {
+ $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
+ } else {
+ $(window).off('resize.bs.modal')
+ }
+ }
+
+ Modal.prototype.hideModal = function () {
+ var that = this
+ this.$element.hide()
+ this.backdrop(function () {
+ that.$body.removeClass('modal-open')
+ that.resetAdjustments()
+ that.resetScrollbar()
+ that.$element.trigger('hidden.bs.modal')
+ })
+ }
+
+ Modal.prototype.removeBackdrop = function () {
+ this.$backdrop && this.$backdrop.remove()
+ this.$backdrop = null
+ }
+
+ Modal.prototype.backdrop = function (callback) {
+ var that = this
+ var animate = this.$element.hasClass('fade') ? 'fade' : ''
+
+ if (this.isShown && this.options.backdrop) {
+ var doAnimate = $.support.transition && animate
+
+ this.$backdrop = $(document.createElement('div'))
+ .addClass('modal-backdrop ' + animate)
+ .appendTo(this.$body)
+
+ this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
+ if (this.ignoreBackdropClick) {
+ this.ignoreBackdropClick = false
+ return
+ }
+ if (e.target !== e.currentTarget) return
+ this.options.backdrop == 'static'
+ ? this.$element[0].focus()
+ : this.hide()
+ }, this))
+
+ if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
+
+ this.$backdrop.addClass('in')
+
+ if (!callback) return
+
+ doAnimate ?
+ this.$backdrop
+ .one('bsTransitionEnd', callback)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callback()
+
+ } else if (!this.isShown && this.$backdrop) {
+ this.$backdrop.removeClass('in')
+
+ var callbackRemove = function () {
+ that.removeBackdrop()
+ callback && callback()
+ }
+ $.support.transition && this.$element.hasClass('fade') ?
+ this.$backdrop
+ .one('bsTransitionEnd', callbackRemove)
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
+ callbackRemove()
+
+ } else if (callback) {
+ callback()
+ }
+ }
+
+ // these following methods are used to handle overflowing modals
+
+ Modal.prototype.handleUpdate = function () {
+ this.adjustDialog()
+ }
+
+ Modal.prototype.adjustDialog = function () {
+ var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
+
+ this.$element.css({
+ paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
+ paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
+ })
+ }
+
+ Modal.prototype.resetAdjustments = function () {
+ this.$element.css({
+ paddingLeft: '',
+ paddingRight: ''
+ })
+ }
+
+ Modal.prototype.checkScrollbar = function () {
+ var fullWindowWidth = window.innerWidth
+ if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
+ var documentElementRect = document.documentElement.getBoundingClientRect()
+ fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
+ }
+ this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
+ this.scrollbarWidth = this.measureScrollbar()
+ }
+
+ Modal.prototype.setScrollbar = function () {
+ var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
+ this.originalBodyPad = document.body.style.paddingRight || ''
+ if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
+ }
+
+ Modal.prototype.resetScrollbar = function () {
+ this.$body.css('padding-right', this.originalBodyPad)
+ }
+
+ Modal.prototype.measureScrollbar = function () { // thx walsh
+ var scrollDiv = document.createElement('div')
+ scrollDiv.className = 'modal-scrollbar-measure'
+ this.$body.append(scrollDiv)
+ var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
+ this.$body[0].removeChild(scrollDiv)
+ return scrollbarWidth
+ }
+
+
+ // MODAL PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option, _relatedTarget) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.modal')
+ var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
+
+ if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
+ if (typeof option == 'string') data[option](_relatedTarget)
+ else if (options.show) data.show(_relatedTarget)
+ })
+ }
+
+ var old = $.fn.modal
+
+ $.fn.modal = Plugin
+ $.fn.modal.Constructor = Modal
+
+
+ // MODAL NO CONFLICT
+ // =================
+
+ $.fn.modal.noConflict = function () {
+ $.fn.modal = old
+ return this
+ }
+
+
+ // MODAL DATA-API
+ // ==============
+
+ $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
+ var $this = $(this)
+ var href = $this.attr('href')
+ var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
+ var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
+
+ if ($this.is('a')) e.preventDefault()
+
+ $target.one('show.bs.modal', function (showEvent) {
+ if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
+ $target.one('hidden.bs.modal', function () {
+ $this.is(':visible') && $this.trigger('focus')
+ })
+ })
+ Plugin.call($target, option, this)
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tooltip.js v3.3.7
+ * http://getbootstrap.com/javascript/#tooltip
+ * Inspired by the original jQuery.tipsy by Jason Frame
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TOOLTIP PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Tooltip = function (element, options) {
+ this.type = null
+ this.options = null
+ this.enabled = null
+ this.timeout = null
+ this.hoverState = null
+ this.$element = null
+ this.inState = null
+
+ this.init('tooltip', element, options)
+ }
+
+ Tooltip.VERSION = '3.3.7'
+
+ Tooltip.TRANSITION_DURATION = 150
+
+ Tooltip.DEFAULTS = {
+ animation: true,
+ placement: 'top',
+ selector: false,
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
+ trigger: 'hover focus',
+ title: '',
+ delay: 0,
+ html: false,
+ container: false,
+ viewport: {
+ selector: 'body',
+ padding: 0
+ }
+ }
+
+ Tooltip.prototype.init = function (type, element, options) {
+ this.enabled = true
+ this.type = type
+ this.$element = $(element)
+ this.options = this.getOptions(options)
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
+ this.inState = { click: false, hover: false, focus: false }
+
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
+ }
+
+ var triggers = this.options.trigger.split(' ')
+
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i]
+
+ if (trigger == 'click') {
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
+ } else if (trigger != 'manual') {
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
+
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
+ }
+ }
+
+ this.options.selector ?
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
+ this.fixTitle()
+ }
+
+ Tooltip.prototype.getDefaults = function () {
+ return Tooltip.DEFAULTS
+ }
+
+ Tooltip.prototype.getOptions = function (options) {
+ options = $.extend({}, this.getDefaults(), this.$element.data(), options)
+
+ if (options.delay && typeof options.delay == 'number') {
+ options.delay = {
+ show: options.delay,
+ hide: options.delay
+ }
+ }
+
+ return options
+ }
+
+ Tooltip.prototype.getDelegateOptions = function () {
+ var options = {}
+ var defaults = this.getDefaults()
+
+ this._options && $.each(this._options, function (key, value) {
+ if (defaults[key] != value) options[key] = value
+ })
+
+ return options
+ }
+
+ Tooltip.prototype.enter = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
+ }
+
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
+ self.hoverState = 'in'
+ return
+ }
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'in'
+
+ if (!self.options.delay || !self.options.delay.show) return self.show()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'in') self.show()
+ }, self.options.delay.show)
+ }
+
+ Tooltip.prototype.isInStateTrue = function () {
+ for (var key in this.inState) {
+ if (this.inState[key]) return true
+ }
+
+ return false
+ }
+
+ Tooltip.prototype.leave = function (obj) {
+ var self = obj instanceof this.constructor ?
+ obj : $(obj.currentTarget).data('bs.' + this.type)
+
+ if (!self) {
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
+ $(obj.currentTarget).data('bs.' + this.type, self)
+ }
+
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
+ }
+
+ if (self.isInStateTrue()) return
+
+ clearTimeout(self.timeout)
+
+ self.hoverState = 'out'
+
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
+
+ self.timeout = setTimeout(function () {
+ if (self.hoverState == 'out') self.hide()
+ }, self.options.delay.hide)
+ }
+
+ Tooltip.prototype.show = function () {
+ var e = $.Event('show.bs.' + this.type)
+
+ if (this.hasContent() && this.enabled) {
+ this.$element.trigger(e)
+
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
+ if (e.isDefaultPrevented() || !inDom) return
+ var that = this
+
+ var $tip = this.tip()
+
+ var tipId = this.getUID(this.type)
+
+ this.setContent()
+ $tip.attr('id', tipId)
+ this.$element.attr('aria-describedby', tipId)
+
+ if (this.options.animation) $tip.addClass('fade')
+
+ var placement = typeof this.options.placement == 'function' ?
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
+ this.options.placement
+
+ var autoToken = /\s?auto?\s?/i
+ var autoPlace = autoToken.test(placement)
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
+
+ $tip
+ .detach()
+ .css({ top: 0, left: 0, display: 'block' })
+ .addClass(placement)
+ .data('bs.' + this.type, this)
+
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+ this.$element.trigger('inserted.bs.' + this.type)
+
+ var pos = this.getPosition()
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (autoPlace) {
+ var orgPlacement = placement
+ var viewportDim = this.getPosition(this.$viewport)
+
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
+ placement
+
+ $tip
+ .removeClass(orgPlacement)
+ .addClass(placement)
+ }
+
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
+
+ this.applyPlacement(calculatedOffset, placement)
+
+ var complete = function () {
+ var prevHoverState = that.hoverState
+ that.$element.trigger('shown.bs.' + that.type)
+ that.hoverState = null
+
+ if (prevHoverState == 'out') that.leave(that)
+ }
+
+ $.support.transition && this.$tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+ }
+ }
+
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
+ var $tip = this.tip()
+ var width = $tip[0].offsetWidth
+ var height = $tip[0].offsetHeight
+
+ // manually read margins because getBoundingClientRect includes difference
+ var marginTop = parseInt($tip.css('margin-top'), 10)
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
+
+ // we must check for NaN for ie 8/9
+ if (isNaN(marginTop)) marginTop = 0
+ if (isNaN(marginLeft)) marginLeft = 0
+
+ offset.top += marginTop
+ offset.left += marginLeft
+
+ // $.fn.offset doesn't round pixel values
+ // so we use setOffset directly with our own function B-0
+ $.offset.setOffset($tip[0], $.extend({
+ using: function (props) {
+ $tip.css({
+ top: Math.round(props.top),
+ left: Math.round(props.left)
+ })
+ }
+ }, offset), 0)
+
+ $tip.addClass('in')
+
+ // check to see if placing tip in new offset caused the tip to resize itself
+ var actualWidth = $tip[0].offsetWidth
+ var actualHeight = $tip[0].offsetHeight
+
+ if (placement == 'top' && actualHeight != height) {
+ offset.top = offset.top + height - actualHeight
+ }
+
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
+
+ if (delta.left) offset.left += delta.left
+ else offset.top += delta.top
+
+ var isVertical = /top|bottom/.test(placement)
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
+
+ $tip.offset(offset)
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
+ }
+
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
+ this.arrow()
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isVertical ? 'top' : 'left', '')
+ }
+
+ Tooltip.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+
+ $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
+ $tip.removeClass('fade in top bottom left right')
+ }
+
+ Tooltip.prototype.hide = function (callback) {
+ var that = this
+ var $tip = $(this.$tip)
+ var e = $.Event('hide.bs.' + this.type)
+
+ function complete() {
+ if (that.hoverState != 'in') $tip.detach()
+ if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ }
+ callback && callback()
+ }
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ $tip.removeClass('in')
+
+ $.support.transition && $tip.hasClass('fade') ?
+ $tip
+ .one('bsTransitionEnd', complete)
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
+ complete()
+
+ this.hoverState = null
+
+ return this
+ }
+
+ Tooltip.prototype.fixTitle = function () {
+ var $e = this.$element
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
+ }
+ }
+
+ Tooltip.prototype.hasContent = function () {
+ return this.getTitle()
+ }
+
+ Tooltip.prototype.getPosition = function ($element) {
+ $element = $element || this.$element
+
+ var el = $element[0]
+ var isBody = el.tagName == 'BODY'
+
+ var elRect = el.getBoundingClientRect()
+ if (elRect.width == null) {
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
+ }
+ var isSvg = window.SVGElement && el instanceof window.SVGElement
+ // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
+ // See https://github.com/twbs/bootstrap/issues/20280
+ var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
+
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
+ }
+
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
+
+ }
+
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
+ var delta = { top: 0, left: 0 }
+ if (!this.$viewport) return delta
+
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
+ var viewportDimensions = this.getPosition(this.$viewport)
+
+ if (/right|left/.test(placement)) {
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
+ delta.top = viewportDimensions.top - topEdgeOffset
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
+ }
+ } else {
+ var leftEdgeOffset = pos.left - viewportPadding
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
+ delta.left = viewportDimensions.left - leftEdgeOffset
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
+ }
+ }
+
+ return delta
+ }
+
+ Tooltip.prototype.getTitle = function () {
+ var title
+ var $e = this.$element
+ var o = this.options
+
+ title = $e.attr('data-original-title')
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
+
+ return title
+ }
+
+ Tooltip.prototype.getUID = function (prefix) {
+ do prefix += ~~(Math.random() * 1000000)
+ while (document.getElementById(prefix))
+ return prefix
+ }
+
+ Tooltip.prototype.tip = function () {
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ if (this.$tip.length != 1) {
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
+ }
+ }
+ return this.$tip
+ }
+
+ Tooltip.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
+ }
+
+ Tooltip.prototype.enable = function () {
+ this.enabled = true
+ }
+
+ Tooltip.prototype.disable = function () {
+ this.enabled = false
+ }
+
+ Tooltip.prototype.toggleEnabled = function () {
+ this.enabled = !this.enabled
+ }
+
+ Tooltip.prototype.toggle = function (e) {
+ var self = this
+ if (e) {
+ self = $(e.currentTarget).data('bs.' + this.type)
+ if (!self) {
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
+ $(e.currentTarget).data('bs.' + this.type, self)
+ }
+ }
+
+ if (e) {
+ self.inState.click = !self.inState.click
+ if (self.isInStateTrue()) self.enter(self)
+ else self.leave(self)
+ } else {
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+ }
+ }
+
+ Tooltip.prototype.destroy = function () {
+ var that = this
+ clearTimeout(this.timeout)
+ this.hide(function () {
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ if (that.$tip) {
+ that.$tip.detach()
+ }
+ that.$tip = null
+ that.$arrow = null
+ that.$viewport = null
+ that.$element = null
+ })
+ }
+
+
+ // TOOLTIP PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tooltip')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tooltip
+
+ $.fn.tooltip = Plugin
+ $.fn.tooltip.Constructor = Tooltip
+
+
+ // TOOLTIP NO CONFLICT
+ // ===================
+
+ $.fn.tooltip.noConflict = function () {
+ $.fn.tooltip = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: popover.js v3.3.7
+ * http://getbootstrap.com/javascript/#popovers
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // POPOVER PUBLIC CLASS DEFINITION
+ // ===============================
+
+ var Popover = function (element, options) {
+ this.init('popover', element, options)
+ }
+
+ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
+
+ Popover.VERSION = '3.3.7'
+
+ Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
+ placement: 'right',
+ trigger: 'click',
+ content: '',
+ template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
+ })
+
+
+ // NOTE: POPOVER EXTENDS tooltip.js
+ // ================================
+
+ Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
+
+ Popover.prototype.constructor = Popover
+
+ Popover.prototype.getDefaults = function () {
+ return Popover.DEFAULTS
+ }
+
+ Popover.prototype.setContent = function () {
+ var $tip = this.tip()
+ var title = this.getTitle()
+ var content = this.getContent()
+
+ $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
+ this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
+ ](content)
+
+ $tip.removeClass('fade top bottom left right in')
+
+ // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
+ // this manually by checking the contents.
+ if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
+ }
+
+ Popover.prototype.hasContent = function () {
+ return this.getTitle() || this.getContent()
+ }
+
+ Popover.prototype.getContent = function () {
+ var $e = this.$element
+ var o = this.options
+
+ return $e.attr('data-content')
+ || (typeof o.content == 'function' ?
+ o.content.call($e[0]) :
+ o.content)
+ }
+
+ Popover.prototype.arrow = function () {
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
+ }
+
+
+ // POPOVER PLUGIN DEFINITION
+ // =========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.popover')
+ var options = typeof option == 'object' && option
+
+ if (!data && /destroy|hide/.test(option)) return
+ if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.popover
+
+ $.fn.popover = Plugin
+ $.fn.popover.Constructor = Popover
+
+
+ // POPOVER NO CONFLICT
+ // ===================
+
+ $.fn.popover.noConflict = function () {
+ $.fn.popover = old
+ return this
+ }
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: scrollspy.js v3.3.7
+ * http://getbootstrap.com/javascript/#scrollspy
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // SCROLLSPY CLASS DEFINITION
+ // ==========================
+
+ function ScrollSpy(element, options) {
+ this.$body = $(document.body)
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
+ this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
+ this.selector = (this.options.target || '') + ' .nav li > a'
+ this.offsets = []
+ this.targets = []
+ this.activeTarget = null
+ this.scrollHeight = 0
+
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
+ this.refresh()
+ this.process()
+ }
+
+ ScrollSpy.VERSION = '3.3.7'
+
+ ScrollSpy.DEFAULTS = {
+ offset: 10
+ }
+
+ ScrollSpy.prototype.getScrollHeight = function () {
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
+ }
+
+ ScrollSpy.prototype.refresh = function () {
+ var that = this
+ var offsetMethod = 'offset'
+ var offsetBase = 0
+
+ this.offsets = []
+ this.targets = []
+ this.scrollHeight = this.getScrollHeight()
+
+ if (!$.isWindow(this.$scrollElement[0])) {
+ offsetMethod = 'position'
+ offsetBase = this.$scrollElement.scrollTop()
+ }
+
+ this.$body
+ .find(this.selector)
+ .map(function () {
+ var $el = $(this)
+ var href = $el.data('target') || $el.attr('href')
+ var $href = /^#./.test(href) && $(href)
+
+ return ($href
+ && $href.length
+ && $href.is(':visible')
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
+ })
+ .sort(function (a, b) { return a[0] - b[0] })
+ .each(function () {
+ that.offsets.push(this[0])
+ that.targets.push(this[1])
+ })
+ }
+
+ ScrollSpy.prototype.process = function () {
+ var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
+ var scrollHeight = this.getScrollHeight()
+ var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
+ var offsets = this.offsets
+ var targets = this.targets
+ var activeTarget = this.activeTarget
+ var i
+
+ if (this.scrollHeight != scrollHeight) {
+ this.refresh()
+ }
+
+ if (scrollTop >= maxScroll) {
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
+ }
+
+ if (activeTarget && scrollTop < offsets[0]) {
+ this.activeTarget = null
+ return this.clear()
+ }
+
+ for (i = offsets.length; i--;) {
+ activeTarget != targets[i]
+ && scrollTop >= offsets[i]
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
+ && this.activate(targets[i])
+ }
+ }
+
+ ScrollSpy.prototype.activate = function (target) {
+ this.activeTarget = target
+
+ this.clear()
+
+ var selector = this.selector +
+ '[data-target="' + target + '"],' +
+ this.selector + '[href="' + target + '"]'
+
+ var active = $(selector)
+ .parents('li')
+ .addClass('active')
+
+ if (active.parent('.dropdown-menu').length) {
+ active = active
+ .closest('li.dropdown')
+ .addClass('active')
+ }
+
+ active.trigger('activate.bs.scrollspy')
+ }
+
+ ScrollSpy.prototype.clear = function () {
+ $(this.selector)
+ .parentsUntil(this.options.target, '.active')
+ .removeClass('active')
+ }
+
+
+ // SCROLLSPY PLUGIN DEFINITION
+ // ===========================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.scrollspy')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.scrollspy
+
+ $.fn.scrollspy = Plugin
+ $.fn.scrollspy.Constructor = ScrollSpy
+
+
+ // SCROLLSPY NO CONFLICT
+ // =====================
+
+ $.fn.scrollspy.noConflict = function () {
+ $.fn.scrollspy = old
+ return this
+ }
+
+
+ // SCROLLSPY DATA-API
+ // ==================
+
+ $(window).on('load.bs.scrollspy.data-api', function () {
+ $('[data-spy="scroll"]').each(function () {
+ var $spy = $(this)
+ Plugin.call($spy, $spy.data())
+ })
+ })
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: tab.js v3.3.7
+ * http://getbootstrap.com/javascript/#tabs
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // TAB CLASS DEFINITION
+ // ====================
+
+ var Tab = function (element) {
+ // jscs:disable requireDollarBeforejQueryAssignment
+ this.element = $(element)
+ // jscs:enable requireDollarBeforejQueryAssignment
+ }
+
+ Tab.VERSION = '3.3.7'
+
+ Tab.TRANSITION_DURATION = 150
+
+ Tab.prototype.show = function () {
+ var $this = this.element
+ var $ul = $this.closest('ul:not(.dropdown-menu)')
+ var selector = $this.data('target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ if ($this.parent('li').hasClass('active')) return
+
+ var $previous = $ul.find('.active:last a')
+ var hideEvent = $.Event('hide.bs.tab', {
+ relatedTarget: $this[0]
+ })
+ var showEvent = $.Event('show.bs.tab', {
+ relatedTarget: $previous[0]
+ })
+
+ $previous.trigger(hideEvent)
+ $this.trigger(showEvent)
+
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
+
+ var $target = $(selector)
+
+ this.activate($this.closest('li'), $ul)
+ this.activate($target, $target.parent(), function () {
+ $previous.trigger({
+ type: 'hidden.bs.tab',
+ relatedTarget: $this[0]
+ })
+ $this.trigger({
+ type: 'shown.bs.tab',
+ relatedTarget: $previous[0]
+ })
+ })
+ }
+
+ Tab.prototype.activate = function (element, container, callback) {
+ var $active = container.find('> .active')
+ var transition = callback
+ && $.support.transition
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
+
+ function next() {
+ $active
+ .removeClass('active')
+ .find('> .dropdown-menu > .active')
+ .removeClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', false)
+
+ element
+ .addClass('active')
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+
+ if (transition) {
+ element[0].offsetWidth // reflow for transition
+ element.addClass('in')
+ } else {
+ element.removeClass('fade')
+ }
+
+ if (element.parent('.dropdown-menu').length) {
+ element
+ .closest('li.dropdown')
+ .addClass('active')
+ .end()
+ .find('[data-toggle="tab"]')
+ .attr('aria-expanded', true)
+ }
+
+ callback && callback()
+ }
+
+ $active.length && transition ?
+ $active
+ .one('bsTransitionEnd', next)
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
+ next()
+
+ $active.removeClass('in')
+ }
+
+
+ // TAB PLUGIN DEFINITION
+ // =====================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.tab')
+
+ if (!data) $this.data('bs.tab', (data = new Tab(this)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.tab
+
+ $.fn.tab = Plugin
+ $.fn.tab.Constructor = Tab
+
+
+ // TAB NO CONFLICT
+ // ===============
+
+ $.fn.tab.noConflict = function () {
+ $.fn.tab = old
+ return this
+ }
+
+
+ // TAB DATA-API
+ // ============
+
+ var clickHandler = function (e) {
+ e.preventDefault()
+ Plugin.call($(this), 'show')
+ }
+
+ $(document)
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
+
+}(jQuery);
+
+/* ========================================================================
+ * Bootstrap: affix.js v3.3.7
+ * http://getbootstrap.com/javascript/#affix
+ * ========================================================================
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * ======================================================================== */
+
+
++function ($) {
+ 'use strict';
+
+ // AFFIX CLASS DEFINITION
+ // ======================
+
+ var Affix = function (element, options) {
+ this.options = $.extend({}, Affix.DEFAULTS, options)
+
+ this.$target = $(this.options.target)
+ .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
+ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
+
+ this.$element = $(element)
+ this.affixed = null
+ this.unpin = null
+ this.pinnedOffset = null
+
+ this.checkPosition()
+ }
+
+ Affix.VERSION = '3.3.7'
+
+ Affix.RESET = 'affix affix-top affix-bottom'
+
+ Affix.DEFAULTS = {
+ offset: 0,
+ target: window
+ }
+
+ Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ var targetHeight = this.$target.height()
+
+ if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
+
+ if (this.affixed == 'bottom') {
+ if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
+ return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
+ }
+
+ var initializing = this.affixed == null
+ var colliderTop = initializing ? scrollTop : position.top
+ var colliderHeight = initializing ? targetHeight : height
+
+ if (offsetTop != null && scrollTop <= offsetTop) return 'top'
+ if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
+
+ return false
+ }
+
+ Affix.prototype.getPinnedOffset = function () {
+ if (this.pinnedOffset) return this.pinnedOffset
+ this.$element.removeClass(Affix.RESET).addClass('affix')
+ var scrollTop = this.$target.scrollTop()
+ var position = this.$element.offset()
+ return (this.pinnedOffset = position.top - scrollTop)
+ }
+
+ Affix.prototype.checkPositionWithEventLoop = function () {
+ setTimeout($.proxy(this.checkPosition, this), 1)
+ }
+
+ Affix.prototype.checkPosition = function () {
+ if (!this.$element.is(':visible')) return
+
+ var height = this.$element.height()
+ var offset = this.options.offset
+ var offsetTop = offset.top
+ var offsetBottom = offset.bottom
+ var scrollHeight = Math.max($(document).height(), $(document.body).height())
+
+ if (typeof offset != 'object') offsetBottom = offsetTop = offset
+ if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element)
+ if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
+
+ var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
+
+ if (this.affixed != affix) {
+ if (this.unpin != null) this.$element.css('top', '')
+
+ var affixType = 'affix' + (affix ? '-' + affix : '')
+ var e = $.Event(affixType + '.bs.affix')
+
+ this.$element.trigger(e)
+
+ if (e.isDefaultPrevented()) return
+
+ this.affixed = affix
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
+
+ this.$element
+ .removeClass(Affix.RESET)
+ .addClass(affixType)
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
+ }
+
+ if (affix == 'bottom') {
+ this.$element.offset({
+ top: scrollHeight - height - offsetBottom
+ })
+ }
+ }
+
+
+ // AFFIX PLUGIN DEFINITION
+ // =======================
+
+ function Plugin(option) {
+ return this.each(function () {
+ var $this = $(this)
+ var data = $this.data('bs.affix')
+ var options = typeof option == 'object' && option
+
+ if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
+ if (typeof option == 'string') data[option]()
+ })
+ }
+
+ var old = $.fn.affix
+
+ $.fn.affix = Plugin
+ $.fn.affix.Constructor = Affix
+
+
+ // AFFIX NO CONFLICT
+ // =================
+
+ $.fn.affix.noConflict = function () {
+ $.fn.affix = old
+ return this
+ }
+
+
+ // AFFIX DATA-API
+ // ==============
+
+ $(window).on('load', function () {
+ $('[data-spy="affix"]').each(function () {
+ var $spy = $(this)
+ var data = $spy.data()
+
+ data.offset = data.offset || {}
+
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
+
+ Plugin.call($spy, data)
+ })
+ })
+
+}(jQuery);
diff --git a/debian/missing-sources/bootstrap-table-1.11.0.js b/debian/missing-sources/bootstrap-table-1.11.0.js
new file mode 100644
index 000000000..cf9e61a20
--- /dev/null
+++ b/debian/missing-sources/bootstrap-table-1.11.0.js
@@ -0,0 +1,3019 @@
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ * version: 1.11.0
+ * https://github.com/wenzhixin/bootstrap-table/
+ */
+
+(function ($) {
+ 'use strict';
+
+ // TOOLS DEFINITION
+ // ======================
+
+ var cachedWidth = null;
+
+ // it only does '%s', and return '' when arguments are undefined
+ var sprintf = function (str) {
+ var args = arguments,
+ flag = true,
+ i = 1;
+
+ str = str.replace(/%s/g, function () {
+ var arg = args[i++];
+
+ if (typeof arg === 'undefined') {
+ flag = false;
+ return '';
+ }
+ return arg;
+ });
+ return flag ? str : '';
+ };
+
+ var getPropertyFromOther = function (list, from, to, value) {
+ var result = '';
+ $.each(list, function (i, item) {
+ if (item[from] === value) {
+ result = item[to];
+ return false;
+ }
+ return true;
+ });
+ return result;
+ };
+
+ var getFieldIndex = function (columns, field) {
+ var index = -1;
+
+ $.each(columns, function (i, column) {
+ if (column.field === field) {
+ index = i;
+ return false;
+ }
+ return true;
+ });
+ return index;
+ };
+
+ // http://jsfiddle.net/wenyi/47nz7ez9/3/
+ var setFieldIndex = function (columns) {
+ var i, j, k,
+ totalCol = 0,
+ flag = [];
+
+ for (i = 0; i < columns[0].length; i++) {
+ totalCol += columns[0][i].colspan || 1;
+ }
+
+ for (i = 0; i < columns.length; i++) {
+ flag[i] = [];
+ for (j = 0; j < totalCol; j++) {
+ flag[i][j] = false;
+ }
+ }
+
+ for (i = 0; i < columns.length; i++) {
+ for (j = 0; j < columns[i].length; j++) {
+ var r = columns[i][j],
+ rowspan = r.rowspan || 1,
+ colspan = r.colspan || 1,
+ index = $.inArray(false, flag[i]);
+
+ if (colspan === 1) {
+ r.fieldIndex = index;
+ // when field is undefined, use index instead
+ if (typeof r.field === 'undefined') {
+ r.field = index;
+ }
+ }
+
+ for (k = 0; k < rowspan; k++) {
+ flag[i + k][index] = true;
+ }
+ for (k = 0; k < colspan; k++) {
+ flag[i][index + k] = true;
+ }
+ }
+ }
+ };
+
+ var getScrollBarWidth = function () {
+ if (cachedWidth === null) {
+ var inner = $('<p/>').addClass('fixed-table-scroll-inner'),
+ outer = $('<div/>').addClass('fixed-table-scroll-outer'),
+ w1, w2;
+
+ outer.append(inner);
+ $('body').append(outer);
+
+ w1 = inner[0].offsetWidth;
+ outer.css('overflow', 'scroll');
+ w2 = inner[0].offsetWidth;
+
+ if (w1 === w2) {
+ w2 = outer[0].clientWidth;
+ }
+
+ outer.remove();
+ cachedWidth = w1 - w2;
+ }
+ return cachedWidth;
+ };
+
+ var calculateObjectValue = function (self, name, args, defaultValue) {
+ var func = name;
+
+ if (typeof name === 'string') {
+ // support obj.func1.func2
+ var names = name.split('.');
+
+ if (names.length > 1) {
+ func = window;
+ $.each(names, function (i, f) {
+ func = func[f];
+ });
+ } else {
+ func = window[name];
+ }
+ }
+ if (typeof func === 'object') {
+ return func;
+ }
+ if (typeof func === 'function') {
+ return func.apply(self, args);
+ }
+ if (!func && typeof name === 'string' && sprintf.apply(this, [name].concat(args))) {
+ return sprintf.apply(this, [name].concat(args));
+ }
+ return defaultValue;
+ };
+
+ var compareObjects = function (objectA, objectB, compareLength) {
+ // Create arrays of property names
+ var objectAProperties = Object.getOwnPropertyNames(objectA),
+ objectBProperties = Object.getOwnPropertyNames(objectB),
+ propName = '';
+
+ if (compareLength) {
+ // If number of properties is different, objects are not equivalent
+ if (objectAProperties.length !== objectBProperties.length) {
+ return false;
+ }
+ }
+
+ for (var i = 0; i < objectAProperties.length; i++) {
+ propName = objectAProperties[i];
+
+ // If the property is not in the object B properties, continue with the next property
+ if ($.inArray(propName, objectBProperties) > -1) {
+ // If values of same property are not equal, objects are not equivalent
+ if (objectA[propName] !== objectB[propName]) {
+ return false;
+ }
+ }
+ }
+
+ // If we made it this far, objects are considered equivalent
+ return true;
+ };
+
+ var escapeHTML = function (text) {
+ if (typeof text === 'string') {
+ return text
+ .replace(/&/g, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;')
+ .replace(/"/g, '&quot;')
+ .replace(/'/g, '&#039;')
+ .replace(/`/g, '&#x60;');
+ }
+ return text;
+ };
+
+ var getRealHeight = function ($el) {
+ var height = 0;
+ $el.children().each(function () {
+ if (height < $(this).outerHeight(true)) {
+ height = $(this).outerHeight(true);
+ }
+ });
+ return height;
+ };
+
+ var getRealDataAttr = function (dataAttr) {
+ for (var attr in dataAttr) {
+ var auxAttr = attr.split(/(?=[A-Z])/).join('-').toLowerCase();
+ if (auxAttr !== attr) {
+ dataAttr[auxAttr] = dataAttr[attr];
+ delete dataAttr[attr];
+ }
+ }
+
+ return dataAttr;
+ };
+
+ var getItemField = function (item, field, escape) {
+ var value = item;
+
+ if (typeof field !== 'string' || item.hasOwnProperty(field)) {
+ return escape ? escapeHTML(item[field]) : item[field];
+ }
+ var props = field.split('.');
+ for (var p in props) {
+ value = value && value[props[p]];
+ }
+ return escape ? escapeHTML(value) : value;
+ };
+
+ var isIEBrowser = function () {
+ return !!(navigator.userAgent.indexOf("MSIE ") > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./));
+ };
+
+ var objectKeys = function () {
+ // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
+ if (!Object.keys) {
+ Object.keys = (function() {
+ var hasOwnProperty = Object.prototype.hasOwnProperty,
+ hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'),
+ dontEnums = [
+ 'toString',
+ 'toLocaleString',
+ 'valueOf',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'constructor'
+ ],
+ dontEnumsLength = dontEnums.length;
+
+ return function(obj) {
+ if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
+ throw new TypeError('Object.keys called on non-object');
+ }
+
+ var result = [], prop, i;
+
+ for (prop in obj) {
+ if (hasOwnProperty.call(obj, prop)) {
+ result.push(prop);
+ }
+ }
+
+ if (hasDontEnumBug) {
+ for (i = 0; i < dontEnumsLength; i++) {
+ if (hasOwnProperty.call(obj, dontEnums[i])) {
+ result.push(dontEnums[i]);
+ }
+ }
+ }
+ return result;
+ };
+ }());
+ }
+ };
+
+ // BOOTSTRAP TABLE CLASS DEFINITION
+ // ======================
+
+ var BootstrapTable = function (el, options) {
+ this.options = options;
+ this.$el = $(el);
+ this.$el_ = this.$el.clone();
+ this.timeoutId_ = 0;
+ this.timeoutFooter_ = 0;
+
+ this.init();
+ };
+
+ BootstrapTable.DEFAULTS = {
+ classes: 'table table-hover',
+ locale: undefined,
+ height: undefined,
+ undefinedText: '-',
+ sortName: undefined,
+ sortOrder: 'asc',
+ sortStable: false,
+ striped: false,
+ columns: [[]],
+ data: [],
+ dataField: 'rows',
+ method: 'get',
+ url: undefined,
+ ajax: undefined,
+ cache: true,
+ contentType: 'application/json',
+ dataType: 'json',
+ ajaxOptions: {},
+ queryParams: function (params) {
+ return params;
+ },
+ queryParamsType: 'limit', // undefined
+ responseHandler: function (res) {
+ return res;
+ },
+ pagination: false,
+ onlyInfoPagination: false,
+ sidePagination: 'client', // client or server
+ totalRows: 0, // server side need to set
+ pageNumber: 1,
+ pageSize: 10,
+ pageList: [10, 25, 50, 100],
+ paginationHAlign: 'right', //right, left
+ paginationVAlign: 'bottom', //bottom, top, both
+ paginationDetailHAlign: 'left', //right, left
+ paginationPreText: '&lsaquo;',
+ paginationNextText: '&rsaquo;',
+ search: false,
+ searchOnEnterKey: false,
+ strictSearch: false,
+ searchAlign: 'right',
+ selectItemName: 'btSelectItem',
+ showHeader: true,
+ showFooter: false,
+ showColumns: false,
+ showPaginationSwitch: false,
+ showRefresh: false,
+ showToggle: false,
+ buttonsAlign: 'right',
+ smartDisplay: true,
+ escape: false,
+ minimumCountColumns: 1,
+ idField: undefined,
+ uniqueId: undefined,
+ cardView: false,
+ detailView: false,
+ detailFormatter: function (index, row) {
+ return '';
+ },
+ trimOnSearch: true,
+ clickToSelect: false,
+ singleSelect: false,
+ toolbar: undefined,
+ toolbarAlign: 'left',
+ checkboxHeader: true,
+ sortable: true,
+ silentSort: true,
+ maintainSelected: false,
+ searchTimeOut: 500,
+ searchText: '',
+ iconSize: undefined,
+ buttonsClass: 'default',
+ iconsPrefix: 'glyphicon', // glyphicon of fa (font awesome)
+ icons: {
+ paginationSwitchDown: 'glyphicon-collapse-down icon-chevron-down',
+ paginationSwitchUp: 'glyphicon-collapse-up icon-chevron-up',
+ refresh: 'glyphicon-refresh icon-refresh',
+ toggle: 'glyphicon-list-alt icon-list-alt',
+ columns: 'glyphicon-th icon-th',
+ detailOpen: 'glyphicon-plus icon-plus',
+ detailClose: 'glyphicon-minus icon-minus'
+ },
+
+ customSearch: $.noop,
+
+ customSort: $.noop,
+
+ rowStyle: function (row, index) {
+ return {};
+ },
+
+ rowAttributes: function (row, index) {
+ return {};
+ },
+
+ footerStyle: function (row, index) {
+ return {};
+ },
+
+ onAll: function (name, args) {
+ return false;
+ },
+ onClickCell: function (field, value, row, $element) {
+ return false;
+ },
+ onDblClickCell: function (field, value, row, $element) {
+ return false;
+ },
+ onClickRow: function (item, $element) {
+ return false;
+ },
+ onDblClickRow: function (item, $element) {
+ return false;
+ },
+ onSort: function (name, order) {
+ return false;
+ },
+ onCheck: function (row) {
+ return false;
+ },
+ onUncheck: function (row) {
+ return false;
+ },
+ onCheckAll: function (rows) {
+ return false;
+ },
+ onUncheckAll: function (rows) {
+ return false;
+ },
+ onCheckSome: function (rows) {
+ return false;
+ },
+ onUncheckSome: function (rows) {
+ return false;
+ },
+ onLoadSuccess: function (data) {
+ return false;
+ },
+ onLoadError: function (status) {
+ return false;
+ },
+ onColumnSwitch: function (field, checked) {
+ return false;
+ },
+ onPageChange: function (number, size) {
+ return false;
+ },
+ onSearch: function (text) {
+ return false;
+ },
+ onToggle: function (cardView) {
+ return false;
+ },
+ onPreBody: function (data) {
+ return false;
+ },
+ onPostBody: function () {
+ return false;
+ },
+ onPostHeader: function () {
+ return false;
+ },
+ onExpandRow: function (index, row, $detail) {
+ return false;
+ },
+ onCollapseRow: function (index, row) {
+ return false;
+ },
+ onRefreshOptions: function (options) {
+ return false;
+ },
+ onRefresh: function (params) {
+ return false;
+ },
+ onResetView: function () {
+ return false;
+ }
+ };
+
+ BootstrapTable.LOCALES = {};
+
+ BootstrapTable.LOCALES['en-US'] = BootstrapTable.LOCALES.en = {
+ formatLoadingMessage: function () {
+ return 'Loading, please wait...';
+ },
+ formatRecordsPerPage: function (pageNumber) {
+ return sprintf('%s rows per page', pageNumber);
+ },
+ formatShowingRows: function (pageFrom, pageTo, totalRows) {
+ return sprintf('Showing %s to %s of %s rows', pageFrom, pageTo, totalRows);
+ },
+ formatDetailPagination: function (totalRows) {
+ return sprintf('Showing %s rows', totalRows);
+ },
+ formatSearch: function () {
+ return 'Search';
+ },
+ formatNoMatches: function () {
+ return 'No matching records found';
+ },
+ formatPaginationSwitch: function () {
+ return 'Hide/Show pagination';
+ },
+ formatRefresh: function () {
+ return 'Refresh';
+ },
+ formatToggle: function () {
+ return 'Toggle';
+ },
+ formatColumns: function () {
+ return 'Columns';
+ },
+ formatAllRows: function () {
+ return 'All';
+ }
+ };
+
+ $.extend(BootstrapTable.DEFAULTS, BootstrapTable.LOCALES['en-US']);
+
+ BootstrapTable.COLUMN_DEFAULTS = {
+ radio: false,
+ checkbox: false,
+ checkboxEnabled: true,
+ field: undefined,
+ title: undefined,
+ titleTooltip: undefined,
+ 'class': undefined,
+ align: undefined, // left, right, center
+ halign: undefined, // left, right, center
+ falign: undefined, // left, right, center
+ valign: undefined, // top, middle, bottom
+ width: undefined,
+ sortable: false,
+ order: 'asc', // asc, desc
+ visible: true,
+ switchable: true,
+ clickToSelect: true,
+ formatter: undefined,
+ footerFormatter: undefined,
+ events: undefined,
+ sorter: undefined,
+ sortName: undefined,
+ cellStyle: undefined,
+ searchable: true,
+ searchFormatter: true,
+ cardVisible: true
+ };
+
+ BootstrapTable.EVENTS = {
+ 'all.bs.table': 'onAll',
+ 'click-cell.bs.table': 'onClickCell',
+ 'dbl-click-cell.bs.table': 'onDblClickCell',
+ 'click-row.bs.table': 'onClickRow',
+ 'dbl-click-row.bs.table': 'onDblClickRow',
+ 'sort.bs.table': 'onSort',
+ 'check.bs.table': 'onCheck',
+ 'uncheck.bs.table': 'onUncheck',
+ 'check-all.bs.table': 'onCheckAll',
+ 'uncheck-all.bs.table': 'onUncheckAll',
+ 'check-some.bs.table': 'onCheckSome',
+ 'uncheck-some.bs.table': 'onUncheckSome',
+ 'load-success.bs.table': 'onLoadSuccess',
+ 'load-error.bs.table': 'onLoadError',
+ 'column-switch.bs.table': 'onColumnSwitch',
+ 'page-change.bs.table': 'onPageChange',
+ 'search.bs.table': 'onSearch',
+ 'toggle.bs.table': 'onToggle',
+ 'pre-body.bs.table': 'onPreBody',
+ 'post-body.bs.table': 'onPostBody',
+ 'post-header.bs.table': 'onPostHeader',
+ 'expand-row.bs.table': 'onExpandRow',
+ 'collapse-row.bs.table': 'onCollapseRow',
+ 'refresh-options.bs.table': 'onRefreshOptions',
+ 'reset-view.bs.table': 'onResetView',
+ 'refresh.bs.table': 'onRefresh'
+ };
+
+ BootstrapTable.prototype.init = function () {
+ this.initLocale();
+ this.initContainer();
+ this.initTable();
+ this.initHeader();
+ this.initData();
+ this.initFooter();
+ this.initToolbar();
+ this.initPagination();
+ this.initBody();
+ this.initSearchText();
+ this.initServer();
+ };
+
+ BootstrapTable.prototype.initLocale = function () {
+ if (this.options.locale) {
+ var parts = this.options.locale.split(/-|_/);
+ parts[0].toLowerCase();
+ if (parts[1]) parts[1].toUpperCase();
+ if ($.fn.bootstrapTable.locales[this.options.locale]) {
+ // locale as requested
+ $.extend(this.options, $.fn.bootstrapTable.locales[this.options.locale]);
+ } else if ($.fn.bootstrapTable.locales[parts.join('-')]) {
+ // locale with sep set to - (in case original was specified with _)
+ $.extend(this.options, $.fn.bootstrapTable.locales[parts.join('-')]);
+ } else if ($.fn.bootstrapTable.locales[parts[0]]) {
+ // short locale language code (i.e. 'en')
+ $.extend(this.options, $.fn.bootstrapTable.locales[parts[0]]);
+ }
+ }
+ };
+
+ BootstrapTable.prototype.initContainer = function () {
+ this.$container = $([
+ '<div class="bootstrap-table">',
+ '<div class="fixed-table-toolbar"></div>',
+ this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ?
+ '<div class="fixed-table-pagination" style="clear: both;"></div>' :
+ '',
+ '<div class="fixed-table-container">',
+ '<div class="fixed-table-header"><table></table></div>',
+ '<div class="fixed-table-body">',
+ '<div class="fixed-table-loading">',
+ this.options.formatLoadingMessage(),
+ '</div>',
+ '</div>',
+ '<div class="fixed-table-footer"><table><tr></tr></table></div>',
+ this.options.paginationVAlign === 'bottom' || this.options.paginationVAlign === 'both' ?
+ '<div class="fixed-table-pagination"></div>' :
+ '',
+ '</div>',
+ '</div>'
+ ].join(''));
+
+ this.$container.insertAfter(this.$el);
+ this.$tableContainer = this.$container.find('.fixed-table-container');
+ this.$tableHeader = this.$container.find('.fixed-table-header');
+ this.$tableBody = this.$container.find('.fixed-table-body');
+ this.$tableLoading = this.$container.find('.fixed-table-loading');
+ this.$tableFooter = this.$container.find('.fixed-table-footer');
+ this.$toolbar = this.$container.find('.fixed-table-toolbar');
+ this.$pagination = this.$container.find('.fixed-table-pagination');
+
+ this.$tableBody.append(this.$el);
+ this.$container.after('<div class="clearfix"></div>');
+
+ this.$el.addClass(this.options.classes);
+ if (this.options.striped) {
+ this.$el.addClass('table-striped');
+ }
+ if ($.inArray('table-no-bordered', this.options.classes.split(' ')) !== -1) {
+ this.$tableContainer.addClass('table-no-bordered');
+ }
+ };
+
+ BootstrapTable.prototype.initTable = function () {
+ var that = this,
+ columns = [],
+ data = [];
+
+ this.$header = this.$el.find('>thead');
+ if (!this.$header.length) {
+ this.$header = $('<thead></thead>').appendTo(this.$el);
+ }
+ this.$header.find('tr').each(function () {
+ var column = [];
+
+ $(this).find('th').each(function () {
+ // Fix #2014 - getFieldIndex and elsewhere assume this is string, causes issues if not
+ if (typeof $(this).data('field') !== 'undefined') {
+ $(this).data('field', $(this).data('field') + '');
+ }
+ column.push($.extend({}, {
+ title: $(this).html(),
+ 'class': $(this).attr('class'),
+ titleTooltip: $(this).attr('title'),
+ rowspan: $(this).attr('rowspan') ? +$(this).attr('rowspan') : undefined,
+ colspan: $(this).attr('colspan') ? +$(this).attr('colspan') : undefined
+ }, $(this).data()));
+ });
+ columns.push(column);
+ });
+ if (!$.isArray(this.options.columns[0])) {
+ this.options.columns = [this.options.columns];
+ }
+ this.options.columns = $.extend(true, [], columns, this.options.columns);
+ this.columns = [];
+
+ setFieldIndex(this.options.columns);
+ $.each(this.options.columns, function (i, columns) {
+ $.each(columns, function (j, column) {
+ column = $.extend({}, BootstrapTable.COLUMN_DEFAULTS, column);
+
+ if (typeof column.fieldIndex !== 'undefined') {
+ that.columns[column.fieldIndex] = column;
+ }
+
+ that.options.columns[i][j] = column;
+ });
+ });
+
+ // if options.data is setting, do not process tbody data
+ if (this.options.data.length) {
+ return;
+ }
+
+ var m = [];
+ this.$el.find('>tbody>tr').each(function (y) {
+ var row = {};
+
+ // save tr's id, class and data-* attributes
+ row._id = $(this).attr('id');
+ row._class = $(this).attr('class');
+ row._data = getRealDataAttr($(this).data());
+
+ $(this).find('>td').each(function (x) {
+ var $this = $(this),
+ cspan = +$this.attr('colspan') || 1,
+ rspan = +$this.attr('rowspan') || 1,
+ tx, ty;
+
+ for (; m[y] && m[y][x]; x++); //skip already occupied cells in current row
+
+ for (tx = x; tx < x + cspan; tx++) { //mark matrix elements occupied by current cell with true
+ for (ty = y; ty < y + rspan; ty++) {
+ if (!m[ty]) { //fill missing rows
+ m[ty] = [];
+ }
+ m[ty][tx] = true;
+ }
+ }
+
+ var field = that.columns[x].field;
+
+ row[field] = $(this).html();
+ // save td's id, class and data-* attributes
+ row['_' + field + '_id'] = $(this).attr('id');
+ row['_' + field + '_class'] = $(this).attr('class');
+ row['_' + field + '_rowspan'] = $(this).attr('rowspan');
+ row['_' + field + '_colspan'] = $(this).attr('colspan');
+ row['_' + field + '_title'] = $(this).attr('title');
+ row['_' + field + '_data'] = getRealDataAttr($(this).data());
+ });
+ data.push(row);
+ });
+ this.options.data = data;
+ if (data.length) this.fromHtml = true;
+ };
+
+ BootstrapTable.prototype.initHeader = function () {
+ var that = this,
+ visibleColumns = {},
+ html = [];
+
+ this.header = {
+ fields: [],
+ styles: [],
+ classes: [],
+ formatters: [],
+ events: [],
+ sorters: [],
+ sortNames: [],
+ cellStyles: [],
+ searchables: []
+ };
+
+ $.each(this.options.columns, function (i, columns) {
+ html.push('<tr>');
+
+ if (i === 0 && !that.options.cardView && that.options.detailView) {
+ html.push(sprintf('<th class="detail" rowspan="%s"><div class="fht-cell"></div></th>',
+ that.options.columns.length));
+ }
+
+ $.each(columns, function (j, column) {
+ var text = '',
+ halign = '', // header align style
+ align = '', // body align style
+ style = '',
+ class_ = sprintf(' class="%s"', column['class']),
+ order = that.options.sortOrder || column.order,
+ unitWidth = 'px',
+ width = column.width;
+
+ if (column.width !== undefined && (!that.options.cardView)) {
+ if (typeof column.width === 'string') {
+ if (column.width.indexOf('%') !== -1) {
+ unitWidth = '%';
+ }
+ }
+ }
+ if (column.width && typeof column.width === 'string') {
+ width = column.width.replace('%', '').replace('px', '');
+ }
+
+ halign = sprintf('text-align: %s; ', column.halign ? column.halign : column.align);
+ align = sprintf('text-align: %s; ', column.align);
+ style = sprintf('vertical-align: %s; ', column.valign);
+ style += sprintf('width: %s; ', (column.checkbox || column.radio) && !width ?
+ '36px' : (width ? width + unitWidth : undefined));
+
+ if (typeof column.fieldIndex !== 'undefined') {
+ that.header.fields[column.fieldIndex] = column.field;
+ that.header.styles[column.fieldIndex] = align + style;
+ that.header.classes[column.fieldIndex] = class_;
+ that.header.formatters[column.fieldIndex] = column.formatter;
+ that.header.events[column.fieldIndex] = column.events;
+ that.header.sorters[column.fieldIndex] = column.sorter;
+ that.header.sortNames[column.fieldIndex] = column.sortName;
+ that.header.cellStyles[column.fieldIndex] = column.cellStyle;
+ that.header.searchables[column.fieldIndex] = column.searchable;
+
+ if (!column.visible) {
+ return;
+ }
+
+ if (that.options.cardView && (!column.cardVisible)) {
+ return;
+ }
+
+ visibleColumns[column.field] = column;
+ }
+
+ html.push('<th' + sprintf(' title="%s"', column.titleTooltip),
+ column.checkbox || column.radio ?
+ sprintf(' class="bs-checkbox %s"', column['class'] || '') :
+ class_,
+ sprintf(' style="%s"', halign + style),
+ sprintf(' rowspan="%s"', column.rowspan),
+ sprintf(' colspan="%s"', column.colspan),
+ sprintf(' data-field="%s"', column.field),
+ "tabindex='0'",
+ '>');
+
+ html.push(sprintf('<div class="th-inner %s">', that.options.sortable && column.sortable ?
+ 'sortable both' : ''));
+
+ text = column.title;
+
+ if (column.checkbox) {
+ if (!that.options.singleSelect && that.options.checkboxHeader) {
+ text = '<input name="btSelectAll" type="checkbox" />';
+ }
+ that.header.stateField = column.field;
+ }
+ if (column.radio) {
+ text = '';
+ that.header.stateField = column.field;
+ that.options.singleSelect = true;
+ }
+
+ html.push(text);
+ html.push('</div>');
+ html.push('<div class="fht-cell"></div>');
+ html.push('</div>');
+ html.push('</th>');
+ });
+ html.push('</tr>');
+ });
+
+ this.$header.html(html.join(''));
+ this.$header.find('th[data-field]').each(function (i) {
+ $(this).data(visibleColumns[$(this).data('field')]);
+ });
+ this.$container.off('click', '.th-inner').on('click', '.th-inner', function (event) {
+ var target = $(this);
+
+ if (that.options.detailView) {
+ if (target.closest('.bootstrap-table')[0] !== that.$container[0])
+ return false;
+ }
+
+ if (that.options.sortable && target.parent().data().sortable) {
+ that.onSort(event);
+ }
+ });
+
+ this.$header.children().children().off('keypress').on('keypress', function (event) {
+ if (that.options.sortable && $(this).data().sortable) {
+ var code = event.keyCode || event.which;
+ if (code == 13) { //Enter keycode
+ that.onSort(event);
+ }
+ }
+ });
+
+ $(window).off('resize.bootstrap-table');
+ if (!this.options.showHeader || this.options.cardView) {
+ this.$header.hide();
+ this.$tableHeader.hide();
+ this.$tableLoading.css('top', 0);
+ } else {
+ this.$header.show();
+ this.$tableHeader.show();
+ this.$tableLoading.css('top', this.$header.outerHeight() + 1);
+ // Assign the correct sortable arrow
+ this.getCaret();
+ $(window).on('resize.bootstrap-table', $.proxy(this.resetWidth, this));
+ }
+
+ this.$selectAll = this.$header.find('[name="btSelectAll"]');
+ this.$selectAll.off('click').on('click', function () {
+ var checked = $(this).prop('checked');
+ that[checked ? 'checkAll' : 'uncheckAll']();
+ that.updateSelected();
+ });
+ };
+
+ BootstrapTable.prototype.initFooter = function () {
+ if (!this.options.showFooter || this.options.cardView) {
+ this.$tableFooter.hide();
+ } else {
+ this.$tableFooter.show();
+ }
+ };
+
+ /**
+ * @param data
+ * @param type: append / prepend
+ */
+ BootstrapTable.prototype.initData = function (data, type) {
+ if (type === 'append') {
+ this.data = this.data.concat(data);
+ } else if (type === 'prepend') {
+ this.data = [].concat(data).concat(this.data);
+ } else {
+ this.data = data || this.options.data;
+ }
+
+ // Fix #839 Records deleted when adding new row on filtered table
+ if (type === 'append') {
+ this.options.data = this.options.data.concat(data);
+ } else if (type === 'prepend') {
+ this.options.data = [].concat(data).concat(this.options.data);
+ } else {
+ this.options.data = this.data;
+ }
+
+ if (this.options.sidePagination === 'server') {
+ return;
+ }
+ this.initSort();
+ };
+
+ BootstrapTable.prototype.initSort = function () {
+ var that = this,
+ name = this.options.sortName,
+ order = this.options.sortOrder === 'desc' ? -1 : 1,
+ index = $.inArray(this.options.sortName, this.header.fields);
+
+ if (this.options.customSort !== $.noop) {
+ this.options.customSort.apply(this, [this.options.sortName, this.options.sortOrder]);
+ return;
+ }
+
+ if (index !== -1) {
+ if (this.options.sortStable) {
+ $.each(this.data, function (i, row) {
+ if (!row.hasOwnProperty('_position')) row._position = i;
+ });
+ }
+
+ this.data.sort(function (a, b) {
+ if (that.header.sortNames[index]) {
+ name = that.header.sortNames[index];
+ }
+ var aa = getItemField(a, name, that.options.escape),
+ bb = getItemField(b, name, that.options.escape),
+ value = calculateObjectValue(that.header, that.header.sorters[index], [aa, bb]);
+
+ if (value !== undefined) {
+ return order * value;
+ }
+
+ // Fix #161: undefined or null string sort bug.
+ if (aa === undefined || aa === null) {
+ aa = '';
+ }
+ if (bb === undefined || bb === null) {
+ bb = '';
+ }
+
+ if (that.options.sortStable && aa === bb) {
+ aa = a._position;
+ bb = b._position;
+ }
+
+ // IF both values are numeric, do a numeric comparison
+ if ($.isNumeric(aa) && $.isNumeric(bb)) {
+ // Convert numerical values form string to float.
+ aa = parseFloat(aa);
+ bb = parseFloat(bb);
+ if (aa < bb) {
+ return order * -1;
+ }
+ return order;
+ }
+
+ if (aa === bb) {
+ return 0;
+ }
+
+ // If value is not a string, convert to string
+ if (typeof aa !== 'string') {
+ aa = aa.toString();
+ }
+
+ if (aa.localeCompare(bb) === -1) {
+ return order * -1;
+ }
+
+ return order;
+ });
+ }
+ };
+
+ BootstrapTable.prototype.onSort = function (event) {
+ var $this = event.type === "keypress" ? $(event.currentTarget) : $(event.currentTarget).parent(),
+ $this_ = this.$header.find('th').eq($this.index());
+
+ this.$header.add(this.$header_).find('span.order').remove();
+
+ if (this.options.sortName === $this.data('field')) {
+ this.options.sortOrder = this.options.sortOrder === 'asc' ? 'desc' : 'asc';
+ } else {
+ this.options.sortName = $this.data('field');
+ this.options.sortOrder = $this.data('order') === 'asc' ? 'desc' : 'asc';
+ }
+ this.trigger('sort', this.options.sortName, this.options.sortOrder);
+
+ $this.add($this_).data('order', this.options.sortOrder);
+
+ // Assign the correct sortable arrow
+ this.getCaret();
+
+ if (this.options.sidePagination === 'server') {
+ this.initServer(this.options.silentSort);
+ return;
+ }
+
+ this.initSort();
+ this.initBody();
+ };
+
+ BootstrapTable.prototype.initToolbar = function () {
+ var that = this,
+ html = [],
+ timeoutId = 0,
+ $keepOpen,
+ $search,
+ switchableCount = 0;
+
+ if (this.$toolbar.find('.bs-bars').children().length) {
+ $('body').append($(this.options.toolbar));
+ }
+ this.$toolbar.html('');
+
+ if (typeof this.options.toolbar === 'string' || typeof this.options.toolbar === 'object') {
+ $(sprintf('<div class="bs-bars pull-%s"></div>', this.options.toolbarAlign))
+ .appendTo(this.$toolbar)
+ .append($(this.options.toolbar));
+ }
+
+ // showColumns, showToggle, showRefresh
+ html = [sprintf('<div class="columns columns-%s btn-group pull-%s">',
+ this.options.buttonsAlign, this.options.buttonsAlign)];
+
+ if (typeof this.options.icons === 'string') {
+ this.options.icons = calculateObjectValue(null, this.options.icons);
+ }
+
+ if (this.options.showPaginationSwitch) {
+ html.push(sprintf('<button class="btn' +
+ sprintf(' btn-%s', this.options.buttonsClass) +
+ sprintf(' btn-%s', this.options.iconSize) +
+ '" type="button" name="paginationSwitch" title="%s">',
+ this.options.formatPaginationSwitch()),
+ sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.paginationSwitchDown),
+ '</button>');
+ }
+
+ if (this.options.showRefresh) {
+ html.push(sprintf('<button class="btn' +
+ sprintf(' btn-%s', this.options.buttonsClass) +
+ sprintf(' btn-%s', this.options.iconSize) +
+ '" type="button" name="refresh" title="%s">',
+ this.options.formatRefresh()),
+ sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.refresh),
+ '</button>');
+ }
+
+ if (this.options.showToggle) {
+ html.push(sprintf('<button class="btn' +
+ sprintf(' btn-%s', this.options.buttonsClass) +
+ sprintf(' btn-%s', this.options.iconSize) +
+ '" type="button" name="toggle" title="%s">',
+ this.options.formatToggle()),
+ sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.toggle),
+ '</button>');
+ }
+
+ if (this.options.showColumns) {
+ html.push(sprintf('<div class="keep-open btn-group" title="%s">',
+ this.options.formatColumns()),
+ '<button type="button" class="btn' +
+ sprintf(' btn-%s', this.options.buttonsClass) +
+ sprintf(' btn-%s', this.options.iconSize) +
+ ' dropdown-toggle" data-toggle="dropdown">',
+ sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.columns),
+ ' <span class="caret"></span>',
+ '</button>',
+ '<ul class="dropdown-menu" role="menu">');
+
+ $.each(this.columns, function (i, column) {
+ if (column.radio || column.checkbox) {
+ return;
+ }
+
+ if (that.options.cardView && !column.cardVisible) {
+ return;
+ }
+
+ var checked = column.visible ? ' checked="checked"' : '';
+
+ if (column.switchable) {
+ html.push(sprintf('<li>' +
+ '<label><input type="checkbox" data-field="%s" value="%s"%s> %s</label>' +
+ '</li>', column.field, i, checked, column.title));
+ switchableCount++;
+ }
+ });
+ html.push('</ul>',
+ '</div>');
+ }
+
+ html.push('</div>');
+
+ // Fix #188: this.showToolbar is for extensions
+ if (this.showToolbar || html.length > 2) {
+ this.$toolbar.append(html.join(''));
+ }
+
+ if (this.options.showPaginationSwitch) {
+ this.$toolbar.find('button[name="paginationSwitch"]')
+ .off('click').on('click', $.proxy(this.togglePagination, this));
+ }
+
+ if (this.options.showRefresh) {
+ this.$toolbar.find('button[name="refresh"]')
+ .off('click').on('click', $.proxy(this.refresh, this));
+ }
+
+ if (this.options.showToggle) {
+ this.$toolbar.find('button[name="toggle"]')
+ .off('click').on('click', function () {
+ that.toggleView();
+ });
+ }
+
+ if (this.options.showColumns) {
+ $keepOpen = this.$toolbar.find('.keep-open');
+
+ if (switchableCount <= this.options.minimumCountColumns) {
+ $keepOpen.find('input').prop('disabled', true);
+ }
+
+ $keepOpen.find('li').off('click').on('click', function (event) {
+ event.stopImmediatePropagation();
+ });
+ $keepOpen.find('input').off('click').on('click', function () {
+ var $this = $(this);
+
+ that.toggleColumn($(this).val(), $this.prop('checked'), false);
+ that.trigger('column-switch', $(this).data('field'), $this.prop('checked'));
+ });
+ }
+
+ if (this.options.search) {
+ html = [];
+ html.push(
+ '<div class="pull-' + this.options.searchAlign + ' search">',
+ sprintf('<input class="form-control' +
+ sprintf(' input-%s', this.options.iconSize) +
+ '" type="text" placeholder="%s">',
+ this.options.formatSearch()),
+ '</div>');
+
+ this.$toolbar.append(html.join(''));
+ $search = this.$toolbar.find('.search input');
+ $search.off('keyup drop').on('keyup drop', function (event) {
+ if (that.options.searchOnEnterKey && event.keyCode !== 13) {
+ return;
+ }
+
+ if ($.inArray(event.keyCode, [37, 38, 39, 40]) > -1) {
+ return;
+ }
+
+ clearTimeout(timeoutId); // doesn't matter if it's 0
+ timeoutId = setTimeout(function () {
+ that.onSearch(event);
+ }, that.options.searchTimeOut);
+ });
+
+ if (isIEBrowser()) {
+ $search.off('mouseup').on('mouseup', function (event) {
+ clearTimeout(timeoutId); // doesn't matter if it's 0
+ timeoutId = setTimeout(function () {
+ that.onSearch(event);
+ }, that.options.searchTimeOut);
+ });
+ }
+ }
+ };
+
+ BootstrapTable.prototype.onSearch = function (event) {
+ var text = $.trim($(event.currentTarget).val());
+
+ // trim search input
+ if (this.options.trimOnSearch && $(event.currentTarget).val() !== text) {
+ $(event.currentTarget).val(text);
+ }
+
+ if (text === this.searchText) {
+ return;
+ }
+ this.searchText = text;
+ this.options.searchText = text;
+
+ this.options.pageNumber = 1;
+ this.initSearch();
+ this.updatePagination();
+ this.trigger('search', text);
+ };
+
+ BootstrapTable.prototype.initSearch = function () {
+ var that = this;
+
+ if (this.options.sidePagination !== 'server') {
+ if (this.options.customSearch !== $.noop) {
+ this.options.customSearch.apply(this, [this.searchText]);
+ return;
+ }
+
+ var s = this.searchText && (this.options.escape ?
+ escapeHTML(this.searchText) : this.searchText).toLowerCase();
+ var f = $.isEmptyObject(this.filterColumns) ? null : this.filterColumns;
+
+ // Check filter
+ this.data = f ? $.grep(this.options.data, function (item, i) {
+ for (var key in f) {
+ if ($.isArray(f[key]) && $.inArray(item[key], f[key]) === -1 ||
+ item[key] !== f[key]) {
+ return false;
+ }
+ }
+ return true;
+ }) : this.options.data;
+
+ this.data = s ? $.grep(this.data, function (item, i) {
+ for (var j = 0; j < that.header.fields.length; j++) {
+
+ if (!that.header.searchables[j]) {
+ continue;
+ }
+
+ var key = $.isNumeric(that.header.fields[j]) ? parseInt(that.header.fields[j], 10) : that.header.fields[j];
+ var column = that.columns[getFieldIndex(that.columns, key)];
+ var value;
+
+ if (typeof key === 'string') {
+ value = item;
+ var props = key.split('.');
+ for (var prop_index = 0; prop_index < props.length; prop_index++) {
+ value = value[props[prop_index]];
+ }
+
+ // Fix #142: respect searchForamtter boolean
+ if (column && column.searchFormatter) {
+ value = calculateObjectValue(column,
+ that.header.formatters[j], [value, item, i], value);
+ }
+ } else {
+ value = item[key];
+ }
+
+ if (typeof value === 'string' || typeof value === 'number') {
+ if (that.options.strictSearch) {
+ if ((value + '').toLowerCase() === s) {
+ return true;
+ }
+ } else {
+ if ((value + '').toLowerCase().indexOf(s) !== -1) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }) : this.data;
+ }
+ };
+
+ BootstrapTable.prototype.initPagination = function () {
+ if (!this.options.pagination) {
+ this.$pagination.hide();
+ return;
+ } else {
+ this.$pagination.show();
+ }
+
+ var that = this,
+ html = [],
+ $allSelected = false,
+ i, from, to,
+ $pageList,
+ $first, $pre,
+ $next, $last,
+ $number,
+ data = this.getData(),
+ pageList = this.options.pageList;
+
+ if (this.options.sidePagination !== 'server') {
+ this.options.totalRows = data.length;
+ }
+
+ this.totalPages = 0;
+ if (this.options.totalRows) {
+ if (this.options.pageSize === this.options.formatAllRows()) {
+ this.options.pageSize = this.options.totalRows;
+ $allSelected = true;
+ } else if (this.options.pageSize === this.options.totalRows) {
+ // Fix #667 Table with pagination,
+ // multiple pages and a search that matches to one page throws exception
+ var pageLst = typeof this.options.pageList === 'string' ?
+ this.options.pageList.replace('[', '').replace(']', '')
+ .replace(/ /g, '').toLowerCase().split(',') : this.options.pageList;
+ if ($.inArray(this.options.formatAllRows().toLowerCase(), pageLst) > -1) {
+ $allSelected = true;
+ }
+ }
+
+ this.totalPages = ~~((this.options.totalRows - 1) / this.options.pageSize) + 1;
+
+ this.options.totalPages = this.totalPages;
+ }
+ if (this.totalPages > 0 && this.options.pageNumber > this.totalPages) {
+ this.options.pageNumber = this.totalPages;
+ }
+
+ this.pageFrom = (this.options.pageNumber - 1) * this.options.pageSize + 1;
+ this.pageTo = this.options.pageNumber * this.options.pageSize;
+ if (this.pageTo > this.options.totalRows) {
+ this.pageTo = this.options.totalRows;
+ }
+
+ html.push(
+ '<div class="pull-' + this.options.paginationDetailHAlign + ' pagination-detail">',
+ '<span class="pagination-info">',
+ this.options.onlyInfoPagination ? this.options.formatDetailPagination(this.options.totalRows) :
+ this.options.formatShowingRows(this.pageFrom, this.pageTo, this.options.totalRows),
+ '</span>');
+
+ if (!this.options.onlyInfoPagination) {
+ html.push('<span class="page-list">');
+
+ var pageNumber = [
+ sprintf('<span class="btn-group %s">',
+ this.options.paginationVAlign === 'top' || this.options.paginationVAlign === 'both' ?
+ 'dropdown' : 'dropup'),
+ '<button type="button" class="btn' +
+ sprintf(' btn-%s', this.options.buttonsClass) +
+ sprintf(' btn-%s', this.options.iconSize) +
+ ' dropdown-toggle" data-toggle="dropdown">',
+ '<span class="page-size">',
+ $allSelected ? this.options.formatAllRows() : this.options.pageSize,
+ '</span>',
+ ' <span class="caret"></span>',
+ '</button>',
+ '<ul class="dropdown-menu" role="menu">'
+ ];
+
+ if (typeof this.options.pageList === 'string') {
+ var list = this.options.pageList.replace('[', '').replace(']', '')
+ .replace(/ /g, '').split(',');
+
+ pageList = [];
+ $.each(list, function (i, value) {
+ pageList.push(value.toUpperCase() === that.options.formatAllRows().toUpperCase() ?
+ that.options.formatAllRows() : +value);
+ });
+ }
+
+ $.each(pageList, function (i, page) {
+ if (!that.options.smartDisplay || i === 0 || pageList[i - 1] <= that.options.totalRows) {
+ var active;
+ if ($allSelected) {
+ active = page === that.options.formatAllRows() ? ' class="active"' : '';
+ } else {
+ active = page === that.options.pageSize ? ' class="active"' : '';
+ }
+ pageNumber.push(sprintf('<li%s><a href="javascript:void(0)">%s</a></li>', active, page));
+ }
+ });
+ pageNumber.push('</ul></span>');
+
+ html.push(this.options.formatRecordsPerPage(pageNumber.join('')));
+ html.push('</span>');
+
+ html.push('</div>',
+ '<div class="pull-' + this.options.paginationHAlign + ' pagination">',
+ '<ul class="pagination' + sprintf(' pagination-%s', this.options.iconSize) + '">',
+ '<li class="page-pre"><a href="javascript:void(0)">' + this.options.paginationPreText + '</a></li>');
+
+ if (this.totalPages < 5) {
+ from = 1;
+ to = this.totalPages;
+ } else {
+ from = this.options.pageNumber - 2;
+ to = from + 4;
+ if (from < 1) {
+ from = 1;
+ to = 5;
+ }
+ if (to > this.totalPages) {
+ to = this.totalPages;
+ from = to - 4;
+ }
+ }
+
+ if (this.totalPages >= 6) {
+ if (this.options.pageNumber >= 3) {
+ html.push('<li class="page-first' + (1 === this.options.pageNumber ? ' active' : '') + '">',
+ '<a href="javascript:void(0)">', 1, '</a>',
+ '</li>');
+
+ from++;
+ }
+
+ if (this.options.pageNumber >= 4) {
+ if (this.options.pageNumber == 4 || this.totalPages == 6 || this.totalPages == 7) {
+ from--;
+ } else {
+ html.push('<li class="page-first-separator disabled">',
+ '<a href="javascript:void(0)">...</a>',
+ '</li>');
+ }
+
+ to--;
+ }
+ }
+
+ if (this.totalPages >= 7) {
+ if (this.options.pageNumber >= (this.totalPages - 2)) {
+ from--;
+ }
+ }
+
+ if (this.totalPages == 6) {
+ if (this.options.pageNumber >= (this.totalPages - 2)) {
+ to++;
+ }
+ } else if (this.totalPages >= 7) {
+ if (this.totalPages == 7 || this.options.pageNumber >= (this.totalPages - 3)) {
+ to++;
+ }
+ }
+
+ for (i = from; i <= to; i++) {
+ html.push('<li class="page-number' + (i === this.options.pageNumber ? ' active' : '') + '">',
+ '<a href="javascript:void(0)">', i, '</a>',
+ '</li>');
+ }
+
+ if (this.totalPages >= 8) {
+ if (this.options.pageNumber <= (this.totalPages - 4)) {
+ html.push('<li class="page-last-separator disabled">',
+ '<a href="javascript:void(0)">...</a>',
+ '</li>');
+ }
+ }
+
+ if (this.totalPages >= 6) {
+ if (this.options.pageNumber <= (this.totalPages - 3)) {
+ html.push('<li class="page-last' + (this.totalPages === this.options.pageNumber ? ' active' : '') + '">',
+ '<a href="javascript:void(0)">', this.totalPages, '</a>',
+ '</li>');
+ }
+ }
+
+ html.push(
+ '<li class="page-next"><a href="javascript:void(0)">' + this.options.paginationNextText + '</a></li>',
+ '</ul>',
+ '</div>');
+ }
+ this.$pagination.html(html.join(''));
+
+ if (!this.options.onlyInfoPagination) {
+ $pageList = this.$pagination.find('.page-list a');
+ $first = this.$pagination.find('.page-first');
+ $pre = this.$pagination.find('.page-pre');
+ $next = this.$pagination.find('.page-next');
+ $last = this.$pagination.find('.page-last');
+ $number = this.$pagination.find('.page-number');
+
+ if (this.options.smartDisplay) {
+ if (this.totalPages <= 1) {
+ this.$pagination.find('div.pagination').hide();
+ }
+ if (pageList.length < 2 || this.options.totalRows <= pageList[0]) {
+ this.$pagination.find('span.page-list').hide();
+ }
+
+ // when data is empty, hide the pagination
+ this.$pagination[this.getData().length ? 'show' : 'hide']();
+ }
+ if ($allSelected) {
+ this.options.pageSize = this.options.formatAllRows();
+ }
+ $pageList.off('click').on('click', $.proxy(this.onPageListChange, this));
+ $first.off('click').on('click', $.proxy(this.onPageFirst, this));
+ $pre.off('click').on('click', $.proxy(this.onPagePre, this));
+ $next.off('click').on('click', $.proxy(this.onPageNext, this));
+ $last.off('click').on('click', $.proxy(this.onPageLast, this));
+ $number.off('click').on('click', $.proxy(this.onPageNumber, this));
+ }
+ };
+
+ BootstrapTable.prototype.updatePagination = function (event) {
+ // Fix #171: IE disabled button can be clicked bug.
+ if (event && $(event.currentTarget).hasClass('disabled')) {
+ return;
+ }
+
+ if (!this.options.maintainSelected) {
+ this.resetRows();
+ }
+
+ this.initPagination();
+ if (this.options.sidePagination === 'server') {
+ this.initServer();
+ } else {
+ this.initBody();
+ }
+
+ this.trigger('page-change', this.options.pageNumber, this.options.pageSize);
+ };
+
+ BootstrapTable.prototype.onPageListChange = function (event) {
+ var $this = $(event.currentTarget);
+
+ $this.parent().addClass('active').siblings().removeClass('active');
+ this.options.pageSize = $this.text().toUpperCase() === this.options.formatAllRows().toUpperCase() ?
+ this.options.formatAllRows() : +$this.text();
+ this.$toolbar.find('.page-size').text(this.options.pageSize);
+
+ this.updatePagination(event);
+ };
+
+ BootstrapTable.prototype.onPageFirst = function (event) {
+ this.options.pageNumber = 1;
+ this.updatePagination(event);
+ };
+
+ BootstrapTable.prototype.onPagePre = function (event) {
+ if ((this.options.pageNumber - 1) === 0) {
+ this.options.pageNumber = this.options.totalPages;
+ } else {
+ this.options.pageNumber--;
+ }
+ this.updatePagination(event);
+ };
+
+ BootstrapTable.prototype.onPageNext = function (event) {
+ if ((this.options.pageNumber + 1) > this.options.totalPages) {
+ this.options.pageNumber = 1;
+ } else {
+ this.options.pageNumber++;
+ }
+ this.updatePagination(event);
+ };
+
+ BootstrapTable.prototype.onPageLast = function (event) {
+ this.options.pageNumber = this.totalPages;
+ this.updatePagination(event);
+ };
+
+ BootstrapTable.prototype.onPageNumber = function (event) {
+ if (this.options.pageNumber === +$(event.currentTarget).text()) {
+ return;
+ }
+ this.options.pageNumber = +$(event.currentTarget).text();
+ this.updatePagination(event);
+ };
+
+ BootstrapTable.prototype.initBody = function (fixedScroll) {
+ var that = this,
+ html = [],
+ data = this.getData();
+
+ this.trigger('pre-body', data);
+
+ this.$body = this.$el.find('>tbody');
+ if (!this.$body.length) {
+ this.$body = $('<tbody></tbody>').appendTo(this.$el);
+ }
+
+ //Fix #389 Bootstrap-table-flatJSON is not working
+
+ if (!this.options.pagination || this.options.sidePagination === 'server') {
+ this.pageFrom = 1;
+ this.pageTo = data.length;
+ }
+
+ for (var i = this.pageFrom - 1; i < this.pageTo; i++) {
+ var key,
+ item = data[i],
+ style = {},
+ csses = [],
+ data_ = '',
+ attributes = {},
+ htmlAttributes = [];
+
+ style = calculateObjectValue(this.options, this.options.rowStyle, [item, i], style);
+
+ if (style && style.css) {
+ for (key in style.css) {
+ csses.push(key + ': ' + style.css[key]);
+ }
+ }
+
+ attributes = calculateObjectValue(this.options,
+ this.options.rowAttributes, [item, i], attributes);
+
+ if (attributes) {
+ for (key in attributes) {
+ htmlAttributes.push(sprintf('%s="%s"', key, escapeHTML(attributes[key])));
+ }
+ }
+
+ if (item._data && !$.isEmptyObject(item._data)) {
+ $.each(item._data, function (k, v) {
+ // ignore data-index
+ if (k === 'index') {
+ return;
+ }
+ data_ += sprintf(' data-%s="%s"', k, v);
+ });
+ }
+
+ html.push('<tr',
+ sprintf(' %s', htmlAttributes.join(' ')),
+ sprintf(' id="%s"', $.isArray(item) ? undefined : item._id),
+ sprintf(' class="%s"', style.classes || ($.isArray(item) ? undefined : item._class)),
+ sprintf(' data-index="%s"', i),
+ sprintf(' data-uniqueid="%s"', item[this.options.uniqueId]),
+ sprintf('%s', data_),
+ '>'
+ );
+
+ if (this.options.cardView) {
+ html.push(sprintf('<td colspan="%s"><div class="card-views">', this.header.fields.length));
+ }
+
+ if (!this.options.cardView && this.options.detailView) {
+ html.push('<td>',
+ '<a class="detail-icon" href="javascript:">',
+ sprintf('<i class="%s %s"></i>', this.options.iconsPrefix, this.options.icons.detailOpen),
+ '</a>',
+ '</td>');
+ }
+
+ $.each(this.header.fields, function (j, field) {
+ var text = '',
+ value = getItemField(item, field, that.options.escape),
+ type = '',
+ cellStyle = {},
+ id_ = '',
+ class_ = that.header.classes[j],
+ data_ = '',
+ rowspan_ = '',
+ colspan_ = '',
+ title_ = '',
+ column = that.columns[j];
+
+ if (that.fromHtml && typeof value === 'undefined') {
+ return;
+ }
+
+ if (!column.visible) {
+ return;
+ }
+
+ if (that.options.cardView && !column.cardVisible) {
+ return;
+ }
+
+ style = sprintf('style="%s"', csses.concat(that.header.styles[j]).join('; '));
+
+ // handle td's id and class
+ if (item['_' + field + '_id']) {
+ id_ = sprintf(' id="%s"', item['_' + field + '_id']);
+ }
+ if (item['_' + field + '_class']) {
+ class_ = sprintf(' class="%s"', item['_' + field + '_class']);
+ }
+ if (item['_' + field + '_rowspan']) {
+ rowspan_ = sprintf(' rowspan="%s"', item['_' + field + '_rowspan']);
+ }
+ if (item['_' + field + '_colspan']) {
+ colspan_ = sprintf(' colspan="%s"', item['_' + field + '_colspan']);
+ }
+ if (item['_' + field + '_title']) {
+ title_ = sprintf(' title="%s"', item['_' + field + '_title']);
+ }
+ cellStyle = calculateObjectValue(that.header,
+ that.header.cellStyles[j], [value, item, i, field], cellStyle);
+ if (cellStyle.classes) {
+ class_ = sprintf(' class="%s"', cellStyle.classes);
+ }
+ if (cellStyle.css) {
+ var csses_ = [];
+ for (var key in cellStyle.css) {
+ csses_.push(key + ': ' + cellStyle.css[key]);
+ }
+ style = sprintf('style="%s"', csses_.concat(that.header.styles[j]).join('; '));
+ }
+
+ value = calculateObjectValue(column,
+ that.header.formatters[j], [value, item, i], value);
+
+ if (item['_' + field + '_data'] && !$.isEmptyObject(item['_' + field + '_data'])) {
+ $.each(item['_' + field + '_data'], function (k, v) {
+ // ignore data-index
+ if (k === 'index') {
+ return;
+ }
+ data_ += sprintf(' data-%s="%s"', k, v);
+ });
+ }
+
+ if (column.checkbox || column.radio) {
+ type = column.checkbox ? 'checkbox' : type;
+ type = column.radio ? 'radio' : type;
+
+ text = [sprintf(that.options.cardView ?
+ '<div class="card-view %s">' : '<td class="bs-checkbox %s">', column['class'] || ''),
+ '<input' +
+ sprintf(' data-index="%s"', i) +
+ sprintf(' name="%s"', that.options.selectItemName) +
+ sprintf(' type="%s"', type) +
+ sprintf(' value="%s"', item[that.options.idField]) +
+ sprintf(' checked="%s"', value === true ||
+ (value && value.checked) ? 'checked' : undefined) +
+ sprintf(' disabled="%s"', !column.checkboxEnabled ||
+ (value && value.disabled) ? 'disabled' : undefined) +
+ ' />',
+ that.header.formatters[j] && typeof value === 'string' ? value : '',
+ that.options.cardView ? '</div>' : '</td>'
+ ].join('');
+
+ item[that.header.stateField] = value === true || (value && value.checked);
+ } else {
+ value = typeof value === 'undefined' || value === null ?
+ that.options.undefinedText : value;
+
+ text = that.options.cardView ? ['<div class="card-view">',
+ that.options.showHeader ? sprintf('<span class="title" %s>%s</span>', style,
+ getPropertyFromOther(that.columns, 'field', 'title', field)) : '',
+ sprintf('<span class="value">%s</span>', value),
+ '</div>'
+ ].join('') : [sprintf('<td%s %s %s %s %s %s %s>',
+ id_, class_, style, data_, rowspan_, colspan_, title_),
+ value,
+ '</td>'
+ ].join('');
+
+ // Hide empty data on Card view when smartDisplay is set to true.
+ if (that.options.cardView && that.options.smartDisplay && value === '') {
+ // Should set a placeholder for event binding correct fieldIndex
+ text = '<div class="card-view"></div>';
+ }
+ }
+
+ html.push(text);
+ });
+
+ if (this.options.cardView) {
+ html.push('</div></td>');
+ }
+
+ html.push('</tr>');
+ }
+
+ // show no records
+ if (!html.length) {
+ html.push('<tr class="no-records-found">',
+ sprintf('<td colspan="%s">%s</td>',
+ this.$header.find('th').length, this.options.formatNoMatches()),
+ '</tr>');
+ }
+
+ this.$body.html(html.join(''));
+
+ if (!fixedScroll) {
+ this.scrollTo(0);
+ }
+
+ // click to select by column
+ this.$body.find('> tr[data-index] > td').off('click dblclick').on('click dblclick', function (e) {
+ var $td = $(this),
+ $tr = $td.parent(),
+ item = that.data[$tr.data('index')],
+ index = $td[0].cellIndex,
+ fields = that.getVisibleFields(),
+ field = fields[that.options.detailView && !that.options.cardView ? index - 1 : index],
+ column = that.columns[getFieldIndex(that.columns, field)],
+ value = getItemField(item, field, that.options.escape);
+
+ if ($td.find('.detail-icon').length) {
+ return;
+ }
+
+ that.trigger(e.type === 'click' ? 'click-cell' : 'dbl-click-cell', field, value, item, $td);
+ that.trigger(e.type === 'click' ? 'click-row' : 'dbl-click-row', item, $tr, field);
+
+ // if click to select - then trigger the checkbox/radio click
+ if (e.type === 'click' && that.options.clickToSelect && column.clickToSelect) {
+ var $selectItem = $tr.find(sprintf('[name="%s"]', that.options.selectItemName));
+ if ($selectItem.length) {
+ $selectItem[0].click(); // #144: .trigger('click') bug
+ }
+ }
+ });
+
+ this.$body.find('> tr[data-index] > td > .detail-icon').off('click').on('click', function () {
+ var $this = $(this),
+ $tr = $this.parent().parent(),
+ index = $tr.data('index'),
+ row = data[index]; // Fix #980 Detail view, when searching, returns wrong row
+
+ // remove and update
+ if ($tr.next().is('tr.detail-view')) {
+ $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailOpen));
+ $tr.next().remove();
+ that.trigger('collapse-row', index, row);
+ } else {
+ $this.find('i').attr('class', sprintf('%s %s', that.options.iconsPrefix, that.options.icons.detailClose));
+ $tr.after(sprintf('<tr class="detail-view"><td colspan="%s"></td></tr>', $tr.find('td').length));
+ var $element = $tr.next().find('td');
+ var content = calculateObjectValue(that.options, that.options.detailFormatter, [index, row, $element], '');
+ if($element.length === 1) {
+ $element.append(content);
+ }
+ that.trigger('expand-row', index, row, $element);
+ }
+ that.resetView();
+ });
+
+ this.$selectItem = this.$body.find(sprintf('[name="%s"]', this.options.selectItemName));
+ this.$selectItem.off('click').on('click', function (event) {
+ event.stopImmediatePropagation();
+
+ var $this = $(this),
+ checked = $this.prop('checked'),
+ row = that.data[$this.data('index')];
+
+ if (that.options.maintainSelected && $(this).is(':radio')) {
+ $.each(that.options.data, function (i, row) {
+ row[that.header.stateField] = false;
+ });
+ }
+
+ row[that.header.stateField] = checked;
+
+ if (that.options.singleSelect) {
+ that.$selectItem.not(this).each(function () {
+ that.data[$(this).data('index')][that.header.stateField] = false;
+ });
+ that.$selectItem.filter(':checked').not(this).prop('checked', false);
+ }
+
+ that.updateSelected();
+ that.trigger(checked ? 'check' : 'uncheck', row, $this);
+ });
+
+ $.each(this.header.events, function (i, events) {
+ if (!events) {
+ return;
+ }
+ // fix bug, if events is defined with namespace
+ if (typeof events === 'string') {
+ events = calculateObjectValue(null, events);
+ }
+
+ var field = that.header.fields[i],
+ fieldIndex = $.inArray(field, that.getVisibleFields());
+
+ if (that.options.detailView && !that.options.cardView) {
+ fieldIndex += 1;
+ }
+
+ for (var key in events) {
+ that.$body.find('>tr:not(.no-records-found)').each(function () {
+ var $tr = $(this),
+ $td = $tr.find(that.options.cardView ? '.card-view' : 'td').eq(fieldIndex),
+ index = key.indexOf(' '),
+ name = key.substring(0, index),
+ el = key.substring(index + 1),
+ func = events[key];
+
+ $td.find(el).off(name).on(name, function (e) {
+ var index = $tr.data('index'),
+ row = that.data[index],
+ value = row[field];
+
+ func.apply(this, [e, value, row, index]);
+ });
+ });
+ }
+ });
+
+ this.updateSelected();
+ this.resetView();
+
+ this.trigger('post-body', data);
+ };
+
+ BootstrapTable.prototype.initServer = function (silent, query, url) {
+ var that = this,
+ data = {},
+ params = {
+ searchText: this.searchText,
+ sortName: this.options.sortName,
+ sortOrder: this.options.sortOrder
+ },
+ request;
+
+ if (this.options.pagination) {
+ params.pageSize = this.options.pageSize === this.options.formatAllRows() ?
+ this.options.totalRows : this.options.pageSize;
+ params.pageNumber = this.options.pageNumber;
+ }
+
+ if (!(url || this.options.url) && !this.options.ajax) {
+ return;
+ }
+
+ if (this.options.queryParamsType === 'limit') {
+ params = {
+ search: params.searchText,
+ sort: params.sortName,
+ order: params.sortOrder
+ };
+
+ if (this.options.pagination) {
+ params.offset = this.options.pageSize === this.options.formatAllRows() ?
+ 0 : this.options.pageSize * (this.options.pageNumber - 1);
+ params.limit = this.options.pageSize === this.options.formatAllRows() ?
+ this.options.totalRows : this.options.pageSize;
+ }
+ }
+
+ if (!($.isEmptyObject(this.filterColumnsPartial))) {
+ params.filter = JSON.stringify(this.filterColumnsPartial, null);
+ }
+
+ data = calculateObjectValue(this.options, this.options.queryParams, [params], data);
+
+ $.extend(data, query || {});
+
+ // false to stop request
+ if (data === false) {
+ return;
+ }
+
+ if (!silent) {
+ this.$tableLoading.show();
+ }
+ request = $.extend({}, calculateObjectValue(null, this.options.ajaxOptions), {
+ type: this.options.method,
+ url: url || this.options.url,
+ data: this.options.contentType === 'application/json' && this.options.method === 'post' ?
+ JSON.stringify(data) : data,
+ cache: this.options.cache,
+ contentType: this.options.contentType,
+ dataType: this.options.dataType,
+ success: function (res) {
+ res = calculateObjectValue(that.options, that.options.responseHandler, [res], res);
+
+ that.load(res);
+ that.trigger('load-success', res);
+ if (!silent) that.$tableLoading.hide();
+ },
+ error: function (res) {
+ that.trigger('load-error', res.status, res);
+ if (!silent) that.$tableLoading.hide();
+ }
+ });
+
+ if (this.options.ajax) {
+ calculateObjectValue(this, this.options.ajax, [request], null);
+ } else {
+ if (this._xhr && this._xhr.readyState !== 4) {
+ this._xhr.abort();
+ }
+ this._xhr = $.ajax(request);
+ }
+ };
+
+ BootstrapTable.prototype.initSearchText = function () {
+ if (this.options.search) {
+ if (this.options.searchText !== '') {
+ var $search = this.$toolbar.find('.search input');
+ $search.val(this.options.searchText);
+ this.onSearch({currentTarget: $search});
+ }
+ }
+ };
+
+ BootstrapTable.prototype.getCaret = function () {
+ var that = this;
+
+ $.each(this.$header.find('th'), function (i, th) {
+ $(th).find('.sortable').removeClass('desc asc').addClass($(th).data('field') === that.options.sortName ? that.options.sortOrder : 'both');
+ });
+ };
+
+ BootstrapTable.prototype.updateSelected = function () {
+ var checkAll = this.$selectItem.filter(':enabled').length &&
+ this.$selectItem.filter(':enabled').length ===
+ this.$selectItem.filter(':enabled').filter(':checked').length;
+
+ this.$selectAll.add(this.$selectAll_).prop('checked', checkAll);
+
+ this.$selectItem.each(function () {
+ $(this).closest('tr')[$(this).prop('checked') ? 'addClass' : 'removeClass']('selected');
+ });
+ };
+
+ BootstrapTable.prototype.updateRows = function () {
+ var that = this;
+
+ this.$selectItem.each(function () {
+ that.data[$(this).data('index')][that.header.stateField] = $(this).prop('checked');
+ });
+ };
+
+ BootstrapTable.prototype.resetRows = function () {
+ var that = this;
+
+ $.each(this.data, function (i, row) {
+ that.$selectAll.prop('checked', false);
+ that.$selectItem.prop('checked', false);
+ if (that.header.stateField) {
+ row[that.header.stateField] = false;
+ }
+ });
+ };
+
+ BootstrapTable.prototype.trigger = function (name) {
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ name += '.bs.table';
+ this.options[BootstrapTable.EVENTS[name]].apply(this.options, args);
+ this.$el.trigger($.Event(name), args);
+
+ this.options.onAll(name, args);
+ this.$el.trigger($.Event('all.bs.table'), [name, args]);
+ };
+
+ BootstrapTable.prototype.resetHeader = function () {
+ // fix #61: the hidden table reset header bug.
+ // fix bug: get $el.css('width') error sometime (height = 500)
+ clearTimeout(this.timeoutId_);
+ this.timeoutId_ = setTimeout($.proxy(this.fitHeader, this), this.$el.is(':hidden') ? 100 : 0);
+ };
+
+ BootstrapTable.prototype.fitHeader = function () {
+ var that = this,
+ fixedBody,
+ scrollWidth,
+ focused,
+ focusedTemp;
+
+ if (that.$el.is(':hidden')) {
+ that.timeoutId_ = setTimeout($.proxy(that.fitHeader, that), 100);
+ return;
+ }
+ fixedBody = this.$tableBody.get(0);
+
+ scrollWidth = fixedBody.scrollWidth > fixedBody.clientWidth &&
+ fixedBody.scrollHeight > fixedBody.clientHeight + this.$header.outerHeight() ?
+ getScrollBarWidth() : 0;
+
+ this.$el.css('margin-top', -this.$header.outerHeight());
+
+ focused = $(':focus');
+ if (focused.length > 0) {
+ var $th = focused.parents('th');
+ if ($th.length > 0) {
+ var dataField = $th.attr('data-field');
+ if (dataField !== undefined) {
+ var $headerTh = this.$header.find("[data-field='" + dataField + "']");
+ if ($headerTh.length > 0) {
+ $headerTh.find(":input").addClass("focus-temp");
+ }
+ }
+ }
+ }
+
+ this.$header_ = this.$header.clone(true, true);
+ this.$selectAll_ = this.$header_.find('[name="btSelectAll"]');
+ this.$tableHeader.css({
+ 'margin-right': scrollWidth
+ }).find('table').css('width', this.$el.outerWidth())
+ .html('').attr('class', this.$el.attr('class'))
+ .append(this.$header_);
+
+
+ focusedTemp = $('.focus-temp:visible:eq(0)');
+ if (focusedTemp.length > 0) {
+ focusedTemp.focus();
+ this.$header.find('.focus-temp').removeClass('focus-temp');
+ }
+
+ // fix bug: $.data() is not working as expected after $.append()
+ this.$header.find('th[data-field]').each(function (i) {
+ that.$header_.find(sprintf('th[data-field="%s"]', $(this).data('field'))).data($(this).data());
+ });
+
+ var visibleFields = this.getVisibleFields(),
+ $ths = this.$header_.find('th');
+
+ this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) {
+ var $this = $(this),
+ index = i;
+
+ if (that.options.detailView && !that.options.cardView) {
+ if (i === 0) {
+ that.$header_.find('th.detail').find('.fht-cell').width($this.innerWidth());
+ }
+ index = i - 1;
+ }
+
+ var $th = that.$header_.find(sprintf('th[data-field="%s"]', visibleFields[index]));
+ if ($th.length > 1) {
+ $th = $($ths[$this[0].cellIndex]);
+ }
+
+ $th.find('.fht-cell').width($this.innerWidth());
+ });
+ // horizontal scroll event
+ // TODO: it's probably better improving the layout than binding to scroll event
+ this.$tableBody.off('scroll').on('scroll', function () {
+ that.$tableHeader.scrollLeft($(this).scrollLeft());
+
+ if (that.options.showFooter && !that.options.cardView) {
+ that.$tableFooter.scrollLeft($(this).scrollLeft());
+ }
+ });
+ that.trigger('post-header');
+ };
+
+ BootstrapTable.prototype.resetFooter = function () {
+ var that = this,
+ data = that.getData(),
+ html = [];
+
+ if (!this.options.showFooter || this.options.cardView) { //do nothing
+ return;
+ }
+
+ if (!this.options.cardView && this.options.detailView) {
+ html.push('<td><div class="th-inner">&nbsp;</div><div class="fht-cell"></div></td>');
+ }
+
+ $.each(this.columns, function (i, column) {
+ var key,
+ falign = '', // footer align style
+ valign = '',
+ csses = [],
+ style = {},
+ class_ = sprintf(' class="%s"', column['class']);
+
+ if (!column.visible) {
+ return;
+ }
+
+ if (that.options.cardView && (!column.cardVisible)) {
+ return;
+ }
+
+ falign = sprintf('text-align: %s; ', column.falign ? column.falign : column.align);
+ valign = sprintf('vertical-align: %s; ', column.valign);
+
+ style = calculateObjectValue(null, that.options.footerStyle);
+
+ if (style && style.css) {
+ for (key in style.css) {
+ csses.push(key + ': ' + style.css[key]);
+ }
+ }
+
+ html.push('<td', class_, sprintf(' style="%s"', falign + valign + csses.concat().join('; ')), '>');
+ html.push('<div class="th-inner">');
+
+ html.push(calculateObjectValue(column, column.footerFormatter, [data], '&nbsp;') || '&nbsp;');
+
+ html.push('</div>');
+ html.push('<div class="fht-cell"></div>');
+ html.push('</div>');
+ html.push('</td>');
+ });
+
+ this.$tableFooter.find('tr').html(html.join(''));
+ this.$tableFooter.show();
+ clearTimeout(this.timeoutFooter_);
+ this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this),
+ this.$el.is(':hidden') ? 100 : 0);
+ };
+
+ BootstrapTable.prototype.fitFooter = function () {
+ var that = this,
+ $footerTd,
+ elWidth,
+ scrollWidth;
+
+ clearTimeout(this.timeoutFooter_);
+ if (this.$el.is(':hidden')) {
+ this.timeoutFooter_ = setTimeout($.proxy(this.fitFooter, this), 100);
+ return;
+ }
+
+ elWidth = this.$el.css('width');
+ scrollWidth = elWidth > this.$tableBody.width() ? getScrollBarWidth() : 0;
+
+ this.$tableFooter.css({
+ 'margin-right': scrollWidth
+ }).find('table').css('width', elWidth)
+ .attr('class', this.$el.attr('class'));
+
+ $footerTd = this.$tableFooter.find('td');
+
+ this.$body.find('>tr:first-child:not(.no-records-found) > *').each(function (i) {
+ var $this = $(this);
+
+ $footerTd.eq(i).find('.fht-cell').width($this.innerWidth());
+ });
+ };
+
+ BootstrapTable.prototype.toggleColumn = function (index, checked, needUpdate) {
+ if (index === -1) {
+ return;
+ }
+ this.columns[index].visible = checked;
+ this.initHeader();
+ this.initSearch();
+ this.initPagination();
+ this.initBody();
+
+ if (this.options.showColumns) {
+ var $items = this.$toolbar.find('.keep-open input').prop('disabled', false);
+
+ if (needUpdate) {
+ $items.filter(sprintf('[value="%s"]', index)).prop('checked', checked);
+ }
+
+ if ($items.filter(':checked').length <= this.options.minimumCountColumns) {
+ $items.filter(':checked').prop('disabled', true);
+ }
+ }
+ };
+
+ BootstrapTable.prototype.toggleRow = function (index, uniqueId, visible) {
+ if (index === -1) {
+ return;
+ }
+
+ this.$body.find(typeof index !== 'undefined' ?
+ sprintf('tr[data-index="%s"]', index) :
+ sprintf('tr[data-uniqueid="%s"]', uniqueId))
+ [visible ? 'show' : 'hide']();
+ };
+
+ BootstrapTable.prototype.getVisibleFields = function () {
+ var that = this,
+ visibleFields = [];
+
+ $.each(this.header.fields, function (j, field) {
+ var column = that.columns[getFieldIndex(that.columns, field)];
+
+ if (!column.visible) {
+ return;
+ }
+ visibleFields.push(field);
+ });
+ return visibleFields;
+ };
+
+ // PUBLIC FUNCTION DEFINITION
+ // =======================
+
+ BootstrapTable.prototype.resetView = function (params) {
+ var padding = 0;
+
+ if (params && params.height) {
+ this.options.height = params.height;
+ }
+
+ this.$selectAll.prop('checked', this.$selectItem.length > 0 &&
+ this.$selectItem.length === this.$selectItem.filter(':checked').length);
+
+ if (this.options.height) {
+ var toolbarHeight = getRealHeight(this.$toolbar),
+ paginationHeight = getRealHeight(this.$pagination),
+ height = this.options.height - toolbarHeight - paginationHeight;
+
+ this.$tableContainer.css('height', height + 'px');
+ }
+
+ if (this.options.cardView) {
+ // remove the element css
+ this.$el.css('margin-top', '0');
+ this.$tableContainer.css('padding-bottom', '0');
+ this.$tableFooter.hide();
+ return;
+ }
+
+ if (this.options.showHeader && this.options.height) {
+ this.$tableHeader.show();
+ this.resetHeader();
+ padding += this.$header.outerHeight();
+ } else {
+ this.$tableHeader.hide();
+ this.trigger('post-header');
+ }
+
+ if (this.options.showFooter) {
+ this.resetFooter();
+ if (this.options.height) {
+ padding += this.$tableFooter.outerHeight() + 1;
+ }
+ }
+
+ // Assign the correct sortable arrow
+ this.getCaret();
+ this.$tableContainer.css('padding-bottom', padding + 'px');
+ this.trigger('reset-view');
+ };
+
+ BootstrapTable.prototype.getData = function (useCurrentPage) {
+ return (this.searchText || !$.isEmptyObject(this.filterColumns) || !$.isEmptyObject(this.filterColumnsPartial)) ?
+ (useCurrentPage ? this.data.slice(this.pageFrom - 1, this.pageTo) : this.data) :
+ (useCurrentPage ? this.options.data.slice(this.pageFrom - 1, this.pageTo) : this.options.data);
+ };
+
+ BootstrapTable.prototype.load = function (data) {
+ var fixedScroll = false;
+
+ // #431: support pagination
+ if (this.options.sidePagination === 'server') {
+ this.options.totalRows = data.total;
+ fixedScroll = data.fixedScroll;
+ data = data[this.options.dataField];
+ } else if (!$.isArray(data)) { // support fixedScroll
+ fixedScroll = data.fixedScroll;
+ data = data.data;
+ }
+
+ this.initData(data);
+ this.initSearch();
+ this.initPagination();
+ this.initBody(fixedScroll);
+ };
+
+ BootstrapTable.prototype.append = function (data) {
+ this.initData(data, 'append');
+ this.initSearch();
+ this.initPagination();
+ this.initSort();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.prepend = function (data) {
+ this.initData(data, 'prepend');
+ this.initSearch();
+ this.initPagination();
+ this.initSort();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.remove = function (params) {
+ var len = this.options.data.length,
+ i, row;
+
+ if (!params.hasOwnProperty('field') || !params.hasOwnProperty('values')) {
+ return;
+ }
+
+ for (i = len - 1; i >= 0; i--) {
+ row = this.options.data[i];
+
+ if (!row.hasOwnProperty(params.field)) {
+ continue;
+ }
+ if ($.inArray(row[params.field], params.values) !== -1) {
+ this.options.data.splice(i, 1);
+ }
+ }
+
+ if (len === this.options.data.length) {
+ return;
+ }
+
+ this.initSearch();
+ this.initPagination();
+ this.initSort();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.removeAll = function () {
+ if (this.options.data.length > 0) {
+ this.options.data.splice(0, this.options.data.length);
+ this.initSearch();
+ this.initPagination();
+ this.initBody(true);
+ }
+ };
+
+ BootstrapTable.prototype.getRowByUniqueId = function (id) {
+ var uniqueId = this.options.uniqueId,
+ len = this.options.data.length,
+ dataRow = null,
+ i, row, rowUniqueId;
+
+ for (i = len - 1; i >= 0; i--) {
+ row = this.options.data[i];
+
+ if (row.hasOwnProperty(uniqueId)) { // uniqueId is a column
+ rowUniqueId = row[uniqueId];
+ } else if(row._data.hasOwnProperty(uniqueId)) { // uniqueId is a row data property
+ rowUniqueId = row._data[uniqueId];
+ } else {
+ continue;
+ }
+
+ if (typeof rowUniqueId === 'string') {
+ id = id.toString();
+ } else if (typeof rowUniqueId === 'number') {
+ if ((Number(rowUniqueId) === rowUniqueId) && (rowUniqueId % 1 === 0)) {
+ id = parseInt(id);
+ } else if ((rowUniqueId === Number(rowUniqueId)) && (rowUniqueId !== 0)) {
+ id = parseFloat(id);
+ }
+ }
+
+ if (rowUniqueId === id) {
+ dataRow = row;
+ break;
+ }
+ }
+
+ return dataRow;
+ };
+
+ BootstrapTable.prototype.removeByUniqueId = function (id) {
+ var len = this.options.data.length,
+ row = this.getRowByUniqueId(id);
+
+ if (row) {
+ this.options.data.splice(this.options.data.indexOf(row), 1);
+ }
+
+ if (len === this.options.data.length) {
+ return;
+ }
+
+ this.initSearch();
+ this.initPagination();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.updateByUniqueId = function (params) {
+ var that = this;
+ var allParams = $.isArray(params) ? params : [ params ];
+
+ $.each(allParams, function(i, params) {
+ var rowId;
+
+ if (!params.hasOwnProperty('id') || !params.hasOwnProperty('row')) {
+ return;
+ }
+
+ rowId = $.inArray(that.getRowByUniqueId(params.id), that.options.data);
+
+ if (rowId === -1) {
+ return;
+ }
+ $.extend(that.options.data[rowId], params.row);
+ });
+
+ this.initSearch();
+ this.initSort();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.insertRow = function (params) {
+ if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) {
+ return;
+ }
+ this.data.splice(params.index, 0, params.row);
+ this.initSearch();
+ this.initPagination();
+ this.initSort();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.updateRow = function (params) {
+ var that = this;
+ var allParams = $.isArray(params) ? params : [ params ];
+
+ $.each(allParams, function(i, params) {
+ if (!params.hasOwnProperty('index') || !params.hasOwnProperty('row')) {
+ return;
+ }
+ $.extend(that.options.data[params.index], params.row);
+ });
+
+ this.initSearch();
+ this.initSort();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.showRow = function (params) {
+ if (!params.hasOwnProperty('index') && !params.hasOwnProperty('uniqueId')) {
+ return;
+ }
+ this.toggleRow(params.index, params.uniqueId, true);
+ };
+
+ BootstrapTable.prototype.hideRow = function (params) {
+ if (!params.hasOwnProperty('index') && !params.hasOwnProperty('uniqueId')) {
+ return;
+ }
+ this.toggleRow(params.index, params.uniqueId, false);
+ };
+
+ BootstrapTable.prototype.getRowsHidden = function (show) {
+ var rows = $(this.$body[0]).children().filter(':hidden'),
+ i = 0;
+ if (show) {
+ for (; i < rows.length; i++) {
+ $(rows[i]).show();
+ }
+ }
+ return rows;
+ };
+
+ BootstrapTable.prototype.mergeCells = function (options) {
+ var row = options.index,
+ col = $.inArray(options.field, this.getVisibleFields()),
+ rowspan = options.rowspan || 1,
+ colspan = options.colspan || 1,
+ i, j,
+ $tr = this.$body.find('>tr'),
+ $td;
+
+ if (this.options.detailView && !this.options.cardView) {
+ col += 1;
+ }
+
+ $td = $tr.eq(row).find('>td').eq(col);
+
+ if (row < 0 || col < 0 || row >= this.data.length) {
+ return;
+ }
+
+ for (i = row; i < row + rowspan; i++) {
+ for (j = col; j < col + colspan; j++) {
+ $tr.eq(i).find('>td').eq(j).hide();
+ }
+ }
+
+ $td.attr('rowspan', rowspan).attr('colspan', colspan).show();
+ };
+
+ BootstrapTable.prototype.updateCell = function (params) {
+ if (!params.hasOwnProperty('index') ||
+ !params.hasOwnProperty('field') ||
+ !params.hasOwnProperty('value')) {
+ return;
+ }
+ this.data[params.index][params.field] = params.value;
+
+ if (params.reinit === false) {
+ return;
+ }
+ this.initSort();
+ this.initBody(true);
+ };
+
+ BootstrapTable.prototype.getOptions = function () {
+ return this.options;
+ };
+
+ BootstrapTable.prototype.getSelections = function () {
+ var that = this;
+
+ return $.grep(this.options.data, function (row) {
+ return row[that.header.stateField];
+ });
+ };
+
+ BootstrapTable.prototype.getAllSelections = function () {
+ var that = this;
+
+ return $.grep(this.options.data, function (row) {
+ return row[that.header.stateField];
+ });
+ };
+
+ BootstrapTable.prototype.checkAll = function () {
+ this.checkAll_(true);
+ };
+
+ BootstrapTable.prototype.uncheckAll = function () {
+ this.checkAll_(false);
+ };
+
+ BootstrapTable.prototype.checkInvert = function () {
+ var that = this;
+ var rows = that.$selectItem.filter(':enabled');
+ var checked = rows.filter(':checked');
+ rows.each(function() {
+ $(this).prop('checked', !$(this).prop('checked'));
+ });
+ that.updateRows();
+ that.updateSelected();
+ that.trigger('uncheck-some', checked);
+ checked = that.getSelections();
+ that.trigger('check-some', checked);
+ };
+
+ BootstrapTable.prototype.checkAll_ = function (checked) {
+ var rows;
+ if (!checked) {
+ rows = this.getSelections();
+ }
+ this.$selectAll.add(this.$selectAll_).prop('checked', checked);
+ this.$selectItem.filter(':enabled').prop('checked', checked);
+ this.updateRows();
+ if (checked) {
+ rows = this.getSelections();
+ }
+ this.trigger(checked ? 'check-all' : 'uncheck-all', rows);
+ };
+
+ BootstrapTable.prototype.check = function (index) {
+ this.check_(true, index);
+ };
+
+ BootstrapTable.prototype.uncheck = function (index) {
+ this.check_(false, index);
+ };
+
+ BootstrapTable.prototype.check_ = function (checked, index) {
+ var $el = this.$selectItem.filter(sprintf('[data-index="%s"]', index)).prop('checked', checked);
+ this.data[index][this.header.stateField] = checked;
+ this.updateSelected();
+ this.trigger(checked ? 'check' : 'uncheck', this.data[index], $el);
+ };
+
+ BootstrapTable.prototype.checkBy = function (obj) {
+ this.checkBy_(true, obj);
+ };
+
+ BootstrapTable.prototype.uncheckBy = function (obj) {
+ this.checkBy_(false, obj);
+ };
+
+ BootstrapTable.prototype.checkBy_ = function (checked, obj) {
+ if (!obj.hasOwnProperty('field') || !obj.hasOwnProperty('values')) {
+ return;
+ }
+
+ var that = this,
+ rows = [];
+ $.each(this.options.data, function (index, row) {
+ if (!row.hasOwnProperty(obj.field)) {
+ return false;
+ }
+ if ($.inArray(row[obj.field], obj.values) !== -1) {
+ var $el = that.$selectItem.filter(':enabled')
+ .filter(sprintf('[data-index="%s"]', index)).prop('checked', checked);
+ row[that.header.stateField] = checked;
+ rows.push(row);
+ that.trigger(checked ? 'check' : 'uncheck', row, $el);
+ }
+ });
+ this.updateSelected();
+ this.trigger(checked ? 'check-some' : 'uncheck-some', rows);
+ };
+
+ BootstrapTable.prototype.destroy = function () {
+ this.$el.insertBefore(this.$container);
+ $(this.options.toolbar).insertBefore(this.$el);
+ this.$container.next().remove();
+ this.$container.remove();
+ this.$el.html(this.$el_.html())
+ .css('margin-top', '0')
+ .attr('class', this.$el_.attr('class') || ''); // reset the class
+ };
+
+ BootstrapTable.prototype.showLoading = function () {
+ this.$tableLoading.show();
+ };
+
+ BootstrapTable.prototype.hideLoading = function () {
+ this.$tableLoading.hide();
+ };
+
+ BootstrapTable.prototype.togglePagination = function () {
+ this.options.pagination = !this.options.pagination;
+ var button = this.$toolbar.find('button[name="paginationSwitch"] i');
+ if (this.options.pagination) {
+ button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchDown);
+ } else {
+ button.attr("class", this.options.iconsPrefix + " " + this.options.icons.paginationSwitchUp);
+ }
+ this.updatePagination();
+ };
+
+ BootstrapTable.prototype.refresh = function (params) {
+ if (params && params.url) {
+ this.options.pageNumber = 1;
+ }
+ this.initServer(params && params.silent,
+ params && params.query, params && params.url);
+ this.trigger('refresh', params);
+ };
+
+ BootstrapTable.prototype.resetWidth = function () {
+ if (this.options.showHeader && this.options.height) {
+ this.fitHeader();
+ }
+ if (this.options.showFooter) {
+ this.fitFooter();
+ }
+ };
+
+ BootstrapTable.prototype.showColumn = function (field) {
+ this.toggleColumn(getFieldIndex(this.columns, field), true, true);
+ };
+
+ BootstrapTable.prototype.hideColumn = function (field) {
+ this.toggleColumn(getFieldIndex(this.columns, field), false, true);
+ };
+
+ BootstrapTable.prototype.getHiddenColumns = function () {
+ return $.grep(this.columns, function (column) {
+ return !column.visible;
+ });
+ };
+
+ BootstrapTable.prototype.getVisibleColumns = function () {
+ return $.grep(this.columns, function (column) {
+ return column.visible;
+ });
+ };
+
+ BootstrapTable.prototype.toggleAllColumns = function (visible) {
+ $.each(this.columns, function (i, column) {
+ this.columns[i].visible = visible;
+ });
+
+ this.initHeader();
+ this.initSearch();
+ this.initPagination();
+ this.initBody();
+ if (this.options.showColumns) {
+ var $items = this.$toolbar.find('.keep-open input').prop('disabled', false);
+
+ if ($items.filter(':checked').length <= this.options.minimumCountColumns) {
+ $items.filter(':checked').prop('disabled', true);
+ }
+ }
+ };
+
+ BootstrapTable.prototype.showAllColumns = function () {
+ this.toggleAllColumns(true);
+ };
+
+ BootstrapTable.prototype.hideAllColumns = function () {
+ this.toggleAllColumns(false);
+ };
+
+ BootstrapTable.prototype.filterBy = function (columns) {
+ this.filterColumns = $.isEmptyObject(columns) ? {} : columns;
+ this.options.pageNumber = 1;
+ this.initSearch();
+ this.updatePagination();
+ };
+
+ BootstrapTable.prototype.scrollTo = function (value) {
+ if (typeof value === 'string') {
+ value = value === 'bottom' ? this.$tableBody[0].scrollHeight : 0;
+ }
+ if (typeof value === 'number') {
+ this.$tableBody.scrollTop(value);
+ }
+ if (typeof value === 'undefined') {
+ return this.$tableBody.scrollTop();
+ }
+ };
+
+ BootstrapTable.prototype.getScrollPosition = function () {
+ return this.scrollTo();
+ };
+
+ BootstrapTable.prototype.selectPage = function (page) {
+ if (page > 0 && page <= this.options.totalPages) {
+ this.options.pageNumber = page;
+ this.updatePagination();
+ }
+ };
+
+ BootstrapTable.prototype.prevPage = function () {
+ if (this.options.pageNumber > 1) {
+ this.options.pageNumber--;
+ this.updatePagination();
+ }
+ };
+
+ BootstrapTable.prototype.nextPage = function () {
+ if (this.options.pageNumber < this.options.totalPages) {
+ this.options.pageNumber++;
+ this.updatePagination();
+ }
+ };
+
+ BootstrapTable.prototype.toggleView = function () {
+ this.options.cardView = !this.options.cardView;
+ this.initHeader();
+ // Fixed remove toolbar when click cardView button.
+ //that.initToolbar();
+ this.initBody();
+ this.trigger('toggle', this.options.cardView);
+ };
+
+ BootstrapTable.prototype.refreshOptions = function (options) {
+ //If the objects are equivalent then avoid the call of destroy / init methods
+ if (compareObjects(this.options, options, true)) {
+ return;
+ }
+ this.options = $.extend(this.options, options);
+ this.trigger('refresh-options', this.options);
+ this.destroy();
+ this.init();
+ };
+
+ BootstrapTable.prototype.resetSearch = function (text) {
+ var $search = this.$toolbar.find('.search input');
+ $search.val(text || '');
+ this.onSearch({currentTarget: $search});
+ };
+
+ BootstrapTable.prototype.expandRow_ = function (expand, index) {
+ var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', index));
+ if ($tr.next().is('tr.detail-view') === (expand ? false : true)) {
+ $tr.find('> td > .detail-icon').click();
+ }
+ };
+
+ BootstrapTable.prototype.expandRow = function (index) {
+ this.expandRow_(true, index);
+ };
+
+ BootstrapTable.prototype.collapseRow = function (index) {
+ this.expandRow_(false, index);
+ };
+
+ BootstrapTable.prototype.expandAllRows = function (isSubTable) {
+ if (isSubTable) {
+ var $tr = this.$body.find(sprintf('> tr[data-index="%s"]', 0)),
+ that = this,
+ detailIcon = null,
+ executeInterval = false,
+ idInterval = -1;
+
+ if (!$tr.next().is('tr.detail-view')) {
+ $tr.find('> td > .detail-icon').click();
+ executeInterval = true;
+ } else if (!$tr.next().next().is('tr.detail-view')) {
+ $tr.next().find(".detail-icon").click();
+ executeInterval = true;
+ }
+
+ if (executeInterval) {
+ try {
+ idInterval = setInterval(function () {
+ detailIcon = that.$body.find("tr.detail-view").last().find(".detail-icon");
+ if (detailIcon.length > 0) {
+ detailIcon.click();
+ } else {
+ clearInterval(idInterval);
+ }
+ }, 1);
+ } catch (ex) {
+ clearInterval(idInterval);
+ }
+ }
+ } else {
+ var trs = this.$body.children();
+ for (var i = 0; i < trs.length; i++) {
+ this.expandRow_(true, $(trs[i]).data("index"));
+ }
+ }
+ };
+
+ BootstrapTable.prototype.collapseAllRows = function (isSubTable) {
+ if (isSubTable) {
+ this.expandRow_(false, 0);
+ } else {
+ var trs = this.$body.children();
+ for (var i = 0; i < trs.length; i++) {
+ this.expandRow_(false, $(trs[i]).data("index"));
+ }
+ }
+ };
+
+ BootstrapTable.prototype.updateFormatText = function (name, text) {
+ if (this.options[sprintf('format%s', name)]) {
+ if (typeof text === 'string') {
+ this.options[sprintf('format%s', name)] = function () {
+ return text;
+ };
+ } else if (typeof text === 'function') {
+ this.options[sprintf('format%s', name)] = text;
+ }
+ }
+ this.initToolbar();
+ this.initPagination();
+ this.initBody();
+ };
+
+ // BOOTSTRAP TABLE PLUGIN DEFINITION
+ // =======================
+
+ var allowedMethods = [
+ 'getOptions',
+ 'getSelections', 'getAllSelections', 'getData',
+ 'load', 'append', 'prepend', 'remove', 'removeAll',
+ 'insertRow', 'updateRow', 'updateCell', 'updateByUniqueId', 'removeByUniqueId',
+ 'getRowByUniqueId', 'showRow', 'hideRow', 'getRowsHidden',
+ 'mergeCells',
+ 'checkAll', 'uncheckAll', 'checkInvert',
+ 'check', 'uncheck',
+ 'checkBy', 'uncheckBy',
+ 'refresh',
+ 'resetView',
+ 'resetWidth',
+ 'destroy',
+ 'showLoading', 'hideLoading',
+ 'showColumn', 'hideColumn', 'getHiddenColumns', 'getVisibleColumns',
+ 'showAllColumns', 'hideAllColumns',
+ 'filterBy',
+ 'scrollTo',
+ 'getScrollPosition',
+ 'selectPage', 'prevPage', 'nextPage',
+ 'togglePagination',
+ 'toggleView',
+ 'refreshOptions',
+ 'resetSearch',
+ 'expandRow', 'collapseRow', 'expandAllRows', 'collapseAllRows',
+ 'updateFormatText'
+ ];
+
+ $.fn.bootstrapTable = function (option) {
+ var value,
+ args = Array.prototype.slice.call(arguments, 1);
+
+ this.each(function () {
+ var $this = $(this),
+ data = $this.data('bootstrap.table'),
+ options = $.extend({}, BootstrapTable.DEFAULTS, $this.data(),
+ typeof option === 'object' && option);
+
+ if (typeof option === 'string') {
+ if ($.inArray(option, allowedMethods) < 0) {
+ throw new Error("Unknown method: " + option);
+ }
+
+ if (!data) {
+ return;
+ }
+
+ value = data[option].apply(data, args);
+
+ if (option === 'destroy') {
+ $this.removeData('bootstrap.table');
+ }
+ }
+
+ if (!data) {
+ $this.data('bootstrap.table', (data = new BootstrapTable(this, options)));
+ }
+ });
+
+ return typeof value === 'undefined' ? this : value;
+ };
+
+ $.fn.bootstrapTable.Constructor = BootstrapTable;
+ $.fn.bootstrapTable.defaults = BootstrapTable.DEFAULTS;
+ $.fn.bootstrapTable.columnDefaults = BootstrapTable.COLUMN_DEFAULTS;
+ $.fn.bootstrapTable.locales = BootstrapTable.LOCALES;
+ $.fn.bootstrapTable.methods = allowedMethods;
+ $.fn.bootstrapTable.utils = {
+ sprintf: sprintf,
+ getFieldIndex: getFieldIndex,
+ compareObjects: compareObjects,
+ calculateObjectValue: calculateObjectValue,
+ getItemField: getItemField,
+ objectKeys: objectKeys,
+ isIEBrowser: isIEBrowser
+ };
+
+ // BOOTSTRAP TABLE INIT
+ // =======================
+
+ $(function () {
+ $('[data-toggle="table"]').bootstrapTable();
+ });
+})(jQuery);
diff --git a/debian/missing-sources/bootstrap-table-export-1.11.0.js b/debian/missing-sources/bootstrap-table-export-1.11.0.js
new file mode 100644
index 000000000..98b8f3235
--- /dev/null
+++ b/debian/missing-sources/bootstrap-table-export-1.11.0.js
@@ -0,0 +1,121 @@
+/**
+ * @author zhixin wen <wenzhixin2010@gmail.com>
+ * extensions: https://github.com/kayalshri/tableExport.jquery.plugin
+ */
+
+(function ($) {
+ 'use strict';
+ var sprintf = $.fn.bootstrapTable.utils.sprintf;
+
+ var TYPE_NAME = {
+ json: 'JSON',
+ xml: 'XML',
+ png: 'PNG',
+ csv: 'CSV',
+ txt: 'TXT',
+ sql: 'SQL',
+ doc: 'MS-Word',
+ excel: 'MS-Excel',
+ powerpoint: 'MS-Powerpoint',
+ pdf: 'PDF'
+ };
+
+ $.extend($.fn.bootstrapTable.defaults, {
+ showExport: false,
+ exportDataType: 'basic', // basic, all, selected
+ // 'json', 'xml', 'png', 'csv', 'txt', 'sql', 'doc', 'excel', 'powerpoint', 'pdf'
+ exportTypes: ['json', 'xml', 'csv', 'txt', 'sql', 'excel'],
+ exportOptions: {}
+ });
+
+ $.extend($.fn.bootstrapTable.defaults.icons, {
+ export: 'glyphicon-export icon-share'
+ });
+
+ $.extend($.fn.bootstrapTable.locales, {
+ formatExport: function () {
+ return 'Export data';
+ }
+ });
+ $.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
+
+ var BootstrapTable = $.fn.bootstrapTable.Constructor,
+ _initToolbar = BootstrapTable.prototype.initToolbar;
+
+ BootstrapTable.prototype.initToolbar = function () {
+ this.showToolbar = this.options.showExport;
+
+ _initToolbar.apply(this, Array.prototype.slice.apply(arguments));
+
+ if (this.options.showExport) {
+ var that = this,
+ $btnGroup = this.$toolbar.find('>.btn-group'),
+ $export = $btnGroup.find('div.export');
+
+ if (!$export.length) {
+ $export = $([
+ '<div class="export btn-group">',
+ '<button class="btn' +
+ sprintf(' btn-%s', this.options.buttonsClass) +
+ sprintf(' btn-%s', this.options.iconSize) +
+ ' dropdown-toggle" ' +
+ 'title="' + this.options.formatExport() + '" ' +
+ 'data-toggle="dropdown" type="button">',
+ sprintf('<i class="%s %s"></i> ', this.options.iconsPrefix, this.options.icons.export),
+ '<span class="caret"></span>',
+ '</button>',
+ '<ul class="dropdown-menu" role="menu">',
+ '</ul>',
+ '</div>'].join('')).appendTo($btnGroup);
+
+ var $menu = $export.find('.dropdown-menu'),
+ exportTypes = this.options.exportTypes;
+
+ if (typeof this.options.exportTypes === 'string') {
+ var types = this.options.exportTypes.slice(1, -1).replace(/ /g, '').split(',');
+
+ exportTypes = [];
+ $.each(types, function (i, value) {
+ exportTypes.push(value.slice(1, -1));
+ });
+ }
+ $.each(exportTypes, function (i, type) {
+ if (TYPE_NAME.hasOwnProperty(type)) {
+ $menu.append(['<li data-type="' + type + '">',
+ '<a href="javascript:void(0)">',
+ TYPE_NAME[type],
+ '</a>',
+ '</li>'].join(''));
+ }
+ });
+
+ $menu.find('li').click(function () {
+ var type = $(this).data('type'),
+ doExport = function () {
+ that.$el.tableExport($.extend({}, that.options.exportOptions, {
+ type: type,
+ escape: false
+ }));
+ };
+
+ if (that.options.exportDataType === 'all' && that.options.pagination) {
+ that.$el.one(that.options.sidePagination === 'server' ? 'post-body.bs.table' : 'page-change.bs.table', function () {
+ doExport();
+ that.togglePagination();
+ });
+ that.togglePagination();
+ } else if (that.options.exportDataType === 'selected') {
+ var data = that.getData(),
+ selectedData = that.getAllSelections();
+
+ that.load(selectedData);
+ doExport();
+ that.load(data);
+ } else {
+ doExport();
+ }
+ });
+ }
+ }
+ };
+})(jQuery);
diff --git a/debian/missing-sources/bootstrap-theme-3.3.7.css b/debian/missing-sources/bootstrap-theme-3.3.7.css
new file mode 100644
index 000000000..31d888266
--- /dev/null
+++ b/debian/missing-sources/bootstrap-theme-3.3.7.css
@@ -0,0 +1,587 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+}
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-default.disabled,
+.btn-primary.disabled,
+.btn-success.disabled,
+.btn-info.disabled,
+.btn-warning.disabled,
+.btn-danger.disabled,
+.btn-default[disabled],
+.btn-primary[disabled],
+.btn-success[disabled],
+.btn-info[disabled],
+.btn-warning[disabled],
+.btn-danger[disabled],
+fieldset[disabled] .btn-default,
+fieldset[disabled] .btn-primary,
+fieldset[disabled] .btn-success,
+fieldset[disabled] .btn-info,
+fieldset[disabled] .btn-warning,
+fieldset[disabled] .btn-danger {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-default .badge,
+.btn-primary .badge,
+.btn-success .badge,
+.btn-info .badge,
+.btn-warning .badge,
+.btn-danger .badge {
+ text-shadow: none;
+}
+.btn:active,
+.btn.active {
+ background-image: none;
+}
+.btn-default {
+ text-shadow: 0 1px 0 #fff;
+ background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+ background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
+ background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #dbdbdb;
+ border-color: #ccc;
+}
+.btn-default:hover,
+.btn-default:focus {
+ background-color: #e0e0e0;
+ background-position: 0 -15px;
+}
+.btn-default:active,
+.btn-default.active {
+ background-color: #e0e0e0;
+ border-color: #dbdbdb;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+ background-color: #e0e0e0;
+ background-image: none;
+}
+.btn-primary {
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #245580;
+}
+.btn-primary:hover,
+.btn-primary:focus {
+ background-color: #265a88;
+ background-position: 0 -15px;
+}
+.btn-primary:active,
+.btn-primary.active {
+ background-color: #265a88;
+ border-color: #245580;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+ background-color: #265a88;
+ background-image: none;
+}
+.btn-success {
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #3e8f3e;
+}
+.btn-success:hover,
+.btn-success:focus {
+ background-color: #419641;
+ background-position: 0 -15px;
+}
+.btn-success:active,
+.btn-success.active {
+ background-color: #419641;
+ border-color: #3e8f3e;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+ background-color: #419641;
+ background-image: none;
+}
+.btn-info {
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #28a4c9;
+}
+.btn-info:hover,
+.btn-info:focus {
+ background-color: #2aabd2;
+ background-position: 0 -15px;
+}
+.btn-info:active,
+.btn-info.active {
+ background-color: #2aabd2;
+ border-color: #28a4c9;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+ background-color: #2aabd2;
+ background-image: none;
+}
+.btn-warning {
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #e38d13;
+}
+.btn-warning:hover,
+.btn-warning:focus {
+ background-color: #eb9316;
+ background-position: 0 -15px;
+}
+.btn-warning:active,
+.btn-warning.active {
+ background-color: #eb9316;
+ border-color: #e38d13;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+ background-color: #eb9316;
+ background-image: none;
+}
+.btn-danger {
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-color: #b92c28;
+}
+.btn-danger:hover,
+.btn-danger:focus {
+ background-color: #c12e2a;
+ background-position: 0 -15px;
+}
+.btn-danger:active,
+.btn-danger.active {
+ background-color: #c12e2a;
+ border-color: #b92c28;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+ background-color: #c12e2a;
+ background-image: none;
+}
+.thumbnail,
+.img-thumbnail {
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ background-color: #e8e8e8;
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+ background-repeat: repeat-x;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ background-color: #2e6da4;
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+ background-repeat: repeat-x;
+}
+.navbar-default {
+ background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+ background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
+ background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .active > a {
+ background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+ background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
+ background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
+ background-repeat: repeat-x;
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+}
+.navbar-brand,
+.navbar-nav > li > a {
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
+}
+.navbar-inverse {
+ background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
+ background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
+ background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ background-repeat: repeat-x;
+ border-radius: 4px;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .active > a {
+ background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+ background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
+ background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
+ background-repeat: repeat-x;
+ -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+ box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+}
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
+}
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ border-radius: 0;
+}
+@media (max-width: 767px) {
+ .navbar .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #fff;
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+ background-repeat: repeat-x;
+ }
+}
+.alert {
+ text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+}
+.alert-success {
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #b2dba1;
+}
+.alert-info {
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #9acfea;
+}
+.alert-warning {
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #f5e79e;
+}
+.alert-danger {
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+ background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
+ background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #dca7a7;
+}
+.progress {
+ background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+ background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
+ background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar {
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-success {
+ background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+ background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
+ background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-info {
+ background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+ background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
+ background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-warning {
+ background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+ background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
+ background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-danger {
+ background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+ background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
+ background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+ background-repeat: repeat-x;
+}
+.progress-bar-striped {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.list-group {
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ text-shadow: 0 -1px 0 #286090;
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #2b669a;
+}
+.list-group-item.active .badge,
+.list-group-item.active:hover .badge,
+.list-group-item.active:focus .badge {
+ text-shadow: none;
+}
+.panel {
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+ box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+}
+.panel-default > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+ background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-primary > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+ background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-success > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+ background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
+ background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-info > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+ background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
+ background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-warning > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+ background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
+ background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+ background-repeat: repeat-x;
+}
+.panel-danger > .panel-heading {
+ background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+ background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
+ background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+ background-repeat: repeat-x;
+}
+.well {
+ background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+ background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
+ background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+ background-repeat: repeat-x;
+ border-color: #dcdcdc;
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+}
+/*# sourceMappingURL=bootstrap-theme.css.map */
diff --git a/debian/missing-sources/bootstrap-toggle.css b/debian/missing-sources/bootstrap-toggle-2.2.2.css
index 057d08b36..057d08b36 100644
--- a/debian/missing-sources/bootstrap-toggle.css
+++ b/debian/missing-sources/bootstrap-toggle-2.2.2.css
diff --git a/debian/missing-sources/bootstrap-toggle.js b/debian/missing-sources/bootstrap-toggle-2.2.2.js
index 533914edd..533914edd 100644
--- a/debian/missing-sources/bootstrap-toggle.js
+++ b/debian/missing-sources/bootstrap-toggle-2.2.2.js
diff --git a/debian/missing-sources/bootstrap.slate.css b/debian/missing-sources/bootstrap.slate.css
deleted file mode 100644
index 1e255597d..000000000
--- a/debian/missing-sources/bootstrap.slate.css
+++ /dev/null
@@ -1,7271 +0,0 @@
-/*!
- * bootswatch v3.3.6
- * Homepage: http://bootswatch.com
- * Copyright 2012-2016 Thomas Park
- * Licensed under MIT
- * Based on Bootstrap
-*/
-/*!
- * Bootstrap v3.3.6 (http://getbootstrap.com)
- * Copyright 2011-2015 Twitter, Inc.
- * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
- */
-/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
-html {
- font-family: sans-serif;
- -ms-text-size-adjust: 100%;
- -webkit-text-size-adjust: 100%;
-}
-body {
- margin: 0;
-}
-article,
-aside,
-details,
-figcaption,
-figure,
-footer,
-header,
-hgroup,
-main,
-menu,
-nav,
-section,
-summary {
- display: block;
-}
-audio,
-canvas,
-progress,
-video {
- display: inline-block;
- vertical-align: baseline;
-}
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-[hidden],
-template {
- display: none;
-}
-a {
- background-color: transparent;
-}
-a:active,
-a:hover {
- outline: 0;
-}
-abbr[title] {
- border-bottom: 1px dotted;
-}
-b,
-strong {
- font-weight: bold;
-}
-dfn {
- font-style: italic;
-}
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-mark {
- background: #ff0;
- color: #000;
-}
-small {
- font-size: 80%;
-}
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-sup {
- top: -0.5em;
-}
-sub {
- bottom: -0.25em;
-}
-img {
- border: 0;
-}
-svg:not(:root) {
- overflow: hidden;
-}
-figure {
- margin: 1em 40px;
-}
-hr {
- -webkit-box-sizing: content-box;
- -moz-box-sizing: content-box;
- box-sizing: content-box;
- height: 0;
-}
-pre {
- overflow: auto;
-}
-code,
-kbd,
-pre,
-samp {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-button,
-input,
-optgroup,
-select,
-textarea {
- color: inherit;
- font: inherit;
- margin: 0;
-}
-button {
- overflow: visible;
-}
-button,
-select {
- text-transform: none;
-}
-button,
-html input[type="button"],
-input[type="reset"],
-input[type="submit"] {
- -webkit-appearance: button;
- cursor: pointer;
-}
-button[disabled],
-html input[disabled] {
- cursor: default;
-}
-button::-moz-focus-inner,
-input::-moz-focus-inner {
- border: 0;
- padding: 0;
-}
-input {
- line-height: normal;
-}
-input[type="checkbox"],
-input[type="radio"] {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
- padding: 0;
-}
-input[type="number"]::-webkit-inner-spin-button,
-input[type="number"]::-webkit-outer-spin-button {
- height: auto;
-}
-input[type="search"] {
- -webkit-appearance: textfield;
- -webkit-box-sizing: content-box;
- -moz-box-sizing: content-box;
- box-sizing: content-box;
-}
-input[type="search"]::-webkit-search-cancel-button,
-input[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
- padding: 0.35em 0.625em 0.75em;
-}
-legend {
- border: 0;
- padding: 0;
-}
-textarea {
- overflow: auto;
-}
-optgroup {
- font-weight: bold;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-td,
-th {
- padding: 0;
-}
-/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
-@media print {
- *,
- *:before,
- *:after {
- background: transparent !important;
- color: #000 !important;
- -webkit-box-shadow: none !important;
- box-shadow: none !important;
- text-shadow: none !important;
- }
- a,
- a:visited {
- text-decoration: underline;
- }
- a[href]:after {
- content: " (" attr(href) ")";
- }
- abbr[title]:after {
- content: " (" attr(title) ")";
- }
- a[href^="#"]:after,
- a[href^="javascript:"]:after {
- content: "";
- }
- pre,
- blockquote {
- border: 1px solid #999;
- page-break-inside: avoid;
- }
- thead {
- display: table-header-group;
- }
- tr,
- img {
- page-break-inside: avoid;
- }
- img {
- max-width: 100% !important;
- }
- p,
- h2,
- h3 {
- orphans: 3;
- widows: 3;
- }
- h2,
- h3 {
- page-break-after: avoid;
- }
- .navbar {
- display: none;
- }
- .btn > .caret,
- .dropup > .btn > .caret {
- border-top-color: #000 !important;
- }
- .label {
- border: 1px solid #000;
- }
- .table {
- border-collapse: collapse !important;
- }
- .table td,
- .table th {
- background-color: #fff !important;
- }
- .table-bordered th,
- .table-bordered td {
- border: 1px solid #ddd !important;
- }
-}
-@font-face {
- font-family: 'Glyphicons Halflings';
- src: url('../fonts/glyphicons-halflings-regular.eot');
- src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
-}
-.glyphicon {
- position: relative;
- top: 1px;
- display: inline-block;
- font-family: 'Glyphicons Halflings';
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-.glyphicon-asterisk:before {
- content: "\002a";
-}
-.glyphicon-plus:before {
- content: "\002b";
-}
-.glyphicon-euro:before,
-.glyphicon-eur:before {
- content: "\20ac";
-}
-.glyphicon-minus:before {
- content: "\2212";
-}
-.glyphicon-cloud:before {
- content: "\2601";
-}
-.glyphicon-envelope:before {
- content: "\2709";
-}
-.glyphicon-pencil:before {
- content: "\270f";
-}
-.glyphicon-glass:before {
- content: "\e001";
-}
-.glyphicon-music:before {
- content: "\e002";
-}
-.glyphicon-search:before {
- content: "\e003";
-}
-.glyphicon-heart:before {
- content: "\e005";
-}
-.glyphicon-star:before {
- content: "\e006";
-}
-.glyphicon-star-empty:before {
- content: "\e007";
-}
-.glyphicon-user:before {
- content: "\e008";
-}
-.glyphicon-film:before {
- content: "\e009";
-}
-.glyphicon-th-large:before {
- content: "\e010";
-}
-.glyphicon-th:before {
- content: "\e011";
-}
-.glyphicon-th-list:before {
- content: "\e012";
-}
-.glyphicon-ok:before {
- content: "\e013";
-}
-.glyphicon-remove:before {
- content: "\e014";
-}
-.glyphicon-zoom-in:before {
- content: "\e015";
-}
-.glyphicon-zoom-out:before {
- content: "\e016";
-}
-.glyphicon-off:before {
- content: "\e017";
-}
-.glyphicon-signal:before {
- content: "\e018";
-}
-.glyphicon-cog:before {
- content: "\e019";
-}
-.glyphicon-trash:before {
- content: "\e020";
-}
-.glyphicon-home:before {
- content: "\e021";
-}
-.glyphicon-file:before {
- content: "\e022";
-}
-.glyphicon-time:before {
- content: "\e023";
-}
-.glyphicon-road:before {
- content: "\e024";
-}
-.glyphicon-download-alt:before {
- content: "\e025";
-}
-.glyphicon-download:before {
- content: "\e026";
-}
-.glyphicon-upload:before {
- content: "\e027";
-}
-.glyphicon-inbox:before {
- content: "\e028";
-}
-.glyphicon-play-circle:before {
- content: "\e029";
-}
-.glyphicon-repeat:before {
- content: "\e030";
-}
-.glyphicon-refresh:before {
- content: "\e031";
-}
-.glyphicon-list-alt:before {
- content: "\e032";
-}
-.glyphicon-lock:before {
- content: "\e033";
-}
-.glyphicon-flag:before {
- content: "\e034";
-}
-.glyphicon-headphones:before {
- content: "\e035";
-}
-.glyphicon-volume-off:before {
- content: "\e036";
-}
-.glyphicon-volume-down:before {
- content: "\e037";
-}
-.glyphicon-volume-up:before {
- content: "\e038";
-}
-.glyphicon-qrcode:before {
- content: "\e039";
-}
-.glyphicon-barcode:before {
- content: "\e040";
-}
-.glyphicon-tag:before {
- content: "\e041";
-}
-.glyphicon-tags:before {
- content: "\e042";
-}
-.glyphicon-book:before {
- content: "\e043";
-}
-.glyphicon-bookmark:before {
- content: "\e044";
-}
-.glyphicon-print:before {
- content: "\e045";
-}
-.glyphicon-camera:before {
- content: "\e046";
-}
-.glyphicon-font:before {
- content: "\e047";
-}
-.glyphicon-bold:before {
- content: "\e048";
-}
-.glyphicon-italic:before {
- content: "\e049";
-}
-.glyphicon-text-height:before {
- content: "\e050";
-}
-.glyphicon-text-width:before {
- content: "\e051";
-}
-.glyphicon-align-left:before {
- content: "\e052";
-}
-.glyphicon-align-center:before {
- content: "\e053";
-}
-.glyphicon-align-right:before {
- content: "\e054";
-}
-.glyphicon-align-justify:before {
- content: "\e055";
-}
-.glyphicon-list:before {
- content: "\e056";
-}
-.glyphicon-indent-left:before {
- content: "\e057";
-}
-.glyphicon-indent-right:before {
- content: "\e058";
-}
-.glyphicon-facetime-video:before {
- content: "\e059";
-}
-.glyphicon-picture:before {
- content: "\e060";
-}
-.glyphicon-map-marker:before {
- content: "\e062";
-}
-.glyphicon-adjust:before {
- content: "\e063";
-}
-.glyphicon-tint:before {
- content: "\e064";
-}
-.glyphicon-edit:before {
- content: "\e065";
-}
-.glyphicon-share:before {
- content: "\e066";
-}
-.glyphicon-check:before {
- content: "\e067";
-}
-.glyphicon-move:before {
- content: "\e068";
-}
-.glyphicon-step-backward:before {
- content: "\e069";
-}
-.glyphicon-fast-backward:before {
- content: "\e070";
-}
-.glyphicon-backward:before {
- content: "\e071";
-}
-.glyphicon-play:before {
- content: "\e072";
-}
-.glyphicon-pause:before {
- content: "\e073";
-}
-.glyphicon-stop:before {
- content: "\e074";
-}
-.glyphicon-forward:before {
- content: "\e075";
-}
-.glyphicon-fast-forward:before {
- content: "\e076";
-}
-.glyphicon-step-forward:before {
- content: "\e077";
-}
-.glyphicon-eject:before {
- content: "\e078";
-}
-.glyphicon-chevron-left:before {
- content: "\e079";
-}
-.glyphicon-chevron-right:before {
- content: "\e080";
-}
-.glyphicon-plus-sign:before {
- content: "\e081";
-}
-.glyphicon-minus-sign:before {
- content: "\e082";
-}
-.glyphicon-remove-sign:before {
- content: "\e083";
-}
-.glyphicon-ok-sign:before {
- content: "\e084";
-}
-.glyphicon-question-sign:before {
- content: "\e085";
-}
-.glyphicon-info-sign:before {
- content: "\e086";
-}
-.glyphicon-screenshot:before {
- content: "\e087";
-}
-.glyphicon-remove-circle:before {
- content: "\e088";
-}
-.glyphicon-ok-circle:before {
- content: "\e089";
-}
-.glyphicon-ban-circle:before {
- content: "\e090";
-}
-.glyphicon-arrow-left:before {
- content: "\e091";
-}
-.glyphicon-arrow-right:before {
- content: "\e092";
-}
-.glyphicon-arrow-up:before {
- content: "\e093";
-}
-.glyphicon-arrow-down:before {
- content: "\e094";
-}
-.glyphicon-share-alt:before {
- content: "\e095";
-}
-.glyphicon-resize-full:before {
- content: "\e096";
-}
-.glyphicon-resize-small:before {
- content: "\e097";
-}
-.glyphicon-exclamation-sign:before {
- content: "\e101";
-}
-.glyphicon-gift:before {
- content: "\e102";
-}
-.glyphicon-leaf:before {
- content: "\e103";
-}
-.glyphicon-fire:before {
- content: "\e104";
-}
-.glyphicon-eye-open:before {
- content: "\e105";
-}
-.glyphicon-eye-close:before {
- content: "\e106";
-}
-.glyphicon-warning-sign:before {
- content: "\e107";
-}
-.glyphicon-plane:before {
- content: "\e108";
-}
-.glyphicon-calendar:before {
- content: "\e109";
-}
-.glyphicon-random:before {
- content: "\e110";
-}
-.glyphicon-comment:before {
- content: "\e111";
-}
-.glyphicon-magnet:before {
- content: "\e112";
-}
-.glyphicon-chevron-up:before {
- content: "\e113";
-}
-.glyphicon-chevron-down:before {
- content: "\e114";
-}
-.glyphicon-retweet:before {
- content: "\e115";
-}
-.glyphicon-shopping-cart:before {
- content: "\e116";
-}
-.glyphicon-folder-close:before {
- content: "\e117";
-}
-.glyphicon-folder-open:before {
- content: "\e118";
-}
-.glyphicon-resize-vertical:before {
- content: "\e119";
-}
-.glyphicon-resize-horizontal:before {
- content: "\e120";
-}
-.glyphicon-hdd:before {
- content: "\e121";
-}
-.glyphicon-bullhorn:before {
- content: "\e122";
-}
-.glyphicon-bell:before {
- content: "\e123";
-}
-.glyphicon-certificate:before {
- content: "\e124";
-}
-.glyphicon-thumbs-up:before {
- content: "\e125";
-}
-.glyphicon-thumbs-down:before {
- content: "\e126";
-}
-.glyphicon-hand-right:before {
- content: "\e127";
-}
-.glyphicon-hand-left:before {
- content: "\e128";
-}
-.glyphicon-hand-up:before {
- content: "\e129";
-}
-.glyphicon-hand-down:before {
- content: "\e130";
-}
-.glyphicon-circle-arrow-right:before {
- content: "\e131";
-}
-.glyphicon-circle-arrow-left:before {
- content: "\e132";
-}
-.glyphicon-circle-arrow-up:before {
- content: "\e133";
-}
-.glyphicon-circle-arrow-down:before {
- content: "\e134";
-}
-.glyphicon-globe:before {
- content: "\e135";
-}
-.glyphicon-wrench:before {
- content: "\e136";
-}
-.glyphicon-tasks:before {
- content: "\e137";
-}
-.glyphicon-filter:before {
- content: "\e138";
-}
-.glyphicon-briefcase:before {
- content: "\e139";
-}
-.glyphicon-fullscreen:before {
- content: "\e140";
-}
-.glyphicon-dashboard:before {
- content: "\e141";
-}
-.glyphicon-paperclip:before {
- content: "\e142";
-}
-.glyphicon-heart-empty:before {
- content: "\e143";
-}
-.glyphicon-link:before {
- content: "\e144";
-}
-.glyphicon-phone:before {
- content: "\e145";
-}
-.glyphicon-pushpin:before {
- content: "\e146";
-}
-.glyphicon-usd:before {
- content: "\e148";
-}
-.glyphicon-gbp:before {
- content: "\e149";
-}
-.glyphicon-sort:before {
- content: "\e150";
-}
-.glyphicon-sort-by-alphabet:before {
- content: "\e151";
-}
-.glyphicon-sort-by-alphabet-alt:before {
- content: "\e152";
-}
-.glyphicon-sort-by-order:before {
- content: "\e153";
-}
-.glyphicon-sort-by-order-alt:before {
- content: "\e154";
-}
-.glyphicon-sort-by-attributes:before {
- content: "\e155";
-}
-.glyphicon-sort-by-attributes-alt:before {
- content: "\e156";
-}
-.glyphicon-unchecked:before {
- content: "\e157";
-}
-.glyphicon-expand:before {
- content: "\e158";
-}
-.glyphicon-collapse-down:before {
- content: "\e159";
-}
-.glyphicon-collapse-up:before {
- content: "\e160";
-}
-.glyphicon-log-in:before {
- content: "\e161";
-}
-.glyphicon-flash:before {
- content: "\e162";
-}
-.glyphicon-log-out:before {
- content: "\e163";
-}
-.glyphicon-new-window:before {
- content: "\e164";
-}
-.glyphicon-record:before {
- content: "\e165";
-}
-.glyphicon-save:before {
- content: "\e166";
-}
-.glyphicon-open:before {
- content: "\e167";
-}
-.glyphicon-saved:before {
- content: "\e168";
-}
-.glyphicon-import:before {
- content: "\e169";
-}
-.glyphicon-export:before {
- content: "\e170";
-}
-.glyphicon-send:before {
- content: "\e171";
-}
-.glyphicon-floppy-disk:before {
- content: "\e172";
-}
-.glyphicon-floppy-saved:before {
- content: "\e173";
-}
-.glyphicon-floppy-remove:before {
- content: "\e174";
-}
-.glyphicon-floppy-save:before {
- content: "\e175";
-}
-.glyphicon-floppy-open:before {
- content: "\e176";
-}
-.glyphicon-credit-card:before {
- content: "\e177";
-}
-.glyphicon-transfer:before {
- content: "\e178";
-}
-.glyphicon-cutlery:before {
- content: "\e179";
-}
-.glyphicon-header:before {
- content: "\e180";
-}
-.glyphicon-compressed:before {
- content: "\e181";
-}
-.glyphicon-earphone:before {
- content: "\e182";
-}
-.glyphicon-phone-alt:before {
- content: "\e183";
-}
-.glyphicon-tower:before {
- content: "\e184";
-}
-.glyphicon-stats:before {
- content: "\e185";
-}
-.glyphicon-sd-video:before {
- content: "\e186";
-}
-.glyphicon-hd-video:before {
- content: "\e187";
-}
-.glyphicon-subtitles:before {
- content: "\e188";
-}
-.glyphicon-sound-stereo:before {
- content: "\e189";
-}
-.glyphicon-sound-dolby:before {
- content: "\e190";
-}
-.glyphicon-sound-5-1:before {
- content: "\e191";
-}
-.glyphicon-sound-6-1:before {
- content: "\e192";
-}
-.glyphicon-sound-7-1:before {
- content: "\e193";
-}
-.glyphicon-copyright-mark:before {
- content: "\e194";
-}
-.glyphicon-registration-mark:before {
- content: "\e195";
-}
-.glyphicon-cloud-download:before {
- content: "\e197";
-}
-.glyphicon-cloud-upload:before {
- content: "\e198";
-}
-.glyphicon-tree-conifer:before {
- content: "\e199";
-}
-.glyphicon-tree-deciduous:before {
- content: "\e200";
-}
-.glyphicon-cd:before {
- content: "\e201";
-}
-.glyphicon-save-file:before {
- content: "\e202";
-}
-.glyphicon-open-file:before {
- content: "\e203";
-}
-.glyphicon-level-up:before {
- content: "\e204";
-}
-.glyphicon-copy:before {
- content: "\e205";
-}
-.glyphicon-paste:before {
- content: "\e206";
-}
-.glyphicon-alert:before {
- content: "\e209";
-}
-.glyphicon-equalizer:before {
- content: "\e210";
-}
-.glyphicon-king:before {
- content: "\e211";
-}
-.glyphicon-queen:before {
- content: "\e212";
-}
-.glyphicon-pawn:before {
- content: "\e213";
-}
-.glyphicon-bishop:before {
- content: "\e214";
-}
-.glyphicon-knight:before {
- content: "\e215";
-}
-.glyphicon-baby-formula:before {
- content: "\e216";
-}
-.glyphicon-tent:before {
- content: "\26fa";
-}
-.glyphicon-blackboard:before {
- content: "\e218";
-}
-.glyphicon-bed:before {
- content: "\e219";
-}
-.glyphicon-apple:before {
- content: "\f8ff";
-}
-.glyphicon-erase:before {
- content: "\e221";
-}
-.glyphicon-hourglass:before {
- content: "\231b";
-}
-.glyphicon-lamp:before {
- content: "\e223";
-}
-.glyphicon-duplicate:before {
- content: "\e224";
-}
-.glyphicon-piggy-bank:before {
- content: "\e225";
-}
-.glyphicon-scissors:before {
- content: "\e226";
-}
-.glyphicon-bitcoin:before {
- content: "\e227";
-}
-.glyphicon-btc:before {
- content: "\e227";
-}
-.glyphicon-xbt:before {
- content: "\e227";
-}
-.glyphicon-yen:before {
- content: "\00a5";
-}
-.glyphicon-jpy:before {
- content: "\00a5";
-}
-.glyphicon-ruble:before {
- content: "\20bd";
-}
-.glyphicon-rub:before {
- content: "\20bd";
-}
-.glyphicon-scale:before {
- content: "\e230";
-}
-.glyphicon-ice-lolly:before {
- content: "\e231";
-}
-.glyphicon-ice-lolly-tasted:before {
- content: "\e232";
-}
-.glyphicon-education:before {
- content: "\e233";
-}
-.glyphicon-option-horizontal:before {
- content: "\e234";
-}
-.glyphicon-option-vertical:before {
- content: "\e235";
-}
-.glyphicon-menu-hamburger:before {
- content: "\e236";
-}
-.glyphicon-modal-window:before {
- content: "\e237";
-}
-.glyphicon-oil:before {
- content: "\e238";
-}
-.glyphicon-grain:before {
- content: "\e239";
-}
-.glyphicon-sunglasses:before {
- content: "\e240";
-}
-.glyphicon-text-size:before {
- content: "\e241";
-}
-.glyphicon-text-color:before {
- content: "\e242";
-}
-.glyphicon-text-background:before {
- content: "\e243";
-}
-.glyphicon-object-align-top:before {
- content: "\e244";
-}
-.glyphicon-object-align-bottom:before {
- content: "\e245";
-}
-.glyphicon-object-align-horizontal:before {
- content: "\e246";
-}
-.glyphicon-object-align-left:before {
- content: "\e247";
-}
-.glyphicon-object-align-vertical:before {
- content: "\e248";
-}
-.glyphicon-object-align-right:before {
- content: "\e249";
-}
-.glyphicon-triangle-right:before {
- content: "\e250";
-}
-.glyphicon-triangle-left:before {
- content: "\e251";
-}
-.glyphicon-triangle-bottom:before {
- content: "\e252";
-}
-.glyphicon-triangle-top:before {
- content: "\e253";
-}
-.glyphicon-console:before {
- content: "\e254";
-}
-.glyphicon-superscript:before {
- content: "\e255";
-}
-.glyphicon-subscript:before {
- content: "\e256";
-}
-.glyphicon-menu-left:before {
- content: "\e257";
-}
-.glyphicon-menu-right:before {
- content: "\e258";
-}
-.glyphicon-menu-down:before {
- content: "\e259";
-}
-.glyphicon-menu-up:before {
- content: "\e260";
-}
-* {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-*:before,
-*:after {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-html {
- font-size: 10px;
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-}
-body {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 14px;
- line-height: 1.42857143;
- color: #c8c8c8;
- background-color: #272b30;
-}
-input,
-button,
-select,
-textarea {
- font-family: inherit;
- font-size: inherit;
- line-height: inherit;
-}
-a {
- color: #ffffff;
- text-decoration: none;
-}
-a:hover,
-a:focus {
- color: #ffffff;
- text-decoration: underline;
-}
-a:focus {
- outline: thin dotted;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-figure {
- margin: 0;
-}
-img {
- vertical-align: middle;
-}
-.img-responsive,
-.thumbnail > img,
-.thumbnail a > img,
-.carousel-inner > .item > img,
-.carousel-inner > .item > a > img {
- display: block;
- max-width: 100%;
- height: auto;
-}
-.img-rounded {
- border-radius: 6px;
-}
-.img-thumbnail {
- padding: 4px;
- line-height: 1.42857143;
- background-color: #1c1e22;
- border: 1px solid #0c0d0e;
- border-radius: 4px;
- -webkit-transition: all 0.2s ease-in-out;
- -o-transition: all 0.2s ease-in-out;
- transition: all 0.2s ease-in-out;
- display: inline-block;
- max-width: 100%;
- height: auto;
-}
-.img-circle {
- border-radius: 50%;
-}
-hr {
- margin-top: 20px;
- margin-bottom: 20px;
- border: 0;
- border-top: 1px solid #1c1e22;
-}
-.sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- margin: -1px;
- padding: 0;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- border: 0;
-}
-.sr-only-focusable:active,
-.sr-only-focusable:focus {
- position: static;
- width: auto;
- height: auto;
- margin: 0;
- overflow: visible;
- clip: auto;
-}
-[role="button"] {
- cursor: pointer;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-.h1,
-.h2,
-.h3,
-.h4,
-.h5,
-.h6 {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-weight: 500;
- line-height: 1.1;
- color: inherit;
-}
-h1 small,
-h2 small,
-h3 small,
-h4 small,
-h5 small,
-h6 small,
-.h1 small,
-.h2 small,
-.h3 small,
-.h4 small,
-.h5 small,
-.h6 small,
-h1 .small,
-h2 .small,
-h3 .small,
-h4 .small,
-h5 .small,
-h6 .small,
-.h1 .small,
-.h2 .small,
-.h3 .small,
-.h4 .small,
-.h5 .small,
-.h6 .small {
- font-weight: normal;
- line-height: 1;
- color: #7a8288;
-}
-h1,
-.h1,
-h2,
-.h2,
-h3,
-.h3 {
- margin-top: 20px;
- margin-bottom: 10px;
-}
-h1 small,
-.h1 small,
-h2 small,
-.h2 small,
-h3 small,
-.h3 small,
-h1 .small,
-.h1 .small,
-h2 .small,
-.h2 .small,
-h3 .small,
-.h3 .small {
- font-size: 65%;
-}
-h4,
-.h4,
-h5,
-.h5,
-h6,
-.h6 {
- margin-top: 10px;
- margin-bottom: 10px;
-}
-h4 small,
-.h4 small,
-h5 small,
-.h5 small,
-h6 small,
-.h6 small,
-h4 .small,
-.h4 .small,
-h5 .small,
-.h5 .small,
-h6 .small,
-.h6 .small {
- font-size: 75%;
-}
-h1,
-.h1 {
- font-size: 36px;
-}
-h2,
-.h2 {
- font-size: 30px;
-}
-h3,
-.h3 {
- font-size: 24px;
-}
-h4,
-.h4 {
- font-size: 18px;
-}
-h5,
-.h5 {
- font-size: 14px;
-}
-h6,
-.h6 {
- font-size: 12px;
-}
-p {
- margin: 0 0 10px;
-}
-.lead {
- margin-bottom: 20px;
- font-size: 16px;
- font-weight: 300;
- line-height: 1.4;
-}
-@media (min-width: 768px) {
- .lead {
- font-size: 21px;
- }
-}
-small,
-.small {
- font-size: 85%;
-}
-mark,
-.mark {
- background-color: #f89406;
- padding: .2em;
-}
-.text-left {
- text-align: left;
-}
-.text-right {
- text-align: right;
-}
-.text-center {
- text-align: center;
-}
-.text-justify {
- text-align: justify;
-}
-.text-nowrap {
- white-space: nowrap;
-}
-.text-lowercase {
- text-transform: lowercase;
-}
-.text-uppercase {
- text-transform: uppercase;
-}
-.text-capitalize {
- text-transform: capitalize;
-}
-.text-muted {
- color: #7a8288;
-}
-.text-primary {
- color: #7a8288;
-}
-a.text-primary:hover,
-a.text-primary:focus {
- color: #62686d;
-}
-.text-success {
- color: #ffffff;
-}
-a.text-success:hover,
-a.text-success:focus {
- color: #e6e6e6;
-}
-.text-info {
- color: #ffffff;
-}
-a.text-info:hover,
-a.text-info:focus {
- color: #e6e6e6;
-}
-.text-warning {
- color: #ffffff;
-}
-a.text-warning:hover,
-a.text-warning:focus {
- color: #e6e6e6;
-}
-.text-danger {
- color: #ffffff;
-}
-a.text-danger:hover,
-a.text-danger:focus {
- color: #e6e6e6;
-}
-.bg-primary {
- color: #fff;
- background-color: #7a8288;
-}
-a.bg-primary:hover,
-a.bg-primary:focus {
- background-color: #62686d;
-}
-.bg-success {
- background-color: #62c462;
-}
-a.bg-success:hover,
-a.bg-success:focus {
- background-color: #42b142;
-}
-.bg-info {
- background-color: #5bc0de;
-}
-a.bg-info:hover,
-a.bg-info:focus {
- background-color: #31b0d5;
-}
-.bg-warning {
- background-color: #f89406;
-}
-a.bg-warning:hover,
-a.bg-warning:focus {
- background-color: #c67605;
-}
-.bg-danger {
- background-color: #ee5f5b;
-}
-a.bg-danger:hover,
-a.bg-danger:focus {
- background-color: #e9322d;
-}
-.page-header {
- padding-bottom: 9px;
- margin: 40px 0 20px;
- border-bottom: 1px solid #1c1e22;
-}
-ul,
-ol {
- margin-top: 0;
- margin-bottom: 10px;
-}
-ul ul,
-ol ul,
-ul ol,
-ol ol {
- margin-bottom: 0;
-}
-.list-unstyled {
- padding-left: 0;
- list-style: none;
-}
-.list-inline {
- padding-left: 0;
- list-style: none;
- margin-left: -5px;
-}
-.list-inline > li {
- display: inline-block;
- padding-left: 5px;
- padding-right: 5px;
-}
-dl {
- margin-top: 0;
- margin-bottom: 20px;
-}
-dt,
-dd {
- line-height: 1.42857143;
-}
-dt {
- font-weight: bold;
-}
-dd {
- margin-left: 0;
-}
-@media (min-width: 768px) {
- .dl-horizontal dt {
- float: left;
- width: 160px;
- clear: left;
- text-align: right;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .dl-horizontal dd {
- margin-left: 180px;
- }
-}
-abbr[title],
-abbr[data-original-title] {
- cursor: help;
- border-bottom: 1px dotted #7a8288;
-}
-.initialism {
- font-size: 90%;
- text-transform: uppercase;
-}
-blockquote {
- padding: 10px 20px;
- margin: 0 0 20px;
- font-size: 17.5px;
- border-left: 5px solid #7a8288;
-}
-blockquote p:last-child,
-blockquote ul:last-child,
-blockquote ol:last-child {
- margin-bottom: 0;
-}
-blockquote footer,
-blockquote small,
-blockquote .small {
- display: block;
- font-size: 80%;
- line-height: 1.42857143;
- color: #7a8288;
-}
-blockquote footer:before,
-blockquote small:before,
-blockquote .small:before {
- content: '\2014 \00A0';
-}
-.blockquote-reverse,
-blockquote.pull-right {
- padding-right: 15px;
- padding-left: 0;
- border-right: 5px solid #7a8288;
- border-left: 0;
- text-align: right;
-}
-.blockquote-reverse footer:before,
-blockquote.pull-right footer:before,
-.blockquote-reverse small:before,
-blockquote.pull-right small:before,
-.blockquote-reverse .small:before,
-blockquote.pull-right .small:before {
- content: '';
-}
-.blockquote-reverse footer:after,
-blockquote.pull-right footer:after,
-.blockquote-reverse small:after,
-blockquote.pull-right small:after,
-.blockquote-reverse .small:after,
-blockquote.pull-right .small:after {
- content: '\00A0 \2014';
-}
-address {
- margin-bottom: 20px;
- font-style: normal;
- line-height: 1.42857143;
-}
-code,
-kbd,
-pre,
-samp {
- font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
-}
-code {
- padding: 2px 4px;
- font-size: 90%;
- color: #c7254e;
- background-color: #f9f2f4;
- border-radius: 4px;
-}
-kbd {
- padding: 2px 4px;
- font-size: 90%;
- color: #ffffff;
- background-color: #333333;
- border-radius: 3px;
- -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
- box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
-}
-kbd kbd {
- padding: 0;
- font-size: 100%;
- font-weight: bold;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-pre {
- display: block;
- padding: 9.5px;
- margin: 0 0 10px;
- font-size: 13px;
- line-height: 1.42857143;
- word-break: break-all;
- word-wrap: break-word;
- color: #3a3f44;
- background-color: #f5f5f5;
- border: 1px solid #cccccc;
- border-radius: 4px;
-}
-pre code {
- padding: 0;
- font-size: inherit;
- color: inherit;
- white-space: pre-wrap;
- background-color: transparent;
- border-radius: 0;
-}
-.pre-scrollable {
- max-height: 340px;
- overflow-y: scroll;
-}
-.container {
- margin-right: auto;
- margin-left: auto;
- padding-left: 15px;
- padding-right: 15px;
-}
-@media (min-width: 768px) {
- .container {
- width: 750px;
- }
-}
-@media (min-width: 992px) {
- .container {
- width: 970px;
- }
-}
-@media (min-width: 1200px) {
- .container {
- width: 1170px;
- }
-}
-.container-fluid {
- margin-right: auto;
- margin-left: auto;
- padding-left: 15px;
- padding-right: 15px;
-}
-.row {
- margin-left: -15px;
- margin-right: -15px;
-}
-.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
- position: relative;
- min-height: 1px;
- padding-left: 15px;
- padding-right: 15px;
-}
-.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
- float: left;
-}
-.col-xs-12 {
- width: 100%;
-}
-.col-xs-11 {
- width: 91.66666667%;
-}
-.col-xs-10 {
- width: 83.33333333%;
-}
-.col-xs-9 {
- width: 75%;
-}
-.col-xs-8 {
- width: 66.66666667%;
-}
-.col-xs-7 {
- width: 58.33333333%;
-}
-.col-xs-6 {
- width: 50%;
-}
-.col-xs-5 {
- width: 41.66666667%;
-}
-.col-xs-4 {
- width: 33.33333333%;
-}
-.col-xs-3 {
- width: 25%;
-}
-.col-xs-2 {
- width: 16.66666667%;
-}
-.col-xs-1 {
- width: 8.33333333%;
-}
-.col-xs-pull-12 {
- right: 100%;
-}
-.col-xs-pull-11 {
- right: 91.66666667%;
-}
-.col-xs-pull-10 {
- right: 83.33333333%;
-}
-.col-xs-pull-9 {
- right: 75%;
-}
-.col-xs-pull-8 {
- right: 66.66666667%;
-}
-.col-xs-pull-7 {
- right: 58.33333333%;
-}
-.col-xs-pull-6 {
- right: 50%;
-}
-.col-xs-pull-5 {
- right: 41.66666667%;
-}
-.col-xs-pull-4 {
- right: 33.33333333%;
-}
-.col-xs-pull-3 {
- right: 25%;
-}
-.col-xs-pull-2 {
- right: 16.66666667%;
-}
-.col-xs-pull-1 {
- right: 8.33333333%;
-}
-.col-xs-pull-0 {
- right: auto;
-}
-.col-xs-push-12 {
- left: 100%;
-}
-.col-xs-push-11 {
- left: 91.66666667%;
-}
-.col-xs-push-10 {
- left: 83.33333333%;
-}
-.col-xs-push-9 {
- left: 75%;
-}
-.col-xs-push-8 {
- left: 66.66666667%;
-}
-.col-xs-push-7 {
- left: 58.33333333%;
-}
-.col-xs-push-6 {
- left: 50%;
-}
-.col-xs-push-5 {
- left: 41.66666667%;
-}
-.col-xs-push-4 {
- left: 33.33333333%;
-}
-.col-xs-push-3 {
- left: 25%;
-}
-.col-xs-push-2 {
- left: 16.66666667%;
-}
-.col-xs-push-1 {
- left: 8.33333333%;
-}
-.col-xs-push-0 {
- left: auto;
-}
-.col-xs-offset-12 {
- margin-left: 100%;
-}
-.col-xs-offset-11 {
- margin-left: 91.66666667%;
-}
-.col-xs-offset-10 {
- margin-left: 83.33333333%;
-}
-.col-xs-offset-9 {
- margin-left: 75%;
-}
-.col-xs-offset-8 {
- margin-left: 66.66666667%;
-}
-.col-xs-offset-7 {
- margin-left: 58.33333333%;
-}
-.col-xs-offset-6 {
- margin-left: 50%;
-}
-.col-xs-offset-5 {
- margin-left: 41.66666667%;
-}
-.col-xs-offset-4 {
- margin-left: 33.33333333%;
-}
-.col-xs-offset-3 {
- margin-left: 25%;
-}
-.col-xs-offset-2 {
- margin-left: 16.66666667%;
-}
-.col-xs-offset-1 {
- margin-left: 8.33333333%;
-}
-.col-xs-offset-0 {
- margin-left: 0%;
-}
-@media (min-width: 768px) {
- .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
- float: left;
- }
- .col-sm-12 {
- width: 100%;
- }
- .col-sm-11 {
- width: 91.66666667%;
- }
- .col-sm-10 {
- width: 83.33333333%;
- }
- .col-sm-9 {
- width: 75%;
- }
- .col-sm-8 {
- width: 66.66666667%;
- }
- .col-sm-7 {
- width: 58.33333333%;
- }
- .col-sm-6 {
- width: 50%;
- }
- .col-sm-5 {
- width: 41.66666667%;
- }
- .col-sm-4 {
- width: 33.33333333%;
- }
- .col-sm-3 {
- width: 25%;
- }
- .col-sm-2 {
- width: 16.66666667%;
- }
- .col-sm-1 {
- width: 8.33333333%;
- }
- .col-sm-pull-12 {
- right: 100%;
- }
- .col-sm-pull-11 {
- right: 91.66666667%;
- }
- .col-sm-pull-10 {
- right: 83.33333333%;
- }
- .col-sm-pull-9 {
- right: 75%;
- }
- .col-sm-pull-8 {
- right: 66.66666667%;
- }
- .col-sm-pull-7 {
- right: 58.33333333%;
- }
- .col-sm-pull-6 {
- right: 50%;
- }
- .col-sm-pull-5 {
- right: 41.66666667%;
- }
- .col-sm-pull-4 {
- right: 33.33333333%;
- }
- .col-sm-pull-3 {
- right: 25%;
- }
- .col-sm-pull-2 {
- right: 16.66666667%;
- }
- .col-sm-pull-1 {
- right: 8.33333333%;
- }
- .col-sm-pull-0 {
- right: auto;
- }
- .col-sm-push-12 {
- left: 100%;
- }
- .col-sm-push-11 {
- left: 91.66666667%;
- }
- .col-sm-push-10 {
- left: 83.33333333%;
- }
- .col-sm-push-9 {
- left: 75%;
- }
- .col-sm-push-8 {
- left: 66.66666667%;
- }
- .col-sm-push-7 {
- left: 58.33333333%;
- }
- .col-sm-push-6 {
- left: 50%;
- }
- .col-sm-push-5 {
- left: 41.66666667%;
- }
- .col-sm-push-4 {
- left: 33.33333333%;
- }
- .col-sm-push-3 {
- left: 25%;
- }
- .col-sm-push-2 {
- left: 16.66666667%;
- }
- .col-sm-push-1 {
- left: 8.33333333%;
- }
- .col-sm-push-0 {
- left: auto;
- }
- .col-sm-offset-12 {
- margin-left: 100%;
- }
- .col-sm-offset-11 {
- margin-left: 91.66666667%;
- }
- .col-sm-offset-10 {
- margin-left: 83.33333333%;
- }
- .col-sm-offset-9 {
- margin-left: 75%;
- }
- .col-sm-offset-8 {
- margin-left: 66.66666667%;
- }
- .col-sm-offset-7 {
- margin-left: 58.33333333%;
- }
- .col-sm-offset-6 {
- margin-left: 50%;
- }
- .col-sm-offset-5 {
- margin-left: 41.66666667%;
- }
- .col-sm-offset-4 {
- margin-left: 33.33333333%;
- }
- .col-sm-offset-3 {
- margin-left: 25%;
- }
- .col-sm-offset-2 {
- margin-left: 16.66666667%;
- }
- .col-sm-offset-1 {
- margin-left: 8.33333333%;
- }
- .col-sm-offset-0 {
- margin-left: 0%;
- }
-}
-@media (min-width: 992px) {
- .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
- float: left;
- }
- .col-md-12 {
- width: 100%;
- }
- .col-md-11 {
- width: 91.66666667%;
- }
- .col-md-10 {
- width: 83.33333333%;
- }
- .col-md-9 {
- width: 75%;
- }
- .col-md-8 {
- width: 66.66666667%;
- }
- .col-md-7 {
- width: 58.33333333%;
- }
- .col-md-6 {
- width: 50%;
- }
- .col-md-5 {
- width: 41.66666667%;
- }
- .col-md-4 {
- width: 33.33333333%;
- }
- .col-md-3 {
- width: 25%;
- }
- .col-md-2 {
- width: 16.66666667%;
- }
- .col-md-1 {
- width: 8.33333333%;
- }
- .col-md-pull-12 {
- right: 100%;
- }
- .col-md-pull-11 {
- right: 91.66666667%;
- }
- .col-md-pull-10 {
- right: 83.33333333%;
- }
- .col-md-pull-9 {
- right: 75%;
- }
- .col-md-pull-8 {
- right: 66.66666667%;
- }
- .col-md-pull-7 {
- right: 58.33333333%;
- }
- .col-md-pull-6 {
- right: 50%;
- }
- .col-md-pull-5 {
- right: 41.66666667%;
- }
- .col-md-pull-4 {
- right: 33.33333333%;
- }
- .col-md-pull-3 {
- right: 25%;
- }
- .col-md-pull-2 {
- right: 16.66666667%;
- }
- .col-md-pull-1 {
- right: 8.33333333%;
- }
- .col-md-pull-0 {
- right: auto;
- }
- .col-md-push-12 {
- left: 100%;
- }
- .col-md-push-11 {
- left: 91.66666667%;
- }
- .col-md-push-10 {
- left: 83.33333333%;
- }
- .col-md-push-9 {
- left: 75%;
- }
- .col-md-push-8 {
- left: 66.66666667%;
- }
- .col-md-push-7 {
- left: 58.33333333%;
- }
- .col-md-push-6 {
- left: 50%;
- }
- .col-md-push-5 {
- left: 41.66666667%;
- }
- .col-md-push-4 {
- left: 33.33333333%;
- }
- .col-md-push-3 {
- left: 25%;
- }
- .col-md-push-2 {
- left: 16.66666667%;
- }
- .col-md-push-1 {
- left: 8.33333333%;
- }
- .col-md-push-0 {
- left: auto;
- }
- .col-md-offset-12 {
- margin-left: 100%;
- }
- .col-md-offset-11 {
- margin-left: 91.66666667%;
- }
- .col-md-offset-10 {
- margin-left: 83.33333333%;
- }
- .col-md-offset-9 {
- margin-left: 75%;
- }
- .col-md-offset-8 {
- margin-left: 66.66666667%;
- }
- .col-md-offset-7 {
- margin-left: 58.33333333%;
- }
- .col-md-offset-6 {
- margin-left: 50%;
- }
- .col-md-offset-5 {
- margin-left: 41.66666667%;
- }
- .col-md-offset-4 {
- margin-left: 33.33333333%;
- }
- .col-md-offset-3 {
- margin-left: 25%;
- }
- .col-md-offset-2 {
- margin-left: 16.66666667%;
- }
- .col-md-offset-1 {
- margin-left: 8.33333333%;
- }
- .col-md-offset-0 {
- margin-left: 0%;
- }
-}
-@media (min-width: 1200px) {
- .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
- float: left;
- }
- .col-lg-12 {
- width: 100%;
- }
- .col-lg-11 {
- width: 91.66666667%;
- }
- .col-lg-10 {
- width: 83.33333333%;
- }
- .col-lg-9 {
- width: 75%;
- }
- .col-lg-8 {
- width: 66.66666667%;
- }
- .col-lg-7 {
- width: 58.33333333%;
- }
- .col-lg-6 {
- width: 50%;
- }
- .col-lg-5 {
- width: 41.66666667%;
- }
- .col-lg-4 {
- width: 33.33333333%;
- }
- .col-lg-3 {
- width: 25%;
- }
- .col-lg-2 {
- width: 16.66666667%;
- }
- .col-lg-1 {
- width: 8.33333333%;
- }
- .col-lg-pull-12 {
- right: 100%;
- }
- .col-lg-pull-11 {
- right: 91.66666667%;
- }
- .col-lg-pull-10 {
- right: 83.33333333%;
- }
- .col-lg-pull-9 {
- right: 75%;
- }
- .col-lg-pull-8 {
- right: 66.66666667%;
- }
- .col-lg-pull-7 {
- right: 58.33333333%;
- }
- .col-lg-pull-6 {
- right: 50%;
- }
- .col-lg-pull-5 {
- right: 41.66666667%;
- }
- .col-lg-pull-4 {
- right: 33.33333333%;
- }
- .col-lg-pull-3 {
- right: 25%;
- }
- .col-lg-pull-2 {
- right: 16.66666667%;
- }
- .col-lg-pull-1 {
- right: 8.33333333%;
- }
- .col-lg-pull-0 {
- right: auto;
- }
- .col-lg-push-12 {
- left: 100%;
- }
- .col-lg-push-11 {
- left: 91.66666667%;
- }
- .col-lg-push-10 {
- left: 83.33333333%;
- }
- .col-lg-push-9 {
- left: 75%;
- }
- .col-lg-push-8 {
- left: 66.66666667%;
- }
- .col-lg-push-7 {
- left: 58.33333333%;
- }
- .col-lg-push-6 {
- left: 50%;
- }
- .col-lg-push-5 {
- left: 41.66666667%;
- }
- .col-lg-push-4 {
- left: 33.33333333%;
- }
- .col-lg-push-3 {
- left: 25%;
- }
- .col-lg-push-2 {
- left: 16.66666667%;
- }
- .col-lg-push-1 {
- left: 8.33333333%;
- }
- .col-lg-push-0 {
- left: auto;
- }
- .col-lg-offset-12 {
- margin-left: 100%;
- }
- .col-lg-offset-11 {
- margin-left: 91.66666667%;
- }
- .col-lg-offset-10 {
- margin-left: 83.33333333%;
- }
- .col-lg-offset-9 {
- margin-left: 75%;
- }
- .col-lg-offset-8 {
- margin-left: 66.66666667%;
- }
- .col-lg-offset-7 {
- margin-left: 58.33333333%;
- }
- .col-lg-offset-6 {
- margin-left: 50%;
- }
- .col-lg-offset-5 {
- margin-left: 41.66666667%;
- }
- .col-lg-offset-4 {
- margin-left: 33.33333333%;
- }
- .col-lg-offset-3 {
- margin-left: 25%;
- }
- .col-lg-offset-2 {
- margin-left: 16.66666667%;
- }
- .col-lg-offset-1 {
- margin-left: 8.33333333%;
- }
- .col-lg-offset-0 {
- margin-left: 0%;
- }
-}
-table {
- background-color: #2e3338;
-}
-caption {
- padding-top: 8px;
- padding-bottom: 8px;
- color: #7a8288;
- text-align: left;
-}
-th {
- text-align: left;
-}
-.table {
- width: 100%;
- max-width: 100%;
- margin-bottom: 20px;
-}
-.table > thead > tr > th,
-.table > tbody > tr > th,
-.table > tfoot > tr > th,
-.table > thead > tr > td,
-.table > tbody > tr > td,
-.table > tfoot > tr > td {
- padding: 8px;
- line-height: 1.42857143;
- vertical-align: top;
- border-top: 1px solid #1c1e22;
-}
-.table > thead > tr > th {
- vertical-align: bottom;
- border-bottom: 2px solid #1c1e22;
-}
-.table > caption + thead > tr:first-child > th,
-.table > colgroup + thead > tr:first-child > th,
-.table > thead:first-child > tr:first-child > th,
-.table > caption + thead > tr:first-child > td,
-.table > colgroup + thead > tr:first-child > td,
-.table > thead:first-child > tr:first-child > td {
- border-top: 0;
-}
-.table > tbody + tbody {
- border-top: 2px solid #1c1e22;
-}
-.table .table {
- background-color: #272b30;
-}
-.table-condensed > thead > tr > th,
-.table-condensed > tbody > tr > th,
-.table-condensed > tfoot > tr > th,
-.table-condensed > thead > tr > td,
-.table-condensed > tbody > tr > td,
-.table-condensed > tfoot > tr > td {
- padding: 5px;
-}
-.table-bordered {
- border: 1px solid #1c1e22;
-}
-.table-bordered > thead > tr > th,
-.table-bordered > tbody > tr > th,
-.table-bordered > tfoot > tr > th,
-.table-bordered > thead > tr > td,
-.table-bordered > tbody > tr > td,
-.table-bordered > tfoot > tr > td {
- border: 1px solid #1c1e22;
-}
-.table-bordered > thead > tr > th,
-.table-bordered > thead > tr > td {
- border-bottom-width: 2px;
-}
-.table-striped > tbody > tr:nth-of-type(odd) {
- background-color: #353a41;
-}
-.table-hover > tbody > tr:hover {
- background-color: #49515a;
-}
-table col[class*="col-"] {
- position: static;
- float: none;
- display: table-column;
-}
-table td[class*="col-"],
-table th[class*="col-"] {
- position: static;
- float: none;
- display: table-cell;
-}
-.table > thead > tr > td.active,
-.table > tbody > tr > td.active,
-.table > tfoot > tr > td.active,
-.table > thead > tr > th.active,
-.table > tbody > tr > th.active,
-.table > tfoot > tr > th.active,
-.table > thead > tr.active > td,
-.table > tbody > tr.active > td,
-.table > tfoot > tr.active > td,
-.table > thead > tr.active > th,
-.table > tbody > tr.active > th,
-.table > tfoot > tr.active > th {
- background-color: #49515a;
-}
-.table-hover > tbody > tr > td.active:hover,
-.table-hover > tbody > tr > th.active:hover,
-.table-hover > tbody > tr.active:hover > td,
-.table-hover > tbody > tr:hover > .active,
-.table-hover > tbody > tr.active:hover > th {
- background-color: #3e444c;
-}
-.table > thead > tr > td.success,
-.table > tbody > tr > td.success,
-.table > tfoot > tr > td.success,
-.table > thead > tr > th.success,
-.table > tbody > tr > th.success,
-.table > tfoot > tr > th.success,
-.table > thead > tr.success > td,
-.table > tbody > tr.success > td,
-.table > tfoot > tr.success > td,
-.table > thead > tr.success > th,
-.table > tbody > tr.success > th,
-.table > tfoot > tr.success > th {
- background-color: #62c462;
-}
-.table-hover > tbody > tr > td.success:hover,
-.table-hover > tbody > tr > th.success:hover,
-.table-hover > tbody > tr.success:hover > td,
-.table-hover > tbody > tr:hover > .success,
-.table-hover > tbody > tr.success:hover > th {
- background-color: #4fbd4f;
-}
-.table > thead > tr > td.info,
-.table > tbody > tr > td.info,
-.table > tfoot > tr > td.info,
-.table > thead > tr > th.info,
-.table > tbody > tr > th.info,
-.table > tfoot > tr > th.info,
-.table > thead > tr.info > td,
-.table > tbody > tr.info > td,
-.table > tfoot > tr.info > td,
-.table > thead > tr.info > th,
-.table > tbody > tr.info > th,
-.table > tfoot > tr.info > th {
- background-color: #5bc0de;
-}
-.table-hover > tbody > tr > td.info:hover,
-.table-hover > tbody > tr > th.info:hover,
-.table-hover > tbody > tr.info:hover > td,
-.table-hover > tbody > tr:hover > .info,
-.table-hover > tbody > tr.info:hover > th {
- background-color: #46b8da;
-}
-.table > thead > tr > td.warning,
-.table > tbody > tr > td.warning,
-.table > tfoot > tr > td.warning,
-.table > thead > tr > th.warning,
-.table > tbody > tr > th.warning,
-.table > tfoot > tr > th.warning,
-.table > thead > tr.warning > td,
-.table > tbody > tr.warning > td,
-.table > tfoot > tr.warning > td,
-.table > thead > tr.warning > th,
-.table > tbody > tr.warning > th,
-.table > tfoot > tr.warning > th {
- background-color: #f89406;
-}
-.table-hover > tbody > tr > td.warning:hover,
-.table-hover > tbody > tr > th.warning:hover,
-.table-hover > tbody > tr.warning:hover > td,
-.table-hover > tbody > tr:hover > .warning,
-.table-hover > tbody > tr.warning:hover > th {
- background-color: #df8505;
-}
-.table > thead > tr > td.danger,
-.table > tbody > tr > td.danger,
-.table > tfoot > tr > td.danger,
-.table > thead > tr > th.danger,
-.table > tbody > tr > th.danger,
-.table > tfoot > tr > th.danger,
-.table > thead > tr.danger > td,
-.table > tbody > tr.danger > td,
-.table > tfoot > tr.danger > td,
-.table > thead > tr.danger > th,
-.table > tbody > tr.danger > th,
-.table > tfoot > tr.danger > th {
- background-color: #ee5f5b;
-}
-.table-hover > tbody > tr > td.danger:hover,
-.table-hover > tbody > tr > th.danger:hover,
-.table-hover > tbody > tr.danger:hover > td,
-.table-hover > tbody > tr:hover > .danger,
-.table-hover > tbody > tr.danger:hover > th {
- background-color: #ec4844;
-}
-.table-responsive {
- overflow-x: auto;
- min-height: 0.01%;
-}
-@media screen and (max-width: 767px) {
- .table-responsive {
- width: 100%;
- margin-bottom: 15px;
- overflow-y: hidden;
- -ms-overflow-style: -ms-autohiding-scrollbar;
- border: 1px solid #1c1e22;
- }
- .table-responsive > .table {
- margin-bottom: 0;
- }
- .table-responsive > .table > thead > tr > th,
- .table-responsive > .table > tbody > tr > th,
- .table-responsive > .table > tfoot > tr > th,
- .table-responsive > .table > thead > tr > td,
- .table-responsive > .table > tbody > tr > td,
- .table-responsive > .table > tfoot > tr > td {
- white-space: nowrap;
- }
- .table-responsive > .table-bordered {
- border: 0;
- }
- .table-responsive > .table-bordered > thead > tr > th:first-child,
- .table-responsive > .table-bordered > tbody > tr > th:first-child,
- .table-responsive > .table-bordered > tfoot > tr > th:first-child,
- .table-responsive > .table-bordered > thead > tr > td:first-child,
- .table-responsive > .table-bordered > tbody > tr > td:first-child,
- .table-responsive > .table-bordered > tfoot > tr > td:first-child {
- border-left: 0;
- }
- .table-responsive > .table-bordered > thead > tr > th:last-child,
- .table-responsive > .table-bordered > tbody > tr > th:last-child,
- .table-responsive > .table-bordered > tfoot > tr > th:last-child,
- .table-responsive > .table-bordered > thead > tr > td:last-child,
- .table-responsive > .table-bordered > tbody > tr > td:last-child,
- .table-responsive > .table-bordered > tfoot > tr > td:last-child {
- border-right: 0;
- }
- .table-responsive > .table-bordered > tbody > tr:last-child > th,
- .table-responsive > .table-bordered > tfoot > tr:last-child > th,
- .table-responsive > .table-bordered > tbody > tr:last-child > td,
- .table-responsive > .table-bordered > tfoot > tr:last-child > td {
- border-bottom: 0;
- }
-}
-fieldset {
- padding: 0;
- margin: 0;
- border: 0;
- min-width: 0;
-}
-legend {
- display: block;
- width: 100%;
- padding: 0;
- margin-bottom: 20px;
- font-size: 21px;
- line-height: inherit;
- color: #c8c8c8;
- border: 0;
- border-bottom: 1px solid #1c1e22;
-}
-label {
- display: inline-block;
- max-width: 100%;
- margin-bottom: 5px;
- font-weight: bold;
-}
-input[type="search"] {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
-}
-input[type="radio"],
-input[type="checkbox"] {
- margin: 4px 0 0;
- margin-top: 1px \9;
- line-height: normal;
-}
-input[type="file"] {
- display: block;
-}
-input[type="range"] {
- display: block;
- width: 100%;
-}
-select[multiple],
-select[size] {
- height: auto;
-}
-input[type="file"]:focus,
-input[type="radio"]:focus,
-input[type="checkbox"]:focus {
- outline: thin dotted;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-output {
- display: block;
- padding-top: 9px;
- font-size: 14px;
- line-height: 1.42857143;
- color: #272b30;
-}
-.form-control {
- display: block;
- width: 100%;
- height: 38px;
- padding: 8px 12px;
- font-size: 14px;
- line-height: 1.42857143;
- color: #272b30;
- background-color: #ffffff;
- background-image: none;
- border: 1px solid #000000;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
- -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
- transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
-}
-.form-control:focus {
- border-color: #66afe9;
- outline: 0;
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
- box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
-}
-.form-control::-moz-placeholder {
- color: #7a8288;
- opacity: 1;
-}
-.form-control:-ms-input-placeholder {
- color: #7a8288;
-}
-.form-control::-webkit-input-placeholder {
- color: #7a8288;
-}
-.form-control::-ms-expand {
- border: 0;
- background-color: transparent;
-}
-.form-control[disabled],
-.form-control[readonly],
-fieldset[disabled] .form-control {
- background-color: #999999;
- opacity: 1;
-}
-.form-control[disabled],
-fieldset[disabled] .form-control {
- cursor: not-allowed;
-}
-textarea.form-control {
- height: auto;
-}
-input[type="search"] {
- -webkit-appearance: none;
-}
-@media screen and (-webkit-min-device-pixel-ratio: 0) {
- input[type="date"].form-control,
- input[type="time"].form-control,
- input[type="datetime-local"].form-control,
- input[type="month"].form-control {
- line-height: 38px;
- }
- input[type="date"].input-sm,
- input[type="time"].input-sm,
- input[type="datetime-local"].input-sm,
- input[type="month"].input-sm,
- .input-group-sm input[type="date"],
- .input-group-sm input[type="time"],
- .input-group-sm input[type="datetime-local"],
- .input-group-sm input[type="month"] {
- line-height: 30px;
- }
- input[type="date"].input-lg,
- input[type="time"].input-lg,
- input[type="datetime-local"].input-lg,
- input[type="month"].input-lg,
- .input-group-lg input[type="date"],
- .input-group-lg input[type="time"],
- .input-group-lg input[type="datetime-local"],
- .input-group-lg input[type="month"] {
- line-height: 54px;
- }
-}
-.form-group {
- margin-bottom: 15px;
-}
-.radio,
-.checkbox {
- position: relative;
- display: block;
- margin-top: 10px;
- margin-bottom: 10px;
-}
-.radio label,
-.checkbox label {
- min-height: 20px;
- padding-left: 20px;
- margin-bottom: 0;
- font-weight: normal;
- cursor: pointer;
-}
-.radio input[type="radio"],
-.radio-inline input[type="radio"],
-.checkbox input[type="checkbox"],
-.checkbox-inline input[type="checkbox"] {
- position: absolute;
- margin-left: -20px;
- margin-top: 4px \9;
-}
-.radio + .radio,
-.checkbox + .checkbox {
- margin-top: -5px;
-}
-.radio-inline,
-.checkbox-inline {
- position: relative;
- display: inline-block;
- padding-left: 20px;
- margin-bottom: 0;
- vertical-align: middle;
- font-weight: normal;
- cursor: pointer;
-}
-.radio-inline + .radio-inline,
-.checkbox-inline + .checkbox-inline {
- margin-top: 0;
- margin-left: 10px;
-}
-input[type="radio"][disabled],
-input[type="checkbox"][disabled],
-input[type="radio"].disabled,
-input[type="checkbox"].disabled,
-fieldset[disabled] input[type="radio"],
-fieldset[disabled] input[type="checkbox"] {
- cursor: not-allowed;
-}
-.radio-inline.disabled,
-.checkbox-inline.disabled,
-fieldset[disabled] .radio-inline,
-fieldset[disabled] .checkbox-inline {
- cursor: not-allowed;
-}
-.radio.disabled label,
-.checkbox.disabled label,
-fieldset[disabled] .radio label,
-fieldset[disabled] .checkbox label {
- cursor: not-allowed;
-}
-.form-control-static {
- padding-top: 9px;
- padding-bottom: 9px;
- margin-bottom: 0;
- min-height: 34px;
-}
-.form-control-static.input-lg,
-.form-control-static.input-sm {
- padding-left: 0;
- padding-right: 0;
-}
-.input-sm {
- height: 30px;
- padding: 5px 10px;
- font-size: 12px;
- line-height: 1.5;
- border-radius: 3px;
-}
-select.input-sm {
- height: 30px;
- line-height: 30px;
-}
-textarea.input-sm,
-select[multiple].input-sm {
- height: auto;
-}
-.form-group-sm .form-control {
- height: 30px;
- padding: 5px 10px;
- font-size: 12px;
- line-height: 1.5;
- border-radius: 3px;
-}
-.form-group-sm select.form-control {
- height: 30px;
- line-height: 30px;
-}
-.form-group-sm textarea.form-control,
-.form-group-sm select[multiple].form-control {
- height: auto;
-}
-.form-group-sm .form-control-static {
- height: 30px;
- min-height: 32px;
- padding: 6px 10px;
- font-size: 12px;
- line-height: 1.5;
-}
-.input-lg {
- height: 54px;
- padding: 14px 16px;
- font-size: 18px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-select.input-lg {
- height: 54px;
- line-height: 54px;
-}
-textarea.input-lg,
-select[multiple].input-lg {
- height: auto;
-}
-.form-group-lg .form-control {
- height: 54px;
- padding: 14px 16px;
- font-size: 18px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-.form-group-lg select.form-control {
- height: 54px;
- line-height: 54px;
-}
-.form-group-lg textarea.form-control,
-.form-group-lg select[multiple].form-control {
- height: auto;
-}
-.form-group-lg .form-control-static {
- height: 54px;
- min-height: 38px;
- padding: 15px 16px;
- font-size: 18px;
- line-height: 1.3333333;
-}
-.has-feedback {
- position: relative;
-}
-.has-feedback .form-control {
- padding-right: 47.5px;
-}
-.form-control-feedback {
- position: absolute;
- top: 0;
- right: 0;
- z-index: 2;
- display: block;
- width: 38px;
- height: 38px;
- line-height: 38px;
- text-align: center;
- pointer-events: none;
-}
-.input-lg + .form-control-feedback,
-.input-group-lg + .form-control-feedback,
-.form-group-lg .form-control + .form-control-feedback {
- width: 54px;
- height: 54px;
- line-height: 54px;
-}
-.input-sm + .form-control-feedback,
-.input-group-sm + .form-control-feedback,
-.form-group-sm .form-control + .form-control-feedback {
- width: 30px;
- height: 30px;
- line-height: 30px;
-}
-.has-success .help-block,
-.has-success .control-label,
-.has-success .radio,
-.has-success .checkbox,
-.has-success .radio-inline,
-.has-success .checkbox-inline,
-.has-success.radio label,
-.has-success.checkbox label,
-.has-success.radio-inline label,
-.has-success.checkbox-inline label {
- color: #ffffff;
-}
-.has-success .form-control {
- border-color: #ffffff;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.has-success .form-control:focus {
- border-color: #e6e6e6;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
-}
-.has-success .input-group-addon {
- color: #ffffff;
- border-color: #ffffff;
- background-color: #62c462;
-}
-.has-success .form-control-feedback {
- color: #ffffff;
-}
-.has-warning .help-block,
-.has-warning .control-label,
-.has-warning .radio,
-.has-warning .checkbox,
-.has-warning .radio-inline,
-.has-warning .checkbox-inline,
-.has-warning.radio label,
-.has-warning.checkbox label,
-.has-warning.radio-inline label,
-.has-warning.checkbox-inline label {
- color: #ffffff;
-}
-.has-warning .form-control {
- border-color: #ffffff;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.has-warning .form-control:focus {
- border-color: #e6e6e6;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
-}
-.has-warning .input-group-addon {
- color: #ffffff;
- border-color: #ffffff;
- background-color: #f89406;
-}
-.has-warning .form-control-feedback {
- color: #ffffff;
-}
-.has-error .help-block,
-.has-error .control-label,
-.has-error .radio,
-.has-error .checkbox,
-.has-error .radio-inline,
-.has-error .checkbox-inline,
-.has-error.radio label,
-.has-error.checkbox label,
-.has-error.radio-inline label,
-.has-error.checkbox-inline label {
- color: #ffffff;
-}
-.has-error .form-control {
- border-color: #ffffff;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-}
-.has-error .form-control:focus {
- border-color: #e6e6e6;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff;
-}
-.has-error .input-group-addon {
- color: #ffffff;
- border-color: #ffffff;
- background-color: #ee5f5b;
-}
-.has-error .form-control-feedback {
- color: #ffffff;
-}
-.has-feedback label ~ .form-control-feedback {
- top: 25px;
-}
-.has-feedback label.sr-only ~ .form-control-feedback {
- top: 0;
-}
-.help-block {
- display: block;
- margin-top: 5px;
- margin-bottom: 10px;
- color: #ffffff;
-}
-@media (min-width: 768px) {
- .form-inline .form-group {
- display: inline-block;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .form-inline .form-control {
- display: inline-block;
- width: auto;
- vertical-align: middle;
- }
- .form-inline .form-control-static {
- display: inline-block;
- }
- .form-inline .input-group {
- display: inline-table;
- vertical-align: middle;
- }
- .form-inline .input-group .input-group-addon,
- .form-inline .input-group .input-group-btn,
- .form-inline .input-group .form-control {
- width: auto;
- }
- .form-inline .input-group > .form-control {
- width: 100%;
- }
- .form-inline .control-label {
- margin-bottom: 0;
- vertical-align: middle;
- }
- .form-inline .radio,
- .form-inline .checkbox {
- display: inline-block;
- margin-top: 0;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .form-inline .radio label,
- .form-inline .checkbox label {
- padding-left: 0;
- }
- .form-inline .radio input[type="radio"],
- .form-inline .checkbox input[type="checkbox"] {
- position: relative;
- margin-left: 0;
- }
- .form-inline .has-feedback .form-control-feedback {
- top: 0;
- }
-}
-.form-horizontal .radio,
-.form-horizontal .checkbox,
-.form-horizontal .radio-inline,
-.form-horizontal .checkbox-inline {
- margin-top: 0;
- margin-bottom: 0;
- padding-top: 9px;
-}
-.form-horizontal .radio,
-.form-horizontal .checkbox {
- min-height: 29px;
-}
-.form-horizontal .form-group {
- margin-left: -15px;
- margin-right: -15px;
-}
-@media (min-width: 768px) {
- .form-horizontal .control-label {
- text-align: right;
- margin-bottom: 0;
- padding-top: 9px;
- }
-}
-.form-horizontal .has-feedback .form-control-feedback {
- right: 15px;
-}
-@media (min-width: 768px) {
- .form-horizontal .form-group-lg .control-label {
- padding-top: 15px;
- font-size: 18px;
- }
-}
-@media (min-width: 768px) {
- .form-horizontal .form-group-sm .control-label {
- padding-top: 6px;
- font-size: 12px;
- }
-}
-.btn {
- display: inline-block;
- margin-bottom: 0;
- font-weight: normal;
- text-align: center;
- vertical-align: middle;
- -ms-touch-action: manipulation;
- touch-action: manipulation;
- cursor: pointer;
- background-image: none;
- border: 1px solid transparent;
- white-space: nowrap;
- padding: 8px 12px;
- font-size: 14px;
- line-height: 1.42857143;
- border-radius: 4px;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-.btn:focus,
-.btn:active:focus,
-.btn.active:focus,
-.btn.focus,
-.btn:active.focus,
-.btn.active.focus {
- outline: thin dotted;
- outline: 5px auto -webkit-focus-ring-color;
- outline-offset: -2px;
-}
-.btn:hover,
-.btn:focus,
-.btn.focus {
- color: #ffffff;
- text-decoration: none;
-}
-.btn:active,
-.btn.active {
- outline: 0;
- background-image: none;
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-}
-.btn.disabled,
-.btn[disabled],
-fieldset[disabled] .btn {
- cursor: not-allowed;
- opacity: 0.65;
- filter: alpha(opacity=65);
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-a.btn.disabled,
-fieldset[disabled] a.btn {
- pointer-events: none;
-}
-.btn-default {
- color: #ffffff;
- background-color: #3a3f44;
- border-color: #3a3f44;
-}
-.btn-default:focus,
-.btn-default.focus {
- color: #ffffff;
- background-color: #232628;
- border-color: #000000;
-}
-.btn-default:hover {
- color: #ffffff;
- background-color: #232628;
- border-color: #1e2023;
-}
-.btn-default:active,
-.btn-default.active,
-.open > .dropdown-toggle.btn-default {
- color: #ffffff;
- background-color: #232628;
- border-color: #1e2023;
-}
-.btn-default:active:hover,
-.btn-default.active:hover,
-.open > .dropdown-toggle.btn-default:hover,
-.btn-default:active:focus,
-.btn-default.active:focus,
-.open > .dropdown-toggle.btn-default:focus,
-.btn-default:active.focus,
-.btn-default.active.focus,
-.open > .dropdown-toggle.btn-default.focus {
- color: #ffffff;
- background-color: #121415;
- border-color: #000000;
-}
-.btn-default:active,
-.btn-default.active,
-.open > .dropdown-toggle.btn-default {
- background-image: none;
-}
-.btn-default.disabled:hover,
-.btn-default[disabled]:hover,
-fieldset[disabled] .btn-default:hover,
-.btn-default.disabled:focus,
-.btn-default[disabled]:focus,
-fieldset[disabled] .btn-default:focus,
-.btn-default.disabled.focus,
-.btn-default[disabled].focus,
-fieldset[disabled] .btn-default.focus {
- background-color: #3a3f44;
- border-color: #3a3f44;
-}
-.btn-default .badge {
- color: #3a3f44;
- background-color: #ffffff;
-}
-.btn-primary {
- color: #ffffff;
- background-color: #7a8288;
- border-color: #7a8288;
-}
-.btn-primary:focus,
-.btn-primary.focus {
- color: #ffffff;
- background-color: #62686d;
- border-color: #3e4245;
-}
-.btn-primary:hover {
- color: #ffffff;
- background-color: #62686d;
- border-color: #5d6368;
-}
-.btn-primary:active,
-.btn-primary.active,
-.open > .dropdown-toggle.btn-primary {
- color: #ffffff;
- background-color: #62686d;
- border-color: #5d6368;
-}
-.btn-primary:active:hover,
-.btn-primary.active:hover,
-.open > .dropdown-toggle.btn-primary:hover,
-.btn-primary:active:focus,
-.btn-primary.active:focus,
-.open > .dropdown-toggle.btn-primary:focus,
-.btn-primary:active.focus,
-.btn-primary.active.focus,
-.open > .dropdown-toggle.btn-primary.focus {
- color: #ffffff;
- background-color: #51565a;
- border-color: #3e4245;
-}
-.btn-primary:active,
-.btn-primary.active,
-.open > .dropdown-toggle.btn-primary {
- background-image: none;
-}
-.btn-primary.disabled:hover,
-.btn-primary[disabled]:hover,
-fieldset[disabled] .btn-primary:hover,
-.btn-primary.disabled:focus,
-.btn-primary[disabled]:focus,
-fieldset[disabled] .btn-primary:focus,
-.btn-primary.disabled.focus,
-.btn-primary[disabled].focus,
-fieldset[disabled] .btn-primary.focus {
- background-color: #7a8288;
- border-color: #7a8288;
-}
-.btn-primary .badge {
- color: #7a8288;
- background-color: #ffffff;
-}
-.btn-success {
- color: #ffffff;
- background-color: #62c462;
- border-color: #62c462;
-}
-.btn-success:focus,
-.btn-success.focus {
- color: #ffffff;
- background-color: #42b142;
- border-color: #2d792d;
-}
-.btn-success:hover {
- color: #ffffff;
- background-color: #42b142;
- border-color: #40a940;
-}
-.btn-success:active,
-.btn-success.active,
-.open > .dropdown-toggle.btn-success {
- color: #ffffff;
- background-color: #42b142;
- border-color: #40a940;
-}
-.btn-success:active:hover,
-.btn-success.active:hover,
-.open > .dropdown-toggle.btn-success:hover,
-.btn-success:active:focus,
-.btn-success.active:focus,
-.open > .dropdown-toggle.btn-success:focus,
-.btn-success:active.focus,
-.btn-success.active.focus,
-.open > .dropdown-toggle.btn-success.focus {
- color: #ffffff;
- background-color: #399739;
- border-color: #2d792d;
-}
-.btn-success:active,
-.btn-success.active,
-.open > .dropdown-toggle.btn-success {
- background-image: none;
-}
-.btn-success.disabled:hover,
-.btn-success[disabled]:hover,
-fieldset[disabled] .btn-success:hover,
-.btn-success.disabled:focus,
-.btn-success[disabled]:focus,
-fieldset[disabled] .btn-success:focus,
-.btn-success.disabled.focus,
-.btn-success[disabled].focus,
-fieldset[disabled] .btn-success.focus {
- background-color: #62c462;
- border-color: #62c462;
-}
-.btn-success .badge {
- color: #62c462;
- background-color: #ffffff;
-}
-.btn-info {
- color: #ffffff;
- background-color: #5bc0de;
- border-color: #5bc0de;
-}
-.btn-info:focus,
-.btn-info.focus {
- color: #ffffff;
- background-color: #31b0d5;
- border-color: #1f7e9a;
-}
-.btn-info:hover {
- color: #ffffff;
- background-color: #31b0d5;
- border-color: #2aabd2;
-}
-.btn-info:active,
-.btn-info.active,
-.open > .dropdown-toggle.btn-info {
- color: #ffffff;
- background-color: #31b0d5;
- border-color: #2aabd2;
-}
-.btn-info:active:hover,
-.btn-info.active:hover,
-.open > .dropdown-toggle.btn-info:hover,
-.btn-info:active:focus,
-.btn-info.active:focus,
-.open > .dropdown-toggle.btn-info:focus,
-.btn-info:active.focus,
-.btn-info.active.focus,
-.open > .dropdown-toggle.btn-info.focus {
- color: #ffffff;
- background-color: #269abc;
- border-color: #1f7e9a;
-}
-.btn-info:active,
-.btn-info.active,
-.open > .dropdown-toggle.btn-info {
- background-image: none;
-}
-.btn-info.disabled:hover,
-.btn-info[disabled]:hover,
-fieldset[disabled] .btn-info:hover,
-.btn-info.disabled:focus,
-.btn-info[disabled]:focus,
-fieldset[disabled] .btn-info:focus,
-.btn-info.disabled.focus,
-.btn-info[disabled].focus,
-fieldset[disabled] .btn-info.focus {
- background-color: #5bc0de;
- border-color: #5bc0de;
-}
-.btn-info .badge {
- color: #5bc0de;
- background-color: #ffffff;
-}
-.btn-warning {
- color: #ffffff;
- background-color: #f89406;
- border-color: #f89406;
-}
-.btn-warning:focus,
-.btn-warning.focus {
- color: #ffffff;
- background-color: #c67605;
- border-color: #7c4a03;
-}
-.btn-warning:hover {
- color: #ffffff;
- background-color: #c67605;
- border-color: #bc7005;
-}
-.btn-warning:active,
-.btn-warning.active,
-.open > .dropdown-toggle.btn-warning {
- color: #ffffff;
- background-color: #c67605;
- border-color: #bc7005;
-}
-.btn-warning:active:hover,
-.btn-warning.active:hover,
-.open > .dropdown-toggle.btn-warning:hover,
-.btn-warning:active:focus,
-.btn-warning.active:focus,
-.open > .dropdown-toggle.btn-warning:focus,
-.btn-warning:active.focus,
-.btn-warning.active.focus,
-.open > .dropdown-toggle.btn-warning.focus {
- color: #ffffff;
- background-color: #a36104;
- border-color: #7c4a03;
-}
-.btn-warning:active,
-.btn-warning.active,
-.open > .dropdown-toggle.btn-warning {
- background-image: none;
-}
-.btn-warning.disabled:hover,
-.btn-warning[disabled]:hover,
-fieldset[disabled] .btn-warning:hover,
-.btn-warning.disabled:focus,
-.btn-warning[disabled]:focus,
-fieldset[disabled] .btn-warning:focus,
-.btn-warning.disabled.focus,
-.btn-warning[disabled].focus,
-fieldset[disabled] .btn-warning.focus {
- background-color: #f89406;
- border-color: #f89406;
-}
-.btn-warning .badge {
- color: #f89406;
- background-color: #ffffff;
-}
-.btn-danger {
- color: #ffffff;
- background-color: #ee5f5b;
- border-color: #ee5f5b;
-}
-.btn-danger:focus,
-.btn-danger.focus {
- color: #ffffff;
- background-color: #e9322d;
- border-color: #b71713;
-}
-.btn-danger:hover {
- color: #ffffff;
- background-color: #e9322d;
- border-color: #e82924;
-}
-.btn-danger:active,
-.btn-danger.active,
-.open > .dropdown-toggle.btn-danger {
- color: #ffffff;
- background-color: #e9322d;
- border-color: #e82924;
-}
-.btn-danger:active:hover,
-.btn-danger.active:hover,
-.open > .dropdown-toggle.btn-danger:hover,
-.btn-danger:active:focus,
-.btn-danger.active:focus,
-.open > .dropdown-toggle.btn-danger:focus,
-.btn-danger:active.focus,
-.btn-danger.active.focus,
-.open > .dropdown-toggle.btn-danger.focus {
- color: #ffffff;
- background-color: #dc1c17;
- border-color: #b71713;
-}
-.btn-danger:active,
-.btn-danger.active,
-.open > .dropdown-toggle.btn-danger {
- background-image: none;
-}
-.btn-danger.disabled:hover,
-.btn-danger[disabled]:hover,
-fieldset[disabled] .btn-danger:hover,
-.btn-danger.disabled:focus,
-.btn-danger[disabled]:focus,
-fieldset[disabled] .btn-danger:focus,
-.btn-danger.disabled.focus,
-.btn-danger[disabled].focus,
-fieldset[disabled] .btn-danger.focus {
- background-color: #ee5f5b;
- border-color: #ee5f5b;
-}
-.btn-danger .badge {
- color: #ee5f5b;
- background-color: #ffffff;
-}
-.btn-link {
- color: #ffffff;
- font-weight: normal;
- border-radius: 0;
-}
-.btn-link,
-.btn-link:active,
-.btn-link.active,
-.btn-link[disabled],
-fieldset[disabled] .btn-link {
- background-color: transparent;
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.btn-link,
-.btn-link:hover,
-.btn-link:focus,
-.btn-link:active {
- border-color: transparent;
-}
-.btn-link:hover,
-.btn-link:focus {
- color: #ffffff;
- text-decoration: underline;
- background-color: transparent;
-}
-.btn-link[disabled]:hover,
-fieldset[disabled] .btn-link:hover,
-.btn-link[disabled]:focus,
-fieldset[disabled] .btn-link:focus {
- color: #7a8288;
- text-decoration: none;
-}
-.btn-lg,
-.btn-group-lg > .btn {
- padding: 14px 16px;
- font-size: 18px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-.btn-sm,
-.btn-group-sm > .btn {
- padding: 5px 10px;
- font-size: 12px;
- line-height: 1.5;
- border-radius: 3px;
-}
-.btn-xs,
-.btn-group-xs > .btn {
- padding: 1px 5px;
- font-size: 12px;
- line-height: 1.5;
- border-radius: 3px;
-}
-.btn-block {
- display: block;
- width: 100%;
-}
-.btn-block + .btn-block {
- margin-top: 5px;
-}
-input[type="submit"].btn-block,
-input[type="reset"].btn-block,
-input[type="button"].btn-block {
- width: 100%;
-}
-.fade {
- opacity: 0;
- -webkit-transition: opacity 0.15s linear;
- -o-transition: opacity 0.15s linear;
- transition: opacity 0.15s linear;
-}
-.fade.in {
- opacity: 1;
-}
-.collapse {
- display: none;
-}
-.collapse.in {
- display: block;
-}
-tr.collapse.in {
- display: table-row;
-}
-tbody.collapse.in {
- display: table-row-group;
-}
-.collapsing {
- position: relative;
- height: 0;
- overflow: hidden;
- -webkit-transition-property: height, visibility;
- -o-transition-property: height, visibility;
- transition-property: height, visibility;
- -webkit-transition-duration: 0.35s;
- -o-transition-duration: 0.35s;
- transition-duration: 0.35s;
- -webkit-transition-timing-function: ease;
- -o-transition-timing-function: ease;
- transition-timing-function: ease;
-}
-.caret {
- display: inline-block;
- width: 0;
- height: 0;
- margin-left: 2px;
- vertical-align: middle;
- border-top: 4px dashed;
- border-top: 4px solid \9;
- border-right: 4px solid transparent;
- border-left: 4px solid transparent;
-}
-.dropup,
-.dropdown {
- position: relative;
-}
-.dropdown-toggle:focus {
- outline: 0;
-}
-.dropdown-menu {
- position: absolute;
- top: 100%;
- left: 0;
- z-index: 1000;
- display: none;
- float: left;
- min-width: 160px;
- padding: 5px 0;
- margin: 2px 0 0;
- list-style: none;
- font-size: 14px;
- text-align: left;
- background-color: #3a3f44;
- border: 1px solid #272b30;
- border: 1px solid rgba(0, 0, 0, 0.15);
- border-radius: 4px;
- -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
- -webkit-background-clip: padding-box;
- background-clip: padding-box;
-}
-.dropdown-menu.pull-right {
- right: 0;
- left: auto;
-}
-.dropdown-menu .divider {
- height: 1px;
- margin: 9px 0;
- overflow: hidden;
- background-color: #272b30;
-}
-.dropdown-menu > li > a {
- display: block;
- padding: 3px 20px;
- clear: both;
- font-weight: normal;
- line-height: 1.42857143;
- color: #c8c8c8;
- white-space: nowrap;
-}
-.dropdown-menu > li > a:hover,
-.dropdown-menu > li > a:focus {
- text-decoration: none;
- color: #ffffff;
- background-color: #272b30;
-}
-.dropdown-menu > .active > a,
-.dropdown-menu > .active > a:hover,
-.dropdown-menu > .active > a:focus {
- color: #ffffff;
- text-decoration: none;
- outline: 0;
- background-color: #272b30;
-}
-.dropdown-menu > .disabled > a,
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
- color: #7a8288;
-}
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
- text-decoration: none;
- background-color: transparent;
- background-image: none;
- filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
- cursor: not-allowed;
-}
-.open > .dropdown-menu {
- display: block;
-}
-.open > a {
- outline: 0;
-}
-.dropdown-menu-right {
- left: auto;
- right: 0;
-}
-.dropdown-menu-left {
- left: 0;
- right: auto;
-}
-.dropdown-header {
- display: block;
- padding: 3px 20px;
- font-size: 12px;
- line-height: 1.42857143;
- color: #7a8288;
- white-space: nowrap;
-}
-.dropdown-backdrop {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- top: 0;
- z-index: 990;
-}
-.pull-right > .dropdown-menu {
- right: 0;
- left: auto;
-}
-.dropup .caret,
-.navbar-fixed-bottom .dropdown .caret {
- border-top: 0;
- border-bottom: 4px dashed;
- border-bottom: 4px solid \9;
- content: "";
-}
-.dropup .dropdown-menu,
-.navbar-fixed-bottom .dropdown .dropdown-menu {
- top: auto;
- bottom: 100%;
- margin-bottom: 2px;
-}
-@media (min-width: 768px) {
- .navbar-right .dropdown-menu {
- left: auto;
- right: 0;
- }
- .navbar-right .dropdown-menu-left {
- left: 0;
- right: auto;
- }
-}
-.btn-group,
-.btn-group-vertical {
- position: relative;
- display: inline-block;
- vertical-align: middle;
-}
-.btn-group > .btn,
-.btn-group-vertical > .btn {
- position: relative;
- float: left;
-}
-.btn-group > .btn:hover,
-.btn-group-vertical > .btn:hover,
-.btn-group > .btn:focus,
-.btn-group-vertical > .btn:focus,
-.btn-group > .btn:active,
-.btn-group-vertical > .btn:active,
-.btn-group > .btn.active,
-.btn-group-vertical > .btn.active {
- z-index: 2;
-}
-.btn-group .btn + .btn,
-.btn-group .btn + .btn-group,
-.btn-group .btn-group + .btn,
-.btn-group .btn-group + .btn-group {
- margin-left: -1px;
-}
-.btn-toolbar {
- margin-left: -5px;
-}
-.btn-toolbar .btn,
-.btn-toolbar .btn-group,
-.btn-toolbar .input-group {
- float: left;
-}
-.btn-toolbar > .btn,
-.btn-toolbar > .btn-group,
-.btn-toolbar > .input-group {
- margin-left: 5px;
-}
-.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
- border-radius: 0;
-}
-.btn-group > .btn:first-child {
- margin-left: 0;
-}
-.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
-}
-.btn-group > .btn:last-child:not(:first-child),
-.btn-group > .dropdown-toggle:not(:first-child) {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
-}
-.btn-group > .btn-group {
- float: left;
-}
-.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
- border-radius: 0;
-}
-.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
-.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
-}
-.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
-}
-.btn-group .dropdown-toggle:active,
-.btn-group.open .dropdown-toggle {
- outline: 0;
-}
-.btn-group > .btn + .dropdown-toggle {
- padding-left: 8px;
- padding-right: 8px;
-}
-.btn-group > .btn-lg + .dropdown-toggle {
- padding-left: 12px;
- padding-right: 12px;
-}
-.btn-group.open .dropdown-toggle {
- -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
-}
-.btn-group.open .dropdown-toggle.btn-link {
- -webkit-box-shadow: none;
- box-shadow: none;
-}
-.btn .caret {
- margin-left: 0;
-}
-.btn-lg .caret {
- border-width: 5px 5px 0;
- border-bottom-width: 0;
-}
-.dropup .btn-lg .caret {
- border-width: 0 5px 5px;
-}
-.btn-group-vertical > .btn,
-.btn-group-vertical > .btn-group,
-.btn-group-vertical > .btn-group > .btn {
- display: block;
- float: none;
- width: 100%;
- max-width: 100%;
-}
-.btn-group-vertical > .btn-group > .btn {
- float: none;
-}
-.btn-group-vertical > .btn + .btn,
-.btn-group-vertical > .btn + .btn-group,
-.btn-group-vertical > .btn-group + .btn,
-.btn-group-vertical > .btn-group + .btn-group {
- margin-top: -1px;
- margin-left: 0;
-}
-.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
- border-radius: 0;
-}
-.btn-group-vertical > .btn:first-child:not(:last-child) {
- border-top-right-radius: 4px;
- border-top-left-radius: 4px;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-.btn-group-vertical > .btn:last-child:not(:first-child) {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
- border-bottom-right-radius: 4px;
- border-bottom-left-radius: 4px;
-}
-.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
- border-radius: 0;
-}
-.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
-.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.btn-group-justified {
- display: table;
- width: 100%;
- table-layout: fixed;
- border-collapse: separate;
-}
-.btn-group-justified > .btn,
-.btn-group-justified > .btn-group {
- float: none;
- display: table-cell;
- width: 1%;
-}
-.btn-group-justified > .btn-group .btn {
- width: 100%;
-}
-.btn-group-justified > .btn-group .dropdown-menu {
- left: auto;
-}
-[data-toggle="buttons"] > .btn input[type="radio"],
-[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
-[data-toggle="buttons"] > .btn input[type="checkbox"],
-[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
- position: absolute;
- clip: rect(0, 0, 0, 0);
- pointer-events: none;
-}
-.input-group {
- position: relative;
- display: table;
- border-collapse: separate;
-}
-.input-group[class*="col-"] {
- float: none;
- padding-left: 0;
- padding-right: 0;
-}
-.input-group .form-control {
- position: relative;
- z-index: 2;
- float: left;
- width: 100%;
- margin-bottom: 0;
-}
-.input-group .form-control:focus {
- z-index: 3;
-}
-.input-group-lg > .form-control,
-.input-group-lg > .input-group-addon,
-.input-group-lg > .input-group-btn > .btn {
- height: 54px;
- padding: 14px 16px;
- font-size: 18px;
- line-height: 1.3333333;
- border-radius: 6px;
-}
-select.input-group-lg > .form-control,
-select.input-group-lg > .input-group-addon,
-select.input-group-lg > .input-group-btn > .btn {
- height: 54px;
- line-height: 54px;
-}
-textarea.input-group-lg > .form-control,
-textarea.input-group-lg > .input-group-addon,
-textarea.input-group-lg > .input-group-btn > .btn,
-select[multiple].input-group-lg > .form-control,
-select[multiple].input-group-lg > .input-group-addon,
-select[multiple].input-group-lg > .input-group-btn > .btn {
- height: auto;
-}
-.input-group-sm > .form-control,
-.input-group-sm > .input-group-addon,
-.input-group-sm > .input-group-btn > .btn {
- height: 30px;
- padding: 5px 10px;
- font-size: 12px;
- line-height: 1.5;
- border-radius: 3px;
-}
-select.input-group-sm > .form-control,
-select.input-group-sm > .input-group-addon,
-select.input-group-sm > .input-group-btn > .btn {
- height: 30px;
- line-height: 30px;
-}
-textarea.input-group-sm > .form-control,
-textarea.input-group-sm > .input-group-addon,
-textarea.input-group-sm > .input-group-btn > .btn,
-select[multiple].input-group-sm > .form-control,
-select[multiple].input-group-sm > .input-group-addon,
-select[multiple].input-group-sm > .input-group-btn > .btn {
- height: auto;
-}
-.input-group-addon,
-.input-group-btn,
-.input-group .form-control {
- display: table-cell;
-}
-.input-group-addon:not(:first-child):not(:last-child),
-.input-group-btn:not(:first-child):not(:last-child),
-.input-group .form-control:not(:first-child):not(:last-child) {
- border-radius: 0;
-}
-.input-group-addon,
-.input-group-btn {
- width: 1%;
- white-space: nowrap;
- vertical-align: middle;
-}
-.input-group-addon {
- padding: 8px 12px;
- font-size: 14px;
- font-weight: normal;
- line-height: 1;
- color: #272b30;
- text-align: center;
- background-color: #999999;
- border: 1px solid rgba(0, 0, 0, 0.6);
- border-radius: 4px;
-}
-.input-group-addon.input-sm {
- padding: 5px 10px;
- font-size: 12px;
- border-radius: 3px;
-}
-.input-group-addon.input-lg {
- padding: 14px 16px;
- font-size: 18px;
- border-radius: 6px;
-}
-.input-group-addon input[type="radio"],
-.input-group-addon input[type="checkbox"] {
- margin-top: 0;
-}
-.input-group .form-control:first-child,
-.input-group-addon:first-child,
-.input-group-btn:first-child > .btn,
-.input-group-btn:first-child > .btn-group > .btn,
-.input-group-btn:first-child > .dropdown-toggle,
-.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
-.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
- border-bottom-right-radius: 0;
- border-top-right-radius: 0;
-}
-.input-group-addon:first-child {
- border-right: 0;
-}
-.input-group .form-control:last-child,
-.input-group-addon:last-child,
-.input-group-btn:last-child > .btn,
-.input-group-btn:last-child > .btn-group > .btn,
-.input-group-btn:last-child > .dropdown-toggle,
-.input-group-btn:first-child > .btn:not(:first-child),
-.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
- border-bottom-left-radius: 0;
- border-top-left-radius: 0;
-}
-.input-group-addon:last-child {
- border-left: 0;
-}
-.input-group-btn {
- position: relative;
- font-size: 0;
- white-space: nowrap;
-}
-.input-group-btn > .btn {
- position: relative;
-}
-.input-group-btn > .btn + .btn {
- margin-left: -1px;
-}
-.input-group-btn > .btn:hover,
-.input-group-btn > .btn:focus,
-.input-group-btn > .btn:active {
- z-index: 2;
-}
-.input-group-btn:first-child > .btn,
-.input-group-btn:first-child > .btn-group {
- margin-right: -1px;
-}
-.input-group-btn:last-child > .btn,
-.input-group-btn:last-child > .btn-group {
- z-index: 2;
- margin-left: -1px;
-}
-.nav {
- margin-bottom: 0;
- padding-left: 0;
- list-style: none;
-}
-.nav > li {
- position: relative;
- display: block;
-}
-.nav > li > a {
- position: relative;
- display: block;
- padding: 10px 15px;
-}
-.nav > li > a:hover,
-.nav > li > a:focus {
- text-decoration: none;
- background-color: #3e444c;
-}
-.nav > li.disabled > a {
- color: #7a8288;
-}
-.nav > li.disabled > a:hover,
-.nav > li.disabled > a:focus {
- color: #7a8288;
- text-decoration: none;
- background-color: transparent;
- cursor: not-allowed;
-}
-.nav .open > a,
-.nav .open > a:hover,
-.nav .open > a:focus {
- background-color: #3e444c;
- border-color: #ffffff;
-}
-.nav .nav-divider {
- height: 1px;
- margin: 9px 0;
- overflow: hidden;
- background-color: #e5e5e5;
-}
-.nav > li > a > img {
- max-width: none;
-}
-.nav-tabs {
- border-bottom: 1px solid #1c1e22;
-}
-.nav-tabs > li {
- float: left;
- margin-bottom: -1px;
-}
-.nav-tabs > li > a {
- margin-right: 2px;
- line-height: 1.42857143;
- border: 1px solid transparent;
- border-radius: 4px 4px 0 0;
-}
-.nav-tabs > li > a:hover {
- border-color: #1c1e22 #1c1e22 #1c1e22;
-}
-.nav-tabs > li.active > a,
-.nav-tabs > li.active > a:hover,
-.nav-tabs > li.active > a:focus {
- color: #ffffff;
- background-color: #3e444c;
- border: 1px solid #1c1e22;
- border-bottom-color: transparent;
- cursor: default;
-}
-.nav-tabs.nav-justified {
- width: 100%;
- border-bottom: 0;
-}
-.nav-tabs.nav-justified > li {
- float: none;
-}
-.nav-tabs.nav-justified > li > a {
- text-align: center;
- margin-bottom: 5px;
-}
-.nav-tabs.nav-justified > .dropdown .dropdown-menu {
- top: auto;
- left: auto;
-}
-@media (min-width: 768px) {
- .nav-tabs.nav-justified > li {
- display: table-cell;
- width: 1%;
- }
- .nav-tabs.nav-justified > li > a {
- margin-bottom: 0;
- }
-}
-.nav-tabs.nav-justified > li > a {
- margin-right: 0;
- border-radius: 4px;
-}
-.nav-tabs.nav-justified > .active > a,
-.nav-tabs.nav-justified > .active > a:hover,
-.nav-tabs.nav-justified > .active > a:focus {
- border: 1px solid #1c1e22;
-}
-@media (min-width: 768px) {
- .nav-tabs.nav-justified > li > a {
- border-bottom: 1px solid #1c1e22;
- border-radius: 4px 4px 0 0;
- }
- .nav-tabs.nav-justified > .active > a,
- .nav-tabs.nav-justified > .active > a:hover,
- .nav-tabs.nav-justified > .active > a:focus {
- border-bottom-color: #272b30;
- }
-}
-.nav-pills > li {
- float: left;
-}
-.nav-pills > li > a {
- border-radius: 4px;
-}
-.nav-pills > li + li {
- margin-left: 2px;
-}
-.nav-pills > li.active > a,
-.nav-pills > li.active > a:hover,
-.nav-pills > li.active > a:focus {
- color: #ffffff;
- background-color: transparent;
-}
-.nav-stacked > li {
- float: none;
-}
-.nav-stacked > li + li {
- margin-top: 2px;
- margin-left: 0;
-}
-.nav-justified {
- width: 100%;
-}
-.nav-justified > li {
- float: none;
-}
-.nav-justified > li > a {
- text-align: center;
- margin-bottom: 5px;
-}
-.nav-justified > .dropdown .dropdown-menu {
- top: auto;
- left: auto;
-}
-@media (min-width: 768px) {
- .nav-justified > li {
- display: table-cell;
- width: 1%;
- }
- .nav-justified > li > a {
- margin-bottom: 0;
- }
-}
-.nav-tabs-justified {
- border-bottom: 0;
-}
-.nav-tabs-justified > li > a {
- margin-right: 0;
- border-radius: 4px;
-}
-.nav-tabs-justified > .active > a,
-.nav-tabs-justified > .active > a:hover,
-.nav-tabs-justified > .active > a:focus {
- border: 1px solid #1c1e22;
-}
-@media (min-width: 768px) {
- .nav-tabs-justified > li > a {
- border-bottom: 1px solid #1c1e22;
- border-radius: 4px 4px 0 0;
- }
- .nav-tabs-justified > .active > a,
- .nav-tabs-justified > .active > a:hover,
- .nav-tabs-justified > .active > a:focus {
- border-bottom-color: #272b30;
- }
-}
-.tab-content > .tab-pane {
- display: none;
-}
-.tab-content > .active {
- display: block;
-}
-.nav-tabs .dropdown-menu {
- margin-top: -1px;
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.navbar {
- position: relative;
- min-height: 50px;
- margin-bottom: 20px;
- border: 1px solid transparent;
-}
-@media (min-width: 768px) {
- .navbar {
- border-radius: 4px;
- }
-}
-@media (min-width: 768px) {
- .navbar-header {
- float: left;
- }
-}
-.navbar-collapse {
- overflow-x: visible;
- padding-right: 15px;
- padding-left: 15px;
- border-top: 1px solid transparent;
- -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
- -webkit-overflow-scrolling: touch;
-}
-.navbar-collapse.in {
- overflow-y: auto;
-}
-@media (min-width: 768px) {
- .navbar-collapse {
- width: auto;
- border-top: 0;
- -webkit-box-shadow: none;
- box-shadow: none;
- }
- .navbar-collapse.collapse {
- display: block !important;
- height: auto !important;
- padding-bottom: 0;
- overflow: visible !important;
- }
- .navbar-collapse.in {
- overflow-y: visible;
- }
- .navbar-fixed-top .navbar-collapse,
- .navbar-static-top .navbar-collapse,
- .navbar-fixed-bottom .navbar-collapse {
- padding-left: 0;
- padding-right: 0;
- }
-}
-.navbar-fixed-top .navbar-collapse,
-.navbar-fixed-bottom .navbar-collapse {
- max-height: 340px;
-}
-@media (max-device-width: 480px) and (orientation: landscape) {
- .navbar-fixed-top .navbar-collapse,
- .navbar-fixed-bottom .navbar-collapse {
- max-height: 200px;
- }
-}
-.container > .navbar-header,
-.container-fluid > .navbar-header,
-.container > .navbar-collapse,
-.container-fluid > .navbar-collapse {
- margin-right: -15px;
- margin-left: -15px;
-}
-@media (min-width: 768px) {
- .container > .navbar-header,
- .container-fluid > .navbar-header,
- .container > .navbar-collapse,
- .container-fluid > .navbar-collapse {
- margin-right: 0;
- margin-left: 0;
- }
-}
-.navbar-static-top {
- z-index: 1000;
- border-width: 0 0 1px;
-}
-@media (min-width: 768px) {
- .navbar-static-top {
- border-radius: 0;
- }
-}
-.navbar-fixed-top,
-.navbar-fixed-bottom {
- position: fixed;
- right: 0;
- left: 0;
- z-index: 1030;
-}
-@media (min-width: 768px) {
- .navbar-fixed-top,
- .navbar-fixed-bottom {
- border-radius: 0;
- }
-}
-.navbar-fixed-top {
- top: 0;
- border-width: 0 0 1px;
-}
-.navbar-fixed-bottom {
- bottom: 0;
- margin-bottom: 0;
- border-width: 1px 0 0;
-}
-.navbar-brand {
- float: left;
- padding: 15px 15px;
- font-size: 18px;
- line-height: 20px;
- height: 50px;
-}
-.navbar-brand:hover,
-.navbar-brand:focus {
- text-decoration: none;
-}
-.navbar-brand > img {
- display: block;
-}
-@media (min-width: 768px) {
- .navbar > .container .navbar-brand,
- .navbar > .container-fluid .navbar-brand {
- margin-left: -15px;
- }
-}
-.navbar-toggle {
- position: relative;
- float: right;
- margin-right: 15px;
- padding: 9px 10px;
- margin-top: 8px;
- margin-bottom: 8px;
- background-color: transparent;
- background-image: none;
- border: 1px solid transparent;
- border-radius: 4px;
-}
-.navbar-toggle:focus {
- outline: 0;
-}
-.navbar-toggle .icon-bar {
- display: block;
- width: 22px;
- height: 2px;
- border-radius: 1px;
-}
-.navbar-toggle .icon-bar + .icon-bar {
- margin-top: 4px;
-}
-@media (min-width: 768px) {
- .navbar-toggle {
- display: none;
- }
-}
-.navbar-nav {
- margin: 7.5px -15px;
-}
-.navbar-nav > li > a {
- padding-top: 10px;
- padding-bottom: 10px;
- line-height: 20px;
-}
-@media (max-width: 767px) {
- .navbar-nav .open .dropdown-menu {
- position: static;
- float: none;
- width: auto;
- margin-top: 0;
- background-color: transparent;
- border: 0;
- -webkit-box-shadow: none;
- box-shadow: none;
- }
- .navbar-nav .open .dropdown-menu > li > a,
- .navbar-nav .open .dropdown-menu .dropdown-header {
- padding: 5px 15px 5px 25px;
- }
- .navbar-nav .open .dropdown-menu > li > a {
- line-height: 20px;
- }
- .navbar-nav .open .dropdown-menu > li > a:hover,
- .navbar-nav .open .dropdown-menu > li > a:focus {
- background-image: none;
- }
-}
-@media (min-width: 768px) {
- .navbar-nav {
- float: left;
- margin: 0;
- }
- .navbar-nav > li {
- float: left;
- }
- .navbar-nav > li > a {
- padding-top: 15px;
- padding-bottom: 15px;
- }
-}
-.navbar-form {
- margin-left: -15px;
- margin-right: -15px;
- padding: 10px 15px;
- border-top: 1px solid transparent;
- border-bottom: 1px solid transparent;
- -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
- box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
- margin-top: 6px;
- margin-bottom: 6px;
-}
-@media (min-width: 768px) {
- .navbar-form .form-group {
- display: inline-block;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .navbar-form .form-control {
- display: inline-block;
- width: auto;
- vertical-align: middle;
- }
- .navbar-form .form-control-static {
- display: inline-block;
- }
- .navbar-form .input-group {
- display: inline-table;
- vertical-align: middle;
- }
- .navbar-form .input-group .input-group-addon,
- .navbar-form .input-group .input-group-btn,
- .navbar-form .input-group .form-control {
- width: auto;
- }
- .navbar-form .input-group > .form-control {
- width: 100%;
- }
- .navbar-form .control-label {
- margin-bottom: 0;
- vertical-align: middle;
- }
- .navbar-form .radio,
- .navbar-form .checkbox {
- display: inline-block;
- margin-top: 0;
- margin-bottom: 0;
- vertical-align: middle;
- }
- .navbar-form .radio label,
- .navbar-form .checkbox label {
- padding-left: 0;
- }
- .navbar-form .radio input[type="radio"],
- .navbar-form .checkbox input[type="checkbox"] {
- position: relative;
- margin-left: 0;
- }
- .navbar-form .has-feedback .form-control-feedback {
- top: 0;
- }
-}
-@media (max-width: 767px) {
- .navbar-form .form-group {
- margin-bottom: 5px;
- }
- .navbar-form .form-group:last-child {
- margin-bottom: 0;
- }
-}
-@media (min-width: 768px) {
- .navbar-form {
- width: auto;
- border: 0;
- margin-left: 0;
- margin-right: 0;
- padding-top: 0;
- padding-bottom: 0;
- -webkit-box-shadow: none;
- box-shadow: none;
- }
-}
-.navbar-nav > li > .dropdown-menu {
- margin-top: 0;
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
- margin-bottom: 0;
- border-top-right-radius: 4px;
- border-top-left-radius: 4px;
- border-bottom-right-radius: 0;
- border-bottom-left-radius: 0;
-}
-.navbar-btn {
- margin-top: 6px;
- margin-bottom: 6px;
-}
-.navbar-btn.btn-sm {
- margin-top: 10px;
- margin-bottom: 10px;
-}
-.navbar-btn.btn-xs {
- margin-top: 14px;
- margin-bottom: 14px;
-}
-.navbar-text {
- margin-top: 15px;
- margin-bottom: 15px;
-}
-@media (min-width: 768px) {
- .navbar-text {
- float: left;
- margin-left: 15px;
- margin-right: 15px;
- }
-}
-@media (min-width: 768px) {
- .navbar-left {
- float: left !important;
- }
- .navbar-right {
- float: right !important;
- margin-right: -15px;
- }
- .navbar-right ~ .navbar-right {
- margin-right: 0;
- }
-}
-.navbar-default {
- background-color: #3a3f44;
- border-color: #2b2e32;
-}
-.navbar-default .navbar-brand {
- color: #c8c8c8;
-}
-.navbar-default .navbar-brand:hover,
-.navbar-default .navbar-brand:focus {
- color: #ffffff;
- background-color: none;
-}
-.navbar-default .navbar-text {
- color: #c8c8c8;
-}
-.navbar-default .navbar-nav > li > a {
- color: #c8c8c8;
-}
-.navbar-default .navbar-nav > li > a:hover,
-.navbar-default .navbar-nav > li > a:focus {
- color: #ffffff;
- background-color: #272b2e;
-}
-.navbar-default .navbar-nav > .active > a,
-.navbar-default .navbar-nav > .active > a:hover,
-.navbar-default .navbar-nav > .active > a:focus {
- color: #ffffff;
- background-color: #272b2e;
-}
-.navbar-default .navbar-nav > .disabled > a,
-.navbar-default .navbar-nav > .disabled > a:hover,
-.navbar-default .navbar-nav > .disabled > a:focus {
- color: #cccccc;
- background-color: transparent;
-}
-.navbar-default .navbar-toggle {
- border-color: #272b2e;
-}
-.navbar-default .navbar-toggle:hover,
-.navbar-default .navbar-toggle:focus {
- background-color: #272b2e;
-}
-.navbar-default .navbar-toggle .icon-bar {
- background-color: #c8c8c8;
-}
-.navbar-default .navbar-collapse,
-.navbar-default .navbar-form {
- border-color: #2b2e32;
-}
-.navbar-default .navbar-nav > .open > a,
-.navbar-default .navbar-nav > .open > a:hover,
-.navbar-default .navbar-nav > .open > a:focus {
- background-color: #272b2e;
- color: #ffffff;
-}
-@media (max-width: 767px) {
- .navbar-default .navbar-nav .open .dropdown-menu > li > a {
- color: #c8c8c8;
- }
- .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
- .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
- color: #ffffff;
- background-color: #272b2e;
- }
- .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
- .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
- .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
- color: #ffffff;
- background-color: #272b2e;
- }
- .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
- .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
- .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
- color: #cccccc;
- background-color: transparent;
- }
-}
-.navbar-default .navbar-link {
- color: #c8c8c8;
-}
-.navbar-default .navbar-link:hover {
- color: #ffffff;
-}
-.navbar-default .btn-link {
- color: #c8c8c8;
-}
-.navbar-default .btn-link:hover,
-.navbar-default .btn-link:focus {
- color: #ffffff;
-}
-.navbar-default .btn-link[disabled]:hover,
-fieldset[disabled] .navbar-default .btn-link:hover,
-.navbar-default .btn-link[disabled]:focus,
-fieldset[disabled] .navbar-default .btn-link:focus {
- color: #cccccc;
-}
-.navbar-inverse {
- background-color: #7a8288;
- border-color: #62686d;
-}
-.navbar-inverse .navbar-brand {
- color: #cccccc;
-}
-.navbar-inverse .navbar-brand:hover,
-.navbar-inverse .navbar-brand:focus {
- color: #ffffff;
- background-color: none;
-}
-.navbar-inverse .navbar-text {
- color: #cccccc;
-}
-.navbar-inverse .navbar-nav > li > a {
- color: #cccccc;
-}
-.navbar-inverse .navbar-nav > li > a:hover,
-.navbar-inverse .navbar-nav > li > a:focus {
- color: #ffffff;
- background-color: #5d6368;
-}
-.navbar-inverse .navbar-nav > .active > a,
-.navbar-inverse .navbar-nav > .active > a:hover,
-.navbar-inverse .navbar-nav > .active > a:focus {
- color: #ffffff;
- background-color: #5d6368;
-}
-.navbar-inverse .navbar-nav > .disabled > a,
-.navbar-inverse .navbar-nav > .disabled > a:hover,
-.navbar-inverse .navbar-nav > .disabled > a:focus {
- color: #cccccc;
- background-color: transparent;
-}
-.navbar-inverse .navbar-toggle {
- border-color: #5d6368;
-}
-.navbar-inverse .navbar-toggle:hover,
-.navbar-inverse .navbar-toggle:focus {
- background-color: #5d6368;
-}
-.navbar-inverse .navbar-toggle .icon-bar {
- background-color: #ffffff;
-}
-.navbar-inverse .navbar-collapse,
-.navbar-inverse .navbar-form {
- border-color: #697075;
-}
-.navbar-inverse .navbar-nav > .open > a,
-.navbar-inverse .navbar-nav > .open > a:hover,
-.navbar-inverse .navbar-nav > .open > a:focus {
- background-color: #5d6368;
- color: #ffffff;
-}
-@media (max-width: 767px) {
- .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
- border-color: #62686d;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
- background-color: #62686d;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
- color: #cccccc;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
- .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
- color: #ffffff;
- background-color: #5d6368;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
- color: #ffffff;
- background-color: #5d6368;
- }
- .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
- .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
- color: #cccccc;
- background-color: transparent;
- }
-}
-.navbar-inverse .navbar-link {
- color: #cccccc;
-}
-.navbar-inverse .navbar-link:hover {
- color: #ffffff;
-}
-.navbar-inverse .btn-link {
- color: #cccccc;
-}
-.navbar-inverse .btn-link:hover,
-.navbar-inverse .btn-link:focus {
- color: #ffffff;
-}
-.navbar-inverse .btn-link[disabled]:hover,
-fieldset[disabled] .navbar-inverse .btn-link:hover,
-.navbar-inverse .btn-link[disabled]:focus,
-fieldset[disabled] .navbar-inverse .btn-link:focus {
- color: #cccccc;
-}
-.breadcrumb {
- padding: 8px 15px;
- margin-bottom: 20px;
- list-style: none;
- background-color: transparent;
- border-radius: 4px;
-}
-.breadcrumb > li {
- display: inline-block;
-}
-.breadcrumb > li + li:before {
- content: "/\00a0";
- padding: 0 5px;
- color: #cccccc;
-}
-.breadcrumb > .active {
- color: #7a8288;
-}
-.pagination {
- display: inline-block;
- padding-left: 0;
- margin: 20px 0;
- border-radius: 4px;
-}
-.pagination > li {
- display: inline;
-}
-.pagination > li > a,
-.pagination > li > span {
- position: relative;
- float: left;
- padding: 8px 12px;
- line-height: 1.42857143;
- text-decoration: none;
- color: #ffffff;
- background-color: #3a3f44;
- border: 1px solid rgba(0, 0, 0, 0.6);
- margin-left: -1px;
-}
-.pagination > li:first-child > a,
-.pagination > li:first-child > span {
- margin-left: 0;
- border-bottom-left-radius: 4px;
- border-top-left-radius: 4px;
-}
-.pagination > li:last-child > a,
-.pagination > li:last-child > span {
- border-bottom-right-radius: 4px;
- border-top-right-radius: 4px;
-}
-.pagination > li > a:hover,
-.pagination > li > span:hover,
-.pagination > li > a:focus,
-.pagination > li > span:focus {
- z-index: 2;
- color: #ffffff;
- background-color: transparent;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.pagination > .active > a,
-.pagination > .active > span,
-.pagination > .active > a:hover,
-.pagination > .active > span:hover,
-.pagination > .active > a:focus,
-.pagination > .active > span:focus {
- z-index: 3;
- color: #ffffff;
- background-color: #232628;
- border-color: rgba(0, 0, 0, 0.6);
- cursor: default;
-}
-.pagination > .disabled > span,
-.pagination > .disabled > span:hover,
-.pagination > .disabled > span:focus,
-.pagination > .disabled > a,
-.pagination > .disabled > a:hover,
-.pagination > .disabled > a:focus {
- color: #7a8288;
- background-color: #ffffff;
- border-color: rgba(0, 0, 0, 0.6);
- cursor: not-allowed;
-}
-.pagination-lg > li > a,
-.pagination-lg > li > span {
- padding: 14px 16px;
- font-size: 18px;
- line-height: 1.3333333;
-}
-.pagination-lg > li:first-child > a,
-.pagination-lg > li:first-child > span {
- border-bottom-left-radius: 6px;
- border-top-left-radius: 6px;
-}
-.pagination-lg > li:last-child > a,
-.pagination-lg > li:last-child > span {
- border-bottom-right-radius: 6px;
- border-top-right-radius: 6px;
-}
-.pagination-sm > li > a,
-.pagination-sm > li > span {
- padding: 5px 10px;
- font-size: 12px;
- line-height: 1.5;
-}
-.pagination-sm > li:first-child > a,
-.pagination-sm > li:first-child > span {
- border-bottom-left-radius: 3px;
- border-top-left-radius: 3px;
-}
-.pagination-sm > li:last-child > a,
-.pagination-sm > li:last-child > span {
- border-bottom-right-radius: 3px;
- border-top-right-radius: 3px;
-}
-.pager {
- padding-left: 0;
- margin: 20px 0;
- list-style: none;
- text-align: center;
-}
-.pager li {
- display: inline;
-}
-.pager li > a,
-.pager li > span {
- display: inline-block;
- padding: 5px 14px;
- background-color: #3a3f44;
- border: 1px solid rgba(0, 0, 0, 0.6);
- border-radius: 15px;
-}
-.pager li > a:hover,
-.pager li > a:focus {
- text-decoration: none;
- background-color: transparent;
-}
-.pager .next > a,
-.pager .next > span {
- float: right;
-}
-.pager .previous > a,
-.pager .previous > span {
- float: left;
-}
-.pager .disabled > a,
-.pager .disabled > a:hover,
-.pager .disabled > a:focus,
-.pager .disabled > span {
- color: #7a8288;
- background-color: #3a3f44;
- cursor: not-allowed;
-}
-.label {
- display: inline;
- padding: .2em .6em .3em;
- font-size: 75%;
- font-weight: bold;
- line-height: 1;
- color: #ffffff;
- text-align: center;
- white-space: nowrap;
- vertical-align: baseline;
- border-radius: .25em;
-}
-a.label:hover,
-a.label:focus {
- color: #ffffff;
- text-decoration: none;
- cursor: pointer;
-}
-.label:empty {
- display: none;
-}
-.btn .label {
- position: relative;
- top: -1px;
-}
-.label-default {
- background-color: #3a3f44;
-}
-.label-default[href]:hover,
-.label-default[href]:focus {
- background-color: #232628;
-}
-.label-primary {
- background-color: #7a8288;
-}
-.label-primary[href]:hover,
-.label-primary[href]:focus {
- background-color: #62686d;
-}
-.label-success {
- background-color: #62c462;
-}
-.label-success[href]:hover,
-.label-success[href]:focus {
- background-color: #42b142;
-}
-.label-info {
- background-color: #5bc0de;
-}
-.label-info[href]:hover,
-.label-info[href]:focus {
- background-color: #31b0d5;
-}
-.label-warning {
- background-color: #f89406;
-}
-.label-warning[href]:hover,
-.label-warning[href]:focus {
- background-color: #c67605;
-}
-.label-danger {
- background-color: #ee5f5b;
-}
-.label-danger[href]:hover,
-.label-danger[href]:focus {
- background-color: #e9322d;
-}
-.badge {
- display: inline-block;
- min-width: 10px;
- padding: 3px 7px;
- font-size: 12px;
- font-weight: bold;
- color: #ffffff;
- line-height: 1;
- vertical-align: middle;
- white-space: nowrap;
- text-align: center;
- background-color: #7a8288;
- border-radius: 10px;
-}
-.badge:empty {
- display: none;
-}
-.btn .badge {
- position: relative;
- top: -1px;
-}
-.btn-xs .badge,
-.btn-group-xs > .btn .badge {
- top: 0;
- padding: 1px 5px;
-}
-a.badge:hover,
-a.badge:focus {
- color: #ffffff;
- text-decoration: none;
- cursor: pointer;
-}
-.list-group-item.active > .badge,
-.nav-pills > .active > a > .badge {
- color: #ffffff;
- background-color: #7a8288;
-}
-.list-group-item > .badge {
- float: right;
-}
-.list-group-item > .badge + .badge {
- margin-right: 5px;
-}
-.nav-pills > li > a > .badge {
- margin-left: 3px;
-}
-.jumbotron {
- padding-top: 30px;
- padding-bottom: 30px;
- margin-bottom: 30px;
- color: inherit;
- background-color: #1c1e22;
-}
-.jumbotron h1,
-.jumbotron .h1 {
- color: inherit;
-}
-.jumbotron p {
- margin-bottom: 15px;
- font-size: 21px;
- font-weight: 200;
-}
-.jumbotron > hr {
- border-top-color: #050506;
-}
-.container .jumbotron,
-.container-fluid .jumbotron {
- border-radius: 6px;
- padding-left: 15px;
- padding-right: 15px;
-}
-.jumbotron .container {
- max-width: 100%;
-}
-@media screen and (min-width: 768px) {
- .jumbotron {
- padding-top: 48px;
- padding-bottom: 48px;
- }
- .container .jumbotron,
- .container-fluid .jumbotron {
- padding-left: 60px;
- padding-right: 60px;
- }
- .jumbotron h1,
- .jumbotron .h1 {
- font-size: 63px;
- }
-}
-.thumbnail {
- display: block;
- padding: 4px;
- margin-bottom: 20px;
- line-height: 1.42857143;
- background-color: #1c1e22;
- border: 1px solid #0c0d0e;
- border-radius: 4px;
- -webkit-transition: border 0.2s ease-in-out;
- -o-transition: border 0.2s ease-in-out;
- transition: border 0.2s ease-in-out;
-}
-.thumbnail > img,
-.thumbnail a > img {
- margin-left: auto;
- margin-right: auto;
-}
-a.thumbnail:hover,
-a.thumbnail:focus,
-a.thumbnail.active {
- border-color: #ffffff;
-}
-.thumbnail .caption {
- padding: 9px;
- color: #c8c8c8;
-}
-.alert {
- padding: 15px;
- margin-bottom: 20px;
- border: 1px solid transparent;
- border-radius: 4px;
-}
-.alert h4 {
- margin-top: 0;
- color: inherit;
-}
-.alert .alert-link {
- font-weight: bold;
-}
-.alert > p,
-.alert > ul {
- margin-bottom: 0;
-}
-.alert > p + p {
- margin-top: 5px;
-}
-.alert-dismissable,
-.alert-dismissible {
- padding-right: 35px;
-}
-.alert-dismissable .close,
-.alert-dismissible .close {
- position: relative;
- top: -2px;
- right: -21px;
- color: inherit;
-}
-.alert-success {
- background-color: #62c462;
- border-color: #62bd4f;
- color: #ffffff;
-}
-.alert-success hr {
- border-top-color: #55b142;
-}
-.alert-success .alert-link {
- color: #e6e6e6;
-}
-.alert-info {
- background-color: #5bc0de;
- border-color: #3dced8;
- color: #ffffff;
-}
-.alert-info hr {
- border-top-color: #2ac7d2;
-}
-.alert-info .alert-link {
- color: #e6e6e6;
-}
-.alert-warning {
- background-color: #f89406;
- border-color: #e96506;
- color: #ffffff;
-}
-.alert-warning hr {
- border-top-color: #d05a05;
-}
-.alert-warning .alert-link {
- color: #e6e6e6;
-}
-.alert-danger {
- background-color: #ee5f5b;
- border-color: #ed4d63;
- color: #ffffff;
-}
-.alert-danger hr {
- border-top-color: #ea364f;
-}
-.alert-danger .alert-link {
- color: #e6e6e6;
-}
-@-webkit-keyframes progress-bar-stripes {
- from {
- background-position: 40px 0;
- }
- to {
- background-position: 0 0;
- }
-}
-@-o-keyframes progress-bar-stripes {
- from {
- background-position: 40px 0;
- }
- to {
- background-position: 0 0;
- }
-}
-@keyframes progress-bar-stripes {
- from {
- background-position: 40px 0;
- }
- to {
- background-position: 0 0;
- }
-}
-.progress {
- overflow: hidden;
- height: 20px;
- margin-bottom: 20px;
- background-color: #1c1e22;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
- box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
-}
-.progress-bar {
- float: left;
- width: 0%;
- height: 100%;
- font-size: 12px;
- line-height: 20px;
- color: #ffffff;
- text-align: center;
- background-color: #7a8288;
- -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
- box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
- -webkit-transition: width 0.6s ease;
- -o-transition: width 0.6s ease;
- transition: width 0.6s ease;
-}
-.progress-striped .progress-bar,
-.progress-bar-striped {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- -webkit-background-size: 40px 40px;
- background-size: 40px 40px;
-}
-.progress.active .progress-bar,
-.progress-bar.active {
- -webkit-animation: progress-bar-stripes 2s linear infinite;
- -o-animation: progress-bar-stripes 2s linear infinite;
- animation: progress-bar-stripes 2s linear infinite;
-}
-.progress-bar-success {
- background-color: #62c462;
-}
-.progress-striped .progress-bar-success {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.progress-bar-info {
- background-color: #5bc0de;
-}
-.progress-striped .progress-bar-info {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.progress-bar-warning {
- background-color: #f89406;
-}
-.progress-striped .progress-bar-warning {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.progress-bar-danger {
- background-color: #ee5f5b;
-}
-.progress-striped .progress-bar-danger {
- background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
- background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
-}
-.media {
- margin-top: 15px;
-}
-.media:first-child {
- margin-top: 0;
-}
-.media,
-.media-body {
- zoom: 1;
- overflow: hidden;
-}
-.media-body {
- width: 10000px;
-}
-.media-object {
- display: block;
-}
-.media-object.img-thumbnail {
- max-width: none;
-}
-.media-right,
-.media > .pull-right {
- padding-left: 10px;
-}
-.media-left,
-.media > .pull-left {
- padding-right: 10px;
-}
-.media-left,
-.media-right,
-.media-body {
- display: table-cell;
- vertical-align: top;
-}
-.media-middle {
- vertical-align: middle;
-}
-.media-bottom {
- vertical-align: bottom;
-}
-.media-heading {
- margin-top: 0;
- margin-bottom: 5px;
-}
-.media-list {
- padding-left: 0;
- list-style: none;
-}
-.list-group {
- margin-bottom: 20px;
- padding-left: 0;
-}
-.list-group-item {
- position: relative;
- display: block;
- padding: 10px 15px;
- margin-bottom: -1px;
- background-color: #32383e;
- border: 1px solid rgba(0, 0, 0, 0.6);
-}
-.list-group-item:first-child {
- border-top-right-radius: 4px;
- border-top-left-radius: 4px;
-}
-.list-group-item:last-child {
- margin-bottom: 0;
- border-bottom-right-radius: 4px;
- border-bottom-left-radius: 4px;
-}
-a.list-group-item,
-button.list-group-item {
- color: #c8c8c8;
-}
-a.list-group-item .list-group-item-heading,
-button.list-group-item .list-group-item-heading {
- color: #ffffff;
-}
-a.list-group-item:hover,
-button.list-group-item:hover,
-a.list-group-item:focus,
-button.list-group-item:focus {
- text-decoration: none;
- color: #c8c8c8;
- background-color: #3e444c;
-}
-button.list-group-item {
- width: 100%;
- text-align: left;
-}
-.list-group-item.disabled,
-.list-group-item.disabled:hover,
-.list-group-item.disabled:focus {
- background-color: #999999;
- color: #7a8288;
- cursor: not-allowed;
-}
-.list-group-item.disabled .list-group-item-heading,
-.list-group-item.disabled:hover .list-group-item-heading,
-.list-group-item.disabled:focus .list-group-item-heading {
- color: inherit;
-}
-.list-group-item.disabled .list-group-item-text,
-.list-group-item.disabled:hover .list-group-item-text,
-.list-group-item.disabled:focus .list-group-item-text {
- color: #7a8288;
-}
-.list-group-item.active,
-.list-group-item.active:hover,
-.list-group-item.active:focus {
- z-index: 2;
- color: #ffffff;
- background-color: #3e444c;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.list-group-item.active .list-group-item-heading,
-.list-group-item.active:hover .list-group-item-heading,
-.list-group-item.active:focus .list-group-item-heading,
-.list-group-item.active .list-group-item-heading > small,
-.list-group-item.active:hover .list-group-item-heading > small,
-.list-group-item.active:focus .list-group-item-heading > small,
-.list-group-item.active .list-group-item-heading > .small,
-.list-group-item.active:hover .list-group-item-heading > .small,
-.list-group-item.active:focus .list-group-item-heading > .small {
- color: inherit;
-}
-.list-group-item.active .list-group-item-text,
-.list-group-item.active:hover .list-group-item-text,
-.list-group-item.active:focus .list-group-item-text {
- color: #a2aab4;
-}
-.list-group-item-success {
- color: #ffffff;
- background-color: #62c462;
-}
-a.list-group-item-success,
-button.list-group-item-success {
- color: #ffffff;
-}
-a.list-group-item-success .list-group-item-heading,
-button.list-group-item-success .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-success:hover,
-button.list-group-item-success:hover,
-a.list-group-item-success:focus,
-button.list-group-item-success:focus {
- color: #ffffff;
- background-color: #4fbd4f;
-}
-a.list-group-item-success.active,
-button.list-group-item-success.active,
-a.list-group-item-success.active:hover,
-button.list-group-item-success.active:hover,
-a.list-group-item-success.active:focus,
-button.list-group-item-success.active:focus {
- color: #fff;
- background-color: #ffffff;
- border-color: #ffffff;
-}
-.list-group-item-info {
- color: #ffffff;
- background-color: #5bc0de;
-}
-a.list-group-item-info,
-button.list-group-item-info {
- color: #ffffff;
-}
-a.list-group-item-info .list-group-item-heading,
-button.list-group-item-info .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-info:hover,
-button.list-group-item-info:hover,
-a.list-group-item-info:focus,
-button.list-group-item-info:focus {
- color: #ffffff;
- background-color: #46b8da;
-}
-a.list-group-item-info.active,
-button.list-group-item-info.active,
-a.list-group-item-info.active:hover,
-button.list-group-item-info.active:hover,
-a.list-group-item-info.active:focus,
-button.list-group-item-info.active:focus {
- color: #fff;
- background-color: #ffffff;
- border-color: #ffffff;
-}
-.list-group-item-warning {
- color: #ffffff;
- background-color: #f89406;
-}
-a.list-group-item-warning,
-button.list-group-item-warning {
- color: #ffffff;
-}
-a.list-group-item-warning .list-group-item-heading,
-button.list-group-item-warning .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-warning:hover,
-button.list-group-item-warning:hover,
-a.list-group-item-warning:focus,
-button.list-group-item-warning:focus {
- color: #ffffff;
- background-color: #df8505;
-}
-a.list-group-item-warning.active,
-button.list-group-item-warning.active,
-a.list-group-item-warning.active:hover,
-button.list-group-item-warning.active:hover,
-a.list-group-item-warning.active:focus,
-button.list-group-item-warning.active:focus {
- color: #fff;
- background-color: #ffffff;
- border-color: #ffffff;
-}
-.list-group-item-danger {
- color: #ffffff;
- background-color: #ee5f5b;
-}
-a.list-group-item-danger,
-button.list-group-item-danger {
- color: #ffffff;
-}
-a.list-group-item-danger .list-group-item-heading,
-button.list-group-item-danger .list-group-item-heading {
- color: inherit;
-}
-a.list-group-item-danger:hover,
-button.list-group-item-danger:hover,
-a.list-group-item-danger:focus,
-button.list-group-item-danger:focus {
- color: #ffffff;
- background-color: #ec4844;
-}
-a.list-group-item-danger.active,
-button.list-group-item-danger.active,
-a.list-group-item-danger.active:hover,
-button.list-group-item-danger.active:hover,
-a.list-group-item-danger.active:focus,
-button.list-group-item-danger.active:focus {
- color: #fff;
- background-color: #ffffff;
- border-color: #ffffff;
-}
-.list-group-item-heading {
- margin-top: 0;
- margin-bottom: 5px;
-}
-.list-group-item-text {
- margin-bottom: 0;
- line-height: 1.3;
-}
-.panel {
- margin-bottom: 20px;
- background-color: #2e3338;
- border: 1px solid transparent;
- border-radius: 4px;
- -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
- box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
-}
-.panel-body {
- padding: 15px;
-}
-.panel-heading {
- padding: 10px 15px;
- border-bottom: 1px solid transparent;
- border-top-right-radius: 3px;
- border-top-left-radius: 3px;
-}
-.panel-heading > .dropdown .dropdown-toggle {
- color: inherit;
-}
-.panel-title {
- margin-top: 0;
- margin-bottom: 0;
- font-size: 16px;
- color: inherit;
-}
-.panel-title > a,
-.panel-title > small,
-.panel-title > .small,
-.panel-title > small > a,
-.panel-title > .small > a {
- color: inherit;
-}
-.panel-footer {
- padding: 10px 15px;
- background-color: #3e444c;
- border-top: 1px solid rgba(0, 0, 0, 0.6);
- border-bottom-right-radius: 3px;
- border-bottom-left-radius: 3px;
-}
-.panel > .list-group,
-.panel > .panel-collapse > .list-group {
- margin-bottom: 0;
-}
-.panel > .list-group .list-group-item,
-.panel > .panel-collapse > .list-group .list-group-item {
- border-width: 1px 0;
- border-radius: 0;
-}
-.panel > .list-group:first-child .list-group-item:first-child,
-.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
- border-top: 0;
- border-top-right-radius: 3px;
- border-top-left-radius: 3px;
-}
-.panel > .list-group:last-child .list-group-item:last-child,
-.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
- border-bottom: 0;
- border-bottom-right-radius: 3px;
- border-bottom-left-radius: 3px;
-}
-.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {
- border-top-right-radius: 0;
- border-top-left-radius: 0;
-}
-.panel-heading + .list-group .list-group-item:first-child {
- border-top-width: 0;
-}
-.list-group + .panel-footer {
- border-top-width: 0;
-}
-.panel > .table,
-.panel > .table-responsive > .table,
-.panel > .panel-collapse > .table {
- margin-bottom: 0;
-}
-.panel > .table caption,
-.panel > .table-responsive > .table caption,
-.panel > .panel-collapse > .table caption {
- padding-left: 15px;
- padding-right: 15px;
-}
-.panel > .table:first-child,
-.panel > .table-responsive:first-child > .table:first-child {
- border-top-right-radius: 3px;
- border-top-left-radius: 3px;
-}
-.panel > .table:first-child > thead:first-child > tr:first-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
- border-top-left-radius: 3px;
- border-top-right-radius: 3px;
-}
-.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
-.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
- border-top-left-radius: 3px;
-}
-.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
-.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
-.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
-.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
-.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
- border-top-right-radius: 3px;
-}
-.panel > .table:last-child,
-.panel > .table-responsive:last-child > .table:last-child {
- border-bottom-right-radius: 3px;
- border-bottom-left-radius: 3px;
-}
-.panel > .table:last-child > tbody:last-child > tr:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
- border-bottom-left-radius: 3px;
- border-bottom-right-radius: 3px;
-}
-.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
-.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
- border-bottom-left-radius: 3px;
-}
-.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
-.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
-.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
-.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
- border-bottom-right-radius: 3px;
-}
-.panel > .panel-body + .table,
-.panel > .panel-body + .table-responsive,
-.panel > .table + .panel-body,
-.panel > .table-responsive + .panel-body {
- border-top: 1px solid #1c1e22;
-}
-.panel > .table > tbody:first-child > tr:first-child th,
-.panel > .table > tbody:first-child > tr:first-child td {
- border-top: 0;
-}
-.panel > .table-bordered,
-.panel > .table-responsive > .table-bordered {
- border: 0;
-}
-.panel > .table-bordered > thead > tr > th:first-child,
-.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
-.panel > .table-bordered > tbody > tr > th:first-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
-.panel > .table-bordered > tfoot > tr > th:first-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
-.panel > .table-bordered > thead > tr > td:first-child,
-.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
-.panel > .table-bordered > tbody > tr > td:first-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
-.panel > .table-bordered > tfoot > tr > td:first-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
- border-left: 0;
-}
-.panel > .table-bordered > thead > tr > th:last-child,
-.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
-.panel > .table-bordered > tbody > tr > th:last-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
-.panel > .table-bordered > tfoot > tr > th:last-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
-.panel > .table-bordered > thead > tr > td:last-child,
-.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
-.panel > .table-bordered > tbody > tr > td:last-child,
-.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
-.panel > .table-bordered > tfoot > tr > td:last-child,
-.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
- border-right: 0;
-}
-.panel > .table-bordered > thead > tr:first-child > td,
-.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
-.panel > .table-bordered > tbody > tr:first-child > td,
-.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
-.panel > .table-bordered > thead > tr:first-child > th,
-.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
-.panel > .table-bordered > tbody > tr:first-child > th,
-.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
- border-bottom: 0;
-}
-.panel > .table-bordered > tbody > tr:last-child > td,
-.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
-.panel > .table-bordered > tfoot > tr:last-child > td,
-.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
-.panel > .table-bordered > tbody > tr:last-child > th,
-.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
-.panel > .table-bordered > tfoot > tr:last-child > th,
-.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
- border-bottom: 0;
-}
-.panel > .table-responsive {
- border: 0;
- margin-bottom: 0;
-}
-.panel-group {
- margin-bottom: 20px;
-}
-.panel-group .panel {
- margin-bottom: 0;
- border-radius: 4px;
-}
-.panel-group .panel + .panel {
- margin-top: 5px;
-}
-.panel-group .panel-heading {
- border-bottom: 0;
-}
-.panel-group .panel-heading + .panel-collapse > .panel-body,
-.panel-group .panel-heading + .panel-collapse > .list-group {
- border-top: 1px solid rgba(0, 0, 0, 0.6);
-}
-.panel-group .panel-footer {
- border-top: 0;
-}
-.panel-group .panel-footer + .panel-collapse .panel-body {
- border-bottom: 1px solid rgba(0, 0, 0, 0.6);
-}
-.panel-default {
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-default > .panel-heading {
- color: #c8c8c8;
- background-color: #3e444c;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-default > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: rgba(0, 0, 0, 0.6);
-}
-.panel-default > .panel-heading .badge {
- color: #3e444c;
- background-color: #c8c8c8;
-}
-.panel-default > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: rgba(0, 0, 0, 0.6);
-}
-.panel-primary {
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-primary > .panel-heading {
- color: #ffffff;
- background-color: #7a8288;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-primary > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: rgba(0, 0, 0, 0.6);
-}
-.panel-primary > .panel-heading .badge {
- color: #7a8288;
- background-color: #ffffff;
-}
-.panel-primary > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: rgba(0, 0, 0, 0.6);
-}
-.panel-success {
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-success > .panel-heading {
- color: #ffffff;
- background-color: #62c462;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-success > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: rgba(0, 0, 0, 0.6);
-}
-.panel-success > .panel-heading .badge {
- color: #62c462;
- background-color: #ffffff;
-}
-.panel-success > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: rgba(0, 0, 0, 0.6);
-}
-.panel-info {
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-info > .panel-heading {
- color: #ffffff;
- background-color: #5bc0de;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-info > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: rgba(0, 0, 0, 0.6);
-}
-.panel-info > .panel-heading .badge {
- color: #5bc0de;
- background-color: #ffffff;
-}
-.panel-info > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: rgba(0, 0, 0, 0.6);
-}
-.panel-warning {
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-warning > .panel-heading {
- color: #ffffff;
- background-color: #f89406;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-warning > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: rgba(0, 0, 0, 0.6);
-}
-.panel-warning > .panel-heading .badge {
- color: #f89406;
- background-color: #ffffff;
-}
-.panel-warning > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: rgba(0, 0, 0, 0.6);
-}
-.panel-danger {
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-danger > .panel-heading {
- color: #ffffff;
- background-color: #ee5f5b;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.panel-danger > .panel-heading + .panel-collapse > .panel-body {
- border-top-color: rgba(0, 0, 0, 0.6);
-}
-.panel-danger > .panel-heading .badge {
- color: #ee5f5b;
- background-color: #ffffff;
-}
-.panel-danger > .panel-footer + .panel-collapse > .panel-body {
- border-bottom-color: rgba(0, 0, 0, 0.6);
-}
-.embed-responsive {
- position: relative;
- display: block;
- height: 0;
- padding: 0;
- overflow: hidden;
-}
-.embed-responsive .embed-responsive-item,
-.embed-responsive iframe,
-.embed-responsive embed,
-.embed-responsive object,
-.embed-responsive video {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- height: 100%;
- width: 100%;
- border: 0;
-}
-.embed-responsive-16by9 {
- padding-bottom: 56.25%;
-}
-.embed-responsive-4by3 {
- padding-bottom: 75%;
-}
-.well {
- min-height: 20px;
- padding: 19px;
- margin-bottom: 20px;
- background-color: #1c1e22;
- border: 1px solid #0c0d0e;
- border-radius: 4px;
- -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
-}
-.well blockquote {
- border-color: #ddd;
- border-color: rgba(0, 0, 0, 0.15);
-}
-.well-lg {
- padding: 24px;
- border-radius: 6px;
-}
-.well-sm {
- padding: 9px;
- border-radius: 3px;
-}
-.close {
- float: right;
- font-size: 21px;
- font-weight: bold;
- line-height: 1;
- color: #000000;
- text-shadow: 0 1px 0 #ffffff;
- opacity: 0.2;
- filter: alpha(opacity=20);
-}
-.close:hover,
-.close:focus {
- color: #000000;
- text-decoration: none;
- cursor: pointer;
- opacity: 0.5;
- filter: alpha(opacity=50);
-}
-button.close {
- padding: 0;
- cursor: pointer;
- background: transparent;
- border: 0;
- -webkit-appearance: none;
-}
-.modal-open {
- overflow: hidden;
-}
-.modal {
- display: none;
- overflow: hidden;
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1050;
- -webkit-overflow-scrolling: touch;
- outline: 0;
-}
-.modal.fade .modal-dialog {
- -webkit-transform: translate(0, -25%);
- -ms-transform: translate(0, -25%);
- -o-transform: translate(0, -25%);
- transform: translate(0, -25%);
- -webkit-transition: -webkit-transform 0.3s ease-out;
- -o-transition: -o-transform 0.3s ease-out;
- transition: transform 0.3s ease-out;
-}
-.modal.in .modal-dialog {
- -webkit-transform: translate(0, 0);
- -ms-transform: translate(0, 0);
- -o-transform: translate(0, 0);
- transform: translate(0, 0);
-}
-.modal-open .modal {
- overflow-x: hidden;
- overflow-y: auto;
-}
-.modal-dialog {
- position: relative;
- width: auto;
- margin: 10px;
-}
-.modal-content {
- position: relative;
- background-color: #2e3338;
- border: 1px solid #999999;
- border: 1px solid rgba(0, 0, 0, 0.2);
- border-radius: 6px;
- -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
- box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
- -webkit-background-clip: padding-box;
- background-clip: padding-box;
- outline: 0;
-}
-.modal-backdrop {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1040;
- background-color: #000000;
-}
-.modal-backdrop.fade {
- opacity: 0;
- filter: alpha(opacity=0);
-}
-.modal-backdrop.in {
- opacity: 0.5;
- filter: alpha(opacity=50);
-}
-.modal-header {
- padding: 15px;
- border-bottom: 1px solid #1c1e22;
-}
-.modal-header .close {
- margin-top: -2px;
-}
-.modal-title {
- margin: 0;
- line-height: 1.42857143;
-}
-.modal-body {
- position: relative;
- padding: 20px;
-}
-.modal-footer {
- padding: 20px;
- text-align: right;
- border-top: 1px solid #1c1e22;
-}
-.modal-footer .btn + .btn {
- margin-left: 5px;
- margin-bottom: 0;
-}
-.modal-footer .btn-group .btn + .btn {
- margin-left: -1px;
-}
-.modal-footer .btn-block + .btn-block {
- margin-left: 0;
-}
-.modal-scrollbar-measure {
- position: absolute;
- top: -9999px;
- width: 50px;
- height: 50px;
- overflow: scroll;
-}
-@media (min-width: 768px) {
- .modal-dialog {
- width: 600px;
- margin: 30px auto;
- }
- .modal-content {
- -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
- }
- .modal-sm {
- width: 300px;
- }
-}
-@media (min-width: 992px) {
- .modal-lg {
- width: 900px;
- }
-}
-.tooltip {
- position: absolute;
- z-index: 1070;
- display: block;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-style: normal;
- font-weight: normal;
- letter-spacing: normal;
- line-break: auto;
- line-height: 1.42857143;
- text-align: left;
- text-align: start;
- text-decoration: none;
- text-shadow: none;
- text-transform: none;
- white-space: normal;
- word-break: normal;
- word-spacing: normal;
- word-wrap: normal;
- font-size: 12px;
- opacity: 0;
- filter: alpha(opacity=0);
-}
-.tooltip.in {
- opacity: 0.9;
- filter: alpha(opacity=90);
-}
-.tooltip.top {
- margin-top: -3px;
- padding: 5px 0;
-}
-.tooltip.right {
- margin-left: 3px;
- padding: 0 5px;
-}
-.tooltip.bottom {
- margin-top: 3px;
- padding: 5px 0;
-}
-.tooltip.left {
- margin-left: -3px;
- padding: 0 5px;
-}
-.tooltip-inner {
- max-width: 200px;
- padding: 3px 8px;
- color: #ffffff;
- text-align: center;
- background-color: #000000;
- border-radius: 4px;
-}
-.tooltip-arrow {
- position: absolute;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
-}
-.tooltip.top .tooltip-arrow {
- bottom: 0;
- left: 50%;
- margin-left: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000000;
-}
-.tooltip.top-left .tooltip-arrow {
- bottom: 0;
- right: 5px;
- margin-bottom: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000000;
-}
-.tooltip.top-right .tooltip-arrow {
- bottom: 0;
- left: 5px;
- margin-bottom: -5px;
- border-width: 5px 5px 0;
- border-top-color: #000000;
-}
-.tooltip.right .tooltip-arrow {
- top: 50%;
- left: 0;
- margin-top: -5px;
- border-width: 5px 5px 5px 0;
- border-right-color: #000000;
-}
-.tooltip.left .tooltip-arrow {
- top: 50%;
- right: 0;
- margin-top: -5px;
- border-width: 5px 0 5px 5px;
- border-left-color: #000000;
-}
-.tooltip.bottom .tooltip-arrow {
- top: 0;
- left: 50%;
- margin-left: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000000;
-}
-.tooltip.bottom-left .tooltip-arrow {
- top: 0;
- right: 5px;
- margin-top: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000000;
-}
-.tooltip.bottom-right .tooltip-arrow {
- top: 0;
- left: 5px;
- margin-top: -5px;
- border-width: 0 5px 5px;
- border-bottom-color: #000000;
-}
-.popover {
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1060;
- display: none;
- max-width: 276px;
- padding: 1px;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-style: normal;
- font-weight: normal;
- letter-spacing: normal;
- line-break: auto;
- line-height: 1.42857143;
- text-align: left;
- text-align: start;
- text-decoration: none;
- text-shadow: none;
- text-transform: none;
- white-space: normal;
- word-break: normal;
- word-spacing: normal;
- word-wrap: normal;
- font-size: 14px;
- background-color: #2e3338;
- -webkit-background-clip: padding-box;
- background-clip: padding-box;
- border: 1px solid #999999;
- border: 1px solid rgba(0, 0, 0, 0.2);
- border-radius: 6px;
- -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
- box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-}
-.popover.top {
- margin-top: -10px;
-}
-.popover.right {
- margin-left: 10px;
-}
-.popover.bottom {
- margin-top: 10px;
-}
-.popover.left {
- margin-left: -10px;
-}
-.popover-title {
- margin: 0;
- padding: 8px 14px;
- font-size: 14px;
- background-color: #2e3338;
- border-bottom: 1px solid #22262a;
- border-radius: 5px 5px 0 0;
-}
-.popover-content {
- padding: 9px 14px;
-}
-.popover > .arrow,
-.popover > .arrow:after {
- position: absolute;
- display: block;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
-}
-.popover > .arrow {
- border-width: 11px;
-}
-.popover > .arrow:after {
- border-width: 10px;
- content: "";
-}
-.popover.top > .arrow {
- left: 50%;
- margin-left: -11px;
- border-bottom-width: 0;
- border-top-color: #666666;
- border-top-color: rgba(0, 0, 0, 0.25);
- bottom: -11px;
-}
-.popover.top > .arrow:after {
- content: " ";
- bottom: 1px;
- margin-left: -10px;
- border-bottom-width: 0;
- border-top-color: #2e3338;
-}
-.popover.right > .arrow {
- top: 50%;
- left: -11px;
- margin-top: -11px;
- border-left-width: 0;
- border-right-color: #666666;
- border-right-color: rgba(0, 0, 0, 0.25);
-}
-.popover.right > .arrow:after {
- content: " ";
- left: 1px;
- bottom: -10px;
- border-left-width: 0;
- border-right-color: #2e3338;
-}
-.popover.bottom > .arrow {
- left: 50%;
- margin-left: -11px;
- border-top-width: 0;
- border-bottom-color: #666666;
- border-bottom-color: rgba(0, 0, 0, 0.25);
- top: -11px;
-}
-.popover.bottom > .arrow:after {
- content: " ";
- top: 1px;
- margin-left: -10px;
- border-top-width: 0;
- border-bottom-color: #2e3338;
-}
-.popover.left > .arrow {
- top: 50%;
- right: -11px;
- margin-top: -11px;
- border-right-width: 0;
- border-left-color: #666666;
- border-left-color: rgba(0, 0, 0, 0.25);
-}
-.popover.left > .arrow:after {
- content: " ";
- right: 1px;
- border-right-width: 0;
- border-left-color: #2e3338;
- bottom: -10px;
-}
-.carousel {
- position: relative;
-}
-.carousel-inner {
- position: relative;
- overflow: hidden;
- width: 100%;
-}
-.carousel-inner > .item {
- display: none;
- position: relative;
- -webkit-transition: 0.6s ease-in-out left;
- -o-transition: 0.6s ease-in-out left;
- transition: 0.6s ease-in-out left;
-}
-.carousel-inner > .item > img,
-.carousel-inner > .item > a > img {
- line-height: 1;
-}
-@media all and (transform-3d), (-webkit-transform-3d) {
- .carousel-inner > .item {
- -webkit-transition: -webkit-transform 0.6s ease-in-out;
- -o-transition: -o-transform 0.6s ease-in-out;
- transition: transform 0.6s ease-in-out;
- -webkit-backface-visibility: hidden;
- backface-visibility: hidden;
- -webkit-perspective: 1000px;
- perspective: 1000px;
- }
- .carousel-inner > .item.next,
- .carousel-inner > .item.active.right {
- -webkit-transform: translate3d(100%, 0, 0);
- transform: translate3d(100%, 0, 0);
- left: 0;
- }
- .carousel-inner > .item.prev,
- .carousel-inner > .item.active.left {
- -webkit-transform: translate3d(-100%, 0, 0);
- transform: translate3d(-100%, 0, 0);
- left: 0;
- }
- .carousel-inner > .item.next.left,
- .carousel-inner > .item.prev.right,
- .carousel-inner > .item.active {
- -webkit-transform: translate3d(0, 0, 0);
- transform: translate3d(0, 0, 0);
- left: 0;
- }
-}
-.carousel-inner > .active,
-.carousel-inner > .next,
-.carousel-inner > .prev {
- display: block;
-}
-.carousel-inner > .active {
- left: 0;
-}
-.carousel-inner > .next,
-.carousel-inner > .prev {
- position: absolute;
- top: 0;
- width: 100%;
-}
-.carousel-inner > .next {
- left: 100%;
-}
-.carousel-inner > .prev {
- left: -100%;
-}
-.carousel-inner > .next.left,
-.carousel-inner > .prev.right {
- left: 0;
-}
-.carousel-inner > .active.left {
- left: -100%;
-}
-.carousel-inner > .active.right {
- left: 100%;
-}
-.carousel-control {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- width: 15%;
- opacity: 0.5;
- filter: alpha(opacity=50);
- font-size: 20px;
- color: #ffffff;
- text-align: center;
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
- background-color: rgba(0, 0, 0, 0);
-}
-.carousel-control.left {
- background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
- background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
- background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));
- background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
-}
-.carousel-control.right {
- left: auto;
- right: 0;
- background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
- background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
- background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));
- background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
- background-repeat: repeat-x;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
-}
-.carousel-control:hover,
-.carousel-control:focus {
- outline: 0;
- color: #ffffff;
- text-decoration: none;
- opacity: 0.9;
- filter: alpha(opacity=90);
-}
-.carousel-control .icon-prev,
-.carousel-control .icon-next,
-.carousel-control .glyphicon-chevron-left,
-.carousel-control .glyphicon-chevron-right {
- position: absolute;
- top: 50%;
- margin-top: -10px;
- z-index: 5;
- display: inline-block;
-}
-.carousel-control .icon-prev,
-.carousel-control .glyphicon-chevron-left {
- left: 50%;
- margin-left: -10px;
-}
-.carousel-control .icon-next,
-.carousel-control .glyphicon-chevron-right {
- right: 50%;
- margin-right: -10px;
-}
-.carousel-control .icon-prev,
-.carousel-control .icon-next {
- width: 20px;
- height: 20px;
- line-height: 1;
- font-family: serif;
-}
-.carousel-control .icon-prev:before {
- content: '\2039';
-}
-.carousel-control .icon-next:before {
- content: '\203a';
-}
-.carousel-indicators {
- position: absolute;
- bottom: 10px;
- left: 50%;
- z-index: 15;
- width: 60%;
- margin-left: -30%;
- padding-left: 0;
- list-style: none;
- text-align: center;
-}
-.carousel-indicators li {
- display: inline-block;
- width: 10px;
- height: 10px;
- margin: 1px;
- text-indent: -999px;
- border: 1px solid #ffffff;
- border-radius: 10px;
- cursor: pointer;
- background-color: #000 \9;
- background-color: rgba(0, 0, 0, 0);
-}
-.carousel-indicators .active {
- margin: 0;
- width: 12px;
- height: 12px;
- background-color: #ffffff;
-}
-.carousel-caption {
- position: absolute;
- left: 15%;
- right: 15%;
- bottom: 20px;
- z-index: 10;
- padding-top: 20px;
- padding-bottom: 20px;
- color: #ffffff;
- text-align: center;
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
-}
-.carousel-caption .btn {
- text-shadow: none;
-}
-@media screen and (min-width: 768px) {
- .carousel-control .glyphicon-chevron-left,
- .carousel-control .glyphicon-chevron-right,
- .carousel-control .icon-prev,
- .carousel-control .icon-next {
- width: 30px;
- height: 30px;
- margin-top: -10px;
- font-size: 30px;
- }
- .carousel-control .glyphicon-chevron-left,
- .carousel-control .icon-prev {
- margin-left: -10px;
- }
- .carousel-control .glyphicon-chevron-right,
- .carousel-control .icon-next {
- margin-right: -10px;
- }
- .carousel-caption {
- left: 20%;
- right: 20%;
- padding-bottom: 30px;
- }
- .carousel-indicators {
- bottom: 20px;
- }
-}
-.clearfix:before,
-.clearfix:after,
-.dl-horizontal dd:before,
-.dl-horizontal dd:after,
-.container:before,
-.container:after,
-.container-fluid:before,
-.container-fluid:after,
-.row:before,
-.row:after,
-.form-horizontal .form-group:before,
-.form-horizontal .form-group:after,
-.btn-toolbar:before,
-.btn-toolbar:after,
-.btn-group-vertical > .btn-group:before,
-.btn-group-vertical > .btn-group:after,
-.nav:before,
-.nav:after,
-.navbar:before,
-.navbar:after,
-.navbar-header:before,
-.navbar-header:after,
-.navbar-collapse:before,
-.navbar-collapse:after,
-.pager:before,
-.pager:after,
-.panel-body:before,
-.panel-body:after,
-.modal-header:before,
-.modal-header:after,
-.modal-footer:before,
-.modal-footer:after {
- content: " ";
- display: table;
-}
-.clearfix:after,
-.dl-horizontal dd:after,
-.container:after,
-.container-fluid:after,
-.row:after,
-.form-horizontal .form-group:after,
-.btn-toolbar:after,
-.btn-group-vertical > .btn-group:after,
-.nav:after,
-.navbar:after,
-.navbar-header:after,
-.navbar-collapse:after,
-.pager:after,
-.panel-body:after,
-.modal-header:after,
-.modal-footer:after {
- clear: both;
-}
-.center-block {
- display: block;
- margin-left: auto;
- margin-right: auto;
-}
-.pull-right {
- float: right !important;
-}
-.pull-left {
- float: left !important;
-}
-.hide {
- display: none !important;
-}
-.show {
- display: block !important;
-}
-.invisible {
- visibility: hidden;
-}
-.text-hide {
- font: 0/0 a;
- color: transparent;
- text-shadow: none;
- background-color: transparent;
- border: 0;
-}
-.hidden {
- display: none !important;
-}
-.affix {
- position: fixed;
-}
-@-ms-viewport {
- width: device-width;
-}
-.visible-xs,
-.visible-sm,
-.visible-md,
-.visible-lg {
- display: none !important;
-}
-.visible-xs-block,
-.visible-xs-inline,
-.visible-xs-inline-block,
-.visible-sm-block,
-.visible-sm-inline,
-.visible-sm-inline-block,
-.visible-md-block,
-.visible-md-inline,
-.visible-md-inline-block,
-.visible-lg-block,
-.visible-lg-inline,
-.visible-lg-inline-block {
- display: none !important;
-}
-@media (max-width: 767px) {
- .visible-xs {
- display: block !important;
- }
- table.visible-xs {
- display: table !important;
- }
- tr.visible-xs {
- display: table-row !important;
- }
- th.visible-xs,
- td.visible-xs {
- display: table-cell !important;
- }
-}
-@media (max-width: 767px) {
- .visible-xs-block {
- display: block !important;
- }
-}
-@media (max-width: 767px) {
- .visible-xs-inline {
- display: inline !important;
- }
-}
-@media (max-width: 767px) {
- .visible-xs-inline-block {
- display: inline-block !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm {
- display: block !important;
- }
- table.visible-sm {
- display: table !important;
- }
- tr.visible-sm {
- display: table-row !important;
- }
- th.visible-sm,
- td.visible-sm {
- display: table-cell !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm-block {
- display: block !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm-inline {
- display: inline !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .visible-sm-inline-block {
- display: inline-block !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md {
- display: block !important;
- }
- table.visible-md {
- display: table !important;
- }
- tr.visible-md {
- display: table-row !important;
- }
- th.visible-md,
- td.visible-md {
- display: table-cell !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md-block {
- display: block !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md-inline {
- display: inline !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .visible-md-inline-block {
- display: inline-block !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg {
- display: block !important;
- }
- table.visible-lg {
- display: table !important;
- }
- tr.visible-lg {
- display: table-row !important;
- }
- th.visible-lg,
- td.visible-lg {
- display: table-cell !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg-block {
- display: block !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg-inline {
- display: inline !important;
- }
-}
-@media (min-width: 1200px) {
- .visible-lg-inline-block {
- display: inline-block !important;
- }
-}
-@media (max-width: 767px) {
- .hidden-xs {
- display: none !important;
- }
-}
-@media (min-width: 768px) and (max-width: 991px) {
- .hidden-sm {
- display: none !important;
- }
-}
-@media (min-width: 992px) and (max-width: 1199px) {
- .hidden-md {
- display: none !important;
- }
-}
-@media (min-width: 1200px) {
- .hidden-lg {
- display: none !important;
- }
-}
-.visible-print {
- display: none !important;
-}
-@media print {
- .visible-print {
- display: block !important;
- }
- table.visible-print {
- display: table !important;
- }
- tr.visible-print {
- display: table-row !important;
- }
- th.visible-print,
- td.visible-print {
- display: table-cell !important;
- }
-}
-.visible-print-block {
- display: none !important;
-}
-@media print {
- .visible-print-block {
- display: block !important;
- }
-}
-.visible-print-inline {
- display: none !important;
-}
-@media print {
- .visible-print-inline {
- display: inline !important;
- }
-}
-.visible-print-inline-block {
- display: none !important;
-}
-@media print {
- .visible-print-inline-block {
- display: inline-block !important;
- }
-}
-@media print {
- .hidden-print {
- display: none !important;
- }
-}
-.navbar {
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
- border: 1px solid rgba(0, 0, 0, 0.6);
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-}
-.navbar .navbar-nav > li > a {
- border-right: 1px solid rgba(0, 0, 0, 0.2);
- border-left: 1px solid rgba(255, 255, 255, 0.1);
-}
-.navbar .navbar-nav > li > a:hover {
- background-image: -webkit-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -o-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#020202), color-stop(40%, #101112), to(#141618));
- background-image: linear-gradient(#020202, #101112 40%, #141618);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff141618', GradientType=0);
- -webkit-filter: none;
- filter: none;
- border-left-color: transparent;
-}
-.navbar-inverse {
- background-image: -webkit-linear-gradient(#8a9196, #7a8288 60%, #70787d);
- background-image: -o-linear-gradient(#8a9196, #7a8288 60%, #70787d);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#8a9196), color-stop(60%, #7a8288), to(#70787d));
- background-image: linear-gradient(#8a9196, #7a8288 60%, #70787d);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8a9196', endColorstr='#ff70787d', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.navbar-inverse .badge {
- background-color: #5d6368;
-}
-.navbar-inverse .navbar-nav > li > a:hover {
- background-image: -webkit-linear-gradient(#404448, #4e5458 40%, #53595d);
- background-image: -o-linear-gradient(#404448, #4e5458 40%, #53595d);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#404448), color-stop(40%, #4e5458), to(#53595d));
- background-image: linear-gradient(#404448, #4e5458 40%, #53595d);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff404448', endColorstr='#ff53595d', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.navbar .nav .open > a {
- border-color: transparent;
-}
-.navbar-nav > li.active > a {
- border-left-color: transparent;
-}
-.navbar-form {
- margin-left: 5px;
- margin-right: 5px;
-}
-.btn,
-.btn:hover {
- border-color: rgba(0, 0, 0, 0.6);
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-}
-.btn-default {
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-default:hover {
- background-image: -webkit-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -o-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#020202), color-stop(40%, #101112), to(#141618));
- background-image: linear-gradient(#020202, #101112 40%, #141618);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff141618', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-primary {
- background-image: -webkit-linear-gradient(#8a9196, #7a8288 60%, #70787d);
- background-image: -o-linear-gradient(#8a9196, #7a8288 60%, #70787d);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#8a9196), color-stop(60%, #7a8288), to(#70787d));
- background-image: linear-gradient(#8a9196, #7a8288 60%, #70787d);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8a9196', endColorstr='#ff70787d', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-primary:hover {
- background-image: -webkit-linear-gradient(#404448, #4e5458 40%, #53595d);
- background-image: -o-linear-gradient(#404448, #4e5458 40%, #53595d);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#404448), color-stop(40%, #4e5458), to(#53595d));
- background-image: linear-gradient(#404448, #4e5458 40%, #53595d);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff404448', endColorstr='#ff53595d', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-success {
- background-image: -webkit-linear-gradient(#78cc78, #62c462 60%, #53be53);
- background-image: -o-linear-gradient(#78cc78, #62c462 60%, #53be53);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#78cc78), color-stop(60%, #62c462), to(#53be53));
- background-image: linear-gradient(#78cc78, #62c462 60%, #53be53);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff78cc78', endColorstr='#ff53be53', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-success:hover {
- background-image: -webkit-linear-gradient(#2f7d2f, #379337 40%, #3a9a3a);
- background-image: -o-linear-gradient(#2f7d2f, #379337 40%, #3a9a3a);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#2f7d2f), color-stop(40%, #379337), to(#3a9a3a));
- background-image: linear-gradient(#2f7d2f, #379337 40%, #3a9a3a);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2f7d2f', endColorstr='#ff3a9a3a', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-info {
- background-image: -webkit-linear-gradient(#74cae3, #5bc0de 60%, #4ab9db);
- background-image: -o-linear-gradient(#74cae3, #5bc0de 60%, #4ab9db);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#74cae3), color-stop(60%, #5bc0de), to(#4ab9db));
- background-image: linear-gradient(#74cae3, #5bc0de 60%, #4ab9db);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff74cae3', endColorstr='#ff4ab9db', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-info:hover {
- background-image: -webkit-linear-gradient(#20829f, #2596b8 40%, #279dc1);
- background-image: -o-linear-gradient(#20829f, #2596b8 40%, #279dc1);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#20829f), color-stop(40%, #2596b8), to(#279dc1));
- background-image: linear-gradient(#20829f, #2596b8 40%, #279dc1);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff20829f', endColorstr='#ff279dc1', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-warning {
- background-image: -webkit-linear-gradient(#faa123, #f89406 60%, #e48806);
- background-image: -o-linear-gradient(#faa123, #f89406 60%, #e48806);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#faa123), color-stop(60%, #f89406), to(#e48806));
- background-image: linear-gradient(#faa123, #f89406 60%, #e48806);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffaa123', endColorstr='#ffe48806', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-warning:hover {
- background-image: -webkit-linear-gradient(#804d03, #9e5f04 40%, #a86404);
- background-image: -o-linear-gradient(#804d03, #9e5f04 40%, #a86404);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#804d03), color-stop(40%, #9e5f04), to(#a86404));
- background-image: linear-gradient(#804d03, #9e5f04 40%, #a86404);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff804d03', endColorstr='#ffa86404', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-danger {
- background-image: -webkit-linear-gradient(#f17a77, #ee5f5b 60%, #ec4d49);
- background-image: -o-linear-gradient(#f17a77, #ee5f5b 60%, #ec4d49);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#f17a77), color-stop(60%, #ee5f5b), to(#ec4d49));
- background-image: linear-gradient(#f17a77, #ee5f5b 60%, #ec4d49);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff17a77', endColorstr='#ffec4d49', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-danger:hover {
- background-image: -webkit-linear-gradient(#bb1813, #d71c16 40%, #e01d17);
- background-image: -o-linear-gradient(#bb1813, #d71c16 40%, #e01d17);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#bb1813), color-stop(40%, #d71c16), to(#e01d17));
- background-image: linear-gradient(#bb1813, #d71c16 40%, #e01d17);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbb1813', endColorstr='#ffe01d17', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.btn-link,
-.btn-link:hover {
- border-color: transparent;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3);
-}
-.text-primary,
-.text-primary:hover {
- color: #7a8288;
-}
-.text-success,
-.text-success:hover {
- color: #62c462;
-}
-.text-danger,
-.text-danger:hover {
- color: #ee5f5b;
-}
-.text-warning,
-.text-warning:hover {
- color: #f89406;
-}
-.text-info,
-.text-info:hover {
- color: #5bc0de;
-}
-.table .success,
-.table .warning,
-.table .danger,
-.table .info {
- color: #fff;
-}
-.table-bordered tbody tr.success td,
-.table-bordered tbody tr.warning td,
-.table-bordered tbody tr.danger td,
-.table-bordered tbody tr.success:hover td,
-.table-bordered tbody tr.warning:hover td,
-.table-bordered tbody tr.danger:hover td {
- border-color: #1c1e22;
-}
-.table-responsive > .table {
- background-color: #2e3338;
-}
-input,
-textarea {
- color: #272b30;
-}
-.has-warning .help-block,
-.has-warning .control-label,
-.has-warning .radio,
-.has-warning .checkbox,
-.has-warning .radio-inline,
-.has-warning .checkbox-inline,
-.has-warning.radio label,
-.has-warning.checkbox label,
-.has-warning.radio-inline label,
-.has-warning.checkbox-inline label,
-.has-warning .form-control-feedback {
- color: #f89406;
-}
-.has-warning .form-control,
-.has-warning .form-control:focus {
- border-color: #f89406;
-}
-.has-warning .input-group-addon {
- background-color: #3a3f44;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.has-error .help-block,
-.has-error .control-label,
-.has-error .radio,
-.has-error .checkbox,
-.has-error .radio-inline,
-.has-error .checkbox-inline,
-.has-error.radio label,
-.has-error.checkbox label,
-.has-error.radio-inline label,
-.has-error.checkbox-inline label,
-.has-error .form-control-feedback {
- color: #ee5f5b;
-}
-.has-error .form-control,
-.has-error .form-control:focus {
- border-color: #ee5f5b;
-}
-.has-error .input-group-addon {
- background-color: #3a3f44;
- border-color: rgba(0, 0, 0, 0.6);
-}
-.has-success .help-block,
-.has-success .control-label,
-.has-success .radio,
-.has-success .checkbox,
-.has-success .radio-inline,
-.has-success .checkbox-inline,
-.has-success.radio label,
-.has-success.checkbox label,
-.has-success.radio-inline label,
-.has-success.checkbox-inline label,
-.has-success .form-control-feedback {
- color: #62c462;
-}
-.has-success .form-control,
-.has-success .form-control:focus {
- border-color: #62c462;
-}
-.has-success .input-group-addon {
- background-color: #3a3f44;
- border-color: rgba(0, 0, 0, 0.6);
-}
-legend {
- color: #fff;
-}
-.input-group-addon {
- background-color: #3a3f44;
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
- color: #ffffff;
-}
-.nav .open > a,
-.nav .open > a:hover,
-.nav .open > a:focus {
- border-color: rgba(0, 0, 0, 0.6);
-}
-.nav-pills > li > a {
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
- border: 1px solid rgba(0, 0, 0, 0.6);
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-}
-.nav-pills > li > a:hover {
- background-image: -webkit-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -o-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#020202), color-stop(40%, #101112), to(#141618));
- background-image: linear-gradient(#020202, #101112 40%, #141618);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff141618', GradientType=0);
- -webkit-filter: none;
- filter: none;
- border: 1px solid rgba(0, 0, 0, 0.6);
-}
-.nav-pills > li.active > a,
-.nav-pills > li.active > a:hover {
- background-color: none;
- background-image: -webkit-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -o-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#020202), color-stop(40%, #101112), to(#141618));
- background-image: linear-gradient(#020202, #101112 40%, #141618);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff141618', GradientType=0);
- -webkit-filter: none;
- filter: none;
- border: 1px solid rgba(0, 0, 0, 0.6);
-}
-.nav-pills > li.disabled > a,
-.nav-pills > li.disabled > a:hover {
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.pagination > li > a,
-.pagination > li > span {
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.pagination > li > a:hover,
-.pagination > li > span:hover {
- background-image: -webkit-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -o-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#020202), color-stop(40%, #101112), to(#141618));
- background-image: linear-gradient(#020202, #101112 40%, #141618);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff141618', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.pagination > li.active > a,
-.pagination > li.active > span {
- background-image: -webkit-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -o-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#020202), color-stop(40%, #101112), to(#141618));
- background-image: linear-gradient(#020202, #101112 40%, #141618);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff141618', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.pagination > li.disabled > a,
-.pagination > li.disabled > a:hover,
-.pagination > li.disabled > span,
-.pagination > li.disabled > span:hover {
- background-color: transparent;
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.pager > li > a {
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
-}
-.pager > li > a:hover {
- background-image: -webkit-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -o-linear-gradient(#020202, #101112 40%, #141618);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#020202), color-stop(40%, #101112), to(#141618));
- background-image: linear-gradient(#020202, #101112 40%, #141618);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff141618', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.pager > li.disabled > a,
-.pager > li.disabled > a:hover {
- background-color: transparent;
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.breadcrumb {
- border: 1px solid rgba(0, 0, 0, 0.6);
- text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
- background-image: -webkit-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -o-linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-image: -webkit-gradient(linear, left top, left bottom, from(#484e55), color-stop(60%, #3a3f44), to(#313539));
- background-image: linear-gradient(#484e55, #3a3f44 60%, #313539);
- background-repeat: no-repeat;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff484e55', endColorstr='#ff313539', GradientType=0);
- -webkit-filter: none;
- filter: none;
-}
-.alert .alert-link,
-.alert a {
- color: #fff;
- text-decoration: underline;
-}
-.alert .close {
- color: #000000;
- text-decoration: none;
-}
-a.thumbnail:hover,
-a.thumbnail:focus,
-a.thumbnail.active {
- border-color: #0c0d0e;
-}
-a.list-group-item.active,
-a.list-group-item.active:hover,
-a.list-group-item.active:focus {
- border-color: rgba(0, 0, 0, 0.6);
-}
-a.list-group-item-success.active {
- background-color: #62c462;
-}
-a.list-group-item-success.active:hover,
-a.list-group-item-success.active:focus {
- background-color: #4fbd4f;
-}
-a.list-group-item-warning.active {
- background-color: #f89406;
-}
-a.list-group-item-warning.active:hover,
-a.list-group-item-warning.active:focus {
- background-color: #df8505;
-}
-a.list-group-item-danger.active {
- background-color: #ee5f5b;
-}
-a.list-group-item-danger.active:hover,
-a.list-group-item-danger.active:focus {
- background-color: #ec4844;
-}
-.jumbotron {
- border: 1px solid rgba(0, 0, 0, 0.6);
-}
-.panel-primary .panel-heading,
-.panel-success .panel-heading,
-.panel-danger .panel-heading,
-.panel-warning .panel-heading,
-.panel-info .panel-heading {
- border-color: #000;
-}
diff --git a/debian/missing-sources/c3.css b/debian/missing-sources/c3-0.4.11.css
index 5de1edfae..fda424272 100644
--- a/debian/missing-sources/c3.css
+++ b/debian/missing-sources/c3-0.4.11.css
@@ -1,7 +1,7 @@
/*-- Chart --*/
.c3 svg {
font: 10px sans-serif;
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
+ -webkit-tap-highlight-color: transparent; }
.c3 path, .c3 line {
fill: none;
@@ -12,7 +12,11 @@
-moz-user-select: none;
user-select: none; }
-.c3-legend-item-tile, .c3-xgrid-focus, .c3-ygrid, .c3-event-rect, .c3-bars path {
+.c3-legend-item-tile,
+.c3-xgrid-focus,
+.c3-ygrid,
+.c3-event-rect,
+.c3-bars path {
shape-rendering: crispEdges; }
.c3-chart-arc path {
@@ -71,11 +75,11 @@
/*-- Region --*/
.c3-region {
fill: steelblue;
- fill-opacity: 0.1; }
+ fill-opacity: .1; }
/*-- Brush --*/
.c3-brush .extent {
- fill-opacity: 0.1; }
+ fill-opacity: .1; }
/*-- Select - Drag --*/
/*-- Legend --*/
diff --git a/debian/missing-sources/c3.js b/debian/missing-sources/c3-0.4.11.js
index aca979c05..2ce7f7e0f 100644
--- a/debian/missing-sources/c3.js
+++ b/debian/missing-sources/c3-0.4.11.js
@@ -3,7 +3,7 @@
/*global define, module, exports, require */
- var c3 = { version: "0.4.11-rc4" };
+ var c3 = { version: "0.4.11" };
var c3_chart_fn,
c3_chart_internal_fn,
@@ -86,7 +86,7 @@
$$.initParams();
if (config.data_url) {
- $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_keys, $$.initWithData);
+ $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_headers, config.data_keys, $$.initWithData);
}
else if (config.data_json) {
$$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
@@ -424,7 +424,7 @@
// for arc
$$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
$$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
- if ($$.hasType('gauge')) {
+ if ($$.hasType('gauge') && !config.gauge_fullCircle) {
$$.arcHeight += $$.height - $$.getGaugeLabelHeight();
}
if ($$.updateRadius) { $$.updateRadius(); }
@@ -1085,6 +1085,7 @@
zoom_onzoomend: function () {},
zoom_x_min: undefined,
zoom_x_max: undefined,
+ interaction_brighten: true,
interaction_enabled: true,
onmouseover: function () {},
onmouseout: function () {},
@@ -1123,6 +1124,7 @@
data_onselected: function () {},
data_onunselected: function () {},
data_url: undefined,
+ data_headers: undefined,
data_json: undefined,
data_rows: undefined,
data_columns: undefined,
@@ -1186,7 +1188,8 @@
axis_y_label: {},
axis_y_tick_format: undefined,
axis_y_tick_outer: true,
- axis_y_tick_values: null,
+ axis_y_tick_values: null,
+ axis_y_tick_rotate: 0,
axis_y_tick_count: undefined,
axis_y_tick_time_value: undefined,
axis_y_tick_time_interval: undefined,
@@ -1233,17 +1236,21 @@
bar_zerobased: true,
// area
area_zerobased: true,
+ area_above: false,
// pie
pie_label_show: true,
pie_label_format: undefined,
pie_label_threshold: 0.05,
+ pie_label_ratio: undefined,
pie_expand: {},
pie_expand_duration: 50,
// gauge
+ gauge_fullCircle: false,
gauge_label_show: true,
gauge_label_format: undefined,
gauge_min: 0,
gauge_max: 100,
+ gauge_startingAngle: -1 * Math.PI/2,
gauge_units: undefined,
gauge_width: undefined,
gauge_expand: {},
@@ -1252,6 +1259,7 @@
donut_label_show: true,
donut_label_format: undefined,
donut_label_threshold: 0.05,
+ donut_label_ratio: undefined,
donut_width: undefined,
donut_title: "",
donut_expand: {},
@@ -2018,9 +2026,15 @@
return current;
};
- c3_chart_internal_fn.convertUrlToData = function (url, mimeType, keys, done) {
+ c3_chart_internal_fn.convertUrlToData = function (url, mimeType, headers, keys, done) {
var $$ = this, type = mimeType ? mimeType : 'csv';
- $$.d3.xhr(url, function (error, data) {
+ var req = $$.d3.xhr(url);
+ if (headers) {
+ Object.keys(headers).forEach(function (header) {
+ req.header(header, headers[header]);
+ });
+ }
+ req.get(function (error, data) {
var d;
if (!data) {
throw new Error(error.responseURL + ' ' + error.status + ' (' + error.statusText + ')');
@@ -2068,7 +2082,10 @@
var new_row = [];
targetKeys.forEach(function (key) {
// convert undefined to null because undefined data will be removed in convertDataToTargets()
- var v = isUndefined(o[key]) ? null : o[key];
+ var v = $$.findValueInJson(o, key);
+ if (isUndefined(v)) {
+ v = null;
+ }
new_row.push(v);
});
new_rows.push(new_row);
@@ -2082,6 +2099,20 @@
}
return data;
};
+ c3_chart_internal_fn.findValueInJson = function (object, path) {
+ path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties (replace [] with .)
+ path = path.replace(/^\./, ''); // strip a leading dot
+ var pathArray = path.split('.');
+ for (var i = 0; i < pathArray.length; ++i) {
+ var k = pathArray[i];
+ if (k in object) {
+ object = object[k];
+ } else {
+ return;
+ }
+ }
+ return object;
+ };
c3_chart_internal_fn.convertRowsToData = function (rows) {
var keys = rows[0], new_row = {}, new_rows = [], i, j;
for (i = 1; i < rows.length; i++) {
@@ -2160,12 +2191,20 @@
id: convertedId,
id_org: id,
values: data.map(function (d, i) {
- var xKey = $$.getXKey(id), rawX = d[xKey], x = $$.generateTargetX(rawX, id, i),
- value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null;
+ var xKey = $$.getXKey(id), rawX = d[xKey],
+ value = d[id] !== null && !isNaN(d[id]) ? +d[id] : null, x;
// use x as categories if custom x and categorized
- if ($$.isCustomX() && $$.isCategorized() && index === 0 && rawX) {
- if (i === 0) { config.axis_x_categories = []; }
- config.axis_x_categories.push(rawX);
+ if ($$.isCustomX() && $$.isCategorized() && index === 0 && !isUndefined(rawX)) {
+ if (index === 0 && i === 0) {
+ config.axis_x_categories = [];
+ }
+ x = config.axis_x_categories.indexOf(rawX);
+ if (x === -1) {
+ x = config.axis_x_categories.length;
+ config.axis_x_categories.push(rawX);
+ }
+ } else {
+ x = $$.generateTargetX(rawX, id, i);
}
// mark as x = undefined if value is undefined and filter to remove after mapped
if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
@@ -2256,7 +2295,7 @@
$$.load($$.convertDataToTargets(args.data), args);
}
else if (args.url) {
- $$.convertUrlToData(args.url, args.mimeType, args.keys, function (data) {
+ $$.convertUrlToData(args.url, args.mimeType, args.headers, args.keys, function (data) {
$$.load($$.convertDataToTargets(data), args);
});
}
@@ -2655,7 +2694,7 @@
c3_chart_internal_fn.getCurrentHeight = function () {
var $$ = this, config = $$.config,
h = config.size_height ? config.size_height : $$.getParentHeight();
- return h > 0 ? h : 320 / ($$.hasType('gauge') ? 2 : 1);
+ return h > 0 ? h : 320 / ($$.hasType('gauge') && !config.gauge_fullCircle ? 2 : 1);
};
c3_chart_internal_fn.getCurrentPaddingTop = function () {
var $$ = this,
@@ -2745,12 +2784,18 @@
var $$ = this, config = $$.config, h = 30;
if (axisId === 'x' && !config.axis_x_show) { return 8; }
if (axisId === 'x' && config.axis_x_height) { return config.axis_x_height; }
- if (axisId === 'y' && !config.axis_y_show) { return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1; }
+ if (axisId === 'y' && !config.axis_y_show) {
+ return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
+ }
if (axisId === 'y2' && !config.axis_y2_show) { return $$.rotated_padding_top; }
// Calculate x axis height when tick rotated
if (axisId === 'x' && !config.axis_rotated && config.axis_x_tick_rotate) {
h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);
}
+ // Calculate y axis height when tick rotated
+ if (axisId === 'y' && config.axis_rotated && config.axis_y_tick_rotate) {
+ h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_y_tick_rotate) / 180);
+ }
return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === 'y2' ? -10 : 0);
};
@@ -3093,7 +3138,7 @@
return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);
};
- area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(value0).y1(value1);
+ area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(config.area_above ? 0 : value0).y1(value1);
if (!config.line_connectNull) {
area = area.defined(function (d) { return d.value !== null; });
}
@@ -3215,7 +3260,7 @@
};
c3_chart_internal_fn.pointSelectR = function (d) {
var $$ = this, config = $$.config;
- return config.point_select_r ? config.point_select_r : $$.pointR(d) * 4;
+ return isFunction(config.point_select_r) ? config.point_select_r(d) : ((config.point_select_r) ? config.point_select_r : $$.pointR(d) * 4);
};
c3_chart_internal_fn.isWithinCircle = function (that, r) {
var d3 = this.d3,
@@ -3846,19 +3891,21 @@
orderAsc = $$.isOrderAsc();
if (config.data_groups.length === 0) {
- d.sort(function(a,b){
- return orderAsc ? a.value - b.value : b.value - a.value;
+ d.sort(function(a, b){
+ var v1 = a ? a.value : null, v2 = b ? b.value : null;
+ return orderAsc ? v1 - v2 : v2 - v1;
});
} else {
var ids = $$.orderTargets($$.data.targets).map(function (i) {
return i.id;
});
d.sort(function(a, b) {
- if (a.value > 0 && b.value > 0) {
- return orderAsc ? ids.indexOf(a.id) - ids.indexOf(b.id) : ids.indexOf(b.id) - ids.indexOf(a.id);
- } else {
- return orderAsc ? a.value - b.value : b.value - a.value;
+ var v1 = a ? a.value : null, v2 = b ? b.value : null;
+ if (v1 > 0 && v2 > 0) {
+ v1 = a ? ids.indexOf(a.id) : null;
+ v2 = b ? ids.indexOf(b.id) : null;
}
+ return orderAsc ? v1 - v2 : v2 - v1;
});
}
@@ -3866,15 +3913,15 @@
if (! (d[i] && (d[i].value || d[i].value === 0))) { continue; }
if (! text) {
- title = titleFormat ? titleFormat(d[i].x) : d[i].x;
+ title = sanitise(titleFormat ? titleFormat(d[i].x) : d[i].x);
text = "<table class='" + $$.CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
}
- value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
+ value = sanitise(valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index, d));
if (value !== undefined) {
// Skip elements when their name is set to null
if (d[i].name === null) { continue; }
- name = nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index);
+ name = sanitise(nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index));
bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
text += "<tr class='" + $$.CLASS.tooltipName + "-" + $$.getTargetSelectorSuffix(d[i].id) + "'>";
@@ -4394,17 +4441,16 @@
}
return tickValues;
};
- Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition) {
- var axisParams = {
- withOuterTick: withOuterTick,
- withoutTransition: withoutTransition,
- },
- $$ = this.owner,
- d3 = $$.d3,
- config = $$.config,
- axis = c3_axis(d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
+ Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
+ var $$ = this.owner, config = $$.config,
+ axisParams = {
+ withOuterTick: withOuterTick,
+ withoutTransition: withoutTransition,
+ tickTextRotate: withoutRotateTickText ? 0 : config.axis_y_tick_rotate
+ },
+ axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
if ($$.isTimeSeriesY()) {
- axis.ticks(d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
+ axis.ticks($$.d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
} else {
axis.tickValues(tickValues);
}
@@ -4594,10 +4640,10 @@
targetsToShow = $$.filterTargetsToShow($$.data.targets);
if (id === 'y') {
scale = $$.y.copy().domain($$.getYDomain(targetsToShow, 'y'));
- axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true);
+ axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true, true);
} else if (id === 'y2') {
scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, 'y2'));
- axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true);
+ axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true, true);
} else {
scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
@@ -4812,9 +4858,9 @@
if ($$.isGaugeType(d.data)) {
gMin = config.gauge_min;
gMax = config.gauge_max;
- gTic = (Math.PI) / (gMax - gMin);
+ gTic = (Math.PI * (config.gauge_fullCircle ? 2 : 1)) / (gMax - gMin);
gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : (gMax - gMin);
- d.startAngle = -1 * (Math.PI / 2);
+ d.startAngle = config.gauge_startingAngle;
d.endAngle = d.startAngle + gTic * gValue;
}
return found ? d : null;
@@ -4849,15 +4895,20 @@
c3_chart_internal_fn.transformForArcLabel = function (d) {
- var $$ = this,
+ var $$ = this, config = $$.config,
updated = $$.updateAngle(d), c, x, y, h, ratio, translate = "";
if (updated && !$$.hasType('gauge')) {
c = this.svgArc.centroid(updated);
x = isNaN(c[0]) ? 0 : c[0];
y = isNaN(c[1]) ? 0 : c[1];
h = Math.sqrt(x * x + y * y);
- // TODO: ratio should be an option?
- ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
+ if ($$.hasType('donut') && config.donut_label_ratio) {
+ ratio = isFunction(config.donut_label_ratio) ? config.donut_label_ratio(d, $$.radius, h) : config.donut_label_ratio;
+ } else if ($$.hasType('pie') && config.pie_label_ratio) {
+ ratio = isFunction(config.pie_label_ratio) ? config.pie_label_ratio(d, $$.radius, h) : config.pie_label_ratio;
+ } else {
+ ratio = $$.radius && h ? (36 / $$.radius > 0.375 ? 1.175 - 36 / $$.radius : 0.8) * $$.radius / h : 0;
+ }
translate = "translate(" + (x * ratio) + ',' + (y * ratio) + ")";
}
return translate;
@@ -4865,7 +4916,8 @@
c3_chart_internal_fn.getArcRatio = function (d) {
var $$ = this,
- whole = $$.hasType('gauge') ? Math.PI : (Math.PI * 2);
+ config = $$.config,
+ whole = Math.PI * ($$.hasType('gauge') && !config.gauge_fullCircle ? 1 : 2);
return d ? (d.endAngle - d.startAngle) / whole : null;
};
@@ -5040,7 +5092,7 @@
.style("opacity", 0)
.each(function (d) {
if ($$.isGaugeType(d.data)) {
- d.startAngle = d.endAngle = -1 * (Math.PI / 2);
+ d.startAngle = d.endAngle = config.gauge_startingAngle;
}
this._current = d;
});
@@ -5150,8 +5202,8 @@
.attr("d", function () {
var d = {
data: [{value: config.gauge_max}],
- startAngle: -1 * (Math.PI / 2),
- endAngle: Math.PI / 2
+ startAngle: config.gauge_startingAngle,
+ endAngle: -1 * config.gauge_startingAngle
};
return $$.getArc(d, true, true);
});
@@ -5159,11 +5211,11 @@
.attr("dy", ".75em")
.text(config.gauge_label_show ? config.gauge_units : '');
$$.arcs.select('.' + CLASS.chartArcsGaugeMin)
- .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / 2)) + "px")
+ .attr("dx", -1 * ($$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2))) + "px")
.attr("dy", "1.2em")
.text(config.gauge_label_show ? config.gauge_min : '');
$$.arcs.select('.' + CLASS.chartArcsGaugeMax)
- .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / 2) + "px")
+ .attr("dx", $$.innerRadius + (($$.radius - $$.innerRadius) / (config.gauge_fullCircle ? 1 : 2)) + "px")
.attr("dy", "1.2em")
.text(config.gauge_label_show ? config.gauge_max : '');
}
@@ -5206,16 +5258,23 @@
$$.mainRegion = $$.main.select('.' + CLASS.regions).selectAll('.' + CLASS.region)
.data(config.regions);
$$.mainRegion.enter().append('g')
- .attr('class', $$.classRegion.bind($$))
.append('rect')
.style("fill-opacity", 0);
+ $$.mainRegion
+ .attr('class', $$.classRegion.bind($$));
$$.mainRegion.exit().transition().duration(duration)
.style("opacity", 0)
.remove();
};
c3_chart_internal_fn.redrawRegion = function (withTransition) {
var $$ = this,
- regions = $$.mainRegion.selectAll('rect'),
+ regions = $$.mainRegion.selectAll('rect').each(function () {
+ // data is binded to g and it's not transferred to rect (child node) automatically,
+ // then data of each rect has to be updated manually.
+ // TODO: there should be more efficient way to solve this?
+ var parentData = $$.d3.select(this.parentNode).datum();
+ $$.d3.select(this).datum(parentData);
+ }),
x = $$.regionX.bind($$),
y = $$.regionY.bind($$),
w = $$.regionWidth.bind($$),
@@ -5387,14 +5446,18 @@
c3_chart_internal_fn.selectPath = function (target, d) {
var $$ = this;
$$.config.data_onselected.call($$, d, target.node());
- target.transition().duration(100)
- .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
+ if ($$.config.interaction_brighten) {
+ target.transition().duration(100)
+ .style("fill", function () { return $$.d3.rgb($$.color(d)).brighter(0.75); });
+ }
};
c3_chart_internal_fn.unselectPath = function (target, d) {
var $$ = this;
$$.config.data_onunselected.call($$, d, target.node());
- target.transition().duration(100)
- .style("fill", function () { return $$.color(d); });
+ if ($$.config.interaction_brighten) {
+ target.transition().duration(100)
+ .style("fill", function () { return $$.color(d); });
+ }
};
c3_chart_internal_fn.togglePath = function (selected, target, d, i) {
selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
@@ -6037,6 +6100,9 @@
});
return found;
},
+ sanitise = c3_chart_internal_fn.sanitise = function (str) {
+ return typeof str === 'string' ? str.replace(/</g, '&lt;').replace(/>/g, '&gt;') : str;
+ },
getPathBox = c3_chart_internal_fn.getPathBox = function (path) {
var box = path.getBoundingClientRect(),
items = [path.pathSegList.getItem(0), path.pathSegList.getItem(1)],
@@ -6217,6 +6283,10 @@
if (args.xs) {
$$.addXs(args.xs);
}
+ // update names if exists
+ if ('names' in args) {
+ c3_chart_fn.data.names.bind(this)(args.names);
+ }
// update classes if exists
if ('classes' in args) {
Object.keys(args.classes).forEach(function (id) {
@@ -6473,7 +6543,7 @@
translateX = diffDomain(domain) / 2;
}
}
- } else if (flow.orgDataCount === 1 || flowStart.x === flowEnd.x) {
+ } else if (flow.orgDataCount === 1 || (flowStart && flowStart.x) === (flowEnd && flowEnd.x)) {
translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
} else {
if ($$.isTimeSeries()) {
@@ -7278,6 +7348,8 @@
return ua.indexOf('Chrome') >= 0;
};
+ /* jshint ignore:start */
+
// PhantomJS doesn't have support for Function.prototype.bind, which has caused confusion. Use
// this polyfill to avoid the confusion.
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill
@@ -7304,6 +7376,821 @@
};
}
+ //SVGPathSeg API polyfill
+ //https://github.com/progers/pathseg
+ //
+ //This is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
+ //SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
+ //changes which were implemented in Firefox 43 and Chrome 46.
+ //Chrome 48 removes these APIs, so this polyfill is required.
+
+ (function() { "use strict";
+ if (!("SVGPathSeg" in window)) {
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
+ window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
+ this.pathSegType = type;
+ this.pathSegTypeAsLetter = typeAsLetter;
+ this._owningPathSegList = owningPathSegList;
+ }
+
+ SVGPathSeg.PATHSEG_UNKNOWN = 0;
+ SVGPathSeg.PATHSEG_CLOSEPATH = 1;
+ SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
+ SVGPathSeg.PATHSEG_MOVETO_REL = 3;
+ SVGPathSeg.PATHSEG_LINETO_ABS = 4;
+ SVGPathSeg.PATHSEG_LINETO_REL = 5;
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
+ SVGPathSeg.PATHSEG_ARC_ABS = 10;
+ SVGPathSeg.PATHSEG_ARC_REL = 11;
+ SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
+ SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
+ SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
+ SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
+ SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
+ SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
+
+ // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
+ SVGPathSeg.prototype._segmentChanged = function() {
+ if (this._owningPathSegList)
+ this._owningPathSegList.segmentChanged(this);
+ }
+
+ window.SVGPathSegClosePath = function(owningPathSegList) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CLOSEPATH, "z", owningPathSegList);
+ }
+ SVGPathSegClosePath.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegClosePath.prototype.toString = function() { return "[object SVGPathSegClosePath]"; }
+ SVGPathSegClosePath.prototype._asPathString = function() { return this.pathSegTypeAsLetter; }
+ SVGPathSegClosePath.prototype.clone = function() { return new SVGPathSegClosePath(undefined); }
+
+ window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_ABS, "M", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ SVGPathSegMovetoAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegMovetoAbs.prototype.toString = function() { return "[object SVGPathSegMovetoAbs]"; }
+ SVGPathSegMovetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
+ SVGPathSegMovetoAbs.prototype.clone = function() { return new SVGPathSegMovetoAbs(undefined, this._x, this._y); }
+ Object.defineProperty(SVGPathSegMovetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegMovetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_MOVETO_REL, "m", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ SVGPathSegMovetoRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegMovetoRel.prototype.toString = function() { return "[object SVGPathSegMovetoRel]"; }
+ SVGPathSegMovetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
+ SVGPathSegMovetoRel.prototype.clone = function() { return new SVGPathSegMovetoRel(undefined, this._x, this._y); }
+ Object.defineProperty(SVGPathSegMovetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegMovetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_ABS, "L", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ SVGPathSegLinetoAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegLinetoAbs.prototype.toString = function() { return "[object SVGPathSegLinetoAbs]"; }
+ SVGPathSegLinetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
+ SVGPathSegLinetoAbs.prototype.clone = function() { return new SVGPathSegLinetoAbs(undefined, this._x, this._y); }
+ Object.defineProperty(SVGPathSegLinetoAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegLinetoAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_REL, "l", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ SVGPathSegLinetoRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegLinetoRel.prototype.toString = function() { return "[object SVGPathSegLinetoRel]"; }
+ SVGPathSegLinetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
+ SVGPathSegLinetoRel.prototype.clone = function() { return new SVGPathSegLinetoRel(undefined, this._x, this._y); }
+ Object.defineProperty(SVGPathSegLinetoRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegLinetoRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicAbs = function(owningPathSegList, x, y, x1, y1, x2, y2) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, "C", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ SVGPathSegCurvetoCubicAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoCubicAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicAbs]"; }
+ SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoCubicAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicRel = function(owningPathSegList, x, y, x1, y1, x2, y2) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, "c", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ SVGPathSegCurvetoCubicRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoCubicRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicRel]"; }
+ SVGPathSegCurvetoCubicRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoCubicRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticAbs = function(owningPathSegList, x, y, x1, y1) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, "Q", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ }
+ SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticAbs]"; }
+ SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticAbs.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticRel = function(owningPathSegList, x, y, x1, y1) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, "q", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ }
+ SVGPathSegCurvetoQuadraticRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoQuadraticRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticRel]"; }
+ SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x1 + " " + this._y1 + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoQuadraticRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "x1", { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticRel.prototype, "y1", { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegArcAbs = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_ABS, "A", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._r1 = r1;
+ this._r2 = r2;
+ this._angle = angle;
+ this._largeArcFlag = largeArcFlag;
+ this._sweepFlag = sweepFlag;
+ }
+ SVGPathSegArcAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegArcAbs.prototype.toString = function() { return "[object SVGPathSegArcAbs]"; }
+ SVGPathSegArcAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
+ SVGPathSegArcAbs.prototype.clone = function() { return new SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcAbs.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegArcRel = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_ARC_REL, "a", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._r1 = r1;
+ this._r2 = r2;
+ this._angle = angle;
+ this._largeArcFlag = largeArcFlag;
+ this._sweepFlag = sweepFlag;
+ }
+ SVGPathSegArcRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegArcRel.prototype.toString = function() { return "[object SVGPathSegArcRel]"; }
+ SVGPathSegArcRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._r1 + " " + this._r2 + " " + this._angle + " " + (this._largeArcFlag ? "1" : "0") + " " + (this._sweepFlag ? "1" : "0") + " " + this._x + " " + this._y; }
+ SVGPathSegArcRel.prototype.clone = function() { return new SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
+ Object.defineProperty(SVGPathSegArcRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcRel.prototype, "r1", { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcRel.prototype, "r2", { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcRel.prototype, "angle", { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcRel.prototype, "largeArcFlag", { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegArcRel.prototype, "sweepFlag", { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, "H", owningPathSegList);
+ this._x = x;
+ }
+ SVGPathSegLinetoHorizontalAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegLinetoHorizontalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalAbs]"; }
+ SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
+ SVGPathSegLinetoHorizontalAbs.prototype.clone = function() { return new SVGPathSegLinetoHorizontalAbs(undefined, this._x); }
+ Object.defineProperty(SVGPathSegLinetoHorizontalAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, "h", owningPathSegList);
+ this._x = x;
+ }
+ SVGPathSegLinetoHorizontalRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegLinetoHorizontalRel.prototype.toString = function() { return "[object SVGPathSegLinetoHorizontalRel]"; }
+ SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x; }
+ SVGPathSegLinetoHorizontalRel.prototype.clone = function() { return new SVGPathSegLinetoHorizontalRel(undefined, this._x); }
+ Object.defineProperty(SVGPathSegLinetoHorizontalRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, "V", owningPathSegList);
+ this._y = y;
+ }
+ SVGPathSegLinetoVerticalAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegLinetoVerticalAbs.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalAbs]"; }
+ SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
+ SVGPathSegLinetoVerticalAbs.prototype.clone = function() { return new SVGPathSegLinetoVerticalAbs(undefined, this._y); }
+ Object.defineProperty(SVGPathSegLinetoVerticalAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, "v", owningPathSegList);
+ this._y = y;
+ }
+ SVGPathSegLinetoVerticalRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegLinetoVerticalRel.prototype.toString = function() { return "[object SVGPathSegLinetoVerticalRel]"; }
+ SVGPathSegLinetoVerticalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._y; }
+ SVGPathSegLinetoVerticalRel.prototype.clone = function() { return new SVGPathSegLinetoVerticalRel(undefined, this._y); }
+ Object.defineProperty(SVGPathSegLinetoVerticalRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicSmoothAbs = function(owningPathSegList, x, y, x2, y2) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, "S", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothAbs]"; }
+ SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothAbs.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicSmoothRel = function(owningPathSegList, x, y, x2, y2) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, "s", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoCubicSmoothRel]"; }
+ SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x2 + " " + this._y2 + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "x2", { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoCubicSmoothRel.prototype, "y2", { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticSmoothAbs = function(owningPathSegList, x, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, "T", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothAbs]"; }
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothAbs.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticSmoothRel = function(owningPathSegList, x, y) {
+ SVGPathSeg.call(this, SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, "t", owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(SVGPathSeg.prototype);
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() { return "[object SVGPathSegCurvetoQuadraticSmoothRel]"; }
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + " " + this._x + " " + this._y; }
+ SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "x", { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(SVGPathSegCurvetoQuadraticSmoothRel.prototype, "y", { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ // Add createSVGPathSeg* functions to SVGPathElement.
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathElement.
+ SVGPathElement.prototype.createSVGPathSegClosePath = function() { return new SVGPathSegClosePath(undefined); }
+ SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) { return new SVGPathSegMovetoAbs(undefined, x, y); }
+ SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) { return new SVGPathSegMovetoRel(undefined, x, y); }
+ SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) { return new SVGPathSegLinetoAbs(undefined, x, y); }
+ SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) { return new SVGPathSegLinetoRel(undefined, x, y); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(x, y, x1, y1, x2, y2) { return new SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(x, y, x1, y1) { return new SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }
+ SVGPathElement.prototype.createSVGPathSegArcAbs = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
+ SVGPathElement.prototype.createSVGPathSegArcRel = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
+ SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(x) { return new SVGPathSegLinetoHorizontalAbs(undefined, x); }
+ SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(x) { return new SVGPathSegLinetoHorizontalRel(undefined, x); }
+ SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(y) { return new SVGPathSegLinetoVerticalAbs(undefined, y); }
+ SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(y) { return new SVGPathSegLinetoVerticalRel(undefined, y); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(x, y, x2, y2) { return new SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }
+ SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(x, y) { return new SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }
+ }
+
+ if (!("SVGPathSegList" in window)) {
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
+ window.SVGPathSegList = function(pathElement) {
+ this._pathElement = pathElement;
+ this._list = this._parsePath(this._pathElement.getAttribute("d"));
+
+ // Use a MutationObserver to catch changes to the path's "d" attribute.
+ this._mutationObserverConfig = { "attributes": true, "attributeFilter": ["d"] };
+ this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+ }
+
+ Object.defineProperty(SVGPathSegList.prototype, "numberOfItems", {
+ get: function() {
+ this._checkPathSynchronizedToList();
+ return this._list.length;
+ },
+ enumerable: true
+ });
+
+ // Add the pathSegList accessors to SVGPathElement.
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
+ Object.defineProperty(SVGPathElement.prototype, "pathSegList", {
+ get: function() {
+ if (!this._pathSegList)
+ this._pathSegList = new SVGPathSegList(this);
+ return this._pathSegList;
+ },
+ enumerable: true
+ });
+ // FIXME: The following are not implemented and simply return SVGPathElement.pathSegList.
+ Object.defineProperty(SVGPathElement.prototype, "normalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
+ Object.defineProperty(SVGPathElement.prototype, "animatedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
+ Object.defineProperty(SVGPathElement.prototype, "animatedNormalizedPathSegList", { get: function() { return this.pathSegList; }, enumerable: true });
+
+ // Process any pending mutations to the path element and update the list as needed.
+ // This should be the first call of all public functions and is needed because
+ // MutationObservers are not synchronous so we can have pending asynchronous mutations.
+ SVGPathSegList.prototype._checkPathSynchronizedToList = function() {
+ this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
+ }
+
+ SVGPathSegList.prototype._updateListFromPathMutations = function(mutationRecords) {
+ if (!this._pathElement)
+ return;
+ var hasPathMutations = false;
+ mutationRecords.forEach(function(record) {
+ if (record.attributeName == "d")
+ hasPathMutations = true;
+ });
+ if (hasPathMutations)
+ this._list = this._parsePath(this._pathElement.getAttribute("d"));
+ }
+
+ // Serialize the list and update the path's 'd' attribute.
+ SVGPathSegList.prototype._writeListToPath = function() {
+ this._pathElementMutationObserver.disconnect();
+ this._pathElement.setAttribute("d", SVGPathSegList._pathSegArrayAsString(this._list));
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+ }
+
+ // When a path segment changes the list needs to be synchronized back to the path element.
+ SVGPathSegList.prototype.segmentChanged = function(pathSeg) {
+ this._writeListToPath();
+ }
+
+ SVGPathSegList.prototype.clear = function() {
+ this._checkPathSynchronizedToList();
+
+ this._list.forEach(function(pathSeg) {
+ pathSeg._owningPathSegList = null;
+ });
+ this._list = [];
+ this._writeListToPath();
+ }
+
+ SVGPathSegList.prototype.initialize = function(newItem) {
+ this._checkPathSynchronizedToList();
+
+ this._list = [newItem];
+ newItem._owningPathSegList = this;
+ this._writeListToPath();
+ return newItem;
+ }
+
+ SVGPathSegList.prototype._checkValidIndex = function(index) {
+ if (isNaN(index) || index < 0 || index >= this.numberOfItems)
+ throw "INDEX_SIZE_ERR";
+ }
+
+ SVGPathSegList.prototype.getItem = function(index) {
+ this._checkPathSynchronizedToList();
+
+ this._checkValidIndex(index);
+ return this._list[index];
+ }
+
+ SVGPathSegList.prototype.insertItemBefore = function(newItem, index) {
+ this._checkPathSynchronizedToList();
+
+ // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+ if (index > this.numberOfItems)
+ index = this.numberOfItems;
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+ this._list.splice(index, 0, newItem);
+ newItem._owningPathSegList = this;
+ this._writeListToPath();
+ return newItem;
+ }
+
+ SVGPathSegList.prototype.replaceItem = function(newItem, index) {
+ this._checkPathSynchronizedToList();
+
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+ this._checkValidIndex(index);
+ this._list[index] = newItem;
+ newItem._owningPathSegList = this;
+ this._writeListToPath();
+ return newItem;
+ }
+
+ SVGPathSegList.prototype.removeItem = function(index) {
+ this._checkPathSynchronizedToList();
+
+ this._checkValidIndex(index);
+ var item = this._list[index];
+ this._list.splice(index, 1);
+ this._writeListToPath();
+ return item;
+ }
+
+ SVGPathSegList.prototype.appendItem = function(newItem) {
+ this._checkPathSynchronizedToList();
+
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+ this._list.push(newItem);
+ newItem._owningPathSegList = this;
+ // TODO: Optimize this to just append to the existing attribute.
+ this._writeListToPath();
+ return newItem;
+ }
+
+ SVGPathSegList._pathSegArrayAsString = function(pathSegArray) {
+ var string = "";
+ var first = true;
+ pathSegArray.forEach(function(pathSeg) {
+ if (first) {
+ first = false;
+ string += pathSeg._asPathString();
+ } else {
+ string += " " + pathSeg._asPathString();
+ }
+ });
+ return string;
+ }
+
+ // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
+ SVGPathSegList.prototype._parsePath = function(string) {
+ if (!string || string.length == 0)
+ return [];
+
+ var owningPathSegList = this;
+
+ var Builder = function() {
+ this.pathSegList = [];
+ }
+
+ Builder.prototype.appendSegment = function(pathSeg) {
+ this.pathSegList.push(pathSeg);
+ }
+
+ var Source = function(string) {
+ this._string = string;
+ this._currentIndex = 0;
+ this._endIndex = this._string.length;
+ this._previousCommand = SVGPathSeg.PATHSEG_UNKNOWN;
+
+ this._skipOptionalSpaces();
+ }
+
+ Source.prototype._isCurrentSpace = function() {
+ var character = this._string[this._currentIndex];
+ return character <= " " && (character == " " || character == "\n" || character == "\t" || character == "\r" || character == "\f");
+ }
+
+ Source.prototype._skipOptionalSpaces = function() {
+ while (this._currentIndex < this._endIndex && this._isCurrentSpace())
+ this._currentIndex++;
+ return this._currentIndex < this._endIndex;
+ }
+
+ Source.prototype._skipOptionalSpacesOrDelimiter = function() {
+ if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ",")
+ return false;
+ if (this._skipOptionalSpaces()) {
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ",") {
+ this._currentIndex++;
+ this._skipOptionalSpaces();
+ }
+ }
+ return this._currentIndex < this._endIndex;
+ }
+
+ Source.prototype.hasMoreData = function() {
+ return this._currentIndex < this._endIndex;
+ }
+
+ Source.prototype.peekSegmentType = function() {
+ var lookahead = this._string[this._currentIndex];
+ return this._pathSegTypeFromChar(lookahead);
+ }
+
+ Source.prototype._pathSegTypeFromChar = function(lookahead) {
+ switch (lookahead) {
+ case "Z":
+ case "z":
+ return SVGPathSeg.PATHSEG_CLOSEPATH;
+ case "M":
+ return SVGPathSeg.PATHSEG_MOVETO_ABS;
+ case "m":
+ return SVGPathSeg.PATHSEG_MOVETO_REL;
+ case "L":
+ return SVGPathSeg.PATHSEG_LINETO_ABS;
+ case "l":
+ return SVGPathSeg.PATHSEG_LINETO_REL;
+ case "C":
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
+ case "c":
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
+ case "Q":
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
+ case "q":
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
+ case "A":
+ return SVGPathSeg.PATHSEG_ARC_ABS;
+ case "a":
+ return SVGPathSeg.PATHSEG_ARC_REL;
+ case "H":
+ return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
+ case "h":
+ return SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
+ case "V":
+ return SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
+ case "v":
+ return SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
+ case "S":
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
+ case "s":
+ return SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
+ case "T":
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
+ case "t":
+ return SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
+ default:
+ return SVGPathSeg.PATHSEG_UNKNOWN;
+ }
+ }
+
+ Source.prototype._nextCommandHelper = function(lookahead, previousCommand) {
+ // Check for remaining coordinates in the current command.
+ if ((lookahead == "+" || lookahead == "-" || lookahead == "." || (lookahead >= "0" && lookahead <= "9")) && previousCommand != SVGPathSeg.PATHSEG_CLOSEPATH) {
+ if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_ABS)
+ return SVGPathSeg.PATHSEG_LINETO_ABS;
+ if (previousCommand == SVGPathSeg.PATHSEG_MOVETO_REL)
+ return SVGPathSeg.PATHSEG_LINETO_REL;
+ return previousCommand;
+ }
+ return SVGPathSeg.PATHSEG_UNKNOWN;
+ }
+
+ Source.prototype.initialCommandIsMoveTo = function() {
+ // If the path is empty it is still valid, so return true.
+ if (!this.hasMoreData())
+ return true;
+ var command = this.peekSegmentType();
+ // Path must start with moveTo.
+ return command == SVGPathSeg.PATHSEG_MOVETO_ABS || command == SVGPathSeg.PATHSEG_MOVETO_REL;
+ }
+
+ // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
+ Source.prototype._parseNumber = function() {
+ var exponent = 0;
+ var integer = 0;
+ var frac = 1;
+ var decimal = 0;
+ var sign = 1;
+ var expsign = 1;
+
+ var startIndex = this._currentIndex;
+
+ this._skipOptionalSpaces();
+
+ // Read the sign.
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "+")
+ this._currentIndex++;
+ else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == "-") {
+ this._currentIndex++;
+ sign = -1;
+ }
+
+ if (this._currentIndex == this._endIndex || ((this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9") && this._string.charAt(this._currentIndex) != "."))
+ // The first character of a number must be one of [0-9+-.].
+ return undefined;
+
+ // Read the integer part, build right-to-left.
+ var startIntPartIndex = this._currentIndex;
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
+ this._currentIndex++; // Advance to first non-digit.
+
+ if (this._currentIndex != startIntPartIndex) {
+ var scanIntPartIndex = this._currentIndex - 1;
+ var multiplier = 1;
+ while (scanIntPartIndex >= startIntPartIndex) {
+ integer += multiplier * (this._string.charAt(scanIntPartIndex--) - "0");
+ multiplier *= 10;
+ }
+ }
+
+ // Read the decimals.
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ".") {
+ this._currentIndex++;
+
+ // There must be a least one digit following the .
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
+ return undefined;
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9")
+ decimal += (this._string.charAt(this._currentIndex++) - "0") * (frac *= 0.1);
+ }
+
+ // Read the exponent part.
+ if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == "e" || this._string.charAt(this._currentIndex) == "E") && (this._string.charAt(this._currentIndex + 1) != "x" && this._string.charAt(this._currentIndex + 1) != "m")) {
+ this._currentIndex++;
+
+ // Read the sign of the exponent.
+ if (this._string.charAt(this._currentIndex) == "+") {
+ this._currentIndex++;
+ } else if (this._string.charAt(this._currentIndex) == "-") {
+ this._currentIndex++;
+ expsign = -1;
+ }
+
+ // There must be an exponent.
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < "0" || this._string.charAt(this._currentIndex) > "9")
+ return undefined;
+
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= "0" && this._string.charAt(this._currentIndex) <= "9") {
+ exponent *= 10;
+ exponent += (this._string.charAt(this._currentIndex) - "0");
+ this._currentIndex++;
+ }
+ }
+
+ var number = integer + decimal;
+ number *= sign;
+
+ if (exponent)
+ number *= Math.pow(10, expsign * exponent);
+
+ if (startIndex == this._currentIndex)
+ return undefined;
+
+ this._skipOptionalSpacesOrDelimiter();
+
+ return number;
+ }
+
+ Source.prototype._parseArcFlag = function() {
+ if (this._currentIndex >= this._endIndex)
+ return undefined;
+ var flag = false;
+ var flagChar = this._string.charAt(this._currentIndex++);
+ if (flagChar == "0")
+ flag = false;
+ else if (flagChar == "1")
+ flag = true;
+ else
+ return undefined;
+
+ this._skipOptionalSpacesOrDelimiter();
+ return flag;
+ }
+
+ Source.prototype.parseSegment = function() {
+ var lookahead = this._string[this._currentIndex];
+ var command = this._pathSegTypeFromChar(lookahead);
+ if (command == SVGPathSeg.PATHSEG_UNKNOWN) {
+ // Possibly an implicit command. Not allowed if this is the first command.
+ if (this._previousCommand == SVGPathSeg.PATHSEG_UNKNOWN)
+ return null;
+ command = this._nextCommandHelper(lookahead, this._previousCommand);
+ if (command == SVGPathSeg.PATHSEG_UNKNOWN)
+ return null;
+ } else {
+ this._currentIndex++;
+ }
+
+ this._previousCommand = command;
+
+ switch (command) {
+ case SVGPathSeg.PATHSEG_MOVETO_REL:
+ return new SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case SVGPathSeg.PATHSEG_MOVETO_ABS:
+ return new SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case SVGPathSeg.PATHSEG_LINETO_REL:
+ return new SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case SVGPathSeg.PATHSEG_LINETO_ABS:
+ return new SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
+ return new SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
+ case SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
+ return new SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
+ case SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
+ return new SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
+ case SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
+ return new SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
+ case SVGPathSeg.PATHSEG_CLOSEPATH:
+ this._skipOptionalSpaces();
+ return new SVGPathSegClosePath(owningPathSegList);
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+ var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
+ case SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+ var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+ return new SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+ return new SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case SVGPathSeg.PATHSEG_ARC_REL:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+ case SVGPathSeg.PATHSEG_ARC_ABS:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
+ return new SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+ default:
+ throw "Unknown path seg type."
+ }
+ }
+
+ var builder = new Builder();
+ var source = new Source(string);
+
+ if (!source.initialCommandIsMoveTo())
+ return [];
+ while (source.hasMoreData()) {
+ var pathSeg = source.parseSegment();
+ if (!pathSeg)
+ return [];
+ builder.appendSegment(pathSeg);
+ }
+
+ return builder.pathSegList;
+ }
+ }
+ }());
+
+ /* jshint ignore:end */
+
if (typeof define === 'function' && define.amd) {
define("c3", ["d3"], function () { return c3; });
} else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
diff --git a/debian/missing-sources/d3-3.5.17.js b/debian/missing-sources/d3-3.5.17.js
new file mode 100644
index 000000000..aded45c44
--- /dev/null
+++ b/debian/missing-sources/d3-3.5.17.js
@@ -0,0 +1,9554 @@
+!function() {
+ var d3 = {
+ version: "3.5.17"
+ };
+ var d3_arraySlice = [].slice, d3_array = function(list) {
+ return d3_arraySlice.call(list);
+ };
+ var d3_document = this.document;
+ function d3_documentElement(node) {
+ return node && (node.ownerDocument || node.document || node).documentElement;
+ }
+ function d3_window(node) {
+ return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
+ }
+ if (d3_document) {
+ try {
+ d3_array(d3_document.documentElement.childNodes)[0].nodeType;
+ } catch (e) {
+ d3_array = function(list) {
+ var i = list.length, array = new Array(i);
+ while (i--) array[i] = list[i];
+ return array;
+ };
+ }
+ }
+ if (!Date.now) Date.now = function() {
+ return +new Date();
+ };
+ if (d3_document) {
+ try {
+ d3_document.createElement("DIV").style.setProperty("opacity", 0, "");
+ } catch (error) {
+ var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
+ d3_element_prototype.setAttribute = function(name, value) {
+ d3_element_setAttribute.call(this, name, value + "");
+ };
+ d3_element_prototype.setAttributeNS = function(space, local, value) {
+ d3_element_setAttributeNS.call(this, space, local, value + "");
+ };
+ d3_style_prototype.setProperty = function(name, value, priority) {
+ d3_style_setProperty.call(this, name, value + "", priority);
+ };
+ }
+ }
+ d3.ascending = d3_ascending;
+ function d3_ascending(a, b) {
+ return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
+ }
+ d3.descending = function(a, b) {
+ return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
+ };
+ d3.min = function(array, f) {
+ var i = -1, n = array.length, a, b;
+ if (arguments.length === 1) {
+ while (++i < n) if ((b = array[i]) != null && b >= b) {
+ a = b;
+ break;
+ }
+ while (++i < n) if ((b = array[i]) != null && a > b) a = b;
+ } else {
+ while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
+ a = b;
+ break;
+ }
+ while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
+ }
+ return a;
+ };
+ d3.max = function(array, f) {
+ var i = -1, n = array.length, a, b;
+ if (arguments.length === 1) {
+ while (++i < n) if ((b = array[i]) != null && b >= b) {
+ a = b;
+ break;
+ }
+ while (++i < n) if ((b = array[i]) != null && b > a) a = b;
+ } else {
+ while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
+ a = b;
+ break;
+ }
+ while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
+ }
+ return a;
+ };
+ d3.extent = function(array, f) {
+ var i = -1, n = array.length, a, b, c;
+ if (arguments.length === 1) {
+ while (++i < n) if ((b = array[i]) != null && b >= b) {
+ a = c = b;
+ break;
+ }
+ while (++i < n) if ((b = array[i]) != null) {
+ if (a > b) a = b;
+ if (c < b) c = b;
+ }
+ } else {
+ while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
+ a = c = b;
+ break;
+ }
+ while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
+ if (a > b) a = b;
+ if (c < b) c = b;
+ }
+ }
+ return [ a, c ];
+ };
+ function d3_number(x) {
+ return x === null ? NaN : +x;
+ }
+ function d3_numeric(x) {
+ return !isNaN(x);
+ }
+ d3.sum = function(array, f) {
+ var s = 0, n = array.length, a, i = -1;
+ if (arguments.length === 1) {
+ while (++i < n) if (d3_numeric(a = +array[i])) s += a;
+ } else {
+ while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
+ }
+ return s;
+ };
+ d3.mean = function(array, f) {
+ var s = 0, n = array.length, a, i = -1, j = n;
+ if (arguments.length === 1) {
+ while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
+ } else {
+ while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
+ }
+ if (j) return s / j;
+ };
+ d3.quantile = function(values, p) {
+ var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
+ return e ? v + e * (values[h] - v) : v;
+ };
+ d3.median = function(array, f) {
+ var numbers = [], n = array.length, a, i = -1;
+ if (arguments.length === 1) {
+ while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
+ } else {
+ while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
+ }
+ if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5);
+ };
+ d3.variance = function(array, f) {
+ var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0;
+ if (arguments.length === 1) {
+ while (++i < n) {
+ if (d3_numeric(a = d3_number(array[i]))) {
+ d = a - m;
+ m += d / ++j;
+ s += d * (a - m);
+ }
+ }
+ } else {
+ while (++i < n) {
+ if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) {
+ d = a - m;
+ m += d / ++j;
+ s += d * (a - m);
+ }
+ }
+ }
+ if (j > 1) return s / (j - 1);
+ };
+ d3.deviation = function() {
+ var v = d3.variance.apply(this, arguments);
+ return v ? Math.sqrt(v) : v;
+ };
+ function d3_bisector(compare) {
+ return {
+ left: function(a, x, lo, hi) {
+ if (arguments.length < 3) lo = 0;
+ if (arguments.length < 4) hi = a.length;
+ while (lo < hi) {
+ var mid = lo + hi >>> 1;
+ if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
+ }
+ return lo;
+ },
+ right: function(a, x, lo, hi) {
+ if (arguments.length < 3) lo = 0;
+ if (arguments.length < 4) hi = a.length;
+ while (lo < hi) {
+ var mid = lo + hi >>> 1;
+ if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
+ }
+ return lo;
+ }
+ };
+ }
+ var d3_bisect = d3_bisector(d3_ascending);
+ d3.bisectLeft = d3_bisect.left;
+ d3.bisect = d3.bisectRight = d3_bisect.right;
+ d3.bisector = function(f) {
+ return d3_bisector(f.length === 1 ? function(d, x) {
+ return d3_ascending(f(d), x);
+ } : f);
+ };
+ d3.shuffle = function(array, i0, i1) {
+ if ((m = arguments.length) < 3) {
+ i1 = array.length;
+ if (m < 2) i0 = 0;
+ }
+ var m = i1 - i0, t, i;
+ while (m) {
+ i = Math.random() * m-- | 0;
+ t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t;
+ }
+ return array;
+ };
+ d3.permute = function(array, indexes) {
+ var i = indexes.length, permutes = new Array(i);
+ while (i--) permutes[i] = array[indexes[i]];
+ return permutes;
+ };
+ d3.pairs = function(array) {
+ var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
+ while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
+ return pairs;
+ };
+ d3.transpose = function(matrix) {
+ if (!(n = matrix.length)) return [];
+ for (var i = -1, m = d3.min(matrix, d3_transposeLength), transpose = new Array(m); ++i < m; ) {
+ for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n; ) {
+ row[j] = matrix[j][i];
+ }
+ }
+ return transpose;
+ };
+ function d3_transposeLength(d) {
+ return d.length;
+ }
+ d3.zip = function() {
+ return d3.transpose(arguments);
+ };
+ d3.keys = function(map) {
+ var keys = [];
+ for (var key in map) keys.push(key);
+ return keys;
+ };
+ d3.values = function(map) {
+ var values = [];
+ for (var key in map) values.push(map[key]);
+ return values;
+ };
+ d3.entries = function(map) {
+ var entries = [];
+ for (var key in map) entries.push({
+ key: key,
+ value: map[key]
+ });
+ return entries;
+ };
+ d3.merge = function(arrays) {
+ var n = arrays.length, m, i = -1, j = 0, merged, array;
+ while (++i < n) j += arrays[i].length;
+ merged = new Array(j);
+ while (--n >= 0) {
+ array = arrays[n];
+ m = array.length;
+ while (--m >= 0) {
+ merged[--j] = array[m];
+ }
+ }
+ return merged;
+ };
+ var abs = Math.abs;
+ d3.range = function(start, stop, step) {
+ if (arguments.length < 3) {
+ step = 1;
+ if (arguments.length < 2) {
+ stop = start;
+ start = 0;
+ }
+ }
+ if ((stop - start) / step === Infinity) throw new Error("infinite range");
+ var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
+ start *= k, stop *= k, step *= k;
+ if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
+ return range;
+ };
+ function d3_range_integerScale(x) {
+ var k = 1;
+ while (x * k % 1) k *= 10;
+ return k;
+ }
+ function d3_class(ctor, properties) {
+ for (var key in properties) {
+ Object.defineProperty(ctor.prototype, key, {
+ value: properties[key],
+ enumerable: false
+ });
+ }
+ }
+ d3.map = function(object, f) {
+ var map = new d3_Map();
+ if (object instanceof d3_Map) {
+ object.forEach(function(key, value) {
+ map.set(key, value);
+ });
+ } else if (Array.isArray(object)) {
+ var i = -1, n = object.length, o;
+ if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o);
+ } else {
+ for (var key in object) map.set(key, object[key]);
+ }
+ return map;
+ };
+ function d3_Map() {
+ this._ = Object.create(null);
+ }
+ var d3_map_proto = "__proto__", d3_map_zero = "\x00";
+ d3_class(d3_Map, {
+ has: d3_map_has,
+ get: function(key) {
+ return this._[d3_map_escape(key)];
+ },
+ set: function(key, value) {
+ return this._[d3_map_escape(key)] = value;
+ },
+ remove: d3_map_remove,
+ keys: d3_map_keys,
+ values: function() {
+ var values = [];
+ for (var key in this._) values.push(this._[key]);
+ return values;
+ },
+ entries: function() {
+ var entries = [];
+ for (var key in this._) entries.push({
+ key: d3_map_unescape(key),
+ value: this._[key]
+ });
+ return entries;
+ },
+ size: d3_map_size,
+ empty: d3_map_empty,
+ forEach: function(f) {
+ for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
+ }
+ });
+ function d3_map_escape(key) {
+ return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
+ }
+ function d3_map_unescape(key) {
+ return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
+ }
+ function d3_map_has(key) {
+ return d3_map_escape(key) in this._;
+ }
+ function d3_map_remove(key) {
+ return (key = d3_map_escape(key)) in this._ && delete this._[key];
+ }
+ function d3_map_keys() {
+ var keys = [];
+ for (var key in this._) keys.push(d3_map_unescape(key));
+ return keys;
+ }
+ function d3_map_size() {
+ var size = 0;
+ for (var key in this._) ++size;
+ return size;
+ }
+ function d3_map_empty() {
+ for (var key in this._) return false;
+ return true;
+ }
+ d3.nest = function() {
+ var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
+ function map(mapType, array, depth) {
+ if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
+ var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
+ while (++i < n) {
+ if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
+ values.push(object);
+ } else {
+ valuesByKey.set(keyValue, [ object ]);
+ }
+ }
+ if (mapType) {
+ object = mapType();
+ setter = function(keyValue, values) {
+ object.set(keyValue, map(mapType, values, depth));
+ };
+ } else {
+ object = {};
+ setter = function(keyValue, values) {
+ object[keyValue] = map(mapType, values, depth);
+ };
+ }
+ valuesByKey.forEach(setter);
+ return object;
+ }
+ function entries(map, depth) {
+ if (depth >= keys.length) return map;
+ var array = [], sortKey = sortKeys[depth++];
+ map.forEach(function(key, keyMap) {
+ array.push({
+ key: key,
+ values: entries(keyMap, depth)
+ });
+ });
+ return sortKey ? array.sort(function(a, b) {
+ return sortKey(a.key, b.key);
+ }) : array;
+ }
+ nest.map = function(array, mapType) {
+ return map(mapType, array, 0);
+ };
+ nest.entries = function(array) {
+ return entries(map(d3.map, array, 0), 0);
+ };
+ nest.key = function(d) {
+ keys.push(d);
+ return nest;
+ };
+ nest.sortKeys = function(order) {
+ sortKeys[keys.length - 1] = order;
+ return nest;
+ };
+ nest.sortValues = function(order) {
+ sortValues = order;
+ return nest;
+ };
+ nest.rollup = function(f) {
+ rollup = f;
+ return nest;
+ };
+ return nest;
+ };
+ d3.set = function(array) {
+ var set = new d3_Set();
+ if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
+ return set;
+ };
+ function d3_Set() {
+ this._ = Object.create(null);
+ }
+ d3_class(d3_Set, {
+ has: d3_map_has,
+ add: function(key) {
+ this._[d3_map_escape(key += "")] = true;
+ return key;
+ },
+ remove: d3_map_remove,
+ values: d3_map_keys,
+ size: d3_map_size,
+ empty: d3_map_empty,
+ forEach: function(f) {
+ for (var key in this._) f.call(this, d3_map_unescape(key));
+ }
+ });
+ d3.behavior = {};
+ function d3_identity(d) {
+ return d;
+ }
+ d3.rebind = function(target, source) {
+ var i = 1, n = arguments.length, method;
+ while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
+ return target;
+ };
+ function d3_rebind(target, source, method) {
+ return function() {
+ var value = method.apply(source, arguments);
+ return value === source ? target : value;
+ };
+ }
+ function d3_vendorSymbol(object, name) {
+ if (name in object) return name;
+ name = name.charAt(0).toUpperCase() + name.slice(1);
+ for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
+ var prefixName = d3_vendorPrefixes[i] + name;
+ if (prefixName in object) return prefixName;
+ }
+ }
+ var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
+ function d3_noop() {}
+ d3.dispatch = function() {
+ var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
+ while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+ return dispatch;
+ };
+ function d3_dispatch() {}
+ d3_dispatch.prototype.on = function(type, listener) {
+ var i = type.indexOf("."), name = "";
+ if (i >= 0) {
+ name = type.slice(i + 1);
+ type = type.slice(0, i);
+ }
+ if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
+ if (arguments.length === 2) {
+ if (listener == null) for (type in this) {
+ if (this.hasOwnProperty(type)) this[type].on(name, null);
+ }
+ return this;
+ }
+ };
+ function d3_dispatch_event(dispatch) {
+ var listeners = [], listenerByName = new d3_Map();
+ function event() {
+ var z = listeners, i = -1, n = z.length, l;
+ while (++i < n) if (l = z[i].on) l.apply(this, arguments);
+ return dispatch;
+ }
+ event.on = function(name, listener) {
+ var l = listenerByName.get(name), i;
+ if (arguments.length < 2) return l && l.on;
+ if (l) {
+ l.on = null;
+ listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
+ listenerByName.remove(name);
+ }
+ if (listener) listeners.push(listenerByName.set(name, {
+ on: listener
+ }));
+ return dispatch;
+ };
+ return event;
+ }
+ d3.event = null;
+ function d3_eventPreventDefault() {
+ d3.event.preventDefault();
+ }
+ function d3_eventSource() {
+ var e = d3.event, s;
+ while (s = e.sourceEvent) e = s;
+ return e;
+ }
+ function d3_eventDispatch(target) {
+ var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
+ while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+ dispatch.of = function(thiz, argumentz) {
+ return function(e1) {
+ try {
+ var e0 = e1.sourceEvent = d3.event;
+ e1.target = target;
+ d3.event = e1;
+ dispatch[e1.type].apply(thiz, argumentz);
+ } finally {
+ d3.event = e0;
+ }
+ };
+ };
+ return dispatch;
+ }
+ d3.requote = function(s) {
+ return s.replace(d3_requote_re, "\\$&");
+ };
+ var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+ var d3_subclass = {}.__proto__ ? function(object, prototype) {
+ object.__proto__ = prototype;
+ } : function(object, prototype) {
+ for (var property in prototype) object[property] = prototype[property];
+ };
+ function d3_selection(groups) {
+ d3_subclass(groups, d3_selectionPrototype);
+ return groups;
+ }
+ var d3_select = function(s, n) {
+ return n.querySelector(s);
+ }, d3_selectAll = function(s, n) {
+ return n.querySelectorAll(s);
+ }, d3_selectMatches = function(n, s) {
+ var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
+ d3_selectMatches = function(n, s) {
+ return d3_selectMatcher.call(n, s);
+ };
+ return d3_selectMatches(n, s);
+ };
+ if (typeof Sizzle === "function") {
+ d3_select = function(s, n) {
+ return Sizzle(s, n)[0] || null;
+ };
+ d3_selectAll = Sizzle;
+ d3_selectMatches = Sizzle.matchesSelector;
+ }
+ d3.selection = function() {
+ return d3.select(d3_document.documentElement);
+ };
+ var d3_selectionPrototype = d3.selection.prototype = [];
+ d3_selectionPrototype.select = function(selector) {
+ var subgroups = [], subgroup, subnode, group, node;
+ selector = d3_selection_selector(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ subgroups.push(subgroup = []);
+ subgroup.parentNode = (group = this[j]).parentNode;
+ for (var i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ subgroup.push(subnode = selector.call(node, node.__data__, i, j));
+ if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
+ } else {
+ subgroup.push(null);
+ }
+ }
+ }
+ return d3_selection(subgroups);
+ };
+ function d3_selection_selector(selector) {
+ return typeof selector === "function" ? selector : function() {
+ return d3_select(selector, this);
+ };
+ }
+ d3_selectionPrototype.selectAll = function(selector) {
+ var subgroups = [], subgroup, node;
+ selector = d3_selection_selectorAll(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
+ subgroup.parentNode = node;
+ }
+ }
+ }
+ return d3_selection(subgroups);
+ };
+ function d3_selection_selectorAll(selector) {
+ return typeof selector === "function" ? selector : function() {
+ return d3_selectAll(selector, this);
+ };
+ }
+ var d3_nsXhtml = "http://www.w3.org/1999/xhtml";
+ var d3_nsPrefix = {
+ svg: "http://www.w3.org/2000/svg",
+ xhtml: d3_nsXhtml,
+ xlink: "http://www.w3.org/1999/xlink",
+ xml: "http://www.w3.org/XML/1998/namespace",
+ xmlns: "http://www.w3.org/2000/xmlns/"
+ };
+ d3.ns = {
+ prefix: d3_nsPrefix,
+ qualify: function(name) {
+ var i = name.indexOf(":"), prefix = name;
+ if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
+ return d3_nsPrefix.hasOwnProperty(prefix) ? {
+ space: d3_nsPrefix[prefix],
+ local: name
+ } : name;
+ }
+ };
+ d3_selectionPrototype.attr = function(name, value) {
+ if (arguments.length < 2) {
+ if (typeof name === "string") {
+ var node = this.node();
+ name = d3.ns.qualify(name);
+ return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
+ }
+ for (value in name) this.each(d3_selection_attr(value, name[value]));
+ return this;
+ }
+ return this.each(d3_selection_attr(name, value));
+ };
+ function d3_selection_attr(name, value) {
+ name = d3.ns.qualify(name);
+ function attrNull() {
+ this.removeAttribute(name);
+ }
+ function attrNullNS() {
+ this.removeAttributeNS(name.space, name.local);
+ }
+ function attrConstant() {
+ this.setAttribute(name, value);
+ }
+ function attrConstantNS() {
+ this.setAttributeNS(name.space, name.local, value);
+ }
+ function attrFunction() {
+ var x = value.apply(this, arguments);
+ if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
+ }
+ function attrFunctionNS() {
+ var x = value.apply(this, arguments);
+ if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
+ }
+ return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
+ }
+ function d3_collapse(s) {
+ return s.trim().replace(/\s+/g, " ");
+ }
+ d3_selectionPrototype.classed = function(name, value) {
+ if (arguments.length < 2) {
+ if (typeof name === "string") {
+ var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
+ if (value = node.classList) {
+ while (++i < n) if (!value.contains(name[i])) return false;
+ } else {
+ value = node.getAttribute("class");
+ while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
+ }
+ return true;
+ }
+ for (value in name) this.each(d3_selection_classed(value, name[value]));
+ return this;
+ }
+ return this.each(d3_selection_classed(name, value));
+ };
+ function d3_selection_classedRe(name) {
+ return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
+ }
+ function d3_selection_classes(name) {
+ return (name + "").trim().split(/^|\s+/);
+ }
+ function d3_selection_classed(name, value) {
+ name = d3_selection_classes(name).map(d3_selection_classedName);
+ var n = name.length;
+ function classedConstant() {
+ var i = -1;
+ while (++i < n) name[i](this, value);
+ }
+ function classedFunction() {
+ var i = -1, x = value.apply(this, arguments);
+ while (++i < n) name[i](this, x);
+ }
+ return typeof value === "function" ? classedFunction : classedConstant;
+ }
+ function d3_selection_classedName(name) {
+ var re = d3_selection_classedRe(name);
+ return function(node, value) {
+ if (c = node.classList) return value ? c.add(name) : c.remove(name);
+ var c = node.getAttribute("class") || "";
+ if (value) {
+ re.lastIndex = 0;
+ if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
+ } else {
+ node.setAttribute("class", d3_collapse(c.replace(re, " ")));
+ }
+ };
+ }
+ d3_selectionPrototype.style = function(name, value, priority) {
+ var n = arguments.length;
+ if (n < 3) {
+ if (typeof name !== "string") {
+ if (n < 2) value = "";
+ for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
+ return this;
+ }
+ if (n < 2) {
+ var node = this.node();
+ return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
+ }
+ priority = "";
+ }
+ return this.each(d3_selection_style(name, value, priority));
+ };
+ function d3_selection_style(name, value, priority) {
+ function styleNull() {
+ this.style.removeProperty(name);
+ }
+ function styleConstant() {
+ this.style.setProperty(name, value, priority);
+ }
+ function styleFunction() {
+ var x = value.apply(this, arguments);
+ if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
+ }
+ return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
+ }
+ d3_selectionPrototype.property = function(name, value) {
+ if (arguments.length < 2) {
+ if (typeof name === "string") return this.node()[name];
+ for (value in name) this.each(d3_selection_property(value, name[value]));
+ return this;
+ }
+ return this.each(d3_selection_property(name, value));
+ };
+ function d3_selection_property(name, value) {
+ function propertyNull() {
+ delete this[name];
+ }
+ function propertyConstant() {
+ this[name] = value;
+ }
+ function propertyFunction() {
+ var x = value.apply(this, arguments);
+ if (x == null) delete this[name]; else this[name] = x;
+ }
+ return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
+ }
+ d3_selectionPrototype.text = function(value) {
+ return arguments.length ? this.each(typeof value === "function" ? function() {
+ var v = value.apply(this, arguments);
+ this.textContent = v == null ? "" : v;
+ } : value == null ? function() {
+ this.textContent = "";
+ } : function() {
+ this.textContent = value;
+ }) : this.node().textContent;
+ };
+ d3_selectionPrototype.html = function(value) {
+ return arguments.length ? this.each(typeof value === "function" ? function() {
+ var v = value.apply(this, arguments);
+ this.innerHTML = v == null ? "" : v;
+ } : value == null ? function() {
+ this.innerHTML = "";
+ } : function() {
+ this.innerHTML = value;
+ }) : this.node().innerHTML;
+ };
+ d3_selectionPrototype.append = function(name) {
+ name = d3_selection_creator(name);
+ return this.select(function() {
+ return this.appendChild(name.apply(this, arguments));
+ });
+ };
+ function d3_selection_creator(name) {
+ function create() {
+ var document = this.ownerDocument, namespace = this.namespaceURI;
+ return namespace === d3_nsXhtml && document.documentElement.namespaceURI === d3_nsXhtml ? document.createElement(name) : document.createElementNS(namespace, name);
+ }
+ function createNS() {
+ return this.ownerDocument.createElementNS(name.space, name.local);
+ }
+ return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create;
+ }
+ d3_selectionPrototype.insert = function(name, before) {
+ name = d3_selection_creator(name);
+ before = d3_selection_selector(before);
+ return this.select(function() {
+ return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
+ });
+ };
+ d3_selectionPrototype.remove = function() {
+ return this.each(d3_selectionRemove);
+ };
+ function d3_selectionRemove() {
+ var parent = this.parentNode;
+ if (parent) parent.removeChild(this);
+ }
+ d3_selectionPrototype.data = function(value, key) {
+ var i = -1, n = this.length, group, node;
+ if (!arguments.length) {
+ value = new Array(n = (group = this[0]).length);
+ while (++i < n) {
+ if (node = group[i]) {
+ value[i] = node.__data__;
+ }
+ }
+ return value;
+ }
+ function bind(group, groupData) {
+ var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
+ if (key) {
+ var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;
+ for (i = -1; ++i < n; ) {
+ if (node = group[i]) {
+ if (nodeByKeyValue.has(keyValue = key.call(node, node.__data__, i))) {
+ exitNodes[i] = node;
+ } else {
+ nodeByKeyValue.set(keyValue, node);
+ }
+ keyValues[i] = keyValue;
+ }
+ }
+ for (i = -1; ++i < m; ) {
+ if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
+ enterNodes[i] = d3_selection_dataNode(nodeData);
+ } else if (node !== true) {
+ updateNodes[i] = node;
+ node.__data__ = nodeData;
+ }
+ nodeByKeyValue.set(keyValue, true);
+ }
+ for (i = -1; ++i < n; ) {
+ if (i in keyValues && nodeByKeyValue.get(keyValues[i]) !== true) {
+ exitNodes[i] = group[i];
+ }
+ }
+ } else {
+ for (i = -1; ++i < n0; ) {
+ node = group[i];
+ nodeData = groupData[i];
+ if (node) {
+ node.__data__ = nodeData;
+ updateNodes[i] = node;
+ } else {
+ enterNodes[i] = d3_selection_dataNode(nodeData);
+ }
+ }
+ for (;i < m; ++i) {
+ enterNodes[i] = d3_selection_dataNode(groupData[i]);
+ }
+ for (;i < n; ++i) {
+ exitNodes[i] = group[i];
+ }
+ }
+ enterNodes.update = updateNodes;
+ enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
+ enter.push(enterNodes);
+ update.push(updateNodes);
+ exit.push(exitNodes);
+ }
+ var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
+ if (typeof value === "function") {
+ while (++i < n) {
+ bind(group = this[i], value.call(group, group.parentNode.__data__, i));
+ }
+ } else {
+ while (++i < n) {
+ bind(group = this[i], value);
+ }
+ }
+ update.enter = function() {
+ return enter;
+ };
+ update.exit = function() {
+ return exit;
+ };
+ return update;
+ };
+ function d3_selection_dataNode(data) {
+ return {
+ __data__: data
+ };
+ }
+ d3_selectionPrototype.datum = function(value) {
+ return arguments.length ? this.property("__data__", value) : this.property("__data__");
+ };
+ d3_selectionPrototype.filter = function(filter) {
+ var subgroups = [], subgroup, group, node;
+ if (typeof filter !== "function") filter = d3_selection_filter(filter);
+ for (var j = 0, m = this.length; j < m; j++) {
+ subgroups.push(subgroup = []);
+ subgroup.parentNode = (group = this[j]).parentNode;
+ for (var i = 0, n = group.length; i < n; i++) {
+ if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
+ subgroup.push(node);
+ }
+ }
+ }
+ return d3_selection(subgroups);
+ };
+ function d3_selection_filter(selector) {
+ return function() {
+ return d3_selectMatches(this, selector);
+ };
+ }
+ d3_selectionPrototype.order = function() {
+ for (var j = -1, m = this.length; ++j < m; ) {
+ for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
+ if (node = group[i]) {
+ if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
+ next = node;
+ }
+ }
+ }
+ return this;
+ };
+ d3_selectionPrototype.sort = function(comparator) {
+ comparator = d3_selection_sortComparator.apply(this, arguments);
+ for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
+ return this.order();
+ };
+ function d3_selection_sortComparator(comparator) {
+ if (!arguments.length) comparator = d3_ascending;
+ return function(a, b) {
+ return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
+ };
+ }
+ d3_selectionPrototype.each = function(callback) {
+ return d3_selection_each(this, function(node, i, j) {
+ callback.call(node, node.__data__, i, j);
+ });
+ };
+ function d3_selection_each(groups, callback) {
+ for (var j = 0, m = groups.length; j < m; j++) {
+ for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
+ if (node = group[i]) callback(node, i, j);
+ }
+ }
+ return groups;
+ }
+ d3_selectionPrototype.call = function(callback) {
+ var args = d3_array(arguments);
+ callback.apply(args[0] = this, args);
+ return this;
+ };
+ d3_selectionPrototype.empty = function() {
+ return !this.node();
+ };
+ d3_selectionPrototype.node = function() {
+ for (var j = 0, m = this.length; j < m; j++) {
+ for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+ var node = group[i];
+ if (node) return node;
+ }
+ }
+ return null;
+ };
+ d3_selectionPrototype.size = function() {
+ var n = 0;
+ d3_selection_each(this, function() {
+ ++n;
+ });
+ return n;
+ };
+ function d3_selection_enter(selection) {
+ d3_subclass(selection, d3_selection_enterPrototype);
+ return selection;
+ }
+ var d3_selection_enterPrototype = [];
+ d3.selection.enter = d3_selection_enter;
+ d3.selection.enter.prototype = d3_selection_enterPrototype;
+ d3_selection_enterPrototype.append = d3_selectionPrototype.append;
+ d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
+ d3_selection_enterPrototype.node = d3_selectionPrototype.node;
+ d3_selection_enterPrototype.call = d3_selectionPrototype.call;
+ d3_selection_enterPrototype.size = d3_selectionPrototype.size;
+ d3_selection_enterPrototype.select = function(selector) {
+ var subgroups = [], subgroup, subnode, upgroup, group, node;
+ for (var j = -1, m = this.length; ++j < m; ) {
+ upgroup = (group = this[j]).update;
+ subgroups.push(subgroup = []);
+ subgroup.parentNode = group.parentNode;
+ for (var i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
+ subnode.__data__ = node.__data__;
+ } else {
+ subgroup.push(null);
+ }
+ }
+ }
+ return d3_selection(subgroups);
+ };
+ d3_selection_enterPrototype.insert = function(name, before) {
+ if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
+ return d3_selectionPrototype.insert.call(this, name, before);
+ };
+ function d3_selection_enterInsertBefore(enter) {
+ var i0, j0;
+ return function(d, i, j) {
+ var group = enter[j].update, n = group.length, node;
+ if (j != j0) j0 = j, i0 = 0;
+ if (i >= i0) i0 = i + 1;
+ while (!(node = group[i0]) && ++i0 < n) ;
+ return node;
+ };
+ }
+ d3.select = function(node) {
+ var group;
+ if (typeof node === "string") {
+ group = [ d3_select(node, d3_document) ];
+ group.parentNode = d3_document.documentElement;
+ } else {
+ group = [ node ];
+ group.parentNode = d3_documentElement(node);
+ }
+ return d3_selection([ group ]);
+ };
+ d3.selectAll = function(nodes) {
+ var group;
+ if (typeof nodes === "string") {
+ group = d3_array(d3_selectAll(nodes, d3_document));
+ group.parentNode = d3_document.documentElement;
+ } else {
+ group = d3_array(nodes);
+ group.parentNode = null;
+ }
+ return d3_selection([ group ]);
+ };
+ d3_selectionPrototype.on = function(type, listener, capture) {
+ var n = arguments.length;
+ if (n < 3) {
+ if (typeof type !== "string") {
+ if (n < 2) listener = false;
+ for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
+ return this;
+ }
+ if (n < 2) return (n = this.node()["__on" + type]) && n._;
+ capture = false;
+ }
+ return this.each(d3_selection_on(type, listener, capture));
+ };
+ function d3_selection_on(type, listener, capture) {
+ var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
+ if (i > 0) type = type.slice(0, i);
+ var filter = d3_selection_onFilters.get(type);
+ if (filter) type = filter, wrap = d3_selection_onFilter;
+ function onRemove() {
+ var l = this[name];
+ if (l) {
+ this.removeEventListener(type, l, l.$);
+ delete this[name];
+ }
+ }
+ function onAdd() {
+ var l = wrap(listener, d3_array(arguments));
+ onRemove.call(this);
+ this.addEventListener(type, this[name] = l, l.$ = capture);
+ l._ = listener;
+ }
+ function removeAll() {
+ var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
+ for (var name in this) {
+ if (match = name.match(re)) {
+ var l = this[name];
+ this.removeEventListener(match[1], l, l.$);
+ delete this[name];
+ }
+ }
+ }
+ return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
+ }
+ var d3_selection_onFilters = d3.map({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+ });
+ if (d3_document) {
+ d3_selection_onFilters.forEach(function(k) {
+ if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
+ });
+ }
+ function d3_selection_onListener(listener, argumentz) {
+ return function(e) {
+ var o = d3.event;
+ d3.event = e;
+ argumentz[0] = this.__data__;
+ try {
+ listener.apply(this, argumentz);
+ } finally {
+ d3.event = o;
+ }
+ };
+ }
+ function d3_selection_onFilter(listener, argumentz) {
+ var l = d3_selection_onListener(listener, argumentz);
+ return function(e) {
+ var target = this, related = e.relatedTarget;
+ if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
+ l.call(target, e);
+ }
+ };
+ }
+ var d3_event_dragSelect, d3_event_dragId = 0;
+ function d3_event_dragSuppress(node) {
+ var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
+ if (d3_event_dragSelect == null) {
+ d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect");
+ }
+ if (d3_event_dragSelect) {
+ var style = d3_documentElement(node).style, select = style[d3_event_dragSelect];
+ style[d3_event_dragSelect] = "none";
+ }
+ return function(suppressClick) {
+ w.on(name, null);
+ if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
+ if (suppressClick) {
+ var off = function() {
+ w.on(click, null);
+ };
+ w.on(click, function() {
+ d3_eventPreventDefault();
+ off();
+ }, true);
+ setTimeout(off, 0);
+ }
+ };
+ }
+ d3.mouse = function(container) {
+ return d3_mousePoint(container, d3_eventSource());
+ };
+ var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0;
+ function d3_mousePoint(container, e) {
+ if (e.changedTouches) e = e.changedTouches[0];
+ var svg = container.ownerSVGElement || container;
+ if (svg.createSVGPoint) {
+ var point = svg.createSVGPoint();
+ if (d3_mouse_bug44083 < 0) {
+ var window = d3_window(container);
+ if (window.scrollX || window.scrollY) {
+ svg = d3.select("body").append("svg").style({
+ position: "absolute",
+ top: 0,
+ left: 0,
+ margin: 0,
+ padding: 0,
+ border: "none"
+ }, "important");
+ var ctm = svg[0][0].getScreenCTM();
+ d3_mouse_bug44083 = !(ctm.f || ctm.e);
+ svg.remove();
+ }
+ }
+ if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX,
+ point.y = e.clientY;
+ point = point.matrixTransform(container.getScreenCTM().inverse());
+ return [ point.x, point.y ];
+ }
+ var rect = container.getBoundingClientRect();
+ return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
+ }
+ d3.touch = function(container, touches, identifier) {
+ if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
+ if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
+ if ((touch = touches[i]).identifier === identifier) {
+ return d3_mousePoint(container, touch);
+ }
+ }
+ };
+ d3.behavior.drag = function() {
+ var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend");
+ function drag() {
+ this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
+ }
+ function dragstart(id, position, subject, move, end) {
+ return function() {
+ var that = this, target = d3.event.target.correspondingElement || d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId);
+ if (origin) {
+ dragOffset = origin.apply(that, arguments);
+ dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
+ } else {
+ dragOffset = [ 0, 0 ];
+ }
+ dispatch({
+ type: "dragstart"
+ });
+ function moved() {
+ var position1 = position(parent, dragId), dx, dy;
+ if (!position1) return;
+ dx = position1[0] - position0[0];
+ dy = position1[1] - position0[1];
+ dragged |= dx | dy;
+ position0 = position1;
+ dispatch({
+ type: "drag",
+ x: position1[0] + dragOffset[0],
+ y: position1[1] + dragOffset[1],
+ dx: dx,
+ dy: dy
+ });
+ }
+ function ended() {
+ if (!position(parent, dragId)) return;
+ dragSubject.on(move + dragName, null).on(end + dragName, null);
+ dragRestore(dragged);
+ dispatch({
+ type: "dragend"
+ });
+ }
+ };
+ }
+ drag.origin = function(x) {
+ if (!arguments.length) return origin;
+ origin = x;
+ return drag;
+ };
+ return d3.rebind(drag, event, "on");
+ };
+ function d3_behavior_dragTouchId() {
+ return d3.event.changedTouches[0].identifier;
+ }
+ d3.touches = function(container, touches) {
+ if (arguments.length < 2) touches = d3_eventSource().touches;
+ return touches ? d3_array(touches).map(function(touch) {
+ var point = d3_mousePoint(container, touch);
+ point.identifier = touch.identifier;
+ return point;
+ }) : [];
+ };
+ var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π;
+ function d3_sgn(x) {
+ return x > 0 ? 1 : x < 0 ? -1 : 0;
+ }
+ function d3_cross2d(a, b, c) {
+ return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
+ }
+ function d3_acos(x) {
+ return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
+ }
+ function d3_asin(x) {
+ return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
+ }
+ function d3_sinh(x) {
+ return ((x = Math.exp(x)) - 1 / x) / 2;
+ }
+ function d3_cosh(x) {
+ return ((x = Math.exp(x)) + 1 / x) / 2;
+ }
+ function d3_tanh(x) {
+ return ((x = Math.exp(2 * x)) - 1) / (x + 1);
+ }
+ function d3_haversin(x) {
+ return (x = Math.sin(x / 2)) * x;
+ }
+ var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
+ d3.interpolateZoom = function(p0, p1) {
+ var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S;
+ if (d2 < ε2) {
+ S = Math.log(w1 / w0) / ρ;
+ i = function(t) {
+ return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * t * S) ];
+ };
+ } else {
+ var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
+ S = (r1 - r0) / ρ;
+ i = function(t) {
+ var s = t * S, coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
+ return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
+ };
+ }
+ i.duration = S * 1e3;
+ return i;
+ };
+ d3.behavior.zoom = function() {
+ var view = {
+ x: 0,
+ y: 0,
+ k: 1
+ }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
+ if (!d3_behavior_zoomWheel) {
+ d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+ return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
+ }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+ return d3.event.wheelDelta;
+ }, "mousewheel") : (d3_behavior_zoomDelta = function() {
+ return -d3.event.detail;
+ }, "MozMousePixelScroll");
+ }
+ function zoom(g) {
+ g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
+ }
+ zoom.event = function(g) {
+ g.each(function() {
+ var dispatch = event.of(this, arguments), view1 = view;
+ if (d3_transitionInheritId) {
+ d3.select(this).transition().each("start.zoom", function() {
+ view = this.__chart__ || {
+ x: 0,
+ y: 0,
+ k: 1
+ };
+ zoomstarted(dispatch);
+ }).tween("zoom:zoom", function() {
+ var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
+ return function(t) {
+ var l = i(t), k = dx / l[2];
+ this.__chart__ = view = {
+ x: cx - l[0] * k,
+ y: cy - l[1] * k,
+ k: k
+ };
+ zoomed(dispatch);
+ };
+ }).each("interrupt.zoom", function() {
+ zoomended(dispatch);
+ }).each("end.zoom", function() {
+ zoomended(dispatch);
+ });
+ } else {
+ this.__chart__ = view;
+ zoomstarted(dispatch);
+ zoomed(dispatch);
+ zoomended(dispatch);
+ }
+ });
+ };
+ zoom.translate = function(_) {
+ if (!arguments.length) return [ view.x, view.y ];
+ view = {
+ x: +_[0],
+ y: +_[1],
+ k: view.k
+ };
+ rescale();
+ return zoom;
+ };
+ zoom.scale = function(_) {
+ if (!arguments.length) return view.k;
+ view = {
+ x: view.x,
+ y: view.y,
+ k: null
+ };
+ scaleTo(+_);
+ rescale();
+ return zoom;
+ };
+ zoom.scaleExtent = function(_) {
+ if (!arguments.length) return scaleExtent;
+ scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
+ return zoom;
+ };
+ zoom.center = function(_) {
+ if (!arguments.length) return center;
+ center = _ && [ +_[0], +_[1] ];
+ return zoom;
+ };
+ zoom.size = function(_) {
+ if (!arguments.length) return size;
+ size = _ && [ +_[0], +_[1] ];
+ return zoom;
+ };
+ zoom.duration = function(_) {
+ if (!arguments.length) return duration;
+ duration = +_;
+ return zoom;
+ };
+ zoom.x = function(z) {
+ if (!arguments.length) return x1;
+ x1 = z;
+ x0 = z.copy();
+ view = {
+ x: 0,
+ y: 0,
+ k: 1
+ };
+ return zoom;
+ };
+ zoom.y = function(z) {
+ if (!arguments.length) return y1;
+ y1 = z;
+ y0 = z.copy();
+ view = {
+ x: 0,
+ y: 0,
+ k: 1
+ };
+ return zoom;
+ };
+ function location(p) {
+ return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
+ }
+ function point(l) {
+ return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
+ }
+ function scaleTo(s) {
+ view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+ }
+ function translateTo(p, l) {
+ l = point(l);
+ view.x += p[0] - l[0];
+ view.y += p[1] - l[1];
+ }
+ function zoomTo(that, p, l, k) {
+ that.__chart__ = {
+ x: view.x,
+ y: view.y,
+ k: view.k
+ };
+ scaleTo(Math.pow(2, k));
+ translateTo(center0 = p, l);
+ that = d3.select(that);
+ if (duration > 0) that = that.transition().duration(duration);
+ that.call(zoom.event);
+ }
+ function rescale() {
+ if (x1) x1.domain(x0.range().map(function(x) {
+ return (x - view.x) / view.k;
+ }).map(x0.invert));
+ if (y1) y1.domain(y0.range().map(function(y) {
+ return (y - view.y) / view.k;
+ }).map(y0.invert));
+ }
+ function zoomstarted(dispatch) {
+ if (!zooming++) dispatch({
+ type: "zoomstart"
+ });
+ }
+ function zoomed(dispatch) {
+ rescale();
+ dispatch({
+ type: "zoom",
+ scale: view.k,
+ translate: [ view.x, view.y ]
+ });
+ }
+ function zoomended(dispatch) {
+ if (!--zooming) dispatch({
+ type: "zoomend"
+ }), center0 = null;
+ }
+ function mousedowned() {
+ var that = this, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that);
+ d3_selection_interrupt.call(that);
+ zoomstarted(dispatch);
+ function moved() {
+ dragged = 1;
+ translateTo(d3.mouse(that), location0);
+ zoomed(dispatch);
+ }
+ function ended() {
+ subject.on(mousemove, null).on(mouseup, null);
+ dragRestore(dragged);
+ zoomended(dispatch);
+ }
+ }
+ function touchstarted() {
+ var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that);
+ started();
+ zoomstarted(dispatch);
+ subject.on(mousedown, null).on(touchstart, started);
+ function relocate() {
+ var touches = d3.touches(that);
+ scale0 = view.k;
+ touches.forEach(function(t) {
+ if (t.identifier in locations0) locations0[t.identifier] = location(t);
+ });
+ return touches;
+ }
+ function started() {
+ var target = d3.event.target;
+ d3.select(target).on(touchmove, moved).on(touchend, ended);
+ targets.push(target);
+ var changed = d3.event.changedTouches;
+ for (var i = 0, n = changed.length; i < n; ++i) {
+ locations0[changed[i].identifier] = null;
+ }
+ var touches = relocate(), now = Date.now();
+ if (touches.length === 1) {
+ if (now - touchtime < 500) {
+ var p = touches[0];
+ zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
+ d3_eventPreventDefault();
+ }
+ touchtime = now;
+ } else if (touches.length > 1) {
+ var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
+ distance0 = dx * dx + dy * dy;
+ }
+ }
+ function moved() {
+ var touches = d3.touches(that), p0, l0, p1, l1;
+ d3_selection_interrupt.call(that);
+ for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
+ p1 = touches[i];
+ if (l1 = locations0[p1.identifier]) {
+ if (l0) break;
+ p0 = p1, l0 = l1;
+ }
+ }
+ if (l1) {
+ var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
+ p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
+ l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
+ scaleTo(scale1 * scale0);
+ }
+ touchtime = null;
+ translateTo(p0, l0);
+ zoomed(dispatch);
+ }
+ function ended() {
+ if (d3.event.touches.length) {
+ var changed = d3.event.changedTouches;
+ for (var i = 0, n = changed.length; i < n; ++i) {
+ delete locations0[changed[i].identifier];
+ }
+ for (var identifier in locations0) {
+ return void relocate();
+ }
+ }
+ d3.selectAll(targets).on(zoomName, null);
+ subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
+ dragRestore();
+ zoomended(dispatch);
+ }
+ }
+ function mousewheeled() {
+ var dispatch = event.of(this, arguments);
+ if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this),
+ translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch);
+ mousewheelTimer = setTimeout(function() {
+ mousewheelTimer = null;
+ zoomended(dispatch);
+ }, 50);
+ d3_eventPreventDefault();
+ scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
+ translateTo(center0, translate0);
+ zoomed(dispatch);
+ }
+ function dblclicked() {
+ var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2;
+ zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
+ }
+ return d3.rebind(zoom, event, "on");
+ };
+ var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel;
+ d3.color = d3_color;
+ function d3_color() {}
+ d3_color.prototype.toString = function() {
+ return this.rgb() + "";
+ };
+ d3.hsl = d3_hsl;
+ function d3_hsl(h, s, l) {
+ return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
+ }
+ var d3_hslPrototype = d3_hsl.prototype = new d3_color();
+ d3_hslPrototype.brighter = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return new d3_hsl(this.h, this.s, this.l / k);
+ };
+ d3_hslPrototype.darker = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return new d3_hsl(this.h, this.s, k * this.l);
+ };
+ d3_hslPrototype.rgb = function() {
+ return d3_hsl_rgb(this.h, this.s, this.l);
+ };
+ function d3_hsl_rgb(h, s, l) {
+ var m1, m2;
+ h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
+ s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
+ l = l < 0 ? 0 : l > 1 ? 1 : l;
+ m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
+ m1 = 2 * l - m2;
+ function v(h) {
+ if (h > 360) h -= 360; else if (h < 0) h += 360;
+ if (h < 60) return m1 + (m2 - m1) * h / 60;
+ if (h < 180) return m2;
+ if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
+ return m1;
+ }
+ function vv(h) {
+ return Math.round(v(h) * 255);
+ }
+ return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
+ }
+ d3.hcl = d3_hcl;
+ function d3_hcl(h, c, l) {
+ return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
+ }
+ var d3_hclPrototype = d3_hcl.prototype = new d3_color();
+ d3_hclPrototype.brighter = function(k) {
+ return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
+ };
+ d3_hclPrototype.darker = function(k) {
+ return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
+ };
+ d3_hclPrototype.rgb = function() {
+ return d3_hcl_lab(this.h, this.c, this.l).rgb();
+ };
+ function d3_hcl_lab(h, c, l) {
+ if (isNaN(h)) h = 0;
+ if (isNaN(c)) c = 0;
+ return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
+ }
+ d3.lab = d3_lab;
+ function d3_lab(l, a, b) {
+ return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
+ }
+ var d3_lab_K = 18;
+ var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
+ var d3_labPrototype = d3_lab.prototype = new d3_color();
+ d3_labPrototype.brighter = function(k) {
+ return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+ };
+ d3_labPrototype.darker = function(k) {
+ return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+ };
+ d3_labPrototype.rgb = function() {
+ return d3_lab_rgb(this.l, this.a, this.b);
+ };
+ function d3_lab_rgb(l, a, b) {
+ var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
+ x = d3_lab_xyz(x) * d3_lab_X;
+ y = d3_lab_xyz(y) * d3_lab_Y;
+ z = d3_lab_xyz(z) * d3_lab_Z;
+ return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
+ }
+ function d3_lab_hcl(l, a, b) {
+ return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
+ }
+ function d3_lab_xyz(x) {
+ return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
+ }
+ function d3_xyz_lab(x) {
+ return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
+ }
+ function d3_xyz_rgb(r) {
+ return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
+ }
+ d3.rgb = d3_rgb;
+ function d3_rgb(r, g, b) {
+ return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
+ }
+ function d3_rgbNumber(value) {
+ return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
+ }
+ function d3_rgbString(value) {
+ return d3_rgbNumber(value) + "";
+ }
+ var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
+ d3_rgbPrototype.brighter = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ var r = this.r, g = this.g, b = this.b, i = 30;
+ if (!r && !g && !b) return new d3_rgb(i, i, i);
+ if (r && r < i) r = i;
+ if (g && g < i) g = i;
+ if (b && b < i) b = i;
+ return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
+ };
+ d3_rgbPrototype.darker = function(k) {
+ k = Math.pow(.7, arguments.length ? k : 1);
+ return new d3_rgb(k * this.r, k * this.g, k * this.b);
+ };
+ d3_rgbPrototype.hsl = function() {
+ return d3_rgb_hsl(this.r, this.g, this.b);
+ };
+ d3_rgbPrototype.toString = function() {
+ return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
+ };
+ function d3_rgb_hex(v) {
+ return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
+ }
+ function d3_rgb_parse(format, rgb, hsl) {
+ var r = 0, g = 0, b = 0, m1, m2, color;
+ m1 = /([a-z]+)\((.*)\)/.exec(format = format.toLowerCase());
+ if (m1) {
+ m2 = m1[2].split(",");
+ switch (m1[1]) {
+ case "hsl":
+ {
+ return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
+ }
+
+ case "rgb":
+ {
+ return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
+ }
+ }
+ }
+ if (color = d3_rgb_names.get(format)) {
+ return rgb(color.r, color.g, color.b);
+ }
+ if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
+ if (format.length === 4) {
+ r = (color & 3840) >> 4;
+ r = r >> 4 | r;
+ g = color & 240;
+ g = g >> 4 | g;
+ b = color & 15;
+ b = b << 4 | b;
+ } else if (format.length === 7) {
+ r = (color & 16711680) >> 16;
+ g = (color & 65280) >> 8;
+ b = color & 255;
+ }
+ }
+ return rgb(r, g, b);
+ }
+ function d3_rgb_hsl(r, g, b) {
+ var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
+ if (d) {
+ s = l < .5 ? d / (max + min) : d / (2 - max - min);
+ if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
+ h *= 60;
+ } else {
+ h = NaN;
+ s = l > 0 && l < 1 ? 0 : h;
+ }
+ return new d3_hsl(h, s, l);
+ }
+ function d3_rgb_lab(r, g, b) {
+ r = d3_rgb_xyz(r);
+ g = d3_rgb_xyz(g);
+ b = d3_rgb_xyz(b);
+ var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
+ return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
+ }
+ function d3_rgb_xyz(r) {
+ return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
+ }
+ function d3_rgb_parseNumber(c) {
+ var f = parseFloat(c);
+ return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
+ }
+ var d3_rgb_names = d3.map({
+ aliceblue: 15792383,
+ antiquewhite: 16444375,
+ aqua: 65535,
+ aquamarine: 8388564,
+ azure: 15794175,
+ beige: 16119260,
+ bisque: 16770244,
+ black: 0,
+ blanchedalmond: 16772045,
+ blue: 255,
+ blueviolet: 9055202,
+ brown: 10824234,
+ burlywood: 14596231,
+ cadetblue: 6266528,
+ chartreuse: 8388352,
+ chocolate: 13789470,
+ coral: 16744272,
+ cornflowerblue: 6591981,
+ cornsilk: 16775388,
+ crimson: 14423100,
+ cyan: 65535,
+ darkblue: 139,
+ darkcyan: 35723,
+ darkgoldenrod: 12092939,
+ darkgray: 11119017,
+ darkgreen: 25600,
+ darkgrey: 11119017,
+ darkkhaki: 12433259,
+ darkmagenta: 9109643,
+ darkolivegreen: 5597999,
+ darkorange: 16747520,
+ darkorchid: 10040012,
+ darkred: 9109504,
+ darksalmon: 15308410,
+ darkseagreen: 9419919,
+ darkslateblue: 4734347,
+ darkslategray: 3100495,
+ darkslategrey: 3100495,
+ darkturquoise: 52945,
+ darkviolet: 9699539,
+ deeppink: 16716947,
+ deepskyblue: 49151,
+ dimgray: 6908265,
+ dimgrey: 6908265,
+ dodgerblue: 2003199,
+ firebrick: 11674146,
+ floralwhite: 16775920,
+ forestgreen: 2263842,
+ fuchsia: 16711935,
+ gainsboro: 14474460,
+ ghostwhite: 16316671,
+ gold: 16766720,
+ goldenrod: 14329120,
+ gray: 8421504,
+ green: 32768,
+ greenyellow: 11403055,
+ grey: 8421504,
+ honeydew: 15794160,
+ hotpink: 16738740,
+ indianred: 13458524,
+ indigo: 4915330,
+ ivory: 16777200,
+ khaki: 15787660,
+ lavender: 15132410,
+ lavenderblush: 16773365,
+ lawngreen: 8190976,
+ lemonchiffon: 16775885,
+ lightblue: 11393254,
+ lightcoral: 15761536,
+ lightcyan: 14745599,
+ lightgoldenrodyellow: 16448210,
+ lightgray: 13882323,
+ lightgreen: 9498256,
+ lightgrey: 13882323,
+ lightpink: 16758465,
+ lightsalmon: 16752762,
+ lightseagreen: 2142890,
+ lightskyblue: 8900346,
+ lightslategray: 7833753,
+ lightslategrey: 7833753,
+ lightsteelblue: 11584734,
+ lightyellow: 16777184,
+ lime: 65280,
+ limegreen: 3329330,
+ linen: 16445670,
+ magenta: 16711935,
+ maroon: 8388608,
+ mediumaquamarine: 6737322,
+ mediumblue: 205,
+ mediumorchid: 12211667,
+ mediumpurple: 9662683,
+ mediumseagreen: 3978097,
+ mediumslateblue: 8087790,
+ mediumspringgreen: 64154,
+ mediumturquoise: 4772300,
+ mediumvioletred: 13047173,
+ midnightblue: 1644912,
+ mintcream: 16121850,
+ mistyrose: 16770273,
+ moccasin: 16770229,
+ navajowhite: 16768685,
+ navy: 128,
+ oldlace: 16643558,
+ olive: 8421376,
+ olivedrab: 7048739,
+ orange: 16753920,
+ orangered: 16729344,
+ orchid: 14315734,
+ palegoldenrod: 15657130,
+ palegreen: 10025880,
+ paleturquoise: 11529966,
+ palevioletred: 14381203,
+ papayawhip: 16773077,
+ peachpuff: 16767673,
+ peru: 13468991,
+ pink: 16761035,
+ plum: 14524637,
+ powderblue: 11591910,
+ purple: 8388736,
+ rebeccapurple: 6697881,
+ red: 16711680,
+ rosybrown: 12357519,
+ royalblue: 4286945,
+ saddlebrown: 9127187,
+ salmon: 16416882,
+ sandybrown: 16032864,
+ seagreen: 3050327,
+ seashell: 16774638,
+ sienna: 10506797,
+ silver: 12632256,
+ skyblue: 8900331,
+ slateblue: 6970061,
+ slategray: 7372944,
+ slategrey: 7372944,
+ snow: 16775930,
+ springgreen: 65407,
+ steelblue: 4620980,
+ tan: 13808780,
+ teal: 32896,
+ thistle: 14204888,
+ tomato: 16737095,
+ turquoise: 4251856,
+ violet: 15631086,
+ wheat: 16113331,
+ white: 16777215,
+ whitesmoke: 16119285,
+ yellow: 16776960,
+ yellowgreen: 10145074
+ });
+ d3_rgb_names.forEach(function(key, value) {
+ d3_rgb_names.set(key, d3_rgbNumber(value));
+ });
+ function d3_functor(v) {
+ return typeof v === "function" ? v : function() {
+ return v;
+ };
+ }
+ d3.functor = d3_functor;
+ d3.xhr = d3_xhrType(d3_identity);
+ function d3_xhrType(response) {
+ return function(url, mimeType, callback) {
+ if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType,
+ mimeType = null;
+ return d3_xhr(url, mimeType, response, callback);
+ };
+ }
+ function d3_xhr(url, mimeType, response, callback) {
+ var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
+ if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
+ "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
+ request.readyState > 3 && respond();
+ };
+ function respond() {
+ var status = request.status, result;
+ if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
+ try {
+ result = response.call(xhr, request);
+ } catch (e) {
+ dispatch.error.call(xhr, e);
+ return;
+ }
+ dispatch.load.call(xhr, result);
+ } else {
+ dispatch.error.call(xhr, request);
+ }
+ }
+ request.onprogress = function(event) {
+ var o = d3.event;
+ d3.event = event;
+ try {
+ dispatch.progress.call(xhr, request);
+ } finally {
+ d3.event = o;
+ }
+ };
+ xhr.header = function(name, value) {
+ name = (name + "").toLowerCase();
+ if (arguments.length < 2) return headers[name];
+ if (value == null) delete headers[name]; else headers[name] = value + "";
+ return xhr;
+ };
+ xhr.mimeType = function(value) {
+ if (!arguments.length) return mimeType;
+ mimeType = value == null ? null : value + "";
+ return xhr;
+ };
+ xhr.responseType = function(value) {
+ if (!arguments.length) return responseType;
+ responseType = value;
+ return xhr;
+ };
+ xhr.response = function(value) {
+ response = value;
+ return xhr;
+ };
+ [ "get", "post" ].forEach(function(method) {
+ xhr[method] = function() {
+ return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
+ };
+ });
+ xhr.send = function(method, data, callback) {
+ if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
+ request.open(method, url, true);
+ if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
+ if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
+ if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
+ if (responseType != null) request.responseType = responseType;
+ if (callback != null) xhr.on("error", callback).on("load", function(request) {
+ callback(null, request);
+ });
+ dispatch.beforesend.call(xhr, request);
+ request.send(data == null ? null : data);
+ return xhr;
+ };
+ xhr.abort = function() {
+ request.abort();
+ return xhr;
+ };
+ d3.rebind(xhr, dispatch, "on");
+ return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
+ }
+ function d3_xhr_fixCallback(callback) {
+ return callback.length === 1 ? function(error, request) {
+ callback(error == null ? request : null);
+ } : callback;
+ }
+ function d3_xhrHasResponse(request) {
+ var type = request.responseType;
+ return type && type !== "text" ? request.response : request.responseText;
+ }
+ d3.dsv = function(delimiter, mimeType) {
+ var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
+ function dsv(url, row, callback) {
+ if (arguments.length < 3) callback = row, row = null;
+ var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
+ xhr.row = function(_) {
+ return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
+ };
+ return xhr;
+ }
+ function response(request) {
+ return dsv.parse(request.responseText);
+ }
+ function typedResponse(f) {
+ return function(request) {
+ return dsv.parse(request.responseText, f);
+ };
+ }
+ dsv.parse = function(text, f) {
+ var o;
+ return dsv.parseRows(text, function(row, i) {
+ if (o) return o(row, i - 1);
+ var a = new Function("d", "return {" + row.map(function(name, i) {
+ return JSON.stringify(name) + ": d[" + i + "]";
+ }).join(",") + "}");
+ o = f ? function(row, i) {
+ return f(a(row), i);
+ } : a;
+ });
+ };
+ dsv.parseRows = function(text, f) {
+ var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
+ function token() {
+ if (I >= N) return EOF;
+ if (eol) return eol = false, EOL;
+ var j = I;
+ if (text.charCodeAt(j) === 34) {
+ var i = j;
+ while (i++ < N) {
+ if (text.charCodeAt(i) === 34) {
+ if (text.charCodeAt(i + 1) !== 34) break;
+ ++i;
+ }
+ }
+ I = i + 2;
+ var c = text.charCodeAt(i + 1);
+ if (c === 13) {
+ eol = true;
+ if (text.charCodeAt(i + 2) === 10) ++I;
+ } else if (c === 10) {
+ eol = true;
+ }
+ return text.slice(j + 1, i).replace(/""/g, '"');
+ }
+ while (I < N) {
+ var c = text.charCodeAt(I++), k = 1;
+ if (c === 10) eol = true; else if (c === 13) {
+ eol = true;
+ if (text.charCodeAt(I) === 10) ++I, ++k;
+ } else if (c !== delimiterCode) continue;
+ return text.slice(j, I - k);
+ }
+ return text.slice(j);
+ }
+ while ((t = token()) !== EOF) {
+ var a = [];
+ while (t !== EOL && t !== EOF) {
+ a.push(t);
+ t = token();
+ }
+ if (f && (a = f(a, n++)) == null) continue;
+ rows.push(a);
+ }
+ return rows;
+ };
+ dsv.format = function(rows) {
+ if (Array.isArray(rows[0])) return dsv.formatRows(rows);
+ var fieldSet = new d3_Set(), fields = [];
+ rows.forEach(function(row) {
+ for (var field in row) {
+ if (!fieldSet.has(field)) {
+ fields.push(fieldSet.add(field));
+ }
+ }
+ });
+ return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
+ return fields.map(function(field) {
+ return formatValue(row[field]);
+ }).join(delimiter);
+ })).join("\n");
+ };
+ dsv.formatRows = function(rows) {
+ return rows.map(formatRow).join("\n");
+ };
+ function formatRow(row) {
+ return row.map(formatValue).join(delimiter);
+ }
+ function formatValue(text) {
+ return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
+ }
+ return dsv;
+ };
+ d3.csv = d3.dsv(",", "text/csv");
+ d3.tsv = d3.dsv(" ", "text/tab-separated-values");
+ var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) {
+ setTimeout(callback, 17);
+ };
+ d3.timer = function() {
+ d3_timer.apply(this, arguments);
+ };
+ function d3_timer(callback, delay, then) {
+ var n = arguments.length;
+ if (n < 2) delay = 0;
+ if (n < 3) then = Date.now();
+ var time = then + delay, timer = {
+ c: callback,
+ t: time,
+ n: null
+ };
+ if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
+ d3_timer_queueTail = timer;
+ if (!d3_timer_interval) {
+ d3_timer_timeout = clearTimeout(d3_timer_timeout);
+ d3_timer_interval = 1;
+ d3_timer_frame(d3_timer_step);
+ }
+ return timer;
+ }
+ function d3_timer_step() {
+ var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
+ if (delay > 24) {
+ if (isFinite(delay)) {
+ clearTimeout(d3_timer_timeout);
+ d3_timer_timeout = setTimeout(d3_timer_step, delay);
+ }
+ d3_timer_interval = 0;
+ } else {
+ d3_timer_interval = 1;
+ d3_timer_frame(d3_timer_step);
+ }
+ }
+ d3.timer.flush = function() {
+ d3_timer_mark();
+ d3_timer_sweep();
+ };
+ function d3_timer_mark() {
+ var now = Date.now(), timer = d3_timer_queueHead;
+ while (timer) {
+ if (now >= timer.t && timer.c(now - timer.t)) timer.c = null;
+ timer = timer.n;
+ }
+ return now;
+ }
+ function d3_timer_sweep() {
+ var t0, t1 = d3_timer_queueHead, time = Infinity;
+ while (t1) {
+ if (t1.c) {
+ if (t1.t < time) time = t1.t;
+ t1 = (t0 = t1).n;
+ } else {
+ t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
+ }
+ }
+ d3_timer_queueTail = t0;
+ return time;
+ }
+ function d3_format_precision(x, p) {
+ return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
+ }
+ d3.round = function(x, n) {
+ return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
+ };
+ var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
+ d3.formatPrefix = function(value, precision) {
+ var i = 0;
+ if (value = +value) {
+ if (value < 0) value *= -1;
+ if (precision) value = d3.round(value, d3_format_precision(value, precision));
+ i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
+ i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
+ }
+ return d3_formatPrefixes[8 + i / 3];
+ };
+ function d3_formatPrefix(d, i) {
+ var k = Math.pow(10, abs(8 - i) * 3);
+ return {
+ scale: i > 8 ? function(d) {
+ return d / k;
+ } : function(d) {
+ return d * k;
+ },
+ symbol: d
+ };
+ }
+ function d3_locale_numberFormat(locale) {
+ var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {
+ var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0;
+ while (i > 0 && g > 0) {
+ if (length + g + 1 > width) g = Math.max(1, width - length);
+ t.push(value.substring(i -= g, i + g));
+ if ((length += g + 1) > width) break;
+ g = locale_grouping[j = (j + 1) % locale_grouping.length];
+ }
+ return t.reverse().join(locale_thousands);
+ } : d3_identity;
+ return function(specifier) {
+ var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true;
+ if (precision) precision = +precision.substring(1);
+ if (zfill || fill === "0" && align === "=") {
+ zfill = fill = "0";
+ align = "=";
+ }
+ switch (type) {
+ case "n":
+ comma = true;
+ type = "g";
+ break;
+
+ case "%":
+ scale = 100;
+ suffix = "%";
+ type = "f";
+ break;
+
+ case "p":
+ scale = 100;
+ suffix = "%";
+ type = "r";
+ break;
+
+ case "b":
+ case "o":
+ case "x":
+ case "X":
+ if (symbol === "#") prefix = "0" + type.toLowerCase();
+
+ case "c":
+ exponent = false;
+
+ case "d":
+ integer = true;
+ precision = 0;
+ break;
+
+ case "s":
+ scale = -1;
+ type = "r";
+ break;
+ }
+ if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
+ if (type == "r" && !precision) type = "g";
+ if (precision != null) {
+ if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
+ }
+ type = d3_format_types.get(type) || d3_format_typeDefault;
+ var zcomma = zfill && comma;
+ return function(value) {
+ var fullSuffix = suffix;
+ if (integer && value % 1) return "";
+ var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign === "-" ? "" : sign;
+ if (scale < 0) {
+ var unit = d3.formatPrefix(value, precision);
+ value = unit.scale(value);
+ fullSuffix = unit.symbol + suffix;
+ } else {
+ value *= scale;
+ }
+ value = type(value, precision);
+ var i = value.lastIndexOf("."), before, after;
+ if (i < 0) {
+ var j = exponent ? value.lastIndexOf("e") : -1;
+ if (j < 0) before = value, after = ""; else before = value.substring(0, j), after = value.substring(j);
+ } else {
+ before = value.substring(0, i);
+ after = locale_decimal + value.substring(i + 1);
+ }
+ if (!zfill && comma) before = formatGroup(before, Infinity);
+ var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
+ if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);
+ negative += prefix;
+ value = before + after;
+ return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
+ };
+ };
+ }
+ var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
+ var d3_format_types = d3.map({
+ b: function(x) {
+ return x.toString(2);
+ },
+ c: function(x) {
+ return String.fromCharCode(x);
+ },
+ o: function(x) {
+ return x.toString(8);
+ },
+ x: function(x) {
+ return x.toString(16);
+ },
+ X: function(x) {
+ return x.toString(16).toUpperCase();
+ },
+ g: function(x, p) {
+ return x.toPrecision(p);
+ },
+ e: function(x, p) {
+ return x.toExponential(p);
+ },
+ f: function(x, p) {
+ return x.toFixed(p);
+ },
+ r: function(x, p) {
+ return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
+ }
+ });
+ function d3_format_typeDefault(x) {
+ return x + "";
+ }
+ var d3_time = d3.time = {}, d3_date = Date;
+ function d3_date_utc() {
+ this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
+ }
+ d3_date_utc.prototype = {
+ getDate: function() {
+ return this._.getUTCDate();
+ },
+ getDay: function() {
+ return this._.getUTCDay();
+ },
+ getFullYear: function() {
+ return this._.getUTCFullYear();
+ },
+ getHours: function() {
+ return this._.getUTCHours();
+ },
+ getMilliseconds: function() {
+ return this._.getUTCMilliseconds();
+ },
+ getMinutes: function() {
+ return this._.getUTCMinutes();
+ },
+ getMonth: function() {
+ return this._.getUTCMonth();
+ },
+ getSeconds: function() {
+ return this._.getUTCSeconds();
+ },
+ getTime: function() {
+ return this._.getTime();
+ },
+ getTimezoneOffset: function() {
+ return 0;
+ },
+ valueOf: function() {
+ return this._.valueOf();
+ },
+ setDate: function() {
+ d3_time_prototype.setUTCDate.apply(this._, arguments);
+ },
+ setDay: function() {
+ d3_time_prototype.setUTCDay.apply(this._, arguments);
+ },
+ setFullYear: function() {
+ d3_time_prototype.setUTCFullYear.apply(this._, arguments);
+ },
+ setHours: function() {
+ d3_time_prototype.setUTCHours.apply(this._, arguments);
+ },
+ setMilliseconds: function() {
+ d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
+ },
+ setMinutes: function() {
+ d3_time_prototype.setUTCMinutes.apply(this._, arguments);
+ },
+ setMonth: function() {
+ d3_time_prototype.setUTCMonth.apply(this._, arguments);
+ },
+ setSeconds: function() {
+ d3_time_prototype.setUTCSeconds.apply(this._, arguments);
+ },
+ setTime: function() {
+ d3_time_prototype.setTime.apply(this._, arguments);
+ }
+ };
+ var d3_time_prototype = Date.prototype;
+ function d3_time_interval(local, step, number) {
+ function round(date) {
+ var d0 = local(date), d1 = offset(d0, 1);
+ return date - d0 < d1 - date ? d0 : d1;
+ }
+ function ceil(date) {
+ step(date = local(new d3_date(date - 1)), 1);
+ return date;
+ }
+ function offset(date, k) {
+ step(date = new d3_date(+date), k);
+ return date;
+ }
+ function range(t0, t1, dt) {
+ var time = ceil(t0), times = [];
+ if (dt > 1) {
+ while (time < t1) {
+ if (!(number(time) % dt)) times.push(new Date(+time));
+ step(time, 1);
+ }
+ } else {
+ while (time < t1) times.push(new Date(+time)), step(time, 1);
+ }
+ return times;
+ }
+ function range_utc(t0, t1, dt) {
+ try {
+ d3_date = d3_date_utc;
+ var utc = new d3_date_utc();
+ utc._ = t0;
+ return range(utc, t1, dt);
+ } finally {
+ d3_date = Date;
+ }
+ }
+ local.floor = local;
+ local.round = round;
+ local.ceil = ceil;
+ local.offset = offset;
+ local.range = range;
+ var utc = local.utc = d3_time_interval_utc(local);
+ utc.floor = utc;
+ utc.round = d3_time_interval_utc(round);
+ utc.ceil = d3_time_interval_utc(ceil);
+ utc.offset = d3_time_interval_utc(offset);
+ utc.range = range_utc;
+ return local;
+ }
+ function d3_time_interval_utc(method) {
+ return function(date, k) {
+ try {
+ d3_date = d3_date_utc;
+ var utc = new d3_date_utc();
+ utc._ = date;
+ return method(utc, k)._;
+ } finally {
+ d3_date = Date;
+ }
+ };
+ }
+ d3_time.year = d3_time_interval(function(date) {
+ date = d3_time.day(date);
+ date.setMonth(0, 1);
+ return date;
+ }, function(date, offset) {
+ date.setFullYear(date.getFullYear() + offset);
+ }, function(date) {
+ return date.getFullYear();
+ });
+ d3_time.years = d3_time.year.range;
+ d3_time.years.utc = d3_time.year.utc.range;
+ d3_time.day = d3_time_interval(function(date) {
+ var day = new d3_date(2e3, 0);
+ day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+ return day;
+ }, function(date, offset) {
+ date.setDate(date.getDate() + offset);
+ }, function(date) {
+ return date.getDate() - 1;
+ });
+ d3_time.days = d3_time.day.range;
+ d3_time.days.utc = d3_time.day.utc.range;
+ d3_time.dayOfYear = function(date) {
+ var year = d3_time.year(date);
+ return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
+ };
+ [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
+ i = 7 - i;
+ var interval = d3_time[day] = d3_time_interval(function(date) {
+ (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
+ return date;
+ }, function(date, offset) {
+ date.setDate(date.getDate() + Math.floor(offset) * 7);
+ }, function(date) {
+ var day = d3_time.year(date).getDay();
+ return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
+ });
+ d3_time[day + "s"] = interval.range;
+ d3_time[day + "s"].utc = interval.utc.range;
+ d3_time[day + "OfYear"] = function(date) {
+ var day = d3_time.year(date).getDay();
+ return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
+ };
+ });
+ d3_time.week = d3_time.sunday;
+ d3_time.weeks = d3_time.sunday.range;
+ d3_time.weeks.utc = d3_time.sunday.utc.range;
+ d3_time.weekOfYear = d3_time.sundayOfYear;
+ function d3_locale_timeFormat(locale) {
+ var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
+ function d3_time_format(template) {
+ var n = template.length;
+ function format(date) {
+ var string = [], i = -1, j = 0, c, p, f;
+ while (++i < n) {
+ if (template.charCodeAt(i) === 37) {
+ string.push(template.slice(j, i));
+ if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
+ if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
+ string.push(c);
+ j = i + 1;
+ }
+ }
+ string.push(template.slice(j, i));
+ return string.join("");
+ }
+ format.parse = function(string) {
+ var d = {
+ y: 1900,
+ m: 0,
+ d: 1,
+ H: 0,
+ M: 0,
+ S: 0,
+ L: 0,
+ Z: null
+ }, i = d3_time_parse(d, template, string, 0);
+ if (i != string.length) return null;
+ if ("p" in d) d.H = d.H % 12 + d.p * 12;
+ var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
+ if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("W" in d || "U" in d) {
+ if (!("w" in d)) d.w = "W" in d ? 1 : 0;
+ date.setFullYear(d.y, 0, 1);
+ date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
+ } else date.setFullYear(d.y, d.m, d.d);
+ date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L);
+ return localZ ? date._ : date;
+ };
+ format.toString = function() {
+ return template;
+ };
+ return format;
+ }
+ function d3_time_parse(date, template, string, j) {
+ var c, p, t, i = 0, n = template.length, m = string.length;
+ while (i < n) {
+ if (j >= m) return -1;
+ c = template.charCodeAt(i++);
+ if (c === 37) {
+ t = template.charAt(i++);
+ p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
+ if (!p || (j = p(date, string, j)) < 0) return -1;
+ } else if (c != string.charCodeAt(j++)) {
+ return -1;
+ }
+ }
+ return j;
+ }
+ d3_time_format.utc = function(template) {
+ var local = d3_time_format(template);
+ function format(date) {
+ try {
+ d3_date = d3_date_utc;
+ var utc = new d3_date();
+ utc._ = date;
+ return local(utc);
+ } finally {
+ d3_date = Date;
+ }
+ }
+ format.parse = function(string) {
+ try {
+ d3_date = d3_date_utc;
+ var date = local.parse(string);
+ return date && date._;
+ } finally {
+ d3_date = Date;
+ }
+ };
+ format.toString = local.toString;
+ return format;
+ };
+ d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
+ var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
+ locale_periods.forEach(function(p, i) {
+ d3_time_periodLookup.set(p.toLowerCase(), i);
+ });
+ var d3_time_formats = {
+ a: function(d) {
+ return locale_shortDays[d.getDay()];
+ },
+ A: function(d) {
+ return locale_days[d.getDay()];
+ },
+ b: function(d) {
+ return locale_shortMonths[d.getMonth()];
+ },
+ B: function(d) {
+ return locale_months[d.getMonth()];
+ },
+ c: d3_time_format(locale_dateTime),
+ d: function(d, p) {
+ return d3_time_formatPad(d.getDate(), p, 2);
+ },
+ e: function(d, p) {
+ return d3_time_formatPad(d.getDate(), p, 2);
+ },
+ H: function(d, p) {
+ return d3_time_formatPad(d.getHours(), p, 2);
+ },
+ I: function(d, p) {
+ return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
+ },
+ j: function(d, p) {
+ return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
+ },
+ L: function(d, p) {
+ return d3_time_formatPad(d.getMilliseconds(), p, 3);
+ },
+ m: function(d, p) {
+ return d3_time_formatPad(d.getMonth() + 1, p, 2);
+ },
+ M: function(d, p) {
+ return d3_time_formatPad(d.getMinutes(), p, 2);
+ },
+ p: function(d) {
+ return locale_periods[+(d.getHours() >= 12)];
+ },
+ S: function(d, p) {
+ return d3_time_formatPad(d.getSeconds(), p, 2);
+ },
+ U: function(d, p) {
+ return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
+ },
+ w: function(d) {
+ return d.getDay();
+ },
+ W: function(d, p) {
+ return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
+ },
+ x: d3_time_format(locale_date),
+ X: d3_time_format(locale_time),
+ y: function(d, p) {
+ return d3_time_formatPad(d.getFullYear() % 100, p, 2);
+ },
+ Y: function(d, p) {
+ return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
+ },
+ Z: d3_time_zone,
+ "%": function() {
+ return "%";
+ }
+ };
+ var d3_time_parsers = {
+ a: d3_time_parseWeekdayAbbrev,
+ A: d3_time_parseWeekday,
+ b: d3_time_parseMonthAbbrev,
+ B: d3_time_parseMonth,
+ c: d3_time_parseLocaleFull,
+ d: d3_time_parseDay,
+ e: d3_time_parseDay,
+ H: d3_time_parseHour24,
+ I: d3_time_parseHour24,
+ j: d3_time_parseDayOfYear,
+ L: d3_time_parseMilliseconds,
+ m: d3_time_parseMonthNumber,
+ M: d3_time_parseMinutes,
+ p: d3_time_parseAmPm,
+ S: d3_time_parseSeconds,
+ U: d3_time_parseWeekNumberSunday,
+ w: d3_time_parseWeekdayNumber,
+ W: d3_time_parseWeekNumberMonday,
+ x: d3_time_parseLocaleDate,
+ X: d3_time_parseLocaleTime,
+ y: d3_time_parseYear,
+ Y: d3_time_parseFullYear,
+ Z: d3_time_parseZone,
+ "%": d3_time_parseLiteralPercent
+ };
+ function d3_time_parseWeekdayAbbrev(date, string, i) {
+ d3_time_dayAbbrevRe.lastIndex = 0;
+ var n = d3_time_dayAbbrevRe.exec(string.slice(i));
+ return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+ }
+ function d3_time_parseWeekday(date, string, i) {
+ d3_time_dayRe.lastIndex = 0;
+ var n = d3_time_dayRe.exec(string.slice(i));
+ return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+ }
+ function d3_time_parseMonthAbbrev(date, string, i) {
+ d3_time_monthAbbrevRe.lastIndex = 0;
+ var n = d3_time_monthAbbrevRe.exec(string.slice(i));
+ return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+ }
+ function d3_time_parseMonth(date, string, i) {
+ d3_time_monthRe.lastIndex = 0;
+ var n = d3_time_monthRe.exec(string.slice(i));
+ return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+ }
+ function d3_time_parseLocaleFull(date, string, i) {
+ return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
+ }
+ function d3_time_parseLocaleDate(date, string, i) {
+ return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
+ }
+ function d3_time_parseLocaleTime(date, string, i) {
+ return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
+ }
+ function d3_time_parseAmPm(date, string, i) {
+ var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase());
+ return n == null ? -1 : (date.p = n, i);
+ }
+ return d3_time_format;
+ }
+ var d3_time_formatPads = {
+ "-": "",
+ _: " ",
+ "0": "0"
+ }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
+ function d3_time_formatPad(value, fill, width) {
+ var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length;
+ return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
+ }
+ function d3_time_formatRe(names) {
+ return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
+ }
+ function d3_time_formatLookup(names) {
+ var map = new d3_Map(), i = -1, n = names.length;
+ while (++i < n) map.set(names[i].toLowerCase(), i);
+ return map;
+ }
+ function d3_time_parseWeekdayNumber(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 1));
+ return n ? (date.w = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseWeekNumberSunday(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i));
+ return n ? (date.U = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseWeekNumberMonday(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i));
+ return n ? (date.W = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseFullYear(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 4));
+ return n ? (date.y = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseYear(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 2));
+ return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
+ }
+ function d3_time_parseZone(date, string, i) {
+ return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string,
+ i + 5) : -1;
+ }
+ function d3_time_expandYear(d) {
+ return d + (d > 68 ? 1900 : 2e3);
+ }
+ function d3_time_parseMonthNumber(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 2));
+ return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
+ }
+ function d3_time_parseDay(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 2));
+ return n ? (date.d = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseDayOfYear(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 3));
+ return n ? (date.j = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseHour24(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 2));
+ return n ? (date.H = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseMinutes(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 2));
+ return n ? (date.M = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseSeconds(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 2));
+ return n ? (date.S = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_parseMilliseconds(date, string, i) {
+ d3_time_numberRe.lastIndex = 0;
+ var n = d3_time_numberRe.exec(string.slice(i, i + 3));
+ return n ? (date.L = +n[0], i + n[0].length) : -1;
+ }
+ function d3_time_zone(d) {
+ var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60;
+ return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
+ }
+ function d3_time_parseLiteralPercent(date, string, i) {
+ d3_time_percentRe.lastIndex = 0;
+ var n = d3_time_percentRe.exec(string.slice(i, i + 1));
+ return n ? i + n[0].length : -1;
+ }
+ function d3_time_formatMulti(formats) {
+ var n = formats.length, i = -1;
+ while (++i < n) formats[i][0] = this(formats[i][0]);
+ return function(date) {
+ var i = 0, f = formats[i];
+ while (!f[1](date)) f = formats[++i];
+ return f[0](date);
+ };
+ }
+ d3.locale = function(locale) {
+ return {
+ numberFormat: d3_locale_numberFormat(locale),
+ timeFormat: d3_locale_timeFormat(locale)
+ };
+ };
+ var d3_locale_enUS = d3.locale({
+ decimal: ".",
+ thousands: ",",
+ grouping: [ 3 ],
+ currency: [ "$", "" ],
+ dateTime: "%a %b %e %X %Y",
+ date: "%m/%d/%Y",
+ time: "%H:%M:%S",
+ periods: [ "AM", "PM" ],
+ days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
+ shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
+ months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
+ shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
+ });
+ d3.format = d3_locale_enUS.numberFormat;
+ d3.geo = {};
+ function d3_adder() {}
+ d3_adder.prototype = {
+ s: 0,
+ t: 0,
+ add: function(y) {
+ d3_adderSum(y, this.t, d3_adderTemp);
+ d3_adderSum(d3_adderTemp.s, this.s, this);
+ if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
+ },
+ reset: function() {
+ this.s = this.t = 0;
+ },
+ valueOf: function() {
+ return this.s;
+ }
+ };
+ var d3_adderTemp = new d3_adder();
+ function d3_adderSum(a, b, o) {
+ var x = o.s = a + b, bv = x - a, av = x - bv;
+ o.t = a - av + (b - bv);
+ }
+ d3.geo.stream = function(object, listener) {
+ if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
+ d3_geo_streamObjectType[object.type](object, listener);
+ } else {
+ d3_geo_streamGeometry(object, listener);
+ }
+ };
+ function d3_geo_streamGeometry(geometry, listener) {
+ if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
+ d3_geo_streamGeometryType[geometry.type](geometry, listener);
+ }
+ }
+ var d3_geo_streamObjectType = {
+ Feature: function(feature, listener) {
+ d3_geo_streamGeometry(feature.geometry, listener);
+ },
+ FeatureCollection: function(object, listener) {
+ var features = object.features, i = -1, n = features.length;
+ while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
+ }
+ };
+ var d3_geo_streamGeometryType = {
+ Sphere: function(object, listener) {
+ listener.sphere();
+ },
+ Point: function(object, listener) {
+ object = object.coordinates;
+ listener.point(object[0], object[1], object[2]);
+ },
+ MultiPoint: function(object, listener) {
+ var coordinates = object.coordinates, i = -1, n = coordinates.length;
+ while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
+ },
+ LineString: function(object, listener) {
+ d3_geo_streamLine(object.coordinates, listener, 0);
+ },
+ MultiLineString: function(object, listener) {
+ var coordinates = object.coordinates, i = -1, n = coordinates.length;
+ while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
+ },
+ Polygon: function(object, listener) {
+ d3_geo_streamPolygon(object.coordinates, listener);
+ },
+ MultiPolygon: function(object, listener) {
+ var coordinates = object.coordinates, i = -1, n = coordinates.length;
+ while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
+ },
+ GeometryCollection: function(object, listener) {
+ var geometries = object.geometries, i = -1, n = geometries.length;
+ while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
+ }
+ };
+ function d3_geo_streamLine(coordinates, listener, closed) {
+ var i = -1, n = coordinates.length - closed, coordinate;
+ listener.lineStart();
+ while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
+ listener.lineEnd();
+ }
+ function d3_geo_streamPolygon(coordinates, listener) {
+ var i = -1, n = coordinates.length;
+ listener.polygonStart();
+ while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
+ listener.polygonEnd();
+ }
+ d3.geo.area = function(object) {
+ d3_geo_areaSum = 0;
+ d3.geo.stream(object, d3_geo_area);
+ return d3_geo_areaSum;
+ };
+ var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
+ var d3_geo_area = {
+ sphere: function() {
+ d3_geo_areaSum += 4 * π;
+ },
+ point: d3_noop,
+ lineStart: d3_noop,
+ lineEnd: d3_noop,
+ polygonStart: function() {
+ d3_geo_areaRingSum.reset();
+ d3_geo_area.lineStart = d3_geo_areaRingStart;
+ },
+ polygonEnd: function() {
+ var area = 2 * d3_geo_areaRingSum;
+ d3_geo_areaSum += area < 0 ? 4 * π + area : area;
+ d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
+ }
+ };
+ function d3_geo_areaRingStart() {
+ var λ00, φ00, λ0, cosφ0, sinφ0;
+ d3_geo_area.point = function(λ, φ) {
+ d3_geo_area.point = nextPoint;
+ λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4),
+ sinφ0 = Math.sin(φ);
+ };
+ function nextPoint(λ, φ) {
+ λ *= d3_radians;
+ φ = φ * d3_radians / 2 + π / 4;
+ var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
+ d3_geo_areaRingSum.add(Math.atan2(v, u));
+ λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
+ }
+ d3_geo_area.lineEnd = function() {
+ nextPoint(λ00, φ00);
+ };
+ }
+ function d3_geo_cartesian(spherical) {
+ var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
+ return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
+ }
+ function d3_geo_cartesianDot(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+ }
+ function d3_geo_cartesianCross(a, b) {
+ return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
+ }
+ function d3_geo_cartesianAdd(a, b) {
+ a[0] += b[0];
+ a[1] += b[1];
+ a[2] += b[2];
+ }
+ function d3_geo_cartesianScale(vector, k) {
+ return [ vector[0] * k, vector[1] * k, vector[2] * k ];
+ }
+ function d3_geo_cartesianNormalize(d) {
+ var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
+ d[0] /= l;
+ d[1] /= l;
+ d[2] /= l;
+ }
+ function d3_geo_spherical(cartesian) {
+ return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
+ }
+ function d3_geo_sphericalEqual(a, b) {
+ return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
+ }
+ d3.geo.bounds = function() {
+ var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
+ var bound = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ bound.point = ringPoint;
+ bound.lineStart = ringStart;
+ bound.lineEnd = ringEnd;
+ dλSum = 0;
+ d3_geo_area.polygonStart();
+ },
+ polygonEnd: function() {
+ d3_geo_area.polygonEnd();
+ bound.point = point;
+ bound.lineStart = lineStart;
+ bound.lineEnd = lineEnd;
+ if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
+ range[0] = λ0, range[1] = λ1;
+ }
+ };
+ function point(λ, φ) {
+ ranges.push(range = [ λ0 = λ, λ1 = λ ]);
+ if (φ < φ0) φ0 = φ;
+ if (φ > φ1) φ1 = φ;
+ }
+ function linePoint(λ, φ) {
+ var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
+ if (p0) {
+ var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
+ d3_geo_cartesianNormalize(inflection);
+ inflection = d3_geo_spherical(inflection);
+ var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
+ if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+ var φi = inflection[1] * d3_degrees;
+ if (φi > φ1) φ1 = φi;
+ } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+ var φi = -inflection[1] * d3_degrees;
+ if (φi < φ0) φ0 = φi;
+ } else {
+ if (φ < φ0) φ0 = φ;
+ if (φ > φ1) φ1 = φ;
+ }
+ if (antimeridian) {
+ if (λ < λ_) {
+ if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+ } else {
+ if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+ }
+ } else {
+ if (λ1 >= λ0) {
+ if (λ < λ0) λ0 = λ;
+ if (λ > λ1) λ1 = λ;
+ } else {
+ if (λ > λ_) {
+ if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+ } else {
+ if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+ }
+ }
+ }
+ } else {
+ point(λ, φ);
+ }
+ p0 = p, λ_ = λ;
+ }
+ function lineStart() {
+ bound.point = linePoint;
+ }
+ function lineEnd() {
+ range[0] = λ0, range[1] = λ1;
+ bound.point = point;
+ p0 = null;
+ }
+ function ringPoint(λ, φ) {
+ if (p0) {
+ var dλ = λ - λ_;
+ dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
+ } else λ__ = λ, φ__ = φ;
+ d3_geo_area.point(λ, φ);
+ linePoint(λ, φ);
+ }
+ function ringStart() {
+ d3_geo_area.lineStart();
+ }
+ function ringEnd() {
+ ringPoint(λ__, φ__);
+ d3_geo_area.lineEnd();
+ if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
+ range[0] = λ0, range[1] = λ1;
+ p0 = null;
+ }
+ function angle(λ0, λ1) {
+ return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
+ }
+ function compareRanges(a, b) {
+ return a[0] - b[0];
+ }
+ function withinRange(x, range) {
+ return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
+ }
+ return function(feature) {
+ φ1 = λ1 = -(λ0 = φ0 = Infinity);
+ ranges = [];
+ d3.geo.stream(feature, bound);
+ var n = ranges.length;
+ if (n) {
+ ranges.sort(compareRanges);
+ for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
+ b = ranges[i];
+ if (withinRange(b[0], a) || withinRange(b[1], a)) {
+ if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
+ if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
+ } else {
+ merged.push(a = b);
+ }
+ }
+ var best = -Infinity, dλ;
+ for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
+ b = merged[i];
+ if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
+ }
+ }
+ ranges = range = null;
+ return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
+ };
+ }();
+ d3.geo.centroid = function(object) {
+ d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+ d3.geo.stream(object, d3_geo_centroid);
+ var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
+ if (m < ε2) {
+ x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
+ if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
+ m = x * x + y * y + z * z;
+ if (m < ε2) return [ NaN, NaN ];
+ }
+ return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
+ };
+ var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
+ var d3_geo_centroid = {
+ sphere: d3_noop,
+ point: d3_geo_centroidPoint,
+ lineStart: d3_geo_centroidLineStart,
+ lineEnd: d3_geo_centroidLineEnd,
+ polygonStart: function() {
+ d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
+ },
+ polygonEnd: function() {
+ d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
+ }
+ };
+ function d3_geo_centroidPoint(λ, φ) {
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians);
+ d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
+ }
+ function d3_geo_centroidPointXYZ(x, y, z) {
+ ++d3_geo_centroidW0;
+ d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
+ d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
+ d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
+ }
+ function d3_geo_centroidLineStart() {
+ var x0, y0, z0;
+ d3_geo_centroid.point = function(λ, φ) {
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians);
+ x0 = cosφ * Math.cos(λ);
+ y0 = cosφ * Math.sin(λ);
+ z0 = Math.sin(φ);
+ d3_geo_centroid.point = nextPoint;
+ d3_geo_centroidPointXYZ(x0, y0, z0);
+ };
+ function nextPoint(λ, φ) {
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
+ d3_geo_centroidW1 += w;
+ d3_geo_centroidX1 += w * (x0 + (x0 = x));
+ d3_geo_centroidY1 += w * (y0 + (y0 = y));
+ d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+ d3_geo_centroidPointXYZ(x0, y0, z0);
+ }
+ }
+ function d3_geo_centroidLineEnd() {
+ d3_geo_centroid.point = d3_geo_centroidPoint;
+ }
+ function d3_geo_centroidRingStart() {
+ var λ00, φ00, x0, y0, z0;
+ d3_geo_centroid.point = function(λ, φ) {
+ λ00 = λ, φ00 = φ;
+ d3_geo_centroid.point = nextPoint;
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians);
+ x0 = cosφ * Math.cos(λ);
+ y0 = cosφ * Math.sin(λ);
+ z0 = Math.sin(φ);
+ d3_geo_centroidPointXYZ(x0, y0, z0);
+ };
+ d3_geo_centroid.lineEnd = function() {
+ nextPoint(λ00, φ00);
+ d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
+ d3_geo_centroid.point = d3_geo_centroidPoint;
+ };
+ function nextPoint(λ, φ) {
+ λ *= d3_radians;
+ var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
+ d3_geo_centroidX2 += v * cx;
+ d3_geo_centroidY2 += v * cy;
+ d3_geo_centroidZ2 += v * cz;
+ d3_geo_centroidW1 += w;
+ d3_geo_centroidX1 += w * (x0 + (x0 = x));
+ d3_geo_centroidY1 += w * (y0 + (y0 = y));
+ d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+ d3_geo_centroidPointXYZ(x0, y0, z0);
+ }
+ }
+ function d3_geo_compose(a, b) {
+ function compose(x, y) {
+ return x = a(x, y), b(x[0], x[1]);
+ }
+ if (a.invert && b.invert) compose.invert = function(x, y) {
+ return x = b.invert(x, y), x && a.invert(x[0], x[1]);
+ };
+ return compose;
+ }
+ function d3_true() {
+ return true;
+ }
+ function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
+ var subject = [], clip = [];
+ segments.forEach(function(segment) {
+ if ((n = segment.length - 1) <= 0) return;
+ var n, p0 = segment[0], p1 = segment[n];
+ if (d3_geo_sphericalEqual(p0, p1)) {
+ listener.lineStart();
+ for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
+ listener.lineEnd();
+ return;
+ }
+ var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
+ a.o = b;
+ subject.push(a);
+ clip.push(b);
+ a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
+ b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
+ a.o = b;
+ subject.push(a);
+ clip.push(b);
+ });
+ clip.sort(compare);
+ d3_geo_clipPolygonLinkCircular(subject);
+ d3_geo_clipPolygonLinkCircular(clip);
+ if (!subject.length) return;
+ for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
+ clip[i].e = entry = !entry;
+ }
+ var start = subject[0], points, point;
+ while (1) {
+ var current = start, isSubject = true;
+ while (current.v) if ((current = current.n) === start) return;
+ points = current.z;
+ listener.lineStart();
+ do {
+ current.v = current.o.v = true;
+ if (current.e) {
+ if (isSubject) {
+ for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
+ } else {
+ interpolate(current.x, current.n.x, 1, listener);
+ }
+ current = current.n;
+ } else {
+ if (isSubject) {
+ points = current.p.z;
+ for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
+ } else {
+ interpolate(current.x, current.p.x, -1, listener);
+ }
+ current = current.p;
+ }
+ current = current.o;
+ points = current.z;
+ isSubject = !isSubject;
+ } while (!current.v);
+ listener.lineEnd();
+ }
+ }
+ function d3_geo_clipPolygonLinkCircular(array) {
+ if (!(n = array.length)) return;
+ var n, i = 0, a = array[0], b;
+ while (++i < n) {
+ a.n = b = array[i];
+ b.p = a;
+ a = b;
+ }
+ a.n = b = array[0];
+ b.p = a;
+ }
+ function d3_geo_clipPolygonIntersection(point, points, other, entry) {
+ this.x = point;
+ this.z = points;
+ this.o = other;
+ this.e = entry;
+ this.v = false;
+ this.n = this.p = null;
+ }
+ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
+ return function(rotate, listener) {
+ var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
+ var clip = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ clip.point = pointRing;
+ clip.lineStart = ringStart;
+ clip.lineEnd = ringEnd;
+ segments = [];
+ polygon = [];
+ },
+ polygonEnd: function() {
+ clip.point = point;
+ clip.lineStart = lineStart;
+ clip.lineEnd = lineEnd;
+ segments = d3.merge(segments);
+ var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
+ if (segments.length) {
+ if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
+ d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
+ } else if (clipStartInside) {
+ if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
+ listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd();
+ }
+ if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
+ segments = polygon = null;
+ },
+ sphere: function() {
+ listener.polygonStart();
+ listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd();
+ listener.polygonEnd();
+ }
+ };
+ function point(λ, φ) {
+ var point = rotate(λ, φ);
+ if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
+ }
+ function pointLine(λ, φ) {
+ var point = rotate(λ, φ);
+ line.point(point[0], point[1]);
+ }
+ function lineStart() {
+ clip.point = pointLine;
+ line.lineStart();
+ }
+ function lineEnd() {
+ clip.point = point;
+ line.lineEnd();
+ }
+ var segments;
+ var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
+ function pointRing(λ, φ) {
+ ring.push([ λ, φ ]);
+ var point = rotate(λ, φ);
+ ringListener.point(point[0], point[1]);
+ }
+ function ringStart() {
+ ringListener.lineStart();
+ ring = [];
+ }
+ function ringEnd() {
+ pointRing(ring[0][0], ring[0][1]);
+ ringListener.lineEnd();
+ var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
+ ring.pop();
+ polygon.push(ring);
+ ring = null;
+ if (!n) return;
+ if (clean & 1) {
+ segment = ringSegments[0];
+ var n = segment.length - 1, i = -1, point;
+ if (n > 0) {
+ if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
+ listener.lineStart();
+ while (++i < n) listener.point((point = segment[i])[0], point[1]);
+ listener.lineEnd();
+ }
+ return;
+ }
+ if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
+ segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
+ }
+ return clip;
+ };
+ }
+ function d3_geo_clipSegmentLength1(segment) {
+ return segment.length > 1;
+ }
+ function d3_geo_clipBufferListener() {
+ var lines = [], line;
+ return {
+ lineStart: function() {
+ lines.push(line = []);
+ },
+ point: function(λ, φ) {
+ line.push([ λ, φ ]);
+ },
+ lineEnd: d3_noop,
+ buffer: function() {
+ var buffer = lines;
+ lines = [];
+ line = null;
+ return buffer;
+ },
+ rejoin: function() {
+ if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
+ }
+ };
+ }
+ function d3_geo_clipSort(a, b) {
+ return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
+ }
+ var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
+ function d3_geo_clipAntimeridianLine(listener) {
+ var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
+ return {
+ lineStart: function() {
+ listener.lineStart();
+ clean = 1;
+ },
+ point: function(λ1, φ1) {
+ var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
+ if (abs(dλ - π) < ε) {
+ listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
+ listener.point(sλ0, φ0);
+ listener.lineEnd();
+ listener.lineStart();
+ listener.point(sλ1, φ0);
+ listener.point(λ1, φ0);
+ clean = 0;
+ } else if (sλ0 !== sλ1 && dλ >= π) {
+ if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
+ if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
+ φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
+ listener.point(sλ0, φ0);
+ listener.lineEnd();
+ listener.lineStart();
+ listener.point(sλ1, φ0);
+ clean = 0;
+ }
+ listener.point(λ0 = λ1, φ0 = φ1);
+ sλ0 = sλ1;
+ },
+ lineEnd: function() {
+ listener.lineEnd();
+ λ0 = φ0 = NaN;
+ },
+ clean: function() {
+ return 2 - clean;
+ }
+ };
+ }
+ function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
+ var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
+ return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
+ }
+ function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
+ var φ;
+ if (from == null) {
+ φ = direction * halfπ;
+ listener.point(-π, φ);
+ listener.point(0, φ);
+ listener.point(π, φ);
+ listener.point(π, 0);
+ listener.point(π, -φ);
+ listener.point(0, -φ);
+ listener.point(-π, -φ);
+ listener.point(-π, 0);
+ listener.point(-π, φ);
+ } else if (abs(from[0] - to[0]) > ε) {
+ var s = from[0] < to[0] ? π : -π;
+ φ = direction * s / 2;
+ listener.point(-s, φ);
+ listener.point(0, φ);
+ listener.point(s, φ);
+ } else {
+ listener.point(to[0], to[1]);
+ }
+ }
+ function d3_geo_pointInPolygon(point, polygon) {
+ var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
+ d3_geo_areaRingSum.reset();
+ for (var i = 0, n = polygon.length; i < n; ++i) {
+ var ring = polygon[i], m = ring.length;
+ if (!m) continue;
+ var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
+ while (true) {
+ if (j === m) j = 0;
+ point = ring[j];
+ var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
+ d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
+ polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
+ if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
+ var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
+ d3_geo_cartesianNormalize(arc);
+ var intersection = d3_geo_cartesianCross(meridianNormal, arc);
+ d3_geo_cartesianNormalize(intersection);
+ var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
+ if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
+ winding += antimeridian ^ dλ >= 0 ? 1 : -1;
+ }
+ }
+ if (!j++) break;
+ λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
+ }
+ }
+ return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < -ε) ^ winding & 1;
+ }
+ function d3_geo_clipCircle(radius) {
+ var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
+ return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
+ function visible(λ, φ) {
+ return Math.cos(λ) * Math.cos(φ) > cr;
+ }
+ function clipLine(listener) {
+ var point0, c0, v0, v00, clean;
+ return {
+ lineStart: function() {
+ v00 = v0 = false;
+ clean = 1;
+ },
+ point: function(λ, φ) {
+ var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
+ if (!point0 && (v00 = v0 = v)) listener.lineStart();
+ if (v !== v0) {
+ point2 = intersect(point0, point1);
+ if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
+ point1[0] += ε;
+ point1[1] += ε;
+ v = visible(point1[0], point1[1]);
+ }
+ }
+ if (v !== v0) {
+ clean = 0;
+ if (v) {
+ listener.lineStart();
+ point2 = intersect(point1, point0);
+ listener.point(point2[0], point2[1]);
+ } else {
+ point2 = intersect(point0, point1);
+ listener.point(point2[0], point2[1]);
+ listener.lineEnd();
+ }
+ point0 = point2;
+ } else if (notHemisphere && point0 && smallRadius ^ v) {
+ var t;
+ if (!(c & c0) && (t = intersect(point1, point0, true))) {
+ clean = 0;
+ if (smallRadius) {
+ listener.lineStart();
+ listener.point(t[0][0], t[0][1]);
+ listener.point(t[1][0], t[1][1]);
+ listener.lineEnd();
+ } else {
+ listener.point(t[1][0], t[1][1]);
+ listener.lineEnd();
+ listener.lineStart();
+ listener.point(t[0][0], t[0][1]);
+ }
+ }
+ }
+ if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
+ listener.point(point1[0], point1[1]);
+ }
+ point0 = point1, v0 = v, c0 = c;
+ },
+ lineEnd: function() {
+ if (v0) listener.lineEnd();
+ point0 = null;
+ },
+ clean: function() {
+ return clean | (v00 && v0) << 1;
+ }
+ };
+ }
+ function intersect(a, b, two) {
+ var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
+ var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
+ if (!determinant) return !two && a;
+ var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
+ d3_geo_cartesianAdd(A, B);
+ var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
+ if (t2 < 0) return;
+ var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
+ d3_geo_cartesianAdd(q, A);
+ q = d3_geo_spherical(q);
+ if (!two) return q;
+ var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
+ if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
+ var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
+ if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
+ if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
+ var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
+ d3_geo_cartesianAdd(q1, A);
+ return [ q, d3_geo_spherical(q1) ];
+ }
+ }
+ function code(λ, φ) {
+ var r = smallRadius ? radius : π - radius, code = 0;
+ if (λ < -r) code |= 1; else if (λ > r) code |= 2;
+ if (φ < -r) code |= 4; else if (φ > r) code |= 8;
+ return code;
+ }
+ }
+ function d3_geom_clipLine(x0, y0, x1, y1) {
+ return function(line) {
+ var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
+ r = x0 - ax;
+ if (!dx && r > 0) return;
+ r /= dx;
+ if (dx < 0) {
+ if (r < t0) return;
+ if (r < t1) t1 = r;
+ } else if (dx > 0) {
+ if (r > t1) return;
+ if (r > t0) t0 = r;
+ }
+ r = x1 - ax;
+ if (!dx && r < 0) return;
+ r /= dx;
+ if (dx < 0) {
+ if (r > t1) return;
+ if (r > t0) t0 = r;
+ } else if (dx > 0) {
+ if (r < t0) return;
+ if (r < t1) t1 = r;
+ }
+ r = y0 - ay;
+ if (!dy && r > 0) return;
+ r /= dy;
+ if (dy < 0) {
+ if (r < t0) return;
+ if (r < t1) t1 = r;
+ } else if (dy > 0) {
+ if (r > t1) return;
+ if (r > t0) t0 = r;
+ }
+ r = y1 - ay;
+ if (!dy && r < 0) return;
+ r /= dy;
+ if (dy < 0) {
+ if (r > t1) return;
+ if (r > t0) t0 = r;
+ } else if (dy > 0) {
+ if (r < t0) return;
+ if (r < t1) t1 = r;
+ }
+ if (t0 > 0) line.a = {
+ x: ax + t0 * dx,
+ y: ay + t0 * dy
+ };
+ if (t1 < 1) line.b = {
+ x: ax + t1 * dx,
+ y: ay + t1 * dy
+ };
+ return line;
+ };
+ }
+ var d3_geo_clipExtentMAX = 1e9;
+ d3.geo.clipExtent = function() {
+ var x0, y0, x1, y1, stream, clip, clipExtent = {
+ stream: function(output) {
+ if (stream) stream.valid = false;
+ stream = clip(output);
+ stream.valid = true;
+ return stream;
+ },
+ extent: function(_) {
+ if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+ clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
+ if (stream) stream.valid = false, stream = null;
+ return clipExtent;
+ }
+ };
+ return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
+ };
+ function d3_geo_clipExtent(x0, y0, x1, y1) {
+ return function(listener) {
+ var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
+ var clip = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ listener = bufferListener;
+ segments = [];
+ polygon = [];
+ clean = true;
+ },
+ polygonEnd: function() {
+ listener = listener_;
+ segments = d3.merge(segments);
+ var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
+ if (inside || visible) {
+ listener.polygonStart();
+ if (inside) {
+ listener.lineStart();
+ interpolate(null, null, 1, listener);
+ listener.lineEnd();
+ }
+ if (visible) {
+ d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
+ }
+ listener.polygonEnd();
+ }
+ segments = polygon = ring = null;
+ }
+ };
+ function insidePolygon(p) {
+ var wn = 0, n = polygon.length, y = p[1];
+ for (var i = 0; i < n; ++i) {
+ for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
+ b = v[j];
+ if (a[1] <= y) {
+ if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
+ } else {
+ if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
+ }
+ a = b;
+ }
+ }
+ return wn !== 0;
+ }
+ function interpolate(from, to, direction, listener) {
+ var a = 0, a1 = 0;
+ if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
+ do {
+ listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
+ } while ((a = (a + direction + 4) % 4) !== a1);
+ } else {
+ listener.point(to[0], to[1]);
+ }
+ }
+ function pointVisible(x, y) {
+ return x0 <= x && x <= x1 && y0 <= y && y <= y1;
+ }
+ function point(x, y) {
+ if (pointVisible(x, y)) listener.point(x, y);
+ }
+ var x__, y__, v__, x_, y_, v_, first, clean;
+ function lineStart() {
+ clip.point = linePoint;
+ if (polygon) polygon.push(ring = []);
+ first = true;
+ v_ = false;
+ x_ = y_ = NaN;
+ }
+ function lineEnd() {
+ if (segments) {
+ linePoint(x__, y__);
+ if (v__ && v_) bufferListener.rejoin();
+ segments.push(bufferListener.buffer());
+ }
+ clip.point = point;
+ if (v_) listener.lineEnd();
+ }
+ function linePoint(x, y) {
+ x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
+ y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
+ var v = pointVisible(x, y);
+ if (polygon) ring.push([ x, y ]);
+ if (first) {
+ x__ = x, y__ = y, v__ = v;
+ first = false;
+ if (v) {
+ listener.lineStart();
+ listener.point(x, y);
+ }
+ } else {
+ if (v && v_) listener.point(x, y); else {
+ var l = {
+ a: {
+ x: x_,
+ y: y_
+ },
+ b: {
+ x: x,
+ y: y
+ }
+ };
+ if (clipLine(l)) {
+ if (!v_) {
+ listener.lineStart();
+ listener.point(l.a.x, l.a.y);
+ }
+ listener.point(l.b.x, l.b.y);
+ if (!v) listener.lineEnd();
+ clean = false;
+ } else if (v) {
+ listener.lineStart();
+ listener.point(x, y);
+ clean = false;
+ }
+ }
+ }
+ x_ = x, y_ = y, v_ = v;
+ }
+ return clip;
+ };
+ function corner(p, direction) {
+ return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
+ }
+ function compare(a, b) {
+ return comparePoints(a.x, b.x);
+ }
+ function comparePoints(a, b) {
+ var ca = corner(a, 1), cb = corner(b, 1);
+ return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
+ }
+ }
+ function d3_geo_conic(projectAt) {
+ var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
+ p.parallels = function(_) {
+ if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
+ return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
+ };
+ return p;
+ }
+ function d3_geo_conicEqualArea(φ0, φ1) {
+ var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
+ function forward(λ, φ) {
+ var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
+ return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
+ }
+ forward.invert = function(x, y) {
+ var ρ0_y = ρ0 - y;
+ return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
+ };
+ return forward;
+ }
+ (d3.geo.conicEqualArea = function() {
+ return d3_geo_conic(d3_geo_conicEqualArea);
+ }).raw = d3_geo_conicEqualArea;
+ d3.geo.albers = function() {
+ return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
+ };
+ d3.geo.albersUsa = function() {
+ var lower48 = d3.geo.albers();
+ var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
+ var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
+ var point, pointStream = {
+ point: function(x, y) {
+ point = [ x, y ];
+ }
+ }, lower48Point, alaskaPoint, hawaiiPoint;
+ function albersUsa(coordinates) {
+ var x = coordinates[0], y = coordinates[1];
+ point = null;
+ (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
+ return point;
+ }
+ albersUsa.invert = function(coordinates) {
+ var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
+ return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
+ };
+ albersUsa.stream = function(stream) {
+ var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
+ return {
+ point: function(x, y) {
+ lower48Stream.point(x, y);
+ alaskaStream.point(x, y);
+ hawaiiStream.point(x, y);
+ },
+ sphere: function() {
+ lower48Stream.sphere();
+ alaskaStream.sphere();
+ hawaiiStream.sphere();
+ },
+ lineStart: function() {
+ lower48Stream.lineStart();
+ alaskaStream.lineStart();
+ hawaiiStream.lineStart();
+ },
+ lineEnd: function() {
+ lower48Stream.lineEnd();
+ alaskaStream.lineEnd();
+ hawaiiStream.lineEnd();
+ },
+ polygonStart: function() {
+ lower48Stream.polygonStart();
+ alaskaStream.polygonStart();
+ hawaiiStream.polygonStart();
+ },
+ polygonEnd: function() {
+ lower48Stream.polygonEnd();
+ alaskaStream.polygonEnd();
+ hawaiiStream.polygonEnd();
+ }
+ };
+ };
+ albersUsa.precision = function(_) {
+ if (!arguments.length) return lower48.precision();
+ lower48.precision(_);
+ alaska.precision(_);
+ hawaii.precision(_);
+ return albersUsa;
+ };
+ albersUsa.scale = function(_) {
+ if (!arguments.length) return lower48.scale();
+ lower48.scale(_);
+ alaska.scale(_ * .35);
+ hawaii.scale(_);
+ return albersUsa.translate(lower48.translate());
+ };
+ albersUsa.translate = function(_) {
+ if (!arguments.length) return lower48.translate();
+ var k = lower48.scale(), x = +_[0], y = +_[1];
+ lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
+ alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+ hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+ return albersUsa;
+ };
+ return albersUsa.scale(1070);
+ };
+ var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
+ point: d3_noop,
+ lineStart: d3_noop,
+ lineEnd: d3_noop,
+ polygonStart: function() {
+ d3_geo_pathAreaPolygon = 0;
+ d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
+ },
+ polygonEnd: function() {
+ d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
+ d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
+ }
+ };
+ function d3_geo_pathAreaRingStart() {
+ var x00, y00, x0, y0;
+ d3_geo_pathArea.point = function(x, y) {
+ d3_geo_pathArea.point = nextPoint;
+ x00 = x0 = x, y00 = y0 = y;
+ };
+ function nextPoint(x, y) {
+ d3_geo_pathAreaPolygon += y0 * x - x0 * y;
+ x0 = x, y0 = y;
+ }
+ d3_geo_pathArea.lineEnd = function() {
+ nextPoint(x00, y00);
+ };
+ }
+ var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
+ var d3_geo_pathBounds = {
+ point: d3_geo_pathBoundsPoint,
+ lineStart: d3_noop,
+ lineEnd: d3_noop,
+ polygonStart: d3_noop,
+ polygonEnd: d3_noop
+ };
+ function d3_geo_pathBoundsPoint(x, y) {
+ if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
+ if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
+ if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
+ if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
+ }
+ function d3_geo_pathBuffer() {
+ var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
+ var stream = {
+ point: point,
+ lineStart: function() {
+ stream.point = pointLineStart;
+ },
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ stream.lineEnd = lineEndPolygon;
+ },
+ polygonEnd: function() {
+ stream.lineEnd = lineEnd;
+ stream.point = point;
+ },
+ pointRadius: function(_) {
+ pointCircle = d3_geo_pathBufferCircle(_);
+ return stream;
+ },
+ result: function() {
+ if (buffer.length) {
+ var result = buffer.join("");
+ buffer = [];
+ return result;
+ }
+ }
+ };
+ function point(x, y) {
+ buffer.push("M", x, ",", y, pointCircle);
+ }
+ function pointLineStart(x, y) {
+ buffer.push("M", x, ",", y);
+ stream.point = pointLine;
+ }
+ function pointLine(x, y) {
+ buffer.push("L", x, ",", y);
+ }
+ function lineEnd() {
+ stream.point = point;
+ }
+ function lineEndPolygon() {
+ buffer.push("Z");
+ }
+ return stream;
+ }
+ function d3_geo_pathBufferCircle(radius) {
+ return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
+ }
+ var d3_geo_pathCentroid = {
+ point: d3_geo_pathCentroidPoint,
+ lineStart: d3_geo_pathCentroidLineStart,
+ lineEnd: d3_geo_pathCentroidLineEnd,
+ polygonStart: function() {
+ d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
+ },
+ polygonEnd: function() {
+ d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+ d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
+ d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
+ }
+ };
+ function d3_geo_pathCentroidPoint(x, y) {
+ d3_geo_centroidX0 += x;
+ d3_geo_centroidY0 += y;
+ ++d3_geo_centroidZ0;
+ }
+ function d3_geo_pathCentroidLineStart() {
+ var x0, y0;
+ d3_geo_pathCentroid.point = function(x, y) {
+ d3_geo_pathCentroid.point = nextPoint;
+ d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+ };
+ function nextPoint(x, y) {
+ var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+ d3_geo_centroidX1 += z * (x0 + x) / 2;
+ d3_geo_centroidY1 += z * (y0 + y) / 2;
+ d3_geo_centroidZ1 += z;
+ d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+ }
+ }
+ function d3_geo_pathCentroidLineEnd() {
+ d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+ }
+ function d3_geo_pathCentroidRingStart() {
+ var x00, y00, x0, y0;
+ d3_geo_pathCentroid.point = function(x, y) {
+ d3_geo_pathCentroid.point = nextPoint;
+ d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
+ };
+ function nextPoint(x, y) {
+ var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+ d3_geo_centroidX1 += z * (x0 + x) / 2;
+ d3_geo_centroidY1 += z * (y0 + y) / 2;
+ d3_geo_centroidZ1 += z;
+ z = y0 * x - x0 * y;
+ d3_geo_centroidX2 += z * (x0 + x);
+ d3_geo_centroidY2 += z * (y0 + y);
+ d3_geo_centroidZ2 += z * 3;
+ d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+ }
+ d3_geo_pathCentroid.lineEnd = function() {
+ nextPoint(x00, y00);
+ };
+ }
+ function d3_geo_pathContext(context) {
+ var pointRadius = 4.5;
+ var stream = {
+ point: point,
+ lineStart: function() {
+ stream.point = pointLineStart;
+ },
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ stream.lineEnd = lineEndPolygon;
+ },
+ polygonEnd: function() {
+ stream.lineEnd = lineEnd;
+ stream.point = point;
+ },
+ pointRadius: function(_) {
+ pointRadius = _;
+ return stream;
+ },
+ result: d3_noop
+ };
+ function point(x, y) {
+ context.moveTo(x + pointRadius, y);
+ context.arc(x, y, pointRadius, 0, τ);
+ }
+ function pointLineStart(x, y) {
+ context.moveTo(x, y);
+ stream.point = pointLine;
+ }
+ function pointLine(x, y) {
+ context.lineTo(x, y);
+ }
+ function lineEnd() {
+ stream.point = point;
+ }
+ function lineEndPolygon() {
+ context.closePath();
+ }
+ return stream;
+ }
+ function d3_geo_resample(project) {
+ var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
+ function resample(stream) {
+ return (maxDepth ? resampleRecursive : resampleNone)(stream);
+ }
+ function resampleNone(stream) {
+ return d3_geo_transformPoint(stream, function(x, y) {
+ x = project(x, y);
+ stream.point(x[0], x[1]);
+ });
+ }
+ function resampleRecursive(stream) {
+ var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
+ var resample = {
+ point: point,
+ lineStart: lineStart,
+ lineEnd: lineEnd,
+ polygonStart: function() {
+ stream.polygonStart();
+ resample.lineStart = ringStart;
+ },
+ polygonEnd: function() {
+ stream.polygonEnd();
+ resample.lineStart = lineStart;
+ }
+ };
+ function point(x, y) {
+ x = project(x, y);
+ stream.point(x[0], x[1]);
+ }
+ function lineStart() {
+ x0 = NaN;
+ resample.point = linePoint;
+ stream.lineStart();
+ }
+ function linePoint(λ, φ) {
+ var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
+ resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
+ stream.point(x0, y0);
+ }
+ function lineEnd() {
+ resample.point = point;
+ stream.lineEnd();
+ }
+ function ringStart() {
+ lineStart();
+ resample.point = ringPoint;
+ resample.lineEnd = ringEnd;
+ }
+ function ringPoint(λ, φ) {
+ linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
+ resample.point = linePoint;
+ }
+ function ringEnd() {
+ resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
+ resample.lineEnd = lineEnd;
+ lineEnd();
+ }
+ return resample;
+ }
+ function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
+ var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
+ if (d2 > 4 * δ2 && depth--) {
+ var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
+ if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
+ resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
+ stream.point(x2, y2);
+ resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
+ }
+ }
+ }
+ resample.precision = function(_) {
+ if (!arguments.length) return Math.sqrt(δ2);
+ maxDepth = (δ2 = _ * _) > 0 && 16;
+ return resample;
+ };
+ return resample;
+ }
+ d3.geo.path = function() {
+ var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
+ function path(object) {
+ if (object) {
+ if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
+ if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
+ d3.geo.stream(object, cacheStream);
+ }
+ return contextStream.result();
+ }
+ path.area = function(object) {
+ d3_geo_pathAreaSum = 0;
+ d3.geo.stream(object, projectStream(d3_geo_pathArea));
+ return d3_geo_pathAreaSum;
+ };
+ path.centroid = function(object) {
+ d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+ d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
+ return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
+ };
+ path.bounds = function(object) {
+ d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
+ d3.geo.stream(object, projectStream(d3_geo_pathBounds));
+ return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
+ };
+ path.projection = function(_) {
+ if (!arguments.length) return projection;
+ projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
+ return reset();
+ };
+ path.context = function(_) {
+ if (!arguments.length) return context;
+ contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
+ if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
+ return reset();
+ };
+ path.pointRadius = function(_) {
+ if (!arguments.length) return pointRadius;
+ pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
+ return path;
+ };
+ function reset() {
+ cacheStream = null;
+ return path;
+ }
+ return path.projection(d3.geo.albersUsa()).context(null);
+ };
+ function d3_geo_pathProjectStream(project) {
+ var resample = d3_geo_resample(function(x, y) {
+ return project([ x * d3_degrees, y * d3_degrees ]);
+ });
+ return function(stream) {
+ return d3_geo_projectionRadians(resample(stream));
+ };
+ }
+ d3.geo.transform = function(methods) {
+ return {
+ stream: function(stream) {
+ var transform = new d3_geo_transform(stream);
+ for (var k in methods) transform[k] = methods[k];
+ return transform;
+ }
+ };
+ };
+ function d3_geo_transform(stream) {
+ this.stream = stream;
+ }
+ d3_geo_transform.prototype = {
+ point: function(x, y) {
+ this.stream.point(x, y);
+ },
+ sphere: function() {
+ this.stream.sphere();
+ },
+ lineStart: function() {
+ this.stream.lineStart();
+ },
+ lineEnd: function() {
+ this.stream.lineEnd();
+ },
+ polygonStart: function() {
+ this.stream.polygonStart();
+ },
+ polygonEnd: function() {
+ this.stream.polygonEnd();
+ }
+ };
+ function d3_geo_transformPoint(stream, point) {
+ return {
+ point: point,
+ sphere: function() {
+ stream.sphere();
+ },
+ lineStart: function() {
+ stream.lineStart();
+ },
+ lineEnd: function() {
+ stream.lineEnd();
+ },
+ polygonStart: function() {
+ stream.polygonStart();
+ },
+ polygonEnd: function() {
+ stream.polygonEnd();
+ }
+ };
+ }
+ d3.geo.projection = d3_geo_projection;
+ d3.geo.projectionMutator = d3_geo_projectionMutator;
+ function d3_geo_projection(project) {
+ return d3_geo_projectionMutator(function() {
+ return project;
+ })();
+ }
+ function d3_geo_projectionMutator(projectAt) {
+ var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
+ x = project(x, y);
+ return [ x[0] * k + δx, δy - x[1] * k ];
+ }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
+ function projection(point) {
+ point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
+ return [ point[0] * k + δx, δy - point[1] * k ];
+ }
+ function invert(point) {
+ point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
+ return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
+ }
+ projection.stream = function(output) {
+ if (stream) stream.valid = false;
+ stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
+ stream.valid = true;
+ return stream;
+ };
+ projection.clipAngle = function(_) {
+ if (!arguments.length) return clipAngle;
+ preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
+ return invalidate();
+ };
+ projection.clipExtent = function(_) {
+ if (!arguments.length) return clipExtent;
+ clipExtent = _;
+ postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
+ return invalidate();
+ };
+ projection.scale = function(_) {
+ if (!arguments.length) return k;
+ k = +_;
+ return reset();
+ };
+ projection.translate = function(_) {
+ if (!arguments.length) return [ x, y ];
+ x = +_[0];
+ y = +_[1];
+ return reset();
+ };
+ projection.center = function(_) {
+ if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
+ λ = _[0] % 360 * d3_radians;
+ φ = _[1] % 360 * d3_radians;
+ return reset();
+ };
+ projection.rotate = function(_) {
+ if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
+ δλ = _[0] % 360 * d3_radians;
+ δφ = _[1] % 360 * d3_radians;
+ δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
+ return reset();
+ };
+ d3.rebind(projection, projectResample, "precision");
+ function reset() {
+ projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
+ var center = project(λ, φ);
+ δx = x - center[0] * k;
+ δy = y + center[1] * k;
+ return invalidate();
+ }
+ function invalidate() {
+ if (stream) stream.valid = false, stream = null;
+ return projection;
+ }
+ return function() {
+ project = projectAt.apply(this, arguments);
+ projection.invert = project.invert && invert;
+ return reset();
+ };
+ }
+ function d3_geo_projectionRadians(stream) {
+ return d3_geo_transformPoint(stream, function(x, y) {
+ stream.point(x * d3_radians, y * d3_radians);
+ });
+ }
+ function d3_geo_equirectangular(λ, φ) {
+ return [ λ, φ ];
+ }
+ (d3.geo.equirectangular = function() {
+ return d3_geo_projection(d3_geo_equirectangular);
+ }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
+ d3.geo.rotation = function(rotate) {
+ rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
+ function forward(coordinates) {
+ coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+ return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+ }
+ forward.invert = function(coordinates) {
+ coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+ return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+ };
+ return forward;
+ };
+ function d3_geo_identityRotation(λ, φ) {
+ return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
+ }
+ d3_geo_identityRotation.invert = d3_geo_equirectangular;
+ function d3_geo_rotation(δλ, δφ, δγ) {
+ return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
+ }
+ function d3_geo_forwardRotationλ(δλ) {
+ return function(λ, φ) {
+ return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
+ };
+ }
+ function d3_geo_rotationλ(δλ) {
+ var rotation = d3_geo_forwardRotationλ(δλ);
+ rotation.invert = d3_geo_forwardRotationλ(-δλ);
+ return rotation;
+ }
+ function d3_geo_rotationφγ(δφ, δγ) {
+ var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
+ function rotation(λ, φ) {
+ var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
+ return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
+ }
+ rotation.invert = function(λ, φ) {
+ var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
+ return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
+ };
+ return rotation;
+ }
+ d3.geo.circle = function() {
+ var origin = [ 0, 0 ], angle, precision = 6, interpolate;
+ function circle() {
+ var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
+ interpolate(null, null, 1, {
+ point: function(x, y) {
+ ring.push(x = rotate(x, y));
+ x[0] *= d3_degrees, x[1] *= d3_degrees;
+ }
+ });
+ return {
+ type: "Polygon",
+ coordinates: [ ring ]
+ };
+ }
+ circle.origin = function(x) {
+ if (!arguments.length) return origin;
+ origin = x;
+ return circle;
+ };
+ circle.angle = function(x) {
+ if (!arguments.length) return angle;
+ interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
+ return circle;
+ };
+ circle.precision = function(_) {
+ if (!arguments.length) return precision;
+ interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
+ return circle;
+ };
+ return circle.angle(90);
+ };
+ function d3_geo_circleInterpolate(radius, precision) {
+ var cr = Math.cos(radius), sr = Math.sin(radius);
+ return function(from, to, direction, listener) {
+ var step = direction * precision;
+ if (from != null) {
+ from = d3_geo_circleAngle(cr, from);
+ to = d3_geo_circleAngle(cr, to);
+ if (direction > 0 ? from < to : from > to) from += direction * τ;
+ } else {
+ from = radius + direction * τ;
+ to = radius - .5 * step;
+ }
+ for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
+ listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
+ }
+ };
+ }
+ function d3_geo_circleAngle(cr, point) {
+ var a = d3_geo_cartesian(point);
+ a[0] -= cr;
+ d3_geo_cartesianNormalize(a);
+ var angle = d3_acos(-a[1]);
+ return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
+ }
+ d3.geo.distance = function(a, b) {
+ var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
+ return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
+ };
+ d3.geo.graticule = function() {
+ var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
+ function graticule() {
+ return {
+ type: "MultiLineString",
+ coordinates: lines()
+ };
+ }
+ function lines() {
+ return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
+ return abs(x % DX) > ε;
+ }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
+ return abs(y % DY) > ε;
+ }).map(y));
+ }
+ graticule.lines = function() {
+ return lines().map(function(coordinates) {
+ return {
+ type: "LineString",
+ coordinates: coordinates
+ };
+ });
+ };
+ graticule.outline = function() {
+ return {
+ type: "Polygon",
+ coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
+ };
+ };
+ graticule.extent = function(_) {
+ if (!arguments.length) return graticule.minorExtent();
+ return graticule.majorExtent(_).minorExtent(_);
+ };
+ graticule.majorExtent = function(_) {
+ if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
+ X0 = +_[0][0], X1 = +_[1][0];
+ Y0 = +_[0][1], Y1 = +_[1][1];
+ if (X0 > X1) _ = X0, X0 = X1, X1 = _;
+ if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
+ return graticule.precision(precision);
+ };
+ graticule.minorExtent = function(_) {
+ if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+ x0 = +_[0][0], x1 = +_[1][0];
+ y0 = +_[0][1], y1 = +_[1][1];
+ if (x0 > x1) _ = x0, x0 = x1, x1 = _;
+ if (y0 > y1) _ = y0, y0 = y1, y1 = _;
+ return graticule.precision(precision);
+ };
+ graticule.step = function(_) {
+ if (!arguments.length) return graticule.minorStep();
+ return graticule.majorStep(_).minorStep(_);
+ };
+ graticule.majorStep = function(_) {
+ if (!arguments.length) return [ DX, DY ];
+ DX = +_[0], DY = +_[1];
+ return graticule;
+ };
+ graticule.minorStep = function(_) {
+ if (!arguments.length) return [ dx, dy ];
+ dx = +_[0], dy = +_[1];
+ return graticule;
+ };
+ graticule.precision = function(_) {
+ if (!arguments.length) return precision;
+ precision = +_;
+ x = d3_geo_graticuleX(y0, y1, 90);
+ y = d3_geo_graticuleY(x0, x1, precision);
+ X = d3_geo_graticuleX(Y0, Y1, 90);
+ Y = d3_geo_graticuleY(X0, X1, precision);
+ return graticule;
+ };
+ return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
+ };
+ function d3_geo_graticuleX(y0, y1, dy) {
+ var y = d3.range(y0, y1 - ε, dy).concat(y1);
+ return function(x) {
+ return y.map(function(y) {
+ return [ x, y ];
+ });
+ };
+ }
+ function d3_geo_graticuleY(x0, x1, dx) {
+ var x = d3.range(x0, x1 - ε, dx).concat(x1);
+ return function(y) {
+ return x.map(function(x) {
+ return [ x, y ];
+ });
+ };
+ }
+ function d3_source(d) {
+ return d.source;
+ }
+ function d3_target(d) {
+ return d.target;
+ }
+ d3.geo.greatArc = function() {
+ var source = d3_source, source_, target = d3_target, target_;
+ function greatArc() {
+ return {
+ type: "LineString",
+ coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
+ };
+ }
+ greatArc.distance = function() {
+ return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
+ };
+ greatArc.source = function(_) {
+ if (!arguments.length) return source;
+ source = _, source_ = typeof _ === "function" ? null : _;
+ return greatArc;
+ };
+ greatArc.target = function(_) {
+ if (!arguments.length) return target;
+ target = _, target_ = typeof _ === "function" ? null : _;
+ return greatArc;
+ };
+ greatArc.precision = function() {
+ return arguments.length ? greatArc : 0;
+ };
+ return greatArc;
+ };
+ d3.geo.interpolate = function(source, target) {
+ return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
+ };
+ function d3_geo_interpolate(x0, y0, x1, y1) {
+ var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
+ var interpolate = d ? function(t) {
+ var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
+ return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
+ } : function() {
+ return [ x0 * d3_degrees, y0 * d3_degrees ];
+ };
+ interpolate.distance = d;
+ return interpolate;
+ }
+ d3.geo.length = function(object) {
+ d3_geo_lengthSum = 0;
+ d3.geo.stream(object, d3_geo_length);
+ return d3_geo_lengthSum;
+ };
+ var d3_geo_lengthSum;
+ var d3_geo_length = {
+ sphere: d3_noop,
+ point: d3_noop,
+ lineStart: d3_geo_lengthLineStart,
+ lineEnd: d3_noop,
+ polygonStart: d3_noop,
+ polygonEnd: d3_noop
+ };
+ function d3_geo_lengthLineStart() {
+ var λ0, sinφ0, cosφ0;
+ d3_geo_length.point = function(λ, φ) {
+ λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
+ d3_geo_length.point = nextPoint;
+ };
+ d3_geo_length.lineEnd = function() {
+ d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
+ };
+ function nextPoint(λ, φ) {
+ var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
+ d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
+ λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
+ }
+ }
+ function d3_geo_azimuthal(scale, angle) {
+ function azimuthal(λ, φ) {
+ var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
+ return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
+ }
+ azimuthal.invert = function(x, y) {
+ var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
+ return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
+ };
+ return azimuthal;
+ }
+ var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
+ return Math.sqrt(2 / (1 + cosλcosφ));
+ }, function(ρ) {
+ return 2 * Math.asin(ρ / 2);
+ });
+ (d3.geo.azimuthalEqualArea = function() {
+ return d3_geo_projection(d3_geo_azimuthalEqualArea);
+ }).raw = d3_geo_azimuthalEqualArea;
+ var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
+ var c = Math.acos(cosλcosφ);
+ return c && c / Math.sin(c);
+ }, d3_identity);
+ (d3.geo.azimuthalEquidistant = function() {
+ return d3_geo_projection(d3_geo_azimuthalEquidistant);
+ }).raw = d3_geo_azimuthalEquidistant;
+ function d3_geo_conicConformal(φ0, φ1) {
+ var cosφ0 = Math.cos(φ0), t = function(φ) {
+ return Math.tan(π / 4 + φ / 2);
+ }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
+ if (!n) return d3_geo_mercator;
+ function forward(λ, φ) {
+ if (F > 0) {
+ if (φ < -halfπ + ε) φ = -halfπ + ε;
+ } else {
+ if (φ > halfπ - ε) φ = halfπ - ε;
+ }
+ var ρ = F / Math.pow(t(φ), n);
+ return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
+ }
+ forward.invert = function(x, y) {
+ var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
+ return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
+ };
+ return forward;
+ }
+ (d3.geo.conicConformal = function() {
+ return d3_geo_conic(d3_geo_conicConformal);
+ }).raw = d3_geo_conicConformal;
+ function d3_geo_conicEquidistant(φ0, φ1) {
+ var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
+ if (abs(n) < ε) return d3_geo_equirectangular;
+ function forward(λ, φ) {
+ var ρ = G - φ;
+ return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
+ }
+ forward.invert = function(x, y) {
+ var ρ0_y = G - y;
+ return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
+ };
+ return forward;
+ }
+ (d3.geo.conicEquidistant = function() {
+ return d3_geo_conic(d3_geo_conicEquidistant);
+ }).raw = d3_geo_conicEquidistant;
+ var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
+ return 1 / cosλcosφ;
+ }, Math.atan);
+ (d3.geo.gnomonic = function() {
+ return d3_geo_projection(d3_geo_gnomonic);
+ }).raw = d3_geo_gnomonic;
+ function d3_geo_mercator(λ, φ) {
+ return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
+ }
+ d3_geo_mercator.invert = function(x, y) {
+ return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
+ };
+ function d3_geo_mercatorProjection(project) {
+ var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
+ m.scale = function() {
+ var v = scale.apply(m, arguments);
+ return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+ };
+ m.translate = function() {
+ var v = translate.apply(m, arguments);
+ return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+ };
+ m.clipExtent = function(_) {
+ var v = clipExtent.apply(m, arguments);
+ if (v === m) {
+ if (clipAuto = _ == null) {
+ var k = π * scale(), t = translate();
+ clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
+ }
+ } else if (clipAuto) {
+ v = null;
+ }
+ return v;
+ };
+ return m.clipExtent(null);
+ }
+ (d3.geo.mercator = function() {
+ return d3_geo_mercatorProjection(d3_geo_mercator);
+ }).raw = d3_geo_mercator;
+ var d3_geo_orthographic = d3_geo_azimuthal(function() {
+ return 1;
+ }, Math.asin);
+ (d3.geo.orthographic = function() {
+ return d3_geo_projection(d3_geo_orthographic);
+ }).raw = d3_geo_orthographic;
+ var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
+ return 1 / (1 + cosλcosφ);
+ }, function(ρ) {
+ return 2 * Math.atan(ρ);
+ });
+ (d3.geo.stereographic = function() {
+ return d3_geo_projection(d3_geo_stereographic);
+ }).raw = d3_geo_stereographic;
+ function d3_geo_transverseMercator(λ, φ) {
+ return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
+ }
+ d3_geo_transverseMercator.invert = function(x, y) {
+ return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
+ };
+ (d3.geo.transverseMercator = function() {
+ var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
+ projection.center = function(_) {
+ return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
+ };
+ projection.rotate = function(_) {
+ return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(),
+ [ _[0], _[1], _[2] - 90 ]);
+ };
+ return rotate([ 0, 0, 90 ]);
+ }).raw = d3_geo_transverseMercator;
+ d3.geom = {};
+ function d3_geom_pointX(d) {
+ return d[0];
+ }
+ function d3_geom_pointY(d) {
+ return d[1];
+ }
+ d3.geom.hull = function(vertices) {
+ var x = d3_geom_pointX, y = d3_geom_pointY;
+ if (arguments.length) return hull(vertices);
+ function hull(data) {
+ if (data.length < 3) return [];
+ var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
+ for (i = 0; i < n; i++) {
+ points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
+ }
+ points.sort(d3_geom_hullOrder);
+ for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
+ var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
+ var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
+ for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
+ for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
+ return polygon;
+ }
+ hull.x = function(_) {
+ return arguments.length ? (x = _, hull) : x;
+ };
+ hull.y = function(_) {
+ return arguments.length ? (y = _, hull) : y;
+ };
+ return hull;
+ };
+ function d3_geom_hullUpper(points) {
+ var n = points.length, hull = [ 0, 1 ], hs = 2;
+ for (var i = 2; i < n; i++) {
+ while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
+ hull[hs++] = i;
+ }
+ return hull.slice(0, hs);
+ }
+ function d3_geom_hullOrder(a, b) {
+ return a[0] - b[0] || a[1] - b[1];
+ }
+ d3.geom.polygon = function(coordinates) {
+ d3_subclass(coordinates, d3_geom_polygonPrototype);
+ return coordinates;
+ };
+ var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
+ d3_geom_polygonPrototype.area = function() {
+ var i = -1, n = this.length, a, b = this[n - 1], area = 0;
+ while (++i < n) {
+ a = b;
+ b = this[i];
+ area += a[1] * b[0] - a[0] * b[1];
+ }
+ return area * .5;
+ };
+ d3_geom_polygonPrototype.centroid = function(k) {
+ var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
+ if (!arguments.length) k = -1 / (6 * this.area());
+ while (++i < n) {
+ a = b;
+ b = this[i];
+ c = a[0] * b[1] - b[0] * a[1];
+ x += (a[0] + b[0]) * c;
+ y += (a[1] + b[1]) * c;
+ }
+ return [ x * k, y * k ];
+ };
+ d3_geom_polygonPrototype.clip = function(subject) {
+ var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
+ while (++i < n) {
+ input = subject.slice();
+ subject.length = 0;
+ b = this[i];
+ c = input[(m = input.length - closed) - 1];
+ j = -1;
+ while (++j < m) {
+ d = input[j];
+ if (d3_geom_polygonInside(d, a, b)) {
+ if (!d3_geom_polygonInside(c, a, b)) {
+ subject.push(d3_geom_polygonIntersect(c, d, a, b));
+ }
+ subject.push(d);
+ } else if (d3_geom_polygonInside(c, a, b)) {
+ subject.push(d3_geom_polygonIntersect(c, d, a, b));
+ }
+ c = d;
+ }
+ if (closed) subject.push(subject[0]);
+ a = b;
+ }
+ return subject;
+ };
+ function d3_geom_polygonInside(p, a, b) {
+ return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
+ }
+ function d3_geom_polygonIntersect(c, d, a, b) {
+ var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
+ return [ x1 + ua * x21, y1 + ua * y21 ];
+ }
+ function d3_geom_polygonClosed(coordinates) {
+ var a = coordinates[0], b = coordinates[coordinates.length - 1];
+ return !(a[0] - b[0] || a[1] - b[1]);
+ }
+ var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
+ function d3_geom_voronoiBeach() {
+ d3_geom_voronoiRedBlackNode(this);
+ this.edge = this.site = this.circle = null;
+ }
+ function d3_geom_voronoiCreateBeach(site) {
+ var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
+ beach.site = site;
+ return beach;
+ }
+ function d3_geom_voronoiDetachBeach(beach) {
+ d3_geom_voronoiDetachCircle(beach);
+ d3_geom_voronoiBeaches.remove(beach);
+ d3_geom_voronoiBeachPool.push(beach);
+ d3_geom_voronoiRedBlackNode(beach);
+ }
+ function d3_geom_voronoiRemoveBeach(beach) {
+ var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
+ x: x,
+ y: y
+ }, previous = beach.P, next = beach.N, disappearing = [ beach ];
+ d3_geom_voronoiDetachBeach(beach);
+ var lArc = previous;
+ while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
+ previous = lArc.P;
+ disappearing.unshift(lArc);
+ d3_geom_voronoiDetachBeach(lArc);
+ lArc = previous;
+ }
+ disappearing.unshift(lArc);
+ d3_geom_voronoiDetachCircle(lArc);
+ var rArc = next;
+ while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
+ next = rArc.N;
+ disappearing.push(rArc);
+ d3_geom_voronoiDetachBeach(rArc);
+ rArc = next;
+ }
+ disappearing.push(rArc);
+ d3_geom_voronoiDetachCircle(rArc);
+ var nArcs = disappearing.length, iArc;
+ for (iArc = 1; iArc < nArcs; ++iArc) {
+ rArc = disappearing[iArc];
+ lArc = disappearing[iArc - 1];
+ d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
+ }
+ lArc = disappearing[0];
+ rArc = disappearing[nArcs - 1];
+ rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
+ d3_geom_voronoiAttachCircle(lArc);
+ d3_geom_voronoiAttachCircle(rArc);
+ }
+ function d3_geom_voronoiAddBeach(site) {
+ var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
+ while (node) {
+ dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
+ if (dxl > ε) node = node.L; else {
+ dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
+ if (dxr > ε) {
+ if (!node.R) {
+ lArc = node;
+ break;
+ }
+ node = node.R;
+ } else {
+ if (dxl > -ε) {
+ lArc = node.P;
+ rArc = node;
+ } else if (dxr > -ε) {
+ lArc = node;
+ rArc = node.N;
+ } else {
+ lArc = rArc = node;
+ }
+ break;
+ }
+ }
+ }
+ var newArc = d3_geom_voronoiCreateBeach(site);
+ d3_geom_voronoiBeaches.insert(lArc, newArc);
+ if (!lArc && !rArc) return;
+ if (lArc === rArc) {
+ d3_geom_voronoiDetachCircle(lArc);
+ rArc = d3_geom_voronoiCreateBeach(lArc.site);
+ d3_geom_voronoiBeaches.insert(newArc, rArc);
+ newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+ d3_geom_voronoiAttachCircle(lArc);
+ d3_geom_voronoiAttachCircle(rArc);
+ return;
+ }
+ if (!rArc) {
+ newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+ return;
+ }
+ d3_geom_voronoiDetachCircle(lArc);
+ d3_geom_voronoiDetachCircle(rArc);
+ var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
+ x: (cy * hb - by * hc) / d + ax,
+ y: (bx * hc - cx * hb) / d + ay
+ };
+ d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
+ newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
+ rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
+ d3_geom_voronoiAttachCircle(lArc);
+ d3_geom_voronoiAttachCircle(rArc);
+ }
+ function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
+ var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
+ if (!pby2) return rfocx;
+ var lArc = arc.P;
+ if (!lArc) return -Infinity;
+ site = lArc.site;
+ var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
+ if (!plby2) return lfocx;
+ var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
+ if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
+ return (rfocx + lfocx) / 2;
+ }
+ function d3_geom_voronoiRightBreakPoint(arc, directrix) {
+ var rArc = arc.N;
+ if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
+ var site = arc.site;
+ return site.y === directrix ? site.x : Infinity;
+ }
+ function d3_geom_voronoiCell(site) {
+ this.site = site;
+ this.edges = [];
+ }
+ d3_geom_voronoiCell.prototype.prepare = function() {
+ var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
+ while (iHalfEdge--) {
+ edge = halfEdges[iHalfEdge].edge;
+ if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
+ }
+ halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
+ return halfEdges.length;
+ };
+ function d3_geom_voronoiCloseCells(extent) {
+ var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
+ while (iCell--) {
+ cell = cells[iCell];
+ if (!cell || !cell.prepare()) continue;
+ halfEdges = cell.edges;
+ nHalfEdges = halfEdges.length;
+ iHalfEdge = 0;
+ while (iHalfEdge < nHalfEdges) {
+ end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
+ start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
+ if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
+ halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
+ x: x0,
+ y: abs(x2 - x0) < ε ? y2 : y1
+ } : abs(y3 - y1) < ε && x1 - x3 > ε ? {
+ x: abs(y2 - y1) < ε ? x2 : x1,
+ y: y1
+ } : abs(x3 - x1) < ε && y3 - y0 > ε ? {
+ x: x1,
+ y: abs(x2 - x1) < ε ? y2 : y0
+ } : abs(y3 - y0) < ε && x3 - x0 > ε ? {
+ x: abs(y2 - y0) < ε ? x2 : x0,
+ y: y0
+ } : null), cell.site, null));
+ ++nHalfEdges;
+ }
+ }
+ }
+ }
+ function d3_geom_voronoiHalfEdgeOrder(a, b) {
+ return b.angle - a.angle;
+ }
+ function d3_geom_voronoiCircle() {
+ d3_geom_voronoiRedBlackNode(this);
+ this.x = this.y = this.arc = this.site = this.cy = null;
+ }
+ function d3_geom_voronoiAttachCircle(arc) {
+ var lArc = arc.P, rArc = arc.N;
+ if (!lArc || !rArc) return;
+ var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
+ if (lSite === rSite) return;
+ var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
+ var d = 2 * (ax * cy - ay * cx);
+ if (d >= -ε2) return;
+ var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
+ var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
+ circle.arc = arc;
+ circle.site = cSite;
+ circle.x = x + bx;
+ circle.y = cy + Math.sqrt(x * x + y * y);
+ circle.cy = cy;
+ arc.circle = circle;
+ var before = null, node = d3_geom_voronoiCircles._;
+ while (node) {
+ if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
+ if (node.L) node = node.L; else {
+ before = node.P;
+ break;
+ }
+ } else {
+ if (node.R) node = node.R; else {
+ before = node;
+ break;
+ }
+ }
+ }
+ d3_geom_voronoiCircles.insert(before, circle);
+ if (!before) d3_geom_voronoiFirstCircle = circle;
+ }
+ function d3_geom_voronoiDetachCircle(arc) {
+ var circle = arc.circle;
+ if (circle) {
+ if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
+ d3_geom_voronoiCircles.remove(circle);
+ d3_geom_voronoiCirclePool.push(circle);
+ d3_geom_voronoiRedBlackNode(circle);
+ arc.circle = null;
+ }
+ }
+ function d3_geom_voronoiClipEdges(extent) {
+ var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
+ while (i--) {
+ e = edges[i];
+ if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
+ e.a = e.b = null;
+ edges.splice(i, 1);
+ }
+ }
+ }
+ function d3_geom_voronoiConnectEdge(edge, extent) {
+ var vb = edge.b;
+ if (vb) return true;
+ var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
+ if (ry === ly) {
+ if (fx < x0 || fx >= x1) return;
+ if (lx > rx) {
+ if (!va) va = {
+ x: fx,
+ y: y0
+ }; else if (va.y >= y1) return;
+ vb = {
+ x: fx,
+ y: y1
+ };
+ } else {
+ if (!va) va = {
+ x: fx,
+ y: y1
+ }; else if (va.y < y0) return;
+ vb = {
+ x: fx,
+ y: y0
+ };
+ }
+ } else {
+ fm = (lx - rx) / (ry - ly);
+ fb = fy - fm * fx;
+ if (fm < -1 || fm > 1) {
+ if (lx > rx) {
+ if (!va) va = {
+ x: (y0 - fb) / fm,
+ y: y0
+ }; else if (va.y >= y1) return;
+ vb = {
+ x: (y1 - fb) / fm,
+ y: y1
+ };
+ } else {
+ if (!va) va = {
+ x: (y1 - fb) / fm,
+ y: y1
+ }; else if (va.y < y0) return;
+ vb = {
+ x: (y0 - fb) / fm,
+ y: y0
+ };
+ }
+ } else {
+ if (ly < ry) {
+ if (!va) va = {
+ x: x0,
+ y: fm * x0 + fb
+ }; else if (va.x >= x1) return;
+ vb = {
+ x: x1,
+ y: fm * x1 + fb
+ };
+ } else {
+ if (!va) va = {
+ x: x1,
+ y: fm * x1 + fb
+ }; else if (va.x < x0) return;
+ vb = {
+ x: x0,
+ y: fm * x0 + fb
+ };
+ }
+ }
+ }
+ edge.a = va;
+ edge.b = vb;
+ return true;
+ }
+ function d3_geom_voronoiEdge(lSite, rSite) {
+ this.l = lSite;
+ this.r = rSite;
+ this.a = this.b = null;
+ }
+ function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
+ var edge = new d3_geom_voronoiEdge(lSite, rSite);
+ d3_geom_voronoiEdges.push(edge);
+ if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
+ if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
+ d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
+ d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
+ return edge;
+ }
+ function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
+ var edge = new d3_geom_voronoiEdge(lSite, null);
+ edge.a = va;
+ edge.b = vb;
+ d3_geom_voronoiEdges.push(edge);
+ return edge;
+ }
+ function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
+ if (!edge.a && !edge.b) {
+ edge.a = vertex;
+ edge.l = lSite;
+ edge.r = rSite;
+ } else if (edge.l === rSite) {
+ edge.b = vertex;
+ } else {
+ edge.a = vertex;
+ }
+ }
+ function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
+ var va = edge.a, vb = edge.b;
+ this.edge = edge;
+ this.site = lSite;
+ this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
+ }
+ d3_geom_voronoiHalfEdge.prototype = {
+ start: function() {
+ return this.edge.l === this.site ? this.edge.a : this.edge.b;
+ },
+ end: function() {
+ return this.edge.l === this.site ? this.edge.b : this.edge.a;
+ }
+ };
+ function d3_geom_voronoiRedBlackTree() {
+ this._ = null;
+ }
+ function d3_geom_voronoiRedBlackNode(node) {
+ node.U = node.C = node.L = node.R = node.P = node.N = null;
+ }
+ d3_geom_voronoiRedBlackTree.prototype = {
+ insert: function(after, node) {
+ var parent, grandpa, uncle;
+ if (after) {
+ node.P = after;
+ node.N = after.N;
+ if (after.N) after.N.P = node;
+ after.N = node;
+ if (after.R) {
+ after = after.R;
+ while (after.L) after = after.L;
+ after.L = node;
+ } else {
+ after.R = node;
+ }
+ parent = after;
+ } else if (this._) {
+ after = d3_geom_voronoiRedBlackFirst(this._);
+ node.P = null;
+ node.N = after;
+ after.P = after.L = node;
+ parent = after;
+ } else {
+ node.P = node.N = null;
+ this._ = node;
+ parent = null;
+ }
+ node.L = node.R = null;
+ node.U = parent;
+ node.C = true;
+ after = node;
+ while (parent && parent.C) {
+ grandpa = parent.U;
+ if (parent === grandpa.L) {
+ uncle = grandpa.R;
+ if (uncle && uncle.C) {
+ parent.C = uncle.C = false;
+ grandpa.C = true;
+ after = grandpa;
+ } else {
+ if (after === parent.R) {
+ d3_geom_voronoiRedBlackRotateLeft(this, parent);
+ after = parent;
+ parent = after.U;
+ }
+ parent.C = false;
+ grandpa.C = true;
+ d3_geom_voronoiRedBlackRotateRight(this, grandpa);
+ }
+ } else {
+ uncle = grandpa.L;
+ if (uncle && uncle.C) {
+ parent.C = uncle.C = false;
+ grandpa.C = true;
+ after = grandpa;
+ } else {
+ if (after === parent.L) {
+ d3_geom_voronoiRedBlackRotateRight(this, parent);
+ after = parent;
+ parent = after.U;
+ }
+ parent.C = false;
+ grandpa.C = true;
+ d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
+ }
+ }
+ parent = after.U;
+ }
+ this._.C = false;
+ },
+ remove: function(node) {
+ if (node.N) node.N.P = node.P;
+ if (node.P) node.P.N = node.N;
+ node.N = node.P = null;
+ var parent = node.U, sibling, left = node.L, right = node.R, next, red;
+ if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
+ if (parent) {
+ if (parent.L === node) parent.L = next; else parent.R = next;
+ } else {
+ this._ = next;
+ }
+ if (left && right) {
+ red = next.C;
+ next.C = node.C;
+ next.L = left;
+ left.U = next;
+ if (next !== right) {
+ parent = next.U;
+ next.U = node.U;
+ node = next.R;
+ parent.L = node;
+ next.R = right;
+ right.U = next;
+ } else {
+ next.U = parent;
+ parent = next;
+ node = next.R;
+ }
+ } else {
+ red = node.C;
+ node = next;
+ }
+ if (node) node.U = parent;
+ if (red) return;
+ if (node && node.C) {
+ node.C = false;
+ return;
+ }
+ do {
+ if (node === this._) break;
+ if (node === parent.L) {
+ sibling = parent.R;
+ if (sibling.C) {
+ sibling.C = false;
+ parent.C = true;
+ d3_geom_voronoiRedBlackRotateLeft(this, parent);
+ sibling = parent.R;
+ }
+ if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
+ if (!sibling.R || !sibling.R.C) {
+ sibling.L.C = false;
+ sibling.C = true;
+ d3_geom_voronoiRedBlackRotateRight(this, sibling);
+ sibling = parent.R;
+ }
+ sibling.C = parent.C;
+ parent.C = sibling.R.C = false;
+ d3_geom_voronoiRedBlackRotateLeft(this, parent);
+ node = this._;
+ break;
+ }
+ } else {
+ sibling = parent.L;
+ if (sibling.C) {
+ sibling.C = false;
+ parent.C = true;
+ d3_geom_voronoiRedBlackRotateRight(this, parent);
+ sibling = parent.L;
+ }
+ if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
+ if (!sibling.L || !sibling.L.C) {
+ sibling.R.C = false;
+ sibling.C = true;
+ d3_geom_voronoiRedBlackRotateLeft(this, sibling);
+ sibling = parent.L;
+ }
+ sibling.C = parent.C;
+ parent.C = sibling.L.C = false;
+ d3_geom_voronoiRedBlackRotateRight(this, parent);
+ node = this._;
+ break;
+ }
+ }
+ sibling.C = true;
+ node = parent;
+ parent = parent.U;
+ } while (!node.C);
+ if (node) node.C = false;
+ }
+ };
+ function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
+ var p = node, q = node.R, parent = p.U;
+ if (parent) {
+ if (parent.L === p) parent.L = q; else parent.R = q;
+ } else {
+ tree._ = q;
+ }
+ q.U = parent;
+ p.U = q;
+ p.R = q.L;
+ if (p.R) p.R.U = p;
+ q.L = p;
+ }
+ function d3_geom_voronoiRedBlackRotateRight(tree, node) {
+ var p = node, q = node.L, parent = p.U;
+ if (parent) {
+ if (parent.L === p) parent.L = q; else parent.R = q;
+ } else {
+ tree._ = q;
+ }
+ q.U = parent;
+ p.U = q;
+ p.L = q.R;
+ if (p.L) p.L.U = p;
+ q.R = p;
+ }
+ function d3_geom_voronoiRedBlackFirst(node) {
+ while (node.L) node = node.L;
+ return node;
+ }
+ function d3_geom_voronoi(sites, bbox) {
+ var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
+ d3_geom_voronoiEdges = [];
+ d3_geom_voronoiCells = new Array(sites.length);
+ d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
+ d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
+ while (true) {
+ circle = d3_geom_voronoiFirstCircle;
+ if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
+ if (site.x !== x0 || site.y !== y0) {
+ d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
+ d3_geom_voronoiAddBeach(site);
+ x0 = site.x, y0 = site.y;
+ }
+ site = sites.pop();
+ } else if (circle) {
+ d3_geom_voronoiRemoveBeach(circle.arc);
+ } else {
+ break;
+ }
+ }
+ if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
+ var diagram = {
+ cells: d3_geom_voronoiCells,
+ edges: d3_geom_voronoiEdges
+ };
+ d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
+ return diagram;
+ }
+ function d3_geom_voronoiVertexOrder(a, b) {
+ return b.y - a.y || b.x - a.x;
+ }
+ d3.geom.voronoi = function(points) {
+ var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
+ if (points) return voronoi(points);
+ function voronoi(data) {
+ var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
+ d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
+ var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
+ var s = e.start();
+ return [ s.x, s.y ];
+ }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
+ polygon.point = data[i];
+ });
+ return polygons;
+ }
+ function sites(data) {
+ return data.map(function(d, i) {
+ return {
+ x: Math.round(fx(d, i) / ε) * ε,
+ y: Math.round(fy(d, i) / ε) * ε,
+ i: i
+ };
+ });
+ }
+ voronoi.links = function(data) {
+ return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
+ return edge.l && edge.r;
+ }).map(function(edge) {
+ return {
+ source: data[edge.l.i],
+ target: data[edge.r.i]
+ };
+ });
+ };
+ voronoi.triangles = function(data) {
+ var triangles = [];
+ d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
+ var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
+ while (++j < m) {
+ e0 = e1;
+ s0 = s1;
+ e1 = edges[j].edge;
+ s1 = e1.l === site ? e1.r : e1.l;
+ if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
+ triangles.push([ data[i], data[s0.i], data[s1.i] ]);
+ }
+ }
+ });
+ return triangles;
+ };
+ voronoi.x = function(_) {
+ return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
+ };
+ voronoi.y = function(_) {
+ return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
+ };
+ voronoi.clipExtent = function(_) {
+ if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
+ clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
+ return voronoi;
+ };
+ voronoi.size = function(_) {
+ if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
+ return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
+ };
+ return voronoi;
+ };
+ var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
+ function d3_geom_voronoiTriangleArea(a, b, c) {
+ return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
+ }
+ d3.geom.delaunay = function(vertices) {
+ return d3.geom.voronoi().triangles(vertices);
+ };
+ d3.geom.quadtree = function(points, x1, y1, x2, y2) {
+ var x = d3_geom_pointX, y = d3_geom_pointY, compat;
+ if (compat = arguments.length) {
+ x = d3_geom_quadtreeCompatX;
+ y = d3_geom_quadtreeCompatY;
+ if (compat === 3) {
+ y2 = y1;
+ x2 = x1;
+ y1 = x1 = 0;
+ }
+ return quadtree(points);
+ }
+ function quadtree(data) {
+ var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
+ if (x1 != null) {
+ x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
+ } else {
+ x2_ = y2_ = -(x1_ = y1_ = Infinity);
+ xs = [], ys = [];
+ n = data.length;
+ if (compat) for (i = 0; i < n; ++i) {
+ d = data[i];
+ if (d.x < x1_) x1_ = d.x;
+ if (d.y < y1_) y1_ = d.y;
+ if (d.x > x2_) x2_ = d.x;
+ if (d.y > y2_) y2_ = d.y;
+ xs.push(d.x);
+ ys.push(d.y);
+ } else for (i = 0; i < n; ++i) {
+ var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
+ if (x_ < x1_) x1_ = x_;
+ if (y_ < y1_) y1_ = y_;
+ if (x_ > x2_) x2_ = x_;
+ if (y_ > y2_) y2_ = y_;
+ xs.push(x_);
+ ys.push(y_);
+ }
+ }
+ var dx = x2_ - x1_, dy = y2_ - y1_;
+ if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
+ function insert(n, d, x, y, x1, y1, x2, y2) {
+ if (isNaN(x) || isNaN(y)) return;
+ if (n.leaf) {
+ var nx = n.x, ny = n.y;
+ if (nx != null) {
+ if (abs(nx - x) + abs(ny - y) < .01) {
+ insertChild(n, d, x, y, x1, y1, x2, y2);
+ } else {
+ var nPoint = n.point;
+ n.x = n.y = n.point = null;
+ insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
+ insertChild(n, d, x, y, x1, y1, x2, y2);
+ }
+ } else {
+ n.x = x, n.y = y, n.point = d;
+ }
+ } else {
+ insertChild(n, d, x, y, x1, y1, x2, y2);
+ }
+ }
+ function insertChild(n, d, x, y, x1, y1, x2, y2) {
+ var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right;
+ n.leaf = false;
+ n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
+ if (right) x1 = xm; else x2 = xm;
+ if (below) y1 = ym; else y2 = ym;
+ insert(n, d, x, y, x1, y1, x2, y2);
+ }
+ var root = d3_geom_quadtreeNode();
+ root.add = function(d) {
+ insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
+ };
+ root.visit = function(f) {
+ d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
+ };
+ root.find = function(point) {
+ return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_);
+ };
+ i = -1;
+ if (x1 == null) {
+ while (++i < n) {
+ insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
+ }
+ --i;
+ } else data.forEach(root.add);
+ xs = ys = data = d = null;
+ return root;
+ }
+ quadtree.x = function(_) {
+ return arguments.length ? (x = _, quadtree) : x;
+ };
+ quadtree.y = function(_) {
+ return arguments.length ? (y = _, quadtree) : y;
+ };
+ quadtree.extent = function(_) {
+ if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
+ if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0],
+ y2 = +_[1][1];
+ return quadtree;
+ };
+ quadtree.size = function(_) {
+ if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
+ if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
+ return quadtree;
+ };
+ return quadtree;
+ };
+ function d3_geom_quadtreeCompatX(d) {
+ return d.x;
+ }
+ function d3_geom_quadtreeCompatY(d) {
+ return d.y;
+ }
+ function d3_geom_quadtreeNode() {
+ return {
+ leaf: true,
+ nodes: [],
+ point: null,
+ x: null,
+ y: null
+ };
+ }
+ function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
+ if (!f(node, x1, y1, x2, y2)) {
+ var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
+ if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
+ if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
+ if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
+ if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
+ }
+ }
+ function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) {
+ var minDistance2 = Infinity, closestPoint;
+ (function find(node, x1, y1, x2, y2) {
+ if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return;
+ if (point = node.point) {
+ var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy;
+ if (distance2 < minDistance2) {
+ var distance = Math.sqrt(minDistance2 = distance2);
+ x0 = x - distance, y0 = y - distance;
+ x3 = x + distance, y3 = y + distance;
+ closestPoint = point;
+ }
+ }
+ var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym;
+ for (var i = below << 1 | right, j = i + 4; i < j; ++i) {
+ if (node = children[i & 3]) switch (i & 3) {
+ case 0:
+ find(node, x1, y1, xm, ym);
+ break;
+
+ case 1:
+ find(node, xm, y1, x2, ym);
+ break;
+
+ case 2:
+ find(node, x1, ym, xm, y2);
+ break;
+
+ case 3:
+ find(node, xm, ym, x2, y2);
+ break;
+ }
+ }
+ })(root, x0, y0, x3, y3);
+ return closestPoint;
+ }
+ d3.interpolateRgb = d3_interpolateRgb;
+ function d3_interpolateRgb(a, b) {
+ a = d3.rgb(a);
+ b = d3.rgb(b);
+ var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
+ return function(t) {
+ return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
+ };
+ }
+ d3.interpolateObject = d3_interpolateObject;
+ function d3_interpolateObject(a, b) {
+ var i = {}, c = {}, k;
+ for (k in a) {
+ if (k in b) {
+ i[k] = d3_interpolate(a[k], b[k]);
+ } else {
+ c[k] = a[k];
+ }
+ }
+ for (k in b) {
+ if (!(k in a)) {
+ c[k] = b[k];
+ }
+ }
+ return function(t) {
+ for (k in i) c[k] = i[k](t);
+ return c;
+ };
+ }
+ d3.interpolateNumber = d3_interpolateNumber;
+ function d3_interpolateNumber(a, b) {
+ a = +a, b = +b;
+ return function(t) {
+ return a * (1 - t) + b * t;
+ };
+ }
+ d3.interpolateString = d3_interpolateString;
+ function d3_interpolateString(a, b) {
+ var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
+ a = a + "", b = b + "";
+ while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {
+ if ((bs = bm.index) > bi) {
+ bs = b.slice(bi, bs);
+ if (s[i]) s[i] += bs; else s[++i] = bs;
+ }
+ if ((am = am[0]) === (bm = bm[0])) {
+ if (s[i]) s[i] += bm; else s[++i] = bm;
+ } else {
+ s[++i] = null;
+ q.push({
+ i: i,
+ x: d3_interpolateNumber(am, bm)
+ });
+ }
+ bi = d3_interpolate_numberB.lastIndex;
+ }
+ if (bi < b.length) {
+ bs = b.slice(bi);
+ if (s[i]) s[i] += bs; else s[++i] = bs;
+ }
+ return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {
+ return b(t) + "";
+ }) : function() {
+ return b;
+ } : (b = q.length, function(t) {
+ for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
+ return s.join("");
+ });
+ }
+ var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
+ d3.interpolate = d3_interpolate;
+ function d3_interpolate(a, b) {
+ var i = d3.interpolators.length, f;
+ while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
+ return f;
+ }
+ d3.interpolators = [ function(a, b) {
+ var t = typeof b;
+ return (t === "string" ? d3_rgb_names.has(b.toLowerCase()) || /^(#|rgb\(|hsl\()/i.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
+ } ];
+ d3.interpolateArray = d3_interpolateArray;
+ function d3_interpolateArray(a, b) {
+ var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
+ for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
+ for (;i < na; ++i) c[i] = a[i];
+ for (;i < nb; ++i) c[i] = b[i];
+ return function(t) {
+ for (i = 0; i < n0; ++i) c[i] = x[i](t);
+ return c;
+ };
+ }
+ var d3_ease_default = function() {
+ return d3_identity;
+ };
+ var d3_ease = d3.map({
+ linear: d3_ease_default,
+ poly: d3_ease_poly,
+ quad: function() {
+ return d3_ease_quad;
+ },
+ cubic: function() {
+ return d3_ease_cubic;
+ },
+ sin: function() {
+ return d3_ease_sin;
+ },
+ exp: function() {
+ return d3_ease_exp;
+ },
+ circle: function() {
+ return d3_ease_circle;
+ },
+ elastic: d3_ease_elastic,
+ back: d3_ease_back,
+ bounce: function() {
+ return d3_ease_bounce;
+ }
+ });
+ var d3_ease_mode = d3.map({
+ "in": d3_identity,
+ out: d3_ease_reverse,
+ "in-out": d3_ease_reflect,
+ "out-in": function(f) {
+ return d3_ease_reflect(d3_ease_reverse(f));
+ }
+ });
+ d3.ease = function(name) {
+ var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in";
+ t = d3_ease.get(t) || d3_ease_default;
+ m = d3_ease_mode.get(m) || d3_identity;
+ return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
+ };
+ function d3_ease_clamp(f) {
+ return function(t) {
+ return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
+ };
+ }
+ function d3_ease_reverse(f) {
+ return function(t) {
+ return 1 - f(1 - t);
+ };
+ }
+ function d3_ease_reflect(f) {
+ return function(t) {
+ return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
+ };
+ }
+ function d3_ease_quad(t) {
+ return t * t;
+ }
+ function d3_ease_cubic(t) {
+ return t * t * t;
+ }
+ function d3_ease_cubicInOut(t) {
+ if (t <= 0) return 0;
+ if (t >= 1) return 1;
+ var t2 = t * t, t3 = t2 * t;
+ return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
+ }
+ function d3_ease_poly(e) {
+ return function(t) {
+ return Math.pow(t, e);
+ };
+ }
+ function d3_ease_sin(t) {
+ return 1 - Math.cos(t * halfπ);
+ }
+ function d3_ease_exp(t) {
+ return Math.pow(2, 10 * (t - 1));
+ }
+ function d3_ease_circle(t) {
+ return 1 - Math.sqrt(1 - t * t);
+ }
+ function d3_ease_elastic(a, p) {
+ var s;
+ if (arguments.length < 2) p = .45;
+ if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
+ return function(t) {
+ return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
+ };
+ }
+ function d3_ease_back(s) {
+ if (!s) s = 1.70158;
+ return function(t) {
+ return t * t * ((s + 1) * t - s);
+ };
+ }
+ function d3_ease_bounce(t) {
+ return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
+ }
+ d3.interpolateHcl = d3_interpolateHcl;
+ function d3_interpolateHcl(a, b) {
+ a = d3.hcl(a);
+ b = d3.hcl(b);
+ var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
+ if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
+ if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+ return function(t) {
+ return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
+ };
+ }
+ d3.interpolateHsl = d3_interpolateHsl;
+ function d3_interpolateHsl(a, b) {
+ a = d3.hsl(a);
+ b = d3.hsl(b);
+ var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
+ if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
+ if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+ return function(t) {
+ return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
+ };
+ }
+ d3.interpolateLab = d3_interpolateLab;
+ function d3_interpolateLab(a, b) {
+ a = d3.lab(a);
+ b = d3.lab(b);
+ var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
+ return function(t) {
+ return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
+ };
+ }
+ d3.interpolateRound = d3_interpolateRound;
+ function d3_interpolateRound(a, b) {
+ b -= a;
+ return function(t) {
+ return Math.round(a + b * t);
+ };
+ }
+ d3.transform = function(string) {
+ var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
+ return (d3.transform = function(string) {
+ if (string != null) {
+ g.setAttribute("transform", string);
+ var t = g.transform.baseVal.consolidate();
+ }
+ return new d3_transform(t ? t.matrix : d3_transformIdentity);
+ })(string);
+ };
+ function d3_transform(m) {
+ var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
+ if (r0[0] * r1[1] < r1[0] * r0[1]) {
+ r0[0] *= -1;
+ r0[1] *= -1;
+ kx *= -1;
+ kz *= -1;
+ }
+ this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
+ this.translate = [ m.e, m.f ];
+ this.scale = [ kx, ky ];
+ this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
+ }
+ d3_transform.prototype.toString = function() {
+ return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
+ };
+ function d3_transformDot(a, b) {
+ return a[0] * b[0] + a[1] * b[1];
+ }
+ function d3_transformNormalize(a) {
+ var k = Math.sqrt(d3_transformDot(a, a));
+ if (k) {
+ a[0] /= k;
+ a[1] /= k;
+ }
+ return k;
+ }
+ function d3_transformCombine(a, b, k) {
+ a[0] += k * b[0];
+ a[1] += k * b[1];
+ return a;
+ }
+ var d3_transformIdentity = {
+ a: 1,
+ b: 0,
+ c: 0,
+ d: 1,
+ e: 0,
+ f: 0
+ };
+ d3.interpolateTransform = d3_interpolateTransform;
+ function d3_interpolateTransformPop(s) {
+ return s.length ? s.pop() + "," : "";
+ }
+ function d3_interpolateTranslate(ta, tb, s, q) {
+ if (ta[0] !== tb[0] || ta[1] !== tb[1]) {
+ var i = s.push("translate(", null, ",", null, ")");
+ q.push({
+ i: i - 4,
+ x: d3_interpolateNumber(ta[0], tb[0])
+ }, {
+ i: i - 2,
+ x: d3_interpolateNumber(ta[1], tb[1])
+ });
+ } else if (tb[0] || tb[1]) {
+ s.push("translate(" + tb + ")");
+ }
+ }
+ function d3_interpolateRotate(ra, rb, s, q) {
+ if (ra !== rb) {
+ if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
+ q.push({
+ i: s.push(d3_interpolateTransformPop(s) + "rotate(", null, ")") - 2,
+ x: d3_interpolateNumber(ra, rb)
+ });
+ } else if (rb) {
+ s.push(d3_interpolateTransformPop(s) + "rotate(" + rb + ")");
+ }
+ }
+ function d3_interpolateSkew(wa, wb, s, q) {
+ if (wa !== wb) {
+ q.push({
+ i: s.push(d3_interpolateTransformPop(s) + "skewX(", null, ")") - 2,
+ x: d3_interpolateNumber(wa, wb)
+ });
+ } else if (wb) {
+ s.push(d3_interpolateTransformPop(s) + "skewX(" + wb + ")");
+ }
+ }
+ function d3_interpolateScale(ka, kb, s, q) {
+ if (ka[0] !== kb[0] || ka[1] !== kb[1]) {
+ var i = s.push(d3_interpolateTransformPop(s) + "scale(", null, ",", null, ")");
+ q.push({
+ i: i - 4,
+ x: d3_interpolateNumber(ka[0], kb[0])
+ }, {
+ i: i - 2,
+ x: d3_interpolateNumber(ka[1], kb[1])
+ });
+ } else if (kb[0] !== 1 || kb[1] !== 1) {
+ s.push(d3_interpolateTransformPop(s) + "scale(" + kb + ")");
+ }
+ }
+ function d3_interpolateTransform(a, b) {
+ var s = [], q = [];
+ a = d3.transform(a), b = d3.transform(b);
+ d3_interpolateTranslate(a.translate, b.translate, s, q);
+ d3_interpolateRotate(a.rotate, b.rotate, s, q);
+ d3_interpolateSkew(a.skew, b.skew, s, q);
+ d3_interpolateScale(a.scale, b.scale, s, q);
+ a = b = null;
+ return function(t) {
+ var i = -1, n = q.length, o;
+ while (++i < n) s[(o = q[i]).i] = o.x(t);
+ return s.join("");
+ };
+ }
+ function d3_uninterpolateNumber(a, b) {
+ b = (b -= a = +a) || 1 / b;
+ return function(x) {
+ return (x - a) / b;
+ };
+ }
+ function d3_uninterpolateClamp(a, b) {
+ b = (b -= a = +a) || 1 / b;
+ return function(x) {
+ return Math.max(0, Math.min(1, (x - a) / b));
+ };
+ }
+ d3.layout = {};
+ d3.layout.bundle = function() {
+ return function(links) {
+ var paths = [], i = -1, n = links.length;
+ while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
+ return paths;
+ };
+ };
+ function d3_layout_bundlePath(link) {
+ var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
+ while (start !== lca) {
+ start = start.parent;
+ points.push(start);
+ }
+ var k = points.length;
+ while (end !== lca) {
+ points.splice(k, 0, end);
+ end = end.parent;
+ }
+ return points;
+ }
+ function d3_layout_bundleAncestors(node) {
+ var ancestors = [], parent = node.parent;
+ while (parent != null) {
+ ancestors.push(node);
+ node = parent;
+ parent = parent.parent;
+ }
+ ancestors.push(node);
+ return ancestors;
+ }
+ function d3_layout_bundleLeastCommonAncestor(a, b) {
+ if (a === b) return a;
+ var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
+ while (aNode === bNode) {
+ sharedNode = aNode;
+ aNode = aNodes.pop();
+ bNode = bNodes.pop();
+ }
+ return sharedNode;
+ }
+ d3.layout.chord = function() {
+ var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
+ function relayout() {
+ var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
+ chords = [];
+ groups = [];
+ k = 0, i = -1;
+ while (++i < n) {
+ x = 0, j = -1;
+ while (++j < n) {
+ x += matrix[i][j];
+ }
+ groupSums.push(x);
+ subgroupIndex.push(d3.range(n));
+ k += x;
+ }
+ if (sortGroups) {
+ groupIndex.sort(function(a, b) {
+ return sortGroups(groupSums[a], groupSums[b]);
+ });
+ }
+ if (sortSubgroups) {
+ subgroupIndex.forEach(function(d, i) {
+ d.sort(function(a, b) {
+ return sortSubgroups(matrix[i][a], matrix[i][b]);
+ });
+ });
+ }
+ k = (τ - padding * n) / k;
+ x = 0, i = -1;
+ while (++i < n) {
+ x0 = x, j = -1;
+ while (++j < n) {
+ var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
+ subgroups[di + "-" + dj] = {
+ index: di,
+ subindex: dj,
+ startAngle: a0,
+ endAngle: a1,
+ value: v
+ };
+ }
+ groups[di] = {
+ index: di,
+ startAngle: x0,
+ endAngle: x,
+ value: groupSums[di]
+ };
+ x += padding;
+ }
+ i = -1;
+ while (++i < n) {
+ j = i - 1;
+ while (++j < n) {
+ var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
+ if (source.value || target.value) {
+ chords.push(source.value < target.value ? {
+ source: target,
+ target: source
+ } : {
+ source: source,
+ target: target
+ });
+ }
+ }
+ }
+ if (sortChords) resort();
+ }
+ function resort() {
+ chords.sort(function(a, b) {
+ return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
+ });
+ }
+ chord.matrix = function(x) {
+ if (!arguments.length) return matrix;
+ n = (matrix = x) && matrix.length;
+ chords = groups = null;
+ return chord;
+ };
+ chord.padding = function(x) {
+ if (!arguments.length) return padding;
+ padding = x;
+ chords = groups = null;
+ return chord;
+ };
+ chord.sortGroups = function(x) {
+ if (!arguments.length) return sortGroups;
+ sortGroups = x;
+ chords = groups = null;
+ return chord;
+ };
+ chord.sortSubgroups = function(x) {
+ if (!arguments.length) return sortSubgroups;
+ sortSubgroups = x;
+ chords = null;
+ return chord;
+ };
+ chord.sortChords = function(x) {
+ if (!arguments.length) return sortChords;
+ sortChords = x;
+ if (chords) resort();
+ return chord;
+ };
+ chord.chords = function() {
+ if (!chords) relayout();
+ return chords;
+ };
+ chord.groups = function() {
+ if (!groups) relayout();
+ return groups;
+ };
+ return chord;
+ };
+ d3.layout.force = function() {
+ var force = {}, event = d3.dispatch("start", "tick", "end"), timer, size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
+ function repulse(node) {
+ return function(quad, x1, _, x2) {
+ if (quad.point !== node) {
+ var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
+ if (dw * dw / theta2 < dn) {
+ if (dn < chargeDistance2) {
+ var k = quad.charge / dn;
+ node.px -= dx * k;
+ node.py -= dy * k;
+ }
+ return true;
+ }
+ if (quad.point && dn && dn < chargeDistance2) {
+ var k = quad.pointCharge / dn;
+ node.px -= dx * k;
+ node.py -= dy * k;
+ }
+ }
+ return !quad.charge;
+ };
+ }
+ force.tick = function() {
+ if ((alpha *= .99) < .005) {
+ timer = null;
+ event.end({
+ type: "end",
+ alpha: alpha = 0
+ });
+ return true;
+ }
+ var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
+ for (i = 0; i < m; ++i) {
+ o = links[i];
+ s = o.source;
+ t = o.target;
+ x = t.x - s.x;
+ y = t.y - s.y;
+ if (l = x * x + y * y) {
+ l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
+ x *= l;
+ y *= l;
+ t.x -= x * (k = s.weight + t.weight ? s.weight / (s.weight + t.weight) : .5);
+ t.y -= y * k;
+ s.x += x * (k = 1 - k);
+ s.y += y * k;
+ }
+ }
+ if (k = alpha * gravity) {
+ x = size[0] / 2;
+ y = size[1] / 2;
+ i = -1;
+ if (k) while (++i < n) {
+ o = nodes[i];
+ o.x += (x - o.x) * k;
+ o.y += (y - o.y) * k;
+ }
+ }
+ if (charge) {
+ d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
+ i = -1;
+ while (++i < n) {
+ if (!(o = nodes[i]).fixed) {
+ q.visit(repulse(o));
+ }
+ }
+ }
+ i = -1;
+ while (++i < n) {
+ o = nodes[i];
+ if (o.fixed) {
+ o.x = o.px;
+ o.y = o.py;
+ } else {
+ o.x -= (o.px - (o.px = o.x)) * friction;
+ o.y -= (o.py - (o.py = o.y)) * friction;
+ }
+ }
+ event.tick({
+ type: "tick",
+ alpha: alpha
+ });
+ };
+ force.nodes = function(x) {
+ if (!arguments.length) return nodes;
+ nodes = x;
+ return force;
+ };
+ force.links = function(x) {
+ if (!arguments.length) return links;
+ links = x;
+ return force;
+ };
+ force.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return force;
+ };
+ force.linkDistance = function(x) {
+ if (!arguments.length) return linkDistance;
+ linkDistance = typeof x === "function" ? x : +x;
+ return force;
+ };
+ force.distance = force.linkDistance;
+ force.linkStrength = function(x) {
+ if (!arguments.length) return linkStrength;
+ linkStrength = typeof x === "function" ? x : +x;
+ return force;
+ };
+ force.friction = function(x) {
+ if (!arguments.length) return friction;
+ friction = +x;
+ return force;
+ };
+ force.charge = function(x) {
+ if (!arguments.length) return charge;
+ charge = typeof x === "function" ? x : +x;
+ return force;
+ };
+ force.chargeDistance = function(x) {
+ if (!arguments.length) return Math.sqrt(chargeDistance2);
+ chargeDistance2 = x * x;
+ return force;
+ };
+ force.gravity = function(x) {
+ if (!arguments.length) return gravity;
+ gravity = +x;
+ return force;
+ };
+ force.theta = function(x) {
+ if (!arguments.length) return Math.sqrt(theta2);
+ theta2 = x * x;
+ return force;
+ };
+ force.alpha = function(x) {
+ if (!arguments.length) return alpha;
+ x = +x;
+ if (alpha) {
+ if (x > 0) {
+ alpha = x;
+ } else {
+ timer.c = null, timer.t = NaN, timer = null;
+ event.end({
+ type: "end",
+ alpha: alpha = 0
+ });
+ }
+ } else if (x > 0) {
+ event.start({
+ type: "start",
+ alpha: alpha = x
+ });
+ timer = d3_timer(force.tick);
+ }
+ return force;
+ };
+ force.start = function() {
+ var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
+ for (i = 0; i < n; ++i) {
+ (o = nodes[i]).index = i;
+ o.weight = 0;
+ }
+ for (i = 0; i < m; ++i) {
+ o = links[i];
+ if (typeof o.source == "number") o.source = nodes[o.source];
+ if (typeof o.target == "number") o.target = nodes[o.target];
+ ++o.source.weight;
+ ++o.target.weight;
+ }
+ for (i = 0; i < n; ++i) {
+ o = nodes[i];
+ if (isNaN(o.x)) o.x = position("x", w);
+ if (isNaN(o.y)) o.y = position("y", h);
+ if (isNaN(o.px)) o.px = o.x;
+ if (isNaN(o.py)) o.py = o.y;
+ }
+ distances = [];
+ if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
+ strengths = [];
+ if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
+ charges = [];
+ if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
+ function position(dimension, size) {
+ if (!neighbors) {
+ neighbors = new Array(n);
+ for (j = 0; j < n; ++j) {
+ neighbors[j] = [];
+ }
+ for (j = 0; j < m; ++j) {
+ var o = links[j];
+ neighbors[o.source.index].push(o.target);
+ neighbors[o.target.index].push(o.source);
+ }
+ }
+ var candidates = neighbors[i], j = -1, l = candidates.length, x;
+ while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x;
+ return Math.random() * size;
+ }
+ return force.resume();
+ };
+ force.resume = function() {
+ return force.alpha(.1);
+ };
+ force.stop = function() {
+ return force.alpha(0);
+ };
+ force.drag = function() {
+ if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
+ if (!arguments.length) return drag;
+ this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
+ };
+ function dragmove(d) {
+ d.px = d3.event.x, d.py = d3.event.y;
+ force.resume();
+ }
+ return d3.rebind(force, event, "on");
+ };
+ function d3_layout_forceDragstart(d) {
+ d.fixed |= 2;
+ }
+ function d3_layout_forceDragend(d) {
+ d.fixed &= ~6;
+ }
+ function d3_layout_forceMouseover(d) {
+ d.fixed |= 4;
+ d.px = d.x, d.py = d.y;
+ }
+ function d3_layout_forceMouseout(d) {
+ d.fixed &= ~4;
+ }
+ function d3_layout_forceAccumulate(quad, alpha, charges) {
+ var cx = 0, cy = 0;
+ quad.charge = 0;
+ if (!quad.leaf) {
+ var nodes = quad.nodes, n = nodes.length, i = -1, c;
+ while (++i < n) {
+ c = nodes[i];
+ if (c == null) continue;
+ d3_layout_forceAccumulate(c, alpha, charges);
+ quad.charge += c.charge;
+ cx += c.charge * c.cx;
+ cy += c.charge * c.cy;
+ }
+ }
+ if (quad.point) {
+ if (!quad.leaf) {
+ quad.point.x += Math.random() - .5;
+ quad.point.y += Math.random() - .5;
+ }
+ var k = alpha * charges[quad.point.index];
+ quad.charge += quad.pointCharge = k;
+ cx += k * quad.point.x;
+ cy += k * quad.point.y;
+ }
+ quad.cx = cx / quad.charge;
+ quad.cy = cy / quad.charge;
+ }
+ var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
+ d3.layout.hierarchy = function() {
+ var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
+ function hierarchy(root) {
+ var stack = [ root ], nodes = [], node;
+ root.depth = 0;
+ while ((node = stack.pop()) != null) {
+ nodes.push(node);
+ if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {
+ var n, childs, child;
+ while (--n >= 0) {
+ stack.push(child = childs[n]);
+ child.parent = node;
+ child.depth = node.depth + 1;
+ }
+ if (value) node.value = 0;
+ node.children = childs;
+ } else {
+ if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
+ delete node.children;
+ }
+ }
+ d3_layout_hierarchyVisitAfter(root, function(node) {
+ var childs, parent;
+ if (sort && (childs = node.children)) childs.sort(sort);
+ if (value && (parent = node.parent)) parent.value += node.value;
+ });
+ return nodes;
+ }
+ hierarchy.sort = function(x) {
+ if (!arguments.length) return sort;
+ sort = x;
+ return hierarchy;
+ };
+ hierarchy.children = function(x) {
+ if (!arguments.length) return children;
+ children = x;
+ return hierarchy;
+ };
+ hierarchy.value = function(x) {
+ if (!arguments.length) return value;
+ value = x;
+ return hierarchy;
+ };
+ hierarchy.revalue = function(root) {
+ if (value) {
+ d3_layout_hierarchyVisitBefore(root, function(node) {
+ if (node.children) node.value = 0;
+ });
+ d3_layout_hierarchyVisitAfter(root, function(node) {
+ var parent;
+ if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
+ if (parent = node.parent) parent.value += node.value;
+ });
+ }
+ return root;
+ };
+ return hierarchy;
+ };
+ function d3_layout_hierarchyRebind(object, hierarchy) {
+ d3.rebind(object, hierarchy, "sort", "children", "value");
+ object.nodes = object;
+ object.links = d3_layout_hierarchyLinks;
+ return object;
+ }
+ function d3_layout_hierarchyVisitBefore(node, callback) {
+ var nodes = [ node ];
+ while ((node = nodes.pop()) != null) {
+ callback(node);
+ if ((children = node.children) && (n = children.length)) {
+ var n, children;
+ while (--n >= 0) nodes.push(children[n]);
+ }
+ }
+ }
+ function d3_layout_hierarchyVisitAfter(node, callback) {
+ var nodes = [ node ], nodes2 = [];
+ while ((node = nodes.pop()) != null) {
+ nodes2.push(node);
+ if ((children = node.children) && (n = children.length)) {
+ var i = -1, n, children;
+ while (++i < n) nodes.push(children[i]);
+ }
+ }
+ while ((node = nodes2.pop()) != null) {
+ callback(node);
+ }
+ }
+ function d3_layout_hierarchyChildren(d) {
+ return d.children;
+ }
+ function d3_layout_hierarchyValue(d) {
+ return d.value;
+ }
+ function d3_layout_hierarchySort(a, b) {
+ return b.value - a.value;
+ }
+ function d3_layout_hierarchyLinks(nodes) {
+ return d3.merge(nodes.map(function(parent) {
+ return (parent.children || []).map(function(child) {
+ return {
+ source: parent,
+ target: child
+ };
+ });
+ }));
+ }
+ d3.layout.partition = function() {
+ var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
+ function position(node, x, dx, dy) {
+ var children = node.children;
+ node.x = x;
+ node.y = node.depth * dy;
+ node.dx = dx;
+ node.dy = dy;
+ if (children && (n = children.length)) {
+ var i = -1, n, c, d;
+ dx = node.value ? dx / node.value : 0;
+ while (++i < n) {
+ position(c = children[i], x, d = c.value * dx, dy);
+ x += d;
+ }
+ }
+ }
+ function depth(node) {
+ var children = node.children, d = 0;
+ if (children && (n = children.length)) {
+ var i = -1, n;
+ while (++i < n) d = Math.max(d, depth(children[i]));
+ }
+ return 1 + d;
+ }
+ function partition(d, i) {
+ var nodes = hierarchy.call(this, d, i);
+ position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
+ return nodes;
+ }
+ partition.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return partition;
+ };
+ return d3_layout_hierarchyRebind(partition, hierarchy);
+ };
+ d3.layout.pie = function() {
+ var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0;
+ function pie(data) {
+ var n = data.length, values = data.map(function(d, i) {
+ return +value.call(pie, d, i);
+ }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), sum = d3.sum(values), k = sum ? (da - n * pa) / sum : 0, index = d3.range(n), arcs = [], v;
+ if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
+ return values[j] - values[i];
+ } : function(i, j) {
+ return sort(data[i], data[j]);
+ });
+ index.forEach(function(i) {
+ arcs[i] = {
+ data: data[i],
+ value: v = values[i],
+ startAngle: a,
+ endAngle: a += v * k + pa,
+ padAngle: p
+ };
+ });
+ return arcs;
+ }
+ pie.value = function(_) {
+ if (!arguments.length) return value;
+ value = _;
+ return pie;
+ };
+ pie.sort = function(_) {
+ if (!arguments.length) return sort;
+ sort = _;
+ return pie;
+ };
+ pie.startAngle = function(_) {
+ if (!arguments.length) return startAngle;
+ startAngle = _;
+ return pie;
+ };
+ pie.endAngle = function(_) {
+ if (!arguments.length) return endAngle;
+ endAngle = _;
+ return pie;
+ };
+ pie.padAngle = function(_) {
+ if (!arguments.length) return padAngle;
+ padAngle = _;
+ return pie;
+ };
+ return pie;
+ };
+ var d3_layout_pieSortByValue = {};
+ d3.layout.stack = function() {
+ var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
+ function stack(data, index) {
+ if (!(n = data.length)) return data;
+ var series = data.map(function(d, i) {
+ return values.call(stack, d, i);
+ });
+ var points = series.map(function(d) {
+ return d.map(function(v, i) {
+ return [ x.call(stack, v, i), y.call(stack, v, i) ];
+ });
+ });
+ var orders = order.call(stack, points, index);
+ series = d3.permute(series, orders);
+ points = d3.permute(points, orders);
+ var offsets = offset.call(stack, points, index);
+ var m = series[0].length, n, i, j, o;
+ for (j = 0; j < m; ++j) {
+ out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
+ for (i = 1; i < n; ++i) {
+ out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
+ }
+ }
+ return data;
+ }
+ stack.values = function(x) {
+ if (!arguments.length) return values;
+ values = x;
+ return stack;
+ };
+ stack.order = function(x) {
+ if (!arguments.length) return order;
+ order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
+ return stack;
+ };
+ stack.offset = function(x) {
+ if (!arguments.length) return offset;
+ offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
+ return stack;
+ };
+ stack.x = function(z) {
+ if (!arguments.length) return x;
+ x = z;
+ return stack;
+ };
+ stack.y = function(z) {
+ if (!arguments.length) return y;
+ y = z;
+ return stack;
+ };
+ stack.out = function(z) {
+ if (!arguments.length) return out;
+ out = z;
+ return stack;
+ };
+ return stack;
+ };
+ function d3_layout_stackX(d) {
+ return d.x;
+ }
+ function d3_layout_stackY(d) {
+ return d.y;
+ }
+ function d3_layout_stackOut(d, y0, y) {
+ d.y0 = y0;
+ d.y = y;
+ }
+ var d3_layout_stackOrders = d3.map({
+ "inside-out": function(data) {
+ var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
+ return max[a] - max[b];
+ }), top = 0, bottom = 0, tops = [], bottoms = [];
+ for (i = 0; i < n; ++i) {
+ j = index[i];
+ if (top < bottom) {
+ top += sums[j];
+ tops.push(j);
+ } else {
+ bottom += sums[j];
+ bottoms.push(j);
+ }
+ }
+ return bottoms.reverse().concat(tops);
+ },
+ reverse: function(data) {
+ return d3.range(data.length).reverse();
+ },
+ "default": d3_layout_stackOrderDefault
+ });
+ var d3_layout_stackOffsets = d3.map({
+ silhouette: function(data) {
+ var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
+ for (j = 0; j < m; ++j) {
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+ if (o > max) max = o;
+ sums.push(o);
+ }
+ for (j = 0; j < m; ++j) {
+ y0[j] = (max - sums[j]) / 2;
+ }
+ return y0;
+ },
+ wiggle: function(data) {
+ var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
+ y0[0] = o = o0 = 0;
+ for (j = 1; j < m; ++j) {
+ for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
+ for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
+ for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
+ s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
+ }
+ s2 += s3 * data[i][j][1];
+ }
+ y0[j] = o -= s1 ? s2 / s1 * dx : 0;
+ if (o < o0) o0 = o;
+ }
+ for (j = 0; j < m; ++j) y0[j] -= o0;
+ return y0;
+ },
+ expand: function(data) {
+ var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
+ for (j = 0; j < m; ++j) {
+ for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+ if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
+ }
+ for (j = 0; j < m; ++j) y0[j] = 0;
+ return y0;
+ },
+ zero: d3_layout_stackOffsetZero
+ });
+ function d3_layout_stackOrderDefault(data) {
+ return d3.range(data.length);
+ }
+ function d3_layout_stackOffsetZero(data) {
+ var j = -1, m = data[0].length, y0 = [];
+ while (++j < m) y0[j] = 0;
+ return y0;
+ }
+ function d3_layout_stackMaxIndex(array) {
+ var i = 1, j = 0, v = array[0][1], k, n = array.length;
+ for (;i < n; ++i) {
+ if ((k = array[i][1]) > v) {
+ j = i;
+ v = k;
+ }
+ }
+ return j;
+ }
+ function d3_layout_stackReduceSum(d) {
+ return d.reduce(d3_layout_stackSum, 0);
+ }
+ function d3_layout_stackSum(p, d) {
+ return p + d[1];
+ }
+ d3.layout.histogram = function() {
+ var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
+ function histogram(data, i) {
+ var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
+ while (++i < m) {
+ bin = bins[i] = [];
+ bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
+ bin.y = 0;
+ }
+ if (m > 0) {
+ i = -1;
+ while (++i < n) {
+ x = values[i];
+ if (x >= range[0] && x <= range[1]) {
+ bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
+ bin.y += k;
+ bin.push(data[i]);
+ }
+ }
+ }
+ return bins;
+ }
+ histogram.value = function(x) {
+ if (!arguments.length) return valuer;
+ valuer = x;
+ return histogram;
+ };
+ histogram.range = function(x) {
+ if (!arguments.length) return ranger;
+ ranger = d3_functor(x);
+ return histogram;
+ };
+ histogram.bins = function(x) {
+ if (!arguments.length) return binner;
+ binner = typeof x === "number" ? function(range) {
+ return d3_layout_histogramBinFixed(range, x);
+ } : d3_functor(x);
+ return histogram;
+ };
+ histogram.frequency = function(x) {
+ if (!arguments.length) return frequency;
+ frequency = !!x;
+ return histogram;
+ };
+ return histogram;
+ };
+ function d3_layout_histogramBinSturges(range, values) {
+ return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
+ }
+ function d3_layout_histogramBinFixed(range, n) {
+ var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
+ while (++x <= n) f[x] = m * x + b;
+ return f;
+ }
+ function d3_layout_histogramRange(values) {
+ return [ d3.min(values), d3.max(values) ];
+ }
+ d3.layout.pack = function() {
+ var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
+ function pack(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
+ return radius;
+ };
+ root.x = root.y = 0;
+ d3_layout_hierarchyVisitAfter(root, function(d) {
+ d.r = +r(d.value);
+ });
+ d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
+ if (padding) {
+ var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
+ d3_layout_hierarchyVisitAfter(root, function(d) {
+ d.r += dr;
+ });
+ d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
+ d3_layout_hierarchyVisitAfter(root, function(d) {
+ d.r -= dr;
+ });
+ }
+ d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
+ return nodes;
+ }
+ pack.size = function(_) {
+ if (!arguments.length) return size;
+ size = _;
+ return pack;
+ };
+ pack.radius = function(_) {
+ if (!arguments.length) return radius;
+ radius = _ == null || typeof _ === "function" ? _ : +_;
+ return pack;
+ };
+ pack.padding = function(_) {
+ if (!arguments.length) return padding;
+ padding = +_;
+ return pack;
+ };
+ return d3_layout_hierarchyRebind(pack, hierarchy);
+ };
+ function d3_layout_packSort(a, b) {
+ return a.value - b.value;
+ }
+ function d3_layout_packInsert(a, b) {
+ var c = a._pack_next;
+ a._pack_next = b;
+ b._pack_prev = a;
+ b._pack_next = c;
+ c._pack_prev = b;
+ }
+ function d3_layout_packSplice(a, b) {
+ a._pack_next = b;
+ b._pack_prev = a;
+ }
+ function d3_layout_packIntersects(a, b) {
+ var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
+ return .999 * dr * dr > dx * dx + dy * dy;
+ }
+ function d3_layout_packSiblings(node) {
+ if (!(nodes = node.children) || !(n = nodes.length)) return;
+ var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
+ function bound(node) {
+ xMin = Math.min(node.x - node.r, xMin);
+ xMax = Math.max(node.x + node.r, xMax);
+ yMin = Math.min(node.y - node.r, yMin);
+ yMax = Math.max(node.y + node.r, yMax);
+ }
+ nodes.forEach(d3_layout_packLink);
+ a = nodes[0];
+ a.x = -a.r;
+ a.y = 0;
+ bound(a);
+ if (n > 1) {
+ b = nodes[1];
+ b.x = b.r;
+ b.y = 0;
+ bound(b);
+ if (n > 2) {
+ c = nodes[2];
+ d3_layout_packPlace(a, b, c);
+ bound(c);
+ d3_layout_packInsert(a, c);
+ a._pack_prev = c;
+ d3_layout_packInsert(c, b);
+ b = a._pack_next;
+ for (i = 3; i < n; i++) {
+ d3_layout_packPlace(a, b, c = nodes[i]);
+ var isect = 0, s1 = 1, s2 = 1;
+ for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
+ if (d3_layout_packIntersects(j, c)) {
+ isect = 1;
+ break;
+ }
+ }
+ if (isect == 1) {
+ for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
+ if (d3_layout_packIntersects(k, c)) {
+ break;
+ }
+ }
+ }
+ if (isect) {
+ if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
+ i--;
+ } else {
+ d3_layout_packInsert(a, c);
+ b = c;
+ bound(c);
+ }
+ }
+ }
+ }
+ var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
+ for (i = 0; i < n; i++) {
+ c = nodes[i];
+ c.x -= cx;
+ c.y -= cy;
+ cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
+ }
+ node.r = cr;
+ nodes.forEach(d3_layout_packUnlink);
+ }
+ function d3_layout_packLink(node) {
+ node._pack_next = node._pack_prev = node;
+ }
+ function d3_layout_packUnlink(node) {
+ delete node._pack_next;
+ delete node._pack_prev;
+ }
+ function d3_layout_packTransform(node, x, y, k) {
+ var children = node.children;
+ node.x = x += k * node.x;
+ node.y = y += k * node.y;
+ node.r *= k;
+ if (children) {
+ var i = -1, n = children.length;
+ while (++i < n) d3_layout_packTransform(children[i], x, y, k);
+ }
+ }
+ function d3_layout_packPlace(a, b, c) {
+ var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
+ if (db && (dx || dy)) {
+ var da = b.r + c.r, dc = dx * dx + dy * dy;
+ da *= da;
+ db *= db;
+ var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
+ c.x = a.x + x * dx + y * dy;
+ c.y = a.y + x * dy - y * dx;
+ } else {
+ c.x = a.x + db;
+ c.y = a.y;
+ }
+ }
+ d3.layout.tree = function() {
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
+ function tree(d, i) {
+ var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
+ d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
+ d3_layout_hierarchyVisitBefore(root1, secondWalk);
+ if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
+ var left = root0, right = root0, bottom = root0;
+ d3_layout_hierarchyVisitBefore(root0, function(node) {
+ if (node.x < left.x) left = node;
+ if (node.x > right.x) right = node;
+ if (node.depth > bottom.depth) bottom = node;
+ });
+ var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
+ d3_layout_hierarchyVisitBefore(root0, function(node) {
+ node.x = (node.x + tx) * kx;
+ node.y = node.depth * ky;
+ });
+ }
+ return nodes;
+ }
+ function wrapTree(root0) {
+ var root1 = {
+ A: null,
+ children: [ root0 ]
+ }, queue = [ root1 ], node1;
+ while ((node1 = queue.pop()) != null) {
+ for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {
+ queue.push((children[i] = child = {
+ _: children[i],
+ parent: node1,
+ children: (child = children[i].children) && child.slice() || [],
+ A: null,
+ a: null,
+ z: 0,
+ m: 0,
+ c: 0,
+ s: 0,
+ t: null,
+ i: i
+ }).a = child);
+ }
+ }
+ return root1.children[0];
+ }
+ function firstWalk(v) {
+ var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
+ if (children.length) {
+ d3_layout_treeShift(v);
+ var midpoint = (children[0].z + children[children.length - 1].z) / 2;
+ if (w) {
+ v.z = w.z + separation(v._, w._);
+ v.m = v.z - midpoint;
+ } else {
+ v.z = midpoint;
+ }
+ } else if (w) {
+ v.z = w.z + separation(v._, w._);
+ }
+ v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
+ }
+ function secondWalk(v) {
+ v._.x = v.z + v.parent.m;
+ v.m += v.parent.m;
+ }
+ function apportion(v, w, ancestor) {
+ if (w) {
+ var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;
+ while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
+ vom = d3_layout_treeLeft(vom);
+ vop = d3_layout_treeRight(vop);
+ vop.a = v;
+ shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
+ if (shift > 0) {
+ d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
+ sip += shift;
+ sop += shift;
+ }
+ sim += vim.m;
+ sip += vip.m;
+ som += vom.m;
+ sop += vop.m;
+ }
+ if (vim && !d3_layout_treeRight(vop)) {
+ vop.t = vim;
+ vop.m += sim - sop;
+ }
+ if (vip && !d3_layout_treeLeft(vom)) {
+ vom.t = vip;
+ vom.m += sip - som;
+ ancestor = v;
+ }
+ }
+ return ancestor;
+ }
+ function sizeNode(node) {
+ node.x *= size[0];
+ node.y = node.depth * size[1];
+ }
+ tree.separation = function(x) {
+ if (!arguments.length) return separation;
+ separation = x;
+ return tree;
+ };
+ tree.size = function(x) {
+ if (!arguments.length) return nodeSize ? null : size;
+ nodeSize = (size = x) == null ? sizeNode : null;
+ return tree;
+ };
+ tree.nodeSize = function(x) {
+ if (!arguments.length) return nodeSize ? size : null;
+ nodeSize = (size = x) == null ? null : sizeNode;
+ return tree;
+ };
+ return d3_layout_hierarchyRebind(tree, hierarchy);
+ };
+ function d3_layout_treeSeparation(a, b) {
+ return a.parent == b.parent ? 1 : 2;
+ }
+ function d3_layout_treeLeft(v) {
+ var children = v.children;
+ return children.length ? children[0] : v.t;
+ }
+ function d3_layout_treeRight(v) {
+ var children = v.children, n;
+ return (n = children.length) ? children[n - 1] : v.t;
+ }
+ function d3_layout_treeMove(wm, wp, shift) {
+ var change = shift / (wp.i - wm.i);
+ wp.c -= change;
+ wp.s += shift;
+ wm.c += change;
+ wp.z += shift;
+ wp.m += shift;
+ }
+ function d3_layout_treeShift(v) {
+ var shift = 0, change = 0, children = v.children, i = children.length, w;
+ while (--i >= 0) {
+ w = children[i];
+ w.z += shift;
+ w.m += shift;
+ shift += w.s + (change += w.c);
+ }
+ }
+ function d3_layout_treeAncestor(vim, v, ancestor) {
+ return vim.a.parent === v.parent ? vim.a : ancestor;
+ }
+ d3.layout.cluster = function() {
+ var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
+ function cluster(d, i) {
+ var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
+ d3_layout_hierarchyVisitAfter(root, function(node) {
+ var children = node.children;
+ if (children && children.length) {
+ node.x = d3_layout_clusterX(children);
+ node.y = d3_layout_clusterY(children);
+ } else {
+ node.x = previousNode ? x += separation(node, previousNode) : 0;
+ node.y = 0;
+ previousNode = node;
+ }
+ });
+ var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
+ d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
+ node.x = (node.x - root.x) * size[0];
+ node.y = (root.y - node.y) * size[1];
+ } : function(node) {
+ node.x = (node.x - x0) / (x1 - x0) * size[0];
+ node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
+ });
+ return nodes;
+ }
+ cluster.separation = function(x) {
+ if (!arguments.length) return separation;
+ separation = x;
+ return cluster;
+ };
+ cluster.size = function(x) {
+ if (!arguments.length) return nodeSize ? null : size;
+ nodeSize = (size = x) == null;
+ return cluster;
+ };
+ cluster.nodeSize = function(x) {
+ if (!arguments.length) return nodeSize ? size : null;
+ nodeSize = (size = x) != null;
+ return cluster;
+ };
+ return d3_layout_hierarchyRebind(cluster, hierarchy);
+ };
+ function d3_layout_clusterY(children) {
+ return 1 + d3.max(children, function(child) {
+ return child.y;
+ });
+ }
+ function d3_layout_clusterX(children) {
+ return children.reduce(function(x, child) {
+ return x + child.x;
+ }, 0) / children.length;
+ }
+ function d3_layout_clusterLeft(node) {
+ var children = node.children;
+ return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
+ }
+ function d3_layout_clusterRight(node) {
+ var children = node.children, n;
+ return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
+ }
+ d3.layout.treemap = function() {
+ var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
+ function scale(children, k) {
+ var i = -1, n = children.length, child, area;
+ while (++i < n) {
+ area = (child = children[i]).value * (k < 0 ? 0 : k);
+ child.area = isNaN(area) || area <= 0 ? 0 : area;
+ }
+ }
+ function squarify(node) {
+ var children = node.children;
+ if (children && children.length) {
+ var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
+ scale(remaining, rect.dx * rect.dy / node.value);
+ row.area = 0;
+ while ((n = remaining.length) > 0) {
+ row.push(child = remaining[n - 1]);
+ row.area += child.area;
+ if (mode !== "squarify" || (score = worst(row, u)) <= best) {
+ remaining.pop();
+ best = score;
+ } else {
+ row.area -= row.pop().area;
+ position(row, u, rect, false);
+ u = Math.min(rect.dx, rect.dy);
+ row.length = row.area = 0;
+ best = Infinity;
+ }
+ }
+ if (row.length) {
+ position(row, u, rect, true);
+ row.length = row.area = 0;
+ }
+ children.forEach(squarify);
+ }
+ }
+ function stickify(node) {
+ var children = node.children;
+ if (children && children.length) {
+ var rect = pad(node), remaining = children.slice(), child, row = [];
+ scale(remaining, rect.dx * rect.dy / node.value);
+ row.area = 0;
+ while (child = remaining.pop()) {
+ row.push(child);
+ row.area += child.area;
+ if (child.z != null) {
+ position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
+ row.length = row.area = 0;
+ }
+ }
+ children.forEach(stickify);
+ }
+ }
+ function worst(row, u) {
+ var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
+ while (++i < n) {
+ if (!(r = row[i].area)) continue;
+ if (r < rmin) rmin = r;
+ if (r > rmax) rmax = r;
+ }
+ s *= s;
+ u *= u;
+ return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
+ }
+ function position(row, u, rect, flush) {
+ var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
+ if (u == rect.dx) {
+ if (flush || v > rect.dy) v = rect.dy;
+ while (++i < n) {
+ o = row[i];
+ o.x = x;
+ o.y = y;
+ o.dy = v;
+ x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
+ }
+ o.z = true;
+ o.dx += rect.x + rect.dx - x;
+ rect.y += v;
+ rect.dy -= v;
+ } else {
+ if (flush || v > rect.dx) v = rect.dx;
+ while (++i < n) {
+ o = row[i];
+ o.x = x;
+ o.y = y;
+ o.dx = v;
+ y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
+ }
+ o.z = false;
+ o.dy += rect.y + rect.dy - y;
+ rect.x += v;
+ rect.dx -= v;
+ }
+ }
+ function treemap(d) {
+ var nodes = stickies || hierarchy(d), root = nodes[0];
+ root.x = root.y = 0;
+ if (root.value) root.dx = size[0], root.dy = size[1]; else root.dx = root.dy = 0;
+ if (stickies) hierarchy.revalue(root);
+ scale([ root ], root.dx * root.dy / root.value);
+ (stickies ? stickify : squarify)(root);
+ if (sticky) stickies = nodes;
+ return nodes;
+ }
+ treemap.size = function(x) {
+ if (!arguments.length) return size;
+ size = x;
+ return treemap;
+ };
+ treemap.padding = function(x) {
+ if (!arguments.length) return padding;
+ function padFunction(node) {
+ var p = x.call(treemap, node, node.depth);
+ return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
+ }
+ function padConstant(node) {
+ return d3_layout_treemapPad(node, x);
+ }
+ var type;
+ pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ],
+ padConstant) : padConstant;
+ return treemap;
+ };
+ treemap.round = function(x) {
+ if (!arguments.length) return round != Number;
+ round = x ? Math.round : Number;
+ return treemap;
+ };
+ treemap.sticky = function(x) {
+ if (!arguments.length) return sticky;
+ sticky = x;
+ stickies = null;
+ return treemap;
+ };
+ treemap.ratio = function(x) {
+ if (!arguments.length) return ratio;
+ ratio = x;
+ return treemap;
+ };
+ treemap.mode = function(x) {
+ if (!arguments.length) return mode;
+ mode = x + "";
+ return treemap;
+ };
+ return d3_layout_hierarchyRebind(treemap, hierarchy);
+ };
+ function d3_layout_treemapPadNull(node) {
+ return {
+ x: node.x,
+ y: node.y,
+ dx: node.dx,
+ dy: node.dy
+ };
+ }
+ function d3_layout_treemapPad(node, padding) {
+ var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
+ if (dx < 0) {
+ x += dx / 2;
+ dx = 0;
+ }
+ if (dy < 0) {
+ y += dy / 2;
+ dy = 0;
+ }
+ return {
+ x: x,
+ y: y,
+ dx: dx,
+ dy: dy
+ };
+ }
+ d3.random = {
+ normal: function(µ, σ) {
+ var n = arguments.length;
+ if (n < 2) σ = 1;
+ if (n < 1) µ = 0;
+ return function() {
+ var x, y, r;
+ do {
+ x = Math.random() * 2 - 1;
+ y = Math.random() * 2 - 1;
+ r = x * x + y * y;
+ } while (!r || r > 1);
+ return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
+ };
+ },
+ logNormal: function() {
+ var random = d3.random.normal.apply(d3, arguments);
+ return function() {
+ return Math.exp(random());
+ };
+ },
+ bates: function(m) {
+ var random = d3.random.irwinHall(m);
+ return function() {
+ return random() / m;
+ };
+ },
+ irwinHall: function(m) {
+ return function() {
+ for (var s = 0, j = 0; j < m; j++) s += Math.random();
+ return s;
+ };
+ }
+ };
+ d3.scale = {};
+ function d3_scaleExtent(domain) {
+ var start = domain[0], stop = domain[domain.length - 1];
+ return start < stop ? [ start, stop ] : [ stop, start ];
+ }
+ function d3_scaleRange(scale) {
+ return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
+ }
+ function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
+ var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
+ return function(x) {
+ return i(u(x));
+ };
+ }
+ function d3_scale_nice(domain, nice) {
+ var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
+ if (x1 < x0) {
+ dx = i0, i0 = i1, i1 = dx;
+ dx = x0, x0 = x1, x1 = dx;
+ }
+ domain[i0] = nice.floor(x0);
+ domain[i1] = nice.ceil(x1);
+ return domain;
+ }
+ function d3_scale_niceStep(step) {
+ return step ? {
+ floor: function(x) {
+ return Math.floor(x / step) * step;
+ },
+ ceil: function(x) {
+ return Math.ceil(x / step) * step;
+ }
+ } : d3_scale_niceIdentity;
+ }
+ var d3_scale_niceIdentity = {
+ floor: d3_identity,
+ ceil: d3_identity
+ };
+ function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
+ var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
+ if (domain[k] < domain[0]) {
+ domain = domain.slice().reverse();
+ range = range.slice().reverse();
+ }
+ while (++j <= k) {
+ u.push(uninterpolate(domain[j - 1], domain[j]));
+ i.push(interpolate(range[j - 1], range[j]));
+ }
+ return function(x) {
+ var j = d3.bisect(domain, x, 1, k) - 1;
+ return i[j](u[j](x));
+ };
+ }
+ d3.scale.linear = function() {
+ return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
+ };
+ function d3_scale_linear(domain, range, interpolate, clamp) {
+ var output, input;
+ function rescale() {
+ var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
+ output = linear(domain, range, uninterpolate, interpolate);
+ input = linear(range, domain, uninterpolate, d3_interpolate);
+ return scale;
+ }
+ function scale(x) {
+ return output(x);
+ }
+ scale.invert = function(y) {
+ return input(y);
+ };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.map(Number);
+ return rescale();
+ };
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
+ };
+ scale.rangeRound = function(x) {
+ return scale.range(x).interpolate(d3_interpolateRound);
+ };
+ scale.clamp = function(x) {
+ if (!arguments.length) return clamp;
+ clamp = x;
+ return rescale();
+ };
+ scale.interpolate = function(x) {
+ if (!arguments.length) return interpolate;
+ interpolate = x;
+ return rescale();
+ };
+ scale.ticks = function(m) {
+ return d3_scale_linearTicks(domain, m);
+ };
+ scale.tickFormat = function(m, format) {
+ return d3_scale_linearTickFormat(domain, m, format);
+ };
+ scale.nice = function(m) {
+ d3_scale_linearNice(domain, m);
+ return rescale();
+ };
+ scale.copy = function() {
+ return d3_scale_linear(domain, range, interpolate, clamp);
+ };
+ return rescale();
+ }
+ function d3_scale_linearRebind(scale, linear) {
+ return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
+ }
+ function d3_scale_linearNice(domain, m) {
+ d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
+ d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
+ return domain;
+ }
+ function d3_scale_linearTickRange(domain, m) {
+ if (m == null) m = 10;
+ var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
+ if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+ extent[0] = Math.ceil(extent[0] / step) * step;
+ extent[1] = Math.floor(extent[1] / step) * step + step * .5;
+ extent[2] = step;
+ return extent;
+ }
+ function d3_scale_linearTicks(domain, m) {
+ return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
+ }
+ function d3_scale_linearTickFormat(domain, m, format) {
+ var range = d3_scale_linearTickRange(domain, m);
+ if (format) {
+ var match = d3_format_re.exec(format);
+ match.shift();
+ if (match[8] === "s") {
+ var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
+ if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
+ match[8] = "f";
+ format = d3.format(match.join(""));
+ return function(d) {
+ return format(prefix.scale(d)) + prefix.symbol;
+ };
+ }
+ if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
+ format = match.join("");
+ } else {
+ format = ",." + d3_scale_linearPrecision(range[2]) + "f";
+ }
+ return d3.format(format);
+ }
+ var d3_scale_linearFormatSignificant = {
+ s: 1,
+ g: 1,
+ p: 1,
+ r: 1,
+ e: 1
+ };
+ function d3_scale_linearPrecision(value) {
+ return -Math.floor(Math.log(value) / Math.LN10 + .01);
+ }
+ function d3_scale_linearFormatPrecision(type, range) {
+ var p = d3_scale_linearPrecision(range[2]);
+ return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
+ }
+ d3.scale.log = function() {
+ return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
+ };
+ function d3_scale_log(linear, base, positive, domain) {
+ function log(x) {
+ return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
+ }
+ function pow(x) {
+ return positive ? Math.pow(base, x) : -Math.pow(base, -x);
+ }
+ function scale(x) {
+ return linear(log(x));
+ }
+ scale.invert = function(x) {
+ return pow(linear.invert(x));
+ };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ positive = x[0] >= 0;
+ linear.domain((domain = x.map(Number)).map(log));
+ return scale;
+ };
+ scale.base = function(_) {
+ if (!arguments.length) return base;
+ base = +_;
+ linear.domain(domain.map(log));
+ return scale;
+ };
+ scale.nice = function() {
+ var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
+ linear.domain(niced);
+ domain = niced.map(pow);
+ return scale;
+ };
+ scale.ticks = function() {
+ var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
+ if (isFinite(j - i)) {
+ if (positive) {
+ for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
+ ticks.push(pow(i));
+ } else {
+ ticks.push(pow(i));
+ for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
+ }
+ for (i = 0; ticks[i] < u; i++) {}
+ for (j = ticks.length; ticks[j - 1] > v; j--) {}
+ ticks = ticks.slice(i, j);
+ }
+ return ticks;
+ };
+ scale.tickFormat = function(n, format) {
+ if (!arguments.length) return d3_scale_logFormat;
+ if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
+ var k = Math.max(1, base * n / scale.ticks().length);
+ return function(d) {
+ var i = d / pow(Math.round(log(d)));
+ if (i * base < base - .5) i *= base;
+ return i <= k ? format(d) : "";
+ };
+ };
+ scale.copy = function() {
+ return d3_scale_log(linear.copy(), base, positive, domain);
+ };
+ return d3_scale_linearRebind(scale, linear);
+ }
+ var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
+ floor: function(x) {
+ return -Math.ceil(-x);
+ },
+ ceil: function(x) {
+ return -Math.floor(-x);
+ }
+ };
+ d3.scale.pow = function() {
+ return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
+ };
+ function d3_scale_pow(linear, exponent, domain) {
+ var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
+ function scale(x) {
+ return linear(powp(x));
+ }
+ scale.invert = function(x) {
+ return powb(linear.invert(x));
+ };
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ linear.domain((domain = x.map(Number)).map(powp));
+ return scale;
+ };
+ scale.ticks = function(m) {
+ return d3_scale_linearTicks(domain, m);
+ };
+ scale.tickFormat = function(m, format) {
+ return d3_scale_linearTickFormat(domain, m, format);
+ };
+ scale.nice = function(m) {
+ return scale.domain(d3_scale_linearNice(domain, m));
+ };
+ scale.exponent = function(x) {
+ if (!arguments.length) return exponent;
+ powp = d3_scale_powPow(exponent = x);
+ powb = d3_scale_powPow(1 / exponent);
+ linear.domain(domain.map(powp));
+ return scale;
+ };
+ scale.copy = function() {
+ return d3_scale_pow(linear.copy(), exponent, domain);
+ };
+ return d3_scale_linearRebind(scale, linear);
+ }
+ function d3_scale_powPow(e) {
+ return function(x) {
+ return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
+ };
+ }
+ d3.scale.sqrt = function() {
+ return d3.scale.pow().exponent(.5);
+ };
+ d3.scale.ordinal = function() {
+ return d3_scale_ordinal([], {
+ t: "range",
+ a: [ [] ]
+ });
+ };
+ function d3_scale_ordinal(domain, ranger) {
+ var index, range, rangeBand;
+ function scale(x) {
+ return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
+ }
+ function steps(start, step) {
+ return d3.range(domain.length).map(function(i) {
+ return start + step * i;
+ });
+ }
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = [];
+ index = new d3_Map();
+ var i = -1, n = x.length, xi;
+ while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
+ return scale[ranger.t].apply(scale, ranger.a);
+ };
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ rangeBand = 0;
+ ranger = {
+ t: "range",
+ a: arguments
+ };
+ return scale;
+ };
+ scale.rangePoints = function(x, padding) {
+ if (arguments.length < 2) padding = 0;
+ var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2,
+ 0) : (stop - start) / (domain.length - 1 + padding);
+ range = steps(start + step * padding / 2, step);
+ rangeBand = 0;
+ ranger = {
+ t: "rangePoints",
+ a: arguments
+ };
+ return scale;
+ };
+ scale.rangeRoundPoints = function(x, padding) {
+ if (arguments.length < 2) padding = 0;
+ var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2),
+ 0) : (stop - start) / (domain.length - 1 + padding) | 0;
+ range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step);
+ rangeBand = 0;
+ ranger = {
+ t: "rangeRoundPoints",
+ a: arguments
+ };
+ return scale;
+ };
+ scale.rangeBands = function(x, padding, outerPadding) {
+ if (arguments.length < 2) padding = 0;
+ if (arguments.length < 3) outerPadding = padding;
+ var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
+ range = steps(start + step * outerPadding, step);
+ if (reverse) range.reverse();
+ rangeBand = step * (1 - padding);
+ ranger = {
+ t: "rangeBands",
+ a: arguments
+ };
+ return scale;
+ };
+ scale.rangeRoundBands = function(x, padding, outerPadding) {
+ if (arguments.length < 2) padding = 0;
+ if (arguments.length < 3) outerPadding = padding;
+ var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding));
+ range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step);
+ if (reverse) range.reverse();
+ rangeBand = Math.round(step * (1 - padding));
+ ranger = {
+ t: "rangeRoundBands",
+ a: arguments
+ };
+ return scale;
+ };
+ scale.rangeBand = function() {
+ return rangeBand;
+ };
+ scale.rangeExtent = function() {
+ return d3_scaleExtent(ranger.a[0]);
+ };
+ scale.copy = function() {
+ return d3_scale_ordinal(domain, ranger);
+ };
+ return scale.domain(domain);
+ }
+ d3.scale.category10 = function() {
+ return d3.scale.ordinal().range(d3_category10);
+ };
+ d3.scale.category20 = function() {
+ return d3.scale.ordinal().range(d3_category20);
+ };
+ d3.scale.category20b = function() {
+ return d3.scale.ordinal().range(d3_category20b);
+ };
+ d3.scale.category20c = function() {
+ return d3.scale.ordinal().range(d3_category20c);
+ };
+ var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
+ var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
+ var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
+ var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
+ d3.scale.quantile = function() {
+ return d3_scale_quantile([], []);
+ };
+ function d3_scale_quantile(domain, range) {
+ var thresholds;
+ function rescale() {
+ var k = 0, q = range.length;
+ thresholds = [];
+ while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
+ return scale;
+ }
+ function scale(x) {
+ if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
+ }
+ scale.domain = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending);
+ return rescale();
+ };
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
+ };
+ scale.quantiles = function() {
+ return thresholds;
+ };
+ scale.invertExtent = function(y) {
+ y = range.indexOf(y);
+ return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
+ };
+ scale.copy = function() {
+ return d3_scale_quantile(domain, range);
+ };
+ return rescale();
+ }
+ d3.scale.quantize = function() {
+ return d3_scale_quantize(0, 1, [ 0, 1 ]);
+ };
+ function d3_scale_quantize(x0, x1, range) {
+ var kx, i;
+ function scale(x) {
+ return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
+ }
+ function rescale() {
+ kx = range.length / (x1 - x0);
+ i = range.length - 1;
+ return scale;
+ }
+ scale.domain = function(x) {
+ if (!arguments.length) return [ x0, x1 ];
+ x0 = +x[0];
+ x1 = +x[x.length - 1];
+ return rescale();
+ };
+ scale.range = function(x) {
+ if (!arguments.length) return range;
+ range = x;
+ return rescale();
+ };
+ scale.invertExtent = function(y) {
+ y = range.indexOf(y);
+ y = y < 0 ? NaN : y / kx + x0;
+ return [ y, y + 1 / kx ];
+ };
+ scale.copy = function() {
+ return d3_scale_quantize(x0, x1, range);
+ };
+ return rescale();
+ }
+ d3.scale.threshold = function() {
+ return d3_scale_threshold([ .5 ], [ 0, 1 ]);
+ };
+ function d3_scale_threshold(domain, range) {
+ function scale(x) {
+ if (x <= x) return range[d3.bisect(domain, x)];
+ }
+ scale.domain = function(_) {
+ if (!arguments.length) return domain;
+ domain = _;
+ return scale;
+ };
+ scale.range = function(_) {
+ if (!arguments.length) return range;
+ range = _;
+ return scale;
+ };
+ scale.invertExtent = function(y) {
+ y = range.indexOf(y);
+ return [ domain[y - 1], domain[y] ];
+ };
+ scale.copy = function() {
+ return d3_scale_threshold(domain, range);
+ };
+ return scale;
+ }
+ d3.scale.identity = function() {
+ return d3_scale_identity([ 0, 1 ]);
+ };
+ function d3_scale_identity(domain) {
+ function identity(x) {
+ return +x;
+ }
+ identity.invert = identity;
+ identity.domain = identity.range = function(x) {
+ if (!arguments.length) return domain;
+ domain = x.map(identity);
+ return identity;
+ };
+ identity.ticks = function(m) {
+ return d3_scale_linearTicks(domain, m);
+ };
+ identity.tickFormat = function(m, format) {
+ return d3_scale_linearTickFormat(domain, m, format);
+ };
+ identity.copy = function() {
+ return d3_scale_identity(domain);
+ };
+ return identity;
+ }
+ d3.svg = {};
+ function d3_zero() {
+ return 0;
+ }
+ d3.svg.arc = function() {
+ var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle;
+ function arc() {
+ var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1;
+ if (r1 < r0) rc = r1, r1 = r0, r0 = rc;
+ if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z";
+ var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = [];
+ if (ap = (+padAngle.apply(this, arguments) || 0) / 2) {
+ rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments);
+ if (!cw) p1 *= -1;
+ if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap));
+ if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap));
+ }
+ if (r1) {
+ x0 = r1 * Math.cos(a0 + p1);
+ y0 = r1 * Math.sin(a0 + p1);
+ x1 = r1 * Math.cos(a1 - p1);
+ y1 = r1 * Math.sin(a1 - p1);
+ var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1;
+ if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) {
+ var h1 = (a0 + a1) / 2;
+ x0 = r1 * Math.cos(h1);
+ y0 = r1 * Math.sin(h1);
+ x1 = y1 = null;
+ }
+ } else {
+ x0 = y0 = 0;
+ }
+ if (r0) {
+ x2 = r0 * Math.cos(a1 - p0);
+ y2 = r0 * Math.sin(a1 - p0);
+ x3 = r0 * Math.cos(a0 + p0);
+ y3 = r0 * Math.sin(a0 + p0);
+ var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1;
+ if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) {
+ var h0 = (a0 + a1) / 2;
+ x2 = r0 * Math.cos(h0);
+ y2 = r0 * Math.sin(h0);
+ x3 = y3 = null;
+ }
+ } else {
+ x2 = y2 = 0;
+ }
+ if (da > ε && (rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) {
+ cr = r0 < r1 ^ cw ? 0 : 1;
+ var rc1 = rc, rc0 = rc;
+ if (da < π) {
+ var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
+ rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
+ rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
+ }
+ if (x1 != null) {
+ var t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw);
+ if (rc === rc1) {
+ path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]);
+ } else {
+ path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]);
+ }
+ } else {
+ path.push("M", x0, ",", y0);
+ }
+ if (x3 != null) {
+ var t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw);
+ if (rc === rc0) {
+ path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
+ } else {
+ path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
+ }
+ } else {
+ path.push("L", x2, ",", y2);
+ }
+ } else {
+ path.push("M", x0, ",", y0);
+ if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1);
+ path.push("L", x2, ",", y2);
+ if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3);
+ }
+ path.push("Z");
+ return path.join("");
+ }
+ function circleSegment(r1, cw) {
+ return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1;
+ }
+ arc.innerRadius = function(v) {
+ if (!arguments.length) return innerRadius;
+ innerRadius = d3_functor(v);
+ return arc;
+ };
+ arc.outerRadius = function(v) {
+ if (!arguments.length) return outerRadius;
+ outerRadius = d3_functor(v);
+ return arc;
+ };
+ arc.cornerRadius = function(v) {
+ if (!arguments.length) return cornerRadius;
+ cornerRadius = d3_functor(v);
+ return arc;
+ };
+ arc.padRadius = function(v) {
+ if (!arguments.length) return padRadius;
+ padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v);
+ return arc;
+ };
+ arc.startAngle = function(v) {
+ if (!arguments.length) return startAngle;
+ startAngle = d3_functor(v);
+ return arc;
+ };
+ arc.endAngle = function(v) {
+ if (!arguments.length) return endAngle;
+ endAngle = d3_functor(v);
+ return arc;
+ };
+ arc.padAngle = function(v) {
+ if (!arguments.length) return padAngle;
+ padAngle = d3_functor(v);
+ return arc;
+ };
+ arc.centroid = function() {
+ var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ;
+ return [ Math.cos(a) * r, Math.sin(a) * r ];
+ };
+ return arc;
+ };
+ var d3_svg_arcAuto = "auto";
+ function d3_svg_arcInnerRadius(d) {
+ return d.innerRadius;
+ }
+ function d3_svg_arcOuterRadius(d) {
+ return d.outerRadius;
+ }
+ function d3_svg_arcStartAngle(d) {
+ return d.startAngle;
+ }
+ function d3_svg_arcEndAngle(d) {
+ return d.endAngle;
+ }
+ function d3_svg_arcPadAngle(d) {
+ return d && d.padAngle;
+ }
+ function d3_svg_arcSweep(x0, y0, x1, y1) {
+ return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1;
+ }
+ function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) {
+ var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3;
+ if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
+ return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ];
+ }
+ function d3_svg_line(projection) {
+ var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
+ function line(data) {
+ var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
+ function segment() {
+ segments.push("M", interpolate(projection(points), tension));
+ }
+ while (++i < n) {
+ if (defined.call(this, d = data[i], i)) {
+ points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
+ } else if (points.length) {
+ segment();
+ points = [];
+ }
+ }
+ if (points.length) segment();
+ return segments.length ? segments.join("") : null;
+ }
+ line.x = function(_) {
+ if (!arguments.length) return x;
+ x = _;
+ return line;
+ };
+ line.y = function(_) {
+ if (!arguments.length) return y;
+ y = _;
+ return line;
+ };
+ line.defined = function(_) {
+ if (!arguments.length) return defined;
+ defined = _;
+ return line;
+ };
+ line.interpolate = function(_) {
+ if (!arguments.length) return interpolateKey;
+ if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+ return line;
+ };
+ line.tension = function(_) {
+ if (!arguments.length) return tension;
+ tension = _;
+ return line;
+ };
+ return line;
+ }
+ d3.svg.line = function() {
+ return d3_svg_line(d3_identity);
+ };
+ var d3_svg_lineInterpolators = d3.map({
+ linear: d3_svg_lineLinear,
+ "linear-closed": d3_svg_lineLinearClosed,
+ step: d3_svg_lineStep,
+ "step-before": d3_svg_lineStepBefore,
+ "step-after": d3_svg_lineStepAfter,
+ basis: d3_svg_lineBasis,
+ "basis-open": d3_svg_lineBasisOpen,
+ "basis-closed": d3_svg_lineBasisClosed,
+ bundle: d3_svg_lineBundle,
+ cardinal: d3_svg_lineCardinal,
+ "cardinal-open": d3_svg_lineCardinalOpen,
+ "cardinal-closed": d3_svg_lineCardinalClosed,
+ monotone: d3_svg_lineMonotone
+ });
+ d3_svg_lineInterpolators.forEach(function(key, value) {
+ value.key = key;
+ value.closed = /-closed$/.test(key);
+ });
+ function d3_svg_lineLinear(points) {
+ return points.length > 1 ? points.join("L") : points + "Z";
+ }
+ function d3_svg_lineLinearClosed(points) {
+ return points.join("L") + "Z";
+ }
+ function d3_svg_lineStep(points) {
+ var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+ while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
+ if (n > 1) path.push("H", p[0]);
+ return path.join("");
+ }
+ function d3_svg_lineStepBefore(points) {
+ var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+ while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
+ return path.join("");
+ }
+ function d3_svg_lineStepAfter(points) {
+ var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+ while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
+ return path.join("");
+ }
+ function d3_svg_lineCardinalOpen(points, tension) {
+ return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension));
+ }
+ function d3_svg_lineCardinalClosed(points, tension) {
+ return points.length < 3 ? d3_svg_lineLinearClosed(points) : points[0] + d3_svg_lineHermite((points.push(points[0]),
+ points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
+ }
+ function d3_svg_lineCardinal(points, tension) {
+ return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
+ }
+ function d3_svg_lineHermite(points, tangents) {
+ if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
+ return d3_svg_lineLinear(points);
+ }
+ var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
+ if (quad) {
+ path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
+ p0 = points[1];
+ pi = 2;
+ }
+ if (tangents.length > 1) {
+ t = tangents[1];
+ p = points[pi];
+ pi++;
+ path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+ for (var i = 2; i < tangents.length; i++, pi++) {
+ p = points[pi];
+ t = tangents[i];
+ path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+ }
+ }
+ if (quad) {
+ var lp = points[pi];
+ path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
+ }
+ return path;
+ }
+ function d3_svg_lineCardinalTangents(points, tension) {
+ var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
+ while (++i < n) {
+ p0 = p1;
+ p1 = p2;
+ p2 = points[i];
+ tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
+ }
+ return tangents;
+ }
+ function d3_svg_lineBasis(points) {
+ if (points.length < 3) return d3_svg_lineLinear(points);
+ var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+ points.push(points[n - 1]);
+ while (++i <= n) {
+ pi = points[i];
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
+ }
+ points.pop();
+ path.push("L", pi);
+ return path.join("");
+ }
+ function d3_svg_lineBasisOpen(points) {
+ if (points.length < 4) return d3_svg_lineLinear(points);
+ var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
+ while (++i < 3) {
+ pi = points[i];
+ px.push(pi[0]);
+ py.push(pi[1]);
+ }
+ path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
+ --i;
+ while (++i < n) {
+ pi = points[i];
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
+ }
+ return path.join("");
+ }
+ function d3_svg_lineBasisClosed(points) {
+ var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
+ while (++i < 4) {
+ pi = points[i % n];
+ px.push(pi[0]);
+ py.push(pi[1]);
+ }
+ path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+ --i;
+ while (++i < m) {
+ pi = points[i % n];
+ px.shift();
+ px.push(pi[0]);
+ py.shift();
+ py.push(pi[1]);
+ d3_svg_lineBasisBezier(path, px, py);
+ }
+ return path.join("");
+ }
+ function d3_svg_lineBundle(points, tension) {
+ var n = points.length - 1;
+ if (n) {
+ var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
+ while (++i <= n) {
+ p = points[i];
+ t = i / n;
+ p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
+ p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
+ }
+ }
+ return d3_svg_lineBasis(points);
+ }
+ function d3_svg_lineDot4(a, b) {
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+ }
+ var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
+ function d3_svg_lineBasisBezier(path, x, y) {
+ path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
+ }
+ function d3_svg_lineSlope(p0, p1) {
+ return (p1[1] - p0[1]) / (p1[0] - p0[0]);
+ }
+ function d3_svg_lineFiniteDifferences(points) {
+ var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
+ while (++i < j) {
+ m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
+ }
+ m[i] = d;
+ return m;
+ }
+ function d3_svg_lineMonotoneTangents(points) {
+ var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
+ while (++i < j) {
+ d = d3_svg_lineSlope(points[i], points[i + 1]);
+ if (abs(d) < ε) {
+ m[i] = m[i + 1] = 0;
+ } else {
+ a = m[i] / d;
+ b = m[i + 1] / d;
+ s = a * a + b * b;
+ if (s > 9) {
+ s = d * 3 / Math.sqrt(s);
+ m[i] = s * a;
+ m[i + 1] = s * b;
+ }
+ }
+ }
+ i = -1;
+ while (++i <= j) {
+ s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
+ tangents.push([ s || 0, m[i] * s || 0 ]);
+ }
+ return tangents;
+ }
+ function d3_svg_lineMonotone(points) {
+ return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+ }
+ d3.svg.line.radial = function() {
+ var line = d3_svg_line(d3_svg_lineRadial);
+ line.radius = line.x, delete line.x;
+ line.angle = line.y, delete line.y;
+ return line;
+ };
+ function d3_svg_lineRadial(points) {
+ var point, i = -1, n = points.length, r, a;
+ while (++i < n) {
+ point = points[i];
+ r = point[0];
+ a = point[1] - halfπ;
+ point[0] = r * Math.cos(a);
+ point[1] = r * Math.sin(a);
+ }
+ return points;
+ }
+ function d3_svg_area(projection) {
+ var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
+ function area(data) {
+ var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
+ return x;
+ } : d3_functor(x1), fy1 = y0 === y1 ? function() {
+ return y;
+ } : d3_functor(y1), x, y;
+ function segment() {
+ segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
+ }
+ while (++i < n) {
+ if (defined.call(this, d = data[i], i)) {
+ points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
+ points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
+ } else if (points0.length) {
+ segment();
+ points0 = [];
+ points1 = [];
+ }
+ }
+ if (points0.length) segment();
+ return segments.length ? segments.join("") : null;
+ }
+ area.x = function(_) {
+ if (!arguments.length) return x1;
+ x0 = x1 = _;
+ return area;
+ };
+ area.x0 = function(_) {
+ if (!arguments.length) return x0;
+ x0 = _;
+ return area;
+ };
+ area.x1 = function(_) {
+ if (!arguments.length) return x1;
+ x1 = _;
+ return area;
+ };
+ area.y = function(_) {
+ if (!arguments.length) return y1;
+ y0 = y1 = _;
+ return area;
+ };
+ area.y0 = function(_) {
+ if (!arguments.length) return y0;
+ y0 = _;
+ return area;
+ };
+ area.y1 = function(_) {
+ if (!arguments.length) return y1;
+ y1 = _;
+ return area;
+ };
+ area.defined = function(_) {
+ if (!arguments.length) return defined;
+ defined = _;
+ return area;
+ };
+ area.interpolate = function(_) {
+ if (!arguments.length) return interpolateKey;
+ if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+ interpolateReverse = interpolate.reverse || interpolate;
+ L = interpolate.closed ? "M" : "L";
+ return area;
+ };
+ area.tension = function(_) {
+ if (!arguments.length) return tension;
+ tension = _;
+ return area;
+ };
+ return area;
+ }
+ d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
+ d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
+ d3.svg.area = function() {
+ return d3_svg_area(d3_identity);
+ };
+ d3.svg.area.radial = function() {
+ var area = d3_svg_area(d3_svg_lineRadial);
+ area.radius = area.x, delete area.x;
+ area.innerRadius = area.x0, delete area.x0;
+ area.outerRadius = area.x1, delete area.x1;
+ area.angle = area.y, delete area.y;
+ area.startAngle = area.y0, delete area.y0;
+ area.endAngle = area.y1, delete area.y1;
+ return area;
+ };
+ d3.svg.chord = function() {
+ var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+ function chord(d, i) {
+ var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
+ return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
+ }
+ function subgroup(self, f, d, i) {
+ var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ;
+ return {
+ r: r,
+ a0: a0,
+ a1: a1,
+ p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
+ p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
+ };
+ }
+ function equals(a, b) {
+ return a.a0 == b.a0 && a.a1 == b.a1;
+ }
+ function arc(r, p, a) {
+ return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
+ }
+ function curve(r0, p0, r1, p1) {
+ return "Q 0,0 " + p1;
+ }
+ chord.radius = function(v) {
+ if (!arguments.length) return radius;
+ radius = d3_functor(v);
+ return chord;
+ };
+ chord.source = function(v) {
+ if (!arguments.length) return source;
+ source = d3_functor(v);
+ return chord;
+ };
+ chord.target = function(v) {
+ if (!arguments.length) return target;
+ target = d3_functor(v);
+ return chord;
+ };
+ chord.startAngle = function(v) {
+ if (!arguments.length) return startAngle;
+ startAngle = d3_functor(v);
+ return chord;
+ };
+ chord.endAngle = function(v) {
+ if (!arguments.length) return endAngle;
+ endAngle = d3_functor(v);
+ return chord;
+ };
+ return chord;
+ };
+ function d3_svg_chordRadius(d) {
+ return d.radius;
+ }
+ d3.svg.diagonal = function() {
+ var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
+ function diagonal(d, i) {
+ var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
+ x: p0.x,
+ y: m
+ }, {
+ x: p3.x,
+ y: m
+ }, p3 ];
+ p = p.map(projection);
+ return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
+ }
+ diagonal.source = function(x) {
+ if (!arguments.length) return source;
+ source = d3_functor(x);
+ return diagonal;
+ };
+ diagonal.target = function(x) {
+ if (!arguments.length) return target;
+ target = d3_functor(x);
+ return diagonal;
+ };
+ diagonal.projection = function(x) {
+ if (!arguments.length) return projection;
+ projection = x;
+ return diagonal;
+ };
+ return diagonal;
+ };
+ function d3_svg_diagonalProjection(d) {
+ return [ d.x, d.y ];
+ }
+ d3.svg.diagonal.radial = function() {
+ var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
+ diagonal.projection = function(x) {
+ return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
+ };
+ return diagonal;
+ };
+ function d3_svg_diagonalRadialProjection(projection) {
+ return function() {
+ var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ;
+ return [ r * Math.cos(a), r * Math.sin(a) ];
+ };
+ }
+ d3.svg.symbol = function() {
+ var type = d3_svg_symbolType, size = d3_svg_symbolSize;
+ function symbol(d, i) {
+ return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
+ }
+ symbol.type = function(x) {
+ if (!arguments.length) return type;
+ type = d3_functor(x);
+ return symbol;
+ };
+ symbol.size = function(x) {
+ if (!arguments.length) return size;
+ size = d3_functor(x);
+ return symbol;
+ };
+ return symbol;
+ };
+ function d3_svg_symbolSize() {
+ return 64;
+ }
+ function d3_svg_symbolType() {
+ return "circle";
+ }
+ function d3_svg_symbolCircle(size) {
+ var r = Math.sqrt(size / π);
+ return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
+ }
+ var d3_svg_symbols = d3.map({
+ circle: d3_svg_symbolCircle,
+ cross: function(size) {
+ var r = Math.sqrt(size / 5) / 2;
+ return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
+ },
+ diamond: function(size) {
+ var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
+ return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
+ },
+ square: function(size) {
+ var r = Math.sqrt(size) / 2;
+ return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
+ },
+ "triangle-down": function(size) {
+ var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+ return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
+ },
+ "triangle-up": function(size) {
+ var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+ return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
+ }
+ });
+ d3.svg.symbolTypes = d3_svg_symbols.keys();
+ var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
+ d3_selectionPrototype.transition = function(name) {
+ var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || {
+ time: Date.now(),
+ ease: d3_ease_cubicInOut,
+ delay: 0,
+ duration: 250
+ };
+ for (var j = -1, m = this.length; ++j < m; ) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) d3_transitionNode(node, i, ns, id, transition);
+ subgroup.push(node);
+ }
+ }
+ return d3_transition(subgroups, ns, id);
+ };
+ d3_selectionPrototype.interrupt = function(name) {
+ return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name)));
+ };
+ var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace());
+ function d3_selection_interruptNS(ns) {
+ return function() {
+ var lock, activeId, active;
+ if ((lock = this[ns]) && (active = lock[activeId = lock.active])) {
+ active.timer.c = null;
+ active.timer.t = NaN;
+ if (--lock.count) delete lock[activeId]; else delete this[ns];
+ lock.active += .5;
+ active.event && active.event.interrupt.call(this, this.__data__, active.index);
+ }
+ };
+ }
+ function d3_transition(groups, ns, id) {
+ d3_subclass(groups, d3_transitionPrototype);
+ groups.namespace = ns;
+ groups.id = id;
+ return groups;
+ }
+ var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
+ d3_transitionPrototype.call = d3_selectionPrototype.call;
+ d3_transitionPrototype.empty = d3_selectionPrototype.empty;
+ d3_transitionPrototype.node = d3_selectionPrototype.node;
+ d3_transitionPrototype.size = d3_selectionPrototype.size;
+ d3.transition = function(selection, name) {
+ return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection);
+ };
+ d3.transition.prototype = d3_transitionPrototype;
+ d3_transitionPrototype.select = function(selector) {
+ var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node;
+ selector = d3_selection_selector(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
+ if ("__data__" in node) subnode.__data__ = node.__data__;
+ d3_transitionNode(subnode, i, ns, id, node[ns][id]);
+ subgroup.push(subnode);
+ } else {
+ subgroup.push(null);
+ }
+ }
+ }
+ return d3_transition(subgroups, ns, id);
+ };
+ d3_transitionPrototype.selectAll = function(selector) {
+ var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition;
+ selector = d3_selection_selectorAll(selector);
+ for (var j = -1, m = this.length; ++j < m; ) {
+ for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+ if (node = group[i]) {
+ transition = node[ns][id];
+ subnodes = selector.call(node, node.__data__, i, j);
+ subgroups.push(subgroup = []);
+ for (var k = -1, o = subnodes.length; ++k < o; ) {
+ if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition);
+ subgroup.push(subnode);
+ }
+ }
+ }
+ }
+ return d3_transition(subgroups, ns, id);
+ };
+ d3_transitionPrototype.filter = function(filter) {
+ var subgroups = [], subgroup, group, node;
+ if (typeof filter !== "function") filter = d3_selection_filter(filter);
+ for (var j = 0, m = this.length; j < m; j++) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+ if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
+ subgroup.push(node);
+ }
+ }
+ }
+ return d3_transition(subgroups, this.namespace, this.id);
+ };
+ d3_transitionPrototype.tween = function(name, tween) {
+ var id = this.id, ns = this.namespace;
+ if (arguments.length < 2) return this.node()[ns][id].tween.get(name);
+ return d3_selection_each(this, tween == null ? function(node) {
+ node[ns][id].tween.remove(name);
+ } : function(node) {
+ node[ns][id].tween.set(name, tween);
+ });
+ };
+ function d3_transition_tween(groups, name, value, tween) {
+ var id = groups.id, ns = groups.namespace;
+ return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
+ node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
+ } : (value = tween(value), function(node) {
+ node[ns][id].tween.set(name, value);
+ }));
+ }
+ d3_transitionPrototype.attr = function(nameNS, value) {
+ if (arguments.length < 2) {
+ for (value in nameNS) this.attr(value, nameNS[value]);
+ return this;
+ }
+ var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
+ function attrNull() {
+ this.removeAttribute(name);
+ }
+ function attrNullNS() {
+ this.removeAttributeNS(name.space, name.local);
+ }
+ function attrTween(b) {
+ return b == null ? attrNull : (b += "", function() {
+ var a = this.getAttribute(name), i;
+ return a !== b && (i = interpolate(a, b), function(t) {
+ this.setAttribute(name, i(t));
+ });
+ });
+ }
+ function attrTweenNS(b) {
+ return b == null ? attrNullNS : (b += "", function() {
+ var a = this.getAttributeNS(name.space, name.local), i;
+ return a !== b && (i = interpolate(a, b), function(t) {
+ this.setAttributeNS(name.space, name.local, i(t));
+ });
+ });
+ }
+ return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
+ };
+ d3_transitionPrototype.attrTween = function(nameNS, tween) {
+ var name = d3.ns.qualify(nameNS);
+ function attrTween(d, i) {
+ var f = tween.call(this, d, i, this.getAttribute(name));
+ return f && function(t) {
+ this.setAttribute(name, f(t));
+ };
+ }
+ function attrTweenNS(d, i) {
+ var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
+ return f && function(t) {
+ this.setAttributeNS(name.space, name.local, f(t));
+ };
+ }
+ return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
+ };
+ d3_transitionPrototype.style = function(name, value, priority) {
+ var n = arguments.length;
+ if (n < 3) {
+ if (typeof name !== "string") {
+ if (n < 2) value = "";
+ for (priority in name) this.style(priority, name[priority], value);
+ return this;
+ }
+ priority = "";
+ }
+ function styleNull() {
+ this.style.removeProperty(name);
+ }
+ function styleString(b) {
+ return b == null ? styleNull : (b += "", function() {
+ var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i;
+ return a !== b && (i = d3_interpolate(a, b), function(t) {
+ this.style.setProperty(name, i(t), priority);
+ });
+ });
+ }
+ return d3_transition_tween(this, "style." + name, value, styleString);
+ };
+ d3_transitionPrototype.styleTween = function(name, tween, priority) {
+ if (arguments.length < 3) priority = "";
+ function styleTween(d, i) {
+ var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name));
+ return f && function(t) {
+ this.style.setProperty(name, f(t), priority);
+ };
+ }
+ return this.tween("style." + name, styleTween);
+ };
+ d3_transitionPrototype.text = function(value) {
+ return d3_transition_tween(this, "text", value, d3_transition_text);
+ };
+ function d3_transition_text(b) {
+ if (b == null) b = "";
+ return function() {
+ this.textContent = b;
+ };
+ }
+ d3_transitionPrototype.remove = function() {
+ var ns = this.namespace;
+ return this.each("end.transition", function() {
+ var p;
+ if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this);
+ });
+ };
+ d3_transitionPrototype.ease = function(value) {
+ var id = this.id, ns = this.namespace;
+ if (arguments.length < 1) return this.node()[ns][id].ease;
+ if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
+ return d3_selection_each(this, function(node) {
+ node[ns][id].ease = value;
+ });
+ };
+ d3_transitionPrototype.delay = function(value) {
+ var id = this.id, ns = this.namespace;
+ if (arguments.length < 1) return this.node()[ns][id].delay;
+ return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+ node[ns][id].delay = +value.call(node, node.__data__, i, j);
+ } : (value = +value, function(node) {
+ node[ns][id].delay = value;
+ }));
+ };
+ d3_transitionPrototype.duration = function(value) {
+ var id = this.id, ns = this.namespace;
+ if (arguments.length < 1) return this.node()[ns][id].duration;
+ return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+ node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j));
+ } : (value = Math.max(1, value), function(node) {
+ node[ns][id].duration = value;
+ }));
+ };
+ d3_transitionPrototype.each = function(type, listener) {
+ var id = this.id, ns = this.namespace;
+ if (arguments.length < 2) {
+ var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
+ try {
+ d3_transitionInheritId = id;
+ d3_selection_each(this, function(node, i, j) {
+ d3_transitionInherit = node[ns][id];
+ type.call(node, node.__data__, i, j);
+ });
+ } finally {
+ d3_transitionInherit = inherit;
+ d3_transitionInheritId = inheritId;
+ }
+ } else {
+ d3_selection_each(this, function(node) {
+ var transition = node[ns][id];
+ (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener);
+ });
+ }
+ return this;
+ };
+ d3_transitionPrototype.transition = function() {
+ var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition;
+ for (var j = 0, m = this.length; j < m; j++) {
+ subgroups.push(subgroup = []);
+ for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+ if (node = group[i]) {
+ transition = node[ns][id0];
+ d3_transitionNode(node, i, ns, id1, {
+ time: transition.time,
+ ease: transition.ease,
+ delay: transition.delay + transition.duration,
+ duration: transition.duration
+ });
+ }
+ subgroup.push(node);
+ }
+ }
+ return d3_transition(subgroups, ns, id1);
+ };
+ function d3_transitionNamespace(name) {
+ return name == null ? "__transition__" : "__transition_" + name + "__";
+ }
+ function d3_transitionNode(node, i, ns, id, inherit) {
+ var lock = node[ns] || (node[ns] = {
+ active: 0,
+ count: 0
+ }), transition = lock[id], time, timer, duration, ease, tweens;
+ function schedule(elapsed) {
+ var delay = transition.delay;
+ timer.t = delay + time;
+ if (delay <= elapsed) return start(elapsed - delay);
+ timer.c = start;
+ }
+ function start(elapsed) {
+ var activeId = lock.active, active = lock[activeId];
+ if (active) {
+ active.timer.c = null;
+ active.timer.t = NaN;
+ --lock.count;
+ delete lock[activeId];
+ active.event && active.event.interrupt.call(node, node.__data__, active.index);
+ }
+ for (var cancelId in lock) {
+ if (+cancelId < id) {
+ var cancel = lock[cancelId];
+ cancel.timer.c = null;
+ cancel.timer.t = NaN;
+ --lock.count;
+ delete lock[cancelId];
+ }
+ }
+ timer.c = tick;
+ d3_timer(function() {
+ if (timer.c && tick(elapsed || 1)) {
+ timer.c = null;
+ timer.t = NaN;
+ }
+ return 1;
+ }, 0, time);
+ lock.active = id;
+ transition.event && transition.event.start.call(node, node.__data__, i);
+ tweens = [];
+ transition.tween.forEach(function(key, value) {
+ if (value = value.call(node, node.__data__, i)) {
+ tweens.push(value);
+ }
+ });
+ ease = transition.ease;
+ duration = transition.duration;
+ }
+ function tick(elapsed) {
+ var t = elapsed / duration, e = ease(t), n = tweens.length;
+ while (n > 0) {
+ tweens[--n].call(node, e);
+ }
+ if (t >= 1) {
+ transition.event && transition.event.end.call(node, node.__data__, i);
+ if (--lock.count) delete lock[id]; else delete node[ns];
+ return 1;
+ }
+ }
+ if (!transition) {
+ time = inherit.time;
+ timer = d3_timer(schedule, 0, time);
+ transition = lock[id] = {
+ tween: new d3_Map(),
+ time: time,
+ timer: timer,
+ delay: inherit.delay,
+ duration: inherit.duration,
+ ease: inherit.ease,
+ index: i
+ };
+ inherit = null;
+ ++lock.count;
+ }
+ }
+ d3.svg.axis = function() {
+ var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
+ function axis(g) {
+ g.each(function() {
+ var g = d3.select(this);
+ var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
+ var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform;
+ var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"),
+ d3.transition(path));
+ tickEnter.append("line");
+ tickEnter.append("text");
+ var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2;
+ if (orient === "bottom" || orient === "top") {
+ tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", y2 = "y2";
+ text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle");
+ pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize);
+ } else {
+ tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", y2 = "x2";
+ text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start");
+ pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize);
+ }
+ lineEnter.attr(y2, sign * innerTickSize);
+ textEnter.attr(y1, sign * tickSpacing);
+ lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize);
+ textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing);
+ if (scale1.rangeBand) {
+ var x = scale1, dx = x.rangeBand() / 2;
+ scale0 = scale1 = function(d) {
+ return x(d) + dx;
+ };
+ } else if (scale0.rangeBand) {
+ scale0 = scale1;
+ } else {
+ tickExit.call(tickTransform, scale1, scale0);
+ }
+ tickEnter.call(tickTransform, scale0, scale1);
+ tickUpdate.call(tickTransform, scale1, scale1);
+ });
+ }
+ axis.scale = function(x) {
+ if (!arguments.length) return scale;
+ scale = x;
+ return axis;
+ };
+ axis.orient = function(x) {
+ if (!arguments.length) return orient;
+ orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
+ return axis;
+ };
+ axis.ticks = function() {
+ if (!arguments.length) return tickArguments_;
+ tickArguments_ = d3_array(arguments);
+ return axis;
+ };
+ axis.tickValues = function(x) {
+ if (!arguments.length) return tickValues;
+ tickValues = x;
+ return axis;
+ };
+ axis.tickFormat = function(x) {
+ if (!arguments.length) return tickFormat_;
+ tickFormat_ = x;
+ return axis;
+ };
+ axis.tickSize = function(x) {
+ var n = arguments.length;
+ if (!n) return innerTickSize;
+ innerTickSize = +x;
+ outerTickSize = +arguments[n - 1];
+ return axis;
+ };
+ axis.innerTickSize = function(x) {
+ if (!arguments.length) return innerTickSize;
+ innerTickSize = +x;
+ return axis;
+ };
+ axis.outerTickSize = function(x) {
+ if (!arguments.length) return outerTickSize;
+ outerTickSize = +x;
+ return axis;
+ };
+ axis.tickPadding = function(x) {
+ if (!arguments.length) return tickPadding;
+ tickPadding = +x;
+ return axis;
+ };
+ axis.tickSubdivide = function() {
+ return arguments.length && axis;
+ };
+ return axis;
+ };
+ var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
+ top: 1,
+ right: 1,
+ bottom: 1,
+ left: 1
+ };
+ function d3_svg_axisX(selection, x0, x1) {
+ selection.attr("transform", function(d) {
+ var v0 = x0(d);
+ return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)";
+ });
+ }
+ function d3_svg_axisY(selection, y0, y1) {
+ selection.attr("transform", function(d) {
+ var v0 = y0(d);
+ return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")";
+ });
+ }
+ d3.svg.brush = function() {
+ var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
+ function brush(g) {
+ g.each(function() {
+ var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
+ var background = g.selectAll(".background").data([ 0 ]);
+ background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
+ g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
+ var resize = g.selectAll(".resize").data(resizes, d3_identity);
+ resize.exit().remove();
+ resize.enter().append("g").attr("class", function(d) {
+ return "resize " + d;
+ }).style("cursor", function(d) {
+ return d3_svg_brushCursor[d];
+ }).append("rect").attr("x", function(d) {
+ return /[ew]$/.test(d) ? -3 : null;
+ }).attr("y", function(d) {
+ return /^[ns]/.test(d) ? -3 : null;
+ }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
+ resize.style("display", brush.empty() ? "none" : null);
+ var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
+ if (x) {
+ range = d3_scaleRange(x);
+ backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
+ redrawX(gUpdate);
+ }
+ if (y) {
+ range = d3_scaleRange(y);
+ backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
+ redrawY(gUpdate);
+ }
+ redraw(gUpdate);
+ });
+ }
+ brush.event = function(g) {
+ g.each(function() {
+ var event_ = event.of(this, arguments), extent1 = {
+ x: xExtent,
+ y: yExtent,
+ i: xExtentDomain,
+ j: yExtentDomain
+ }, extent0 = this.__chart__ || extent1;
+ this.__chart__ = extent1;
+ if (d3_transitionInheritId) {
+ d3.select(this).transition().each("start.brush", function() {
+ xExtentDomain = extent0.i;
+ yExtentDomain = extent0.j;
+ xExtent = extent0.x;
+ yExtent = extent0.y;
+ event_({
+ type: "brushstart"
+ });
+ }).tween("brush:brush", function() {
+ var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
+ xExtentDomain = yExtentDomain = null;
+ return function(t) {
+ xExtent = extent1.x = xi(t);
+ yExtent = extent1.y = yi(t);
+ event_({
+ type: "brush",
+ mode: "resize"
+ });
+ };
+ }).each("end.brush", function() {
+ xExtentDomain = extent1.i;
+ yExtentDomain = extent1.j;
+ event_({
+ type: "brush",
+ mode: "resize"
+ });
+ event_({
+ type: "brushend"
+ });
+ });
+ } else {
+ event_({
+ type: "brushstart"
+ });
+ event_({
+ type: "brush",
+ mode: "resize"
+ });
+ event_({
+ type: "brushend"
+ });
+ }
+ });
+ };
+ function redraw(g) {
+ g.selectAll(".resize").attr("transform", function(d) {
+ return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
+ });
+ }
+ function redrawX(g) {
+ g.select(".extent").attr("x", xExtent[0]);
+ g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
+ }
+ function redrawY(g) {
+ g.select(".extent").attr("y", yExtent[0]);
+ g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
+ }
+ function brushstart() {
+ var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset;
+ var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup);
+ if (d3.event.changedTouches) {
+ w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
+ } else {
+ w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
+ }
+ g.interrupt().selectAll("*").interrupt();
+ if (dragging) {
+ origin[0] = xExtent[0] - origin[0];
+ origin[1] = yExtent[0] - origin[1];
+ } else if (resizing) {
+ var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
+ offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
+ origin[0] = xExtent[ex];
+ origin[1] = yExtent[ey];
+ } else if (d3.event.altKey) center = origin.slice();
+ g.style("pointer-events", "none").selectAll(".resize").style("display", null);
+ d3.select("body").style("cursor", eventTarget.style("cursor"));
+ event_({
+ type: "brushstart"
+ });
+ brushmove();
+ function keydown() {
+ if (d3.event.keyCode == 32) {
+ if (!dragging) {
+ center = null;
+ origin[0] -= xExtent[1];
+ origin[1] -= yExtent[1];
+ dragging = 2;
+ }
+ d3_eventPreventDefault();
+ }
+ }
+ function keyup() {
+ if (d3.event.keyCode == 32 && dragging == 2) {
+ origin[0] += xExtent[1];
+ origin[1] += yExtent[1];
+ dragging = 0;
+ d3_eventPreventDefault();
+ }
+ }
+ function brushmove() {
+ var point = d3.mouse(target), moved = false;
+ if (offset) {
+ point[0] += offset[0];
+ point[1] += offset[1];
+ }
+ if (!dragging) {
+ if (d3.event.altKey) {
+ if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
+ origin[0] = xExtent[+(point[0] < center[0])];
+ origin[1] = yExtent[+(point[1] < center[1])];
+ } else center = null;
+ }
+ if (resizingX && move1(point, x, 0)) {
+ redrawX(g);
+ moved = true;
+ }
+ if (resizingY && move1(point, y, 1)) {
+ redrawY(g);
+ moved = true;
+ }
+ if (moved) {
+ redraw(g);
+ event_({
+ type: "brush",
+ mode: dragging ? "move" : "resize"
+ });
+ }
+ }
+ function move1(point, scale, i) {
+ var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
+ if (dragging) {
+ r0 -= position;
+ r1 -= size + position;
+ }
+ min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
+ if (dragging) {
+ max = (min += position) + size;
+ } else {
+ if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
+ if (position < min) {
+ max = min;
+ min = position;
+ } else {
+ max = position;
+ }
+ }
+ if (extent[0] != min || extent[1] != max) {
+ if (i) yExtentDomain = null; else xExtentDomain = null;
+ extent[0] = min;
+ extent[1] = max;
+ return true;
+ }
+ }
+ function brushend() {
+ brushmove();
+ g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
+ d3.select("body").style("cursor", null);
+ w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
+ dragRestore();
+ event_({
+ type: "brushend"
+ });
+ }
+ }
+ brush.x = function(z) {
+ if (!arguments.length) return x;
+ x = z;
+ resizes = d3_svg_brushResizes[!x << 1 | !y];
+ return brush;
+ };
+ brush.y = function(z) {
+ if (!arguments.length) return y;
+ y = z;
+ resizes = d3_svg_brushResizes[!x << 1 | !y];
+ return brush;
+ };
+ brush.clamp = function(z) {
+ if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
+ if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
+ return brush;
+ };
+ brush.extent = function(z) {
+ var x0, x1, y0, y1, t;
+ if (!arguments.length) {
+ if (x) {
+ if (xExtentDomain) {
+ x0 = xExtentDomain[0], x1 = xExtentDomain[1];
+ } else {
+ x0 = xExtent[0], x1 = xExtent[1];
+ if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ }
+ }
+ if (y) {
+ if (yExtentDomain) {
+ y0 = yExtentDomain[0], y1 = yExtentDomain[1];
+ } else {
+ y0 = yExtent[0], y1 = yExtent[1];
+ if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
+ if (y1 < y0) t = y0, y0 = y1, y1 = t;
+ }
+ }
+ return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
+ }
+ if (x) {
+ x0 = z[0], x1 = z[1];
+ if (y) x0 = x0[0], x1 = x1[0];
+ xExtentDomain = [ x0, x1 ];
+ if (x.invert) x0 = x(x0), x1 = x(x1);
+ if (x1 < x0) t = x0, x0 = x1, x1 = t;
+ if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
+ }
+ if (y) {
+ y0 = z[0], y1 = z[1];
+ if (x) y0 = y0[1], y1 = y1[1];
+ yExtentDomain = [ y0, y1 ];
+ if (y.invert) y0 = y(y0), y1 = y(y1);
+ if (y1 < y0) t = y0, y0 = y1, y1 = t;
+ if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
+ }
+ return brush;
+ };
+ brush.clear = function() {
+ if (!brush.empty()) {
+ xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
+ xExtentDomain = yExtentDomain = null;
+ }
+ return brush;
+ };
+ brush.empty = function() {
+ return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
+ };
+ return d3.rebind(brush, event, "on");
+ };
+ var d3_svg_brushCursor = {
+ n: "ns-resize",
+ e: "ew-resize",
+ s: "ns-resize",
+ w: "ew-resize",
+ nw: "nwse-resize",
+ ne: "nesw-resize",
+ se: "nwse-resize",
+ sw: "nesw-resize"
+ };
+ var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
+ var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
+ var d3_time_formatUtc = d3_time_format.utc;
+ var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
+ d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
+ function d3_time_formatIsoNative(date) {
+ return date.toISOString();
+ }
+ d3_time_formatIsoNative.parse = function(string) {
+ var date = new Date(string);
+ return isNaN(date) ? null : date;
+ };
+ d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
+ d3_time.second = d3_time_interval(function(date) {
+ return new d3_date(Math.floor(date / 1e3) * 1e3);
+ }, function(date, offset) {
+ date.setTime(date.getTime() + Math.floor(offset) * 1e3);
+ }, function(date) {
+ return date.getSeconds();
+ });
+ d3_time.seconds = d3_time.second.range;
+ d3_time.seconds.utc = d3_time.second.utc.range;
+ d3_time.minute = d3_time_interval(function(date) {
+ return new d3_date(Math.floor(date / 6e4) * 6e4);
+ }, function(date, offset) {
+ date.setTime(date.getTime() + Math.floor(offset) * 6e4);
+ }, function(date) {
+ return date.getMinutes();
+ });
+ d3_time.minutes = d3_time.minute.range;
+ d3_time.minutes.utc = d3_time.minute.utc.range;
+ d3_time.hour = d3_time_interval(function(date) {
+ var timezone = date.getTimezoneOffset() / 60;
+ return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
+ }, function(date, offset) {
+ date.setTime(date.getTime() + Math.floor(offset) * 36e5);
+ }, function(date) {
+ return date.getHours();
+ });
+ d3_time.hours = d3_time.hour.range;
+ d3_time.hours.utc = d3_time.hour.utc.range;
+ d3_time.month = d3_time_interval(function(date) {
+ date = d3_time.day(date);
+ date.setDate(1);
+ return date;
+ }, function(date, offset) {
+ date.setMonth(date.getMonth() + offset);
+ }, function(date) {
+ return date.getMonth();
+ });
+ d3_time.months = d3_time.month.range;
+ d3_time.months.utc = d3_time.month.utc.range;
+ function d3_time_scale(linear, methods, format) {
+ function scale(x) {
+ return linear(x);
+ }
+ scale.invert = function(x) {
+ return d3_time_scaleDate(linear.invert(x));
+ };
+ scale.domain = function(x) {
+ if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
+ linear.domain(x);
+ return scale;
+ };
+ function tickMethod(extent, count) {
+ var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
+ return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
+ return d / 31536e6;
+ }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
+ }
+ scale.nice = function(interval, skip) {
+ var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
+ if (method) interval = method[0], skip = method[1];
+ function skipped(date) {
+ return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
+ }
+ return scale.domain(d3_scale_nice(domain, skip > 1 ? {
+ floor: function(date) {
+ while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
+ return date;
+ },
+ ceil: function(date) {
+ while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
+ return date;
+ }
+ } : interval));
+ };
+ scale.ticks = function(interval, skip) {
+ var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
+ range: interval
+ }, skip ];
+ if (method) interval = method[0], skip = method[1];
+ return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
+ };
+ scale.tickFormat = function() {
+ return format;
+ };
+ scale.copy = function() {
+ return d3_time_scale(linear.copy(), methods, format);
+ };
+ return d3_scale_linearRebind(scale, linear);
+ }
+ function d3_time_scaleDate(t) {
+ return new Date(t);
+ }
+ var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
+ var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
+ var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
+ return d.getMilliseconds();
+ } ], [ ":%S", function(d) {
+ return d.getSeconds();
+ } ], [ "%I:%M", function(d) {
+ return d.getMinutes();
+ } ], [ "%I %p", function(d) {
+ return d.getHours();
+ } ], [ "%a %d", function(d) {
+ return d.getDay() && d.getDate() != 1;
+ } ], [ "%b %d", function(d) {
+ return d.getDate() != 1;
+ } ], [ "%B", function(d) {
+ return d.getMonth();
+ } ], [ "%Y", d3_true ] ]);
+ var d3_time_scaleMilliseconds = {
+ range: function(start, stop, step) {
+ return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
+ },
+ floor: d3_identity,
+ ceil: d3_identity
+ };
+ d3_time_scaleLocalMethods.year = d3_time.year;
+ d3_time.scale = function() {
+ return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
+ };
+ var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
+ return [ m[0].utc, m[1] ];
+ });
+ var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
+ return d.getUTCMilliseconds();
+ } ], [ ":%S", function(d) {
+ return d.getUTCSeconds();
+ } ], [ "%I:%M", function(d) {
+ return d.getUTCMinutes();
+ } ], [ "%I %p", function(d) {
+ return d.getUTCHours();
+ } ], [ "%a %d", function(d) {
+ return d.getUTCDay() && d.getUTCDate() != 1;
+ } ], [ "%b %d", function(d) {
+ return d.getUTCDate() != 1;
+ } ], [ "%B", function(d) {
+ return d.getUTCMonth();
+ } ], [ "%Y", d3_true ] ]);
+ d3_time_scaleUtcMethods.year = d3_time.year.utc;
+ d3_time.scale.utc = function() {
+ return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
+ };
+ d3.text = d3_xhrType(function(request) {
+ return request.responseText;
+ });
+ d3.json = function(url, callback) {
+ return d3_xhr(url, "application/json", d3_json, callback);
+ };
+ function d3_json(request) {
+ return JSON.parse(request.responseText);
+ }
+ d3.html = function(url, callback) {
+ return d3_xhr(url, "text/html", d3_html, callback);
+ };
+ function d3_html(request) {
+ var range = d3_document.createRange();
+ range.selectNode(d3_document.body);
+ return range.createContextualFragment(request.responseText);
+ }
+ d3.xml = d3_xhrType(function(request) {
+ return request.responseXML;
+ });
+ if (typeof define === "function" && define.amd) this.d3 = d3, define(d3); else if (typeof module === "object" && module.exports) module.exports = d3; else this.d3 = d3;
+}(); \ No newline at end of file
diff --git a/debian/missing-sources/dygraph-combined-dd74404.js b/debian/missing-sources/dygraph-combined-dd74404.js
new file mode 100644
index 000000000..887c272b2
--- /dev/null
+++ b/debian/missing-sources/dygraph-combined-dd74404.js
@@ -0,0 +1,6 @@
+/*! @license Copyright 2014 Dan Vanderkam (danvdk@gmail.com) MIT-licensed (http://opensource.org/licenses/MIT) */
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Dygraph=t()}}(function(){return function t(e,a,i){function n(o,s){if(!a[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var h=new Error("Cannot find module '"+o+"'");throw h.code="MODULE_NOT_FOUND",h}var u=a[o]={exports:{}};e[o][0].call(u.exports,function(t){var a=e[o][1][t];return n(a?a:t)},u,u.exports,t,e,a,i)}return a[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)n(i[o]);return n}({1:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./bars"),r=i(n),o=function(){};o.prototype=new r.default,o.prototype.extractSeries=function(t,e,a){for(var i,n,r,o=[],s=a.get("logscale"),l=0;l<t.length;l++)i=t[l][0],r=t[l][e],s&&null!==r&&(r[0]<=0||r[1]<=0||r[2]<=0)&&(r=null),null!==r?(n=r[1],null===n||isNaN(n)?o.push([i,n,[n,n]]):o.push([i,n,[r[0],r[2]]])):o.push([i,null,[null,null]]);return o},o.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l,h,u=[];for(n=0,o=0,r=0,s=0,l=0;l<t.length;l++){if(i=t[l][1],h=t[l][2],u[l]=t[l],null===i||isNaN(i)||(n+=h[0],o+=i,r+=h[1],s+=1),l-e>=0){var d=t[l-e];null===d[1]||isNaN(d[1])||(n-=d[2][0],o-=d[1],r-=d[2][1],s-=1)}s?u[l]=[t[l][0],1*o/s,[1*n/s,1*r/s]]:u[l]=[t[l][0],null,[null,null]]}return u},a.default=o,e.exports=a.default},{"./bars":4}],2:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./bars"),r=i(n),o=function(){};o.prototype=new r.default,o.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s=[],l=a.get("sigma"),h=a.get("logscale"),u=0;u<t.length;u++)i=t[u][0],o=t[u][e],h&&null!==o&&(o[0]<=0||o[0]-l*o[1]<=0)&&(o=null),null!==o?(n=o[0],null===n||isNaN(n)?s.push([i,n,[n,n,n]]):(r=l*o[1],s.push([i,n,[n-r,n+r,o[1]]]))):s.push([i,null,[null,null,null]]);return s},o.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l,h,u,d,c=[],p=a.get("sigma");for(i=0;i<t.length;i++){for(s=0,u=0,l=0,n=Math.max(0,i-e+1);n<i+1;n++)r=t[n][1],null===r||isNaN(r)||(l++,s+=r,u+=Math.pow(t[n][2][2],2));l?(h=Math.sqrt(u)/l,d=s/l,c[i]=[t[i][0],d,[d-p*h,d+p*h]]):(o=1==e?t[i][1]:null,c[i]=[t[i][0],o,[o,o]])}return c},a.default=o,e.exports=a.default},{"./bars":4}],3:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./bars"),r=i(n),o=function(){};o.prototype=new r.default,o.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s,l,h,u,d=[],c=100,p=a.get("sigma"),g=a.get("logscale"),f=0;f<t.length;f++)i=t[f][0],r=t[f][e],g&&null!==r&&(r[0]<=0||r[1]<=0)&&(r=null),null!==r?(o=r[0],s=r[1],null===o||isNaN(o)?d.push([i,o,[o,o,o,s]]):(l=s?o/s:0,h=s?p*Math.sqrt(l*(1-l)/s):1,u=c*h,n=c*l,d.push([i,n,[n-u,n+u,o,s]]))):d.push([i,null,[null,null,null,null]]);return d},o.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s=[],l=a.get("sigma"),h=a.get("wilsonInterval"),u=0,d=0,c=100;for(r=0;r<t.length;r++){u+=t[r][2][2],d+=t[r][2][3],r-e>=0&&(u-=t[r-e][2][2],d-=t[r-e][2][3]);var p=t[r][0],g=d?u/d:0;if(h)if(d){var f=g<0?0:g,v=d,_=l*Math.sqrt(f*(1-f)/v+l*l/(4*v*v)),y=1+l*l/d;i=(f+l*l/(2*d)-_)/y,n=(f+l*l/(2*d)+_)/y,s[r]=[p,f*c,[i*c,n*c]]}else s[r]=[p,0,[0,0]];else o=d?l*Math.sqrt(g*(1-g)/d):1,s[r]=[p,c*g,[c*(g-o),c*(g+o)]]}return s},a.default=o,e.exports=a.default},{"./bars":4}],4:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./datahandler"),r=i(n),o=t("../dygraph-layout"),s=i(o),l=function(){r.default.call(this)};l.prototype=new r.default,l.prototype.extractSeries=function(t,e,a){},l.prototype.rollingAverage=function(t,e,a){},l.prototype.onPointsCreated_=function(t,e){for(var a=0;a<t.length;++a){var i=t[a],n=e[a];n.y_top=NaN,n.y_bottom=NaN,n.yval_minus=r.default.parseFloat(i[2][0]),n.yval_plus=r.default.parseFloat(i[2][1])}},l.prototype.getExtremeYValues=function(t,e,a){for(var i,n=null,r=null,o=0,s=t.length-1,l=o;l<=s;l++)if(i=t[l][1],null!==i&&!isNaN(i)){var h=t[l][2][0],u=t[l][2][1];h>i&&(h=i),u<i&&(u=i),(null===r||u>r)&&(r=u),(null===n||h<n)&&(n=h)}return[n,r]},l.prototype.onLineEvaluated=function(t,e,a){for(var i,n=0;n<t.length;n++)i=t[n],i.y_top=s.default.calcYNormal_(e,i.yval_minus,a),i.y_bottom=s.default.calcYNormal_(e,i.yval_plus,a)},a.default=l,e.exports=a.default},{"../dygraph-layout":12,"./datahandler":5}],5:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){},n=i;n.X=0,n.Y=1,n.EXTRAS=2,n.prototype.extractSeries=function(t,e,a){},n.prototype.seriesToPoints=function(t,e,a){for(var i=[],r=0;r<t.length;++r){var o=t[r],s=o[1],l=null===s?null:n.parseFloat(s),h={x:NaN,y:NaN,xval:n.parseFloat(o[0]),yval:l,name:e,idx:r+a};i.push(h)}return this.onPointsCreated_(t,i),i},n.prototype.onPointsCreated_=function(t,e){},n.prototype.rollingAverage=function(t,e,a){},n.prototype.getExtremeYValues=function(t,e,a){},n.prototype.onLineEvaluated=function(t,e,a){},n.prototype.computeYInterpolation_=function(t,e,a){var i=e[1]-t[1],n=e[0]-t[0],r=i/n,o=(a-t[0])*r;return t[1]+o},n.prototype.getIndexesInWindow_=function(t,e){var a=0,i=t.length-1;if(e){for(var n=0,r=e[0],o=e[1];n<t.length-1&&t[n][0]<r;)a++,n++;for(n=t.length-1;n>0&&t[n][0]>o;)i--,n--}return a<=i?[a,i]:[0,t.length-1]},n.parseFloat=function(t){return null===t?NaN:t},a.default=i,e.exports=a.default},{}],6:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./datahandler"),r=(i(n),t("./default")),o=i(r),s=function(){};s.prototype=new o.default,s.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s,l,h=[],u=100,d=a.get("logscale"),c=0;c<t.length;c++)i=t[c][0],r=t[c][e],d&&null!==r&&(r[0]<=0||r[1]<=0)&&(r=null),null!==r?(o=r[0],s=r[1],null===o||isNaN(o)?h.push([i,o,[o,s]]):(l=s?o/s:0,n=u*l,h.push([i,n,[o,s]]))):h.push([i,null,[null,null]]);return h},s.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n=[],r=0,o=0,s=100;for(i=0;i<t.length;i++){r+=t[i][2][0],o+=t[i][2][1],i-e>=0&&(r-=t[i-e][2][0],o-=t[i-e][2][1]);var l=t[i][0],h=o?r/o:0;n[i]=[l,s*h]}return n},a.default=s,e.exports=a.default},{"./datahandler":5,"./default":7}],7:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./datahandler"),r=i(n),o=function(){};o.prototype=new r.default,o.prototype.extractSeries=function(t,e,a){for(var i=[],n=a.get("logscale"),r=0;r<t.length;r++){var o=t[r][0],s=t[r][e];n&&s<=0&&(s=null),i.push([o,s])}return i},o.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l=[];if(1==e)return t;for(i=0;i<t.length;i++){for(o=0,s=0,n=Math.max(0,i-e+1);n<i+1;n++)r=t[n][1],null===r||isNaN(r)||(s++,o+=t[n][1]);s?l[i]=[t[i][0],o/s]:l[i]=[t[i][0],null]}return l},o.prototype.getExtremeYValues=function(t,e,a){for(var i,n=null,r=null,o=0,s=t.length-1,l=o;l<=s;l++)i=t[l][1],null===i||isNaN(i)||((null===r||i>r)&&(r=i),(null===n||i<n)&&(n=i));return[n,r]},a.default=o,e.exports=a.default},{"./datahandler":5}],8:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-utils"),o=n(r),s=t("./dygraph"),l=i(s),h=function(t,e,a,i){if(this.dygraph_=t,this.layout=i,this.element=e,this.elementContext=a,this.height=t.height_,this.width=t.width_,!o.isCanvasSupported(this.element))throw"Canvas is not supported.";if(this.area=i.getPlotArea(),!o.isAndroid()){var n=this.dygraph_.canvas_ctx_;n.beginPath(),n.rect(this.area.x,this.area.y,this.area.w,this.area.h),n.clip(),n=this.dygraph_.hidden_ctx_,n.beginPath(),n.rect(this.area.x,this.area.y,this.area.w,this.area.h),n.clip()}};h.prototype.clear=function(){this.elementContext.clearRect(0,0,this.width,this.height)},h.prototype.render=function(){this._updatePoints(),this._renderLineChart()},h._getIteratorPredicate=function(t){return t?h._predicateThatSkipsEmptyPoints:null},h._predicateThatSkipsEmptyPoints=function(t,e){return null!==t[e].yval},h._drawStyledLine=function(t,e,a,i,n,r,s){var l=t.dygraph,u=l.getBooleanOption("stepPlot",t.setName);o.isArrayLike(i)||(i=null);var d=l.getBooleanOption("drawGapEdgePoints",t.setName),c=t.points,p=t.setName,g=o.createIterator(c,0,c.length,h._getIteratorPredicate(l.getBooleanOption("connectSeparatedPoints",p))),f=i&&i.length>=2,v=t.drawingContext;v.save(),f&&v.setLineDash&&v.setLineDash(i);var _=h._drawSeries(t,g,a,s,n,d,u,e);h._drawPointsOnLine(t,_,r,e,s),f&&v.setLineDash&&v.setLineDash([]),v.restore()},h._drawSeries=function(t,e,a,i,n,r,o,s){var l,h,u=null,d=null,c=null,p=[],g=!0,f=t.drawingContext;f.beginPath(),f.strokeStyle=s,f.lineWidth=a;for(var v=e.array_,_=e.end_,y=e.predicate_,x=e.start_;x<_;x++){if(h=v[x],y){for(;x<_&&!y(v,x);)x++;if(x==_)break;h=v[x]}if(null===h.canvasy||h.canvasy!=h.canvasy)o&&null!==u&&(f.moveTo(u,d),f.lineTo(h.canvasx,d)),u=d=null;else{if(l=!1,r||!u){e.nextIdx_=x,e.next(),c=e.hasNext?e.peek.canvasy:null;var m=null===c||c!=c;l=!u&&m,r&&(!g&&!u||e.hasNext&&m)&&(l=!0)}null!==u?a&&(o&&(f.moveTo(u,d),f.lineTo(h.canvasx,d)),f.lineTo(h.canvasx,h.canvasy)):f.moveTo(h.canvasx,h.canvasy),(n||l)&&p.push([h.canvasx,h.canvasy,h.idx]),u=h.canvasx,d=h.canvasy}g=!1}return f.stroke(),p},h._drawPointsOnLine=function(t,e,a,i,n){for(var r=t.drawingContext,o=0;o<e.length;o++){var s=e[o];r.save(),a.call(t.dygraph,t.dygraph,t.setName,r,s[0],s[1],i,n,s[2]),r.restore()}},h.prototype._updatePoints=function(){for(var t=this.layout.points,e=t.length;e--;)for(var a=t[e],i=a.length;i--;){var n=a[i];n.canvasx=this.area.w*n.x+this.area.x,n.canvasy=this.area.h*n.y+this.area.y}},h.prototype._renderLineChart=function(t,e){var a,i,n=e||this.elementContext,r=this.layout.points,s=this.layout.setNames;this.colors=this.dygraph_.colorsMap_;var l=this.dygraph_.getOption("plotter"),h=l;o.isArrayLike(h)||(h=[h]);var u={};for(a=0;a<s.length;a++){i=s[a];var d=this.dygraph_.getOption("plotter",i);d!=l&&(u[i]=d)}for(a=0;a<h.length;a++)for(var c=h[a],p=a==h.length-1,g=0;g<r.length;g++)if(i=s[g],!t||i==t){var f=r[g],v=c;if(i in u){if(!p)continue;v=u[i]}var _=this.colors[i],y=this.dygraph_.getOption("strokeWidth",i);n.save(),n.strokeStyle=_,n.lineWidth=y,v({points:f,setName:i,drawingContext:n,color:_,strokeWidth:y,dygraph:this.dygraph_,axis:this.dygraph_.axisPropertiesForSeries(i),plotArea:this.area,seriesIndex:g,seriesCount:r.length,singleSeriesName:t,allSeriesPoints:r}),n.restore()}},h._Plotters={linePlotter:function(t){h._linePlotter(t)},fillPlotter:function(t){h._fillPlotter(t)},errorPlotter:function(t){h._errorPlotter(t)}},h._linePlotter=function(t){var e=t.dygraph,a=t.setName,i=t.strokeWidth,n=e.getNumericOption("strokeBorderWidth",a),r=e.getOption("drawPointCallback",a)||o.Circles.DEFAULT,s=e.getOption("strokePattern",a),l=e.getBooleanOption("drawPoints",a),u=e.getNumericOption("pointSize",a);n&&i&&h._drawStyledLine(t,e.getOption("strokeBorderColor",a),i+2*n,s,l,r,u),h._drawStyledLine(t,t.color,i,s,l,r,u)},h._errorPlotter=function(t){var e=t.dygraph,a=t.setName,i=e.getBooleanOption("errorBars")||e.getBooleanOption("customBars");if(i){var n=e.getBooleanOption("fillGraph",a);n&&console.warn("Can't use fillGraph option with error bars");var r,s=t.drawingContext,l=t.color,u=e.getNumericOption("fillAlpha",a),d=e.getBooleanOption("stepPlot",a),c=t.points,p=o.createIterator(c,0,c.length,h._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",a))),g=NaN,f=NaN,v=[-1,-1],_=o.toRGB_(l),y="rgba("+_.r+","+_.g+","+_.b+","+u+")";s.fillStyle=y,s.beginPath();for(var x=function(t){return null===t||void 0===t||isNaN(t)};p.hasNext;){var m=p.next();!d&&x(m.y)||d&&!isNaN(f)&&x(f)?g=NaN:(r=[m.y_bottom,m.y_top],d&&(f=m.y),isNaN(r[0])&&(r[0]=m.y),isNaN(r[1])&&(r[1]=m.y),r[0]=t.plotArea.h*r[0]+t.plotArea.y,r[1]=t.plotArea.h*r[1]+t.plotArea.y,isNaN(g)||(d?(s.moveTo(g,v[0]),s.lineTo(m.canvasx,v[0]),s.lineTo(m.canvasx,v[1])):(s.moveTo(g,v[0]),s.lineTo(m.canvasx,r[0]),s.lineTo(m.canvasx,r[1])),s.lineTo(g,v[1]),s.closePath()),v=r,g=m.canvasx)}s.fill()}},h._fastCanvasProxy=function(t){var e=[],a=null,i=null,n=1,r=2,o=0,s=function(t){if(!(e.length<=1)){for(var a=e.length-1;a>0;a--){var i=e[a];if(i[0]==r){var o=e[a-1];o[1]==i[1]&&o[2]==i[2]&&e.splice(a,1)}}for(var a=0;a<e.length-1;){var i=e[a];i[0]==r&&e[a+1][0]==r?e.splice(a,1):a++}if(e.length>2&&!t){var s=0;e[0][0]==r&&s++;for(var l=null,h=null,a=s;a<e.length;a++){var i=e[a];if(i[0]==n)if(null===l&&null===h)l=a,h=a;else{var u=i[2];u<e[l][2]?l=a:u>e[h][2]&&(h=a)}}var d=e[l],c=e[h];e.splice(s,e.length-s),l<h?(e.push(d),e.push(c)):l>h?(e.push(c),e.push(d)):e.push(d)}}},l=function(a){s(a);for(var l=0,h=e.length;l<h;l++){var u=e[l];u[0]==n?t.lineTo(u[1],u[2]):u[0]==r&&t.moveTo(u[1],u[2])}e.length&&(i=e[e.length-1][1]),o+=e.length,e=[]},h=function(t,n,r){var o=Math.round(n);if(null===a||o!=a){var s=a-i>1,h=o-a>1,u=s||h;l(u),a=o}e.push([t,n,r])};return{moveTo:function(t,e){h(r,t,e)},lineTo:function(t,e){h(n,t,e)},stroke:function(){l(!0),t.stroke()},fill:function(){l(!0),t.fill()},beginPath:function(){l(!0),t.beginPath()},closePath:function(){l(!0),t.closePath()},_count:function(){return o}}},h._fillPlotter=function(t){if(!t.singleSeriesName&&0===t.seriesIndex){for(var e=t.dygraph,a=e.getLabels().slice(1),i=a.length;i>=0;i--)e.visibility()[i]||a.splice(i,1);var n=function(){for(var t=0;t<a.length;t++)if(e.getBooleanOption("fillGraph",a[t]))return!0;return!1}();if(n)for(var r,s,u=t.plotArea,d=t.allSeriesPoints,c=d.length,p=e.getBooleanOption("stackedGraph"),g=e.getColors(),f={},v=function(t,e,a,i){if(t.lineTo(e,a),p)for(var n=i.length-1;n>=0;n--){var r=i[n];t.lineTo(r[0],r[1])}},_=c-1;_>=0;_--){var y=t.drawingContext,x=a[_];if(e.getBooleanOption("fillGraph",x)){var m=e.getNumericOption("fillAlpha",x),b=e.getBooleanOption("stepPlot",x),w=g[_],A=e.axisPropertiesForSeries(x),O=1+A.minyval*A.yscale;O<0?O=0:O>1&&(O=1),O=u.h*O+u.y;var D,S=d[_],T=o.createIterator(S,0,S.length,h._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",x))),P=NaN,L=[-1,-1],E=o.toRGB_(w),C="rgba("+E.r+","+E.g+","+E.b+","+m+")";y.fillStyle=C,y.beginPath();var M,k=!0;(S.length>2*e.width_||l.default.FORCE_FAST_PROXY)&&(y=h._fastCanvasProxy(y));for(var N,F=[];T.hasNext;)if(N=T.next(),o.isOK(N.y)||b){if(p){if(!k&&M==N.xval)continue;k=!1,M=N.xval,r=f[N.canvasx];var R;R=void 0===r?O:s?r[0]:r,D=[N.canvasy,R],b?L[0]===-1?f[N.canvasx]=[N.canvasy,O]:f[N.canvasx]=[N.canvasy,L[0]]:f[N.canvasx]=N.canvasy}else D=isNaN(N.canvasy)&&b?[u.y+u.h,O]:[N.canvasy,O];isNaN(P)?(y.moveTo(N.canvasx,D[1]),y.lineTo(N.canvasx,D[0])):(b?(y.lineTo(N.canvasx,L[0]),y.lineTo(N.canvasx,D[0])):y.lineTo(N.canvasx,D[0]),p&&(F.push([P,L[1]]),s&&r?F.push([N.canvasx,r[1]]):F.push([N.canvasx,D[1]]))),L=D,P=N.canvasx}else v(y,P,L[1],F),F=[],P=NaN,null===N.y_stacked||isNaN(N.y_stacked)||(f[N.canvasx]=u.h*N.y_stacked+u.y);s=b,D&&N&&(v(y,N.canvasx,D[1],F),F=[]),y.fill()}}}},a.default=h,e.exports=a.default},{"./dygraph":17,"./dygraph-utils":16}],9:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-tickers"),o=n(r),s=t("./dygraph-interaction-model"),l=i(s),h=t("./dygraph-canvas"),u=i(h),d=t("./dygraph-utils"),c=n(d),p={highlightCircleSize:3,highlightSeriesOpts:null,highlightSeriesBackgroundAlpha:.5,highlightSeriesBackgroundColor:"rgb(255, 255, 255)",labelsDivWidth:250,labelsDivStyles:{},labelsSeparateLines:!1,labelsShowZeroValues:!0,labelsKMB:!1,labelsKMG2:!1,showLabelsOnHighlight:!0,digitsAfterDecimal:2,maxNumberWidth:6,sigFigs:null,strokeWidth:1,strokeBorderWidth:0,strokeBorderColor:"white",axisTickSize:3,axisLabelFontSize:14,rightGap:5,showRoller:!1,xValueParser:void 0,delimiter:",",sigma:2,errorBars:!1,fractions:!1,wilsonInterval:!0,customBars:!1,fillGraph:!1,fillAlpha:.15,connectSeparatedPoints:!1,stackedGraph:!1,stackedGraphNaNFill:"all",hideOverlayOnMouseOut:!0,legend:"onmouseover",stepPlot:!1,avoidMinZero:!1,xRangePad:0,yRangePad:null,drawAxesAtZero:!1,titleHeight:28,xLabelHeight:18,yLabelWidth:18,axisLineColor:"black",axisLineWidth:.3,gridLineWidth:.3,axisLabelColor:"black",axisLabelWidth:50,gridLineColor:"rgb(128,128,128)",interactionModel:l.default.defaultModel,animatedZooms:!1,showRangeSelector:!1,rangeSelectorHeight:40,rangeSelectorPlotStrokeColor:"#808FAB",rangeSelectorPlotFillGradientColor:"white",rangeSelectorPlotFillColor:"#A7B1C4",rangeSelectorBackgroundStrokeColor:"gray",rangeSelectorBackgroundLineWidth:1,rangeSelectorPlotLineWidth:1.5,rangeSelectorForegroundStrokeColor:"black",rangeSelectorForegroundLineWidth:1,rangeSelectorAlpha:.6,showInRangeSelector:null,plotter:[u.default._fillPlotter,u.default._errorPlotter,u.default._linePlotter],plugins:[],axes:{x:{pixelsPerLabel:70,axisLabelWidth:60,axisLabelFormatter:c.dateAxisLabelFormatter,valueFormatter:c.dateValueFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:o.dateTicker},y:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:c.numberValueFormatter,axisLabelFormatter:c.numberAxisLabelFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:o.numericTicks},y2:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:c.numberValueFormatter,axisLabelFormatter:c.numberAxisLabelFormatter,drawAxis:!0,drawGrid:!1,independentTicks:!1,ticker:o.numericTicks}}};a.default=p,e.exports=a.default},{"./dygraph-canvas":8,"./dygraph-interaction-model":11,"./dygraph-tickers":15,"./dygraph-utils":16}],10:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./dygraph"),r=i(n),o=function(t){this.container=t};o.prototype.draw=function(t,e){this.container.innerHTML="","undefined"!=typeof this.date_graph&&this.date_graph.destroy(),this.date_graph=new r.default(this.container,t,e)},o.prototype.setSelection=function(t){var e=!1;t.length&&(e=t[0].row),this.date_graph.setSelection(e)},o.prototype.getSelection=function(){var t=[],e=this.date_graph.getSelection();if(e<0)return t;for(var a=this.date_graph.layout_.points,i=0;i<a.length;++i)t.push({row:e,column:i+1});return t},a.default=o,e.exports=a.default},{"./dygraph":17}],11:[function(t,e,a){"use strict";function i(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./dygraph-utils"),r=i(n),o=100,s={};s.maybeTreatMouseOpAsClick=function(t,e,a){a.dragEndX=r.dragGetX_(t,a),a.dragEndY=r.dragGetY_(t,a);var i=Math.abs(a.dragEndX-a.dragStartX),n=Math.abs(a.dragEndY-a.dragStartY);i<2&&n<2&&void 0!==e.lastx_&&e.lastx_!=-1&&s.treatMouseOpAsClick(e,t,a),a.regionWidth=i,a.regionHeight=n},s.startPan=function(t,e,a){var i,n;a.isPanning=!0;var o=e.xAxisRange();if(e.getOptionForAxis("logscale","x")?(a.initialLeftmostDate=r.log10(o[0]),a.dateRange=r.log10(o[1])-r.log10(o[0])):(a.initialLeftmostDate=o[0],a.dateRange=o[1]-o[0]),a.xUnitsPerPixel=a.dateRange/(e.plotter_.area.w-1),e.getNumericOption("panEdgeFraction")){var s=e.width_*e.getNumericOption("panEdgeFraction"),l=e.xAxisExtremes(),h=e.toDomXCoord(l[0])-s,u=e.toDomXCoord(l[1])+s,d=e.toDataXCoord(h),c=e.toDataXCoord(u);a.boundedDates=[d,c];var p=[],g=e.height_*e.getNumericOption("panEdgeFraction");for(i=0;i<e.axes_.length;i++){n=e.axes_[i];var f=n.extremeRange,v=e.toDomYCoord(f[0],i)+g,_=e.toDomYCoord(f[1],i)-g,y=e.toDataYCoord(v,i),x=e.toDataYCoord(_,i);p[i]=[y,x]}a.boundedValues=p}for(a.is2DPan=!1,a.axes=[],i=0;i<e.axes_.length;i++){n=e.axes_[i];var m={},b=e.yAxisRange(i),w=e.attributes_.getForAxis("logscale",i);w?(m.initialTopValue=r.log10(b[1]),m.dragValueRange=r.log10(b[1])-r.log10(b[0])):(m.initialTopValue=b[1],m.dragValueRange=b[1]-b[0]),m.unitsPerPixel=m.dragValueRange/(e.plotter_.area.h-1),a.axes.push(m),(n.valueWindow||n.valueRange)&&(a.is2DPan=!0)}},s.movePan=function(t,e,a){a.dragEndX=r.dragGetX_(t,a),a.dragEndY=r.dragGetY_(t,a);var i=a.initialLeftmostDate-(a.dragEndX-a.dragStartX)*a.xUnitsPerPixel;a.boundedDates&&(i=Math.max(i,a.boundedDates[0]));var n=i+a.dateRange;if(a.boundedDates&&n>a.boundedDates[1]&&(i-=n-a.boundedDates[1],n=i+a.dateRange),e.getOptionForAxis("logscale","x")?e.dateWindow_=[Math.pow(r.LOG_SCALE,i),Math.pow(r.LOG_SCALE,n)]:e.dateWindow_=[i,n],a.is2DPan)for(var o=a.dragEndY-a.dragStartY,s=0;s<e.axes_.length;s++){var l=e.axes_[s],h=a.axes[s],u=o*h.unitsPerPixel,d=a.boundedValues?a.boundedValues[s]:null,c=h.initialTopValue+u;d&&(c=Math.min(c,d[1]));var p=c-h.dragValueRange;d&&p<d[0]&&(c-=p-d[0],p=c-h.dragValueRange),e.attributes_.getForAxis("logscale",s)?l.valueWindow=[Math.pow(r.LOG_SCALE,p),Math.pow(r.LOG_SCALE,c)]:l.valueWindow=[p,c]}e.drawGraph_(!1)},s.endPan=s.maybeTreatMouseOpAsClick,s.startZoom=function(t,e,a){a.isZooming=!0,a.zoomMoved=!1},s.moveZoom=function(t,e,a){a.zoomMoved=!0,a.dragEndX=r.dragGetX_(t,a),a.dragEndY=r.dragGetY_(t,a);var i=Math.abs(a.dragStartX-a.dragEndX),n=Math.abs(a.dragStartY-a.dragEndY);a.dragDirection=i<n/2?r.VERTICAL:r.HORIZONTAL,e.drawZoomRect_(a.dragDirection,a.dragStartX,a.dragEndX,a.dragStartY,a.dragEndY,a.prevDragDirection,a.prevEndX,a.prevEndY),a.prevEndX=a.dragEndX,a.prevEndY=a.dragEndY,a.prevDragDirection=a.dragDirection},s.treatMouseOpAsClick=function(t,e,a){for(var i=t.getFunctionOption("clickCallback"),n=t.getFunctionOption("pointClickCallback"),r=null,o=-1,s=Number.MAX_VALUE,l=0;l<t.selPoints_.length;l++){var h=t.selPoints_[l],u=Math.pow(h.canvasx-a.dragEndX,2)+Math.pow(h.canvasy-a.dragEndY,2);!isNaN(u)&&(o==-1||u<s)&&(s=u,o=l)}var d=t.getNumericOption("highlightCircleSize")+2;if(s<=d*d&&(r=t.selPoints_[o]),r){var c={cancelable:!0,point:r,canvasx:a.dragEndX,canvasy:a.dragEndY},p=t.cascadeEvents_("pointClick",c);if(p)return;n&&n.call(t,e,r)}var c={cancelable:!0,xval:t.lastx_,pts:t.selPoints_,canvasx:a.dragEndX,canvasy:a.dragEndY};t.cascadeEvents_("click",c)||i&&i.call(t,e,t.lastx_,t.selPoints_)},s.endZoom=function(t,e,a){e.clearZoomRect_(),a.isZooming=!1,s.maybeTreatMouseOpAsClick(t,e,a);var i=e.getArea();if(a.regionWidth>=10&&a.dragDirection==r.HORIZONTAL){var n=Math.min(a.dragStartX,a.dragEndX),o=Math.max(a.dragStartX,a.dragEndX);n=Math.max(n,i.x),o=Math.min(o,i.x+i.w),n<o&&e.doZoomX_(n,o),a.cancelNextDblclick=!0}else if(a.regionHeight>=10&&a.dragDirection==r.VERTICAL){var l=Math.min(a.dragStartY,a.dragEndY),h=Math.max(a.dragStartY,a.dragEndY);l=Math.max(l,i.y),h=Math.min(h,i.y+i.h),l<h&&e.doZoomY_(l,h),a.cancelNextDblclick=!0}a.dragStartX=null,a.dragStartY=null},s.startTouch=function(t,e,a){t.preventDefault(),t.touches.length>1&&(a.startTimeForDoubleTapMs=null);for(var i=[],n=0;n<t.touches.length;n++){var r=t.touches[n];i.push({pageX:r.pageX,pageY:r.pageY,dataX:e.toDataXCoord(r.pageX),dataY:e.toDataYCoord(r.pageY)})}if(a.initialTouches=i,1==i.length)a.initialPinchCenter=i[0],a.touchDirections={x:!0,y:!0};else if(i.length>=2){a.initialPinchCenter={pageX:.5*(i[0].pageX+i[1].pageX),pageY:.5*(i[0].pageY+i[1].pageY),dataX:.5*(i[0].dataX+i[1].dataX),dataY:.5*(i[0].dataY+i[1].dataY)};var o=180/Math.PI*Math.atan2(a.initialPinchCenter.pageY-i[0].pageY,i[0].pageX-a.initialPinchCenter.pageX);o=Math.abs(o),o>90&&(o=90-o),a.touchDirections={x:o<67.5,y:o>22.5}}a.initialRange={x:e.xAxisRange(),y:e.yAxisRange()}},s.moveTouch=function(t,e,a){a.startTimeForDoubleTapMs=null;var i,n=[];for(i=0;i<t.touches.length;i++){var r=t.touches[i];n.push({pageX:r.pageX,pageY:r.pageY})}var o,s=a.initialTouches,l=a.initialPinchCenter;o=1==n.length?n[0]:{pageX:.5*(n[0].pageX+n[1].pageX),pageY:.5*(n[0].pageY+n[1].pageY)};var h={pageX:o.pageX-l.pageX,pageY:o.pageY-l.pageY},u=a.initialRange.x[1]-a.initialRange.x[0],d=a.initialRange.y[0]-a.initialRange.y[1];h.dataX=h.pageX/e.plotter_.area.w*u,h.dataY=h.pageY/e.plotter_.area.h*d;var c,p;if(1==n.length)c=1,p=1;else if(n.length>=2){var g=s[1].pageX-l.pageX;c=(n[1].pageX-o.pageX)/g;var f=s[1].pageY-l.pageY;p=(n[1].pageY-o.pageY)/f}c=Math.min(8,Math.max(.125,c)),p=Math.min(8,Math.max(.125,p));var v=!1;if(a.touchDirections.x&&(e.dateWindow_=[l.dataX-h.dataX+(a.initialRange.x[0]-l.dataX)/c,l.dataX-h.dataX+(a.initialRange.x[1]-l.dataX)/c],v=!0),a.touchDirections.y)for(i=0;i<1;i++){var _=e.axes_[i],y=e.attributes_.getForAxis("logscale",i);y||(_.valueWindow=[l.dataY-h.dataY+(a.initialRange.y[0]-l.dataY)/p,l.dataY-h.dataY+(a.initialRange.y[1]-l.dataY)/p],v=!0)}if(e.drawGraph_(!1),v&&n.length>1&&e.getFunctionOption("zoomCallback")){var x=e.xAxisRange();e.getFunctionOption("zoomCallback").call(e,x[0],x[1],e.yAxisRanges())}},s.endTouch=function(t,e,a){if(0!==t.touches.length)s.startTouch(t,e,a);else if(1==t.changedTouches.length){var i=(new Date).getTime(),n=t.changedTouches[0];a.startTimeForDoubleTapMs&&i-a.startTimeForDoubleTapMs<500&&a.doubleTapX&&Math.abs(a.doubleTapX-n.screenX)<50&&a.doubleTapY&&Math.abs(a.doubleTapY-n.screenY)<50?e.resetZoom():(a.startTimeForDoubleTapMs=i,a.doubleTapX=n.screenX,a.doubleTapY=n.screenY)}};var l=function(t,e,a){return t<e?e-t:t>a?t-a:0},h=function(t,e){var a=r.findPos(e.canvas_),i={left:a.x,right:a.x+e.canvas_.offsetWidth,top:a.y,bottom:a.y+e.canvas_.offsetHeight},n={x:r.pageX(t),y:r.pageY(t)},o=l(n.x,i.left,i.right),s=l(n.y,i.top,i.bottom);return Math.max(o,s)};s.defaultModel={mousedown:function(t,e,a){if(!t.button||2!=t.button){a.initializeMouseDown(t,e,a),t.altKey||t.shiftKey?s.startPan(t,e,a):s.startZoom(t,e,a);var i=function(t){if(a.isZooming){var i=h(t,e);i<o?s.moveZoom(t,e,a):null!==a.dragEndX&&(a.dragEndX=null,a.dragEndY=null,e.clearZoomRect_())}else a.isPanning&&s.movePan(t,e,a)},n=function t(n){a.isZooming?null!==a.dragEndX?s.endZoom(n,e,a):s.maybeTreatMouseOpAsClick(n,e,a):a.isPanning&&s.endPan(n,e,a),r.removeEvent(document,"mousemove",i),r.removeEvent(document,"mouseup",t),a.destroy()};e.addAndTrackEvent(document,"mousemove",i),e.addAndTrackEvent(document,"mouseup",n)}},willDestroyContextMyself:!0,touchstart:function(t,e,a){s.startTouch(t,e,a)},touchmove:function(t,e,a){s.moveTouch(t,e,a)},touchend:function(t,e,a){s.endTouch(t,e,a)},dblclick:function(t,e,a){if(a.cancelNextDblclick)return void(a.cancelNextDblclick=!1);var i={canvasx:a.dragEndX,canvasy:a.dragEndY};e.cascadeEvents_("dblclick",i)||t.altKey||t.shiftKey||e.resetZoom()}},s.nonInteractiveModel_={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a)},mouseup:s.maybeTreatMouseOpAsClick},s.dragIsPanInteractionModel={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a),s.startPan(t,e,a)},mousemove:function(t,e,a){a.isPanning&&s.movePan(t,e,a)},mouseup:function(t,e,a){a.isPanning&&s.endPan(t,e,a)}},a.default=s,e.exports=a.default},{"./dygraph-utils":16}],12:[function(t,e,a){"use strict";function i(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./dygraph-utils"),r=i(n),o=function(t){this.dygraph_=t,this.points=[],this.setNames=[],this.annotations=[],this.yAxes_=null,this.xTicks_=null,this.yTicks_=null};o.prototype.addDataset=function(t,e){this.points.push(e),this.setNames.push(t)},o.prototype.getPlotArea=function(){return this.area_},o.prototype.computePlotArea=function(){var t={x:0,y:0};t.w=this.dygraph_.width_-t.x-this.dygraph_.getOption("rightGap"),t.h=this.dygraph_.height_;var e={chart_div:this.dygraph_.graphDiv,reserveSpaceLeft:function(e){var a={x:t.x,y:t.y,w:e,h:t.h};return t.x+=e,t.w-=e,a},reserveSpaceRight:function(e){var a={x:t.x+t.w-e,y:t.y,w:e,h:t.h};return t.w-=e,a},reserveSpaceTop:function(e){var a={x:t.x,y:t.y,w:t.w,h:e};return t.y+=e,t.h-=e,a},reserveSpaceBottom:function(e){var a={x:t.x,y:t.y+t.h-e,w:t.w,h:e};return t.h-=e,a},chartRect:function(){return{x:t.x,y:t.y,w:t.w,h:t.h}}};this.dygraph_.cascadeEvents_("layout",e),this.area_=t},o.prototype.setAnnotations=function(t){this.annotations=[];for(var e=this.dygraph_.getOption("xValueParser")||function(t){return t},a=0;a<t.length;a++){var i={};if(!t[a].xval&&void 0===t[a].x)return void console.error("Annotations must have an 'x' property");if(t[a].icon&&(!t[a].hasOwnProperty("width")||!t[a].hasOwnProperty("height")))return void console.error("Must set width and height when setting annotation.icon property");r.update(i,t[a]),i.xval||(i.xval=e(i.x)),this.annotations.push(i)}},o.prototype.setXTicks=function(t){this.xTicks_=t},o.prototype.setYAxes=function(t){this.yAxes_=t},o.prototype.evaluate=function(){this._xAxis={},this._evaluateLimits(),this._evaluateLineCharts(),this._evaluateLineTicks(),this._evaluateAnnotations()},o.prototype._evaluateLimits=function(){var t=this.dygraph_.xAxisRange();this._xAxis.minval=t[0],this._xAxis.maxval=t[1];var e=t[1]-t[0];this._xAxis.scale=0!==e?1/e:1,this.dygraph_.getOptionForAxis("logscale","x")&&(this._xAxis.xlogrange=r.log10(this._xAxis.maxval)-r.log10(this._xAxis.minval),this._xAxis.xlogscale=0!==this._xAxis.xlogrange?1/this._xAxis.xlogrange:1);for(var a=0;a<this.yAxes_.length;a++){var i=this.yAxes_[a];i.minyval=i.computedValueRange[0],i.maxyval=i.computedValueRange[1],i.yrange=i.maxyval-i.minyval,i.yscale=0!==i.yrange?1/i.yrange:1,this.dygraph_.getOption("logscale")&&(i.ylogrange=r.log10(i.maxyval)-r.log10(i.minyval),i.ylogscale=0!==i.ylogrange?1/i.ylogrange:1,isFinite(i.ylogrange)&&!isNaN(i.ylogrange)||console.error("axis "+a+" of graph at "+i.g+" can't be displayed in log scale for range ["+i.minyval+" - "+i.maxyval+"]"))}},o.calcXNormal_=function(t,e,a){return a?(r.log10(t)-r.log10(e.minval))*e.xlogscale:(t-e.minval)*e.scale},o.calcYNormal_=function(t,e,a){if(a){var i=1-(r.log10(e)-r.log10(t.minyval))*t.ylogscale;return isFinite(i)?i:NaN}return 1-(e-t.minyval)*t.yscale},o.prototype._evaluateLineCharts=function(){for(var t=this.dygraph_.getOption("stackedGraph"),e=this.dygraph_.getOptionForAxis("logscale","x"),a=0;a<this.points.length;a++){for(var i=this.points[a],n=this.setNames[a],r=this.dygraph_.getOption("connectSeparatedPoints",n),s=this.dygraph_.axisPropertiesForSeries(n),l=this.dygraph_.attributes_.getForSeries("logscale",n),h=0;h<i.length;h++){var u=i[h];u.x=o.calcXNormal_(u.xval,this._xAxis,e);var d=u.yval;t&&(u.y_stacked=o.calcYNormal_(s,u.yval_stacked,l),null===d||isNaN(d)||(d=u.yval_stacked)),null===d&&(d=NaN,r||(u.yval=NaN)),u.y=o.calcYNormal_(s,d,l)}this.dygraph_.dataHandler_.onLineEvaluated(i,s,l)}},o.prototype._evaluateLineTicks=function(){var t,e,a,i;for(this.xticks=[],t=0;t<this.xTicks_.length;t++)e=this.xTicks_[t],a=e.label,i=this.dygraph_.toPercentXCoord(e.v),i>=0&&i<1&&this.xticks.push([i,a]);for(this.yticks=[],t=0;t<this.yAxes_.length;t++)for(var n=this.yAxes_[t],r=0;r<n.ticks.length;r++)e=n.ticks[r],a=e.label,i=this.dygraph_.toPercentYCoord(e.v,t),i>0&&i<=1&&this.yticks.push([t,i,a])},o.prototype._evaluateAnnotations=function(){var t,e={};for(t=0;t<this.annotations.length;t++){var a=this.annotations[t];e[a.xval+","+a.series]=a}if(this.annotated_points=[],this.annotations&&this.annotations.length)for(var i=0;i<this.points.length;i++){var n=this.points[i];for(t=0;t<n.length;t++){var r=n[t],o=r.xval+","+r.name;o in e&&(r.annotation=e[o],this.annotated_points.push(r))}}},o.prototype.removeAllDatasets=function(){delete this.points,delete this.setNames,delete this.setPointsLengths,delete this.setPointsOffsets,this.points=[],this.setNames=[],this.setPointsLengths=[],this.setPointsOffsets=[]},a.default=o,e.exports=a.default},{"./dygraph-utils":16
+}],13:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=null;a.default=i,e.exports=a.default},{}],14:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-utils"),o=n(r),s=t("./dygraph-default-attrs"),l=i(s),h=t("./dygraph-options-reference"),u=(i(h),function(t){this.dygraph_=t,this.yAxes_=[],this.xAxis_={},this.series_={},this.global_=this.dygraph_.attrs_,this.user_=this.dygraph_.user_attrs_||{},this.labels_=[],this.highlightSeries_=this.get("highlightSeriesOpts")||{},this.reparseSeries()});u.AXIS_STRING_MAPPINGS_={y:0,Y:0,y1:0,Y1:0,y2:1,Y2:1},u.axisToIndex_=function(t){if("string"==typeof t){if(u.AXIS_STRING_MAPPINGS_.hasOwnProperty(t))return u.AXIS_STRING_MAPPINGS_[t];throw"Unknown axis : "+t}if("number"==typeof t){if(0===t||1===t)return t;throw"Dygraphs only supports two y-axes, indexed from 0-1."}if(t)throw"Unknown axis : "+t;return 0},u.prototype.reparseSeries=function(){var t=this.get("labels");if(t){this.labels_=t.slice(1),this.yAxes_=[{series:[],options:{}}],this.xAxis_={options:{}},this.series_={};for(var e=this.user_.series||{},a=0;a<this.labels_.length;a++){var i=this.labels_[a],n=e[i]||{},r=u.axisToIndex_(n.axis);this.series_[i]={idx:a,yAxis:r,options:n},this.yAxes_[r]?this.yAxes_[r].series.push(i):this.yAxes_[r]={series:[i],options:{}}}var s=this.user_.axes||{};o.update(this.yAxes_[0].options,s.y||{}),this.yAxes_.length>1&&o.update(this.yAxes_[1].options,s.y2||{}),o.update(this.xAxis_.options,s.x||{})}},u.prototype.get=function(t){var e=this.getGlobalUser_(t);return null!==e?e:this.getGlobalDefault_(t)},u.prototype.getGlobalUser_=function(t){return this.user_.hasOwnProperty(t)?this.user_[t]:null},u.prototype.getGlobalDefault_=function(t){return this.global_.hasOwnProperty(t)?this.global_[t]:l.default.hasOwnProperty(t)?l.default[t]:null},u.prototype.getForAxis=function(t,e){var a,i;if("number"==typeof e)a=e,i=0===a?"y":"y2";else{if("y1"==e&&(e="y"),"y"==e)a=0;else if("y2"==e)a=1;else{if("x"!=e)throw"Unknown axis "+e;a=-1}i=e}var n=a==-1?this.xAxis_:this.yAxes_[a];if(n){var r=n.options;if(r.hasOwnProperty(t))return r[t]}if("x"!==e||"logscale"!==t){var o=this.getGlobalUser_(t);if(null!==o)return o}var s=l.default.axes[i];return s.hasOwnProperty(t)?s[t]:this.getGlobalDefault_(t)},u.prototype.getForSeries=function(t,e){if(e===this.dygraph_.getHighlightSeries()&&this.highlightSeries_.hasOwnProperty(t))return this.highlightSeries_[t];if(!this.series_.hasOwnProperty(e))throw"Unknown series: "+e;var a=this.series_[e],i=a.options;return i.hasOwnProperty(t)?i[t]:this.getForAxis(t,a.yAxis)},u.prototype.numAxes=function(){return this.yAxes_.length},u.prototype.axisForSeries=function(t){return this.series_[t].yAxis},u.prototype.axisOptions=function(t){return this.yAxes_[t].options},u.prototype.seriesForAxis=function(t){return this.yAxes_[t].series},u.prototype.seriesNames=function(){return this.labels_};a.default=u,e.exports=a.default},{"./dygraph-default-attrs":9,"./dygraph-options-reference":13,"./dygraph-utils":16}],15:[function(t,e,a){"use strict";function i(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./dygraph-utils"),r=i(n),o=function(t,e,a,i,n,r){var o=function(t){return"logscale"!==t&&i(t)};return s(t,e,a,o,n,r)};a.numericLinearTicks=o;var s=function(t,e,a,i,n,o){var s,l,h,u,d=i("pixelsPerLabel"),p=[];if(o)for(s=0;s<o.length;s++)p.push({v:o[s]});else{if(i("logscale")){u=Math.floor(a/d);var g=r.binarySearch(t,c,1),f=r.binarySearch(e,c,-1);g==-1&&(g=0),f==-1&&(f=c.length-1);var v=null;if(f-g>=u/4){for(var _=f;_>=g;_--){var y=c[_],x=Math.log(y/t)/Math.log(e/t)*a,m={v:y};null===v?v={tickValue:y,pixel_coord:x}:Math.abs(x-v.pixel_coord)>=d?v={tickValue:y,pixel_coord:x}:m.label="",p.push(m)}p.reverse()}}if(0===p.length){var b,w,A=i("labelsKMG2");A?(b=[1,2,4,8,16,32,64,128,256],w=16):(b=[1,2,5,10,20,50,100],w=10);var O,D,S,T,P=Math.ceil(a/d),L=Math.abs(e-t)/P,E=Math.floor(Math.log(L)/Math.log(w)),C=Math.pow(w,E);for(l=0;l<b.length&&(O=C*b[l],D=Math.floor(t/O)*O,S=Math.ceil(e/O)*O,u=Math.abs(S-D)/O,T=a/u,!(T>d));l++);for(D>S&&(O*=-1),s=0;s<=u;s++)h=D+s*O,p.push({v:h})}}var M=i("axisLabelFormatter");for(s=0;s<p.length;s++)void 0===p[s].label&&(p[s].label=M.call(n,p[s].v,0,i,n));return p};a.numericTicks=s;var l=function(t,e,a,i,n,r){var o=p(t,e,a,i);return o>=0?f(t,e,o,i,n):[]};a.dateTicker=l;var h={SECONDLY:0,TWO_SECONDLY:1,FIVE_SECONDLY:2,TEN_SECONDLY:3,THIRTY_SECONDLY:4,MINUTELY:5,TWO_MINUTELY:6,FIVE_MINUTELY:7,TEN_MINUTELY:8,THIRTY_MINUTELY:9,HOURLY:10,TWO_HOURLY:11,SIX_HOURLY:12,DAILY:13,TWO_DAILY:14,WEEKLY:15,MONTHLY:16,QUARTERLY:17,BIANNUAL:18,ANNUAL:19,DECADAL:20,CENTENNIAL:21,NUM_GRANULARITIES:22};a.Granularity=h;var u={DATEFIELD_Y:0,DATEFIELD_M:1,DATEFIELD_D:2,DATEFIELD_HH:3,DATEFIELD_MM:4,DATEFIELD_SS:5,DATEFIELD_MS:6,NUM_DATEFIELDS:7},d=[];d[h.SECONDLY]={datefield:u.DATEFIELD_SS,step:1,spacing:1e3},d[h.TWO_SECONDLY]={datefield:u.DATEFIELD_SS,step:2,spacing:2e3},d[h.FIVE_SECONDLY]={datefield:u.DATEFIELD_SS,step:5,spacing:5e3},d[h.TEN_SECONDLY]={datefield:u.DATEFIELD_SS,step:10,spacing:1e4},d[h.THIRTY_SECONDLY]={datefield:u.DATEFIELD_SS,step:30,spacing:3e4},d[h.MINUTELY]={datefield:u.DATEFIELD_MM,step:1,spacing:6e4},d[h.TWO_MINUTELY]={datefield:u.DATEFIELD_MM,step:2,spacing:12e4},d[h.FIVE_MINUTELY]={datefield:u.DATEFIELD_MM,step:5,spacing:3e5},d[h.TEN_MINUTELY]={datefield:u.DATEFIELD_MM,step:10,spacing:6e5},d[h.THIRTY_MINUTELY]={datefield:u.DATEFIELD_MM,step:30,spacing:18e5},d[h.HOURLY]={datefield:u.DATEFIELD_HH,step:1,spacing:36e5},d[h.TWO_HOURLY]={datefield:u.DATEFIELD_HH,step:2,spacing:72e5},d[h.SIX_HOURLY]={datefield:u.DATEFIELD_HH,step:6,spacing:216e5},d[h.DAILY]={datefield:u.DATEFIELD_D,step:1,spacing:864e5},d[h.TWO_DAILY]={datefield:u.DATEFIELD_D,step:2,spacing:1728e5},d[h.WEEKLY]={datefield:u.DATEFIELD_D,step:7,spacing:6048e5},d[h.MONTHLY]={datefield:u.DATEFIELD_M,step:1,spacing:2629817280},d[h.QUARTERLY]={datefield:u.DATEFIELD_M,step:3,spacing:216e5*365.2524},d[h.BIANNUAL]={datefield:u.DATEFIELD_M,step:6,spacing:432e5*365.2524},d[h.ANNUAL]={datefield:u.DATEFIELD_Y,step:1,spacing:864e5*365.2524},d[h.DECADAL]={datefield:u.DATEFIELD_Y,step:10,spacing:315578073600},d[h.CENTENNIAL]={datefield:u.DATEFIELD_Y,step:100,spacing:3155780736e3};var c=function(){for(var t=[],e=-39;e<=39;e++)for(var a=Math.pow(10,e),i=1;i<=9;i++){var n=a*i;t.push(n)}return t}(),p=function(t,e,a,i){for(var n=i("pixelsPerLabel"),r=0;r<h.NUM_GRANULARITIES;r++){var o=g(t,e,r);if(a/o>=n)return r}return-1},g=function(t,e,a){var i=d[a].spacing;return Math.round(1*(e-t)/i)},f=function(t,e,a,i,n){var o=i("axisLabelFormatter"),s=i("labelsUTC"),l=s?r.DateAccessorsUTC:r.DateAccessorsLocal,c=d[a].datefield,p=d[a].step,g=d[a].spacing,f=new Date(t),v=[];v[u.DATEFIELD_Y]=l.getFullYear(f),v[u.DATEFIELD_M]=l.getMonth(f),v[u.DATEFIELD_D]=l.getDate(f),v[u.DATEFIELD_HH]=l.getHours(f),v[u.DATEFIELD_MM]=l.getMinutes(f),v[u.DATEFIELD_SS]=l.getSeconds(f),v[u.DATEFIELD_MS]=l.getMilliseconds(f);var _=v[c]%p;a==h.WEEKLY&&(_=l.getDay(f)),v[c]-=_;for(var y=c+1;y<u.NUM_DATEFIELDS;y++)v[y]=y===u.DATEFIELD_D?1:0;var x=[],m=l.makeDate.apply(null,v),b=m.getTime();if(a<=h.HOURLY)for(b<t&&(b+=g,m=new Date(b));b<=e;)x.push({v:b,label:o.call(n,m,a,i,n)}),b+=g,m=new Date(b);else for(b<t&&(v[c]+=p,m=l.makeDate.apply(null,v),b=m.getTime());b<=e;)(a>=h.DAILY||l.getHours(m)%p===0)&&x.push({v:b,label:o.call(n,m,a,i,n)}),v[c]+=p,m=l.makeDate.apply(null,v),b=m.getTime();return x};a.getDateAxis=f},{"./dygraph-utils":16}],16:[function(t,e,a){"use strict";function i(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}function n(t,e,a){t.removeEventListener(e,a,!1)}function r(t){return t=t?t:window.event,t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),t.cancelBubble=!0,t.cancel=!0,t.returnValue=!1,!1}function o(t,e,a){var i,n,r;if(0===e)i=a,n=a,r=a;else{var o=Math.floor(6*t),s=6*t-o,l=a*(1-e),h=a*(1-e*s),u=a*(1-e*(1-s));switch(o){case 1:i=h,n=a,r=l;break;case 2:i=l,n=a,r=u;break;case 3:i=l,n=h,r=a;break;case 4:i=u,n=l,r=a;break;case 5:i=a,n=l,r=h;break;case 6:case 0:i=a,n=u,r=l}}return i=Math.floor(255*i+.5),n=Math.floor(255*n+.5),r=Math.floor(255*r+.5),"rgb("+i+","+n+","+r+")"}function s(t){var e=t.getBoundingClientRect(),a=window,i=document.documentElement;return{x:e.left+(a.pageXOffset||i.scrollLeft),y:e.top+(a.pageYOffset||i.scrollTop)}}function l(t){return!t.pageX||t.pageX<0?0:t.pageX}function h(t){return!t.pageY||t.pageY<0?0:t.pageY}function u(t,e){return l(t)-e.px}function d(t,e){return h(t)-e.py}function c(t){return!!t&&!isNaN(t)}function p(t,e){return!!t&&(null!==t.yval&&(null!==t.x&&void 0!==t.x&&(null!==t.y&&void 0!==t.y&&!(isNaN(t.x)||!e&&isNaN(t.y)))))}function g(t,e){var a=Math.min(Math.max(1,e||2),21);return Math.abs(t)<.001&&0!==t?t.toExponential(a-1):t.toPrecision(a)}function f(t){return t<10?"0"+t:""+t}function v(t,e,a){var i=f(t)+":"+f(e);return a&&(i+=":"+f(a)),i}function _(t,e){var a=e?nt:it,i=new Date(t),n=a.getFullYear(i),r=a.getMonth(i),o=a.getDate(i),s=a.getHours(i),l=a.getMinutes(i),h=a.getSeconds(i),u=""+n,d=f(r+1),c=f(o),p=3600*s+60*l+h,g=u+"/"+d+"/"+c;return p&&(g+=" "+v(s,l,h)),g}function y(t,e){var a=Math.pow(10,e);return Math.round(t*a)/a}function x(t,e,a,i,n){for(var r=!0;r;){var o=t,s=e,l=a,h=i,u=n;if(r=!1,null!==h&&void 0!==h&&null!==u&&void 0!==u||(h=0,u=s.length-1),h>u)return-1;null!==l&&void 0!==l||(l=0);var d,c=function(t){return t>=0&&t<s.length},p=parseInt((h+u)/2,10),g=s[p];if(g==o)return p;if(g>o){if(l>0&&(d=p-1,c(d)&&s[d]<o))return p;t=o,e=s,a=l,i=h,n=p-1,r=!0,c=p=g=d=void 0}else{if(!(g<o))return-1;if(l<0&&(d=p+1,c(d)&&s[d]>o))return p;t=o,e=s,a=l,i=p+1,n=u,r=!0,c=p=g=d=void 0}}}function m(t){var e,a;if((t.search("-")==-1||t.search("T")!=-1||t.search("Z")!=-1)&&(a=b(t),a&&!isNaN(a)))return a;if(t.search("-")!=-1){for(e=t.replace("-","/","g");e.search("-")!=-1;)e=e.replace("-","/");a=b(e)}else 8==t.length?(e=t.substr(0,4)+"/"+t.substr(4,2)+"/"+t.substr(6,2),a=b(e)):a=b(t);return a&&!isNaN(a)||console.error("Couldn't parse "+t+" as a date"),a}function b(t){return new Date(t).getTime()}function w(t,e){if("undefined"!=typeof e&&null!==e)for(var a in e)e.hasOwnProperty(a)&&(t[a]=e[a]);return t}function A(t,e){function a(t){return"object"==typeof Node?t instanceof Node:"object"==typeof t&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName}if("undefined"!=typeof e&&null!==e)for(var i in e)e.hasOwnProperty(i)&&(null===e[i]?t[i]=null:O(e[i])?t[i]=e[i].slice():a(e[i])?t[i]=e[i]:"object"==typeof e[i]?("object"==typeof t[i]&&null!==t[i]||(t[i]={}),A(t[i],e[i])):t[i]=e[i]);return t}function O(t){var e=typeof t;return("object"==e||"function"==e&&"function"==typeof t.item)&&null!==t&&"number"==typeof t.length&&3!==t.nodeType}function D(t){return"object"==typeof t&&null!==t&&"function"==typeof t.getTime}function S(t){for(var e=[],a=0;a<t.length;a++)O(t[a])?e.push(S(t[a])):e.push(t[a]);return e}function T(){return document.createElement("canvas")}function P(t){try{var e=window.devicePixelRatio,a=t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1;return void 0!==e?e/a:1}catch(t){return 1}}function L(){return/Android/.test(navigator.userAgent)}function E(t,e,a,i){e=e||0,a=a||t.length,this.hasNext=!0,this.peek=null,this.start_=e,this.array_=t,this.predicate_=i,this.end_=Math.min(t.length,e+a),this.nextIdx_=e-1,this.next()}function C(t,e,a,i){return new E(t,e,a,i)}function M(t,e,a,i){var n,r=0,o=(new Date).getTime();if(t(r),1==e)return void i();var s=e-1;!function l(){r>=e||rt.call(window,function(){var e=(new Date).getTime(),h=e-o;n=r,r=Math.floor(h/a);var u=r-n,d=r+u>s;d||r>=s?(t(s),i()):(0!==u&&t(r),l())})}()}function k(t,e){var a={};if(t)for(var i=1;i<t.length;i++)a[t[i]]=!0;var n=function(t){for(var e in t)if(t.hasOwnProperty(e)&&!ot[e])return!0;return!1};for(var r in e)if(e.hasOwnProperty(r))if("highlightSeriesOpts"==r||a[r]&&!e.series){if(n(e[r]))return!0}else if("series"==r||"axes"==r){var o=e[r];for(var s in o)if(o.hasOwnProperty(s)&&n(o[s]))return!0}else if(!ot[r])return!0;return!1}function N(t){for(var e=0;e<t.length;e++){var a=t.charAt(e);if("\r"===a)return e+1<t.length&&"\n"===t.charAt(e+1)?"\r\n":a;if("\n"===a)return e+1<t.length&&"\r"===t.charAt(e+1)?"\n\r":a}return null}function F(t,e){if(null===e||null===t)return!1;for(var a=t;a&&a!==e;)a=a.parentNode;return a===e}function R(t,e){return e<0?1/Math.pow(t,-e):Math.pow(t,e)}function I(t){var e=lt.exec(t);if(!e)return null;var a=parseInt(e[1],10),i=parseInt(e[2],10),n=parseInt(e[3],10);return e[4]?{r:a,g:i,b:n,a:parseFloat(e[4])}:{r:a,g:i,b:n}}function H(t){var e=I(t);if(e)return e;var a=document.createElement("div");a.style.backgroundColor=t,a.style.visibility="hidden",document.body.appendChild(a);var i=window.getComputedStyle(a,null).backgroundColor;return document.body.removeChild(a),I(i)}function Y(t){try{var e=t||document.createElement("canvas");e.getContext("2d")}catch(t){return!1}return!0}function X(t,e,a){var i=parseFloat(t);if(!isNaN(i))return i;if(/^ *$/.test(t))return null;if(/^ *nan *$/i.test(t))return NaN;var n="Unable to parse '"+t+"' as a number";return void 0!==a&&void 0!==e&&(n+=" on line "+(1+(e||0))+" ('"+a+"') of CSV."),console.error(n),null}function V(t,e){var a=e("sigFigs");if(null!==a)return g(t,a);var i,n=e("digitsAfterDecimal"),r=e("maxNumberWidth"),o=e("labelsKMB"),s=e("labelsKMG2");if(i=0!==t&&(Math.abs(t)>=Math.pow(10,r)||Math.abs(t)<Math.pow(10,-n))?t.toExponential(n):""+y(t,n),o||s){var l,h=[],u=[];o&&(l=1e3,h=ht),s&&(o&&console.warn("Setting both labelsKMB and labelsKMG2. Pick one!"),l=1024,h=ut,u=dt);for(var d=Math.abs(t),c=R(l,h.length),p=h.length-1;p>=0;p--,c/=l)if(d>=c){i=y(t/c,n)+h[p];break}if(s){var f=String(t.toExponential()).split("e-");2===f.length&&f[1]>=3&&f[1]<=24&&(i=f[1]%3>0?y(f[0]/R(10,f[1]%3),n):Number(f[0]).toFixed(2),i+=u[Math.floor(f[1]/3)-1])}}return i}function W(t,e,a){return V.call(this,t,a)}function Z(t,e,a){var i=a("labelsUTC"),n=i?nt:it,r=n.getFullYear(t),o=n.getMonth(t),s=n.getDate(t),l=n.getHours(t),h=n.getMinutes(t),u=n.getSeconds(t),d=n.getSeconds(t);if(e>=G.Granularity.DECADAL)return""+r;if(e>=G.Granularity.MONTHLY)return ct[o]+"&#160;"+r;var c=3600*l+60*h+u+.001*d;return 0===c||e>=G.Granularity.DAILY?f(s)+"&#160;"+ct[o]:v(l,h,u)}function z(t,e){return _(t,e("labelsUTC"))}Object.defineProperty(a,"__esModule",{value:!0}),a.removeEvent=n,a.cancelEvent=r,a.hsvToRGB=o,a.findPos=s,a.pageX=l,a.pageY=h,a.dragGetX_=u,a.dragGetY_=d,a.isOK=c,a.isValidPoint=p,a.floatFormat=g,a.zeropad=f,a.hmsString_=v,a.dateString_=_,a.round_=y,a.binarySearch=x,a.dateParser=m,a.dateStrToMillis=b,a.update=w,a.updateDeep=A,a.isArrayLike=O,a.isDateLike=D,a.clone=S,a.createCanvas=T,a.getContextPixelRatio=P,a.isAndroid=L,a.Iterator=E,a.createIterator=C,a.repeatAndCleanup=M,a.isPixelChangingOptionList=k,a.detectLineDelimiter=N,a.isNodeContainedBy=F,a.pow=R,a.toRGB_=H,a.isCanvasSupported=Y,a.parseFloat_=X,a.numberValueFormatter=V,a.numberAxisLabelFormatter=W,a.dateAxisLabelFormatter=Z,a.dateValueFormatter=z;var B=t("./dygraph-tickers"),G=i(B),U=10;a.LOG_SCALE=U;var j=Math.log(U);a.LN_TEN=j;var K=function(t){return Math.log(t)/j};a.log10=K;var q=[2,2];a.DOTTED_LINE=q;var Q=[7,3];a.DASHED_LINE=Q;var J=[7,2,2,2];a.DOT_DASH_LINE=J;var $=1;a.HORIZONTAL=$;var tt=2;a.VERTICAL=tt;var et=function(t){return t.getContext("2d")};a.getContext=et;var at=function(t,e,a){t.addEventListener(e,a,!1)};a.addEvent=at;var it={getFullYear:function(t){return t.getFullYear()},getMonth:function(t){return t.getMonth()},getDate:function(t){return t.getDate()},getHours:function(t){return t.getHours()},getMinutes:function(t){return t.getMinutes()},getSeconds:function(t){return t.getSeconds()},getMilliseconds:function(t){return t.getMilliseconds()},getDay:function(t){return t.getDay()},makeDate:function(t,e,a,i,n,r,o){return new Date(t,e,a,i,n,r,o)}};a.DateAccessorsLocal=it;var nt={getFullYear:function(t){return t.getUTCFullYear()},getMonth:function(t){return t.getUTCMonth()},getDate:function(t){return t.getUTCDate()},getHours:function(t){return t.getUTCHours()},getMinutes:function(t){return t.getUTCMinutes()},getSeconds:function(t){return t.getUTCSeconds()},getMilliseconds:function(t){return t.getUTCMilliseconds()},getDay:function(t){return t.getUTCDay()},makeDate:function(t,e,a,i,n,r,o){return new Date(Date.UTC(t,e,a,i,n,r,o))}};a.DateAccessorsUTC=nt,E.prototype.next=function(){if(!this.hasNext)return null;for(var t=this.peek,e=this.nextIdx_+1,a=!1;e<this.end_;){if(!this.predicate_||this.predicate_(this.array_,e)){this.peek=this.array_[e],a=!0;break}e++}return this.nextIdx_=e,a||(this.hasNext=!1,this.peek=null),t};var rt=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){window.setTimeout(t,1e3/60)}}();a.requestAnimFrame=rt;var ot={annotationClickHandler:!0,annotationDblClickHandler:!0,annotationMouseOutHandler:!0,annotationMouseOverHandler:!0,axisLabelColor:!0,axisLineColor:!0,axisLineWidth:!0,clickCallback:!0,drawCallback:!0,drawHighlightPointCallback:!0,drawPoints:!0,drawPointCallback:!0,drawGrid:!0,fillAlpha:!0,gridLineColor:!0,gridLineWidth:!0,hideOverlayOnMouseOut:!0,highlightCallback:!0,highlightCircleSize:!0,interactionModel:!0,isZoomedIgnoreProgrammaticZoom:!0,labelsDiv:!0,labelsDivStyles:!0,labelsDivWidth:!0,labelsKMB:!0,labelsKMG2:!0,labelsSeparateLines:!0,labelsShowZeroValues:!0,legend:!0,panEdgeFraction:!0,pixelsPerYLabel:!0,pointClickCallback:!0,pointSize:!0,rangeSelectorPlotFillColor:!0,rangeSelectorPlotFillGradientColor:!0,rangeSelectorPlotStrokeColor:!0,rangeSelectorBackgroundStrokeColor:!0,rangeSelectorBackgroundLineWidth:!0,rangeSelectorPlotLineWidth:!0,rangeSelectorForegroundStrokeColor:!0,rangeSelectorForegroundLineWidth:!0,rangeSelectorAlpha:!0,showLabelsOnHighlight:!0,showRoller:!0,strokeWidth:!0,underlayCallback:!0,unhighlightCallback:!0,zoomCallback:!0},st={DEFAULT:function(t,e,a,i,n,r,o){a.beginPath(),a.fillStyle=r,a.arc(i,n,o,0,2*Math.PI,!1),a.fill()}};a.Circles=st;var lt=/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(?:,\s*([01](?:\.\d+)?))?\)$/,ht=["K","M","B","T","Q"],ut=["k","M","G","T","P","E","Z","Y"],dt=["m","u","n","p","f","a","z","y"],ct=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]},{"./dygraph-tickers":15}],17:[function(t,e,a){"use strict";function i(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}function n(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-layout"),o=n(r),s=t("./dygraph-canvas"),l=n(s),h=t("./dygraph-options"),u=n(h),d=t("./dygraph-interaction-model"),c=n(d),p=t("./dygraph-tickers"),g=i(p),f=t("./dygraph-utils"),v=i(f),_=t("./dygraph-default-attrs"),y=n(_),x=t("./dygraph-options-reference"),m=(n(x),t("./iframe-tarp")),b=n(m),w=t("./datahandler/default"),A=n(w),O=t("./datahandler/bars-error"),D=n(O),S=t("./datahandler/bars-custom"),T=n(S),P=t("./datahandler/default-fractions"),L=n(P),E=t("./datahandler/bars-fractions"),C=n(E),M=t("./datahandler/bars"),k=n(M),N=t("./plugins/annotations"),F=n(N),R=t("./plugins/axes"),I=n(R),H=t("./plugins/chart-labels"),Y=n(H),X=t("./plugins/grid"),V=n(X),W=t("./plugins/legend"),Z=n(W),z=t("./plugins/range-selector"),B=n(z),G=t("./dygraph-gviz"),U=n(G),j=function(t,e,a){this.__init__(t,e,a)};j.NAME="Dygraph",j.VERSION="1.1.0",j.DEFAULT_ROLL_PERIOD=1,j.DEFAULT_WIDTH=480,j.DEFAULT_HEIGHT=320,j.ANIMATION_STEPS=12,j.ANIMATION_DURATION=200,j.Plotters=l.default._Plotters,j.addedAnnotationCSS=!1,j.prototype.__init__=function(t,e,a){if(this.is_initial_draw_=!0,this.readyFns_=[],null!==a&&void 0!==a||(a={}),a=j.copyUserAttrs_(a),"string"==typeof t&&(t=document.getElementById(t)),!t)throw new Error("Constructing dygraph with a non-existent div!");this.maindiv_=t,this.file_=e,this.rollPeriod_=a.rollPeriod||j.DEFAULT_ROLL_PERIOD,this.previousVerticalX_=-1,this.fractions_=a.fractions||!1,this.dateWindow_=a.dateWindow||null,this.annotations_=[],this.zoomed_x_=!1,this.zoomed_y_=!1,t.innerHTML="",""===t.style.width&&a.width&&(t.style.width=a.width+"px"),""===t.style.height&&a.height&&(t.style.height=a.height+"px"),""===t.style.height&&0===t.clientHeight&&(t.style.height=j.DEFAULT_HEIGHT+"px",""===t.style.width&&(t.style.width=j.DEFAULT_WIDTH+"px")),this.width_=t.clientWidth||a.width||0,this.height_=t.clientHeight||a.height||0,a.stackedGraph&&(a.fillGraph=!0),this.user_attrs_={},v.update(this.user_attrs_,a),this.attrs_={},v.updateDeep(this.attrs_,y.default),this.boundaryIds_=[],this.setIndexByName_={},this.datasetIndex_=[],this.registeredEvents_=[],this.eventListeners_={},this.attributes_=new u.default(this),this.createInterface_(),this.plugins_=[];for(var i=j.PLUGINS.concat(this.getOption("plugins")),n=0;n<i.length;n++){var r,o=i[n];r="undefined"!=typeof o.activate?o:new o;var s={plugin:r,events:{},options:{},pluginOptions:{}},l=r.activate(this);for(var h in l)l.hasOwnProperty(h)&&(s.events[h]=l[h]);this.plugins_.push(s)}for(var n=0;n<this.plugins_.length;n++){var d=this.plugins_[n];for(var h in d.events)if(d.events.hasOwnProperty(h)){var c=d.events[h],p=[d.plugin,c];h in this.eventListeners_?this.eventListeners_[h].push(p):this.eventListeners_[h]=[p]}}this.createDragInterface_(),this.start_()},j.prototype.cascadeEvents_=function(t,e){if(!(t in this.eventListeners_))return!1;var a={dygraph:this,cancelable:!1,defaultPrevented:!1,preventDefault:function(){if(!a.cancelable)throw"Cannot call preventDefault on non-cancelable event.";a.defaultPrevented=!0},propagationStopped:!1,stopPropagation:function(){a.propagationStopped=!0}};v.update(a,e);var i=this.eventListeners_[t];if(i)for(var n=i.length-1;n>=0;n--){var r=i[n][0],o=i[n][1];if(o.call(r,a),a.propagationStopped)break}return a.defaultPrevented},j.prototype.getPluginInstance_=function(t){for(var e=0;e<this.plugins_.length;e++){var a=this.plugins_[e];if(a.plugin instanceof t)return a.plugin}return null},j.prototype.isZoomed=function(t){if(null===t||void 0===t)return this.zoomed_x_||this.zoomed_y_;if("x"===t)return this.zoomed_x_;if("y"===t)return this.zoomed_y_;throw"axis parameter is ["+t+"] must be null, 'x' or 'y'."},j.prototype.toString=function(){var t=this.maindiv_,e=t&&t.id?t.id:t;return"[Dygraph "+e+"]"},j.prototype.attr_=function(t,e){return e?this.attributes_.getForSeries(t,e):this.attributes_.get(t)},j.prototype.getOption=function(t,e){return this.attr_(t,e)},j.prototype.getNumericOption=function(t,e){return this.getOption(t,e)},j.prototype.getStringOption=function(t,e){return this.getOption(t,e)},j.prototype.getBooleanOption=function(t,e){return this.getOption(t,e)},j.prototype.getFunctionOption=function(t,e){return this.getOption(t,e)},j.prototype.getOptionForAxis=function(t,e){return this.attributes_.getForAxis(t,e)},j.prototype.optionsViewForAxis_=function(t){var e=this;return function(a){var i=e.user_attrs_.axes;return i&&i[t]&&i[t].hasOwnProperty(a)?i[t][a]:("x"!==t||"logscale"!==a)&&("undefined"!=typeof e.user_attrs_[a]?e.user_attrs_[a]:(i=e.attrs_.axes,i&&i[t]&&i[t].hasOwnProperty(a)?i[t][a]:"y"==t&&e.axes_[0].hasOwnProperty(a)?e.axes_[0][a]:"y2"==t&&e.axes_[1].hasOwnProperty(a)?e.axes_[1][a]:e.attr_(a)))}},j.prototype.rollPeriod=function(){return this.rollPeriod_},j.prototype.xAxisRange=function(){return this.dateWindow_?this.dateWindow_:this.xAxisExtremes()},j.prototype.xAxisExtremes=function(){var t=this.getNumericOption("xRangePad")/this.plotter_.area.w;if(0===this.numRows())return[0-t,1+t];var e=this.rawData_[0][0],a=this.rawData_[this.rawData_.length-1][0];if(t){var i=a-e;e-=i*t,a+=i*t}return[e,a]},j.prototype.yAxisRange=function(t){if("undefined"==typeof t&&(t=0),t<0||t>=this.axes_.length)return null;var e=this.axes_[t];return[e.computedValueRange[0],e.computedValueRange[1]]},j.prototype.yAxisRanges=function(){for(var t=[],e=0;e<this.axes_.length;e++)t.push(this.yAxisRange(e));return t},j.prototype.toDomCoords=function(t,e,a){return[this.toDomXCoord(t),this.toDomYCoord(e,a)]},j.prototype.toDomXCoord=function(t){if(null===t)return null;var e=this.plotter_.area,a=this.xAxisRange();return e.x+(t-a[0])/(a[1]-a[0])*e.w},j.prototype.toDomYCoord=function(t,e){var a=this.toPercentYCoord(t,e);if(null===a)return null;var i=this.plotter_.area;return i.y+a*i.h},j.prototype.toDataCoords=function(t,e,a){return[this.toDataXCoord(t),this.toDataYCoord(e,a)]},j.prototype.toDataXCoord=function(t){if(null===t)return null;var e=this.plotter_.area,a=this.xAxisRange();if(this.attributes_.getForAxis("logscale","x")){var i=(t-e.x)/e.w,n=v.log10(a[0]),r=v.log10(a[1]),o=n+i*(r-n),s=Math.pow(v.LOG_SCALE,o);return s}return a[0]+(t-e.x)/e.w*(a[1]-a[0])},j.prototype.toDataYCoord=function(t,e){if(null===t)return null;var a=this.plotter_.area,i=this.yAxisRange(e);if("undefined"==typeof e&&(e=0),this.attributes_.getForAxis("logscale",e)){var n=(t-a.y)/a.h,r=v.log10(i[0]),o=v.log10(i[1]),s=o-n*(o-r),l=Math.pow(v.LOG_SCALE,s);return l}return i[0]+(a.y+a.h-t)/a.h*(i[1]-i[0])},j.prototype.toPercentYCoord=function(t,e){if(null===t)return null;"undefined"==typeof e&&(e=0);var a,i=this.yAxisRange(e),n=this.attributes_.getForAxis("logscale",e);if(n){var r=v.log10(i[0]),o=v.log10(i[1]);a=(o-v.log10(t))/(o-r)}else a=(i[1]-t)/(i[1]-i[0]);return a},j.prototype.toPercentXCoord=function(t){if(null===t)return null;var e,a=this.xAxisRange(),i=this.attributes_.getForAxis("logscale","x");if(i===!0){var n=v.log10(a[0]),r=v.log10(a[1]);e=(v.log10(t)-n)/(r-n)}else e=(t-a[0])/(a[1]-a[0]);return e},j.prototype.numColumns=function(){return this.rawData_?this.rawData_[0]?this.rawData_[0].length:this.attr_("labels").length:0},j.prototype.numRows=function(){return this.rawData_?this.rawData_.length:0},j.prototype.getValue=function(t,e){return t<0||t>this.rawData_.length?null:e<0||e>this.rawData_[t].length?null:this.rawData_[t][e]},j.prototype.createInterface_=function(){var t=this.maindiv_;this.graphDiv=document.createElement("div"),this.graphDiv.style.textAlign="left",this.graphDiv.style.position="relative",t.appendChild(this.graphDiv),this.canvas_=v.createCanvas(),this.canvas_.style.position="absolute",this.hidden_=this.createPlotKitCanvas_(this.canvas_),this.canvas_ctx_=v.getContext(this.canvas_),this.hidden_ctx_=v.getContext(this.hidden_),this.resizeElements_(),this.graphDiv.appendChild(this.hidden_),this.graphDiv.appendChild(this.canvas_),this.mouseEventElement_=this.createMouseEventElement_(),this.layout_=new o.default(this);var e=this;this.mouseMoveHandler_=function(t){e.mouseMove_(t)},this.mouseOutHandler_=function(t){var a=t.target||t.fromElement,i=t.relatedTarget||t.toElement;v.isNodeContainedBy(a,e.graphDiv)&&!v.isNodeContainedBy(i,e.graphDiv)&&e.mouseOut_(t)},this.addAndTrackEvent(window,"mouseout",this.mouseOutHandler_),this.addAndTrackEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),this.resizeHandler_||(this.resizeHandler_=function(t){e.resize()},this.addAndTrackEvent(window,"resize",this.resizeHandler_))},j.prototype.resizeElements_=function(){this.graphDiv.style.width=this.width_+"px",this.graphDiv.style.height=this.height_+"px";var t=v.getContextPixelRatio(this.canvas_ctx_);this.canvas_.width=this.width_*t,this.canvas_.height=this.height_*t,this.canvas_.style.width=this.width_+"px",this.canvas_.style.height=this.height_+"px",1!==t&&this.canvas_ctx_.scale(t,t);var e=v.getContextPixelRatio(this.hidden_ctx_);this.hidden_.width=this.width_*e,this.hidden_.height=this.height_*e,this.hidden_.style.width=this.width_+"px",this.hidden_.style.height=this.height_+"px",1!==e&&this.hidden_ctx_.scale(e,e)},j.prototype.destroy=function(){this.canvas_ctx_.restore(),this.hidden_ctx_.restore();for(var t=this.plugins_.length-1;t>=0;t--){var e=this.plugins_.pop();e.plugin.destroy&&e.plugin.destroy()}var a=function t(e){for(;e.hasChildNodes();)t(e.firstChild),e.removeChild(e.firstChild)};this.removeTrackedEvents_(),v.removeEvent(window,"mouseout",this.mouseOutHandler_),v.removeEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),v.removeEvent(window,"resize",this.resizeHandler_),this.resizeHandler_=null,a(this.maindiv_);var i=function(t){for(var e in t)"object"==typeof t[e]&&(t[e]=null)};i(this.layout_),i(this.plotter_),i(this)},j.prototype.createPlotKitCanvas_=function(t){var e=v.createCanvas();return e.style.position="absolute",e.style.top=t.style.top,e.style.left=t.style.left,e.width=this.width_,e.height=this.height_,e.style.width=this.width_+"px",e.style.height=this.height_+"px",e},j.prototype.createMouseEventElement_=function(){return this.canvas_},j.prototype.setColors_=function(){var t=this.getLabels(),e=t.length-1;this.colors_=[],this.colorsMap_={};for(var a=this.getNumericOption("colorSaturation")||1,i=this.getNumericOption("colorValue")||.5,n=Math.ceil(e/2),r=this.getOption("colors"),o=this.visibility(),s=0;s<e;s++)if(o[s]){var l=t[s+1],h=this.attributes_.getForSeries("color",l);if(!h)if(r)h=r[s%r.length];else{var u=s%2?n+(s+1)/2:Math.ceil((s+1)/2),d=1*u/(1+e);h=v.hsvToRGB(d,a,i)}this.colors_.push(h),this.colorsMap_[l]=h}},j.prototype.getColors=function(){return this.colors_},j.prototype.getPropertiesForSeries=function(t){for(var e=-1,a=this.getLabels(),i=1;i<a.length;i++)if(a[i]==t){e=i;break}return e==-1?null:{name:t,column:e,visible:this.visibility()[e-1],color:this.colorsMap_[t],axis:1+this.attributes_.axisForSeries(t)}},j.prototype.createRollInterface_=function(){this.roller_||(this.roller_=document.createElement("input"),this.roller_.type="text",this.roller_.style.display="none",this.graphDiv.appendChild(this.roller_));var t=this.getBooleanOption("showRoller")?"block":"none",e=this.plotter_.area,a={position:"absolute",zIndex:10,top:e.y+e.h-25+"px",left:e.x+1+"px",display:t};this.roller_.size="2",this.roller_.value=this.rollPeriod_;for(var i in a)a.hasOwnProperty(i)&&(this.roller_.style[i]=a[i]);var n=this;this.roller_.onchange=function(){n.adjustRoll(n.roller_.value)}},j.prototype.createDragInterface_=function(){var t={isZooming:!1,isPanning:!1,is2DPan:!1,dragStartX:null,dragStartY:null,dragEndX:null,dragEndY:null,dragDirection:null,prevEndX:null,prevEndY:null,prevDragDirection:null,cancelNextDblclick:!1,initialLeftmostDate:null,xUnitsPerPixel:null,dateRange:null,px:0,py:0,boundedDates:null,boundedValues:null,tarp:new b.default,initializeMouseDown:function(t,e,a){t.preventDefault?t.preventDefault():(t.returnValue=!1,t.cancelBubble=!0);var i=v.findPos(e.canvas_);a.px=i.x,a.py=i.y,a.dragStartX=v.dragGetX_(t,a),a.dragStartY=v.dragGetY_(t,a),a.cancelNextDblclick=!1,a.tarp.cover()},destroy:function(){var t=this;if((t.isZooming||t.isPanning)&&(t.isZooming=!1,t.dragStartX=null,t.dragStartY=null),t.isPanning){t.isPanning=!1,t.draggingDate=null,t.dateRange=null;for(var e=0;e<a.axes_.length;e++)delete a.axes_[e].draggingValue,delete a.axes_[e].dragValueRange}t.tarp.uncover()}},e=this.getOption("interactionModel"),a=this,i=function(e){return function(i){e(i,a,t)}};for(var n in e)e.hasOwnProperty(n)&&this.addAndTrackEvent(this.mouseEventElement_,n,i(e[n]));if(!e.willDestroyContextMyself){var r=function(e){t.destroy()};this.addAndTrackEvent(document,"mouseup",r)}},j.prototype.drawZoomRect_=function(t,e,a,i,n,r,o,s){var l=this.canvas_ctx_;r==v.HORIZONTAL?l.clearRect(Math.min(e,o),this.layout_.getPlotArea().y,Math.abs(e-o),this.layout_.getPlotArea().h):r==v.VERTICAL&&l.clearRect(this.layout_.getPlotArea().x,Math.min(i,s),this.layout_.getPlotArea().w,Math.abs(i-s)),t==v.HORIZONTAL?a&&e&&(l.fillStyle="rgba(128,128,128,0.33)",
+l.fillRect(Math.min(e,a),this.layout_.getPlotArea().y,Math.abs(a-e),this.layout_.getPlotArea().h)):t==v.VERTICAL&&n&&i&&(l.fillStyle="rgba(128,128,128,0.33)",l.fillRect(this.layout_.getPlotArea().x,Math.min(i,n),this.layout_.getPlotArea().w,Math.abs(n-i)))},j.prototype.clearZoomRect_=function(){this.currentZoomRectArgs_=null,this.canvas_ctx_.clearRect(0,0,this.width_,this.height_)},j.prototype.doZoomX_=function(t,e){this.currentZoomRectArgs_=null;var a=this.toDataXCoord(t),i=this.toDataXCoord(e);this.doZoomXDates_(a,i)},j.prototype.doZoomXDates_=function(t,e){var a=this.xAxisRange(),i=[t,e];this.zoomed_x_=!0;var n=this;this.doAnimatedZoom(a,i,null,null,function(){n.getFunctionOption("zoomCallback")&&n.getFunctionOption("zoomCallback").call(n,t,e,n.yAxisRanges())})},j.prototype.doZoomY_=function(t,e){this.currentZoomRectArgs_=null;for(var a=this.yAxisRanges(),i=[],n=0;n<this.axes_.length;n++){var r=this.toDataYCoord(t,n),o=this.toDataYCoord(e,n);i.push([o,r])}this.zoomed_y_=!0;var s=this;this.doAnimatedZoom(null,null,a,i,function(){if(s.getFunctionOption("zoomCallback")){var t=s.xAxisRange();s.getFunctionOption("zoomCallback").call(s,t[0],t[1],s.yAxisRanges())}})},j.zoomAnimationFunction=function(t,e){var a=1.5;return(1-Math.pow(a,-t))/(1-Math.pow(a,-e))},j.prototype.resetZoom=function(){var t=!1,e=!1,a=!1;null!==this.dateWindow_&&(t=!0,e=!0);for(var i=0;i<this.axes_.length;i++)"undefined"!=typeof this.axes_[i].valueWindow&&null!==this.axes_[i].valueWindow&&(t=!0,a=!0);if(this.clearSelection(),t){this.zoomed_x_=!1,this.zoomed_y_=!1;var n=this.xAxisExtremes(),r=n[0],o=n[1];if(!this.getBooleanOption("animatedZooms")){for(this.dateWindow_=null,i=0;i<this.axes_.length;i++)null!==this.axes_[i].valueWindow&&delete this.axes_[i].valueWindow;return this.drawGraph_(),void(this.getFunctionOption("zoomCallback")&&this.getFunctionOption("zoomCallback").call(this,r,o,this.yAxisRanges()))}var s=null,l=null,h=null,u=null;if(e&&(s=this.xAxisRange(),l=[r,o]),a){h=this.yAxisRanges();var d=this.gatherDatasets_(this.rolledSeries_,null),n=d.extremes;for(this.computeYAxisRanges_(n),u=[],i=0;i<this.axes_.length;i++){var c=this.axes_[i];u.push(null!==c.valueRange&&void 0!==c.valueRange?c.valueRange:c.extremeRange)}}var p=this;this.doAnimatedZoom(s,l,h,u,function(){p.dateWindow_=null;for(var t=0;t<p.axes_.length;t++)null!==p.axes_[t].valueWindow&&delete p.axes_[t].valueWindow;p.getFunctionOption("zoomCallback")&&p.getFunctionOption("zoomCallback").call(p,r,o,p.yAxisRanges())})}},j.prototype.doAnimatedZoom=function(t,e,a,i,n){var r,o,s=this.getBooleanOption("animatedZooms")?j.ANIMATION_STEPS:1,l=[],h=[];if(null!==t&&null!==e)for(r=1;r<=s;r++)o=j.zoomAnimationFunction(r,s),l[r-1]=[t[0]*(1-o)+o*e[0],t[1]*(1-o)+o*e[1]];if(null!==a&&null!==i)for(r=1;r<=s;r++){o=j.zoomAnimationFunction(r,s);for(var u=[],d=0;d<this.axes_.length;d++)u.push([a[d][0]*(1-o)+o*i[d][0],a[d][1]*(1-o)+o*i[d][1]]);h[r-1]=u}var c=this;v.repeatAndCleanup(function(t){if(h.length)for(var e=0;e<c.axes_.length;e++){var a=h[t][e];c.axes_[e].valueWindow=[a[0],a[1]]}l.length&&(c.dateWindow_=l[t]),c.drawGraph_()},s,j.ANIMATION_DURATION/s,n)},j.prototype.getArea=function(){return this.plotter_.area},j.prototype.eventToDomCoords=function(t){if(t.offsetX&&t.offsetY)return[t.offsetX,t.offsetY];var e=v.findPos(this.mouseEventElement_),a=v.pageX(t)-e.x,i=v.pageY(t)-e.y;return[a,i]},j.prototype.findClosestRow=function(t){for(var e=1/0,a=-1,i=this.layout_.points,n=0;n<i.length;n++)for(var r=i[n],o=r.length,s=0;s<o;s++){var l=r[s];if(v.isValidPoint(l,!0)){var h=Math.abs(l.canvasx-t);h<e&&(e=h,a=l.idx)}}return a},j.prototype.findClosestPoint=function(t,e){for(var a,i,n,r,o,s,l,h=1/0,u=this.layout_.points.length-1;u>=0;--u)for(var d=this.layout_.points[u],c=0;c<d.length;++c)r=d[c],v.isValidPoint(r)&&(i=r.canvasx-t,n=r.canvasy-e,a=i*i+n*n,a<h&&(h=a,o=r,s=u,l=r.idx));var p=this.layout_.setNames[s];return{row:l,seriesName:p,point:o}},j.prototype.findStackedPoint=function(t,e){for(var a,i,n=this.findClosestRow(t),r=0;r<this.layout_.points.length;++r){var o=this.getLeftBoundary_(r),s=n-o,l=this.layout_.points[r];if(!(s>=l.length)){var h=l[s];if(v.isValidPoint(h)){var u=h.canvasy;if(t>h.canvasx&&s+1<l.length){var d=l[s+1];if(v.isValidPoint(d)){var c=d.canvasx-h.canvasx;if(c>0){var p=(t-h.canvasx)/c;u+=p*(d.canvasy-h.canvasy)}}}else if(t<h.canvasx&&s>0){var g=l[s-1];if(v.isValidPoint(g)){var c=h.canvasx-g.canvasx;if(c>0){var p=(h.canvasx-t)/c;u+=p*(g.canvasy-h.canvasy)}}}(0===r||u<e)&&(a=h,i=r)}}}var f=this.layout_.setNames[i];return{row:n,seriesName:f,point:a}},j.prototype.mouseMove_=function(t){var e=this.layout_.points;if(void 0!==e&&null!==e){var a=this.eventToDomCoords(t),i=a[0],n=a[1],r=this.getOption("highlightSeriesOpts"),o=!1;if(r&&!this.isSeriesLocked()){var s;s=this.getBooleanOption("stackedGraph")?this.findStackedPoint(i,n):this.findClosestPoint(i,n),o=this.setSelection(s.row,s.seriesName)}else{var l=this.findClosestRow(i);o=this.setSelection(l)}var h=this.getFunctionOption("highlightCallback");h&&o&&h.call(this,t,this.lastx_,this.selPoints_,this.lastRow_,this.highlightSet_)}},j.prototype.getLeftBoundary_=function(t){if(this.boundaryIds_[t])return this.boundaryIds_[t][0];for(var e=0;e<this.boundaryIds_.length;e++)if(void 0!==this.boundaryIds_[e])return this.boundaryIds_[e][0];return 0},j.prototype.animateSelection_=function(t){var e=10,a=30;void 0===this.fadeLevel&&(this.fadeLevel=0),void 0===this.animateId&&(this.animateId=0);var i=this.fadeLevel,n=t<0?i:e-i;if(n<=0)return void(this.fadeLevel&&this.updateSelection_(1));var r=++this.animateId,o=this,s=function(){0!==o.fadeLevel&&t<0&&(o.fadeLevel=0,o.clearSelection())};v.repeatAndCleanup(function(a){o.animateId==r&&(o.fadeLevel+=t,0===o.fadeLevel?o.clearSelection():o.updateSelection_(o.fadeLevel/e))},n,a,s)},j.prototype.updateSelection_=function(t){this.cascadeEvents_("select",{selectedRow:this.lastRow_,selectedX:this.lastx_,selectedPoints:this.selPoints_});var e,a=this.canvas_ctx_;if(this.getOption("highlightSeriesOpts")){a.clearRect(0,0,this.width_,this.height_);var i=1-this.getNumericOption("highlightSeriesBackgroundAlpha"),n=v.toRGB_(this.getOption("highlightSeriesBackgroundColor"));if(i){var r=!0;if(r){if(void 0===t)return void this.animateSelection_(1);i*=t}a.fillStyle="rgba("+n.r+","+n.g+","+n.b+","+i+")",a.fillRect(0,0,this.width_,this.height_)}this.plotter_._renderLineChart(this.highlightSet_,a)}else if(this.previousVerticalX_>=0){var o=0,s=this.attr_("labels");for(e=1;e<s.length;e++){var l=this.getNumericOption("highlightCircleSize",s[e]);l>o&&(o=l)}var h=this.previousVerticalX_;a.clearRect(h-o-1,0,2*o+2,this.height_)}if(this.selPoints_.length>0){var u=this.selPoints_[0].canvasx;for(a.save(),e=0;e<this.selPoints_.length;e++){var d=this.selPoints_[e];if(!isNaN(d.canvasy)){var c=this.getNumericOption("highlightCircleSize",d.name),p=this.getFunctionOption("drawHighlightPointCallback",d.name),g=this.plotter_.colors[d.name];p||(p=v.Circles.DEFAULT),a.lineWidth=this.getNumericOption("strokeWidth",d.name),a.strokeStyle=g,a.fillStyle=g,p.call(this,this,d.name,a,u,d.canvasy,g,c,d.idx)}}a.restore(),this.previousVerticalX_=u}},j.prototype.setSelection=function(t,e,a){this.selPoints_=[];var i=!1;if(t!==!1&&t>=0){t!=this.lastRow_&&(i=!0),this.lastRow_=t;for(var n=0;n<this.layout_.points.length;++n){var r=this.layout_.points[n],o=t-this.getLeftBoundary_(n);if(o<r.length&&r[o].idx==t){var s=r[o];null!==s.yval&&this.selPoints_.push(s)}else for(var l=0;l<r.length;++l){var s=r[l];if(s.idx==t){null!==s.yval&&this.selPoints_.push(s);break}}}}else this.lastRow_>=0&&(i=!0),this.lastRow_=-1;return this.selPoints_.length?this.lastx_=this.selPoints_[0].xval:this.lastx_=-1,void 0!==e&&(this.highlightSet_!==e&&(i=!0),this.highlightSet_=e),void 0!==a&&(this.lockedSet_=a),i&&this.updateSelection_(void 0),i},j.prototype.mouseOut_=function(t){this.getFunctionOption("unhighlightCallback")&&this.getFunctionOption("unhighlightCallback").call(this,t),this.getBooleanOption("hideOverlayOnMouseOut")&&!this.lockedSet_&&this.clearSelection()},j.prototype.clearSelection=function(){return this.cascadeEvents_("deselect",{}),this.lockedSet_=!1,this.fadeLevel?void this.animateSelection_(-1):(this.canvas_ctx_.clearRect(0,0,this.width_,this.height_),this.fadeLevel=0,this.selPoints_=[],this.lastx_=-1,this.lastRow_=-1,void(this.highlightSet_=null))},j.prototype.getSelection=function(){if(!this.selPoints_||this.selPoints_.length<1)return-1;for(var t=0;t<this.layout_.points.length;t++)for(var e=this.layout_.points[t],a=0;a<e.length;a++)if(e[a].x==this.selPoints_[0].x)return e[a].idx;return-1},j.prototype.getHighlightSeries=function(){return this.highlightSet_},j.prototype.isSeriesLocked=function(){return this.lockedSet_},j.prototype.loadedEvent_=function(t){this.rawData_=this.parseCSV_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_()},j.prototype.addXTicks_=function(){var t;t=this.dateWindow_?[this.dateWindow_[0],this.dateWindow_[1]]:this.xAxisExtremes();var e=this.optionsViewForAxis_("x"),a=e("ticker")(t[0],t[1],this.plotter_.area.w,e,this);this.layout_.setXTicks(a)},j.prototype.getHandlerClass_=function(){var t;return t=this.attr_("dataHandler")?this.attr_("dataHandler"):this.fractions_?this.getBooleanOption("errorBars")?C.default:L.default:this.getBooleanOption("customBars")?T.default:this.getBooleanOption("errorBars")?D.default:A.default},j.prototype.predraw_=function(){var t=new Date;this.dataHandler_=new(this.getHandlerClass_()),this.layout_.computePlotArea(),this.computeYAxes_(),this.is_initial_draw_||(this.canvas_ctx_.restore(),this.hidden_ctx_.restore()),this.canvas_ctx_.save(),this.hidden_ctx_.save(),this.plotter_=new l.default(this,this.hidden_,this.hidden_ctx_,this.layout_),this.createRollInterface_(),this.cascadeEvents_("predraw"),this.rolledSeries_=[null];for(var e=1;e<this.numColumns();e++){var a=this.dataHandler_.extractSeries(this.rawData_,e,this.attributes_);this.rollPeriod_>1&&(a=this.dataHandler_.rollingAverage(a,this.rollPeriod_,this.attributes_)),this.rolledSeries_.push(a)}this.drawGraph_();var i=new Date;this.drawingTimeMs_=i-t},j.PointType=void 0,j.stackPoints_=function(t,e,a,i){for(var n=null,r=null,o=null,s=-1,l=function(e){if(!(s>=e))for(var a=e;a<t.length;++a)if(o=null,!isNaN(t[a].yval)&&null!==t[a].yval){s=a,o=t[a];break}},h=0;h<t.length;++h){var u=t[h],d=u.xval;void 0===e[d]&&(e[d]=0);var c=u.yval;isNaN(c)||null===c?"none"==i?c=0:(l(h),c=r&&o&&"none"!=i?r.yval+(o.yval-r.yval)*((d-r.xval)/(o.xval-r.xval)):r&&"all"==i?r.yval:o&&"all"==i?o.yval:0):r=u;var p=e[d];n!=d&&(p+=c,e[d]=p),n=d,u.yval_stacked=p,p>a[1]&&(a[1]=p),p<a[0]&&(a[0]=p)}},j.prototype.gatherDatasets_=function(t,e){var a,i,n,r,o,s,l=[],h=[],u=[],d={},c=t.length-1;for(a=c;a>=1;a--)if(this.visibility()[a-1]){if(e){s=t[a];var p=e[0],g=e[1];for(n=null,r=null,i=0;i<s.length;i++)s[i][0]>=p&&null===n&&(n=i),s[i][0]<=g&&(r=i);null===n&&(n=0);for(var f=n,v=!0;v&&f>0;)f--,v=null===s[f][1];null===r&&(r=s.length-1);var _=r;for(v=!0;v&&_<s.length-1;)_++,v=null===s[_][1];f!==n&&(n=f),_!==r&&(r=_),l[a-1]=[n,r],s=s.slice(n,r+1)}else s=t[a],l[a-1]=[0,s.length-1];var y=this.attr_("labels")[a],x=this.dataHandler_.getExtremeYValues(s,e,this.getBooleanOption("stepPlot",y)),m=this.dataHandler_.seriesToPoints(s,y,l[a-1][0]);this.getBooleanOption("stackedGraph")&&(o=this.attributes_.axisForSeries(y),void 0===u[o]&&(u[o]=[]),j.stackPoints_(m,u[o],x,this.getBooleanOption("stackedGraphNaNFill"))),d[y]=x,h[a]=m}return{points:h,extremes:d,boundaryIds:l}},j.prototype.drawGraph_=function(){var t=new Date,e=this.is_initial_draw_;this.is_initial_draw_=!1,this.layout_.removeAllDatasets(),this.setColors_(),this.attrs_.pointSize=.5*this.getNumericOption("highlightCircleSize");var a=this.gatherDatasets_(this.rolledSeries_,this.dateWindow_),i=a.points,n=a.extremes;this.boundaryIds_=a.boundaryIds,this.setIndexByName_={};var r=this.attr_("labels");r.length>0&&(this.setIndexByName_[r[0]]=0);for(var o=0,s=1;s<i.length;s++)this.setIndexByName_[r[s]]=s,this.visibility()[s-1]&&(this.layout_.addDataset(r[s],i[s]),this.datasetIndex_[s]=o++);this.computeYAxisRanges_(n),this.layout_.setYAxes(this.axes_),this.addXTicks_();var l=this.zoomed_x_;if(this.zoomed_x_=l,this.layout_.evaluate(),this.renderGraph_(e),this.getStringOption("timingName")){var h=new Date;console.log(this.getStringOption("timingName")+" - drawGraph: "+(h-t)+"ms")}},j.prototype.renderGraph_=function(t){this.cascadeEvents_("clearChart"),this.plotter_.clear(),this.getFunctionOption("underlayCallback")&&this.getFunctionOption("underlayCallback").call(this,this.hidden_ctx_,this.layout_.getPlotArea(),this,this);var e={canvas:this.hidden_,drawingContext:this.hidden_ctx_};if(this.cascadeEvents_("willDrawChart",e),this.plotter_.render(),this.cascadeEvents_("didDrawChart",e),this.lastRow_=-1,this.canvas_.getContext("2d").clearRect(0,0,this.width_,this.height_),null!==this.getFunctionOption("drawCallback")&&this.getFunctionOption("drawCallback").call(this,this,t),t)for(this.readyFired_=!0;this.readyFns_.length>0;){var a=this.readyFns_.pop();a(this)}},j.prototype.computeYAxes_=function(){var t,e,a,i,n;if(void 0!==this.axes_&&this.user_attrs_.hasOwnProperty("valueRange")===!1)for(t=[],a=0;a<this.axes_.length;a++)t.push(this.axes_[a].valueWindow);for(this.axes_=[],e=0;e<this.attributes_.numAxes();e++)i={g:this},v.update(i,this.attributes_.axisOptions(e)),this.axes_[e]=i;if(n=this.attr_("valueRange"),n&&(this.axes_[0].valueRange=n),void 0!==t){var r=Math.min(t.length,this.axes_.length);for(a=0;a<r;a++)this.axes_[a].valueWindow=t[a]}for(e=0;e<this.axes_.length;e++)if(0===e)i=this.optionsViewForAxis_("y"+(e?"2":"")),n=i("valueRange"),n&&(this.axes_[e].valueRange=n);else{var o=this.user_attrs_.axes;o&&o.y2&&(n=o.y2.valueRange,n&&(this.axes_[e].valueRange=n))}},j.prototype.numAxes=function(){return this.attributes_.numAxes()},j.prototype.axisPropertiesForSeries=function(t){return this.axes_[this.attributes_.axisForSeries(t)]},j.prototype.computeYAxisRanges_=function(t){for(var e,a,i,n,r,o=function(t){return isNaN(parseFloat(t))},s=this.attributes_.numAxes(),l=0;l<s;l++){var h=this.axes_[l],u=this.attributes_.getForAxis("logscale",l),d=this.attributes_.getForAxis("includeZero",l),c=this.attributes_.getForAxis("independentTicks",l);if(i=this.attributes_.seriesForAxis(l),e=!0,n=.1,null!==this.getNumericOption("yRangePad")&&(e=!1,n=this.getNumericOption("yRangePad")/this.plotter_.area.h),0===i.length)h.extremeRange=[0,1];else{for(var p,g,f=1/0,v=-(1/0),_=0;_<i.length;_++)t.hasOwnProperty(i[_])&&(p=t[i[_]][0],null!==p&&(f=Math.min(p,f)),g=t[i[_]][1],null!==g&&(v=Math.max(g,v)));d&&!u&&(f>0&&(f=0),v<0&&(v=0)),f==1/0&&(f=0),v==-(1/0)&&(v=1),a=v-f,0===a&&(0!==v?a=Math.abs(v):(v=1,a=1));var y,x;if(u)if(e)y=v+n*a,x=f;else{var m=Math.exp(Math.log(a)*n);y=v*m,x=f/m}else y=v+n*a,x=f-n*a,e&&!this.getBooleanOption("avoidMinZero")&&(x<0&&f>=0&&(x=0),y>0&&v<=0&&(y=0));h.extremeRange=[x,y]}if(h.valueWindow)h.computedValueRange=[h.valueWindow[0],h.valueWindow[1]];else if(h.valueRange){var b=o(h.valueRange[0])?h.extremeRange[0]:h.valueRange[0],w=o(h.valueRange[1])?h.extremeRange[1]:h.valueRange[1];if(!e)if(h.logscale){var m=Math.exp(Math.log(a)*n);b*=m,w/=m}else a=w-b,b-=a*n,w+=a*n;h.computedValueRange=[b,w]}else h.computedValueRange=h.extremeRange;if(c){h.independentTicks=c;var A=this.optionsViewForAxis_("y"+(l?"2":"")),O=A("ticker");h.ticks=O(h.computedValueRange[0],h.computedValueRange[1],this.plotter_.area.h,A,this),r||(r=h)}}if(void 0===r)throw'Configuration Error: At least one axis has to have the "independentTicks" option activated.';for(var l=0;l<s;l++){var h=this.axes_[l];if(!h.independentTicks){for(var A=this.optionsViewForAxis_("y"+(l?"2":"")),O=A("ticker"),D=r.ticks,S=r.computedValueRange[1]-r.computedValueRange[0],T=h.computedValueRange[1]-h.computedValueRange[0],P=[],L=0;L<D.length;L++){var E=(D[L].v-r.computedValueRange[0])/S,C=h.computedValueRange[0]+E*T;P.push(C)}h.ticks=O(h.computedValueRange[0],h.computedValueRange[1],this.plotter_.area.h,A,this,P)}}},j.prototype.detectTypeFromString_=function(t){var e=!1,a=t.indexOf("-");a>0&&"e"!=t[a-1]&&"E"!=t[a-1]||t.indexOf("/")>=0||isNaN(parseFloat(t))?e=!0:8==t.length&&t>"19700101"&&t<"20371231"&&(e=!0),this.setXAxisOptions_(e)},j.prototype.setXAxisOptions_=function(t){t?(this.attrs_.xValueParser=v.dateParser,this.attrs_.axes.x.valueFormatter=v.dateValueFormatter,this.attrs_.axes.x.ticker=g.dateTicker,this.attrs_.axes.x.axisLabelFormatter=v.dateAxisLabelFormatter):(this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=g.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter)},j.prototype.parseCSV_=function(t){var e,a,i=[],n=v.detectLineDelimiter(t),r=t.split(n||"\n"),o=this.getStringOption("delimiter");r[0].indexOf(o)==-1&&r[0].indexOf("\t")>=0&&(o="\t");var s=0;"labels"in this.user_attrs_||(s=1,this.attrs_.labels=r[0].split(o),this.attributes_.reparseSeries());for(var l,h=0,u=!1,d=this.attr_("labels").length,c=!1,p=s;p<r.length;p++){var g=r[p];if(h=p,0!==g.length&&"#"!=g[0]){var f=g.split(o);if(!(f.length<2)){var _=[];if(u||(this.detectTypeFromString_(f[0]),l=this.getFunctionOption("xValueParser"),u=!0),_[0]=l(f[0],this),this.fractions_)for(a=1;a<f.length;a++)e=f[a].split("/"),2!=e.length?(console.error('Expected fractional "num/den" values in CSV data but found a value \''+f[a]+"' on line "+(1+p)+" ('"+g+"') which is not of this form."),_[a]=[0,0]):_[a]=[v.parseFloat_(e[0],p,g),v.parseFloat_(e[1],p,g)];else if(this.getBooleanOption("errorBars"))for(f.length%2!=1&&console.error("Expected alternating (value, stdev.) pairs in CSV data but line "+(1+p)+" has an odd number of values ("+(f.length-1)+"): '"+g+"'"),a=1;a<f.length;a+=2)_[(a+1)/2]=[v.parseFloat_(f[a],p,g),v.parseFloat_(f[a+1],p,g)];else if(this.getBooleanOption("customBars"))for(a=1;a<f.length;a++){var y=f[a];/^ *$/.test(y)?_[a]=[null,null,null]:(e=y.split(";"),3==e.length?_[a]=[v.parseFloat_(e[0],p,g),v.parseFloat_(e[1],p,g),v.parseFloat_(e[2],p,g)]:console.warn('When using customBars, values must be either blank or "low;center;high" tuples (got "'+y+'" on line '+(1+p)))}else for(a=1;a<f.length;a++)_[a]=v.parseFloat_(f[a],p,g);if(i.length>0&&_[0]<i[i.length-1][0]&&(c=!0),_.length!=d&&console.error("Number of columns in line "+p+" ("+_.length+") does not agree with number of labels ("+d+") "+g),0===p&&this.attr_("labels")){var x=!0;for(a=0;x&&a<_.length;a++)_[a]&&(x=!1);if(x){console.warn("The dygraphs 'labels' option is set, but the first row of CSV data ('"+g+"') appears to also contain labels. Will drop the CSV labels and use the option labels.");continue}}i.push(_)}}}return c&&(console.warn("CSV is out of order; order it correctly to speed loading."),i.sort(function(t,e){return t[0]-e[0]})),i},j.prototype.parseArray_=function(t){if(0===t.length)return console.error("Can't plot empty data set"),null;if(0===t[0].length)return console.error("Data set cannot contain an empty row"),null;var e;if(null===this.attr_("labels")){for(console.warn("Using default labels. Set labels explicitly via 'labels' in the options parameter"),this.attrs_.labels=["X"],e=1;e<t[0].length;e++)this.attrs_.labels.push("Y"+e);this.attributes_.reparseSeries()}else{var a=this.attr_("labels");if(a.length!=t[0].length)return console.error("Mismatch between number of labels ("+a+") and number of columns in array ("+t[0].length+")"),null}if(v.isDateLike(t[0][0])){this.attrs_.axes.x.valueFormatter=v.dateValueFormatter,this.attrs_.axes.x.ticker=g.dateTicker,this.attrs_.axes.x.axisLabelFormatter=v.dateAxisLabelFormatter;var i=v.clone(t);for(e=0;e<t.length;e++){if(0===i[e].length)return console.error("Row "+(1+e)+" of data is empty"),null;if(null===i[e][0]||"function"!=typeof i[e][0].getTime||isNaN(i[e][0].getTime()))return console.error("x value in row "+(1+e)+" is not a Date"),null;i[e][0]=i[e][0].getTime()}return i}return this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=g.numericTicks,this.attrs_.axes.x.axisLabelFormatter=v.numberAxisLabelFormatter,t},j.prototype.parseDataTable_=function(t){var e=function(t){var e=String.fromCharCode(65+t%26);for(t=Math.floor(t/26);t>0;)e=String.fromCharCode(65+(t-1)%26)+e.toLowerCase(),t=Math.floor((t-1)/26);return e},a=t.getNumberOfColumns(),i=t.getNumberOfRows(),n=t.getColumnType(0);if("date"==n||"datetime"==n)this.attrs_.xValueParser=v.dateParser,this.attrs_.axes.x.valueFormatter=v.dateValueFormatter,this.attrs_.axes.x.ticker=g.dateTicker,this.attrs_.axes.x.axisLabelFormatter=v.dateAxisLabelFormatter;else{if("number"!=n)throw new Error("only 'date', 'datetime' and 'number' types are supported for column 1 of DataTable input (Got '"+n+"')");this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=g.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter}var r,o,s=[],l={},h=!1;for(r=1;r<a;r++){var u=t.getColumnType(r);if("number"==u)s.push(r);else{if("string"!=u||!this.getBooleanOption("displayAnnotations"))throw new Error("Only 'number' is supported as a dependent type with Gviz. 'string' is only supported if displayAnnotations is true");var d=s[s.length-1];l.hasOwnProperty(d)?l[d].push(r):l[d]=[r],h=!0}}var c=[t.getColumnLabel(0)];for(r=0;r<s.length;r++)c.push(t.getColumnLabel(s[r])),this.getBooleanOption("errorBars")&&(r+=1);this.attrs_.labels=c,a=c.length;var p=[],f=!1,_=[];for(r=0;r<i;r++){var y=[];if("undefined"!=typeof t.getValue(r,0)&&null!==t.getValue(r,0)){if("date"==n||"datetime"==n?y.push(t.getValue(r,0).getTime()):y.push(t.getValue(r,0)),this.getBooleanOption("errorBars"))for(o=0;o<a-1;o++)y.push([t.getValue(r,1+2*o),t.getValue(r,2+2*o)]);else{for(o=0;o<s.length;o++){var x=s[o];if(y.push(t.getValue(r,x)),h&&l.hasOwnProperty(x)&&null!==t.getValue(r,l[x][0])){var m={};m.series=t.getColumnLabel(x),m.xval=y[0],m.shortText=e(_.length),m.text="";for(var b=0;b<l[x].length;b++)b&&(m.text+="\n"),m.text+=t.getValue(r,l[x][b]);_.push(m)}}for(o=0;o<y.length;o++)isFinite(y[o])||(y[o]=null)}p.length>0&&y[0]<p[p.length-1][0]&&(f=!0),p.push(y)}else console.warn("Ignoring row "+r+" of DataTable because of undefined or null first column.")}f&&(console.warn("DataTable is out of order; order it correctly to speed loading."),p.sort(function(t,e){return t[0]-e[0]})),this.rawData_=p,_.length>0&&this.setAnnotations(_,!0),this.attributes_.reparseSeries()},j.prototype.cascadeDataDidUpdateEvent_=function(){this.cascadeEvents_("dataDidUpdate",{})},j.prototype.start_=function(){var t=this.file_;if("function"==typeof t&&(t=t()),v.isArrayLike(t))this.rawData_=this.parseArray_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_();else if("object"==typeof t&&"function"==typeof t.getColumnRange)this.parseDataTable_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_();else if("string"==typeof t){var e=v.detectLineDelimiter(t);if(e)this.loadedEvent_(t);else{var a;a=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");var i=this;a.onreadystatechange=function(){4==a.readyState&&(200!==a.status&&0!==a.status||i.loadedEvent_(a.responseText))},a.open("GET",t,!0),a.send(null)}}else console.error("Unknown data format: "+typeof t)},j.prototype.updateOptions=function(t,e){"undefined"==typeof e&&(e=!1);var a=t.file,i=j.copyUserAttrs_(t);"rollPeriod"in i&&(this.rollPeriod_=i.rollPeriod),"dateWindow"in i&&(this.dateWindow_=i.dateWindow,"isZoomedIgnoreProgrammaticZoom"in i||(this.zoomed_x_=null!==i.dateWindow)),"valueRange"in i&&!("isZoomedIgnoreProgrammaticZoom"in i)&&(this.zoomed_y_=null!==i.valueRange);var n=v.isPixelChangingOptionList(this.attr_("labels"),i);v.updateDeep(this.user_attrs_,i),this.attributes_.reparseSeries(),a?(this.cascadeEvents_("dataWillUpdate",{}),this.file_=a,e||this.start_()):e||(n?this.predraw_():this.renderGraph_(!1))},j.copyUserAttrs_=function(t){var e={};for(var a in t)t.hasOwnProperty(a)&&"file"!=a&&t.hasOwnProperty(a)&&(e[a]=t[a]);return e},j.prototype.resize=function(t,e){if(!this.resize_lock){this.resize_lock=!0,null===t!=(null===e)&&(console.warn("Dygraph.resize() should be called with zero parameters or two non-NULL parameters. Pretending it was zero."),t=e=null);var a=this.width_,i=this.height_;t?(this.maindiv_.style.width=t+"px",this.maindiv_.style.height=e+"px",this.width_=t,this.height_=e):(this.width_=this.maindiv_.clientWidth,this.height_=this.maindiv_.clientHeight),a==this.width_&&i==this.height_||(this.resizeElements_(),this.predraw_()),this.resize_lock=!1}},j.prototype.adjustRoll=function(t){this.rollPeriod_=t,this.predraw_()},j.prototype.visibility=function(){for(this.getOption("visibility")||(this.attrs_.visibility=[]);this.getOption("visibility").length<this.numColumns()-1;)this.attrs_.visibility.push(!0);return this.getOption("visibility")},j.prototype.setVisibility=function(t,e){var a=this.visibility(),i=!1;if(Array.isArray(t)||(null!==t&&"object"==typeof t?i=!0:t=[t]),i)for(var n in t)t.hasOwnProperty(n)&&(n<0||n>=a.length?console.warn("Invalid series number in setVisibility: "+n):a[n]=t[n]);else for(var n=0;n<t.length;n++)"boolean"==typeof t[n]?n>=a.length?console.warn("Invalid series number in setVisibility: "+n):a[n]=t[n]:t[n]<0||t[n]>=a.length?console.warn("Invalid series number in setVisibility: "+t[n]):a[t[n]]=e;this.predraw_()},j.prototype.size=function(){return{width:this.width_,height:this.height_}},j.prototype.setAnnotations=function(t,e){return j.addAnnotationRule(),this.annotations_=t,this.layout_?(this.layout_.setAnnotations(this.annotations_),void(e||this.predraw_())):void console.warn("Tried to setAnnotations before dygraph was ready. Try setting them in a ready() block. See dygraphs.com/tests/annotation.html")},j.prototype.annotations=function(){return this.annotations_},j.prototype.getLabels=function(){var t=this.attr_("labels");return t?t.slice():null},j.prototype.indexFromSetName=function(t){return this.setIndexByName_[t]},j.prototype.getRowForX=function(t){for(var e=0,a=this.numRows()-1;e<=a;){var i=a+e>>1,n=this.getValue(i,0);if(n<t)e=i+1;else if(n>t)a=i-1;else{if(e==i)return i;a=i}}return null},j.prototype.ready=function(t){this.is_initial_draw_?this.readyFns_.push(t):t.call(this,this)},j.addAnnotationRule=function(){if(!j.addedAnnotationCSS){var t="border: 1px solid black; background-color: white; text-align: center;",e=document.createElement("style");e.type="text/css",document.getElementsByTagName("head")[0].appendChild(e);for(var a=0;a<document.styleSheets.length;a++)if(!document.styleSheets[a].disabled){var i=document.styleSheets[a];try{if(i.insertRule){var n=i.cssRules?i.cssRules.length:0;i.insertRule(".dygraphDefaultAnnotation { "+t+" }",n)}else i.addRule&&i.addRule(".dygraphDefaultAnnotation",t);return void(j.addedAnnotationCSS=!0)}catch(t){}}console.warn("Unable to add default annotation CSS rule; display may be off.")}},j.prototype.addAndTrackEvent=function(t,e,a){v.addEvent(t,e,a),this.registeredEvents_.push({elem:t,type:e,fn:a})},j.prototype.removeTrackedEvents_=function(){if(this.registeredEvents_)for(var t=0;t<this.registeredEvents_.length;t++){var e=this.registeredEvents_[t];v.removeEvent(e.elem,e.type,e.fn)}this.registeredEvents_=[]},j.PLUGINS=[Z.default,I.default,B.default,Y.default,F.default,V.default],j.GVizChart=U.default,j.DASHED_LINE=v.DASHED_LINE,j.DOT_DASH_LINE=v.DOT_DASH_LINE,j.dateAxisLabelFormatter=v.dateAxisLabelFormatter,j.toRGB_=v.toRGB_,j.findPos=v.findPos,j.pageX=v.pageX,j.pageY=v.pageY,j.dateString_=v.dateString_,j.defaultInteractionModel=c.default.defaultModel,j.nonInteractiveModel=j.nonInteractiveModel_=c.default.nonInteractiveModel_,j.Circles=v.Circles,j.Plugins={Legend:Z.default,Axes:I.default,Annotations:F.default,ChartLabels:Y.default,Grid:V.default,RangeSelector:B.default},j.DataHandlers={DefaultHandler:A.default,BarsHandler:k.default,CustomBarsHandler:T.default,DefaultFractionHandler:L.default,ErrorBarsHandler:D.default,FractionsBarsHandler:C.default},j.startPan=c.default.startPan,j.startZoom=c.default.startZoom,j.movePan=c.default.movePan,j.moveZoom=c.default.moveZoom,j.endPan=c.default.endPan,j.endZoom=c.default.endZoom,j.numericLinearTicks=g.numericLinearTicks,j.numericTicks=g.numericTicks,j.dateTicker=g.dateTicker,j.Granularity=g.Granularity,j.getDateAxis=g.getDateAxis,j.floatFormat=v.floatFormat,a.default=j,e.exports=a.default},{"./datahandler/bars":4,"./datahandler/bars-custom":1,"./datahandler/bars-error":2,"./datahandler/bars-fractions":3,"./datahandler/default":7,"./datahandler/default-fractions":6,"./dygraph-canvas":8,"./dygraph-default-attrs":9,"./dygraph-gviz":10,"./dygraph-interaction-model":11,"./dygraph-layout":12,"./dygraph-options":14,"./dygraph-options-reference":13,"./dygraph-tickers":15,"./dygraph-utils":16,"./iframe-tarp":18,"./plugins/annotations":19,"./plugins/axes":20,"./plugins/chart-labels":21,"./plugins/grid":22,"./plugins/legend":23,"./plugins/range-selector":24}],18:[function(t,e,a){"use strict";function i(){this.tarps=[]}Object.defineProperty(a,"__esModule",{value:!0}),i.prototype.cover=function(){for(var t=document.getElementsByTagName("iframe"),e=0;e<t.length;e++){var a=t[e],i=utils.findPos(a),n=i.x,r=i.y,o=a.offsetWidth,s=a.offsetHeight,l=document.createElement("div");l.style.position="absolute",l.style.left=n+"px",l.style.top=r+"px",l.style.width=o+"px",l.style.height=s+"px",l.style.zIndex=999,document.body.appendChild(l),this.tarps.push(l)}},i.prototype.uncover=function(){for(var t=0;t<this.tarps.length;t++)this.tarps[t].parentNode.removeChild(this.tarps[t]);this.tarps=[]},a.default=i,e.exports=a.default},{}],19:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){this.annotations_=[]};i.prototype.toString=function(){return"Annotations Plugin"},i.prototype.activate=function(t){return{clearChart:this.clearChart,didDrawChart:this.didDrawChart}},i.prototype.detachLabels=function(){for(var t=0;t<this.annotations_.length;t++){var e=this.annotations_[t];e.parentNode&&e.parentNode.removeChild(e),this.annotations_[t]=null}this.annotations_=[]},i.prototype.clearChart=function(t){this.detachLabels()},i.prototype.didDrawChart=function(t){var e=t.dygraph,a=e.layout_.annotated_points;if(a&&0!==a.length)for(var i=t.canvas.parentNode,n={position:"absolute",fontSize:e.getOption("axisLabelFontSize")+"px",zIndex:10,overflow:"hidden"},r=function(t,a,i){return function(n){var r=i.annotation;r.hasOwnProperty(t)?r[t](r,i,e,n):e.getOption(a)&&e.getOption(a)(r,i,e,n)}},o=t.dygraph.plotter_.area,s={},l=0;l<a.length;l++){var h=a[l];if(!(h.canvasx<o.x||h.canvasx>o.x+o.w||h.canvasy<o.y||h.canvasy>o.y+o.h)){var u=h.annotation,d=6;u.hasOwnProperty("tickHeight")&&(d=u.tickHeight);var c=document.createElement("div");for(var p in n)n.hasOwnProperty(p)&&(c.style[p]=n[p]);u.hasOwnProperty("icon")||(c.className="dygraphDefaultAnnotation"),u.hasOwnProperty("cssClass")&&(c.className+=" "+u.cssClass);var g=u.hasOwnProperty("width")?u.width:16,f=u.hasOwnProperty("height")?u.height:16;if(u.hasOwnProperty("icon")){var v=document.createElement("img");v.src=u.icon,v.width=g,v.height=f,c.appendChild(v)}else h.annotation.hasOwnProperty("shortText")&&c.appendChild(document.createTextNode(h.annotation.shortText));var _=h.canvasx-g/2;c.style.left=_+"px";var y=0;if(u.attachAtBottom){var x=o.y+o.h-f-d;s[_]?x-=s[_]:s[_]=0,s[_]+=d+f,y=x}else y=h.canvasy-f-d;c.style.top=y+"px",c.style.width=g+"px",c.style.height=f+"px",c.title=h.annotation.text,c.style.color=e.colorsMap_[h.name],c.style.borderColor=e.colorsMap_[h.name],u.div=c,e.addAndTrackEvent(c,"click",r("clickHandler","annotationClickHandler",h,this)),e.addAndTrackEvent(c,"mouseover",r("mouseOverHandler","annotationMouseOverHandler",h,this)),e.addAndTrackEvent(c,"mouseout",r("mouseOutHandler","annotationMouseOutHandler",h,this)),e.addAndTrackEvent(c,"dblclick",r("dblClickHandler","annotationDblClickHandler",h,this)),i.appendChild(c),this.annotations_.push(c);var m=t.drawingContext;if(m.save(),m.strokeStyle=e.colorsMap_[h.name],
+m.beginPath(),u.attachAtBottom){var x=y+f;m.moveTo(h.canvasx,x),m.lineTo(h.canvasx,x+d)}else m.moveTo(h.canvasx,h.canvasy),m.lineTo(h.canvasx,h.canvasy-2-d);m.closePath(),m.stroke(),m.restore()}}},i.prototype.destroy=function(){this.detachLabels()},a.default=i,e.exports=a.default},{}],20:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){this.xlabels_=[],this.ylabels_=[]};i.prototype.toString=function(){return"Axes Plugin"},i.prototype.activate=function(t){return{layout:this.layout,clearChart:this.clearChart,willDrawChart:this.willDrawChart}},i.prototype.layout=function(t){var e=t.dygraph;if(e.getOptionForAxis("drawAxis","y")){var a=e.getOptionForAxis("axisLabelWidth","y")+2*e.getOptionForAxis("axisTickSize","y");t.reserveSpaceLeft(a)}if(e.getOptionForAxis("drawAxis","x")){var i;i=e.getOption("xAxisHeight")?e.getOption("xAxisHeight"):e.getOptionForAxis("axisLabelFontSize","x")+2*e.getOptionForAxis("axisTickSize","x"),t.reserveSpaceBottom(i)}if(2==e.numAxes()){if(e.getOptionForAxis("drawAxis","y2")){var a=e.getOptionForAxis("axisLabelWidth","y2")+2*e.getOptionForAxis("axisTickSize","y2");t.reserveSpaceRight(a)}}else e.numAxes()>2&&e.error("Only two y-axes are supported at this time. (Trying to use "+e.numAxes()+")")},i.prototype.detachLabels=function(){function t(t){for(var e=0;e<t.length;e++){var a=t[e];a.parentNode&&a.parentNode.removeChild(a)}}t(this.xlabels_),t(this.ylabels_),this.xlabels_=[],this.ylabels_=[]},i.prototype.clearChart=function(t){this.detachLabels()},i.prototype.willDrawChart=function(t){function e(t){return Math.round(t)+.5}function a(t){return Math.round(t)-.5}var i=t.dygraph;if(i.getOptionForAxis("drawAxis","x")||i.getOptionForAxis("drawAxis","y")||i.getOptionForAxis("drawAxis","y2")){var n,r,o,s,l,h=t.drawingContext,u=t.canvas.parentNode,d=i.width_,c=i.height_,p=function(t){return{position:"absolute",fontSize:i.getOptionForAxis("axisLabelFontSize",t)+"px",zIndex:10,color:i.getOptionForAxis("axisLabelColor",t),width:i.getOptionForAxis("axisLabelWidth",t)+"px",lineHeight:"normal",overflow:"hidden"}},g={x:p("x"),y:p("y"),y2:p("y2")},f=function(t,e,a){var i=document.createElement("div"),n=g["y2"==a?"y2":e];for(var r in n)n.hasOwnProperty(r)&&(i.style[r]=n[r]);var o=document.createElement("div");return o.className="dygraph-axis-label dygraph-axis-label-"+e+(a?" dygraph-axis-label-"+a:""),o.innerHTML=t,i.appendChild(o),i};h.save();var v=i.layout_,_=t.dygraph.plotter_.area,y=function(t){return function(e){return i.getOptionForAxis(e,t)}};if(i.getOptionForAxis("drawAxis","y")){if(v.yticks&&v.yticks.length>0){var x=i.numAxes(),m=[y("y"),y("y2")];for(l=0;l<v.yticks.length;l++){if(s=v.yticks[l],"function"==typeof s)return;r=_.x;var b=1,w="y1",A=m[0];1==s[0]&&(r=_.x+_.w,b=-1,w="y2",A=m[1]);var O=A("axisLabelFontSize");o=_.y+s[1]*_.h,n=f(s[2],"y",2==x?w:null);var D=o-O/2;D<0&&(D=0),D+O+3>c?n.style.bottom="0":n.style.top=D+"px",0===s[0]?(n.style.left=_.x-A("axisLabelWidth")-A("axisTickSize")+"px",n.style.textAlign="right"):1==s[0]&&(n.style.left=_.x+_.w+A("axisTickSize")+"px",n.style.textAlign="left"),n.style.width=A("axisLabelWidth")+"px",u.appendChild(n),this.ylabels_.push(n)}var S=this.ylabels_[0],O=i.getOptionForAxis("axisLabelFontSize","y"),T=parseInt(S.style.top,10)+O;T>c-O&&(S.style.top=parseInt(S.style.top,10)-O/2+"px")}var P;if(i.getOption("drawAxesAtZero")){var L=i.toPercentXCoord(0);(L>1||L<0||isNaN(L))&&(L=0),P=e(_.x+L*_.w)}else P=e(_.x);h.strokeStyle=i.getOptionForAxis("axisLineColor","y"),h.lineWidth=i.getOptionForAxis("axisLineWidth","y"),h.beginPath(),h.moveTo(P,a(_.y)),h.lineTo(P,a(_.y+_.h)),h.closePath(),h.stroke(),2==i.numAxes()&&(h.strokeStyle=i.getOptionForAxis("axisLineColor","y2"),h.lineWidth=i.getOptionForAxis("axisLineWidth","y2"),h.beginPath(),h.moveTo(a(_.x+_.w),a(_.y)),h.lineTo(a(_.x+_.w),a(_.y+_.h)),h.closePath(),h.stroke())}if(i.getOptionForAxis("drawAxis","x")){if(v.xticks){var A=y("x");for(l=0;l<v.xticks.length;l++){s=v.xticks[l],r=_.x+s[0]*_.w,o=_.y+_.h,n=f(s[1],"x"),n.style.textAlign="center",n.style.top=o+A("axisTickSize")+"px";var E=r-A("axisLabelWidth")/2;E+A("axisLabelWidth")>d&&(E=d-A("axisLabelWidth"),n.style.textAlign="right"),E<0&&(E=0,n.style.textAlign="left"),n.style.left=E+"px",n.style.width=A("axisLabelWidth")+"px",u.appendChild(n),this.xlabels_.push(n)}}h.strokeStyle=i.getOptionForAxis("axisLineColor","x"),h.lineWidth=i.getOptionForAxis("axisLineWidth","x"),h.beginPath();var C;if(i.getOption("drawAxesAtZero")){var L=i.toPercentYCoord(0,0);(L>1||L<0)&&(L=1),C=a(_.y+L*_.h)}else C=a(_.y+_.h);h.moveTo(e(_.x),C),h.lineTo(e(_.x+_.w),C),h.closePath(),h.stroke()}h.restore()}},a.default=i,e.exports=a.default},{}],21:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null};i.prototype.toString=function(){return"ChartLabels Plugin"},i.prototype.activate=function(t){return{layout:this.layout,didDrawChart:this.didDrawChart}};var n=function(t){var e=document.createElement("div");return e.style.position="absolute",e.style.left=t.x+"px",e.style.top=t.y+"px",e.style.width=t.w+"px",e.style.height=t.h+"px",e};i.prototype.detachLabels_=function(){for(var t=[this.title_div_,this.xlabel_div_,this.ylabel_div_,this.y2label_div_],e=0;e<t.length;e++){var a=t[e];a&&a.parentNode&&a.parentNode.removeChild(a)}this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null};var r=function(t,e,a,i,n){var r=document.createElement("div");r.style.position="absolute",1==a?r.style.left="0px":r.style.left=e.x+"px",r.style.top=e.y+"px",r.style.width=e.w+"px",r.style.height=e.h+"px",r.style.fontSize=t.getOption("yLabelWidth")-2+"px";var o=document.createElement("div");o.style.position="absolute",o.style.width=e.h+"px",o.style.height=e.w+"px",o.style.top=e.h/2-e.w/2+"px",o.style.left=e.w/2-e.h/2+"px",o.style.textAlign="center";var s="rotate("+(1==a?"-":"")+"90deg)";o.style.transform=s,o.style.WebkitTransform=s,o.style.MozTransform=s,o.style.OTransform=s,o.style.msTransform=s;var l=document.createElement("div");return l.className=i,l.innerHTML=n,o.appendChild(l),r.appendChild(o),r};i.prototype.layout=function(t){this.detachLabels_();var e=t.dygraph,a=t.chart_div;if(e.getOption("title")){var i=t.reserveSpaceTop(e.getOption("titleHeight"));this.title_div_=n(i),this.title_div_.style.textAlign="center",this.title_div_.style.fontSize=e.getOption("titleHeight")-8+"px",this.title_div_.style.fontWeight="bold",this.title_div_.style.zIndex=10;var o=document.createElement("div");o.className="dygraph-label dygraph-title",o.innerHTML=e.getOption("title"),this.title_div_.appendChild(o),a.appendChild(this.title_div_)}if(e.getOption("xlabel")){var s=t.reserveSpaceBottom(e.getOption("xLabelHeight"));this.xlabel_div_=n(s),this.xlabel_div_.style.textAlign="center",this.xlabel_div_.style.fontSize=e.getOption("xLabelHeight")-2+"px";var o=document.createElement("div");o.className="dygraph-label dygraph-xlabel",o.innerHTML=e.getOption("xlabel"),this.xlabel_div_.appendChild(o),a.appendChild(this.xlabel_div_)}if(e.getOption("ylabel")){var l=t.reserveSpaceLeft(0);this.ylabel_div_=r(e,l,1,"dygraph-label dygraph-ylabel",e.getOption("ylabel")),a.appendChild(this.ylabel_div_)}if(e.getOption("y2label")&&2==e.numAxes()){var h=t.reserveSpaceRight(0);this.y2label_div_=r(e,h,2,"dygraph-label dygraph-y2label",e.getOption("y2label")),a.appendChild(this.y2label_div_)}},i.prototype.didDrawChart=function(t){var e=t.dygraph;this.title_div_&&(this.title_div_.children[0].innerHTML=e.getOption("title")),this.xlabel_div_&&(this.xlabel_div_.children[0].innerHTML=e.getOption("xlabel")),this.ylabel_div_&&(this.ylabel_div_.children[0].children[0].innerHTML=e.getOption("ylabel")),this.y2label_div_&&(this.y2label_div_.children[0].children[0].innerHTML=e.getOption("y2label"))},i.prototype.clearChart=function(){},i.prototype.destroy=function(){this.detachLabels_()},a.default=i,e.exports=a.default},{}],22:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){};i.prototype.toString=function(){return"Gridline Plugin"},i.prototype.activate=function(t){return{willDrawChart:this.willDrawChart}},i.prototype.willDrawChart=function(t){function e(t){return Math.round(t)+.5}function a(t){return Math.round(t)-.5}var i,n,r,o,s=t.dygraph,l=t.drawingContext,h=s.layout_,u=t.dygraph.plotter_.area;if(s.getOptionForAxis("drawGrid","y")){for(var d=["y","y2"],c=[],p=[],g=[],f=[],v=[],r=0;r<d.length;r++)g[r]=s.getOptionForAxis("drawGrid",d[r]),g[r]&&(c[r]=s.getOptionForAxis("gridLineColor",d[r]),p[r]=s.getOptionForAxis("gridLineWidth",d[r]),v[r]=s.getOptionForAxis("gridLinePattern",d[r]),f[r]=v[r]&&v[r].length>=2);for(o=h.yticks,l.save(),r=0;r<o.length;r++){var _=o[r][0];g[_]&&(l.save(),f[_]&&l.setLineDash&&l.setLineDash(v[_]),l.strokeStyle=c[_],l.lineWidth=p[_],i=e(u.x),n=a(u.y+o[r][1]*u.h),l.beginPath(),l.moveTo(i,n),l.lineTo(i+u.w,n),l.stroke(),l.restore())}l.restore()}if(s.getOptionForAxis("drawGrid","x")){o=h.xticks,l.save();var v=s.getOptionForAxis("gridLinePattern","x"),f=v&&v.length>=2;for(f&&l.setLineDash&&l.setLineDash(v),l.strokeStyle=s.getOptionForAxis("gridLineColor","x"),l.lineWidth=s.getOptionForAxis("gridLineWidth","x"),r=0;r<o.length;r++)i=e(u.x+o[r][0]*u.w),n=a(u.y+u.h),l.beginPath(),l.moveTo(i,n),l.lineTo(i,u.y),l.closePath(),l.stroke();f&&l.setLineDash&&l.setLineDash([]),l.restore()}},i.prototype.destroy=function(){},a.default=i,e.exports=a.default},{}],23:[function(t,e,a){"use strict";function i(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var n=t("../dygraph-utils"),r=i(n),o=function(){this.legend_div_=null,this.is_generated_div_=!1};o.prototype.toString=function(){return"Legend Plugin"};var s;o.prototype.activate=function(t){var e,a=t.getOption("labelsDivWidth"),i=t.getOption("labelsDiv");if(i&&null!==i)e="string"==typeof i||i instanceof String?document.getElementById(i):i;else{var n={position:"absolute",fontSize:"14px",zIndex:10,width:a+"px",top:"0px",left:t.size().width-a-2+"px",background:"white",lineHeight:"normal",textAlign:"left",overflow:"hidden"};r.update(n,t.getOption("labelsDivStyles")),e=document.createElement("div"),e.className="dygraph-legend";for(var o in n)if(n.hasOwnProperty(o))try{e.style[o]=n[o]}catch(t){console.warn("You are using unsupported css properties for your browser in labelsDivStyles")}t.graphDiv.appendChild(e),this.is_generated_div_=!0}return this.legend_div_=e,this.one_em_width_=10,{select:this.select,deselect:this.deselect,predraw:this.predraw,didDrawChart:this.didDrawChart}};var l=function(t){var e=document.createElement("span");e.setAttribute("style","margin: 0; padding: 0 0 0 1em; border: 0;"),t.appendChild(e);var a=e.offsetWidth;return t.removeChild(e),a},h=function(t){return t.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")};o.prototype.select=function(t){var e=t.selectedX,a=t.selectedPoints,i=t.selectedRow,n=t.dygraph.getOption("legend");if("never"===n)return void(this.legend_div_.style.display="none");if("follow"===n){var r=t.dygraph.plotter_.area,s=t.dygraph.getOption("labelsDivWidth"),l=t.dygraph.getOptionForAxis("axisLabelWidth","y"),h=a[0].x*r.w+50,u=a[0].y*r.h-50;h+s+1>r.w&&(h=h-100-s-(l-r.x)),t.dygraph.graphDiv.appendChild(this.legend_div_),this.legend_div_.style.left=l+h+"px",this.legend_div_.style.top=u+"px"}var d=o.generateLegendHTML(t.dygraph,e,a,this.one_em_width_,i);this.legend_div_.innerHTML=d,this.legend_div_.style.display=""},o.prototype.deselect=function(t){var e=t.dygraph.getOption("legend");"always"!==e&&(this.legend_div_.style.display="none");var a=l(this.legend_div_);this.one_em_width_=a;var i=o.generateLegendHTML(t.dygraph,void 0,void 0,a,null);this.legend_div_.innerHTML=i},o.prototype.didDrawChart=function(t){this.deselect(t)},o.prototype.predraw=function(t){if(this.is_generated_div_){t.dygraph.graphDiv.appendChild(this.legend_div_);var e=t.dygraph.getArea(),a=t.dygraph.getOption("labelsDivWidth");this.legend_div_.style.left=e.x+e.w-a-1+"px",this.legend_div_.style.top=e.y+"px",this.legend_div_.style.width=a+"px"}},o.prototype.destroy=function(){this.legend_div_=null},o.generateLegendHTML=function(t,e,a,i,n){var l={dygraph:t,x:e,series:[]},u={},d=t.getLabels();if(d)for(var c=1;c<d.length;c++){var p=t.getPropertiesForSeries(d[c]),g=t.getOption("strokePattern",d[c]),f={dashHTML:s(g,p.color,i),label:d[c],labelHTML:h(d[c]),isVisible:p.visible,color:p.color};l.series.push(f),u[d[c]]=f}if("undefined"!=typeof e){var v=t.optionsViewForAxis_("x"),_=v("valueFormatter");l.xHTML=_.call(t,e,v,d[0],t,n,0);for(var y=[],x=t.numAxes(),c=0;c<x;c++)y[c]=t.optionsViewForAxis_("y"+(c?1+c:""));var m=t.getOption("labelsShowZeroValues"),b=t.getHighlightSeries();for(c=0;c<a.length;c++){var w=a[c],f=u[w.name];if(f.y=w.yval,0===w.yval&&!m||isNaN(w.canvasy))f.isVisible=!1;else{var p=t.getPropertiesForSeries(w.name),A=y[p.axis-1],O=A("valueFormatter"),D=O.call(t,w.yval,A,w.name,t,n,d.indexOf(w.name));r.update(f,{yHTML:D}),w.name==b&&(f.isHighlighted=!0)}}}var S=t.getOption("legendFormatter")||o.defaultFormatter;return S.call(t,l)},o.defaultFormatter=function(t){var e=t.dygraph;if(e.getOption("showLabelsOnHighlight")!==!0)return"";var a,i=e.getOption("labelsSeparateLines");if("undefined"==typeof t.x){if("always"!=e.getOption("legend"))return"";a="";for(var n=0;n<t.series.length;n++){var r=t.series[n];r.isVisible&&(""!==a&&(a+=i?"<br/>":" "),a+="<span style='font-weight: bold; color: "+r.color+";'>"+r.dashHTML+" "+r.labelHTML+"</span>")}return a}a=t.xHTML+":";for(var n=0;n<t.series.length;n++){var r=t.series[n];if(r.isVisible){i&&(a+="<br>");var o=r.isHighlighted?' class="highlight"':"";a+="<span"+o+"> <b><span style='color: "+r.color+";'>"+r.labelHTML+"</span></b>:&#160;"+r.yHTML+"</span>"}}return a},s=function(t,e,a){if(!t||t.length<=1)return'<div style="display: inline-block; position: relative; bottom: .5ex; padding-left: 1em; height: 1px; border-bottom: 2px solid '+e+';"></div>';var i,n,r,o,s,l=0,h=0,u=[];for(i=0;i<=t.length;i++)l+=t[i%t.length];if(s=Math.floor(a/(l-t[0])),s>1){for(i=0;i<t.length;i++)u[i]=t[i]/a;h=u.length}else{for(s=1,i=0;i<t.length;i++)u[i]=t[i]/l;h=u.length+1}var d="";for(n=0;n<s;n++)for(i=0;i<h;i+=2)r=u[i%u.length],o=i<t.length?u[(i+1)%u.length]:0,d+='<div style="display: inline-block; position: relative; bottom: .5ex; margin-right: '+o+"em; padding-left: "+r+"em; height: 1px; border-bottom: 2px solid "+e+';"></div>';return d},a.default=o,e.exports=a.default},{"../dygraph-utils":16}],24:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var r=t("../dygraph-utils"),o=n(r),s=t("../dygraph-interaction-model"),l=i(s),h=t("../iframe-tarp"),u=i(h),d=function(){this.hasTouchInterface_="undefined"!=typeof TouchEvent,this.isMobileDevice_=/mobile|android/gi.test(navigator.appVersion),this.interfaceCreated_=!1};d.prototype.toString=function(){return"RangeSelector Plugin"},d.prototype.activate=function(t){return this.dygraph_=t,this.getOption_("showRangeSelector")&&this.createInterface_(),{layout:this.reserveSpace_,predraw:this.renderStaticLayer_,didDrawChart:this.renderInteractiveLayer_}},d.prototype.destroy=function(){this.bgcanvas_=null,this.fgcanvas_=null,this.leftZoomHandle_=null,this.rightZoomHandle_=null},d.prototype.getOption_=function(t,e){return this.dygraph_.getOption(t,e)},d.prototype.setDefaultOption_=function(t,e){this.dygraph_.attrs_[t]=e},d.prototype.createInterface_=function(){this.createCanvases_(),this.createZoomHandles_(),this.initInteraction_(),this.getOption_("animatedZooms")&&(console.warn("Animated zooms and range selector are not compatible; disabling animatedZooms."),this.dygraph_.updateOptions({animatedZooms:!1},!0)),this.interfaceCreated_=!0,this.addToGraph_()},d.prototype.addToGraph_=function(){var t=this.graphDiv_=this.dygraph_.graphDiv;t.appendChild(this.bgcanvas_),t.appendChild(this.fgcanvas_),t.appendChild(this.leftZoomHandle_),t.appendChild(this.rightZoomHandle_)},d.prototype.removeFromGraph_=function(){var t=this.graphDiv_;t.removeChild(this.bgcanvas_),t.removeChild(this.fgcanvas_),t.removeChild(this.leftZoomHandle_),t.removeChild(this.rightZoomHandle_),this.graphDiv_=null},d.prototype.reserveSpace_=function(t){this.getOption_("showRangeSelector")&&t.reserveSpaceBottom(this.getOption_("rangeSelectorHeight")+4)},d.prototype.renderStaticLayer_=function(){this.updateVisibility_()&&(this.resize_(),this.drawStaticLayer_())},d.prototype.renderInteractiveLayer_=function(){this.updateVisibility_()&&!this.isChangingRange_&&(this.placeZoomHandles_(),this.drawInteractiveLayer_())},d.prototype.updateVisibility_=function(){var t=this.getOption_("showRangeSelector");if(t)this.interfaceCreated_?this.graphDiv_&&this.graphDiv_.parentNode||this.addToGraph_():this.createInterface_();else if(this.graphDiv_){this.removeFromGraph_();var e=this.dygraph_;setTimeout(function(){e.width_=0,e.resize()},1)}return t},d.prototype.resize_=function(){function t(t,e,a){var i=o.getContextPixelRatio(e);t.style.top=a.y+"px",t.style.left=a.x+"px",t.width=a.w*i,t.height=a.h*i,t.style.width=a.w+"px",t.style.height=a.h+"px",1!=i&&e.scale(i,i)}var e=this.dygraph_.layout_.getPlotArea(),a=0;this.dygraph_.getOptionForAxis("drawAxis","x")&&(a=this.getOption_("xAxisHeight")||this.getOption_("axisLabelFontSize")+2*this.getOption_("axisTickSize")),this.canvasRect_={x:e.x,y:e.y+e.h+a+4,w:e.w,h:this.getOption_("rangeSelectorHeight")},t(this.bgcanvas_,this.bgcanvas_ctx_,this.canvasRect_),t(this.fgcanvas_,this.fgcanvas_ctx_,this.canvasRect_)},d.prototype.createCanvases_=function(){this.bgcanvas_=o.createCanvas(),this.bgcanvas_.className="dygraph-rangesel-bgcanvas",this.bgcanvas_.style.position="absolute",this.bgcanvas_.style.zIndex=9,this.bgcanvas_ctx_=o.getContext(this.bgcanvas_),this.fgcanvas_=o.createCanvas(),this.fgcanvas_.className="dygraph-rangesel-fgcanvas",this.fgcanvas_.style.position="absolute",this.fgcanvas_.style.zIndex=9,this.fgcanvas_.style.cursor="default",this.fgcanvas_ctx_=o.getContext(this.fgcanvas_)},d.prototype.createZoomHandles_=function(){var t=new Image;t.className="dygraph-rangesel-zoomhandle",t.style.position="absolute",t.style.zIndex=10,t.style.visibility="hidden",t.style.cursor="col-resize",t.width=9,t.height=16,t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAYAAADESFVDAAAAAXNSR0IArs4c6QAAAAZiS0dEANAAzwDP4Z7KegAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sHGw0cMqdt1UwAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAaElEQVQoz+3SsRFAQBCF4Z9WJM8KCDVwownl6YXsTmCUsyKGkZzcl7zkz3YLkypgAnreFmDEpHkIwVOMfpdi9CEEN2nGpFdwD03yEqDtOgCaun7sqSTDH32I1pQA2Pb9sZecAxc5r3IAb21d6878xsAAAAAASUVORK5CYII=",this.isMobileDevice_&&(t.width*=2,t.height*=2),this.leftZoomHandle_=t,this.rightZoomHandle_=t.cloneNode(!1)},d.prototype.initInteraction_=function(){var t,e,a,i,n,r,s,h,d,c,p,g,f,v,_=this,y=document,x=0,m=null,b=!1,w=!1,A=!this.isMobileDevice_,O=new u.default;t=function(t){var e=_.dygraph_.xAxisExtremes(),a=(e[1]-e[0])/_.canvasRect_.w,i=e[0]+(t.leftHandlePos-_.canvasRect_.x)*a,n=e[0]+(t.rightHandlePos-_.canvasRect_.x)*a;return[i,n]},e=function(t){return o.cancelEvent(t),b=!0,x=t.clientX,m=t.target?t.target:t.srcElement,"mousedown"!==t.type&&"dragstart"!==t.type||(o.addEvent(y,"mousemove",a),o.addEvent(y,"mouseup",i)),_.fgcanvas_.style.cursor="col-resize",O.cover(),!0},a=function(t){if(!b)return!1;o.cancelEvent(t);var e=t.clientX-x;if(Math.abs(e)<4)return!0;x=t.clientX;var a,i=_.getZoomHandleStatus_();m==_.leftZoomHandle_?(a=i.leftHandlePos+e,a=Math.min(a,i.rightHandlePos-m.width-3),a=Math.max(a,_.canvasRect_.x)):(a=i.rightHandlePos+e,a=Math.min(a,_.canvasRect_.x+_.canvasRect_.w),a=Math.max(a,i.leftHandlePos+m.width+3));var r=m.width/2;return m.style.left=a-r+"px",_.drawInteractiveLayer_(),A&&n(),!0},i=function(t){return!!b&&(b=!1,O.uncover(),o.removeEvent(y,"mousemove",a),o.removeEvent(y,"mouseup",i),_.fgcanvas_.style.cursor="default",A||n(),!0)},n=function(){try{var e=_.getZoomHandleStatus_();if(_.isChangingRange_=!0,e.isZoomed){var a=t(e);_.dygraph_.doZoomXDates_(a[0],a[1])}else _.dygraph_.resetZoom()}finally{_.isChangingRange_=!1}},r=function(t){var e=_.leftZoomHandle_.getBoundingClientRect(),a=e.left+e.width/2;e=_.rightZoomHandle_.getBoundingClientRect();var i=e.left+e.width/2;return t.clientX>a&&t.clientX<i},s=function(t){return!(w||!r(t)||!_.getZoomHandleStatus_().isZoomed)&&(o.cancelEvent(t),w=!0,x=t.clientX,"mousedown"===t.type&&(o.addEvent(y,"mousemove",h),o.addEvent(y,"mouseup",d)),!0)},h=function(t){if(!w)return!1;o.cancelEvent(t);var e=t.clientX-x;if(Math.abs(e)<4)return!0;x=t.clientX;var a=_.getZoomHandleStatus_(),i=a.leftHandlePos,n=a.rightHandlePos,r=n-i;i+e<=_.canvasRect_.x?(i=_.canvasRect_.x,n=i+r):n+e>=_.canvasRect_.x+_.canvasRect_.w?(n=_.canvasRect_.x+_.canvasRect_.w,i=n-r):(i+=e,n+=e);var s=_.leftZoomHandle_.width/2;return _.leftZoomHandle_.style.left=i-s+"px",_.rightZoomHandle_.style.left=n-s+"px",_.drawInteractiveLayer_(),A&&c(),!0},d=function(t){return!!w&&(w=!1,o.removeEvent(y,"mousemove",h),o.removeEvent(y,"mouseup",d),A||c(),!0)},c=function(){try{_.isChangingRange_=!0,_.dygraph_.dateWindow_=t(_.getZoomHandleStatus_()),_.dygraph_.drawGraph_(!1)}finally{_.isChangingRange_=!1}},p=function(t){if(!b&&!w){var e=r(t)?"move":"default";e!=_.fgcanvas_.style.cursor&&(_.fgcanvas_.style.cursor=e)}},g=function(t){"touchstart"==t.type&&1==t.targetTouches.length?e(t.targetTouches[0])&&o.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?a(t.targetTouches[0])&&o.cancelEvent(t):i(t)},f=function(t){"touchstart"==t.type&&1==t.targetTouches.length?s(t.targetTouches[0])&&o.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?h(t.targetTouches[0])&&o.cancelEvent(t):d(t)},v=function(t,e){for(var a=["touchstart","touchend","touchmove","touchcancel"],i=0;i<a.length;i++)_.dygraph_.addAndTrackEvent(t,a[i],e)},this.setDefaultOption_("interactionModel",l.default.dragIsPanInteractionModel),this.setDefaultOption_("panEdgeFraction",1e-4);var D=window.opera?"mousedown":"dragstart";this.dygraph_.addAndTrackEvent(this.leftZoomHandle_,D,e),this.dygraph_.addAndTrackEvent(this.rightZoomHandle_,D,e),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousedown",s),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousemove",p),this.hasTouchInterface_&&(v(this.leftZoomHandle_,g),v(this.rightZoomHandle_,g),v(this.fgcanvas_,f))},d.prototype.drawStaticLayer_=function(){var t=this.bgcanvas_ctx_;t.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h);try{this.drawMiniPlot_()}catch(t){console.warn(t)}var e=.5;this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorBackgroundLineWidth"),t.strokeStyle=this.getOption_("rangeSelectorBackgroundStrokeColor"),t.beginPath(),t.moveTo(e,e),t.lineTo(e,this.canvasRect_.h-e),t.lineTo(this.canvasRect_.w-e,this.canvasRect_.h-e),t.lineTo(this.canvasRect_.w-e,e),t.stroke()},d.prototype.drawMiniPlot_=function(){var t=this.getOption_("rangeSelectorPlotFillColor"),e=this.getOption_("rangeSelectorPlotFillGradientColor"),a=this.getOption_("rangeSelectorPlotStrokeColor");if(t||a){var i=this.getOption_("stepPlot"),n=this.computeCombinedSeriesAndLimits_(),r=n.yMax-n.yMin,o=this.bgcanvas_ctx_,s=.5,l=this.dygraph_.xAxisExtremes(),h=Math.max(l[1]-l[0],1e-30),u=(this.canvasRect_.w-s)/h,d=(this.canvasRect_.h-s)/r,c=this.canvasRect_.w-s,p=this.canvasRect_.h-s,g=null,f=null;o.beginPath(),o.moveTo(s,p);for(var v=0;v<n.data.length;v++){var _=n.data[v],y=null!==_[0]?(_[0]-l[0])*u:NaN,x=null!==_[1]?p-(_[1]-n.yMin)*d:NaN;(i||null===g||Math.round(y)!=Math.round(g))&&(isFinite(y)&&isFinite(x)?(null===g?o.lineTo(y,p):i&&o.lineTo(y,f),o.lineTo(y,x),g=y,f=x):(null!==g&&(i?(o.lineTo(y,f),o.lineTo(y,p)):o.lineTo(g,p)),g=f=null))}if(o.lineTo(c,p),o.closePath(),t){var m=this.bgcanvas_ctx_.createLinearGradient(0,0,0,p);e&&m.addColorStop(0,e),m.addColorStop(1,t),this.bgcanvas_ctx_.fillStyle=m,o.fill()}a&&(this.bgcanvas_ctx_.strokeStyle=a,this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorPlotLineWidth"),o.stroke())}},d.prototype.computeCombinedSeriesAndLimits_=function(){var t,e=this.dygraph_,a=this.getOption_("logscale"),i=e.numColumns(),n=e.getLabels(),r=new Array(i),s=!1;for(t=1;t<i;t++){var l=this.getOption_("showInRangeSelector",n[t]);r[t]=l,null!==l&&(s=!0)}if(!s)for(t=0;t<r.length;t++)r[t]=!0;var h=[],u=e.dataHandler_,d=e.attributes_;for(t=1;t<e.numColumns();t++)if(r[t]){var c=u.extractSeries(e.rawData_,t,d);e.rollPeriod()>1&&(c=u.rollingAverage(c,e.rollPeriod(),d)),h.push(c)}var p=[];for(t=0;t<h[0].length;t++){for(var g=0,f=0,v=0;v<h.length;v++){var _=h[v][t][1];null===_||isNaN(_)||(f++,g+=_)}p.push([h[0][t][0],g/f])}var y=Number.MAX_VALUE,x=-Number.MAX_VALUE;for(t=0;t<p.length;t++){var m=p[t][1];null!==m&&isFinite(m)&&(!a||m>0)&&(y=Math.min(y,m),x=Math.max(x,m))}var b=.25;if(a)for(x=o.log10(x),x+=x*b,y=o.log10(y),t=0;t<p.length;t++)p[t][1]=o.log10(p[t][1]);else{var w,A=x-y;w=A<=Number.MIN_VALUE?x*b:A*b,x+=w,y-=w}return{data:p,yMin:y,yMax:x}},d.prototype.placeZoomHandles_=function(){var t=this.dygraph_.xAxisExtremes(),e=this.dygraph_.xAxisRange(),a=t[1]-t[0],i=Math.max(0,(e[0]-t[0])/a),n=Math.max(0,(t[1]-e[1])/a),r=this.canvasRect_.x+this.canvasRect_.w*i,o=this.canvasRect_.x+this.canvasRect_.w*(1-n),s=Math.max(this.canvasRect_.y,this.canvasRect_.y+(this.canvasRect_.h-this.leftZoomHandle_.height)/2),l=this.leftZoomHandle_.width/2;this.leftZoomHandle_.style.left=r-l+"px",this.leftZoomHandle_.style.top=s+"px",this.rightZoomHandle_.style.left=o-l+"px",this.rightZoomHandle_.style.top=this.leftZoomHandle_.style.top,this.leftZoomHandle_.style.visibility="visible",this.rightZoomHandle_.style.visibility="visible"},d.prototype.drawInteractiveLayer_=function(){var t=this.fgcanvas_ctx_;t.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h);var e=1,a=this.canvasRect_.w-e,i=this.canvasRect_.h-e,n=this.getZoomHandleStatus_();if(t.strokeStyle=this.getOption_("rangeSelectorForegroundStrokeColor"),t.lineWidth=this.getOption_("rangeSelectorForegroundLineWidth"),n.isZoomed){var r=Math.max(e,n.leftHandlePos-this.canvasRect_.x),o=Math.min(a,n.rightHandlePos-this.canvasRect_.x);t.fillStyle="rgba(240, 240, 240, "+this.getOption_("rangeSelectorAlpha").toString()+")",t.fillRect(0,0,r,this.canvasRect_.h),t.fillRect(o,0,this.canvasRect_.w-o,this.canvasRect_.h),t.beginPath(),t.moveTo(e,e),t.lineTo(r,e),t.lineTo(r,i),t.lineTo(o,i),t.lineTo(o,e),t.lineTo(a,e),t.stroke()}else t.beginPath(),t.moveTo(e,e),t.lineTo(e,i),t.lineTo(a,i),t.lineTo(a,e),t.stroke()},d.prototype.getZoomHandleStatus_=function(){var t=this.leftZoomHandle_.width/2,e=parseFloat(this.leftZoomHandle_.style.left)+t,a=parseFloat(this.rightZoomHandle_.style.left)+t;return{leftHandlePos:e,rightHandlePos:a,isZoomed:e-1>this.canvasRect_.x||a+1<this.canvasRect_.x+this.canvasRect_.w}},a.default=d,e.exports=a.default},{"../dygraph-interaction-model":11,"../dygraph-utils":16,"../iframe-tarp":18}]},{},[17])(17)});
+//# sourceMappingURL=dist/dygraph.min.js.map \ No newline at end of file
diff --git a/debian/missing-sources/dygraph-combined.js b/debian/missing-sources/dygraph-combined.js
deleted file mode 100644
index 5316fe49d..000000000
--- a/debian/missing-sources/dygraph-combined.js
+++ /dev/null
@@ -1,11219 +0,0 @@
-/*! @license Copyright 2014 Dan Vanderkam (danvdk@gmail.com) MIT-licensed (http://opensource.org/licenses/MIT) */
-// Console-polyfill. MIT license.
-// https://github.com/paulmillr/console-polyfill
-// Make it safe to do console.log() always.
-(function(con) {
- 'use strict';
- var prop, method;
- var empty = {};
- var dummy = function() {};
- var properties = 'memory'.split(',');
- var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
- 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' +
- 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(',');
- while (prop = properties.pop()) con[prop] = con[prop] || empty;
- while (method = methods.pop()) con[method] = con[method] || dummy;
-})(this.console = this.console || {}); // Using `this` for web workers.
-/**
- * @license
- * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-(function() {
-'use strict';
-
-/**
- * @fileoverview Adds support for dashed lines to the HTML5 canvas.
- *
- * Usage:
- * var ctx = canvas.getContext("2d");
- * ctx.installPattern([10, 5]) // draw 10 pixels, skip 5 pixels, repeat.
- * ctx.beginPath();
- * ctx.moveTo(100, 100); // start the first line segment.
- * ctx.lineTo(150, 200);
- * ctx.lineTo(200, 100);
- * ctx.moveTo(300, 150); // start a second, unconnected line
- * ctx.lineTo(400, 250);
- * ...
- * ctx.stroke(); // draw the dashed line.
- * ctx.uninstallPattern();
- *
- * This is designed to leave the canvas untouched when it's not used.
- * If you never install a pattern, or call uninstallPattern(), then the canvas
- * will be exactly as it would have if you'd never used this library. The only
- * difference from the standard canvas will be the "installPattern" method of
- * the drawing context.
- */
-
-/**
- * Change the stroking style of the canvas drawing context from a solid line to
- * a pattern (e.g. dashes, dash-dot-dash, etc.)
- *
- * Once you've installed the pattern, you can draw with it by using the
- * beginPath(), moveTo(), lineTo() and stroke() method calls. Note that some
- * more advanced methods (e.g. quadraticCurveTo() and bezierCurveTo()) are not
- * supported. See file overview for a working example.
- *
- * Side effects of calling this method include adding an "isPatternInstalled"
- * property and "uninstallPattern" method to this particular canvas context.
- * You must call uninstallPattern() before calling installPattern() again.
- *
- * @param {Array.<number>} pattern A description of the stroke pattern. Even
- * indices indicate a draw and odd indices indicate a gap (in pixels). The
- * array should have a even length as any odd lengthed array could be expressed
- * as a smaller even length array.
- */
-CanvasRenderingContext2D.prototype.installPattern = function(pattern) {
- if (typeof(this.isPatternInstalled) !== 'undefined') {
- throw "Must un-install old line pattern before installing a new one.";
- }
- this.isPatternInstalled = true;
-
- var dashedLineToHistory = [0, 0];
-
- // list of connected line segements:
- // [ [x1, y1], ..., [xn, yn] ], [ [x1, y1], ..., [xn, yn] ]
- var segments = [];
-
- // Stash away copies of the unmodified line-drawing functions.
- var realBeginPath = this.beginPath;
- var realLineTo = this.lineTo;
- var realMoveTo = this.moveTo;
- var realStroke = this.stroke;
-
- /** @type {function()|undefined} */
- this.uninstallPattern = function() {
- this.beginPath = realBeginPath;
- this.lineTo = realLineTo;
- this.moveTo = realMoveTo;
- this.stroke = realStroke;
- this.uninstallPattern = undefined;
- this.isPatternInstalled = undefined;
- };
-
- // Keep our own copies of the line segments as they're drawn.
- this.beginPath = function() {
- segments = [];
- realBeginPath.call(this);
- };
- this.moveTo = function(x, y) {
- segments.push([[x, y]]);
- realMoveTo.call(this, x, y);
- };
- this.lineTo = function(x, y) {
- var last = segments[segments.length - 1];
- last.push([x, y]);
- };
-
- this.stroke = function() {
- if (segments.length === 0) {
- // Maybe the user is drawing something other than a line.
- // TODO(danvk): test this case.
- realStroke.call(this);
- return;
- }
-
- for (var i = 0; i < segments.length; i++) {
- var seg = segments[i];
- var x1 = seg[0][0], y1 = seg[0][1];
- for (var j = 1; j < seg.length; j++) {
- // Draw a dashed line from (x1, y1) - (x2, y2)
- var x2 = seg[j][0], y2 = seg[j][1];
- this.save();
-
- // Calculate transformation parameters
- var dx = (x2-x1);
- var dy = (y2-y1);
- var len = Math.sqrt(dx*dx + dy*dy);
- var rot = Math.atan2(dy, dx);
-
- // Set transformation
- this.translate(x1, y1);
- realMoveTo.call(this, 0, 0);
- this.rotate(rot);
-
- // Set last pattern index we used for this pattern.
- var patternIndex = dashedLineToHistory[0];
- var x = 0;
- while (len > x) {
- // Get the length of the pattern segment we are dealing with.
- var segment = pattern[patternIndex];
- // If our last draw didn't complete the pattern segment all the way
- // we will try to finish it. Otherwise we will try to do the whole
- // segment.
- if (dashedLineToHistory[1]) {
- x += dashedLineToHistory[1];
- } else {
- x += segment;
- }
-
- if (x > len) {
- // We were unable to complete this pattern index all the way, keep
- // where we are the history so our next draw continues where we
- // left off in the pattern.
- dashedLineToHistory = [patternIndex, x-len];
- x = len;
- } else {
- // We completed this patternIndex, we put in the history that we
- // are on the beginning of the next segment.
- dashedLineToHistory = [(patternIndex+1)%pattern.length, 0];
- }
-
- // We do a line on a even pattern index and just move on a odd
- // pattern index. The move is the empty space in the dash.
- if (patternIndex % 2 === 0) {
- realLineTo.call(this, x, 0);
- } else {
- realMoveTo.call(this, x, 0);
- }
-
- // If we are not done, next loop process the next pattern segment, or
- // the first segment again if we are at the end of the pattern.
- patternIndex = (patternIndex+1) % pattern.length;
- }
-
- this.restore();
- x1 = x2;
- y1 = y2;
- }
- }
- realStroke.call(this);
- segments = [];
- };
-};
-
-/**
- * Removes the previously-installed pattern.
- * You must call installPattern() before calling this. You can install at most
- * one pattern at a time--there is no pattern stack.
- */
-CanvasRenderingContext2D.prototype.uninstallPattern = function() {
- // This will be replaced by a non-error version when a pattern is installed.
- throw "Must install a line pattern before uninstalling it.";
-};
-
-})();
-/**
- * @license
- * Copyright 2011 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview DygraphOptions is responsible for parsing and returning information about options.
- *
- * Still tightly coupled to Dygraphs, we could remove some of that, you know.
- */
-
-var DygraphOptions = (function() {
-/*jshint strict:false */
-
-// For "production" code, this gets set to false by uglifyjs.
-// Need to define it outside of "use strict", hence the nested IIFEs.
-if (typeof(DEBUG) === 'undefined') DEBUG=true;
-
-return (function() {
-
-// TODO: remove this jshint directive & fix the warnings.
-/*jshint sub:true */
-/*global Dygraph:false */
-"use strict";
-
-/*
- * Interesting member variables: (REMOVING THIS LIST AS I CLOSURIZE)
- * global_ - global attributes (common among all graphs, AIUI)
- * user - attributes set by the user
- * series_ - { seriesName -> { idx, yAxis, options }}
- */
-
-/**
- * This parses attributes into an object that can be easily queried.
- *
- * It doesn't necessarily mean that all options are available, specifically
- * if labels are not yet available, since those drive details of the per-series
- * and per-axis options.
- *
- * @param {Dygraph} dygraph The chart to which these options belong.
- * @constructor
- */
-var DygraphOptions = function(dygraph) {
- /**
- * The dygraph.
- * @type {!Dygraph}
- */
- this.dygraph_ = dygraph;
-
- /**
- * Array of axis index to { series : [ series names ] , options : { axis-specific options. }
- * @type {Array.<{series : Array.<string>, options : Object}>} @private
- */
- this.yAxes_ = [];
-
- /**
- * Contains x-axis specific options, which are stored in the options key.
- * This matches the yAxes_ object structure (by being a dictionary with an
- * options element) allowing for shared code.
- * @type {options: Object} @private
- */
- this.xAxis_ = {};
- this.series_ = {};
-
- // Once these two objects are initialized, you can call get();
- this.global_ = this.dygraph_.attrs_;
- this.user_ = this.dygraph_.user_attrs_ || {};
-
- /**
- * A list of series in columnar order.
- * @type {Array.<string>}
- */
- this.labels_ = [];
-
- this.highlightSeries_ = this.get("highlightSeriesOpts") || {};
- this.reparseSeries();
-};
-
-/**
- * Not optimal, but does the trick when you're only using two axes.
- * If we move to more axes, this can just become a function.
- *
- * @type {Object.<number>}
- * @private
- */
-DygraphOptions.AXIS_STRING_MAPPINGS_ = {
- 'y' : 0,
- 'Y' : 0,
- 'y1' : 0,
- 'Y1' : 0,
- 'y2' : 1,
- 'Y2' : 1
-};
-
-/**
- * @param {string|number} axis
- * @private
- */
-DygraphOptions.axisToIndex_ = function(axis) {
- if (typeof(axis) == "string") {
- if (DygraphOptions.AXIS_STRING_MAPPINGS_.hasOwnProperty(axis)) {
- return DygraphOptions.AXIS_STRING_MAPPINGS_[axis];
- }
- throw "Unknown axis : " + axis;
- }
- if (typeof(axis) == "number") {
- if (axis === 0 || axis === 1) {
- return axis;
- }
- throw "Dygraphs only supports two y-axes, indexed from 0-1.";
- }
- if (axis) {
- throw "Unknown axis : " + axis;
- }
- // No axis specification means axis 0.
- return 0;
-};
-
-/**
- * Reparses options that are all related to series. This typically occurs when
- * options are either updated, or source data has been made available.
- *
- * TODO(konigsberg): The method name is kind of weak; fix.
- */
-DygraphOptions.prototype.reparseSeries = function() {
- var labels = this.get("labels");
- if (!labels) {
- return; // -- can't do more for now, will parse after getting the labels.
- }
-
- this.labels_ = labels.slice(1);
-
- this.yAxes_ = [ { series : [], options : {}} ]; // Always one axis at least.
- this.xAxis_ = { options : {} };
- this.series_ = {};
-
- // Traditionally, per-series options were specified right up there with the options. For instance
- // {
- // labels: [ "X", "foo", "bar" ],
- // pointSize: 3,
- // foo : {}, // options for foo
- // bar : {} // options for bar
- // }
- //
- // Moving forward, series really should be specified in the series element, separating them.
- // like so:
- //
- // {
- // labels: [ "X", "foo", "bar" ],
- // pointSize: 3,
- // series : {
- // foo : {}, // options for foo
- // bar : {} // options for bar
- // }
- // }
- //
- // So, if series is found, it's expected to contain per-series data, otherwise we fall
- // back.
- var oldStyleSeries = !this.user_["series"];
-
- if (oldStyleSeries) {
- var axisId = 0; // 0-offset; there's always one.
- // Go through once, add all the series, and for those with {} axis options, add a new axis.
- for (var idx = 0; idx < this.labels_.length; idx++) {
- var seriesName = this.labels_[idx];
-
- var optionsForSeries = this.user_[seriesName] || {};
-
- var yAxis = 0;
- var axis = optionsForSeries["axis"];
- if (typeof(axis) == 'object') {
- yAxis = ++axisId;
- this.yAxes_[yAxis] = { series : [ seriesName ], options : axis };
- }
-
- // Associate series without axis options with axis 0.
- if (!axis) { // undefined
- this.yAxes_[0].series.push(seriesName);
- }
-
- this.series_[seriesName] = { idx: idx, yAxis: yAxis, options : optionsForSeries };
- }
-
- // Go through one more time and assign series to an axis defined by another
- // series, e.g. { 'Y1: { axis: {} }, 'Y2': { axis: 'Y1' } }
- for (var idx = 0; idx < this.labels_.length; idx++) {
- var seriesName = this.labels_[idx];
- var optionsForSeries = this.series_[seriesName]["options"];
- var axis = optionsForSeries["axis"];
-
- if (typeof(axis) == 'string') {
- if (!this.series_.hasOwnProperty(axis)) {
- console.error("Series " + seriesName + " wants to share a y-axis with " +
- "series " + axis + ", which does not define its own axis.");
- return;
- }
- var yAxis = this.series_[axis].yAxis;
- this.series_[seriesName].yAxis = yAxis;
- this.yAxes_[yAxis].series.push(seriesName);
- }
- }
- } else {
- for (var idx = 0; idx < this.labels_.length; idx++) {
- var seriesName = this.labels_[idx];
- var optionsForSeries = this.user_.series[seriesName] || {};
- var yAxis = DygraphOptions.axisToIndex_(optionsForSeries["axis"]);
-
- this.series_[seriesName] = {
- idx: idx,
- yAxis: yAxis,
- options : optionsForSeries };
-
- if (!this.yAxes_[yAxis]) {
- this.yAxes_[yAxis] = { series : [ seriesName ], options : {} };
- } else {
- this.yAxes_[yAxis].series.push(seriesName);
- }
- }
- }
-
- var axis_opts = this.user_["axes"] || {};
- Dygraph.update(this.yAxes_[0].options, axis_opts["y"] || {});
- if (this.yAxes_.length > 1) {
- Dygraph.update(this.yAxes_[1].options, axis_opts["y2"] || {});
- }
- Dygraph.update(this.xAxis_.options, axis_opts["x"] || {});
-
- if (DEBUG) this.validateOptions_();
-};
-
-/**
- * Get a global value.
- *
- * @param {string} name the name of the option.
- */
-DygraphOptions.prototype.get = function(name) {
- var result = this.getGlobalUser_(name);
- if (result !== null) {
- return result;
- }
- return this.getGlobalDefault_(name);
-};
-
-DygraphOptions.prototype.getGlobalUser_ = function(name) {
- if (this.user_.hasOwnProperty(name)) {
- return this.user_[name];
- }
- return null;
-};
-
-DygraphOptions.prototype.getGlobalDefault_ = function(name) {
- if (this.global_.hasOwnProperty(name)) {
- return this.global_[name];
- }
- if (Dygraph.DEFAULT_ATTRS.hasOwnProperty(name)) {
- return Dygraph.DEFAULT_ATTRS[name];
- }
- return null;
-};
-
-/**
- * Get a value for a specific axis. If there is no specific value for the axis,
- * the global value is returned.
- *
- * @param {string} name the name of the option.
- * @param {string|number} axis the axis to search. Can be the string representation
- * ("y", "y2") or the axis number (0, 1).
- */
-DygraphOptions.prototype.getForAxis = function(name, axis) {
- var axisIdx;
- var axisString;
-
- // Since axis can be a number or a string, straighten everything out here.
- if (typeof(axis) == 'number') {
- axisIdx = axis;
- axisString = axisIdx === 0 ? "y" : "y2";
- } else {
- if (axis == "y1") { axis = "y"; } // Standardize on 'y'. Is this bad? I think so.
- if (axis == "y") {
- axisIdx = 0;
- } else if (axis == "y2") {
- axisIdx = 1;
- } else if (axis == "x") {
- axisIdx = -1; // simply a placeholder for below.
- } else {
- throw "Unknown axis " + axis;
- }
- axisString = axis;
- }
-
- var userAxis = (axisIdx == -1) ? this.xAxis_ : this.yAxes_[axisIdx];
-
- // Search the user-specified axis option first.
- if (userAxis) { // This condition could be removed if we always set up this.yAxes_ for y2.
- var axisOptions = userAxis.options;
- if (axisOptions.hasOwnProperty(name)) {
- return axisOptions[name];
- }
- }
-
- // User-specified global options second.
- // But, hack, ignore globally-specified 'logscale' for 'x' axis declaration.
- if (!(axis === 'x' && name === 'logscale')) {
- var result = this.getGlobalUser_(name);
- if (result !== null) {
- return result;
- }
- }
- // Default axis options third.
- var defaultAxisOptions = Dygraph.DEFAULT_ATTRS.axes[axisString];
- if (defaultAxisOptions.hasOwnProperty(name)) {
- return defaultAxisOptions[name];
- }
-
- // Default global options last.
- return this.getGlobalDefault_(name);
-};
-
-/**
- * Get a value for a specific series. If there is no specific value for the series,
- * the value for the axis is returned (and afterwards, the global value.)
- *
- * @param {string} name the name of the option.
- * @param {string} series the series to search.
- */
-DygraphOptions.prototype.getForSeries = function(name, series) {
- // Honors indexes as series.
- if (series === this.dygraph_.getHighlightSeries()) {
- if (this.highlightSeries_.hasOwnProperty(name)) {
- return this.highlightSeries_[name];
- }
- }
-
- if (!this.series_.hasOwnProperty(series)) {
- throw "Unknown series: " + series;
- }
-
- var seriesObj = this.series_[series];
- var seriesOptions = seriesObj["options"];
- if (seriesOptions.hasOwnProperty(name)) {
- return seriesOptions[name];
- }
-
- return this.getForAxis(name, seriesObj["yAxis"]);
-};
-
-/**
- * Returns the number of y-axes on the chart.
- * @return {number} the number of axes.
- */
-DygraphOptions.prototype.numAxes = function() {
- return this.yAxes_.length;
-};
-
-/**
- * Return the y-axis for a given series, specified by name.
- */
-DygraphOptions.prototype.axisForSeries = function(series) {
- return this.series_[series].yAxis;
-};
-
-/**
- * Returns the options for the specified axis.
- */
-// TODO(konigsberg): this is y-axis specific. Support the x axis.
-DygraphOptions.prototype.axisOptions = function(yAxis) {
- return this.yAxes_[yAxis].options;
-};
-
-/**
- * Return the series associated with an axis.
- */
-DygraphOptions.prototype.seriesForAxis = function(yAxis) {
- return this.yAxes_[yAxis].series;
-};
-
-/**
- * Return the list of all series, in their columnar order.
- */
-DygraphOptions.prototype.seriesNames = function() {
- return this.labels_;
-};
-
-if (DEBUG) {
-
-/**
- * Validate all options.
- * This requires Dygraph.OPTIONS_REFERENCE, which is only available in debug builds.
- * @private
- */
-DygraphOptions.prototype.validateOptions_ = function() {
- if (typeof Dygraph.OPTIONS_REFERENCE === 'undefined') {
- throw 'Called validateOptions_ in prod build.';
- }
-
- var that = this;
- var validateOption = function(optionName) {
- if (!Dygraph.OPTIONS_REFERENCE[optionName]) {
- that.warnInvalidOption_(optionName);
- }
- };
-
- var optionsDicts = [this.xAxis_.options,
- this.yAxes_[0].options,
- this.yAxes_[1] && this.yAxes_[1].options,
- this.global_,
- this.user_,
- this.highlightSeries_];
- var names = this.seriesNames();
- for (var i = 0; i < names.length; i++) {
- var name = names[i];
- if (this.series_.hasOwnProperty(name)) {
- optionsDicts.push(this.series_[name].options);
- }
- }
- for (var i = 0; i < optionsDicts.length; i++) {
- var dict = optionsDicts[i];
- if (!dict) continue;
- for (var optionName in dict) {
- if (dict.hasOwnProperty(optionName)) {
- validateOption(optionName);
- }
- }
- }
-};
-
-var WARNINGS = {}; // Only show any particular warning once.
-
-/**
- * Logs a warning about invalid options.
- * TODO: make this throw for testing
- * @private
- */
-DygraphOptions.prototype.warnInvalidOption_ = function(optionName) {
- if (!WARNINGS[optionName]) {
- WARNINGS[optionName] = true;
- var isSeries = (this.labels_.indexOf(optionName) >= 0);
- if (isSeries) {
- console.warn('Use new-style per-series options (saw ' + optionName + ' as top-level options key). See http://bit.ly/1tceaJs');
- } else {
- console.warn('Unknown option ' + optionName + ' (full list of options at dygraphs.com/options.html');
- throw "invalid option " + optionName;
- }
- }
-};
-
-// Reset list of previously-shown warnings. Used for testing.
-DygraphOptions.resetWarnings_ = function() {
- WARNINGS = {};
-};
-
-}
-
-return DygraphOptions;
-
-})();
-})();
-/**
- * @license
- * Copyright 2011 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview Based on PlotKitLayout, but modified to meet the needs of
- * dygraphs.
- */
-
-var DygraphLayout = (function() {
-
-/*global Dygraph:false */
-"use strict";
-
-/**
- * Creates a new DygraphLayout object.
- *
- * This class contains all the data to be charted.
- * It uses data coordinates, but also records the chart range (in data
- * coordinates) and hence is able to calculate percentage positions ('In this
- * view, Point A lies 25% down the x-axis.')
- *
- * Two things that it does not do are:
- * 1. Record pixel coordinates for anything.
- * 2. (oddly) determine anything about the layout of chart elements.
- *
- * The naming is a vestige of Dygraph's original PlotKit roots.
- *
- * @constructor
- */
-var DygraphLayout = function(dygraph) {
- this.dygraph_ = dygraph;
- /**
- * Array of points for each series.
- *
- * [series index][row index in series] = |Point| structure,
- * where series index refers to visible series only, and the
- * point index is for the reduced set of points for the current
- * zoom region (including one point just outside the window).
- * All points in the same row index share the same X value.
- *
- * @type {Array.<Array.<Dygraph.PointType>>}
- */
- this.points = [];
- this.setNames = [];
- this.annotations = [];
- this.yAxes_ = null;
-
- // TODO(danvk): it's odd that xTicks_ and yTicks_ are inputs, but xticks and
- // yticks are outputs. Clean this up.
- this.xTicks_ = null;
- this.yTicks_ = null;
-};
-
-/**
- * Add points for a single series.
- *
- * @param {string} setname Name of the series.
- * @param {Array.<Dygraph.PointType>} set_xy Points for the series.
- */
-DygraphLayout.prototype.addDataset = function(setname, set_xy) {
- this.points.push(set_xy);
- this.setNames.push(setname);
-};
-
-/**
- * Returns the box which the chart should be drawn in. This is the canvas's
- * box, less space needed for the axis and chart labels.
- *
- * @return {{x: number, y: number, w: number, h: number}}
- */
-DygraphLayout.prototype.getPlotArea = function() {
- return this.area_;
-};
-
-// Compute the box which the chart should be drawn in. This is the canvas's
-// box, less space needed for axis, chart labels, and other plug-ins.
-// NOTE: This should only be called by Dygraph.predraw_().
-DygraphLayout.prototype.computePlotArea = function() {
- var area = {
- // TODO(danvk): per-axis setting.
- x: 0,
- y: 0
- };
-
- area.w = this.dygraph_.width_ - area.x - this.dygraph_.getOption('rightGap');
- area.h = this.dygraph_.height_;
-
- // Let plugins reserve space.
- var e = {
- chart_div: this.dygraph_.graphDiv,
- reserveSpaceLeft: function(px) {
- var r = {
- x: area.x,
- y: area.y,
- w: px,
- h: area.h
- };
- area.x += px;
- area.w -= px;
- return r;
- },
- reserveSpaceRight: function(px) {
- var r = {
- x: area.x + area.w - px,
- y: area.y,
- w: px,
- h: area.h
- };
- area.w -= px;
- return r;
- },
- reserveSpaceTop: function(px) {
- var r = {
- x: area.x,
- y: area.y,
- w: area.w,
- h: px
- };
- area.y += px;
- area.h -= px;
- return r;
- },
- reserveSpaceBottom: function(px) {
- var r = {
- x: area.x,
- y: area.y + area.h - px,
- w: area.w,
- h: px
- };
- area.h -= px;
- return r;
- },
- chartRect: function() {
- return {x:area.x, y:area.y, w:area.w, h:area.h};
- }
- };
- this.dygraph_.cascadeEvents_('layout', e);
-
- this.area_ = area;
-};
-
-DygraphLayout.prototype.setAnnotations = function(ann) {
- // The Dygraph object's annotations aren't parsed. We parse them here and
- // save a copy. If there is no parser, then the user must be using raw format.
- this.annotations = [];
- var parse = this.dygraph_.getOption('xValueParser') || function(x) { return x; };
- for (var i = 0; i < ann.length; i++) {
- var a = {};
- if (!ann[i].xval && ann[i].x === undefined) {
- console.error("Annotations must have an 'x' property");
- return;
- }
- if (ann[i].icon &&
- !(ann[i].hasOwnProperty('width') &&
- ann[i].hasOwnProperty('height'))) {
- console.error("Must set width and height when setting " +
- "annotation.icon property");
- return;
- }
- Dygraph.update(a, ann[i]);
- if (!a.xval) a.xval = parse(a.x);
- this.annotations.push(a);
- }
-};
-
-DygraphLayout.prototype.setXTicks = function(xTicks) {
- this.xTicks_ = xTicks;
-};
-
-// TODO(danvk): add this to the Dygraph object's API or move it into Layout.
-DygraphLayout.prototype.setYAxes = function (yAxes) {
- this.yAxes_ = yAxes;
-};
-
-DygraphLayout.prototype.evaluate = function() {
- this._xAxis = {};
- this._evaluateLimits();
- this._evaluateLineCharts();
- this._evaluateLineTicks();
- this._evaluateAnnotations();
-};
-
-DygraphLayout.prototype._evaluateLimits = function() {
- var xlimits = this.dygraph_.xAxisRange();
- this._xAxis.minval = xlimits[0];
- this._xAxis.maxval = xlimits[1];
- var xrange = xlimits[1] - xlimits[0];
- this._xAxis.scale = (xrange !== 0 ? 1 / xrange : 1.0);
-
- if (this.dygraph_.getOptionForAxis("logscale", 'x')) {
- this._xAxis.xlogrange = Dygraph.log10(this._xAxis.maxval) - Dygraph.log10(this._xAxis.minval);
- this._xAxis.xlogscale = (this._xAxis.xlogrange !== 0 ? 1.0 / this._xAxis.xlogrange : 1.0);
- }
- for (var i = 0; i < this.yAxes_.length; i++) {
- var axis = this.yAxes_[i];
- axis.minyval = axis.computedValueRange[0];
- axis.maxyval = axis.computedValueRange[1];
- axis.yrange = axis.maxyval - axis.minyval;
- axis.yscale = (axis.yrange !== 0 ? 1.0 / axis.yrange : 1.0);
-
- if (this.dygraph_.getOption("logscale")) {
- axis.ylogrange = Dygraph.log10(axis.maxyval) - Dygraph.log10(axis.minyval);
- axis.ylogscale = (axis.ylogrange !== 0 ? 1.0 / axis.ylogrange : 1.0);
- if (!isFinite(axis.ylogrange) || isNaN(axis.ylogrange)) {
- console.error('axis ' + i + ' of graph at ' + axis.g +
- ' can\'t be displayed in log scale for range [' +
- axis.minyval + ' - ' + axis.maxyval + ']');
- }
- }
- }
-};
-
-DygraphLayout.calcXNormal_ = function(value, xAxis, logscale) {
- if (logscale) {
- return ((Dygraph.log10(value) - Dygraph.log10(xAxis.minval)) * xAxis.xlogscale);
- } else {
- return (value - xAxis.minval) * xAxis.scale;
- }
-};
-
-/**
- * @param {DygraphAxisType} axis
- * @param {number} value
- * @param {boolean} logscale
- * @return {number}
- */
-DygraphLayout.calcYNormal_ = function(axis, value, logscale) {
- if (logscale) {
- var x = 1.0 - ((Dygraph.log10(value) - Dygraph.log10(axis.minyval)) * axis.ylogscale);
- return isFinite(x) ? x : NaN; // shim for v8 issue; see pull request 276
- } else {
- return 1.0 - ((value - axis.minyval) * axis.yscale);
- }
-};
-
-DygraphLayout.prototype._evaluateLineCharts = function() {
- var isStacked = this.dygraph_.getOption("stackedGraph");
- var isLogscaleForX = this.dygraph_.getOptionForAxis("logscale", 'x');
-
- for (var setIdx = 0; setIdx < this.points.length; setIdx++) {
- var points = this.points[setIdx];
- var setName = this.setNames[setIdx];
- var connectSeparated = this.dygraph_.getOption('connectSeparatedPoints', setName);
- var axis = this.dygraph_.axisPropertiesForSeries(setName);
- // TODO (konigsberg): use optionsForAxis instead.
- var logscale = this.dygraph_.attributes_.getForSeries("logscale", setName);
-
- for (var j = 0; j < points.length; j++) {
- var point = points[j];
-
- // Range from 0-1 where 0 represents left and 1 represents right.
- point.x = DygraphLayout.calcXNormal_(point.xval, this._xAxis, isLogscaleForX);
- // Range from 0-1 where 0 represents top and 1 represents bottom
- var yval = point.yval;
- if (isStacked) {
- point.y_stacked = DygraphLayout.calcYNormal_(
- axis, point.yval_stacked, logscale);
- if (yval !== null && !isNaN(yval)) {
- yval = point.yval_stacked;
- }
- }
- if (yval === null) {
- yval = NaN;
- if (!connectSeparated) {
- point.yval = NaN;
- }
- }
- point.y = DygraphLayout.calcYNormal_(axis, yval, logscale);
- }
-
- this.dygraph_.dataHandler_.onLineEvaluated(points, axis, logscale);
- }
-};
-
-DygraphLayout.prototype._evaluateLineTicks = function() {
- var i, tick, label, pos;
- this.xticks = [];
- for (i = 0; i < this.xTicks_.length; i++) {
- tick = this.xTicks_[i];
- label = tick.label;
- pos = this.dygraph_.toPercentXCoord(tick.v);
- if ((pos >= 0.0) && (pos < 1.0)) {
- this.xticks.push([pos, label]);
- }
- }
-
- this.yticks = [];
- for (i = 0; i < this.yAxes_.length; i++ ) {
- var axis = this.yAxes_[i];
- for (var j = 0; j < axis.ticks.length; j++) {
- tick = axis.ticks[j];
- label = tick.label;
- pos = this.dygraph_.toPercentYCoord(tick.v, i);
- if ((pos > 0.0) && (pos <= 1.0)) {
- this.yticks.push([i, pos, label]);
- }
- }
- }
-};
-
-DygraphLayout.prototype._evaluateAnnotations = function() {
- // Add the annotations to the point to which they belong.
- // Make a map from (setName, xval) to annotation for quick lookups.
- var i;
- var annotations = {};
- for (i = 0; i < this.annotations.length; i++) {
- var a = this.annotations[i];
- annotations[a.xval + "," + a.series] = a;
- }
-
- this.annotated_points = [];
-
- // Exit the function early if there are no annotations.
- if (!this.annotations || !this.annotations.length) {
- return;
- }
-
- // TODO(antrob): loop through annotations not points.
- for (var setIdx = 0; setIdx < this.points.length; setIdx++) {
- var points = this.points[setIdx];
- for (i = 0; i < points.length; i++) {
- var p = points[i];
- var k = p.xval + "," + p.name;
- if (k in annotations) {
- p.annotation = annotations[k];
- this.annotated_points.push(p);
- }
- }
- }
-};
-
-/**
- * Convenience function to remove all the data sets from a graph
- */
-DygraphLayout.prototype.removeAllDatasets = function() {
- delete this.points;
- delete this.setNames;
- delete this.setPointsLengths;
- delete this.setPointsOffsets;
- this.points = [];
- this.setNames = [];
- this.setPointsLengths = [];
- this.setPointsOffsets = [];
-};
-
-return DygraphLayout;
-
-})();
-/**
- * @license
- * Copyright 2006 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview Based on PlotKit.CanvasRenderer, but modified to meet the
- * needs of dygraphs.
- *
- * In particular, support for:
- * - grid overlays
- * - error bars
- * - dygraphs attribute system
- */
-
-/**
- * The DygraphCanvasRenderer class does the actual rendering of the chart onto
- * a canvas. It's based on PlotKit.CanvasRenderer.
- * @param {Object} element The canvas to attach to
- * @param {Object} elementContext The 2d context of the canvas (injected so it
- * can be mocked for testing.)
- * @param {Layout} layout The DygraphLayout object for this graph.
- * @constructor
- */
-
-var DygraphCanvasRenderer = (function() {
-/*global Dygraph:false */
-"use strict";
-
-
-/**
- * @constructor
- *
- * This gets called when there are "new points" to chart. This is generally the
- * case when the underlying data being charted has changed. It is _not_ called
- * in the common case that the user has zoomed or is panning the view.
- *
- * The chart canvas has already been created by the Dygraph object. The
- * renderer simply gets a drawing context.
- *
- * @param {Dygraph} dygraph The chart to which this renderer belongs.
- * @param {HTMLCanvasElement} element The &lt;canvas&gt; DOM element on which to draw.
- * @param {CanvasRenderingContext2D} elementContext The drawing context.
- * @param {DygraphLayout} layout The chart's DygraphLayout object.
- *
- * TODO(danvk): remove the elementContext property.
- */
-var DygraphCanvasRenderer = function(dygraph, element, elementContext, layout) {
- this.dygraph_ = dygraph;
-
- this.layout = layout;
- this.element = element;
- this.elementContext = elementContext;
-
- this.height = dygraph.height_;
- this.width = dygraph.width_;
-
- // --- check whether everything is ok before we return
- // NOTE(konigsberg): isIE is never defined in this object. Bug of some sort.
- if (!this.isIE && !(Dygraph.isCanvasSupported(this.element)))
- throw "Canvas is not supported.";
-
- // internal state
- this.area = layout.getPlotArea();
-
- // Set up a clipping area for the canvas (and the interaction canvas).
- // This ensures that we don't overdraw.
- if (this.dygraph_.isUsingExcanvas_) {
- this._createIEClipArea();
- } else {
- // on Android 3 and 4, setting a clipping area on a canvas prevents it from
- // displaying anything.
- if (!Dygraph.isAndroid()) {
- var ctx = this.dygraph_.canvas_ctx_;
- ctx.beginPath();
- ctx.rect(this.area.x, this.area.y, this.area.w, this.area.h);
- ctx.clip();
-
- ctx = this.dygraph_.hidden_ctx_;
- ctx.beginPath();
- ctx.rect(this.area.x, this.area.y, this.area.w, this.area.h);
- ctx.clip();
- }
- }
-};
-
-/**
- * Clears out all chart content and DOM elements.
- * This is called immediately before render() on every frame, including
- * during zooms and pans.
- * @private
- */
-DygraphCanvasRenderer.prototype.clear = function() {
- var context;
- if (this.isIE) {
- // VML takes a while to start up, so we just poll every this.IEDelay
- try {
- if (this.clearDelay) {
- this.clearDelay.cancel();
- this.clearDelay = null;
- }
- context = this.elementContext;
- }
- catch (e) {
- // TODO(danvk): this is broken, since MochiKit.Async is gone.
- // this.clearDelay = MochiKit.Async.wait(this.IEDelay);
- // this.clearDelay.addCallback(bind(this.clear, this));
- return;
- }
- }
-
- context = this.elementContext;
- context.clearRect(0, 0, this.width, this.height);
-};
-
-/**
- * This method is responsible for drawing everything on the chart, including
- * lines, error bars, fills and axes.
- * It is called immediately after clear() on every frame, including during pans
- * and zooms.
- * @private
- */
-DygraphCanvasRenderer.prototype.render = function() {
- // attaches point.canvas{x,y}
- this._updatePoints();
-
- // actually draws the chart.
- this._renderLineChart();
-};
-
-DygraphCanvasRenderer.prototype._createIEClipArea = function() {
- var className = 'dygraph-clip-div';
- var graphDiv = this.dygraph_.graphDiv;
-
- // Remove old clip divs.
- for (var i = graphDiv.childNodes.length-1; i >= 0; i--) {
- if (graphDiv.childNodes[i].className == className) {
- graphDiv.removeChild(graphDiv.childNodes[i]);
- }
- }
-
- // Determine background color to give clip divs.
- var backgroundColor = document.bgColor;
- var element = this.dygraph_.graphDiv;
- while (element != document) {
- var bgcolor = element.currentStyle.backgroundColor;
- if (bgcolor && bgcolor != 'transparent') {
- backgroundColor = bgcolor;
- break;
- }
- element = element.parentNode;
- }
-
- function createClipDiv(area) {
- if (area.w === 0 || area.h === 0) {
- return;
- }
- var elem = document.createElement('div');
- elem.className = className;
- elem.style.backgroundColor = backgroundColor;
- elem.style.position = 'absolute';
- elem.style.left = area.x + 'px';
- elem.style.top = area.y + 'px';
- elem.style.width = area.w + 'px';
- elem.style.height = area.h + 'px';
- graphDiv.appendChild(elem);
- }
-
- var plotArea = this.area;
- // Left side
- createClipDiv({
- x:0, y:0,
- w:plotArea.x,
- h:this.height
- });
-
- // Top
- createClipDiv({
- x: plotArea.x, y: 0,
- w: this.width - plotArea.x,
- h: plotArea.y
- });
-
- // Right side
- createClipDiv({
- x: plotArea.x + plotArea.w, y: 0,
- w: this.width - plotArea.x - plotArea.w,
- h: this.height
- });
-
- // Bottom
- createClipDiv({
- x: plotArea.x,
- y: plotArea.y + plotArea.h,
- w: this.width - plotArea.x,
- h: this.height - plotArea.h - plotArea.y
- });
-};
-
-
-/**
- * Returns a predicate to be used with an iterator, which will
- * iterate over points appropriately, depending on whether
- * connectSeparatedPoints is true. When it's false, the predicate will
- * skip over points with missing yVals.
- */
-DygraphCanvasRenderer._getIteratorPredicate = function(connectSeparatedPoints) {
- return connectSeparatedPoints ?
- DygraphCanvasRenderer._predicateThatSkipsEmptyPoints :
- null;
-};
-
-DygraphCanvasRenderer._predicateThatSkipsEmptyPoints =
- function(array, idx) {
- return array[idx].yval !== null;
-};
-
-/**
- * Draws a line with the styles passed in and calls all the drawPointCallbacks.
- * @param {Object} e The dictionary passed to the plotter function.
- * @private
- */
-DygraphCanvasRenderer._drawStyledLine = function(e,
- color, strokeWidth, strokePattern, drawPoints,
- drawPointCallback, pointSize) {
- var g = e.dygraph;
- // TODO(konigsberg): Compute attributes outside this method call.
- var stepPlot = g.getBooleanOption("stepPlot", e.setName);
-
- if (!Dygraph.isArrayLike(strokePattern)) {
- strokePattern = null;
- }
-
- var drawGapPoints = g.getBooleanOption('drawGapEdgePoints', e.setName);
-
- var points = e.points;
- var setName = e.setName;
- var iter = Dygraph.createIterator(points, 0, points.length,
- DygraphCanvasRenderer._getIteratorPredicate(
- g.getBooleanOption("connectSeparatedPoints", setName)));
-
- var stroking = strokePattern && (strokePattern.length >= 2);
-
- var ctx = e.drawingContext;
- ctx.save();
- if (stroking) {
- ctx.installPattern(strokePattern);
- }
-
- var pointsOnLine = DygraphCanvasRenderer._drawSeries(
- e, iter, strokeWidth, pointSize, drawPoints, drawGapPoints, stepPlot, color);
- DygraphCanvasRenderer._drawPointsOnLine(
- e, pointsOnLine, drawPointCallback, color, pointSize);
-
- if (stroking) {
- ctx.uninstallPattern();
- }
-
- ctx.restore();
-};
-
-/**
- * This does the actual drawing of lines on the canvas, for just one series.
- * Returns a list of [canvasx, canvasy] pairs for points for which a
- * drawPointCallback should be fired. These include isolated points, or all
- * points if drawPoints=true.
- * @param {Object} e The dictionary passed to the plotter function.
- * @private
- */
-DygraphCanvasRenderer._drawSeries = function(e,
- iter, strokeWidth, pointSize, drawPoints, drawGapPoints, stepPlot, color) {
-
- var prevCanvasX = null;
- var prevCanvasY = null;
- var nextCanvasY = null;
- var isIsolated; // true if this point is isolated (no line segments)
- var point; // the point being processed in the while loop
- var pointsOnLine = []; // Array of [canvasx, canvasy] pairs.
- var first = true; // the first cycle through the while loop
-
- var ctx = e.drawingContext;
- ctx.beginPath();
- ctx.strokeStyle = color;
- ctx.lineWidth = strokeWidth;
-
- // NOTE: we break the iterator's encapsulation here for about a 25% speedup.
- var arr = iter.array_;
- var limit = iter.end_;
- var predicate = iter.predicate_;
-
- for (var i = iter.start_; i < limit; i++) {
- point = arr[i];
- if (predicate) {
- while (i < limit && !predicate(arr, i)) {
- i++;
- }
- if (i == limit) break;
- point = arr[i];
- }
-
- // FIXME: The 'canvasy != canvasy' test here catches NaN values but the test
- // doesn't catch Infinity values. Could change this to
- // !isFinite(point.canvasy), but I assume it avoids isNaN for performance?
- if (point.canvasy === null || point.canvasy != point.canvasy) {
- if (stepPlot && prevCanvasX !== null) {
- // Draw a horizontal line to the start of the missing data
- ctx.moveTo(prevCanvasX, prevCanvasY);
- ctx.lineTo(point.canvasx, prevCanvasY);
- }
- prevCanvasX = prevCanvasY = null;
- } else {
- isIsolated = false;
- if (drawGapPoints || !prevCanvasX) {
- iter.nextIdx_ = i;
- iter.next();
- nextCanvasY = iter.hasNext ? iter.peek.canvasy : null;
-
- var isNextCanvasYNullOrNaN = nextCanvasY === null ||
- nextCanvasY != nextCanvasY;
- isIsolated = (!prevCanvasX && isNextCanvasYNullOrNaN);
- if (drawGapPoints) {
- // Also consider a point to be "isolated" if it's adjacent to a
- // null point, excluding the graph edges.
- if ((!first && !prevCanvasX) ||
- (iter.hasNext && isNextCanvasYNullOrNaN)) {
- isIsolated = true;
- }
- }
- }
-
- if (prevCanvasX !== null) {
- if (strokeWidth) {
- if (stepPlot) {
- ctx.moveTo(prevCanvasX, prevCanvasY);
- ctx.lineTo(point.canvasx, prevCanvasY);
- }
-
- ctx.lineTo(point.canvasx, point.canvasy);
- }
- } else {
- ctx.moveTo(point.canvasx, point.canvasy);
- }
- if (drawPoints || isIsolated) {
- pointsOnLine.push([point.canvasx, point.canvasy, point.idx]);
- }
- prevCanvasX = point.canvasx;
- prevCanvasY = point.canvasy;
- }
- first = false;
- }
- ctx.stroke();
- return pointsOnLine;
-};
-
-/**
- * This fires the drawPointCallback functions, which draw dots on the points by
- * default. This gets used when the "drawPoints" option is set, or when there
- * are isolated points.
- * @param {Object} e The dictionary passed to the plotter function.
- * @private
- */
-DygraphCanvasRenderer._drawPointsOnLine = function(
- e, pointsOnLine, drawPointCallback, color, pointSize) {
- var ctx = e.drawingContext;
- for (var idx = 0; idx < pointsOnLine.length; idx++) {
- var cb = pointsOnLine[idx];
- ctx.save();
- drawPointCallback.call(e.dygraph,
- e.dygraph, e.setName, ctx, cb[0], cb[1], color, pointSize, cb[2]);
- ctx.restore();
- }
-};
-
-/**
- * Attaches canvas coordinates to the points array.
- * @private
- */
-DygraphCanvasRenderer.prototype._updatePoints = function() {
- // Update Points
- // TODO(danvk): here
- //
- // TODO(bhs): this loop is a hot-spot for high-point-count charts. These
- // transformations can be pushed into the canvas via linear transformation
- // matrices.
- // NOTE(danvk): this is trickier than it sounds at first. The transformation
- // needs to be done before the .moveTo() and .lineTo() calls, but must be
- // undone before the .stroke() call to ensure that the stroke width is
- // unaffected. An alternative is to reduce the stroke width in the
- // transformed coordinate space, but you can't specify different values for
- // each dimension (as you can with .scale()). The speedup here is ~12%.
- var sets = this.layout.points;
- for (var i = sets.length; i--;) {
- var points = sets[i];
- for (var j = points.length; j--;) {
- var point = points[j];
- point.canvasx = this.area.w * point.x + this.area.x;
- point.canvasy = this.area.h * point.y + this.area.y;
- }
- }
-};
-
-/**
- * Add canvas Actually draw the lines chart, including error bars.
- *
- * This function can only be called if DygraphLayout's points array has been
- * updated with canvas{x,y} attributes, i.e. by
- * DygraphCanvasRenderer._updatePoints.
- *
- * @param {string=} opt_seriesName when specified, only that series will
- * be drawn. (This is used for expedited redrawing with highlightSeriesOpts)
- * @param {CanvasRenderingContext2D} opt_ctx when specified, the drawing
- * context. However, lines are typically drawn on the object's
- * elementContext.
- * @private
- */
-DygraphCanvasRenderer.prototype._renderLineChart = function(opt_seriesName, opt_ctx) {
- var ctx = opt_ctx || this.elementContext;
- var i;
-
- var sets = this.layout.points;
- var setNames = this.layout.setNames;
- var setName;
-
- this.colors = this.dygraph_.colorsMap_;
-
- // Determine which series have specialized plotters.
- var plotter_attr = this.dygraph_.getOption("plotter");
- var plotters = plotter_attr;
- if (!Dygraph.isArrayLike(plotters)) {
- plotters = [plotters];
- }
-
- var setPlotters = {}; // series name -> plotter fn.
- for (i = 0; i < setNames.length; i++) {
- setName = setNames[i];
- var setPlotter = this.dygraph_.getOption("plotter", setName);
- if (setPlotter == plotter_attr) continue; // not specialized.
-
- setPlotters[setName] = setPlotter;
- }
-
- for (i = 0; i < plotters.length; i++) {
- var plotter = plotters[i];
- var is_last = (i == plotters.length - 1);
-
- for (var j = 0; j < sets.length; j++) {
- setName = setNames[j];
- if (opt_seriesName && setName != opt_seriesName) continue;
-
- var points = sets[j];
-
- // Only throw in the specialized plotters on the last iteration.
- var p = plotter;
- if (setName in setPlotters) {
- if (is_last) {
- p = setPlotters[setName];
- } else {
- // Don't use the standard plotters in this case.
- continue;
- }
- }
-
- var color = this.colors[setName];
- var strokeWidth = this.dygraph_.getOption("strokeWidth", setName);
-
- ctx.save();
- ctx.strokeStyle = color;
- ctx.lineWidth = strokeWidth;
- p({
- points: points,
- setName: setName,
- drawingContext: ctx,
- color: color,
- strokeWidth: strokeWidth,
- dygraph: this.dygraph_,
- axis: this.dygraph_.axisPropertiesForSeries(setName),
- plotArea: this.area,
- seriesIndex: j,
- seriesCount: sets.length,
- singleSeriesName: opt_seriesName,
- allSeriesPoints: sets
- });
- ctx.restore();
- }
- }
-};
-
-/**
- * Standard plotters. These may be used by clients via Dygraph.Plotters.
- * See comments there for more details.
- */
-DygraphCanvasRenderer._Plotters = {
- linePlotter: function(e) {
- DygraphCanvasRenderer._linePlotter(e);
- },
-
- fillPlotter: function(e) {
- DygraphCanvasRenderer._fillPlotter(e);
- },
-
- errorPlotter: function(e) {
- DygraphCanvasRenderer._errorPlotter(e);
- }
-};
-
-/**
- * Plotter which draws the central lines for a series.
- * @private
- */
-DygraphCanvasRenderer._linePlotter = function(e) {
- var g = e.dygraph;
- var setName = e.setName;
- var strokeWidth = e.strokeWidth;
-
- // TODO(danvk): Check if there's any performance impact of just calling
- // getOption() inside of _drawStyledLine. Passing in so many parameters makes
- // this code a bit nasty.
- var borderWidth = g.getNumericOption("strokeBorderWidth", setName);
- var drawPointCallback = g.getOption("drawPointCallback", setName) ||
- Dygraph.Circles.DEFAULT;
- var strokePattern = g.getOption("strokePattern", setName);
- var drawPoints = g.getBooleanOption("drawPoints", setName);
- var pointSize = g.getNumericOption("pointSize", setName);
-
- if (borderWidth && strokeWidth) {
- DygraphCanvasRenderer._drawStyledLine(e,
- g.getOption("strokeBorderColor", setName),
- strokeWidth + 2 * borderWidth,
- strokePattern,
- drawPoints,
- drawPointCallback,
- pointSize
- );
- }
-
- DygraphCanvasRenderer._drawStyledLine(e,
- e.color,
- strokeWidth,
- strokePattern,
- drawPoints,
- drawPointCallback,
- pointSize
- );
-};
-
-/**
- * Draws the shaded error bars/confidence intervals for each series.
- * This happens before the center lines are drawn, since the center lines
- * need to be drawn on top of the error bars for all series.
- * @private
- */
-DygraphCanvasRenderer._errorPlotter = function(e) {
- var g = e.dygraph;
- var setName = e.setName;
- var errorBars = g.getBooleanOption("errorBars") ||
- g.getBooleanOption("customBars");
- if (!errorBars) return;
-
- var fillGraph = g.getBooleanOption("fillGraph", setName);
- if (fillGraph) {
- console.warn("Can't use fillGraph option with error bars");
- }
-
- var ctx = e.drawingContext;
- var color = e.color;
- var fillAlpha = g.getNumericOption('fillAlpha', setName);
- var stepPlot = g.getBooleanOption("stepPlot", setName);
- var points = e.points;
-
- var iter = Dygraph.createIterator(points, 0, points.length,
- DygraphCanvasRenderer._getIteratorPredicate(
- g.getBooleanOption("connectSeparatedPoints", setName)));
-
- var newYs;
-
- // setup graphics context
- var prevX = NaN;
- var prevY = NaN;
- var prevYs = [-1, -1];
- // should be same color as the lines but only 15% opaque.
- var rgb = Dygraph.toRGB_(color);
- var err_color =
- 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + fillAlpha + ')';
- ctx.fillStyle = err_color;
- ctx.beginPath();
-
- var isNullUndefinedOrNaN = function(x) {
- return (x === null ||
- x === undefined ||
- isNaN(x));
- };
-
- while (iter.hasNext) {
- var point = iter.next();
- if ((!stepPlot && isNullUndefinedOrNaN(point.y)) ||
- (stepPlot && !isNaN(prevY) && isNullUndefinedOrNaN(prevY))) {
- prevX = NaN;
- continue;
- }
-
- newYs = [ point.y_bottom, point.y_top ];
- if (stepPlot) {
- prevY = point.y;
- }
-
- // The documentation specifically disallows nulls inside the point arrays,
- // but in case it happens we should do something sensible.
- if (isNaN(newYs[0])) newYs[0] = point.y;
- if (isNaN(newYs[1])) newYs[1] = point.y;
-
- newYs[0] = e.plotArea.h * newYs[0] + e.plotArea.y;
- newYs[1] = e.plotArea.h * newYs[1] + e.plotArea.y;
- if (!isNaN(prevX)) {
- if (stepPlot) {
- ctx.moveTo(prevX, prevYs[0]);
- ctx.lineTo(point.canvasx, prevYs[0]);
- ctx.lineTo(point.canvasx, prevYs[1]);
- } else {
- ctx.moveTo(prevX, prevYs[0]);
- ctx.lineTo(point.canvasx, newYs[0]);
- ctx.lineTo(point.canvasx, newYs[1]);
- }
- ctx.lineTo(prevX, prevYs[1]);
- ctx.closePath();
- }
- prevYs = newYs;
- prevX = point.canvasx;
- }
- ctx.fill();
-};
-
-
-/**
- * Proxy for CanvasRenderingContext2D which drops moveTo/lineTo calls which are
- * superfluous. It accumulates all movements which haven't changed the x-value
- * and only applies the two with the most extreme y-values.
- *
- * Calls to lineTo/moveTo must have non-decreasing x-values.
- */
-DygraphCanvasRenderer._fastCanvasProxy = function(context) {
- var pendingActions = []; // array of [type, x, y] tuples
- var lastRoundedX = null;
-
- var LINE_TO = 1,
- MOVE_TO = 2;
-
- var actionCount = 0; // number of moveTos and lineTos passed to context.
-
- // Drop superfluous motions
- // Assumes all pendingActions have the same (rounded) x-value.
- var compressActions = function(opt_losslessOnly) {
- if (pendingActions.length <= 1) return;
-
- // Lossless compression: drop inconsequential moveTos.
- for (var i = pendingActions.length - 1; i > 0; i--) {
- var action = pendingActions[i];
- if (action[0] == MOVE_TO) {
- var prevAction = pendingActions[i - 1];
- if (prevAction[1] == action[1] && prevAction[2] == action[2]) {
- pendingActions.splice(i, 1);
- }
- }
- }
-
- // Lossless compression: ... drop consecutive moveTos ...
- for (var i = 0; i < pendingActions.length - 1; /* incremented internally */) {
- var action = pendingActions[i];
- if (action[0] == MOVE_TO && pendingActions[i + 1][0] == MOVE_TO) {
- pendingActions.splice(i, 1);
- } else {
- i++;
- }
- }
-
- // Lossy compression: ... drop all but the extreme y-values ...
- if (pendingActions.length > 2 && !opt_losslessOnly) {
- // keep an initial moveTo, but drop all others.
- var startIdx = 0;
- if (pendingActions[0][0] == MOVE_TO) startIdx++;
- var minIdx = null, maxIdx = null;
- for (var i = startIdx; i < pendingActions.length; i++) {
- var action = pendingActions[i];
- if (action[0] != LINE_TO) continue;
- if (minIdx === null && maxIdx === null) {
- minIdx = i;
- maxIdx = i;
- } else {
- var y = action[2];
- if (y < pendingActions[minIdx][2]) {
- minIdx = i;
- } else if (y > pendingActions[maxIdx][2]) {
- maxIdx = i;
- }
- }
- }
- var minAction = pendingActions[minIdx],
- maxAction = pendingActions[maxIdx];
- pendingActions.splice(startIdx, pendingActions.length - startIdx);
- if (minIdx < maxIdx) {
- pendingActions.push(minAction);
- pendingActions.push(maxAction);
- } else if (minIdx > maxIdx) {
- pendingActions.push(maxAction);
- pendingActions.push(minAction);
- } else {
- pendingActions.push(minAction);
- }
- }
- };
-
- var flushActions = function(opt_noLossyCompression) {
- compressActions(opt_noLossyCompression);
- for (var i = 0, len = pendingActions.length; i < len; i++) {
- var action = pendingActions[i];
- if (action[0] == LINE_TO) {
- context.lineTo(action[1], action[2]);
- } else if (action[0] == MOVE_TO) {
- context.moveTo(action[1], action[2]);
- }
- }
- actionCount += pendingActions.length;
- pendingActions = [];
- };
-
- var addAction = function(action, x, y) {
- var rx = Math.round(x);
- if (lastRoundedX === null || rx != lastRoundedX) {
- flushActions();
- lastRoundedX = rx;
- }
- pendingActions.push([action, x, y]);
- };
-
- return {
- moveTo: function(x, y) {
- addAction(MOVE_TO, x, y);
- },
- lineTo: function(x, y) {
- addAction(LINE_TO, x, y);
- },
-
- // for major operations like stroke/fill, we skip compression to ensure
- // that there are no artifacts at the right edge.
- stroke: function() { flushActions(true); context.stroke(); },
- fill: function() { flushActions(true); context.fill(); },
- beginPath: function() { flushActions(true); context.beginPath(); },
- closePath: function() { flushActions(true); context.closePath(); },
-
- _count: function() { return actionCount; }
- };
-};
-
-/**
- * Draws the shaded regions when "fillGraph" is set. Not to be confused with
- * error bars.
- *
- * For stacked charts, it's more convenient to handle all the series
- * simultaneously. So this plotter plots all the points on the first series
- * it's asked to draw, then ignores all the other series.
- *
- * @private
- */
-DygraphCanvasRenderer._fillPlotter = function(e) {
- // Skip if we're drawing a single series for interactive highlight overlay.
- if (e.singleSeriesName) return;
-
- // We'll handle all the series at once, not one-by-one.
- if (e.seriesIndex !== 0) return;
-
- var g = e.dygraph;
- var setNames = g.getLabels().slice(1); // remove x-axis
-
- // getLabels() includes names for invisible series, which are not included in
- // allSeriesPoints. We remove those to make the two match.
- // TODO(danvk): provide a simpler way to get this information.
- for (var i = setNames.length; i >= 0; i--) {
- if (!g.visibility()[i]) setNames.splice(i, 1);
- }
-
- var anySeriesFilled = (function() {
- for (var i = 0; i < setNames.length; i++) {
- if (g.getBooleanOption("fillGraph", setNames[i])) return true;
- }
- return false;
- })();
-
- if (!anySeriesFilled) return;
-
- var area = e.plotArea;
- var sets = e.allSeriesPoints;
- var setCount = sets.length;
-
- var fillAlpha = g.getNumericOption('fillAlpha');
- var stackedGraph = g.getBooleanOption("stackedGraph");
- var colors = g.getColors();
-
- // For stacked graphs, track the baseline for filling.
- //
- // The filled areas below graph lines are trapezoids with two
- // vertical edges. The top edge is the line segment being drawn, and
- // the baseline is the bottom edge. Each baseline corresponds to the
- // top line segment from the previous stacked line. In the case of
- // step plots, the trapezoids are rectangles.
- var baseline = {};
- var currBaseline;
- var prevStepPlot; // for different line drawing modes (line/step) per series
-
- // Helper function to trace a line back along the baseline.
- var traceBackPath = function(ctx, baselineX, baselineY, pathBack) {
- ctx.lineTo(baselineX, baselineY);
- if (stackedGraph) {
- for (var i = pathBack.length - 1; i >= 0; i--) {
- var pt = pathBack[i];
- ctx.lineTo(pt[0], pt[1]);
- }
- }
- };
-
- // process sets in reverse order (needed for stacked graphs)
- for (var setIdx = setCount - 1; setIdx >= 0; setIdx--) {
- var ctx = e.drawingContext;
- var setName = setNames[setIdx];
- if (!g.getBooleanOption('fillGraph', setName)) continue;
-
- var stepPlot = g.getBooleanOption('stepPlot', setName);
- var color = colors[setIdx];
- var axis = g.axisPropertiesForSeries(setName);
- var axisY = 1.0 + axis.minyval * axis.yscale;
- if (axisY < 0.0) axisY = 0.0;
- else if (axisY > 1.0) axisY = 1.0;
- axisY = area.h * axisY + area.y;
-
- var points = sets[setIdx];
- var iter = Dygraph.createIterator(points, 0, points.length,
- DygraphCanvasRenderer._getIteratorPredicate(
- g.getBooleanOption("connectSeparatedPoints", setName)));
-
- // setup graphics context
- var prevX = NaN;
- var prevYs = [-1, -1];
- var newYs;
- // should be same color as the lines but only 15% opaque.
- var rgb = Dygraph.toRGB_(color);
- var err_color =
- 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + fillAlpha + ')';
- ctx.fillStyle = err_color;
- ctx.beginPath();
- var last_x, is_first = true;
-
- // If the point density is high enough, dropping segments on their way to
- // the canvas justifies the overhead of doing so.
- if (points.length > 2 * g.width_) {
- ctx = DygraphCanvasRenderer._fastCanvasProxy(ctx);
- }
-
- // For filled charts, we draw points from left to right, then back along
- // the x-axis to complete a shape for filling.
- // For stacked plots, this "back path" is a more complex shape. This array
- // stores the [x, y] values needed to trace that shape.
- var pathBack = [];
-
- // TODO(danvk): there are a lot of options at play in this loop.
- // The logic would be much clearer if some (e.g. stackGraph and
- // stepPlot) were split off into separate sub-plotters.
- var point;
- while (iter.hasNext) {
- point = iter.next();
- if (!Dygraph.isOK(point.y) && !stepPlot) {
- traceBackPath(ctx, prevX, prevYs[1], pathBack);
- pathBack = [];
- prevX = NaN;
- if (point.y_stacked !== null && !isNaN(point.y_stacked)) {
- baseline[point.canvasx] = area.h * point.y_stacked + area.y;
- }
- continue;
- }
- if (stackedGraph) {
- if (!is_first && last_x == point.xval) {
- continue;
- } else {
- is_first = false;
- last_x = point.xval;
- }
-
- currBaseline = baseline[point.canvasx];
- var lastY;
- if (currBaseline === undefined) {
- lastY = axisY;
- } else {
- if(prevStepPlot) {
- lastY = currBaseline[0];
- } else {
- lastY = currBaseline;
- }
- }
- newYs = [ point.canvasy, lastY ];
-
- if (stepPlot) {
- // Step plots must keep track of the top and bottom of
- // the baseline at each point.
- if (prevYs[0] === -1) {
- baseline[point.canvasx] = [ point.canvasy, axisY ];
- } else {
- baseline[point.canvasx] = [ point.canvasy, prevYs[0] ];
- }
- } else {
- baseline[point.canvasx] = point.canvasy;
- }
-
- } else {
- if (isNaN(point.canvasy) && stepPlot) {
- newYs = [ area.y + area.h, axisY ];
- } else {
- newYs = [ point.canvasy, axisY ];
- }
- }
- if (!isNaN(prevX)) {
- // Move to top fill point
- if (stepPlot) {
- ctx.lineTo(point.canvasx, prevYs[0]);
- ctx.lineTo(point.canvasx, newYs[0]);
- } else {
- ctx.lineTo(point.canvasx, newYs[0]);
- }
-
- // Record the baseline for the reverse path.
- if (stackedGraph) {
- pathBack.push([prevX, prevYs[1]]);
- if (prevStepPlot && currBaseline) {
- // Draw to the bottom of the baseline
- pathBack.push([point.canvasx, currBaseline[1]]);
- } else {
- pathBack.push([point.canvasx, newYs[1]]);
- }
- }
- } else {
- ctx.moveTo(point.canvasx, newYs[1]);
- ctx.lineTo(point.canvasx, newYs[0]);
- }
- prevYs = newYs;
- prevX = point.canvasx;
- }
- prevStepPlot = stepPlot;
- if (newYs && point) {
- traceBackPath(ctx, point.canvasx, newYs[1], pathBack);
- pathBack = [];
- }
- ctx.fill();
- }
-};
-
-return DygraphCanvasRenderer;
-
-})();
-/**
- * @license
- * Copyright 2006 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview Creates an interactive, zoomable graph based on a CSV file or
- * string. Dygraph can handle multiple series with or without error bars. The
- * date/value ranges will be automatically set. Dygraph uses the
- * &lt;canvas&gt; tag, so it only works in FF1.5+.
- * @author danvdk@gmail.com (Dan Vanderkam)
-
- Usage:
- <div id="graphdiv" style="width:800px; height:500px;"></div>
- <script type="text/javascript">
- new Dygraph(document.getElementById("graphdiv"),
- "datafile.csv", // CSV file with headers
- { }); // options
- </script>
-
- The CSV file is of the form
-
- Date,SeriesA,SeriesB,SeriesC
- YYYYMMDD,A1,B1,C1
- YYYYMMDD,A2,B2,C2
-
- If the 'errorBars' option is set in the constructor, the input should be of
- the form
- Date,SeriesA,SeriesB,...
- YYYYMMDD,A1,sigmaA1,B1,sigmaB1,...
- YYYYMMDD,A2,sigmaA2,B2,sigmaB2,...
-
- If the 'fractions' option is set, the input should be of the form:
-
- Date,SeriesA,SeriesB,...
- YYYYMMDD,A1/B1,A2/B2,...
- YYYYMMDD,A1/B1,A2/B2,...
-
- And error bars will be calculated automatically using a binomial distribution.
-
- For further documentation and examples, see http://dygraphs.com/
-
- */
-
-// For "production" code, this gets set to false by uglifyjs.
-if (typeof(DEBUG) === 'undefined') DEBUG=true;
-
-var Dygraph = (function() {
-/*global DygraphLayout:false, DygraphCanvasRenderer:false, DygraphOptions:false, G_vmlCanvasManager:false,ActiveXObject:false */
-"use strict";
-
-/**
- * Creates an interactive, zoomable chart.
- *
- * @constructor
- * @param {div | String} div A div or the id of a div into which to construct
- * the chart.
- * @param {String | Function} file A file containing CSV data or a function
- * that returns this data. The most basic expected format for each line is
- * "YYYY/MM/DD,val1,val2,...". For more information, see
- * http://dygraphs.com/data.html.
- * @param {Object} attrs Various other attributes, e.g. errorBars determines
- * whether the input data contains error ranges. For a complete list of
- * options, see http://dygraphs.com/options.html.
- */
-var Dygraph = function(div, data, opts, opt_fourth_param) {
- // These have to go above the "Hack for IE" in __init__ since .ready() can be
- // called as soon as the constructor returns. Once support for OldIE is
- // dropped, this can go down with the rest of the initializers.
- this.is_initial_draw_ = true;
- this.readyFns_ = [];
-
- if (opt_fourth_param !== undefined) {
- // Old versions of dygraphs took in the series labels as a constructor
- // parameter. This doesn't make sense anymore, but it's easy to continue
- // to support this usage.
- console.warn("Using deprecated four-argument dygraph constructor");
- this.__old_init__(div, data, opts, opt_fourth_param);
- } else {
- this.__init__(div, data, opts);
- }
-};
-
-Dygraph.NAME = "Dygraph";
-Dygraph.VERSION = "1.1.0";
-Dygraph.__repr__ = function() {
- return "[" + Dygraph.NAME + " " + Dygraph.VERSION + "]";
-};
-
-/**
- * Returns information about the Dygraph class.
- */
-Dygraph.toString = function() {
- return Dygraph.__repr__();
-};
-
-// Various default values
-Dygraph.DEFAULT_ROLL_PERIOD = 1;
-Dygraph.DEFAULT_WIDTH = 480;
-Dygraph.DEFAULT_HEIGHT = 320;
-
-// For max 60 Hz. animation:
-Dygraph.ANIMATION_STEPS = 12;
-Dygraph.ANIMATION_DURATION = 200;
-
-// Label constants for the labelsKMB and labelsKMG2 options.
-// (i.e. '100000' -> '100K')
-Dygraph.KMB_LABELS = [ 'K', 'M', 'B', 'T', 'Q' ];
-Dygraph.KMG2_BIG_LABELS = [ 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ];
-Dygraph.KMG2_SMALL_LABELS = [ 'm', 'u', 'n', 'p', 'f', 'a', 'z', 'y' ];
-
-// These are defined before DEFAULT_ATTRS so that it can refer to them.
-/**
- * @private
- * Return a string version of a number. This respects the digitsAfterDecimal
- * and maxNumberWidth options.
- * @param {number} x The number to be formatted
- * @param {Dygraph} opts An options view
- */
-Dygraph.numberValueFormatter = function(x, opts) {
- var sigFigs = opts('sigFigs');
-
- if (sigFigs !== null) {
- // User has opted for a fixed number of significant figures.
- return Dygraph.floatFormat(x, sigFigs);
- }
-
- var digits = opts('digitsAfterDecimal');
- var maxNumberWidth = opts('maxNumberWidth');
-
- var kmb = opts('labelsKMB');
- var kmg2 = opts('labelsKMG2');
-
- var label;
-
- // switch to scientific notation if we underflow or overflow fixed display.
- if (x !== 0.0 &&
- (Math.abs(x) >= Math.pow(10, maxNumberWidth) ||
- Math.abs(x) < Math.pow(10, -digits))) {
- label = x.toExponential(digits);
- } else {
- label = '' + Dygraph.round_(x, digits);
- }
-
- if (kmb || kmg2) {
- var k;
- var k_labels = [];
- var m_labels = [];
- if (kmb) {
- k = 1000;
- k_labels = Dygraph.KMB_LABELS;
- }
- if (kmg2) {
- if (kmb) console.warn("Setting both labelsKMB and labelsKMG2. Pick one!");
- k = 1024;
- k_labels = Dygraph.KMG2_BIG_LABELS;
- m_labels = Dygraph.KMG2_SMALL_LABELS;
- }
-
- var absx = Math.abs(x);
- var n = Dygraph.pow(k, k_labels.length);
- for (var j = k_labels.length - 1; j >= 0; j--, n /= k) {
- if (absx >= n) {
- label = Dygraph.round_(x / n, digits) + k_labels[j];
- break;
- }
- }
- if (kmg2) {
- // TODO(danvk): clean up this logic. Why so different than kmb?
- var x_parts = String(x.toExponential()).split('e-');
- if (x_parts.length === 2 && x_parts[1] >= 3 && x_parts[1] <= 24) {
- if (x_parts[1] % 3 > 0) {
- label = Dygraph.round_(x_parts[0] /
- Dygraph.pow(10, (x_parts[1] % 3)),
- digits);
- } else {
- label = Number(x_parts[0]).toFixed(2);
- }
- label += m_labels[Math.floor(x_parts[1] / 3) - 1];
- }
- }
- }
-
- return label;
-};
-
-/**
- * variant for use as an axisLabelFormatter.
- * @private
- */
-Dygraph.numberAxisLabelFormatter = function(x, granularity, opts) {
- return Dygraph.numberValueFormatter(x, opts);
-};
-
-/**
- * @type {!Array.<string>}
- * @private
- * @constant
- */
-Dygraph.SHORT_MONTH_NAMES_ = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
-
-
-/**
- * Convert a JS date to a string appropriate to display on an axis that
- * is displaying values at the stated granularity. This respects the
- * labelsUTC option.
- * @param {Date} date The date to format
- * @param {number} granularity One of the Dygraph granularity constants
- * @param {Dygraph} opts An options view
- * @return {string} The date formatted as local time
- * @private
- */
-Dygraph.dateAxisLabelFormatter = function(date, granularity, opts) {
- var utc = opts('labelsUTC');
- var accessors = utc ? Dygraph.DateAccessorsUTC : Dygraph.DateAccessorsLocal;
-
- var year = accessors.getFullYear(date),
- month = accessors.getMonth(date),
- day = accessors.getDate(date),
- hours = accessors.getHours(date),
- mins = accessors.getMinutes(date),
- secs = accessors.getSeconds(date),
- millis = accessors.getSeconds(date);
-
- if (granularity >= Dygraph.DECADAL) {
- return '' + year;
- } else if (granularity >= Dygraph.MONTHLY) {
- return Dygraph.SHORT_MONTH_NAMES_[month] + '&#160;' + year;
- } else {
- var frac = hours * 3600 + mins * 60 + secs + 1e-3 * millis;
- if (frac === 0 || granularity >= Dygraph.DAILY) {
- // e.g. '21 Jan' (%d%b)
- return Dygraph.zeropad(day) + '&#160;' + Dygraph.SHORT_MONTH_NAMES_[month];
- } else {
- return Dygraph.hmsString_(hours, mins, secs);
- }
- }
-};
-// alias in case anyone is referencing the old method.
-Dygraph.dateAxisFormatter = Dygraph.dateAxisLabelFormatter;
-
-/**
- * Return a string version of a JS date for a value label. This respects the
- * labelsUTC option.
- * @param {Date} date The date to be formatted
- * @param {Dygraph} opts An options view
- * @private
- */
-Dygraph.dateValueFormatter = function(d, opts) {
- return Dygraph.dateString_(d, opts('labelsUTC'));
-};
-
-/**
- * Standard plotters. These may be used by clients.
- * Available plotters are:
- * - Dygraph.Plotters.linePlotter: draws central lines (most common)
- * - Dygraph.Plotters.errorPlotter: draws error bars
- * - Dygraph.Plotters.fillPlotter: draws fills under lines (used with fillGraph)
- *
- * By default, the plotter is [fillPlotter, errorPlotter, linePlotter].
- * This causes all the lines to be drawn over all the fills/error bars.
- */
-Dygraph.Plotters = DygraphCanvasRenderer._Plotters;
-
-
-// Default attribute values.
-Dygraph.DEFAULT_ATTRS = {
- highlightCircleSize: 3,
- highlightSeriesOpts: null,
- highlightSeriesBackgroundAlpha: 0.5,
-
- labelsDivWidth: 250,
- labelsDivStyles: {
- // TODO(danvk): move defaults from createStatusMessage_ here.
- },
- labelsSeparateLines: false,
- labelsShowZeroValues: true,
- labelsKMB: false,
- labelsKMG2: false,
- showLabelsOnHighlight: true,
-
- digitsAfterDecimal: 2,
- maxNumberWidth: 6,
- sigFigs: null,
-
- strokeWidth: 1.0,
- strokeBorderWidth: 0,
- strokeBorderColor: "white",
-
- axisTickSize: 3,
- axisLabelFontSize: 14,
- rightGap: 5,
-
- showRoller: false,
- xValueParser: Dygraph.dateParser,
-
- delimiter: ',',
-
- sigma: 2.0,
- errorBars: false,
- fractions: false,
- wilsonInterval: true, // only relevant if fractions is true
- customBars: false,
- fillGraph: false,
- fillAlpha: 0.15,
- connectSeparatedPoints: false,
-
- stackedGraph: false,
- stackedGraphNaNFill: 'all',
- hideOverlayOnMouseOut: true,
-
- legend: 'onmouseover',
- stepPlot: false,
- avoidMinZero: false,
- xRangePad: 0,
- yRangePad: null,
- drawAxesAtZero: false,
-
- // Sizes of the various chart labels.
- titleHeight: 28,
- xLabelHeight: 18,
- yLabelWidth: 18,
-
- drawXAxis: true,
- drawYAxis: true,
- axisLineColor: "black",
- axisLineWidth: 0.3,
- gridLineWidth: 0.3,
- axisLabelColor: "black",
- axisLabelWidth: 50,
- drawYGrid: true,
- drawXGrid: true,
- gridLineColor: "rgb(128,128,128)",
-
- interactionModel: null, // will be set to Dygraph.Interaction.defaultModel
- animatedZooms: false, // (for now)
-
- // Range selector options
- showRangeSelector: false,
- rangeSelectorHeight: 40,
- rangeSelectorPlotStrokeColor: "#808FAB",
- rangeSelectorPlotFillColor: "#A7B1C4",
- showInRangeSelector: null,
-
- // The ordering here ensures that central lines always appear above any
- // fill bars/error bars.
- plotter: [
- Dygraph.Plotters.fillPlotter,
- Dygraph.Plotters.errorPlotter,
- Dygraph.Plotters.linePlotter
- ],
-
- plugins: [ ],
-
- // per-axis options
- axes: {
- x: {
- pixelsPerLabel: 70,
- axisLabelWidth: 60,
- axisLabelFormatter: Dygraph.dateAxisLabelFormatter,
- valueFormatter: Dygraph.dateValueFormatter,
- drawGrid: true,
- drawAxis: true,
- independentTicks: true,
- ticker: null // will be set in dygraph-tickers.js
- },
- y: {
- axisLabelWidth: 50,
- pixelsPerLabel: 30,
- valueFormatter: Dygraph.numberValueFormatter,
- axisLabelFormatter: Dygraph.numberAxisLabelFormatter,
- drawGrid: true,
- drawAxis: true,
- independentTicks: true,
- ticker: null // will be set in dygraph-tickers.js
- },
- y2: {
- axisLabelWidth: 50,
- pixelsPerLabel: 30,
- valueFormatter: Dygraph.numberValueFormatter,
- axisLabelFormatter: Dygraph.numberAxisLabelFormatter,
- drawAxis: true, // only applies when there are two axes of data.
- drawGrid: false,
- independentTicks: false,
- ticker: null // will be set in dygraph-tickers.js
- }
- }
-};
-
-// Directions for panning and zooming. Use bit operations when combined
-// values are possible.
-Dygraph.HORIZONTAL = 1;
-Dygraph.VERTICAL = 2;
-
-// Installed plugins, in order of precedence (most-general to most-specific).
-// Plugins are installed after they are defined, in plugins/install.js.
-Dygraph.PLUGINS = [
-];
-
-// Used for initializing annotation CSS rules only once.
-Dygraph.addedAnnotationCSS = false;
-
-Dygraph.prototype.__old_init__ = function(div, file, labels, attrs) {
- // Labels is no longer a constructor parameter, since it's typically set
- // directly from the data source. It also conains a name for the x-axis,
- // which the previous constructor form did not.
- if (labels !== null) {
- var new_labels = ["Date"];
- for (var i = 0; i < labels.length; i++) new_labels.push(labels[i]);
- Dygraph.update(attrs, { 'labels': new_labels });
- }
- this.__init__(div, file, attrs);
-};
-
-/**
- * Initializes the Dygraph. This creates a new DIV and constructs the PlotKit
- * and context &lt;canvas&gt; inside of it. See the constructor for details.
- * on the parameters.
- * @param {Element} div the Element to render the graph into.
- * @param {string | Function} file Source data
- * @param {Object} attrs Miscellaneous other options
- * @private
- */
-Dygraph.prototype.__init__ = function(div, file, attrs) {
- // Hack for IE: if we're using excanvas and the document hasn't finished
- // loading yet (and hence may not have initialized whatever it needs to
- // initialize), then keep calling this routine periodically until it has.
- if (/MSIE/.test(navigator.userAgent) && !window.opera &&
- typeof(G_vmlCanvasManager) != 'undefined' &&
- document.readyState != 'complete') {
- var self = this;
- setTimeout(function() { self.__init__(div, file, attrs); }, 100);
- return;
- }
-
- // Support two-argument constructor
- if (attrs === null || attrs === undefined) { attrs = {}; }
-
- attrs = Dygraph.mapLegacyOptions_(attrs);
-
- if (typeof(div) == 'string') {
- div = document.getElementById(div);
- }
-
- if (!div) {
- console.error("Constructing dygraph with a non-existent div!");
- return;
- }
-
- this.isUsingExcanvas_ = typeof(G_vmlCanvasManager) != 'undefined';
-
- // Copy the important bits into the object
- // TODO(danvk): most of these should just stay in the attrs_ dictionary.
- this.maindiv_ = div;
- this.file_ = file;
- this.rollPeriod_ = attrs.rollPeriod || Dygraph.DEFAULT_ROLL_PERIOD;
- this.previousVerticalX_ = -1;
- this.fractions_ = attrs.fractions || false;
- this.dateWindow_ = attrs.dateWindow || null;
-
- this.annotations_ = [];
-
- // Zoomed indicators - These indicate when the graph has been zoomed and on what axis.
- this.zoomed_x_ = false;
- this.zoomed_y_ = false;
-
- // Clear the div. This ensure that, if multiple dygraphs are passed the same
- // div, then only one will be drawn.
- div.innerHTML = "";
-
- // For historical reasons, the 'width' and 'height' options trump all CSS
- // rules _except_ for an explicit 'width' or 'height' on the div.
- // As an added convenience, if the div has zero height (like <div></div> does
- // without any styles), then we use a default height/width.
- if (div.style.width === '' && attrs.width) {
- div.style.width = attrs.width + "px";
- }
- if (div.style.height === '' && attrs.height) {
- div.style.height = attrs.height + "px";
- }
- if (div.style.height === '' && div.clientHeight === 0) {
- div.style.height = Dygraph.DEFAULT_HEIGHT + "px";
- if (div.style.width === '') {
- div.style.width = Dygraph.DEFAULT_WIDTH + "px";
- }
- }
- // These will be zero if the dygraph's div is hidden. In that case,
- // use the user-specified attributes if present. If not, use zero
- // and assume the user will call resize to fix things later.
- this.width_ = div.clientWidth || attrs.width || 0;
- this.height_ = div.clientHeight || attrs.height || 0;
-
- // TODO(danvk): set fillGraph to be part of attrs_ here, not user_attrs_.
- if (attrs.stackedGraph) {
- attrs.fillGraph = true;
- // TODO(nikhilk): Add any other stackedGraph checks here.
- }
-
- // DEPRECATION WARNING: All option processing should be moved from
- // attrs_ and user_attrs_ to options_, which holds all this information.
- //
- // Dygraphs has many options, some of which interact with one another.
- // To keep track of everything, we maintain two sets of options:
- //
- // this.user_attrs_ only options explicitly set by the user.
- // this.attrs_ defaults, options derived from user_attrs_, data.
- //
- // Options are then accessed this.attr_('attr'), which first looks at
- // user_attrs_ and then computed attrs_. This way Dygraphs can set intelligent
- // defaults without overriding behavior that the user specifically asks for.
- this.user_attrs_ = {};
- Dygraph.update(this.user_attrs_, attrs);
-
- // This sequence ensures that Dygraph.DEFAULT_ATTRS is never modified.
- this.attrs_ = {};
- Dygraph.updateDeep(this.attrs_, Dygraph.DEFAULT_ATTRS);
-
- this.boundaryIds_ = [];
- this.setIndexByName_ = {};
- this.datasetIndex_ = [];
-
- this.registeredEvents_ = [];
- this.eventListeners_ = {};
-
- this.attributes_ = new DygraphOptions(this);
-
- // Create the containing DIV and other interactive elements
- this.createInterface_();
-
- // Activate plugins.
- this.plugins_ = [];
- var plugins = Dygraph.PLUGINS.concat(this.getOption('plugins'));
- for (var i = 0; i < plugins.length; i++) {
- // the plugins option may contain either plugin classes or instances.
- // Plugin instances contain an activate method.
- var Plugin = plugins[i]; // either a constructor or an instance.
- var pluginInstance;
- if (typeof(Plugin.activate) !== 'undefined') {
- pluginInstance = Plugin;
- } else {
- pluginInstance = new Plugin();
- }
-
- var pluginDict = {
- plugin: pluginInstance,
- events: {},
- options: {},
- pluginOptions: {}
- };
-
- var handlers = pluginInstance.activate(this);
- for (var eventName in handlers) {
- if (!handlers.hasOwnProperty(eventName)) continue;
- // TODO(danvk): validate eventName.
- pluginDict.events[eventName] = handlers[eventName];
- }
-
- this.plugins_.push(pluginDict);
- }
-
- // At this point, plugins can no longer register event handlers.
- // Construct a map from event -> ordered list of [callback, plugin].
- for (var i = 0; i < this.plugins_.length; i++) {
- var plugin_dict = this.plugins_[i];
- for (var eventName in plugin_dict.events) {
- if (!plugin_dict.events.hasOwnProperty(eventName)) continue;
- var callback = plugin_dict.events[eventName];
-
- var pair = [plugin_dict.plugin, callback];
- if (!(eventName in this.eventListeners_)) {
- this.eventListeners_[eventName] = [pair];
- } else {
- this.eventListeners_[eventName].push(pair);
- }
- }
- }
-
- this.createDragInterface_();
-
- this.start_();
-};
-
-/**
- * Triggers a cascade of events to the various plugins which are interested in them.
- * Returns true if the "default behavior" should be prevented, i.e. if one
- * of the event listeners called event.preventDefault().
- * @private
- */
-Dygraph.prototype.cascadeEvents_ = function(name, extra_props) {
- if (!(name in this.eventListeners_)) return false;
-
- // QUESTION: can we use objects & prototypes to speed this up?
- var e = {
- dygraph: this,
- cancelable: false,
- defaultPrevented: false,
- preventDefault: function() {
- if (!e.cancelable) throw "Cannot call preventDefault on non-cancelable event.";
- e.defaultPrevented = true;
- },
- propagationStopped: false,
- stopPropagation: function() {
- e.propagationStopped = true;
- }
- };
- Dygraph.update(e, extra_props);
-
- var callback_plugin_pairs = this.eventListeners_[name];
- if (callback_plugin_pairs) {
- for (var i = callback_plugin_pairs.length - 1; i >= 0; i--) {
- var plugin = callback_plugin_pairs[i][0];
- var callback = callback_plugin_pairs[i][1];
- callback.call(plugin, e);
- if (e.propagationStopped) break;
- }
- }
- return e.defaultPrevented;
-};
-
-/**
- * Fetch a plugin instance of a particular class. Only for testing.
- * @private
- * @param {!Class} type The type of the plugin.
- * @return {Object} Instance of the plugin, or null if there is none.
- */
-Dygraph.prototype.getPluginInstance_ = function(type) {
- for (var i = 0; i < this.plugins_.length; i++) {
- var p = this.plugins_[i];
- if (p.plugin instanceof type) {
- return p.plugin;
- }
- }
- return null;
-};
-
-/**
- * Returns the zoomed status of the chart for one or both axes.
- *
- * Axis is an optional parameter. Can be set to 'x' or 'y'.
- *
- * The zoomed status for an axis is set whenever a user zooms using the mouse
- * or when the dateWindow or valueRange are updated (unless the
- * isZoomedIgnoreProgrammaticZoom option is also specified).
- */
-Dygraph.prototype.isZoomed = function(axis) {
- if (axis === null || axis === undefined) {
- return this.zoomed_x_ || this.zoomed_y_;
- }
- if (axis === 'x') return this.zoomed_x_;
- if (axis === 'y') return this.zoomed_y_;
- throw "axis parameter is [" + axis + "] must be null, 'x' or 'y'.";
-};
-
-/**
- * Returns information about the Dygraph object, including its containing ID.
- */
-Dygraph.prototype.toString = function() {
- var maindiv = this.maindiv_;
- var id = (maindiv && maindiv.id) ? maindiv.id : maindiv;
- return "[Dygraph " + id + "]";
-};
-
-/**
- * @private
- * Returns the value of an option. This may be set by the user (either in the
- * constructor or by calling updateOptions) or by dygraphs, and may be set to a
- * per-series value.
- * @param {string} name The name of the option, e.g. 'rollPeriod'.
- * @param {string} [seriesName] The name of the series to which the option
- * will be applied. If no per-series value of this option is available, then
- * the global value is returned. This is optional.
- * @return { ... } The value of the option.
- */
-Dygraph.prototype.attr_ = function(name, seriesName) {
- if (DEBUG) {
- if (typeof(Dygraph.OPTIONS_REFERENCE) === 'undefined') {
- console.error('Must include options reference JS for testing');
- } else if (!Dygraph.OPTIONS_REFERENCE.hasOwnProperty(name)) {
- console.error('Dygraphs is using property ' + name + ', which has no ' +
- 'entry in the Dygraphs.OPTIONS_REFERENCE listing.');
- // Only log this error once.
- Dygraph.OPTIONS_REFERENCE[name] = true;
- }
- }
- return seriesName ? this.attributes_.getForSeries(name, seriesName) : this.attributes_.get(name);
-};
-
-/**
- * Returns the current value for an option, as set in the constructor or via
- * updateOptions. You may pass in an (optional) series name to get per-series
- * values for the option.
- *
- * All values returned by this method should be considered immutable. If you
- * modify them, there is no guarantee that the changes will be honored or that
- * dygraphs will remain in a consistent state. If you want to modify an option,
- * use updateOptions() instead.
- *
- * @param {string} name The name of the option (e.g. 'strokeWidth')
- * @param {string=} opt_seriesName Series name to get per-series values.
- * @return {*} The value of the option.
- */
-Dygraph.prototype.getOption = function(name, opt_seriesName) {
- return this.attr_(name, opt_seriesName);
-};
-
-/**
- * Like getOption(), but specifically returns a number.
- * This is a convenience function for working with the Closure Compiler.
- * @param {string} name The name of the option (e.g. 'strokeWidth')
- * @param {string=} opt_seriesName Series name to get per-series values.
- * @return {number} The value of the option.
- * @private
- */
-Dygraph.prototype.getNumericOption = function(name, opt_seriesName) {
- return /** @type{number} */(this.getOption(name, opt_seriesName));
-};
-
-/**
- * Like getOption(), but specifically returns a string.
- * This is a convenience function for working with the Closure Compiler.
- * @param {string} name The name of the option (e.g. 'strokeWidth')
- * @param {string=} opt_seriesName Series name to get per-series values.
- * @return {string} The value of the option.
- * @private
- */
-Dygraph.prototype.getStringOption = function(name, opt_seriesName) {
- return /** @type{string} */(this.getOption(name, opt_seriesName));
-};
-
-/**
- * Like getOption(), but specifically returns a boolean.
- * This is a convenience function for working with the Closure Compiler.
- * @param {string} name The name of the option (e.g. 'strokeWidth')
- * @param {string=} opt_seriesName Series name to get per-series values.
- * @return {boolean} The value of the option.
- * @private
- */
-Dygraph.prototype.getBooleanOption = function(name, opt_seriesName) {
- return /** @type{boolean} */(this.getOption(name, opt_seriesName));
-};
-
-/**
- * Like getOption(), but specifically returns a function.
- * This is a convenience function for working with the Closure Compiler.
- * @param {string} name The name of the option (e.g. 'strokeWidth')
- * @param {string=} opt_seriesName Series name to get per-series values.
- * @return {function(...)} The value of the option.
- * @private
- */
-Dygraph.prototype.getFunctionOption = function(name, opt_seriesName) {
- return /** @type{function(...)} */(this.getOption(name, opt_seriesName));
-};
-
-Dygraph.prototype.getOptionForAxis = function(name, axis) {
- return this.attributes_.getForAxis(name, axis);
-};
-
-/**
- * @private
- * @param {string} axis The name of the axis (i.e. 'x', 'y' or 'y2')
- * @return { ... } A function mapping string -> option value
- */
-Dygraph.prototype.optionsViewForAxis_ = function(axis) {
- var self = this;
- return function(opt) {
- var axis_opts = self.user_attrs_.axes;
- if (axis_opts && axis_opts[axis] && axis_opts[axis].hasOwnProperty(opt)) {
- return axis_opts[axis][opt];
- }
-
- // I don't like that this is in a second spot.
- if (axis === 'x' && opt === 'logscale') {
- // return the default value.
- // TODO(konigsberg): pull the default from a global default.
- return false;
- }
-
- // user-specified attributes always trump defaults, even if they're less
- // specific.
- if (typeof(self.user_attrs_[opt]) != 'undefined') {
- return self.user_attrs_[opt];
- }
-
- axis_opts = self.attrs_.axes;
- if (axis_opts && axis_opts[axis] && axis_opts[axis].hasOwnProperty(opt)) {
- return axis_opts[axis][opt];
- }
- // check old-style axis options
- // TODO(danvk): add a deprecation warning if either of these match.
- if (axis == 'y' && self.axes_[0].hasOwnProperty(opt)) {
- return self.axes_[0][opt];
- } else if (axis == 'y2' && self.axes_[1].hasOwnProperty(opt)) {
- return self.axes_[1][opt];
- }
- return self.attr_(opt);
- };
-};
-
-/**
- * Returns the current rolling period, as set by the user or an option.
- * @return {number} The number of points in the rolling window
- */
-Dygraph.prototype.rollPeriod = function() {
- return this.rollPeriod_;
-};
-
-/**
- * Returns the currently-visible x-range. This can be affected by zooming,
- * panning or a call to updateOptions.
- * Returns a two-element array: [left, right].
- * If the Dygraph has dates on the x-axis, these will be millis since epoch.
- */
-Dygraph.prototype.xAxisRange = function() {
- return this.dateWindow_ ? this.dateWindow_ : this.xAxisExtremes();
-};
-
-/**
- * Returns the lower- and upper-bound x-axis values of the
- * data set.
- */
-Dygraph.prototype.xAxisExtremes = function() {
- var pad = this.getNumericOption('xRangePad') / this.plotter_.area.w;
- if (this.numRows() === 0) {
- return [0 - pad, 1 + pad];
- }
- var left = this.rawData_[0][0];
- var right = this.rawData_[this.rawData_.length - 1][0];
- if (pad) {
- // Must keep this in sync with dygraph-layout _evaluateLimits()
- var range = right - left;
- left -= range * pad;
- right += range * pad;
- }
- return [left, right];
-};
-
-/**
- * Returns the currently-visible y-range for an axis. This can be affected by
- * zooming, panning or a call to updateOptions. Axis indices are zero-based. If
- * called with no arguments, returns the range of the first axis.
- * Returns a two-element array: [bottom, top].
- */
-Dygraph.prototype.yAxisRange = function(idx) {
- if (typeof(idx) == "undefined") idx = 0;
- if (idx < 0 || idx >= this.axes_.length) {
- return null;
- }
- var axis = this.axes_[idx];
- return [ axis.computedValueRange[0], axis.computedValueRange[1] ];
-};
-
-/**
- * Returns the currently-visible y-ranges for each axis. This can be affected by
- * zooming, panning, calls to updateOptions, etc.
- * Returns an array of [bottom, top] pairs, one for each y-axis.
- */
-Dygraph.prototype.yAxisRanges = function() {
- var ret = [];
- for (var i = 0; i < this.axes_.length; i++) {
- ret.push(this.yAxisRange(i));
- }
- return ret;
-};
-
-// TODO(danvk): use these functions throughout dygraphs.
-/**
- * Convert from data coordinates to canvas/div X/Y coordinates.
- * If specified, do this conversion for the coordinate system of a particular
- * axis. Uses the first axis by default.
- * Returns a two-element array: [X, Y]
- *
- * Note: use toDomXCoord instead of toDomCoords(x, null) and use toDomYCoord
- * instead of toDomCoords(null, y, axis).
- */
-Dygraph.prototype.toDomCoords = function(x, y, axis) {
- return [ this.toDomXCoord(x), this.toDomYCoord(y, axis) ];
-};
-
-/**
- * Convert from data x coordinates to canvas/div X coordinate.
- * If specified, do this conversion for the coordinate system of a particular
- * axis.
- * Returns a single value or null if x is null.
- */
-Dygraph.prototype.toDomXCoord = function(x) {
- if (x === null) {
- return null;
- }
-
- var area = this.plotter_.area;
- var xRange = this.xAxisRange();
- return area.x + (x - xRange[0]) / (xRange[1] - xRange[0]) * area.w;
-};
-
-/**
- * Convert from data x coordinates to canvas/div Y coordinate and optional
- * axis. Uses the first axis by default.
- *
- * returns a single value or null if y is null.
- */
-Dygraph.prototype.toDomYCoord = function(y, axis) {
- var pct = this.toPercentYCoord(y, axis);
-
- if (pct === null) {
- return null;
- }
- var area = this.plotter_.area;
- return area.y + pct * area.h;
-};
-
-/**
- * Convert from canvas/div coords to data coordinates.
- * If specified, do this conversion for the coordinate system of a particular
- * axis. Uses the first axis by default.
- * Returns a two-element array: [X, Y].
- *
- * Note: use toDataXCoord instead of toDataCoords(x, null) and use toDataYCoord
- * instead of toDataCoords(null, y, axis).
- */
-Dygraph.prototype.toDataCoords = function(x, y, axis) {
- return [ this.toDataXCoord(x), this.toDataYCoord(y, axis) ];
-};
-
-/**
- * Convert from canvas/div x coordinate to data coordinate.
- *
- * If x is null, this returns null.
- */
-Dygraph.prototype.toDataXCoord = function(x) {
- if (x === null) {
- return null;
- }
-
- var area = this.plotter_.area;
- var xRange = this.xAxisRange();
-
- if (!this.attributes_.getForAxis("logscale", 'x')) {
- return xRange[0] + (x - area.x) / area.w * (xRange[1] - xRange[0]);
- } else {
- // TODO: remove duplicate code?
- // Computing the inverse of toDomCoord.
- var pct = (x - area.x) / area.w;
-
- // Computing the inverse of toPercentXCoord. The function was arrived at with
- // the following steps:
- //
- // Original calcuation:
- // pct = (log(x) - log(xRange[0])) / (log(xRange[1]) - log(xRange[0])));
- //
- // Multiply both sides by the right-side demoninator.
- // pct * (log(xRange[1] - log(xRange[0]))) = log(x) - log(xRange[0])
- //
- // add log(xRange[0]) to both sides
- // log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0])) = log(x);
- //
- // Swap both sides of the equation,
- // log(x) = log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0]))
- //
- // Use both sides as the exponent in 10^exp and we're done.
- // x = 10 ^ (log(xRange[0]) + (pct * (log(xRange[1]) - log(xRange[0])))
- var logr0 = Dygraph.log10(xRange[0]);
- var logr1 = Dygraph.log10(xRange[1]);
- var exponent = logr0 + (pct * (logr1 - logr0));
- var value = Math.pow(Dygraph.LOG_SCALE, exponent);
- return value;
- }
-};
-
-/**
- * Convert from canvas/div y coord to value.
- *
- * If y is null, this returns null.
- * if axis is null, this uses the first axis.
- */
-Dygraph.prototype.toDataYCoord = function(y, axis) {
- if (y === null) {
- return null;
- }
-
- var area = this.plotter_.area;
- var yRange = this.yAxisRange(axis);
-
- if (typeof(axis) == "undefined") axis = 0;
- if (!this.attributes_.getForAxis("logscale", axis)) {
- return yRange[0] + (area.y + area.h - y) / area.h * (yRange[1] - yRange[0]);
- } else {
- // Computing the inverse of toDomCoord.
- var pct = (y - area.y) / area.h;
-
- // Computing the inverse of toPercentYCoord. The function was arrived at with
- // the following steps:
- //
- // Original calcuation:
- // pct = (log(yRange[1]) - log(y)) / (log(yRange[1]) - log(yRange[0]));
- //
- // Multiply both sides by the right-side demoninator.
- // pct * (log(yRange[1]) - log(yRange[0])) = log(yRange[1]) - log(y);
- //
- // subtract log(yRange[1]) from both sides.
- // (pct * (log(yRange[1]) - log(yRange[0]))) - log(yRange[1]) = -log(y);
- //
- // and multiply both sides by -1.
- // log(yRange[1]) - (pct * (logr1 - log(yRange[0])) = log(y);
- //
- // Swap both sides of the equation,
- // log(y) = log(yRange[1]) - (pct * (log(yRange[1]) - log(yRange[0])));
- //
- // Use both sides as the exponent in 10^exp and we're done.
- // y = 10 ^ (log(yRange[1]) - (pct * (log(yRange[1]) - log(yRange[0]))));
- var logr0 = Dygraph.log10(yRange[0]);
- var logr1 = Dygraph.log10(yRange[1]);
- var exponent = logr1 - (pct * (logr1 - logr0));
- var value = Math.pow(Dygraph.LOG_SCALE, exponent);
- return value;
- }
-};
-
-/**
- * Converts a y for an axis to a percentage from the top to the
- * bottom of the drawing area.
- *
- * If the coordinate represents a value visible on the canvas, then
- * the value will be between 0 and 1, where 0 is the top of the canvas.
- * However, this method will return values outside the range, as
- * values can fall outside the canvas.
- *
- * If y is null, this returns null.
- * if axis is null, this uses the first axis.
- *
- * @param {number} y The data y-coordinate.
- * @param {number} [axis] The axis number on which the data coordinate lives.
- * @return {number} A fraction in [0, 1] where 0 = the top edge.
- */
-Dygraph.prototype.toPercentYCoord = function(y, axis) {
- if (y === null) {
- return null;
- }
- if (typeof(axis) == "undefined") axis = 0;
-
- var yRange = this.yAxisRange(axis);
-
- var pct;
- var logscale = this.attributes_.getForAxis("logscale", axis);
- if (logscale) {
- var logr0 = Dygraph.log10(yRange[0]);
- var logr1 = Dygraph.log10(yRange[1]);
- pct = (logr1 - Dygraph.log10(y)) / (logr1 - logr0);
- } else {
- // yRange[1] - y is unit distance from the bottom.
- // yRange[1] - yRange[0] is the scale of the range.
- // (yRange[1] - y) / (yRange[1] - yRange[0]) is the % from the bottom.
- pct = (yRange[1] - y) / (yRange[1] - yRange[0]);
- }
- return pct;
-};
-
-/**
- * Converts an x value to a percentage from the left to the right of
- * the drawing area.
- *
- * If the coordinate represents a value visible on the canvas, then
- * the value will be between 0 and 1, where 0 is the left of the canvas.
- * However, this method will return values outside the range, as
- * values can fall outside the canvas.
- *
- * If x is null, this returns null.
- * @param {number} x The data x-coordinate.
- * @return {number} A fraction in [0, 1] where 0 = the left edge.
- */
-Dygraph.prototype.toPercentXCoord = function(x) {
- if (x === null) {
- return null;
- }
-
- var xRange = this.xAxisRange();
- var pct;
- var logscale = this.attributes_.getForAxis("logscale", 'x') ;
- if (logscale === true) { // logscale can be null so we test for true explicitly.
- var logr0 = Dygraph.log10(xRange[0]);
- var logr1 = Dygraph.log10(xRange[1]);
- pct = (Dygraph.log10(x) - logr0) / (logr1 - logr0);
- } else {
- // x - xRange[0] is unit distance from the left.
- // xRange[1] - xRange[0] is the scale of the range.
- // The full expression below is the % from the left.
- pct = (x - xRange[0]) / (xRange[1] - xRange[0]);
- }
- return pct;
-};
-
-/**
- * Returns the number of columns (including the independent variable).
- * @return {number} The number of columns.
- */
-Dygraph.prototype.numColumns = function() {
- if (!this.rawData_) return 0;
- return this.rawData_[0] ? this.rawData_[0].length : this.attr_("labels").length;
-};
-
-/**
- * Returns the number of rows (excluding any header/label row).
- * @return {number} The number of rows, less any header.
- */
-Dygraph.prototype.numRows = function() {
- if (!this.rawData_) return 0;
- return this.rawData_.length;
-};
-
-/**
- * Returns the value in the given row and column. If the row and column exceed
- * the bounds on the data, returns null. Also returns null if the value is
- * missing.
- * @param {number} row The row number of the data (0-based). Row 0 is the
- * first row of data, not a header row.
- * @param {number} col The column number of the data (0-based)
- * @return {number} The value in the specified cell or null if the row/col
- * were out of range.
- */
-Dygraph.prototype.getValue = function(row, col) {
- if (row < 0 || row > this.rawData_.length) return null;
- if (col < 0 || col > this.rawData_[row].length) return null;
-
- return this.rawData_[row][col];
-};
-
-/**
- * Generates interface elements for the Dygraph: a containing div, a div to
- * display the current point, and a textbox to adjust the rolling average
- * period. Also creates the Renderer/Layout elements.
- * @private
- */
-Dygraph.prototype.createInterface_ = function() {
- // Create the all-enclosing graph div
- var enclosing = this.maindiv_;
-
- this.graphDiv = document.createElement("div");
-
- // TODO(danvk): any other styles that are useful to set here?
- this.graphDiv.style.textAlign = 'left'; // This is a CSS "reset"
- this.graphDiv.style.position = 'relative';
- enclosing.appendChild(this.graphDiv);
-
- // Create the canvas for interactive parts of the chart.
- this.canvas_ = Dygraph.createCanvas();
- this.canvas_.style.position = "absolute";
-
- // ... and for static parts of the chart.
- this.hidden_ = this.createPlotKitCanvas_(this.canvas_);
-
- this.canvas_ctx_ = Dygraph.getContext(this.canvas_);
- this.hidden_ctx_ = Dygraph.getContext(this.hidden_);
-
- this.resizeElements_();
-
- // The interactive parts of the graph are drawn on top of the chart.
- this.graphDiv.appendChild(this.hidden_);
- this.graphDiv.appendChild(this.canvas_);
- this.mouseEventElement_ = this.createMouseEventElement_();
-
- // Create the grapher
- this.layout_ = new DygraphLayout(this);
-
- var dygraph = this;
-
- this.mouseMoveHandler_ = function(e) {
- dygraph.mouseMove_(e);
- };
-
- this.mouseOutHandler_ = function(e) {
- // The mouse has left the chart if:
- // 1. e.target is inside the chart
- // 2. e.relatedTarget is outside the chart
- var target = e.target || e.fromElement;
- var relatedTarget = e.relatedTarget || e.toElement;
- if (Dygraph.isNodeContainedBy(target, dygraph.graphDiv) &&
- !Dygraph.isNodeContainedBy(relatedTarget, dygraph.graphDiv)) {
- dygraph.mouseOut_(e);
- }
- };
-
- this.addAndTrackEvent(window, 'mouseout', this.mouseOutHandler_);
- this.addAndTrackEvent(this.mouseEventElement_, 'mousemove', this.mouseMoveHandler_);
-
- // Don't recreate and register the resize handler on subsequent calls.
- // This happens when the graph is resized.
- if (!this.resizeHandler_) {
- this.resizeHandler_ = function(e) {
- dygraph.resize();
- };
-
- // Update when the window is resized.
- // TODO(danvk): drop frames depending on complexity of the chart.
- this.addAndTrackEvent(window, 'resize', this.resizeHandler_);
- }
-};
-
-Dygraph.prototype.resizeElements_ = function() {
- this.graphDiv.style.width = this.width_ + "px";
- this.graphDiv.style.height = this.height_ + "px";
-
- var canvasScale = Dygraph.getContextPixelRatio(this.canvas_ctx_);
- this.canvas_.width = this.width_ * canvasScale;
- this.canvas_.height = this.height_ * canvasScale;
- this.canvas_.style.width = this.width_ + "px"; // for IE
- this.canvas_.style.height = this.height_ + "px"; // for IE
- if (canvasScale !== 1) {
- this.canvas_ctx_.scale(canvasScale, canvasScale);
- }
-
- var hiddenScale = Dygraph.getContextPixelRatio(this.hidden_ctx_);
- this.hidden_.width = this.width_ * hiddenScale;
- this.hidden_.height = this.height_ * hiddenScale;
- this.hidden_.style.width = this.width_ + "px"; // for IE
- this.hidden_.style.height = this.height_ + "px"; // for IE
- if (hiddenScale !== 1) {
- this.hidden_ctx_.scale(hiddenScale, hiddenScale);
- }
-};
-
-/**
- * Detach DOM elements in the dygraph and null out all data references.
- * Calling this when you're done with a dygraph can dramatically reduce memory
- * usage. See, e.g., the tests/perf.html example.
- */
-Dygraph.prototype.destroy = function() {
- this.canvas_ctx_.restore();
- this.hidden_ctx_.restore();
-
- // Destroy any plugins, in the reverse order that they were registered.
- for (var i = this.plugins_.length - 1; i >= 0; i--) {
- var p = this.plugins_.pop();
- if (p.plugin.destroy) p.plugin.destroy();
- }
-
- var removeRecursive = function(node) {
- while (node.hasChildNodes()) {
- removeRecursive(node.firstChild);
- node.removeChild(node.firstChild);
- }
- };
-
- this.removeTrackedEvents_();
-
- // remove mouse event handlers (This may not be necessary anymore)
- Dygraph.removeEvent(window, 'mouseout', this.mouseOutHandler_);
- Dygraph.removeEvent(this.mouseEventElement_, 'mousemove', this.mouseMoveHandler_);
-
- // remove window handlers
- Dygraph.removeEvent(window,'resize', this.resizeHandler_);
- this.resizeHandler_ = null;
-
- removeRecursive(this.maindiv_);
-
- var nullOut = function(obj) {
- for (var n in obj) {
- if (typeof(obj[n]) === 'object') {
- obj[n] = null;
- }
- }
- };
- // These may not all be necessary, but it can't hurt...
- nullOut(this.layout_);
- nullOut(this.plotter_);
- nullOut(this);
-};
-
-/**
- * Creates the canvas on which the chart will be drawn. Only the Renderer ever
- * draws on this particular canvas. All Dygraph work (i.e. drawing hover dots
- * or the zoom rectangles) is done on this.canvas_.
- * @param {Object} canvas The Dygraph canvas over which to overlay the plot
- * @return {Object} The newly-created canvas
- * @private
- */
-Dygraph.prototype.createPlotKitCanvas_ = function(canvas) {
- var h = Dygraph.createCanvas();
- h.style.position = "absolute";
- // TODO(danvk): h should be offset from canvas. canvas needs to include
- // some extra area to make it easier to zoom in on the far left and far
- // right. h needs to be precisely the plot area, so that clipping occurs.
- h.style.top = canvas.style.top;
- h.style.left = canvas.style.left;
- h.width = this.width_;
- h.height = this.height_;
- h.style.width = this.width_ + "px"; // for IE
- h.style.height = this.height_ + "px"; // for IE
- return h;
-};
-
-/**
- * Creates an overlay element used to handle mouse events.
- * @return {Object} The mouse event element.
- * @private
- */
-Dygraph.prototype.createMouseEventElement_ = function() {
- if (this.isUsingExcanvas_) {
- var elem = document.createElement("div");
- elem.style.position = 'absolute';
- elem.style.backgroundColor = 'white';
- elem.style.filter = 'alpha(opacity=0)';
- elem.style.width = this.width_ + "px";
- elem.style.height = this.height_ + "px";
- this.graphDiv.appendChild(elem);
- return elem;
- } else {
- return this.canvas_;
- }
-};
-
-/**
- * Generate a set of distinct colors for the data series. This is done with a
- * color wheel. Saturation/Value are customizable, and the hue is
- * equally-spaced around the color wheel. If a custom set of colors is
- * specified, that is used instead.
- * @private
- */
-Dygraph.prototype.setColors_ = function() {
- var labels = this.getLabels();
- var num = labels.length - 1;
- this.colors_ = [];
- this.colorsMap_ = {};
-
- // These are used for when no custom colors are specified.
- var sat = this.getNumericOption('colorSaturation') || 1.0;
- var val = this.getNumericOption('colorValue') || 0.5;
- var half = Math.ceil(num / 2);
-
- var colors = this.getOption('colors');
- var visibility = this.visibility();
- for (var i = 0; i < num; i++) {
- if (!visibility[i]) {
- continue;
- }
- var label = labels[i + 1];
- var colorStr = this.attributes_.getForSeries('color', label);
- if (!colorStr) {
- if (colors) {
- colorStr = colors[i % colors.length];
- } else {
- // alternate colors for high contrast.
- var idx = i % 2 ? (half + (i + 1)/ 2) : Math.ceil((i + 1) / 2);
- var hue = (1.0 * idx / (1 + num));
- colorStr = Dygraph.hsvToRGB(hue, sat, val);
- }
- }
- this.colors_.push(colorStr);
- this.colorsMap_[label] = colorStr;
- }
-};
-
-/**
- * Return the list of colors. This is either the list of colors passed in the
- * attributes or the autogenerated list of rgb(r,g,b) strings.
- * This does not return colors for invisible series.
- * @return {Array.<string>} The list of colors.
- */
-Dygraph.prototype.getColors = function() {
- return this.colors_;
-};
-
-/**
- * Returns a few attributes of a series, i.e. its color, its visibility, which
- * axis it's assigned to, and its column in the original data.
- * Returns null if the series does not exist.
- * Otherwise, returns an object with column, visibility, color and axis properties.
- * The "axis" property will be set to 1 for y1 and 2 for y2.
- * The "column" property can be fed back into getValue(row, column) to get
- * values for this series.
- */
-Dygraph.prototype.getPropertiesForSeries = function(series_name) {
- var idx = -1;
- var labels = this.getLabels();
- for (var i = 1; i < labels.length; i++) {
- if (labels[i] == series_name) {
- idx = i;
- break;
- }
- }
- if (idx == -1) return null;
-
- return {
- name: series_name,
- column: idx,
- visible: this.visibility()[idx - 1],
- color: this.colorsMap_[series_name],
- axis: 1 + this.attributes_.axisForSeries(series_name)
- };
-};
-
-/**
- * Create the text box to adjust the averaging period
- * @private
- */
-Dygraph.prototype.createRollInterface_ = function() {
- // Create a roller if one doesn't exist already.
- if (!this.roller_) {
- this.roller_ = document.createElement("input");
- this.roller_.type = "text";
- this.roller_.style.display = "none";
- this.graphDiv.appendChild(this.roller_);
- }
-
- var display = this.getBooleanOption('showRoller') ? 'block' : 'none';
-
- var area = this.plotter_.area;
- var textAttr = { "position": "absolute",
- "zIndex": 10,
- "top": (area.y + area.h - 25) + "px",
- "left": (area.x + 1) + "px",
- "display": display
- };
- this.roller_.size = "2";
- this.roller_.value = this.rollPeriod_;
- for (var name in textAttr) {
- if (textAttr.hasOwnProperty(name)) {
- this.roller_.style[name] = textAttr[name];
- }
- }
-
- var dygraph = this;
- this.roller_.onchange = function() { dygraph.adjustRoll(dygraph.roller_.value); };
-};
-
-/**
- * Set up all the mouse handlers needed to capture dragging behavior for zoom
- * events.
- * @private
- */
-Dygraph.prototype.createDragInterface_ = function() {
- var context = {
- // Tracks whether the mouse is down right now
- isZooming: false,
- isPanning: false, // is this drag part of a pan?
- is2DPan: false, // if so, is that pan 1- or 2-dimensional?
- dragStartX: null, // pixel coordinates
- dragStartY: null, // pixel coordinates
- dragEndX: null, // pixel coordinates
- dragEndY: null, // pixel coordinates
- dragDirection: null,
- prevEndX: null, // pixel coordinates
- prevEndY: null, // pixel coordinates
- prevDragDirection: null,
- cancelNextDblclick: false, // see comment in dygraph-interaction-model.js
-
- // The value on the left side of the graph when a pan operation starts.
- initialLeftmostDate: null,
-
- // The number of units each pixel spans. (This won't be valid for log
- // scales)
- xUnitsPerPixel: null,
-
- // TODO(danvk): update this comment
- // The range in second/value units that the viewport encompasses during a
- // panning operation.
- dateRange: null,
-
- // Top-left corner of the canvas, in DOM coords
- // TODO(konigsberg): Rename topLeftCanvasX, topLeftCanvasY.
- px: 0,
- py: 0,
-
- // Values for use with panEdgeFraction, which limit how far outside the
- // graph's data boundaries it can be panned.
- boundedDates: null, // [minDate, maxDate]
- boundedValues: null, // [[minValue, maxValue] ...]
-
- // We cover iframes during mouse interactions. See comments in
- // dygraph-utils.js for more info on why this is a good idea.
- tarp: new Dygraph.IFrameTarp(),
-
- // contextB is the same thing as this context object but renamed.
- initializeMouseDown: function(event, g, contextB) {
- // prevents mouse drags from selecting page text.
- if (event.preventDefault) {
- event.preventDefault(); // Firefox, Chrome, etc.
- } else {
- event.returnValue = false; // IE
- event.cancelBubble = true;
- }
-
- var canvasPos = Dygraph.findPos(g.canvas_);
- contextB.px = canvasPos.x;
- contextB.py = canvasPos.y;
- contextB.dragStartX = Dygraph.dragGetX_(event, contextB);
- contextB.dragStartY = Dygraph.dragGetY_(event, contextB);
- contextB.cancelNextDblclick = false;
- contextB.tarp.cover();
- },
- destroy: function() {
- var context = this;
- if (context.isZooming || context.isPanning) {
- context.isZooming = false;
- context.dragStartX = null;
- context.dragStartY = null;
- }
-
- if (context.isPanning) {
- context.isPanning = false;
- context.draggingDate = null;
- context.dateRange = null;
- for (var i = 0; i < self.axes_.length; i++) {
- delete self.axes_[i].draggingValue;
- delete self.axes_[i].dragValueRange;
- }
- }
-
- context.tarp.uncover();
- }
- };
-
- var interactionModel = this.getOption("interactionModel");
-
- // Self is the graph.
- var self = this;
-
- // Function that binds the graph and context to the handler.
- var bindHandler = function(handler) {
- return function(event) {
- handler(event, self, context);
- };
- };
-
- for (var eventName in interactionModel) {
- if (!interactionModel.hasOwnProperty(eventName)) continue;
- this.addAndTrackEvent(this.mouseEventElement_, eventName,
- bindHandler(interactionModel[eventName]));
- }
-
- // If the user releases the mouse button during a drag, but not over the
- // canvas, then it doesn't count as a zooming action.
- if (!interactionModel.willDestroyContextMyself) {
- var mouseUpHandler = function(event) {
- context.destroy();
- };
-
- this.addAndTrackEvent(document, 'mouseup', mouseUpHandler);
- }
-};
-
-/**
- * Draw a gray zoom rectangle over the desired area of the canvas. Also clears
- * up any previous zoom rectangles that were drawn. This could be optimized to
- * avoid extra redrawing, but it's tricky to avoid interactions with the status
- * dots.
- *
- * @param {number} direction the direction of the zoom rectangle. Acceptable
- * values are Dygraph.HORIZONTAL and Dygraph.VERTICAL.
- * @param {number} startX The X position where the drag started, in canvas
- * coordinates.
- * @param {number} endX The current X position of the drag, in canvas coords.
- * @param {number} startY The Y position where the drag started, in canvas
- * coordinates.
- * @param {number} endY The current Y position of the drag, in canvas coords.
- * @param {number} prevDirection the value of direction on the previous call to
- * this function. Used to avoid excess redrawing
- * @param {number} prevEndX The value of endX on the previous call to this
- * function. Used to avoid excess redrawing
- * @param {number} prevEndY The value of endY on the previous call to this
- * function. Used to avoid excess redrawing
- * @private
- */
-Dygraph.prototype.drawZoomRect_ = function(direction, startX, endX, startY,
- endY, prevDirection, prevEndX,
- prevEndY) {
- var ctx = this.canvas_ctx_;
-
- // Clean up from the previous rect if necessary
- if (prevDirection == Dygraph.HORIZONTAL) {
- ctx.clearRect(Math.min(startX, prevEndX), this.layout_.getPlotArea().y,
- Math.abs(startX - prevEndX), this.layout_.getPlotArea().h);
- } else if (prevDirection == Dygraph.VERTICAL) {
- ctx.clearRect(this.layout_.getPlotArea().x, Math.min(startY, prevEndY),
- this.layout_.getPlotArea().w, Math.abs(startY - prevEndY));
- }
-
- // Draw a light-grey rectangle to show the new viewing area
- if (direction == Dygraph.HORIZONTAL) {
- if (endX && startX) {
- ctx.fillStyle = "rgba(128,128,128,0.33)";
- ctx.fillRect(Math.min(startX, endX), this.layout_.getPlotArea().y,
- Math.abs(endX - startX), this.layout_.getPlotArea().h);
- }
- } else if (direction == Dygraph.VERTICAL) {
- if (endY && startY) {
- ctx.fillStyle = "rgba(128,128,128,0.33)";
- ctx.fillRect(this.layout_.getPlotArea().x, Math.min(startY, endY),
- this.layout_.getPlotArea().w, Math.abs(endY - startY));
- }
- }
-
- if (this.isUsingExcanvas_) {
- this.currentZoomRectArgs_ = [direction, startX, endX, startY, endY, 0, 0, 0];
- }
-};
-
-/**
- * Clear the zoom rectangle (and perform no zoom).
- * @private
- */
-Dygraph.prototype.clearZoomRect_ = function() {
- this.currentZoomRectArgs_ = null;
- this.canvas_ctx_.clearRect(0, 0, this.width_, this.height_);
-};
-
-/**
- * Zoom to something containing [lowX, highX]. These are pixel coordinates in
- * the canvas. The exact zoom window may be slightly larger if there are no data
- * points near lowX or highX. Don't confuse this function with doZoomXDates,
- * which accepts dates that match the raw data. This function redraws the graph.
- *
- * @param {number} lowX The leftmost pixel value that should be visible.
- * @param {number} highX The rightmost pixel value that should be visible.
- * @private
- */
-Dygraph.prototype.doZoomX_ = function(lowX, highX) {
- this.currentZoomRectArgs_ = null;
- // Find the earliest and latest dates contained in this canvasx range.
- // Convert the call to date ranges of the raw data.
- var minDate = this.toDataXCoord(lowX);
- var maxDate = this.toDataXCoord(highX);
- this.doZoomXDates_(minDate, maxDate);
-};
-
-/**
- * Zoom to something containing [minDate, maxDate] values. Don't confuse this
- * method with doZoomX which accepts pixel coordinates. This function redraws
- * the graph.
- *
- * @param {number} minDate The minimum date that should be visible.
- * @param {number} maxDate The maximum date that should be visible.
- * @private
- */
-Dygraph.prototype.doZoomXDates_ = function(minDate, maxDate) {
- // TODO(danvk): when xAxisRange is null (i.e. "fit to data", the animation
- // can produce strange effects. Rather than the x-axis transitioning slowly
- // between values, it can jerk around.)
- var old_window = this.xAxisRange();
- var new_window = [minDate, maxDate];
- this.zoomed_x_ = true;
- var that = this;
- this.doAnimatedZoom(old_window, new_window, null, null, function() {
- if (that.getFunctionOption("zoomCallback")) {
- that.getFunctionOption("zoomCallback").call(that,
- minDate, maxDate, that.yAxisRanges());
- }
- });
-};
-
-/**
- * Zoom to something containing [lowY, highY]. These are pixel coordinates in
- * the canvas. This function redraws the graph.
- *
- * @param {number} lowY The topmost pixel value that should be visible.
- * @param {number} highY The lowest pixel value that should be visible.
- * @private
- */
-Dygraph.prototype.doZoomY_ = function(lowY, highY) {
- this.currentZoomRectArgs_ = null;
- // Find the highest and lowest values in pixel range for each axis.
- // Note that lowY (in pixels) corresponds to the max Value (in data coords).
- // This is because pixels increase as you go down on the screen, whereas data
- // coordinates increase as you go up the screen.
- var oldValueRanges = this.yAxisRanges();
- var newValueRanges = [];
- for (var i = 0; i < this.axes_.length; i++) {
- var hi = this.toDataYCoord(lowY, i);
- var low = this.toDataYCoord(highY, i);
- newValueRanges.push([low, hi]);
- }
-
- this.zoomed_y_ = true;
- var that = this;
- this.doAnimatedZoom(null, null, oldValueRanges, newValueRanges, function() {
- if (that.getFunctionOption("zoomCallback")) {
- var xRange = that.xAxisRange();
- that.getFunctionOption("zoomCallback").call(that,
- xRange[0], xRange[1], that.yAxisRanges());
- }
- });
-};
-
-/**
- * Transition function to use in animations. Returns values between 0.0
- * (totally old values) and 1.0 (totally new values) for each frame.
- * @private
- */
-Dygraph.zoomAnimationFunction = function(frame, numFrames) {
- var k = 1.5;
- return (1.0 - Math.pow(k, -frame)) / (1.0 - Math.pow(k, -numFrames));
-};
-
-/**
- * Reset the zoom to the original view coordinates. This is the same as
- * double-clicking on the graph.
- */
-Dygraph.prototype.resetZoom = function() {
- var dirty = false, dirtyX = false, dirtyY = false;
- if (this.dateWindow_ !== null) {
- dirty = true;
- dirtyX = true;
- }
-
- for (var i = 0; i < this.axes_.length; i++) {
- if (typeof(this.axes_[i].valueWindow) !== 'undefined' && this.axes_[i].valueWindow !== null) {
- dirty = true;
- dirtyY = true;
- }
- }
-
- // Clear any selection, since it's likely to be drawn in the wrong place.
- this.clearSelection();
-
- if (dirty) {
- this.zoomed_x_ = false;
- this.zoomed_y_ = false;
-
- var minDate = this.rawData_[0][0];
- var maxDate = this.rawData_[this.rawData_.length - 1][0];
-
- // With only one frame, don't bother calculating extreme ranges.
- // TODO(danvk): merge this block w/ the code below.
- if (!this.getBooleanOption("animatedZooms")) {
- this.dateWindow_ = null;
- for (i = 0; i < this.axes_.length; i++) {
- if (this.axes_[i].valueWindow !== null) {
- delete this.axes_[i].valueWindow;
- }
- }
- this.drawGraph_();
- if (this.getFunctionOption("zoomCallback")) {
- this.getFunctionOption("zoomCallback").call(this,
- minDate, maxDate, this.yAxisRanges());
- }
- return;
- }
-
- var oldWindow=null, newWindow=null, oldValueRanges=null, newValueRanges=null;
- if (dirtyX) {
- oldWindow = this.xAxisRange();
- newWindow = [minDate, maxDate];
- }
-
- if (dirtyY) {
- oldValueRanges = this.yAxisRanges();
- // TODO(danvk): this is pretty inefficient
- var packed = this.gatherDatasets_(this.rolledSeries_, null);
- var extremes = packed.extremes;
-
- // this has the side-effect of modifying this.axes_.
- // this doesn't make much sense in this context, but it's convenient (we
- // need this.axes_[*].extremeValues) and not harmful since we'll be
- // calling drawGraph_ shortly, which clobbers these values.
- this.computeYAxisRanges_(extremes);
-
- newValueRanges = [];
- for (i = 0; i < this.axes_.length; i++) {
- var axis = this.axes_[i];
- newValueRanges.push((axis.valueRange !== null &&
- axis.valueRange !== undefined) ?
- axis.valueRange : axis.extremeRange);
- }
- }
-
- var that = this;
- this.doAnimatedZoom(oldWindow, newWindow, oldValueRanges, newValueRanges,
- function() {
- that.dateWindow_ = null;
- for (var i = 0; i < that.axes_.length; i++) {
- if (that.axes_[i].valueWindow !== null) {
- delete that.axes_[i].valueWindow;
- }
- }
- if (that.getFunctionOption("zoomCallback")) {
- that.getFunctionOption("zoomCallback").call(that,
- minDate, maxDate, that.yAxisRanges());
- }
- });
- }
-};
-
-/**
- * Combined animation logic for all zoom functions.
- * either the x parameters or y parameters may be null.
- * @private
- */
-Dygraph.prototype.doAnimatedZoom = function(oldXRange, newXRange, oldYRanges, newYRanges, callback) {
- var steps = this.getBooleanOption("animatedZooms") ?
- Dygraph.ANIMATION_STEPS : 1;
-
- var windows = [];
- var valueRanges = [];
- var step, frac;
-
- if (oldXRange !== null && newXRange !== null) {
- for (step = 1; step <= steps; step++) {
- frac = Dygraph.zoomAnimationFunction(step, steps);
- windows[step-1] = [oldXRange[0]*(1-frac) + frac*newXRange[0],
- oldXRange[1]*(1-frac) + frac*newXRange[1]];
- }
- }
-
- if (oldYRanges !== null && newYRanges !== null) {
- for (step = 1; step <= steps; step++) {
- frac = Dygraph.zoomAnimationFunction(step, steps);
- var thisRange = [];
- for (var j = 0; j < this.axes_.length; j++) {
- thisRange.push([oldYRanges[j][0]*(1-frac) + frac*newYRanges[j][0],
- oldYRanges[j][1]*(1-frac) + frac*newYRanges[j][1]]);
- }
- valueRanges[step-1] = thisRange;
- }
- }
-
- var that = this;
- Dygraph.repeatAndCleanup(function(step) {
- if (valueRanges.length) {
- for (var i = 0; i < that.axes_.length; i++) {
- var w = valueRanges[step][i];
- that.axes_[i].valueWindow = [w[0], w[1]];
- }
- }
- if (windows.length) {
- that.dateWindow_ = windows[step];
- }
- that.drawGraph_();
- }, steps, Dygraph.ANIMATION_DURATION / steps, callback);
-};
-
-/**
- * Get the current graph's area object.
- *
- * Returns: {x, y, w, h}
- */
-Dygraph.prototype.getArea = function() {
- return this.plotter_.area;
-};
-
-/**
- * Convert a mouse event to DOM coordinates relative to the graph origin.
- *
- * Returns a two-element array: [X, Y].
- */
-Dygraph.prototype.eventToDomCoords = function(event) {
- if (event.offsetX && event.offsetY) {
- return [ event.offsetX, event.offsetY ];
- } else {
- var eventElementPos = Dygraph.findPos(this.mouseEventElement_);
- var canvasx = Dygraph.pageX(event) - eventElementPos.x;
- var canvasy = Dygraph.pageY(event) - eventElementPos.y;
- return [canvasx, canvasy];
- }
-};
-
-/**
- * Given a canvas X coordinate, find the closest row.
- * @param {number} domX graph-relative DOM X coordinate
- * Returns {number} row number.
- * @private
- */
-Dygraph.prototype.findClosestRow = function(domX) {
- var minDistX = Infinity;
- var closestRow = -1;
- var sets = this.layout_.points;
- for (var i = 0; i < sets.length; i++) {
- var points = sets[i];
- var len = points.length;
- for (var j = 0; j < len; j++) {
- var point = points[j];
- if (!Dygraph.isValidPoint(point, true)) continue;
- var dist = Math.abs(point.canvasx - domX);
- if (dist < minDistX) {
- minDistX = dist;
- closestRow = point.idx;
- }
- }
- }
-
- return closestRow;
-};
-
-/**
- * Given canvas X,Y coordinates, find the closest point.
- *
- * This finds the individual data point across all visible series
- * that's closest to the supplied DOM coordinates using the standard
- * Euclidean X,Y distance.
- *
- * @param {number} domX graph-relative DOM X coordinate
- * @param {number} domY graph-relative DOM Y coordinate
- * Returns: {row, seriesName, point}
- * @private
- */
-Dygraph.prototype.findClosestPoint = function(domX, domY) {
- var minDist = Infinity;
- var dist, dx, dy, point, closestPoint, closestSeries, closestRow;
- for ( var setIdx = this.layout_.points.length - 1 ; setIdx >= 0 ; --setIdx ) {
- var points = this.layout_.points[setIdx];
- for (var i = 0; i < points.length; ++i) {
- point = points[i];
- if (!Dygraph.isValidPoint(point)) continue;
- dx = point.canvasx - domX;
- dy = point.canvasy - domY;
- dist = dx * dx + dy * dy;
- if (dist < minDist) {
- minDist = dist;
- closestPoint = point;
- closestSeries = setIdx;
- closestRow = point.idx;
- }
- }
- }
- var name = this.layout_.setNames[closestSeries];
- return {
- row: closestRow,
- seriesName: name,
- point: closestPoint
- };
-};
-
-/**
- * Given canvas X,Y coordinates, find the touched area in a stacked graph.
- *
- * This first finds the X data point closest to the supplied DOM X coordinate,
- * then finds the series which puts the Y coordinate on top of its filled area,
- * using linear interpolation between adjacent point pairs.
- *
- * @param {number} domX graph-relative DOM X coordinate
- * @param {number} domY graph-relative DOM Y coordinate
- * Returns: {row, seriesName, point}
- * @private
- */
-Dygraph.prototype.findStackedPoint = function(domX, domY) {
- var row = this.findClosestRow(domX);
- var closestPoint, closestSeries;
- for (var setIdx = 0; setIdx < this.layout_.points.length; ++setIdx) {
- var boundary = this.getLeftBoundary_(setIdx);
- var rowIdx = row - boundary;
- var points = this.layout_.points[setIdx];
- if (rowIdx >= points.length) continue;
- var p1 = points[rowIdx];
- if (!Dygraph.isValidPoint(p1)) continue;
- var py = p1.canvasy;
- if (domX > p1.canvasx && rowIdx + 1 < points.length) {
- // interpolate series Y value using next point
- var p2 = points[rowIdx + 1];
- if (Dygraph.isValidPoint(p2)) {
- var dx = p2.canvasx - p1.canvasx;
- if (dx > 0) {
- var r = (domX - p1.canvasx) / dx;
- py += r * (p2.canvasy - p1.canvasy);
- }
- }
- } else if (domX < p1.canvasx && rowIdx > 0) {
- // interpolate series Y value using previous point
- var p0 = points[rowIdx - 1];
- if (Dygraph.isValidPoint(p0)) {
- var dx = p1.canvasx - p0.canvasx;
- if (dx > 0) {
- var r = (p1.canvasx - domX) / dx;
- py += r * (p0.canvasy - p1.canvasy);
- }
- }
- }
- // Stop if the point (domX, py) is above this series' upper edge
- if (setIdx === 0 || py < domY) {
- closestPoint = p1;
- closestSeries = setIdx;
- }
- }
- var name = this.layout_.setNames[closestSeries];
- return {
- row: row,
- seriesName: name,
- point: closestPoint
- };
-};
-
-/**
- * When the mouse moves in the canvas, display information about a nearby data
- * point and draw dots over those points in the data series. This function
- * takes care of cleanup of previously-drawn dots.
- * @param {Object} event The mousemove event from the browser.
- * @private
- */
-Dygraph.prototype.mouseMove_ = function(event) {
- // This prevents JS errors when mousing over the canvas before data loads.
- var points = this.layout_.points;
- if (points === undefined || points === null) return;
-
- var canvasCoords = this.eventToDomCoords(event);
- var canvasx = canvasCoords[0];
- var canvasy = canvasCoords[1];
-
- var highlightSeriesOpts = this.getOption("highlightSeriesOpts");
- var selectionChanged = false;
- if (highlightSeriesOpts && !this.isSeriesLocked()) {
- var closest;
- if (this.getBooleanOption("stackedGraph")) {
- closest = this.findStackedPoint(canvasx, canvasy);
- } else {
- closest = this.findClosestPoint(canvasx, canvasy);
- }
- selectionChanged = this.setSelection(closest.row, closest.seriesName);
- } else {
- var idx = this.findClosestRow(canvasx);
- selectionChanged = this.setSelection(idx);
- }
-
- var callback = this.getFunctionOption("highlightCallback");
- if (callback && selectionChanged) {
- callback.call(this, event,
- this.lastx_,
- this.selPoints_,
- this.lastRow_,
- this.highlightSet_);
- }
-};
-
-/**
- * Fetch left offset from the specified set index or if not passed, the
- * first defined boundaryIds record (see bug #236).
- * @private
- */
-Dygraph.prototype.getLeftBoundary_ = function(setIdx) {
- if (this.boundaryIds_[setIdx]) {
- return this.boundaryIds_[setIdx][0];
- } else {
- for (var i = 0; i < this.boundaryIds_.length; i++) {
- if (this.boundaryIds_[i] !== undefined) {
- return this.boundaryIds_[i][0];
- }
- }
- return 0;
- }
-};
-
-Dygraph.prototype.animateSelection_ = function(direction) {
- var totalSteps = 10;
- var millis = 30;
- if (this.fadeLevel === undefined) this.fadeLevel = 0;
- if (this.animateId === undefined) this.animateId = 0;
- var start = this.fadeLevel;
- var steps = direction < 0 ? start : totalSteps - start;
- if (steps <= 0) {
- if (this.fadeLevel) {
- this.updateSelection_(1.0);
- }
- return;
- }
-
- var thisId = ++this.animateId;
- var that = this;
- Dygraph.repeatAndCleanup(
- function(n) {
- // ignore simultaneous animations
- if (that.animateId != thisId) return;
-
- that.fadeLevel += direction;
- if (that.fadeLevel === 0) {
- that.clearSelection();
- } else {
- that.updateSelection_(that.fadeLevel / totalSteps);
- }
- },
- steps, millis, function() {});
-};
-
-/**
- * Draw dots over the selectied points in the data series. This function
- * takes care of cleanup of previously-drawn dots.
- * @private
- */
-Dygraph.prototype.updateSelection_ = function(opt_animFraction) {
- /*var defaultPrevented = */
- this.cascadeEvents_('select', {
- selectedX: this.lastx_,
- selectedPoints: this.selPoints_
- });
- // TODO(danvk): use defaultPrevented here?
-
- // Clear the previously drawn vertical, if there is one
- var i;
- var ctx = this.canvas_ctx_;
- if (this.getOption('highlightSeriesOpts')) {
- ctx.clearRect(0, 0, this.width_, this.height_);
- var alpha = 1.0 - this.getNumericOption('highlightSeriesBackgroundAlpha');
- if (alpha) {
- // Activating background fade includes an animation effect for a gradual
- // fade. TODO(klausw): make this independently configurable if it causes
- // issues? Use a shared preference to control animations?
- var animateBackgroundFade = true;
- if (animateBackgroundFade) {
- if (opt_animFraction === undefined) {
- // start a new animation
- this.animateSelection_(1);
- return;
- }
- alpha *= opt_animFraction;
- }
- ctx.fillStyle = 'rgba(255,255,255,' + alpha + ')';
- ctx.fillRect(0, 0, this.width_, this.height_);
- }
-
- // Redraw only the highlighted series in the interactive canvas (not the
- // static plot canvas, which is where series are usually drawn).
- this.plotter_._renderLineChart(this.highlightSet_, ctx);
- } else if (this.previousVerticalX_ >= 0) {
- // Determine the maximum highlight circle size.
- var maxCircleSize = 0;
- var labels = this.attr_('labels');
- for (i = 1; i < labels.length; i++) {
- var r = this.getNumericOption('highlightCircleSize', labels[i]);
- if (r > maxCircleSize) maxCircleSize = r;
- }
- var px = this.previousVerticalX_;
- ctx.clearRect(px - maxCircleSize - 1, 0,
- 2 * maxCircleSize + 2, this.height_);
- }
-
- if (this.isUsingExcanvas_ && this.currentZoomRectArgs_) {
- Dygraph.prototype.drawZoomRect_.apply(this, this.currentZoomRectArgs_);
- }
-
- if (this.selPoints_.length > 0) {
- // Draw colored circles over the center of each selected point
- var canvasx = this.selPoints_[0].canvasx;
- ctx.save();
- for (i = 0; i < this.selPoints_.length; i++) {
- var pt = this.selPoints_[i];
- if (!Dygraph.isOK(pt.canvasy)) continue;
-
- var circleSize = this.getNumericOption('highlightCircleSize', pt.name);
- var callback = this.getFunctionOption("drawHighlightPointCallback", pt.name);
- var color = this.plotter_.colors[pt.name];
- if (!callback) {
- callback = Dygraph.Circles.DEFAULT;
- }
- ctx.lineWidth = this.getNumericOption('strokeWidth', pt.name);
- ctx.strokeStyle = color;
- ctx.fillStyle = color;
- callback.call(this, this, pt.name, ctx, canvasx, pt.canvasy,
- color, circleSize, pt.idx);
- }
- ctx.restore();
-
- this.previousVerticalX_ = canvasx;
- }
-};
-
-/**
- * Manually set the selected points and display information about them in the
- * legend. The selection can be cleared using clearSelection() and queried
- * using getSelection().
- * @param {number} row Row number that should be highlighted (i.e. appear with
- * hover dots on the chart).
- * @param {seriesName} optional series name to highlight that series with the
- * the highlightSeriesOpts setting.
- * @param { locked } optional If true, keep seriesName selected when mousing
- * over the graph, disabling closest-series highlighting. Call clearSelection()
- * to unlock it.
- */
-Dygraph.prototype.setSelection = function(row, opt_seriesName, opt_locked) {
- // Extract the points we've selected
- this.selPoints_ = [];
-
- var changed = false;
- if (row !== false && row >= 0) {
- if (row != this.lastRow_) changed = true;
- this.lastRow_ = row;
- for (var setIdx = 0; setIdx < this.layout_.points.length; ++setIdx) {
- var points = this.layout_.points[setIdx];
- // Check if the point at the appropriate index is the point we're looking
- // for. If it is, just use it, otherwise search the array for a point
- // in the proper place.
- var setRow = row - this.getLeftBoundary_(setIdx);
- if (setRow < points.length && points[setRow].idx == row) {
- var point = points[setRow];
- if (point.yval !== null) this.selPoints_.push(point);
- } else {
- for (var pointIdx = 0; pointIdx < points.length; ++pointIdx) {
- var point = points[pointIdx];
- if (point.idx == row) {
- if (point.yval !== null) {
- this.selPoints_.push(point);
- }
- break;
- }
- }
- }
- }
- } else {
- if (this.lastRow_ >= 0) changed = true;
- this.lastRow_ = -1;
- }
-
- if (this.selPoints_.length) {
- this.lastx_ = this.selPoints_[0].xval;
- } else {
- this.lastx_ = -1;
- }
-
- if (opt_seriesName !== undefined) {
- if (this.highlightSet_ !== opt_seriesName) changed = true;
- this.highlightSet_ = opt_seriesName;
- }
-
- if (opt_locked !== undefined) {
- this.lockedSet_ = opt_locked;
- }
-
- if (changed) {
- this.updateSelection_(undefined);
- }
- return changed;
-};
-
-/**
- * The mouse has left the canvas. Clear out whatever artifacts remain
- * @param {Object} event the mouseout event from the browser.
- * @private
- */
-Dygraph.prototype.mouseOut_ = function(event) {
- if (this.getFunctionOption("unhighlightCallback")) {
- this.getFunctionOption("unhighlightCallback").call(this, event);
- }
-
- if (this.getBooleanOption("hideOverlayOnMouseOut") && !this.lockedSet_) {
- this.clearSelection();
- }
-};
-
-/**
- * Clears the current selection (i.e. points that were highlighted by moving
- * the mouse over the chart).
- */
-Dygraph.prototype.clearSelection = function() {
- this.cascadeEvents_('deselect', {});
-
- this.lockedSet_ = false;
- // Get rid of the overlay data
- if (this.fadeLevel) {
- this.animateSelection_(-1);
- return;
- }
- this.canvas_ctx_.clearRect(0, 0, this.width_, this.height_);
- this.fadeLevel = 0;
- this.selPoints_ = [];
- this.lastx_ = -1;
- this.lastRow_ = -1;
- this.highlightSet_ = null;
-};
-
-/**
- * Returns the number of the currently selected row. To get data for this row,
- * you can use the getValue method.
- * @return {number} row number, or -1 if nothing is selected
- */
-Dygraph.prototype.getSelection = function() {
- if (!this.selPoints_ || this.selPoints_.length < 1) {
- return -1;
- }
-
- for (var setIdx = 0; setIdx < this.layout_.points.length; setIdx++) {
- var points = this.layout_.points[setIdx];
- for (var row = 0; row < points.length; row++) {
- if (points[row].x == this.selPoints_[0].x) {
- return points[row].idx;
- }
- }
- }
- return -1;
-};
-
-/**
- * Returns the name of the currently-highlighted series.
- * Only available when the highlightSeriesOpts option is in use.
- */
-Dygraph.prototype.getHighlightSeries = function() {
- return this.highlightSet_;
-};
-
-/**
- * Returns true if the currently-highlighted series was locked
- * via setSelection(..., seriesName, true).
- */
-Dygraph.prototype.isSeriesLocked = function() {
- return this.lockedSet_;
-};
-
-/**
- * Fires when there's data available to be graphed.
- * @param {string} data Raw CSV data to be plotted
- * @private
- */
-Dygraph.prototype.loadedEvent_ = function(data) {
- this.rawData_ = this.parseCSV_(data);
- this.cascadeDataDidUpdateEvent_();
- this.predraw_();
-};
-
-/**
- * Add ticks on the x-axis representing years, months, quarters, weeks, or days
- * @private
- */
-Dygraph.prototype.addXTicks_ = function() {
- // Determine the correct ticks scale on the x-axis: quarterly, monthly, ...
- var range;
- if (this.dateWindow_) {
- range = [this.dateWindow_[0], this.dateWindow_[1]];
- } else {
- range = this.xAxisExtremes();
- }
-
- var xAxisOptionsView = this.optionsViewForAxis_('x');
- var xTicks = xAxisOptionsView('ticker')(
- range[0],
- range[1],
- this.plotter_.area.w, // TODO(danvk): should be area.width
- xAxisOptionsView,
- this);
- // var msg = 'ticker(' + range[0] + ', ' + range[1] + ', ' + this.width_ + ', ' + this.attr_('pixelsPerXLabel') + ') -> ' + JSON.stringify(xTicks);
- // console.log(msg);
- this.layout_.setXTicks(xTicks);
-};
-
-/**
- * Returns the correct handler class for the currently set options.
- * @private
- */
-Dygraph.prototype.getHandlerClass_ = function() {
- var handlerClass;
- if (this.attr_('dataHandler')) {
- handlerClass = this.attr_('dataHandler');
- } else if (this.fractions_) {
- if (this.getBooleanOption('errorBars')) {
- handlerClass = Dygraph.DataHandlers.FractionsBarsHandler;
- } else {
- handlerClass = Dygraph.DataHandlers.DefaultFractionHandler;
- }
- } else if (this.getBooleanOption('customBars')) {
- handlerClass = Dygraph.DataHandlers.CustomBarsHandler;
- } else if (this.getBooleanOption('errorBars')) {
- handlerClass = Dygraph.DataHandlers.ErrorBarsHandler;
- } else {
- handlerClass = Dygraph.DataHandlers.DefaultHandler;
- }
- return handlerClass;
-};
-
-/**
- * @private
- * This function is called once when the chart's data is changed or the options
- * dictionary is updated. It is _not_ called when the user pans or zooms. The
- * idea is that values derived from the chart's data can be computed here,
- * rather than every time the chart is drawn. This includes things like the
- * number of axes, rolling averages, etc.
- */
-Dygraph.prototype.predraw_ = function() {
- var start = new Date();
-
- // Create the correct dataHandler
- this.dataHandler_ = new (this.getHandlerClass_())();
-
- this.layout_.computePlotArea();
-
- // TODO(danvk): move more computations out of drawGraph_ and into here.
- this.computeYAxes_();
-
- if (!this.is_initial_draw_) {
- this.canvas_ctx_.restore();
- this.hidden_ctx_.restore();
- }
-
- this.canvas_ctx_.save();
- this.hidden_ctx_.save();
-
- // Create a new plotter.
- this.plotter_ = new DygraphCanvasRenderer(this,
- this.hidden_,
- this.hidden_ctx_,
- this.layout_);
-
- // The roller sits in the bottom left corner of the chart. We don't know where
- // this will be until the options are available, so it's positioned here.
- this.createRollInterface_();
-
- this.cascadeEvents_('predraw');
-
- // Convert the raw data (a 2D array) into the internal format and compute
- // rolling averages.
- this.rolledSeries_ = [null]; // x-axis is the first series and it's special
- for (var i = 1; i < this.numColumns(); i++) {
- // var logScale = this.attr_('logscale', i); // TODO(klausw): this looks wrong // konigsberg thinks so too.
- var series = this.dataHandler_.extractSeries(this.rawData_, i, this.attributes_);
- if (this.rollPeriod_ > 1) {
- series = this.dataHandler_.rollingAverage(series, this.rollPeriod_, this.attributes_);
- }
-
- this.rolledSeries_.push(series);
- }
-
- // If the data or options have changed, then we'd better redraw.
- this.drawGraph_();
-
- // This is used to determine whether to do various animations.
- var end = new Date();
- this.drawingTimeMs_ = (end - start);
-};
-
-/**
- * Point structure.
- *
- * xval_* and yval_* are the original unscaled data values,
- * while x_* and y_* are scaled to the range (0.0-1.0) for plotting.
- * yval_stacked is the cumulative Y value used for stacking graphs,
- * and bottom/top/minus/plus are used for error bar graphs.
- *
- * @typedef {{
- * idx: number,
- * name: string,
- * x: ?number,
- * xval: ?number,
- * y_bottom: ?number,
- * y: ?number,
- * y_stacked: ?number,
- * y_top: ?number,
- * yval_minus: ?number,
- * yval: ?number,
- * yval_plus: ?number,
- * yval_stacked
- * }}
- */
-Dygraph.PointType = undefined;
-
-/**
- * Calculates point stacking for stackedGraph=true.
- *
- * For stacking purposes, interpolate or extend neighboring data across
- * NaN values based on stackedGraphNaNFill settings. This is for display
- * only, the underlying data value as shown in the legend remains NaN.
- *
- * @param {Array.<Dygraph.PointType>} points Point array for a single series.
- * Updates each Point's yval_stacked property.
- * @param {Array.<number>} cumulativeYval Accumulated top-of-graph stacked Y
- * values for the series seen so far. Index is the row number. Updated
- * based on the current series's values.
- * @param {Array.<number>} seriesExtremes Min and max values, updated
- * to reflect the stacked values.
- * @param {string} fillMethod Interpolation method, one of 'all', 'inside', or
- * 'none'.
- * @private
- */
-Dygraph.stackPoints_ = function(
- points, cumulativeYval, seriesExtremes, fillMethod) {
- var lastXval = null;
- var prevPoint = null;
- var nextPoint = null;
- var nextPointIdx = -1;
-
- // Find the next stackable point starting from the given index.
- var updateNextPoint = function(idx) {
- // If we've previously found a non-NaN point and haven't gone past it yet,
- // just use that.
- if (nextPointIdx >= idx) return;
-
- // We haven't found a non-NaN point yet or have moved past it,
- // look towards the right to find a non-NaN point.
- for (var j = idx; j < points.length; ++j) {
- // Clear out a previously-found point (if any) since it's no longer
- // valid, we shouldn't use it for interpolation anymore.
- nextPoint = null;
- if (!isNaN(points[j].yval) && points[j].yval !== null) {
- nextPointIdx = j;
- nextPoint = points[j];
- break;
- }
- }
- };
-
- for (var i = 0; i < points.length; ++i) {
- var point = points[i];
- var xval = point.xval;
- if (cumulativeYval[xval] === undefined) {
- cumulativeYval[xval] = 0;
- }
-
- var actualYval = point.yval;
- if (isNaN(actualYval) || actualYval === null) {
- if(fillMethod == 'none') {
- actualYval = 0;
- } else {
- // Interpolate/extend for stacking purposes if possible.
- updateNextPoint(i);
- if (prevPoint && nextPoint && fillMethod != 'none') {
- // Use linear interpolation between prevPoint and nextPoint.
- actualYval = prevPoint.yval + (nextPoint.yval - prevPoint.yval) *
- ((xval - prevPoint.xval) / (nextPoint.xval - prevPoint.xval));
- } else if (prevPoint && fillMethod == 'all') {
- actualYval = prevPoint.yval;
- } else if (nextPoint && fillMethod == 'all') {
- actualYval = nextPoint.yval;
- } else {
- actualYval = 0;
- }
- }
- } else {
- prevPoint = point;
- }
-
- var stackedYval = cumulativeYval[xval];
- if (lastXval != xval) {
- // If an x-value is repeated, we ignore the duplicates.
- stackedYval += actualYval;
- cumulativeYval[xval] = stackedYval;
- }
- lastXval = xval;
-
- point.yval_stacked = stackedYval;
-
- if (stackedYval > seriesExtremes[1]) {
- seriesExtremes[1] = stackedYval;
- }
- if (stackedYval < seriesExtremes[0]) {
- seriesExtremes[0] = stackedYval;
- }
- }
-};
-
-
-/**
- * Loop over all fields and create datasets, calculating extreme y-values for
- * each series and extreme x-indices as we go.
- *
- * dateWindow is passed in as an explicit parameter so that we can compute
- * extreme values "speculatively", i.e. without actually setting state on the
- * dygraph.
- *
- * @param {Array.<Array.<Array.<(number|Array<number>)>>} rolledSeries, where
- * rolledSeries[seriesIndex][row] = raw point, where
- * seriesIndex is the column number starting with 1, and
- * rawPoint is [x,y] or [x, [y, err]] or [x, [y, yminus, yplus]].
- * @param {?Array.<number>} dateWindow [xmin, xmax] pair, or null.
- * @return {{
- * points: Array.<Array.<Dygraph.PointType>>,
- * seriesExtremes: Array.<Array.<number>>,
- * boundaryIds: Array.<number>}}
- * @private
- */
-Dygraph.prototype.gatherDatasets_ = function(rolledSeries, dateWindow) {
- var boundaryIds = [];
- var points = [];
- var cumulativeYval = []; // For stacked series.
- var extremes = {}; // series name -> [low, high]
- var seriesIdx, sampleIdx;
- var firstIdx, lastIdx;
- var axisIdx;
-
- // Loop over the fields (series). Go from the last to the first,
- // because if they're stacked that's how we accumulate the values.
- var num_series = rolledSeries.length - 1;
- var series;
- for (seriesIdx = num_series; seriesIdx >= 1; seriesIdx--) {
- if (!this.visibility()[seriesIdx - 1]) continue;
-
- // Prune down to the desired range, if necessary (for zooming)
- // Because there can be lines going to points outside of the visible area,
- // we actually prune to visible points, plus one on either side.
- if (dateWindow) {
- series = rolledSeries[seriesIdx];
- var low = dateWindow[0];
- var high = dateWindow[1];
-
- // TODO(danvk): do binary search instead of linear search.
- // TODO(danvk): pass firstIdx and lastIdx directly to the renderer.
- firstIdx = null;
- lastIdx = null;
- for (sampleIdx = 0; sampleIdx < series.length; sampleIdx++) {
- if (series[sampleIdx][0] >= low && firstIdx === null) {
- firstIdx = sampleIdx;
- }
- if (series[sampleIdx][0] <= high) {
- lastIdx = sampleIdx;
- }
- }
-
- if (firstIdx === null) firstIdx = 0;
- var correctedFirstIdx = firstIdx;
- var isInvalidValue = true;
- while (isInvalidValue && correctedFirstIdx > 0) {
- correctedFirstIdx--;
- // check if the y value is null.
- isInvalidValue = series[correctedFirstIdx][1] === null;
- }
-
- if (lastIdx === null) lastIdx = series.length - 1;
- var correctedLastIdx = lastIdx;
- isInvalidValue = true;
- while (isInvalidValue && correctedLastIdx < series.length - 1) {
- correctedLastIdx++;
- isInvalidValue = series[correctedLastIdx][1] === null;
- }
-
- if (correctedFirstIdx!==firstIdx) {
- firstIdx = correctedFirstIdx;
- }
- if (correctedLastIdx !== lastIdx) {
- lastIdx = correctedLastIdx;
- }
-
- boundaryIds[seriesIdx-1] = [firstIdx, lastIdx];
-
- // .slice's end is exclusive, we want to include lastIdx.
- series = series.slice(firstIdx, lastIdx + 1);
- } else {
- series = rolledSeries[seriesIdx];
- boundaryIds[seriesIdx-1] = [0, series.length-1];
- }
-
- var seriesName = this.attr_("labels")[seriesIdx];
- var seriesExtremes = this.dataHandler_.getExtremeYValues(series,
- dateWindow, this.getBooleanOption("stepPlot",seriesName));
-
- var seriesPoints = this.dataHandler_.seriesToPoints(series,
- seriesName, boundaryIds[seriesIdx-1][0]);
-
- if (this.getBooleanOption("stackedGraph")) {
- axisIdx = this.attributes_.axisForSeries(seriesName);
- if (cumulativeYval[axisIdx] === undefined) {
- cumulativeYval[axisIdx] = [];
- }
- Dygraph.stackPoints_(seriesPoints, cumulativeYval[axisIdx], seriesExtremes,
- this.getBooleanOption("stackedGraphNaNFill"));
- }
-
- extremes[seriesName] = seriesExtremes;
- points[seriesIdx] = seriesPoints;
- }
-
- return { points: points, extremes: extremes, boundaryIds: boundaryIds };
-};
-
-/**
- * Update the graph with new data. This method is called when the viewing area
- * has changed. If the underlying data or options have changed, predraw_ will
- * be called before drawGraph_ is called.
- *
- * @private
- */
-Dygraph.prototype.drawGraph_ = function() {
- var start = new Date();
-
- // This is used to set the second parameter to drawCallback, below.
- var is_initial_draw = this.is_initial_draw_;
- this.is_initial_draw_ = false;
-
- this.layout_.removeAllDatasets();
- this.setColors_();
- this.attrs_.pointSize = 0.5 * this.getNumericOption('highlightCircleSize');
-
- var packed = this.gatherDatasets_(this.rolledSeries_, this.dateWindow_);
- var points = packed.points;
- var extremes = packed.extremes;
- this.boundaryIds_ = packed.boundaryIds;
-
- this.setIndexByName_ = {};
- var labels = this.attr_("labels");
- if (labels.length > 0) {
- this.setIndexByName_[labels[0]] = 0;
- }
- var dataIdx = 0;
- for (var i = 1; i < points.length; i++) {
- this.setIndexByName_[labels[i]] = i;
- if (!this.visibility()[i - 1]) continue;
- this.layout_.addDataset(labels[i], points[i]);
- this.datasetIndex_[i] = dataIdx++;
- }
-
- this.computeYAxisRanges_(extremes);
- this.layout_.setYAxes(this.axes_);
-
- this.addXTicks_();
-
- // Save the X axis zoomed status as the updateOptions call will tend to set it erroneously
- var tmp_zoomed_x = this.zoomed_x_;
- // Tell PlotKit to use this new data and render itself
- this.zoomed_x_ = tmp_zoomed_x;
- this.layout_.evaluate();
- this.renderGraph_(is_initial_draw);
-
- if (this.getStringOption("timingName")) {
- var end = new Date();
- console.log(this.getStringOption("timingName") + " - drawGraph: " + (end - start) + "ms");
- }
-};
-
-/**
- * This does the work of drawing the chart. It assumes that the layout and axis
- * scales have already been set (e.g. by predraw_).
- *
- * @private
- */
-Dygraph.prototype.renderGraph_ = function(is_initial_draw) {
- this.cascadeEvents_('clearChart');
- this.plotter_.clear();
-
- if (this.getFunctionOption('underlayCallback')) {
- // NOTE: we pass the dygraph object to this callback twice to avoid breaking
- // users who expect a deprecated form of this callback.
- this.getFunctionOption('underlayCallback').call(this,
- this.hidden_ctx_, this.layout_.getPlotArea(), this, this);
- }
-
- var e = {
- canvas: this.hidden_,
- drawingContext: this.hidden_ctx_
- };
- this.cascadeEvents_('willDrawChart', e);
- this.plotter_.render();
- this.cascadeEvents_('didDrawChart', e);
- this.lastRow_ = -1; // because plugins/legend.js clears the legend
-
- // TODO(danvk): is this a performance bottleneck when panning?
- // The interaction canvas should already be empty in that situation.
- this.canvas_.getContext('2d').clearRect(0, 0, this.width_, this.height_);
-
- if (this.getFunctionOption("drawCallback") !== null) {
- this.getFunctionOption("drawCallback")(this, is_initial_draw);
- }
- if (is_initial_draw) {
- this.readyFired_ = true;
- while (this.readyFns_.length > 0) {
- var fn = this.readyFns_.pop();
- fn(this);
- }
- }
-};
-
-/**
- * @private
- * Determine properties of the y-axes which are independent of the data
- * currently being displayed. This includes things like the number of axes and
- * the style of the axes. It does not include the range of each axis and its
- * tick marks.
- * This fills in this.axes_.
- * axes_ = [ { options } ]
- * indices are into the axes_ array.
- */
-Dygraph.prototype.computeYAxes_ = function() {
- // Preserve valueWindow settings if they exist, and if the user hasn't
- // specified a new valueRange.
- var valueWindows, axis, index, opts, v;
- if (this.axes_ !== undefined && this.user_attrs_.hasOwnProperty("valueRange") === false) {
- valueWindows = [];
- for (index = 0; index < this.axes_.length; index++) {
- valueWindows.push(this.axes_[index].valueWindow);
- }
- }
-
- // this.axes_ doesn't match this.attributes_.axes_.options. It's used for
- // data computation as well as options storage.
- // Go through once and add all the axes.
- this.axes_ = [];
-
- for (axis = 0; axis < this.attributes_.numAxes(); axis++) {
- // Add a new axis, making a copy of its per-axis options.
- opts = { g : this };
- Dygraph.update(opts, this.attributes_.axisOptions(axis));
- this.axes_[axis] = opts;
- }
-
-
- // Copy global valueRange option over to the first axis.
- // NOTE(konigsberg): Are these two statements necessary?
- // I tried removing it. The automated tests pass, and manually
- // messing with tests/zoom.html showed no trouble.
- v = this.attr_('valueRange');
- if (v) this.axes_[0].valueRange = v;
-
- if (valueWindows !== undefined) {
- // Restore valueWindow settings.
-
- // When going from two axes back to one, we only restore
- // one axis.
- var idxCount = Math.min(valueWindows.length, this.axes_.length);
-
- for (index = 0; index < idxCount; index++) {
- this.axes_[index].valueWindow = valueWindows[index];
- }
- }
-
- for (axis = 0; axis < this.axes_.length; axis++) {
- if (axis === 0) {
- opts = this.optionsViewForAxis_('y' + (axis ? '2' : ''));
- v = opts("valueRange");
- if (v) this.axes_[axis].valueRange = v;
- } else { // To keep old behavior
- var axes = this.user_attrs_.axes;
- if (axes && axes.y2) {
- v = axes.y2.valueRange;
- if (v) this.axes_[axis].valueRange = v;
- }
- }
- }
-};
-
-/**
- * Returns the number of y-axes on the chart.
- * @return {number} the number of axes.
- */
-Dygraph.prototype.numAxes = function() {
- return this.attributes_.numAxes();
-};
-
-/**
- * @private
- * Returns axis properties for the given series.
- * @param {string} setName The name of the series for which to get axis
- * properties, e.g. 'Y1'.
- * @return {Object} The axis properties.
- */
-Dygraph.prototype.axisPropertiesForSeries = function(series) {
- // TODO(danvk): handle errors.
- return this.axes_[this.attributes_.axisForSeries(series)];
-};
-
-/**
- * @private
- * Determine the value range and tick marks for each axis.
- * @param {Object} extremes A mapping from seriesName -> [low, high]
- * This fills in the valueRange and ticks fields in each entry of this.axes_.
- */
-Dygraph.prototype.computeYAxisRanges_ = function(extremes) {
- var isNullUndefinedOrNaN = function(num) {
- return isNaN(parseFloat(num));
- };
- var numAxes = this.attributes_.numAxes();
- var ypadCompat, span, series, ypad;
-
- var p_axis;
-
- // Compute extreme values, a span and tick marks for each axis.
- for (var i = 0; i < numAxes; i++) {
- var axis = this.axes_[i];
- var logscale = this.attributes_.getForAxis("logscale", i);
- var includeZero = this.attributes_.getForAxis("includeZero", i);
- var independentTicks = this.attributes_.getForAxis("independentTicks", i);
- series = this.attributes_.seriesForAxis(i);
-
- // Add some padding. This supports two Y padding operation modes:
- //
- // - backwards compatible (yRangePad not set):
- // 10% padding for automatic Y ranges, but not for user-supplied
- // ranges, and move a close-to-zero edge to zero except if
- // avoidMinZero is set, since drawing at the edge results in
- // invisible lines. Unfortunately lines drawn at the edge of a
- // user-supplied range will still be invisible. If logscale is
- // set, add a variable amount of padding at the top but
- // none at the bottom.
- //
- // - new-style (yRangePad set by the user):
- // always add the specified Y padding.
- //
- ypadCompat = true;
- ypad = 0.1; // add 10%
- if (this.getNumericOption('yRangePad') !== null) {
- ypadCompat = false;
- // Convert pixel padding to ratio
- ypad = this.getNumericOption('yRangePad') / this.plotter_.area.h;
- }
-
- if (series.length === 0) {
- // If no series are defined or visible then use a reasonable default
- axis.extremeRange = [0, 1];
- } else {
- // Calculate the extremes of extremes.
- var minY = Infinity; // extremes[series[0]][0];
- var maxY = -Infinity; // extremes[series[0]][1];
- var extremeMinY, extremeMaxY;
-
- for (var j = 0; j < series.length; j++) {
- // this skips invisible series
- if (!extremes.hasOwnProperty(series[j])) continue;
-
- // Only use valid extremes to stop null data series' from corrupting the scale.
- extremeMinY = extremes[series[j]][0];
- if (extremeMinY !== null) {
- minY = Math.min(extremeMinY, minY);
- }
- extremeMaxY = extremes[series[j]][1];
- if (extremeMaxY !== null) {
- maxY = Math.max(extremeMaxY, maxY);
- }
- }
-
- // Include zero if requested by the user.
- if (includeZero && !logscale) {
- if (minY > 0) minY = 0;
- if (maxY < 0) maxY = 0;
- }
-
- // Ensure we have a valid scale, otherwise default to [0, 1] for safety.
- if (minY == Infinity) minY = 0;
- if (maxY == -Infinity) maxY = 1;
-
- span = maxY - minY;
- // special case: if we have no sense of scale, center on the sole value.
- if (span === 0) {
- if (maxY !== 0) {
- span = Math.abs(maxY);
- } else {
- // ... and if the sole value is zero, use range 0-1.
- maxY = 1;
- span = 1;
- }
- }
-
- var maxAxisY, minAxisY;
- if (logscale) {
- if (ypadCompat) {
- maxAxisY = maxY + ypad * span;
- minAxisY = minY;
- } else {
- var logpad = Math.exp(Math.log(span) * ypad);
- maxAxisY = maxY * logpad;
- minAxisY = minY / logpad;
- }
- } else {
- maxAxisY = maxY + ypad * span;
- minAxisY = minY - ypad * span;
-
- // Backwards-compatible behavior: Move the span to start or end at zero if it's
- // close to zero, but not if avoidMinZero is set.
- if (ypadCompat && !this.getBooleanOption("avoidMinZero")) {
- if (minAxisY < 0 && minY >= 0) minAxisY = 0;
- if (maxAxisY > 0 && maxY <= 0) maxAxisY = 0;
- }
- }
- axis.extremeRange = [minAxisY, maxAxisY];
- }
- if (axis.valueWindow) {
- // This is only set if the user has zoomed on the y-axis. It is never set
- // by a user. It takes precedence over axis.valueRange because, if you set
- // valueRange, you'd still expect to be able to pan.
- axis.computedValueRange = [axis.valueWindow[0], axis.valueWindow[1]];
- } else if (axis.valueRange) {
- // This is a user-set value range for this axis.
- var y0 = isNullUndefinedOrNaN(axis.valueRange[0]) ? axis.extremeRange[0] : axis.valueRange[0];
- var y1 = isNullUndefinedOrNaN(axis.valueRange[1]) ? axis.extremeRange[1] : axis.valueRange[1];
- if (!ypadCompat) {
- if (axis.logscale) {
- var logpad = Math.exp(Math.log(span) * ypad);
- y0 *= logpad;
- y1 /= logpad;
- } else {
- span = y1 - y0;
- y0 -= span * ypad;
- y1 += span * ypad;
- }
- }
- axis.computedValueRange = [y0, y1];
- } else {
- axis.computedValueRange = axis.extremeRange;
- }
-
-
- if (independentTicks) {
- axis.independentTicks = independentTicks;
- var opts = this.optionsViewForAxis_('y' + (i ? '2' : ''));
- var ticker = opts('ticker');
- axis.ticks = ticker(axis.computedValueRange[0],
- axis.computedValueRange[1],
- this.plotter_.area.h,
- opts,
- this);
- // Define the first independent axis as primary axis.
- if (!p_axis) p_axis = axis;
- }
- }
- if (p_axis === undefined) {
- throw ("Configuration Error: At least one axis has to have the \"independentTicks\" option activated.");
- }
- // Add ticks. By default, all axes inherit the tick positions of the
- // primary axis. However, if an axis is specifically marked as having
- // independent ticks, then that is permissible as well.
- for (var i = 0; i < numAxes; i++) {
- var axis = this.axes_[i];
-
- if (!axis.independentTicks) {
- var opts = this.optionsViewForAxis_('y' + (i ? '2' : ''));
- var ticker = opts('ticker');
- var p_ticks = p_axis.ticks;
- var p_scale = p_axis.computedValueRange[1] - p_axis.computedValueRange[0];
- var scale = axis.computedValueRange[1] - axis.computedValueRange[0];
- var tick_values = [];
- for (var k = 0; k < p_ticks.length; k++) {
- var y_frac = (p_ticks[k].v - p_axis.computedValueRange[0]) / p_scale;
- var y_val = axis.computedValueRange[0] + y_frac * scale;
- tick_values.push(y_val);
- }
-
- axis.ticks = ticker(axis.computedValueRange[0],
- axis.computedValueRange[1],
- this.plotter_.area.h,
- opts,
- this,
- tick_values);
- }
- }
-};
-
-/**
- * Detects the type of the str (date or numeric) and sets the various
- * formatting attributes in this.attrs_ based on this type.
- * @param {string} str An x value.
- * @private
- */
-Dygraph.prototype.detectTypeFromString_ = function(str) {
- var isDate = false;
- var dashPos = str.indexOf('-'); // could be 2006-01-01 _or_ 1.0e-2
- if ((dashPos > 0 && (str[dashPos-1] != 'e' && str[dashPos-1] != 'E')) ||
- str.indexOf('/') >= 0 ||
- isNaN(parseFloat(str))) {
- isDate = true;
- } else if (str.length == 8 && str > '19700101' && str < '20371231') {
- // TODO(danvk): remove support for this format.
- isDate = true;
- }
-
- this.setXAxisOptions_(isDate);
-};
-
-Dygraph.prototype.setXAxisOptions_ = function(isDate) {
- if (isDate) {
- this.attrs_.xValueParser = Dygraph.dateParser;
- this.attrs_.axes.x.valueFormatter = Dygraph.dateValueFormatter;
- this.attrs_.axes.x.ticker = Dygraph.dateTicker;
- this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisLabelFormatter;
- } else {
- /** @private (shut up, jsdoc!) */
- this.attrs_.xValueParser = function(x) { return parseFloat(x); };
- // TODO(danvk): use Dygraph.numberValueFormatter here?
- /** @private (shut up, jsdoc!) */
- this.attrs_.axes.x.valueFormatter = function(x) { return x; };
- this.attrs_.axes.x.ticker = Dygraph.numericTicks;
- this.attrs_.axes.x.axisLabelFormatter = this.attrs_.axes.x.valueFormatter;
- }
-};
-
-/**
- * @private
- * Parses a string in a special csv format. We expect a csv file where each
- * line is a date point, and the first field in each line is the date string.
- * We also expect that all remaining fields represent series.
- * if the errorBars attribute is set, then interpret the fields as:
- * date, series1, stddev1, series2, stddev2, ...
- * @param {[Object]} data See above.
- *
- * @return [Object] An array with one entry for each row. These entries
- * are an array of cells in that row. The first entry is the parsed x-value for
- * the row. The second, third, etc. are the y-values. These can take on one of
- * three forms, depending on the CSV and constructor parameters:
- * 1. numeric value
- * 2. [ value, stddev ]
- * 3. [ low value, center value, high value ]
- */
-Dygraph.prototype.parseCSV_ = function(data) {
- var ret = [];
- var line_delimiter = Dygraph.detectLineDelimiter(data);
- var lines = data.split(line_delimiter || "\n");
- var vals, j;
-
- // Use the default delimiter or fall back to a tab if that makes sense.
- var delim = this.getStringOption('delimiter');
- if (lines[0].indexOf(delim) == -1 && lines[0].indexOf('\t') >= 0) {
- delim = '\t';
- }
-
- var start = 0;
- if (!('labels' in this.user_attrs_)) {
- // User hasn't explicitly set labels, so they're (presumably) in the CSV.
- start = 1;
- this.attrs_.labels = lines[0].split(delim); // NOTE: _not_ user_attrs_.
- this.attributes_.reparseSeries();
- }
- var line_no = 0;
-
- var xParser;
- var defaultParserSet = false; // attempt to auto-detect x value type
- var expectedCols = this.attr_("labels").length;
- var outOfOrder = false;
- for (var i = start; i < lines.length; i++) {
- var line = lines[i];
- line_no = i;
- if (line.length === 0) continue; // skip blank lines
- if (line[0] == '#') continue; // skip comment lines
- var inFields = line.split(delim);
- if (inFields.length < 2) continue;
-
- var fields = [];
- if (!defaultParserSet) {
- this.detectTypeFromString_(inFields[0]);
- xParser = this.getFunctionOption("xValueParser");
- defaultParserSet = true;
- }
- fields[0] = xParser(inFields[0], this);
-
- // If fractions are expected, parse the numbers as "A/B"
- if (this.fractions_) {
- for (j = 1; j < inFields.length; j++) {
- // TODO(danvk): figure out an appropriate way to flag parse errors.
- vals = inFields[j].split("/");
- if (vals.length != 2) {
- console.error('Expected fractional "num/den" values in CSV data ' +
- "but found a value '" + inFields[j] + "' on line " +
- (1 + i) + " ('" + line + "') which is not of this form.");
- fields[j] = [0, 0];
- } else {
- fields[j] = [Dygraph.parseFloat_(vals[0], i, line),
- Dygraph.parseFloat_(vals[1], i, line)];
- }
- }
- } else if (this.getBooleanOption("errorBars")) {
- // If there are error bars, values are (value, stddev) pairs
- if (inFields.length % 2 != 1) {
- console.error('Expected alternating (value, stdev.) pairs in CSV data ' +
- 'but line ' + (1 + i) + ' has an odd number of values (' +
- (inFields.length - 1) + "): '" + line + "'");
- }
- for (j = 1; j < inFields.length; j += 2) {
- fields[(j + 1) / 2] = [Dygraph.parseFloat_(inFields[j], i, line),
- Dygraph.parseFloat_(inFields[j + 1], i, line)];
- }
- } else if (this.getBooleanOption("customBars")) {
- // Bars are a low;center;high tuple
- for (j = 1; j < inFields.length; j++) {
- var val = inFields[j];
- if (/^ *$/.test(val)) {
- fields[j] = [null, null, null];
- } else {
- vals = val.split(";");
- if (vals.length == 3) {
- fields[j] = [ Dygraph.parseFloat_(vals[0], i, line),
- Dygraph.parseFloat_(vals[1], i, line),
- Dygraph.parseFloat_(vals[2], i, line) ];
- } else {
- console.warn('When using customBars, values must be either blank ' +
- 'or "low;center;high" tuples (got "' + val +
- '" on line ' + (1+i));
- }
- }
- }
- } else {
- // Values are just numbers
- for (j = 1; j < inFields.length; j++) {
- fields[j] = Dygraph.parseFloat_(inFields[j], i, line);
- }
- }
- if (ret.length > 0 && fields[0] < ret[ret.length - 1][0]) {
- outOfOrder = true;
- }
-
- if (fields.length != expectedCols) {
- console.error("Number of columns in line " + i + " (" + fields.length +
- ") does not agree with number of labels (" + expectedCols +
- ") " + line);
- }
-
- // If the user specified the 'labels' option and none of the cells of the
- // first row parsed correctly, then they probably double-specified the
- // labels. We go with the values set in the option, discard this row and
- // log a warning to the JS console.
- if (i === 0 && this.attr_('labels')) {
- var all_null = true;
- for (j = 0; all_null && j < fields.length; j++) {
- if (fields[j]) all_null = false;
- }
- if (all_null) {
- console.warn("The dygraphs 'labels' option is set, but the first row " +
- "of CSV data ('" + line + "') appears to also contain " +
- "labels. Will drop the CSV labels and use the option " +
- "labels.");
- continue;
- }
- }
- ret.push(fields);
- }
-
- if (outOfOrder) {
- console.warn("CSV is out of order; order it correctly to speed loading.");
- ret.sort(function(a,b) { return a[0] - b[0]; });
- }
-
- return ret;
-};
-
-/**
- * The user has provided their data as a pre-packaged JS array. If the x values
- * are numeric, this is the same as dygraphs' internal format. If the x values
- * are dates, we need to convert them from Date objects to ms since epoch.
- * @param {!Array} data
- * @return {Object} data with numeric x values.
- * @private
- */
-Dygraph.prototype.parseArray_ = function(data) {
- // Peek at the first x value to see if it's numeric.
- if (data.length === 0) {
- console.error("Can't plot empty data set");
- return null;
- }
- if (data[0].length === 0) {
- console.error("Data set cannot contain an empty row");
- return null;
- }
-
- var i;
- if (this.attr_("labels") === null) {
- console.warn("Using default labels. Set labels explicitly via 'labels' " +
- "in the options parameter");
- this.attrs_.labels = [ "X" ];
- for (i = 1; i < data[0].length; i++) {
- this.attrs_.labels.push("Y" + i); // Not user_attrs_.
- }
- this.attributes_.reparseSeries();
- } else {
- var num_labels = this.attr_("labels");
- if (num_labels.length != data[0].length) {
- console.error("Mismatch between number of labels (" + num_labels + ")" +
- " and number of columns in array (" + data[0].length + ")");
- return null;
- }
- }
-
- if (Dygraph.isDateLike(data[0][0])) {
- // Some intelligent defaults for a date x-axis.
- this.attrs_.axes.x.valueFormatter = Dygraph.dateValueFormatter;
- this.attrs_.axes.x.ticker = Dygraph.dateTicker;
- this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisLabelFormatter;
-
- // Assume they're all dates.
- var parsedData = Dygraph.clone(data);
- for (i = 0; i < data.length; i++) {
- if (parsedData[i].length === 0) {
- console.error("Row " + (1 + i) + " of data is empty");
- return null;
- }
- if (parsedData[i][0] === null ||
- typeof(parsedData[i][0].getTime) != 'function' ||
- isNaN(parsedData[i][0].getTime())) {
- console.error("x value in row " + (1 + i) + " is not a Date");
- return null;
- }
- parsedData[i][0] = parsedData[i][0].getTime();
- }
- return parsedData;
- } else {
- // Some intelligent defaults for a numeric x-axis.
- /** @private (shut up, jsdoc!) */
- this.attrs_.axes.x.valueFormatter = function(x) { return x; };
- this.attrs_.axes.x.ticker = Dygraph.numericTicks;
- this.attrs_.axes.x.axisLabelFormatter = Dygraph.numberAxisLabelFormatter;
- return data;
- }
-};
-
-/**
- * Parses a DataTable object from gviz.
- * The data is expected to have a first column that is either a date or a
- * number. All subsequent columns must be numbers. If there is a clear mismatch
- * between this.xValueParser_ and the type of the first column, it will be
- * fixed. Fills out rawData_.
- * @param {!google.visualization.DataTable} data See above.
- * @private
- */
-Dygraph.prototype.parseDataTable_ = function(data) {
- var shortTextForAnnotationNum = function(num) {
- // converts [0-9]+ [A-Z][a-z]*
- // example: 0=A, 1=B, 25=Z, 26=Aa, 27=Ab
- // and continues like.. Ba Bb .. Za .. Zz..Aaa...Zzz Aaaa Zzzz
- var shortText = String.fromCharCode(65 /* A */ + num % 26);
- num = Math.floor(num / 26);
- while ( num > 0 ) {
- shortText = String.fromCharCode(65 /* A */ + (num - 1) % 26 ) + shortText.toLowerCase();
- num = Math.floor((num - 1) / 26);
- }
- return shortText;
- };
-
- var cols = data.getNumberOfColumns();
- var rows = data.getNumberOfRows();
-
- var indepType = data.getColumnType(0);
- if (indepType == 'date' || indepType == 'datetime') {
- this.attrs_.xValueParser = Dygraph.dateParser;
- this.attrs_.axes.x.valueFormatter = Dygraph.dateValueFormatter;
- this.attrs_.axes.x.ticker = Dygraph.dateTicker;
- this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisLabelFormatter;
- } else if (indepType == 'number') {
- this.attrs_.xValueParser = function(x) { return parseFloat(x); };
- this.attrs_.axes.x.valueFormatter = function(x) { return x; };
- this.attrs_.axes.x.ticker = Dygraph.numericTicks;
- this.attrs_.axes.x.axisLabelFormatter = this.attrs_.axes.x.valueFormatter;
- } else {
- console.error("only 'date', 'datetime' and 'number' types are supported " +
- "for column 1 of DataTable input (Got '" + indepType + "')");
- return null;
- }
-
- // Array of the column indices which contain data (and not annotations).
- var colIdx = [];
- var annotationCols = {}; // data index -> [annotation cols]
- var hasAnnotations = false;
- var i, j;
- for (i = 1; i < cols; i++) {
- var type = data.getColumnType(i);
- if (type == 'number') {
- colIdx.push(i);
- } else if (type == 'string' && this.getBooleanOption('displayAnnotations')) {
- // This is OK -- it's an annotation column.
- var dataIdx = colIdx[colIdx.length - 1];
- if (!annotationCols.hasOwnProperty(dataIdx)) {
- annotationCols[dataIdx] = [i];
- } else {
- annotationCols[dataIdx].push(i);
- }
- hasAnnotations = true;
- } else {
- console.error("Only 'number' is supported as a dependent type with Gviz." +
- " 'string' is only supported if displayAnnotations is true");
- }
- }
-
- // Read column labels
- // TODO(danvk): add support back for errorBars
- var labels = [data.getColumnLabel(0)];
- for (i = 0; i < colIdx.length; i++) {
- labels.push(data.getColumnLabel(colIdx[i]));
- if (this.getBooleanOption("errorBars")) i += 1;
- }
- this.attrs_.labels = labels;
- cols = labels.length;
-
- var ret = [];
- var outOfOrder = false;
- var annotations = [];
- for (i = 0; i < rows; i++) {
- var row = [];
- if (typeof(data.getValue(i, 0)) === 'undefined' ||
- data.getValue(i, 0) === null) {
- console.warn("Ignoring row " + i +
- " of DataTable because of undefined or null first column.");
- continue;
- }
-
- if (indepType == 'date' || indepType == 'datetime') {
- row.push(data.getValue(i, 0).getTime());
- } else {
- row.push(data.getValue(i, 0));
- }
- if (!this.getBooleanOption("errorBars")) {
- for (j = 0; j < colIdx.length; j++) {
- var col = colIdx[j];
- row.push(data.getValue(i, col));
- if (hasAnnotations &&
- annotationCols.hasOwnProperty(col) &&
- data.getValue(i, annotationCols[col][0]) !== null) {
- var ann = {};
- ann.series = data.getColumnLabel(col);
- ann.xval = row[0];
- ann.shortText = shortTextForAnnotationNum(annotations.length);
- ann.text = '';
- for (var k = 0; k < annotationCols[col].length; k++) {
- if (k) ann.text += "\n";
- ann.text += data.getValue(i, annotationCols[col][k]);
- }
- annotations.push(ann);
- }
- }
-
- // Strip out infinities, which give dygraphs problems later on.
- for (j = 0; j < row.length; j++) {
- if (!isFinite(row[j])) row[j] = null;
- }
- } else {
- for (j = 0; j < cols - 1; j++) {
- row.push([ data.getValue(i, 1 + 2 * j), data.getValue(i, 2 + 2 * j) ]);
- }
- }
- if (ret.length > 0 && row[0] < ret[ret.length - 1][0]) {
- outOfOrder = true;
- }
- ret.push(row);
- }
-
- if (outOfOrder) {
- console.warn("DataTable is out of order; order it correctly to speed loading.");
- ret.sort(function(a,b) { return a[0] - b[0]; });
- }
- this.rawData_ = ret;
-
- if (annotations.length > 0) {
- this.setAnnotations(annotations, true);
- }
- this.attributes_.reparseSeries();
-};
-
-/**
- * Signals to plugins that the chart data has updated.
- * This happens after the data has updated but before the chart has redrawn.
- */
-Dygraph.prototype.cascadeDataDidUpdateEvent_ = function() {
- // TODO(danvk): there are some issues checking xAxisRange() and using
- // toDomCoords from handlers of this event. The visible range should be set
- // when the chart is drawn, not derived from the data.
- this.cascadeEvents_('dataDidUpdate', {});
-};
-
-/**
- * Get the CSV data. If it's in a function, call that function. If it's in a
- * file, do an XMLHttpRequest to get it.
- * @private
- */
-Dygraph.prototype.start_ = function() {
- var data = this.file_;
-
- // Functions can return references of all other types.
- if (typeof data == 'function') {
- data = data();
- }
-
- if (Dygraph.isArrayLike(data)) {
- this.rawData_ = this.parseArray_(data);
- this.cascadeDataDidUpdateEvent_();
- this.predraw_();
- } else if (typeof data == 'object' &&
- typeof data.getColumnRange == 'function') {
- // must be a DataTable from gviz.
- this.parseDataTable_(data);
- this.cascadeDataDidUpdateEvent_();
- this.predraw_();
- } else if (typeof data == 'string') {
- // Heuristic: a newline means it's CSV data. Otherwise it's an URL.
- var line_delimiter = Dygraph.detectLineDelimiter(data);
- if (line_delimiter) {
- this.loadedEvent_(data);
- } else {
- // REMOVE_FOR_IE
- var req;
- if (window.XMLHttpRequest) {
- // Firefox, Opera, IE7, and other browsers will use the native object
- req = new XMLHttpRequest();
- } else {
- // IE 5 and 6 will use the ActiveX control
- req = new ActiveXObject("Microsoft.XMLHTTP");
- }
-
- var caller = this;
- req.onreadystatechange = function () {
- if (req.readyState == 4) {
- if (req.status === 200 || // Normal http
- req.status === 0) { // Chrome w/ --allow-file-access-from-files
- caller.loadedEvent_(req.responseText);
- }
- }
- };
-
- req.open("GET", data, true);
- req.send(null);
- }
- } else {
- console.error("Unknown data format: " + (typeof data));
- }
-};
-
-/**
- * Changes various properties of the graph. These can include:
- * <ul>
- * <li>file: changes the source data for the graph</li>
- * <li>errorBars: changes whether the data contains stddev</li>
- * </ul>
- *
- * There's a huge variety of options that can be passed to this method. For a
- * full list, see http://dygraphs.com/options.html.
- *
- * @param {Object} input_attrs The new properties and values
- * @param {boolean} block_redraw Usually the chart is redrawn after every
- * call to updateOptions(). If you know better, you can pass true to
- * explicitly block the redraw. This can be useful for chaining
- * updateOptions() calls, avoiding the occasional infinite loop and
- * preventing redraws when it's not necessary (e.g. when updating a
- * callback).
- */
-Dygraph.prototype.updateOptions = function(input_attrs, block_redraw) {
- if (typeof(block_redraw) == 'undefined') block_redraw = false;
-
- // mapLegacyOptions_ drops the "file" parameter as a convenience to us.
- var file = input_attrs.file;
- var attrs = Dygraph.mapLegacyOptions_(input_attrs);
-
- // TODO(danvk): this is a mess. Move these options into attr_.
- if ('rollPeriod' in attrs) {
- this.rollPeriod_ = attrs.rollPeriod;
- }
- if ('dateWindow' in attrs) {
- this.dateWindow_ = attrs.dateWindow;
- if (!('isZoomedIgnoreProgrammaticZoom' in attrs)) {
- this.zoomed_x_ = (attrs.dateWindow !== null);
- }
- }
- if ('valueRange' in attrs && !('isZoomedIgnoreProgrammaticZoom' in attrs)) {
- this.zoomed_y_ = (attrs.valueRange !== null);
- }
-
- // TODO(danvk): validate per-series options.
- // Supported:
- // strokeWidth
- // pointSize
- // drawPoints
- // highlightCircleSize
-
- // Check if this set options will require new points.
- var requiresNewPoints = Dygraph.isPixelChangingOptionList(this.attr_("labels"), attrs);
-
- Dygraph.updateDeep(this.user_attrs_, attrs);
-
- this.attributes_.reparseSeries();
-
- if (file) {
- // This event indicates that the data is about to change, but hasn't yet.
- // TODO(danvk): support cancelation of the update via this event.
- this.cascadeEvents_('dataWillUpdate', {});
-
- this.file_ = file;
- if (!block_redraw) this.start_();
- } else {
- if (!block_redraw) {
- if (requiresNewPoints) {
- this.predraw_();
- } else {
- this.renderGraph_(false);
- }
- }
- }
-};
-
-/**
- * Returns a copy of the options with deprecated names converted into current
- * names. Also drops the (potentially-large) 'file' attribute. If the caller is
- * interested in that, they should save a copy before calling this.
- * @private
- */
-Dygraph.mapLegacyOptions_ = function(attrs) {
- var my_attrs = {};
- for (var k in attrs) {
- if (!attrs.hasOwnProperty(k)) continue;
- if (k == 'file') continue;
- if (attrs.hasOwnProperty(k)) my_attrs[k] = attrs[k];
- }
-
- var set = function(axis, opt, value) {
- if (!my_attrs.axes) my_attrs.axes = {};
- if (!my_attrs.axes[axis]) my_attrs.axes[axis] = {};
- my_attrs.axes[axis][opt] = value;
- };
- var map = function(opt, axis, new_opt) {
- if (typeof(attrs[opt]) != 'undefined') {
- console.warn("Option " + opt + " is deprecated. Use the " +
- new_opt + " option for the " + axis + " axis instead. " +
- "(e.g. { axes : { " + axis + " : { " + new_opt + " : ... } } } " +
- "(see http://dygraphs.com/per-axis.html for more information.");
- set(axis, new_opt, attrs[opt]);
- delete my_attrs[opt];
- }
- };
-
- // This maps, e.g., xValueFormater -> axes: { x: { valueFormatter: ... } }
- map('xValueFormatter', 'x', 'valueFormatter');
- map('pixelsPerXLabel', 'x', 'pixelsPerLabel');
- map('xAxisLabelFormatter', 'x', 'axisLabelFormatter');
- map('xTicker', 'x', 'ticker');
- map('yValueFormatter', 'y', 'valueFormatter');
- map('pixelsPerYLabel', 'y', 'pixelsPerLabel');
- map('yAxisLabelFormatter', 'y', 'axisLabelFormatter');
- map('yTicker', 'y', 'ticker');
- map('drawXGrid', 'x', 'drawGrid');
- map('drawXAxis', 'x', 'drawAxis');
- map('drawYGrid', 'y', 'drawGrid');
- map('drawYAxis', 'y', 'drawAxis');
- map('xAxisLabelWidth', 'x', 'axisLabelWidth');
- map('yAxisLabelWidth', 'y', 'axisLabelWidth');
- return my_attrs;
-};
-
-/**
- * Resizes the dygraph. If no parameters are specified, resizes to fill the
- * containing div (which has presumably changed size since the dygraph was
- * instantiated. If the width/height are specified, the div will be resized.
- *
- * This is far more efficient than destroying and re-instantiating a
- * Dygraph, since it doesn't have to reparse the underlying data.
- *
- * @param {number} width Width (in pixels)
- * @param {number} height Height (in pixels)
- */
-Dygraph.prototype.resize = function(width, height) {
- if (this.resize_lock) {
- return;
- }
- this.resize_lock = true;
-
- if ((width === null) != (height === null)) {
- console.warn("Dygraph.resize() should be called with zero parameters or " +
- "two non-NULL parameters. Pretending it was zero.");
- width = height = null;
- }
-
- var old_width = this.width_;
- var old_height = this.height_;
-
- if (width) {
- this.maindiv_.style.width = width + "px";
- this.maindiv_.style.height = height + "px";
- this.width_ = width;
- this.height_ = height;
- } else {
- this.width_ = this.maindiv_.clientWidth;
- this.height_ = this.maindiv_.clientHeight;
- }
-
- if (old_width != this.width_ || old_height != this.height_) {
- // Resizing a canvas erases it, even when the size doesn't change, so
- // any resize needs to be followed by a redraw.
- this.resizeElements_();
- this.predraw_();
- }
-
- this.resize_lock = false;
-};
-
-/**
- * Adjusts the number of points in the rolling average. Updates the graph to
- * reflect the new averaging period.
- * @param {number} length Number of points over which to average the data.
- */
-Dygraph.prototype.adjustRoll = function(length) {
- this.rollPeriod_ = length;
- this.predraw_();
-};
-
-/**
- * Returns a boolean array of visibility statuses.
- */
-Dygraph.prototype.visibility = function() {
- // Do lazy-initialization, so that this happens after we know the number of
- // data series.
- if (!this.getOption("visibility")) {
- this.attrs_.visibility = [];
- }
- // TODO(danvk): it looks like this could go into an infinite loop w/ user_attrs.
- while (this.getOption("visibility").length < this.numColumns() - 1) {
- this.attrs_.visibility.push(true);
- }
- return this.getOption("visibility");
-};
-
-/**
- * Changes the visiblity of a series.
- *
- * @param {number} num the series index
- * @param {boolean} value true or false, identifying the visibility.
- */
-Dygraph.prototype.setVisibility = function(num, value) {
- var x = this.visibility();
- if (num < 0 || num >= x.length) {
- console.warn("invalid series number in setVisibility: " + num);
- } else {
- x[num] = value;
- this.predraw_();
- }
-};
-
-/**
- * How large of an area will the dygraph render itself in?
- * This is used for testing.
- * @return A {width: w, height: h} object.
- * @private
- */
-Dygraph.prototype.size = function() {
- return { width: this.width_, height: this.height_ };
-};
-
-/**
- * Update the list of annotations and redraw the chart.
- * See dygraphs.com/annotations.html for more info on how to use annotations.
- * @param ann {Array} An array of annotation objects.
- * @param suppressDraw {Boolean} Set to "true" to block chart redraw (optional).
- */
-Dygraph.prototype.setAnnotations = function(ann, suppressDraw) {
- // Only add the annotation CSS rule once we know it will be used.
- Dygraph.addAnnotationRule();
- this.annotations_ = ann;
- if (!this.layout_) {
- console.warn("Tried to setAnnotations before dygraph was ready. " +
- "Try setting them in a ready() block. See " +
- "dygraphs.com/tests/annotation.html");
- return;
- }
-
- this.layout_.setAnnotations(this.annotations_);
- if (!suppressDraw) {
- this.predraw_();
- }
-};
-
-/**
- * Return the list of annotations.
- */
-Dygraph.prototype.annotations = function() {
- return this.annotations_;
-};
-
-/**
- * Get the list of label names for this graph. The first column is the
- * x-axis, so the data series names start at index 1.
- *
- * Returns null when labels have not yet been defined.
- */
-Dygraph.prototype.getLabels = function() {
- var labels = this.attr_("labels");
- return labels ? labels.slice() : null;
-};
-
-/**
- * Get the index of a series (column) given its name. The first column is the
- * x-axis, so the data series start with index 1.
- */
-Dygraph.prototype.indexFromSetName = function(name) {
- return this.setIndexByName_[name];
-};
-
-/**
- * Trigger a callback when the dygraph has drawn itself and is ready to be
- * manipulated. This is primarily useful when dygraphs has to do an XHR for the
- * data (i.e. a URL is passed as the data source) and the chart is drawn
- * asynchronously. If the chart has already drawn, the callback will fire
- * immediately.
- *
- * This is a good place to call setAnnotation().
- *
- * @param {function(!Dygraph)} callback The callback to trigger when the chart
- * is ready.
- */
-Dygraph.prototype.ready = function(callback) {
- if (this.is_initial_draw_) {
- this.readyFns_.push(callback);
- } else {
- callback.call(this, this);
- }
-};
-
-/**
- * @private
- * Adds a default style for the annotation CSS classes to the document. This is
- * only executed when annotations are actually used. It is designed to only be
- * called once -- all calls after the first will return immediately.
- */
-Dygraph.addAnnotationRule = function() {
- // TODO(danvk): move this function into plugins/annotations.js?
- if (Dygraph.addedAnnotationCSS) return;
-
- var rule = "border: 1px solid black; " +
- "background-color: white; " +
- "text-align: center;";
-
- var styleSheetElement = document.createElement("style");
- styleSheetElement.type = "text/css";
- document.getElementsByTagName("head")[0].appendChild(styleSheetElement);
-
- // Find the first style sheet that we can access.
- // We may not add a rule to a style sheet from another domain for security
- // reasons. This sometimes comes up when using gviz, since the Google gviz JS
- // adds its own style sheets from google.com.
- for (var i = 0; i < document.styleSheets.length; i++) {
- if (document.styleSheets[i].disabled) continue;
- var mysheet = document.styleSheets[i];
- try {
- if (mysheet.insertRule) { // Firefox
- var idx = mysheet.cssRules ? mysheet.cssRules.length : 0;
- mysheet.insertRule(".dygraphDefaultAnnotation { " + rule + " }", idx);
- } else if (mysheet.addRule) { // IE
- mysheet.addRule(".dygraphDefaultAnnotation", rule);
- }
- Dygraph.addedAnnotationCSS = true;
- return;
- } catch(err) {
- // Was likely a security exception.
- }
- }
-
- console.warn("Unable to add default annotation CSS rule; display may be off.");
-};
-
-return Dygraph;
-
-})();
-/**
- * @license
- * Copyright 2011 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview This file contains utility functions used by dygraphs. These
- * are typically static (i.e. not related to any particular dygraph). Examples
- * include date/time formatting functions, basic algorithms (e.g. binary
- * search) and generic DOM-manipulation functions.
- */
-
-(function() {
-
-/*global Dygraph:false, G_vmlCanvasManager:false, Node:false */
-"use strict";
-
-Dygraph.LOG_SCALE = 10;
-Dygraph.LN_TEN = Math.log(Dygraph.LOG_SCALE);
-
-/**
- * @private
- * @param {number} x
- * @return {number}
- */
-Dygraph.log10 = function(x) {
- return Math.log(x) / Dygraph.LN_TEN;
-};
-
-/** A dotted line stroke pattern. */
-Dygraph.DOTTED_LINE = [2, 2];
-/** A dashed line stroke pattern. */
-Dygraph.DASHED_LINE = [7, 3];
-/** A dot dash stroke pattern. */
-Dygraph.DOT_DASH_LINE = [7, 2, 2, 2];
-
-/**
- * Return the 2d context for a dygraph canvas.
- *
- * This method is only exposed for the sake of replacing the function in
- * automated tests, e.g.
- *
- * var oldFunc = Dygraph.getContext();
- * Dygraph.getContext = function(canvas) {
- * var realContext = oldFunc(canvas);
- * return new Proxy(realContext);
- * };
- * @param {!HTMLCanvasElement} canvas
- * @return {!CanvasRenderingContext2D}
- * @private
- */
-Dygraph.getContext = function(canvas) {
- return /** @type{!CanvasRenderingContext2D}*/(canvas.getContext("2d"));
-};
-
-/**
- * Add an event handler. This smooths a difference between IE and the rest of
- * the world.
- * @param {!Node} elem The element to add the event to.
- * @param {string} type The type of the event, e.g. 'click' or 'mousemove'.
- * @param {function(Event):(boolean|undefined)} fn The function to call
- * on the event. The function takes one parameter: the event object.
- * @private
- */
-Dygraph.addEvent = function addEvent(elem, type, fn) {
- if (elem.addEventListener) {
- elem.addEventListener(type, fn, false);
- } else {
- elem[type+fn] = function(){fn(window.event);};
- elem.attachEvent('on'+type, elem[type+fn]);
- }
-};
-
-/**
- * Add an event handler. This event handler is kept until the graph is
- * destroyed with a call to graph.destroy().
- *
- * @param {!Node} elem The element to add the event to.
- * @param {string} type The type of the event, e.g. 'click' or 'mousemove'.
- * @param {function(Event):(boolean|undefined)} fn The function to call
- * on the event. The function takes one parameter: the event object.
- * @private
- */
-Dygraph.prototype.addAndTrackEvent = function(elem, type, fn) {
- Dygraph.addEvent(elem, type, fn);
- this.registeredEvents_.push({ elem : elem, type : type, fn : fn });
-};
-
-/**
- * Remove an event handler. This smooths a difference between IE and the rest
- * of the world.
- * @param {!Node} elem The element to remove the event from.
- * @param {string} type The type of the event, e.g. 'click' or 'mousemove'.
- * @param {function(Event):(boolean|undefined)} fn The function to call
- * on the event. The function takes one parameter: the event object.
- * @private
- */
-Dygraph.removeEvent = function(elem, type, fn) {
- if (elem.removeEventListener) {
- elem.removeEventListener(type, fn, false);
- } else {
- try {
- elem.detachEvent('on'+type, elem[type+fn]);
- } catch(e) {
- // We only detach event listeners on a "best effort" basis in IE. See:
- // http://stackoverflow.com/questions/2553632/detachevent-not-working-with-named-inline-functions
- }
- elem[type+fn] = null;
- }
-};
-
-Dygraph.prototype.removeTrackedEvents_ = function() {
- if (this.registeredEvents_) {
- for (var idx = 0; idx < this.registeredEvents_.length; idx++) {
- var reg = this.registeredEvents_[idx];
- Dygraph.removeEvent(reg.elem, reg.type, reg.fn);
- }
- }
-
- this.registeredEvents_ = [];
-};
-
-/**
- * Cancels further processing of an event. This is useful to prevent default
- * browser actions, e.g. highlighting text on a double-click.
- * Based on the article at
- * http://www.switchonthecode.com/tutorials/javascript-tutorial-the-scroll-wheel
- * @param {!Event} e The event whose normal behavior should be canceled.
- * @private
- */
-Dygraph.cancelEvent = function(e) {
- e = e ? e : window.event;
- if (e.stopPropagation) {
- e.stopPropagation();
- }
- if (e.preventDefault) {
- e.preventDefault();
- }
- e.cancelBubble = true;
- e.cancel = true;
- e.returnValue = false;
- return false;
-};
-
-/**
- * Convert hsv values to an rgb(r,g,b) string. Taken from MochiKit.Color. This
- * is used to generate default series colors which are evenly spaced on the
- * color wheel.
- * @param { number } hue Range is 0.0-1.0.
- * @param { number } saturation Range is 0.0-1.0.
- * @param { number } value Range is 0.0-1.0.
- * @return { string } "rgb(r,g,b)" where r, g and b range from 0-255.
- * @private
- */
-Dygraph.hsvToRGB = function (hue, saturation, value) {
- var red;
- var green;
- var blue;
- if (saturation === 0) {
- red = value;
- green = value;
- blue = value;
- } else {
- var i = Math.floor(hue * 6);
- var f = (hue * 6) - i;
- var p = value * (1 - saturation);
- var q = value * (1 - (saturation * f));
- var t = value * (1 - (saturation * (1 - f)));
- switch (i) {
- case 1: red = q; green = value; blue = p; break;
- case 2: red = p; green = value; blue = t; break;
- case 3: red = p; green = q; blue = value; break;
- case 4: red = t; green = p; blue = value; break;
- case 5: red = value; green = p; blue = q; break;
- case 6: // fall through
- case 0: red = value; green = t; blue = p; break;
- }
- }
- red = Math.floor(255 * red + 0.5);
- green = Math.floor(255 * green + 0.5);
- blue = Math.floor(255 * blue + 0.5);
- return 'rgb(' + red + ',' + green + ',' + blue + ')';
-};
-
-// The following functions are from quirksmode.org with a modification for Safari from
-// http://blog.firetree.net/2005/07/04/javascript-find-position/
-// http://www.quirksmode.org/js/findpos.html
-// ... and modifications to support scrolling divs.
-
-/**
- * Find the coordinates of an object relative to the top left of the page.
- *
- * TODO(danvk): change obj type from Node -&gt; !Node
- * @param {Node} obj
- * @return {{x:number,y:number}}
- * @private
- */
-Dygraph.findPos = function(obj) {
- var curleft = 0, curtop = 0;
- if (obj.offsetParent) {
- var copyObj = obj;
- while (1) {
- // NOTE: the if statement here is for IE8.
- var borderLeft = "0", borderTop = "0";
- if (window.getComputedStyle) {
- var computedStyle = window.getComputedStyle(copyObj, null);
- borderLeft = computedStyle.borderLeft || "0";
- borderTop = computedStyle.borderTop || "0";
- }
- curleft += parseInt(borderLeft, 10) ;
- curtop += parseInt(borderTop, 10) ;
- curleft += copyObj.offsetLeft;
- curtop += copyObj.offsetTop;
- if (!copyObj.offsetParent) {
- break;
- }
- copyObj = copyObj.offsetParent;
- }
- } else {
- // TODO(danvk): why would obj ever have these properties?
- if (obj.x) curleft += obj.x;
- if (obj.y) curtop += obj.y;
- }
-
- // This handles the case where the object is inside a scrolled div.
- while (obj && obj != document.body) {
- curleft -= obj.scrollLeft;
- curtop -= obj.scrollTop;
- obj = obj.parentNode;
- }
- return {x: curleft, y: curtop};
-};
-
-/**
- * Returns the x-coordinate of the event in a coordinate system where the
- * top-left corner of the page (not the window) is (0,0).
- * Taken from MochiKit.Signal
- * @param {!Event} e
- * @return {number}
- * @private
- */
-Dygraph.pageX = function(e) {
- if (e.pageX) {
- return (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
- } else {
- var de = document.documentElement;
- var b = document.body;
- return e.clientX +
- (de.scrollLeft || b.scrollLeft) -
- (de.clientLeft || 0);
- }
-};
-
-/**
- * Returns the y-coordinate of the event in a coordinate system where the
- * top-left corner of the page (not the window) is (0,0).
- * Taken from MochiKit.Signal
- * @param {!Event} e
- * @return {number}
- * @private
- */
-Dygraph.pageY = function(e) {
- if (e.pageY) {
- return (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
- } else {
- var de = document.documentElement;
- var b = document.body;
- return e.clientY +
- (de.scrollTop || b.scrollTop) -
- (de.clientTop || 0);
- }
-};
-
-/**
- * Converts page the x-coordinate of the event to pixel x-coordinates on the
- * canvas (i.e. DOM Coords).
- * @param {!Event} e Drag event.
- * @param {!DygraphInteractionContext} context Interaction context object.
- * @return {number} The amount by which the drag has moved to the right.
- */
-Dygraph.dragGetX_ = function(e, context) {
- return Dygraph.pageX(e) - context.px;
-};
-
-/**
- * Converts page the y-coordinate of the event to pixel y-coordinates on the
- * canvas (i.e. DOM Coords).
- * @param {!Event} e Drag event.
- * @param {!DygraphInteractionContext} context Interaction context object.
- * @return {number} The amount by which the drag has moved down.
- */
-Dygraph.dragGetY_ = function(e, context) {
- return Dygraph.pageY(e) - context.py;
-};
-
-/**
- * This returns true unless the parameter is 0, null, undefined or NaN.
- * TODO(danvk): rename this function to something like 'isNonZeroNan'.
- *
- * @param {number} x The number to consider.
- * @return {boolean} Whether the number is zero or NaN.
- * @private
- */
-Dygraph.isOK = function(x) {
- return !!x && !isNaN(x);
-};
-
-/**
- * @param {{x:?number,y:?number,yval:?number}} p The point to consider, valid
- * points are {x, y} objects
- * @param {boolean=} opt_allowNaNY Treat point with y=NaN as valid
- * @return {boolean} Whether the point has numeric x and y.
- * @private
- */
-Dygraph.isValidPoint = function(p, opt_allowNaNY) {
- if (!p) return false; // null or undefined object
- if (p.yval === null) return false; // missing point
- if (p.x === null || p.x === undefined) return false;
- if (p.y === null || p.y === undefined) return false;
- if (isNaN(p.x) || (!opt_allowNaNY && isNaN(p.y))) return false;
- return true;
-};
-
-/**
- * Number formatting function which mimicks the behavior of %g in printf, i.e.
- * either exponential or fixed format (without trailing 0s) is used depending on
- * the length of the generated string. The advantage of this format is that
- * there is a predictable upper bound on the resulting string length,
- * significant figures are not dropped, and normal numbers are not displayed in
- * exponential notation.
- *
- * NOTE: JavaScript's native toPrecision() is NOT a drop-in replacement for %g.
- * It creates strings which are too long for absolute values between 10^-4 and
- * 10^-6, e.g. '0.00001' instead of '1e-5'. See tests/number-format.html for
- * output examples.
- *
- * @param {number} x The number to format
- * @param {number=} opt_precision The precision to use, default 2.
- * @return {string} A string formatted like %g in printf. The max generated
- * string length should be precision + 6 (e.g 1.123e+300).
- */
-Dygraph.floatFormat = function(x, opt_precision) {
- // Avoid invalid precision values; [1, 21] is the valid range.
- var p = Math.min(Math.max(1, opt_precision || 2), 21);
-
- // This is deceptively simple. The actual algorithm comes from:
- //
- // Max allowed length = p + 4
- // where 4 comes from 'e+n' and '.'.
- //
- // Length of fixed format = 2 + y + p
- // where 2 comes from '0.' and y = # of leading zeroes.
- //
- // Equating the two and solving for y yields y = 2, or 0.00xxxx which is
- // 1.0e-3.
- //
- // Since the behavior of toPrecision() is identical for larger numbers, we
- // don't have to worry about the other bound.
- //
- // Finally, the argument for toExponential() is the number of trailing digits,
- // so we take off 1 for the value before the '.'.
- return (Math.abs(x) < 1.0e-3 && x !== 0.0) ?
- x.toExponential(p - 1) : x.toPrecision(p);
-};
-
-/**
- * Converts '9' to '09' (useful for dates)
- * @param {number} x
- * @return {string}
- * @private
- */
-Dygraph.zeropad = function(x) {
- if (x < 10) return "0" + x; else return "" + x;
-};
-
-/**
- * Date accessors to get the parts of a calendar date (year, month,
- * day, hour, minute, second and millisecond) according to local time,
- * and factory method to call the Date constructor with an array of arguments.
- */
-Dygraph.DateAccessorsLocal = {
- getFullYear: function(d) {return d.getFullYear();},
- getMonth: function(d) {return d.getMonth();},
- getDate: function(d) {return d.getDate();},
- getHours: function(d) {return d.getHours();},
- getMinutes: function(d) {return d.getMinutes();},
- getSeconds: function(d) {return d.getSeconds();},
- getMilliseconds: function(d) {return d.getMilliseconds();},
- getDay: function(d) {return d.getDay();},
- makeDate: function(y, m, d, hh, mm, ss, ms) {
- return new Date(y, m, d, hh, mm, ss, ms);
- }
-};
-
-/**
- * Date accessors to get the parts of a calendar date (year, month,
- * day of month, hour, minute, second and millisecond) according to UTC time,
- * and factory method to call the Date constructor with an array of arguments.
- */
-Dygraph.DateAccessorsUTC = {
- getFullYear: function(d) {return d.getUTCFullYear();},
- getMonth: function(d) {return d.getUTCMonth();},
- getDate: function(d) {return d.getUTCDate();},
- getHours: function(d) {return d.getUTCHours();},
- getMinutes: function(d) {return d.getUTCMinutes();},
- getSeconds: function(d) {return d.getUTCSeconds();},
- getMilliseconds: function(d) {return d.getUTCMilliseconds();},
- getDay: function(d) {return d.getUTCDay();},
- makeDate: function(y, m, d, hh, mm, ss, ms) {
- return new Date(Date.UTC(y, m, d, hh, mm, ss, ms));
- }
-};
-
-/**
- * Return a string version of the hours, minutes and seconds portion of a date.
- * @param {number} hh The hours (from 0-23)
- * @param {number} mm The minutes (from 0-59)
- * @param {number} ss The seconds (from 0-59)
- * @return {string} A time of the form "HH:MM" or "HH:MM:SS"
- * @private
- */
-Dygraph.hmsString_ = function(hh, mm, ss) {
- var zeropad = Dygraph.zeropad;
- var ret = zeropad(hh) + ":" + zeropad(mm);
- if (ss) {
- ret += ":" + zeropad(ss);
- }
- return ret;
-};
-
-/**
- * Convert a JS date (millis since epoch) to a formatted string.
- * @param {number} time The JavaScript time value (ms since epoch)
- * @param {boolean} utc Wether output UTC or local time
- * @return {string} A date of one of these forms:
- * "YYYY/MM/DD", "YYYY/MM/DD HH:MM" or "YYYY/MM/DD HH:MM:SS"
- * @private
- */
-Dygraph.dateString_ = function(time, utc) {
- var zeropad = Dygraph.zeropad;
- var accessors = utc ? Dygraph.DateAccessorsUTC : Dygraph.DateAccessorsLocal;
- var date = new Date(time);
- var y = accessors.getFullYear(date);
- var m = accessors.getMonth(date);
- var d = accessors.getDate(date);
- var hh = accessors.getHours(date);
- var mm = accessors.getMinutes(date);
- var ss = accessors.getSeconds(date);
- // Get a year string:
- var year = "" + y;
- // Get a 0 padded month string
- var month = zeropad(m + 1); //months are 0-offset, sigh
- // Get a 0 padded day string
- var day = zeropad(d);
- var frac = hh * 3600 + mm * 60 + ss;
- var ret = year + "/" + month + "/" + day;
- if (frac) {
- ret += " " + Dygraph.hmsString_(hh, mm, ss);
- }
- return ret;
-};
-
-/**
- * Round a number to the specified number of digits past the decimal point.
- * @param {number} num The number to round
- * @param {number} places The number of decimals to which to round
- * @return {number} The rounded number
- * @private
- */
-Dygraph.round_ = function(num, places) {
- var shift = Math.pow(10, places);
- return Math.round(num * shift)/shift;
-};
-
-/**
- * Implementation of binary search over an array.
- * Currently does not work when val is outside the range of arry's values.
- * @param {number} val the value to search for
- * @param {Array.<number>} arry is the value over which to search
- * @param {number} abs If abs > 0, find the lowest entry greater than val
- * If abs < 0, find the highest entry less than val.
- * If abs == 0, find the entry that equals val.
- * @param {number=} low The first index in arry to consider (optional)
- * @param {number=} high The last index in arry to consider (optional)
- * @return {number} Index of the element, or -1 if it isn't found.
- * @private
- */
-Dygraph.binarySearch = function(val, arry, abs, low, high) {
- if (low === null || low === undefined ||
- high === null || high === undefined) {
- low = 0;
- high = arry.length - 1;
- }
- if (low > high) {
- return -1;
- }
- if (abs === null || abs === undefined) {
- abs = 0;
- }
- var validIndex = function(idx) {
- return idx >= 0 && idx < arry.length;
- };
- var mid = parseInt((low + high) / 2, 10);
- var element = arry[mid];
- var idx;
- if (element == val) {
- return mid;
- } else if (element > val) {
- if (abs > 0) {
- // Accept if element > val, but also if prior element < val.
- idx = mid - 1;
- if (validIndex(idx) && arry[idx] < val) {
- return mid;
- }
- }
- return Dygraph.binarySearch(val, arry, abs, low, mid - 1);
- } else if (element < val) {
- if (abs < 0) {
- // Accept if element < val, but also if prior element > val.
- idx = mid + 1;
- if (validIndex(idx) && arry[idx] > val) {
- return mid;
- }
- }
- return Dygraph.binarySearch(val, arry, abs, mid + 1, high);
- }
- return -1; // can't actually happen, but makes closure compiler happy
-};
-
-/**
- * Parses a date, returning the number of milliseconds since epoch. This can be
- * passed in as an xValueParser in the Dygraph constructor.
- * TODO(danvk): enumerate formats that this understands.
- *
- * @param {string} dateStr A date in a variety of possible string formats.
- * @return {number} Milliseconds since epoch.
- * @private
- */
-Dygraph.dateParser = function(dateStr) {
- var dateStrSlashed;
- var d;
-
- // Let the system try the format first, with one caveat:
- // YYYY-MM-DD[ HH:MM:SS] is interpreted as UTC by a variety of browsers.
- // dygraphs displays dates in local time, so this will result in surprising
- // inconsistencies. But if you specify "T" or "Z" (i.e. YYYY-MM-DDTHH:MM:SS),
- // then you probably know what you're doing, so we'll let you go ahead.
- // Issue: http://code.google.com/p/dygraphs/issues/detail?id=255
- if (dateStr.search("-") == -1 ||
- dateStr.search("T") != -1 || dateStr.search("Z") != -1) {
- d = Dygraph.dateStrToMillis(dateStr);
- if (d && !isNaN(d)) return d;
- }
-
- if (dateStr.search("-") != -1) { // e.g. '2009-7-12' or '2009-07-12'
- dateStrSlashed = dateStr.replace("-", "/", "g");
- while (dateStrSlashed.search("-") != -1) {
- dateStrSlashed = dateStrSlashed.replace("-", "/");
- }
- d = Dygraph.dateStrToMillis(dateStrSlashed);
- } else if (dateStr.length == 8) { // e.g. '20090712'
- // TODO(danvk): remove support for this format. It's confusing.
- dateStrSlashed = dateStr.substr(0,4) + "/" + dateStr.substr(4,2) + "/" +
- dateStr.substr(6,2);
- d = Dygraph.dateStrToMillis(dateStrSlashed);
- } else {
- // Any format that Date.parse will accept, e.g. "2009/07/12" or
- // "2009/07/12 12:34:56"
- d = Dygraph.dateStrToMillis(dateStr);
- }
-
- if (!d || isNaN(d)) {
- console.error("Couldn't parse " + dateStr + " as a date");
- }
- return d;
-};
-
-/**
- * This is identical to JavaScript's built-in Date.parse() method, except that
- * it doesn't get replaced with an incompatible method by aggressive JS
- * libraries like MooTools or Joomla.
- * @param {string} str The date string, e.g. "2011/05/06"
- * @return {number} millis since epoch
- * @private
- */
-Dygraph.dateStrToMillis = function(str) {
- return new Date(str).getTime();
-};
-
-// These functions are all based on MochiKit.
-/**
- * Copies all the properties from o to self.
- *
- * @param {!Object} self
- * @param {!Object} o
- * @return {!Object}
- */
-Dygraph.update = function(self, o) {
- if (typeof(o) != 'undefined' && o !== null) {
- for (var k in o) {
- if (o.hasOwnProperty(k)) {
- self[k] = o[k];
- }
- }
- }
- return self;
-};
-
-/**
- * Copies all the properties from o to self.
- *
- * @param {!Object} self
- * @param {!Object} o
- * @return {!Object}
- * @private
- */
-Dygraph.updateDeep = function (self, o) {
- // Taken from http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
- function isNode(o) {
- return (
- typeof Node === "object" ? o instanceof Node :
- typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
- );
- }
-
- if (typeof(o) != 'undefined' && o !== null) {
- for (var k in o) {
- if (o.hasOwnProperty(k)) {
- if (o[k] === null) {
- self[k] = null;
- } else if (Dygraph.isArrayLike(o[k])) {
- self[k] = o[k].slice();
- } else if (isNode(o[k])) {
- // DOM objects are shallowly-copied.
- self[k] = o[k];
- } else if (typeof(o[k]) == 'object') {
- if (typeof(self[k]) != 'object' || self[k] === null) {
- self[k] = {};
- }
- Dygraph.updateDeep(self[k], o[k]);
- } else {
- self[k] = o[k];
- }
- }
- }
- }
- return self;
-};
-
-/**
- * @param {*} o
- * @return {boolean}
- * @private
- */
-Dygraph.isArrayLike = function(o) {
- var typ = typeof(o);
- if (
- (typ != 'object' && !(typ == 'function' &&
- typeof(o.item) == 'function')) ||
- o === null ||
- typeof(o.length) != 'number' ||
- o.nodeType === 3
- ) {
- return false;
- }
- return true;
-};
-
-/**
- * @param {Object} o
- * @return {boolean}
- * @private
- */
-Dygraph.isDateLike = function (o) {
- if (typeof(o) != "object" || o === null ||
- typeof(o.getTime) != 'function') {
- return false;
- }
- return true;
-};
-
-/**
- * Note: this only seems to work for arrays.
- * @param {!Array} o
- * @return {!Array}
- * @private
- */
-Dygraph.clone = function(o) {
- // TODO(danvk): figure out how MochiKit's version works
- var r = [];
- for (var i = 0; i < o.length; i++) {
- if (Dygraph.isArrayLike(o[i])) {
- r.push(Dygraph.clone(o[i]));
- } else {
- r.push(o[i]);
- }
- }
- return r;
-};
-
-/**
- * Create a new canvas element. This is more complex than a simple
- * document.createElement("canvas") because of IE and excanvas.
- *
- * @return {!HTMLCanvasElement}
- * @private
- */
-Dygraph.createCanvas = function() {
- var canvas = document.createElement("canvas");
-
- var isIE = (/MSIE/.test(navigator.userAgent) && !window.opera);
- if (isIE && (typeof(G_vmlCanvasManager) != 'undefined')) {
- canvas = G_vmlCanvasManager.initElement(
- /**@type{!HTMLCanvasElement}*/(canvas));
- }
-
- return canvas;
-};
-
-/**
- * Returns the context's pixel ratio, which is the ratio between the device
- * pixel ratio and the backing store ratio. Typically this is 1 for conventional
- * displays, and > 1 for HiDPI displays (such as the Retina MBP).
- * See http://www.html5rocks.com/en/tutorials/canvas/hidpi/ for more details.
- *
- * @param {!CanvasRenderingContext2D} context The canvas's 2d context.
- * @return {number} The ratio of the device pixel ratio and the backing store
- * ratio for the specified context.
- */
-Dygraph.getContextPixelRatio = function(context) {
- try {
- var devicePixelRatio = window.devicePixelRatio;
- var backingStoreRatio = context.webkitBackingStorePixelRatio ||
- context.mozBackingStorePixelRatio ||
- context.msBackingStorePixelRatio ||
- context.oBackingStorePixelRatio ||
- context.backingStorePixelRatio || 1;
- if (devicePixelRatio !== undefined) {
- return devicePixelRatio / backingStoreRatio;
- } else {
- // At least devicePixelRatio must be defined for this ratio to make sense.
- // We default backingStoreRatio to 1: this does not exist on some browsers
- // (i.e. desktop Chrome).
- return 1;
- }
- } catch (e) {
- return 1;
- }
-};
-
-/**
- * Checks whether the user is on an Android browser.
- * Android does not fully support the <canvas> tag, e.g. w/r/t/ clipping.
- * @return {boolean}
- * @private
- */
-Dygraph.isAndroid = function() {
- return (/Android/).test(navigator.userAgent);
-};
-
-
-/**
- * TODO(danvk): use @template here when it's better supported for classes.
- * @param {!Array} array
- * @param {number} start
- * @param {number} length
- * @param {function(!Array,?):boolean=} predicate
- * @constructor
- */
-Dygraph.Iterator = function(array, start, length, predicate) {
- start = start || 0;
- length = length || array.length;
- this.hasNext = true; // Use to identify if there's another element.
- this.peek = null; // Use for look-ahead
- this.start_ = start;
- this.array_ = array;
- this.predicate_ = predicate;
- this.end_ = Math.min(array.length, start + length);
- this.nextIdx_ = start - 1; // use -1 so initial advance works.
- this.next(); // ignoring result.
-};
-
-/**
- * @return {Object}
- */
-Dygraph.Iterator.prototype.next = function() {
- if (!this.hasNext) {
- return null;
- }
- var obj = this.peek;
-
- var nextIdx = this.nextIdx_ + 1;
- var found = false;
- while (nextIdx < this.end_) {
- if (!this.predicate_ || this.predicate_(this.array_, nextIdx)) {
- this.peek = this.array_[nextIdx];
- found = true;
- break;
- }
- nextIdx++;
- }
- this.nextIdx_ = nextIdx;
- if (!found) {
- this.hasNext = false;
- this.peek = null;
- }
- return obj;
-};
-
-/**
- * Returns a new iterator over array, between indexes start and
- * start + length, and only returns entries that pass the accept function
- *
- * @param {!Array} array the array to iterate over.
- * @param {number} start the first index to iterate over, 0 if absent.
- * @param {number} length the number of elements in the array to iterate over.
- * This, along with start, defines a slice of the array, and so length
- * doesn't imply the number of elements in the iterator when accept doesn't
- * always accept all values. array.length when absent.
- * @param {function(?):boolean=} opt_predicate a function that takes
- * parameters array and idx, which returns true when the element should be
- * returned. If omitted, all elements are accepted.
- * @private
- */
-Dygraph.createIterator = function(array, start, length, opt_predicate) {
- return new Dygraph.Iterator(array, start, length, opt_predicate);
-};
-
-// Shim layer with setTimeout fallback.
-// From: http://paulirish.com/2011/requestanimationframe-for-smart-animating/
-// Should be called with the window context:
-// Dygraph.requestAnimFrame.call(window, function() {})
-Dygraph.requestAnimFrame = (function() {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function (callback) {
- window.setTimeout(callback, 1000 / 60);
- };
-})();
-
-/**
- * Call a function at most maxFrames times at an attempted interval of
- * framePeriodInMillis, then call a cleanup function once. repeatFn is called
- * once immediately, then at most (maxFrames - 1) times asynchronously. If
- * maxFrames==1, then cleanup_fn() is also called synchronously. This function
- * is used to sequence animation.
- * @param {function(number)} repeatFn Called repeatedly -- takes the frame
- * number (from 0 to maxFrames-1) as an argument.
- * @param {number} maxFrames The max number of times to call repeatFn
- * @param {number} framePeriodInMillis Max requested time between frames.
- * @param {function()} cleanupFn A function to call after all repeatFn calls.
- * @private
- */
-Dygraph.repeatAndCleanup = function(repeatFn, maxFrames, framePeriodInMillis,
- cleanupFn) {
- var frameNumber = 0;
- var previousFrameNumber;
- var startTime = new Date().getTime();
- repeatFn(frameNumber);
- if (maxFrames == 1) {
- cleanupFn();
- return;
- }
- var maxFrameArg = maxFrames - 1;
-
- (function loop() {
- if (frameNumber >= maxFrames) return;
- Dygraph.requestAnimFrame.call(window, function() {
- // Determine which frame to draw based on the delay so far. Will skip
- // frames if necessary.
- var currentTime = new Date().getTime();
- var delayInMillis = currentTime - startTime;
- previousFrameNumber = frameNumber;
- frameNumber = Math.floor(delayInMillis / framePeriodInMillis);
- var frameDelta = frameNumber - previousFrameNumber;
- // If we predict that the subsequent repeatFn call will overshoot our
- // total frame target, so our last call will cause a stutter, then jump to
- // the last call immediately. If we're going to cause a stutter, better
- // to do it faster than slower.
- var predictOvershootStutter = (frameNumber + frameDelta) > maxFrameArg;
- if (predictOvershootStutter || (frameNumber >= maxFrameArg)) {
- repeatFn(maxFrameArg); // Ensure final call with maxFrameArg.
- cleanupFn();
- } else {
- if (frameDelta !== 0) { // Don't call repeatFn with duplicate frames.
- repeatFn(frameNumber);
- }
- loop();
- }
- });
- })();
-};
-
-// A whitelist of options that do not change pixel positions.
-var pixelSafeOptions = {
- 'annotationClickHandler': true,
- 'annotationDblClickHandler': true,
- 'annotationMouseOutHandler': true,
- 'annotationMouseOverHandler': true,
- 'axisLabelColor': true,
- 'axisLineColor': true,
- 'axisLineWidth': true,
- 'clickCallback': true,
- 'drawCallback': true,
- 'drawHighlightPointCallback': true,
- 'drawPoints': true,
- 'drawPointCallback': true,
- 'drawXGrid': true,
- 'drawYGrid': true,
- 'fillAlpha': true,
- 'gridLineColor': true,
- 'gridLineWidth': true,
- 'hideOverlayOnMouseOut': true,
- 'highlightCallback': true,
- 'highlightCircleSize': true,
- 'interactionModel': true,
- 'isZoomedIgnoreProgrammaticZoom': true,
- 'labelsDiv': true,
- 'labelsDivStyles': true,
- 'labelsDivWidth': true,
- 'labelsKMB': true,
- 'labelsKMG2': true,
- 'labelsSeparateLines': true,
- 'labelsShowZeroValues': true,
- 'legend': true,
- 'panEdgeFraction': true,
- 'pixelsPerYLabel': true,
- 'pointClickCallback': true,
- 'pointSize': true,
- 'rangeSelectorPlotFillColor': true,
- 'rangeSelectorPlotStrokeColor': true,
- 'showLabelsOnHighlight': true,
- 'showRoller': true,
- 'strokeWidth': true,
- 'underlayCallback': true,
- 'unhighlightCallback': true,
- 'zoomCallback': true
-};
-
-/**
- * This function will scan the option list and determine if they
- * require us to recalculate the pixel positions of each point.
- * TODO: move this into dygraph-options.js
- * @param {!Array.<string>} labels a list of options to check.
- * @param {!Object} attrs
- * @return {boolean} true if the graph needs new points else false.
- * @private
- */
-Dygraph.isPixelChangingOptionList = function(labels, attrs) {
- // Assume that we do not require new points.
- // This will change to true if we actually do need new points.
-
- // Create a dictionary of series names for faster lookup.
- // If there are no labels, then the dictionary stays empty.
- var seriesNamesDictionary = { };
- if (labels) {
- for (var i = 1; i < labels.length; i++) {
- seriesNamesDictionary[labels[i]] = true;
- }
- }
-
- // Scan through a flat (i.e. non-nested) object of options.
- // Returns true/false depending on whether new points are needed.
- var scanFlatOptions = function(options) {
- for (var property in options) {
- if (options.hasOwnProperty(property) &&
- !pixelSafeOptions[property]) {
- return true;
- }
- }
- return false;
- };
-
- // Iterate through the list of updated options.
- for (var property in attrs) {
- if (!attrs.hasOwnProperty(property)) continue;
-
- // Find out of this field is actually a series specific options list.
- if (property == 'highlightSeriesOpts' ||
- (seriesNamesDictionary[property] && !attrs.series)) {
- // This property value is a list of options for this series.
- if (scanFlatOptions(attrs[property])) return true;
- } else if (property == 'series' || property == 'axes') {
- // This is twice-nested options list.
- var perSeries = attrs[property];
- for (var series in perSeries) {
- if (perSeries.hasOwnProperty(series) &&
- scanFlatOptions(perSeries[series])) {
- return true;
- }
- }
- } else {
- // If this was not a series specific option list, check if it's a pixel
- // changing property.
- if (!pixelSafeOptions[property]) return true;
- }
- }
-
- return false;
-};
-
-Dygraph.Circles = {
- DEFAULT : function(g, name, ctx, canvasx, canvasy, color, radius) {
- ctx.beginPath();
- ctx.fillStyle = color;
- ctx.arc(canvasx, canvasy, radius, 0, 2 * Math.PI, false);
- ctx.fill();
- }
- // For more shapes, include extras/shapes.js
-};
-
-/**
- * To create a "drag" interaction, you typically register a mousedown event
- * handler on the element where the drag begins. In that handler, you register a
- * mouseup handler on the window to determine when the mouse is released,
- * wherever that release happens. This works well, except when the user releases
- * the mouse over an off-domain iframe. In that case, the mouseup event is
- * handled by the iframe and never bubbles up to the window handler.
- *
- * To deal with this issue, we cover iframes with high z-index divs to make sure
- * they don't capture mouseup.
- *
- * Usage:
- * element.addEventListener('mousedown', function() {
- * var tarper = new Dygraph.IFrameTarp();
- * tarper.cover();
- * var mouseUpHandler = function() {
- * ...
- * window.removeEventListener(mouseUpHandler);
- * tarper.uncover();
- * };
- * window.addEventListener('mouseup', mouseUpHandler);
- * };
- *
- * @constructor
- */
-Dygraph.IFrameTarp = function() {
- /** @type {Array.<!HTMLDivElement>} */
- this.tarps = [];
-};
-
-/**
- * Find all the iframes in the document and cover them with high z-index
- * transparent divs.
- */
-Dygraph.IFrameTarp.prototype.cover = function() {
- var iframes = document.getElementsByTagName("iframe");
- for (var i = 0; i < iframes.length; i++) {
- var iframe = iframes[i];
- var pos = Dygraph.findPos(iframe),
- x = pos.x,
- y = pos.y,
- width = iframe.offsetWidth,
- height = iframe.offsetHeight;
-
- var div = document.createElement("div");
- div.style.position = "absolute";
- div.style.left = x + 'px';
- div.style.top = y + 'px';
- div.style.width = width + 'px';
- div.style.height = height + 'px';
- div.style.zIndex = 999;
- document.body.appendChild(div);
- this.tarps.push(div);
- }
-};
-
-/**
- * Remove all the iframe covers. You should call this in a mouseup handler.
- */
-Dygraph.IFrameTarp.prototype.uncover = function() {
- for (var i = 0; i < this.tarps.length; i++) {
- this.tarps[i].parentNode.removeChild(this.tarps[i]);
- }
- this.tarps = [];
-};
-
-/**
- * Determine whether |data| is delimited by CR, CRLF, LF, LFCR.
- * @param {string} data
- * @return {?string} the delimiter that was detected (or null on failure).
- */
-Dygraph.detectLineDelimiter = function(data) {
- for (var i = 0; i < data.length; i++) {
- var code = data.charAt(i);
- if (code === '\r') {
- // Might actually be "\r\n".
- if (((i + 1) < data.length) && (data.charAt(i + 1) === '\n')) {
- return '\r\n';
- }
- return code;
- }
- if (code === '\n') {
- // Might actually be "\n\r".
- if (((i + 1) < data.length) && (data.charAt(i + 1) === '\r')) {
- return '\n\r';
- }
- return code;
- }
- }
-
- return null;
-};
-
-/**
- * Is one node contained by another?
- * @param {Node} containee The contained node.
- * @param {Node} container The container node.
- * @return {boolean} Whether containee is inside (or equal to) container.
- * @private
- */
-Dygraph.isNodeContainedBy = function(containee, container) {
- if (container === null || containee === null) {
- return false;
- }
- var containeeNode = /** @type {Node} */ (containee);
- while (containeeNode && containeeNode !== container) {
- containeeNode = containeeNode.parentNode;
- }
- return (containeeNode === container);
-};
-
-
-// This masks some numeric issues in older versions of Firefox,
-// where 1.0/Math.pow(10,2) != Math.pow(10,-2).
-/** @type {function(number,number):number} */
-Dygraph.pow = function(base, exp) {
- if (exp < 0) {
- return 1.0 / Math.pow(base, -exp);
- }
- return Math.pow(base, exp);
-};
-
-/**
- * Converts any valid CSS color (hex, rgb(), named color) to an RGB tuple.
- *
- * @param {!string} colorStr Any valid CSS color string.
- * @return {{r:number,g:number,b:number}} Parsed RGB tuple.
- * @private
- */
-Dygraph.toRGB_ = function(colorStr) {
- // TODO(danvk): cache color parses to avoid repeated DOM manipulation.
- var div = document.createElement('div');
- div.style.backgroundColor = colorStr;
- div.style.visibility = 'hidden';
- document.body.appendChild(div);
- var rgbStr;
- if (window.getComputedStyle) {
- rgbStr = window.getComputedStyle(div, null).backgroundColor;
- } else {
- // IE8
- rgbStr = div.currentStyle.backgroundColor;
- }
- document.body.removeChild(div);
- var bits = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(rgbStr);
- return {
- r: parseInt(bits[1], 10),
- g: parseInt(bits[2], 10),
- b: parseInt(bits[3], 10)
- };
-};
-
-/**
- * Checks whether the browser supports the &lt;canvas&gt; tag.
- * @param {HTMLCanvasElement=} opt_canvasElement Pass a canvas element as an
- * optimization if you have one.
- * @return {boolean} Whether the browser supports canvas.
- */
-Dygraph.isCanvasSupported = function(opt_canvasElement) {
- var canvas;
- try {
- canvas = opt_canvasElement || document.createElement("canvas");
- canvas.getContext("2d");
- }
- catch (e) {
- var ie = navigator.appVersion.match(/MSIE (\d\.\d)/);
- var opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
- if ((!ie) || (ie[1] < 6) || (opera))
- return false;
- return true;
- }
- return true;
-};
-
-/**
- * Parses the value as a floating point number. This is like the parseFloat()
- * built-in, but with a few differences:
- * - the empty string is parsed as null, rather than NaN.
- * - if the string cannot be parsed at all, an error is logged.
- * If the string can't be parsed, this method returns null.
- * @param {string} x The string to be parsed
- * @param {number=} opt_line_no The line number from which the string comes.
- * @param {string=} opt_line The text of the line from which the string comes.
- */
-Dygraph.parseFloat_ = function(x, opt_line_no, opt_line) {
- var val = parseFloat(x);
- if (!isNaN(val)) return val;
-
- // Try to figure out what happeend.
- // If the value is the empty string, parse it as null.
- if (/^ *$/.test(x)) return null;
-
- // If it was actually "NaN", return it as NaN.
- if (/^ *nan *$/i.test(x)) return NaN;
-
- // Looks like a parsing error.
- var msg = "Unable to parse '" + x + "' as a number";
- if (opt_line !== undefined && opt_line_no !== undefined) {
- msg += " on line " + (1+(opt_line_no||0)) + " ('" + opt_line + "') of CSV.";
- }
- console.error(msg);
-
- return null;
-};
-
-})();
-/**
- * @license
- * Copyright 2011 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview A wrapper around the Dygraph class which implements the
- * interface for a GViz (aka Google Visualization API) visualization.
- * It is designed to be a drop-in replacement for Google's AnnotatedTimeline,
- * so the documentation at
- * http://code.google.com/apis/chart/interactive/docs/gallery/annotatedtimeline.html
- * translates over directly.
- *
- * For a full demo, see:
- * - http://dygraphs.com/tests/gviz.html
- * - http://dygraphs.com/tests/annotation-gviz.html
- */
-
-(function() {
-/*global Dygraph:false */
-"use strict";
-
-/**
- * A wrapper around Dygraph that implements the gviz API.
- * @param {!HTMLDivElement} container The DOM object the visualization should
- * live in.
- * @constructor
- */
-Dygraph.GVizChart = function(container) {
- this.container = container;
-};
-
-/**
- * @param {GVizDataTable} data
- * @param {Object.<*>} options
- */
-Dygraph.GVizChart.prototype.draw = function(data, options) {
- // Clear out any existing dygraph.
- // TODO(danvk): would it make more sense to simply redraw using the current
- // date_graph object?
- this.container.innerHTML = '';
- if (typeof(this.date_graph) != 'undefined') {
- this.date_graph.destroy();
- }
-
- this.date_graph = new Dygraph(this.container, data, options);
-};
-
-/**
- * Google charts compatible setSelection
- * Only row selection is supported, all points in the row will be highlighted
- * @param {Array.<{row:number}>} selection_array array of the selected cells
- * @public
- */
-Dygraph.GVizChart.prototype.setSelection = function(selection_array) {
- var row = false;
- if (selection_array.length) {
- row = selection_array[0].row;
- }
- this.date_graph.setSelection(row);
-};
-
-/**
- * Google charts compatible getSelection implementation
- * @return {Array.<{row:number,column:number}>} array of the selected cells
- * @public
- */
-Dygraph.GVizChart.prototype.getSelection = function() {
- var selection = [];
-
- var row = this.date_graph.getSelection();
-
- if (row < 0) return selection;
-
- var points = this.date_graph.layout_.points;
- for (var setIdx = 0; setIdx < points.length; ++setIdx) {
- selection.push({row: row, column: setIdx + 1});
- }
-
- return selection;
-};
-
-})();
-/**
- * @license
- * Copyright 2011 Robert Konigsberg (konigsberg@google.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview The default interaction model for Dygraphs. This is kept out
- * of dygraph.js for better navigability.
- * @author Robert Konigsberg (konigsberg@google.com)
- */
-
-(function() {
-/*global Dygraph:false */
-"use strict";
-
-/**
- * You can drag this many pixels past the edge of the chart and still have it
- * be considered a zoom. This makes it easier to zoom to the exact edge of the
- * chart, a fairly common operation.
- */
-var DRAG_EDGE_MARGIN = 100;
-
-/**
- * A collection of functions to facilitate build custom interaction models.
- * @class
- */
-Dygraph.Interaction = {};
-
-/**
- * Checks whether the beginning & ending of an event were close enough that it
- * should be considered a click. If it should, dispatch appropriate events.
- * Returns true if the event was treated as a click.
- *
- * @param {Event} event
- * @param {Dygraph} g
- * @param {Object} context
- */
-Dygraph.Interaction.maybeTreatMouseOpAsClick = function(event, g, context) {
- context.dragEndX = Dygraph.dragGetX_(event, context);
- context.dragEndY = Dygraph.dragGetY_(event, context);
- var regionWidth = Math.abs(context.dragEndX - context.dragStartX);
- var regionHeight = Math.abs(context.dragEndY - context.dragStartY);
-
- if (regionWidth < 2 && regionHeight < 2 &&
- g.lastx_ !== undefined && g.lastx_ != -1) {
- Dygraph.Interaction.treatMouseOpAsClick(g, event, context);
- }
-
- context.regionWidth = regionWidth;
- context.regionHeight = regionHeight;
-};
-
-/**
- * Called in response to an interaction model operation that
- * should start the default panning behavior.
- *
- * It's used in the default callback for "mousedown" operations.
- * Custom interaction model builders can use it to provide the default
- * panning behavior.
- *
- * @param {Event} event the event object which led to the startPan call.
- * @param {Dygraph} g The dygraph on which to act.
- * @param {Object} context The dragging context object (with
- * dragStartX/dragStartY/etc. properties). This function modifies the
- * context.
- */
-Dygraph.Interaction.startPan = function(event, g, context) {
- var i, axis;
- context.isPanning = true;
- var xRange = g.xAxisRange();
-
- if (g.getOptionForAxis("logscale", "x")) {
- context.initialLeftmostDate = Dygraph.log10(xRange[0]);
- context.dateRange = Dygraph.log10(xRange[1]) - Dygraph.log10(xRange[0]);
- } else {
- context.initialLeftmostDate = xRange[0];
- context.dateRange = xRange[1] - xRange[0];
- }
- context.xUnitsPerPixel = context.dateRange / (g.plotter_.area.w - 1);
-
- if (g.getNumericOption("panEdgeFraction")) {
- var maxXPixelsToDraw = g.width_ * g.getNumericOption("panEdgeFraction");
- var xExtremes = g.xAxisExtremes(); // I REALLY WANT TO CALL THIS xTremes!
-
- var boundedLeftX = g.toDomXCoord(xExtremes[0]) - maxXPixelsToDraw;
- var boundedRightX = g.toDomXCoord(xExtremes[1]) + maxXPixelsToDraw;
-
- var boundedLeftDate = g.toDataXCoord(boundedLeftX);
- var boundedRightDate = g.toDataXCoord(boundedRightX);
- context.boundedDates = [boundedLeftDate, boundedRightDate];
-
- var boundedValues = [];
- var maxYPixelsToDraw = g.height_ * g.getNumericOption("panEdgeFraction");
-
- for (i = 0; i < g.axes_.length; i++) {
- axis = g.axes_[i];
- var yExtremes = axis.extremeRange;
-
- var boundedTopY = g.toDomYCoord(yExtremes[0], i) + maxYPixelsToDraw;
- var boundedBottomY = g.toDomYCoord(yExtremes[1], i) - maxYPixelsToDraw;
-
- var boundedTopValue = g.toDataYCoord(boundedTopY, i);
- var boundedBottomValue = g.toDataYCoord(boundedBottomY, i);
-
- boundedValues[i] = [boundedTopValue, boundedBottomValue];
- }
- context.boundedValues = boundedValues;
- }
-
- // Record the range of each y-axis at the start of the drag.
- // If any axis has a valueRange or valueWindow, then we want a 2D pan.
- // We can't store data directly in g.axes_, because it does not belong to us
- // and could change out from under us during a pan (say if there's a data
- // update).
- context.is2DPan = false;
- context.axes = [];
- for (i = 0; i < g.axes_.length; i++) {
- axis = g.axes_[i];
- var axis_data = {};
- var yRange = g.yAxisRange(i);
- // TODO(konigsberg): These values should be in |context|.
- // In log scale, initialTopValue, dragValueRange and unitsPerPixel are log scale.
- var logscale = g.attributes_.getForAxis("logscale", i);
- if (logscale) {
- axis_data.initialTopValue = Dygraph.log10(yRange[1]);
- axis_data.dragValueRange = Dygraph.log10(yRange[1]) - Dygraph.log10(yRange[0]);
- } else {
- axis_data.initialTopValue = yRange[1];
- axis_data.dragValueRange = yRange[1] - yRange[0];
- }
- axis_data.unitsPerPixel = axis_data.dragValueRange / (g.plotter_.area.h - 1);
- context.axes.push(axis_data);
-
- // While calculating axes, set 2dpan.
- if (axis.valueWindow || axis.valueRange) context.is2DPan = true;
- }
-};
-
-/**
- * Called in response to an interaction model operation that
- * responds to an event that pans the view.
- *
- * It's used in the default callback for "mousemove" operations.
- * Custom interaction model builders can use it to provide the default
- * panning behavior.
- *
- * @param {Event} event the event object which led to the movePan call.
- * @param {Dygraph} g The dygraph on which to act.
- * @param {Object} context The dragging context object (with
- * dragStartX/dragStartY/etc. properties). This function modifies the
- * context.
- */
-Dygraph.Interaction.movePan = function(event, g, context) {
- context.dragEndX = Dygraph.dragGetX_(event, context);
- context.dragEndY = Dygraph.dragGetY_(event, context);
-
- var minDate = context.initialLeftmostDate -
- (context.dragEndX - context.dragStartX) * context.xUnitsPerPixel;
- if (context.boundedDates) {
- minDate = Math.max(minDate, context.boundedDates[0]);
- }
- var maxDate = minDate + context.dateRange;
- if (context.boundedDates) {
- if (maxDate > context.boundedDates[1]) {
- // Adjust minDate, and recompute maxDate.
- minDate = minDate - (maxDate - context.boundedDates[1]);
- maxDate = minDate + context.dateRange;
- }
- }
-
- if (g.getOptionForAxis("logscale", "x")) {
- g.dateWindow_ = [ Math.pow(Dygraph.LOG_SCALE, minDate),
- Math.pow(Dygraph.LOG_SCALE, maxDate) ];
- } else {
- g.dateWindow_ = [minDate, maxDate];
- }
-
- // y-axis scaling is automatic unless this is a full 2D pan.
- if (context.is2DPan) {
-
- var pixelsDragged = context.dragEndY - context.dragStartY;
-
- // Adjust each axis appropriately.
- for (var i = 0; i < g.axes_.length; i++) {
- var axis = g.axes_[i];
- var axis_data = context.axes[i];
- var unitsDragged = pixelsDragged * axis_data.unitsPerPixel;
-
- var boundedValue = context.boundedValues ? context.boundedValues[i] : null;
-
- // In log scale, maxValue and minValue are the logs of those values.
- var maxValue = axis_data.initialTopValue + unitsDragged;
- if (boundedValue) {
- maxValue = Math.min(maxValue, boundedValue[1]);
- }
- var minValue = maxValue - axis_data.dragValueRange;
- if (boundedValue) {
- if (minValue < boundedValue[0]) {
- // Adjust maxValue, and recompute minValue.
- maxValue = maxValue - (minValue - boundedValue[0]);
- minValue = maxValue - axis_data.dragValueRange;
- }
- }
- if (g.attributes_.getForAxis("logscale", i)) {
- axis.valueWindow = [ Math.pow(Dygraph.LOG_SCALE, minValue),
- Math.pow(Dygraph.LOG_SCALE, maxValue) ];
- } else {
- axis.valueWindow = [ minValue, maxValue ];
- }
- }
- }
-
- g.drawGraph_(false);
-};
-
-/**
- * Called in response to an interaction model operation that
- * responds to an event that ends panning.
- *
- * It's used in the default callback for "mouseup" operations.
- * Custom interaction model builders can use it to provide the default
- * panning behavior.
- *
- * @param {Event} event the event object which led to the endPan call.
- * @param {Dygraph} g The dygraph on which to act.
- * @param {Object} context The dragging context object (with
- * dragStartX/dragStartY/etc. properties). This function modifies the
- * context.
- */
-Dygraph.Interaction.endPan = Dygraph.Interaction.maybeTreatMouseOpAsClick;
-
-/**
- * Called in response to an interaction model operation that
- * responds to an event that starts zooming.
- *
- * It's used in the default callback for "mousedown" operations.
- * Custom interaction model builders can use it to provide the default
- * zooming behavior.
- *
- * @param {Event} event the event object which led to the startZoom call.
- * @param {Dygraph} g The dygraph on which to act.
- * @param {Object} context The dragging context object (with
- * dragStartX/dragStartY/etc. properties). This function modifies the
- * context.
- */
-Dygraph.Interaction.startZoom = function(event, g, context) {
- context.isZooming = true;
- context.zoomMoved = false;
-};
-
-/**
- * Called in response to an interaction model operation that
- * responds to an event that defines zoom boundaries.
- *
- * It's used in the default callback for "mousemove" operations.
- * Custom interaction model builders can use it to provide the default
- * zooming behavior.
- *
- * @param {Event} event the event object which led to the moveZoom call.
- * @param {Dygraph} g The dygraph on which to act.
- * @param {Object} context The dragging context object (with
- * dragStartX/dragStartY/etc. properties). This function modifies the
- * context.
- */
-Dygraph.Interaction.moveZoom = function(event, g, context) {
- context.zoomMoved = true;
- context.dragEndX = Dygraph.dragGetX_(event, context);
- context.dragEndY = Dygraph.dragGetY_(event, context);
-
- var xDelta = Math.abs(context.dragStartX - context.dragEndX);
- var yDelta = Math.abs(context.dragStartY - context.dragEndY);
-
- // drag direction threshold for y axis is twice as large as x axis
- context.dragDirection = (xDelta < yDelta / 2) ? Dygraph.VERTICAL : Dygraph.HORIZONTAL;
-
- g.drawZoomRect_(
- context.dragDirection,
- context.dragStartX,
- context.dragEndX,
- context.dragStartY,
- context.dragEndY,
- context.prevDragDirection,
- context.prevEndX,
- context.prevEndY);
-
- context.prevEndX = context.dragEndX;
- context.prevEndY = context.dragEndY;
- context.prevDragDirection = context.dragDirection;
-};
-
-/**
- * TODO(danvk): move this logic into dygraph.js
- * @param {Dygraph} g
- * @param {Event} event
- * @param {Object} context
- */
-Dygraph.Interaction.treatMouseOpAsClick = function(g, event, context) {
- var clickCallback = g.getFunctionOption('clickCallback');
- var pointClickCallback = g.getFunctionOption('pointClickCallback');
-
- var selectedPoint = null;
-
- // Find out if the click occurs on a point.
- var closestIdx = -1;
- var closestDistance = Number.MAX_VALUE;
-
- // check if the click was on a particular point.
- for (var i = 0; i < g.selPoints_.length; i++) {
- var p = g.selPoints_[i];
- var distance = Math.pow(p.canvasx - context.dragEndX, 2) +
- Math.pow(p.canvasy - context.dragEndY, 2);
- if (!isNaN(distance) &&
- (closestIdx == -1 || distance < closestDistance)) {
- closestDistance = distance;
- closestIdx = i;
- }
- }
-
- // Allow any click within two pixels of the dot.
- var radius = g.getNumericOption('highlightCircleSize') + 2;
- if (closestDistance <= radius * radius) {
- selectedPoint = g.selPoints_[closestIdx];
- }
-
- if (selectedPoint) {
- var e = {
- cancelable: true,
- point: selectedPoint,
- canvasx: context.dragEndX,
- canvasy: context.dragEndY
- };
- var defaultPrevented = g.cascadeEvents_('pointClick', e);
- if (defaultPrevented) {
- // Note: this also prevents click / clickCallback from firing.
- return;
- }
- if (pointClickCallback) {
- pointClickCallback.call(g, event, selectedPoint);
- }
- }
-
- var e = {
- cancelable: true,
- xval: g.lastx_, // closest point by x value
- pts: g.selPoints_,
- canvasx: context.dragEndX,
- canvasy: context.dragEndY
- };
- if (!g.cascadeEvents_('click', e)) {
- if (clickCallback) {
- // TODO(danvk): pass along more info about the points, e.g. 'x'
- clickCallback.call(g, event, g.lastx_, g.selPoints_);
- }
- }
-};
-
-/**
- * Called in response to an interaction model operation that
- * responds to an event that performs a zoom based on previously defined
- * bounds..
- *
- * It's used in the default callback for "mouseup" operations.
- * Custom interaction model builders can use it to provide the default
- * zooming behavior.
- *
- * @param {Event} event the event object which led to the endZoom call.
- * @param {Dygraph} g The dygraph on which to end the zoom.
- * @param {Object} context The dragging context object (with
- * dragStartX/dragStartY/etc. properties). This function modifies the
- * context.
- */
-Dygraph.Interaction.endZoom = function(event, g, context) {
- g.clearZoomRect_();
- context.isZooming = false;
- Dygraph.Interaction.maybeTreatMouseOpAsClick(event, g, context);
-
- // The zoom rectangle is visibly clipped to the plot area, so its behavior
- // should be as well.
- // See http://code.google.com/p/dygraphs/issues/detail?id=280
- var plotArea = g.getArea();
- if (context.regionWidth >= 10 &&
- context.dragDirection == Dygraph.HORIZONTAL) {
- var left = Math.min(context.dragStartX, context.dragEndX),
- right = Math.max(context.dragStartX, context.dragEndX);
- left = Math.max(left, plotArea.x);
- right = Math.min(right, plotArea.x + plotArea.w);
- if (left < right) {
- g.doZoomX_(left, right);
- }
- context.cancelNextDblclick = true;
- } else if (context.regionHeight >= 10 &&
- context.dragDirection == Dygraph.VERTICAL) {
- var top = Math.min(context.dragStartY, context.dragEndY),
- bottom = Math.max(context.dragStartY, context.dragEndY);
- top = Math.max(top, plotArea.y);
- bottom = Math.min(bottom, plotArea.y + plotArea.h);
- if (top < bottom) {
- g.doZoomY_(top, bottom);
- }
- context.cancelNextDblclick = true;
- }
- context.dragStartX = null;
- context.dragStartY = null;
-};
-
-/**
- * @private
- */
-Dygraph.Interaction.startTouch = function(event, g, context) {
- event.preventDefault(); // touch browsers are all nice.
- if (event.touches.length > 1) {
- // If the user ever puts two fingers down, it's not a double tap.
- context.startTimeForDoubleTapMs = null;
- }
-
- var touches = [];
- for (var i = 0; i < event.touches.length; i++) {
- var t = event.touches[i];
- // we dispense with 'dragGetX_' because all touchBrowsers support pageX
- touches.push({
- pageX: t.pageX,
- pageY: t.pageY,
- dataX: g.toDataXCoord(t.pageX),
- dataY: g.toDataYCoord(t.pageY)
- // identifier: t.identifier
- });
- }
- context.initialTouches = touches;
-
- if (touches.length == 1) {
- // This is just a swipe.
- context.initialPinchCenter = touches[0];
- context.touchDirections = { x: true, y: true };
- } else if (touches.length >= 2) {
- // It's become a pinch!
- // In case there are 3+ touches, we ignore all but the "first" two.
-
- // only screen coordinates can be averaged (data coords could be log scale).
- context.initialPinchCenter = {
- pageX: 0.5 * (touches[0].pageX + touches[1].pageX),
- pageY: 0.5 * (touches[0].pageY + touches[1].pageY),
-
- // TODO(danvk): remove
- dataX: 0.5 * (touches[0].dataX + touches[1].dataX),
- dataY: 0.5 * (touches[0].dataY + touches[1].dataY)
- };
-
- // Make pinches in a 45-degree swath around either axis 1-dimensional zooms.
- var initialAngle = 180 / Math.PI * Math.atan2(
- context.initialPinchCenter.pageY - touches[0].pageY,
- touches[0].pageX - context.initialPinchCenter.pageX);
-
- // use symmetry to get it into the first quadrant.
- initialAngle = Math.abs(initialAngle);
- if (initialAngle > 90) initialAngle = 90 - initialAngle;
-
- context.touchDirections = {
- x: (initialAngle < (90 - 45/2)),
- y: (initialAngle > 45/2)
- };
- }
-
- // save the full x & y ranges.
- context.initialRange = {
- x: g.xAxisRange(),
- y: g.yAxisRange()
- };
-};
-
-/**
- * @private
- */
-Dygraph.Interaction.moveTouch = function(event, g, context) {
- // If the tap moves, then it's definitely not part of a double-tap.
- context.startTimeForDoubleTapMs = null;
-
- var i, touches = [];
- for (i = 0; i < event.touches.length; i++) {
- var t = event.touches[i];
- touches.push({
- pageX: t.pageX,
- pageY: t.pageY
- });
- }
- var initialTouches = context.initialTouches;
-
- var c_now;
-
- // old and new centers.
- var c_init = context.initialPinchCenter;
- if (touches.length == 1) {
- c_now = touches[0];
- } else {
- c_now = {
- pageX: 0.5 * (touches[0].pageX + touches[1].pageX),
- pageY: 0.5 * (touches[0].pageY + touches[1].pageY)
- };
- }
-
- // this is the "swipe" component
- // we toss it out for now, but could use it in the future.
- var swipe = {
- pageX: c_now.pageX - c_init.pageX,
- pageY: c_now.pageY - c_init.pageY
- };
- var dataWidth = context.initialRange.x[1] - context.initialRange.x[0];
- var dataHeight = context.initialRange.y[0] - context.initialRange.y[1];
- swipe.dataX = (swipe.pageX / g.plotter_.area.w) * dataWidth;
- swipe.dataY = (swipe.pageY / g.plotter_.area.h) * dataHeight;
- var xScale, yScale;
-
- // The residual bits are usually split into scale & rotate bits, but we split
- // them into x-scale and y-scale bits.
- if (touches.length == 1) {
- xScale = 1.0;
- yScale = 1.0;
- } else if (touches.length >= 2) {
- var initHalfWidth = (initialTouches[1].pageX - c_init.pageX);
- xScale = (touches[1].pageX - c_now.pageX) / initHalfWidth;
-
- var initHalfHeight = (initialTouches[1].pageY - c_init.pageY);
- yScale = (touches[1].pageY - c_now.pageY) / initHalfHeight;
- }
-
- // Clip scaling to [1/8, 8] to prevent too much blowup.
- xScale = Math.min(8, Math.max(0.125, xScale));
- yScale = Math.min(8, Math.max(0.125, yScale));
-
- var didZoom = false;
- if (context.touchDirections.x) {
- g.dateWindow_ = [
- c_init.dataX - swipe.dataX + (context.initialRange.x[0] - c_init.dataX) / xScale,
- c_init.dataX - swipe.dataX + (context.initialRange.x[1] - c_init.dataX) / xScale
- ];
- didZoom = true;
- }
-
- if (context.touchDirections.y) {
- for (i = 0; i < 1 /*g.axes_.length*/; i++) {
- var axis = g.axes_[i];
- var logscale = g.attributes_.getForAxis("logscale", i);
- if (logscale) {
- // TODO(danvk): implement
- } else {
- axis.valueWindow = [
- c_init.dataY - swipe.dataY + (context.initialRange.y[0] - c_init.dataY) / yScale,
- c_init.dataY - swipe.dataY + (context.initialRange.y[1] - c_init.dataY) / yScale
- ];
- didZoom = true;
- }
- }
- }
-
- g.drawGraph_(false);
-
- // We only call zoomCallback on zooms, not pans, to mirror desktop behavior.
- if (didZoom && touches.length > 1 && g.getFunctionOption('zoomCallback')) {
- var viewWindow = g.xAxisRange();
- g.getFunctionOption("zoomCallback").call(g, viewWindow[0], viewWindow[1], g.yAxisRanges());
- }
-};
-
-/**
- * @private
- */
-Dygraph.Interaction.endTouch = function(event, g, context) {
- if (event.touches.length !== 0) {
- // this is effectively a "reset"
- Dygraph.Interaction.startTouch(event, g, context);
- } else if (event.changedTouches.length == 1) {
- // Could be part of a "double tap"
- // The heuristic here is that it's a double-tap if the two touchend events
- // occur within 500ms and within a 50x50 pixel box.
- var now = new Date().getTime();
- var t = event.changedTouches[0];
- if (context.startTimeForDoubleTapMs &&
- now - context.startTimeForDoubleTapMs < 500 &&
- context.doubleTapX && Math.abs(context.doubleTapX - t.screenX) < 50 &&
- context.doubleTapY && Math.abs(context.doubleTapY - t.screenY) < 50) {
- g.resetZoom();
- } else {
- context.startTimeForDoubleTapMs = now;
- context.doubleTapX = t.screenX;
- context.doubleTapY = t.screenY;
- }
- }
-};
-
-// Determine the distance from x to [left, right].
-var distanceFromInterval = function(x, left, right) {
- if (x < left) {
- return left - x;
- } else if (x > right) {
- return x - right;
- } else {
- return 0;
- }
-};
-
-/**
- * Returns the number of pixels by which the event happens from the nearest
- * edge of the chart. For events in the interior of the chart, this returns zero.
- */
-var distanceFromChart = function(event, g) {
- var chartPos = Dygraph.findPos(g.canvas_);
- var box = {
- left: chartPos.x,
- right: chartPos.x + g.canvas_.offsetWidth,
- top: chartPos.y,
- bottom: chartPos.y + g.canvas_.offsetHeight
- };
-
- var pt = {
- x: Dygraph.pageX(event),
- y: Dygraph.pageY(event)
- };
-
- var dx = distanceFromInterval(pt.x, box.left, box.right),
- dy = distanceFromInterval(pt.y, box.top, box.bottom);
- return Math.max(dx, dy);
-};
-
-/**
- * Default interation model for dygraphs. You can refer to specific elements of
- * this when constructing your own interaction model, e.g.:
- * g.updateOptions( {
- * interactionModel: {
- * mousedown: Dygraph.defaultInteractionModel.mousedown
- * }
- * } );
- */
-Dygraph.Interaction.defaultModel = {
- // Track the beginning of drag events
- mousedown: function(event, g, context) {
- // Right-click should not initiate a zoom.
- if (event.button && event.button == 2) return;
-
- context.initializeMouseDown(event, g, context);
-
- if (event.altKey || event.shiftKey) {
- Dygraph.startPan(event, g, context);
- } else {
- Dygraph.startZoom(event, g, context);
- }
-
- // Note: we register mousemove/mouseup on document to allow some leeway for
- // events to move outside of the chart. Interaction model events get
- // registered on the canvas, which is too small to allow this.
- var mousemove = function(event) {
- if (context.isZooming) {
- // When the mouse moves >200px from the chart edge, cancel the zoom.
- var d = distanceFromChart(event, g);
- if (d < DRAG_EDGE_MARGIN) {
- Dygraph.moveZoom(event, g, context);
- } else {
- if (context.dragEndX !== null) {
- context.dragEndX = null;
- context.dragEndY = null;
- g.clearZoomRect_();
- }
- }
- } else if (context.isPanning) {
- Dygraph.movePan(event, g, context);
- }
- };
- var mouseup = function(event) {
- if (context.isZooming) {
- if (context.dragEndX !== null) {
- Dygraph.endZoom(event, g, context);
- } else {
- Dygraph.Interaction.maybeTreatMouseOpAsClick(event, g, context);
- }
- } else if (context.isPanning) {
- Dygraph.endPan(event, g, context);
- }
-
- Dygraph.removeEvent(document, 'mousemove', mousemove);
- Dygraph.removeEvent(document, 'mouseup', mouseup);
- context.destroy();
- };
-
- g.addAndTrackEvent(document, 'mousemove', mousemove);
- g.addAndTrackEvent(document, 'mouseup', mouseup);
- },
- willDestroyContextMyself: true,
-
- touchstart: function(event, g, context) {
- Dygraph.Interaction.startTouch(event, g, context);
- },
- touchmove: function(event, g, context) {
- Dygraph.Interaction.moveTouch(event, g, context);
- },
- touchend: function(event, g, context) {
- Dygraph.Interaction.endTouch(event, g, context);
- },
-
- // Disable zooming out if panning.
- dblclick: function(event, g, context) {
- if (context.cancelNextDblclick) {
- context.cancelNextDblclick = false;
- return;
- }
-
- // Give plugins a chance to grab this event.
- var e = {
- canvasx: context.dragEndX,
- canvasy: context.dragEndY
- };
- if (g.cascadeEvents_('dblclick', e)) {
- return;
- }
-
- if (event.altKey || event.shiftKey) {
- return;
- }
- g.resetZoom();
- }
-};
-
-Dygraph.DEFAULT_ATTRS.interactionModel = Dygraph.Interaction.defaultModel;
-
-// old ways of accessing these methods/properties
-Dygraph.defaultInteractionModel = Dygraph.Interaction.defaultModel;
-Dygraph.endZoom = Dygraph.Interaction.endZoom;
-Dygraph.moveZoom = Dygraph.Interaction.moveZoom;
-Dygraph.startZoom = Dygraph.Interaction.startZoom;
-Dygraph.endPan = Dygraph.Interaction.endPan;
-Dygraph.movePan = Dygraph.Interaction.movePan;
-Dygraph.startPan = Dygraph.Interaction.startPan;
-
-Dygraph.Interaction.nonInteractiveModel_ = {
- mousedown: function(event, g, context) {
- context.initializeMouseDown(event, g, context);
- },
- mouseup: Dygraph.Interaction.maybeTreatMouseOpAsClick
-};
-
-// Default interaction model when using the range selector.
-Dygraph.Interaction.dragIsPanInteractionModel = {
- mousedown: function(event, g, context) {
- context.initializeMouseDown(event, g, context);
- Dygraph.startPan(event, g, context);
- },
- mousemove: function(event, g, context) {
- if (context.isPanning) {
- Dygraph.movePan(event, g, context);
- }
- },
- mouseup: function(event, g, context) {
- if (context.isPanning) {
- Dygraph.endPan(event, g, context);
- }
- }
-};
-
-})();
-/**
- * @license
- * Copyright 2011 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview Description of this file.
- * @author danvk@google.com (Dan Vanderkam)
- *
- * A ticker is a function with the following interface:
- *
- * function(a, b, pixels, options_view, dygraph, forced_values);
- * -> [ { v: tick1_v, label: tick1_label[, label_v: label_v1] },
- * { v: tick2_v, label: tick2_label[, label_v: label_v2] },
- * ...
- * ]
- *
- * The returned value is called a "tick list".
- *
- * Arguments
- * ---------
- *
- * [a, b] is the range of the axis for which ticks are being generated. For a
- * numeric axis, these will simply be numbers. For a date axis, these will be
- * millis since epoch (convertable to Date objects using "new Date(a)" and "new
- * Date(b)").
- *
- * opts provides access to chart- and axis-specific options. It can be used to
- * access number/date formatting code/options, check for a log scale, etc.
- *
- * pixels is the length of the axis in pixels. opts('pixelsPerLabel') is the
- * minimum amount of space to be allotted to each label. For instance, if
- * pixels=400 and opts('pixelsPerLabel')=40 then the ticker should return
- * between zero and ten (400/40) ticks.
- *
- * dygraph is the Dygraph object for which an axis is being constructed.
- *
- * forced_values is used for secondary y-axes. The tick positions are typically
- * set by the primary y-axis, so the secondary y-axis has no choice in where to
- * put these. It simply has to generate labels for these data values.
- *
- * Tick lists
- * ----------
- * Typically a tick will have both a grid/tick line and a label at one end of
- * that line (at the bottom for an x-axis, at left or right for the y-axis).
- *
- * A tick may be missing one of these two components:
- * - If "label_v" is specified instead of "v", then there will be no tick or
- * gridline, just a label.
- * - Similarly, if "label" is not specified, then there will be a gridline
- * without a label.
- *
- * This flexibility is useful in a few situations:
- * - For log scales, some of the tick lines may be too close to all have labels.
- * - For date scales where years are being displayed, it is desirable to display
- * tick marks at the beginnings of years but labels (e.g. "2006") in the
- * middle of the years.
- */
-
-/*jshint sub:true */
-/*global Dygraph:false */
-(function() {
-"use strict";
-
-/** @typedef {Array.<{v:number, label:string, label_v:(string|undefined)}>} */
-Dygraph.TickList = undefined; // the ' = undefined' keeps jshint happy.
-
-/** @typedef {function(
- * number,
- * number,
- * number,
- * function(string):*,
- * Dygraph=,
- * Array.<number>=
- * ): Dygraph.TickList}
- */
-Dygraph.Ticker = undefined; // the ' = undefined' keeps jshint happy.
-
-/** @type {Dygraph.Ticker} */
-Dygraph.numericLinearTicks = function(a, b, pixels, opts, dygraph, vals) {
- var nonLogscaleOpts = function(opt) {
- if (opt === 'logscale') return false;
- return opts(opt);
- };
- return Dygraph.numericTicks(a, b, pixels, nonLogscaleOpts, dygraph, vals);
-};
-
-/** @type {Dygraph.Ticker} */
-Dygraph.numericTicks = function(a, b, pixels, opts, dygraph, vals) {
- var pixels_per_tick = /** @type{number} */(opts('pixelsPerLabel'));
- var ticks = [];
- var i, j, tickV, nTicks;
- if (vals) {
- for (i = 0; i < vals.length; i++) {
- ticks.push({v: vals[i]});
- }
- } else {
- // TODO(danvk): factor this log-scale block out into a separate function.
- if (opts("logscale")) {
- nTicks = Math.floor(pixels / pixels_per_tick);
- var minIdx = Dygraph.binarySearch(a, Dygraph.PREFERRED_LOG_TICK_VALUES, 1);
- var maxIdx = Dygraph.binarySearch(b, Dygraph.PREFERRED_LOG_TICK_VALUES, -1);
- if (minIdx == -1) {
- minIdx = 0;
- }
- if (maxIdx == -1) {
- maxIdx = Dygraph.PREFERRED_LOG_TICK_VALUES.length - 1;
- }
- // Count the number of tick values would appear, if we can get at least
- // nTicks / 4 accept them.
- var lastDisplayed = null;
- if (maxIdx - minIdx >= nTicks / 4) {
- for (var idx = maxIdx; idx >= minIdx; idx--) {
- var tickValue = Dygraph.PREFERRED_LOG_TICK_VALUES[idx];
- var pixel_coord = Math.log(tickValue / a) / Math.log(b / a) * pixels;
- var tick = { v: tickValue };
- if (lastDisplayed === null) {
- lastDisplayed = {
- tickValue : tickValue,
- pixel_coord : pixel_coord
- };
- } else {
- if (Math.abs(pixel_coord - lastDisplayed.pixel_coord) >= pixels_per_tick) {
- lastDisplayed = {
- tickValue : tickValue,
- pixel_coord : pixel_coord
- };
- } else {
- tick.label = "";
- }
- }
- ticks.push(tick);
- }
- // Since we went in backwards order.
- ticks.reverse();
- }
- }
-
- // ticks.length won't be 0 if the log scale function finds values to insert.
- if (ticks.length === 0) {
- // Basic idea:
- // Try labels every 1, 2, 5, 10, 20, 50, 100, etc.
- // Calculate the resulting tick spacing (i.e. this.height_ / nTicks).
- // The first spacing greater than pixelsPerYLabel is what we use.
- // TODO(danvk): version that works on a log scale.
- var kmg2 = opts("labelsKMG2");
- var mults, base;
- if (kmg2) {
- mults = [1, 2, 4, 8, 16, 32, 64, 128, 256];
- base = 16;
- } else {
- mults = [1, 2, 5, 10, 20, 50, 100];
- base = 10;
- }
-
- // Get the maximum number of permitted ticks based on the
- // graph's pixel size and pixels_per_tick setting.
- var max_ticks = Math.ceil(pixels / pixels_per_tick);
-
- // Now calculate the data unit equivalent of this tick spacing.
- // Use abs() since graphs may have a reversed Y axis.
- var units_per_tick = Math.abs(b - a) / max_ticks;
-
- // Based on this, get a starting scale which is the largest
- // integer power of the chosen base (10 or 16) that still remains
- // below the requested pixels_per_tick spacing.
- var base_power = Math.floor(Math.log(units_per_tick) / Math.log(base));
- var base_scale = Math.pow(base, base_power);
-
- // Now try multiples of the starting scale until we find one
- // that results in tick marks spaced sufficiently far apart.
- // The "mults" array should cover the range 1 .. base^2 to
- // adjust for rounding and edge effects.
- var scale, low_val, high_val, spacing;
- for (j = 0; j < mults.length; j++) {
- scale = base_scale * mults[j];
- low_val = Math.floor(a / scale) * scale;
- high_val = Math.ceil(b / scale) * scale;
- nTicks = Math.abs(high_val - low_val) / scale;
- spacing = pixels / nTicks;
- if (spacing > pixels_per_tick) break;
- }
-
- // Construct the set of ticks.
- // Allow reverse y-axis if it's explicitly requested.
- if (low_val > high_val) scale *= -1;
- for (i = 0; i <= nTicks; i++) {
- tickV = low_val + i * scale;
- ticks.push( {v: tickV} );
- }
- }
- }
-
- var formatter = /**@type{AxisLabelFormatter}*/(opts('axisLabelFormatter'));
-
- // Add labels to the ticks.
- for (i = 0; i < ticks.length; i++) {
- if (ticks[i].label !== undefined) continue; // Use current label.
- // TODO(danvk): set granularity to something appropriate here.
- ticks[i].label = formatter(ticks[i].v, 0, opts, dygraph);
- }
-
- return ticks;
-};
-
-
-/** @type {Dygraph.Ticker} */
-Dygraph.dateTicker = function(a, b, pixels, opts, dygraph, vals) {
- var chosen = Dygraph.pickDateTickGranularity(a, b, pixels, opts);
-
- if (chosen >= 0) {
- return Dygraph.getDateAxis(a, b, chosen, opts, dygraph);
- } else {
- // this can happen if self.width_ is zero.
- return [];
- }
-};
-
-// Time granularity enumeration
-// TODO(danvk): make this an @enum
-Dygraph.SECONDLY = 0;
-Dygraph.TWO_SECONDLY = 1;
-Dygraph.FIVE_SECONDLY = 2;
-Dygraph.TEN_SECONDLY = 3;
-Dygraph.THIRTY_SECONDLY = 4;
-Dygraph.MINUTELY = 5;
-Dygraph.TWO_MINUTELY = 6;
-Dygraph.FIVE_MINUTELY = 7;
-Dygraph.TEN_MINUTELY = 8;
-Dygraph.THIRTY_MINUTELY = 9;
-Dygraph.HOURLY = 10;
-Dygraph.TWO_HOURLY = 11;
-Dygraph.SIX_HOURLY = 12;
-Dygraph.DAILY = 13;
-Dygraph.TWO_DAILY = 14;
-Dygraph.WEEKLY = 15;
-Dygraph.MONTHLY = 16;
-Dygraph.QUARTERLY = 17;
-Dygraph.BIANNUAL = 18;
-Dygraph.ANNUAL = 19;
-Dygraph.DECADAL = 20;
-Dygraph.CENTENNIAL = 21;
-Dygraph.NUM_GRANULARITIES = 22;
-
-// Date components enumeration (in the order of the arguments in Date)
-// TODO: make this an @enum
-Dygraph.DATEFIELD_Y = 0;
-Dygraph.DATEFIELD_M = 1;
-Dygraph.DATEFIELD_D = 2;
-Dygraph.DATEFIELD_HH = 3;
-Dygraph.DATEFIELD_MM = 4;
-Dygraph.DATEFIELD_SS = 5;
-Dygraph.DATEFIELD_MS = 6;
-Dygraph.NUM_DATEFIELDS = 7;
-
-
-/**
- * The value of datefield will start at an even multiple of "step", i.e.
- * if datefield=SS and step=5 then the first tick will be on a multiple of 5s.
- *
- * For granularities <= HOURLY, ticks are generated every `spacing` ms.
- *
- * At coarser granularities, ticks are generated by incrementing `datefield` by
- * `step`. In this case, the `spacing` value is only used to estimate the
- * number of ticks. It should roughly correspond to the spacing between
- * adjacent ticks.
- *
- * @type {Array.<{datefield:number, step:number, spacing:number}>}
- */
-Dygraph.TICK_PLACEMENT = [];
-Dygraph.TICK_PLACEMENT[Dygraph.SECONDLY] = {datefield: Dygraph.DATEFIELD_SS, step: 1, spacing: 1000 * 1};
-Dygraph.TICK_PLACEMENT[Dygraph.TWO_SECONDLY] = {datefield: Dygraph.DATEFIELD_SS, step: 2, spacing: 1000 * 2};
-Dygraph.TICK_PLACEMENT[Dygraph.FIVE_SECONDLY] = {datefield: Dygraph.DATEFIELD_SS, step: 5, spacing: 1000 * 5};
-Dygraph.TICK_PLACEMENT[Dygraph.TEN_SECONDLY] = {datefield: Dygraph.DATEFIELD_SS, step: 10, spacing: 1000 * 10};
-Dygraph.TICK_PLACEMENT[Dygraph.THIRTY_SECONDLY] = {datefield: Dygraph.DATEFIELD_SS, step: 30, spacing: 1000 * 30};
-Dygraph.TICK_PLACEMENT[Dygraph.MINUTELY] = {datefield: Dygraph.DATEFIELD_MM, step: 1, spacing: 1000 * 60};
-Dygraph.TICK_PLACEMENT[Dygraph.TWO_MINUTELY] = {datefield: Dygraph.DATEFIELD_MM, step: 2, spacing: 1000 * 60 * 2};
-Dygraph.TICK_PLACEMENT[Dygraph.FIVE_MINUTELY] = {datefield: Dygraph.DATEFIELD_MM, step: 5, spacing: 1000 * 60 * 5};
-Dygraph.TICK_PLACEMENT[Dygraph.TEN_MINUTELY] = {datefield: Dygraph.DATEFIELD_MM, step: 10, spacing: 1000 * 60 * 10};
-Dygraph.TICK_PLACEMENT[Dygraph.THIRTY_MINUTELY] = {datefield: Dygraph.DATEFIELD_MM, step: 30, spacing: 1000 * 60 * 30};
-Dygraph.TICK_PLACEMENT[Dygraph.HOURLY] = {datefield: Dygraph.DATEFIELD_HH, step: 1, spacing: 1000 * 3600};
-Dygraph.TICK_PLACEMENT[Dygraph.TWO_HOURLY] = {datefield: Dygraph.DATEFIELD_HH, step: 2, spacing: 1000 * 3600 * 2};
-Dygraph.TICK_PLACEMENT[Dygraph.SIX_HOURLY] = {datefield: Dygraph.DATEFIELD_HH, step: 6, spacing: 1000 * 3600 * 6};
-Dygraph.TICK_PLACEMENT[Dygraph.DAILY] = {datefield: Dygraph.DATEFIELD_D, step: 1, spacing: 1000 * 86400};
-Dygraph.TICK_PLACEMENT[Dygraph.TWO_DAILY] = {datefield: Dygraph.DATEFIELD_D, step: 2, spacing: 1000 * 86400 * 2};
-Dygraph.TICK_PLACEMENT[Dygraph.WEEKLY] = {datefield: Dygraph.DATEFIELD_D, step: 7, spacing: 1000 * 604800};
-Dygraph.TICK_PLACEMENT[Dygraph.MONTHLY] = {datefield: Dygraph.DATEFIELD_M, step: 1, spacing: 1000 * 7200 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 / 12
-Dygraph.TICK_PLACEMENT[Dygraph.QUARTERLY] = {datefield: Dygraph.DATEFIELD_M, step: 3, spacing: 1000 * 21600 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 / 4
-Dygraph.TICK_PLACEMENT[Dygraph.BIANNUAL] = {datefield: Dygraph.DATEFIELD_M, step: 6, spacing: 1000 * 43200 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 / 2
-Dygraph.TICK_PLACEMENT[Dygraph.ANNUAL] = {datefield: Dygraph.DATEFIELD_Y, step: 1, spacing: 1000 * 86400 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 * 1
-Dygraph.TICK_PLACEMENT[Dygraph.DECADAL] = {datefield: Dygraph.DATEFIELD_Y, step: 10, spacing: 1000 * 864000 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 * 10
-Dygraph.TICK_PLACEMENT[Dygraph.CENTENNIAL] = {datefield: Dygraph.DATEFIELD_Y, step: 100, spacing: 1000 * 8640000 * 365.2524}; // 1e3 * 60 * 60 * 24 * 365.2524 * 100
-
-
-/**
- * This is a list of human-friendly values at which to show tick marks on a log
- * scale. It is k * 10^n, where k=1..9 and n=-39..+39, so:
- * ..., 1, 2, 3, 4, 5, ..., 9, 10, 20, 30, ..., 90, 100, 200, 300, ...
- * NOTE: this assumes that Dygraph.LOG_SCALE = 10.
- * @type {Array.<number>}
- */
-Dygraph.PREFERRED_LOG_TICK_VALUES = (function() {
- var vals = [];
- for (var power = -39; power <= 39; power++) {
- var range = Math.pow(10, power);
- for (var mult = 1; mult <= 9; mult++) {
- var val = range * mult;
- vals.push(val);
- }
- }
- return vals;
-})();
-
-/**
- * Determine the correct granularity of ticks on a date axis.
- *
- * @param {number} a Left edge of the chart (ms)
- * @param {number} b Right edge of the chart (ms)
- * @param {number} pixels Size of the chart in the relevant dimension (width).
- * @param {function(string):*} opts Function mapping from option name -&gt; value.
- * @return {number} The appropriate axis granularity for this chart. See the
- * enumeration of possible values in dygraph-tickers.js.
- */
-Dygraph.pickDateTickGranularity = function(a, b, pixels, opts) {
- var pixels_per_tick = /** @type{number} */(opts('pixelsPerLabel'));
- for (var i = 0; i < Dygraph.NUM_GRANULARITIES; i++) {
- var num_ticks = Dygraph.numDateTicks(a, b, i);
- if (pixels / num_ticks >= pixels_per_tick) {
- return i;
- }
- }
- return -1;
-};
-
-/**
- * Compute the number of ticks on a date axis for a given granularity.
- * @param {number} start_time
- * @param {number} end_time
- * @param {number} granularity (one of the granularities enumerated above)
- * @return {number} (Approximate) number of ticks that would result.
- */
-Dygraph.numDateTicks = function(start_time, end_time, granularity) {
- var spacing = Dygraph.TICK_PLACEMENT[granularity].spacing;
- return Math.round(1.0 * (end_time - start_time) / spacing);
-};
-
-/**
- * Compute the positions and labels of ticks on a date axis for a given granularity.
- * @param {number} start_time
- * @param {number} end_time
- * @param {number} granularity (one of the granularities enumerated above)
- * @param {function(string):*} opts Function mapping from option name -&gt; value.
- * @param {Dygraph=} dg
- * @return {!Dygraph.TickList}
- */
-Dygraph.getDateAxis = function(start_time, end_time, granularity, opts, dg) {
- var formatter = /** @type{AxisLabelFormatter} */(
- opts("axisLabelFormatter"));
- var utc = opts("labelsUTC");
- var accessors = utc ? Dygraph.DateAccessorsUTC : Dygraph.DateAccessorsLocal;
-
- var datefield = Dygraph.TICK_PLACEMENT[granularity].datefield;
- var step = Dygraph.TICK_PLACEMENT[granularity].step;
- var spacing = Dygraph.TICK_PLACEMENT[granularity].spacing;
-
- // Choose a nice tick position before the initial instant.
- // Currently, this code deals properly with the existent daily granularities:
- // DAILY (with step of 1) and WEEKLY (with step of 7 but specially handled).
- // Other daily granularities (say TWO_DAILY) should also be handled specially
- // by setting the start_date_offset to 0.
- var start_date = new Date(start_time);
- var date_array = [];
- date_array[Dygraph.DATEFIELD_Y] = accessors.getFullYear(start_date);
- date_array[Dygraph.DATEFIELD_M] = accessors.getMonth(start_date);
- date_array[Dygraph.DATEFIELD_D] = accessors.getDate(start_date);
- date_array[Dygraph.DATEFIELD_HH] = accessors.getHours(start_date);
- date_array[Dygraph.DATEFIELD_MM] = accessors.getMinutes(start_date);
- date_array[Dygraph.DATEFIELD_SS] = accessors.getSeconds(start_date);
- date_array[Dygraph.DATEFIELD_MS] = accessors.getMilliseconds(start_date);
-
- var start_date_offset = date_array[datefield] % step;
- if (granularity == Dygraph.WEEKLY) {
- // This will put the ticks on Sundays.
- start_date_offset = accessors.getDay(start_date);
- }
-
- date_array[datefield] -= start_date_offset;
- for (var df = datefield + 1; df < Dygraph.NUM_DATEFIELDS; df++) {
- // The minimum value is 1 for the day of month, and 0 for all other fields.
- date_array[df] = (df === Dygraph.DATEFIELD_D) ? 1 : 0;
- }
-
- // Generate the ticks.
- // For granularities not coarser than HOURLY we use the fact that:
- // the number of milliseconds between ticks is constant
- // and equal to the defined spacing.
- // Otherwise we rely on the 'roll over' property of the Date functions:
- // when some date field is set to a value outside of its logical range,
- // the excess 'rolls over' the next (more significant) field.
- // However, when using local time with DST transitions,
- // there are dates that do not represent any time value at all
- // (those in the hour skipped at the 'spring forward'),
- // and the JavaScript engines usually return an equivalent value.
- // Hence we have to check that the date is properly increased at each step,
- // returning a date at a nice tick position.
- var ticks = [];
- var tick_date = accessors.makeDate.apply(null, date_array);
- var tick_time = tick_date.getTime();
- if (granularity <= Dygraph.HOURLY) {
- if (tick_time < start_time) {
- tick_time += spacing;
- tick_date = new Date(tick_time);
- }
- while (tick_time <= end_time) {
- ticks.push({ v: tick_time,
- label: formatter(tick_date, granularity, opts, dg)
- });
- tick_time += spacing;
- tick_date = new Date(tick_time);
- }
- } else {
- if (tick_time < start_time) {
- date_array[datefield] += step;
- tick_date = accessors.makeDate.apply(null, date_array);
- tick_time = tick_date.getTime();
- }
- while (tick_time <= end_time) {
- if (granularity >= Dygraph.DAILY ||
- accessors.getHours(tick_date) % step === 0) {
- ticks.push({ v: tick_time,
- label: formatter(tick_date, granularity, opts, dg)
- });
- }
- date_array[datefield] += step;
- tick_date = accessors.makeDate.apply(null, date_array);
- tick_time = tick_date.getTime();
- }
- }
- return ticks;
-};
-
-// These are set here so that this file can be included after dygraph.js
-// or independently.
-if (Dygraph &&
- Dygraph.DEFAULT_ATTRS &&
- Dygraph.DEFAULT_ATTRS['axes'] &&
- Dygraph.DEFAULT_ATTRS['axes']['x'] &&
- Dygraph.DEFAULT_ATTRS['axes']['y'] &&
- Dygraph.DEFAULT_ATTRS['axes']['y2']) {
- Dygraph.DEFAULT_ATTRS['axes']['x']['ticker'] = Dygraph.dateTicker;
- Dygraph.DEFAULT_ATTRS['axes']['y']['ticker'] = Dygraph.numericTicks;
- Dygraph.DEFAULT_ATTRS['axes']['y2']['ticker'] = Dygraph.numericTicks;
-}
-
-})();
-/*global Dygraph:false */
-
-// Namespace for plugins. Load this before plugins/*.js files.
-Dygraph.Plugins = {};
-/**
- * @license
- * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/*global Dygraph:false */
-
-Dygraph.Plugins.Annotations = (function() {
-
-"use strict";
-
-/**
-Current bits of jankiness:
-- Uses dygraph.layout_ to get the parsed annotations.
-- Uses dygraph.plotter_.area
-
-It would be nice if the plugin didn't require so much special support inside
-the core dygraphs classes, but annotations involve quite a bit of parsing and
-layout.
-
-TODO(danvk): cache DOM elements.
-
-*/
-
-var annotations = function() {
- this.annotations_ = [];
-};
-
-annotations.prototype.toString = function() {
- return "Annotations Plugin";
-};
-
-annotations.prototype.activate = function(g) {
- return {
- clearChart: this.clearChart,
- didDrawChart: this.didDrawChart
- };
-};
-
-annotations.prototype.detachLabels = function() {
- for (var i = 0; i < this.annotations_.length; i++) {
- var a = this.annotations_[i];
- if (a.parentNode) a.parentNode.removeChild(a);
- this.annotations_[i] = null;
- }
- this.annotations_ = [];
-};
-
-annotations.prototype.clearChart = function(e) {
- this.detachLabels();
-};
-
-annotations.prototype.didDrawChart = function(e) {
- var g = e.dygraph;
-
- // Early out in the (common) case of zero annotations.
- var points = g.layout_.annotated_points;
- if (!points || points.length === 0) return;
-
- var containerDiv = e.canvas.parentNode;
- var annotationStyle = {
- "position": "absolute",
- "fontSize": g.getOption('axisLabelFontSize') + "px",
- "zIndex": 10,
- "overflow": "hidden"
- };
-
- var bindEvt = function(eventName, classEventName, pt) {
- return function(annotation_event) {
- var a = pt.annotation;
- if (a.hasOwnProperty(eventName)) {
- a[eventName](a, pt, g, annotation_event);
- } else if (g.getOption(classEventName)) {
- g.getOption(classEventName)(a, pt, g, annotation_event );
- }
- };
- };
-
- // Add the annotations one-by-one.
- var area = e.dygraph.plotter_.area;
-
- // x-coord to sum of previous annotation's heights (used for stacking).
- var xToUsedHeight = {};
-
- for (var i = 0; i < points.length; i++) {
- var p = points[i];
- if (p.canvasx < area.x || p.canvasx > area.x + area.w ||
- p.canvasy < area.y || p.canvasy > area.y + area.h) {
- continue;
- }
-
- var a = p.annotation;
- var tick_height = 6;
- if (a.hasOwnProperty("tickHeight")) {
- tick_height = a.tickHeight;
- }
-
- var div = document.createElement("div");
- for (var name in annotationStyle) {
- if (annotationStyle.hasOwnProperty(name)) {
- div.style[name] = annotationStyle[name];
- }
- }
- if (!a.hasOwnProperty('icon')) {
- div.className = "dygraphDefaultAnnotation";
- }
- if (a.hasOwnProperty('cssClass')) {
- div.className += " " + a.cssClass;
- }
-
- var width = a.hasOwnProperty('width') ? a.width : 16;
- var height = a.hasOwnProperty('height') ? a.height : 16;
- if (a.hasOwnProperty('icon')) {
- var img = document.createElement("img");
- img.src = a.icon;
- img.width = width;
- img.height = height;
- div.appendChild(img);
- } else if (p.annotation.hasOwnProperty('shortText')) {
- div.appendChild(document.createTextNode(p.annotation.shortText));
- }
- var left = p.canvasx - width / 2;
- div.style.left = left + "px";
- var divTop = 0;
- if (a.attachAtBottom) {
- var y = (area.y + area.h - height - tick_height);
- if (xToUsedHeight[left]) {
- y -= xToUsedHeight[left];
- } else {
- xToUsedHeight[left] = 0;
- }
- xToUsedHeight[left] += (tick_height + height);
- divTop = y;
- } else {
- divTop = p.canvasy - height - tick_height;
- }
- div.style.top = divTop + "px";
- div.style.width = width + "px";
- div.style.height = height + "px";
- div.title = p.annotation.text;
- div.style.color = g.colorsMap_[p.name];
- div.style.borderColor = g.colorsMap_[p.name];
- a.div = div;
-
- g.addAndTrackEvent(div, 'click',
- bindEvt('clickHandler', 'annotationClickHandler', p, this));
- g.addAndTrackEvent(div, 'mouseover',
- bindEvt('mouseOverHandler', 'annotationMouseOverHandler', p, this));
- g.addAndTrackEvent(div, 'mouseout',
- bindEvt('mouseOutHandler', 'annotationMouseOutHandler', p, this));
- g.addAndTrackEvent(div, 'dblclick',
- bindEvt('dblClickHandler', 'annotationDblClickHandler', p, this));
-
- containerDiv.appendChild(div);
- this.annotations_.push(div);
-
- var ctx = e.drawingContext;
- ctx.save();
- ctx.strokeStyle = g.colorsMap_[p.name];
- ctx.beginPath();
- if (!a.attachAtBottom) {
- ctx.moveTo(p.canvasx, p.canvasy);
- ctx.lineTo(p.canvasx, p.canvasy - 2 - tick_height);
- } else {
- var y = divTop + height;
- ctx.moveTo(p.canvasx, y);
- ctx.lineTo(p.canvasx, y + tick_height);
- }
- ctx.closePath();
- ctx.stroke();
- ctx.restore();
- }
-};
-
-annotations.prototype.destroy = function() {
- this.detachLabels();
-};
-
-return annotations;
-
-})();
-/**
- * @license
- * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/*global Dygraph:false */
-
-Dygraph.Plugins.Axes = (function() {
-
-'use strict';
-
-/*
-Bits of jankiness:
-- Direct layout access
-- Direct area access
-- Should include calculation of ticks, not just the drawing.
-
-Options left to make axis-friendly.
- ('drawAxesAtZero')
- ('xAxisHeight')
-*/
-
-/**
- * Draws the axes. This includes the labels on the x- and y-axes, as well
- * as the tick marks on the axes.
- * It does _not_ draw the grid lines which span the entire chart.
- */
-var axes = function() {
- this.xlabels_ = [];
- this.ylabels_ = [];
-};
-
-axes.prototype.toString = function() {
- return 'Axes Plugin';
-};
-
-axes.prototype.activate = function(g) {
- return {
- layout: this.layout,
- clearChart: this.clearChart,
- willDrawChart: this.willDrawChart
- };
-};
-
-axes.prototype.layout = function(e) {
- var g = e.dygraph;
-
- if (g.getOptionForAxis('drawAxis', 'y')) {
- var w = g.getOptionForAxis('axisLabelWidth', 'y') + 2 * g.getOptionForAxis('axisTickSize', 'y');
- e.reserveSpaceLeft(w);
- }
-
- if (g.getOptionForAxis('drawAxis', 'x')) {
- var h;
- // NOTE: I think this is probably broken now, since g.getOption() now
- // hits the dictionary. (That is, g.getOption('xAxisHeight') now always
- // has a value.)
- if (g.getOption('xAxisHeight')) {
- h = g.getOption('xAxisHeight');
- } else {
- h = g.getOptionForAxis('axisLabelFontSize', 'x') + 2 * g.getOptionForAxis('axisTickSize', 'x');
- }
- e.reserveSpaceBottom(h);
- }
-
- if (g.numAxes() == 2) {
- if (g.getOptionForAxis('drawAxis', 'y2')) {
- var w = g.getOptionForAxis('axisLabelWidth', 'y2') + 2 * g.getOptionForAxis('axisTickSize', 'y2');
- e.reserveSpaceRight(w);
- }
- } else if (g.numAxes() > 2) {
- g.error('Only two y-axes are supported at this time. (Trying ' +
- 'to use ' + g.numAxes() + ')');
- }
-};
-
-axes.prototype.detachLabels = function() {
- function removeArray(ary) {
- for (var i = 0; i < ary.length; i++) {
- var el = ary[i];
- if (el.parentNode) el.parentNode.removeChild(el);
- }
- }
-
- removeArray(this.xlabels_);
- removeArray(this.ylabels_);
- this.xlabels_ = [];
- this.ylabels_ = [];
-};
-
-axes.prototype.clearChart = function(e) {
- this.detachLabels();
-};
-
-axes.prototype.willDrawChart = function(e) {
- var g = e.dygraph;
-
- if (!g.getOptionForAxis('drawAxis', 'x') &&
- !g.getOptionForAxis('drawAxis', 'y') &&
- !g.getOptionForAxis('drawAxis', 'y2')) {
- return;
- }
-
- // Round pixels to half-integer boundaries for crisper drawing.
- function halfUp(x) { return Math.round(x) + 0.5; }
- function halfDown(y){ return Math.round(y) - 0.5; }
-
- var context = e.drawingContext;
- var containerDiv = e.canvas.parentNode;
- var canvasWidth = g.width_; // e.canvas.width is affected by pixel ratio.
- var canvasHeight = g.height_;
-
- var label, x, y, tick, i;
-
- var makeLabelStyle = function(axis) {
- return {
- position: 'absolute',
- fontSize: g.getOptionForAxis('axisLabelFontSize', axis) + 'px',
- zIndex: 10,
- color: g.getOptionForAxis('axisLabelColor', axis),
- width: g.getOptionForAxis('axisLabelWidth', axis) + 'px',
- // height: g.getOptionForAxis('axisLabelFontSize', 'x') + 2 + "px",
- lineHeight: 'normal', // Something other than "normal" line-height screws up label positioning.
- overflow: 'hidden'
- };
- };
-
- var labelStyles = {
- x : makeLabelStyle('x'),
- y : makeLabelStyle('y'),
- y2 : makeLabelStyle('y2')
- };
-
- var makeDiv = function(txt, axis, prec_axis) {
- /*
- * This seems to be called with the following three sets of axis/prec_axis:
- * x: undefined
- * y: y1
- * y: y2
- */
- var div = document.createElement('div');
- var labelStyle = labelStyles[prec_axis == 'y2' ? 'y2' : axis];
- for (var name in labelStyle) {
- if (labelStyle.hasOwnProperty(name)) {
- div.style[name] = labelStyle[name];
- }
- }
- var inner_div = document.createElement('div');
- inner_div.className = 'dygraph-axis-label' +
- ' dygraph-axis-label-' + axis +
- (prec_axis ? ' dygraph-axis-label-' + prec_axis : '');
- inner_div.innerHTML = txt;
- div.appendChild(inner_div);
- return div;
- };
-
- // axis lines
- context.save();
-
- var layout = g.layout_;
- var area = e.dygraph.plotter_.area;
-
- // Helper for repeated axis-option accesses.
- var makeOptionGetter = function(axis) {
- return function(option) {
- return g.getOptionForAxis(option, axis);
- };
- };
-
- if (g.getOptionForAxis('drawAxis', 'y')) {
- if (layout.yticks && layout.yticks.length > 0) {
- var num_axes = g.numAxes();
- var getOptions = [makeOptionGetter('y'), makeOptionGetter('y2')];
- for (i = 0; i < layout.yticks.length; i++) {
- tick = layout.yticks[i];
- if (typeof(tick) == 'function') return; // <-- when would this happen?
- x = area.x;
- var sgn = 1;
- var prec_axis = 'y1';
- var getAxisOption = getOptions[0];
- if (tick[0] == 1) { // right-side y-axis
- x = area.x + area.w;
- sgn = -1;
- prec_axis = 'y2';
- getAxisOption = getOptions[1];
- }
- var fontSize = getAxisOption('axisLabelFontSize');
- y = area.y + tick[1] * area.h;
-
- /* Tick marks are currently clipped, so don't bother drawing them.
- context.beginPath();
- context.moveTo(halfUp(x), halfDown(y));
- context.lineTo(halfUp(x - sgn * this.attr_('axisTickSize')), halfDown(y));
- context.closePath();
- context.stroke();
- */
-
- label = makeDiv(tick[2], 'y', num_axes == 2 ? prec_axis : null);
- var top = (y - fontSize / 2);
- if (top < 0) top = 0;
-
- if (top + fontSize + 3 > canvasHeight) {
- label.style.bottom = '0';
- } else {
- label.style.top = top + 'px';
- }
- if (tick[0] === 0) {
- label.style.left = (area.x - getAxisOption('axisLabelWidth') - getAxisOption('axisTickSize')) + 'px';
- label.style.textAlign = 'right';
- } else if (tick[0] == 1) {
- label.style.left = (area.x + area.w +
- getAxisOption('axisTickSize')) + 'px';
- label.style.textAlign = 'left';
- }
- label.style.width = getAxisOption('axisLabelWidth') + 'px';
- containerDiv.appendChild(label);
- this.ylabels_.push(label);
- }
-
- // The lowest tick on the y-axis often overlaps with the leftmost
- // tick on the x-axis. Shift the bottom tick up a little bit to
- // compensate if necessary.
- var bottomTick = this.ylabels_[0];
- // Interested in the y2 axis also?
- var fontSize = g.getOptionForAxis('axisLabelFontSize', 'y');
- var bottom = parseInt(bottomTick.style.top, 10) + fontSize;
- if (bottom > canvasHeight - fontSize) {
- bottomTick.style.top = (parseInt(bottomTick.style.top, 10) -
- fontSize / 2) + 'px';
- }
- }
-
- // draw a vertical line on the left to separate the chart from the labels.
- var axisX;
- if (g.getOption('drawAxesAtZero')) {
- var r = g.toPercentXCoord(0);
- if (r > 1 || r < 0 || isNaN(r)) r = 0;
- axisX = halfUp(area.x + r * area.w);
- } else {
- axisX = halfUp(area.x);
- }
-
- context.strokeStyle = g.getOptionForAxis('axisLineColor', 'y');
- context.lineWidth = g.getOptionForAxis('axisLineWidth', 'y');
-
- context.beginPath();
- context.moveTo(axisX, halfDown(area.y));
- context.lineTo(axisX, halfDown(area.y + area.h));
- context.closePath();
- context.stroke();
-
- // if there's a secondary y-axis, draw a vertical line for that, too.
- if (g.numAxes() == 2) {
- context.strokeStyle = g.getOptionForAxis('axisLineColor', 'y2');
- context.lineWidth = g.getOptionForAxis('axisLineWidth', 'y2');
- context.beginPath();
- context.moveTo(halfDown(area.x + area.w), halfDown(area.y));
- context.lineTo(halfDown(area.x + area.w), halfDown(area.y + area.h));
- context.closePath();
- context.stroke();
- }
- }
-
- if (g.getOptionForAxis('drawAxis', 'x')) {
- if (layout.xticks) {
- var getAxisOption = makeOptionGetter('x');
- for (i = 0; i < layout.xticks.length; i++) {
- tick = layout.xticks[i];
- x = area.x + tick[0] * area.w;
- y = area.y + area.h;
-
- /* Tick marks are currently clipped, so don't bother drawing them.
- context.beginPath();
- context.moveTo(halfUp(x), halfDown(y));
- context.lineTo(halfUp(x), halfDown(y + this.attr_('axisTickSize')));
- context.closePath();
- context.stroke();
- */
-
- label = makeDiv(tick[1], 'x');
- label.style.textAlign = 'center';
- label.style.top = (y + getAxisOption('axisTickSize')) + 'px';
-
- var left = (x - getAxisOption('axisLabelWidth')/2);
- if (left + getAxisOption('axisLabelWidth') > canvasWidth) {
- left = canvasWidth - getAxisOption('axisLabelWidth');
- label.style.textAlign = 'right';
- }
- if (left < 0) {
- left = 0;
- label.style.textAlign = 'left';
- }
-
- label.style.left = left + 'px';
- label.style.width = getAxisOption('axisLabelWidth') + 'px';
- containerDiv.appendChild(label);
- this.xlabels_.push(label);
- }
- }
-
- context.strokeStyle = g.getOptionForAxis('axisLineColor', 'x');
- context.lineWidth = g.getOptionForAxis('axisLineWidth', 'x');
- context.beginPath();
- var axisY;
- if (g.getOption('drawAxesAtZero')) {
- var r = g.toPercentYCoord(0, 0);
- if (r > 1 || r < 0) r = 1;
- axisY = halfDown(area.y + r * area.h);
- } else {
- axisY = halfDown(area.y + area.h);
- }
- context.moveTo(halfUp(area.x), axisY);
- context.lineTo(halfUp(area.x + area.w), axisY);
- context.closePath();
- context.stroke();
- }
-
- context.restore();
-};
-
-return axes;
-})();
-/**
- * @license
- * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-/*global Dygraph:false */
-
-Dygraph.Plugins.ChartLabels = (function() {
-
-"use strict";
-
-// TODO(danvk): move chart label options out of dygraphs and into the plugin.
-// TODO(danvk): only tear down & rebuild the DIVs when it's necessary.
-
-var chart_labels = function() {
- this.title_div_ = null;
- this.xlabel_div_ = null;
- this.ylabel_div_ = null;
- this.y2label_div_ = null;
-};
-
-chart_labels.prototype.toString = function() {
- return "ChartLabels Plugin";
-};
-
-chart_labels.prototype.activate = function(g) {
- return {
- layout: this.layout,
- // clearChart: this.clearChart,
- didDrawChart: this.didDrawChart
- };
-};
-
-// QUESTION: should there be a plugin-utils.js?
-var createDivInRect = function(r) {
- var div = document.createElement('div');
- div.style.position = 'absolute';
- div.style.left = r.x + 'px';
- div.style.top = r.y + 'px';
- div.style.width = r.w + 'px';
- div.style.height = r.h + 'px';
- return div;
-};
-
-// Detach and null out any existing nodes.
-chart_labels.prototype.detachLabels_ = function() {
- var els = [ this.title_div_,
- this.xlabel_div_,
- this.ylabel_div_,
- this.y2label_div_ ];
- for (var i = 0; i < els.length; i++) {
- var el = els[i];
- if (!el) continue;
- if (el.parentNode) el.parentNode.removeChild(el);
- }
-
- this.title_div_ = null;
- this.xlabel_div_ = null;
- this.ylabel_div_ = null;
- this.y2label_div_ = null;
-};
-
-var createRotatedDiv = function(g, box, axis, classes, html) {
- // TODO(danvk): is this outer div actually necessary?
- var div = document.createElement("div");
- div.style.position = 'absolute';
- if (axis == 1) {
- // NOTE: this is cheating. Should be positioned relative to the box.
- div.style.left = '0px';
- } else {
- div.style.left = box.x + 'px';
- }
- div.style.top = box.y + 'px';
- div.style.width = box.w + 'px';
- div.style.height = box.h + 'px';
- div.style.fontSize = (g.getOption('yLabelWidth') - 2) + 'px';
-
- var inner_div = document.createElement("div");
- inner_div.style.position = 'absolute';
- inner_div.style.width = box.h + 'px';
- inner_div.style.height = box.w + 'px';
- inner_div.style.top = (box.h / 2 - box.w / 2) + 'px';
- inner_div.style.left = (box.w / 2 - box.h / 2) + 'px';
- inner_div.style.textAlign = 'center';
-
- // CSS rotation is an HTML5 feature which is not standardized. Hence every
- // browser has its own name for the CSS style.
- var val = 'rotate(' + (axis == 1 ? '-' : '') + '90deg)';
- inner_div.style.transform = val; // HTML5
- inner_div.style.WebkitTransform = val; // Safari/Chrome
- inner_div.style.MozTransform = val; // Firefox
- inner_div.style.OTransform = val; // Opera
- inner_div.style.msTransform = val; // IE9
-
- if (typeof(document.documentMode) !== 'undefined' &&
- document.documentMode < 9) {
- // We're dealing w/ an old version of IE, so we have to rotate the text
- // using a BasicImage transform. This uses a different origin of rotation
- // than HTML5 rotation (top left of div vs. its center).
- inner_div.style.filter =
- 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' +
- (axis == 1 ? '3' : '1') + ')';
- inner_div.style.left = '0px';
- inner_div.style.top = '0px';
- }
-
- var class_div = document.createElement("div");
- class_div.className = classes;
- class_div.innerHTML = html;
-
- inner_div.appendChild(class_div);
- div.appendChild(inner_div);
- return div;
-};
-
-chart_labels.prototype.layout = function(e) {
- this.detachLabels_();
-
- var g = e.dygraph;
- var div = e.chart_div;
- if (g.getOption('title')) {
- // QUESTION: should this return an absolutely-positioned div instead?
- var title_rect = e.reserveSpaceTop(g.getOption('titleHeight'));
- this.title_div_ = createDivInRect(title_rect);
- this.title_div_.style.textAlign = 'center';
- this.title_div_.style.fontSize = (g.getOption('titleHeight') - 8) + 'px';
- this.title_div_.style.fontWeight = 'bold';
- this.title_div_.style.zIndex = 10;
-
- var class_div = document.createElement("div");
- class_div.className = 'dygraph-label dygraph-title';
- class_div.innerHTML = g.getOption('title');
- this.title_div_.appendChild(class_div);
- div.appendChild(this.title_div_);
- }
-
- if (g.getOption('xlabel')) {
- var x_rect = e.reserveSpaceBottom(g.getOption('xLabelHeight'));
- this.xlabel_div_ = createDivInRect(x_rect);
- this.xlabel_div_.style.textAlign = 'center';
- this.xlabel_div_.style.fontSize = (g.getOption('xLabelHeight') - 2) + 'px';
-
- var class_div = document.createElement("div");
- class_div.className = 'dygraph-label dygraph-xlabel';
- class_div.innerHTML = g.getOption('xlabel');
- this.xlabel_div_.appendChild(class_div);
- div.appendChild(this.xlabel_div_);
- }
-
- if (g.getOption('ylabel')) {
- // It would make sense to shift the chart here to make room for the y-axis
- // label, but the default yAxisLabelWidth is large enough that this results
- // in overly-padded charts. The y-axis label should fit fine. If it
- // doesn't, the yAxisLabelWidth option can be increased.
- var y_rect = e.reserveSpaceLeft(0);
-
- this.ylabel_div_ = createRotatedDiv(
- g, y_rect,
- 1, // primary (left) y-axis
- 'dygraph-label dygraph-ylabel',
- g.getOption('ylabel'));
- div.appendChild(this.ylabel_div_);
- }
-
- if (g.getOption('y2label') && g.numAxes() == 2) {
- // same logic applies here as for ylabel.
- var y2_rect = e.reserveSpaceRight(0);
- this.y2label_div_ = createRotatedDiv(
- g, y2_rect,
- 2, // secondary (right) y-axis
- 'dygraph-label dygraph-y2label',
- g.getOption('y2label'));
- div.appendChild(this.y2label_div_);
- }
-};
-
-chart_labels.prototype.didDrawChart = function(e) {
- var g = e.dygraph;
- if (this.title_div_) {
- this.title_div_.children[0].innerHTML = g.getOption('title');
- }
- if (this.xlabel_div_) {
- this.xlabel_div_.children[0].innerHTML = g.getOption('xlabel');
- }
- if (this.ylabel_div_) {
- this.ylabel_div_.children[0].children[0].innerHTML = g.getOption('ylabel');
- }
- if (this.y2label_div_) {
- this.y2label_div_.children[0].children[0].innerHTML = g.getOption('y2label');
- }
-};
-
-chart_labels.prototype.clearChart = function() {
-};
-
-chart_labels.prototype.destroy = function() {
- this.detachLabels_();
-};
-
-
-return chart_labels;
-})();
-/**
- * @license
- * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-/*global Dygraph:false */
-
-Dygraph.Plugins.Grid = (function() {
-
-/*
-
-Current bits of jankiness:
-- Direct layout access
-- Direct area access
-
-*/
-
-"use strict";
-
-
-/**
- * Draws the gridlines, i.e. the gray horizontal & vertical lines running the
- * length of the chart.
- *
- * @constructor
- */
-var grid = function() {
-};
-
-grid.prototype.toString = function() {
- return "Gridline Plugin";
-};
-
-grid.prototype.activate = function(g) {
- return {
- willDrawChart: this.willDrawChart
- };
-};
-
-grid.prototype.willDrawChart = function(e) {
- // Draw the new X/Y grid. Lines appear crisper when pixels are rounded to
- // half-integers. This prevents them from drawing in two rows/cols.
- var g = e.dygraph;
- var ctx = e.drawingContext;
- var layout = g.layout_;
- var area = e.dygraph.plotter_.area;
-
- function halfUp(x) { return Math.round(x) + 0.5; }
- function halfDown(y){ return Math.round(y) - 0.5; }
-
- var x, y, i, ticks;
- if (g.getOptionForAxis('drawGrid', 'y')) {
- var axes = ["y", "y2"];
- var strokeStyles = [], lineWidths = [], drawGrid = [], stroking = [], strokePattern = [];
- for (var i = 0; i < axes.length; i++) {
- drawGrid[i] = g.getOptionForAxis('drawGrid', axes[i]);
- if (drawGrid[i]) {
- strokeStyles[i] = g.getOptionForAxis('gridLineColor', axes[i]);
- lineWidths[i] = g.getOptionForAxis('gridLineWidth', axes[i]);
- strokePattern[i] = g.getOptionForAxis('gridLinePattern', axes[i]);
- stroking[i] = strokePattern[i] && (strokePattern[i].length >= 2);
- }
- }
- ticks = layout.yticks;
- ctx.save();
- // draw grids for the different y axes
- for (i = 0; i < ticks.length; i++) {
- var axis = ticks[i][0];
- if(drawGrid[axis]) {
- if (stroking[axis]) {
- ctx.installPattern(strokePattern[axis]);
- }
- ctx.strokeStyle = strokeStyles[axis];
- ctx.lineWidth = lineWidths[axis];
-
- x = halfUp(area.x);
- y = halfDown(area.y + ticks[i][1] * area.h);
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(x + area.w, y);
- ctx.closePath();
- ctx.stroke();
-
- if (stroking[axis]) {
- ctx.uninstallPattern();
- }
- }
- }
- ctx.restore();
- }
-
- // draw grid for x axis
- if (g.getOptionForAxis('drawGrid', 'x')) {
- ticks = layout.xticks;
- ctx.save();
- var strokePattern = g.getOptionForAxis('gridLinePattern', 'x');
- var stroking = strokePattern && (strokePattern.length >= 2);
- if (stroking) {
- ctx.installPattern(strokePattern);
- }
- ctx.strokeStyle = g.getOptionForAxis('gridLineColor', 'x');
- ctx.lineWidth = g.getOptionForAxis('gridLineWidth', 'x');
- for (i = 0; i < ticks.length; i++) {
- x = halfUp(area.x + ticks[i][0] * area.w);
- y = halfDown(area.y + area.h);
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.lineTo(x, area.y);
- ctx.closePath();
- ctx.stroke();
- }
- if (stroking) {
- ctx.uninstallPattern();
- }
- ctx.restore();
- }
-};
-
-grid.prototype.destroy = function() {
-};
-
-return grid;
-
-})();
-/**
- * @license
- * Copyright 2012 Dan Vanderkam (danvdk@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-/*global Dygraph:false */
-
-Dygraph.Plugins.Legend = (function() {
-/*
-Current bits of jankiness:
-- Uses two private APIs:
- 1. Dygraph.optionsViewForAxis_
- 2. dygraph.plotter_.area
-- Registers for a "predraw" event, which should be renamed.
-- I call calculateEmWidthInDiv more often than needed.
-*/
-
-/*global Dygraph:false */
-"use strict";
-
-
-/**
- * Creates the legend, which appears when the user hovers over the chart.
- * The legend can be either a user-specified or generated div.
- *
- * @constructor
- */
-var legend = function() {
- this.legend_div_ = null;
- this.is_generated_div_ = false; // do we own this div, or was it user-specified?
-};
-
-legend.prototype.toString = function() {
- return "Legend Plugin";
-};
-
-// (defined below)
-var generateLegendDashHTML;
-
-/**
- * This is called during the dygraph constructor, after options have been set
- * but before the data is available.
- *
- * Proper tasks to do here include:
- * - Reading your own options
- * - DOM manipulation
- * - Registering event listeners
- *
- * @param {Dygraph} g Graph instance.
- * @return {object.<string, function(ev)>} Mapping of event names to callbacks.
- */
-legend.prototype.activate = function(g) {
- var div;
- var divWidth = g.getOption('labelsDivWidth');
-
- var userLabelsDiv = g.getOption('labelsDiv');
- if (userLabelsDiv && null !== userLabelsDiv) {
- if (typeof(userLabelsDiv) == "string" || userLabelsDiv instanceof String) {
- div = document.getElementById(userLabelsDiv);
- } else {
- div = userLabelsDiv;
- }
- } else {
- // Default legend styles. These can be overridden in CSS by adding
- // "!important" after your rule, e.g. "left: 30px !important;"
- var messagestyle = {
- "position": "absolute",
- "fontSize": "14px",
- "zIndex": 10,
- "width": divWidth + "px",
- "top": "0px",
- "left": (g.size().width - divWidth - 2) + "px",
- "background": "white",
- "lineHeight": "normal",
- "textAlign": "left",
- "overflow": "hidden"};
-
- // TODO(danvk): get rid of labelsDivStyles? CSS is better.
- Dygraph.update(messagestyle, g.getOption('labelsDivStyles'));
- div = document.createElement("div");
- div.className = "dygraph-legend";
- for (var name in messagestyle) {
- if (!messagestyle.hasOwnProperty(name)) continue;
-
- try {
- div.style[name] = messagestyle[name];
- } catch (e) {
- console.warn("You are using unsupported css properties for your " +
- "browser in labelsDivStyles");
- }
- }
-
- // TODO(danvk): come up with a cleaner way to expose this.
- g.graphDiv.appendChild(div);
- this.is_generated_div_ = true;
- }
-
- this.legend_div_ = div;
- this.one_em_width_ = 10; // just a guess, will be updated.
-
- return {
- select: this.select,
- deselect: this.deselect,
- // TODO(danvk): rethink the name "predraw" before we commit to it in any API.
- predraw: this.predraw,
- didDrawChart: this.didDrawChart
- };
-};
-
-// Needed for dashed lines.
-var calculateEmWidthInDiv = function(div) {
- var sizeSpan = document.createElement('span');
- sizeSpan.setAttribute('style', 'margin: 0; padding: 0 0 0 1em; border: 0;');
- div.appendChild(sizeSpan);
- var oneEmWidth=sizeSpan.offsetWidth;
- div.removeChild(sizeSpan);
- return oneEmWidth;
-};
-
-var escapeHTML = function(str) {
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-};
-
-legend.prototype.select = function(e) {
- var xValue = e.selectedX;
- var points = e.selectedPoints;
-
- var legendMode = e.dygraph.getOption('legend');
- if (legendMode === 'never') {
- this.legend_div_.style.display = 'none';
- return;
- }
-
- if (legendMode === 'follow') {
- // create floating legend div
- var area = e.dygraph.plotter_.area;
- var labelsDivWidth = e.dygraph.getOption('labelsDivWidth');
- var yAxisLabelWidth = e.dygraph.getOptionForAxis('axisLabelWidth', 'y');
- // determine floating [left, top] coordinates of the legend div
- // within the plotter_ area
- // offset 20 px to the right and down from the first selection point
- // 20 px is guess based on mouse cursor size
- var leftLegend = points[0].x * area.w + 20;
- var topLegend = points[0].y * area.h - 20;
-
- // if legend floats to end of the window area, it flips to the other
- // side of the selection point
- if ((leftLegend + labelsDivWidth + 1) > (window.scrollX + window.innerWidth)) {
- leftLegend = leftLegend - 2 * 20 - labelsDivWidth - (yAxisLabelWidth - area.x);
- }
-
- e.dygraph.graphDiv.appendChild(this.legend_div_);
- this.legend_div_.style.left = yAxisLabelWidth + leftLegend + "px";
- this.legend_div_.style.top = topLegend + "px";
- }
-
- var html = legend.generateLegendHTML(e.dygraph, xValue, points, this.one_em_width_);
- this.legend_div_.innerHTML = html;
- this.legend_div_.style.display = '';
-};
-
-legend.prototype.deselect = function(e) {
- var legendMode = e.dygraph.getOption('legend');
- if (legendMode !== 'always') {
- this.legend_div_.style.display = "none";
- }
-
- // Have to do this every time, since styles might have changed.
- var oneEmWidth = calculateEmWidthInDiv(this.legend_div_);
- this.one_em_width_ = oneEmWidth;
-
- var html = legend.generateLegendHTML(e.dygraph, undefined, undefined, oneEmWidth);
- this.legend_div_.innerHTML = html;
-};
-
-legend.prototype.didDrawChart = function(e) {
- this.deselect(e);
-};
-
-// Right edge should be flush with the right edge of the charting area (which
-// may not be the same as the right edge of the div, if we have two y-axes.
-// TODO(danvk): is any of this really necessary? Could just set "right" in "activate".
-/**
- * Position the labels div so that:
- * - its right edge is flush with the right edge of the charting area
- * - its top edge is flush with the top edge of the charting area
- * @private
- */
-legend.prototype.predraw = function(e) {
- // Don't touch a user-specified labelsDiv.
- if (!this.is_generated_div_) return;
-
- // TODO(danvk): only use real APIs for this.
- e.dygraph.graphDiv.appendChild(this.legend_div_);
- var area = e.dygraph.plotter_.area;
- var labelsDivWidth = e.dygraph.getOption("labelsDivWidth");
- this.legend_div_.style.left = area.x + area.w - labelsDivWidth - 1 + "px";
- this.legend_div_.style.top = area.y + "px";
- this.legend_div_.style.width = labelsDivWidth + "px";
-};
-
-/**
- * Called when dygraph.destroy() is called.
- * You should null out any references and detach any DOM elements.
- */
-legend.prototype.destroy = function() {
- this.legend_div_ = null;
-};
-
-/**
- * @private
- * Generates HTML for the legend which is displayed when hovering over the
- * chart. If no selected points are specified, a default legend is returned
- * (this may just be the empty string).
- * @param { Number } [x] The x-value of the selected points.
- * @param { [Object] } [sel_points] List of selected points for the given
- * x-value. Should have properties like 'name', 'yval' and 'canvasy'.
- * @param { Number } [oneEmWidth] The pixel width for 1em in the legend. Only
- * relevant when displaying a legend with no selection (i.e. {legend:
- * 'always'}) and with dashed lines.
- */
-legend.generateLegendHTML = function(g, x, sel_points, oneEmWidth) {
- // TODO(danvk): deprecate this option in place of {legend: 'never'}
- if (g.getOption('showLabelsOnHighlight') !== true) return '';
-
- // If no points are selected, we display a default legend. Traditionally,
- // this has been blank. But a better default would be a conventional legend,
- // which provides essential information for a non-interactive chart.
- var html, sepLines, i, dash, strokePattern;
- var labels = g.getLabels();
-
- if (typeof(x) === 'undefined') {
- if (g.getOption('legend') != 'always') {
- return '';
- }
-
- sepLines = g.getOption('labelsSeparateLines');
- html = '';
- for (i = 1; i < labels.length; i++) {
- var series = g.getPropertiesForSeries(labels[i]);
- if (!series.visible) continue;
-
- if (html !== '') html += (sepLines ? '<br/>' : ' ');
- strokePattern = g.getOption("strokePattern", labels[i]);
- dash = generateLegendDashHTML(strokePattern, series.color, oneEmWidth);
- html += "<span style='font-weight: bold; color: " + series.color + ";'>" +
- dash + " " + escapeHTML(labels[i]) + "</span>";
- }
- return html;
- }
-
- // TODO(danvk): remove this use of a private API
- var xOptView = g.optionsViewForAxis_('x');
- var xvf = xOptView('valueFormatter');
- html = xvf(x, xOptView, labels[0], g);
- if (html !== '') {
- html += ':';
- }
-
- var yOptViews = [];
- var num_axes = g.numAxes();
- for (i = 0; i < num_axes; i++) {
- // TODO(danvk): remove this use of a private API
- yOptViews[i] = g.optionsViewForAxis_('y' + (i ? 1 + i : ''));
- }
- var showZeros = g.getOption("labelsShowZeroValues");
- sepLines = g.getOption("labelsSeparateLines");
- var highlightSeries = g.getHighlightSeries();
- for (i = 0; i < sel_points.length; i++) {
- var pt = sel_points[i];
- if (pt.yval === 0 && !showZeros) continue;
- if (!Dygraph.isOK(pt.canvasy)) continue;
- if (sepLines) html += "<br/>";
-
- var series = g.getPropertiesForSeries(pt.name);
- var yOptView = yOptViews[series.axis - 1];
- var fmtFunc = yOptView('valueFormatter');
- var yval = fmtFunc(pt.yval, yOptView, pt.name, g);
-
- var cls = (pt.name == highlightSeries) ? " class='highlight'" : "";
-
- // TODO(danvk): use a template string here and make it an attribute.
- html += "<span" + cls + ">" + " <b><span style='color: " + series.color + ";'>" +
- escapeHTML(pt.name) + "</span></b>:&#160;" + yval + "</span>";
- }
- return html;
-};
-
-
-/**
- * Generates html for the "dash" displayed on the legend when using "legend: always".
- * In particular, this works for dashed lines with any stroke pattern. It will
- * try to scale the pattern to fit in 1em width. Or if small enough repeat the
- * pattern for 1em width.
- *
- * @param strokePattern The pattern
- * @param color The color of the series.
- * @param oneEmWidth The width in pixels of 1em in the legend.
- * @private
- */
-generateLegendDashHTML = function(strokePattern, color, oneEmWidth) {
- // IE 7,8 fail at these divs, so they get boring legend, have not tested 9.
- var isIE = (/MSIE/.test(navigator.userAgent) && !window.opera);
- if (isIE) return "&mdash;";
-
- // Easy, common case: a solid line
- if (!strokePattern || strokePattern.length <= 1) {
- return "<div style=\"display: inline-block; position: relative; " +
- "bottom: .5ex; padding-left: 1em; height: 1px; " +
- "border-bottom: 2px solid " + color + ";\"></div>";
- }
-
- var i, j, paddingLeft, marginRight;
- var strokePixelLength = 0, segmentLoop = 0;
- var normalizedPattern = [];
- var loop;
-
- // Compute the length of the pixels including the first segment twice,
- // since we repeat it.
- for (i = 0; i <= strokePattern.length; i++) {
- strokePixelLength += strokePattern[i%strokePattern.length];
- }
-
- // See if we can loop the pattern by itself at least twice.
- loop = Math.floor(oneEmWidth/(strokePixelLength-strokePattern[0]));
- if (loop > 1) {
- // This pattern fits at least two times, no scaling just convert to em;
- for (i = 0; i < strokePattern.length; i++) {
- normalizedPattern[i] = strokePattern[i]/oneEmWidth;
- }
- // Since we are repeating the pattern, we don't worry about repeating the
- // first segment in one draw.
- segmentLoop = normalizedPattern.length;
- } else {
- // If the pattern doesn't fit in the legend we scale it to fit.
- loop = 1;
- for (i = 0; i < strokePattern.length; i++) {
- normalizedPattern[i] = strokePattern[i]/strokePixelLength;
- }
- // For the scaled patterns we do redraw the first segment.
- segmentLoop = normalizedPattern.length+1;
- }
-
- // Now make the pattern.
- var dash = "";
- for (j = 0; j < loop; j++) {
- for (i = 0; i < segmentLoop; i+=2) {
- // The padding is the drawn segment.
- paddingLeft = normalizedPattern[i%normalizedPattern.length];
- if (i < strokePattern.length) {
- // The margin is the space segment.
- marginRight = normalizedPattern[(i+1)%normalizedPattern.length];
- } else {
- // The repeated first segment has no right margin.
- marginRight = 0;
- }
- dash += "<div style=\"display: inline-block; position: relative; " +
- "bottom: .5ex; margin-right: " + marginRight + "em; padding-left: " +
- paddingLeft + "em; height: 1px; border-bottom: 2px solid " + color +
- ";\"></div>";
- }
- }
- return dash;
-};
-
-
-return legend;
-})();
-/**
- * @license
- * Copyright 2011 Paul Felix (paul.eric.felix@gmail.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-/*global Dygraph:false,TouchEvent:false */
-
-/**
- * @fileoverview This file contains the RangeSelector plugin used to provide
- * a timeline range selector widget for dygraphs.
- */
-
-Dygraph.Plugins.RangeSelector = (function() {
-
-/*global Dygraph:false */
-"use strict";
-
-var rangeSelector = function() {
- this.isIE_ = /MSIE/.test(navigator.userAgent) && !window.opera;
- this.hasTouchInterface_ = typeof(TouchEvent) != 'undefined';
- this.isMobileDevice_ = /mobile|android/gi.test(navigator.appVersion);
- this.interfaceCreated_ = false;
-};
-
-rangeSelector.prototype.toString = function() {
- return "RangeSelector Plugin";
-};
-
-rangeSelector.prototype.activate = function(dygraph) {
- this.dygraph_ = dygraph;
- this.isUsingExcanvas_ = dygraph.isUsingExcanvas_;
- if (this.getOption_('showRangeSelector')) {
- this.createInterface_();
- }
- return {
- layout: this.reserveSpace_,
- predraw: this.renderStaticLayer_,
- didDrawChart: this.renderInteractiveLayer_
- };
-};
-
-rangeSelector.prototype.destroy = function() {
- this.bgcanvas_ = null;
- this.fgcanvas_ = null;
- this.leftZoomHandle_ = null;
- this.rightZoomHandle_ = null;
- this.iePanOverlay_ = null;
-};
-
-//------------------------------------------------------------------
-// Private methods
-//------------------------------------------------------------------
-
-rangeSelector.prototype.getOption_ = function(name, opt_series) {
- return this.dygraph_.getOption(name, opt_series);
-};
-
-rangeSelector.prototype.setDefaultOption_ = function(name, value) {
- this.dygraph_.attrs_[name] = value;
-};
-
-/**
- * @private
- * Creates the range selector elements and adds them to the graph.
- */
-rangeSelector.prototype.createInterface_ = function() {
- this.createCanvases_();
- if (this.isUsingExcanvas_) {
- this.createIEPanOverlay_();
- }
- this.createZoomHandles_();
- this.initInteraction_();
-
- // Range selector and animatedZooms have a bad interaction. See issue 359.
- if (this.getOption_('animatedZooms')) {
- console.warn('Animated zooms and range selector are not compatible; disabling animatedZooms.');
- this.dygraph_.updateOptions({animatedZooms: false}, true);
- }
-
- this.interfaceCreated_ = true;
- this.addToGraph_();
-};
-
-/**
- * @private
- * Adds the range selector to the graph.
- */
-rangeSelector.prototype.addToGraph_ = function() {
- var graphDiv = this.graphDiv_ = this.dygraph_.graphDiv;
- graphDiv.appendChild(this.bgcanvas_);
- graphDiv.appendChild(this.fgcanvas_);
- graphDiv.appendChild(this.leftZoomHandle_);
- graphDiv.appendChild(this.rightZoomHandle_);
-};
-
-/**
- * @private
- * Removes the range selector from the graph.
- */
-rangeSelector.prototype.removeFromGraph_ = function() {
- var graphDiv = this.graphDiv_;
- graphDiv.removeChild(this.bgcanvas_);
- graphDiv.removeChild(this.fgcanvas_);
- graphDiv.removeChild(this.leftZoomHandle_);
- graphDiv.removeChild(this.rightZoomHandle_);
- this.graphDiv_ = null;
-};
-
-/**
- * @private
- * Called by Layout to allow range selector to reserve its space.
- */
-rangeSelector.prototype.reserveSpace_ = function(e) {
- if (this.getOption_('showRangeSelector')) {
- e.reserveSpaceBottom(this.getOption_('rangeSelectorHeight') + 4);
- }
-};
-
-/**
- * @private
- * Renders the static portion of the range selector at the predraw stage.
- */
-rangeSelector.prototype.renderStaticLayer_ = function() {
- if (!this.updateVisibility_()) {
- return;
- }
- this.resize_();
- this.drawStaticLayer_();
-};
-
-/**
- * @private
- * Renders the interactive portion of the range selector after the chart has been drawn.
- */
-rangeSelector.prototype.renderInteractiveLayer_ = function() {
- if (!this.updateVisibility_() || this.isChangingRange_) {
- return;
- }
- this.placeZoomHandles_();
- this.drawInteractiveLayer_();
-};
-
-/**
- * @private
- * Check to see if the range selector is enabled/disabled and update visibility accordingly.
- */
-rangeSelector.prototype.updateVisibility_ = function() {
- var enabled = this.getOption_('showRangeSelector');
- if (enabled) {
- if (!this.interfaceCreated_) {
- this.createInterface_();
- } else if (!this.graphDiv_ || !this.graphDiv_.parentNode) {
- this.addToGraph_();
- }
- } else if (this.graphDiv_) {
- this.removeFromGraph_();
- var dygraph = this.dygraph_;
- setTimeout(function() { dygraph.width_ = 0; dygraph.resize(); }, 1);
- }
- return enabled;
-};
-
-/**
- * @private
- * Resizes the range selector.
- */
-rangeSelector.prototype.resize_ = function() {
- function setElementRect(canvas, context, rect) {
- var canvasScale = Dygraph.getContextPixelRatio(context);
-
- canvas.style.top = rect.y + 'px';
- canvas.style.left = rect.x + 'px';
- canvas.width = rect.w * canvasScale;
- canvas.height = rect.h * canvasScale;
- canvas.style.width = rect.w + 'px';
- canvas.style.height = rect.h + 'px';
-
- if(canvasScale != 1) {
- context.scale(canvasScale, canvasScale);
- }
- }
-
- var plotArea = this.dygraph_.layout_.getPlotArea();
-
- var xAxisLabelHeight = 0;
- if (this.dygraph_.getOptionForAxis('drawAxis', 'x')) {
- xAxisLabelHeight = this.getOption_('xAxisHeight') || (this.getOption_('axisLabelFontSize') + 2 * this.getOption_('axisTickSize'));
- }
- this.canvasRect_ = {
- x: plotArea.x,
- y: plotArea.y + plotArea.h + xAxisLabelHeight + 4,
- w: plotArea.w,
- h: this.getOption_('rangeSelectorHeight')
- };
-
- setElementRect(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_);
- setElementRect(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_);
-};
-
-/**
- * @private
- * Creates the background and foreground canvases.
- */
-rangeSelector.prototype.createCanvases_ = function() {
- this.bgcanvas_ = Dygraph.createCanvas();
- this.bgcanvas_.className = 'dygraph-rangesel-bgcanvas';
- this.bgcanvas_.style.position = 'absolute';
- this.bgcanvas_.style.zIndex = 9;
- this.bgcanvas_ctx_ = Dygraph.getContext(this.bgcanvas_);
-
- this.fgcanvas_ = Dygraph.createCanvas();
- this.fgcanvas_.className = 'dygraph-rangesel-fgcanvas';
- this.fgcanvas_.style.position = 'absolute';
- this.fgcanvas_.style.zIndex = 9;
- this.fgcanvas_.style.cursor = 'default';
- this.fgcanvas_ctx_ = Dygraph.getContext(this.fgcanvas_);
-};
-
-/**
- * @private
- * Creates overlay divs for IE/Excanvas so that mouse events are handled properly.
- */
-rangeSelector.prototype.createIEPanOverlay_ = function() {
- this.iePanOverlay_ = document.createElement("div");
- this.iePanOverlay_.style.position = 'absolute';
- this.iePanOverlay_.style.backgroundColor = 'white';
- this.iePanOverlay_.style.filter = 'alpha(opacity=0)';
- this.iePanOverlay_.style.display = 'none';
- this.iePanOverlay_.style.cursor = 'move';
- this.fgcanvas_.appendChild(this.iePanOverlay_);
-};
-
-/**
- * @private
- * Creates the zoom handle elements.
- */
-rangeSelector.prototype.createZoomHandles_ = function() {
- var img = new Image();
- img.className = 'dygraph-rangesel-zoomhandle';
- img.style.position = 'absolute';
- img.style.zIndex = 10;
- img.style.visibility = 'hidden'; // Initially hidden so they don't show up in the wrong place.
- img.style.cursor = 'col-resize';
-
- if (/MSIE 7/.test(navigator.userAgent)) { // IE7 doesn't support embedded src data.
- img.width = 7;
- img.height = 14;
- img.style.backgroundColor = 'white';
- img.style.border = '1px solid #333333'; // Just show box in IE7.
- } else {
- img.width = 9;
- img.height = 16;
- img.src = 'data:image/png;base64,' +
-'iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAYAAADESFVDAAAAAXNSR0IArs4c6QAAAAZiS0dEANAA' +
-'zwDP4Z7KegAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sHGw0cMqdt1UwAAAAZdEVYdENv' +
-'bW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAaElEQVQoz+3SsRFAQBCF4Z9WJM8KCDVwownl' +
-'6YXsTmCUsyKGkZzcl7zkz3YLkypgAnreFmDEpHkIwVOMfpdi9CEEN2nGpFdwD03yEqDtOgCaun7s' +
-'qSTDH32I1pQA2Pb9sZecAxc5r3IAb21d6878xsAAAAAASUVORK5CYII=';
- }
-
- if (this.isMobileDevice_) {
- img.width *= 2;
- img.height *= 2;
- }
-
- this.leftZoomHandle_ = img;
- this.rightZoomHandle_ = img.cloneNode(false);
-};
-
-/**
- * @private
- * Sets up the interaction for the range selector.
- */
-rangeSelector.prototype.initInteraction_ = function() {
- var self = this;
- var topElem = document;
- var clientXLast = 0;
- var handle = null;
- var isZooming = false;
- var isPanning = false;
- var dynamic = !this.isMobileDevice_ && !this.isUsingExcanvas_;
-
- // We cover iframes during mouse interactions. See comments in
- // dygraph-utils.js for more info on why this is a good idea.
- var tarp = new Dygraph.IFrameTarp();
-
- // functions, defined below. Defining them this way (rather than with
- // "function foo() {...}" makes JSHint happy.
- var toXDataWindow, onZoomStart, onZoom, onZoomEnd, doZoom, isMouseInPanZone,
- onPanStart, onPan, onPanEnd, doPan, onCanvasHover;
-
- // Touch event functions
- var onZoomHandleTouchEvent, onCanvasTouchEvent, addTouchEvents;
-
- toXDataWindow = function(zoomHandleStatus) {
- var xDataLimits = self.dygraph_.xAxisExtremes();
- var fact = (xDataLimits[1] - xDataLimits[0])/self.canvasRect_.w;
- var xDataMin = xDataLimits[0] + (zoomHandleStatus.leftHandlePos - self.canvasRect_.x)*fact;
- var xDataMax = xDataLimits[0] + (zoomHandleStatus.rightHandlePos - self.canvasRect_.x)*fact;
- return [xDataMin, xDataMax];
- };
-
- onZoomStart = function(e) {
- Dygraph.cancelEvent(e);
- isZooming = true;
- clientXLast = e.clientX;
- handle = e.target ? e.target : e.srcElement;
- if (e.type === 'mousedown' || e.type === 'dragstart') {
- // These events are removed manually.
- Dygraph.addEvent(topElem, 'mousemove', onZoom);
- Dygraph.addEvent(topElem, 'mouseup', onZoomEnd);
- }
- self.fgcanvas_.style.cursor = 'col-resize';
- tarp.cover();
- return true;
- };
-
- onZoom = function(e) {
- if (!isZooming) {
- return false;
- }
- Dygraph.cancelEvent(e);
-
- var delX = e.clientX - clientXLast;
- if (Math.abs(delX) < 4) {
- return true;
- }
- clientXLast = e.clientX;
-
- // Move handle.
- var zoomHandleStatus = self.getZoomHandleStatus_();
- var newPos;
- if (handle == self.leftZoomHandle_) {
- newPos = zoomHandleStatus.leftHandlePos + delX;
- newPos = Math.min(newPos, zoomHandleStatus.rightHandlePos - handle.width - 3);
- newPos = Math.max(newPos, self.canvasRect_.x);
- } else {
- newPos = zoomHandleStatus.rightHandlePos + delX;
- newPos = Math.min(newPos, self.canvasRect_.x + self.canvasRect_.w);
- newPos = Math.max(newPos, zoomHandleStatus.leftHandlePos + handle.width + 3);
- }
- var halfHandleWidth = handle.width/2;
- handle.style.left = (newPos - halfHandleWidth) + 'px';
- self.drawInteractiveLayer_();
-
- // Zoom on the fly (if not using excanvas).
- if (dynamic) {
- doZoom();
- }
- return true;
- };
-
- onZoomEnd = function(e) {
- if (!isZooming) {
- return false;
- }
- isZooming = false;
- tarp.uncover();
- Dygraph.removeEvent(topElem, 'mousemove', onZoom);
- Dygraph.removeEvent(topElem, 'mouseup', onZoomEnd);
- self.fgcanvas_.style.cursor = 'default';
-
- // If using excanvas, Zoom now.
- if (!dynamic) {
- doZoom();
- }
- return true;
- };
-
- doZoom = function() {
- try {
- var zoomHandleStatus = self.getZoomHandleStatus_();
- self.isChangingRange_ = true;
- if (!zoomHandleStatus.isZoomed) {
- self.dygraph_.resetZoom();
- } else {
- var xDataWindow = toXDataWindow(zoomHandleStatus);
- self.dygraph_.doZoomXDates_(xDataWindow[0], xDataWindow[1]);
- }
- } finally {
- self.isChangingRange_ = false;
- }
- };
-
- isMouseInPanZone = function(e) {
- if (self.isUsingExcanvas_) {
- return e.srcElement == self.iePanOverlay_;
- } else {
- var rect = self.leftZoomHandle_.getBoundingClientRect();
- var leftHandleClientX = rect.left + rect.width/2;
- rect = self.rightZoomHandle_.getBoundingClientRect();
- var rightHandleClientX = rect.left + rect.width/2;
- return (e.clientX > leftHandleClientX && e.clientX < rightHandleClientX);
- }
- };
-
- onPanStart = function(e) {
- if (!isPanning && isMouseInPanZone(e) && self.getZoomHandleStatus_().isZoomed) {
- Dygraph.cancelEvent(e);
- isPanning = true;
- clientXLast = e.clientX;
- if (e.type === 'mousedown') {
- // These events are removed manually.
- Dygraph.addEvent(topElem, 'mousemove', onPan);
- Dygraph.addEvent(topElem, 'mouseup', onPanEnd);
- }
- return true;
- }
- return false;
- };
-
- onPan = function(e) {
- if (!isPanning) {
- return false;
- }
- Dygraph.cancelEvent(e);
-
- var delX = e.clientX - clientXLast;
- if (Math.abs(delX) < 4) {
- return true;
- }
- clientXLast = e.clientX;
-
- // Move range view
- var zoomHandleStatus = self.getZoomHandleStatus_();
- var leftHandlePos = zoomHandleStatus.leftHandlePos;
- var rightHandlePos = zoomHandleStatus.rightHandlePos;
- var rangeSize = rightHandlePos - leftHandlePos;
- if (leftHandlePos + delX <= self.canvasRect_.x) {
- leftHandlePos = self.canvasRect_.x;
- rightHandlePos = leftHandlePos + rangeSize;
- } else if (rightHandlePos + delX >= self.canvasRect_.x + self.canvasRect_.w) {
- rightHandlePos = self.canvasRect_.x + self.canvasRect_.w;
- leftHandlePos = rightHandlePos - rangeSize;
- } else {
- leftHandlePos += delX;
- rightHandlePos += delX;
- }
- var halfHandleWidth = self.leftZoomHandle_.width/2;
- self.leftZoomHandle_.style.left = (leftHandlePos - halfHandleWidth) + 'px';
- self.rightZoomHandle_.style.left = (rightHandlePos - halfHandleWidth) + 'px';
- self.drawInteractiveLayer_();
-
- // Do pan on the fly (if not using excanvas).
- if (dynamic) {
- doPan();
- }
- return true;
- };
-
- onPanEnd = function(e) {
- if (!isPanning) {
- return false;
- }
- isPanning = false;
- Dygraph.removeEvent(topElem, 'mousemove', onPan);
- Dygraph.removeEvent(topElem, 'mouseup', onPanEnd);
- // If using excanvas, do pan now.
- if (!dynamic) {
- doPan();
- }
- return true;
- };
-
- doPan = function() {
- try {
- self.isChangingRange_ = true;
- self.dygraph_.dateWindow_ = toXDataWindow(self.getZoomHandleStatus_());
- self.dygraph_.drawGraph_(false);
- } finally {
- self.isChangingRange_ = false;
- }
- };
-
- onCanvasHover = function(e) {
- if (isZooming || isPanning) {
- return;
- }
- var cursor = isMouseInPanZone(e) ? 'move' : 'default';
- if (cursor != self.fgcanvas_.style.cursor) {
- self.fgcanvas_.style.cursor = cursor;
- }
- };
-
- onZoomHandleTouchEvent = function(e) {
- if (e.type == 'touchstart' && e.targetTouches.length == 1) {
- if (onZoomStart(e.targetTouches[0])) {
- Dygraph.cancelEvent(e);
- }
- } else if (e.type == 'touchmove' && e.targetTouches.length == 1) {
- if (onZoom(e.targetTouches[0])) {
- Dygraph.cancelEvent(e);
- }
- } else {
- onZoomEnd(e);
- }
- };
-
- onCanvasTouchEvent = function(e) {
- if (e.type == 'touchstart' && e.targetTouches.length == 1) {
- if (onPanStart(e.targetTouches[0])) {
- Dygraph.cancelEvent(e);
- }
- } else if (e.type == 'touchmove' && e.targetTouches.length == 1) {
- if (onPan(e.targetTouches[0])) {
- Dygraph.cancelEvent(e);
- }
- } else {
- onPanEnd(e);
- }
- };
-
- addTouchEvents = function(elem, fn) {
- var types = ['touchstart', 'touchend', 'touchmove', 'touchcancel'];
- for (var i = 0; i < types.length; i++) {
- self.dygraph_.addAndTrackEvent(elem, types[i], fn);
- }
- };
-
- this.setDefaultOption_('interactionModel', Dygraph.Interaction.dragIsPanInteractionModel);
- this.setDefaultOption_('panEdgeFraction', 0.0001);
-
- var dragStartEvent = window.opera ? 'mousedown' : 'dragstart';
- this.dygraph_.addAndTrackEvent(this.leftZoomHandle_, dragStartEvent, onZoomStart);
- this.dygraph_.addAndTrackEvent(this.rightZoomHandle_, dragStartEvent, onZoomStart);
-
- if (this.isUsingExcanvas_) {
- this.dygraph_.addAndTrackEvent(this.iePanOverlay_, 'mousedown', onPanStart);
- } else {
- this.dygraph_.addAndTrackEvent(this.fgcanvas_, 'mousedown', onPanStart);
- this.dygraph_.addAndTrackEvent(this.fgcanvas_, 'mousemove', onCanvasHover);
- }
-
- // Touch events
- if (this.hasTouchInterface_) {
- addTouchEvents(this.leftZoomHandle_, onZoomHandleTouchEvent);
- addTouchEvents(this.rightZoomHandle_, onZoomHandleTouchEvent);
- addTouchEvents(this.fgcanvas_, onCanvasTouchEvent);
- }
-};
-
-/**
- * @private
- * Draws the static layer in the background canvas.
- */
-rangeSelector.prototype.drawStaticLayer_ = function() {
- var ctx = this.bgcanvas_ctx_;
- ctx.clearRect(0, 0, this.canvasRect_.w, this.canvasRect_.h);
- try {
- this.drawMiniPlot_();
- } catch(ex) {
- console.warn(ex);
- }
-
- var margin = 0.5;
- this.bgcanvas_ctx_.lineWidth = 1;
- ctx.strokeStyle = 'gray';
- ctx.beginPath();
- ctx.moveTo(margin, margin);
- ctx.lineTo(margin, this.canvasRect_.h-margin);
- ctx.lineTo(this.canvasRect_.w-margin, this.canvasRect_.h-margin);
- ctx.lineTo(this.canvasRect_.w-margin, margin);
- ctx.stroke();
-};
-
-
-/**
- * @private
- * Draws the mini plot in the background canvas.
- */
-rangeSelector.prototype.drawMiniPlot_ = function() {
- var fillStyle = this.getOption_('rangeSelectorPlotFillColor');
- var strokeStyle = this.getOption_('rangeSelectorPlotStrokeColor');
- if (!fillStyle && !strokeStyle) {
- return;
- }
-
- var stepPlot = this.getOption_('stepPlot');
-
- var combinedSeriesData = this.computeCombinedSeriesAndLimits_();
- var yRange = combinedSeriesData.yMax - combinedSeriesData.yMin;
-
- // Draw the mini plot.
- var ctx = this.bgcanvas_ctx_;
- var margin = 0.5;
-
- var xExtremes = this.dygraph_.xAxisExtremes();
- var xRange = Math.max(xExtremes[1] - xExtremes[0], 1.e-30);
- var xFact = (this.canvasRect_.w - margin)/xRange;
- var yFact = (this.canvasRect_.h - margin)/yRange;
- var canvasWidth = this.canvasRect_.w - margin;
- var canvasHeight = this.canvasRect_.h - margin;
-
- var prevX = null, prevY = null;
-
- ctx.beginPath();
- ctx.moveTo(margin, canvasHeight);
- for (var i = 0; i < combinedSeriesData.data.length; i++) {
- var dataPoint = combinedSeriesData.data[i];
- var x = ((dataPoint[0] !== null) ? ((dataPoint[0] - xExtremes[0])*xFact) : NaN);
- var y = ((dataPoint[1] !== null) ? (canvasHeight - (dataPoint[1] - combinedSeriesData.yMin)*yFact) : NaN);
-
- // Skip points that don't change the x-value. Overly fine-grained points
- // can cause major slowdowns with the ctx.fill() call below.
- if (!stepPlot && prevX !== null && Math.round(x) == Math.round(prevX)) {
- continue;
- }
-
- if (isFinite(x) && isFinite(y)) {
- if(prevX === null) {
- ctx.lineTo(x, canvasHeight);
- }
- else if (stepPlot) {
- ctx.lineTo(x, prevY);
- }
- ctx.lineTo(x, y);
- prevX = x;
- prevY = y;
- }
- else {
- if(prevX !== null) {
- if (stepPlot) {
- ctx.lineTo(x, prevY);
- ctx.lineTo(x, canvasHeight);
- }
- else {
- ctx.lineTo(prevX, canvasHeight);
- }
- }
- prevX = prevY = null;
- }
- }
- ctx.lineTo(canvasWidth, canvasHeight);
- ctx.closePath();
-
- if (fillStyle) {
- var lingrad = this.bgcanvas_ctx_.createLinearGradient(0, 0, 0, canvasHeight);
- lingrad.addColorStop(0, 'white');
- lingrad.addColorStop(1, fillStyle);
- this.bgcanvas_ctx_.fillStyle = lingrad;
- ctx.fill();
- }
-
- if (strokeStyle) {
- this.bgcanvas_ctx_.strokeStyle = strokeStyle;
- this.bgcanvas_ctx_.lineWidth = 1.5;
- ctx.stroke();
- }
-};
-
-/**
- * @private
- * Computes and returns the combined series data along with min/max for the mini plot.
- * The combined series consists of averaged values for all series.
- * When series have error bars, the error bars are ignored.
- * @return {Object} An object containing combined series array, ymin, ymax.
- */
-rangeSelector.prototype.computeCombinedSeriesAndLimits_ = function() {
- var g = this.dygraph_;
- var logscale = this.getOption_('logscale');
- var i;
-
- // Select series to combine. By default, all series are combined.
- var numColumns = g.numColumns();
- var labels = g.getLabels();
- var includeSeries = new Array(numColumns);
- var anySet = false;
- for (i = 1; i < numColumns; i++) {
- var include = this.getOption_('showInRangeSelector', labels[i]);
- includeSeries[i] = include;
- if (include !== null) anySet = true; // it's set explicitly for this series
- }
- if (!anySet) {
- for (i = 0; i < includeSeries.length; i++) includeSeries[i] = true;
- }
-
- // Create a combined series (average of selected series values).
- // TODO(danvk): short-circuit if there's only one series.
- var rolledSeries = [];
- var dataHandler = g.dataHandler_;
- var options = g.attributes_;
- for (i = 1; i < g.numColumns(); i++) {
- if (!includeSeries[i]) continue;
- var series = dataHandler.extractSeries(g.rawData_, i, options);
- if (g.rollPeriod() > 1) {
- series = dataHandler.rollingAverage(series, g.rollPeriod(), options);
- }
-
- rolledSeries.push(series);
- }
-
- var combinedSeries = [];
- for (i = 0; i < rolledSeries[0].length; i++) {
- var sum = 0;
- var count = 0;
- for (var j = 0; j < rolledSeries.length; j++) {
- var y = rolledSeries[j][i][1];
- if (y === null || isNaN(y)) continue;
- count++;
- sum += y;
- }
- combinedSeries.push([rolledSeries[0][i][0], sum / count]);
- }
-
- // Compute the y range.
- var yMin = Number.MAX_VALUE;
- var yMax = -Number.MAX_VALUE;
- for (i = 0; i < combinedSeries.length; i++) {
- var yVal = combinedSeries[i][1];
- if (yVal !== null && isFinite(yVal) && (!logscale || yVal > 0)) {
- yMin = Math.min(yMin, yVal);
- yMax = Math.max(yMax, yVal);
- }
- }
-
- // Convert Y data to log scale if needed.
- // Also, expand the Y range to compress the mini plot a little.
- var extraPercent = 0.25;
- if (logscale) {
- yMax = Dygraph.log10(yMax);
- yMax += yMax*extraPercent;
- yMin = Dygraph.log10(yMin);
- for (i = 0; i < combinedSeries.length; i++) {
- combinedSeries[i][1] = Dygraph.log10(combinedSeries[i][1]);
- }
- } else {
- var yExtra;
- var yRange = yMax - yMin;
- if (yRange <= Number.MIN_VALUE) {
- yExtra = yMax*extraPercent;
- } else {
- yExtra = yRange*extraPercent;
- }
- yMax += yExtra;
- yMin -= yExtra;
- }
-
- return {data: combinedSeries, yMin: yMin, yMax: yMax};
-};
-
-/**
- * @private
- * Places the zoom handles in the proper position based on the current X data window.
- */
-rangeSelector.prototype.placeZoomHandles_ = function() {
- var xExtremes = this.dygraph_.xAxisExtremes();
- var xWindowLimits = this.dygraph_.xAxisRange();
- var xRange = xExtremes[1] - xExtremes[0];
- var leftPercent = Math.max(0, (xWindowLimits[0] - xExtremes[0])/xRange);
- var rightPercent = Math.max(0, (xExtremes[1] - xWindowLimits[1])/xRange);
- var leftCoord = this.canvasRect_.x + this.canvasRect_.w*leftPercent;
- var rightCoord = this.canvasRect_.x + this.canvasRect_.w*(1 - rightPercent);
- var handleTop = Math.max(this.canvasRect_.y, this.canvasRect_.y + (this.canvasRect_.h - this.leftZoomHandle_.height)/2);
- var halfHandleWidth = this.leftZoomHandle_.width/2;
- this.leftZoomHandle_.style.left = (leftCoord - halfHandleWidth) + 'px';
- this.leftZoomHandle_.style.top = handleTop + 'px';
- this.rightZoomHandle_.style.left = (rightCoord - halfHandleWidth) + 'px';
- this.rightZoomHandle_.style.top = this.leftZoomHandle_.style.top;
-
- this.leftZoomHandle_.style.visibility = 'visible';
- this.rightZoomHandle_.style.visibility = 'visible';
-};
-
-/**
- * @private
- * Draws the interactive layer in the foreground canvas.
- */
-rangeSelector.prototype.drawInteractiveLayer_ = function() {
- var ctx = this.fgcanvas_ctx_;
- ctx.clearRect(0, 0, this.canvasRect_.w, this.canvasRect_.h);
- var margin = 1;
- var width = this.canvasRect_.w - margin;
- var height = this.canvasRect_.h - margin;
- var zoomHandleStatus = this.getZoomHandleStatus_();
-
- ctx.strokeStyle = 'black';
- if (!zoomHandleStatus.isZoomed) {
- ctx.beginPath();
- ctx.moveTo(margin, margin);
- ctx.lineTo(margin, height);
- ctx.lineTo(width, height);
- ctx.lineTo(width, margin);
- ctx.stroke();
- if (this.iePanOverlay_) {
- this.iePanOverlay_.style.display = 'none';
- }
- } else {
- var leftHandleCanvasPos = Math.max(margin, zoomHandleStatus.leftHandlePos - this.canvasRect_.x);
- var rightHandleCanvasPos = Math.min(width, zoomHandleStatus.rightHandlePos - this.canvasRect_.x);
-
- ctx.fillStyle = 'rgba(240, 240, 240, 0.6)';
- ctx.fillRect(0, 0, leftHandleCanvasPos, this.canvasRect_.h);
- ctx.fillRect(rightHandleCanvasPos, 0, this.canvasRect_.w - rightHandleCanvasPos, this.canvasRect_.h);
-
- ctx.beginPath();
- ctx.moveTo(margin, margin);
- ctx.lineTo(leftHandleCanvasPos, margin);
- ctx.lineTo(leftHandleCanvasPos, height);
- ctx.lineTo(rightHandleCanvasPos, height);
- ctx.lineTo(rightHandleCanvasPos, margin);
- ctx.lineTo(width, margin);
- ctx.stroke();
-
- if (this.isUsingExcanvas_) {
- this.iePanOverlay_.style.width = (rightHandleCanvasPos - leftHandleCanvasPos) + 'px';
- this.iePanOverlay_.style.left = leftHandleCanvasPos + 'px';
- this.iePanOverlay_.style.height = height + 'px';
- this.iePanOverlay_.style.display = 'inline';
- }
- }
-};
-
-/**
- * @private
- * Returns the current zoom handle position information.
- * @return {Object} The zoom handle status.
- */
-rangeSelector.prototype.getZoomHandleStatus_ = function() {
- var halfHandleWidth = this.leftZoomHandle_.width/2;
- var leftHandlePos = parseFloat(this.leftZoomHandle_.style.left) + halfHandleWidth;
- var rightHandlePos = parseFloat(this.rightZoomHandle_.style.left) + halfHandleWidth;
- return {
- leftHandlePos: leftHandlePos,
- rightHandlePos: rightHandlePos,
- isZoomed: (leftHandlePos - 1 > this.canvasRect_.x || rightHandlePos + 1 < this.canvasRect_.x+this.canvasRect_.w)
- };
-};
-
-return rangeSelector;
-
-})();
-/*global Dygraph:false */
-
-// This file defines the ordering of the plugins.
-//
-// The ordering is from most-general to most-specific.
-// This means that, in an event cascade, plugins which have registered for that
-// event will be called in reverse order.
-//
-// This is most relevant for plugins which register a layout event, e.g.
-// Axes, Legend and ChartLabels.
-
-Dygraph.PLUGINS.push(
- Dygraph.Plugins.Legend,
- Dygraph.Plugins.Axes,
- Dygraph.Plugins.RangeSelector, // Has to be before ChartLabels so that its callbacks are called after ChartLabels' callbacks.
- Dygraph.Plugins.ChartLabels,
- Dygraph.Plugins.Annotations,
- Dygraph.Plugins.Grid
-);
-/**
- * @license
- * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview This file contains the managment of data handlers
- * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
- *
- * The idea is to define a common, generic data format that works for all data
- * structures supported by dygraphs. To make this possible, the DataHandler
- * interface is introduced. This makes it possible, that dygraph itself can work
- * with the same logic for every data type independent of the actual format and
- * the DataHandler takes care of the data format specific jobs.
- * DataHandlers are implemented for all data types supported by Dygraphs and
- * return Dygraphs compliant formats.
- * By default the correct DataHandler is chosen based on the options set.
- * Optionally the user may use his own DataHandler (similar to the plugin
- * system).
- *
- *
- * The unified data format returend by each handler is defined as so:
- * series[n][point] = [x,y,(extras)]
- *
- * This format contains the common basis that is needed to draw a simple line
- * series extended by optional extras for more complex graphing types. It
- * contains a primitive x value as first array entry, a primitive y value as
- * second array entry and an optional extras object for additional data needed.
- *
- * x must always be a number.
- * y must always be a number, NaN of type number or null.
- * extras is optional and must be interpreted by the DataHandler. It may be of
- * any type.
- *
- * In practice this might look something like this:
- * default: [x, yVal]
- * errorBar / customBar: [x, yVal, [yTopVariance, yBottomVariance] ]
- *
- */
-/*global Dygraph:false */
-/*global DygraphLayout:false */
-
-/**
- *
- * The data handler is responsible for all data specific operations. All of the
- * series data it receives and returns is always in the unified data format.
- * Initially the unified data is created by the extractSeries method
- * @constructor
- */
-Dygraph.DataHandler = function () {
-};
-
-/**
- * A collection of functions to create and retrieve data handlers.
- * @type {Object.<!Dygraph.DataHandler>}
- */
-Dygraph.DataHandlers = {};
-
-(function() {
-
-"use strict";
-
-var handler = Dygraph.DataHandler;
-
-/**
- * X-value array index constant for unified data samples.
- * @const
- * @type {number}
- */
-handler.X = 0;
-
-/**
- * Y-value array index constant for unified data samples.
- * @const
- * @type {number}
- */
-handler.Y = 1;
-
-/**
- * Extras-value array index constant for unified data samples.
- * @const
- * @type {number}
- */
-handler.EXTRAS = 2;
-
-/**
- * Extracts one series from the raw data (a 2D array) into an array of the
- * unified data format.
- * This is where undesirable points (i.e. negative values on log scales and
- * missing values through which we wish to connect lines) are dropped.
- * TODO(danvk): the "missing values" bit above doesn't seem right.
- *
- * @param {!Array.<Array>} rawData The raw data passed into dygraphs where
- * rawData[i] = [x,ySeries1,...,ySeriesN].
- * @param {!number} seriesIndex Index of the series to extract. All other
- * series should be ignored.
- * @param {!DygraphOptions} options Dygraph options.
- * @return {Array.<[!number,?number,?]>} The series in the unified data format
- * where series[i] = [x,y,{extras}].
- */
-handler.prototype.extractSeries = function(rawData, seriesIndex, options) {
-};
-
-/**
- * Converts a series to a Point array. The resulting point array must be
- * returned in increasing order of idx property.
- *
- * @param {!Array.<[!number,?number,?]>} series The series in the unified
- * data format where series[i] = [x,y,{extras}].
- * @param {!string} setName Name of the series.
- * @param {!number} boundaryIdStart Index offset of the first point, equal to the
- * number of skipped points left of the date window minimum (if any).
- * @return {!Array.<Dygraph.PointType>} List of points for this series.
- */
-handler.prototype.seriesToPoints = function(series, setName, boundaryIdStart) {
- // TODO(bhs): these loops are a hot-spot for high-point-count charts. In
- // fact,
- // on chrome+linux, they are 6 times more expensive than iterating through
- // the
- // points and drawing the lines. The brunt of the cost comes from allocating
- // the |point| structures.
- var points = [];
- for ( var i = 0; i < series.length; ++i) {
- var item = series[i];
- var yraw = item[1];
- var yval = yraw === null ? null : handler.parseFloat(yraw);
- var point = {
- x : NaN,
- y : NaN,
- xval : handler.parseFloat(item[0]),
- yval : yval,
- name : setName, // TODO(danvk): is this really necessary?
- idx : i + boundaryIdStart
- };
- points.push(point);
- }
- this.onPointsCreated_(series, points);
- return points;
-};
-
-/**
- * Callback called for each series after the series points have been generated
- * which will later be used by the plotters to draw the graph.
- * Here data may be added to the seriesPoints which is needed by the plotters.
- * The indexes of series and points are in sync meaning the original data
- * sample for series[i] is points[i].
- *
- * @param {!Array.<[!number,?number,?]>} series The series in the unified
- * data format where series[i] = [x,y,{extras}].
- * @param {!Array.<Dygraph.PointType>} points The corresponding points passed
- * to the plotter.
- * @protected
- */
-handler.prototype.onPointsCreated_ = function(series, points) {
-};
-
-/**
- * Calculates the rolling average of a data set.
- *
- * @param {!Array.<[!number,?number,?]>} series The series in the unified
- * data format where series[i] = [x,y,{extras}].
- * @param {!number} rollPeriod The number of points over which to average the data
- * @param {!DygraphOptions} options The dygraph options.
- * @return {!Array.<[!number,?number,?]>} the rolled series.
- */
-handler.prototype.rollingAverage = function(series, rollPeriod, options) {
-};
-
-/**
- * Computes the range of the data series (including confidence intervals).
- *
- * @param {!Array.<[!number,?number,?]>} series The series in the unified
- * data format where series[i] = [x, y, {extras}].
- * @param {!Array.<number>} dateWindow The x-value range to display with
- * the format: [min, max].
- * @param {!DygraphOptions} options The dygraph options.
- * @return {Array.<number>} The low and high extremes of the series in the
- * given window with the format: [low, high].
- */
-handler.prototype.getExtremeYValues = function(series, dateWindow, options) {
-};
-
-/**
- * Callback called for each series after the layouting data has been
- * calculated before the series is drawn. Here normalized positioning data
- * should be calculated for the extras of each point.
- *
- * @param {!Array.<Dygraph.PointType>} points The points passed to
- * the plotter.
- * @param {!Object} axis The axis on which the series will be plotted.
- * @param {!boolean} logscale Weather or not to use a logscale.
- */
-handler.prototype.onLineEvaluated = function(points, axis, logscale) {
-};
-
-/**
- * Helper method that computes the y value of a line defined by the points p1
- * and p2 and a given x value.
- *
- * @param {!Array.<number>} p1 left point ([x,y]).
- * @param {!Array.<number>} p2 right point ([x,y]).
- * @param {!number} xValue The x value to compute the y-intersection for.
- * @return {number} corresponding y value to x on the line defined by p1 and p2.
- * @private
- */
-handler.prototype.computeYInterpolation_ = function(p1, p2, xValue) {
- var deltaY = p2[1] - p1[1];
- var deltaX = p2[0] - p1[0];
- var gradient = deltaY / deltaX;
- var growth = (xValue - p1[0]) * gradient;
- return p1[1] + growth;
-};
-
-/**
- * Helper method that returns the first and the last index of the given series
- * that lie inside the given dateWindow.
- *
- * @param {!Array.<[!number,?number,?]>} series The series in the unified
- * data format where series[i] = [x,y,{extras}].
- * @param {!Array.<number>} dateWindow The x-value range to display with
- * the format: [min,max].
- * @return {!Array.<[!number,?number,?]>} The samples of the series that
- * are in the given date window.
- * @private
- */
-handler.prototype.getIndexesInWindow_ = function(series, dateWindow) {
- var firstIdx = 0, lastIdx = series.length - 1;
- if (dateWindow) {
- var idx = 0;
- var low = dateWindow[0];
- var high = dateWindow[1];
-
- // Start from each side of the array to minimize the performance
- // needed.
- while (idx < series.length - 1 && series[idx][0] < low) {
- firstIdx++;
- idx++;
- }
- idx = series.length - 1;
- while (idx > 0 && series[idx][0] > high) {
- lastIdx--;
- idx--;
- }
- }
- if (firstIdx <= lastIdx) {
- return [ firstIdx, lastIdx ];
- } else {
- return [ 0, series.length - 1 ];
- }
-};
-
-/**
- * Optimized replacement for parseFloat, which was way too slow when almost
- * all values were type number, with few edge cases, none of which were strings.
- * @param {?number} val
- * @return {number}
- * @protected
- */
-handler.parseFloat = function(val) {
- // parseFloat(null) is NaN
- if (val === null) {
- return NaN;
- }
-
- // Assume it's a number or NaN. If it's something else, I'll be shocked.
- return val;
-};
-
-})();
-/**
- * @license
- * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview DataHandler default implementation used for simple line charts.
- * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
- */
-
-(function() {
-
-/*global Dygraph:false */
-"use strict";
-
-/**
- * @constructor
- * @extends Dygraph.DataHandler
- */
-Dygraph.DataHandlers.DefaultHandler = function() {
-};
-
-var DefaultHandler = Dygraph.DataHandlers.DefaultHandler;
-DefaultHandler.prototype = new Dygraph.DataHandler();
-
-/** @inheritDoc */
-DefaultHandler.prototype.extractSeries = function(rawData, i, options) {
- // TODO(danvk): pre-allocate series here.
- var series = [];
- var logScale = options.get('logscale');
- for ( var j = 0; j < rawData.length; j++) {
- var x = rawData[j][0];
- var point = rawData[j][i];
- if (logScale) {
- // On the log scale, points less than zero do not exist.
- // This will create a gap in the chart.
- if (point <= 0) {
- point = null;
- }
- }
- series.push([ x, point ]);
- }
- return series;
-};
-
-/** @inheritDoc */
-DefaultHandler.prototype.rollingAverage = function(originalData, rollPeriod,
- options) {
- rollPeriod = Math.min(rollPeriod, originalData.length);
- var rollingData = [];
-
- var i, j, y, sum, num_ok;
- // Calculate the rolling average for the first rollPeriod - 1 points
- // where
- // there is not enough data to roll over the full number of points
- if (rollPeriod == 1) {
- return originalData;
- }
- for (i = 0; i < originalData.length; i++) {
- sum = 0;
- num_ok = 0;
- for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
- y = originalData[j][1];
- if (y === null || isNaN(y))
- continue;
- num_ok++;
- sum += originalData[j][1];
- }
- if (num_ok) {
- rollingData[i] = [ originalData[i][0], sum / num_ok ];
- } else {
- rollingData[i] = [ originalData[i][0], null ];
- }
- }
-
- return rollingData;
-};
-
-/** @inheritDoc */
-DefaultHandler.prototype.getExtremeYValues = function(series, dateWindow,
- options) {
- var minY = null, maxY = null, y;
- var firstIdx = 0, lastIdx = series.length - 1;
-
- for ( var j = firstIdx; j <= lastIdx; j++) {
- y = series[j][1];
- if (y === null || isNaN(y))
- continue;
- if (maxY === null || y > maxY) {
- maxY = y;
- }
- if (minY === null || y < minY) {
- minY = y;
- }
- }
- return [ minY, maxY ];
-};
-
-})();
-/**
- * @license
- * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview DataHandler implementation for the fractions option.
- * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
- */
-
-(function() {
-
-/*global Dygraph:false */
-"use strict";
-
-/**
- * @extends Dygraph.DataHandlers.DefaultHandler
- * @constructor
- */
-Dygraph.DataHandlers.DefaultFractionHandler = function() {
-};
-
-var DefaultFractionHandler = Dygraph.DataHandlers.DefaultFractionHandler;
-DefaultFractionHandler.prototype = new Dygraph.DataHandlers.DefaultHandler();
-
-DefaultFractionHandler.prototype.extractSeries = function(rawData, i, options) {
- // TODO(danvk): pre-allocate series here.
- var series = [];
- var x, y, point, num, den, value;
- var mult = 100.0;
- var logScale = options.get('logscale');
- for ( var j = 0; j < rawData.length; j++) {
- x = rawData[j][0];
- point = rawData[j][i];
- if (logScale && point !== null) {
- // On the log scale, points less than zero do not exist.
- // This will create a gap in the chart.
- if (point[0] <= 0 || point[1] <= 0) {
- point = null;
- }
- }
- // Extract to the unified data format.
- if (point !== null) {
- num = point[0];
- den = point[1];
- if (num !== null && !isNaN(num)) {
- value = den ? num / den : 0.0;
- y = mult * value;
- // preserve original values in extras for further filtering
- series.push([ x, y, [ num, den ] ]);
- } else {
- series.push([ x, num, [ num, den ] ]);
- }
- } else {
- series.push([ x, null, [ null, null ] ]);
- }
- }
- return series;
-};
-
-DefaultFractionHandler.prototype.rollingAverage = function(originalData, rollPeriod,
- options) {
- rollPeriod = Math.min(rollPeriod, originalData.length);
- var rollingData = [];
-
- var i;
- var num = 0;
- var den = 0; // numerator/denominator
- var mult = 100.0;
- for (i = 0; i < originalData.length; i++) {
- num += originalData[i][2][0];
- den += originalData[i][2][1];
- if (i - rollPeriod >= 0) {
- num -= originalData[i - rollPeriod][2][0];
- den -= originalData[i - rollPeriod][2][1];
- }
-
- var date = originalData[i][0];
- var value = den ? num / den : 0.0;
- rollingData[i] = [ date, mult * value ];
- }
-
- return rollingData;
-};
-
-})();
-/**
- * @license
- * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview DataHandler base implementation for the "bar"
- * data formats. This implementation must be extended and the
- * extractSeries and rollingAverage must be implemented.
- * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
- */
-
-(function() {
-
-/*global Dygraph:false */
-/*global DygraphLayout:false */
-"use strict";
-
-/**
- * @constructor
- * @extends {Dygraph.DataHandler}
- */
-Dygraph.DataHandlers.BarsHandler = function() {
- Dygraph.DataHandler.call(this);
-};
-Dygraph.DataHandlers.BarsHandler.prototype = new Dygraph.DataHandler();
-
-// alias for the rest of the implementation
-var BarsHandler = Dygraph.DataHandlers.BarsHandler;
-
-// TODO(danvk): figure out why the jsdoc has to be copy/pasted from superclass.
-// (I get closure compiler errors if this isn't here.)
-/**
- * @override
- * @param {!Array.<Array>} rawData The raw data passed into dygraphs where
- * rawData[i] = [x,ySeries1,...,ySeriesN].
- * @param {!number} seriesIndex Index of the series to extract. All other
- * series should be ignored.
- * @param {!DygraphOptions} options Dygraph options.
- * @return {Array.<[!number,?number,?]>} The series in the unified data format
- * where series[i] = [x,y,{extras}].
- */
-BarsHandler.prototype.extractSeries = function(rawData, seriesIndex, options) {
- // Not implemented here must be extended
-};
-
-/**
- * @override
- * @param {!Array.<[!number,?number,?]>} series The series in the unified
- * data format where series[i] = [x,y,{extras}].
- * @param {!number} rollPeriod The number of points over which to average the data
- * @param {!DygraphOptions} options The dygraph options.
- * TODO(danvk): be more specific than "Array" here.
- * @return {!Array.<[!number,?number,?]>} the rolled series.
- */
-BarsHandler.prototype.rollingAverage =
- function(series, rollPeriod, options) {
- // Not implemented here, must be extended.
-};
-
-/** @inheritDoc */
-BarsHandler.prototype.onPointsCreated_ = function(series, points) {
- for (var i = 0; i < series.length; ++i) {
- var item = series[i];
- var point = points[i];
- point.y_top = NaN;
- point.y_bottom = NaN;
- point.yval_minus = Dygraph.DataHandler.parseFloat(item[2][0]);
- point.yval_plus = Dygraph.DataHandler.parseFloat(item[2][1]);
- }
-};
-
-/** @inheritDoc */
-BarsHandler.prototype.getExtremeYValues = function(series, dateWindow, options) {
- var minY = null, maxY = null, y;
-
- var firstIdx = 0;
- var lastIdx = series.length - 1;
-
- for ( var j = firstIdx; j <= lastIdx; j++) {
- y = series[j][1];
- if (y === null || isNaN(y)) continue;
-
- var low = series[j][2][0];
- var high = series[j][2][1];
-
- if (low > y) low = y; // this can happen with custom bars,
- if (high < y) high = y; // e.g. in tests/custom-bars.html
-
- if (maxY === null || high > maxY) maxY = high;
- if (minY === null || low < minY) minY = low;
- }
-
- return [ minY, maxY ];
-};
-
-/** @inheritDoc */
-BarsHandler.prototype.onLineEvaluated = function(points, axis, logscale) {
- var point;
- for (var j = 0; j < points.length; j++) {
- // Copy over the error terms
- point = points[j];
- point.y_top = DygraphLayout.calcYNormal_(axis, point.yval_minus, logscale);
- point.y_bottom = DygraphLayout.calcYNormal_(axis, point.yval_plus, logscale);
- }
-};
-
-})();
-/**
- * @license
- * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview DataHandler implementation for the custom bars option.
- * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
- */
-
-(function() {
-
-/*global Dygraph:false */
-"use strict";
-
-/**
- * @constructor
- * @extends Dygraph.DataHandlers.BarsHandler
- */
-Dygraph.DataHandlers.CustomBarsHandler = function() {
-};
-
-var CustomBarsHandler = Dygraph.DataHandlers.CustomBarsHandler;
-CustomBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler();
-
-/** @inheritDoc */
-CustomBarsHandler.prototype.extractSeries = function(rawData, i, options) {
- // TODO(danvk): pre-allocate series here.
- var series = [];
- var x, y, point;
- var logScale = options.get('logscale');
- for ( var j = 0; j < rawData.length; j++) {
- x = rawData[j][0];
- point = rawData[j][i];
- if (logScale && point !== null) {
- // On the log scale, points less than zero do not exist.
- // This will create a gap in the chart.
- if (point[0] <= 0 || point[1] <= 0 || point[2] <= 0) {
- point = null;
- }
- }
- // Extract to the unified data format.
- if (point !== null) {
- y = point[1];
- if (y !== null && !isNaN(y)) {
- series.push([ x, y, [ point[0], point[2] ] ]);
- } else {
- series.push([ x, y, [ y, y ] ]);
- }
- } else {
- series.push([ x, null, [ null, null ] ]);
- }
- }
- return series;
-};
-
-/** @inheritDoc */
-CustomBarsHandler.prototype.rollingAverage =
- function(originalData, rollPeriod, options) {
- rollPeriod = Math.min(rollPeriod, originalData.length);
- var rollingData = [];
- var y, low, high, mid,count, i, extremes;
-
- low = 0;
- mid = 0;
- high = 0;
- count = 0;
- for (i = 0; i < originalData.length; i++) {
- y = originalData[i][1];
- extremes = originalData[i][2];
- rollingData[i] = originalData[i];
-
- if (y !== null && !isNaN(y)) {
- low += extremes[0];
- mid += y;
- high += extremes[1];
- count += 1;
- }
- if (i - rollPeriod >= 0) {
- var prev = originalData[i - rollPeriod];
- if (prev[1] !== null && !isNaN(prev[1])) {
- low -= prev[2][0];
- mid -= prev[1];
- high -= prev[2][1];
- count -= 1;
- }
- }
- if (count) {
- rollingData[i] = [
- originalData[i][0],
- 1.0 * mid / count,
- [ 1.0 * low / count,
- 1.0 * high / count ] ];
- } else {
- rollingData[i] = [ originalData[i][0], null, [ null, null ] ];
- }
- }
-
- return rollingData;
-};
-
-})();
-/**
- * @license
- * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview DataHandler implementation for the error bars option.
- * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
- */
-
-(function() {
-
-/*global Dygraph:false */
-"use strict";
-
-/**
- * @constructor
- * @extends Dygraph.DataHandlers.BarsHandler
- */
-Dygraph.DataHandlers.ErrorBarsHandler = function() {
-};
-
-var ErrorBarsHandler = Dygraph.DataHandlers.ErrorBarsHandler;
-ErrorBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler();
-
-/** @inheritDoc */
-ErrorBarsHandler.prototype.extractSeries = function(rawData, i, options) {
- // TODO(danvk): pre-allocate series here.
- var series = [];
- var x, y, variance, point;
- var sigma = options.get("sigma");
- var logScale = options.get('logscale');
- for ( var j = 0; j < rawData.length; j++) {
- x = rawData[j][0];
- point = rawData[j][i];
- if (logScale && point !== null) {
- // On the log scale, points less than zero do not exist.
- // This will create a gap in the chart.
- if (point[0] <= 0 || point[0] - sigma * point[1] <= 0) {
- point = null;
- }
- }
- // Extract to the unified data format.
- if (point !== null) {
- y = point[0];
- if (y !== null && !isNaN(y)) {
- variance = sigma * point[1];
- // preserve original error value in extras for further
- // filtering
- series.push([ x, y, [ y - variance, y + variance, point[1] ] ]);
- } else {
- series.push([ x, y, [ y, y, y ] ]);
- }
- } else {
- series.push([ x, null, [ null, null, null ] ]);
- }
- }
- return series;
-};
-
-/** @inheritDoc */
-ErrorBarsHandler.prototype.rollingAverage =
- function(originalData, rollPeriod, options) {
- rollPeriod = Math.min(rollPeriod, originalData.length);
- var rollingData = [];
- var sigma = options.get("sigma");
-
- var i, j, y, v, sum, num_ok, stddev, variance, value;
-
- // Calculate the rolling average for the first rollPeriod - 1 points
- // where there is not enough data to roll over the full number of points
- for (i = 0; i < originalData.length; i++) {
- sum = 0;
- variance = 0;
- num_ok = 0;
- for (j = Math.max(0, i - rollPeriod + 1); j < i + 1; j++) {
- y = originalData[j][1];
- if (y === null || isNaN(y))
- continue;
- num_ok++;
- sum += y;
- variance += Math.pow(originalData[j][2][2], 2);
- }
- if (num_ok) {
- stddev = Math.sqrt(variance) / num_ok;
- value = sum / num_ok;
- rollingData[i] = [ originalData[i][0], value,
- [value - sigma * stddev, value + sigma * stddev] ];
- } else {
- // This explicitly preserves NaNs to aid with "independent
- // series".
- // See testRollingAveragePreservesNaNs.
- v = (rollPeriod == 1) ? originalData[i][1] : null;
- rollingData[i] = [ originalData[i][0], v, [ v, v ] ];
- }
- }
-
- return rollingData;
-};
-
-})();
-/**
- * @license
- * Copyright 2013 David Eberlein (david.eberlein@ch.sauter-bc.com)
- * MIT-licensed (http://opensource.org/licenses/MIT)
- */
-
-/**
- * @fileoverview DataHandler implementation for the combination
- * of error bars and fractions options.
- * @author David Eberlein (david.eberlein@ch.sauter-bc.com)
- */
-
-(function() {
-
-/*global Dygraph:false */
-"use strict";
-
-/**
- * @constructor
- * @extends Dygraph.DataHandlers.BarsHandler
- */
-Dygraph.DataHandlers.FractionsBarsHandler = function() {
-};
-
-var FractionsBarsHandler = Dygraph.DataHandlers.FractionsBarsHandler;
-FractionsBarsHandler.prototype = new Dygraph.DataHandlers.BarsHandler();
-
-/** @inheritDoc */
-FractionsBarsHandler.prototype.extractSeries = function(rawData, i, options) {
- // TODO(danvk): pre-allocate series here.
- var series = [];
- var x, y, point, num, den, value, stddev, variance;
- var mult = 100.0;
- var sigma = options.get("sigma");
- var logScale = options.get('logscale');
- for ( var j = 0; j < rawData.length; j++) {
- x = rawData[j][0];
- point = rawData[j][i];
- if (logScale && point !== null) {
- // On the log scale, points less than zero do not exist.
- // This will create a gap in the chart.
- if (point[0] <= 0 || point[1] <= 0) {
- point = null;
- }
- }
- // Extract to the unified data format.
- if (point !== null) {
- num = point[0];
- den = point[1];
- if (num !== null && !isNaN(num)) {
- value = den ? num / den : 0.0;
- stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
- variance = mult * stddev;
- y = mult * value;
- // preserve original values in extras for further filtering
- series.push([ x, y, [ y - variance, y + variance, num, den ] ]);
- } else {
- series.push([ x, num, [ num, num, num, den ] ]);
- }
- } else {
- series.push([ x, null, [ null, null, null, null ] ]);
- }
- }
- return series;
-};
-
-/** @inheritDoc */
-FractionsBarsHandler.prototype.rollingAverage =
- function(originalData, rollPeriod, options) {
- rollPeriod = Math.min(rollPeriod, originalData.length);
- var rollingData = [];
- var sigma = options.get("sigma");
- var wilsonInterval = options.get("wilsonInterval");
-
- var low, high, i, stddev;
- var num = 0;
- var den = 0; // numerator/denominator
- var mult = 100.0;
- for (i = 0; i < originalData.length; i++) {
- num += originalData[i][2][2];
- den += originalData[i][2][3];
- if (i - rollPeriod >= 0) {
- num -= originalData[i - rollPeriod][2][2];
- den -= originalData[i - rollPeriod][2][3];
- }
-
- var date = originalData[i][0];
- var value = den ? num / den : 0.0;
- if (wilsonInterval) {
- // For more details on this confidence interval, see:
- // http://en.wikipedia.org/wiki/Binomial_confidence_interval
- if (den) {
- var p = value < 0 ? 0 : value, n = den;
- var pm = sigma * Math.sqrt(p * (1 - p) / n + sigma * sigma / (4 * n * n));
- var denom = 1 + sigma * sigma / den;
- low = (p + sigma * sigma / (2 * den) - pm) / denom;
- high = (p + sigma * sigma / (2 * den) + pm) / denom;
- rollingData[i] = [ date, p * mult,
- [ low * mult, high * mult ] ];
- } else {
- rollingData[i] = [ date, 0, [ 0, 0 ] ];
- }
- } else {
- stddev = den ? sigma * Math.sqrt(value * (1 - value) / den) : 1.0;
- rollingData[i] = [ date, mult * value,
- [ mult * (value - stddev), mult * (value + stddev) ] ];
- }
- }
-
- return rollingData;
-};
-
-})();
diff --git a/debian/missing-sources/gauge.coffee b/debian/missing-sources/gauge-d5260c3.coffee
index 0ae4c8daf..d7366f44e 100644
--- a/debian/missing-sources/gauge.coffee
+++ b/debian/missing-sources/gauge-d5260c3.coffee
@@ -213,7 +213,6 @@ class GaugePointer extends ValueUpdater
@strokeWidth = @canvas.height * @options.strokeWidth
@maxValue = @gauge.maxValue
@minValue = @gauge.minValue
- @displayedValue = @gauge.minValue
@animationSpeed = @gauge.animationSpeed
@options.angle = @gauge.options.angle
@@ -320,7 +319,7 @@ class Gauge extends BaseGauge
@percentColors[i] = { pct: @options.percentColors[i][0], color: { r: rval, g: gval, b: bval } }
set: (value) ->
- @displayedValue = @minValue
+
if not (value instanceof Array)
value = [value]
# check if we have enough GaugePointers initialized
diff --git a/debian/missing-sources/jquery-2.2.4.js b/debian/missing-sources/jquery-2.2.4.js
new file mode 100644
index 000000000..5c3c456ac
--- /dev/null
+++ b/debian/missing-sources/jquery-2.2.4.js
@@ -0,0 +1,9814 @@
+/*!
+ * jQuery JavaScript Library v2.2.4
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2016-05-20T17:23Z
+ */
+
+(function( global, factory ) {
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Support: Firefox 18+
+// Can't be in strict mode, several libs including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+//"use strict";
+var arr = [];
+
+var document = window.document;
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+ version = "2.2.4",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android<4.1
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // 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();
+ };
+
+jQuery.fn = jQuery.prototype = {
+
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return 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 just the one element from the set
+ ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+ // Return all the elements in a clean array
+ slice.call( this );
+ },
+
+ // 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.
+ each: function( callback ) {
+ return jQuery.each( this, callback );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map( this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ } ) );
+ },
+
+ slice: function() {
+ return this.pushStack( 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 ] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor();
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: arr.sort,
+ splice: arr.splice
+};
+
+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;
+
+ // Skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // 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 ( i === length ) {
+ 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" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ isFunction: function( obj ) {
+ return jQuery.type( obj ) === "function";
+ },
+
+ isArray: Array.isArray,
+
+ isWindow: function( obj ) {
+ return obj != null && obj === obj.window;
+ },
+
+ isNumeric: function( obj ) {
+
+ // parseFloat NaNs numeric-cast false positives (null|true|false|"")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ // adding 1 corrects loss of precision from parseFloat (#15100)
+ var realStringObj = obj && obj.toString();
+ return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
+ },
+
+ isPlainObject: function( obj ) {
+ var key;
+
+ // 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;
+ }
+
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call( obj, "constructor" ) &&
+ !hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) {
+ return false;
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+
+ // Support: Android<4.0, iOS<6 (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call( obj ) ] || "object" :
+ typeof obj;
+ },
+
+ // 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
+ // Support: IE9-11+
+ // 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();
+ },
+
+ each: function( obj, callback ) {
+ var length, i = 0;
+
+ if ( isArrayLike( obj ) ) {
+ length = obj.length;
+ for ( ; i < length; i++ ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android<4.1
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // 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 {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ return arr == null ? -1 : indexOf.call( arr, elem, i );
+ },
+
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ for ( ; j < len; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var length, value,
+ i = 0,
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArrayLike( elems ) ) {
+ length = elems.length;
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return 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 = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( 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;
+ },
+
+ now: Date.now,
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+} );
+
+// JSHint would error on this code due to the Symbol not being defined in ES5.
+// Defining this global in .jshintrc would create a danger of using the global
+// unguarded in another place, it seems safer to just disable JSHint for these
+// three lines.
+/* jshint ignore: start */
+if ( typeof Symbol === "function" ) {
+ jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+}
+/* jshint ignore: end */
+
+// Populate the class2type map
+jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+function( i, name ) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+} );
+
+function isArrayLike( obj ) {
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = !!obj && "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.1
+ * http://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-10-17
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // General-purpose constants
+ 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 as it's faster than native
+ // http://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[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
+
+ // http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+
+ // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + identifier + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + identifier + ")" ),
+ "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+ "TAG": new RegExp( "^(" + identifier + "|[*])" ),
+ "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" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+ 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<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ };
+
+// 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 m, i, elem, nid, nidselect, match, groups, newSelector,
+ newContext = context && context.ownerDocument,
+
+ // nodeType defaults to 9, since context defaults to document
+ nodeType = context ? context.nodeType : 9;
+
+ results = results || [];
+
+ // Return early from calls with invalid selector or context
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ // Try to shortcut find operations (as opposed to filters) in HTML documents
+ if ( !seed ) {
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+ context = context || document;
+
+ if ( documentIsHTML ) {
+
+ // If the selector is sufficiently simple, try using a "get*By*" DOM method
+ // (excepting DocumentFragment context, where the methods don't exist)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+ // ID selector
+ if ( (m = match[1]) ) {
+
+ // Document context
+ if ( nodeType === 9 ) {
+ if ( (elem = context.getElementById( m )) ) {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+
+ // Element context
+ } else {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( newContext && (elem = newContext.getElementById( m )) &&
+ contains( context, elem ) &&
+ elem.id === m ) {
+
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Type selector
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Class selector
+ } else if ( (m = match[3]) && support.getElementsByClassName &&
+ context.getElementsByClassName ) {
+
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // Take advantage of querySelectorAll
+ if ( support.qsa &&
+ !compilerCache[ selector + " " ] &&
+ (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+
+ if ( nodeType !== 1 ) {
+ newContext = context;
+ newSelector = selector;
+
+ // qSA looks outside Element context, which is not what we want
+ // Thanks to Andrew Dupont for this workaround technique
+ // Support: IE <=8
+ // Exclude object elements
+ } else if ( context.nodeName.toLowerCase() !== "object" ) {
+
+ // Capture the context ID, setting it first if necessary
+ if ( (nid = context.getAttribute( "id" )) ) {
+ nid = nid.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", (nid = expando) );
+ }
+
+ // Prefix every selector in the list
+ groups = tokenize( selector );
+ i = groups.length;
+ nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
+ while ( i-- ) {
+ groups[i] = nidselect + " " + toSelector( groups[i] );
+ }
+ newSelector = groups.join( "," );
+
+ // Expand context for sibling selectors
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+ context;
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch ( qsaError ) {
+ } finally {
+ if ( nid === expando ) {
+ 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 = arr.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]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+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;
+};
+
+/**
+ * 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 hasCompare, parent,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // Return early if doc is invalid or already selected
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Update global variables
+ document = doc;
+ docElem = document.documentElement;
+ documentIsHTML = !isXML( document );
+
+ // Support: IE 9-11, Edge
+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+ if ( (parent = document.defaultView) && parent.top !== parent ) {
+ // Support: IE 11
+ if ( parent.addEventListener ) {
+ parent.addEventListener( "unload", unloadHandler, false );
+
+ // Support: IE 9 - 10 only
+ } else if ( parent.attachEvent ) {
+ parent.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* 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( document.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( document.getElementsByClassName );
+
+ // 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 !document.getElementsByName || !document.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var m = context.getElementById( id );
+ return m ? [ 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 !== "undefined" &&
+ elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ 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 !== "undefined" && 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( document.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
+ docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\r\\' msallowcapture=''>" +
+ "<option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+ if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // 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");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibing-combinator selector` fails
+ if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( div ) {
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = document.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ div.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( div.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + 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.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
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully self-exclusive
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ 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 = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === document ? -1 :
+ b === document ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( 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 document;
+};
+
+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 &&
+ !compilerCache[ expr + " " ] &&
+ ( !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 ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+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 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ 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
+ while ( (node = elem[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 (jQuery #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[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[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // 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 !== "undefined" && 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.replace( rwhitespace, " " ) + " " ).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, uniqueCache, outerCache, node, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType,
+ diff = false;
+
+ 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
+
+ // ...in a gzip-friendly way
+ node = parent;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex && 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 ) {
+ uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ } else {
+ // Use previously-cached element index if available
+ if ( useCache ) {
+ // ...in a gzip-friendly way
+ node = elem;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex;
+ }
+
+ // xml :nth-child(...)
+ // or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ if ( diff === false ) {
+ // 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 ) {
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ uniqueCache[ 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( 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 );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ 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 negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ 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;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // 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();
+
+tokenize = Sizzle.tokenize = function( 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 oldCache, uniqueCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from combinator 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 ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
+
+ if ( (oldCache = uniqueCache[ dir ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ uniqueCache[ dir ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ 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 multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+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( 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( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ 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 ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context === document || context || outermost;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ if ( !context && elem.ownerDocument !== document ) {
+ setDocument( elem );
+ xml = !documentIsHTML;
+ }
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context || document, xml) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // 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 );
+ }
+ }
+ }
+
+ // `i` is now the count of elements visited above, and adding it to `matchedCount`
+ // makes the latter nonnegative.
+ matchedCount += i;
+
+ // Apply set filters to unmatched elements
+ // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
+ // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
+ // no element matchers and no seed.
+ // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
+ // case, which will result in a "00" `matchedCount` that differs from `i` but is also
+ // numerically zero.
+ 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, match /* 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 ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is only one selector in the list and no seed
+ // (the latter of which guarantees us context)
+ if ( match.length === 1 ) {
+
+ // Reduce context if the leading compound 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;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ 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 ) && testContext( 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 if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// 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 elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[ ":" ] = jQuery.expr.pseudos;
+jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var 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;
+};
+
+
+var siblings = function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+};
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// 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 ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
+ } );
+}
+
+jQuery.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;
+ } ) );
+};
+
+jQuery.fn.extend( {
+ find: function( selector ) {
+ var i,
+ len = this.length,
+ ret = [],
+ self = this;
+
+ 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;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], false ) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], true ) );
+ },
+ 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;
+ }
+} );
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // 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-]*))$/,
+
+ init = jQuery.fn.init = function( selector, context, root ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Method init() accepts an alternate rootjQuery
+ // so migrate can support jQuery.sub (gh-2101)
+ root = root || rootjQuery;
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector[ 0 ] === "<" &&
+ selector[ 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;
+
+ // Option to run scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ 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 ] );
+
+ // Support: Blackberry 4.6
+ // gEBID returns nodes 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 || root ).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 root.ready !== undefined ?
+ root.ready( selector ) :
+
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+
+ // 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( {
+ 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;
+ }
+ }
+ } );
+ },
+
+ 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 ) ) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
+ },
+
+ // Determine the position of an element within the set
+ 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 indexOf.call( jQuery( elem ), this[ 0 ] );
+ }
+
+ // Locate the position of the desired element
+ return indexOf.call( this,
+
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[ 0 ] : elem
+ );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.uniqueSort(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ 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 dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return siblings( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return siblings( 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.uniqueSort( matched );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ matched.reverse();
+ }
+ }
+
+ return this.pushStack( matched );
+ };
+} );
+var rnotwhite = ( /\S+/g );
+
+
+
+// Convert String-formatted options into Object-formatted ones
+function createOptions( options ) {
+ var object = {};
+ jQuery.each( options.match( 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" ?
+ createOptions( options ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+
+ // Last fire value for non-forgettable lists
+ memory,
+
+ // Flag to know if list was already fired
+ fired,
+
+ // Flag to prevent firing
+ locked,
+
+ // Actual callback list
+ list = [],
+
+ // Queue of execution data for repeatable lists
+ queue = [],
+
+ // Index of currently firing callback (modified by add/remove as needed)
+ firingIndex = -1,
+
+ // Fire callbacks
+ fire = function() {
+
+ // Enforce single-firing
+ locked = options.once;
+
+ // Execute callbacks for all pending executions,
+ // respecting firingIndex overrides and runtime changes
+ fired = firing = true;
+ for ( ; queue.length; firingIndex = -1 ) {
+ memory = queue.shift();
+ while ( ++firingIndex < list.length ) {
+
+ // Run callback and check for early termination
+ if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
+ options.stopOnFalse ) {
+
+ // Jump to end and forget the data so .add doesn't re-fire
+ firingIndex = list.length;
+ memory = false;
+ }
+ }
+ }
+
+ // Forget the data if we're done with it
+ if ( !options.memory ) {
+ memory = false;
+ }
+
+ firing = false;
+
+ // Clean up if we're done firing for good
+ if ( locked ) {
+
+ // Keep an empty list if we have data for future add calls
+ if ( memory ) {
+ list = [];
+
+ // Otherwise, this object is spent
+ } else {
+ list = "";
+ }
+ }
+ },
+
+ // Actual Callbacks object
+ self = {
+
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+
+ // If we have memory from a past run, we should fire after adding
+ if ( memory && !firing ) {
+ firingIndex = list.length - 1;
+ queue.push( memory );
+ }
+
+ ( function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ if ( jQuery.isFunction( arg ) ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+
+ // Inspect recursively
+ add( arg );
+ }
+ } );
+ } )( arguments );
+
+ if ( memory && !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Remove a callback from the list
+ remove: function() {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+
+ // Handle firing indexes
+ 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.length > 0;
+ },
+
+ // Remove all callbacks from the list
+ empty: function() {
+ if ( list ) {
+ list = [];
+ }
+ return this;
+ },
+
+ // Disable .fire and .add
+ // Abort any current/pending executions
+ // Clear all callbacks and values
+ disable: function() {
+ locked = queue = [];
+ list = memory = "";
+ return this;
+ },
+ disabled: function() {
+ return !list;
+ },
+
+ // Disable .fire
+ // Also disable .add unless we have memory (since it would have no effect)
+ // Abort any pending executions
+ lock: function() {
+ locked = queue = [];
+ if ( !memory ) {
+ list = memory = "";
+ }
+ return this;
+ },
+ locked: function() {
+ return !!locked;
+ },
+
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( !locked ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ queue.push( args );
+ if ( !firing ) {
+ fire();
+ }
+ }
+ 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 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()
+ .progress( newDefer.notify )
+ .done( newDefer.resolve )
+ .fail( newDefer.reject );
+ } else {
+ newDefer[ tuple[ 0 ] + "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 = 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 ? 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()
+ .progress( updateFunc( i, progressContexts, progressValues ) )
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // If we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+} );
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+};
+
+jQuery.extend( {
+
+ // 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.triggerHandler ) {
+ jQuery( document ).triggerHandler( "ready" );
+ jQuery( document ).off( "ready" );
+ }
+ }
+} );
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+ document.removeEventListener( "DOMContentLoaded", completed );
+ window.removeEventListener( "load", completed );
+ jQuery.ready();
+}
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called
+ // after the browser event has already occurred.
+ // Support: IE9-10 only
+ // Older IE sometimes signals "interactive" too soon
+ if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
+
+ } else {
+
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+ }
+ }
+ return readyList.promise( obj );
+};
+
+// Kick off the DOM ready check even if the user does not
+jQuery.ready.promise();
+
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ len = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ 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 < len; i++ ) {
+ fn(
+ elems[ i ], key, raw ?
+ value :
+ value.call( elems[ i ], i, fn( elems[ i ], key ) )
+ );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ len ? fn( elems[ 0 ], key ) : emptyGet;
+};
+var acceptData = function( owner ) {
+
+ // Accepts only:
+ // - Node
+ // - Node.ELEMENT_NODE
+ // - Node.DOCUMENT_NODE
+ // - Object
+ // - Any
+ /* jshint -W018 */
+ return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
+
+
+
+
+function Data() {
+ this.expando = jQuery.expando + Data.uid++;
+}
+
+Data.uid = 1;
+
+Data.prototype = {
+
+ register: function( owner, initial ) {
+ var value = initial || {};
+
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
+
+ // Otherwise secure it in a non-enumerable, non-writable property
+ // configurability must be true to allow the property to be
+ // deleted with the delete operator
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ writable: true,
+ configurable: true
+ } );
+ }
+ return owner[ this.expando ];
+ },
+ cache: function( owner ) {
+
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( !acceptData( owner ) ) {
+ return {};
+ }
+
+ // Check if the owner object already has a cache
+ var value = owner[ this.expando ];
+
+ // If not, create one
+ if ( !value ) {
+ value = {};
+
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( acceptData( owner ) ) {
+
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
+
+ // Otherwise secure it in a non-enumerable property
+ // configurable must be true to allow the property to be
+ // deleted when data is removed
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ configurable: true
+ } );
+ }
+ }
+ }
+
+ return value;
+ },
+ set: function( owner, data, value ) {
+ var prop,
+ cache = this.cache( owner );
+
+ // Handle: [ owner, key, value ] args
+ if ( typeof data === "string" ) {
+ cache[ data ] = value;
+
+ // Handle: [ owner, { properties } ] args
+ } else {
+
+ // Copy the properties one-by-one to the cache object
+ for ( prop in data ) {
+ cache[ prop ] = data[ prop ];
+ }
+ }
+ return cache;
+ },
+ get: function( owner, key ) {
+ return key === undefined ?
+ this.cache( owner ) :
+ owner[ this.expando ] && owner[ this.expando ][ 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,
+ cache = owner[ this.expando ];
+
+ if ( cache === undefined ) {
+ return;
+ }
+
+ if ( key === undefined ) {
+ this.register( owner );
+
+ } 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( rnotwhite ) || [] );
+ }
+ }
+
+ i = name.length;
+
+ while ( i-- ) {
+ delete cache[ name[ i ] ];
+ }
+ }
+
+ // Remove the expando if there's no more data
+ if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
+
+ // Support: Chrome <= 35-45+
+ // Webkit & Blink performance suffers when deleting properties
+ // from DOM nodes, so set to undefined instead
+ // https://code.google.com/p/chromium/issues/detail?id=378607
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = undefined;
+ } else {
+ delete owner[ this.expando ];
+ }
+ }
+ },
+ hasData: function( owner ) {
+ var cache = owner[ this.expando ];
+ return cache !== undefined && !jQuery.isEmptyObject( cache );
+ }
+};
+var dataPriv = new Data();
+
+var dataUser = new Data();
+
+
+
+// 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 rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /[A-Z]/g;
+
+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, "-$&" ).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 ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch ( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ dataUser.set( elem, key, data );
+ } else {
+ data = undefined;
+ }
+ }
+ return data;
+}
+
+jQuery.extend( {
+ hasData: function( elem ) {
+ return dataUser.hasData( elem ) || dataPriv.hasData( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return dataUser.access( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ dataUser.remove( elem, name );
+ },
+
+ // TODO: Now that all calls to _data and _removeData have been replaced
+ // with direct calls to dataPriv methods, these can be deprecated.
+ _data: function( elem, name, data ) {
+ return dataPriv.access( elem, name, data );
+ },
+
+ _removeData: function( elem, name ) {
+ dataPriv.remove( elem, name );
+ }
+} );
+
+jQuery.fn.extend( {
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[ 0 ],
+ attrs = elem && elem.attributes;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = dataUser.get( elem );
+
+ if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE11+
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice( 5 ) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ dataPriv.set( elem, "hasDataAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each( function() {
+ dataUser.set( this, key );
+ } );
+ }
+
+ return access( this, function( value ) {
+ var data, camelKey;
+
+ // 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 = dataUser.get( elem, key ) ||
+
+ // Try to find dashed key if it exists (gh-2779)
+ // This is for 2.2.x only
+ dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() );
+
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ camelKey = jQuery.camelCase( key );
+
+ // Attempt to get data from the cache
+ // with the key camelized
+ data = dataUser.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...
+ camelKey = jQuery.camelCase( key );
+ 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 = dataUser.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...*
+ dataUser.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 ) {
+ dataUser.set( this, key, value );
+ }
+ } );
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each( function() {
+ dataUser.remove( this, key );
+ } );
+ }
+} );
+
+
+jQuery.extend( {
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = dataPriv.get( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray( data ) ) {
+ queue = dataPriv.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 public - generate a queueHooks object, or return the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
+ empty: jQuery.Callbacks( "once memory" ).add( function() {
+ dataPriv.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 );
+ } );
+ },
+ 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 = dataPriv.get( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+} );
+var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
+
+var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
+
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( 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 );
+ };
+
+
+
+function adjustCSS( elem, prop, valueParts, tween ) {
+ var adjusted,
+ scale = 1,
+ maxIterations = 20,
+ currentValue = tween ?
+ function() { return tween.cur(); } :
+ function() { return jQuery.css( elem, prop, "" ); },
+ initial = currentValue(),
+ unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+ rcssNum.exec( jQuery.css( elem, prop ) );
+
+ if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+
+ // Trust units reported by jQuery.css
+ unit = unit || initialInUnit[ 3 ];
+
+ // Make sure we update the tween properties later on
+ valueParts = valueParts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ initialInUnit = +initial || 1;
+
+ do {
+
+ // If previous iteration zeroed out, double until we get *something*.
+ // Use string for doubling so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ initialInUnit = initialInUnit / scale;
+ jQuery.style( elem, prop, initialInUnit + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // Break the loop if scale is unchanged or perfect, or if we've just had enough.
+ } while (
+ scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
+ );
+ }
+
+ if ( valueParts ) {
+ initialInUnit = +initialInUnit || +initial || 0;
+
+ // Apply relative offset (+=/-=) if specified
+ adjusted = valueParts[ 1 ] ?
+ initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+ +valueParts[ 2 ];
+ if ( tween ) {
+ tween.unit = unit;
+ tween.start = initialInUnit;
+ tween.end = adjusted;
+ }
+ }
+ return adjusted;
+}
+var rcheckableType = ( /^(?:checkbox|radio)$/i );
+
+var rtagName = ( /<([\w:-]+)/ );
+
+var rscriptType = ( /^$|\/(?:java|ecma)script/i );
+
+
+
+// We have to close these tags to support XHTML (#13200)
+var wrapMap = {
+
+ // Support: IE9
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+ // XHTML parsers do not magically insert elements in the
+ // same way that tag soup parsers do. So we cannot shorten
+ // this by omitting <tbody> or other required elements.
+ 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: IE9
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function getAll( context, tag ) {
+
+ // Support: IE9-11+
+ // Use typeof to avoid zero-argument method invocation on host objects (#15151)
+ var ret = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== "undefined" ?
+ context.querySelectorAll( tag || "*" ) :
+ [];
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], ret ) :
+ ret;
+}
+
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ dataPriv.set(
+ elems[ i ],
+ "globalEval",
+ !refElements || dataPriv.get( refElements[ i ], "globalEval" )
+ );
+ }
+}
+
+
+var rhtml = /<|&#?\w+;/;
+
+function buildFragment( elems, context, scripts, selection, ignored ) {
+ var elem, tmp, tag, wrap, contains, j,
+ fragment = context.createDocumentFragment(),
+ nodes = [],
+ i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+
+ // Support: Android<4.1, PhantomJS<2
+ // push.apply(_, arraylike) throws on ancient WebKit
+ 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 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
+
+ // Descend through wrappers to the right content
+ j = wrap[ 0 ];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Support: Android<4.1, PhantomJS<2
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Remember the top-level container
+ tmp = fragment.firstChild;
+
+ // Ensure the created nodes are orphaned (#12392)
+ tmp.textContent = "";
+ }
+ }
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+
+ i = 0;
+ while ( ( elem = nodes[ i++ ] ) ) {
+
+ // Skip elements already in the context collection (trac-4087)
+ if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
+ if ( ignored ) {
+ ignored.push( elem );
+ }
+ 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;
+}
+
+
+( function() {
+ var fragment = document.createDocumentFragment(),
+ div = fragment.appendChild( document.createElement( "div" ) ),
+ input = document.createElement( "input" );
+
+ // Support: Android 4.0-4.3, Safari<=5.1
+ // Check state lost if the name is set (#11217)
+ // Support: Windows Web Apps (WWA)
+ // `name` and `type` must use .setAttribute for WWA (#14901)
+ input.setAttribute( "type", "radio" );
+ input.setAttribute( "checked", "checked" );
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+
+ // Support: Safari<=5.1, Android<4.2
+ // Older WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<=11+
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+} )();
+
+
+var
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+// Support: IE9
+// See #13393 for more info
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+function on( elem, types, selector, data, fn, 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 ) {
+ on( elem, type, selector, data, types[ type ], one );
+ }
+ return elem;
+ }
+
+ 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 elem;
+ }
+
+ 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 elem.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ } );
+}
+
+/*
+ * 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 = dataPriv.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 !== "undefined" && jQuery.event.triggered !== e.type ?
+ jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+ };
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( 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 );
+ }
+ }
+ }
+
+ 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;
+ }
+
+ },
+
+ // 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 = dataPriv.hasData( elem ) && dataPriv.get( elem );
+
+ if ( !elemData || !( events = elemData.events ) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( 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 data and the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ dataPriv.remove( elem, "handle events" );
+ }
+ },
+
+ 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 = slice.call( arguments ),
+ handlers = ( dataPriv.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.rnamespace || event.rnamespace.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;
+
+ // Support (at least): Chrome, IE9
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ //
+ // Support: Firefox<=42+
+ // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
+ if ( delegateCount && cur.nodeType &&
+ ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
+
+ for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && ( 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 ) > -1 :
+ 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 detail 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 ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ }
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+
+ // This "if" is needed for plain objects
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle );
+ }
+};
+
+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.defaultPrevented === undefined &&
+
+ // Support: Android<4.0
+ src.returnValue === false ?
+ 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 = {
+ constructor: jQuery.Event,
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+ isSimulated: false,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.preventDefault();
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopPropagation();
+ }
+ },
+ stopImmediatePropagation: function() {
+ var e = this.originalEvent;
+
+ this.isImmediatePropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopImmediatePropagation();
+ }
+
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// so that event delegation works in jQuery.
+// Do the same for pointerenter/pointerleave and pointerover/pointerout
+//
+// Support: Safari 7 only
+// Safari sends mouseenter too often; see:
+// https://code.google.com/p/chromium/issues/detail?id=470258
+// for the description of the bug (it existed in older Chrome versions as well).
+jQuery.each( {
+ mouseenter: "mouseover",
+ mouseleave: "mouseout",
+ pointerenter: "pointerover",
+ pointerleave: "pointerout"
+}, 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 mouseenter/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;
+ }
+ };
+} );
+
+jQuery.fn.extend( {
+ on: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn );
+ },
+ one: function( types, selector, data, fn ) {
+ return on( this, 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 );
+ } );
+ }
+} );
+
+
+var
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
+
+ // Support: IE 10-11, Edge 10240+
+ // In IE/Edge using regex groups here causes severe slowdowns.
+ // See https://connect.microsoft.com/IE/feedback/details/1736512/
+ rnoInnerhtml = /<script|<style|<link/i,
+
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
+
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+ return jQuery.nodeName( elem, "table" ) &&
+ jQuery.nodeName( content.nodeType !== 11 ? 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;
+}
+
+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 ( dataPriv.hasData( src ) ) {
+ pdataOld = dataPriv.access( src );
+ pdataCur = dataPriv.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 ( dataUser.hasData( src ) ) {
+ udataOld = dataUser.access( src );
+ udataCur = jQuery.extend( {}, udataOld );
+
+ dataUser.set( dest, udataCur );
+ }
+}
+
+// Fix IE bugs, see support tests
+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" && 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;
+ }
+}
+
+function domManip( collection, args, callback, ignored ) {
+
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
+
+ var fragment, first, scripts, hasScripts, node, doc,
+ i = 0,
+ l = collection.length,
+ 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" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return collection.each( function( index ) {
+ var self = collection.eq( index );
+ if ( isFunction ) {
+ args[ 0 ] = value.call( this, index, self.html() );
+ }
+ domManip( self, args, callback, ignored );
+ } );
+ }
+
+ if ( l ) {
+ fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ // Require either new content or an interest in ignored elements to invoke the callback
+ if ( first || ignored ) {
+ 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: Android<4.1, PhantomJS<2
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( collection[ 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 || "" ) &&
+ !dataPriv.access( node, "globalEval" ) &&
+ jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return collection;
+}
+
+function remove( elem, selector, keepData ) {
+ var node,
+ nodes = selector ? jQuery.filter( selector, elem ) : elem,
+ i = 0;
+
+ for ( ; ( node = nodes[ i ] ) != null; i++ ) {
+ if ( !keepData && node.nodeType === 1 ) {
+ jQuery.cleanData( getAll( node ) );
+ }
+
+ if ( node.parentNode ) {
+ if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
+ setGlobalEval( getAll( node, "script" ) );
+ }
+ node.parentNode.removeChild( node );
+ }
+ }
+
+ return elem;
+}
+
+jQuery.extend( {
+ htmlPrefilter: function( html ) {
+ return html.replace( rxhtmlTag, "<$1></$2>" );
+ },
+
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var i, l, srcElements, destElements,
+ clone = elem.cloneNode( true ),
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ // Fix IE cloning issues
+ if ( !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;
+ },
+
+ cleanData: function( elems ) {
+ var data, elem, type,
+ special = jQuery.event.special,
+ i = 0;
+
+ for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
+ if ( acceptData( elem ) ) {
+ if ( ( data = elem[ dataPriv.expando ] ) ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ 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 );
+ }
+ }
+ }
+
+ // Support: Chrome <= 35-45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataPriv.expando ] = undefined;
+ }
+ if ( elem[ dataUser.expando ] ) {
+
+ // Support: Chrome <= 35-45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataUser.expando ] = undefined;
+ }
+ }
+ }
+ }
+} );
+
+jQuery.fn.extend( {
+
+ // Keep domManip exposed until 3.0 (gh-2225)
+ domManip: domManip,
+
+ detach: function( selector ) {
+ return remove( this, selector, true );
+ },
+
+ remove: function( selector ) {
+ return remove( this, selector );
+ },
+
+ text: function( value ) {
+ return access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().each( function() {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.textContent = value;
+ }
+ } );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ } );
+ },
+
+ prepend: function() {
+ return domManip( this, 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 domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ } );
+ },
+
+ after: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ } );
+ },
+
+ 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 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 = jQuery.htmlPrefilter( value );
+
+ 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 ignored = [];
+
+ // Make the changes, replacing each non-ignored context element with the new content
+ return domManip( this, arguments, function( elem ) {
+ var parent = this.parentNode;
+
+ if ( jQuery.inArray( this, ignored ) < 0 ) {
+ jQuery.cleanData( getAll( this ) );
+ if ( parent ) {
+ parent.replaceChild( elem, this );
+ }
+ }
+
+ // Force callback invocation
+ }, ignored );
+ }
+} );
+
+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 push.apply(_, arraylike) throws
+ push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+} );
+
+
+var iframe,
+ elemdisplay = {
+
+ // Support: Firefox
+ // We have to pre-define these values for FF (#10227)
+ HTML: "block",
+ BODY: "block"
+ };
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+ display = jQuery.css( elem[ 0 ], "display" );
+
+ // We don't have any data stored on the element,
+ // so use "detach" method as fast way to get rid of the element
+ elem.detach();
+
+ return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function 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'/>" ) )
+ .appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = iframe[ 0 ].contentDocument;
+
+ // Support: IE
+ doc.write();
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+var rmargin = ( /^margin/ );
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+var getStyles = function( elem ) {
+
+ // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
+ // IE throws on elements created in popups
+ // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+ var view = elem.ownerDocument.defaultView;
+
+ if ( !view || !view.opener ) {
+ view = window;
+ }
+
+ return view.getComputedStyle( elem );
+ };
+
+var 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;
+};
+
+
+var documentElement = document.documentElement;
+
+
+
+( function() {
+ var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
+ container = document.createElement( "div" ),
+ div = document.createElement( "div" );
+
+ // Finish early in limited (non-browser) environments
+ if ( !div.style ) {
+ return;
+ }
+
+ // Support: IE9-11+
+ // Style of cloned element affects source element cloned (#8908)
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
+ "padding:0;margin-top:1px;position:absolute";
+ container.appendChild( div );
+
+ // Executing both pixelPosition & boxSizingReliable tests require only one layout
+ // so they're executed at the same time to save the second computation.
+ function computeStyleTests() {
+ div.style.cssText =
+
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" +
+ "position:relative;display:block;" +
+ "margin:auto;border:1px;padding:1px;" +
+ "top:1%;width:50%";
+ div.innerHTML = "";
+ documentElement.appendChild( container );
+
+ var divStyle = window.getComputedStyle( div );
+ pixelPositionVal = divStyle.top !== "1%";
+ reliableMarginLeftVal = divStyle.marginLeft === "2px";
+ boxSizingReliableVal = divStyle.width === "4px";
+
+ // Support: Android 4.0 - 4.3 only
+ // Some styles come back with percentage values, even though they shouldn't
+ div.style.marginRight = "50%";
+ pixelMarginRightVal = divStyle.marginRight === "4px";
+
+ documentElement.removeChild( container );
+ }
+
+ jQuery.extend( support, {
+ pixelPosition: function() {
+
+ // This test is executed only once but we still do memoizing
+ // since we can use the boxSizingReliable pre-computing.
+ // No need to check if the test was already performed, though.
+ computeStyleTests();
+ return pixelPositionVal;
+ },
+ boxSizingReliable: function() {
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return boxSizingReliableVal;
+ },
+ pixelMarginRight: function() {
+
+ // Support: Android 4.0-4.3
+ // We're checking for boxSizingReliableVal here instead of pixelMarginRightVal
+ // since that compresses better and they're computed together anyway.
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return pixelMarginRightVal;
+ },
+ reliableMarginLeft: function() {
+
+ // Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return reliableMarginLeftVal;
+ },
+ reliableMarginRight: function() {
+
+ // 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
+ // This support function is only executed once so no memoizing is needed.
+ var ret,
+ marginDiv = div.appendChild( document.createElement( "div" ) );
+
+ // Reset CSS: box-sizing; display; margin; border; padding
+ marginDiv.style.cssText = div.style.cssText =
+
+ // Support: Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:content-box;box-sizing:content-box;" +
+ "display:block;margin:0;border:0;padding:0";
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+ documentElement.appendChild( container );
+
+ ret = !parseFloat( window.getComputedStyle( marginDiv ).marginRight );
+
+ documentElement.removeChild( container );
+ div.removeChild( marginDiv );
+
+ return ret;
+ }
+ } );
+} )();
+
+
+function curCSS( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+ // Support: Opera 12.1x only
+ // Fall back to style even without computed
+ // computed is undefined for elems on document fragments
+ if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // Support: IE9
+ // getPropertyValue is only needed for .css('filter') (#12537)
+ if ( computed ) {
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Android Browser returns percentage for some values,
+ // but width seems to be reliably pixels.
+ // This is against the CSSOM draft spec:
+ // http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( !support.pixelMarginRight() && 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 !== undefined ?
+
+ // Support: IE9-11+
+ // IE returns zIndex value as an integer.
+ ret + "" :
+ ret;
+}
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+
+ // Define the hook, we'll check on the first run if it's really needed.
+ return {
+ get: function() {
+ if ( conditionFn() ) {
+
+ // Hook not needed (or it's not possible to use it due
+ // to missing dependency), remove it.
+ delete this.get;
+ return;
+ }
+
+ // Hook needed; redefine it so that the support test is not executed again.
+ return ( this.get = hookFn ).apply( this, arguments );
+ }
+ };
+}
+
+
+var
+
+ // 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]).+)/,
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: "0",
+ fontWeight: "400"
+ },
+
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
+ emptyStyle = document.createElement( "div" ).style;
+
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( name ) {
+
+ // Shortcut for names that are not vendor prefixed
+ if ( name in emptyStyle ) {
+ return name;
+ }
+
+ // Check for vendor prefixed names
+ var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in emptyStyle ) {
+ return name;
+ }
+ }
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+
+ // Any relative (+/-) values have already been
+ // normalized at this point
+ var matches = rcssNum.exec( value );
+ return matches ?
+
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "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.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;
+ }
+
+ // Check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox &&
+ ( 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";
+}
+
+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 ] = dataPriv.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 ] = dataPriv.access(
+ elem,
+ "olddisplay",
+ defaultDisplay( elem.nodeName )
+ );
+ }
+ } else {
+ hidden = isHidden( elem );
+
+ if ( display !== "none" || !hidden ) {
+ dataPriv.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.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: {
+ "animationIterationCount": true,
+ "columnCount": true,
+ "fillOpacity": true,
+ "flexGrow": true,
+ "flexShrink": 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: {
+ "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( origName ) || origName );
+
+ // Gets hook for the prefixed version, then unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // Convert "+=" or "-=" to relative numbers (#7345)
+ if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
+ value = adjustCSS( elem, name, ret );
+
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that null and NaN values aren't set (#7116)
+ if ( value == null || value !== value ) {
+ return;
+ }
+
+ // If a number was passed in, add the unit (except for certain CSS properties)
+ if ( type === "number" ) {
+ value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
+ }
+
+ // Support: IE9-11+
+ // background-* props affect original clone's values
+ if ( !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( origName ) || origName );
+
+ // Try prefixed name followed by the unprefixed name
+ 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 ];
+ }
+
+ // Make numeric if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || isFinite( num ) ? num || 0 : val;
+ }
+ return val;
+ }
+} );
+
+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
+ // but it must have a current display style that would benefit
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
+ elem.offsetWidth === 0 ?
+ swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ } ) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var matches,
+ styles = extra && getStyles( elem ),
+ subtract = extra && augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ );
+
+ // Convert to pixels if value adjustment is needed
+ if ( subtract && ( matches = rcssNum.exec( value ) ) &&
+ ( matches[ 3 ] || "px" ) !== "px" ) {
+
+ elem.style[ name ] = value;
+ value = jQuery.css( elem, name );
+ }
+
+ return setPositiveNumber( elem, value, subtract );
+ }
+ };
+} );
+
+jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
+ function( elem, computed ) {
+ if ( computed ) {
+ return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
+ elem.getBoundingClientRect().left -
+ swap( elem, { marginLeft: 0 }, function() {
+ return elem.getBoundingClientRect().left;
+ } )
+ ) + "px";
+ }
+ }
+);
+
+// Support: Android 2.3
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+ function( elem, computed ) {
+ if ( computed ) {
+ return swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+);
+
+// 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;
+ }
+} );
+
+jQuery.fn.extend( {
+ css: function( name, value ) {
+ return 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();
+ }
+ } );
+ }
+} );
+
+
+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 || jQuery.easing._default;
+ 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;
+
+ // Use a property on the element directly when it is not a DOM element,
+ // or when there is no matching style property that exists.
+ if ( tween.elem.nodeType !== 1 ||
+ tween.elem[ tween.prop ] != null && 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.
+ // 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 available and use plain properties where available.
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.nodeType === 1 &&
+ ( 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.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p * Math.PI ) / 2;
+ },
+ _default: "swing"
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+ fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rrun = /queueHooks$/;
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ window.setTimeout( function() {
+ fxNow = undefined;
+ } );
+ return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ i = 0,
+ attrs = { height: type };
+
+ // If we include width, step value is 1 to do all cssExpand values,
+ // otherwise 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;
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.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 defaultPrefilter( elem, props, opts ) {
+ /* jshint validthis: true */
+ var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHidden( elem ),
+ dataShow = dataPriv.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() {
+
+ // Ensure the complete handler is 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
+ display = jQuery.css( elem, "display" );
+
+ // Test default display if display is currently "none"
+ checkDisplay = display === "none" ?
+ dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+ if ( checkDisplay === "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 );
+
+ // Any non-fx value stops us from restoring the original display value
+ } else {
+ display = undefined;
+ }
+ }
+
+ if ( !jQuery.isEmptyObject( orig ) ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = dataPriv.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;
+
+ dataPriv.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;
+ }
+ }
+ }
+
+ // If this is a noop like .hide().hide(), restore an overwritten display value
+ } else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) {
+ style.display = display;
+ }
+}
+
+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 won't overwrite existing keys.
+ // Reusing 'index' 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;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = Animation.prefilters.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 ),
+
+ // Support: Android 2.3
+ // 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: {},
+ easing: jQuery.easing._default
+ }, 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.notifyWith( elem, [ animation, 1, 0 ] );
+ 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 = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ if ( jQuery.isFunction( result.stop ) ) {
+ jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
+ jQuery.proxy( result.stop, 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 );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+ tweeners: {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value );
+ adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
+ return tween;
+ } ]
+ },
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.match( rnotwhite );
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
+ Animation.tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilters: [ defaultPrefilter ],
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ Animation.prefilters.unshift( callback );
+ } else {
+ Animation.prefilters.push( 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.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 || dataPriv.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 = dataPriv.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 = dataPriv.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;
+ } );
+ }
+} );
+
+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 );
+ };
+} );
+
+// 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.timers = [];
+jQuery.fx.tick = function() {
+ var timer,
+ i = 0,
+ timers = jQuery.timers;
+
+ 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 ) {
+ jQuery.timers.push( timer );
+ if ( timer() ) {
+ jQuery.fx.start();
+ } else {
+ jQuery.timers.pop();
+ }
+};
+
+jQuery.fx.interval = 13;
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ window.clearInterval( timerId );
+
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+
+ // Default speed
+ _default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.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 = window.setTimeout( next, time );
+ hooks.stop = function() {
+ window.clearTimeout( timeout );
+ };
+ } );
+};
+
+
+( function() {
+ var input = document.createElement( "input" ),
+ select = document.createElement( "select" ),
+ opt = select.appendChild( document.createElement( "option" ) );
+
+ input.type = "checkbox";
+
+ // Support: iOS<=5.1, Android<=4.2+
+ // Default value for a checkbox should be "on"
+ support.checkOn = input.value !== "";
+
+ // Support: IE<=11+
+ // Must access selectedIndex to make default options select
+ support.optSelected = opt.selected;
+
+ // Support: Android<=2.3
+ // Options inside disabled selects are incorrectly marked as disabled
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE<=11+
+ // An input loses its value after becoming a radio
+ input = document.createElement( "input" );
+ input.value = "t";
+ input.type = "radio";
+ support.radioValue = input.value === "t";
+} )();
+
+
+var boolHook,
+ attrHandle = jQuery.expr.attrHandle;
+
+jQuery.fn.extend( {
+ attr: function( name, value ) {
+ return access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each( function() {
+ jQuery.removeAttr( this, name );
+ } );
+ }
+} );
+
+jQuery.extend( {
+ attr: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set attributes on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ 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 : undefined );
+ }
+
+ if ( value !== undefined ) {
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+ }
+
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ? undefined : ret;
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !support.radioValue && value === "radio" &&
+ jQuery.nodeName( elem, "input" ) ) {
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( 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 );
+ }
+ }
+ }
+} );
+
+// 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 = attrHandle[ name ] || jQuery.find.attr;
+
+ attrHandle[ name ] = function( elem, name, isXML ) {
+ var ret, handle;
+ if ( !isXML ) {
+
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ name ];
+ attrHandle[ name ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ name.toLowerCase() :
+ null;
+ attrHandle[ name ] = handle;
+ }
+ return ret;
+ };
+} );
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button)$/i,
+ rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend( {
+ prop: function( name, value ) {
+ return access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ return this.each( function() {
+ delete this[ jQuery.propFix[ name ] || name ];
+ } );
+ }
+} );
+
+jQuery.extend( {
+ prop: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set properties on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ return ( elem[ name ] = value );
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ return elem[ name ];
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+
+ // elem.tabIndex doesn't always return the
+ // correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ // Use proper attribute retrieval(#12072)
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+ return tabindex ?
+ parseInt( tabindex, 10 ) :
+ rfocusable.test( elem.nodeName ) ||
+ rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ -1;
+ }
+ }
+ },
+
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ }
+} );
+
+// Support: IE <=11 only
+// Accessing the selectedIndex property
+// forces the browser to respect setting selected
+// on the option
+// The getter ensures a default option is selected
+// when in an optgroup
+if ( !support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+ if ( parent && parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ return null;
+ },
+ set: function( elem ) {
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
+ };
+}
+
+jQuery.each( [
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+} );
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+function getClass( elem ) {
+ return elem.getAttribute && elem.getAttribute( "class" ) || "";
+}
+
+jQuery.fn.extend( {
+ addClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( !arguments.length ) {
+ return this.attr( "class", "" );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ 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, getClass( this ), stateVal ),
+ stateVal
+ );
+ } );
+ }
+
+ return this.each( function() {
+ var className, i, self, classNames;
+
+ if ( type === "string" ) {
+
+ // Toggle individual class names
+ i = 0;
+ self = jQuery( this );
+ classNames = value.match( 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 ( value === undefined || type === "boolean" ) {
+ className = getClass( this );
+ if ( className ) {
+
+ // Store className if set
+ dataPriv.set( this, "__className__", 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.
+ if ( this.setAttribute ) {
+ this.setAttribute( "class",
+ className || value === false ?
+ "" :
+ dataPriv.get( this, "__className__" ) || ""
+ );
+ }
+ }
+ } );
+ },
+
+ hasClass: function( selector ) {
+ var className, elem,
+ i = 0;
+
+ className = " " + selector + " ";
+ while ( ( elem = this[ i++ ] ) ) {
+ if ( elem.nodeType === 1 &&
+ ( " " + getClass( elem ) + " " ).replace( rclass, " " )
+ .indexOf( className ) > -1
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} );
+
+
+
+
+var rreturn = /\r/g,
+ rspaces = /[\x20\t\r\n\f]+/g;
+
+jQuery.fn.extend( {
+ 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 ) {
+
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+
+ // Support: IE10-11+
+ // option.text throws exceptions (#14686, #14858)
+ // Strip and collapse whitespace
+ // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
+ jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
+ }
+ },
+ 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 ];
+
+ // IE8-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
+ ( 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.valHooks.option.get( option ), values ) > -1
+ ) {
+ optionSet = true;
+ }
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ }
+} );
+
+// 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 ) > -1 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ return elem.getAttribute( "value" ) === null ? "on" : elem.value;
+ };
+ }
+} );
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
+
+jQuery.extend( jQuery.event, {
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+
+ var i, cur, tmp, bubbleType, ontype, handle, special,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = 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( "." ) > -1 ) {
+
+ // 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.rnamespace = 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 = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
+ dataPriv.get( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === 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 ) &&
+ 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;
+ },
+
+ // Piggyback on a donor event to simulate a different one
+ // Used only for `focus(in | out)` events
+ simulate: function( type, elem, event ) {
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true
+ }
+ );
+
+ jQuery.event.trigger( e, null, elem );
+ }
+
+} );
+
+jQuery.fn.extend( {
+
+ 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 );
+ }
+ }
+} );
+
+
+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 );
+ }
+} );
+
+
+
+
+support.focusin = "onfocusin" in window;
+
+
+// Support: Firefox
+// Firefox doesn't have focus(in | out) events
+// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
+//
+// Support: Chrome, Safari
+// focus(in | out) events fire after focus & blur events,
+// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
+// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857
+if ( !support.focusin ) {
+ jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix );
+
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix ) - 1;
+
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ dataPriv.remove( doc, fix );
+
+ } else {
+ dataPriv.access( doc, fix, attaches );
+ }
+ }
+ };
+ } );
+}
+var location = window.location;
+
+var nonce = jQuery.now();
+
+var rquery = ( /\?/ );
+
+
+
+// Support: Android 2.3
+// Workaround failure to string-cast null input
+jQuery.parseJSON = function( data ) {
+ return JSON.parse( data + "" );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+ var xml;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+
+ // Support: IE9
+ try {
+ xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
+ } catch ( e ) {
+ xml = undefined;
+ }
+
+ if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+};
+
+
+var
+ 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 = /^\/\//,
+
+ /* 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( "*" ),
+
+ // Anchor tag for parsing the document origin
+ originAnchor = document.createElement( "a" );
+ originAnchor.href = location.href;
+
+// 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( 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;
+}
+
+/* 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 };
+}
+
+jQuery.extend( {
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: location.href,
+ type: "GET",
+ isLocal: rlocalProtocol.test( location.protocol ),
+ 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: /\bxml\b/,
+ html: /\bhtml/,
+ json: /\bjson\b/
+ },
+
+ 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,
+
+ // Url cleanup var
+ urlAnchor,
+
+ // 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 || location.href ) + "" ).replace( rhash, "" )
+ .replace( rprotocol, location.protocol + "//" );
+
+ // 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( rnotwhite ) || [ "" ];
+
+ // A cross-domain request is in order when the origin doesn't match the current origin.
+ if ( s.crossDomain == null ) {
+ urlAnchor = document.createElement( "a" );
+
+ // Support: IE8-11+
+ // IE throws exception if url is malformed, e.g. http://example.com:80x/
+ try {
+ urlAnchor.href = s.url;
+
+ // Support: IE8-11+
+ // Anchor's host property isn't correctly set when s.url is relative
+ urlAnchor.href = urlAnchor.href;
+ s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+ urlAnchor.protocol + "//" + urlAnchor.host;
+ } catch ( e ) {
+
+ // If there is an error parsing the URL, assume it is crossDomain,
+ // it can be rejected by the transport if it is invalid
+ s.crossDomain = true;
+ }
+ }
+
+ // 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
+ // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+ fireGlobals = jQuery.event && 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 += ( 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_=" + nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + 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 ] );
+ }
+
+ // If request was aborted inside ajaxSend, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = window.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 ) {
+ window.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 {
+
+ // Extract error from statusText and normalize 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;
+ }
+
+ // The url can be an options object (which then must have .url)
+ return jQuery.ajax( jQuery.extend( {
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ }, jQuery.isPlainObject( url ) && url ) );
+ };
+} );
+
+
+jQuery._evalUrl = function( url ) {
+ return jQuery.ajax( {
+ url: url,
+
+ // Make this explicit, since user can override this through ajaxSetup (#11264)
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ } );
+};
+
+
+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();
+ }
+} );
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+ return !jQuery.expr.filters.visible( elem );
+};
+jQuery.expr.filters.visible = function( elem ) {
+
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ // Use OR instead of AND as the element is not visible if either is true
+ // See tickets #10406 and #13132
+ return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0;
+};
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+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" && v != null ? 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 );
+ }
+}
+
+// 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, "+" );
+};
+
+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 || !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();
+ }
+} );
+
+
+jQuery.ajaxSettings.xhr = function() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch ( e ) {}
+};
+
+var 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
+ },
+ xhrSupported = jQuery.ajaxSettings.xhr();
+
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport( function( options ) {
+ var callback, errorCallback;
+
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( support.cors || xhrSupported && !options.crossDomain ) {
+ return {
+ send: function( headers, complete ) {
+ var i,
+ 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 ) {
+ callback = errorCallback = xhr.onload =
+ xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
+
+ if ( type === "abort" ) {
+ xhr.abort();
+ } else if ( type === "error" ) {
+
+ // Support: IE9
+ // On a manual native abort, IE9 throws
+ // errors on any property access that is not readyState
+ if ( typeof xhr.status !== "number" ) {
+ complete( 0, "error" );
+ } else {
+ complete(
+
+ // File: protocol always yields status 0; see #8605, #14207
+ xhr.status,
+ xhr.statusText
+ );
+ }
+ } else {
+ complete(
+ xhrSuccessStatus[ xhr.status ] || xhr.status,
+ xhr.statusText,
+
+ // Support: IE9 only
+ // IE9 has no XHR2 but throws on binary (trac-11426)
+ // For XHR2 non-text, let the caller handle it (gh-2498)
+ ( xhr.responseType || "text" ) !== "text" ||
+ typeof xhr.responseText !== "string" ?
+ { binary: xhr.response } :
+ { text: xhr.responseText },
+ xhr.getAllResponseHeaders()
+ );
+ }
+ }
+ };
+ };
+
+ // Listen to events
+ xhr.onload = callback();
+ errorCallback = xhr.onerror = callback( "error" );
+
+ // Support: IE9
+ // Use onreadystatechange to replace onabort
+ // to handle uncaught aborts
+ if ( xhr.onabort !== undefined ) {
+ xhr.onabort = errorCallback;
+ } else {
+ xhr.onreadystatechange = function() {
+
+ // Check readyState before timeout as it changes
+ if ( xhr.readyState === 4 ) {
+
+ // Allow onerror to be called first,
+ // but that will not handle a native abort
+ // Also, save errorCallback to a variable
+ // as xhr.onerror cannot be accessed
+ window.setTimeout( function() {
+ if ( callback ) {
+ errorCallback();
+ }
+ } );
+ }
+ };
+ }
+
+ // Create the abort callback
+ callback = callback( "abort" );
+
+ try {
+
+ // Do send the request (this may raise an exception)
+ xhr.send( options.hasContent && options.data || null );
+ } catch ( e ) {
+
+ // #14683: Only rethrow if this hasn't been notified as an error yet
+ if ( callback ) {
+ throw e;
+ }
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup( {
+ accepts: {
+ script: "text/javascript, application/javascript, " +
+ "application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /\b(?:java|ecma)script\b/
+ },
+ 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( {
+ 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 );
+ }
+ }
+ );
+
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ 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 + "_" + ( 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" ) === 0 &&
+ 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 += ( 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() {
+
+ // If previous value didn't exist - remove it
+ if ( overwritten === undefined ) {
+ jQuery( window ).removeProp( callbackName );
+
+ // Otherwise restore preexisting value
+ } else {
+ 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";
+ }
+} );
+
+
+
+
+// Argument "data" should be 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
+jQuery.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 = buildFragment( [ data ], context, scripts );
+
+ if ( scripts && scripts.length ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+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 > -1 ) {
+ selector = jQuery.trim( 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.
+ // Make value of this field explicit since
+ // user can override it through ajaxSetup method
+ type: type || "GET",
+ 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 );
+
+ // If the request succeeds, this function gets "data", "status", "jqXHR"
+ // but they are ignored because response was set above.
+ // If it fails, this function gets "jqXHR", "status", "error"
+ } ).always( callback && function( jqXHR, status ) {
+ self.each( function() {
+ callback.apply( this, 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.expr.filters.animated = function( elem ) {
+ return jQuery.grep( jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ } ).length;
+};
+
+
+
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
+}
+
+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 ) ) {
+
+ // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
+ options = options.call( elem, i, jQuery.extend( {}, 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( {
+ 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;
+ }
+
+ box = elem.getBoundingClientRect();
+ win = getWindow( doc );
+ return {
+ top: box.top + win.pageYOffset - docElem.clientTop,
+ left: box.left + win.pageXOffset - docElem.clientLeft
+ };
+ },
+
+ 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 its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+
+ // Assume getBoundingClientRect is there 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 )
+ };
+ },
+
+ // This method will return documentElement in the following cases:
+ // 1) For the element inside the iframe without offsetParent, this method will return
+ // documentElement of the parent window
+ // 2) For the hidden or detached element
+ // 3) For body or html element, i.e. in case of the html node - it will return itself
+ //
+ // but those exceptions were never presented as a real life use-cases
+ // and might be considered as more preferable results.
+ //
+ // This logic, however, is not guaranteed and can change at any point in the future
+ offsetParent: function() {
+ return this.map( function() {
+ var offsetParent = this.offsetParent;
+
+ while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || documentElement;
+ } );
+ }
+} );
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = "pageYOffset" === prop;
+
+ jQuery.fn[ method ] = function( val ) {
+ return 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 : win.pageXOffset,
+ top ? val : win.pageYOffset
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length );
+ };
+} );
+
+// Support: Safari<7-8+, Chrome<37-44+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ 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;
+ }
+ }
+ );
+} );
+
+
+// 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 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 );
+ };
+ } );
+} );
+
+
+jQuery.fn.extend( {
+
+ 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 );
+ },
+ size: function() {
+ return this.length;
+ }
+} );
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// 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.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function() {
+ return jQuery;
+ } );
+}
+
+
+
+var
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( !noGlobal ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+return jQuery;
+}));
diff --git a/debian/missing-sources/jquery.easypiechart.js b/debian/missing-sources/jquery.easypiechart-97b5824.js
index 5ac3dc1b3..5ac3dc1b3 100644
--- a/debian/missing-sources/jquery.easypiechart.js
+++ b/debian/missing-sources/jquery.easypiechart-97b5824.js
diff --git a/debian/missing-sources/jquery.nanoscroller.js b/debian/missing-sources/jquery.nanoscroller.js
deleted file mode 100644
index edcbfaa44..000000000
--- a/debian/missing-sources/jquery.nanoscroller.js
+++ /dev/null
@@ -1,1000 +0,0 @@
-/*! nanoScrollerJS - v0.8.7 - 2015
-* http://jamesflorentino.github.com/nanoScrollerJS/
-* Copyright (c) 2015 James Florentino; Licensed MIT */
-(function(factory) {
- if (typeof define === 'function' && define.amd) {
- return define(['jquery'], function($) {
- return factory($, window, document);
- });
- } else if (typeof exports === 'object') {
- return module.exports = factory(require('jquery'), window, document);
- } else {
- return factory(jQuery, window, document);
- }
-})(function($, window, document) {
- "use strict";
- var BROWSER_IS_IE7, BROWSER_SCROLLBAR_WIDTH, DOMSCROLL, DOWN, DRAG, ENTER, KEYDOWN, KEYUP, MOUSEDOWN, MOUSEENTER, MOUSEMOVE, MOUSEUP, MOUSEWHEEL, NanoScroll, PANEDOWN, RESIZE, SCROLL, SCROLLBAR, TOUCHMOVE, UP, WHEEL, cAF, defaults, getBrowserScrollbarWidth, hasTransform, isFFWithBuggyScrollbar, rAF, transform, _elementStyle, _prefixStyle, _vendor;
- defaults = {
-
- /**
- a classname for the pane element.
- @property paneClass
- @type String
- @default 'nano-pane'
- */
- paneClass: 'nano-pane',
-
- /**
- a classname for the slider element.
- @property sliderClass
- @type String
- @default 'nano-slider'
- */
- sliderClass: 'nano-slider',
-
- /**
- a classname for the content element.
- @property contentClass
- @type String
- @default 'nano-content'
- */
- contentClass: 'nano-content',
-
- /**
- a classname for enabled mode
- @property enabledClass
- @type String
- @default 'has-scrollbar'
- */
- enabledClass: 'has-scrollbar',
-
- /**
- a classname for flashed mode
- @property flashedClass
- @type String
- @default 'flashed'
- */
- flashedClass: 'flashed',
-
- /**
- a classname for active mode
- @property activeClass
- @type String
- @default 'active'
- */
- activeClass: 'active',
-
- /**
- a setting to enable native scrolling in iOS devices.
- @property iOSNativeScrolling
- @type Boolean
- @default false
- */
- iOSNativeScrolling: false,
-
- /**
- a setting to prevent the rest of the page being
- scrolled when user scrolls the `.content` element.
- @property preventPageScrolling
- @type Boolean
- @default false
- */
- preventPageScrolling: false,
-
- /**
- a setting to disable binding to the resize event.
- @property disableResize
- @type Boolean
- @default false
- */
- disableResize: false,
-
- /**
- a setting to make the scrollbar always visible.
- @property alwaysVisible
- @type Boolean
- @default false
- */
- alwaysVisible: false,
-
- /**
- a default timeout for the `flash()` method.
- @property flashDelay
- @type Number
- @default 1500
- */
- flashDelay: 1500,
-
- /**
- a minimum height for the `.slider` element.
- @property sliderMinHeight
- @type Number
- @default 20
- */
- sliderMinHeight: 20,
-
- /**
- a maximum height for the `.slider` element.
- @property sliderMaxHeight
- @type Number
- @default null
- */
- sliderMaxHeight: null,
-
- /**
- an alternate document context.
- @property documentContext
- @type Document
- @default null
- */
- documentContext: null,
-
- /**
- an alternate window context.
- @property windowContext
- @type Window
- @default null
- */
- windowContext: null
- };
-
- /**
- @property SCROLLBAR
- @type String
- @static
- @final
- @private
- */
- SCROLLBAR = 'scrollbar';
-
- /**
- @property SCROLL
- @type String
- @static
- @final
- @private
- */
- SCROLL = 'scroll';
-
- /**
- @property MOUSEDOWN
- @type String
- @final
- @private
- */
- MOUSEDOWN = 'mousedown';
-
- /**
- @property MOUSEENTER
- @type String
- @final
- @private
- */
- MOUSEENTER = 'mouseenter';
-
- /**
- @property MOUSEMOVE
- @type String
- @static
- @final
- @private
- */
- MOUSEMOVE = 'mousemove';
-
- /**
- @property MOUSEWHEEL
- @type String
- @final
- @private
- */
- MOUSEWHEEL = 'mousewheel';
-
- /**
- @property MOUSEUP
- @type String
- @static
- @final
- @private
- */
- MOUSEUP = 'mouseup';
-
- /**
- @property RESIZE
- @type String
- @final
- @private
- */
- RESIZE = 'resize';
-
- /**
- @property DRAG
- @type String
- @static
- @final
- @private
- */
- DRAG = 'drag';
-
- /**
- @property ENTER
- @type String
- @static
- @final
- @private
- */
- ENTER = 'enter';
-
- /**
- @property UP
- @type String
- @static
- @final
- @private
- */
- UP = 'up';
-
- /**
- @property PANEDOWN
- @type String
- @static
- @final
- @private
- */
- PANEDOWN = 'panedown';
-
- /**
- @property DOMSCROLL
- @type String
- @static
- @final
- @private
- */
- DOMSCROLL = 'DOMMouseScroll';
-
- /**
- @property DOWN
- @type String
- @static
- @final
- @private
- */
- DOWN = 'down';
-
- /**
- @property WHEEL
- @type String
- @static
- @final
- @private
- */
- WHEEL = 'wheel';
-
- /**
- @property KEYDOWN
- @type String
- @static
- @final
- @private
- */
- KEYDOWN = 'keydown';
-
- /**
- @property KEYUP
- @type String
- @static
- @final
- @private
- */
- KEYUP = 'keyup';
-
- /**
- @property TOUCHMOVE
- @type String
- @static
- @final
- @private
- */
- TOUCHMOVE = 'touchmove';
-
- /**
- @property BROWSER_IS_IE7
- @type Boolean
- @static
- @final
- @private
- */
- BROWSER_IS_IE7 = window.navigator.appName === 'Microsoft Internet Explorer' && /msie 7./i.test(window.navigator.appVersion) && window.ActiveXObject;
-
- /**
- @property BROWSER_SCROLLBAR_WIDTH
- @type Number
- @static
- @default null
- @private
- */
- BROWSER_SCROLLBAR_WIDTH = null;
- rAF = window.requestAnimationFrame;
- cAF = window.cancelAnimationFrame;
- _elementStyle = document.createElement('div').style;
- _vendor = (function() {
- var i, transform, vendor, vendors, _i, _len;
- vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'];
- for (i = _i = 0, _len = vendors.length; _i < _len; i = ++_i) {
- vendor = vendors[i];
- transform = vendors[i] + 'ransform';
- if (transform in _elementStyle) {
- return vendors[i].substr(0, vendors[i].length - 1);
- }
- }
- return false;
- })();
- _prefixStyle = function(style) {
- if (_vendor === false) {
- return false;
- }
- if (_vendor === '') {
- return style;
- }
- return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
- };
- transform = _prefixStyle('transform');
- hasTransform = transform !== false;
-
- /**
- Returns browser's native scrollbar width
- @method getBrowserScrollbarWidth
- @return {Number} the scrollbar width in pixels
- @static
- @private
- */
- getBrowserScrollbarWidth = function() {
- var outer, outerStyle, scrollbarWidth;
- outer = document.createElement('div');
- outerStyle = outer.style;
- outerStyle.position = 'absolute';
- outerStyle.width = '100px';
- outerStyle.height = '100px';
- outerStyle.overflow = SCROLL;
- outerStyle.top = '-9999px';
- document.body.appendChild(outer);
- scrollbarWidth = outer.offsetWidth - outer.clientWidth;
- document.body.removeChild(outer);
- return scrollbarWidth;
- };
- isFFWithBuggyScrollbar = function() {
- var isOSXFF, ua, version;
- ua = window.navigator.userAgent;
- isOSXFF = /(?=.+Mac OS X)(?=.+Firefox)/.test(ua);
- if (!isOSXFF) {
- return false;
- }
- version = /Firefox\/\d{2}\./.exec(ua);
- if (version) {
- version = version[0].replace(/\D+/g, '');
- }
- return isOSXFF && +version > 23;
- };
-
- /**
- @class NanoScroll
- @param element {HTMLElement|Node} the main element
- @param options {Object} nanoScroller's options
- @constructor
- */
- NanoScroll = (function() {
- function NanoScroll(el, options) {
- this.el = el;
- this.options = options;
- BROWSER_SCROLLBAR_WIDTH || (BROWSER_SCROLLBAR_WIDTH = getBrowserScrollbarWidth());
- this.$el = $(this.el);
- this.doc = $(this.options.documentContext || document);
- this.win = $(this.options.windowContext || window);
- this.body = this.doc.find('body');
- this.$content = this.$el.children("." + this.options.contentClass);
- this.$content.attr('tabindex', this.options.tabIndex || 0);
- this.content = this.$content[0];
- this.previousPosition = 0;
- if (this.options.iOSNativeScrolling && (this.el.style.WebkitOverflowScrolling != null)) {
- this.nativeScrolling();
- } else {
- this.generate();
- }
- this.createEvents();
- this.addEvents();
- this.reset();
- }
-
-
- /**
- Prevents the rest of the page being scrolled
- when user scrolls the `.nano-content` element.
- @method preventScrolling
- @param event {Event}
- @param direction {String} Scroll direction (up or down)
- @private
- */
-
- NanoScroll.prototype.preventScrolling = function(e, direction) {
- if (!this.isActive) {
- return;
- }
- if (e.type === DOMSCROLL) {
- if (direction === DOWN && e.originalEvent.detail > 0 || direction === UP && e.originalEvent.detail < 0) {
- e.preventDefault();
- }
- } else if (e.type === MOUSEWHEEL) {
- if (!e.originalEvent || !e.originalEvent.wheelDelta) {
- return;
- }
- if (direction === DOWN && e.originalEvent.wheelDelta < 0 || direction === UP && e.originalEvent.wheelDelta > 0) {
- e.preventDefault();
- }
- }
- };
-
-
- /**
- Enable iOS native scrolling
- @method nativeScrolling
- @private
- */
-
- NanoScroll.prototype.nativeScrolling = function() {
- this.$content.css({
- WebkitOverflowScrolling: 'touch'
- });
- this.iOSNativeScrolling = true;
- this.isActive = true;
- };
-
-
- /**
- Updates those nanoScroller properties that
- are related to current scrollbar position.
- @method updateScrollValues
- @private
- */
-
- NanoScroll.prototype.updateScrollValues = function() {
- var content, direction;
- content = this.content;
- this.maxScrollTop = content.scrollHeight - content.clientHeight;
- this.prevScrollTop = this.contentScrollTop || 0;
- this.contentScrollTop = content.scrollTop;
- direction = this.contentScrollTop > this.previousPosition ? "down" : this.contentScrollTop < this.previousPosition ? "up" : "same";
- this.previousPosition = this.contentScrollTop;
- if (direction !== "same") {
- this.$el.trigger('update', {
- position: this.contentScrollTop,
- maximum: this.maxScrollTop,
- direction: direction
- });
- }
- if (!this.iOSNativeScrolling) {
- this.maxSliderTop = this.paneHeight - this.sliderHeight;
- this.sliderTop = this.maxScrollTop === 0 ? 0 : this.contentScrollTop * this.maxSliderTop / this.maxScrollTop;
- }
- };
-
-
- /**
- Updates CSS styles for current scroll position.
- Uses CSS 2d transfroms and `window.requestAnimationFrame` if available.
- @method setOnScrollStyles
- @private
- */
-
- NanoScroll.prototype.setOnScrollStyles = function() {
- var cssValue;
- if (hasTransform) {
- cssValue = {};
- cssValue[transform] = "translate(0, " + this.sliderTop + "px)";
- } else {
- cssValue = {
- top: this.sliderTop
- };
- }
- if (rAF) {
- if (cAF && this.scrollRAF) {
- cAF(this.scrollRAF);
- }
- this.scrollRAF = rAF((function(_this) {
- return function() {
- _this.scrollRAF = null;
- return _this.slider.css(cssValue);
- };
- })(this));
- } else {
- this.slider.css(cssValue);
- }
- };
-
-
- /**
- Creates event related methods
- @method createEvents
- @private
- */
-
- NanoScroll.prototype.createEvents = function() {
- this.events = {
- down: (function(_this) {
- return function(e) {
- _this.isBeingDragged = true;
- _this.offsetY = e.pageY - _this.slider.offset().top;
- if (!_this.slider.is(e.target)) {
- _this.offsetY = 0;
- }
- _this.pane.addClass(_this.options.activeClass);
- _this.doc.bind(MOUSEMOVE, _this.events[DRAG]).bind(MOUSEUP, _this.events[UP]);
- _this.body.bind(MOUSEENTER, _this.events[ENTER]);
- return false;
- };
- })(this),
- drag: (function(_this) {
- return function(e) {
- _this.sliderY = e.pageY - _this.$el.offset().top - _this.paneTop - (_this.offsetY || _this.sliderHeight * 0.5);
- _this.scroll();
- if (_this.contentScrollTop >= _this.maxScrollTop && _this.prevScrollTop !== _this.maxScrollTop) {
- _this.$el.trigger('scrollend');
- } else if (_this.contentScrollTop === 0 && _this.prevScrollTop !== 0) {
- _this.$el.trigger('scrolltop');
- }
- return false;
- };
- })(this),
- up: (function(_this) {
- return function(e) {
- _this.isBeingDragged = false;
- _this.pane.removeClass(_this.options.activeClass);
- _this.doc.unbind(MOUSEMOVE, _this.events[DRAG]).unbind(MOUSEUP, _this.events[UP]);
- _this.body.unbind(MOUSEENTER, _this.events[ENTER]);
- return false;
- };
- })(this),
- resize: (function(_this) {
- return function(e) {
- _this.reset();
- };
- })(this),
- panedown: (function(_this) {
- return function(e) {
- _this.sliderY = (e.offsetY || e.originalEvent.layerY) - (_this.sliderHeight * 0.5);
- _this.scroll();
- _this.events.down(e);
- return false;
- };
- })(this),
- scroll: (function(_this) {
- return function(e) {
- _this.updateScrollValues();
- if (_this.isBeingDragged) {
- return;
- }
- if (!_this.iOSNativeScrolling) {
- _this.sliderY = _this.sliderTop;
- _this.setOnScrollStyles();
- }
- if (e == null) {
- return;
- }
- if (_this.contentScrollTop >= _this.maxScrollTop) {
- if (_this.options.preventPageScrolling) {
- _this.preventScrolling(e, DOWN);
- }
- if (_this.prevScrollTop !== _this.maxScrollTop) {
- _this.$el.trigger('scrollend');
- }
- } else if (_this.contentScrollTop === 0) {
- if (_this.options.preventPageScrolling) {
- _this.preventScrolling(e, UP);
- }
- if (_this.prevScrollTop !== 0) {
- _this.$el.trigger('scrolltop');
- }
- }
- };
- })(this),
- wheel: (function(_this) {
- return function(e) {
- var delta;
- if (e == null) {
- return;
- }
- delta = e.delta || e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.detail || (e.originalEvent && -e.originalEvent.detail);
- if (delta) {
- _this.sliderY += -delta / 3;
- }
- _this.scroll();
- return false;
- };
- })(this),
- enter: (function(_this) {
- return function(e) {
- var _ref;
- if (!_this.isBeingDragged) {
- return;
- }
- if ((e.buttons || e.which) !== 1) {
- return (_ref = _this.events)[UP].apply(_ref, arguments);
- }
- };
- })(this)
- };
- };
-
-
- /**
- Adds event listeners with jQuery.
- @method addEvents
- @private
- */
-
- NanoScroll.prototype.addEvents = function() {
- var events;
- this.removeEvents();
- events = this.events;
- if (!this.options.disableResize) {
- this.win.bind(RESIZE, events[RESIZE]);
- }
- if (!this.iOSNativeScrolling) {
- this.slider.bind(MOUSEDOWN, events[DOWN]);
- this.pane.bind(MOUSEDOWN, events[PANEDOWN]).bind("" + MOUSEWHEEL + " " + DOMSCROLL, events[WHEEL]);
- }
- this.$content.bind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
- };
-
-
- /**
- Removes event listeners with jQuery.
- @method removeEvents
- @private
- */
-
- NanoScroll.prototype.removeEvents = function() {
- var events;
- events = this.events;
- this.win.unbind(RESIZE, events[RESIZE]);
- if (!this.iOSNativeScrolling) {
- this.slider.unbind();
- this.pane.unbind();
- }
- this.$content.unbind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
- };
-
-
- /**
- Generates nanoScroller's scrollbar and elements for it.
- @method generate
- @chainable
- @private
- */
-
- NanoScroll.prototype.generate = function() {
- var contentClass, cssRule, currentPadding, options, pane, paneClass, sliderClass;
- options = this.options;
- paneClass = options.paneClass, sliderClass = options.sliderClass, contentClass = options.contentClass;
- if (!(pane = this.$el.children("." + paneClass)).length && !pane.children("." + sliderClass).length) {
- this.$el.append("<div class=\"" + paneClass + "\"><div class=\"" + sliderClass + "\" /></div>");
- }
- this.pane = this.$el.children("." + paneClass);
- this.slider = this.pane.find("." + sliderClass);
- if (BROWSER_SCROLLBAR_WIDTH === 0 && isFFWithBuggyScrollbar()) {
- currentPadding = window.getComputedStyle(this.content, null).getPropertyValue('padding-right').replace(/[^0-9.]+/g, '');
- cssRule = {
- right: -14,
- paddingRight: +currentPadding + 14
- };
- } else if (BROWSER_SCROLLBAR_WIDTH) {
- cssRule = {
- right: -BROWSER_SCROLLBAR_WIDTH
- };
- this.$el.addClass(options.enabledClass);
- }
- if (cssRule != null) {
- this.$content.css(cssRule);
- }
- return this;
- };
-
-
- /**
- @method restore
- @private
- */
-
- NanoScroll.prototype.restore = function() {
- this.stopped = false;
- if (!this.iOSNativeScrolling) {
- this.pane.show();
- }
- this.addEvents();
- };
-
-
- /**
- Resets nanoScroller's scrollbar.
- @method reset
- @chainable
- @example
- $(".nano").nanoScroller();
- */
-
- NanoScroll.prototype.reset = function() {
- var content, contentHeight, contentPosition, contentStyle, contentStyleOverflowY, paneBottom, paneHeight, paneOuterHeight, paneTop, parentMaxHeight, right, sliderHeight;
- if (this.iOSNativeScrolling) {
- this.contentHeight = this.content.scrollHeight;
- return;
- }
- if (!this.$el.find("." + this.options.paneClass).length) {
- this.generate().stop();
- }
- if (this.stopped) {
- this.restore();
- }
- content = this.content;
- contentStyle = content.style;
- contentStyleOverflowY = contentStyle.overflowY;
- if (BROWSER_IS_IE7) {
- this.$content.css({
- height: this.$content.height()
- });
- }
- contentHeight = content.scrollHeight + BROWSER_SCROLLBAR_WIDTH;
- parentMaxHeight = parseInt(this.$el.css("max-height"), 10);
- if (parentMaxHeight > 0) {
- this.$el.height("");
- this.$el.height(content.scrollHeight > parentMaxHeight ? parentMaxHeight : content.scrollHeight);
- }
- paneHeight = this.pane.outerHeight(false);
- paneTop = parseInt(this.pane.css('top'), 10);
- paneBottom = parseInt(this.pane.css('bottom'), 10);
- paneOuterHeight = paneHeight + paneTop + paneBottom;
- sliderHeight = Math.round(paneOuterHeight / contentHeight * paneHeight);
- if (sliderHeight < this.options.sliderMinHeight) {
- sliderHeight = this.options.sliderMinHeight;
- } else if ((this.options.sliderMaxHeight != null) && sliderHeight > this.options.sliderMaxHeight) {
- sliderHeight = this.options.sliderMaxHeight;
- }
- if (contentStyleOverflowY === SCROLL && contentStyle.overflowX !== SCROLL) {
- sliderHeight += BROWSER_SCROLLBAR_WIDTH;
- }
- this.maxSliderTop = paneOuterHeight - sliderHeight;
- this.contentHeight = contentHeight;
- this.paneHeight = paneHeight;
- this.paneOuterHeight = paneOuterHeight;
- this.sliderHeight = sliderHeight;
- this.paneTop = paneTop;
- this.slider.height(sliderHeight);
- this.events.scroll();
- this.pane.show();
- this.isActive = true;
- if ((content.scrollHeight === content.clientHeight) || (this.pane.outerHeight(true) >= content.scrollHeight && contentStyleOverflowY !== SCROLL)) {
- this.pane.hide();
- this.isActive = false;
- } else if (this.el.clientHeight === content.scrollHeight && contentStyleOverflowY === SCROLL) {
- this.slider.hide();
- } else {
- this.slider.show();
- }
- this.pane.css({
- opacity: (this.options.alwaysVisible ? 1 : ''),
- visibility: (this.options.alwaysVisible ? 'visible' : '')
- });
- contentPosition = this.$content.css('position');
- if (contentPosition === 'static' || contentPosition === 'relative') {
- right = parseInt(this.$content.css('right'), 10);
- if (right) {
- this.$content.css({
- right: '',
- marginRight: right
- });
- }
- }
- return this;
- };
-
-
- /**
- @method scroll
- @private
- @example
- $(".nano").nanoScroller({ scroll: 'top' });
- */
-
- NanoScroll.prototype.scroll = function() {
- if (!this.isActive) {
- return;
- }
- this.sliderY = Math.max(0, this.sliderY);
- this.sliderY = Math.min(this.maxSliderTop, this.sliderY);
- this.$content.scrollTop(this.maxScrollTop * this.sliderY / this.maxSliderTop);
- if (!this.iOSNativeScrolling) {
- this.updateScrollValues();
- this.setOnScrollStyles();
- }
- return this;
- };
-
-
- /**
- Scroll at the bottom with an offset value
- @method scrollBottom
- @param offsetY {Number}
- @chainable
- @example
- $(".nano").nanoScroller({ scrollBottom: value });
- */
-
- NanoScroll.prototype.scrollBottom = function(offsetY) {
- if (!this.isActive) {
- return;
- }
- this.$content.scrollTop(this.contentHeight - this.$content.height() - offsetY).trigger(MOUSEWHEEL);
- this.stop().restore();
- return this;
- };
-
-
- /**
- Scroll at the top with an offset value
- @method scrollTop
- @param offsetY {Number}
- @chainable
- @example
- $(".nano").nanoScroller({ scrollTop: value });
- */
-
- NanoScroll.prototype.scrollTop = function(offsetY) {
- if (!this.isActive) {
- return;
- }
- this.$content.scrollTop(+offsetY).trigger(MOUSEWHEEL);
- this.stop().restore();
- return this;
- };
-
-
- /**
- Scroll to an element
- @method scrollTo
- @param node {Node} A node to scroll to.
- @chainable
- @example
- $(".nano").nanoScroller({ scrollTo: $('#a_node') });
- */
-
- NanoScroll.prototype.scrollTo = function(node) {
- if (!this.isActive) {
- return;
- }
- this.scrollTop(this.$el.find(node).get(0).offsetTop);
- return this;
- };
-
-
- /**
- To stop the operation.
- This option will tell the plugin to disable all event bindings and hide the gadget scrollbar from the UI.
- @method stop
- @chainable
- @example
- $(".nano").nanoScroller({ stop: true });
- */
-
- NanoScroll.prototype.stop = function() {
- if (cAF && this.scrollRAF) {
- cAF(this.scrollRAF);
- this.scrollRAF = null;
- }
- this.stopped = true;
- this.removeEvents();
- if (!this.iOSNativeScrolling) {
- this.pane.hide();
- }
- return this;
- };
-
-
- /**
- Destroys nanoScroller and restores browser's native scrollbar.
- @method destroy
- @chainable
- @example
- $(".nano").nanoScroller({ destroy: true });
- */
-
- NanoScroll.prototype.destroy = function() {
- if (!this.stopped) {
- this.stop();
- }
- if (!this.iOSNativeScrolling && this.pane.length) {
- this.pane.remove();
- }
- if (BROWSER_IS_IE7) {
- this.$content.height('');
- }
- this.$content.removeAttr('tabindex');
- if (this.$el.hasClass(this.options.enabledClass)) {
- this.$el.removeClass(this.options.enabledClass);
- this.$content.css({
- right: ''
- });
- }
- return this;
- };
-
-
- /**
- To flash the scrollbar gadget for an amount of time defined in plugin settings (defaults to 1,5s).
- Useful if you want to show the user (e.g. on pageload) that there is more content waiting for him.
- @method flash
- @chainable
- @example
- $(".nano").nanoScroller({ flash: true });
- */
-
- NanoScroll.prototype.flash = function() {
- if (this.iOSNativeScrolling) {
- return;
- }
- if (!this.isActive) {
- return;
- }
- this.reset();
- this.pane.addClass(this.options.flashedClass);
- setTimeout((function(_this) {
- return function() {
- _this.pane.removeClass(_this.options.flashedClass);
- };
- })(this), this.options.flashDelay);
- return this;
- };
-
- return NanoScroll;
-
- })();
- $.fn.nanoScroller = function(settings) {
- return this.each(function() {
- var options, scrollbar;
- if (!(scrollbar = this.nanoscroller)) {
- options = $.extend({}, defaults, settings);
- this.nanoscroller = scrollbar = new NanoScroll(this, options);
- }
- if (settings && typeof settings === "object") {
- $.extend(scrollbar.options, settings);
- if (settings.scrollBottom != null) {
- return scrollbar.scrollBottom(settings.scrollBottom);
- }
- if (settings.scrollTop != null) {
- return scrollbar.scrollTop(settings.scrollTop);
- }
- if (settings.scrollTo) {
- return scrollbar.scrollTo(settings.scrollTo);
- }
- if (settings.scroll === 'bottom') {
- return scrollbar.scrollBottom(0);
- }
- if (settings.scroll === 'top') {
- return scrollbar.scrollTop(0);
- }
- if (settings.scroll && settings.scroll instanceof $) {
- return scrollbar.scrollTo(settings.scroll);
- }
- if (settings.stop) {
- return scrollbar.stop();
- }
- if (settings.destroy) {
- return scrollbar.destroy();
- }
- if (settings.flash) {
- return scrollbar.flash();
- }
- }
- return scrollbar.reset();
- });
- };
- $.fn.nanoScroller.Constructor = NanoScroll;
-});
-
-//# sourceMappingURL=jquery.nanoscroller.js.map
diff --git a/debian/missing-sources/jquery.peity.js b/debian/missing-sources/jquery.peity-3.2.0.js
index 8c4c9a527..8c4c9a527 100644
--- a/debian/missing-sources/jquery.peity.js
+++ b/debian/missing-sources/jquery.peity-3.2.0.js
diff --git a/debian/missing-sources/jquery.sparkline.js b/debian/missing-sources/jquery.sparkline-2.1.2.js
index 721e03b76..721e03b76 100644
--- a/debian/missing-sources/jquery.sparkline.js
+++ b/debian/missing-sources/jquery.sparkline-2.1.2.js
diff --git a/debian/missing-sources/morris.css b/debian/missing-sources/morris-0.5.1.css
index 209f09156..209f09156 100644
--- a/debian/missing-sources/morris.css
+++ b/debian/missing-sources/morris-0.5.1.css
diff --git a/debian/missing-sources/morris.js b/debian/missing-sources/morris-0.5.1.js
index 60b3132df..3a1a83084 100644
--- a/debian/missing-sources/morris.js
+++ b/debian/missing-sources/morris-0.5.1.js
@@ -10,10 +10,7 @@ Licensed under the BSD-2-Clause License.
__slice = [].slice,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) {
- for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
- function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child;
- },
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
Morris = window.Morris = {};
diff --git a/debian/missing-sources/perfect-scrollbar-0.6.15.js b/debian/missing-sources/perfect-scrollbar-0.6.15.js
new file mode 100644
index 000000000..0eb1c879a
--- /dev/null
+++ b/debian/missing-sources/perfect-scrollbar-0.6.15.js
@@ -0,0 +1,1552 @@
+/* perfect-scrollbar v0.6.15 */
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+'use strict';
+
+var ps = require('../main');
+
+if (typeof define === 'function' && define.amd) {
+ // AMD
+ define(ps);
+} else {
+ // Add to a global object.
+ window.PerfectScrollbar = ps;
+ if (typeof window.Ps === 'undefined') {
+ window.Ps = ps;
+ }
+}
+
+},{"../main":7}],2:[function(require,module,exports){
+'use strict';
+
+function oldAdd(element, className) {
+ var classes = element.className.split(' ');
+ if (classes.indexOf(className) < 0) {
+ classes.push(className);
+ }
+ element.className = classes.join(' ');
+}
+
+function oldRemove(element, className) {
+ var classes = element.className.split(' ');
+ var idx = classes.indexOf(className);
+ if (idx >= 0) {
+ classes.splice(idx, 1);
+ }
+ element.className = classes.join(' ');
+}
+
+exports.add = function (element, className) {
+ if (element.classList) {
+ element.classList.add(className);
+ } else {
+ oldAdd(element, className);
+ }
+};
+
+exports.remove = function (element, className) {
+ if (element.classList) {
+ element.classList.remove(className);
+ } else {
+ oldRemove(element, className);
+ }
+};
+
+exports.list = function (element) {
+ if (element.classList) {
+ return Array.prototype.slice.apply(element.classList);
+ } else {
+ return element.className.split(' ');
+ }
+};
+
+},{}],3:[function(require,module,exports){
+'use strict';
+
+var DOM = {};
+
+DOM.e = function (tagName, className) {
+ var element = document.createElement(tagName);
+ element.className = className;
+ return element;
+};
+
+DOM.appendTo = function (child, parent) {
+ parent.appendChild(child);
+ return child;
+};
+
+function cssGet(element, styleName) {
+ return window.getComputedStyle(element)[styleName];
+}
+
+function cssSet(element, styleName, styleValue) {
+ if (typeof styleValue === 'number') {
+ styleValue = styleValue.toString() + 'px';
+ }
+ element.style[styleName] = styleValue;
+ return element;
+}
+
+function cssMultiSet(element, obj) {
+ for (var key in obj) {
+ var val = obj[key];
+ if (typeof val === 'number') {
+ val = val.toString() + 'px';
+ }
+ element.style[key] = val;
+ }
+ return element;
+}
+
+DOM.css = function (element, styleNameOrObject, styleValue) {
+ if (typeof styleNameOrObject === 'object') {
+ // multiple set with object
+ return cssMultiSet(element, styleNameOrObject);
+ } else {
+ if (typeof styleValue === 'undefined') {
+ return cssGet(element, styleNameOrObject);
+ } else {
+ return cssSet(element, styleNameOrObject, styleValue);
+ }
+ }
+};
+
+DOM.matches = function (element, query) {
+ if (typeof element.matches !== 'undefined') {
+ return element.matches(query);
+ } else {
+ if (typeof element.matchesSelector !== 'undefined') {
+ return element.matchesSelector(query);
+ } else if (typeof element.webkitMatchesSelector !== 'undefined') {
+ return element.webkitMatchesSelector(query);
+ } else if (typeof element.mozMatchesSelector !== 'undefined') {
+ return element.mozMatchesSelector(query);
+ } else if (typeof element.msMatchesSelector !== 'undefined') {
+ return element.msMatchesSelector(query);
+ }
+ }
+};
+
+DOM.remove = function (element) {
+ if (typeof element.remove !== 'undefined') {
+ element.remove();
+ } else {
+ if (element.parentNode) {
+ element.parentNode.removeChild(element);
+ }
+ }
+};
+
+DOM.queryChildren = function (element, selector) {
+ return Array.prototype.filter.call(element.childNodes, function (child) {
+ return DOM.matches(child, selector);
+ });
+};
+
+module.exports = DOM;
+
+},{}],4:[function(require,module,exports){
+'use strict';
+
+var EventElement = function (element) {
+ this.element = element;
+ this.events = {};
+};
+
+EventElement.prototype.bind = function (eventName, handler) {
+ if (typeof this.events[eventName] === 'undefined') {
+ this.events[eventName] = [];
+ }
+ this.events[eventName].push(handler);
+ this.element.addEventListener(eventName, handler, false);
+};
+
+EventElement.prototype.unbind = function (eventName, handler) {
+ var isHandlerProvided = (typeof handler !== 'undefined');
+ this.events[eventName] = this.events[eventName].filter(function (hdlr) {
+ if (isHandlerProvided && hdlr !== handler) {
+ return true;
+ }
+ this.element.removeEventListener(eventName, hdlr, false);
+ return false;
+ }, this);
+};
+
+EventElement.prototype.unbindAll = function () {
+ for (var name in this.events) {
+ this.unbind(name);
+ }
+};
+
+var EventManager = function () {
+ this.eventElements = [];
+};
+
+EventManager.prototype.eventElement = function (element) {
+ var ee = this.eventElements.filter(function (eventElement) {
+ return eventElement.element === element;
+ })[0];
+ if (typeof ee === 'undefined') {
+ ee = new EventElement(element);
+ this.eventElements.push(ee);
+ }
+ return ee;
+};
+
+EventManager.prototype.bind = function (element, eventName, handler) {
+ this.eventElement(element).bind(eventName, handler);
+};
+
+EventManager.prototype.unbind = function (element, eventName, handler) {
+ this.eventElement(element).unbind(eventName, handler);
+};
+
+EventManager.prototype.unbindAll = function () {
+ for (var i = 0; i < this.eventElements.length; i++) {
+ this.eventElements[i].unbindAll();
+ }
+};
+
+EventManager.prototype.once = function (element, eventName, handler) {
+ var ee = this.eventElement(element);
+ var onceHandler = function (e) {
+ ee.unbind(eventName, onceHandler);
+ handler(e);
+ };
+ ee.bind(eventName, onceHandler);
+};
+
+module.exports = EventManager;
+
+},{}],5:[function(require,module,exports){
+'use strict';
+
+module.exports = (function () {
+ function s4() {
+ return Math.floor((1 + Math.random()) * 0x10000)
+ .toString(16)
+ .substring(1);
+ }
+ return function () {
+ return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
+ s4() + '-' + s4() + s4() + s4();
+ };
+})();
+
+},{}],6:[function(require,module,exports){
+'use strict';
+
+var cls = require('./class');
+var dom = require('./dom');
+
+var toInt = exports.toInt = function (x) {
+ return parseInt(x, 10) || 0;
+};
+
+var clone = exports.clone = function (obj) {
+ if (!obj) {
+ return null;
+ } else if (obj.constructor === Array) {
+ return obj.map(clone);
+ } else if (typeof obj === 'object') {
+ var result = {};
+ for (var key in obj) {
+ result[key] = clone(obj[key]);
+ }
+ return result;
+ } else {
+ return obj;
+ }
+};
+
+exports.extend = function (original, source) {
+ var result = clone(original);
+ for (var key in source) {
+ result[key] = clone(source[key]);
+ }
+ return result;
+};
+
+exports.isEditable = function (el) {
+ return dom.matches(el, "input,[contenteditable]") ||
+ dom.matches(el, "select,[contenteditable]") ||
+ dom.matches(el, "textarea,[contenteditable]") ||
+ dom.matches(el, "button,[contenteditable]");
+};
+
+exports.removePsClasses = function (element) {
+ var clsList = cls.list(element);
+ for (var i = 0; i < clsList.length; i++) {
+ var className = clsList[i];
+ if (className.indexOf('ps-') === 0) {
+ cls.remove(element, className);
+ }
+ }
+};
+
+exports.outerWidth = function (element) {
+ return toInt(dom.css(element, 'width')) +
+ toInt(dom.css(element, 'paddingLeft')) +
+ toInt(dom.css(element, 'paddingRight')) +
+ toInt(dom.css(element, 'borderLeftWidth')) +
+ toInt(dom.css(element, 'borderRightWidth'));
+};
+
+exports.startScrolling = function (element, axis) {
+ cls.add(element, 'ps-in-scrolling');
+ if (typeof axis !== 'undefined') {
+ cls.add(element, 'ps-' + axis);
+ } else {
+ cls.add(element, 'ps-x');
+ cls.add(element, 'ps-y');
+ }
+};
+
+exports.stopScrolling = function (element, axis) {
+ cls.remove(element, 'ps-in-scrolling');
+ if (typeof axis !== 'undefined') {
+ cls.remove(element, 'ps-' + axis);
+ } else {
+ cls.remove(element, 'ps-x');
+ cls.remove(element, 'ps-y');
+ }
+};
+
+exports.env = {
+ isWebKit: 'WebkitAppearance' in document.documentElement.style,
+ supportsTouch: (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch),
+ supportsIePointer: window.navigator.msMaxTouchPoints !== null
+};
+
+},{"./class":2,"./dom":3}],7:[function(require,module,exports){
+'use strict';
+
+var destroy = require('./plugin/destroy');
+var initialize = require('./plugin/initialize');
+var update = require('./plugin/update');
+
+module.exports = {
+ initialize: initialize,
+ update: update,
+ destroy: destroy
+};
+
+},{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":21}],8:[function(require,module,exports){
+'use strict';
+
+module.exports = {
+ handlers: ['click-rail', 'drag-scrollbar', 'keyboard', 'wheel', 'touch'],
+ maxScrollbarLength: null,
+ minScrollbarLength: null,
+ scrollXMarginOffset: 0,
+ scrollYMarginOffset: 0,
+ suppressScrollX: false,
+ suppressScrollY: false,
+ swipePropagation: true,
+ useBothWheelAxes: false,
+ wheelPropagation: false,
+ wheelSpeed: 1,
+ theme: 'default'
+};
+
+},{}],9:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lib/helper');
+var dom = require('../lib/dom');
+var instances = require('./instances');
+
+module.exports = function (element) {
+ var i = instances.get(element);
+
+ if (!i) {
+ return;
+ }
+
+ i.event.unbindAll();
+ dom.remove(i.scrollbarX);
+ dom.remove(i.scrollbarY);
+ dom.remove(i.scrollbarXRail);
+ dom.remove(i.scrollbarYRail);
+ _.removePsClasses(element);
+
+ instances.remove(element);
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){
+'use strict';
+
+var instances = require('../instances');
+var updateGeometry = require('../update-geometry');
+var updateScroll = require('../update-scroll');
+
+function bindClickRailHandler(element, i) {
+ function pageOffset(el) {
+ return el.getBoundingClientRect();
+ }
+ var stopPropagation = function (e) { e.stopPropagation(); };
+
+ i.event.bind(i.scrollbarY, 'click', stopPropagation);
+ i.event.bind(i.scrollbarYRail, 'click', function (e) {
+ var positionTop = e.pageY - window.pageYOffset - pageOffset(i.scrollbarYRail).top;
+ var direction = positionTop > i.scrollbarYTop ? 1 : -1;
+
+ updateScroll(element, 'top', element.scrollTop + direction * i.containerHeight);
+ updateGeometry(element);
+
+ e.stopPropagation();
+ });
+
+ i.event.bind(i.scrollbarX, 'click', stopPropagation);
+ i.event.bind(i.scrollbarXRail, 'click', function (e) {
+ var positionLeft = e.pageX - window.pageXOffset - pageOffset(i.scrollbarXRail).left;
+ var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
+
+ updateScroll(element, 'left', element.scrollLeft + direction * i.containerWidth);
+ updateGeometry(element);
+
+ e.stopPropagation();
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindClickRailHandler(element, i);
+};
+
+},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){
+'use strict';
+
+var _ = require('../../lib/helper');
+var dom = require('../../lib/dom');
+var instances = require('../instances');
+var updateGeometry = require('../update-geometry');
+var updateScroll = require('../update-scroll');
+
+function bindMouseScrollXHandler(element, i) {
+ var currentLeft = null;
+ var currentPageX = null;
+
+ function updateScrollLeft(deltaX) {
+ var newLeft = currentLeft + (deltaX * i.railXRatio);
+ var maxLeft = Math.max(0, i.scrollbarXRail.getBoundingClientRect().left) + (i.railXRatio * (i.railXWidth - i.scrollbarXWidth));
+
+ if (newLeft < 0) {
+ i.scrollbarXLeft = 0;
+ } else if (newLeft > maxLeft) {
+ i.scrollbarXLeft = maxLeft;
+ } else {
+ i.scrollbarXLeft = newLeft;
+ }
+
+ var scrollLeft = _.toInt(i.scrollbarXLeft * (i.contentWidth - i.containerWidth) / (i.containerWidth - (i.railXRatio * i.scrollbarXWidth))) - i.negativeScrollAdjustment;
+ updateScroll(element, 'left', scrollLeft);
+ }
+
+ var mouseMoveHandler = function (e) {
+ updateScrollLeft(e.pageX - currentPageX);
+ updateGeometry(element);
+ e.stopPropagation();
+ e.preventDefault();
+ };
+
+ var mouseUpHandler = function () {
+ _.stopScrolling(element, 'x');
+ i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ };
+
+ i.event.bind(i.scrollbarX, 'mousedown', function (e) {
+ currentPageX = e.pageX;
+ currentLeft = _.toInt(dom.css(i.scrollbarX, 'left')) * i.railXRatio;
+ _.startScrolling(element, 'x');
+
+ i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+ e.stopPropagation();
+ e.preventDefault();
+ });
+}
+
+function bindMouseScrollYHandler(element, i) {
+ var currentTop = null;
+ var currentPageY = null;
+
+ function updateScrollTop(deltaY) {
+ var newTop = currentTop + (deltaY * i.railYRatio);
+ var maxTop = Math.max(0, i.scrollbarYRail.getBoundingClientRect().top) + (i.railYRatio * (i.railYHeight - i.scrollbarYHeight));
+
+ if (newTop < 0) {
+ i.scrollbarYTop = 0;
+ } else if (newTop > maxTop) {
+ i.scrollbarYTop = maxTop;
+ } else {
+ i.scrollbarYTop = newTop;
+ }
+
+ var scrollTop = _.toInt(i.scrollbarYTop * (i.contentHeight - i.containerHeight) / (i.containerHeight - (i.railYRatio * i.scrollbarYHeight)));
+ updateScroll(element, 'top', scrollTop);
+ }
+
+ var mouseMoveHandler = function (e) {
+ updateScrollTop(e.pageY - currentPageY);
+ updateGeometry(element);
+ e.stopPropagation();
+ e.preventDefault();
+ };
+
+ var mouseUpHandler = function () {
+ _.stopScrolling(element, 'y');
+ i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ };
+
+ i.event.bind(i.scrollbarY, 'mousedown', function (e) {
+ currentPageY = e.pageY;
+ currentTop = _.toInt(dom.css(i.scrollbarY, 'top')) * i.railYRatio;
+ _.startScrolling(element, 'y');
+
+ i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
+ i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
+
+ e.stopPropagation();
+ e.preventDefault();
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindMouseScrollXHandler(element, i);
+ bindMouseScrollYHandler(element, i);
+};
+
+},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){
+'use strict';
+
+var _ = require('../../lib/helper');
+var dom = require('../../lib/dom');
+var instances = require('../instances');
+var updateGeometry = require('../update-geometry');
+var updateScroll = require('../update-scroll');
+
+function bindKeyboardHandler(element, i) {
+ var hovered = false;
+ i.event.bind(element, 'mouseenter', function () {
+ hovered = true;
+ });
+ i.event.bind(element, 'mouseleave', function () {
+ hovered = false;
+ });
+
+ var shouldPrevent = false;
+ function shouldPreventDefault(deltaX, deltaY) {
+ var scrollTop = element.scrollTop;
+ if (deltaX === 0) {
+ if (!i.scrollbarYActive) {
+ return false;
+ }
+ if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+
+ var scrollLeft = element.scrollLeft;
+ if (deltaY === 0) {
+ if (!i.scrollbarXActive) {
+ return false;
+ }
+ if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+ return true;
+ }
+
+ i.event.bind(i.ownerDocument, 'keydown', function (e) {
+ if ((e.isDefaultPrevented && e.isDefaultPrevented()) || e.defaultPrevented) {
+ return;
+ }
+
+ var focused = dom.matches(i.scrollbarX, ':focus') ||
+ dom.matches(i.scrollbarY, ':focus');
+
+ if (!hovered && !focused) {
+ return;
+ }
+
+ var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement;
+ if (activeElement) {
+ if (activeElement.tagName === 'IFRAME') {
+ activeElement = activeElement.contentDocument.activeElement;
+ } else {
+ // go deeper if element is a webcomponent
+ while (activeElement.shadowRoot) {
+ activeElement = activeElement.shadowRoot.activeElement;
+ }
+ }
+ if (_.isEditable(activeElement)) {
+ return;
+ }
+ }
+
+ var deltaX = 0;
+ var deltaY = 0;
+
+ switch (e.which) {
+ case 37: // left
+ if (e.metaKey) {
+ deltaX = -i.contentWidth;
+ } else if (e.altKey) {
+ deltaX = -i.containerWidth;
+ } else {
+ deltaX = -30;
+ }
+ break;
+ case 38: // up
+ if (e.metaKey) {
+ deltaY = i.contentHeight;
+ } else if (e.altKey) {
+ deltaY = i.containerHeight;
+ } else {
+ deltaY = 30;
+ }
+ break;
+ case 39: // right
+ if (e.metaKey) {
+ deltaX = i.contentWidth;
+ } else if (e.altKey) {
+ deltaX = i.containerWidth;
+ } else {
+ deltaX = 30;
+ }
+ break;
+ case 40: // down
+ if (e.metaKey) {
+ deltaY = -i.contentHeight;
+ } else if (e.altKey) {
+ deltaY = -i.containerHeight;
+ } else {
+ deltaY = -30;
+ }
+ break;
+ case 33: // page up
+ deltaY = 90;
+ break;
+ case 32: // space bar
+ if (e.shiftKey) {
+ deltaY = 90;
+ } else {
+ deltaY = -90;
+ }
+ break;
+ case 34: // page down
+ deltaY = -90;
+ break;
+ case 35: // end
+ if (e.ctrlKey) {
+ deltaY = -i.contentHeight;
+ } else {
+ deltaY = -i.containerHeight;
+ }
+ break;
+ case 36: // home
+ if (e.ctrlKey) {
+ deltaY = element.scrollTop;
+ } else {
+ deltaY = i.containerHeight;
+ }
+ break;
+ default:
+ return;
+ }
+
+ updateScroll(element, 'top', element.scrollTop - deltaY);
+ updateScroll(element, 'left', element.scrollLeft + deltaX);
+ updateGeometry(element);
+
+ shouldPrevent = shouldPreventDefault(deltaX, deltaY);
+ if (shouldPrevent) {
+ e.preventDefault();
+ }
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindKeyboardHandler(element, i);
+};
+
+},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){
+'use strict';
+
+var instances = require('../instances');
+var updateGeometry = require('../update-geometry');
+var updateScroll = require('../update-scroll');
+
+function bindMouseWheelHandler(element, i) {
+ var shouldPrevent = false;
+
+ function shouldPreventDefault(deltaX, deltaY) {
+ var scrollTop = element.scrollTop;
+ if (deltaX === 0) {
+ if (!i.scrollbarYActive) {
+ return false;
+ }
+ if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+
+ var scrollLeft = element.scrollLeft;
+ if (deltaY === 0) {
+ if (!i.scrollbarXActive) {
+ return false;
+ }
+ if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)) {
+ return !i.settings.wheelPropagation;
+ }
+ }
+ return true;
+ }
+
+ function getDeltaFromEvent(e) {
+ var deltaX = e.deltaX;
+ var deltaY = -1 * e.deltaY;
+
+ if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
+ // OS X Safari
+ deltaX = -1 * e.wheelDeltaX / 6;
+ deltaY = e.wheelDeltaY / 6;
+ }
+
+ if (e.deltaMode && e.deltaMode === 1) {
+ // Firefox in deltaMode 1: Line scrolling
+ deltaX *= 10;
+ deltaY *= 10;
+ }
+
+ if (deltaX !== deltaX && deltaY !== deltaY/* NaN checks */) {
+ // IE in some mouse drivers
+ deltaX = 0;
+ deltaY = e.wheelDelta;
+ }
+
+ if (e.shiftKey) {
+ // reverse axis with shift key
+ return [-deltaY, -deltaX];
+ }
+ return [deltaX, deltaY];
+ }
+
+ function shouldBeConsumedByChild(deltaX, deltaY) {
+ var child = element.querySelector('textarea:hover, select[multiple]:hover, .ps-child:hover');
+ if (child) {
+ if (!window.getComputedStyle(child).overflow.match(/(scroll|auto)/)) {
+ // if not scrollable
+ return false;
+ }
+
+ var maxScrollTop = child.scrollHeight - child.clientHeight;
+ if (maxScrollTop > 0) {
+ if (!(child.scrollTop === 0 && deltaY > 0) && !(child.scrollTop === maxScrollTop && deltaY < 0)) {
+ return true;
+ }
+ }
+ var maxScrollLeft = child.scrollLeft - child.clientWidth;
+ if (maxScrollLeft > 0) {
+ if (!(child.scrollLeft === 0 && deltaX < 0) && !(child.scrollLeft === maxScrollLeft && deltaX > 0)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ function mousewheelHandler(e) {
+ var delta = getDeltaFromEvent(e);
+
+ var deltaX = delta[0];
+ var deltaY = delta[1];
+
+ if (shouldBeConsumedByChild(deltaX, deltaY)) {
+ return;
+ }
+
+ shouldPrevent = false;
+ if (!i.settings.useBothWheelAxes) {
+ // deltaX will only be used for horizontal scrolling and deltaY will
+ // only be used for vertical scrolling - this is the default
+ updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
+ updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
+ } else if (i.scrollbarYActive && !i.scrollbarXActive) {
+ // only vertical scrollbar is active and useBothWheelAxes option is
+ // active, so let's scroll vertical bar using both mouse wheel axes
+ if (deltaY) {
+ updateScroll(element, 'top', element.scrollTop - (deltaY * i.settings.wheelSpeed));
+ } else {
+ updateScroll(element, 'top', element.scrollTop + (deltaX * i.settings.wheelSpeed));
+ }
+ shouldPrevent = true;
+ } else if (i.scrollbarXActive && !i.scrollbarYActive) {
+ // useBothWheelAxes and only horizontal bar is active, so use both
+ // wheel axes for horizontal bar
+ if (deltaX) {
+ updateScroll(element, 'left', element.scrollLeft + (deltaX * i.settings.wheelSpeed));
+ } else {
+ updateScroll(element, 'left', element.scrollLeft - (deltaY * i.settings.wheelSpeed));
+ }
+ shouldPrevent = true;
+ }
+
+ updateGeometry(element);
+
+ shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
+ if (shouldPrevent) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+
+ if (typeof window.onwheel !== "undefined") {
+ i.event.bind(element, 'wheel', mousewheelHandler);
+ } else if (typeof window.onmousewheel !== "undefined") {
+ i.event.bind(element, 'mousewheel', mousewheelHandler);
+ }
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindMouseWheelHandler(element, i);
+};
+
+},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){
+'use strict';
+
+var instances = require('../instances');
+var updateGeometry = require('../update-geometry');
+
+function bindNativeScrollHandler(element, i) {
+ i.event.bind(element, 'scroll', function () {
+ updateGeometry(element);
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindNativeScrollHandler(element, i);
+};
+
+},{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){
+'use strict';
+
+var _ = require('../../lib/helper');
+var instances = require('../instances');
+var updateGeometry = require('../update-geometry');
+var updateScroll = require('../update-scroll');
+
+function bindSelectionHandler(element, i) {
+ function getRangeNode() {
+ var selection = window.getSelection ? window.getSelection() :
+ document.getSelection ? document.getSelection() : '';
+ if (selection.toString().length === 0) {
+ return null;
+ } else {
+ return selection.getRangeAt(0).commonAncestorContainer;
+ }
+ }
+
+ var scrollingLoop = null;
+ var scrollDiff = {top: 0, left: 0};
+ function startScrolling() {
+ if (!scrollingLoop) {
+ scrollingLoop = setInterval(function () {
+ if (!instances.get(element)) {
+ clearInterval(scrollingLoop);
+ return;
+ }
+
+ updateScroll(element, 'top', element.scrollTop + scrollDiff.top);
+ updateScroll(element, 'left', element.scrollLeft + scrollDiff.left);
+ updateGeometry(element);
+ }, 50); // every .1 sec
+ }
+ }
+ function stopScrolling() {
+ if (scrollingLoop) {
+ clearInterval(scrollingLoop);
+ scrollingLoop = null;
+ }
+ _.stopScrolling(element);
+ }
+
+ var isSelected = false;
+ i.event.bind(i.ownerDocument, 'selectionchange', function () {
+ if (element.contains(getRangeNode())) {
+ isSelected = true;
+ } else {
+ isSelected = false;
+ stopScrolling();
+ }
+ });
+ i.event.bind(window, 'mouseup', function () {
+ if (isSelected) {
+ isSelected = false;
+ stopScrolling();
+ }
+ });
+ i.event.bind(window, 'keyup', function () {
+ if (isSelected) {
+ isSelected = false;
+ stopScrolling();
+ }
+ });
+
+ i.event.bind(window, 'mousemove', function (e) {
+ if (isSelected) {
+ var mousePosition = {x: e.pageX, y: e.pageY};
+ var containerGeometry = {
+ left: element.offsetLeft,
+ right: element.offsetLeft + element.offsetWidth,
+ top: element.offsetTop,
+ bottom: element.offsetTop + element.offsetHeight
+ };
+
+ if (mousePosition.x < containerGeometry.left + 3) {
+ scrollDiff.left = -5;
+ _.startScrolling(element, 'x');
+ } else if (mousePosition.x > containerGeometry.right - 3) {
+ scrollDiff.left = 5;
+ _.startScrolling(element, 'x');
+ } else {
+ scrollDiff.left = 0;
+ }
+
+ if (mousePosition.y < containerGeometry.top + 3) {
+ if (containerGeometry.top + 3 - mousePosition.y < 5) {
+ scrollDiff.top = -5;
+ } else {
+ scrollDiff.top = -20;
+ }
+ _.startScrolling(element, 'y');
+ } else if (mousePosition.y > containerGeometry.bottom - 3) {
+ if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
+ scrollDiff.top = 5;
+ } else {
+ scrollDiff.top = 20;
+ }
+ _.startScrolling(element, 'y');
+ } else {
+ scrollDiff.top = 0;
+ }
+
+ if (scrollDiff.top === 0 && scrollDiff.left === 0) {
+ stopScrolling();
+ } else {
+ startScrolling();
+ }
+ }
+ });
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+ bindSelectionHandler(element, i);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){
+'use strict';
+
+var _ = require('../../lib/helper');
+var instances = require('../instances');
+var updateGeometry = require('../update-geometry');
+var updateScroll = require('../update-scroll');
+
+function bindTouchHandler(element, i, supportsTouch, supportsIePointer) {
+ function shouldPreventDefault(deltaX, deltaY) {
+ var scrollTop = element.scrollTop;
+ var scrollLeft = element.scrollLeft;
+ var magnitudeX = Math.abs(deltaX);
+ var magnitudeY = Math.abs(deltaY);
+
+ if (magnitudeY > magnitudeX) {
+ // user is perhaps trying to swipe up/down the page
+
+ if (((deltaY < 0) && (scrollTop === i.contentHeight - i.containerHeight)) ||
+ ((deltaY > 0) && (scrollTop === 0))) {
+ return !i.settings.swipePropagation;
+ }
+ } else if (magnitudeX > magnitudeY) {
+ // user is perhaps trying to swipe left/right across the page
+
+ if (((deltaX < 0) && (scrollLeft === i.contentWidth - i.containerWidth)) ||
+ ((deltaX > 0) && (scrollLeft === 0))) {
+ return !i.settings.swipePropagation;
+ }
+ }
+
+ return true;
+ }
+
+ function applyTouchMove(differenceX, differenceY) {
+ updateScroll(element, 'top', element.scrollTop - differenceY);
+ updateScroll(element, 'left', element.scrollLeft - differenceX);
+
+ updateGeometry(element);
+ }
+
+ var startOffset = {};
+ var startTime = 0;
+ var speed = {};
+ var easingLoop = null;
+ var inGlobalTouch = false;
+ var inLocalTouch = false;
+
+ function globalTouchStart() {
+ inGlobalTouch = true;
+ }
+ function globalTouchEnd() {
+ inGlobalTouch = false;
+ }
+
+ function getTouch(e) {
+ if (e.targetTouches) {
+ return e.targetTouches[0];
+ } else {
+ // Maybe IE pointer
+ return e;
+ }
+ }
+ function shouldHandle(e) {
+ if (e.targetTouches && e.targetTouches.length === 1) {
+ return true;
+ }
+ if (e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE) {
+ return true;
+ }
+ return false;
+ }
+ function touchStart(e) {
+ if (shouldHandle(e)) {
+ inLocalTouch = true;
+
+ var touch = getTouch(e);
+
+ startOffset.pageX = touch.pageX;
+ startOffset.pageY = touch.pageY;
+
+ startTime = (new Date()).getTime();
+
+ if (easingLoop !== null) {
+ clearInterval(easingLoop);
+ }
+
+ e.stopPropagation();
+ }
+ }
+ function touchMove(e) {
+ if (!inLocalTouch && i.settings.swipePropagation) {
+ touchStart(e);
+ }
+ if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
+ var touch = getTouch(e);
+
+ var currentOffset = {pageX: touch.pageX, pageY: touch.pageY};
+
+ var differenceX = currentOffset.pageX - startOffset.pageX;
+ var differenceY = currentOffset.pageY - startOffset.pageY;
+
+ applyTouchMove(differenceX, differenceY);
+ startOffset = currentOffset;
+
+ var currentTime = (new Date()).getTime();
+
+ var timeGap = currentTime - startTime;
+ if (timeGap > 0) {
+ speed.x = differenceX / timeGap;
+ speed.y = differenceY / timeGap;
+ startTime = currentTime;
+ }
+
+ if (shouldPreventDefault(differenceX, differenceY)) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ }
+ }
+ function touchEnd() {
+ if (!inGlobalTouch && inLocalTouch) {
+ inLocalTouch = false;
+
+ clearInterval(easingLoop);
+ easingLoop = setInterval(function () {
+ if (!instances.get(element)) {
+ clearInterval(easingLoop);
+ return;
+ }
+
+ if (!speed.x && !speed.y) {
+ clearInterval(easingLoop);
+ return;
+ }
+
+ if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
+ clearInterval(easingLoop);
+ return;
+ }
+
+ applyTouchMove(speed.x * 30, speed.y * 30);
+
+ speed.x *= 0.8;
+ speed.y *= 0.8;
+ }, 10);
+ }
+ }
+
+ if (supportsTouch) {
+ i.event.bind(window, 'touchstart', globalTouchStart);
+ i.event.bind(window, 'touchend', globalTouchEnd);
+ i.event.bind(element, 'touchstart', touchStart);
+ i.event.bind(element, 'touchmove', touchMove);
+ i.event.bind(element, 'touchend', touchEnd);
+ }
+
+ if (supportsIePointer) {
+ if (window.PointerEvent) {
+ i.event.bind(window, 'pointerdown', globalTouchStart);
+ i.event.bind(window, 'pointerup', globalTouchEnd);
+ i.event.bind(element, 'pointerdown', touchStart);
+ i.event.bind(element, 'pointermove', touchMove);
+ i.event.bind(element, 'pointerup', touchEnd);
+ } else if (window.MSPointerEvent) {
+ i.event.bind(window, 'MSPointerDown', globalTouchStart);
+ i.event.bind(window, 'MSPointerUp', globalTouchEnd);
+ i.event.bind(element, 'MSPointerDown', touchStart);
+ i.event.bind(element, 'MSPointerMove', touchMove);
+ i.event.bind(element, 'MSPointerUp', touchEnd);
+ }
+ }
+}
+
+module.exports = function (element) {
+ if (!_.env.supportsTouch && !_.env.supportsIePointer) {
+ return;
+ }
+
+ var i = instances.get(element);
+ bindTouchHandler(element, i, _.env.supportsTouch, _.env.supportsIePointer);
+};
+
+},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lib/helper');
+var cls = require('../lib/class');
+var instances = require('./instances');
+var updateGeometry = require('./update-geometry');
+
+// Handlers
+var handlers = {
+ 'click-rail': require('./handler/click-rail'),
+ 'drag-scrollbar': require('./handler/drag-scrollbar'),
+ 'keyboard': require('./handler/keyboard'),
+ 'wheel': require('./handler/mouse-wheel'),
+ 'touch': require('./handler/touch'),
+ 'selection': require('./handler/selection')
+};
+var nativeScrollHandler = require('./handler/native-scroll');
+
+module.exports = function (element, userSettings) {
+ userSettings = typeof userSettings === 'object' ? userSettings : {};
+
+ cls.add(element, 'ps-container');
+
+ // Create a plugin instance.
+ var i = instances.add(element);
+
+ i.settings = _.extend(i.settings, userSettings);
+ cls.add(element, 'ps-theme-' + i.settings.theme);
+
+ i.settings.handlers.forEach(function (handlerName) {
+ handlers[handlerName](element);
+ });
+
+ nativeScrollHandler(element);
+
+ updateGeometry(element);
+};
+
+},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lib/helper');
+var cls = require('../lib/class');
+var defaultSettings = require('./default-setting');
+var dom = require('../lib/dom');
+var EventManager = require('../lib/event-manager');
+var guid = require('../lib/guid');
+
+var instances = {};
+
+function Instance(element) {
+ var i = this;
+
+ i.settings = _.clone(defaultSettings);
+ i.containerWidth = null;
+ i.containerHeight = null;
+ i.contentWidth = null;
+ i.contentHeight = null;
+
+ i.isRtl = dom.css(element, 'direction') === "rtl";
+ i.isNegativeScroll = (function () {
+ var originalScrollLeft = element.scrollLeft;
+ var result = null;
+ element.scrollLeft = -1;
+ result = element.scrollLeft < 0;
+ element.scrollLeft = originalScrollLeft;
+ return result;
+ })();
+ i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+ i.event = new EventManager();
+ i.ownerDocument = element.ownerDocument || document;
+
+ function focus() {
+ cls.add(element, 'ps-focus');
+ }
+
+ function blur() {
+ cls.remove(element, 'ps-focus');
+ }
+
+ i.scrollbarXRail = dom.appendTo(dom.e('div', 'ps-scrollbar-x-rail'), element);
+ i.scrollbarX = dom.appendTo(dom.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
+ i.scrollbarX.setAttribute('tabindex', 0);
+ i.event.bind(i.scrollbarX, 'focus', focus);
+ i.event.bind(i.scrollbarX, 'blur', blur);
+ i.scrollbarXActive = null;
+ i.scrollbarXWidth = null;
+ i.scrollbarXLeft = null;
+ i.scrollbarXBottom = _.toInt(dom.css(i.scrollbarXRail, 'bottom'));
+ i.isScrollbarXUsingBottom = i.scrollbarXBottom === i.scrollbarXBottom; // !isNaN
+ i.scrollbarXTop = i.isScrollbarXUsingBottom ? null : _.toInt(dom.css(i.scrollbarXRail, 'top'));
+ i.railBorderXWidth = _.toInt(dom.css(i.scrollbarXRail, 'borderLeftWidth')) + _.toInt(dom.css(i.scrollbarXRail, 'borderRightWidth'));
+ // Set rail to display:block to calculate margins
+ dom.css(i.scrollbarXRail, 'display', 'block');
+ i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
+ dom.css(i.scrollbarXRail, 'display', '');
+ i.railXWidth = null;
+ i.railXRatio = null;
+
+ i.scrollbarYRail = dom.appendTo(dom.e('div', 'ps-scrollbar-y-rail'), element);
+ i.scrollbarY = dom.appendTo(dom.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
+ i.scrollbarY.setAttribute('tabindex', 0);
+ i.event.bind(i.scrollbarY, 'focus', focus);
+ i.event.bind(i.scrollbarY, 'blur', blur);
+ i.scrollbarYActive = null;
+ i.scrollbarYHeight = null;
+ i.scrollbarYTop = null;
+ i.scrollbarYRight = _.toInt(dom.css(i.scrollbarYRail, 'right'));
+ i.isScrollbarYUsingRight = i.scrollbarYRight === i.scrollbarYRight; // !isNaN
+ i.scrollbarYLeft = i.isScrollbarYUsingRight ? null : _.toInt(dom.css(i.scrollbarYRail, 'left'));
+ i.scrollbarYOuterWidth = i.isRtl ? _.outerWidth(i.scrollbarY) : null;
+ i.railBorderYWidth = _.toInt(dom.css(i.scrollbarYRail, 'borderTopWidth')) + _.toInt(dom.css(i.scrollbarYRail, 'borderBottomWidth'));
+ dom.css(i.scrollbarYRail, 'display', 'block');
+ i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
+ dom.css(i.scrollbarYRail, 'display', '');
+ i.railYHeight = null;
+ i.railYRatio = null;
+}
+
+function getId(element) {
+ return element.getAttribute('data-ps-id');
+}
+
+function setId(element, id) {
+ element.setAttribute('data-ps-id', id);
+}
+
+function removeId(element) {
+ element.removeAttribute('data-ps-id');
+}
+
+exports.add = function (element) {
+ var newId = guid();
+ setId(element, newId);
+ instances[newId] = new Instance(element);
+ return instances[newId];
+};
+
+exports.remove = function (element) {
+ delete instances[getId(element)];
+ removeId(element);
+};
+
+exports.get = function (element) {
+ return instances[getId(element)];
+};
+
+},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lib/helper');
+var cls = require('../lib/class');
+var dom = require('../lib/dom');
+var instances = require('./instances');
+var updateScroll = require('./update-scroll');
+
+function getThumbSize(i, thumbSize) {
+ if (i.settings.minScrollbarLength) {
+ thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
+ }
+ if (i.settings.maxScrollbarLength) {
+ thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
+ }
+ return thumbSize;
+}
+
+function updateCss(element, i) {
+ var xRailOffset = {width: i.railXWidth};
+ if (i.isRtl) {
+ xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth;
+ } else {
+ xRailOffset.left = element.scrollLeft;
+ }
+ if (i.isScrollbarXUsingBottom) {
+ xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop;
+ } else {
+ xRailOffset.top = i.scrollbarXTop + element.scrollTop;
+ }
+ dom.css(i.scrollbarXRail, xRailOffset);
+
+ var yRailOffset = {top: element.scrollTop, height: i.railYHeight};
+ if (i.isScrollbarYUsingRight) {
+ if (i.isRtl) {
+ yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth;
+ } else {
+ yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
+ }
+ } else {
+ if (i.isRtl) {
+ yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth;
+ } else {
+ yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
+ }
+ }
+ dom.css(i.scrollbarYRail, yRailOffset);
+
+ dom.css(i.scrollbarX, {left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth});
+ dom.css(i.scrollbarY, {top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth});
+}
+
+module.exports = function (element) {
+ var i = instances.get(element);
+
+ i.containerWidth = element.clientWidth;
+ i.containerHeight = element.clientHeight;
+ i.contentWidth = element.scrollWidth;
+ i.contentHeight = element.scrollHeight;
+
+ var existingRails;
+ if (!element.contains(i.scrollbarXRail)) {
+ existingRails = dom.queryChildren(element, '.ps-scrollbar-x-rail');
+ if (existingRails.length > 0) {
+ existingRails.forEach(function (rail) {
+ dom.remove(rail);
+ });
+ }
+ dom.appendTo(i.scrollbarXRail, element);
+ }
+ if (!element.contains(i.scrollbarYRail)) {
+ existingRails = dom.queryChildren(element, '.ps-scrollbar-y-rail');
+ if (existingRails.length > 0) {
+ existingRails.forEach(function (rail) {
+ dom.remove(rail);
+ });
+ }
+ dom.appendTo(i.scrollbarYRail, element);
+ }
+
+ if (!i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth) {
+ i.scrollbarXActive = true;
+ i.railXWidth = i.containerWidth - i.railXMarginWidth;
+ i.railXRatio = i.containerWidth / i.railXWidth;
+ i.scrollbarXWidth = getThumbSize(i, _.toInt(i.railXWidth * i.containerWidth / i.contentWidth));
+ i.scrollbarXLeft = _.toInt((i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth));
+ } else {
+ i.scrollbarXActive = false;
+ }
+
+ if (!i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight) {
+ i.scrollbarYActive = true;
+ i.railYHeight = i.containerHeight - i.railYMarginHeight;
+ i.railYRatio = i.containerHeight / i.railYHeight;
+ i.scrollbarYHeight = getThumbSize(i, _.toInt(i.railYHeight * i.containerHeight / i.contentHeight));
+ i.scrollbarYTop = _.toInt(element.scrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight));
+ } else {
+ i.scrollbarYActive = false;
+ }
+
+ if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
+ i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
+ }
+ if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
+ i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
+ }
+
+ updateCss(element, i);
+
+ if (i.scrollbarXActive) {
+ cls.add(element, 'ps-active-x');
+ } else {
+ cls.remove(element, 'ps-active-x');
+ i.scrollbarXWidth = 0;
+ i.scrollbarXLeft = 0;
+ updateScroll(element, 'left', 0);
+ }
+ if (i.scrollbarYActive) {
+ cls.add(element, 'ps-active-y');
+ } else {
+ cls.remove(element, 'ps-active-y');
+ i.scrollbarYHeight = 0;
+ i.scrollbarYTop = 0;
+ updateScroll(element, 'top', 0);
+ }
+};
+
+},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){
+'use strict';
+
+var instances = require('./instances');
+
+var lastTop;
+var lastLeft;
+
+var createDOMEvent = function (name) {
+ var event = document.createEvent("Event");
+ event.initEvent(name, true, true);
+ return event;
+};
+
+module.exports = function (element, axis, value) {
+ if (typeof element === 'undefined') {
+ throw 'You must provide an element to the update-scroll function';
+ }
+
+ if (typeof axis === 'undefined') {
+ throw 'You must provide an axis to the update-scroll function';
+ }
+
+ if (typeof value === 'undefined') {
+ throw 'You must provide a value to the update-scroll function';
+ }
+
+ if (axis === 'top' && value <= 0) {
+ element.scrollTop = value = 0; // don't allow negative scroll
+ element.dispatchEvent(createDOMEvent('ps-y-reach-start'));
+ }
+
+ if (axis === 'left' && value <= 0) {
+ element.scrollLeft = value = 0; // don't allow negative scroll
+ element.dispatchEvent(createDOMEvent('ps-x-reach-start'));
+ }
+
+ var i = instances.get(element);
+
+ if (axis === 'top' && value >= i.contentHeight - i.containerHeight) {
+ // don't allow scroll past container
+ value = i.contentHeight - i.containerHeight;
+ if (value - element.scrollTop <= 1) {
+ // mitigates rounding errors on non-subpixel scroll values
+ value = element.scrollTop;
+ } else {
+ element.scrollTop = value;
+ }
+ element.dispatchEvent(createDOMEvent('ps-y-reach-end'));
+ }
+
+ if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
+ // don't allow scroll past container
+ value = i.contentWidth - i.containerWidth;
+ if (value - element.scrollLeft <= 1) {
+ // mitigates rounding errors on non-subpixel scroll values
+ value = element.scrollLeft;
+ } else {
+ element.scrollLeft = value;
+ }
+ element.dispatchEvent(createDOMEvent('ps-x-reach-end'));
+ }
+
+ if (!lastTop) {
+ lastTop = element.scrollTop;
+ }
+
+ if (!lastLeft) {
+ lastLeft = element.scrollLeft;
+ }
+
+ if (axis === 'top' && value < lastTop) {
+ element.dispatchEvent(createDOMEvent('ps-scroll-up'));
+ }
+
+ if (axis === 'top' && value > lastTop) {
+ element.dispatchEvent(createDOMEvent('ps-scroll-down'));
+ }
+
+ if (axis === 'left' && value < lastLeft) {
+ element.dispatchEvent(createDOMEvent('ps-scroll-left'));
+ }
+
+ if (axis === 'left' && value > lastLeft) {
+ element.dispatchEvent(createDOMEvent('ps-scroll-right'));
+ }
+
+ if (axis === 'top') {
+ element.scrollTop = lastTop = value;
+ element.dispatchEvent(createDOMEvent('ps-scroll-y'));
+ }
+
+ if (axis === 'left') {
+ element.scrollLeft = lastLeft = value;
+ element.dispatchEvent(createDOMEvent('ps-scroll-x'));
+ }
+
+};
+
+},{"./instances":18}],21:[function(require,module,exports){
+'use strict';
+
+var _ = require('../lib/helper');
+var dom = require('../lib/dom');
+var instances = require('./instances');
+var updateGeometry = require('./update-geometry');
+var updateScroll = require('./update-scroll');
+
+module.exports = function (element) {
+ var i = instances.get(element);
+
+ if (!i) {
+ return;
+ }
+
+ // Recalcuate negative scrollLeft adjustment
+ i.negativeScrollAdjustment = i.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0;
+
+ // Recalculate rail margins
+ dom.css(i.scrollbarXRail, 'display', 'block');
+ dom.css(i.scrollbarYRail, 'display', 'block');
+ i.railXMarginWidth = _.toInt(dom.css(i.scrollbarXRail, 'marginLeft')) + _.toInt(dom.css(i.scrollbarXRail, 'marginRight'));
+ i.railYMarginHeight = _.toInt(dom.css(i.scrollbarYRail, 'marginTop')) + _.toInt(dom.css(i.scrollbarYRail, 'marginBottom'));
+
+ // Hide scrollbars not to affect scrollWidth and scrollHeight
+ dom.css(i.scrollbarXRail, 'display', 'none');
+ dom.css(i.scrollbarYRail, 'display', 'none');
+
+ updateGeometry(element);
+
+ // Update top/left scroll to trigger events
+ updateScroll(element, 'top', element.scrollTop);
+ updateScroll(element, 'left', element.scrollLeft);
+
+ dom.css(i.scrollbarXRail, 'display', '');
+ dom.css(i.scrollbarYRail, 'display', '');
+};
+
+},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]);
diff --git a/debian/missing-sources/raphael-2.2.4.js b/debian/missing-sources/raphael-2.2.4.js
new file mode 100644
index 000000000..90184313f
--- /dev/null
+++ b/debian/missing-sources/raphael-2.2.4.js
@@ -0,0 +1,8190 @@
+// ┌───────────────────────────────────────────────────────────────────────────────────────────────────────┐ \\
+// │ Raphaël 2.2.0 - JavaScript Vector Library │ \\
+// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
+// │ Copyright © 2008-2016 Dmitry Baranovskiy (http://raphaeljs.com) │ \\
+// │ Copyright © 2008-2016 Sencha Labs (http://sencha.com) │ \\
+// ├───────────────────────────────────────────────────────────────────────────────────────────────────────┤ \\
+// │ Licensed under the MIT (https://github.com/DmitryBaranovskiy/raphael/blob/master/license.txt) license.│ \\
+// └───────────────────────────────────────────────────────────────────────────────────────────────────────┘ \\
+
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["Raphael"] = factory();
+ else
+ root["Raphael"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(3), __webpack_require__(4)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
+
+ return R;
+
+ }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(2)], __WEBPACK_AMD_DEFINE_RESULT__ = function(eve) {
+
+ /*\
+ * Raphael
+ [ method ]
+ **
+ * Creates a canvas object on which to draw.
+ * You must do this first, as all future calls to drawing methods
+ * from this instance will be bound to this canvas.
+ > Parameters
+ **
+ - container (HTMLElement|string) DOM element or its ID which is going to be a parent for drawing surface
+ - width (number)
+ - height (number)
+ - callback (function) #optional callback function which is going to be executed in the context of newly created paper
+ * or
+ - x (number)
+ - y (number)
+ - width (number)
+ - height (number)
+ - callback (function) #optional callback function which is going to be executed in the context of newly created paper
+ * or
+ - all (array) (first 3 or 4 elements in the array are equal to [containerID, width, height] or [x, y, width, height]. The rest are element descriptions in format {type: type, <attributes>}). See @Paper.add.
+ - callback (function) #optional callback function which is going to be executed in the context of newly created paper
+ * or
+ - onReadyCallback (function) function that is going to be called on DOM ready event. You can also subscribe to this event via Eve’s “DOMLoad” event. In this case method returns `undefined`.
+ = (object) @Paper
+ > Usage
+ | // Each of the following examples create a canvas
+ | // that is 320px wide by 200px high.
+ | // Canvas is created at the viewport’s 10,50 coordinate.
+ | var paper = Raphael(10, 50, 320, 200);
+ | // Canvas is created at the top left corner of the #notepad element
+ | // (or its top right corner in dir="rtl" elements)
+ | var paper = Raphael(document.getElementById("notepad"), 320, 200);
+ | // Same as above
+ | var paper = Raphael("notepad", 320, 200);
+ | // Image dump
+ | var set = Raphael(["notepad", 320, 200, {
+ | type: "rect",
+ | x: 10,
+ | y: 10,
+ | width: 25,
+ | height: 25,
+ | stroke: "#f00"
+ | }, {
+ | type: "text",
+ | x: 30,
+ | y: 40,
+ | text: "Dump"
+ | }]);
+ \*/
+ function R(first) {
+ if (R.is(first, "function")) {
+ return loaded ? first() : eve.on("raphael.DOMload", first);
+ } else if (R.is(first, array)) {
+ return R._engine.create[apply](R, first.splice(0, 3 + R.is(first[0], nu))).add(first);
+ } else {
+ var args = Array.prototype.slice.call(arguments, 0);
+ if (R.is(args[args.length - 1], "function")) {
+ var f = args.pop();
+ return loaded ? f.call(R._engine.create[apply](R, args)) : eve.on("raphael.DOMload", function () {
+ f.call(R._engine.create[apply](R, args));
+ });
+ } else {
+ return R._engine.create[apply](R, arguments);
+ }
+ }
+ }
+ R.version = "2.2.0";
+ R.eve = eve;
+ var loaded,
+ separator = /[, ]+/,
+ elements = {circle: 1, rect: 1, path: 1, ellipse: 1, text: 1, image: 1},
+ formatrg = /\{(\d+)\}/g,
+ proto = "prototype",
+ has = "hasOwnProperty",
+ g = {
+ doc: document,
+ win: window
+ },
+ oldRaphael = {
+ was: Object.prototype[has].call(g.win, "Raphael"),
+ is: g.win.Raphael
+ },
+ Paper = function () {
+ /*\
+ * Paper.ca
+ [ property (object) ]
+ **
+ * Shortcut for @Paper.customAttributes
+ \*/
+ /*\
+ * Paper.customAttributes
+ [ property (object) ]
+ **
+ * If you have a set of attributes that you would like to represent
+ * as a function of some number you can do it easily with custom attributes:
+ > Usage
+ | paper.customAttributes.hue = function (num) {
+ | num = num % 1;
+ | return {fill: "hsb(" + num + ", 0.75, 1)"};
+ | };
+ | // Custom attribute “hue” will change fill
+ | // to be given hue with fixed saturation and brightness.
+ | // Now you can use it like this:
+ | var c = paper.circle(10, 10, 10).attr({hue: .45});
+ | // or even like this:
+ | c.animate({hue: 1}, 1e3);
+ |
+ | // You could also create custom attribute
+ | // with multiple parameters:
+ | paper.customAttributes.hsb = function (h, s, b) {
+ | return {fill: "hsb(" + [h, s, b].join(",") + ")"};
+ | };
+ | c.attr({hsb: "0.5 .8 1"});
+ | c.animate({hsb: [1, 0, 0.5]}, 1e3);
+ \*/
+ this.ca = this.customAttributes = {};
+ },
+ paperproto,
+ appendChild = "appendChild",
+ apply = "apply",
+ concat = "concat",
+ supportsTouch = ('ontouchstart' in g.win) || g.win.DocumentTouch && g.doc instanceof DocumentTouch, //taken from Modernizr touch test
+ E = "",
+ S = " ",
+ Str = String,
+ split = "split",
+ events = "click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel"[split](S),
+ touchMap = {
+ mousedown: "touchstart",
+ mousemove: "touchmove",
+ mouseup: "touchend"
+ },
+ lowerCase = Str.prototype.toLowerCase,
+ math = Math,
+ mmax = math.max,
+ mmin = math.min,
+ abs = math.abs,
+ pow = math.pow,
+ PI = math.PI,
+ nu = "number",
+ string = "string",
+ array = "array",
+ toString = "toString",
+ fillString = "fill",
+ objectToString = Object.prototype.toString,
+ paper = {},
+ push = "push",
+ ISURL = R._ISURL = /^url\(['"]?(.+?)['"]?\)$/i,
+ colourRegExp = /^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?)%?\s*\))\s*$/i,
+ isnan = {"NaN": 1, "Infinity": 1, "-Infinity": 1},
+ bezierrg = /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
+ round = math.round,
+ setAttribute = "setAttribute",
+ toFloat = parseFloat,
+ toInt = parseInt,
+ upperCase = Str.prototype.toUpperCase,
+ availableAttrs = R._availableAttrs = {
+ "arrow-end": "none",
+ "arrow-start": "none",
+ blur: 0,
+ "clip-rect": "0 0 1e9 1e9",
+ cursor: "default",
+ cx: 0,
+ cy: 0,
+ fill: "#fff",
+ "fill-opacity": 1,
+ font: '10px "Arial"',
+ "font-family": '"Arial"',
+ "font-size": "10",
+ "font-style": "normal",
+ "font-weight": 400,
+ gradient: 0,
+ height: 0,
+ href: "http://raphaeljs.com/",
+ "letter-spacing": 0,
+ opacity: 1,
+ path: "M0,0",
+ r: 0,
+ rx: 0,
+ ry: 0,
+ src: "",
+ stroke: "#000",
+ "stroke-dasharray": "",
+ "stroke-linecap": "butt",
+ "stroke-linejoin": "butt",
+ "stroke-miterlimit": 0,
+ "stroke-opacity": 1,
+ "stroke-width": 1,
+ target: "_blank",
+ "text-anchor": "middle",
+ title: "Raphael",
+ transform: "",
+ width: 0,
+ x: 0,
+ y: 0,
+ class: ""
+ },
+ availableAnimAttrs = R._availableAnimAttrs = {
+ blur: nu,
+ "clip-rect": "csv",
+ cx: nu,
+ cy: nu,
+ fill: "colour",
+ "fill-opacity": nu,
+ "font-size": nu,
+ height: nu,
+ opacity: nu,
+ path: "path",
+ r: nu,
+ rx: nu,
+ ry: nu,
+ stroke: "colour",
+ "stroke-opacity": nu,
+ "stroke-width": nu,
+ transform: "transform",
+ width: nu,
+ x: nu,
+ y: nu
+ },
+ whitespace = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]/g,
+ commaSpaces = /[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/,
+ hsrg = {hs: 1, rg: 1},
+ p2s = /,?([achlmqrstvxz]),?/gi,
+ pathCommand = /([achlmrqstvz])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,
+ tCommand = /([rstm])[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\d*\.?\d*(?:e[\-+]?\d+)?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)/ig,
+ pathValues = /(-?\d*\.?\d*(?:e[\-+]?\d+)?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*/ig,
+ radial_gradient = R._radial_gradient = /^r(?:\(([^,]+?)[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*([^\)]+?)\))?/,
+ eldata = {},
+ sortByKey = function (a, b) {
+ return a.key - b.key;
+ },
+ sortByNumber = function (a, b) {
+ return toFloat(a) - toFloat(b);
+ },
+ fun = function () {},
+ pipe = function (x) {
+ return x;
+ },
+ rectPath = R._rectPath = function (x, y, w, h, r) {
+ if (r) {
+ return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]];
+ }
+ return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]];
+ },
+ ellipsePath = function (x, y, rx, ry) {
+ if (ry == null) {
+ ry = rx;
+ }
+ return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]];
+ },
+ getPath = R._getPath = {
+ path: function (el) {
+ return el.attr("path");
+ },
+ circle: function (el) {
+ var a = el.attrs;
+ return ellipsePath(a.cx, a.cy, a.r);
+ },
+ ellipse: function (el) {
+ var a = el.attrs;
+ return ellipsePath(a.cx, a.cy, a.rx, a.ry);
+ },
+ rect: function (el) {
+ var a = el.attrs;
+ return rectPath(a.x, a.y, a.width, a.height, a.r);
+ },
+ image: function (el) {
+ var a = el.attrs;
+ return rectPath(a.x, a.y, a.width, a.height);
+ },
+ text: function (el) {
+ var bbox = el._getBBox();
+ return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
+ },
+ set : function(el) {
+ var bbox = el._getBBox();
+ return rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
+ }
+ },
+ /*\
+ * Raphael.mapPath
+ [ method ]
+ **
+ * Transform the path string with given matrix.
+ > Parameters
+ - path (string) path string
+ - matrix (object) see @Matrix
+ = (string) transformed path string
+ \*/
+ mapPath = R.mapPath = function (path, matrix) {
+ if (!matrix) {
+ return path;
+ }
+ var x, y, i, j, ii, jj, pathi;
+ path = path2curve(path);
+ for (i = 0, ii = path.length; i < ii; i++) {
+ pathi = path[i];
+ for (j = 1, jj = pathi.length; j < jj; j += 2) {
+ x = matrix.x(pathi[j], pathi[j + 1]);
+ y = matrix.y(pathi[j], pathi[j + 1]);
+ pathi[j] = x;
+ pathi[j + 1] = y;
+ }
+ }
+ return path;
+ };
+
+ R._g = g;
+ /*\
+ * Raphael.type
+ [ property (string) ]
+ **
+ * Can be “SVG”, “VML” or empty, depending on browser support.
+ \*/
+ R.type = (g.win.SVGAngle || g.doc.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML");
+ if (R.type == "VML") {
+ var d = g.doc.createElement("div"),
+ b;
+ d.innerHTML = '<v:shape adj="1"/>';
+ b = d.firstChild;
+ b.style.behavior = "url(#default#VML)";
+ if (!(b && typeof b.adj == "object")) {
+ return (R.type = E);
+ }
+ d = null;
+ }
+ /*\
+ * Raphael.svg
+ [ property (boolean) ]
+ **
+ * `true` if browser supports SVG.
+ \*/
+ /*\
+ * Raphael.vml
+ [ property (boolean) ]
+ **
+ * `true` if browser supports VML.
+ \*/
+ R.svg = !(R.vml = R.type == "VML");
+ R._Paper = Paper;
+ /*\
+ * Raphael.fn
+ [ property (object) ]
+ **
+ * You can add your own method to the canvas. For example if you want to draw a pie chart,
+ * you can create your own pie chart function and ship it as a Raphaël plugin. To do this
+ * you need to extend the `Raphael.fn` object. You should modify the `fn` object before a
+ * Raphaël instance is created, otherwise it will take no effect. Please note that the
+ * ability for namespaced plugins was removed in Raphael 2.0. It is up to the plugin to
+ * ensure any namespacing ensures proper context.
+ > Usage
+ | Raphael.fn.arrow = function (x1, y1, x2, y2, size) {
+ | return this.path( ... );
+ | };
+ | // or create namespace
+ | Raphael.fn.mystuff = {
+ | arrow: function () {…},
+ | star: function () {…},
+ | // etc…
+ | };
+ | var paper = Raphael(10, 10, 630, 480);
+ | // then use it
+ | paper.arrow(10, 10, 30, 30, 5).attr({fill: "#f00"});
+ | paper.mystuff.arrow();
+ | paper.mystuff.star();
+ \*/
+ R.fn = paperproto = Paper.prototype = R.prototype;
+ R._id = 0;
+ /*\
+ * Raphael.is
+ [ method ]
+ **
+ * Handful of replacements for `typeof` operator.
+ > Parameters
+ - o (…) any object or primitive
+ - type (string) name of the type, i.e. “string”, “function”, “number”, etc.
+ = (boolean) is given value is of given type
+ \*/
+ R.is = function (o, type) {
+ type = lowerCase.call(type);
+ if (type == "finite") {
+ return !isnan[has](+o);
+ }
+ if (type == "array") {
+ return o instanceof Array;
+ }
+ return (type == "null" && o === null) ||
+ (type == typeof o && o !== null) ||
+ (type == "object" && o === Object(o)) ||
+ (type == "array" && Array.isArray && Array.isArray(o)) ||
+ objectToString.call(o).slice(8, -1).toLowerCase() == type;
+ };
+
+ function clone(obj) {
+ if (typeof obj == "function" || Object(obj) !== obj) {
+ return obj;
+ }
+ var res = new obj.constructor;
+ for (var key in obj) if (obj[has](key)) {
+ res[key] = clone(obj[key]);
+ }
+ return res;
+ }
+
+ /*\
+ * Raphael.angle
+ [ method ]
+ **
+ * Returns angle between two or three points
+ > Parameters
+ - x1 (number) x coord of first point
+ - y1 (number) y coord of first point
+ - x2 (number) x coord of second point
+ - y2 (number) y coord of second point
+ - x3 (number) #optional x coord of third point
+ - y3 (number) #optional y coord of third point
+ = (number) angle in degrees.
+ \*/
+ R.angle = function (x1, y1, x2, y2, x3, y3) {
+ if (x3 == null) {
+ var x = x1 - x2,
+ y = y1 - y2;
+ if (!x && !y) {
+ return 0;
+ }
+ return (180 + math.atan2(-y, -x) * 180 / PI + 360) % 360;
+ } else {
+ return R.angle(x1, y1, x3, y3) - R.angle(x2, y2, x3, y3);
+ }
+ };
+ /*\
+ * Raphael.rad
+ [ method ]
+ **
+ * Transform angle to radians
+ > Parameters
+ - deg (number) angle in degrees
+ = (number) angle in radians.
+ \*/
+ R.rad = function (deg) {
+ return deg % 360 * PI / 180;
+ };
+ /*\
+ * Raphael.deg
+ [ method ]
+ **
+ * Transform angle to degrees
+ > Parameters
+ - rad (number) angle in radians
+ = (number) angle in degrees.
+ \*/
+ R.deg = function (rad) {
+ return Math.round ((rad * 180 / PI% 360)* 1000) / 1000;
+ };
+ /*\
+ * Raphael.snapTo
+ [ method ]
+ **
+ * Snaps given value to given grid.
+ > Parameters
+ - values (array|number) given array of values or step of the grid
+ - value (number) value to adjust
+ - tolerance (number) #optional tolerance for snapping. Default is `10`.
+ = (number) adjusted value.
+ \*/
+ R.snapTo = function (values, value, tolerance) {
+ tolerance = R.is(tolerance, "finite") ? tolerance : 10;
+ if (R.is(values, array)) {
+ var i = values.length;
+ while (i--) if (abs(values[i] - value) <= tolerance) {
+ return values[i];
+ }
+ } else {
+ values = +values;
+ var rem = value % values;
+ if (rem < tolerance) {
+ return value - rem;
+ }
+ if (rem > values - tolerance) {
+ return value - rem + values;
+ }
+ }
+ return value;
+ };
+
+ /*\
+ * Raphael.createUUID
+ [ method ]
+ **
+ * Returns RFC4122, version 4 ID
+ \*/
+ var createUUID = R.createUUID = (function (uuidRegEx, uuidReplacer) {
+ return function () {
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(uuidRegEx, uuidReplacer).toUpperCase();
+ };
+ })(/[xy]/g, function (c) {
+ var r = math.random() * 16 | 0,
+ v = c == "x" ? r : (r & 3 | 8);
+ return v.toString(16);
+ });
+
+ /*\
+ * Raphael.setWindow
+ [ method ]
+ **
+ * Used when you need to draw in `&lt;iframe>`. Switched window to the iframe one.
+ > Parameters
+ - newwin (window) new window object
+ \*/
+ R.setWindow = function (newwin) {
+ eve("raphael.setWindow", R, g.win, newwin);
+ g.win = newwin;
+ g.doc = g.win.document;
+ if (R._engine.initWin) {
+ R._engine.initWin(g.win);
+ }
+ };
+ var toHex = function (color) {
+ if (R.vml) {
+ // http://dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/
+ var trim = /^\s+|\s+$/g;
+ var bod;
+ try {
+ var docum = new ActiveXObject("htmlfile");
+ docum.write("<body>");
+ docum.close();
+ bod = docum.body;
+ } catch(e) {
+ bod = createPopup().document.body;
+ }
+ var range = bod.createTextRange();
+ toHex = cacher(function (color) {
+ try {
+ bod.style.color = Str(color).replace(trim, E);
+ var value = range.queryCommandValue("ForeColor");
+ value = ((value & 255) << 16) | (value & 65280) | ((value & 16711680) >>> 16);
+ return "#" + ("000000" + value.toString(16)).slice(-6);
+ } catch(e) {
+ return "none";
+ }
+ });
+ } else {
+ var i = g.doc.createElement("i");
+ i.title = "Rapha\xebl Colour Picker";
+ i.style.display = "none";
+ g.doc.body.appendChild(i);
+ toHex = cacher(function (color) {
+ i.style.color = color;
+ return g.doc.defaultView.getComputedStyle(i, E).getPropertyValue("color");
+ });
+ }
+ return toHex(color);
+ },
+ hsbtoString = function () {
+ return "hsb(" + [this.h, this.s, this.b] + ")";
+ },
+ hsltoString = function () {
+ return "hsl(" + [this.h, this.s, this.l] + ")";
+ },
+ rgbtoString = function () {
+ return this.hex;
+ },
+ prepareRGB = function (r, g, b) {
+ if (g == null && R.is(r, "object") && "r" in r && "g" in r && "b" in r) {
+ b = r.b;
+ g = r.g;
+ r = r.r;
+ }
+ if (g == null && R.is(r, string)) {
+ var clr = R.getRGB(r);
+ r = clr.r;
+ g = clr.g;
+ b = clr.b;
+ }
+ if (r > 1 || g > 1 || b > 1) {
+ r /= 255;
+ g /= 255;
+ b /= 255;
+ }
+
+ return [r, g, b];
+ },
+ packageRGB = function (r, g, b, o) {
+ r *= 255;
+ g *= 255;
+ b *= 255;
+ var rgb = {
+ r: r,
+ g: g,
+ b: b,
+ hex: R.rgb(r, g, b),
+ toString: rgbtoString
+ };
+ R.is(o, "finite") && (rgb.opacity = o);
+ return rgb;
+ };
+
+ /*\
+ * Raphael.color
+ [ method ]
+ **
+ * Parses the color string and returns object with all values for the given color.
+ > Parameters
+ - clr (string) color string in one of the supported formats (see @Raphael.getRGB)
+ = (object) Combined RGB & HSB object in format:
+ o {
+ o r (number) red,
+ o g (number) green,
+ o b (number) blue,
+ o hex (string) color in HTML/CSS format: #••••••,
+ o error (boolean) `true` if string can’t be parsed,
+ o h (number) hue,
+ o s (number) saturation,
+ o v (number) value (brightness),
+ o l (number) lightness
+ o }
+ \*/
+ R.color = function (clr) {
+ var rgb;
+ if (R.is(clr, "object") && "h" in clr && "s" in clr && "b" in clr) {
+ rgb = R.hsb2rgb(clr);
+ clr.r = rgb.r;
+ clr.g = rgb.g;
+ clr.b = rgb.b;
+ clr.hex = rgb.hex;
+ } else if (R.is(clr, "object") && "h" in clr && "s" in clr && "l" in clr) {
+ rgb = R.hsl2rgb(clr);
+ clr.r = rgb.r;
+ clr.g = rgb.g;
+ clr.b = rgb.b;
+ clr.hex = rgb.hex;
+ } else {
+ if (R.is(clr, "string")) {
+ clr = R.getRGB(clr);
+ }
+ if (R.is(clr, "object") && "r" in clr && "g" in clr && "b" in clr) {
+ rgb = R.rgb2hsl(clr);
+ clr.h = rgb.h;
+ clr.s = rgb.s;
+ clr.l = rgb.l;
+ rgb = R.rgb2hsb(clr);
+ clr.v = rgb.b;
+ } else {
+ clr = {hex: "none"};
+ clr.r = clr.g = clr.b = clr.h = clr.s = clr.v = clr.l = -1;
+ }
+ }
+ clr.toString = rgbtoString;
+ return clr;
+ };
+ /*\
+ * Raphael.hsb2rgb
+ [ method ]
+ **
+ * Converts HSB values to RGB object.
+ > Parameters
+ - h (number) hue
+ - s (number) saturation
+ - v (number) value or brightness
+ = (object) RGB object in format:
+ o {
+ o r (number) red,
+ o g (number) green,
+ o b (number) blue,
+ o hex (string) color in HTML/CSS format: #••••••
+ o }
+ \*/
+ R.hsb2rgb = function (h, s, v, o) {
+ if (this.is(h, "object") && "h" in h && "s" in h && "b" in h) {
+ v = h.b;
+ s = h.s;
+ o = h.o;
+ h = h.h;
+ }
+ h *= 360;
+ var R, G, B, X, C;
+ h = (h % 360) / 60;
+ C = v * s;
+ X = C * (1 - abs(h % 2 - 1));
+ R = G = B = v - C;
+
+ h = ~~h;
+ R += [C, X, 0, 0, X, C][h];
+ G += [X, C, C, X, 0, 0][h];
+ B += [0, 0, X, C, C, X][h];
+ return packageRGB(R, G, B, o);
+ };
+ /*\
+ * Raphael.hsl2rgb
+ [ method ]
+ **
+ * Converts HSL values to RGB object.
+ > Parameters
+ - h (number) hue
+ - s (number) saturation
+ - l (number) luminosity
+ = (object) RGB object in format:
+ o {
+ o r (number) red,
+ o g (number) green,
+ o b (number) blue,
+ o hex (string) color in HTML/CSS format: #••••••
+ o }
+ \*/
+ R.hsl2rgb = function (h, s, l, o) {
+ if (this.is(h, "object") && "h" in h && "s" in h && "l" in h) {
+ l = h.l;
+ s = h.s;
+ h = h.h;
+ }
+ if (h > 1 || s > 1 || l > 1) {
+ h /= 360;
+ s /= 100;
+ l /= 100;
+ }
+ h *= 360;
+ var R, G, B, X, C;
+ h = (h % 360) / 60;
+ C = 2 * s * (l < .5 ? l : 1 - l);
+ X = C * (1 - abs(h % 2 - 1));
+ R = G = B = l - C / 2;
+
+ h = ~~h;
+ R += [C, X, 0, 0, X, C][h];
+ G += [X, C, C, X, 0, 0][h];
+ B += [0, 0, X, C, C, X][h];
+ return packageRGB(R, G, B, o);
+ };
+ /*\
+ * Raphael.rgb2hsb
+ [ method ]
+ **
+ * Converts RGB values to HSB object.
+ > Parameters
+ - r (number) red
+ - g (number) green
+ - b (number) blue
+ = (object) HSB object in format:
+ o {
+ o h (number) hue
+ o s (number) saturation
+ o b (number) brightness
+ o }
+ \*/
+ R.rgb2hsb = function (r, g, b) {
+ b = prepareRGB(r, g, b);
+ r = b[0];
+ g = b[1];
+ b = b[2];
+
+ var H, S, V, C;
+ V = mmax(r, g, b);
+ C = V - mmin(r, g, b);
+ H = (C == 0 ? null :
+ V == r ? (g - b) / C :
+ V == g ? (b - r) / C + 2 :
+ (r - g) / C + 4
+ );
+ H = ((H + 360) % 6) * 60 / 360;
+ S = C == 0 ? 0 : C / V;
+ return {h: H, s: S, b: V, toString: hsbtoString};
+ };
+ /*\
+ * Raphael.rgb2hsl
+ [ method ]
+ **
+ * Converts RGB values to HSL object.
+ > Parameters
+ - r (number) red
+ - g (number) green
+ - b (number) blue
+ = (object) HSL object in format:
+ o {
+ o h (number) hue
+ o s (number) saturation
+ o l (number) luminosity
+ o }
+ \*/
+ R.rgb2hsl = function (r, g, b) {
+ b = prepareRGB(r, g, b);
+ r = b[0];
+ g = b[1];
+ b = b[2];
+
+ var H, S, L, M, m, C;
+ M = mmax(r, g, b);
+ m = mmin(r, g, b);
+ C = M - m;
+ H = (C == 0 ? null :
+ M == r ? (g - b) / C :
+ M == g ? (b - r) / C + 2 :
+ (r - g) / C + 4);
+ H = ((H + 360) % 6) * 60 / 360;
+ L = (M + m) / 2;
+ S = (C == 0 ? 0 :
+ L < .5 ? C / (2 * L) :
+ C / (2 - 2 * L));
+ return {h: H, s: S, l: L, toString: hsltoString};
+ };
+ R._path2string = function () {
+ return this.join(",").replace(p2s, "$1");
+ };
+ function repush(array, item) {
+ for (var i = 0, ii = array.length; i < ii; i++) if (array[i] === item) {
+ return array.push(array.splice(i, 1)[0]);
+ }
+ }
+ function cacher(f, scope, postprocessor) {
+ function newf() {
+ var arg = Array.prototype.slice.call(arguments, 0),
+ args = arg.join("\u2400"),
+ cache = newf.cache = newf.cache || {},
+ count = newf.count = newf.count || [];
+ if (cache[has](args)) {
+ repush(count, args);
+ return postprocessor ? postprocessor(cache[args]) : cache[args];
+ }
+ count.length >= 1e3 && delete cache[count.shift()];
+ count.push(args);
+ cache[args] = f[apply](scope, arg);
+ return postprocessor ? postprocessor(cache[args]) : cache[args];
+ }
+ return newf;
+ }
+
+ var preload = R._preload = function (src, f) {
+ var img = g.doc.createElement("img");
+ img.style.cssText = "position:absolute;left:-9999em;top:-9999em";
+ img.onload = function () {
+ f.call(this);
+ this.onload = null;
+ g.doc.body.removeChild(this);
+ };
+ img.onerror = function () {
+ g.doc.body.removeChild(this);
+ };
+ g.doc.body.appendChild(img);
+ img.src = src;
+ };
+
+ function clrToString() {
+ return this.hex;
+ }
+
+ /*\
+ * Raphael.getRGB
+ [ method ]
+ **
+ * Parses colour string as RGB object
+ > Parameters
+ - colour (string) colour string in one of formats:
+ # <ul>
+ # <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>
+ # <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>
+ # <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>
+ # <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>
+ # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>
+ # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>
+ # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
+ # <li>hsl(•••, •••, •••) — same as hsb</li>
+ # <li>hsl(•••%, •••%, •••%) — same as hsb</li>
+ # </ul>
+ = (object) RGB object in format:
+ o {
+ o r (number) red,
+ o g (number) green,
+ o b (number) blue
+ o hex (string) color in HTML/CSS format: #••••••,
+ o error (boolean) true if string can’t be parsed
+ o }
+ \*/
+ R.getRGB = cacher(function (colour) {
+ if (!colour || !!((colour = Str(colour)).indexOf("-") + 1)) {
+ return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
+ }
+ if (colour == "none") {
+ return {r: -1, g: -1, b: -1, hex: "none", toString: clrToString};
+ }
+ !(hsrg[has](colour.toLowerCase().substring(0, 2)) || colour.charAt() == "#") && (colour = toHex(colour));
+ var res,
+ red,
+ green,
+ blue,
+ opacity,
+ t,
+ values,
+ rgb = colour.match(colourRegExp);
+ if (rgb) {
+ if (rgb[2]) {
+ blue = toInt(rgb[2].substring(5), 16);
+ green = toInt(rgb[2].substring(3, 5), 16);
+ red = toInt(rgb[2].substring(1, 3), 16);
+ }
+ if (rgb[3]) {
+ blue = toInt((t = rgb[3].charAt(3)) + t, 16);
+ green = toInt((t = rgb[3].charAt(2)) + t, 16);
+ red = toInt((t = rgb[3].charAt(1)) + t, 16);
+ }
+ if (rgb[4]) {
+ values = rgb[4][split](commaSpaces);
+ red = toFloat(values[0]);
+ values[0].slice(-1) == "%" && (red *= 2.55);
+ green = toFloat(values[1]);
+ values[1].slice(-1) == "%" && (green *= 2.55);
+ blue = toFloat(values[2]);
+ values[2].slice(-1) == "%" && (blue *= 2.55);
+ rgb[1].toLowerCase().slice(0, 4) == "rgba" && (opacity = toFloat(values[3]));
+ values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
+ }
+ if (rgb[5]) {
+ values = rgb[5][split](commaSpaces);
+ red = toFloat(values[0]);
+ values[0].slice(-1) == "%" && (red *= 2.55);
+ green = toFloat(values[1]);
+ values[1].slice(-1) == "%" && (green *= 2.55);
+ blue = toFloat(values[2]);
+ values[2].slice(-1) == "%" && (blue *= 2.55);
+ (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
+ rgb[1].toLowerCase().slice(0, 4) == "hsba" && (opacity = toFloat(values[3]));
+ values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
+ return R.hsb2rgb(red, green, blue, opacity);
+ }
+ if (rgb[6]) {
+ values = rgb[6][split](commaSpaces);
+ red = toFloat(values[0]);
+ values[0].slice(-1) == "%" && (red *= 2.55);
+ green = toFloat(values[1]);
+ values[1].slice(-1) == "%" && (green *= 2.55);
+ blue = toFloat(values[2]);
+ values[2].slice(-1) == "%" && (blue *= 2.55);
+ (values[0].slice(-3) == "deg" || values[0].slice(-1) == "\xb0") && (red /= 360);
+ rgb[1].toLowerCase().slice(0, 4) == "hsla" && (opacity = toFloat(values[3]));
+ values[3] && values[3].slice(-1) == "%" && (opacity /= 100);
+ return R.hsl2rgb(red, green, blue, opacity);
+ }
+ rgb = {r: red, g: green, b: blue, toString: clrToString};
+ rgb.hex = "#" + (16777216 | blue | (green << 8) | (red << 16)).toString(16).slice(1);
+ R.is(opacity, "finite") && (rgb.opacity = opacity);
+ return rgb;
+ }
+ return {r: -1, g: -1, b: -1, hex: "none", error: 1, toString: clrToString};
+ }, R);
+ /*\
+ * Raphael.hsb
+ [ method ]
+ **
+ * Converts HSB values to hex representation of the colour.
+ > Parameters
+ - h (number) hue
+ - s (number) saturation
+ - b (number) value or brightness
+ = (string) hex representation of the colour.
+ \*/
+ R.hsb = cacher(function (h, s, b) {
+ return R.hsb2rgb(h, s, b).hex;
+ });
+ /*\
+ * Raphael.hsl
+ [ method ]
+ **
+ * Converts HSL values to hex representation of the colour.
+ > Parameters
+ - h (number) hue
+ - s (number) saturation
+ - l (number) luminosity
+ = (string) hex representation of the colour.
+ \*/
+ R.hsl = cacher(function (h, s, l) {
+ return R.hsl2rgb(h, s, l).hex;
+ });
+ /*\
+ * Raphael.rgb
+ [ method ]
+ **
+ * Converts RGB values to hex representation of the colour.
+ > Parameters
+ - r (number) red
+ - g (number) green
+ - b (number) blue
+ = (string) hex representation of the colour.
+ \*/
+ R.rgb = cacher(function (r, g, b) {
+ function round(x) { return (x + 0.5) | 0; }
+ return "#" + (16777216 | round(b) | (round(g) << 8) | (round(r) << 16)).toString(16).slice(1);
+ });
+ /*\
+ * Raphael.getColor
+ [ method ]
+ **
+ * On each call returns next colour in the spectrum. To reset it back to red call @Raphael.getColor.reset
+ > Parameters
+ - value (number) #optional brightness, default is `0.75`
+ = (string) hex representation of the colour.
+ \*/
+ R.getColor = function (value) {
+ var start = this.getColor.start = this.getColor.start || {h: 0, s: 1, b: value || .75},
+ rgb = this.hsb2rgb(start.h, start.s, start.b);
+ start.h += .075;
+ if (start.h > 1) {
+ start.h = 0;
+ start.s -= .2;
+ start.s <= 0 && (this.getColor.start = {h: 0, s: 1, b: start.b});
+ }
+ return rgb.hex;
+ };
+ /*\
+ * Raphael.getColor.reset
+ [ method ]
+ **
+ * Resets spectrum position for @Raphael.getColor back to red.
+ \*/
+ R.getColor.reset = function () {
+ delete this.start;
+ };
+
+ // http://schepers.cc/getting-to-the-point
+ function catmullRom2bezier(crp, z) {
+ var d = [];
+ for (var i = 0, iLen = crp.length; iLen - 2 * !z > i; i += 2) {
+ var p = [
+ {x: +crp[i - 2], y: +crp[i - 1]},
+ {x: +crp[i], y: +crp[i + 1]},
+ {x: +crp[i + 2], y: +crp[i + 3]},
+ {x: +crp[i + 4], y: +crp[i + 5]}
+ ];
+ if (z) {
+ if (!i) {
+ p[0] = {x: +crp[iLen - 2], y: +crp[iLen - 1]};
+ } else if (iLen - 4 == i) {
+ p[3] = {x: +crp[0], y: +crp[1]};
+ } else if (iLen - 2 == i) {
+ p[2] = {x: +crp[0], y: +crp[1]};
+ p[3] = {x: +crp[2], y: +crp[3]};
+ }
+ } else {
+ if (iLen - 4 == i) {
+ p[3] = p[2];
+ } else if (!i) {
+ p[0] = {x: +crp[i], y: +crp[i + 1]};
+ }
+ }
+ d.push(["C",
+ (-p[0].x + 6 * p[1].x + p[2].x) / 6,
+ (-p[0].y + 6 * p[1].y + p[2].y) / 6,
+ (p[1].x + 6 * p[2].x - p[3].x) / 6,
+ (p[1].y + 6*p[2].y - p[3].y) / 6,
+ p[2].x,
+ p[2].y
+ ]);
+ }
+
+ return d;
+ }
+ /*\
+ * Raphael.parsePathString
+ [ method ]
+ **
+ * Utility method
+ **
+ * Parses given path string into an array of arrays of path segments.
+ > Parameters
+ - pathString (string|array) path string or array of segments (in the last case it will be returned straight away)
+ = (array) array of segments.
+ \*/
+ R.parsePathString = function (pathString) {
+ if (!pathString) {
+ return null;
+ }
+ var pth = paths(pathString);
+ if (pth.arr) {
+ return pathClone(pth.arr);
+ }
+
+ var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, r: 4, q: 4, s: 4, t: 2, v: 1, z: 0},
+ data = [];
+ if (R.is(pathString, array) && R.is(pathString[0], array)) { // rough assumption
+ data = pathClone(pathString);
+ }
+ if (!data.length) {
+ Str(pathString).replace(pathCommand, function (a, b, c) {
+ var params = [],
+ name = b.toLowerCase();
+ c.replace(pathValues, function (a, b) {
+ b && params.push(+b);
+ });
+ if (name == "m" && params.length > 2) {
+ data.push([b][concat](params.splice(0, 2)));
+ name = "l";
+ b = b == "m" ? "l" : "L";
+ }
+ if (name == "r") {
+ data.push([b][concat](params));
+ } else while (params.length >= paramCounts[name]) {
+ data.push([b][concat](params.splice(0, paramCounts[name])));
+ if (!paramCounts[name]) {
+ break;
+ }
+ }
+ });
+ }
+ data.toString = R._path2string;
+ pth.arr = pathClone(data);
+ return data;
+ };
+ /*\
+ * Raphael.parseTransformString
+ [ method ]
+ **
+ * Utility method
+ **
+ * Parses given path string into an array of transformations.
+ > Parameters
+ - TString (string|array) transform string or array of transformations (in the last case it will be returned straight away)
+ = (array) array of transformations.
+ \*/
+ R.parseTransformString = cacher(function (TString) {
+ if (!TString) {
+ return null;
+ }
+ var paramCounts = {r: 3, s: 4, t: 2, m: 6},
+ data = [];
+ if (R.is(TString, array) && R.is(TString[0], array)) { // rough assumption
+ data = pathClone(TString);
+ }
+ if (!data.length) {
+ Str(TString).replace(tCommand, function (a, b, c) {
+ var params = [],
+ name = lowerCase.call(b);
+ c.replace(pathValues, function (a, b) {
+ b && params.push(+b);
+ });
+ data.push([b][concat](params));
+ });
+ }
+ data.toString = R._path2string;
+ return data;
+ });
+ // PATHS
+ var paths = function (ps) {
+ var p = paths.ps = paths.ps || {};
+ if (p[ps]) {
+ p[ps].sleep = 100;
+ } else {
+ p[ps] = {
+ sleep: 100
+ };
+ }
+ setTimeout(function () {
+ for (var key in p) if (p[has](key) && key != ps) {
+ p[key].sleep--;
+ !p[key].sleep && delete p[key];
+ }
+ });
+ return p[ps];
+ };
+ /*\
+ * Raphael.findDotsAtSegment
+ [ method ]
+ **
+ * Utility method
+ **
+ * Find dot coordinates on the given cubic bezier curve at the given t.
+ > Parameters
+ - p1x (number) x of the first point of the curve
+ - p1y (number) y of the first point of the curve
+ - c1x (number) x of the first anchor of the curve
+ - c1y (number) y of the first anchor of the curve
+ - c2x (number) x of the second anchor of the curve
+ - c2y (number) y of the second anchor of the curve
+ - p2x (number) x of the second point of the curve
+ - p2y (number) y of the second point of the curve
+ - t (number) position on the curve (0..1)
+ = (object) point information in format:
+ o {
+ o x: (number) x coordinate of the point
+ o y: (number) y coordinate of the point
+ o m: {
+ o x: (number) x coordinate of the left anchor
+ o y: (number) y coordinate of the left anchor
+ o }
+ o n: {
+ o x: (number) x coordinate of the right anchor
+ o y: (number) y coordinate of the right anchor
+ o }
+ o start: {
+ o x: (number) x coordinate of the start of the curve
+ o y: (number) y coordinate of the start of the curve
+ o }
+ o end: {
+ o x: (number) x coordinate of the end of the curve
+ o y: (number) y coordinate of the end of the curve
+ o }
+ o alpha: (number) angle of the curve derivative at the point
+ o }
+ \*/
+ R.findDotsAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
+ var t1 = 1 - t,
+ t13 = pow(t1, 3),
+ t12 = pow(t1, 2),
+ t2 = t * t,
+ t3 = t2 * t,
+ x = t13 * p1x + t12 * 3 * t * c1x + t1 * 3 * t * t * c2x + t3 * p2x,
+ y = t13 * p1y + t12 * 3 * t * c1y + t1 * 3 * t * t * c2y + t3 * p2y,
+ mx = p1x + 2 * t * (c1x - p1x) + t2 * (c2x - 2 * c1x + p1x),
+ my = p1y + 2 * t * (c1y - p1y) + t2 * (c2y - 2 * c1y + p1y),
+ nx = c1x + 2 * t * (c2x - c1x) + t2 * (p2x - 2 * c2x + c1x),
+ ny = c1y + 2 * t * (c2y - c1y) + t2 * (p2y - 2 * c2y + c1y),
+ ax = t1 * p1x + t * c1x,
+ ay = t1 * p1y + t * c1y,
+ cx = t1 * c2x + t * p2x,
+ cy = t1 * c2y + t * p2y,
+ alpha = (90 - math.atan2(mx - nx, my - ny) * 180 / PI);
+ (mx > nx || my < ny) && (alpha += 180);
+ return {
+ x: x,
+ y: y,
+ m: {x: mx, y: my},
+ n: {x: nx, y: ny},
+ start: {x: ax, y: ay},
+ end: {x: cx, y: cy},
+ alpha: alpha
+ };
+ };
+ /*\
+ * Raphael.bezierBBox
+ [ method ]
+ **
+ * Utility method
+ **
+ * Return bounding box of a given cubic bezier curve
+ > Parameters
+ - p1x (number) x of the first point of the curve
+ - p1y (number) y of the first point of the curve
+ - c1x (number) x of the first anchor of the curve
+ - c1y (number) y of the first anchor of the curve
+ - c2x (number) x of the second anchor of the curve
+ - c2y (number) y of the second anchor of the curve
+ - p2x (number) x of the second point of the curve
+ - p2y (number) y of the second point of the curve
+ * or
+ - bez (array) array of six points for bezier curve
+ = (object) point information in format:
+ o {
+ o min: {
+ o x: (number) x coordinate of the left point
+ o y: (number) y coordinate of the top point
+ o }
+ o max: {
+ o x: (number) x coordinate of the right point
+ o y: (number) y coordinate of the bottom point
+ o }
+ o }
+ \*/
+ R.bezierBBox = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
+ if (!R.is(p1x, "array")) {
+ p1x = [p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y];
+ }
+ var bbox = curveDim.apply(null, p1x);
+ return {
+ x: bbox.min.x,
+ y: bbox.min.y,
+ x2: bbox.max.x,
+ y2: bbox.max.y,
+ width: bbox.max.x - bbox.min.x,
+ height: bbox.max.y - bbox.min.y
+ };
+ };
+ /*\
+ * Raphael.isPointInsideBBox
+ [ method ]
+ **
+ * Utility method
+ **
+ * Returns `true` if given point is inside bounding boxes.
+ > Parameters
+ - bbox (string) bounding box
+ - x (string) x coordinate of the point
+ - y (string) y coordinate of the point
+ = (boolean) `true` if point inside
+ \*/
+ R.isPointInsideBBox = function (bbox, x, y) {
+ return x >= bbox.x && x <= bbox.x2 && y >= bbox.y && y <= bbox.y2;
+ };
+ /*\
+ * Raphael.isBBoxIntersect
+ [ method ]
+ **
+ * Utility method
+ **
+ * Returns `true` if two bounding boxes intersect
+ > Parameters
+ - bbox1 (string) first bounding box
+ - bbox2 (string) second bounding box
+ = (boolean) `true` if they intersect
+ \*/
+ R.isBBoxIntersect = function (bbox1, bbox2) {
+ var i = R.isPointInsideBBox;
+ return i(bbox2, bbox1.x, bbox1.y)
+ || i(bbox2, bbox1.x2, bbox1.y)
+ || i(bbox2, bbox1.x, bbox1.y2)
+ || i(bbox2, bbox1.x2, bbox1.y2)
+ || i(bbox1, bbox2.x, bbox2.y)
+ || i(bbox1, bbox2.x2, bbox2.y)
+ || i(bbox1, bbox2.x, bbox2.y2)
+ || i(bbox1, bbox2.x2, bbox2.y2)
+ || (bbox1.x < bbox2.x2 && bbox1.x > bbox2.x || bbox2.x < bbox1.x2 && bbox2.x > bbox1.x)
+ && (bbox1.y < bbox2.y2 && bbox1.y > bbox2.y || bbox2.y < bbox1.y2 && bbox2.y > bbox1.y);
+ };
+ function base3(t, p1, p2, p3, p4) {
+ var t1 = -3 * p1 + 9 * p2 - 9 * p3 + 3 * p4,
+ t2 = t * t1 + 6 * p1 - 12 * p2 + 6 * p3;
+ return t * t2 - 3 * p1 + 3 * p2;
+ }
+ function bezlen(x1, y1, x2, y2, x3, y3, x4, y4, z) {
+ if (z == null) {
+ z = 1;
+ }
+ z = z > 1 ? 1 : z < 0 ? 0 : z;
+ var z2 = z / 2,
+ n = 12,
+ Tvalues = [-0.1252,0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],
+ Cvalues = [0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],
+ sum = 0;
+ for (var i = 0; i < n; i++) {
+ var ct = z2 * Tvalues[i] + z2,
+ xbase = base3(ct, x1, x2, x3, x4),
+ ybase = base3(ct, y1, y2, y3, y4),
+ comb = xbase * xbase + ybase * ybase;
+ sum += Cvalues[i] * math.sqrt(comb);
+ }
+ return z2 * sum;
+ }
+ function getTatLen(x1, y1, x2, y2, x3, y3, x4, y4, ll) {
+ if (ll < 0 || bezlen(x1, y1, x2, y2, x3, y3, x4, y4) < ll) {
+ return;
+ }
+ var t = 1,
+ step = t / 2,
+ t2 = t - step,
+ l,
+ e = .01;
+ l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
+ while (abs(l - ll) > e) {
+ step /= 2;
+ t2 += (l < ll ? 1 : -1) * step;
+ l = bezlen(x1, y1, x2, y2, x3, y3, x4, y4, t2);
+ }
+ return t2;
+ }
+ function intersect(x1, y1, x2, y2, x3, y3, x4, y4) {
+ if (
+ mmax(x1, x2) < mmin(x3, x4) ||
+ mmin(x1, x2) > mmax(x3, x4) ||
+ mmax(y1, y2) < mmin(y3, y4) ||
+ mmin(y1, y2) > mmax(y3, y4)
+ ) {
+ return;
+ }
+ var nx = (x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4),
+ ny = (x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4),
+ denominator = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
+
+ if (!denominator) {
+ return;
+ }
+ var px = nx / denominator,
+ py = ny / denominator,
+ px2 = +px.toFixed(2),
+ py2 = +py.toFixed(2);
+ if (
+ px2 < +mmin(x1, x2).toFixed(2) ||
+ px2 > +mmax(x1, x2).toFixed(2) ||
+ px2 < +mmin(x3, x4).toFixed(2) ||
+ px2 > +mmax(x3, x4).toFixed(2) ||
+ py2 < +mmin(y1, y2).toFixed(2) ||
+ py2 > +mmax(y1, y2).toFixed(2) ||
+ py2 < +mmin(y3, y4).toFixed(2) ||
+ py2 > +mmax(y3, y4).toFixed(2)
+ ) {
+ return;
+ }
+ return {x: px, y: py};
+ }
+ function inter(bez1, bez2) {
+ return interHelper(bez1, bez2);
+ }
+ function interCount(bez1, bez2) {
+ return interHelper(bez1, bez2, 1);
+ }
+ function interHelper(bez1, bez2, justCount) {
+ var bbox1 = R.bezierBBox(bez1),
+ bbox2 = R.bezierBBox(bez2);
+ if (!R.isBBoxIntersect(bbox1, bbox2)) {
+ return justCount ? 0 : [];
+ }
+ var l1 = bezlen.apply(0, bez1),
+ l2 = bezlen.apply(0, bez2),
+ n1 = mmax(~~(l1 / 5), 1),
+ n2 = mmax(~~(l2 / 5), 1),
+ dots1 = [],
+ dots2 = [],
+ xy = {},
+ res = justCount ? 0 : [];
+ for (var i = 0; i < n1 + 1; i++) {
+ var p = R.findDotsAtSegment.apply(R, bez1.concat(i / n1));
+ dots1.push({x: p.x, y: p.y, t: i / n1});
+ }
+ for (i = 0; i < n2 + 1; i++) {
+ p = R.findDotsAtSegment.apply(R, bez2.concat(i / n2));
+ dots2.push({x: p.x, y: p.y, t: i / n2});
+ }
+ for (i = 0; i < n1; i++) {
+ for (var j = 0; j < n2; j++) {
+ var di = dots1[i],
+ di1 = dots1[i + 1],
+ dj = dots2[j],
+ dj1 = dots2[j + 1],
+ ci = abs(di1.x - di.x) < .001 ? "y" : "x",
+ cj = abs(dj1.x - dj.x) < .001 ? "y" : "x",
+ is = intersect(di.x, di.y, di1.x, di1.y, dj.x, dj.y, dj1.x, dj1.y);
+ if (is) {
+ if (xy[is.x.toFixed(4)] == is.y.toFixed(4)) {
+ continue;
+ }
+ xy[is.x.toFixed(4)] = is.y.toFixed(4);
+ var t1 = di.t + abs((is[ci] - di[ci]) / (di1[ci] - di[ci])) * (di1.t - di.t),
+ t2 = dj.t + abs((is[cj] - dj[cj]) / (dj1[cj] - dj[cj])) * (dj1.t - dj.t);
+ if (t1 >= 0 && t1 <= 1.001 && t2 >= 0 && t2 <= 1.001) {
+ if (justCount) {
+ res++;
+ } else {
+ res.push({
+ x: is.x,
+ y: is.y,
+ t1: mmin(t1, 1),
+ t2: mmin(t2, 1)
+ });
+ }
+ }
+ }
+ }
+ }
+ return res;
+ }
+ /*\
+ * Raphael.pathIntersection
+ [ method ]
+ **
+ * Utility method
+ **
+ * Finds intersections of two paths
+ > Parameters
+ - path1 (string) path string
+ - path2 (string) path string
+ = (array) dots of intersection
+ o [
+ o {
+ o x: (number) x coordinate of the point
+ o y: (number) y coordinate of the point
+ o t1: (number) t value for segment of path1
+ o t2: (number) t value for segment of path2
+ o segment1: (number) order number for segment of path1
+ o segment2: (number) order number for segment of path2
+ o bez1: (array) eight coordinates representing beziér curve for the segment of path1
+ o bez2: (array) eight coordinates representing beziér curve for the segment of path2
+ o }
+ o ]
+ \*/
+ R.pathIntersection = function (path1, path2) {
+ return interPathHelper(path1, path2);
+ };
+ R.pathIntersectionNumber = function (path1, path2) {
+ return interPathHelper(path1, path2, 1);
+ };
+ function interPathHelper(path1, path2, justCount) {
+ path1 = R._path2curve(path1);
+ path2 = R._path2curve(path2);
+ var x1, y1, x2, y2, x1m, y1m, x2m, y2m, bez1, bez2,
+ res = justCount ? 0 : [];
+ for (var i = 0, ii = path1.length; i < ii; i++) {
+ var pi = path1[i];
+ if (pi[0] == "M") {
+ x1 = x1m = pi[1];
+ y1 = y1m = pi[2];
+ } else {
+ if (pi[0] == "C") {
+ bez1 = [x1, y1].concat(pi.slice(1));
+ x1 = bez1[6];
+ y1 = bez1[7];
+ } else {
+ bez1 = [x1, y1, x1, y1, x1m, y1m, x1m, y1m];
+ x1 = x1m;
+ y1 = y1m;
+ }
+ for (var j = 0, jj = path2.length; j < jj; j++) {
+ var pj = path2[j];
+ if (pj[0] == "M") {
+ x2 = x2m = pj[1];
+ y2 = y2m = pj[2];
+ } else {
+ if (pj[0] == "C") {
+ bez2 = [x2, y2].concat(pj.slice(1));
+ x2 = bez2[6];
+ y2 = bez2[7];
+ } else {
+ bez2 = [x2, y2, x2, y2, x2m, y2m, x2m, y2m];
+ x2 = x2m;
+ y2 = y2m;
+ }
+ var intr = interHelper(bez1, bez2, justCount);
+ if (justCount) {
+ res += intr;
+ } else {
+ for (var k = 0, kk = intr.length; k < kk; k++) {
+ intr[k].segment1 = i;
+ intr[k].segment2 = j;
+ intr[k].bez1 = bez1;
+ intr[k].bez2 = bez2;
+ }
+ res = res.concat(intr);
+ }
+ }
+ }
+ }
+ }
+ return res;
+ }
+ /*\
+ * Raphael.isPointInsidePath
+ [ method ]
+ **
+ * Utility method
+ **
+ * Returns `true` if given point is inside a given closed path.
+ > Parameters
+ - path (string) path string
+ - x (number) x of the point
+ - y (number) y of the point
+ = (boolean) true, if point is inside the path
+ \*/
+ R.isPointInsidePath = function (path, x, y) {
+ var bbox = R.pathBBox(path);
+ return R.isPointInsideBBox(bbox, x, y) &&
+ interPathHelper(path, [["M", x, y], ["H", bbox.x2 + 10]], 1) % 2 == 1;
+ };
+ R._removedFactory = function (methodname) {
+ return function () {
+ eve("raphael.log", null, "Rapha\xebl: you are calling to method \u201c" + methodname + "\u201d of removed object", methodname);
+ };
+ };
+ /*\
+ * Raphael.pathBBox
+ [ method ]
+ **
+ * Utility method
+ **
+ * Return bounding box of a given path
+ > Parameters
+ - path (string) path string
+ = (object) bounding box
+ o {
+ o x: (number) x coordinate of the left top point of the box
+ o y: (number) y coordinate of the left top point of the box
+ o x2: (number) x coordinate of the right bottom point of the box
+ o y2: (number) y coordinate of the right bottom point of the box
+ o width: (number) width of the box
+ o height: (number) height of the box
+ o cx: (number) x coordinate of the center of the box
+ o cy: (number) y coordinate of the center of the box
+ o }
+ \*/
+ var pathDimensions = R.pathBBox = function (path) {
+ var pth = paths(path);
+ if (pth.bbox) {
+ return clone(pth.bbox);
+ }
+ if (!path) {
+ return {x: 0, y: 0, width: 0, height: 0, x2: 0, y2: 0};
+ }
+ path = path2curve(path);
+ var x = 0,
+ y = 0,
+ X = [],
+ Y = [],
+ p;
+ for (var i = 0, ii = path.length; i < ii; i++) {
+ p = path[i];
+ if (p[0] == "M") {
+ x = p[1];
+ y = p[2];
+ X.push(x);
+ Y.push(y);
+ } else {
+ var dim = curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
+ X = X[concat](dim.min.x, dim.max.x);
+ Y = Y[concat](dim.min.y, dim.max.y);
+ x = p[5];
+ y = p[6];
+ }
+ }
+ var xmin = mmin[apply](0, X),
+ ymin = mmin[apply](0, Y),
+ xmax = mmax[apply](0, X),
+ ymax = mmax[apply](0, Y),
+ width = xmax - xmin,
+ height = ymax - ymin,
+ bb = {
+ x: xmin,
+ y: ymin,
+ x2: xmax,
+ y2: ymax,
+ width: width,
+ height: height,
+ cx: xmin + width / 2,
+ cy: ymin + height / 2
+ };
+ pth.bbox = clone(bb);
+ return bb;
+ },
+ pathClone = function (pathArray) {
+ var res = clone(pathArray);
+ res.toString = R._path2string;
+ return res;
+ },
+ pathToRelative = R._pathToRelative = function (pathArray) {
+ var pth = paths(pathArray);
+ if (pth.rel) {
+ return pathClone(pth.rel);
+ }
+ if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
+ pathArray = R.parsePathString(pathArray);
+ }
+ var res = [],
+ x = 0,
+ y = 0,
+ mx = 0,
+ my = 0,
+ start = 0;
+ if (pathArray[0][0] == "M") {
+ x = pathArray[0][1];
+ y = pathArray[0][2];
+ mx = x;
+ my = y;
+ start++;
+ res.push(["M", x, y]);
+ }
+ for (var i = start, ii = pathArray.length; i < ii; i++) {
+ var r = res[i] = [],
+ pa = pathArray[i];
+ if (pa[0] != lowerCase.call(pa[0])) {
+ r[0] = lowerCase.call(pa[0]);
+ switch (r[0]) {
+ case "a":
+ r[1] = pa[1];
+ r[2] = pa[2];
+ r[3] = pa[3];
+ r[4] = pa[4];
+ r[5] = pa[5];
+ r[6] = +(pa[6] - x).toFixed(3);
+ r[7] = +(pa[7] - y).toFixed(3);
+ break;
+ case "v":
+ r[1] = +(pa[1] - y).toFixed(3);
+ break;
+ case "m":
+ mx = pa[1];
+ my = pa[2];
+ default:
+ for (var j = 1, jj = pa.length; j < jj; j++) {
+ r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3);
+ }
+ }
+ } else {
+ r = res[i] = [];
+ if (pa[0] == "m") {
+ mx = pa[1] + x;
+ my = pa[2] + y;
+ }
+ for (var k = 0, kk = pa.length; k < kk; k++) {
+ res[i][k] = pa[k];
+ }
+ }
+ var len = res[i].length;
+ switch (res[i][0]) {
+ case "z":
+ x = mx;
+ y = my;
+ break;
+ case "h":
+ x += +res[i][len - 1];
+ break;
+ case "v":
+ y += +res[i][len - 1];
+ break;
+ default:
+ x += +res[i][len - 2];
+ y += +res[i][len - 1];
+ }
+ }
+ res.toString = R._path2string;
+ pth.rel = pathClone(res);
+ return res;
+ },
+ pathToAbsolute = R._pathToAbsolute = function (pathArray) {
+ var pth = paths(pathArray);
+ if (pth.abs) {
+ return pathClone(pth.abs);
+ }
+ if (!R.is(pathArray, array) || !R.is(pathArray && pathArray[0], array)) { // rough assumption
+ pathArray = R.parsePathString(pathArray);
+ }
+ if (!pathArray || !pathArray.length) {
+ return [["M", 0, 0]];
+ }
+ var res = [],
+ x = 0,
+ y = 0,
+ mx = 0,
+ my = 0,
+ start = 0;
+ if (pathArray[0][0] == "M") {
+ x = +pathArray[0][1];
+ y = +pathArray[0][2];
+ mx = x;
+ my = y;
+ start++;
+ res[0] = ["M", x, y];
+ }
+ var crz = pathArray.length == 3 && pathArray[0][0] == "M" && pathArray[1][0].toUpperCase() == "R" && pathArray[2][0].toUpperCase() == "Z";
+ for (var r, pa, i = start, ii = pathArray.length; i < ii; i++) {
+ res.push(r = []);
+ pa = pathArray[i];
+ if (pa[0] != upperCase.call(pa[0])) {
+ r[0] = upperCase.call(pa[0]);
+ switch (r[0]) {
+ case "A":
+ r[1] = pa[1];
+ r[2] = pa[2];
+ r[3] = pa[3];
+ r[4] = pa[4];
+ r[5] = pa[5];
+ r[6] = +(pa[6] + x);
+ r[7] = +(pa[7] + y);
+ break;
+ case "V":
+ r[1] = +pa[1] + y;
+ break;
+ case "H":
+ r[1] = +pa[1] + x;
+ break;
+ case "R":
+ var dots = [x, y][concat](pa.slice(1));
+ for (var j = 2, jj = dots.length; j < jj; j++) {
+ dots[j] = +dots[j] + x;
+ dots[++j] = +dots[j] + y;
+ }
+ res.pop();
+ res = res[concat](catmullRom2bezier(dots, crz));
+ break;
+ case "M":
+ mx = +pa[1] + x;
+ my = +pa[2] + y;
+ default:
+ for (j = 1, jj = pa.length; j < jj; j++) {
+ r[j] = +pa[j] + ((j % 2) ? x : y);
+ }
+ }
+ } else if (pa[0] == "R") {
+ dots = [x, y][concat](pa.slice(1));
+ res.pop();
+ res = res[concat](catmullRom2bezier(dots, crz));
+ r = ["R"][concat](pa.slice(-2));
+ } else {
+ for (var k = 0, kk = pa.length; k < kk; k++) {
+ r[k] = pa[k];
+ }
+ }
+ switch (r[0]) {
+ case "Z":
+ x = mx;
+ y = my;
+ break;
+ case "H":
+ x = r[1];
+ break;
+ case "V":
+ y = r[1];
+ break;
+ case "M":
+ mx = r[r.length - 2];
+ my = r[r.length - 1];
+ default:
+ x = r[r.length - 2];
+ y = r[r.length - 1];
+ }
+ }
+ res.toString = R._path2string;
+ pth.abs = pathClone(res);
+ return res;
+ },
+ l2c = function (x1, y1, x2, y2) {
+ return [x1, y1, x2, y2, x2, y2];
+ },
+ q2c = function (x1, y1, ax, ay, x2, y2) {
+ var _13 = 1 / 3,
+ _23 = 2 / 3;
+ return [
+ _13 * x1 + _23 * ax,
+ _13 * y1 + _23 * ay,
+ _13 * x2 + _23 * ax,
+ _13 * y2 + _23 * ay,
+ x2,
+ y2
+ ];
+ },
+ a2c = function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
+ // for more information of where this math came from visit:
+ // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
+ var _120 = PI * 120 / 180,
+ rad = PI / 180 * (+angle || 0),
+ res = [],
+ xy,
+ rotate = cacher(function (x, y, rad) {
+ var X = x * math.cos(rad) - y * math.sin(rad),
+ Y = x * math.sin(rad) + y * math.cos(rad);
+ return {x: X, y: Y};
+ });
+ if (!recursive) {
+ xy = rotate(x1, y1, -rad);
+ x1 = xy.x;
+ y1 = xy.y;
+ xy = rotate(x2, y2, -rad);
+ x2 = xy.x;
+ y2 = xy.y;
+ var cos = math.cos(PI / 180 * angle),
+ sin = math.sin(PI / 180 * angle),
+ x = (x1 - x2) / 2,
+ y = (y1 - y2) / 2;
+ var h = (x * x) / (rx * rx) + (y * y) / (ry * ry);
+ if (h > 1) {
+ h = math.sqrt(h);
+ rx = h * rx;
+ ry = h * ry;
+ }
+ var rx2 = rx * rx,
+ ry2 = ry * ry,
+ k = (large_arc_flag == sweep_flag ? -1 : 1) *
+ math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
+ cx = k * rx * y / ry + (x1 + x2) / 2,
+ cy = k * -ry * x / rx + (y1 + y2) / 2,
+ f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
+ f2 = math.asin(((y2 - cy) / ry).toFixed(9));
+
+ f1 = x1 < cx ? PI - f1 : f1;
+ f2 = x2 < cx ? PI - f2 : f2;
+ f1 < 0 && (f1 = PI * 2 + f1);
+ f2 < 0 && (f2 = PI * 2 + f2);
+ if (sweep_flag && f1 > f2) {
+ f1 = f1 - PI * 2;
+ }
+ if (!sweep_flag && f2 > f1) {
+ f2 = f2 - PI * 2;
+ }
+ } else {
+ f1 = recursive[0];
+ f2 = recursive[1];
+ cx = recursive[2];
+ cy = recursive[3];
+ }
+ var df = f2 - f1;
+ if (abs(df) > _120) {
+ var f2old = f2,
+ x2old = x2,
+ y2old = y2;
+ f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1);
+ x2 = cx + rx * math.cos(f2);
+ y2 = cy + ry * math.sin(f2);
+ res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]);
+ }
+ df = f2 - f1;
+ var c1 = math.cos(f1),
+ s1 = math.sin(f1),
+ c2 = math.cos(f2),
+ s2 = math.sin(f2),
+ t = math.tan(df / 4),
+ hx = 4 / 3 * rx * t,
+ hy = 4 / 3 * ry * t,
+ m1 = [x1, y1],
+ m2 = [x1 + hx * s1, y1 - hy * c1],
+ m3 = [x2 + hx * s2, y2 - hy * c2],
+ m4 = [x2, y2];
+ m2[0] = 2 * m1[0] - m2[0];
+ m2[1] = 2 * m1[1] - m2[1];
+ if (recursive) {
+ return [m2, m3, m4][concat](res);
+ } else {
+ res = [m2, m3, m4][concat](res).join()[split](",");
+ var newres = [];
+ for (var i = 0, ii = res.length; i < ii; i++) {
+ newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x;
+ }
+ return newres;
+ }
+ },
+ findDotAtSegment = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) {
+ var t1 = 1 - t;
+ return {
+ x: pow(t1, 3) * p1x + pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + pow(t, 3) * p2x,
+ y: pow(t1, 3) * p1y + pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + pow(t, 3) * p2y
+ };
+ },
+ curveDim = cacher(function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
+ var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
+ b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
+ c = p1x - c1x,
+ t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a,
+ t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a,
+ y = [p1y, p2y],
+ x = [p1x, p2x],
+ dot;
+ abs(t1) > "1e12" && (t1 = .5);
+ abs(t2) > "1e12" && (t2 = .5);
+ if (t1 > 0 && t1 < 1) {
+ dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
+ x.push(dot.x);
+ y.push(dot.y);
+ }
+ if (t2 > 0 && t2 < 1) {
+ dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
+ x.push(dot.x);
+ y.push(dot.y);
+ }
+ a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
+ b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
+ c = p1y - c1y;
+ t1 = (-b + math.sqrt(b * b - 4 * a * c)) / 2 / a;
+ t2 = (-b - math.sqrt(b * b - 4 * a * c)) / 2 / a;
+ abs(t1) > "1e12" && (t1 = .5);
+ abs(t2) > "1e12" && (t2 = .5);
+ if (t1 > 0 && t1 < 1) {
+ dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
+ x.push(dot.x);
+ y.push(dot.y);
+ }
+ if (t2 > 0 && t2 < 1) {
+ dot = findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
+ x.push(dot.x);
+ y.push(dot.y);
+ }
+ return {
+ min: {x: mmin[apply](0, x), y: mmin[apply](0, y)},
+ max: {x: mmax[apply](0, x), y: mmax[apply](0, y)}
+ };
+ }),
+ path2curve = R._path2curve = cacher(function (path, path2) {
+ var pth = !path2 && paths(path);
+ if (!path2 && pth.curve) {
+ return pathClone(pth.curve);
+ }
+ var p = pathToAbsolute(path),
+ p2 = path2 && pathToAbsolute(path2),
+ attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
+ attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null},
+ processPath = function (path, d, pcom) {
+ var nx, ny, tq = {T:1, Q:1};
+ if (!path) {
+ return ["C", d.x, d.y, d.x, d.y, d.x, d.y];
+ }
+ !(path[0] in tq) && (d.qx = d.qy = null);
+ switch (path[0]) {
+ case "M":
+ d.X = path[1];
+ d.Y = path[2];
+ break;
+ case "A":
+ path = ["C"][concat](a2c[apply](0, [d.x, d.y][concat](path.slice(1))));
+ break;
+ case "S":
+ if (pcom == "C" || pcom == "S") { // In "S" case we have to take into account, if the previous command is C/S.
+ nx = d.x * 2 - d.bx; // And reflect the previous
+ ny = d.y * 2 - d.by; // command's control point relative to the current point.
+ }
+ else { // or some else or nothing
+ nx = d.x;
+ ny = d.y;
+ }
+ path = ["C", nx, ny][concat](path.slice(1));
+ break;
+ case "T":
+ if (pcom == "Q" || pcom == "T") { // In "T" case we have to take into account, if the previous command is Q/T.
+ d.qx = d.x * 2 - d.qx; // And make a reflection similar
+ d.qy = d.y * 2 - d.qy; // to case "S".
+ }
+ else { // or something else or nothing
+ d.qx = d.x;
+ d.qy = d.y;
+ }
+ path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
+ break;
+ case "Q":
+ d.qx = path[1];
+ d.qy = path[2];
+ path = ["C"][concat](q2c(d.x, d.y, path[1], path[2], path[3], path[4]));
+ break;
+ case "L":
+ path = ["C"][concat](l2c(d.x, d.y, path[1], path[2]));
+ break;
+ case "H":
+ path = ["C"][concat](l2c(d.x, d.y, path[1], d.y));
+ break;
+ case "V":
+ path = ["C"][concat](l2c(d.x, d.y, d.x, path[1]));
+ break;
+ case "Z":
+ path = ["C"][concat](l2c(d.x, d.y, d.X, d.Y));
+ break;
+ }
+ return path;
+ },
+ fixArc = function (pp, i) {
+ if (pp[i].length > 7) {
+ pp[i].shift();
+ var pi = pp[i];
+ while (pi.length) {
+ pcoms1[i]="A"; // if created multiple C:s, their original seg is saved
+ p2 && (pcoms2[i]="A"); // the same as above
+ pp.splice(i++, 0, ["C"][concat](pi.splice(0, 6)));
+ }
+ pp.splice(i, 1);
+ ii = mmax(p.length, p2 && p2.length || 0);
+ }
+ },
+ fixM = function (path1, path2, a1, a2, i) {
+ if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") {
+ path2.splice(i, 0, ["M", a2.x, a2.y]);
+ a1.bx = 0;
+ a1.by = 0;
+ a1.x = path1[i][1];
+ a1.y = path1[i][2];
+ ii = mmax(p.length, p2 && p2.length || 0);
+ }
+ },
+ pcoms1 = [], // path commands of original path p
+ pcoms2 = [], // path commands of original path p2
+ pfirst = "", // temporary holder for original path command
+ pcom = ""; // holder for previous path command of original path
+ for (var i = 0, ii = mmax(p.length, p2 && p2.length || 0); i < ii; i++) {
+ p[i] && (pfirst = p[i][0]); // save current path command
+
+ if (pfirst != "C") // C is not saved yet, because it may be result of conversion
+ {
+ pcoms1[i] = pfirst; // Save current path command
+ i && ( pcom = pcoms1[i-1]); // Get previous path command pcom
+ }
+ p[i] = processPath(p[i], attrs, pcom); // Previous path command is inputted to processPath
+
+ if (pcoms1[i] != "A" && pfirst == "C") pcoms1[i] = "C"; // A is the only command
+ // which may produce multiple C:s
+ // so we have to make sure that C is also C in original path
+
+ fixArc(p, i); // fixArc adds also the right amount of A:s to pcoms1
+
+ if (p2) { // the same procedures is done to p2
+ p2[i] && (pfirst = p2[i][0]);
+ if (pfirst != "C")
+ {
+ pcoms2[i] = pfirst;
+ i && (pcom = pcoms2[i-1]);
+ }
+ p2[i] = processPath(p2[i], attrs2, pcom);
+
+ if (pcoms2[i]!="A" && pfirst=="C") pcoms2[i]="C";
+
+ fixArc(p2, i);
+ }
+ fixM(p, p2, attrs, attrs2, i);
+ fixM(p2, p, attrs2, attrs, i);
+ var seg = p[i],
+ seg2 = p2 && p2[i],
+ seglen = seg.length,
+ seg2len = p2 && seg2.length;
+ attrs.x = seg[seglen - 2];
+ attrs.y = seg[seglen - 1];
+ attrs.bx = toFloat(seg[seglen - 4]) || attrs.x;
+ attrs.by = toFloat(seg[seglen - 3]) || attrs.y;
+ attrs2.bx = p2 && (toFloat(seg2[seg2len - 4]) || attrs2.x);
+ attrs2.by = p2 && (toFloat(seg2[seg2len - 3]) || attrs2.y);
+ attrs2.x = p2 && seg2[seg2len - 2];
+ attrs2.y = p2 && seg2[seg2len - 1];
+ }
+ if (!p2) {
+ pth.curve = pathClone(p);
+ }
+ return p2 ? [p, p2] : p;
+ }, null, pathClone),
+ parseDots = R._parseDots = cacher(function (gradient) {
+ var dots = [];
+ for (var i = 0, ii = gradient.length; i < ii; i++) {
+ var dot = {},
+ par = gradient[i].match(/^([^:]*):?([\d\.]*)/);
+ dot.color = R.getRGB(par[1]);
+ if (dot.color.error) {
+ return null;
+ }
+ dot.opacity = dot.color.opacity;
+ dot.color = dot.color.hex;
+ par[2] && (dot.offset = par[2] + "%");
+ dots.push(dot);
+ }
+ for (i = 1, ii = dots.length - 1; i < ii; i++) {
+ if (!dots[i].offset) {
+ var start = toFloat(dots[i - 1].offset || 0),
+ end = 0;
+ for (var j = i + 1; j < ii; j++) {
+ if (dots[j].offset) {
+ end = dots[j].offset;
+ break;
+ }
+ }
+ if (!end) {
+ end = 100;
+ j = ii;
+ }
+ end = toFloat(end);
+ var d = (end - start) / (j - i + 1);
+ for (; i < j; i++) {
+ start += d;
+ dots[i].offset = start + "%";
+ }
+ }
+ }
+ return dots;
+ }),
+ tear = R._tear = function (el, paper) {
+ el == paper.top && (paper.top = el.prev);
+ el == paper.bottom && (paper.bottom = el.next);
+ el.next && (el.next.prev = el.prev);
+ el.prev && (el.prev.next = el.next);
+ },
+ tofront = R._tofront = function (el, paper) {
+ if (paper.top === el) {
+ return;
+ }
+ tear(el, paper);
+ el.next = null;
+ el.prev = paper.top;
+ paper.top.next = el;
+ paper.top = el;
+ },
+ toback = R._toback = function (el, paper) {
+ if (paper.bottom === el) {
+ return;
+ }
+ tear(el, paper);
+ el.next = paper.bottom;
+ el.prev = null;
+ paper.bottom.prev = el;
+ paper.bottom = el;
+ },
+ insertafter = R._insertafter = function (el, el2, paper) {
+ tear(el, paper);
+ el2 == paper.top && (paper.top = el);
+ el2.next && (el2.next.prev = el);
+ el.next = el2.next;
+ el.prev = el2;
+ el2.next = el;
+ },
+ insertbefore = R._insertbefore = function (el, el2, paper) {
+ tear(el, paper);
+ el2 == paper.bottom && (paper.bottom = el);
+ el2.prev && (el2.prev.next = el);
+ el.prev = el2.prev;
+ el2.prev = el;
+ el.next = el2;
+ },
+ /*\
+ * Raphael.toMatrix
+ [ method ]
+ **
+ * Utility method
+ **
+ * Returns matrix of transformations applied to a given path
+ > Parameters
+ - path (string) path string
+ - transform (string|array) transformation string
+ = (object) @Matrix
+ \*/
+ toMatrix = R.toMatrix = function (path, transform) {
+ var bb = pathDimensions(path),
+ el = {
+ _: {
+ transform: E
+ },
+ getBBox: function () {
+ return bb;
+ }
+ };
+ extractTransform(el, transform);
+ return el.matrix;
+ },
+ /*\
+ * Raphael.transformPath
+ [ method ]
+ **
+ * Utility method
+ **
+ * Returns path transformed by a given transformation
+ > Parameters
+ - path (string) path string
+ - transform (string|array) transformation string
+ = (string) path
+ \*/
+ transformPath = R.transformPath = function (path, transform) {
+ return mapPath(path, toMatrix(path, transform));
+ },
+ extractTransform = R._extractTransform = function (el, tstr) {
+ if (tstr == null) {
+ return el._.transform;
+ }
+ tstr = Str(tstr).replace(/\.{3}|\u2026/g, el._.transform || E);
+ var tdata = R.parseTransformString(tstr),
+ deg = 0,
+ dx = 0,
+ dy = 0,
+ sx = 1,
+ sy = 1,
+ _ = el._,
+ m = new Matrix;
+ _.transform = tdata || [];
+ if (tdata) {
+ for (var i = 0, ii = tdata.length; i < ii; i++) {
+ var t = tdata[i],
+ tlen = t.length,
+ command = Str(t[0]).toLowerCase(),
+ absolute = t[0] != command,
+ inver = absolute ? m.invert() : 0,
+ x1,
+ y1,
+ x2,
+ y2,
+ bb;
+ if (command == "t" && tlen == 3) {
+ if (absolute) {
+ x1 = inver.x(0, 0);
+ y1 = inver.y(0, 0);
+ x2 = inver.x(t[1], t[2]);
+ y2 = inver.y(t[1], t[2]);
+ m.translate(x2 - x1, y2 - y1);
+ } else {
+ m.translate(t[1], t[2]);
+ }
+ } else if (command == "r") {
+ if (tlen == 2) {
+ bb = bb || el.getBBox(1);
+ m.rotate(t[1], bb.x + bb.width / 2, bb.y + bb.height / 2);
+ deg += t[1];
+ } else if (tlen == 4) {
+ if (absolute) {
+ x2 = inver.x(t[2], t[3]);
+ y2 = inver.y(t[2], t[3]);
+ m.rotate(t[1], x2, y2);
+ } else {
+ m.rotate(t[1], t[2], t[3]);
+ }
+ deg += t[1];
+ }
+ } else if (command == "s") {
+ if (tlen == 2 || tlen == 3) {
+ bb = bb || el.getBBox(1);
+ m.scale(t[1], t[tlen - 1], bb.x + bb.width / 2, bb.y + bb.height / 2);
+ sx *= t[1];
+ sy *= t[tlen - 1];
+ } else if (tlen == 5) {
+ if (absolute) {
+ x2 = inver.x(t[3], t[4]);
+ y2 = inver.y(t[3], t[4]);
+ m.scale(t[1], t[2], x2, y2);
+ } else {
+ m.scale(t[1], t[2], t[3], t[4]);
+ }
+ sx *= t[1];
+ sy *= t[2];
+ }
+ } else if (command == "m" && tlen == 7) {
+ m.add(t[1], t[2], t[3], t[4], t[5], t[6]);
+ }
+ _.dirtyT = 1;
+ el.matrix = m;
+ }
+ }
+
+ /*\
+ * Element.matrix
+ [ property (object) ]
+ **
+ * Keeps @Matrix object, which represents element transformation
+ \*/
+ el.matrix = m;
+
+ _.sx = sx;
+ _.sy = sy;
+ _.deg = deg;
+ _.dx = dx = m.e;
+ _.dy = dy = m.f;
+
+ if (sx == 1 && sy == 1 && !deg && _.bbox) {
+ _.bbox.x += +dx;
+ _.bbox.y += +dy;
+ } else {
+ _.dirtyT = 1;
+ }
+ },
+ getEmpty = function (item) {
+ var l = item[0];
+ switch (l.toLowerCase()) {
+ case "t": return [l, 0, 0];
+ case "m": return [l, 1, 0, 0, 1, 0, 0];
+ case "r": if (item.length == 4) {
+ return [l, 0, item[2], item[3]];
+ } else {
+ return [l, 0];
+ }
+ case "s": if (item.length == 5) {
+ return [l, 1, 1, item[3], item[4]];
+ } else if (item.length == 3) {
+ return [l, 1, 1];
+ } else {
+ return [l, 1];
+ }
+ }
+ },
+ equaliseTransform = R._equaliseTransform = function (t1, t2) {
+ t2 = Str(t2).replace(/\.{3}|\u2026/g, t1);
+ t1 = R.parseTransformString(t1) || [];
+ t2 = R.parseTransformString(t2) || [];
+ var maxlength = mmax(t1.length, t2.length),
+ from = [],
+ to = [],
+ i = 0, j, jj,
+ tt1, tt2;
+ for (; i < maxlength; i++) {
+ tt1 = t1[i] || getEmpty(t2[i]);
+ tt2 = t2[i] || getEmpty(tt1);
+ if ((tt1[0] != tt2[0]) ||
+ (tt1[0].toLowerCase() == "r" && (tt1[2] != tt2[2] || tt1[3] != tt2[3])) ||
+ (tt1[0].toLowerCase() == "s" && (tt1[3] != tt2[3] || tt1[4] != tt2[4]))
+ ) {
+ return;
+ }
+ from[i] = [];
+ to[i] = [];
+ for (j = 0, jj = mmax(tt1.length, tt2.length); j < jj; j++) {
+ j in tt1 && (from[i][j] = tt1[j]);
+ j in tt2 && (to[i][j] = tt2[j]);
+ }
+ }
+ return {
+ from: from,
+ to: to
+ };
+ };
+ R._getContainer = function (x, y, w, h) {
+ var container;
+ container = h == null && !R.is(x, "object") ? g.doc.getElementById(x) : x;
+ if (container == null) {
+ return;
+ }
+ if (container.tagName) {
+ if (y == null) {
+ return {
+ container: container,
+ width: container.style.pixelWidth || container.offsetWidth,
+ height: container.style.pixelHeight || container.offsetHeight
+ };
+ } else {
+ return {
+ container: container,
+ width: y,
+ height: w
+ };
+ }
+ }
+ return {
+ container: 1,
+ x: x,
+ y: y,
+ width: w,
+ height: h
+ };
+ };
+ /*\
+ * Raphael.pathToRelative
+ [ method ]
+ **
+ * Utility method
+ **
+ * Converts path to relative form
+ > Parameters
+ - pathString (string|array) path string or array of segments
+ = (array) array of segments.
+ \*/
+ R.pathToRelative = pathToRelative;
+ R._engine = {};
+ /*\
+ * Raphael.path2curve
+ [ method ]
+ **
+ * Utility method
+ **
+ * Converts path to a new path where all segments are cubic bezier curves.
+ > Parameters
+ - pathString (string|array) path string or array of segments
+ = (array) array of segments.
+ \*/
+ R.path2curve = path2curve;
+ /*\
+ * Raphael.matrix
+ [ method ]
+ **
+ * Utility method
+ **
+ * Returns matrix based on given parameters.
+ > Parameters
+ - a (number)
+ - b (number)
+ - c (number)
+ - d (number)
+ - e (number)
+ - f (number)
+ = (object) @Matrix
+ \*/
+ R.matrix = function (a, b, c, d, e, f) {
+ return new Matrix(a, b, c, d, e, f);
+ };
+ function Matrix(a, b, c, d, e, f) {
+ if (a != null) {
+ this.a = +a;
+ this.b = +b;
+ this.c = +c;
+ this.d = +d;
+ this.e = +e;
+ this.f = +f;
+ } else {
+ this.a = 1;
+ this.b = 0;
+ this.c = 0;
+ this.d = 1;
+ this.e = 0;
+ this.f = 0;
+ }
+ }
+ (function (matrixproto) {
+ /*\
+ * Matrix.add
+ [ method ]
+ **
+ * Adds given matrix to existing one.
+ > Parameters
+ - a (number)
+ - b (number)
+ - c (number)
+ - d (number)
+ - e (number)
+ - f (number)
+ or
+ - matrix (object) @Matrix
+ \*/
+ matrixproto.add = function (a, b, c, d, e, f) {
+ var out = [[], [], []],
+ m = [[this.a, this.c, this.e], [this.b, this.d, this.f], [0, 0, 1]],
+ matrix = [[a, c, e], [b, d, f], [0, 0, 1]],
+ x, y, z, res;
+
+ if (a && a instanceof Matrix) {
+ matrix = [[a.a, a.c, a.e], [a.b, a.d, a.f], [0, 0, 1]];
+ }
+
+ for (x = 0; x < 3; x++) {
+ for (y = 0; y < 3; y++) {
+ res = 0;
+ for (z = 0; z < 3; z++) {
+ res += m[x][z] * matrix[z][y];
+ }
+ out[x][y] = res;
+ }
+ }
+ this.a = out[0][0];
+ this.b = out[1][0];
+ this.c = out[0][1];
+ this.d = out[1][1];
+ this.e = out[0][2];
+ this.f = out[1][2];
+ };
+ /*\
+ * Matrix.invert
+ [ method ]
+ **
+ * Returns inverted version of the matrix
+ = (object) @Matrix
+ \*/
+ matrixproto.invert = function () {
+ var me = this,
+ x = me.a * me.d - me.b * me.c;
+ return new Matrix(me.d / x, -me.b / x, -me.c / x, me.a / x, (me.c * me.f - me.d * me.e) / x, (me.b * me.e - me.a * me.f) / x);
+ };
+ /*\
+ * Matrix.clone
+ [ method ]
+ **
+ * Returns copy of the matrix
+ = (object) @Matrix
+ \*/
+ matrixproto.clone = function () {
+ return new Matrix(this.a, this.b, this.c, this.d, this.e, this.f);
+ };
+ /*\
+ * Matrix.translate
+ [ method ]
+ **
+ * Translate the matrix
+ > Parameters
+ - x (number)
+ - y (number)
+ \*/
+ matrixproto.translate = function (x, y) {
+ this.add(1, 0, 0, 1, x, y);
+ };
+ /*\
+ * Matrix.scale
+ [ method ]
+ **
+ * Scales the matrix
+ > Parameters
+ - x (number)
+ - y (number) #optional
+ - cx (number) #optional
+ - cy (number) #optional
+ \*/
+ matrixproto.scale = function (x, y, cx, cy) {
+ y == null && (y = x);
+ (cx || cy) && this.add(1, 0, 0, 1, cx, cy);
+ this.add(x, 0, 0, y, 0, 0);
+ (cx || cy) && this.add(1, 0, 0, 1, -cx, -cy);
+ };
+ /*\
+ * Matrix.rotate
+ [ method ]
+ **
+ * Rotates the matrix
+ > Parameters
+ - a (number)
+ - x (number)
+ - y (number)
+ \*/
+ matrixproto.rotate = function (a, x, y) {
+ a = R.rad(a);
+ x = x || 0;
+ y = y || 0;
+ var cos = +math.cos(a).toFixed(9),
+ sin = +math.sin(a).toFixed(9);
+ this.add(cos, sin, -sin, cos, x, y);
+ this.add(1, 0, 0, 1, -x, -y);
+ };
+ /*\
+ * Matrix.x
+ [ method ]
+ **
+ * Return x coordinate for given point after transformation described by the matrix. See also @Matrix.y
+ > Parameters
+ - x (number)
+ - y (number)
+ = (number) x
+ \*/
+ matrixproto.x = function (x, y) {
+ return x * this.a + y * this.c + this.e;
+ };
+ /*\
+ * Matrix.y
+ [ method ]
+ **
+ * Return y coordinate for given point after transformation described by the matrix. See also @Matrix.x
+ > Parameters
+ - x (number)
+ - y (number)
+ = (number) y
+ \*/
+ matrixproto.y = function (x, y) {
+ return x * this.b + y * this.d + this.f;
+ };
+ matrixproto.get = function (i) {
+ return +this[Str.fromCharCode(97 + i)].toFixed(4);
+ };
+ matrixproto.toString = function () {
+ return R.svg ?
+ "matrix(" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)].join() + ")" :
+ [this.get(0), this.get(2), this.get(1), this.get(3), 0, 0].join();
+ };
+ matrixproto.toFilter = function () {
+ return "progid:DXImageTransform.Microsoft.Matrix(M11=" + this.get(0) +
+ ", M12=" + this.get(2) + ", M21=" + this.get(1) + ", M22=" + this.get(3) +
+ ", Dx=" + this.get(4) + ", Dy=" + this.get(5) + ", sizingmethod='auto expand')";
+ };
+ matrixproto.offset = function () {
+ return [this.e.toFixed(4), this.f.toFixed(4)];
+ };
+ function norm(a) {
+ return a[0] * a[0] + a[1] * a[1];
+ }
+ function normalize(a) {
+ var mag = math.sqrt(norm(a));
+ a[0] && (a[0] /= mag);
+ a[1] && (a[1] /= mag);
+ }
+ /*\
+ * Matrix.split
+ [ method ]
+ **
+ * Splits matrix into primitive transformations
+ = (object) in format:
+ o dx (number) translation by x
+ o dy (number) translation by y
+ o scalex (number) scale by x
+ o scaley (number) scale by y
+ o shear (number) shear
+ o rotate (number) rotation in deg
+ o isSimple (boolean) could it be represented via simple transformations
+ \*/
+ matrixproto.split = function () {
+ var out = {};
+ // translation
+ out.dx = this.e;
+ out.dy = this.f;
+
+ // scale and shear
+ var row = [[this.a, this.c], [this.b, this.d]];
+ out.scalex = math.sqrt(norm(row[0]));
+ normalize(row[0]);
+
+ out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1];
+ row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear];
+
+ out.scaley = math.sqrt(norm(row[1]));
+ normalize(row[1]);
+ out.shear /= out.scaley;
+
+ // rotation
+ var sin = -row[0][1],
+ cos = row[1][1];
+ if (cos < 0) {
+ out.rotate = R.deg(math.acos(cos));
+ if (sin < 0) {
+ out.rotate = 360 - out.rotate;
+ }
+ } else {
+ out.rotate = R.deg(math.asin(sin));
+ }
+
+ out.isSimple = !+out.shear.toFixed(9) && (out.scalex.toFixed(9) == out.scaley.toFixed(9) || !out.rotate);
+ out.isSuperSimple = !+out.shear.toFixed(9) && out.scalex.toFixed(9) == out.scaley.toFixed(9) && !out.rotate;
+ out.noRotation = !+out.shear.toFixed(9) && !out.rotate;
+ return out;
+ };
+ /*\
+ * Matrix.toTransformString
+ [ method ]
+ **
+ * Return transform string that represents given matrix
+ = (string) transform string
+ \*/
+ matrixproto.toTransformString = function (shorter) {
+ var s = shorter || this[split]();
+ if (s.isSimple) {
+ s.scalex = +s.scalex.toFixed(4);
+ s.scaley = +s.scaley.toFixed(4);
+ s.rotate = +s.rotate.toFixed(4);
+ return (s.dx || s.dy ? "t" + [s.dx, s.dy] : E) +
+ (s.scalex != 1 || s.scaley != 1 ? "s" + [s.scalex, s.scaley, 0, 0] : E) +
+ (s.rotate ? "r" + [s.rotate, 0, 0] : E);
+ } else {
+ return "m" + [this.get(0), this.get(1), this.get(2), this.get(3), this.get(4), this.get(5)];
+ }
+ };
+ })(Matrix.prototype);
+
+ var preventDefault = function () {
+ this.returnValue = false;
+ },
+ preventTouch = function () {
+ return this.originalEvent.preventDefault();
+ },
+ stopPropagation = function () {
+ this.cancelBubble = true;
+ },
+ stopTouch = function () {
+ return this.originalEvent.stopPropagation();
+ },
+ getEventPosition = function (e) {
+ var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+ scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
+
+ return {
+ x: e.clientX + scrollX,
+ y: e.clientY + scrollY
+ };
+ },
+ addEvent = (function () {
+ if (g.doc.addEventListener) {
+ return function (obj, type, fn, element) {
+ var f = function (e) {
+ var pos = getEventPosition(e);
+ return fn.call(element, e, pos.x, pos.y);
+ };
+ obj.addEventListener(type, f, false);
+
+ if (supportsTouch && touchMap[type]) {
+ var _f = function (e) {
+ var pos = getEventPosition(e),
+ olde = e;
+
+ for (var i = 0, ii = e.targetTouches && e.targetTouches.length; i < ii; i++) {
+ if (e.targetTouches[i].target == obj) {
+ e = e.targetTouches[i];
+ e.originalEvent = olde;
+ e.preventDefault = preventTouch;
+ e.stopPropagation = stopTouch;
+ break;
+ }
+ }
+
+ return fn.call(element, e, pos.x, pos.y);
+ };
+ obj.addEventListener(touchMap[type], _f, false);
+ }
+
+ return function () {
+ obj.removeEventListener(type, f, false);
+
+ if (supportsTouch && touchMap[type])
+ obj.removeEventListener(touchMap[type], _f, false);
+
+ return true;
+ };
+ };
+ } else if (g.doc.attachEvent) {
+ return function (obj, type, fn, element) {
+ var f = function (e) {
+ e = e || g.win.event;
+ var scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+ scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
+ x = e.clientX + scrollX,
+ y = e.clientY + scrollY;
+ e.preventDefault = e.preventDefault || preventDefault;
+ e.stopPropagation = e.stopPropagation || stopPropagation;
+ return fn.call(element, e, x, y);
+ };
+ obj.attachEvent("on" + type, f);
+ var detacher = function () {
+ obj.detachEvent("on" + type, f);
+ return true;
+ };
+ return detacher;
+ };
+ }
+ })(),
+ drag = [],
+ dragMove = function (e) {
+ var x = e.clientX,
+ y = e.clientY,
+ scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+ scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft,
+ dragi,
+ j = drag.length;
+ while (j--) {
+ dragi = drag[j];
+ if (supportsTouch && e.touches) {
+ var i = e.touches.length,
+ touch;
+ while (i--) {
+ touch = e.touches[i];
+ if (touch.identifier == dragi.el._drag.id) {
+ x = touch.clientX;
+ y = touch.clientY;
+ (e.originalEvent ? e.originalEvent : e).preventDefault();
+ break;
+ }
+ }
+ } else {
+ e.preventDefault();
+ }
+ var node = dragi.el.node,
+ o,
+ next = node.nextSibling,
+ parent = node.parentNode,
+ display = node.style.display;
+ g.win.opera && parent.removeChild(node);
+ node.style.display = "none";
+ o = dragi.el.paper.getElementByPoint(x, y);
+ node.style.display = display;
+ g.win.opera && (next ? parent.insertBefore(node, next) : parent.appendChild(node));
+ o && eve("raphael.drag.over." + dragi.el.id, dragi.el, o);
+ x += scrollX;
+ y += scrollY;
+ eve("raphael.drag.move." + dragi.el.id, dragi.move_scope || dragi.el, x - dragi.el._drag.x, y - dragi.el._drag.y, x, y, e);
+ }
+ },
+ dragUp = function (e) {
+ R.unmousemove(dragMove).unmouseup(dragUp);
+ var i = drag.length,
+ dragi;
+ while (i--) {
+ dragi = drag[i];
+ dragi.el._drag = {};
+ eve("raphael.drag.end." + dragi.el.id, dragi.end_scope || dragi.start_scope || dragi.move_scope || dragi.el, e);
+ }
+ drag = [];
+ },
+ /*\
+ * Raphael.el
+ [ property (object) ]
+ **
+ * You can add your own method to elements. This is useful when you want to hack default functionality or
+ * want to wrap some common transformation or attributes in one method. In difference to canvas methods,
+ * you can redefine element method at any time. Expending element methods wouldn’t affect set.
+ > Usage
+ | Raphael.el.red = function () {
+ | this.attr({fill: "#f00"});
+ | };
+ | // then use it
+ | paper.circle(100, 100, 20).red();
+ \*/
+ elproto = R.el = {};
+ /*\
+ * Element.click
+ [ method ]
+ **
+ * Adds event handler for click for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.unclick
+ [ method ]
+ **
+ * Removes event handler for click for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.dblclick
+ [ method ]
+ **
+ * Adds event handler for double click for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.undblclick
+ [ method ]
+ **
+ * Removes event handler for double click for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.mousedown
+ [ method ]
+ **
+ * Adds event handler for mousedown for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.unmousedown
+ [ method ]
+ **
+ * Removes event handler for mousedown for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.mousemove
+ [ method ]
+ **
+ * Adds event handler for mousemove for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.unmousemove
+ [ method ]
+ **
+ * Removes event handler for mousemove for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.mouseout
+ [ method ]
+ **
+ * Adds event handler for mouseout for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.unmouseout
+ [ method ]
+ **
+ * Removes event handler for mouseout for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.mouseover
+ [ method ]
+ **
+ * Adds event handler for mouseover for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.unmouseover
+ [ method ]
+ **
+ * Removes event handler for mouseover for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.mouseup
+ [ method ]
+ **
+ * Adds event handler for mouseup for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.unmouseup
+ [ method ]
+ **
+ * Removes event handler for mouseup for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.touchstart
+ [ method ]
+ **
+ * Adds event handler for touchstart for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.untouchstart
+ [ method ]
+ **
+ * Removes event handler for touchstart for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.touchmove
+ [ method ]
+ **
+ * Adds event handler for touchmove for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.untouchmove
+ [ method ]
+ **
+ * Removes event handler for touchmove for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.touchend
+ [ method ]
+ **
+ * Adds event handler for touchend for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.untouchend
+ [ method ]
+ **
+ * Removes event handler for touchend for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+
+ /*\
+ * Element.touchcancel
+ [ method ]
+ **
+ * Adds event handler for touchcancel for the element.
+ > Parameters
+ - handler (function) handler for the event
+ = (object) @Element
+ \*/
+ /*\
+ * Element.untouchcancel
+ [ method ]
+ **
+ * Removes event handler for touchcancel for the element.
+ > Parameters
+ - handler (function) #optional handler for the event
+ = (object) @Element
+ \*/
+ for (var i = events.length; i--;) {
+ (function (eventName) {
+ R[eventName] = elproto[eventName] = function (fn, scope) {
+ if (R.is(fn, "function")) {
+ this.events = this.events || [];
+ this.events.push({name: eventName, f: fn, unbind: addEvent(this.shape || this.node || g.doc, eventName, fn, scope || this)});
+ }
+ return this;
+ };
+ R["un" + eventName] = elproto["un" + eventName] = function (fn) {
+ var events = this.events || [],
+ l = events.length;
+ while (l--){
+ if (events[l].name == eventName && (R.is(fn, "undefined") || events[l].f == fn)) {
+ events[l].unbind();
+ events.splice(l, 1);
+ !events.length && delete this.events;
+ }
+ }
+ return this;
+ };
+ })(events[i]);
+ }
+
+ /*\
+ * Element.data
+ [ method ]
+ **
+ * Adds or retrieves given value associated with given key.
+ **
+ * See also @Element.removeData
+ > Parameters
+ - key (string) key to store data
+ - value (any) #optional value to store
+ = (object) @Element
+ * or, if value is not specified:
+ = (any) value
+ * or, if key and value are not specified:
+ = (object) Key/value pairs for all the data associated with the element.
+ > Usage
+ | for (var i = 0, i < 5, i++) {
+ | paper.circle(10 + 15 * i, 10, 10)
+ | .attr({fill: "#000"})
+ | .data("i", i)
+ | .click(function () {
+ | alert(this.data("i"));
+ | });
+ | }
+ \*/
+ elproto.data = function (key, value) {
+ var data = eldata[this.id] = eldata[this.id] || {};
+ if (arguments.length == 0) {
+ return data;
+ }
+ if (arguments.length == 1) {
+ if (R.is(key, "object")) {
+ for (var i in key) if (key[has](i)) {
+ this.data(i, key[i]);
+ }
+ return this;
+ }
+ eve("raphael.data.get." + this.id, this, data[key], key);
+ return data[key];
+ }
+ data[key] = value;
+ eve("raphael.data.set." + this.id, this, value, key);
+ return this;
+ };
+ /*\
+ * Element.removeData
+ [ method ]
+ **
+ * Removes value associated with an element by given key.
+ * If key is not provided, removes all the data of the element.
+ > Parameters
+ - key (string) #optional key
+ = (object) @Element
+ \*/
+ elproto.removeData = function (key) {
+ if (key == null) {
+ eldata[this.id] = {};
+ } else {
+ eldata[this.id] && delete eldata[this.id][key];
+ }
+ return this;
+ };
+ /*\
+ * Element.getData
+ [ method ]
+ **
+ * Retrieves the element data
+ = (object) data
+ \*/
+ elproto.getData = function () {
+ return clone(eldata[this.id] || {});
+ };
+ /*\
+ * Element.hover
+ [ method ]
+ **
+ * Adds event handlers for hover for the element.
+ > Parameters
+ - f_in (function) handler for hover in
+ - f_out (function) handler for hover out
+ - icontext (object) #optional context for hover in handler
+ - ocontext (object) #optional context for hover out handler
+ = (object) @Element
+ \*/
+ elproto.hover = function (f_in, f_out, scope_in, scope_out) {
+ return this.mouseover(f_in, scope_in).mouseout(f_out, scope_out || scope_in);
+ };
+ /*\
+ * Element.unhover
+ [ method ]
+ **
+ * Removes event handlers for hover for the element.
+ > Parameters
+ - f_in (function) handler for hover in
+ - f_out (function) handler for hover out
+ = (object) @Element
+ \*/
+ elproto.unhover = function (f_in, f_out) {
+ return this.unmouseover(f_in).unmouseout(f_out);
+ };
+ var draggable = [];
+ /*\
+ * Element.drag
+ [ method ]
+ **
+ * Adds event handlers for drag of the element.
+ > Parameters
+ - onmove (function) handler for moving
+ - onstart (function) handler for drag start
+ - onend (function) handler for drag end
+ - mcontext (object) #optional context for moving handler
+ - scontext (object) #optional context for drag start handler
+ - econtext (object) #optional context for drag end handler
+ * Additionally following `drag` events will be triggered: `drag.start.<id>` on start,
+ * `drag.end.<id>` on end and `drag.move.<id>` on every move. When element will be dragged over another element
+ * `drag.over.<id>` will be fired as well.
+ *
+ * Start event and start handler will be called in specified context or in context of the element with following parameters:
+ o x (number) x position of the mouse
+ o y (number) y position of the mouse
+ o event (object) DOM event object
+ * Move event and move handler will be called in specified context or in context of the element with following parameters:
+ o dx (number) shift by x from the start point
+ o dy (number) shift by y from the start point
+ o x (number) x position of the mouse
+ o y (number) y position of the mouse
+ o event (object) DOM event object
+ * End event and end handler will be called in specified context or in context of the element with following parameters:
+ o event (object) DOM event object
+ = (object) @Element
+ \*/
+ elproto.drag = function (onmove, onstart, onend, move_scope, start_scope, end_scope) {
+ function start(e) {
+ (e.originalEvent || e).preventDefault();
+ var x = e.clientX,
+ y = e.clientY,
+ scrollY = g.doc.documentElement.scrollTop || g.doc.body.scrollTop,
+ scrollX = g.doc.documentElement.scrollLeft || g.doc.body.scrollLeft;
+ this._drag.id = e.identifier;
+ if (supportsTouch && e.touches) {
+ var i = e.touches.length, touch;
+ while (i--) {
+ touch = e.touches[i];
+ this._drag.id = touch.identifier;
+ if (touch.identifier == this._drag.id) {
+ x = touch.clientX;
+ y = touch.clientY;
+ break;
+ }
+ }
+ }
+ this._drag.x = x + scrollX;
+ this._drag.y = y + scrollY;
+ !drag.length && R.mousemove(dragMove).mouseup(dragUp);
+ drag.push({el: this, move_scope: move_scope, start_scope: start_scope, end_scope: end_scope});
+ onstart && eve.on("raphael.drag.start." + this.id, onstart);
+ onmove && eve.on("raphael.drag.move." + this.id, onmove);
+ onend && eve.on("raphael.drag.end." + this.id, onend);
+ eve("raphael.drag.start." + this.id, start_scope || move_scope || this, e.clientX + scrollX, e.clientY + scrollY, e);
+ }
+ this._drag = {};
+ draggable.push({el: this, start: start});
+ this.mousedown(start);
+ return this;
+ };
+ /*\
+ * Element.onDragOver
+ [ method ]
+ **
+ * Shortcut for assigning event handler for `drag.over.<id>` event, where id is id of the element (see @Element.id).
+ > Parameters
+ - f (function) handler for event, first argument would be the element you are dragging over
+ \*/
+ elproto.onDragOver = function (f) {
+ f ? eve.on("raphael.drag.over." + this.id, f) : eve.unbind("raphael.drag.over." + this.id);
+ };
+ /*\
+ * Element.undrag
+ [ method ]
+ **
+ * Removes all drag event handlers from given element.
+ \*/
+ elproto.undrag = function () {
+ var i = draggable.length;
+ while (i--) if (draggable[i].el == this) {
+ this.unmousedown(draggable[i].start);
+ draggable.splice(i, 1);
+ eve.unbind("raphael.drag.*." + this.id);
+ }
+ !draggable.length && R.unmousemove(dragMove).unmouseup(dragUp);
+ drag = [];
+ };
+ /*\
+ * Paper.circle
+ [ method ]
+ **
+ * Draws a circle.
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the centre
+ - y (number) y coordinate of the centre
+ - r (number) radius
+ = (object) Raphaël element object with type “circle”
+ **
+ > Usage
+ | var c = paper.circle(50, 50, 40);
+ \*/
+ paperproto.circle = function (x, y, r) {
+ var out = R._engine.circle(this, x || 0, y || 0, r || 0);
+ this.__set__ && this.__set__.push(out);
+ return out;
+ };
+ /*\
+ * Paper.rect
+ [ method ]
+ *
+ * Draws a rectangle.
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the top left corner
+ - y (number) y coordinate of the top left corner
+ - width (number) width
+ - height (number) height
+ - r (number) #optional radius for rounded corners, default is 0
+ = (object) Raphaël element object with type “rect”
+ **
+ > Usage
+ | // regular rectangle
+ | var c = paper.rect(10, 10, 50, 50);
+ | // rectangle with rounded corners
+ | var c = paper.rect(40, 40, 50, 50, 10);
+ \*/
+ paperproto.rect = function (x, y, w, h, r) {
+ var out = R._engine.rect(this, x || 0, y || 0, w || 0, h || 0, r || 0);
+ this.__set__ && this.__set__.push(out);
+ return out;
+ };
+ /*\
+ * Paper.ellipse
+ [ method ]
+ **
+ * Draws an ellipse.
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the centre
+ - y (number) y coordinate of the centre
+ - rx (number) horizontal radius
+ - ry (number) vertical radius
+ = (object) Raphaël element object with type “ellipse”
+ **
+ > Usage
+ | var c = paper.ellipse(50, 50, 40, 20);
+ \*/
+ paperproto.ellipse = function (x, y, rx, ry) {
+ var out = R._engine.ellipse(this, x || 0, y || 0, rx || 0, ry || 0);
+ this.__set__ && this.__set__.push(out);
+ return out;
+ };
+ /*\
+ * Paper.path
+ [ method ]
+ **
+ * Creates a path element by given path data string.
+ > Parameters
+ - pathString (string) #optional path string in SVG format.
+ * Path string consists of one-letter commands, followed by comma seprarated arguments in numercal form. Example:
+ | "M10,20L30,40"
+ * Here we can see two commands: “M”, with arguments `(10, 20)` and “L” with arguments `(30, 40)`. Upper case letter mean command is absolute, lower case—relative.
+ *
+ # <p>Here is short list of commands available, for more details see <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path's data attribute's format are described in the SVG specification.">SVG path string format</a>.</p>
+ # <table><thead><tr><th>Command</th><th>Name</th><th>Parameters</th></tr></thead><tbody>
+ # <tr><td>M</td><td>moveto</td><td>(x y)+</td></tr>
+ # <tr><td>Z</td><td>closepath</td><td>(none)</td></tr>
+ # <tr><td>L</td><td>lineto</td><td>(x y)+</td></tr>
+ # <tr><td>H</td><td>horizontal lineto</td><td>x+</td></tr>
+ # <tr><td>V</td><td>vertical lineto</td><td>y+</td></tr>
+ # <tr><td>C</td><td>curveto</td><td>(x1 y1 x2 y2 x y)+</td></tr>
+ # <tr><td>S</td><td>smooth curveto</td><td>(x2 y2 x y)+</td></tr>
+ # <tr><td>Q</td><td>quadratic Bézier curveto</td><td>(x1 y1 x y)+</td></tr>
+ # <tr><td>T</td><td>smooth quadratic Bézier curveto</td><td>(x y)+</td></tr>
+ # <tr><td>A</td><td>elliptical arc</td><td>(rx ry x-axis-rotation large-arc-flag sweep-flag x y)+</td></tr>
+ # <tr><td>R</td><td><a href="http://en.wikipedia.org/wiki/Catmull–Rom_spline#Catmull.E2.80.93Rom_spline">Catmull-Rom curveto</a>*</td><td>x1 y1 (x y)+</td></tr></tbody></table>
+ * * “Catmull-Rom curveto” is a not standard SVG command and added in 2.0 to make life easier.
+ * Note: there is a special case when path consist of just three commands: “M10,10R…z”. In this case path will smoothly connects to its beginning.
+ > Usage
+ | var c = paper.path("M10 10L90 90");
+ | // draw a diagonal line:
+ | // move to 10,10, line to 90,90
+ * For example of path strings, check out these icons: http://raphaeljs.com/icons/
+ \*/
+ paperproto.path = function (pathString) {
+ pathString && !R.is(pathString, string) && !R.is(pathString[0], array) && (pathString += E);
+ var out = R._engine.path(R.format[apply](R, arguments), this);
+ this.__set__ && this.__set__.push(out);
+ return out;
+ };
+ /*\
+ * Paper.image
+ [ method ]
+ **
+ * Embeds an image into the surface.
+ **
+ > Parameters
+ **
+ - src (string) URI of the source image
+ - x (number) x coordinate position
+ - y (number) y coordinate position
+ - width (number) width of the image
+ - height (number) height of the image
+ = (object) Raphaël element object with type “image”
+ **
+ > Usage
+ | var c = paper.image("apple.png", 10, 10, 80, 80);
+ \*/
+ paperproto.image = function (src, x, y, w, h) {
+ var out = R._engine.image(this, src || "about:blank", x || 0, y || 0, w || 0, h || 0);
+ this.__set__ && this.__set__.push(out);
+ return out;
+ };
+ /*\
+ * Paper.text
+ [ method ]
+ **
+ * Draws a text string. If you need line breaks, put “\n” in the string.
+ **
+ > Parameters
+ **
+ - x (number) x coordinate position
+ - y (number) y coordinate position
+ - text (string) The text string to draw
+ = (object) Raphaël element object with type “text”
+ **
+ > Usage
+ | var t = paper.text(50, 50, "Raphaël\nkicks\nbutt!");
+ \*/
+ paperproto.text = function (x, y, text) {
+ var out = R._engine.text(this, x || 0, y || 0, Str(text));
+ this.__set__ && this.__set__.push(out);
+ return out;
+ };
+ /*\
+ * Paper.set
+ [ method ]
+ **
+ * Creates array-like object to keep and operate several elements at once.
+ * Warning: it doesn’t create any elements for itself in the page, it just groups existing elements.
+ * Sets act as pseudo elements — all methods available to an element can be used on a set.
+ = (object) array-like object that represents set of elements
+ **
+ > Usage
+ | var st = paper.set();
+ | st.push(
+ | paper.circle(10, 10, 5),
+ | paper.circle(30, 10, 5)
+ | );
+ | st.attr({fill: "red"}); // changes the fill of both circles
+ \*/
+ paperproto.set = function (itemsArray) {
+ !R.is(itemsArray, "array") && (itemsArray = Array.prototype.splice.call(arguments, 0, arguments.length));
+ var out = new Set(itemsArray);
+ this.__set__ && this.__set__.push(out);
+ out["paper"] = this;
+ out["type"] = "set";
+ return out;
+ };
+ /*\
+ * Paper.setStart
+ [ method ]
+ **
+ * Creates @Paper.set. All elements that will be created after calling this method and before calling
+ * @Paper.setFinish will be added to the set.
+ **
+ > Usage
+ | paper.setStart();
+ | paper.circle(10, 10, 5),
+ | paper.circle(30, 10, 5)
+ | var st = paper.setFinish();
+ | st.attr({fill: "red"}); // changes the fill of both circles
+ \*/
+ paperproto.setStart = function (set) {
+ this.__set__ = set || this.set();
+ };
+ /*\
+ * Paper.setFinish
+ [ method ]
+ **
+ * See @Paper.setStart. This method finishes catching and returns resulting set.
+ **
+ = (object) set
+ \*/
+ paperproto.setFinish = function (set) {
+ var out = this.__set__;
+ delete this.__set__;
+ return out;
+ };
+ /*\
+ * Paper.getSize
+ [ method ]
+ **
+ * Obtains current paper actual size.
+ **
+ = (object)
+ \*/
+ paperproto.getSize = function () {
+ var container = this.canvas.parentNode;
+ return {
+ width: container.offsetWidth,
+ height: container.offsetHeight
+ };
+ };
+ /*\
+ * Paper.setSize
+ [ method ]
+ **
+ * If you need to change dimensions of the canvas call this method
+ **
+ > Parameters
+ **
+ - width (number) new width of the canvas
+ - height (number) new height of the canvas
+ \*/
+ paperproto.setSize = function (width, height) {
+ return R._engine.setSize.call(this, width, height);
+ };
+ /*\
+ * Paper.setViewBox
+ [ method ]
+ **
+ * Sets the view box of the paper. Practically it gives you ability to zoom and pan whole paper surface by
+ * specifying new boundaries.
+ **
+ > Parameters
+ **
+ - x (number) new x position, default is `0`
+ - y (number) new y position, default is `0`
+ - w (number) new width of the canvas
+ - h (number) new height of the canvas
+ - fit (boolean) `true` if you want graphics to fit into new boundary box
+ \*/
+ paperproto.setViewBox = function (x, y, w, h, fit) {
+ return R._engine.setViewBox.call(this, x, y, w, h, fit);
+ };
+ /*\
+ * Paper.top
+ [ property ]
+ **
+ * Points to the topmost element on the paper
+ \*/
+ /*\
+ * Paper.bottom
+ [ property ]
+ **
+ * Points to the bottom element on the paper
+ \*/
+ paperproto.top = paperproto.bottom = null;
+ /*\
+ * Paper.raphael
+ [ property ]
+ **
+ * Points to the @Raphael object/function
+ \*/
+ paperproto.raphael = R;
+ var getOffset = function (elem) {
+ var box = elem.getBoundingClientRect(),
+ doc = elem.ownerDocument,
+ body = doc.body,
+ docElem = doc.documentElement,
+ clientTop = docElem.clientTop || body.clientTop || 0, clientLeft = docElem.clientLeft || body.clientLeft || 0,
+ top = box.top + (g.win.pageYOffset || docElem.scrollTop || body.scrollTop ) - clientTop,
+ left = box.left + (g.win.pageXOffset || docElem.scrollLeft || body.scrollLeft) - clientLeft;
+ return {
+ y: top,
+ x: left
+ };
+ };
+ /*\
+ * Paper.getElementByPoint
+ [ method ]
+ **
+ * Returns you topmost element under given point.
+ **
+ = (object) Raphaël element object
+ > Parameters
+ **
+ - x (number) x coordinate from the top left corner of the window
+ - y (number) y coordinate from the top left corner of the window
+ > Usage
+ | paper.getElementByPoint(mouseX, mouseY).attr({stroke: "#f00"});
+ \*/
+ paperproto.getElementByPoint = function (x, y) {
+ var paper = this,
+ svg = paper.canvas,
+ target = g.doc.elementFromPoint(x, y);
+ if (g.win.opera && target.tagName == "svg") {
+ var so = getOffset(svg),
+ sr = svg.createSVGRect();
+ sr.x = x - so.x;
+ sr.y = y - so.y;
+ sr.width = sr.height = 1;
+ var hits = svg.getIntersectionList(sr, null);
+ if (hits.length) {
+ target = hits[hits.length - 1];
+ }
+ }
+ if (!target) {
+ return null;
+ }
+ while (target.parentNode && target != svg.parentNode && !target.raphael) {
+ target = target.parentNode;
+ }
+ target == paper.canvas.parentNode && (target = svg);
+ target = target && target.raphael ? paper.getById(target.raphaelid) : null;
+ return target;
+ };
+
+ /*\
+ * Paper.getElementsByBBox
+ [ method ]
+ **
+ * Returns set of elements that have an intersecting bounding box
+ **
+ > Parameters
+ **
+ - bbox (object) bbox to check with
+ = (object) @Set
+ \*/
+ paperproto.getElementsByBBox = function (bbox) {
+ var set = this.set();
+ this.forEach(function (el) {
+ if (R.isBBoxIntersect(el.getBBox(), bbox)) {
+ set.push(el);
+ }
+ });
+ return set;
+ };
+
+ /*\
+ * Paper.getById
+ [ method ]
+ **
+ * Returns you element by its internal ID.
+ **
+ > Parameters
+ **
+ - id (number) id
+ = (object) Raphaël element object
+ \*/
+ paperproto.getById = function (id) {
+ var bot = this.bottom;
+ while (bot) {
+ if (bot.id == id) {
+ return bot;
+ }
+ bot = bot.next;
+ }
+ return null;
+ };
+ /*\
+ * Paper.forEach
+ [ method ]
+ **
+ * Executes given function for each element on the paper
+ *
+ * If callback function returns `false` it will stop loop running.
+ **
+ > Parameters
+ **
+ - callback (function) function to run
+ - thisArg (object) context object for the callback
+ = (object) Paper object
+ > Usage
+ | paper.forEach(function (el) {
+ | el.attr({ stroke: "blue" });
+ | });
+ \*/
+ paperproto.forEach = function (callback, thisArg) {
+ var bot = this.bottom;
+ while (bot) {
+ if (callback.call(thisArg, bot) === false) {
+ return this;
+ }
+ bot = bot.next;
+ }
+ return this;
+ };
+ /*\
+ * Paper.getElementsByPoint
+ [ method ]
+ **
+ * Returns set of elements that have common point inside
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the point
+ - y (number) y coordinate of the point
+ = (object) @Set
+ \*/
+ paperproto.getElementsByPoint = function (x, y) {
+ var set = this.set();
+ this.forEach(function (el) {
+ if (el.isPointInside(x, y)) {
+ set.push(el);
+ }
+ });
+ return set;
+ };
+ function x_y() {
+ return this.x + S + this.y;
+ }
+ function x_y_w_h() {
+ return this.x + S + this.y + S + this.width + " \xd7 " + this.height;
+ }
+ /*\
+ * Element.isPointInside
+ [ method ]
+ **
+ * Determine if given point is inside this element’s shape
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the point
+ - y (number) y coordinate of the point
+ = (boolean) `true` if point inside the shape
+ \*/
+ elproto.isPointInside = function (x, y) {
+ var rp = this.realPath = getPath[this.type](this);
+ if (this.attr('transform') && this.attr('transform').length) {
+ rp = R.transformPath(rp, this.attr('transform'));
+ }
+ return R.isPointInsidePath(rp, x, y);
+ };
+ /*\
+ * Element.getBBox
+ [ method ]
+ **
+ * Return bounding box for a given element
+ **
+ > Parameters
+ **
+ - isWithoutTransform (boolean) flag, `true` if you want to have bounding box before transformations. Default is `false`.
+ = (object) Bounding box object:
+ o {
+ o x: (number) top left corner x
+ o y: (number) top left corner y
+ o x2: (number) bottom right corner x
+ o y2: (number) bottom right corner y
+ o width: (number) width
+ o height: (number) height
+ o }
+ \*/
+ elproto.getBBox = function (isWithoutTransform) {
+ if (this.removed) {
+ return {};
+ }
+ var _ = this._;
+ if (isWithoutTransform) {
+ if (_.dirty || !_.bboxwt) {
+ this.realPath = getPath[this.type](this);
+ _.bboxwt = pathDimensions(this.realPath);
+ _.bboxwt.toString = x_y_w_h;
+ _.dirty = 0;
+ }
+ return _.bboxwt;
+ }
+ if (_.dirty || _.dirtyT || !_.bbox) {
+ if (_.dirty || !this.realPath) {
+ _.bboxwt = 0;
+ this.realPath = getPath[this.type](this);
+ }
+ _.bbox = pathDimensions(mapPath(this.realPath, this.matrix));
+ _.bbox.toString = x_y_w_h;
+ _.dirty = _.dirtyT = 0;
+ }
+ return _.bbox;
+ };
+ /*\
+ * Element.clone
+ [ method ]
+ **
+ = (object) clone of a given element
+ **
+ \*/
+ elproto.clone = function () {
+ if (this.removed) {
+ return null;
+ }
+ var out = this.paper[this.type]().attr(this.attr());
+ this.__set__ && this.__set__.push(out);
+ return out;
+ };
+ /*\
+ * Element.glow
+ [ method ]
+ **
+ * Return set of elements that create glow-like effect around given element. See @Paper.set.
+ *
+ * Note: Glow is not connected to the element. If you change element attributes it won’t adjust itself.
+ **
+ > Parameters
+ **
+ - glow (object) #optional parameters object with all properties optional:
+ o {
+ o width (number) size of the glow, default is `10`
+ o fill (boolean) will it be filled, default is `false`
+ o opacity (number) opacity, default is `0.5`
+ o offsetx (number) horizontal offset, default is `0`
+ o offsety (number) vertical offset, default is `0`
+ o color (string) glow colour, default is `black`
+ o }
+ = (object) @Paper.set of elements that represents glow
+ \*/
+ elproto.glow = function (glow) {
+ if (this.type == "text") {
+ return null;
+ }
+ glow = glow || {};
+ var s = {
+ width: (glow.width || 10) + (+this.attr("stroke-width") || 1),
+ fill: glow.fill || false,
+ opacity: glow.opacity == null ? .5 : glow.opacity,
+ offsetx: glow.offsetx || 0,
+ offsety: glow.offsety || 0,
+ color: glow.color || "#000"
+ },
+ c = s.width / 2,
+ r = this.paper,
+ out = r.set(),
+ path = this.realPath || getPath[this.type](this);
+ path = this.matrix ? mapPath(path, this.matrix) : path;
+ for (var i = 1; i < c + 1; i++) {
+ out.push(r.path(path).attr({
+ stroke: s.color,
+ fill: s.fill ? s.color : "none",
+ "stroke-linejoin": "round",
+ "stroke-linecap": "round",
+ "stroke-width": +(s.width / c * i).toFixed(3),
+ opacity: +(s.opacity / c).toFixed(3)
+ }));
+ }
+ return out.insertBefore(this).translate(s.offsetx, s.offsety);
+ };
+ var curveslengths = {},
+ getPointAtSegmentLength = function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length) {
+ if (length == null) {
+ return bezlen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y);
+ } else {
+ return R.findDotsAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, getTatLen(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, length));
+ }
+ },
+ getLengthFactory = function (istotal, subpath) {
+ return function (path, length, onlystart) {
+ path = path2curve(path);
+ var x, y, p, l, sp = "", subpaths = {}, point,
+ len = 0;
+ for (var i = 0, ii = path.length; i < ii; i++) {
+ p = path[i];
+ if (p[0] == "M") {
+ x = +p[1];
+ y = +p[2];
+ } else {
+ l = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6]);
+ if (len + l > length) {
+ if (subpath && !subpaths.start) {
+ point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
+ sp += ["C" + point.start.x, point.start.y, point.m.x, point.m.y, point.x, point.y];
+ if (onlystart) {return sp;}
+ subpaths.start = sp;
+ sp = ["M" + point.x, point.y + "C" + point.n.x, point.n.y, point.end.x, point.end.y, p[5], p[6]].join();
+ len += l;
+ x = +p[5];
+ y = +p[6];
+ continue;
+ }
+ if (!istotal && !subpath) {
+ point = getPointAtSegmentLength(x, y, p[1], p[2], p[3], p[4], p[5], p[6], length - len);
+ return {x: point.x, y: point.y, alpha: point.alpha};
+ }
+ }
+ len += l;
+ x = +p[5];
+ y = +p[6];
+ }
+ sp += p.shift() + p;
+ }
+ subpaths.end = sp;
+ point = istotal ? len : subpath ? subpaths : R.findDotsAtSegment(x, y, p[0], p[1], p[2], p[3], p[4], p[5], 1);
+ point.alpha && (point = {x: point.x, y: point.y, alpha: point.alpha});
+ return point;
+ };
+ };
+ var getTotalLength = getLengthFactory(1),
+ getPointAtLength = getLengthFactory(),
+ getSubpathsAtLength = getLengthFactory(0, 1);
+ /*\
+ * Raphael.getTotalLength
+ [ method ]
+ **
+ * Returns length of the given path in pixels.
+ **
+ > Parameters
+ **
+ - path (string) SVG path string.
+ **
+ = (number) length.
+ \*/
+ R.getTotalLength = getTotalLength;
+ /*\
+ * Raphael.getPointAtLength
+ [ method ]
+ **
+ * Return coordinates of the point located at the given length on the given path.
+ **
+ > Parameters
+ **
+ - path (string) SVG path string
+ - length (number)
+ **
+ = (object) representation of the point:
+ o {
+ o x: (number) x coordinate
+ o y: (number) y coordinate
+ o alpha: (number) angle of derivative
+ o }
+ \*/
+ R.getPointAtLength = getPointAtLength;
+ /*\
+ * Raphael.getSubpath
+ [ method ]
+ **
+ * Return subpath of a given path from given length to given length.
+ **
+ > Parameters
+ **
+ - path (string) SVG path string
+ - from (number) position of the start of the segment
+ - to (number) position of the end of the segment
+ **
+ = (string) pathstring for the segment
+ \*/
+ R.getSubpath = function (path, from, to) {
+ if (this.getTotalLength(path) - to < 1e-6) {
+ return getSubpathsAtLength(path, from).end;
+ }
+ var a = getSubpathsAtLength(path, to, 1);
+ return from ? getSubpathsAtLength(a, from).end : a;
+ };
+ /*\
+ * Element.getTotalLength
+ [ method ]
+ **
+ * Returns length of the path in pixels. Only works for element of “path” type.
+ = (number) length.
+ \*/
+ elproto.getTotalLength = function () {
+ var path = this.getPath();
+ if (!path) {
+ return;
+ }
+
+ if (this.node.getTotalLength) {
+ return this.node.getTotalLength();
+ }
+
+ return getTotalLength(path);
+ };
+ /*\
+ * Element.getPointAtLength
+ [ method ]
+ **
+ * Return coordinates of the point located at the given length on the given path. Only works for element of “path” type.
+ **
+ > Parameters
+ **
+ - length (number)
+ **
+ = (object) representation of the point:
+ o {
+ o x: (number) x coordinate
+ o y: (number) y coordinate
+ o alpha: (number) angle of derivative
+ o }
+ \*/
+ elproto.getPointAtLength = function (length) {
+ var path = this.getPath();
+ if (!path) {
+ return;
+ }
+
+ return getPointAtLength(path, length);
+ };
+ /*\
+ * Element.getPath
+ [ method ]
+ **
+ * Returns path of the element. Only works for elements of “path” type and simple elements like circle.
+ = (object) path
+ **
+ \*/
+ elproto.getPath = function () {
+ var path,
+ getPath = R._getPath[this.type];
+
+ if (this.type == "text" || this.type == "set") {
+ return;
+ }
+
+ if (getPath) {
+ path = getPath(this);
+ }
+
+ return path;
+ };
+ /*\
+ * Element.getSubpath
+ [ method ]
+ **
+ * Return subpath of a given element from given length to given length. Only works for element of “path” type.
+ **
+ > Parameters
+ **
+ - from (number) position of the start of the segment
+ - to (number) position of the end of the segment
+ **
+ = (string) pathstring for the segment
+ \*/
+ elproto.getSubpath = function (from, to) {
+ var path = this.getPath();
+ if (!path) {
+ return;
+ }
+
+ return R.getSubpath(path, from, to);
+ };
+ /*\
+ * Raphael.easing_formulas
+ [ property ]
+ **
+ * Object that contains easing formulas for animation. You could extend it with your own. By default it has following list of easing:
+ # <ul>
+ # <li>“linear”</li>
+ # <li>“&lt;” or “easeIn” or “ease-in”</li>
+ # <li>“>” or “easeOut” or “ease-out”</li>
+ # <li>“&lt;>” or “easeInOut” or “ease-in-out”</li>
+ # <li>“backIn” or “back-in”</li>
+ # <li>“backOut” or “back-out”</li>
+ # <li>“elastic”</li>
+ # <li>“bounce”</li>
+ # </ul>
+ # <p>See also <a href="http://raphaeljs.com/easing.html">Easing demo</a>.</p>
+ \*/
+ var ef = R.easing_formulas = {
+ linear: function (n) {
+ return n;
+ },
+ "<": function (n) {
+ return pow(n, 1.7);
+ },
+ ">": function (n) {
+ return pow(n, .48);
+ },
+ "<>": function (n) {
+ var q = .48 - n / 1.04,
+ Q = math.sqrt(.1734 + q * q),
+ x = Q - q,
+ X = pow(abs(x), 1 / 3) * (x < 0 ? -1 : 1),
+ y = -Q - q,
+ Y = pow(abs(y), 1 / 3) * (y < 0 ? -1 : 1),
+ t = X + Y + .5;
+ return (1 - t) * 3 * t * t + t * t * t;
+ },
+ backIn: function (n) {
+ var s = 1.70158;
+ return n * n * ((s + 1) * n - s);
+ },
+ backOut: function (n) {
+ n = n - 1;
+ var s = 1.70158;
+ return n * n * ((s + 1) * n + s) + 1;
+ },
+ elastic: function (n) {
+ if (n == !!n) {
+ return n;
+ }
+ return pow(2, -10 * n) * math.sin((n - .075) * (2 * PI) / .3) + 1;
+ },
+ bounce: function (n) {
+ var s = 7.5625,
+ p = 2.75,
+ l;
+ if (n < (1 / p)) {
+ l = s * n * n;
+ } else {
+ if (n < (2 / p)) {
+ n -= (1.5 / p);
+ l = s * n * n + .75;
+ } else {
+ if (n < (2.5 / p)) {
+ n -= (2.25 / p);
+ l = s * n * n + .9375;
+ } else {
+ n -= (2.625 / p);
+ l = s * n * n + .984375;
+ }
+ }
+ }
+ return l;
+ }
+ };
+ ef.easeIn = ef["ease-in"] = ef["<"];
+ ef.easeOut = ef["ease-out"] = ef[">"];
+ ef.easeInOut = ef["ease-in-out"] = ef["<>"];
+ ef["back-in"] = ef.backIn;
+ ef["back-out"] = ef.backOut;
+
+ var animationElements = [],
+ requestAnimFrame = window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function (callback) {
+ setTimeout(callback, 16);
+ },
+ animation = function () {
+ var Now = +new Date,
+ l = 0;
+ for (; l < animationElements.length; l++) {
+ var e = animationElements[l];
+ if (e.el.removed || e.paused) {
+ continue;
+ }
+ var time = Now - e.start,
+ ms = e.ms,
+ easing = e.easing,
+ from = e.from,
+ diff = e.diff,
+ to = e.to,
+ t = e.t,
+ that = e.el,
+ set = {},
+ now,
+ init = {},
+ key;
+ if (e.initstatus) {
+ time = (e.initstatus * e.anim.top - e.prev) / (e.percent - e.prev) * ms;
+ e.status = e.initstatus;
+ delete e.initstatus;
+ e.stop && animationElements.splice(l--, 1);
+ } else {
+ e.status = (e.prev + (e.percent - e.prev) * (time / ms)) / e.anim.top;
+ }
+ if (time < 0) {
+ continue;
+ }
+ if (time < ms) {
+ var pos = easing(time / ms);
+ for (var attr in from) if (from[has](attr)) {
+ switch (availableAnimAttrs[attr]) {
+ case nu:
+ now = +from[attr] + pos * ms * diff[attr];
+ break;
+ case "colour":
+ now = "rgb(" + [
+ upto255(round(from[attr].r + pos * ms * diff[attr].r)),
+ upto255(round(from[attr].g + pos * ms * diff[attr].g)),
+ upto255(round(from[attr].b + pos * ms * diff[attr].b))
+ ].join(",") + ")";
+ break;
+ case "path":
+ now = [];
+ for (var i = 0, ii = from[attr].length; i < ii; i++) {
+ now[i] = [from[attr][i][0]];
+ for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
+ now[i][j] = +from[attr][i][j] + pos * ms * diff[attr][i][j];
+ }
+ now[i] = now[i].join(S);
+ }
+ now = now.join(S);
+ break;
+ case "transform":
+ if (diff[attr].real) {
+ now = [];
+ for (i = 0, ii = from[attr].length; i < ii; i++) {
+ now[i] = [from[attr][i][0]];
+ for (j = 1, jj = from[attr][i].length; j < jj; j++) {
+ now[i][j] = from[attr][i][j] + pos * ms * diff[attr][i][j];
+ }
+ }
+ } else {
+ var get = function (i) {
+ return +from[attr][i] + pos * ms * diff[attr][i];
+ };
+ // now = [["r", get(2), 0, 0], ["t", get(3), get(4)], ["s", get(0), get(1), 0, 0]];
+ now = [["m", get(0), get(1), get(2), get(3), get(4), get(5)]];
+ }
+ break;
+ case "csv":
+ if (attr == "clip-rect") {
+ now = [];
+ i = 4;
+ while (i--) {
+ now[i] = +from[attr][i] + pos * ms * diff[attr][i];
+ }
+ }
+ break;
+ default:
+ var from2 = [][concat](from[attr]);
+ now = [];
+ i = that.paper.customAttributes[attr].length;
+ while (i--) {
+ now[i] = +from2[i] + pos * ms * diff[attr][i];
+ }
+ break;
+ }
+ set[attr] = now;
+ }
+ that.attr(set);
+ (function (id, that, anim) {
+ setTimeout(function () {
+ eve("raphael.anim.frame." + id, that, anim);
+ });
+ })(that.id, that, e.anim);
+ } else {
+ (function(f, el, a) {
+ setTimeout(function() {
+ eve("raphael.anim.frame." + el.id, el, a);
+ eve("raphael.anim.finish." + el.id, el, a);
+ R.is(f, "function") && f.call(el);
+ });
+ })(e.callback, that, e.anim);
+ that.attr(to);
+ animationElements.splice(l--, 1);
+ if (e.repeat > 1 && !e.next) {
+ for (key in to) if (to[has](key)) {
+ init[key] = e.totalOrigin[key];
+ }
+ e.el.attr(init);
+ runAnimation(e.anim, e.el, e.anim.percents[0], null, e.totalOrigin, e.repeat - 1);
+ }
+ if (e.next && !e.stop) {
+ runAnimation(e.anim, e.el, e.next, null, e.totalOrigin, e.repeat);
+ }
+ }
+ }
+ animationElements.length && requestAnimFrame(animation);
+ },
+ upto255 = function (color) {
+ return color > 255 ? 255 : color < 0 ? 0 : color;
+ };
+ /*\
+ * Element.animateWith
+ [ method ]
+ **
+ * Acts similar to @Element.animate, but ensure that given animation runs in sync with another given element.
+ **
+ > Parameters
+ **
+ - el (object) element to sync with
+ - anim (object) animation to sync with
+ - params (object) #optional final attributes for the element, see also @Element.attr
+ - ms (number) #optional number of milliseconds for animation to run
+ - easing (string) #optional easing type. Accept on of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
+ - callback (function) #optional callback function. Will be called at the end of animation.
+ * or
+ - element (object) element to sync with
+ - anim (object) animation to sync with
+ - animation (object) #optional animation object, see @Raphael.animation
+ **
+ = (object) original element
+ \*/
+ elproto.animateWith = function (el, anim, params, ms, easing, callback) {
+ var element = this;
+ if (element.removed) {
+ callback && callback.call(element);
+ return element;
+ }
+ var a = params instanceof Animation ? params : R.animation(params, ms, easing, callback),
+ x, y;
+ runAnimation(a, element, a.percents[0], null, element.attr());
+ for (var i = 0, ii = animationElements.length; i < ii; i++) {
+ if (animationElements[i].anim == anim && animationElements[i].el == el) {
+ animationElements[ii - 1].start = animationElements[i].start;
+ break;
+ }
+ }
+ return element;
+ //
+ //
+ // var a = params ? R.animation(params, ms, easing, callback) : anim,
+ // status = element.status(anim);
+ // return this.animate(a).status(a, status * anim.ms / a.ms);
+ };
+ function CubicBezierAtTime(t, p1x, p1y, p2x, p2y, duration) {
+ var cx = 3 * p1x,
+ bx = 3 * (p2x - p1x) - cx,
+ ax = 1 - cx - bx,
+ cy = 3 * p1y,
+ by = 3 * (p2y - p1y) - cy,
+ ay = 1 - cy - by;
+ function sampleCurveX(t) {
+ return ((ax * t + bx) * t + cx) * t;
+ }
+ function solve(x, epsilon) {
+ var t = solveCurveX(x, epsilon);
+ return ((ay * t + by) * t + cy) * t;
+ }
+ function solveCurveX(x, epsilon) {
+ var t0, t1, t2, x2, d2, i;
+ for(t2 = x, i = 0; i < 8; i++) {
+ x2 = sampleCurveX(t2) - x;
+ if (abs(x2) < epsilon) {
+ return t2;
+ }
+ d2 = (3 * ax * t2 + 2 * bx) * t2 + cx;
+ if (abs(d2) < 1e-6) {
+ break;
+ }
+ t2 = t2 - x2 / d2;
+ }
+ t0 = 0;
+ t1 = 1;
+ t2 = x;
+ if (t2 < t0) {
+ return t0;
+ }
+ if (t2 > t1) {
+ return t1;
+ }
+ while (t0 < t1) {
+ x2 = sampleCurveX(t2);
+ if (abs(x2 - x) < epsilon) {
+ return t2;
+ }
+ if (x > x2) {
+ t0 = t2;
+ } else {
+ t1 = t2;
+ }
+ t2 = (t1 - t0) / 2 + t0;
+ }
+ return t2;
+ }
+ return solve(t, 1 / (200 * duration));
+ }
+ elproto.onAnimation = function (f) {
+ f ? eve.on("raphael.anim.frame." + this.id, f) : eve.unbind("raphael.anim.frame." + this.id);
+ return this;
+ };
+ function Animation(anim, ms) {
+ var percents = [],
+ newAnim = {};
+ this.ms = ms;
+ this.times = 1;
+ if (anim) {
+ for (var attr in anim) if (anim[has](attr)) {
+ newAnim[toFloat(attr)] = anim[attr];
+ percents.push(toFloat(attr));
+ }
+ percents.sort(sortByNumber);
+ }
+ this.anim = newAnim;
+ this.top = percents[percents.length - 1];
+ this.percents = percents;
+ }
+ /*\
+ * Animation.delay
+ [ method ]
+ **
+ * Creates a copy of existing animation object with given delay.
+ **
+ > Parameters
+ **
+ - delay (number) number of ms to pass between animation start and actual animation
+ **
+ = (object) new altered Animation object
+ | var anim = Raphael.animation({cx: 10, cy: 20}, 2e3);
+ | circle1.animate(anim); // run the given animation immediately
+ | circle2.animate(anim.delay(500)); // run the given animation after 500 ms
+ \*/
+ Animation.prototype.delay = function (delay) {
+ var a = new Animation(this.anim, this.ms);
+ a.times = this.times;
+ a.del = +delay || 0;
+ return a;
+ };
+ /*\
+ * Animation.repeat
+ [ method ]
+ **
+ * Creates a copy of existing animation object with given repetition.
+ **
+ > Parameters
+ **
+ - repeat (number) number iterations of animation. For infinite animation pass `Infinity`
+ **
+ = (object) new altered Animation object
+ \*/
+ Animation.prototype.repeat = function (times) {
+ var a = new Animation(this.anim, this.ms);
+ a.del = this.del;
+ a.times = math.floor(mmax(times, 0)) || 1;
+ return a;
+ };
+ function runAnimation(anim, element, percent, status, totalOrigin, times) {
+ percent = toFloat(percent);
+ var params,
+ isInAnim,
+ isInAnimSet,
+ percents = [],
+ next,
+ prev,
+ timestamp,
+ ms = anim.ms,
+ from = {},
+ to = {},
+ diff = {};
+ if (status) {
+ for (i = 0, ii = animationElements.length; i < ii; i++) {
+ var e = animationElements[i];
+ if (e.el.id == element.id && e.anim == anim) {
+ if (e.percent != percent) {
+ animationElements.splice(i, 1);
+ isInAnimSet = 1;
+ } else {
+ isInAnim = e;
+ }
+ element.attr(e.totalOrigin);
+ break;
+ }
+ }
+ } else {
+ status = +to; // NaN
+ }
+ for (var i = 0, ii = anim.percents.length; i < ii; i++) {
+ if (anim.percents[i] == percent || anim.percents[i] > status * anim.top) {
+ percent = anim.percents[i];
+ prev = anim.percents[i - 1] || 0;
+ ms = ms / anim.top * (percent - prev);
+ next = anim.percents[i + 1];
+ params = anim.anim[percent];
+ break;
+ } else if (status) {
+ element.attr(anim.anim[anim.percents[i]]);
+ }
+ }
+ if (!params) {
+ return;
+ }
+ if (!isInAnim) {
+ for (var attr in params) if (params[has](attr)) {
+ if (availableAnimAttrs[has](attr) || element.paper.customAttributes[has](attr)) {
+ from[attr] = element.attr(attr);
+ (from[attr] == null) && (from[attr] = availableAttrs[attr]);
+ to[attr] = params[attr];
+ switch (availableAnimAttrs[attr]) {
+ case nu:
+ diff[attr] = (to[attr] - from[attr]) / ms;
+ break;
+ case "colour":
+ from[attr] = R.getRGB(from[attr]);
+ var toColour = R.getRGB(to[attr]);
+ diff[attr] = {
+ r: (toColour.r - from[attr].r) / ms,
+ g: (toColour.g - from[attr].g) / ms,
+ b: (toColour.b - from[attr].b) / ms
+ };
+ break;
+ case "path":
+ var pathes = path2curve(from[attr], to[attr]),
+ toPath = pathes[1];
+ from[attr] = pathes[0];
+ diff[attr] = [];
+ for (i = 0, ii = from[attr].length; i < ii; i++) {
+ diff[attr][i] = [0];
+ for (var j = 1, jj = from[attr][i].length; j < jj; j++) {
+ diff[attr][i][j] = (toPath[i][j] - from[attr][i][j]) / ms;
+ }
+ }
+ break;
+ case "transform":
+ var _ = element._,
+ eq = equaliseTransform(_[attr], to[attr]);
+ if (eq) {
+ from[attr] = eq.from;
+ to[attr] = eq.to;
+ diff[attr] = [];
+ diff[attr].real = true;
+ for (i = 0, ii = from[attr].length; i < ii; i++) {
+ diff[attr][i] = [from[attr][i][0]];
+ for (j = 1, jj = from[attr][i].length; j < jj; j++) {
+ diff[attr][i][j] = (to[attr][i][j] - from[attr][i][j]) / ms;
+ }
+ }
+ } else {
+ var m = (element.matrix || new Matrix),
+ to2 = {
+ _: {transform: _.transform},
+ getBBox: function () {
+ return element.getBBox(1);
+ }
+ };
+ from[attr] = [
+ m.a,
+ m.b,
+ m.c,
+ m.d,
+ m.e,
+ m.f
+ ];
+ extractTransform(to2, to[attr]);
+ to[attr] = to2._.transform;
+ diff[attr] = [
+ (to2.matrix.a - m.a) / ms,
+ (to2.matrix.b - m.b) / ms,
+ (to2.matrix.c - m.c) / ms,
+ (to2.matrix.d - m.d) / ms,
+ (to2.matrix.e - m.e) / ms,
+ (to2.matrix.f - m.f) / ms
+ ];
+ // from[attr] = [_.sx, _.sy, _.deg, _.dx, _.dy];
+ // var to2 = {_:{}, getBBox: function () { return element.getBBox(); }};
+ // extractTransform(to2, to[attr]);
+ // diff[attr] = [
+ // (to2._.sx - _.sx) / ms,
+ // (to2._.sy - _.sy) / ms,
+ // (to2._.deg - _.deg) / ms,
+ // (to2._.dx - _.dx) / ms,
+ // (to2._.dy - _.dy) / ms
+ // ];
+ }
+ break;
+ case "csv":
+ var values = Str(params[attr])[split](separator),
+ from2 = Str(from[attr])[split](separator);
+ if (attr == "clip-rect") {
+ from[attr] = from2;
+ diff[attr] = [];
+ i = from2.length;
+ while (i--) {
+ diff[attr][i] = (values[i] - from[attr][i]) / ms;
+ }
+ }
+ to[attr] = values;
+ break;
+ default:
+ values = [][concat](params[attr]);
+ from2 = [][concat](from[attr]);
+ diff[attr] = [];
+ i = element.paper.customAttributes[attr].length;
+ while (i--) {
+ diff[attr][i] = ((values[i] || 0) - (from2[i] || 0)) / ms;
+ }
+ break;
+ }
+ }
+ }
+ var easing = params.easing,
+ easyeasy = R.easing_formulas[easing];
+ if (!easyeasy) {
+ easyeasy = Str(easing).match(bezierrg);
+ if (easyeasy && easyeasy.length == 5) {
+ var curve = easyeasy;
+ easyeasy = function (t) {
+ return CubicBezierAtTime(t, +curve[1], +curve[2], +curve[3], +curve[4], ms);
+ };
+ } else {
+ easyeasy = pipe;
+ }
+ }
+ timestamp = params.start || anim.start || +new Date;
+ e = {
+ anim: anim,
+ percent: percent,
+ timestamp: timestamp,
+ start: timestamp + (anim.del || 0),
+ status: 0,
+ initstatus: status || 0,
+ stop: false,
+ ms: ms,
+ easing: easyeasy,
+ from: from,
+ diff: diff,
+ to: to,
+ el: element,
+ callback: params.callback,
+ prev: prev,
+ next: next,
+ repeat: times || anim.times,
+ origin: element.attr(),
+ totalOrigin: totalOrigin
+ };
+ animationElements.push(e);
+ if (status && !isInAnim && !isInAnimSet) {
+ e.stop = true;
+ e.start = new Date - ms * status;
+ if (animationElements.length == 1) {
+ return animation();
+ }
+ }
+ if (isInAnimSet) {
+ e.start = new Date - e.ms * status;
+ }
+ animationElements.length == 1 && requestAnimFrame(animation);
+ } else {
+ isInAnim.initstatus = status;
+ isInAnim.start = new Date - isInAnim.ms * status;
+ }
+ eve("raphael.anim.start." + element.id, element, anim);
+ }
+ /*\
+ * Raphael.animation
+ [ method ]
+ **
+ * Creates an animation object that can be passed to the @Element.animate or @Element.animateWith methods.
+ * See also @Animation.delay and @Animation.repeat methods.
+ **
+ > Parameters
+ **
+ - params (object) final attributes for the element, see also @Element.attr
+ - ms (number) number of milliseconds for animation to run
+ - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
+ - callback (function) #optional callback function. Will be called at the end of animation.
+ **
+ = (object) @Animation
+ \*/
+ R.animation = function (params, ms, easing, callback) {
+ if (params instanceof Animation) {
+ return params;
+ }
+ if (R.is(easing, "function") || !easing) {
+ callback = callback || easing || null;
+ easing = null;
+ }
+ params = Object(params);
+ ms = +ms || 0;
+ var p = {},
+ json,
+ attr;
+ for (attr in params) if (params[has](attr) && toFloat(attr) != attr && toFloat(attr) + "%" != attr) {
+ json = true;
+ p[attr] = params[attr];
+ }
+ if (!json) {
+ // if percent-like syntax is used and end-of-all animation callback used
+ if(callback){
+ // find the last one
+ var lastKey = 0;
+ for(var i in params){
+ var percent = toInt(i);
+ if(params[has](i) && percent > lastKey){
+ lastKey = percent;
+ }
+ }
+ lastKey += '%';
+ // if already defined callback in the last keyframe, skip
+ !params[lastKey].callback && (params[lastKey].callback = callback);
+ }
+ return new Animation(params, ms);
+ } else {
+ easing && (p.easing = easing);
+ callback && (p.callback = callback);
+ return new Animation({100: p}, ms);
+ }
+ };
+ /*\
+ * Element.animate
+ [ method ]
+ **
+ * Creates and starts animation for given element.
+ **
+ > Parameters
+ **
+ - params (object) final attributes for the element, see also @Element.attr
+ - ms (number) number of milliseconds for animation to run
+ - easing (string) #optional easing type. Accept one of @Raphael.easing_formulas or CSS format: `cubic&#x2010;bezier(XX,&#160;XX,&#160;XX,&#160;XX)`
+ - callback (function) #optional callback function. Will be called at the end of animation.
+ * or
+ - animation (object) animation object, see @Raphael.animation
+ **
+ = (object) original element
+ \*/
+ elproto.animate = function (params, ms, easing, callback) {
+ var element = this;
+ if (element.removed) {
+ callback && callback.call(element);
+ return element;
+ }
+ var anim = params instanceof Animation ? params : R.animation(params, ms, easing, callback);
+ runAnimation(anim, element, anim.percents[0], null, element.attr());
+ return element;
+ };
+ /*\
+ * Element.setTime
+ [ method ]
+ **
+ * Sets the status of animation of the element in milliseconds. Similar to @Element.status method.
+ **
+ > Parameters
+ **
+ - anim (object) animation object
+ - value (number) number of milliseconds from the beginning of the animation
+ **
+ = (object) original element if `value` is specified
+ * Note, that during animation following events are triggered:
+ *
+ * On each animation frame event `anim.frame.<id>`, on start `anim.start.<id>` and on end `anim.finish.<id>`.
+ \*/
+ elproto.setTime = function (anim, value) {
+ if (anim && value != null) {
+ this.status(anim, mmin(value, anim.ms) / anim.ms);
+ }
+ return this;
+ };
+ /*\
+ * Element.status
+ [ method ]
+ **
+ * Gets or sets the status of animation of the element.
+ **
+ > Parameters
+ **
+ - anim (object) #optional animation object
+ - value (number) #optional 0 – 1. If specified, method works like a setter and sets the status of a given animation to the value. This will cause animation to jump to the given position.
+ **
+ = (number) status
+ * or
+ = (array) status if `anim` is not specified. Array of objects in format:
+ o {
+ o anim: (object) animation object
+ o status: (number) status
+ o }
+ * or
+ = (object) original element if `value` is specified
+ \*/
+ elproto.status = function (anim, value) {
+ var out = [],
+ i = 0,
+ len,
+ e;
+ if (value != null) {
+ runAnimation(anim, this, -1, mmin(value, 1));
+ return this;
+ } else {
+ len = animationElements.length;
+ for (; i < len; i++) {
+ e = animationElements[i];
+ if (e.el.id == this.id && (!anim || e.anim == anim)) {
+ if (anim) {
+ return e.status;
+ }
+ out.push({
+ anim: e.anim,
+ status: e.status
+ });
+ }
+ }
+ if (anim) {
+ return 0;
+ }
+ return out;
+ }
+ };
+ /*\
+ * Element.pause
+ [ method ]
+ **
+ * Stops animation of the element with ability to resume it later on.
+ **
+ > Parameters
+ **
+ - anim (object) #optional animation object
+ **
+ = (object) original element
+ \*/
+ elproto.pause = function (anim) {
+ for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
+ if (eve("raphael.anim.pause." + this.id, this, animationElements[i].anim) !== false) {
+ animationElements[i].paused = true;
+ }
+ }
+ return this;
+ };
+ /*\
+ * Element.resume
+ [ method ]
+ **
+ * Resumes animation if it was paused with @Element.pause method.
+ **
+ > Parameters
+ **
+ - anim (object) #optional animation object
+ **
+ = (object) original element
+ \*/
+ elproto.resume = function (anim) {
+ for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
+ var e = animationElements[i];
+ if (eve("raphael.anim.resume." + this.id, this, e.anim) !== false) {
+ delete e.paused;
+ this.status(e.anim, e.status);
+ }
+ }
+ return this;
+ };
+ /*\
+ * Element.stop
+ [ method ]
+ **
+ * Stops animation of the element.
+ **
+ > Parameters
+ **
+ - anim (object) #optional animation object
+ **
+ = (object) original element
+ \*/
+ elproto.stop = function (anim) {
+ for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.id == this.id && (!anim || animationElements[i].anim == anim)) {
+ if (eve("raphael.anim.stop." + this.id, this, animationElements[i].anim) !== false) {
+ animationElements.splice(i--, 1);
+ }
+ }
+ return this;
+ };
+ function stopAnimation(paper) {
+ for (var i = 0; i < animationElements.length; i++) if (animationElements[i].el.paper == paper) {
+ animationElements.splice(i--, 1);
+ }
+ }
+ eve.on("raphael.remove", stopAnimation);
+ eve.on("raphael.clear", stopAnimation);
+ elproto.toString = function () {
+ return "Rapha\xebl\u2019s object";
+ };
+
+ // Set
+ var Set = function (items) {
+ this.items = [];
+ this.length = 0;
+ this.type = "set";
+ if (items) {
+ for (var i = 0, ii = items.length; i < ii; i++) {
+ if (items[i] && (items[i].constructor == elproto.constructor || items[i].constructor == Set)) {
+ this[this.items.length] = this.items[this.items.length] = items[i];
+ this.length++;
+ }
+ }
+ }
+ },
+ setproto = Set.prototype;
+ /*\
+ * Set.push
+ [ method ]
+ **
+ * Adds each argument to the current set.
+ = (object) original element
+ \*/
+ setproto.push = function () {
+ var item,
+ len;
+ for (var i = 0, ii = arguments.length; i < ii; i++) {
+ item = arguments[i];
+ if (item && (item.constructor == elproto.constructor || item.constructor == Set)) {
+ len = this.items.length;
+ this[len] = this.items[len] = item;
+ this.length++;
+ }
+ }
+ return this;
+ };
+ /*\
+ * Set.pop
+ [ method ]
+ **
+ * Removes last element and returns it.
+ = (object) element
+ \*/
+ setproto.pop = function () {
+ this.length && delete this[this.length--];
+ return this.items.pop();
+ };
+ /*\
+ * Set.forEach
+ [ method ]
+ **
+ * Executes given function for each element in the set.
+ *
+ * If function returns `false` it will stop loop running.
+ **
+ > Parameters
+ **
+ - callback (function) function to run
+ - thisArg (object) context object for the callback
+ = (object) Set object
+ \*/
+ setproto.forEach = function (callback, thisArg) {
+ for (var i = 0, ii = this.items.length; i < ii; i++) {
+ if (callback.call(thisArg, this.items[i], i) === false) {
+ return this;
+ }
+ }
+ return this;
+ };
+ for (var method in elproto) if (elproto[has](method)) {
+ setproto[method] = (function (methodname) {
+ return function () {
+ var arg = arguments;
+ return this.forEach(function (el) {
+ el[methodname][apply](el, arg);
+ });
+ };
+ })(method);
+ }
+ setproto.attr = function (name, value) {
+ if (name && R.is(name, array) && R.is(name[0], "object")) {
+ for (var j = 0, jj = name.length; j < jj; j++) {
+ this.items[j].attr(name[j]);
+ }
+ } else {
+ for (var i = 0, ii = this.items.length; i < ii; i++) {
+ this.items[i].attr(name, value);
+ }
+ }
+ return this;
+ };
+ /*\
+ * Set.clear
+ [ method ]
+ **
+ * Removes all elements from the set
+ \*/
+ setproto.clear = function () {
+ while (this.length) {
+ this.pop();
+ }
+ };
+ /*\
+ * Set.splice
+ [ method ]
+ **
+ * Removes given element from the set
+ **
+ > Parameters
+ **
+ - index (number) position of the deletion
+ - count (number) number of element to remove
+ - insertion… (object) #optional elements to insert
+ = (object) set elements that were deleted
+ \*/
+ setproto.splice = function (index, count, insertion) {
+ index = index < 0 ? mmax(this.length + index, 0) : index;
+ count = mmax(0, mmin(this.length - index, count));
+ var tail = [],
+ todel = [],
+ args = [],
+ i;
+ for (i = 2; i < arguments.length; i++) {
+ args.push(arguments[i]);
+ }
+ for (i = 0; i < count; i++) {
+ todel.push(this[index + i]);
+ }
+ for (; i < this.length - index; i++) {
+ tail.push(this[index + i]);
+ }
+ var arglen = args.length;
+ for (i = 0; i < arglen + tail.length; i++) {
+ this.items[index + i] = this[index + i] = i < arglen ? args[i] : tail[i - arglen];
+ }
+ i = this.items.length = this.length -= count - arglen;
+ while (this[i]) {
+ delete this[i++];
+ }
+ return new Set(todel);
+ };
+ /*\
+ * Set.exclude
+ [ method ]
+ **
+ * Removes given element from the set
+ **
+ > Parameters
+ **
+ - element (object) element to remove
+ = (boolean) `true` if object was found & removed from the set
+ \*/
+ setproto.exclude = function (el) {
+ for (var i = 0, ii = this.length; i < ii; i++) if (this[i] == el) {
+ this.splice(i, 1);
+ return true;
+ }
+ };
+ setproto.animate = function (params, ms, easing, callback) {
+ (R.is(easing, "function") || !easing) && (callback = easing || null);
+ var len = this.items.length,
+ i = len,
+ item,
+ set = this,
+ collector;
+ if (!len) {
+ return this;
+ }
+ callback && (collector = function () {
+ !--len && callback.call(set);
+ });
+ easing = R.is(easing, string) ? easing : collector;
+ var anim = R.animation(params, ms, easing, collector);
+ item = this.items[--i].animate(anim);
+ while (i--) {
+ this.items[i] && !this.items[i].removed && this.items[i].animateWith(item, anim, anim);
+ (this.items[i] && !this.items[i].removed) || len--;
+ }
+ return this;
+ };
+ setproto.insertAfter = function (el) {
+ var i = this.items.length;
+ while (i--) {
+ this.items[i].insertAfter(el);
+ }
+ return this;
+ };
+ setproto.getBBox = function () {
+ var x = [],
+ y = [],
+ x2 = [],
+ y2 = [];
+ for (var i = this.items.length; i--;) if (!this.items[i].removed) {
+ var box = this.items[i].getBBox();
+ x.push(box.x);
+ y.push(box.y);
+ x2.push(box.x + box.width);
+ y2.push(box.y + box.height);
+ }
+ x = mmin[apply](0, x);
+ y = mmin[apply](0, y);
+ x2 = mmax[apply](0, x2);
+ y2 = mmax[apply](0, y2);
+ return {
+ x: x,
+ y: y,
+ x2: x2,
+ y2: y2,
+ width: x2 - x,
+ height: y2 - y
+ };
+ };
+ setproto.clone = function (s) {
+ s = this.paper.set();
+ for (var i = 0, ii = this.items.length; i < ii; i++) {
+ s.push(this.items[i].clone());
+ }
+ return s;
+ };
+ setproto.toString = function () {
+ return "Rapha\xebl\u2018s set";
+ };
+
+ setproto.glow = function(glowConfig) {
+ var ret = this.paper.set();
+ this.forEach(function(shape, index){
+ var g = shape.glow(glowConfig);
+ if(g != null){
+ g.forEach(function(shape2, index2){
+ ret.push(shape2);
+ });
+ }
+ });
+ return ret;
+ };
+
+
+ /*\
+ * Set.isPointInside
+ [ method ]
+ **
+ * Determine if given point is inside this set’s elements
+ **
+ > Parameters
+ **
+ - x (number) x coordinate of the point
+ - y (number) y coordinate of the point
+ = (boolean) `true` if point is inside any of the set's elements
+ \*/
+ setproto.isPointInside = function (x, y) {
+ var isPointInside = false;
+ this.forEach(function (el) {
+ if (el.isPointInside(x, y)) {
+ isPointInside = true;
+ return false; // stop loop
+ }
+ });
+ return isPointInside;
+ };
+
+ /*\
+ * Raphael.registerFont
+ [ method ]
+ **
+ * Adds given font to the registered set of fonts for Raphaël. Should be used as an internal call from within Cufón’s font file.
+ * Returns original parameter, so it could be used with chaining.
+ # <a href="http://wiki.github.com/sorccu/cufon/about">More about Cufón and how to convert your font form TTF, OTF, etc to JavaScript file.</a>
+ **
+ > Parameters
+ **
+ - font (object) the font to register
+ = (object) the font you passed in
+ > Usage
+ | Cufon.registerFont(Raphael.registerFont({…}));
+ \*/
+ R.registerFont = function (font) {
+ if (!font.face) {
+ return font;
+ }
+ this.fonts = this.fonts || {};
+ var fontcopy = {
+ w: font.w,
+ face: {},
+ glyphs: {}
+ },
+ family = font.face["font-family"];
+ for (var prop in font.face) if (font.face[has](prop)) {
+ fontcopy.face[prop] = font.face[prop];
+ }
+ if (this.fonts[family]) {
+ this.fonts[family].push(fontcopy);
+ } else {
+ this.fonts[family] = [fontcopy];
+ }
+ if (!font.svg) {
+ fontcopy.face["units-per-em"] = toInt(font.face["units-per-em"], 10);
+ for (var glyph in font.glyphs) if (font.glyphs[has](glyph)) {
+ var path = font.glyphs[glyph];
+ fontcopy.glyphs[glyph] = {
+ w: path.w,
+ k: {},
+ d: path.d && "M" + path.d.replace(/[mlcxtrv]/g, function (command) {
+ return {l: "L", c: "C", x: "z", t: "m", r: "l", v: "c"}[command] || "M";
+ }) + "z"
+ };
+ if (path.k) {
+ for (var k in path.k) if (path[has](k)) {
+ fontcopy.glyphs[glyph].k[k] = path.k[k];
+ }
+ }
+ }
+ }
+ return font;
+ };
+ /*\
+ * Paper.getFont
+ [ method ]
+ **
+ * Finds font object in the registered fonts by given parameters. You could specify only one word from the font name, like “Myriad” for “Myriad Pro”.
+ **
+ > Parameters
+ **
+ - family (string) font family name or any word from it
+ - weight (string) #optional font weight
+ - style (string) #optional font style
+ - stretch (string) #optional font stretch
+ = (object) the font object
+ > Usage
+ | paper.print(100, 100, "Test string", paper.getFont("Times", 800), 30);
+ \*/
+ paperproto.getFont = function (family, weight, style, stretch) {
+ stretch = stretch || "normal";
+ style = style || "normal";
+ weight = +weight || {normal: 400, bold: 700, lighter: 300, bolder: 800}[weight] || 400;
+ if (!R.fonts) {
+ return;
+ }
+ var font = R.fonts[family];
+ if (!font) {
+ var name = new RegExp("(^|\\s)" + family.replace(/[^\w\d\s+!~.:_-]/g, E) + "(\\s|$)", "i");
+ for (var fontName in R.fonts) if (R.fonts[has](fontName)) {
+ if (name.test(fontName)) {
+ font = R.fonts[fontName];
+ break;
+ }
+ }
+ }
+ var thefont;
+ if (font) {
+ for (var i = 0, ii = font.length; i < ii; i++) {
+ thefont = font[i];
+ if (thefont.face["font-weight"] == weight && (thefont.face["font-style"] == style || !thefont.face["font-style"]) && thefont.face["font-stretch"] == stretch) {
+ break;
+ }
+ }
+ }
+ return thefont;
+ };
+ /*\
+ * Paper.print
+ [ method ]
+ **
+ * Creates path that represent given text written using given font at given position with given size.
+ * Result of the method is path element that contains whole text as a separate path.
+ **
+ > Parameters
+ **
+ - x (number) x position of the text
+ - y (number) y position of the text
+ - string (string) text to print
+ - font (object) font object, see @Paper.getFont
+ - size (number) #optional size of the font, default is `16`
+ - origin (string) #optional could be `"baseline"` or `"middle"`, default is `"middle"`
+ - letter_spacing (number) #optional number in range `-1..1`, default is `0`
+ - line_spacing (number) #optional number in range `1..3`, default is `1`
+ = (object) resulting path element, which consist of all letters
+ > Usage
+ | var txt = r.print(10, 50, "print", r.getFont("Museo"), 30).attr({fill: "#fff"});
+ \*/
+ paperproto.print = function (x, y, string, font, size, origin, letter_spacing, line_spacing) {
+ origin = origin || "middle"; // baseline|middle
+ letter_spacing = mmax(mmin(letter_spacing || 0, 1), -1);
+ line_spacing = mmax(mmin(line_spacing || 1, 3), 1);
+ var letters = Str(string)[split](E),
+ shift = 0,
+ notfirst = 0,
+ path = E,
+ scale;
+ R.is(font, "string") && (font = this.getFont(font));
+ if (font) {
+ scale = (size || 16) / font.face["units-per-em"];
+ var bb = font.face.bbox[split](separator),
+ top = +bb[0],
+ lineHeight = bb[3] - bb[1],
+ shifty = 0,
+ height = +bb[1] + (origin == "baseline" ? lineHeight + (+font.face.descent) : lineHeight / 2);
+ for (var i = 0, ii = letters.length; i < ii; i++) {
+ if (letters[i] == "\n") {
+ shift = 0;
+ curr = 0;
+ notfirst = 0;
+ shifty += lineHeight * line_spacing;
+ } else {
+ var prev = notfirst && font.glyphs[letters[i - 1]] || {},
+ curr = font.glyphs[letters[i]];
+ shift += notfirst ? (prev.w || font.w) + (prev.k && prev.k[letters[i]] || 0) + (font.w * letter_spacing) : 0;
+ notfirst = 1;
+ }
+ if (curr && curr.d) {
+ path += R.transformPath(curr.d, ["t", shift * scale, shifty * scale, "s", scale, scale, top, height, "t", (x - top) / scale, (y - height) / scale]);
+ }
+ }
+ }
+ return this.path(path).attr({
+ fill: "#000",
+ stroke: "none"
+ });
+ };
+
+ /*\
+ * Paper.add
+ [ method ]
+ **
+ * Imports elements in JSON array in format `{type: type, <attributes>}`
+ **
+ > Parameters
+ **
+ - json (array)
+ = (object) resulting set of imported elements
+ > Usage
+ | paper.add([
+ | {
+ | type: "circle",
+ | cx: 10,
+ | cy: 10,
+ | r: 5
+ | },
+ | {
+ | type: "rect",
+ | x: 10,
+ | y: 10,
+ | width: 10,
+ | height: 10,
+ | fill: "#fc0"
+ | }
+ | ]);
+ \*/
+ paperproto.add = function (json) {
+ if (R.is(json, "array")) {
+ var res = this.set(),
+ i = 0,
+ ii = json.length,
+ j;
+ for (; i < ii; i++) {
+ j = json[i] || {};
+ elements[has](j.type) && res.push(this[j.type]().attr(j));
+ }
+ }
+ return res;
+ };
+
+ /*\
+ * Raphael.format
+ [ method ]
+ **
+ * Simple format function. Replaces construction of type “`{<number>}`” to the corresponding argument.
+ **
+ > Parameters
+ **
+ - token (string) string to format
+ - … (string) rest of arguments will be treated as parameters for replacement
+ = (string) formated string
+ > Usage
+ | var x = 10,
+ | y = 20,
+ | width = 40,
+ | height = 50;
+ | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z"
+ | paper.path(Raphael.format("M{0},{1}h{2}v{3}h{4}z", x, y, width, height, -width));
+ \*/
+ R.format = function (token, params) {
+ var args = R.is(params, array) ? [0][concat](params) : arguments;
+ token && R.is(token, string) && args.length - 1 && (token = token.replace(formatrg, function (str, i) {
+ return args[++i] == null ? E : args[i];
+ }));
+ return token || E;
+ };
+ /*\
+ * Raphael.fullfill
+ [ method ]
+ **
+ * A little bit more advanced format function than @Raphael.format. Replaces construction of type “`{<name>}`” to the corresponding argument.
+ **
+ > Parameters
+ **
+ - token (string) string to format
+ - json (object) object which properties will be used as a replacement
+ = (string) formated string
+ > Usage
+ | // this will draw a rectangular shape equivalent to "M10,20h40v50h-40z"
+ | paper.path(Raphael.fullfill("M{x},{y}h{dim.width}v{dim.height}h{dim['negative width']}z", {
+ | x: 10,
+ | y: 20,
+ | dim: {
+ | width: 40,
+ | height: 50,
+ | "negative width": -40
+ | }
+ | }));
+ \*/
+ R.fullfill = (function () {
+ var tokenRegex = /\{([^\}]+)\}/g,
+ objNotationRegex = /(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g, // matches .xxxxx or ["xxxxx"] to run over object properties
+ replacer = function (all, key, obj) {
+ var res = obj;
+ key.replace(objNotationRegex, function (all, name, quote, quotedName, isFunc) {
+ name = name || quotedName;
+ if (res) {
+ if (name in res) {
+ res = res[name];
+ }
+ typeof res == "function" && isFunc && (res = res());
+ }
+ });
+ res = (res == null || res == obj ? all : res) + "";
+ return res;
+ };
+ return function (str, obj) {
+ return String(str).replace(tokenRegex, function (all, key) {
+ return replacer(all, key, obj);
+ });
+ };
+ })();
+ /*\
+ * Raphael.ninja
+ [ method ]
+ **
+ * If you want to leave no trace of Raphaël (Well, Raphaël creates only one global variable `Raphael`, but anyway.) You can use `ninja` method.
+ * Beware, that in this case plugins could stop working, because they are depending on global variable existence.
+ **
+ = (object) Raphael object
+ > Usage
+ | (function (local_raphael) {
+ | var paper = local_raphael(10, 10, 320, 200);
+ | …
+ | })(Raphael.ninja());
+ \*/
+ R.ninja = function () {
+ if (oldRaphael.was) {
+ g.win.Raphael = oldRaphael.is;
+ } else {
+ // IE8 raises an error when deleting window property
+ window.Raphael = undefined;
+ try {
+ delete window.Raphael;
+ } catch(e) {}
+ }
+ return R;
+ };
+ /*\
+ * Raphael.st
+ [ property (object) ]
+ **
+ * You can add your own method to elements and sets. It is wise to add a set method for each element method
+ * you added, so you will be able to call the same method on sets too.
+ **
+ * See also @Raphael.el.
+ > Usage
+ | Raphael.el.red = function () {
+ | this.attr({fill: "#f00"});
+ | };
+ | Raphael.st.red = function () {
+ | this.forEach(function (el) {
+ | el.red();
+ | });
+ | };
+ | // then use it
+ | paper.set(paper.circle(100, 100, 20), paper.circle(110, 100, 20)).red();
+ \*/
+ R.st = setproto;
+
+ eve.on("raphael.DOMload", function () {
+ loaded = true;
+ });
+
+ // Firefox <3.6 fix: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
+ (function (doc, loaded, f) {
+ if (doc.readyState == null && doc.addEventListener){
+ doc.addEventListener(loaded, f = function () {
+ doc.removeEventListener(loaded, f, false);
+ doc.readyState = "complete";
+ }, false);
+ doc.readyState = "loading";
+ }
+ function isLoaded() {
+ (/in/).test(doc.readyState) ? setTimeout(isLoaded, 9) : R.eve("raphael.DOMload");
+ }
+ isLoaded();
+ })(document, "DOMContentLoaded");
+
+ return R;
+ }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+
+
+/***/ },
+/* 2 */
+/***/ function(module, exports) {
+
+ /*
+ * Eve 0.2.4 - JavaScript Events Library
+ *
+ * Copyright (c) 2011 Dmitry Baranovskiy (http://dmitry.baranovskiy.com/)
+ * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
+ */
+
+ (function (glob) {
+ var version = "0.2.4",
+ has = "hasOwnProperty",
+ separator = /[\.\/]/,
+ wildcard = "*",
+ fun = function () {},
+ numsort = function (a, b) {
+ return a - b;
+ },
+ current_event,
+ events = {n: {}},
+ /*\
+ * eve
+ [ method ]
+ **
+ * Fires event with given `name`, given scope and other parameters.
+ **
+ > Arguments
+ **
+ - name (string) name of the event, dot (`.`) or slash (`/`) separated
+ - scope (object) context for the event handlers
+ - varargs (...) the rest of arguments will be sent to event handlers
+ **
+ = (array) array of errors, if any. Each element of the array is in format:
+ o {
+ o error (string) error message
+ o func (function) handler that caused error
+ o }
+ \*/
+ eve = function (name, scope) {
+ var e = events,
+ args = Array.prototype.slice.call(arguments, 2),
+ listeners = eve.listeners(name),
+ z = 0,
+ f = false,
+ l,
+ indexed = [],
+ queue = {},
+ errors = [];
+ current_event = name;
+ for (var i = 0, ii = listeners.length; i < ii; i++) if ("zIndex" in listeners[i]) {
+ indexed.push(listeners[i].zIndex);
+ if (listeners[i].zIndex < 0) {
+ queue[listeners[i].zIndex] = listeners[i];
+ }
+ }
+ indexed.sort(numsort);
+ while (indexed[z] < 0) {
+ l = queue[indexed[z++]];
+ if (l.apply(scope, args) === f) {
+ return f;
+ }
+ }
+ for (i = 0; i < ii; i++) {
+ l = listeners[i];
+ if ("zIndex" in l) {
+ if (l.zIndex == indexed[z]) {
+ if (l.apply(scope, args) === f) {
+ return f;
+ }
+ do {
+ z++;
+ l = queue[indexed[z]];
+ if (l && l.apply(scope, args) === f) {
+ return f;
+ }
+ } while (l)
+ } else {
+ queue[l.zIndex] = l;
+ }
+ } else {
+ if (l.apply(scope, args) === f) {
+ return f;
+ }
+ }
+ }
+ };
+ /*\
+ * eve.listeners
+ [ method ]
+ **
+ * Internal method which gives you array of all event handlers that will be triggered by the given `name`.
+ **
+ > Arguments
+ **
+ - name (string) name of the event, dot (`.`) or slash (`/`) separated
+ **
+ = (array) array of event handlers
+ \*/
+ eve.listeners = function (name) {
+ var names = name.split(separator),
+ e = events,
+ item,
+ items,
+ k,
+ i,
+ ii,
+ j,
+ jj,
+ nes,
+ es = [e],
+ out = [];
+ for (i = 0, ii = names.length; i < ii; i++) {
+ nes = [];
+ for (j = 0, jj = es.length; j < jj; j++) {
+ e = es[j].n;
+ items = [e[names[i]], e[wildcard]];
+ k = 2;
+ while (k--) {
+ item = items[k];
+ if (item) {
+ nes.push(item);
+ out = out.concat(item.f || []);
+ }
+ }
+ }
+ es = nes;
+ }
+ return out;
+ };
+
+ /*\
+ * eve.on
+ [ method ]
+ **
+ * Binds given event handler with a given name. You can use wildcards “`*`” for the names:
+ | eve.on("*.under.*", f);
+ | eve("mouse.under.floor"); // triggers f
+ * Use @eve to trigger the listener.
+ **
+ > Arguments
+ **
+ - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
+ - f (function) event handler function
+ **
+ = (function) returned function accept one number parameter that represents z-index of the handler. It is optional feature and only used when you need to ensure that some subset of handlers will be invoked in a given order, despite of the order of assignment.
+ > Example:
+ | eve.on("mouse", eat)(2);
+ | eve.on("mouse", scream);
+ | eve.on("mouse", catch)(1);
+ * This will ensure that `catch` function will be called before `eat`.
+ * If you want to put you hadler before not indexed handlers specify negative value.
+ * Note: I assume most of the time you don’t need to worry about z-index, but it’s nice to have this feature “just in case”.
+ \*/
+ eve.on = function (name, f) {
+ var names = name.split(separator),
+ e = events;
+ for (var i = 0, ii = names.length; i < ii; i++) {
+ e = e.n;
+ !e[names[i]] && (e[names[i]] = {n: {}});
+ e = e[names[i]];
+ }
+ e.f = e.f || [];
+ for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
+ return fun;
+ }
+ e.f.push(f);
+ return function (zIndex) {
+ if (+zIndex == +zIndex) {
+ f.zIndex = +zIndex;
+ }
+ };
+ };
+ /*\
+ * eve.nt
+ [ method ]
+ **
+ * Could be used inside event handler to figure out actual name of the event.
+ **
+ > Arguments
+ **
+ - subname (string) #optional subname of the event
+ **
+ = (string) name of the event, if `subname` is not specified
+ * or
+ = (boolean) `true`, if current event’s name contains `subname`
+ \*/
+ eve.nt = function (subname) {
+ if (subname) {
+ return new RegExp("(?:\\.|\\/|^)" + subname + "(?:\\.|\\/|$)").test(current_event);
+ }
+ return current_event;
+ };
+ /*\
+ * eve.unbind
+ [ method ]
+ **
+ * Removes given function from the list of event listeners assigned to given name.
+ **
+ > Arguments
+ **
+ - name (string) name of the event, dot (`.`) or slash (`/`) separated, with optional wildcards
+ - f (function) event handler function
+ \*/
+ eve.unbind = function (name, f) {
+ var names = name.split(separator),
+ e,
+ key,
+ splice,
+ cur = [events];
+ for (var i = 0, ii = names.length; i < ii; i++) {
+ for (var j = 0; j < cur.length; j += splice.length - 2) {
+ splice = [j, 1];
+ e = cur[j].n;
+ if (names[i] != wildcard) {
+ if (e[names[i]]) {
+ splice.push(e[names[i]]);
+ }
+ } else {
+ for (key in e) if (e[has](key)) {
+ splice.push(e[key]);
+ }
+ }
+ cur.splice.apply(cur, splice);
+ }
+ }
+ for (i = 0, ii = cur.length; i < ii; i++) {
+ e = cur[i];
+ while (e.n) {
+ if (f) {
+ if (e.f) {
+ for (i = 0, ii = e.f.length; i < ii; i++) if (e.f[i] == f) {
+ e.f.splice(i, 1);
+ break;
+ }
+ !e.f.length && delete e.f;
+ }
+ for (key in e.n) if (e.n[has](key) && e.n[key].f) {
+ var funcs = e.n[key].f;
+ for (i = 0, ii = funcs.length; i < ii; i++) if (funcs[i] == f) {
+ funcs.splice(i, 1);
+ break;
+ }
+ !funcs.length && delete e.n[key].f;
+ }
+ } else {
+ delete e.f;
+ for (key in e.n) if (e.n[has](key) && e.n[key].f) {
+ delete e.n[key].f;
+ }
+ }
+ e = e.n;
+ }
+ }
+ };
+ /*\
+ * eve.version
+ [ property (string) ]
+ **
+ * Current version of the library.
+ \*/
+ eve.version = version;
+ eve.toString = function () {
+ return "You are running Eve " + version;
+ };
+ (typeof module != "undefined" && module.exports) ? (module.exports = eve) : (glob.eve = eve);
+ })(this);
+
+/***/ },
+/* 3 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
+ if (R && !R.svg) {
+ return;
+ }
+
+ var has = "hasOwnProperty",
+ Str = String,
+ toFloat = parseFloat,
+ toInt = parseInt,
+ math = Math,
+ mmax = math.max,
+ abs = math.abs,
+ pow = math.pow,
+ separator = /[, ]+/,
+ eve = R.eve,
+ E = "",
+ S = " ";
+ var xlink = "http://www.w3.org/1999/xlink",
+ markers = {
+ block: "M5,0 0,2.5 5,5z",
+ classic: "M5,0 0,2.5 5,5 3.5,3 3.5,2z",
+ diamond: "M2.5,0 5,2.5 2.5,5 0,2.5z",
+ open: "M6,1 1,3.5 6,6",
+ oval: "M2.5,0A2.5,2.5,0,0,1,2.5,5 2.5,2.5,0,0,1,2.5,0z"
+ },
+ markerCounter = {};
+ R.toString = function () {
+ return "Your browser supports SVG.\nYou are running Rapha\xebl " + this.version;
+ };
+ var $ = function (el, attr) {
+ if (attr) {
+ if (typeof el == "string") {
+ el = $(el);
+ }
+ for (var key in attr) if (attr[has](key)) {
+ if (key.substring(0, 6) == "xlink:") {
+ el.setAttributeNS(xlink, key.substring(6), Str(attr[key]));
+ } else {
+ el.setAttribute(key, Str(attr[key]));
+ }
+ }
+ } else {
+ el = R._g.doc.createElementNS("http://www.w3.org/2000/svg", el);
+ el.style && (el.style.webkitTapHighlightColor = "rgba(0,0,0,0)");
+ }
+ return el;
+ },
+ addGradientFill = function (element, gradient) {
+ var type = "linear",
+ id = element.id + gradient,
+ fx = .5, fy = .5,
+ o = element.node,
+ SVG = element.paper,
+ s = o.style,
+ el = R._g.doc.getElementById(id);
+ if (!el) {
+ gradient = Str(gradient).replace(R._radial_gradient, function (all, _fx, _fy) {
+ type = "radial";
+ if (_fx && _fy) {
+ fx = toFloat(_fx);
+ fy = toFloat(_fy);
+ var dir = ((fy > .5) * 2 - 1);
+ pow(fx - .5, 2) + pow(fy - .5, 2) > .25 &&
+ (fy = math.sqrt(.25 - pow(fx - .5, 2)) * dir + .5) &&
+ fy != .5 &&
+ (fy = fy.toFixed(5) - 1e-5 * dir);
+ }
+ return E;
+ });
+ gradient = gradient.split(/\s*\-\s*/);
+ if (type == "linear") {
+ var angle = gradient.shift();
+ angle = -toFloat(angle);
+ if (isNaN(angle)) {
+ return null;
+ }
+ var vector = [0, 0, math.cos(R.rad(angle)), math.sin(R.rad(angle))],
+ max = 1 / (mmax(abs(vector[2]), abs(vector[3])) || 1);
+ vector[2] *= max;
+ vector[3] *= max;
+ if (vector[2] < 0) {
+ vector[0] = -vector[2];
+ vector[2] = 0;
+ }
+ if (vector[3] < 0) {
+ vector[1] = -vector[3];
+ vector[3] = 0;
+ }
+ }
+ var dots = R._parseDots(gradient);
+ if (!dots) {
+ return null;
+ }
+ id = id.replace(/[\(\)\s,\xb0#]/g, "_");
+
+ if (element.gradient && id != element.gradient.id) {
+ SVG.defs.removeChild(element.gradient);
+ delete element.gradient;
+ }
+
+ if (!element.gradient) {
+ el = $(type + "Gradient", {id: id});
+ element.gradient = el;
+ $(el, type == "radial" ? {
+ fx: fx,
+ fy: fy
+ } : {
+ x1: vector[0],
+ y1: vector[1],
+ x2: vector[2],
+ y2: vector[3],
+ gradientTransform: element.matrix.invert()
+ });
+ SVG.defs.appendChild(el);
+ for (var i = 0, ii = dots.length; i < ii; i++) {
+ el.appendChild($("stop", {
+ offset: dots[i].offset ? dots[i].offset : i ? "100%" : "0%",
+ "stop-color": dots[i].color || "#fff",
+ "stop-opacity": isFinite(dots[i].opacity) ? dots[i].opacity : 1
+ }));
+ }
+ }
+ }
+ $(o, {
+ fill: fillurl(id),
+ opacity: 1,
+ "fill-opacity": 1
+ });
+ s.fill = E;
+ s.opacity = 1;
+ s.fillOpacity = 1;
+ return 1;
+ },
+ isIE9or10 = function () {
+ var mode = document.documentMode;
+ return mode && (mode === 9 || mode === 10);
+ },
+ fillurl = function (id) {
+ if (isIE9or10()) {
+ return "url('#" + id + "')";
+ }
+ var location = document.location;
+ var locationString = (
+ location.protocol + '//' +
+ location.host +
+ location.pathname +
+ location.search
+ );
+ return "url('" + locationString + "#" + id + "')";
+ },
+ updatePosition = function (o) {
+ var bbox = o.getBBox(1);
+ $(o.pattern, {patternTransform: o.matrix.invert() + " translate(" + bbox.x + "," + bbox.y + ")"});
+ },
+ addArrow = function (o, value, isEnd) {
+ if (o.type == "path") {
+ var values = Str(value).toLowerCase().split("-"),
+ p = o.paper,
+ se = isEnd ? "end" : "start",
+ node = o.node,
+ attrs = o.attrs,
+ stroke = attrs["stroke-width"],
+ i = values.length,
+ type = "classic",
+ from,
+ to,
+ dx,
+ refX,
+ attr,
+ w = 3,
+ h = 3,
+ t = 5;
+ while (i--) {
+ switch (values[i]) {
+ case "block":
+ case "classic":
+ case "oval":
+ case "diamond":
+ case "open":
+ case "none":
+ type = values[i];
+ break;
+ case "wide": h = 5; break;
+ case "narrow": h = 2; break;
+ case "long": w = 5; break;
+ case "short": w = 2; break;
+ }
+ }
+ if (type == "open") {
+ w += 2;
+ h += 2;
+ t += 2;
+ dx = 1;
+ refX = isEnd ? 4 : 1;
+ attr = {
+ fill: "none",
+ stroke: attrs.stroke
+ };
+ } else {
+ refX = dx = w / 2;
+ attr = {
+ fill: attrs.stroke,
+ stroke: "none"
+ };
+ }
+ if (o._.arrows) {
+ if (isEnd) {
+ o._.arrows.endPath && markerCounter[o._.arrows.endPath]--;
+ o._.arrows.endMarker && markerCounter[o._.arrows.endMarker]--;
+ } else {
+ o._.arrows.startPath && markerCounter[o._.arrows.startPath]--;
+ o._.arrows.startMarker && markerCounter[o._.arrows.startMarker]--;
+ }
+ } else {
+ o._.arrows = {};
+ }
+ if (type != "none") {
+ var pathId = "raphael-marker-" + type,
+ markerId = "raphael-marker-" + se + type + w + h + "-obj" + o.id;
+ if (!R._g.doc.getElementById(pathId)) {
+ p.defs.appendChild($($("path"), {
+ "stroke-linecap": "round",
+ d: markers[type],
+ id: pathId
+ }));
+ markerCounter[pathId] = 1;
+ } else {
+ markerCounter[pathId]++;
+ }
+ var marker = R._g.doc.getElementById(markerId),
+ use;
+ if (!marker) {
+ marker = $($("marker"), {
+ id: markerId,
+ markerHeight: h,
+ markerWidth: w,
+ orient: "auto",
+ refX: refX,
+ refY: h / 2
+ });
+ use = $($("use"), {
+ "xlink:href": "#" + pathId,
+ transform: (isEnd ? "rotate(180 " + w / 2 + " " + h / 2 + ") " : E) + "scale(" + w / t + "," + h / t + ")",
+ "stroke-width": (1 / ((w / t + h / t) / 2)).toFixed(4)
+ });
+ marker.appendChild(use);
+ p.defs.appendChild(marker);
+ markerCounter[markerId] = 1;
+ } else {
+ markerCounter[markerId]++;
+ use = marker.getElementsByTagName("use")[0];
+ }
+ $(use, attr);
+ var delta = dx * (type != "diamond" && type != "oval");
+ if (isEnd) {
+ from = o._.arrows.startdx * stroke || 0;
+ to = R.getTotalLength(attrs.path) - delta * stroke;
+ } else {
+ from = delta * stroke;
+ to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
+ }
+ attr = {};
+ attr["marker-" + se] = "url(#" + markerId + ")";
+ if (to || from) {
+ attr.d = R.getSubpath(attrs.path, from, to);
+ }
+ $(node, attr);
+ o._.arrows[se + "Path"] = pathId;
+ o._.arrows[se + "Marker"] = markerId;
+ o._.arrows[se + "dx"] = delta;
+ o._.arrows[se + "Type"] = type;
+ o._.arrows[se + "String"] = value;
+ } else {
+ if (isEnd) {
+ from = o._.arrows.startdx * stroke || 0;
+ to = R.getTotalLength(attrs.path) - from;
+ } else {
+ from = 0;
+ to = R.getTotalLength(attrs.path) - (o._.arrows.enddx * stroke || 0);
+ }
+ o._.arrows[se + "Path"] && $(node, {d: R.getSubpath(attrs.path, from, to)});
+ delete o._.arrows[se + "Path"];
+ delete o._.arrows[se + "Marker"];
+ delete o._.arrows[se + "dx"];
+ delete o._.arrows[se + "Type"];
+ delete o._.arrows[se + "String"];
+ }
+ for (attr in markerCounter) if (markerCounter[has](attr) && !markerCounter[attr]) {
+ var item = R._g.doc.getElementById(attr);
+ item && item.parentNode.removeChild(item);
+ }
+ }
+ },
+ dasharray = {
+ "-": [3, 1],
+ ".": [1, 1],
+ "-.": [3, 1, 1, 1],
+ "-..": [3, 1, 1, 1, 1, 1],
+ ". ": [1, 3],
+ "- ": [4, 3],
+ "--": [8, 3],
+ "- .": [4, 3, 1, 3],
+ "--.": [8, 3, 1, 3],
+ "--..": [8, 3, 1, 3, 1, 3]
+ },
+ addDashes = function (o, value, params) {
+ value = dasharray[Str(value).toLowerCase()];
+ if (value) {
+ var width = o.attrs["stroke-width"] || "1",
+ butt = {round: width, square: width, butt: 0}[o.attrs["stroke-linecap"] || params["stroke-linecap"]] || 0,
+ dashes = [],
+ i = value.length;
+ while (i--) {
+ dashes[i] = value[i] * width + ((i % 2) ? 1 : -1) * butt;
+ }
+ $(o.node, {"stroke-dasharray": dashes.join(",")});
+ }
+ else {
+ $(o.node, {"stroke-dasharray": "none"});
+ }
+ },
+ setFillAndStroke = function (o, params) {
+ var node = o.node,
+ attrs = o.attrs,
+ vis = node.style.visibility;
+ node.style.visibility = "hidden";
+ for (var att in params) {
+ if (params[has](att)) {
+ if (!R._availableAttrs[has](att)) {
+ continue;
+ }
+ var value = params[att];
+ attrs[att] = value;
+ switch (att) {
+ case "blur":
+ o.blur(value);
+ break;
+ case "title":
+ var title = node.getElementsByTagName("title");
+
+ // Use the existing <title>.
+ if (title.length && (title = title[0])) {
+ title.firstChild.nodeValue = value;
+ } else {
+ title = $("title");
+ var val = R._g.doc.createTextNode(value);
+ title.appendChild(val);
+ node.appendChild(title);
+ }
+ break;
+ case "href":
+ case "target":
+ var pn = node.parentNode;
+ if (pn.tagName.toLowerCase() != "a") {
+ var hl = $("a");
+ pn.insertBefore(hl, node);
+ hl.appendChild(node);
+ pn = hl;
+ }
+ if (att == "target") {
+ pn.setAttributeNS(xlink, "show", value == "blank" ? "new" : value);
+ } else {
+ pn.setAttributeNS(xlink, att, value);
+ }
+ break;
+ case "cursor":
+ node.style.cursor = value;
+ break;
+ case "transform":
+ o.transform(value);
+ break;
+ case "arrow-start":
+ addArrow(o, value);
+ break;
+ case "arrow-end":
+ addArrow(o, value, 1);
+ break;
+ case "clip-rect":
+ var rect = Str(value).split(separator);
+ if (rect.length == 4) {
+ o.clip && o.clip.parentNode.parentNode.removeChild(o.clip.parentNode);
+ var el = $("clipPath"),
+ rc = $("rect");
+ el.id = R.createUUID();
+ $(rc, {
+ x: rect[0],
+ y: rect[1],
+ width: rect[2],
+ height: rect[3]
+ });
+ el.appendChild(rc);
+ o.paper.defs.appendChild(el);
+ $(node, {"clip-path": "url(#" + el.id + ")"});
+ o.clip = rc;
+ }
+ if (!value) {
+ var path = node.getAttribute("clip-path");
+ if (path) {
+ var clip = R._g.doc.getElementById(path.replace(/(^url\(#|\)$)/g, E));
+ clip && clip.parentNode.removeChild(clip);
+ $(node, {"clip-path": E});
+ delete o.clip;
+ }
+ }
+ break;
+ case "path":
+ if (o.type == "path") {
+ $(node, {d: value ? attrs.path = R._pathToAbsolute(value) : "M0,0"});
+ o._.dirty = 1;
+ if (o._.arrows) {
+ "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
+ "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
+ }
+ }
+ break;
+ case "width":
+ node.setAttribute(att, value);
+ o._.dirty = 1;
+ if (attrs.fx) {
+ att = "x";
+ value = attrs.x;
+ } else {
+ break;
+ }
+ case "x":
+ if (attrs.fx) {
+ value = -attrs.x - (attrs.width || 0);
+ }
+ case "rx":
+ if (att == "rx" && o.type == "rect") {
+ break;
+ }
+ case "cx":
+ node.setAttribute(att, value);
+ o.pattern && updatePosition(o);
+ o._.dirty = 1;
+ break;
+ case "height":
+ node.setAttribute(att, value);
+ o._.dirty = 1;
+ if (attrs.fy) {
+ att = "y";
+ value = attrs.y;
+ } else {
+ break;
+ }
+ case "y":
+ if (attrs.fy) {
+ value = -attrs.y - (attrs.height || 0);
+ }
+ case "ry":
+ if (att == "ry" && o.type == "rect") {
+ break;
+ }
+ case "cy":
+ node.setAttribute(att, value);
+ o.pattern && updatePosition(o);
+ o._.dirty = 1;
+ break;
+ case "r":
+ if (o.type == "rect") {
+ $(node, {rx: value, ry: value});
+ } else {
+ node.setAttribute(att, value);
+ }
+ o._.dirty = 1;
+ break;
+ case "src":
+ if (o.type == "image") {
+ node.setAttributeNS(xlink, "href", value);
+ }
+ break;
+ case "stroke-width":
+ if (o._.sx != 1 || o._.sy != 1) {
+ value /= mmax(abs(o._.sx), abs(o._.sy)) || 1;
+ }
+ node.setAttribute(att, value);
+ if (attrs["stroke-dasharray"]) {
+ addDashes(o, attrs["stroke-dasharray"], params);
+ }
+ if (o._.arrows) {
+ "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
+ "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
+ }
+ break;
+ case "stroke-dasharray":
+ addDashes(o, value, params);
+ break;
+ case "fill":
+ var isURL = Str(value).match(R._ISURL);
+ if (isURL) {
+ el = $("pattern");
+ var ig = $("image");
+ el.id = R.createUUID();
+ $(el, {x: 0, y: 0, patternUnits: "userSpaceOnUse", height: 1, width: 1});
+ $(ig, {x: 0, y: 0, "xlink:href": isURL[1]});
+ el.appendChild(ig);
+
+ (function (el) {
+ R._preload(isURL[1], function () {
+ var w = this.offsetWidth,
+ h = this.offsetHeight;
+ $(el, {width: w, height: h});
+ $(ig, {width: w, height: h});
+ });
+ })(el);
+ o.paper.defs.appendChild(el);
+ $(node, {fill: "url(#" + el.id + ")"});
+ o.pattern = el;
+ o.pattern && updatePosition(o);
+ break;
+ }
+ var clr = R.getRGB(value);
+ if (!clr.error) {
+ delete params.gradient;
+ delete attrs.gradient;
+ !R.is(attrs.opacity, "undefined") &&
+ R.is(params.opacity, "undefined") &&
+ $(node, {opacity: attrs.opacity});
+ !R.is(attrs["fill-opacity"], "undefined") &&
+ R.is(params["fill-opacity"], "undefined") &&
+ $(node, {"fill-opacity": attrs["fill-opacity"]});
+ } else if ((o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value)) {
+ if ("opacity" in attrs || "fill-opacity" in attrs) {
+ var gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
+ if (gradient) {
+ var stops = gradient.getElementsByTagName("stop");
+ $(stops[stops.length - 1], {"stop-opacity": ("opacity" in attrs ? attrs.opacity : 1) * ("fill-opacity" in attrs ? attrs["fill-opacity"] : 1)});
+ }
+ }
+ attrs.gradient = value;
+ attrs.fill = "none";
+ break;
+ }
+ clr[has]("opacity") && $(node, {"fill-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
+ case "stroke":
+ clr = R.getRGB(value);
+ node.setAttribute(att, clr.hex);
+ att == "stroke" && clr[has]("opacity") && $(node, {"stroke-opacity": clr.opacity > 1 ? clr.opacity / 100 : clr.opacity});
+ if (att == "stroke" && o._.arrows) {
+ "startString" in o._.arrows && addArrow(o, o._.arrows.startString);
+ "endString" in o._.arrows && addArrow(o, o._.arrows.endString, 1);
+ }
+ break;
+ case "gradient":
+ (o.type == "circle" || o.type == "ellipse" || Str(value).charAt() != "r") && addGradientFill(o, value);
+ break;
+ case "opacity":
+ if (attrs.gradient && !attrs[has]("stroke-opacity")) {
+ $(node, {"stroke-opacity": value > 1 ? value / 100 : value});
+ }
+ // fall
+ case "fill-opacity":
+ if (attrs.gradient) {
+ gradient = R._g.doc.getElementById(node.getAttribute("fill").replace(/^url\(#|\)$/g, E));
+ if (gradient) {
+ stops = gradient.getElementsByTagName("stop");
+ $(stops[stops.length - 1], {"stop-opacity": value});
+ }
+ break;
+ }
+ default:
+ att == "font-size" && (value = toInt(value, 10) + "px");
+ var cssrule = att.replace(/(\-.)/g, function (w) {
+ return w.substring(1).toUpperCase();
+ });
+ node.style[cssrule] = value;
+ o._.dirty = 1;
+ node.setAttribute(att, value);
+ break;
+ }
+ }
+ }
+
+ tuneText(o, params);
+ node.style.visibility = vis;
+ },
+ leading = 1.2,
+ tuneText = function (el, params) {
+ if (el.type != "text" || !(params[has]("text") || params[has]("font") || params[has]("font-size") || params[has]("x") || params[has]("y"))) {
+ return;
+ }
+ var a = el.attrs,
+ node = el.node,
+ fontSize = node.firstChild ? toInt(R._g.doc.defaultView.getComputedStyle(node.firstChild, E).getPropertyValue("font-size"), 10) : 10;
+
+ if (params[has]("text")) {
+ a.text = params.text;
+ while (node.firstChild) {
+ node.removeChild(node.firstChild);
+ }
+ var texts = Str(params.text).split("\n"),
+ tspans = [],
+ tspan;
+ for (var i = 0, ii = texts.length; i < ii; i++) {
+ tspan = $("tspan");
+ i && $(tspan, {dy: fontSize * leading, x: a.x});
+ tspan.appendChild(R._g.doc.createTextNode(texts[i]));
+ node.appendChild(tspan);
+ tspans[i] = tspan;
+ }
+ } else {
+ tspans = node.getElementsByTagName("tspan");
+ for (i = 0, ii = tspans.length; i < ii; i++) if (i) {
+ $(tspans[i], {dy: fontSize * leading, x: a.x});
+ } else {
+ $(tspans[0], {dy: 0});
+ }
+ }
+ $(node, {x: a.x, y: a.y});
+ el._.dirty = 1;
+ var bb = el._getBBox(),
+ dif = a.y - (bb.y + bb.height / 2);
+ dif && R.is(dif, "finite") && $(tspans[0], {dy: dif});
+ },
+ getRealNode = function (node) {
+ if (node.parentNode && node.parentNode.tagName.toLowerCase() === "a") {
+ return node.parentNode;
+ } else {
+ return node;
+ }
+ },
+ Element = function (node, svg) {
+ var X = 0,
+ Y = 0;
+ /*\
+ * Element.node
+ [ property (object) ]
+ **
+ * Gives you a reference to the DOM object, so you can assign event handlers or just mess around.
+ **
+ * Note: Don’t mess with it.
+ > Usage
+ | // draw a circle at coordinate 10,10 with radius of 10
+ | var c = paper.circle(10, 10, 10);
+ | c.node.onclick = function () {
+ | c.attr("fill", "red");
+ | };
+ \*/
+ this[0] = this.node = node;
+ /*\
+ * Element.raphael
+ [ property (object) ]
+ **
+ * Internal reference to @Raphael object. In case it is not available.
+ > Usage
+ | Raphael.el.red = function () {
+ | var hsb = this.paper.raphael.rgb2hsb(this.attr("fill"));
+ | hsb.h = 1;
+ | this.attr({fill: this.paper.raphael.hsb2rgb(hsb).hex});
+ | }
+ \*/
+ node.raphael = true;
+ /*\
+ * Element.id
+ [ property (number) ]
+ **
+ * Unique id of the element. Especially useful when you want to listen to events of the element,
+ * because all events are fired in format `<module>.<action>.<id>`. Also useful for @Paper.getById method.
+ \*/
+ this.id = guid();
+ node.raphaelid = this.id;
+
+ /**
+ * Method that returns a 5 letter/digit id, enough for 36^5 = 60466176 elements
+ * @returns {string} id
+ */
+ function guid() {
+ return ("0000" + (Math.random()*Math.pow(36,5) << 0).toString(36)).slice(-5);
+ }
+
+ this.matrix = R.matrix();
+ this.realPath = null;
+ /*\
+ * Element.paper
+ [ property (object) ]
+ **
+ * Internal reference to “paper” where object drawn. Mainly for use in plugins and element extensions.
+ > Usage
+ | Raphael.el.cross = function () {
+ | this.attr({fill: "red"});
+ | this.paper.path("M10,10L50,50M50,10L10,50")
+ | .attr({stroke: "red"});
+ | }
+ \*/
+ this.paper = svg;
+ this.attrs = this.attrs || {};
+ this._ = {
+ transform: [],
+ sx: 1,
+ sy: 1,
+ deg: 0,
+ dx: 0,
+ dy: 0,
+ dirty: 1
+ };
+ !svg.bottom && (svg.bottom = this);
+ /*\
+ * Element.prev
+ [ property (object) ]
+ **
+ * Reference to the previous element in the hierarchy.
+ \*/
+ this.prev = svg.top;
+ svg.top && (svg.top.next = this);
+ svg.top = this;
+ /*\
+ * Element.next
+ [ property (object) ]
+ **
+ * Reference to the next element in the hierarchy.
+ \*/
+ this.next = null;
+ },
+ elproto = R.el;
+
+ Element.prototype = elproto;
+ elproto.constructor = Element;
+
+ R._engine.path = function (pathString, SVG) {
+ var el = $("path");
+ SVG.canvas && SVG.canvas.appendChild(el);
+ var p = new Element(el, SVG);
+ p.type = "path";
+ setFillAndStroke(p, {
+ fill: "none",
+ stroke: "#000",
+ path: pathString
+ });
+ return p;
+ };
+ /*\
+ * Element.rotate
+ [ method ]
+ **
+ * Deprecated! Use @Element.transform instead.
+ * Adds rotation by given angle around given point to the list of
+ * transformations of the element.
+ > Parameters
+ - deg (number) angle in degrees
+ - cx (number) #optional x coordinate of the centre of rotation
+ - cy (number) #optional y coordinate of the centre of rotation
+ * If cx & cy aren’t specified centre of the shape is used as a point of rotation.
+ = (object) @Element
+ \*/
+ elproto.rotate = function (deg, cx, cy) {
+ if (this.removed) {
+ return this;
+ }
+ deg = Str(deg).split(separator);
+ if (deg.length - 1) {
+ cx = toFloat(deg[1]);
+ cy = toFloat(deg[2]);
+ }
+ deg = toFloat(deg[0]);
+ (cy == null) && (cx = cy);
+ if (cx == null || cy == null) {
+ var bbox = this.getBBox(1);
+ cx = bbox.x + bbox.width / 2;
+ cy = bbox.y + bbox.height / 2;
+ }
+ this.transform(this._.transform.concat([["r", deg, cx, cy]]));
+ return this;
+ };
+ /*\
+ * Element.scale
+ [ method ]
+ **
+ * Deprecated! Use @Element.transform instead.
+ * Adds scale by given amount relative to given point to the list of
+ * transformations of the element.
+ > Parameters
+ - sx (number) horisontal scale amount
+ - sy (number) vertical scale amount
+ - cx (number) #optional x coordinate of the centre of scale
+ - cy (number) #optional y coordinate of the centre of scale
+ * If cx & cy aren’t specified centre of the shape is used instead.
+ = (object) @Element
+ \*/
+ elproto.scale = function (sx, sy, cx, cy) {
+ if (this.removed) {
+ return this;
+ }
+ sx = Str(sx).split(separator);
+ if (sx.length - 1) {
+ sy = toFloat(sx[1]);
+ cx = toFloat(sx[2]);
+ cy = toFloat(sx[3]);
+ }
+ sx = toFloat(sx[0]);
+ (sy == null) && (sy = sx);
+ (cy == null) && (cx = cy);
+ if (cx == null || cy == null) {
+ var bbox = this.getBBox(1);
+ }
+ cx = cx == null ? bbox.x + bbox.width / 2 : cx;
+ cy = cy == null ? bbox.y + bbox.height / 2 : cy;
+ this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
+ return this;
+ };
+ /*\
+ * Element.translate
+ [ method ]
+ **
+ * Deprecated! Use @Element.transform instead.
+ * Adds translation by given amount to the list of transformations of the element.
+ > Parameters
+ - dx (number) horisontal shift
+ - dy (number) vertical shift
+ = (object) @Element
+ \*/
+ elproto.translate = function (dx, dy) {
+ if (this.removed) {
+ return this;
+ }
+ dx = Str(dx).split(separator);
+ if (dx.length - 1) {
+ dy = toFloat(dx[1]);
+ }
+ dx = toFloat(dx[0]) || 0;
+ dy = +dy || 0;
+ this.transform(this._.transform.concat([["t", dx, dy]]));
+ return this;
+ };
+ /*\
+ * Element.transform
+ [ method ]
+ **
+ * Adds transformation to the element which is separate to other attributes,
+ * i.e. translation doesn’t change `x` or `y` of the rectange. The format
+ * of transformation string is similar to the path string syntax:
+ | "t100,100r30,100,100s2,2,100,100r45s1.5"
+ * Each letter is a command. There are four commands: `t` is for translate, `r` is for rotate, `s` is for
+ * scale and `m` is for matrix.
+ *
+ * There are also alternative “absolute” translation, rotation and scale: `T`, `R` and `S`. They will not take previous transformation into account. For example, `...T100,0` will always move element 100 px horisontally, while `...t100,0` could move it vertically if there is `r90` before. Just compare results of `r90t100,0` and `r90T100,0`.
+ *
+ * So, the example line above could be read like “translate by 100, 100; rotate 30° around 100, 100; scale twice around 100, 100;
+ * rotate 45° around centre; scale 1.5 times relative to centre”. As you can see rotate and scale commands have origin
+ * coordinates as optional parameters, the default is the centre point of the element.
+ * Matrix accepts six parameters.
+ > Usage
+ | var el = paper.rect(10, 20, 300, 200);
+ | // translate 100, 100, rotate 45°, translate -100, 0
+ | el.transform("t100,100r45t-100,0");
+ | // if you want you can append or prepend transformations
+ | el.transform("...t50,50");
+ | el.transform("s2...");
+ | // or even wrap
+ | el.transform("t50,50...t-50-50");
+ | // to reset transformation call method with empty string
+ | el.transform("");
+ | // to get current value call it without parameters
+ | console.log(el.transform());
+ > Parameters
+ - tstr (string) #optional transformation string
+ * If tstr isn’t specified
+ = (string) current transformation string
+ * else
+ = (object) @Element
+ \*/
+ elproto.transform = function (tstr) {
+ var _ = this._;
+ if (tstr == null) {
+ return _.transform;
+ }
+ R._extractTransform(this, tstr);
+
+ this.clip && $(this.clip, {transform: this.matrix.invert()});
+ this.pattern && updatePosition(this);
+ this.node && $(this.node, {transform: this.matrix});
+
+ if (_.sx != 1 || _.sy != 1) {
+ var sw = this.attrs[has]("stroke-width") ? this.attrs["stroke-width"] : 1;
+ this.attr({"stroke-width": sw});
+ }
+
+ return this;
+ };
+ /*\
+ * Element.hide
+ [ method ]
+ **
+ * Makes element invisible. See @Element.show.
+ = (object) @Element
+ \*/
+ elproto.hide = function () {
+ if(!this.removed) this.node.style.display = "none";
+ return this;
+ };
+ /*\
+ * Element.show
+ [ method ]
+ **
+ * Makes element visible. See @Element.hide.
+ = (object) @Element
+ \*/
+ elproto.show = function () {
+ if(!this.removed) this.node.style.display = "";
+ return this;
+ };
+ /*\
+ * Element.remove
+ [ method ]
+ **
+ * Removes element from the paper.
+ \*/
+ elproto.remove = function () {
+ var node = getRealNode(this.node);
+ if (this.removed || !node.parentNode) {
+ return;
+ }
+ var paper = this.paper;
+ paper.__set__ && paper.__set__.exclude(this);
+ eve.unbind("raphael.*.*." + this.id);
+ if (this.gradient) {
+ paper.defs.removeChild(this.gradient);
+ }
+ R._tear(this, paper);
+
+ node.parentNode.removeChild(node);
+
+ // Remove custom data for element
+ this.removeData();
+
+ for (var i in this) {
+ this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
+ }
+ this.removed = true;
+ };
+ elproto._getBBox = function () {
+ if (this.node.style.display == "none") {
+ this.show();
+ var hide = true;
+ }
+ var canvasHidden = false,
+ containerStyle;
+ if (this.paper.canvas.parentElement) {
+ containerStyle = this.paper.canvas.parentElement.style;
+ } //IE10+ can't find parentElement
+ else if (this.paper.canvas.parentNode) {
+ containerStyle = this.paper.canvas.parentNode.style;
+ }
+
+ if(containerStyle && containerStyle.display == "none") {
+ canvasHidden = true;
+ containerStyle.display = "";
+ }
+ var bbox = {};
+ try {
+ bbox = this.node.getBBox();
+ } catch(e) {
+ // Firefox 3.0.x, 25.0.1 (probably more versions affected) play badly here - possible fix
+ bbox = {
+ x: this.node.clientLeft,
+ y: this.node.clientTop,
+ width: this.node.clientWidth,
+ height: this.node.clientHeight
+ }
+ } finally {
+ bbox = bbox || {};
+ if(canvasHidden){
+ containerStyle.display = "none";
+ }
+ }
+ hide && this.hide();
+ return bbox;
+ };
+ /*\
+ * Element.attr
+ [ method ]
+ **
+ * Sets the attributes of the element.
+ > Parameters
+ - attrName (string) attribute’s name
+ - value (string) value
+ * or
+ - params (object) object of name/value pairs
+ * or
+ - attrName (string) attribute’s name
+ * or
+ - attrNames (array) in this case method returns array of current values for given attribute names
+ = (object) @Element if attrsName & value or params are passed in.
+ = (...) value of the attribute if only attrsName is passed in.
+ = (array) array of values of the attribute if attrsNames is passed in.
+ = (object) object of attributes if nothing is passed in.
+ > Possible parameters
+ # <p>Please refer to the <a href="http://www.w3.org/TR/SVG/" title="The W3C Recommendation for the SVG language describes these properties in detail.">SVG specification</a> for an explanation of these parameters.</p>
+ o arrow-end (string) arrowhead on the end of the path. The format for string is `<type>[-<width>[-<length>]]`. Possible types: `classic`, `block`, `open`, `oval`, `diamond`, `none`, width: `wide`, `narrow`, `medium`, length: `long`, `short`, `midium`.
+ o clip-rect (string) comma or space separated values: x, y, width and height
+ o cursor (string) CSS type of the cursor
+ o cx (number) the x-axis coordinate of the center of the circle, or ellipse
+ o cy (number) the y-axis coordinate of the center of the circle, or ellipse
+ o fill (string) colour, gradient or image
+ o fill-opacity (number)
+ o font (string)
+ o font-family (string)
+ o font-size (number) font size in pixels
+ o font-weight (string)
+ o height (number)
+ o href (string) URL, if specified element behaves as hyperlink
+ o opacity (number)
+ o path (string) SVG path string format
+ o r (number) radius of the circle, ellipse or rounded corner on the rect
+ o rx (number) horisontal radius of the ellipse
+ o ry (number) vertical radius of the ellipse
+ o src (string) image URL, only works for @Element.image element
+ o stroke (string) stroke colour
+ o stroke-dasharray (string) [“”, “none”, “`-`”, “`.`”, “`-.`”, “`-..`”, “`. `”, “`- `”, “`--`”, “`- .`”, “`--.`”, “`--..`”]
+ o stroke-linecap (string) [“`butt`”, “`square`”, “`round`”]
+ o stroke-linejoin (string) [“`bevel`”, “`round`”, “`miter`”]
+ o stroke-miterlimit (number)
+ o stroke-opacity (number)
+ o stroke-width (number) stroke width in pixels, default is '1'
+ o target (string) used with href
+ o text (string) contents of the text element. Use `\n` for multiline text
+ o text-anchor (string) [“`start`”, “`middle`”, “`end`”], default is “`middle`”
+ o title (string) will create tooltip with a given text
+ o transform (string) see @Element.transform
+ o width (number)
+ o x (number)
+ o y (number)
+ > Gradients
+ * Linear gradient format: “`‹angle›-‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`90-#fff-#000`” – 90°
+ * gradient from white to black or “`0-#fff-#f00:20-#000`” – 0° gradient from white via red (at 20%) to black.
+ *
+ * radial gradient: “`r[(‹fx›, ‹fy›)]‹colour›[-‹colour›[:‹offset›]]*-‹colour›`”, example: “`r#fff-#000`” –
+ * gradient from white to black or “`r(0.25, 0.75)#fff-#000`” – gradient from white to black with focus point
+ * at 0.25, 0.75. Focus point coordinates are in 0..1 range. Radial gradients can only be applied to circles and ellipses.
+ > Path String
+ # <p>Please refer to <a href="http://www.w3.org/TR/SVG/paths.html#PathData" title="Details of a path’s data attribute’s format are described in the SVG specification.">SVG documentation regarding path string</a>. Raphaël fully supports it.</p>
+ > Colour Parsing
+ # <ul>
+ # <li>Colour name (“<code>red</code>”, “<code>green</code>”, “<code>cornflowerblue</code>”, etc)</li>
+ # <li>#••• — shortened HTML colour: (“<code>#000</code>”, “<code>#fc0</code>”, etc)</li>
+ # <li>#•••••• — full length HTML colour: (“<code>#000000</code>”, “<code>#bd2300</code>”)</li>
+ # <li>rgb(•••, •••, •••) — red, green and blue channels’ values: (“<code>rgb(200,&nbsp;100,&nbsp;0)</code>”)</li>
+ # <li>rgb(•••%, •••%, •••%) — same as above, but in %: (“<code>rgb(100%,&nbsp;175%,&nbsp;0%)</code>”)</li>
+ # <li>rgba(•••, •••, •••, •••) — red, green and blue channels’ values: (“<code>rgba(200,&nbsp;100,&nbsp;0, .5)</code>”)</li>
+ # <li>rgba(•••%, •••%, •••%, •••%) — same as above, but in %: (“<code>rgba(100%,&nbsp;175%,&nbsp;0%, 50%)</code>”)</li>
+ # <li>hsb(•••, •••, •••) — hue, saturation and brightness values: (“<code>hsb(0.5,&nbsp;0.25,&nbsp;1)</code>”)</li>
+ # <li>hsb(•••%, •••%, •••%) — same as above, but in %</li>
+ # <li>hsba(•••, •••, •••, •••) — same as above, but with opacity</li>
+ # <li>hsl(•••, •••, •••) — almost the same as hsb, see <a href="http://en.wikipedia.org/wiki/HSL_and_HSV" title="HSL and HSV - Wikipedia, the free encyclopedia">Wikipedia page</a></li>
+ # <li>hsl(•••%, •••%, •••%) — same as above, but in %</li>
+ # <li>hsla(•••, •••, •••, •••) — same as above, but with opacity</li>
+ # <li>Optionally for hsb and hsl you could specify hue as a degree: “<code>hsl(240deg,&nbsp;1,&nbsp;.5)</code>” or, if you want to go fancy, “<code>hsl(240°,&nbsp;1,&nbsp;.5)</code>”</li>
+ # </ul>
+ \*/
+ elproto.attr = function (name, value) {
+ if (this.removed) {
+ return this;
+ }
+ if (name == null) {
+ var res = {};
+ for (var a in this.attrs) if (this.attrs[has](a)) {
+ res[a] = this.attrs[a];
+ }
+ res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
+ res.transform = this._.transform;
+ return res;
+ }
+ if (value == null && R.is(name, "string")) {
+ if (name == "fill" && this.attrs.fill == "none" && this.attrs.gradient) {
+ return this.attrs.gradient;
+ }
+ if (name == "transform") {
+ return this._.transform;
+ }
+ var names = name.split(separator),
+ out = {};
+ for (var i = 0, ii = names.length; i < ii; i++) {
+ name = names[i];
+ if (name in this.attrs) {
+ out[name] = this.attrs[name];
+ } else if (R.is(this.paper.customAttributes[name], "function")) {
+ out[name] = this.paper.customAttributes[name].def;
+ } else {
+ out[name] = R._availableAttrs[name];
+ }
+ }
+ return ii - 1 ? out : out[names[0]];
+ }
+ if (value == null && R.is(name, "array")) {
+ out = {};
+ for (i = 0, ii = name.length; i < ii; i++) {
+ out[name[i]] = this.attr(name[i]);
+ }
+ return out;
+ }
+ if (value != null) {
+ var params = {};
+ params[name] = value;
+ } else if (name != null && R.is(name, "object")) {
+ params = name;
+ }
+ for (var key in params) {
+ eve("raphael.attr." + key + "." + this.id, this, params[key]);
+ }
+ for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
+ var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
+ this.attrs[key] = params[key];
+ for (var subkey in par) if (par[has](subkey)) {
+ params[subkey] = par[subkey];
+ }
+ }
+ setFillAndStroke(this, params);
+ return this;
+ };
+ /*\
+ * Element.toFront
+ [ method ]
+ **
+ * Moves the element so it is the closest to the viewer’s eyes, on top of other elements.
+ = (object) @Element
+ \*/
+ elproto.toFront = function () {
+ if (this.removed) {
+ return this;
+ }
+ var node = getRealNode(this.node);
+ node.parentNode.appendChild(node);
+ var svg = this.paper;
+ svg.top != this && R._tofront(this, svg);
+ return this;
+ };
+ /*\
+ * Element.toBack
+ [ method ]
+ **
+ * Moves the element so it is the furthest from the viewer’s eyes, behind other elements.
+ = (object) @Element
+ \*/
+ elproto.toBack = function () {
+ if (this.removed) {
+ return this;
+ }
+ var node = getRealNode(this.node);
+ var parentNode = node.parentNode;
+ parentNode.insertBefore(node, parentNode.firstChild);
+ R._toback(this, this.paper);
+ var svg = this.paper;
+ return this;
+ };
+ /*\
+ * Element.insertAfter
+ [ method ]
+ **
+ * Inserts current object after the given one.
+ = (object) @Element
+ \*/
+ elproto.insertAfter = function (element) {
+ if (this.removed || !element) {
+ return this;
+ }
+
+ var node = getRealNode(this.node);
+ var afterNode = getRealNode(element.node || element[element.length - 1].node);
+ if (afterNode.nextSibling) {
+ afterNode.parentNode.insertBefore(node, afterNode.nextSibling);
+ } else {
+ afterNode.parentNode.appendChild(node);
+ }
+ R._insertafter(this, element, this.paper);
+ return this;
+ };
+ /*\
+ * Element.insertBefore
+ [ method ]
+ **
+ * Inserts current object before the given one.
+ = (object) @Element
+ \*/
+ elproto.insertBefore = function (element) {
+ if (this.removed || !element) {
+ return this;
+ }
+
+ var node = getRealNode(this.node);
+ var beforeNode = getRealNode(element.node || element[0].node);
+ beforeNode.parentNode.insertBefore(node, beforeNode);
+ R._insertbefore(this, element, this.paper);
+ return this;
+ };
+ elproto.blur = function (size) {
+ // Experimental. No Safari support. Use it on your own risk.
+ var t = this;
+ if (+size !== 0) {
+ var fltr = $("filter"),
+ blur = $("feGaussianBlur");
+ t.attrs.blur = size;
+ fltr.id = R.createUUID();
+ $(blur, {stdDeviation: +size || 1.5});
+ fltr.appendChild(blur);
+ t.paper.defs.appendChild(fltr);
+ t._blur = fltr;
+ $(t.node, {filter: "url(#" + fltr.id + ")"});
+ } else {
+ if (t._blur) {
+ t._blur.parentNode.removeChild(t._blur);
+ delete t._blur;
+ delete t.attrs.blur;
+ }
+ t.node.removeAttribute("filter");
+ }
+ return t;
+ };
+ R._engine.circle = function (svg, x, y, r) {
+ var el = $("circle");
+ svg.canvas && svg.canvas.appendChild(el);
+ var res = new Element(el, svg);
+ res.attrs = {cx: x, cy: y, r: r, fill: "none", stroke: "#000"};
+ res.type = "circle";
+ $(el, res.attrs);
+ return res;
+ };
+ R._engine.rect = function (svg, x, y, w, h, r) {
+ var el = $("rect");
+ svg.canvas && svg.canvas.appendChild(el);
+ var res = new Element(el, svg);
+ res.attrs = {x: x, y: y, width: w, height: h, rx: r || 0, ry: r || 0, fill: "none", stroke: "#000"};
+ res.type = "rect";
+ $(el, res.attrs);
+ return res;
+ };
+ R._engine.ellipse = function (svg, x, y, rx, ry) {
+ var el = $("ellipse");
+ svg.canvas && svg.canvas.appendChild(el);
+ var res = new Element(el, svg);
+ res.attrs = {cx: x, cy: y, rx: rx, ry: ry, fill: "none", stroke: "#000"};
+ res.type = "ellipse";
+ $(el, res.attrs);
+ return res;
+ };
+ R._engine.image = function (svg, src, x, y, w, h) {
+ var el = $("image");
+ $(el, {x: x, y: y, width: w, height: h, preserveAspectRatio: "none"});
+ el.setAttributeNS(xlink, "href", src);
+ svg.canvas && svg.canvas.appendChild(el);
+ var res = new Element(el, svg);
+ res.attrs = {x: x, y: y, width: w, height: h, src: src};
+ res.type = "image";
+ return res;
+ };
+ R._engine.text = function (svg, x, y, text) {
+ var el = $("text");
+ svg.canvas && svg.canvas.appendChild(el);
+ var res = new Element(el, svg);
+ res.attrs = {
+ x: x,
+ y: y,
+ "text-anchor": "middle",
+ text: text,
+ "font-family": R._availableAttrs["font-family"],
+ "font-size": R._availableAttrs["font-size"],
+ stroke: "none",
+ fill: "#000"
+ };
+ res.type = "text";
+ setFillAndStroke(res, res.attrs);
+ return res;
+ };
+ R._engine.setSize = function (width, height) {
+ this.width = width || this.width;
+ this.height = height || this.height;
+ this.canvas.setAttribute("width", this.width);
+ this.canvas.setAttribute("height", this.height);
+ if (this._viewBox) {
+ this.setViewBox.apply(this, this._viewBox);
+ }
+ return this;
+ };
+ R._engine.create = function () {
+ var con = R._getContainer.apply(0, arguments),
+ container = con && con.container,
+ x = con.x,
+ y = con.y,
+ width = con.width,
+ height = con.height;
+ if (!container) {
+ throw new Error("SVG container not found.");
+ }
+ var cnvs = $("svg"),
+ css = "overflow:hidden;",
+ isFloating;
+ x = x || 0;
+ y = y || 0;
+ width = width || 512;
+ height = height || 342;
+ $(cnvs, {
+ height: height,
+ version: 1.1,
+ width: width,
+ xmlns: "http://www.w3.org/2000/svg",
+ "xmlns:xlink": "http://www.w3.org/1999/xlink"
+ });
+ if (container == 1) {
+ cnvs.style.cssText = css + "position:absolute;left:" + x + "px;top:" + y + "px";
+ R._g.doc.body.appendChild(cnvs);
+ isFloating = 1;
+ } else {
+ cnvs.style.cssText = css + "position:relative";
+ if (container.firstChild) {
+ container.insertBefore(cnvs, container.firstChild);
+ } else {
+ container.appendChild(cnvs);
+ }
+ }
+ container = new R._Paper;
+ container.width = width;
+ container.height = height;
+ container.canvas = cnvs;
+ container.clear();
+ container._left = container._top = 0;
+ isFloating && (container.renderfix = function () {});
+ container.renderfix();
+ return container;
+ };
+ R._engine.setViewBox = function (x, y, w, h, fit) {
+ eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
+ var paperSize = this.getSize(),
+ size = mmax(w / paperSize.width, h / paperSize.height),
+ top = this.top,
+ aspectRatio = fit ? "xMidYMid meet" : "xMinYMin",
+ vb,
+ sw;
+ if (x == null) {
+ if (this._vbSize) {
+ size = 1;
+ }
+ delete this._vbSize;
+ vb = "0 0 " + this.width + S + this.height;
+ } else {
+ this._vbSize = size;
+ vb = x + S + y + S + w + S + h;
+ }
+ $(this.canvas, {
+ viewBox: vb,
+ preserveAspectRatio: aspectRatio
+ });
+ while (size && top) {
+ sw = "stroke-width" in top.attrs ? top.attrs["stroke-width"] : 1;
+ top.attr({"stroke-width": sw});
+ top._.dirty = 1;
+ top._.dirtyT = 1;
+ top = top.prev;
+ }
+ this._viewBox = [x, y, w, h, !!fit];
+ return this;
+ };
+ /*\
+ * Paper.renderfix
+ [ method ]
+ **
+ * Fixes the issue of Firefox and IE9 regarding subpixel rendering. If paper is dependent
+ * on other elements after reflow it could shift half pixel which cause for lines to lost their crispness.
+ * This method fixes the issue.
+ **
+ Special thanks to Mariusz Nowak (http://www.medikoo.com/) for this method.
+ \*/
+ R.prototype.renderfix = function () {
+ var cnvs = this.canvas,
+ s = cnvs.style,
+ pos;
+ try {
+ pos = cnvs.getScreenCTM() || cnvs.createSVGMatrix();
+ } catch (e) {
+ pos = cnvs.createSVGMatrix();
+ }
+ var left = -pos.e % 1,
+ top = -pos.f % 1;
+ if (left || top) {
+ if (left) {
+ this._left = (this._left + left) % 1;
+ s.left = this._left + "px";
+ }
+ if (top) {
+ this._top = (this._top + top) % 1;
+ s.top = this._top + "px";
+ }
+ }
+ };
+ /*\
+ * Paper.clear
+ [ method ]
+ **
+ * Clears the paper, i.e. removes all the elements.
+ \*/
+ R.prototype.clear = function () {
+ R.eve("raphael.clear", this);
+ var c = this.canvas;
+ while (c.firstChild) {
+ c.removeChild(c.firstChild);
+ }
+ this.bottom = this.top = null;
+ (this.desc = $("desc")).appendChild(R._g.doc.createTextNode("Created with Rapha\xebl " + R.version));
+ c.appendChild(this.desc);
+ c.appendChild(this.defs = $("defs"));
+ };
+ /*\
+ * Paper.remove
+ [ method ]
+ **
+ * Removes the paper from the DOM.
+ \*/
+ R.prototype.remove = function () {
+ eve("raphael.remove", this);
+ this.canvas.parentNode && this.canvas.parentNode.removeChild(this.canvas);
+ for (var i in this) {
+ this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
+ }
+ };
+ var setproto = R.st;
+ for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
+ setproto[method] = (function (methodname) {
+ return function () {
+ var arg = arguments;
+ return this.forEach(function (el) {
+ el[methodname].apply(el, arg);
+ });
+ };
+ })(method);
+ }
+ }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = function(R) {
+ if (R && !R.vml) {
+ return;
+ }
+
+ var has = "hasOwnProperty",
+ Str = String,
+ toFloat = parseFloat,
+ math = Math,
+ round = math.round,
+ mmax = math.max,
+ mmin = math.min,
+ abs = math.abs,
+ fillString = "fill",
+ separator = /[, ]+/,
+ eve = R.eve,
+ ms = " progid:DXImageTransform.Microsoft",
+ S = " ",
+ E = "",
+ map = {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"},
+ bites = /([clmz]),?([^clmz]*)/gi,
+ blurregexp = / progid:\S+Blur\([^\)]+\)/g,
+ val = /-?[^,\s-]+/g,
+ cssDot = "position:absolute;left:0;top:0;width:1px;height:1px;behavior:url(#default#VML)",
+ zoom = 21600,
+ pathTypes = {path: 1, rect: 1, image: 1},
+ ovalTypes = {circle: 1, ellipse: 1},
+ path2vml = function (path) {
+ var total = /[ahqstv]/ig,
+ command = R._pathToAbsolute;
+ Str(path).match(total) && (command = R._path2curve);
+ total = /[clmz]/g;
+ if (command == R._pathToAbsolute && !Str(path).match(total)) {
+ var res = Str(path).replace(bites, function (all, command, args) {
+ var vals = [],
+ isMove = command.toLowerCase() == "m",
+ res = map[command];
+ args.replace(val, function (value) {
+ if (isMove && vals.length == 2) {
+ res += vals + map[command == "m" ? "l" : "L"];
+ vals = [];
+ }
+ vals.push(round(value * zoom));
+ });
+ return res + vals;
+ });
+ return res;
+ }
+ var pa = command(path), p, r;
+ res = [];
+ for (var i = 0, ii = pa.length; i < ii; i++) {
+ p = pa[i];
+ r = pa[i][0].toLowerCase();
+ r == "z" && (r = "x");
+ for (var j = 1, jj = p.length; j < jj; j++) {
+ r += round(p[j] * zoom) + (j != jj - 1 ? "," : E);
+ }
+ res.push(r);
+ }
+ return res.join(S);
+ },
+ compensation = function (deg, dx, dy) {
+ var m = R.matrix();
+ m.rotate(-deg, .5, .5);
+ return {
+ dx: m.x(dx, dy),
+ dy: m.y(dx, dy)
+ };
+ },
+ setCoords = function (p, sx, sy, dx, dy, deg) {
+ var _ = p._,
+ m = p.matrix,
+ fillpos = _.fillpos,
+ o = p.node,
+ s = o.style,
+ y = 1,
+ flip = "",
+ dxdy,
+ kx = zoom / sx,
+ ky = zoom / sy;
+ s.visibility = "hidden";
+ if (!sx || !sy) {
+ return;
+ }
+ o.coordsize = abs(kx) + S + abs(ky);
+ s.rotation = deg * (sx * sy < 0 ? -1 : 1);
+ if (deg) {
+ var c = compensation(deg, dx, dy);
+ dx = c.dx;
+ dy = c.dy;
+ }
+ sx < 0 && (flip += "x");
+ sy < 0 && (flip += " y") && (y = -1);
+ s.flip = flip;
+ o.coordorigin = (dx * -kx) + S + (dy * -ky);
+ if (fillpos || _.fillsize) {
+ var fill = o.getElementsByTagName(fillString);
+ fill = fill && fill[0];
+ o.removeChild(fill);
+ if (fillpos) {
+ c = compensation(deg, m.x(fillpos[0], fillpos[1]), m.y(fillpos[0], fillpos[1]));
+ fill.position = c.dx * y + S + c.dy * y;
+ }
+ if (_.fillsize) {
+ fill.size = _.fillsize[0] * abs(sx) + S + _.fillsize[1] * abs(sy);
+ }
+ o.appendChild(fill);
+ }
+ s.visibility = "visible";
+ };
+ R.toString = function () {
+ return "Your browser doesn\u2019t support SVG. Falling down to VML.\nYou are running Rapha\xebl " + this.version;
+ };
+ var addArrow = function (o, value, isEnd) {
+ var values = Str(value).toLowerCase().split("-"),
+ se = isEnd ? "end" : "start",
+ i = values.length,
+ type = "classic",
+ w = "medium",
+ h = "medium";
+ while (i--) {
+ switch (values[i]) {
+ case "block":
+ case "classic":
+ case "oval":
+ case "diamond":
+ case "open":
+ case "none":
+ type = values[i];
+ break;
+ case "wide":
+ case "narrow": h = values[i]; break;
+ case "long":
+ case "short": w = values[i]; break;
+ }
+ }
+ var stroke = o.node.getElementsByTagName("stroke")[0];
+ stroke[se + "arrow"] = type;
+ stroke[se + "arrowlength"] = w;
+ stroke[se + "arrowwidth"] = h;
+ },
+ setFillAndStroke = function (o, params) {
+ // o.paper.canvas.style.display = "none";
+ o.attrs = o.attrs || {};
+ var node = o.node,
+ a = o.attrs,
+ s = node.style,
+ xy,
+ newpath = pathTypes[o.type] && (params.x != a.x || params.y != a.y || params.width != a.width || params.height != a.height || params.cx != a.cx || params.cy != a.cy || params.rx != a.rx || params.ry != a.ry || params.r != a.r),
+ isOval = ovalTypes[o.type] && (a.cx != params.cx || a.cy != params.cy || a.r != params.r || a.rx != params.rx || a.ry != params.ry),
+ res = o;
+
+
+ for (var par in params) if (params[has](par)) {
+ a[par] = params[par];
+ }
+ if (newpath) {
+ a.path = R._getPath[o.type](o);
+ o._.dirty = 1;
+ }
+ params.href && (node.href = params.href);
+ params.title && (node.title = params.title);
+ params.target && (node.target = params.target);
+ params.cursor && (s.cursor = params.cursor);
+ "blur" in params && o.blur(params.blur);
+ if (params.path && o.type == "path" || newpath) {
+ node.path = path2vml(~Str(a.path).toLowerCase().indexOf("r") ? R._pathToAbsolute(a.path) : a.path);
+ o._.dirty = 1;
+ if (o.type == "image") {
+ o._.fillpos = [a.x, a.y];
+ o._.fillsize = [a.width, a.height];
+ setCoords(o, 1, 1, 0, 0, 0);
+ }
+ }
+ "transform" in params && o.transform(params.transform);
+ if (isOval) {
+ var cx = +a.cx,
+ cy = +a.cy,
+ rx = +a.rx || +a.r || 0,
+ ry = +a.ry || +a.r || 0;
+ node.path = R.format("ar{0},{1},{2},{3},{4},{1},{4},{1}x", round((cx - rx) * zoom), round((cy - ry) * zoom), round((cx + rx) * zoom), round((cy + ry) * zoom), round(cx * zoom));
+ o._.dirty = 1;
+ }
+ if ("clip-rect" in params) {
+ var rect = Str(params["clip-rect"]).split(separator);
+ if (rect.length == 4) {
+ rect[2] = +rect[2] + (+rect[0]);
+ rect[3] = +rect[3] + (+rect[1]);
+ var div = node.clipRect || R._g.doc.createElement("div"),
+ dstyle = div.style;
+ dstyle.clip = R.format("rect({1}px {2}px {3}px {0}px)", rect);
+ if (!node.clipRect) {
+ dstyle.position = "absolute";
+ dstyle.top = 0;
+ dstyle.left = 0;
+ dstyle.width = o.paper.width + "px";
+ dstyle.height = o.paper.height + "px";
+ node.parentNode.insertBefore(div, node);
+ div.appendChild(node);
+ node.clipRect = div;
+ }
+ }
+ if (!params["clip-rect"]) {
+ node.clipRect && (node.clipRect.style.clip = "auto");
+ }
+ }
+ if (o.textpath) {
+ var textpathStyle = o.textpath.style;
+ params.font && (textpathStyle.font = params.font);
+ params["font-family"] && (textpathStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(/^['"]+|['"]+$/g, E) + '"');
+ params["font-size"] && (textpathStyle.fontSize = params["font-size"]);
+ params["font-weight"] && (textpathStyle.fontWeight = params["font-weight"]);
+ params["font-style"] && (textpathStyle.fontStyle = params["font-style"]);
+ }
+ if ("arrow-start" in params) {
+ addArrow(res, params["arrow-start"]);
+ }
+ if ("arrow-end" in params) {
+ addArrow(res, params["arrow-end"], 1);
+ }
+ if (params.opacity != null ||
+ params.fill != null ||
+ params.src != null ||
+ params.stroke != null ||
+ params["stroke-width"] != null ||
+ params["stroke-opacity"] != null ||
+ params["fill-opacity"] != null ||
+ params["stroke-dasharray"] != null ||
+ params["stroke-miterlimit"] != null ||
+ params["stroke-linejoin"] != null ||
+ params["stroke-linecap"] != null) {
+ var fill = node.getElementsByTagName(fillString),
+ newfill = false;
+ fill = fill && fill[0];
+ !fill && (newfill = fill = createNode(fillString));
+ if (o.type == "image" && params.src) {
+ fill.src = params.src;
+ }
+ params.fill && (fill.on = true);
+ if (fill.on == null || params.fill == "none" || params.fill === null) {
+ fill.on = false;
+ }
+ if (fill.on && params.fill) {
+ var isURL = Str(params.fill).match(R._ISURL);
+ if (isURL) {
+ fill.parentNode == node && node.removeChild(fill);
+ fill.rotate = true;
+ fill.src = isURL[1];
+ fill.type = "tile";
+ var bbox = o.getBBox(1);
+ fill.position = bbox.x + S + bbox.y;
+ o._.fillpos = [bbox.x, bbox.y];
+
+ R._preload(isURL[1], function () {
+ o._.fillsize = [this.offsetWidth, this.offsetHeight];
+ });
+ } else {
+ fill.color = R.getRGB(params.fill).hex;
+ fill.src = E;
+ fill.type = "solid";
+ if (R.getRGB(params.fill).error && (res.type in {circle: 1, ellipse: 1} || Str(params.fill).charAt() != "r") && addGradientFill(res, params.fill, fill)) {
+ a.fill = "none";
+ a.gradient = params.fill;
+ fill.rotate = false;
+ }
+ }
+ }
+ if ("fill-opacity" in params || "opacity" in params) {
+ var opacity = ((+a["fill-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+R.getRGB(params.fill).o + 1 || 2) - 1);
+ opacity = mmin(mmax(opacity, 0), 1);
+ fill.opacity = opacity;
+ if (fill.src) {
+ fill.color = "none";
+ }
+ }
+ node.appendChild(fill);
+ var stroke = (node.getElementsByTagName("stroke") && node.getElementsByTagName("stroke")[0]),
+ newstroke = false;
+ !stroke && (newstroke = stroke = createNode("stroke"));
+ if ((params.stroke && params.stroke != "none") ||
+ params["stroke-width"] ||
+ params["stroke-opacity"] != null ||
+ params["stroke-dasharray"] ||
+ params["stroke-miterlimit"] ||
+ params["stroke-linejoin"] ||
+ params["stroke-linecap"]) {
+ stroke.on = true;
+ }
+ (params.stroke == "none" || params.stroke === null || stroke.on == null || params.stroke == 0 || params["stroke-width"] == 0) && (stroke.on = false);
+ var strokeColor = R.getRGB(params.stroke);
+ stroke.on && params.stroke && (stroke.color = strokeColor.hex);
+ opacity = ((+a["stroke-opacity"] + 1 || 2) - 1) * ((+a.opacity + 1 || 2) - 1) * ((+strokeColor.o + 1 || 2) - 1);
+ var width = (toFloat(params["stroke-width"]) || 1) * .75;
+ opacity = mmin(mmax(opacity, 0), 1);
+ params["stroke-width"] == null && (width = a["stroke-width"]);
+ params["stroke-width"] && (stroke.weight = width);
+ width && width < 1 && (opacity *= width) && (stroke.weight = 1);
+ stroke.opacity = opacity;
+
+ params["stroke-linejoin"] && (stroke.joinstyle = params["stroke-linejoin"] || "miter");
+ stroke.miterlimit = params["stroke-miterlimit"] || 8;
+ params["stroke-linecap"] && (stroke.endcap = params["stroke-linecap"] == "butt" ? "flat" : params["stroke-linecap"] == "square" ? "square" : "round");
+ if ("stroke-dasharray" in params) {
+ var dasharray = {
+ "-": "shortdash",
+ ".": "shortdot",
+ "-.": "shortdashdot",
+ "-..": "shortdashdotdot",
+ ". ": "dot",
+ "- ": "dash",
+ "--": "longdash",
+ "- .": "dashdot",
+ "--.": "longdashdot",
+ "--..": "longdashdotdot"
+ };
+ stroke.dashstyle = dasharray[has](params["stroke-dasharray"]) ? dasharray[params["stroke-dasharray"]] : E;
+ }
+ newstroke && node.appendChild(stroke);
+ }
+ if (res.type == "text") {
+ res.paper.canvas.style.display = E;
+ var span = res.paper.span,
+ m = 100,
+ fontSize = a.font && a.font.match(/\d+(?:\.\d*)?(?=px)/);
+ s = span.style;
+ a.font && (s.font = a.font);
+ a["font-family"] && (s.fontFamily = a["font-family"]);
+ a["font-weight"] && (s.fontWeight = a["font-weight"]);
+ a["font-style"] && (s.fontStyle = a["font-style"]);
+ fontSize = toFloat(a["font-size"] || fontSize && fontSize[0]) || 10;
+ s.fontSize = fontSize * m + "px";
+ res.textpath.string && (span.innerHTML = Str(res.textpath.string).replace(/</g, "&#60;").replace(/&/g, "&#38;").replace(/\n/g, "<br>"));
+ var brect = span.getBoundingClientRect();
+ res.W = a.w = (brect.right - brect.left) / m;
+ res.H = a.h = (brect.bottom - brect.top) / m;
+ // res.paper.canvas.style.display = "none";
+ res.X = a.x;
+ res.Y = a.y + res.H / 2;
+
+ ("x" in params || "y" in params) && (res.path.v = R.format("m{0},{1}l{2},{1}", round(a.x * zoom), round(a.y * zoom), round(a.x * zoom) + 1));
+ var dirtyattrs = ["x", "y", "text", "font", "font-family", "font-weight", "font-style", "font-size"];
+ for (var d = 0, dd = dirtyattrs.length; d < dd; d++) if (dirtyattrs[d] in params) {
+ res._.dirty = 1;
+ break;
+ }
+
+ // text-anchor emulation
+ switch (a["text-anchor"]) {
+ case "start":
+ res.textpath.style["v-text-align"] = "left";
+ res.bbx = res.W / 2;
+ break;
+ case "end":
+ res.textpath.style["v-text-align"] = "right";
+ res.bbx = -res.W / 2;
+ break;
+ default:
+ res.textpath.style["v-text-align"] = "center";
+ res.bbx = 0;
+ break;
+ }
+ res.textpath.style["v-text-kern"] = true;
+ }
+ // res.paper.canvas.style.display = E;
+ },
+ addGradientFill = function (o, gradient, fill) {
+ o.attrs = o.attrs || {};
+ var attrs = o.attrs,
+ pow = Math.pow,
+ opacity,
+ oindex,
+ type = "linear",
+ fxfy = ".5 .5";
+ o.attrs.gradient = gradient;
+ gradient = Str(gradient).replace(R._radial_gradient, function (all, fx, fy) {
+ type = "radial";
+ if (fx && fy) {
+ fx = toFloat(fx);
+ fy = toFloat(fy);
+ pow(fx - .5, 2) + pow(fy - .5, 2) > .25 && (fy = math.sqrt(.25 - pow(fx - .5, 2)) * ((fy > .5) * 2 - 1) + .5);
+ fxfy = fx + S + fy;
+ }
+ return E;
+ });
+ gradient = gradient.split(/\s*\-\s*/);
+ if (type == "linear") {
+ var angle = gradient.shift();
+ angle = -toFloat(angle);
+ if (isNaN(angle)) {
+ return null;
+ }
+ }
+ var dots = R._parseDots(gradient);
+ if (!dots) {
+ return null;
+ }
+ o = o.shape || o.node;
+ if (dots.length) {
+ o.removeChild(fill);
+ fill.on = true;
+ fill.method = "none";
+ fill.color = dots[0].color;
+ fill.color2 = dots[dots.length - 1].color;
+ var clrs = [];
+ for (var i = 0, ii = dots.length; i < ii; i++) {
+ dots[i].offset && clrs.push(dots[i].offset + S + dots[i].color);
+ }
+ fill.colors = clrs.length ? clrs.join() : "0% " + fill.color;
+ if (type == "radial") {
+ fill.type = "gradientTitle";
+ fill.focus = "100%";
+ fill.focussize = "0 0";
+ fill.focusposition = fxfy;
+ fill.angle = 0;
+ } else {
+ // fill.rotate= true;
+ fill.type = "gradient";
+ fill.angle = (270 - angle) % 360;
+ }
+ o.appendChild(fill);
+ }
+ return 1;
+ },
+ Element = function (node, vml) {
+ this[0] = this.node = node;
+ node.raphael = true;
+ this.id = R._oid++;
+ node.raphaelid = this.id;
+ this.X = 0;
+ this.Y = 0;
+ this.attrs = {};
+ this.paper = vml;
+ this.matrix = R.matrix();
+ this._ = {
+ transform: [],
+ sx: 1,
+ sy: 1,
+ dx: 0,
+ dy: 0,
+ deg: 0,
+ dirty: 1,
+ dirtyT: 1
+ };
+ !vml.bottom && (vml.bottom = this);
+ this.prev = vml.top;
+ vml.top && (vml.top.next = this);
+ vml.top = this;
+ this.next = null;
+ };
+ var elproto = R.el;
+
+ Element.prototype = elproto;
+ elproto.constructor = Element;
+ elproto.transform = function (tstr) {
+ if (tstr == null) {
+ return this._.transform;
+ }
+ var vbs = this.paper._viewBoxShift,
+ vbt = vbs ? "s" + [vbs.scale, vbs.scale] + "-1-1t" + [vbs.dx, vbs.dy] : E,
+ oldt;
+ if (vbs) {
+ oldt = tstr = Str(tstr).replace(/\.{3}|\u2026/g, this._.transform || E);
+ }
+ R._extractTransform(this, vbt + tstr);
+ var matrix = this.matrix.clone(),
+ skew = this.skew,
+ o = this.node,
+ split,
+ isGrad = ~Str(this.attrs.fill).indexOf("-"),
+ isPatt = !Str(this.attrs.fill).indexOf("url(");
+ matrix.translate(1, 1);
+ if (isPatt || isGrad || this.type == "image") {
+ skew.matrix = "1 0 0 1";
+ skew.offset = "0 0";
+ split = matrix.split();
+ if ((isGrad && split.noRotation) || !split.isSimple) {
+ o.style.filter = matrix.toFilter();
+ var bb = this.getBBox(),
+ bbt = this.getBBox(1),
+ dx = bb.x - bbt.x,
+ dy = bb.y - bbt.y;
+ o.coordorigin = (dx * -zoom) + S + (dy * -zoom);
+ setCoords(this, 1, 1, dx, dy, 0);
+ } else {
+ o.style.filter = E;
+ setCoords(this, split.scalex, split.scaley, split.dx, split.dy, split.rotate);
+ }
+ } else {
+ o.style.filter = E;
+ skew.matrix = Str(matrix);
+ skew.offset = matrix.offset();
+ }
+ if (oldt !== null) { // empty string value is true as well
+ this._.transform = oldt;
+ R._extractTransform(this, oldt);
+ }
+ return this;
+ };
+ elproto.rotate = function (deg, cx, cy) {
+ if (this.removed) {
+ return this;
+ }
+ if (deg == null) {
+ return;
+ }
+ deg = Str(deg).split(separator);
+ if (deg.length - 1) {
+ cx = toFloat(deg[1]);
+ cy = toFloat(deg[2]);
+ }
+ deg = toFloat(deg[0]);
+ (cy == null) && (cx = cy);
+ if (cx == null || cy == null) {
+ var bbox = this.getBBox(1);
+ cx = bbox.x + bbox.width / 2;
+ cy = bbox.y + bbox.height / 2;
+ }
+ this._.dirtyT = 1;
+ this.transform(this._.transform.concat([["r", deg, cx, cy]]));
+ return this;
+ };
+ elproto.translate = function (dx, dy) {
+ if (this.removed) {
+ return this;
+ }
+ dx = Str(dx).split(separator);
+ if (dx.length - 1) {
+ dy = toFloat(dx[1]);
+ }
+ dx = toFloat(dx[0]) || 0;
+ dy = +dy || 0;
+ if (this._.bbox) {
+ this._.bbox.x += dx;
+ this._.bbox.y += dy;
+ }
+ this.transform(this._.transform.concat([["t", dx, dy]]));
+ return this;
+ };
+ elproto.scale = function (sx, sy, cx, cy) {
+ if (this.removed) {
+ return this;
+ }
+ sx = Str(sx).split(separator);
+ if (sx.length - 1) {
+ sy = toFloat(sx[1]);
+ cx = toFloat(sx[2]);
+ cy = toFloat(sx[3]);
+ isNaN(cx) && (cx = null);
+ isNaN(cy) && (cy = null);
+ }
+ sx = toFloat(sx[0]);
+ (sy == null) && (sy = sx);
+ (cy == null) && (cx = cy);
+ if (cx == null || cy == null) {
+ var bbox = this.getBBox(1);
+ }
+ cx = cx == null ? bbox.x + bbox.width / 2 : cx;
+ cy = cy == null ? bbox.y + bbox.height / 2 : cy;
+
+ this.transform(this._.transform.concat([["s", sx, sy, cx, cy]]));
+ this._.dirtyT = 1;
+ return this;
+ };
+ elproto.hide = function () {
+ !this.removed && (this.node.style.display = "none");
+ return this;
+ };
+ elproto.show = function () {
+ !this.removed && (this.node.style.display = E);
+ return this;
+ };
+ // Needed to fix the vml setViewBox issues
+ elproto.auxGetBBox = R.el.getBBox;
+ elproto.getBBox = function(){
+ var b = this.auxGetBBox();
+ if (this.paper && this.paper._viewBoxShift)
+ {
+ var c = {};
+ var z = 1/this.paper._viewBoxShift.scale;
+ c.x = b.x - this.paper._viewBoxShift.dx;
+ c.x *= z;
+ c.y = b.y - this.paper._viewBoxShift.dy;
+ c.y *= z;
+ c.width = b.width * z;
+ c.height = b.height * z;
+ c.x2 = c.x + c.width;
+ c.y2 = c.y + c.height;
+ return c;
+ }
+ return b;
+ };
+ elproto._getBBox = function () {
+ if (this.removed) {
+ return {};
+ }
+ return {
+ x: this.X + (this.bbx || 0) - this.W / 2,
+ y: this.Y - this.H,
+ width: this.W,
+ height: this.H
+ };
+ };
+ elproto.remove = function () {
+ if (this.removed || !this.node.parentNode) {
+ return;
+ }
+ this.paper.__set__ && this.paper.__set__.exclude(this);
+ R.eve.unbind("raphael.*.*." + this.id);
+ R._tear(this, this.paper);
+ this.node.parentNode.removeChild(this.node);
+ this.shape && this.shape.parentNode.removeChild(this.shape);
+ for (var i in this) {
+ this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
+ }
+ this.removed = true;
+ };
+ elproto.attr = function (name, value) {
+ if (this.removed) {
+ return this;
+ }
+ if (name == null) {
+ var res = {};
+ for (var a in this.attrs) if (this.attrs[has](a)) {
+ res[a] = this.attrs[a];
+ }
+ res.gradient && res.fill == "none" && (res.fill = res.gradient) && delete res.gradient;
+ res.transform = this._.transform;
+ return res;
+ }
+ if (value == null && R.is(name, "string")) {
+ if (name == fillString && this.attrs.fill == "none" && this.attrs.gradient) {
+ return this.attrs.gradient;
+ }
+ var names = name.split(separator),
+ out = {};
+ for (var i = 0, ii = names.length; i < ii; i++) {
+ name = names[i];
+ if (name in this.attrs) {
+ out[name] = this.attrs[name];
+ } else if (R.is(this.paper.customAttributes[name], "function")) {
+ out[name] = this.paper.customAttributes[name].def;
+ } else {
+ out[name] = R._availableAttrs[name];
+ }
+ }
+ return ii - 1 ? out : out[names[0]];
+ }
+ if (this.attrs && value == null && R.is(name, "array")) {
+ out = {};
+ for (i = 0, ii = name.length; i < ii; i++) {
+ out[name[i]] = this.attr(name[i]);
+ }
+ return out;
+ }
+ var params;
+ if (value != null) {
+ params = {};
+ params[name] = value;
+ }
+ value == null && R.is(name, "object") && (params = name);
+ for (var key in params) {
+ eve("raphael.attr." + key + "." + this.id, this, params[key]);
+ }
+ if (params) {
+ for (key in this.paper.customAttributes) if (this.paper.customAttributes[has](key) && params[has](key) && R.is(this.paper.customAttributes[key], "function")) {
+ var par = this.paper.customAttributes[key].apply(this, [].concat(params[key]));
+ this.attrs[key] = params[key];
+ for (var subkey in par) if (par[has](subkey)) {
+ params[subkey] = par[subkey];
+ }
+ }
+ // this.paper.canvas.style.display = "none";
+ if (params.text && this.type == "text") {
+ this.textpath.string = params.text;
+ }
+ setFillAndStroke(this, params);
+ // this.paper.canvas.style.display = E;
+ }
+ return this;
+ };
+ elproto.toFront = function () {
+ !this.removed && this.node.parentNode.appendChild(this.node);
+ this.paper && this.paper.top != this && R._tofront(this, this.paper);
+ return this;
+ };
+ elproto.toBack = function () {
+ if (this.removed) {
+ return this;
+ }
+ if (this.node.parentNode.firstChild != this.node) {
+ this.node.parentNode.insertBefore(this.node, this.node.parentNode.firstChild);
+ R._toback(this, this.paper);
+ }
+ return this;
+ };
+ elproto.insertAfter = function (element) {
+ if (this.removed) {
+ return this;
+ }
+ if (element.constructor == R.st.constructor) {
+ element = element[element.length - 1];
+ }
+ if (element.node.nextSibling) {
+ element.node.parentNode.insertBefore(this.node, element.node.nextSibling);
+ } else {
+ element.node.parentNode.appendChild(this.node);
+ }
+ R._insertafter(this, element, this.paper);
+ return this;
+ };
+ elproto.insertBefore = function (element) {
+ if (this.removed) {
+ return this;
+ }
+ if (element.constructor == R.st.constructor) {
+ element = element[0];
+ }
+ element.node.parentNode.insertBefore(this.node, element.node);
+ R._insertbefore(this, element, this.paper);
+ return this;
+ };
+ elproto.blur = function (size) {
+ var s = this.node.runtimeStyle,
+ f = s.filter;
+ f = f.replace(blurregexp, E);
+ if (+size !== 0) {
+ this.attrs.blur = size;
+ s.filter = f + S + ms + ".Blur(pixelradius=" + (+size || 1.5) + ")";
+ s.margin = R.format("-{0}px 0 0 -{0}px", round(+size || 1.5));
+ } else {
+ s.filter = f;
+ s.margin = 0;
+ delete this.attrs.blur;
+ }
+ return this;
+ };
+
+ R._engine.path = function (pathString, vml) {
+ var el = createNode("shape");
+ el.style.cssText = cssDot;
+ el.coordsize = zoom + S + zoom;
+ el.coordorigin = vml.coordorigin;
+ var p = new Element(el, vml),
+ attr = {fill: "none", stroke: "#000"};
+ pathString && (attr.path = pathString);
+ p.type = "path";
+ p.path = [];
+ p.Path = E;
+ setFillAndStroke(p, attr);
+ vml.canvas && vml.canvas.appendChild(el);
+ var skew = createNode("skew");
+ skew.on = true;
+ el.appendChild(skew);
+ p.skew = skew;
+ p.transform(E);
+ return p;
+ };
+ R._engine.rect = function (vml, x, y, w, h, r) {
+ var path = R._rectPath(x, y, w, h, r),
+ res = vml.path(path),
+ a = res.attrs;
+ res.X = a.x = x;
+ res.Y = a.y = y;
+ res.W = a.width = w;
+ res.H = a.height = h;
+ a.r = r;
+ a.path = path;
+ res.type = "rect";
+ return res;
+ };
+ R._engine.ellipse = function (vml, x, y, rx, ry) {
+ var res = vml.path(),
+ a = res.attrs;
+ res.X = x - rx;
+ res.Y = y - ry;
+ res.W = rx * 2;
+ res.H = ry * 2;
+ res.type = "ellipse";
+ setFillAndStroke(res, {
+ cx: x,
+ cy: y,
+ rx: rx,
+ ry: ry
+ });
+ return res;
+ };
+ R._engine.circle = function (vml, x, y, r) {
+ var res = vml.path(),
+ a = res.attrs;
+ res.X = x - r;
+ res.Y = y - r;
+ res.W = res.H = r * 2;
+ res.type = "circle";
+ setFillAndStroke(res, {
+ cx: x,
+ cy: y,
+ r: r
+ });
+ return res;
+ };
+ R._engine.image = function (vml, src, x, y, w, h) {
+ var path = R._rectPath(x, y, w, h),
+ res = vml.path(path).attr({stroke: "none"}),
+ a = res.attrs,
+ node = res.node,
+ fill = node.getElementsByTagName(fillString)[0];
+ a.src = src;
+ res.X = a.x = x;
+ res.Y = a.y = y;
+ res.W = a.width = w;
+ res.H = a.height = h;
+ a.path = path;
+ res.type = "image";
+ fill.parentNode == node && node.removeChild(fill);
+ fill.rotate = true;
+ fill.src = src;
+ fill.type = "tile";
+ res._.fillpos = [x, y];
+ res._.fillsize = [w, h];
+ node.appendChild(fill);
+ setCoords(res, 1, 1, 0, 0, 0);
+ return res;
+ };
+ R._engine.text = function (vml, x, y, text) {
+ var el = createNode("shape"),
+ path = createNode("path"),
+ o = createNode("textpath");
+ x = x || 0;
+ y = y || 0;
+ text = text || "";
+ path.v = R.format("m{0},{1}l{2},{1}", round(x * zoom), round(y * zoom), round(x * zoom) + 1);
+ path.textpathok = true;
+ o.string = Str(text);
+ o.on = true;
+ el.style.cssText = cssDot;
+ el.coordsize = zoom + S + zoom;
+ el.coordorigin = "0 0";
+ var p = new Element(el, vml),
+ attr = {
+ fill: "#000",
+ stroke: "none",
+ font: R._availableAttrs.font,
+ text: text
+ };
+ p.shape = el;
+ p.path = path;
+ p.textpath = o;
+ p.type = "text";
+ p.attrs.text = Str(text);
+ p.attrs.x = x;
+ p.attrs.y = y;
+ p.attrs.w = 1;
+ p.attrs.h = 1;
+ setFillAndStroke(p, attr);
+ el.appendChild(o);
+ el.appendChild(path);
+ vml.canvas.appendChild(el);
+ var skew = createNode("skew");
+ skew.on = true;
+ el.appendChild(skew);
+ p.skew = skew;
+ p.transform(E);
+ return p;
+ };
+ R._engine.setSize = function (width, height) {
+ var cs = this.canvas.style;
+ this.width = width;
+ this.height = height;
+ width == +width && (width += "px");
+ height == +height && (height += "px");
+ cs.width = width;
+ cs.height = height;
+ cs.clip = "rect(0 " + width + " " + height + " 0)";
+ if (this._viewBox) {
+ R._engine.setViewBox.apply(this, this._viewBox);
+ }
+ return this;
+ };
+ R._engine.setViewBox = function (x, y, w, h, fit) {
+ R.eve("raphael.setViewBox", this, this._viewBox, [x, y, w, h, fit]);
+ var paperSize = this.getSize(),
+ width = paperSize.width,
+ height = paperSize.height,
+ H, W;
+ if (fit) {
+ H = height / h;
+ W = width / w;
+ if (w * H < width) {
+ x -= (width - w * H) / 2 / H;
+ }
+ if (h * W < height) {
+ y -= (height - h * W) / 2 / W;
+ }
+ }
+ this._viewBox = [x, y, w, h, !!fit];
+ this._viewBoxShift = {
+ dx: -x,
+ dy: -y,
+ scale: paperSize
+ };
+ this.forEach(function (el) {
+ el.transform("...");
+ });
+ return this;
+ };
+ var createNode;
+ R._engine.initWin = function (win) {
+ var doc = win.document;
+ if (doc.styleSheets.length < 31) {
+ doc.createStyleSheet().addRule(".rvml", "behavior:url(#default#VML)");
+ } else {
+ // no more room, add to the existing one
+ // http://msdn.microsoft.com/en-us/library/ms531194%28VS.85%29.aspx
+ doc.styleSheets[0].addRule(".rvml", "behavior:url(#default#VML)");
+ }
+ try {
+ !doc.namespaces.rvml && doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
+ createNode = function (tagName) {
+ return doc.createElement('<rvml:' + tagName + ' class="rvml">');
+ };
+ } catch (e) {
+ createNode = function (tagName) {
+ return doc.createElement('<' + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
+ };
+ }
+ };
+ R._engine.initWin(R._g.win);
+ R._engine.create = function () {
+ var con = R._getContainer.apply(0, arguments),
+ container = con.container,
+ height = con.height,
+ s,
+ width = con.width,
+ x = con.x,
+ y = con.y;
+ if (!container) {
+ throw new Error("VML container not found.");
+ }
+ var res = new R._Paper,
+ c = res.canvas = R._g.doc.createElement("div"),
+ cs = c.style;
+ x = x || 0;
+ y = y || 0;
+ width = width || 512;
+ height = height || 342;
+ res.width = width;
+ res.height = height;
+ width == +width && (width += "px");
+ height == +height && (height += "px");
+ res.coordsize = zoom * 1e3 + S + zoom * 1e3;
+ res.coordorigin = "0 0";
+ res.span = R._g.doc.createElement("span");
+ res.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;";
+ c.appendChild(res.span);
+ cs.cssText = R.format("top:0;left:0;width:{0};height:{1};display:inline-block;position:relative;clip:rect(0 {0} {1} 0);overflow:hidden", width, height);
+ if (container == 1) {
+ R._g.doc.body.appendChild(c);
+ cs.left = x + "px";
+ cs.top = y + "px";
+ cs.position = "absolute";
+ } else {
+ if (container.firstChild) {
+ container.insertBefore(c, container.firstChild);
+ } else {
+ container.appendChild(c);
+ }
+ }
+ res.renderfix = function () {};
+ return res;
+ };
+ R.prototype.clear = function () {
+ R.eve("raphael.clear", this);
+ this.canvas.innerHTML = E;
+ this.span = R._g.doc.createElement("span");
+ this.span.style.cssText = "position:absolute;left:-9999em;top:-9999em;padding:0;margin:0;line-height:1;display:inline;";
+ this.canvas.appendChild(this.span);
+ this.bottom = this.top = null;
+ };
+ R.prototype.remove = function () {
+ R.eve("raphael.remove", this);
+ this.canvas.parentNode.removeChild(this.canvas);
+ for (var i in this) {
+ this[i] = typeof this[i] == "function" ? R._removedFactory(i) : null;
+ }
+ return true;
+ };
+
+ var setproto = R.st;
+ for (var method in elproto) if (elproto[has](method) && !setproto[has](method)) {
+ setproto[method] = (function (methodname) {
+ return function () {
+ var arg = arguments;
+ return this.forEach(function (el) {
+ el[methodname].apply(el, arg);
+ });
+ };
+ })(method);
+ }
+ }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+
+
+/***/ }
+/******/ ])
+});
+; \ No newline at end of file
diff --git a/debian/missing-sources/tableExport-1.6.0.js b/debian/missing-sources/tableExport-1.6.0.js
new file mode 100644
index 000000000..0d67afe87
--- /dev/null
+++ b/debian/missing-sources/tableExport-1.6.0.js
@@ -0,0 +1,1736 @@
+/**
+ * @preserve tableExport.jquery.plugin
+ *
+ * Copyright (c) 2015-2017 hhurz, https://github.com/hhurz/tableExport.jquery.plugin
+ * Original work Copyright (c) 2014 Giri Raj, https://github.com/kayalshri/
+ *
+ * Licensed under the MIT License, http://opensource.org/licenses/mit-license
+ */
+
+(function ($) {
+ $.fn.extend({
+ tableExport: function (options) {
+ var defaults = {
+ consoleLog: false,
+ csvEnclosure: '"',
+ csvSeparator: ',',
+ csvUseBOM: true,
+ displayTableName: false,
+ escape: false,
+ excelstyles: [], // e.g. ['border-bottom', 'border-top', 'border-left', 'border-right']
+ fileName: 'tableExport',
+ htmlContent: false,
+ ignoreColumn: [],
+ ignoreRow:[],
+ jsonScope: 'all', // head, data, all
+ jspdf: {orientation: 'p',
+ unit: 'pt',
+ format: 'a4', // jspdf page format or 'bestfit' for autmatic paper format selection
+ margins: {left: 20, right: 10, top: 10, bottom: 10},
+ autotable: {styles: {cellPadding: 2,
+ rowHeight: 12,
+ fontSize: 8,
+ fillColor: 255, // color value or 'inherit' to use css background-color from html table
+ textColor: 50, // color value or 'inherit' to use css color from html table
+ fontStyle: 'normal', // normal, bold, italic, bolditalic or 'inherit' to use css font-weight and fonst-style from html table
+ overflow: 'ellipsize', // visible, hidden, ellipsize or linebreak
+ halign: 'left', // left, center, right
+ valign: 'middle' // top, middle, bottom
+ },
+ headerStyles: {fillColor: [52, 73, 94],
+ textColor: 255,
+ fontStyle: 'bold',
+ halign: 'center'
+ },
+ alternateRowStyles: {fillColor: 245
+ },
+ tableExport: {onAfterAutotable: null,
+ onBeforeAutotable: null,
+ onTable: null,
+ outputImages: true
+ }
+ }
+ },
+ numbers: {html: {decimalMark: '.',
+ thousandsSeparator: ','
+ },
+ output: {decimalMark: '.',
+ thousandsSeparator: ','
+ }
+ },
+ onCellData: null,
+ onCellHtmlData: null,
+ outputMode: 'file', // 'file', 'string', 'base64' or 'window' (experimental)
+ pdfmake: {enabled: false}, // true: use pdfmake instead of jspdf(-autotable)
+ tbodySelector: 'tr',
+ tfootSelector: 'tr', // set empty ('') to prevent export of tfoot rows
+ theadSelector: 'tr',
+ tableName: 'myTableName',
+ type: 'csv', // 'csv', 'tsv', 'txt', 'sql', 'json', 'xml', 'excel', 'doc', 'png' or 'pdf'
+ worksheetName: 'xlsWorksheetName'
+ };
+
+ var FONT_ROW_RATIO = 1.15;
+ var el = this;
+ var DownloadEvt = null;
+ var $hrows = [];
+ var $rows = [];
+ var rowIndex = 0;
+ var rowspans = [];
+ var trData = '';
+ var colNames = [];
+ var blob;
+
+ $.extend(true, defaults, options);
+
+ colNames = GetColumnNames (el);
+
+ if (defaults.type == 'csv' || defaults.type == 'tsv' || defaults.type == 'txt') {
+
+ var csvData = "";
+ var rowlength = 0;
+ rowIndex = 0;
+
+ function csvString(cell, rowIndex, colIndex) {
+ var result = '';
+
+ if (cell !== null) {
+ var dataString = parseString(cell, rowIndex, colIndex);
+
+ var csvValue = (dataString === null || dataString === '') ? '' : dataString.toString();
+
+ if (defaults.type == 'tsv') {
+ if (dataString instanceof Date)
+ result = dataString.toLocaleString();
+
+ // According to http://www.iana.org/assignments/media-types/text/tab-separated-values
+ // are fields that contain tabs not allowable in tsv encoding
+ result = replaceAll(csvValue, '\t', ' ');
+ }
+ else {
+ // Takes a string and encapsulates it (by default in double-quotes) if it
+ // contains the csv field separator, spaces, or linebreaks.
+ if (dataString instanceof Date)
+ result = defaults.csvEnclosure + dataString.toLocaleString() + defaults.csvEnclosure;
+ else {
+ result = replaceAll(csvValue, defaults.csvEnclosure, defaults.csvEnclosure + defaults.csvEnclosure);
+
+ if (result.indexOf(defaults.csvSeparator) >= 0 || /[\r\n ]/g.test(result))
+ result = defaults.csvEnclosure + result + defaults.csvEnclosure;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ var CollectCsvData = function ($rows, rowselector, length) {
+
+ $rows.each(function () {
+ trData = "";
+ ForEachVisibleCell(this, rowselector, rowIndex, length + $rows.length,
+ function (cell, row, col) {
+ trData += csvString(cell, row, col) + (defaults.type == 'tsv' ? '\t' : defaults.csvSeparator);
+ });
+ trData = $.trim(trData).substring(0, trData.length - 1);
+ if (trData.length > 0) {
+
+ if (csvData.length > 0)
+ csvData += "\n";
+
+ csvData += trData;
+ }
+ rowIndex++;
+ });
+
+ return $rows.length;
+ };
+
+ rowlength += CollectCsvData ($(el).find('thead').first().find(defaults.theadSelector), 'th,td', rowlength);
+ $(el).find('tbody').each(function() {
+ rowlength += CollectCsvData ($(this).find(defaults.tbodySelector), 'td,th', rowlength);
+ });
+ if (defaults.tfootSelector.length)
+ CollectCsvData ($(el).find('tfoot').first().find(defaults.tfootSelector), 'td,th', rowlength);
+
+ csvData += "\n";
+
+ //output
+ if (defaults.consoleLog === true)
+ console.log(csvData);
+
+ if (defaults.outputMode === 'string')
+ return csvData;
+
+ if (defaults.outputMode === 'base64')
+ return base64encode(csvData);
+
+ if (defaults.outputMode === 'window') {
+ downloadFile(false, 'data:text/' + (defaults.type == 'csv' ? 'csv' : 'plain') + ';charset=utf-8,', csvData);
+ return;
+ }
+
+ try {
+ blob = new Blob([csvData], {type: "text/" + (defaults.type == 'csv' ? 'csv' : 'plain') + ";charset=utf-8"});
+ saveAs(blob, defaults.fileName + '.' + defaults.type, (defaults.type != 'csv' || defaults.csvUseBOM === false));
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.' + defaults.type,
+ 'data:text/' + (defaults.type == 'csv' ? 'csv' : 'plain') + ';charset=utf-8,' + ((defaults.type == 'csv' && defaults.csvUseBOM)? '\ufeff' : ''),
+ csvData);
+ }
+
+ } else if (defaults.type == 'sql') {
+
+ // Header
+ rowIndex = 0;
+ var tdData = "INSERT INTO `" + defaults.tableName + "` (";
+ $hrows = $(el).find('thead').first().find(defaults.theadSelector);
+ $hrows.each(function () {
+ ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
+ function (cell, row, col) {
+ tdData += "'" + parseString(cell, row, col) + "',";
+ });
+ rowIndex++;
+ tdData = $.trim(tdData);
+ tdData = $.trim(tdData).substring(0, tdData.length - 1);
+ });
+ tdData += ") VALUES ";
+ // Row vs Column
+ $(el).find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
+ $($rows).each(function () {
+ trData = "";
+ ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
+ function (cell, row, col) {
+ trData += "'" + parseString(cell, row, col) + "',";
+ });
+ if (trData.length > 3) {
+ tdData += "(" + trData;
+ tdData = $.trim(tdData).substring(0, tdData.length - 1);
+ tdData += "),";
+ }
+ rowIndex++;
+ });
+
+ tdData = $.trim(tdData).substring(0, tdData.length - 1);
+ tdData += ";";
+
+ //output
+ if (defaults.consoleLog === true)
+ console.log(tdData);
+
+ if (defaults.outputMode === 'string')
+ return tdData;
+
+ if (defaults.outputMode === 'base64')
+ return base64encode(tdData);
+
+ try {
+ blob = new Blob([tdData], {type: "text/plain;charset=utf-8"});
+ saveAs(blob, defaults.fileName + '.sql');
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.sql',
+ 'data:application/sql;charset=utf-8,',
+ tdData);
+ }
+
+ } else if (defaults.type == 'json') {
+
+ var jsonHeaderArray = [];
+ $hrows = $(el).find('thead').first().find(defaults.theadSelector);
+ $hrows.each(function () {
+ var jsonArrayTd = [];
+
+ ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
+ function (cell, row, col) {
+ jsonArrayTd.push(parseString(cell, row, col));
+ });
+ jsonHeaderArray.push(jsonArrayTd);
+ });
+
+ var jsonArray = [];
+ $(el).find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
+ $($rows).each(function () {
+ var jsonObjectTd = {};
+
+ var colIndex = 0;
+ ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
+ function (cell, row, col) {
+ if (jsonHeaderArray.length) {
+ jsonObjectTd[jsonHeaderArray[jsonHeaderArray.length-1][colIndex]] = parseString(cell, row, col);
+ } else {
+ jsonObjectTd[colIndex] = parseString(cell, row, col);
+ }
+ colIndex++;
+ });
+ if ($.isEmptyObject(jsonObjectTd) === false)
+ jsonArray.push(jsonObjectTd);
+
+ rowIndex++;
+ });
+
+ var sdata = "";
+
+ if (defaults.jsonScope == 'head')
+ sdata = JSON.stringify(jsonHeaderArray);
+ else if (defaults.jsonScope == 'data')
+ sdata = JSON.stringify(jsonArray);
+ else // all
+ sdata = JSON.stringify({header: jsonHeaderArray, data: jsonArray});
+
+ if (defaults.consoleLog === true)
+ console.log(sdata);
+
+ if (defaults.outputMode === 'string')
+ return sdata;
+
+ if (defaults.outputMode === 'base64')
+ return base64encode(sdata);
+
+ try {
+ blob = new Blob([sdata], {type: "application/json;charset=utf-8"});
+ saveAs(blob, defaults.fileName + '.json');
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.json',
+ 'data:application/json;charset=utf-8;base64,',
+ sdata);
+ }
+
+ } else if (defaults.type === 'xml') {
+
+ rowIndex = 0;
+ var xml = '<?xml version="1.0" encoding="utf-8"?>';
+ xml += '<tabledata><fields>';
+
+ // Header
+ $hrows = $(el).find('thead').first().find(defaults.theadSelector);
+ $hrows.each(function () {
+
+ ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
+ function (cell, row, col) {
+ xml += "<field>" + parseString(cell, row, col) + "</field>";
+ });
+ rowIndex++;
+ });
+ xml += '</fields><data>';
+
+ // Row Vs Column
+ var rowCount = 1;
+ $(el).find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
+ $($rows).each(function () {
+ var colCount = 1;
+ trData = "";
+ ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
+ function (cell, row, col) {
+ trData += "<column-" + colCount + ">" + parseString(cell, row, col) + "</column-" + colCount + ">";
+ colCount++;
+ });
+ if (trData.length > 0 && trData != "<column-1></column-1>") {
+ xml += '<row id="' + rowCount + '">' + trData + '</row>';
+ rowCount++;
+ }
+
+ rowIndex++;
+ });
+ xml += '</data></tabledata>';
+
+ //output
+ if (defaults.consoleLog === true)
+ console.log(xml);
+
+ if (defaults.outputMode === 'string')
+ return xml;
+
+ if (defaults.outputMode === 'base64')
+ return base64encode(xml);
+
+ try {
+ blob = new Blob([xml], {type: "application/xml;charset=utf-8"});
+ saveAs(blob, defaults.fileName + '.xml');
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.xml',
+ 'data:application/xml;charset=utf-8;base64,',
+ xml);
+ }
+
+ } else if (defaults.type == 'excel' || defaults.type == 'xls' || defaults.type == 'word' || defaults.type == 'doc') {
+
+ var MSDocType = (defaults.type == 'excel' || defaults.type == 'xls') ? 'excel' : 'word';
+ var MSDocExt = (MSDocType == 'excel') ? 'xls' : 'doc';
+ var MSDocSchema = 'xmlns:x="urn:schemas-microsoft-com:office:' + MSDocType + '"';
+ var $tables = $(el).filter(function() {
+ return $(this).data("tableexport-display") != 'none' &&
+ ($(this).is(':visible') ||
+ $(this).data("tableexport-display") == 'always');
+ });
+ var docData = '';
+
+ $tables.each(function(){
+ var $table = $(this);
+ rowIndex = 0;
+ colNames = GetColumnNames (this);
+
+ docData += '<table><thead>';
+ // Header
+ $hrows = $table.find('thead').first().find(defaults.theadSelector);
+ $hrows.each(function() {
+ trData = "";
+ ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
+ function(cell, row, col) {
+ if (cell !== null) {
+ var thstyle = '';
+ trData += '<th';
+ for (var styles in defaults.excelstyles) {
+ if (defaults.excelstyles.hasOwnProperty(styles)) {
+ var thcss = $(cell).css(defaults.excelstyles[styles]);
+ if (thcss !== '' && thcss !='0px none rgb(0, 0, 0)' && thcss != 'rgba(0, 0, 0, 0)') {
+ thstyle += (thstyle === '') ? 'style="' : ';';
+ thstyle += defaults.excelstyles[styles] + ':' + thcss;
+ }
+ }
+ }
+ if (thstyle !== '' )
+ trData += ' ' + thstyle + '"';
+ if ($(cell).is("[colspan]"))
+ trData += ' colspan="' + $(cell).attr('colspan') + '"';
+ if ($(cell).is("[rowspan]"))
+ trData += ' rowspan="' + $(cell).attr('rowspan') + '"';
+ trData += '>' + parseString(cell, row, col) + '</th>';
+ }
+ });
+ if (trData.length > 0)
+ docData += '<tr>' + trData + '</tr>';
+ rowIndex++;
+ });
+
+ docData += '</thead><tbody>';
+ // Row Vs Column, support multiple tbodys
+ $table.find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $table.find('tfoot').find(defaults.tfootSelector));
+
+ $($rows).each(function() {
+ var $row = $(this);
+ trData = "";
+ ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
+ function(cell, row, col) {
+ if (cell !== null) {
+ var tdstyle = '';
+ var tdcss = $(cell).data("tableexport-msonumberformat");
+
+ if (typeof tdcss == 'undefined' && typeof defaults.onMsoNumberFormat === 'function')
+ tdcss = defaults.onMsoNumberFormat(cell, row, col);
+
+ if (typeof tdcss != 'undefined' && tdcss !== '')
+ tdstyle = 'style="mso-number-format:\'' + tdcss + '\'';
+
+ for (var cssStyle in defaults.excelstyles) {
+ if (defaults.excelstyles.hasOwnProperty(cssStyle)) {
+ tdcss = $(cell).css(defaults.excelstyles[cssStyle]);
+ if (tdcss === '')
+ tdcss = $row.css(defaults.excelstyles[cssStyle]);
+
+ if (tdcss !== '' && tdcss !='0px none rgb(0, 0, 0)' && tdcss != 'rgba(0, 0, 0, 0)') {
+ tdstyle += (tdstyle === '') ? 'style="' : ';';
+ tdstyle += defaults.excelstyles[cssStyle] + ':' + tdcss;
+ }
+ }
+ }
+ trData += '<td';
+ if (tdstyle !== '' )
+ trData += ' ' + tdstyle + '"';
+ if ($(cell).is("[colspan]"))
+ trData += ' colspan="' + $(cell).attr('colspan') + '"';
+ if ($(cell).is("[rowspan]"))
+ trData += ' rowspan="' + $(cell).attr('rowspan') + '"';
+ trData += '>' + parseString(cell, row, col).replace(/\n/g,'<br>') + '</td>';
+ }
+ });
+ if (trData.length > 0)
+ docData += '<tr>' + trData + '</tr>';
+ rowIndex++;
+ });
+
+ if (defaults.displayTableName)
+ docData += '<tr><td></td></tr><tr><td></td></tr><tr><td>' + parseString($('<p>' + defaults.tableName + '</p>')) + '</td></tr>';
+
+ docData += '</tbody></table>';
+
+ if (defaults.consoleLog === true)
+ console.log(docData);
+ });
+
+ var docFile = '<html xmlns:o="urn:schemas-microsoft-com:office:office" ' + MSDocSchema + ' xmlns="http://www.w3.org/TR/REC-html40">';
+ docFile += '<meta http-equiv="content-type" content="application/vnd.ms-' + MSDocType + '; charset=UTF-8">';
+ docFile += "<head>";
+ if (MSDocType === 'excel') {
+ docFile += "<!--[if gte mso 9]>";
+ docFile += "<xml>";
+ docFile += "<x:ExcelWorkbook>";
+ docFile += "<x:ExcelWorksheets>";
+ docFile += "<x:ExcelWorksheet>";
+ docFile += "<x:Name>";
+ docFile += defaults.worksheetName;
+ docFile += "</x:Name>";
+ docFile += "<x:WorksheetOptions>";
+ docFile += "<x:DisplayGridlines/>";
+ docFile += "</x:WorksheetOptions>";
+ docFile += "</x:ExcelWorksheet>";
+ docFile += "</x:ExcelWorksheets>";
+ docFile += "</x:ExcelWorkbook>";
+ docFile += "</xml>";
+ docFile += "<![endif]-->";
+ }
+ docFile += "<style>br {mso-data-placement:same-cell;}</style>";
+ docFile += "</head>";
+ docFile += "<body>";
+ docFile += docData;
+ docFile += "</body>";
+ docFile += "</html>";
+
+ if (defaults.consoleLog === true)
+ console.log(docFile);
+
+ if (defaults.outputMode === 'string')
+ return docFile;
+
+ if (defaults.outputMode === 'base64')
+ return base64encode(docFile);
+
+ try {
+ blob = new Blob([docFile], {type: 'application/vnd.ms-' + defaults.type});
+ saveAs(blob, defaults.fileName + '.' + MSDocExt);
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.' + MSDocExt,
+ 'data:application/vnd.ms-' + MSDocType + ';base64,',
+ docFile);
+ }
+
+ } else if (defaults.type == 'xlsx') {
+
+ var data = [];
+ var ranges = [];
+ rowIndex = 0;
+
+ $rows = $(el).find('thead').first().find(defaults.theadSelector);
+ $(el).find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $(el).find('tfoot').find(defaults.tfootSelector));
+
+ $($rows).each(function () {
+ var cols = [];
+ ForEachVisibleCell(this, 'th,td', rowIndex, $rows.length,
+ function (cell, row, col) {
+ if (typeof cell !== 'undefined' && cell !== null) {
+
+ var colspan = parseInt(cell.getAttribute('colspan'));
+ var rowspan = parseInt(cell.getAttribute('rowspan'));
+
+ var cellValue = parseString(cell, row, col);
+
+ if(cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
+
+ //Skip ranges
+ ranges.forEach(function(range) {
+ if(rowIndex >= range.s.r && rowIndex <= range.e.r && cols.length >= range.s.c && cols.length <= range.e.c) {
+ for(var i = 0; i <= range.e.c - range.s.c; ++i) cols.push(null);
+ }
+ });
+
+ //Handle Row Span
+ if (rowspan || colspan) {
+ rowspan = rowspan || 1;
+ colspan = colspan || 1;
+ ranges.push({s:{r:rowIndex, c:cols.length},e:{r:rowIndex+rowspan-1, c:cols.length+colspan-1}});
+ }
+
+ //Handle Value
+ cols.push(cellValue !== "" ? cellValue : null);
+
+ //Handle Colspan
+ if (colspan) for (var k = 0; k < colspan - 1; ++k) cols.push(null);
+ }
+ });
+ data.push(cols);
+ rowIndex++;
+ });
+
+ var wb = new jx_Workbook(),
+ ws = jx_createSheet(data);
+
+ // add ranges to worksheet
+ ws['!merges'] = ranges;
+
+ // add worksheet to workbook
+ wb.SheetNames.push(defaults.worksheetName);
+ wb.Sheets[defaults.worksheetName] = ws;
+
+ var wbout = XLSX.write(wb, {bookType: defaults.type, bookSST: false, type: 'binary'});
+
+ try {
+ blob = new Blob([jx_s2ab(wbout)], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8'});
+ saveAs(blob, defaults.fileName + '.' + defaults.type);
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.' + defaults.type,
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8',
+ data);
+ }
+
+ } else if (defaults.type == 'png') {
+ //html2canvas($(el)[0], {
+ // onrendered: function (canvas) {
+ html2canvas($(el)[0]).then(
+ function (canvas) {
+
+ var image = canvas.toDataURL();
+ var byteString = atob(image.substring(22)); // remove data stuff
+ var buffer = new ArrayBuffer(byteString.length);
+ var intArray = new Uint8Array(buffer);
+
+ for (var i = 0; i < byteString.length; i++)
+ intArray[i] = byteString.charCodeAt(i);
+
+ if (defaults.consoleLog === true)
+ console.log(byteString);
+
+ if (defaults.outputMode === 'string')
+ return byteString;
+
+ if (defaults.outputMode === 'base64')
+ return base64encode(image);
+
+ if (defaults.outputMode === 'window') {
+ window.open(image);
+ return;
+ }
+
+ try {
+ blob = new Blob([buffer], {type: "image/png"});
+ saveAs(blob, defaults.fileName + '.png');
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.png',
+ 'data:image/png,',
+ image);
+ }
+ //}
+ });
+
+ } else if (defaults.type == 'pdf') {
+
+ if (defaults.pdfmake.enabled === true) {
+ // pdf output using pdfmake
+ // https://github.com/bpampuch/pdfmake
+
+ var widths = [];
+ var body = [];
+ rowIndex = 0;
+
+ $hrows = $(this).find('thead').first().find(defaults.theadSelector);
+ $hrows.each(function () {
+ var h = [];
+
+ ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
+ function (cell, row, col) {
+ h.push(parseString(cell, row, col));
+ });
+
+ if (h.length)
+ body.push(h);
+
+ for(var i = widths.length; i < h.length;i++)
+ widths.push("*");
+
+ rowIndex++;
+ });
+
+ $(this).find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $(this).find('tfoot').find(defaults.tfootSelector));
+
+ $($rows).each(function () {
+ var r = [];
+
+ ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
+ function (cell, row, col) {
+ r.push(parseString(cell, row, col));
+ });
+
+ if (r.length)
+ body.push(r);
+ rowIndex++;
+ });
+
+ var docDefinition = {
+ pageOrientation: 'landscape',
+ content: [
+ {
+ table: {
+ headerRows: $hrows.length,
+ widths: widths,
+ body: body
+ }
+ }
+ ]
+ };
+ pdfMake.createPdf(docDefinition).getBuffer(function (buffer) {
+
+ try {
+ var blob = new Blob([buffer], {type: "application/pdf"});
+ saveAs(blob, defaults.fileName + '.pdf');
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.pdf',
+ 'data:application/pdf;base64,',
+ buffer);
+ }
+ });
+
+ }
+ else if (defaults.jspdf.autotable === false) {
+ // pdf output using jsPDF's core html support
+
+ var addHtmlOptions = {
+ dim: {
+ w: getPropertyUnitValue($(el).first().get(0), 'width', 'mm'),
+ h: getPropertyUnitValue($(el).first().get(0), 'height', 'mm')
+ },
+ pagesplit: false
+ };
+
+ var doc = new jsPDF(defaults.jspdf.orientation, defaults.jspdf.unit, defaults.jspdf.format);
+ doc.addHTML($(el).first(),
+ defaults.jspdf.margins.left,
+ defaults.jspdf.margins.top,
+ addHtmlOptions,
+ function () {
+ jsPdfOutput(doc);
+ });
+ //delete doc;
+ }
+ else {
+ // pdf output using jsPDF AutoTable plugin
+ // https://github.com/simonbengtsson/jsPDF-AutoTable
+
+ var teOptions = defaults.jspdf.autotable.tableExport;
+
+ // When setting jspdf.format to 'bestfit' tableExport tries to choose
+ // the minimum required paper format and orientation in which the table
+ // (or tables in multitable mode) completely fits without column adjustment
+ if (typeof defaults.jspdf.format === 'string' && defaults.jspdf.format.toLowerCase() === 'bestfit') {
+ var pageFormats = {
+ 'a0': [2383.94, 3370.39], 'a1': [1683.78, 2383.94],
+ 'a2': [1190.55, 1683.78], 'a3': [841.89, 1190.55],
+ 'a4': [595.28, 841.89]
+ };
+ var rk = '', ro = '';
+ var mw = 0;
+
+ $(el).filter(':visible').each(function () {
+ if ($(this).css('display') != 'none') {
+ var w = getPropertyUnitValue($(this).get(0), 'width', 'pt');
+
+ if (w > mw) {
+ if (w > pageFormats.a0[0]) {
+ rk = 'a0';
+ ro = 'l';
+ }
+ for (var key in pageFormats) {
+ if (pageFormats.hasOwnProperty(key)) {
+ if (pageFormats[key][1] > w) {
+ rk = key;
+ ro = 'l';
+ if (pageFormats[key][0] > w)
+ ro = 'p';
+ }
+ }
+ }
+ mw = w;
+ }
+ }
+ });
+ defaults.jspdf.format = (rk === '' ? 'a4' : rk);
+ defaults.jspdf.orientation = (ro === '' ? 'w' : ro);
+ }
+
+ // The jsPDF doc object is stored in defaults.jspdf.autotable.tableExport,
+ // thus it can be accessed from any callback function
+ teOptions.doc = new jsPDF(defaults.jspdf.orientation,
+ defaults.jspdf.unit,
+ defaults.jspdf.format);
+
+ if (teOptions.outputImages === true)
+ teOptions.images = {};
+
+ if (typeof teOptions.images != 'undefined') {
+ $(el).filter(function() {
+ return $(this).data("tableexport-display") != 'none' &&
+ ($(this).is(':visible') ||
+ $(this).data("tableexport-display") == 'always');
+ }).each(function () {
+ var rowCount = 0;
+
+ $hrows = $(this).find('thead').find(defaults.theadSelector);
+ $(this).find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $(this).find('tfoot').find(defaults.tfootSelector));
+
+ $($rows).each(function () {
+ ForEachVisibleCell(this, 'td,th', $hrows.length + rowCount, $hrows.length + $rows.length,
+ function (cell, row, col) {
+ if (typeof cell !== 'undefined' && cell !== null) {
+ var kids = $(cell).children();
+ if (typeof kids != 'undefined' && kids.length > 0)
+ collectImages (cell, kids, teOptions);
+ }
+ });
+ rowCount++;
+ });
+ });
+
+ $hrows = [];
+ $rows = [];
+ }
+
+ loadImages ( teOptions, function (imageCount) {
+
+ $(el).filter(function() {
+ return $(this).data("tableexport-display") != 'none' &&
+ ($(this).is(':visible') ||
+ $(this).data("tableexport-display") == 'always');
+ }).each(function () {
+ var colKey;
+ var rowIndex = 0;
+
+ colNames = GetColumnNames (this);
+
+ teOptions.columns = [];
+ teOptions.rows = [];
+ teOptions.rowoptions = {};
+
+ // onTable: optional callback function for every matching table that can be used
+ // to modify the tableExport options or to skip the output of a particular table
+ // if the table selector targets multiple tables
+ if (typeof teOptions.onTable === 'function')
+ if (teOptions.onTable($(this), defaults) === false)
+ return true; // continue to next iteration step (table)
+
+ // each table works with an own copy of AutoTable options
+ defaults.jspdf.autotable.tableExport = null; // avoid deep recursion error
+ var atOptions = $.extend(true, {}, defaults.jspdf.autotable);
+ defaults.jspdf.autotable.tableExport = teOptions;
+
+ atOptions.margin = {};
+ $.extend(true, atOptions.margin, defaults.jspdf.margins);
+ atOptions.tableExport = teOptions;
+
+ // Fix jsPDF Autotable's row height calculation
+ if (typeof atOptions.beforePageContent !== 'function') {
+ atOptions.beforePageContent = function (data) {
+ if (data.pageCount == 1) {
+ var all = data.table.rows.concat(data.table.headerRow);
+ all.forEach(function (row) {
+ if ( row.height > 0 ) {
+ row.height += (2 - FONT_ROW_RATIO) / 2 * row.styles.fontSize;
+ data.table.height += (2 - FONT_ROW_RATIO) / 2 * row.styles.fontSize;
+ }
+ });
+ }
+ };
+ }
+
+ if (typeof atOptions.createdHeaderCell !== 'function') {
+ // apply some original css styles to pdf header cells
+ atOptions.createdHeaderCell = function (cell, data) {
+
+ // jsPDF AutoTable plugin v2.0.14 fix: each cell needs its own styles object
+ cell.styles = $.extend({}, data.row.styles);
+
+ if (typeof teOptions.columns [data.column.dataKey] != 'undefined') {
+ var col = teOptions.columns [data.column.dataKey];
+
+ if (typeof col.rect != 'undefined') {
+ var rh;
+
+ cell.contentWidth = col.rect.width;
+
+ if (typeof teOptions.heightRatio == 'undefined' || teOptions.heightRatio === 0) {
+ if (data.row.raw [data.column.dataKey].rowspan)
+ rh = data.row.raw [data.column.dataKey].rect.height / data.row.raw [data.column.dataKey].rowspan;
+ else
+ rh = data.row.raw [data.column.dataKey].rect.height;
+
+ teOptions.heightRatio = cell.styles.rowHeight / rh;
+ }
+
+ rh = data.row.raw [data.column.dataKey].rect.height * teOptions.heightRatio;
+ if (rh > cell.styles.rowHeight)
+ cell.styles.rowHeight = rh;
+ }
+
+ if (typeof col.style != 'undefined' && col.style.hidden !== true) {
+ cell.styles.halign = col.style.align;
+ if (atOptions.styles.fillColor === 'inherit')
+ cell.styles.fillColor = col.style.bcolor;
+ if (atOptions.styles.textColor === 'inherit')
+ cell.styles.textColor = col.style.color;
+ if (atOptions.styles.fontStyle === 'inherit')
+ cell.styles.fontStyle = col.style.fstyle;
+ }
+ }
+ };
+ }
+
+ if (typeof atOptions.createdCell !== 'function') {
+ // apply some original css styles to pdf table cells
+ atOptions.createdCell = function (cell, data) {
+ var rowopt = teOptions.rowoptions [data.row.index + ":" + data.column.dataKey];
+
+ if (typeof rowopt != 'undefined' &&
+ typeof rowopt.style != 'undefined' &&
+ rowopt.style.hidden !== true) {
+ cell.styles.halign = rowopt.style.align;
+ if (atOptions.styles.fillColor === 'inherit')
+ cell.styles.fillColor = rowopt.style.bcolor;
+ if (atOptions.styles.textColor === 'inherit')
+ cell.styles.textColor = rowopt.style.color;
+ if (atOptions.styles.fontStyle === 'inherit')
+ cell.styles.fontStyle = rowopt.style.fstyle;
+ }
+ };
+ }
+
+ if (typeof atOptions.drawHeaderCell !== 'function') {
+ atOptions.drawHeaderCell = function (cell, data) {
+ var colopt = teOptions.columns [data.column.dataKey];
+
+ if ((colopt.style.hasOwnProperty("hidden") !== true || colopt.style.hidden !== true) &&
+ colopt.rowIndex >= 0 )
+ return prepareAutoTableText (cell, data, colopt);
+ else
+ return false; // cell is hidden
+ };
+ }
+
+ if (typeof atOptions.drawCell !== 'function') {
+ atOptions.drawCell = function (cell, data) {
+ var rowopt = teOptions.rowoptions [data.row.index + ":" + data.column.dataKey];
+ if ( prepareAutoTableText (cell, data, rowopt) ) {
+
+ teOptions.doc.rect(cell.x, cell.y, cell.width, cell.height, cell.styles.fillStyle);
+
+ if (typeof rowopt != 'undefined' && typeof rowopt.kids != 'undefined' && rowopt.kids.length > 0) {
+
+ var dh = cell.height / rowopt.rect.height;
+ if ( dh > teOptions.dh || typeof teOptions.dh == 'undefined' )
+ teOptions.dh = dh;
+ teOptions.dw = cell.width / rowopt.rect.width;
+
+ drawCellElements (cell, rowopt.kids, teOptions);
+ }
+ teOptions.doc.autoTableText(cell.text, cell.textPos.x, cell.textPos.y, {
+ halign: cell.styles.halign,
+ valign: cell.styles.valign
+ });
+ }
+ return false;
+ };
+ }
+
+ // collect header and data rows
+ teOptions.headerrows = [];
+ $hrows = $(this).find('thead').find(defaults.theadSelector);
+ $hrows.each(function () {
+ colKey = 0;
+
+ teOptions.headerrows[rowIndex] = [];
+
+ ForEachVisibleCell(this, 'th,td', rowIndex, $hrows.length,
+ function (cell, row, col) {
+ var obj = getCellStyles (cell);
+ obj.title = parseString(cell, row, col);
+ obj.key = colKey++;
+ obj.rowIndex = rowIndex;
+ teOptions.headerrows[rowIndex].push(obj);
+ });
+ rowIndex++;
+ });
+
+ if (rowIndex > 0) {
+ // iterate through last row
+ $.each(teOptions.headerrows[rowIndex-1], function () {
+ var obj = this;
+ if (rowIndex > 1 && this.rect === null)
+ obj = teOptions.headerrows[rowIndex-2][this.key];
+ if (obj !== null)
+ teOptions.columns.push(obj);
+ });
+ }
+
+ var rowCount = 0;
+ $rows = [];
+ $(this).find('tbody').each(function() {
+ $rows.push.apply ($rows, $(this).find(defaults.tbodySelector));
+ });
+ if (defaults.tfootSelector.length)
+ $rows.push.apply ($rows, $(this).find('tfoot').find(defaults.tfootSelector));
+ $($rows).each(function () {
+ var rowData = [];
+ colKey = 0;
+
+ ForEachVisibleCell(this, 'td,th', rowIndex, $hrows.length + $rows.length,
+ function (cell, row, col) {
+ if (typeof teOptions.columns[colKey] === 'undefined') {
+ // jsPDF-Autotable needs columns. Thus define hidden ones for tables without thead
+ var obj = {
+ title: '',
+ key: colKey,
+ style: {
+ hidden: true
+ }
+ };
+ teOptions.columns.push(obj);
+ }
+ if (typeof cell !== 'undefined' && cell !== null) {
+ var obj = getCellStyles (cell);
+ obj.kids = $(cell).children();
+ teOptions.rowoptions [rowCount + ":" + colKey++] = obj;
+ }
+ else {
+ var obj = $.extend(true, {}, teOptions.rowoptions [rowCount + ":" + (colKey-1)]);
+ obj.colspan = -1;
+ teOptions.rowoptions [rowCount + ":" + colKey++] = obj;
+ }
+
+ rowData.push(parseString(cell, row, col));
+ });
+ if (rowData.length) {
+ teOptions.rows.push(rowData);
+ rowCount++;
+ }
+ rowIndex++;
+ });
+
+ // onBeforeAutotable: optional callback function before calling
+ // jsPDF AutoTable that can be used to modify the AutoTable options
+ if (typeof teOptions.onBeforeAutotable === 'function')
+ teOptions.onBeforeAutotable($(this), teOptions.columns, teOptions.rows, atOptions);
+
+ teOptions.doc.autoTable(teOptions.columns, teOptions.rows, atOptions);
+
+ // onAfterAutotable: optional callback function after returning
+ // from jsPDF AutoTable that can be used to modify the AutoTable options
+ if (typeof teOptions.onAfterAutotable === 'function')
+ teOptions.onAfterAutotable($(this), atOptions);
+
+ // set the start position for the next table (in case there is one)
+ defaults.jspdf.autotable.startY = teOptions.doc.autoTableEndPosY() + atOptions.margin.top;
+
+ });
+
+ jsPdfOutput(teOptions.doc);
+
+ if (typeof teOptions.headerrows != 'undefined')
+ teOptions.headerrows.length = 0;
+ if (typeof teOptions.columns != 'undefined')
+ teOptions.columns.length = 0;
+ if (typeof teOptions.rows != 'undefined')
+ teOptions.rows.length = 0;
+ delete teOptions.doc;
+ teOptions.doc = null;
+ });
+ }
+ }
+
+ function FindColObject (objects, colIndex, rowIndex) {
+ var result = null;
+ $.each(objects, function () {
+ if (this.rowIndex == rowIndex && this.key == colIndex) {
+ result = this;
+ return false;
+ }
+ });
+ return result;
+ }
+
+ function GetColumnNames (table) {
+ var result = [];
+ $(table).find('thead').first().find('th').each(function(index, el) {
+ if ($(el).attr("data-field") !== undefined)
+ result[index] = $(el).attr("data-field");
+ else
+ result[index] = index.toString();
+ });
+ return result;
+ }
+
+ function isColumnIgnored($row, colIndex) {
+ var result = false;
+ if (defaults.ignoreColumn.length > 0) {
+ if (typeof defaults.ignoreColumn[0] == 'string') {
+ if (colNames.length > colIndex && typeof colNames[colIndex] != 'undefined')
+ if ($.inArray(colNames[colIndex], defaults.ignoreColumn) != -1)
+ result = true;
+ }
+ else if (typeof defaults.ignoreColumn[0] == 'number') {
+ if ($.inArray(colIndex, defaults.ignoreColumn) != -1 ||
+ $.inArray(colIndex-$row.length, defaults.ignoreColumn) != -1)
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ function ForEachVisibleCell(tableRow, selector, rowIndex, rowCount, cellcallback) {
+ if ($.inArray(rowIndex, defaults.ignoreRow) == -1 &&
+ $.inArray(rowIndex-rowCount, defaults.ignoreRow) == -1) {
+
+ var $row = $(tableRow).filter(function() {
+ return $(this).data("tableexport-display") != 'none' &&
+ ($(this).is(':visible') ||
+ $(this).data("tableexport-display") == 'always' ||
+ $(this).closest('table').data("tableexport-display") == 'always');
+ }).find(selector);
+
+ var rowColspan = 0;
+ var rowColIndex = 0;
+
+ $row.each(function (colIndex) {
+ if ($(this).data("tableexport-display") == 'always' ||
+ ($(this).css('display') != 'none' &&
+ $(this).css('visibility') != 'hidden' &&
+ $(this).data("tableexport-display") != 'none')) {
+ if (isColumnIgnored($row, colIndex) === false) {
+ if (typeof (cellcallback) === "function") {
+ var c, Colspan = 0;
+ var r, Rowspan = 0;
+
+ // handle rowspans from previous rows
+ if (typeof rowspans[rowIndex] != 'undefined' && rowspans[rowIndex].length > 0) {
+ for (c = 0; c <= colIndex; c++) {
+ if (typeof rowspans[rowIndex][c] != 'undefined') {
+ cellcallback(null, rowIndex, c);
+ delete rowspans[rowIndex][c];
+ colIndex++;
+ }
+ }
+ }
+ rowColIndex = colIndex;
+
+ if ($(this).is("[colspan]")) {
+ Colspan = parseInt($(this).attr('colspan'));
+ rowColspan += Colspan > 0 ? Colspan - 1 : 0;
+ }
+
+ if ($(this).is("[rowspan]"))
+ Rowspan = parseInt($(this).attr('rowspan'));
+
+ // output content of current cell
+ cellcallback(this, rowIndex, colIndex);
+
+ // handle colspan of current cell
+ for (c = 0; c < Colspan - 1; c++)
+ cellcallback(null, rowIndex, colIndex + c);
+
+ // store rowspan for following rows
+ if (Rowspan) {
+ for (r = 1; r < Rowspan; r++) {
+ if (typeof rowspans[rowIndex + r] == 'undefined')
+ rowspans[rowIndex + r] = [];
+
+ rowspans[rowIndex + r][colIndex + rowColspan] = "";
+
+ for (c = 1; c < Colspan; c++)
+ rowspans[rowIndex + r][colIndex + rowColspan - c] = "";
+ }
+ }
+ }
+ }
+ }
+ });
+ // handle rowspans from previous rows
+ if (typeof rowspans[rowIndex] != 'undefined' && rowspans[rowIndex].length > 0) {
+ for (var c = 0; c <= rowspans[rowIndex].length; c++) {
+ if (typeof rowspans[rowIndex][c] != 'undefined') {
+ cellcallback(null, rowIndex, c);
+ delete rowspans[rowIndex][c];
+ }
+ }
+ }
+ }
+ }
+
+ function jsPdfOutput(doc) {
+ if (defaults.consoleLog === true)
+ console.log(doc.output());
+
+ if (defaults.outputMode === 'string')
+ return doc.output();
+
+ if (defaults.outputMode === 'base64')
+ return base64encode(doc.output());
+
+ if (defaults.outputMode === 'window') {
+ window.open(URL.createObjectURL(doc.output("blob")));
+ return;
+ }
+
+ try {
+ var blob = doc.output('blob');
+ saveAs(blob, defaults.fileName + '.pdf');
+ }
+ catch (e) {
+ downloadFile(defaults.fileName + '.pdf',
+ 'data:application/pdf;base64,',
+ doc.output());
+ }
+ }
+
+ function prepareAutoTableText (cell, data, cellopt) {
+ var cs = 0;
+ if ( typeof cellopt != 'undefined' )
+ cs = cellopt.colspan;
+
+ if ( cs >= 0 ) {
+ // colspan handling
+ var cellWidth = cell.width;
+ var textPosX = cell.textPos.x;
+ var i = data.table.columns.indexOf(data.column);
+
+ for (var c = 1; c < cs; c++) {
+ var column = data.table.columns[i+c];
+ cellWidth += column.width;
+ }
+
+ if ( cs > 1 ) {
+ if ( cell.styles.halign === 'right' )
+ textPosX = cell.textPos.x + cellWidth - cell.width;
+ else if ( cell.styles.halign === 'center' )
+ textPosX = cell.textPos.x + (cellWidth - cell.width) / 2;
+ }
+
+ cell.width = cellWidth;
+ cell.textPos.x = textPosX;
+
+ if ( typeof cellopt != 'undefined' && cellopt.rowspan > 1 )
+ cell.height = cell.height * cellopt.rowspan;
+
+ // fix jsPDF's calculation of text position
+ if ( cell.styles.valign === 'middle' || cell.styles.valign === 'bottom' ) {
+ var splittedText = typeof cell.text === 'string' ? cell.text.split(/\r\n|\r|\n/g) : cell.text;
+ var lineCount = splittedText.length || 1;
+ if (lineCount > 2)
+ cell.textPos.y -= ((2 - FONT_ROW_RATIO) / 2 * data.row.styles.fontSize) * (lineCount-2) / 3 ;
+ }
+ return true;
+ }
+ else
+ return false; // cell is hidden (colspan = -1), don't draw it
+ }
+
+ function collectImages (cell, elements, teOptions) {
+ if (typeof teOptions.images != 'undefined') {
+ elements.each(function () {
+ var kids = $(this).children();
+
+ if ( $(this).is("img") ) {
+ var hash = strHashCode(this.src);
+
+ teOptions.images[hash] = { url: this.src,
+ src: this.src };
+ }
+
+ if (typeof kids != 'undefined' && kids.length > 0)
+ collectImages (cell, kids, teOptions);
+ });
+ }
+ }
+
+ function loadImages (teOptions, callback) {
+ var i;
+ var imageCount = 0;
+ var x = 0;
+
+ function done() {
+ callback(imageCount);
+ }
+ function loadImage(image) {
+ if (!image.url)
+ return;
+ var img = new Image();
+ imageCount = ++x;
+ img.crossOrigin = 'Anonymous';
+ img.onerror = img.onload = function () {
+ if(img.complete) {
+
+ if (img.src.indexOf('data:image/') === 0) {
+ img.width = image.width || img.width || 0;
+ img.height = image.height || img.height || 0;
+ }
+
+ if (img.width + img.height) {
+ var canvas = document.createElement("canvas");
+ var ctx = canvas.getContext("2d");
+
+ canvas.width = img.width;
+ canvas.height = img.height;
+ ctx.drawImage( img, 0, 0 );
+
+ image.src = canvas.toDataURL("image/jpeg");
+ }
+ }
+ if(!--x)
+ done();
+ };
+ img.src = image.url;
+ }
+
+ if (typeof teOptions.images != 'undefined') {
+ for (i in teOptions.images)
+ if (teOptions.images.hasOwnProperty(i))
+ loadImage(teOptions.images[i]);
+ }
+
+ return x || done();
+ }
+
+ function drawCellElements (cell, elements, teOptions) {
+ elements.each(function () {
+ var kids = $(this).children();
+
+ if ( $(this).is("div") ) {
+ var bcolor = rgb2array(getStyle(this, 'background-color'), [255, 255, 255]);
+ var lcolor = rgb2array(getStyle(this, 'border-top-color'), [0, 0, 0]);
+ var lwidth = getPropertyUnitValue(this, 'border-top-width', defaults.jspdf.unit);
+
+ var r = this.getBoundingClientRect();
+ var ux = this.offsetLeft * teOptions.dw;
+ var uy = this.offsetTop * teOptions.dh;
+ var uw = r.width * teOptions.dw;
+ var uh = r.height * teOptions.dh;
+
+ teOptions.doc.setDrawColor.apply (undefined, lcolor);
+ teOptions.doc.setFillColor.apply (undefined, bcolor);
+ teOptions.doc.setLineWidth (lwidth);
+ teOptions.doc.rect(cell.x + ux, cell.y + uy, uw, uh, lwidth ? "FD" : "F");
+ }
+ else if ( $(this).is("img") ) {
+ if (typeof teOptions.images != 'undefined') {
+ var hash = strHashCode(this.src);
+ var image = teOptions.images[hash];
+
+ if (typeof image != 'undefined') {
+
+ var arCell = cell.width / cell.height;
+ var arImg = this.width / this.height;
+ var imgWidth = cell.width;
+ var imgHeight = cell.height;
+ var uy = 0;
+
+ if (arImg < arCell) {
+ imgHeight = Math.min (cell.height, this.height);
+ imgWidth = this.width * imgHeight / this.height;
+ }
+ else if (arImg > arCell) {
+ imgWidth = Math.min (cell.width, this.width);
+ imgHeight = this.height * imgWidth / this.width;
+ }
+
+ if (imgHeight < cell.height)
+ uy = (cell.height - imgHeight) / 2;
+
+ teOptions.doc.addImage (image.src, cell.textPos.x, cell.y + uy, imgWidth, imgHeight);
+ cell.textPos.x += imgWidth;
+ }
+ }
+ }
+
+ if (typeof kids != 'undefined' && kids.length > 0)
+ drawCellElements (cell, kids, teOptions);
+ });
+ }
+
+ function escapeRegExp(string) {
+ return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
+ }
+
+ function replaceAll(string, find, replace) {
+ return string.replace(new RegExp(escapeRegExp(find), 'g'), replace);
+ }
+
+ function parseNumber(value) {
+ value = value || "0";
+ value = replaceAll(value, defaults.numbers.html.thousandsSeparator, '');
+ value = replaceAll(value, defaults.numbers.html.decimalMark, '.');
+
+ return typeof value === "number" || jQuery.isNumeric(value) !== false ? value : false;
+ }
+
+ function parseString(cell, rowIndex, colIndex) {
+ var result = '';
+
+ if (cell !== null) {
+ var $cell = $(cell);
+ var htmlData;
+
+ if ($cell[0].hasAttribute("data-tableexport-value"))
+ htmlData = $cell.data("tableexport-value");
+ else {
+ htmlData = $cell.html();
+
+ if (htmlData != '') {
+ var html = $.parseHTML( htmlData );
+
+ htmlData = '';
+ $.each( html, function() {
+ if ( $(this).is("input") )
+ htmlData += $cell.find('input').val();
+ else if ( $(this).is("select") )
+ htmlData += $cell.find('select option:selected').text();
+ else {
+ htmlData += $cell.html();
+ return false;
+ }
+ });
+ }
+ }
+
+ if (typeof defaults.onCellHtmlData === 'function')
+ htmlData = defaults.onCellHtmlData($cell, rowIndex, colIndex, htmlData);
+
+ if (defaults.htmlContent === true) {
+ result = $.trim(htmlData);
+ }
+ else {
+ var text = htmlData.replace(/\n/g,'\u2028').replace(/<br\s*[\/]?>/gi, '\u2060');
+ var obj = $('<div/>').html(text).contents();
+ text = '';
+ $.each(obj.text().split("\u2028"), function(i, v) {
+ if (i > 0)
+ text += " ";
+ text += $.trim(v);
+ });
+
+ $.each(text.split("\u2060"), function(i, v) {
+ if (i > 0)
+ result += "\n";
+ result += $.trim(v).replace(/\u00AD/g, ""); // remove soft hyphens
+ });
+
+ if (defaults.numbers.html.decimalMark != defaults.numbers.output.decimalMark ||
+ defaults.numbers.html.thousandsSeparator != defaults.numbers.output.thousandsSeparator) {
+ var number = parseNumber (result);
+
+ if ( number !== false ) {
+ var frac = ("" + number).split('.');
+ if ( frac.length == 1 )
+ frac[1] = "";
+ var mod = frac[0].length > 3 ? frac[0].length % 3 : 0;
+
+ result = (number < 0 ? "-" : "") +
+ (defaults.numbers.output.thousandsSeparator ? ((mod ? frac[0].substr(0, mod) + defaults.numbers.output.thousandsSeparator : "") + frac[0].substr(mod).replace(/(\d{3})(?=\d)/g, "$1" + defaults.numbers.output.thousandsSeparator)) : frac[0]) +
+ (frac[1].length ? defaults.numbers.output.decimalMark + frac[1] : "");
+ }
+ }
+ }
+
+ if (defaults.escape === true) {
+ result = escape(result);
+ }
+
+ if (typeof defaults.onCellData === 'function') {
+ result = defaults.onCellData($cell, rowIndex, colIndex, result);
+ }
+ }
+
+ return result;
+ }
+
+ function hyphenate(a, b, c) {
+ return b + "-" + c.toLowerCase();
+ }
+
+ function rgb2array(rgb_string, default_result) {
+ var re = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/;
+ var bits = re.exec(rgb_string);
+ var result = default_result;
+ if (bits)
+ result = [ parseInt(bits[1]), parseInt(bits[2]), parseInt(bits[3]) ];
+ return result;
+ }
+
+ function getCellStyles (cell) {
+ var a = getStyle(cell, 'text-align');
+ var fw = getStyle(cell, 'font-weight');
+ var fs = getStyle(cell, 'font-style');
+ var f = '';
+ if (a == 'start')
+ a = getStyle(cell, 'direction') == 'rtl' ? 'right' : 'left';
+ if (fw >= 700)
+ f = 'bold';
+ if (fs == 'italic')
+ f += fs;
+ if (f === '')
+ f = 'normal';
+
+ var result = {
+ style: {
+ align: a,
+ bcolor: rgb2array(getStyle(cell, 'background-color'), [255, 255, 255]),
+ color: rgb2array(getStyle(cell, 'color'), [0, 0, 0]),
+ fstyle: f
+ },
+ colspan: (parseInt($(cell).attr('colspan')) || 0),
+ rowspan: (parseInt($(cell).attr('rowspan')) || 0)
+ };
+
+ if (cell !== null) {
+ var r = cell.getBoundingClientRect();
+ result.rect = {
+ width: r.width,
+ height: r.height
+ };
+ }
+
+ return result;
+ }
+
+ // get computed style property
+ function getStyle(target, prop) {
+ try {
+ if (window.getComputedStyle) { // gecko and webkit
+ prop = prop.replace(/([a-z])([A-Z])/, hyphenate); // requires hyphenated, not camel
+ return window.getComputedStyle(target, null).getPropertyValue(prop);
+ }
+ if (target.currentStyle) { // ie
+ return target.currentStyle[prop];
+ }
+ return target.style[prop];
+ }
+ catch (e) {
+ }
+ return "";
+ }
+
+ function getUnitValue(parent, value, unit) {
+ var baseline = 100; // any number serves
+
+ var temp = document.createElement("div"); // create temporary element
+ temp.style.overflow = "hidden"; // in case baseline is set too low
+ temp.style.visibility = "hidden"; // no need to show it
+
+ parent.appendChild(temp); // insert it into the parent for em, ex and %
+
+ temp.style.width = baseline + unit;
+ var factor = baseline / temp.offsetWidth;
+
+ parent.removeChild(temp); // clean up
+
+ return (value * factor);
+ }
+
+ function getPropertyUnitValue(target, prop, unit) {
+ var value = getStyle(target, prop); // get the computed style value
+
+ var numeric = value.match(/\d+/); // get the numeric component
+ if (numeric !== null) {
+ numeric = numeric[0]; // get the string
+
+ return getUnitValue (target.parentElement, numeric, unit);
+ }
+ return 0;
+ }
+
+ function jx_Workbook() {
+ if(!(this instanceof jx_Workbook)) return new jx_Workbook();
+ this.SheetNames = [];
+ this.Sheets = {};
+ }
+
+ function jx_s2ab(s) {
+ var buf = new ArrayBuffer(s.length);
+ var view = new Uint8Array(buf);
+ for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
+ return buf;
+ }
+
+ function jx_datenum(v, date1904) {
+ if(date1904) v+=1462;
+ var epoch = Date.parse(v);
+ return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
+ }
+
+ function jx_createSheet(data) {
+ var ws = {};
+ var range = {s: {c:10000000, r:10000000}, e: {c:0, r:0 }};
+ for(var R = 0; R != data.length; ++R) {
+ for(var C = 0; C != data[R].length; ++C) {
+ if(range.s.r > R) range.s.r = R;
+ if(range.s.c > C) range.s.c = C;
+ if(range.e.r < R) range.e.r = R;
+ if(range.e.c < C) range.e.c = C;
+ var cell = {v: data[R][C] };
+ if(cell.v === null) continue;
+ var cell_ref = XLSX.utils.encode_cell({c:C,r:R});
+
+ if(typeof cell.v === 'number') cell.t = 'n';
+ else if(typeof cell.v === 'boolean') cell.t = 'b';
+ else if(cell.v instanceof Date) {
+ cell.t = 'n'; cell.z = XLSX.SSF._table[14];
+ cell.v = jx_datenum(cell.v);
+ }
+ else cell.t = 's';
+ ws[cell_ref] = cell;
+ }
+ }
+
+ if(range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
+ return ws;
+ }
+
+ function strHashCode (str) {
+ var hash = 0, i, chr, len;
+ if (str.length === 0) return hash;
+ for (i = 0, len = str.length; i < len; i++) {
+ chr = str.charCodeAt(i);
+ hash = ((hash << 5) - hash) + chr;
+ hash |= 0; // Convert to 32bit integer
+ }
+ return hash;
+ }
+
+ function downloadFile(filename, header, data) {
+
+ var ua = window.navigator.userAgent;
+ if (filename !== false && (ua.indexOf("MSIE ") > 0 || !!ua.match(/Trident.*rv\:11\./))) {
+ if (window.navigator.msSaveOrOpenBlob)
+ window.navigator.msSaveOrOpenBlob(new Blob([data]), filename);
+ else {
+ // Internet Explorer (<= 9) workaround by Darryl (https://github.com/dawiong/tableExport.jquery.plugin)
+ // based on sampopes answer on http://stackoverflow.com/questions/22317951
+ // ! Not working for json and pdf format !
+ var frame = document.createElement("iframe");
+
+ if (frame) {
+ document.body.appendChild(frame);
+ frame.setAttribute("style", "display:none");
+ frame.contentDocument.open("txt/html", "replace");
+ frame.contentDocument.write(data);
+ frame.contentDocument.close();
+ frame.focus();
+
+ frame.contentDocument.execCommand("SaveAs", true, filename);
+ document.body.removeChild(frame);
+ }
+ }
+ }
+ else {
+ var DownloadLink = document.createElement('a');
+
+ if (DownloadLink) {
+ DownloadLink.style.display = 'none';
+ if (filename !== false)
+ DownloadLink.download = filename;
+ else
+ DownloadLink.target = '_blank';
+
+ if (header.toLowerCase().indexOf("base64,") >= 0)
+ DownloadLink.href = header + base64encode(data);
+ else
+ DownloadLink.href = header + encodeURIComponent(data);
+
+ document.body.appendChild(DownloadLink);
+
+ if (document.createEvent) {
+ if (DownloadEvt === null)
+ DownloadEvt = document.createEvent('MouseEvents');
+
+ DownloadEvt.initEvent('click', true, false);
+ DownloadLink.dispatchEvent(DownloadEvt);
+ }
+ else if (document.createEventObject)
+ DownloadLink.fireEvent('onclick');
+ else if (typeof DownloadLink.onclick == 'function')
+ DownloadLink.onclick();
+
+ document.body.removeChild(DownloadLink);
+ }
+ }
+ }
+
+ function utf8Encode(string) {
+ string = string.replace(/\x0d\x0a/g, "\x0a");
+ var utftext = "";
+ for (var n = 0; n < string.length; n++) {
+ var c = string.charCodeAt(n);
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if ((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ }
+ return utftext;
+ }
+
+ function base64encode(input) {
+ var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+ input = utf8Encode(input);
+ while (i < input.length) {
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+ output = output +
+ keyStr.charAt(enc1) + keyStr.charAt(enc2) +
+ keyStr.charAt(enc3) + keyStr.charAt(enc4);
+ }
+ return output;
+ }
+
+ return this;
+ }
+ });
+})(jQuery);