<commit_before>/* --------------------------------------- *
* Guerrilla UI                             *
* @module: Charm, timed animations based   *
* on scrolling and page location           *
* ---------------------------------------- */
$.GUI().use(function(gui) {

    return {

        load: function(api) {
            var Charm;

            Charm = (function() {

                function Charm(options) {

                    if (!options || options === null) {
                        options = {};
                    }

                    this.start = api.broker.bind(this.start, this);
                    this.scrollHandler = api.broker.bind(this.scrollHandler, this);
                    this.scrollCallback = api.broker.bind(this.scrollCallback, this);
                    this.resetAnimation = api.broker.bind(this.resetAnimation, this);

                    this.config = this.extend(options, this.defaults);
                    this.charmEvent = this.Event.create(this.config.boxClass);

                    this.scrolled = true;
                    this.animationNameCache = api.dom.map;
                }

                Charm.prototype.defaults = {
                    boxClass: 'charm',
                    animateClass: 'animated',
                    offset: 0,
                    mobile: true,
                    live: true,
                    callback: null,
                    scrollContainer: null
                };

                Charm.prototype.extend = function(custom, defaults) {
                    var key, value;

                    for (key in defaults) {

                        value = defaults[key];

                        if (custom[key] !== null) {
                            custom[key] = value;
                        }
                    }

                    return custom;
                };

                Charm.prototype.vendors = ["moz", "webkit"];

                Charm.prototype.Event = api.dom.Event;

                Charm.prototype.disabled = function() {
                    return !this.config.mobile && this.Event.isMobile(navigator.userAgent);
                };

                Charm.prototype.init = function() {
                    var ref;

                    this.element = document.documentElement;

                    if ((ref = document.readyState) === "interactive" || ref === "complete") {

                        this.start();

                    } else {

                        this.Event.add(document, 'DOMContentLoaded', this.start);
                    }

                    this.finished = [];

                    return this.finished;
                };

                Charm.prototype.start = function() {
                    var _this = this, box, j, length, _ref;

                    this.stopped = false;

                    this.boxes = (function() {
                        var i = 0, length, _ref, results = [];

                        _ref = this.element.querySelectorAll("." + this.config.boxClass);

                        length = _ref.length;

                        if (length > 0) {

                            do {
                                box = _ref[i];

                                results.push(box);

                                i++;
                            } while (--length);
                        }

                        return results;

                    }).call(this);

                    this.all = (function() {
                        var j, len, ref, results;

                        ref = this.boxes;
                        results = [];

                        for (j = 0, len = ref.length; j < len; j++) {
                          box = ref[j];
                          results.push(box);
                        }

                        return results;

                    }).call(this);

                    if(this.boxes.length){

                        if(this.disabled()){

                            this.resetStyle();

                        }else{
                            ref = this.boxes;

                            for(j = 0, length = ref.length; j < length; j++){
                                box = ref[j];
                                this.applyStyle(box, true);
                            }
                        }
                    }

                    if (!this.disabled()) {
                        this.Event.add(window, 'scroll', this.scrollHandler);
                        this.Event.add(window, 'resize', this.scrollHandler);

                        this.interval = window.setInterval(this.scrollCallback, 50);
                    }

                    if (this.config.live) {

                        return new MutationObserver((function(_this) {
                            return function(records) {
                                var i = 0, length, node, record, results = [];

                                for (length = records.length; i < length; i++) {
                                    record = records[i];

                                    results.push((function() {
                                        var l, len2, ref1, results1;

                                        ref1 = record.addedNodes || [];
                                        results1 = [];

                                        for(l = 0, len2 = ref1.length; l < len2; l++){
                                            node = ref1[l];
                                            results1.push(this.doSync(node));
                                        }

                                        return results1;

                                    }).call(_this));
                                }

                                return results;
                            };
                        })(this)).observe(document.body, {
                            childList: true,
                            subtree: true
                        });
                    }
                };

                Charm.prototype.stop = function() {
                    this.stopped = true;

                    this.Event.remove(window, 'scroll', this.scrollHandler);
                    this.Event.remove(window, 'resize', this.scrollHandler);

                    if (this.interval !== null) {
                        return window.clearInterval(this.interval);
                    }
                };

                /**
                 * Check for MutationObserver support
                 *
                 * @param element {object} - dom element object
                 * @return sync {function} - attempt to sync with dom element
                **/
                Charm.prototype.sync = function(element) {
                    if (MutationObserver.notSupported) {
                        return this.doSync(this.element);
                    }
                };

                Charm.prototype.doSync = function(element) {
                    var box, i = 0, length, ref, results = [];

                    if (element === null) {
                        element = this.element;
                    }

                    if (element.nodeType !== 1) {
                        return;
                    }

                    element = element.parentNode || element;
                    ref = element.querySelectorAll("." + this.config.boxClass);

                    for (length = ref.length; i < length; i++) {
                        box = ref[i];

                        if (indexOf.call(this.all, box) < 0) {
                            this.boxes.push(box);
                            this.all.push(box);

                            if (this.stopped || this.disabled()) {
                                this.resetStyle();
                            } else {
                                this.applyStyle(box, true);
                            }

                            results.push(this.scrolled = true);

                        } else {

                            results.push(void 0);
                        }
                    }

                    return results;
                };

                /**
                 * Add needed show events to reset animations
                 *
                 * @param box {object} - the box element with animation props
                 * @return box {object} - updated box element with added events
                **/
                Charm.prototype.show = function(box) {
                    this.applyStyle(box);

                    box.className = box.className + " " + this.config.animateClass;

                    if (this.config.callback !== null) {
                        this.config.callback(box);
                    }

                    this.Event.fire(box, this.charmEvent);

                    this.Event.add(box, 'animationend', this.resetAnimation);
                    this.Event.add(box, 'oanimationend', this.resetAnimation);
                    this.Event.add(box, 'webkitAnimationEnd', this.resetAnimation);
                    this.Event.add(box, 'MSAnimationEnd', this.resetAnimation);

                    return box;
                };

                Charm.prototype.applyStyle = function(box, hidden) {
                    var delay, duration, iteration;

                    duration = box.getAttribute('data-charm-duration');
                    delay = box.getAttribute('data-charm-delay');
                    iteration = box.getAttribute('data-charm-iteration');

                    return this.animate((function(_this) {

                        return function() {
                            return _this.customStyle(box, hidden, duration, delay, iteration);
                        };
                    })(this));
                };

                Charm.prototype.animate = (function() {
                    if ('requestAnimationFrame' in window) {
                        return function(callback) {
                            return window.requestAnimationFrame(callback);
                        };

                    } else {
                        return function(callback) {
                            return callback();
                        };
                    }
                })();

                Charm.prototype.resetStyle = function() {
                    var box, i = 0, length, ref, results = [];

                    ref = this.boxes;

                    for (length = ref.length; i < length; i++) {
                        box = ref[i];
                        results.push(box.style.visibility = 'visible');
                    }

                    return results;
                };

                Charm.prototype.resetAnimation = function(e) {
                    var target;

                    if (e.type.toLowerCase().indexOf('animationend') >= 0) {
                        target = e.target || e.srcElement;

                        target.className = target.className.replace(this.config.animateClass, '').trim();

                        return target.className;
                    }
                };

                Charm.prototype.customStyle = function(box, hidden, duration, delay, iteration) {
                    if (hidden) {
                        this.cacheAnimationName(box);
                    }

                    box.style.visibility = hidden ? 'hidden' : 'visible';

                    if (duration) {
                        this.vendorSet(box.style, {
                            animationDuration: duration
                        });
                    }

                    if (delay) {
                        this.vendorSet(box.style, {
                            animationDelay: delay
                        });
                    }

                    if (iteration) {
                        this.vendorSet(box.style, {
                            animationIterationCount: iteration
                        });
                    }

                    this.vendorSet(box.style, {
                        animationName: hidden ? 'none' : this.cachedAnimationName(box)
                    });

                    return box;
                };

                Charm.prototype.vendorSet = function(elem, properties) {
                    var name, results = [], value, vendor;

                    for (name in properties) {
                        value = properties[name];
                        elem["" + name] = value;

                        results.push((function() {
                            var i, ref, results1;

                            ref = this.vendors;
                            results1 = [];

                            for (i = 0; i < ref.length; i++) {

                                vendor = ref[i];
                                results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value);
                            }

                            return results1;

                        }).call(this));
                    }

                    return results;
                };

                Charm.prototype.vendorCSS = function(elem, property) {
                    var i = 0, length, ref, result, style, vendor;

                    style = window.getComputedStyle(elem);
                    result = style.getPropertyCSSValue(property);

                    ref = this.vendors;

                    for (length = ref.length; i < len; i++) {
                        vendor = ref[i];
                        result = result || style.getPropertyCSSValue("-" + vendor + "-" + property);
                    }

                    return result;
                };

                Charm.prototype.animationName = function(box) {
                    var animationName;

                    try {

                        animationName = this.vendorCSS(box, 'animation-name').cssText;

                    } catch (_error) {

                        animationName = window.getComputedStyle(box).getPropertyValue('animation-name');
                    }

                    if (animationName === 'none') {

                        return '';

                    } else {

                        return animationName;
                    }
                };

                Charm.prototype.cacheAnimationName = function(box) {
                    return this.animationNameCache.set(box, this.animationName(box));
                };

                Charm.prototype.cachedAnimationName = function(box) {
                    return this.animationNameCache.get(box);
                };

                Charm.prototype.scrollHandler = function() {
                    this.scrolled = true;

                    return this.scrolled;
                };

                Charm.prototype.scrollCallback = function() {
                    var box;

                    if (this.scrolled) {
                        this.scrolled = false;
                        this.boxes = (function() {
                            var j, len, ref, results;

                            ref = this.boxes;
                            results = [];

                            for (j = 0, len = ref.length; j < len; j++) {
                                box = ref[j];

                                if (!(box)) {
                                    continue;
                                }

                                if (this.isVisible(box)) {
                                    this.show(box);
                                    continue;
                                }

                                results.push(box);
                            }

                            return results;

                        }).call(this);

                        if (!(this.boxes.length || this.config.live)) {
                            return this.stop();
                        }
                    }
                };

                Charm.prototype.offsetTop = function(element) {
                    var top;

                    while (element.offsetTop === void 0) {

                        element = element.parentNode;
                    }

                    top = element.offsetTop;

                    while (element == element.offsetParent) {

                        top += element.offsetTop;
                    }

                    return top;
                };

                Charm.prototype.isVisible = function(box) {
                    var bottom, offset, top, viewBottom, viewTop;

                    offset = box.getAttribute('data-charm-offset') || this.config.offset;

                    viewTop = window.pageYOffset;
                    viewBottom = viewTop + Math.min(this.element.clientHeight, this.Event.innerHeight()) - offset;

                    top = this.offsetTop(box);
                    bottom = top + box.clientHeight;

                    return top <= viewBottom && bottom >= viewTop;
                };

                return Charm;

            })();

            api.ui.charm = Charm;
        },
        unload: function() {}
    };
});
<commit_msg>--fix charm module to use custom Array.index method.<commit_after>/* --------------------------------------- *
* Guerrilla UI                             *
* @module: Charm, timed animations based   *
* on scrolling and page location           *
* ---------------------------------------- */
$.GUI().use(function(gui) {

    return {

        load: function(api) {
            var Charm;

            Charm = (function() {

                function Charm(options) {

                    if (!options || options === null) {
                        options = {};
                    }

                    this.start = api.broker.bind(this.start, this);
                    this.scrollHandler = api.broker.bind(this.scrollHandler, this);
                    this.scrollCallback = api.broker.bind(this.scrollCallback, this);
                    this.resetAnimation = api.broker.bind(this.resetAnimation, this);

                    this.config = this.extend(options, this.defaults);
                    this.charmEvent = this.Event.create(this.config.boxClass);

                    this.scrolled = true;
                    this.animationNameCache = api.dom.map;
                }

                Charm.prototype.defaults = {
                    boxClass: 'charm',
                    animateClass: 'animated',
                    offset: 0,
                    mobile: true,
                    live: true,
                    callback: null,
                    scrollContainer: null
                };

                Charm.prototype.extend = function(custom, defaults) {
                    var key, value;

                    for (key in defaults) {

                        value = defaults[key];

                        if (custom[key] !== null) {
                            custom[key] = value;
                        }
                    }

                    return custom;
                };

                Charm.prototype.vendors = ["moz", "webkit"];

                Charm.prototype.Event = api.dom.Event;

                Charm.prototype.disabled = function() {
                    return !this.config.mobile && this.Event.isMobile(navigator.userAgent);
                };

                Charm.prototype.init = function() {
                    var ref;

                    this.element = document.documentElement;

                    if ((ref = document.readyState) === "interactive" || ref === "complete") {

                        this.start();

                    } else {

                        this.Event.add(document, 'DOMContentLoaded', this.start);
                    }

                    this.finished = [];

                    return this.finished;
                };

                Charm.prototype.start = function() {
                    var _this = this, box, j, length, _ref;

                    this.stopped = false;

                    this.boxes = (function() {
                        var i = 0, length, _ref, results = [];

                        _ref = this.element.querySelectorAll("." + this.config.boxClass);

                        length = _ref.length;

                        if (length > 0) {

                            do {
                                box = _ref[i];

                                results.push(box);

                                i++;
                            } while (--length);
                        }

                        return results;

                    }).call(this);

                    this.all = (function() {
                        var j, len, ref, results;

                        ref = this.boxes;
                        results = [];

                        for (j = 0, len = ref.length; j < len; j++) {
                          box = ref[j];
                          results.push(box);
                        }

                        return results;

                    }).call(this);

                    if(this.boxes.length){

                        if(this.disabled()){

                            this.resetStyle();

                        }else{
                            ref = this.boxes;

                            for(j = 0, length = ref.length; j < length; j++){
                                box = ref[j];
                                this.applyStyle(box, true);
                            }
                        }
                    }

                    if (!this.disabled()) {
                        this.Event.add(window, 'scroll', this.scrollHandler);
                        this.Event.add(window, 'resize', this.scrollHandler);

                        this.interval = window.setInterval(this.scrollCallback, 50);
                    }

                    if (this.config.live) {

                        return new MutationObserver((function(_this) {
                            return function(records) {
                                var i = 0, length, node, record, results = [];

                                for (length = records.length; i < length; i++) {
                                    record = records[i];

                                    results.push((function() {
                                        var l, len2, ref1, results1;

                                        ref1 = record.addedNodes || [];
                                        results1 = [];

                                        for(l = 0, len2 = ref1.length; l < len2; l++){
                                            node = ref1[l];
                                            results1.push(this.doSync(node));
                                        }

                                        return results1;

                                    }).call(_this));
                                }

                                return results;
                            };
                        })(this)).observe(document.body, {
                            childList: true,
                            subtree: true
                        });
                    }
                };

                Charm.prototype.stop = function() {
                    this.stopped = true;

                    this.Event.remove(window, 'scroll', this.scrollHandler);
                    this.Event.remove(window, 'resize', this.scrollHandler);

                    if (this.interval !== null) {
                        return window.clearInterval(this.interval);
                    }
                };

                /**
                 * Check for MutationObserver support
                 *
                 * @param element {object} - dom element object
                 * @return sync {function} - attempt to sync with dom element
                **/
                Charm.prototype.sync = function(element) {
                    if (MutationObserver.notSupported) {
                        return this.doSync(this.element);
                    }
                };

                Charm.prototype.doSync = function(element) {
                    var box, i = 0, length, ref, results = [];

                    if (element === null) {
                        element = this.element;
                    }

                    if (element.nodeType !== 1) {
                        return;
                    }

                    element = element.parentNode || element;
                    ref = element.querySelectorAll("." + this.config.boxClass);

                    for (length = ref.length; i < length; i++) {
                        box = ref[i];

                        if (api.Array.index.call(this.all, box) < 0) {
                            this.boxes.push(box);
                            this.all.push(box);

                            if (this.stopped || this.disabled()) {
                                this.resetStyle();
                            } else {
                                this.applyStyle(box, true);
                            }

                            results.push(this.scrolled = true);

                        } else {

                            results.push(void 0);
                        }
                    }

                    return results;
                };

                /**
                 * Add needed show events to reset animations
                 *
                 * @param box {object} - the box element with animation props
                 * @return box {object} - updated box element with added events
                **/
                Charm.prototype.show = function(box) {
                    this.applyStyle(box);

                    box.className = box.className + " " + this.config.animateClass;

                    if (this.config.callback !== null) {
                        this.config.callback(box);
                    }

                    this.Event.fire(box, this.charmEvent);

                    this.Event.add(box, 'animationend', this.resetAnimation);
                    this.Event.add(box, 'oanimationend', this.resetAnimation);
                    this.Event.add(box, 'webkitAnimationEnd', this.resetAnimation);
                    this.Event.add(box, 'MSAnimationEnd', this.resetAnimation);

                    return box;
                };

                Charm.prototype.applyStyle = function(box, hidden) {
                    var delay, duration, iteration;

                    duration = box.getAttribute('data-charm-duration');
                    delay = box.getAttribute('data-charm-delay');
                    iteration = box.getAttribute('data-charm-iteration');

                    return this.animate((function(_this) {

                        return function() {
                            return _this.customStyle(box, hidden, duration, delay, iteration);
                        };
                    })(this));
                };

                Charm.prototype.animate = (function() {
                    if ('requestAnimationFrame' in window) {
                        return function(callback) {
                            return window.requestAnimationFrame(callback);
                        };

                    } else {
                        return function(callback) {
                            return callback();
                        };
                    }
                })();

                Charm.prototype.resetStyle = function() {
                    var box, i = 0, length, ref, results = [];

                    ref = this.boxes;

                    for (length = ref.length; i < length; i++) {
                        box = ref[i];
                        results.push(box.style.visibility = 'visible');
                    }

                    return results;
                };

                Charm.prototype.resetAnimation = function(e) {
                    var target;

                    if (e.type.toLowerCase().indexOf('animationend') >= 0) {
                        target = e.target || e.srcElement;

                        target.className = target.className.replace(this.config.animateClass, '').trim();

                        return target.className;
                    }
                };

                Charm.prototype.customStyle = function(box, hidden, duration, delay, iteration) {
                    if (hidden) {
                        this.cacheAnimationName(box);
                    }

                    box.style.visibility = hidden ? 'hidden' : 'visible';

                    if (duration) {
                        this.vendorSet(box.style, {
                            animationDuration: duration
                        });
                    }

                    if (delay) {
                        this.vendorSet(box.style, {
                            animationDelay: delay
                        });
                    }

                    if (iteration) {
                        this.vendorSet(box.style, {
                            animationIterationCount: iteration
                        });
                    }

                    this.vendorSet(box.style, {
                        animationName: hidden ? 'none' : this.cachedAnimationName(box)
                    });

                    return box;
                };

                Charm.prototype.vendorSet = function(elem, properties) {
                    var name, results = [], value, vendor;

                    for (name in properties) {
                        value = properties[name];
                        elem["" + name] = value;

                        results.push((function() {
                            var i, ref, results1;

                            ref = this.vendors;
                            results1 = [];

                            for (i = 0; i < ref.length; i++) {

                                vendor = ref[i];
                                results1.push(elem["" + vendor + (name.charAt(0).toUpperCase()) + (name.substr(1))] = value);
                            }

                            return results1;

                        }).call(this));
                    }

                    return results;
                };

                Charm.prototype.vendorCSS = function(elem, property) {
                    var i = 0, length, ref, result, style, vendor;

                    style = window.getComputedStyle(elem);
                    result = style.getPropertyCSSValue(property);

                    ref = this.vendors;

                    for (length = ref.length; i < len; i++) {
                        vendor = ref[i];
                        result = result || style.getPropertyCSSValue("-" + vendor + "-" + property);
                    }

                    return result;
                };

                Charm.prototype.animationName = function(box) {
                    var animationName;

                    try {

                        animationName = this.vendorCSS(box, 'animation-name').cssText;

                    } catch (_error) {

                        animationName = window.getComputedStyle(box).getPropertyValue('animation-name');
                    }

                    if (animationName === 'none') {

                        return '';

                    } else {

                        return animationName;
                    }
                };

                Charm.prototype.cacheAnimationName = function(box) {
                    return this.animationNameCache.set(box, this.animationName(box));
                };

                Charm.prototype.cachedAnimationName = function(box) {
                    return this.animationNameCache.get(box);
                };

                Charm.prototype.scrollHandler = function() {
                    this.scrolled = true;

                    return this.scrolled;
                };

                Charm.prototype.scrollCallback = function() {
                    var box;

                    if (this.scrolled) {
                        this.scrolled = false;
                        this.boxes = (function() {
                            var j, len, ref, results;

                            ref = this.boxes;
                            results = [];

                            for (j = 0, len = ref.length; j < len; j++) {
                                box = ref[j];

                                if (!(box)) {
                                    continue;
                                }

                                if (this.isVisible(box)) {
                                    this.show(box);
                                    continue;
                                }

                                results.push(box);
                            }

                            return results;

                        }).call(this);

                        if (!(this.boxes.length || this.config.live)) {
                            return this.stop();
                        }
                    }
                };

                Charm.prototype.offsetTop = function(element) {
                    var top;

                    while (element.offsetTop === void 0) {

                        element = element.parentNode;
                    }

                    top = element.offsetTop;

                    while (element == element.offsetParent) {

                        top += element.offsetTop;
                    }

                    return top;
                };

                Charm.prototype.isVisible = function(box) {
                    var bottom, offset, top, viewBottom, viewTop;

                    offset = box.getAttribute('data-charm-offset') || this.config.offset;

                    viewTop = window.pageYOffset;
                    viewBottom = viewTop + Math.min(this.element.clientHeight, this.Event.innerHeight()) - offset;

                    top = this.offsetTop(box);
                    bottom = top + box.clientHeight;

                    return top <= viewBottom && bottom >= viewTop;
                };

                return Charm;

            })();

            api.ui.charm = Charm;
        },
        unload: function() {}
    };
});
<|endoftext|>


<commit_before>import React from "react";

type PropsType = {
  name: "blueGreen",
  children?: React$Element<any>
};
const BackgroundGradient = (props: PropsType) => (

{props.children}

);

const colors = {
  blue: "#006BF6",
  green: "#10E951"
};

const gradients = {
  blueGreen: {
    color: colors.blue,
    background: `linear-gradient(to bottom right, ${colors.blue}, ${colors.green})`
  }
};

export default BackgroundGradient;
<commit_msg>docs: fix BackgroundGradient warning<commit_after>import React from "react";
import { View } from "react-primitives";

type PropsType = {
  name: "blueGreen",
  style: any,
  children?: React$Element<any>
};
const BackgroundGradient = (props: PropsType) => (

    <View style={props.style}>
      {props.children}
    </View>

);

const colors = {
  blue: "#006BF6",
  green: "#10E951"
};

const gradients = {
  blueGreen: {
    backgroundColor: colors.blue,
    background: `linear-gradient(to bottom right, ${colors.blue}, ${colors.green})`
  }
};

export default BackgroundGradient;
<|endoftext|>


<commit_before>/* This is a variant of the suggestion in the jQuery FAQ:
     https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
   We need this since election IDs now have dots in them.
 */
function escapeID(originalID) {
  return originalID.replace( /(:|\.|\[|\]|,)/g, "\\$1" );
}

/* Change the visibility of a Select2 widget; select2Element should be a
   jQuery-wrapped element */

function setSelect2Visibility(select2Element, visibility) {
  /* If visibility is false, this both disables the Select2 boxes and
   * hides them by hiding their enclosing element. Otherwise it
   * enables it and makes the enclosure visible. */
  select2Element.prop(
    'disabled',
    !visibility
  );
  if (visibility) {
    select2Element.show()
  } else {
    select2Element.hide();
  }
}

/* Make all the party drop-downs into Select2 widgets */

function setUpPartySelect2s() {
  $('.party-select').not('.select2-offscreen').not('.select2-container')
    .select2({
        width: '100%',
        placeholder: 'Select a party',
        allowClear: true
    });
}

$(document).on('focus', '.select2', function (e) {
  if (e.originalEvent) {
    $(this).siblings('select').select2('open');
  }
});

/* Make all the post drop-downs into Select2 widgets */

function setUpPostSelect2s() {
  $('.post-select').each(function(i) {
    var postSelect = $(this),
      hidden = postSelect.prop('tagName') == 'INPUT' &&
         postSelect.attr('type') == 'hidden';
    /* If it's a real select box (not a hidden input) make it into a
     * Select2 box; also, don't try to reinitialize a select that's
     * already a Select2 */
    if (!(hidden || $(postSelect).data('select2'))) {
      postSelect.select2({
        placeholder: 'Post',
        allowClear: true,
        width: '100%'
      });
    }
    postSelect.on('change', function (e) {
      updateFields();
    });
    updateFields();
  });
}

/* Set the visibility of an input element and any label for it */

function setVisibility(plainInputElement, newVisiblity) {
  var inputElement = $(plainInputElement),
      inputElementID = escapeID(plainInputElement.id),
      labelElement = $('label[for=' + inputElementID + ']');
  inputElement.toggle(newVisiblity);
  labelElement.toggle(newVisiblity);
}

/* Update the visibility of the party and post drop-downs for a particular
   election */

function updateSelectsForElection(show, election) {
  /* Whether we should show the party and post selects is
     determined by the boolean 'show'. */
  var partySelectToShowID,
      partyPositionToShowID,
      postID = $('#id_constituency_' + escapeID(election)).val(),
      partySet;
  if (postID) {
    partySet = postIDToPartySet[postID];
  }
  if (show) {
    if (postID) {
      partySelectToShowID = 'id_party_' + partySet + '_' + election;
      partyPositionToShowID = 'id_party_list_position_' + partySet + '_' + election;
      $('.party-select-' + escapeID(election)).each(function(i) {
        setSelect2Visibility(
          $(this),
          $(this).attr('id') == partySelectToShowID
        );
      });
      $('.party-position-' + escapeID(election)).each(function(i) {
        setVisibility(this, $(this).attr('id') == partyPositionToShowID);
      });
    } else {
      /* Then just show the first party select and hide the others: */
      $('.party-select-' + escapeID(election)).each(function(i) {
        setSelect2Visibility($(this), i == 0);
      });
      $('.party-position-' + escapeID(election)).each(function(i) {
        setVisibility(this, i == 0);
      });
    }
  } else {
    $('.party-select-' + escapeID(election)).each(function(i) {
      setSelect2Visibility($(this), false);
    });
    $('.party-position-' + escapeID(election)).each(function() {
      setVisibility(this, false);
    });
  }
  setSelect2Visibility($('#id_constituency_' + escapeID(election)), show);
}

/* Make sure that the party and constituency select boxes are updated
   when you choose whether the candidate is standing in that election
   or not. */

function setUpStandingCheckbox() {
  $('#person-details select.standing-select').on('change', function() {
    updateFields();
  });
}

/* This should be called whenever the select drop-downs for party
   and post that have to be shown might have to be shown.  */

function updateFields() {
  $('#person-details select.standing-select').each(function(i) {
    var standing = $(this).val() == 'standing',
        match = /^id_standing_(.*)/.exec($(this).attr('id')),
        election = match[1];
    updateSelectsForElection(standing, election); });
}

/* This is called to display a new election form on the edit person
   page, if the dynamic "add new election" button is being used. */

function showElectionsForm() {
  $.getJSON("/api/current-elections/").done(function( data ) {
    var select_data = $.map(data, function(obj, key) {
      return { id: key, text: obj.name + ' (' + obj.election_date + ')' };
    })
    $('#add_more_elections').select2({
      data: select_data,
    }).on('change', function(e) {
      var url = window.location.pathname + '/single_election_form/' + e.val;
      $.get(url, function(data) {
        $('.extra_elections_forms').html(data);
        setUpStandingCheckbox();
        setUpPartySelect2s();
        setUpPostSelect2s();
        updateFields();
      });
    });
    $('.add_more_elections_field').show();
    $('#add_election_button').hide();
  });
}

function toTitleCase(str) {
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

suggest_correction = function(el, suggestion) {

    suggestion_el = $('Change to ' + suggestion + '?');
    suggestion_el.click(function(clicked_el) {
        var this_link = $(this);
        this_link.prev('input').val($(this_link).find('span').text());
        $('.suggested').remove();
    })
    $('.suggested').remove();
    $(el).after(suggestion_el);

};

function checkNameFormat(e) {
    var name = e.target.value;
    var upper_first_matcher = /([A-Z]+,? [A-Za-z]+)/g;
    var match = upper_first_matcher.exec(name);
    if (match) {
        var name_parts = name.split(' ');
        var last_name = name_parts.shift();
        var name = name_parts.join(' ') + ' ' + toTitleCase(last_name);
        suggest_correction(e.target, name);
    }
}

$(document).ready(function() {
  $.getJSON('/post-id-to-party-set.json', function(data) {
      window.postIDToPartySet = data;
      setUpPartySelect2s();
      setUpPostSelect2s();
      setUpStandingCheckbox();
      updateFields();
      /* Now enable the "add an extra election" button if it's present */
      $('#add_election_button').on('click', showElectionsForm);
      $('.add_more_elections_field').hide();
      $('[name=name]').on('paste keyup', checkNameFormat);
      $('[name*=-name]').on('paste keyup', checkNameFormat);
  });
});
<commit_msg>Correctly show and hide selects<commit_after>/* This is a variant of the suggestion in the jQuery FAQ:
     https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
   We need this since election IDs now have dots in them.
 */
function escapeID(originalID) {
  return originalID.replace( /(:|\.|\[|\]|,)/g, "\\$1" );
}

/* Change the visibility of a Select2 widget; select2Element should be a
   jQuery-wrapped element */

function setSelect2Visibility(select2Element, visibility) {
  /* If visibility is false, this both disables the Select2 boxes and
   * hides them by hiding their enclosing element. Otherwise it
   * enables it and makes the enclosure visible. */
  console.log(select2Element)
  console.log(visibility)
  select2Element.prop(
    'disabled',
    !visibility
  );

  if (visibility) {
    select2Element.parent().show()
  } else {
    select2Element.parent().hide();
  }
}

/* Make all the party drop-downs into Select2 widgets */

function setUpPartySelect2s() {
  $('.party-select').not('.select2-offscreen').not('.select2-container')
    .select2({
        width: '100%',
        placeholder: 'Select a party',
        allowClear: true
    });
}

$(document).on('focus', '.select2', function (e) {
  if (e.originalEvent) {
    $(this).siblings('select').select2('open');
  }
});

/* Make all the post drop-downs into Select2 widgets */

function setUpPostSelect2s() {
  $('.post-select').each(function(i) {
    var postSelect = $(this),
      hidden = postSelect.prop('tagName') == 'INPUT' &&
         postSelect.attr('type') == 'hidden';
    /* If it's a real select box (not a hidden input) make it into a
     * Select2 box; also, don't try to reinitialize a select that's
     * already a Select2 */
    if (!(hidden || $(postSelect).data('select2'))) {
      postSelect.select2({
        placeholder: 'Post',
        allowClear: true,
        width: '100%'
      });
    }
    postSelect.on('change', function (e) {
      updateFields();
    });
    updateFields();
  });
}

/* Set the visibility of an input element and any label for it */

function setVisibility(plainInputElement, newVisiblity) {
  var inputElement = $(plainInputElement),
      inputElementID = escapeID(plainInputElement.id),
      labelElement = $('label[for=' + inputElementID + ']');
  inputElement.toggle(newVisiblity);
  labelElement.toggle(newVisiblity);
}

/* Update the visibility of the party and post drop-downs for a particular
   election */

function updateSelectsForElection(show, election) {
  /* Whether we should show the party and post selects is
     determined by the boolean 'show'. */
  var partySelectToShowID,
      partyPositionToShowID,
      postID = $('#id_constituency_' + escapeID(election)).val(),
      partySet;
  if (postID) {
    partySet = postIDToPartySet[postID];
  }
  if (show) {
    if (postID) {
      partySelectToShowID = 'id_party_' + partySet + '_' + election;
      partyPositionToShowID = 'id_party_list_position_' + partySet + '_' + election;
      $('.party-select-' + escapeID(election)).each(function(i) {
        setSelect2Visibility(
          $(this),
          $(this).attr('id') == partySelectToShowID
        );
      });
      $('.party-position-' + escapeID(election)).each(function(i) {
        setVisibility(this, $(this).attr('id') == partyPositionToShowID);
      });
    } else {
      /* Then just show the first party select and hide the others: */
      $('.party-select-' + escapeID(election)).each(function(i) {
        setSelect2Visibility($(this), i == 0);
      });
      $('.party-position-' + escapeID(election)).each(function(i) {
        setVisibility(this, i == 0);
      });
    }
  } else {
    $('.party-select-' + escapeID(election)).each(function(i) {
      setSelect2Visibility($(this), false);
    });
    $('.party-position-' + escapeID(election)).each(function() {
      setVisibility(this, false);
    });
  }
  setSelect2Visibility($('#id_constituency_' + escapeID(election)), show);
}

/* Make sure that the party and constituency select boxes are updated
   when you choose whether the candidate is standing in that election
   or not. */

function setUpStandingCheckbox() {
  $('#person-details select.standing-select').on('change', function() {
    updateFields();
  });
}

/* This should be called whenever the select drop-downs for party
   and post that have to be shown might have to be shown.  */

function updateFields() {
  $('#person-details select.standing-select').each(function(i) {
    var standing = $(this).val() == 'standing',
        match = /^id_standing_(.*)/.exec($(this).attr('id')),
        election = match[1];
    updateSelectsForElection(standing, election); });
}

/* This is called to display a new election form on the edit person
   page, if the dynamic "add new election" button is being used. */

function showElectionsForm() {
  $.getJSON("/api/current-elections/").done(function( data ) {
    var select_data = $.map(data, function(obj, key) {
      return { id: key, text: obj.name + ' (' + obj.election_date + ')' };
    })
    $('#add_more_elections').select2({
      data: select_data,
    }).on('change', function(e) {
      var url = window.location.pathname + '/single_election_form/' + e.val;
      $.get(url, function(data) {
        $('.extra_elections_forms').html(data);
        setUpStandingCheckbox();
        setUpPartySelect2s();
        setUpPostSelect2s();
        updateFields();
      });
    });
    $('.add_more_elections_field').show();
    $('#add_election_button').hide();
  });
}

function toTitleCase(str) {
    return str.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
}

suggest_correction = function(el, suggestion) {

    suggestion_el = $('Change to ' + suggestion + '?');
    suggestion_el.click(function(clicked_el) {
        var this_link = $(this);
        this_link.prev('input').val($(this_link).find('span').text());
        $('.suggested').remove();
    })
    $('.suggested').remove();
    $(el).after(suggestion_el);

};

function checkNameFormat(e) {
    var name = e.target.value;
    var upper_first_matcher = /([A-Z]+,? [A-Za-z]+)/g;
    var match = upper_first_matcher.exec(name);
    if (match) {
        var name_parts = name.split(' ');
        var last_name = name_parts.shift();
        var name = name_parts.join(' ') + ' ' + toTitleCase(last_name);
        suggest_correction(e.target, name);
    }
}

$(document).ready(function() {
  $.getJSON('/post-id-to-party-set.json', function(data) {
      window.postIDToPartySet = data;
      setUpPartySelect2s();
      setUpPostSelect2s();
      setUpStandingCheckbox();
      updateFields();
      /* Now enable the "add an extra election" button if it's present */
      $('#add_election_button').on('click', showElectionsForm);
      $('.add_more_elections_field').hide();
      $('[name=name]').on('paste keyup', checkNameFormat);
      $('[name*=-name]').on('paste keyup', checkNameFormat);
  });
});
<|endoftext|>


<commit_before>/// <reference types="cypress" />

context('Actions', () => {
  beforeEach(() => {
    cy.visit('http://localhost:8000')
  })

  it('All + elements are clickable', () => {
    cy.get('.step-up').click( { multiple: true } )

    cy.get('input.st-al')
      .should('has.value', '7')
  })
})
<commit_msg>Modify the cypress test since the "first" input is now the days projection input<commit_after>/// <reference types="cypress" />

context('Actions', () => {
  beforeEach(() => {
    cy.visit('http://localhost:8000')
  })

  it('All + elements are clickable', () => {
    cy.get('.step-up').click( { multiple: true } )

    cy.get('input.st-al')
      .should('has.value', '70')
  })
})
<|endoftext|>


<commit_before>/*
* Copyright (c) 2012 Sprymix Inc.
* All rights reserved.
*
* See LICENSE for details.
**/

$SXJSP = (function() {
    'use strict';

    var modules = {};

    var hop = Object.prototype.hasOwnProperty,
        tos = Object.prototype.toString;

    var Array_some = Array.prototype.some;
    if (typeof Array_some == 'undefined') {
        Array_some = function(cb, scope) {
            'use strict';

            var i = 0, len = this.length >>> 0;
            for (; i < len; i++) {
                if (cb.call(scope, this[i], i)) {
                    return true;
                }
            }
        }
    }

    function Module(name, dct) {
        this.$name = name;
        this.$initialized = dct != null;

        for (var i in dct) {
            if (hop.call(dct, i) && i.length && i[0] != '$') {
                this[i] = dct[i];
            }
        }
    }

    function error(msg) {
        throw '$SXJSP: ' + msg;
    }

    return {
        module: function(name, dct) {
            var parts = name.split('.'),
                i, len = parts.length,
                next = modules,
                next_sub,
                iter_name = [],
                part,
                mod,
                mod_name,
                mod_dct;

            if (!len) {
                error('invalid module name: "' +name + '"');
            }

            for (i = 0; i < len - 1; i++) {
                part = parts[i];
                iter_name.push(part);
                next_sub = next;
                if (next_sub.hasOwnProperty(part)) {
                    next = next_sub[part];
                } else {
                    next = next_sub[part] = new Module(iter_name.join('.'));
                }
            }

            mod_name = parts[len - 1];
            mod = next[mod_name];
            if (mod != null) {
                if (mod.$initialized) {
                    error('duplicate module? (' + name + ')');
                }
                for (i in dct) {
                    if (!mod.hasOwnProperty(i) && dct.hasOwnProperty(i)) {
                        mod[i] = dct[i];
                    }
                }
            } else {
                next[mod_name] = new Module(name, dct);
            }
        },

        each: function(arg_cnt, it, cb, scope) {
            var t = tos.call(it);

            if (t == '[object Array]') {
                if (arg_cnt != 1) {
                    error('foreach supports only one iterator variable when iterating over arrays');
                }
                Array_some.call(it, cb, scope);
                return;
            }

            if (t == '[object Object]') {
                var k;
                if (arg_cnt == 2) {
                    for (k in it) {
                        if (hop.call(it, k)) {
                            if (cb.call(scope, k, it[k])) {
                                return;
                            }
                        }
                    }
                } else {
                    // arg_cnt == 1
                    for (k in it) {
                        if (hop.call(it, k)) {
                            if (cb.call(scope, [k, it[k]])) {
                                return;
                            }
                        }
                    }
                }
                return;
            }

            if (t == '[object String]' || t == '[object NodeList]') {
                if (arg_cnt != 1) {
                    error('foreach supports only one iterator variable when iterating over '
                          + 'strings or NodeList');
                }

                var len = it.length >>> 0, i = 0;

                for (; i < len; i++) {
                    if (cb.call(scope, it[i])) {
                        return;
                    }
                }
                return;
            }

            error('foreach: unsupported iterable: ' + it);
        }
    };
})();
<commit_msg>utils.lang.jp.base: Better code for getting native hasOwnProperty & toString<commit_after>/*
* Copyright (c) 2012 Sprymix Inc.
* All rights reserved.
*
* See LICENSE for details.
**/

$SXJSP = (function() {
    'use strict';

    var modules = {};

    var StdObject = {}.constructor,
        StdArray = [].constructor,
        hop = StdObject.prototype.hasOwnProperty,
        tos = StdObject.prototype.toString;

    var Array_some = StdArray.prototype.some;
    if (typeof Array_some == 'undefined') {
        Array_some = function(cb, scope) {
            'use strict';

            var i = 0, len = this.length >>> 0;
            for (; i < len; i++) {
                if (cb.call(scope, this[i], i)) {
                    return true;
                }
            }
        }
    }

    function Module(name, dct) {
        this.$name = name;
        this.$initialized = dct != null;

        for (var i in dct) {
            if (hop.call(dct, i) && i.length && i[0] != '$') {
                this[i] = dct[i];
            }
        }
    }

    function error(msg) {
        throw '$SXJSP: ' + msg;
    }

    return {
        module: function(name, dct) {
            var parts = name.split('.'),
                i, len = parts.length,
                next = modules,
                next_sub,
                iter_name = [],
                part,
                mod,
                mod_name,
                mod_dct;

            if (!len) {
                error('invalid module name: "' +name + '"');
            }

            for (i = 0; i < len - 1; i++) {
                part = parts[i];
                iter_name.push(part);
                next_sub = next;
                if (next_sub.hasOwnProperty(part)) {
                    next = next_sub[part];
                } else {
                    next = next_sub[part] = new Module(iter_name.join('.'));
                }
            }

            mod_name = parts[len - 1];
            mod = next[mod_name];
            if (mod != null) {
                if (mod.$initialized) {
                    error('duplicate module? (' + name + ')');
                }
                for (i in dct) {
                    if (!mod.hasOwnProperty(i) && dct.hasOwnProperty(i)) {
                        mod[i] = dct[i];
                    }
                }
            } else {
                next[mod_name] = new Module(name, dct);
            }
        },

        each: function(arg_cnt, it, cb, scope) {
            var t = tos.call(it);

            if (t == '[object Array]') {
                if (arg_cnt != 1) {
                    error('foreach supports only one iterator variable when iterating over arrays');
                }
                Array_some.call(it, cb, scope);
                return;
            }

            if (t == '[object Object]') {
                var k;
                if (arg_cnt == 2) {
                    for (k in it) {
                        if (hop.call(it, k)) {
                            if (cb.call(scope, k, it[k])) {
                                return;
                            }
                        }
                    }
                } else {
                    // arg_cnt == 1
                    for (k in it) {
                        if (hop.call(it, k)) {
                            if (cb.call(scope, [k, it[k]])) {
                                return;
                            }
                        }
                    }
                }
                return;
            }

            if (t == '[object String]' || t == '[object NodeList]') {
                if (arg_cnt != 1) {
                    error('foreach supports only one iterator variable when iterating over '
                          + 'strings or NodeList');
                }

                var len = it.length >>> 0, i = 0;

                for (; i < len; i++) {
                    if (cb.call(scope, it[i])) {
                        return;
                    }
                }
                return;
            }

            error('foreach: unsupported iterable: ' + it);
        }
    };
})();
<|endoftext|>


<commit_before>var compose = require('./compose');

function Future(producer) {
	return {
		isMonad: true,
		bind: function(right, left) {
			return Future(function(resolve, reject) {
				producer(compose(resolve, right), compose(reject, left));
			});
		},
		subscribe: function(fn) {
			return producer(fn);
		}
	};
}

function Resolve(value) {
	return Future(function(resolve) {
		resolve(value);
	});
}

function Reject(error) {
	return Future(function(resolve, reject) {
		reject(error);
	});
}

Future.Resolve = Resolve;
Future.Reject = Reject;
module.exports = Future;
<commit_msg>two functions<commit_after>var compose = require('./compose');

function Future(producer) {
	return {
		isMonad: true,
		bind: function(right, left) {
			return Future(function(resolve, reject) {
				producer(compose(resolve, right), compose(reject, left));
			});
		},
		subscribe: function(onRight, onLeft) {
			return producer(onRight, onLeft);
		}
	};
}

function Resolve(value) {
	return Future(function(resolve) {
		resolve(value);
	});
}

function Reject(error) {
	return Future(function(resolve, reject) {
		reject(error);
	});
}

Future.Resolve = Resolve;
Future.Reject = Reject;
module.exports = Future;
<|endoftext|>


<commit_before>import React from 'react';

import SPELLS from 'common/SPELLS';
import Analyzer from 'Parser/Core/Analyzer';
import SpellIcon from 'common/SpellIcon';
import Combatants from 'Parser/Core/Modules/Combatants';
import SpellLink from 'common/SpellLink';
import ItemDamageDone from 'Main/ItemDamageDone';
import StatisticBox from 'Main/StatisticBox';
import Wrapper from 'common/Wrapper';
import ItemLink from 'common/ItemLink';
import ITEMS from 'common/ITEMS/HUNTER';

class ButcheryCarve extends Analyzer {

  static dependencies = {
    combatants: Combatants,
  };

  bonusDamage = 0;
  damageHits = 0;
  casts = 0;
  totalStacksUsed = 0;

  get averageTargetsHit() {
    return (this.damageHits / this.casts).toFixed(2);
  }

  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.BUTCHERY_TALENT.id && spellId !== SPELLS.CARVE.id) {
      return;
    }
    this.casts++;
  }

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.BUTCHERY_TALENT.id && spellId !== SPELLS.CARVE.id) {
      return;
    }
    this.damageHits++;
    this.bonusDamage += event.amount + (event.absorbed || 0);
  }

  get averageTargetsThreshold() {
    return {
      actual: this.averageTargetsHit,
      isLessThan: {
        minor: 2,
        average: 1.75,
        major: 1.5,
      },
      style: 'number',
    };
  }

  suggestions(when) {
    const spellLink = this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id) ? SPELLS.BUTCHERY_TALENT : SPELLS.CARVE;
    when(this.averageTargetsThreshold).addSuggestion((suggest, actual, recommended) => {
      return suggest(<Wrapper>Your <SpellLink id={spellLink.id} icon /> hit a low amount of targets on average throughout this encounter. Try and position yourself so that you'll hit as many targets as possible with <SpellLink id={spellLink.id} icon />. Note: that when using <ItemLink id={ITEMS.BUTCHERS_BONE_APRON.id} icon /> it can be worth using <SpellLink id={spellLink.id} icon /> on single-target when at 10 stacks, however it's generally recommended to use a different legendary if possible for largely single-target fights.</Wrapper>)
        .icon(spellLink.icon)
        .actual(`${this.averageTargetsHit} targets hit on averages`)
        .recommended(`>${recommended} targets hit on average is recommended`);
    });
  }

  statistic() {
    if (this.bonusDamage > 0) {
      const spellLink = this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id) ? SPELLS.BUTCHERY_TALENT : SPELLS.CARVE;
      return (
        <StatisticBox
          icon={<SpellIcon id={spellLink.id} />}
          value={this.averageTargetsHit}
          label="Average targets hit"

        />
      );
    }
  }

  subStatistic() {
    if (this.bonusDamage > 0) {
      const spellLink = this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id) ? SPELLS.BUTCHERY_TALENT : SPELLS.CARVE;
      return (

            <SpellLink id={spellLink.id}>
              <SpellIcon id={spellLink.id} noLink /> {spellLink.name}
            </SpellLink>

            <ItemDamageDone amount={this.bonusDamage} />

      );
    }
  }
}

export default ButcheryCarve;
<commit_msg>remove new line<commit_after>import React from 'react';

import SPELLS from 'common/SPELLS';
import Analyzer from 'Parser/Core/Analyzer';
import SpellIcon from 'common/SpellIcon';
import Combatants from 'Parser/Core/Modules/Combatants';
import SpellLink from 'common/SpellLink';
import ItemDamageDone from 'Main/ItemDamageDone';
import StatisticBox from 'Main/StatisticBox';
import Wrapper from 'common/Wrapper';
import ItemLink from 'common/ItemLink';
import ITEMS from 'common/ITEMS/HUNTER';

class ButcheryCarve extends Analyzer {

  static dependencies = {
    combatants: Combatants,
  };

  bonusDamage = 0;
  damageHits = 0;
  casts = 0;
  totalStacksUsed = 0;

  get averageTargetsHit() {
    return (this.damageHits / this.casts).toFixed(2);
  }

  on_byPlayer_cast(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.BUTCHERY_TALENT.id && spellId !== SPELLS.CARVE.id) {
      return;
    }
    this.casts++;
  }

  on_byPlayer_damage(event) {
    const spellId = event.ability.guid;
    if (spellId !== SPELLS.BUTCHERY_TALENT.id && spellId !== SPELLS.CARVE.id) {
      return;
    }
    this.damageHits++;
    this.bonusDamage += event.amount + (event.absorbed || 0);
  }

  get averageTargetsThreshold() {
    return {
      actual: this.averageTargetsHit,
      isLessThan: {
        minor: 2,
        average: 1.75,
        major: 1.5,
      },
      style: 'number',
    };
  }

  suggestions(when) {
    const spellLink = this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id) ? SPELLS.BUTCHERY_TALENT : SPELLS.CARVE;
    when(this.averageTargetsThreshold).addSuggestion((suggest, actual, recommended) => {
      return suggest(<Wrapper>Your <SpellLink id={spellLink.id} icon /> hit a low amount of targets on average throughout this encounter. Try and position yourself so that you'll hit as many targets as possible with <SpellLink id={spellLink.id} icon />. Note: that when using <ItemLink id={ITEMS.BUTCHERS_BONE_APRON.id} icon /> it can be worth using <SpellLink id={spellLink.id} icon /> on single-target when at 10 stacks, however it's generally recommended to use a different legendary if possible for largely single-target fights.</Wrapper>)
        .icon(spellLink.icon)
        .actual(`${this.averageTargetsHit} targets hit on averages`)
        .recommended(`>${recommended} targets hit on average is recommended`);
    });
  }

  statistic() {
    if (this.bonusDamage > 0) {
      const spellLink = this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id) ? SPELLS.BUTCHERY_TALENT : SPELLS.CARVE;
      return (
        <StatisticBox
          icon={<SpellIcon id={spellLink.id} />}
          value={this.averageTargetsHit}
          label="Average targets hit"
        />
      );
    }
  }

  subStatistic() {
    if (this.bonusDamage > 0) {
      const spellLink = this.combatants.selected.hasTalent(SPELLS.BUTCHERY_TALENT.id) ? SPELLS.BUTCHERY_TALENT : SPELLS.CARVE;
      return (

            <SpellLink id={spellLink.id}>
              <SpellIcon id={spellLink.id} noLink /> {spellLink.name}
            </SpellLink>

            <ItemDamageDone amount={this.bonusDamage} />

      );
    }
  }
}

export default ButcheryCarve;
<|endoftext|>


<commit_before>import React from 'react';
import SPELLS from 'common/SPELLS';
import CoreChecklist, { Requirement, Rule } from 'Parser/Core/Modules/Features/Checklist';
import SpellLink from 'common/SpellLink';
import {PreparationRule} from 'Parser/Core/Modules/Features/Checklist/Rules';
import {GenericCastEfficiencyRequirement} from 'Parser/Core/Modules/Features/Checklist/Requirements';
import CastEfficiency from 'Parser/Core/Modules/CastEfficiency';
import Combatants from 'Parser/Core/Modules/Combatants';
import Abilities from 'Parser/Core/Modules/Abilities';
import LegendaryUpgradeChecker from 'Parser/Core/Modules/Items/LegendaryUpgradeChecker';
import PrePotion from 'Parser/Core/Modules/Items/PrePotion';
import EnchantChecker from 'Parser/Core/Modules/Items/EnchantChecker';
import SoulShardDetails from 'Parser/Warlock/Demonology/Modules/SoulShards/SoulShardDetails';
import SoulShardTracker from 'Parser/Warlock/Demonology/Modules/SoulShards/SoulShardTracker';
import AlwaysBeCasting from 'Parser/Warlock/Demonology/Modules/Features/AlwaysBeCasting';
import LegendaryCountChecker from 'Parser/Core/Modules/Items/LegendaryCountChecker';
import DoomguardInfernal from 'Parser/Warlock/Demonology/Modules/Features/DoomguardInfernal';
import Felstorm from 'Parser/Warlock/Demonology/Modules/Features/Felstorm';
import CallDreadstalkers from 'Parser/Warlock/Demonology/Modules/Features/CallDreadstalkers';
import DemEmpUptimePet from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimePet';
import AbilityTracker from 'Parser/Core/Modules/Combatants';
import DemEmpUptimeDreadstalkers from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimeDreadstalkers';
import DemEmpUptimeHoG from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimeHoG';
import DemEmpUptimeDoomguardInfernal from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimeDoomguardInfernal';

const rotation_description = <React.Fragment>Follow your rotation closely to maximize DPS. Note that if you have <SpellLink id={SPELLS.WARLOCK_DEMO_T20_2P_BONUS.id} icon/>, Call Dreadstalkers is a rough estimate based on number of procs.</React.Fragment>;

class Checklist extends CoreChecklist{
  static dependencies = {
    abilities: Abilities,
    abilityTracker: AbilityTracker,
    combatants : Combatants,
    castEfficiency: CastEfficiency,
    alwaysBeCasting: AlwaysBeCasting,
    legendaryUpgradeChecker: LegendaryUpgradeChecker,
    legendaryCountChecker: LegendaryCountChecker,
    prePotion: PrePotion,
    doomguardInfernal : DoomguardInfernal,
    felstorm: Felstorm,
    callDreadstalkers: CallDreadstalkers,
    demEmpUptimePet: DemEmpUptimePet,
    demEmpUptimeDreadstalkers: DemEmpUptimeDreadstalkers,
    demEmpUptimeHog: DemEmpUptimeHoG,
    demEmpUptimeDoomguardInfernal: DemEmpUptimeDoomguardInfernal,
    enchantChecker: EnchantChecker,
    soulShardDetails: SoulShardDetails,
    soulShardTracker: SoulShardTracker,
  };

  rules = [
    new Rule({
      name: 'Rotation Spells',
      description: rotation_description,
      requirements: () => {
        return [
          new Requirement({
           name: <React.Fragment><SpellLink id={SPELLS.CALL_DREADSTALKERS.id} icon/> Efficiency</React.Fragment>,
           check: () => this.callDreadstalkers.suggestionThresholds,
         }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.DEMONIC_EMPOWERMENT.id} icon/> Main Pet Uptime</React.Fragment>,
            check: () => this.demEmpUptimePet.suggestionThresholds,
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.CALL_DREADSTALKERS.id} icon/> Empowerment Uptime</React.Fragment>,
            check: () => this.demEmpUptimeDreadstalkers.suggestionThresholds,
            valueToolTip: `How often your Dreadstalkers were empowered while active.`,
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.HAND_OF_GULDAN_CAST.id} icon/> Empowerment Uptime</React.Fragment>,
            check: () => this.demEmpUptimeHog.suggestionThresholds,
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.SUMMON_DOOMGUARD_UNTALENTED.id} icon/>/<SpellLink id={SPELLS.SUMMON_INFERNAL_UNTALENTED.id} icon/> Empowerment Uptime</React.Fragment>,
            check: () => this.demEmpUptimeDoomguardInfernal.suggestionThresholds,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Don\'t cap your Soul Shards',
      description: 'Avoid overcapping Soul Shards.',
      requirements: () => {
        return [
          new Requirement({
            name: 'Wasted shards per minute',
            check: () => this.soulShardDetails.suggestionThresholds,
            valueTooltip: `You wasted ${this.soulShardTracker.shardsWasted} shards and spent ${this.soulShardTracker.timeOnFullShardsSeconds} seconds on full shards`,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Use your offensive cooldowns',
      description: 'Be mindful of your cooldowns if you are specced into them and use them when it\'s appropriate. It\'s okay to hold a cooldown for a little bit when the encounter requires it (burn phases), but generally speaking you should use them as much as you can.',
      requirements: () => {
        const combatant = this.combatants.selected;
        return [
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.SUMMON_DOOMGUARD_UNTALENTED.id} icon/>/<SpellLink id={SPELLS.SUMMON_INFERNAL_UNTALENTED.id} icon/> Casts</React.Fragment>,
            check: () => this.doomguardInfernal.suggestionThresholds,
            when: !combatant.hasTalent(SPELLS.GRIMOIRE_OF_SUPREMACY_TALENT.id),
          }),
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.GRIMOIRE_FELGUARD,
            when: combatant.hasTalent(SPELLS.GRIMOIRE_OF_SERVICE_TALENT.id),
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.FELSTORM_BUFF.id} icon/></React.Fragment>,
            check: () => this.felstorm.suggestionThresholds,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Use your defensive and utility spells.',
      description: <React.Fragment>Use other spells in your toolkit to your advantage. For example, you can try to minimize necessary movement by using <SpellLink id={SPELLS.DEMONIC_GATEWAY_CAST.id} icon />, <SpellLink id={SPELLS.DEMONIC_CIRCLE_TALENT.id} icon />, <SpellLink id={SPELLS.BURNING_RUSH_TALENT.id} icon /> or mitigate incoming damage with <SpellLink id={SPELLS.UNENDING_RESOLVE.id} icon />/<SpellLink id={SPELLS.DARK_PACT_TALENT.id} icon />.

        While you shouldn't cast these defensives on cooldown, be aware of them and use them whenever effective. Not using them at all indicates you might not be aware of them or not using them optimally.</React.Fragment>,
      requirements: () => {
        const combatant = this.combatants.selected;
        return [
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.DEMONIC_CIRCLE_TALENT_TELEPORT,
            when: combatant.hasTalent(SPELLS.DEMONIC_CIRCLE_TALENT.id),
          }),
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.DARK_PACT_TALENT,
            when: combatant.hasTalent(SPELLS.DARK_PACT_TALENT.id),
          }),
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.UNENDING_RESOLVE,
            onlyWithSuggestion: false,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Always be casting',
      description: 'Avoid doing nothing at any point during the fight. Use filler spells like Shadowbolt and Demonwrath when moving.',
      requirements: () => {
        return [
          new Requirement({
            name: 'Downtime',
            check: () => this.alwaysBeCasting.suggestionThresholds,
          }),
        ];
      },
    }),

    new PreparationRule(),
  ]
}

export default Checklist;

<commit_msg>Remove unnecessary value tooltips.<commit_after>import React from 'react';
import SPELLS from 'common/SPELLS';
import CoreChecklist, { Requirement, Rule } from 'Parser/Core/Modules/Features/Checklist';
import SpellLink from 'common/SpellLink';
import {PreparationRule} from 'Parser/Core/Modules/Features/Checklist/Rules';
import {GenericCastEfficiencyRequirement} from 'Parser/Core/Modules/Features/Checklist/Requirements';
import CastEfficiency from 'Parser/Core/Modules/CastEfficiency';
import Combatants from 'Parser/Core/Modules/Combatants';
import Abilities from 'Parser/Core/Modules/Abilities';
import LegendaryUpgradeChecker from 'Parser/Core/Modules/Items/LegendaryUpgradeChecker';
import PrePotion from 'Parser/Core/Modules/Items/PrePotion';
import EnchantChecker from 'Parser/Core/Modules/Items/EnchantChecker';
import SoulShardDetails from 'Parser/Warlock/Demonology/Modules/SoulShards/SoulShardDetails';
import SoulShardTracker from 'Parser/Warlock/Demonology/Modules/SoulShards/SoulShardTracker';
import AlwaysBeCasting from 'Parser/Warlock/Demonology/Modules/Features/AlwaysBeCasting';
import LegendaryCountChecker from 'Parser/Core/Modules/Items/LegendaryCountChecker';
import DoomguardInfernal from 'Parser/Warlock/Demonology/Modules/Features/DoomguardInfernal';
import Felstorm from 'Parser/Warlock/Demonology/Modules/Features/Felstorm';
import CallDreadstalkers from 'Parser/Warlock/Demonology/Modules/Features/CallDreadstalkers';
import DemEmpUptimePet from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimePet';
import AbilityTracker from 'Parser/Core/Modules/Combatants';
import DemEmpUptimeDreadstalkers from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimeDreadstalkers';
import DemEmpUptimeHoG from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimeHoG';
import DemEmpUptimeDoomguardInfernal from 'Parser/Warlock/Demonology/Modules/Features/DemEmpUptimeDoomguardInfernal';

const rotation_description = <React.Fragment>Follow your rotation closely to maximize DPS. Note that if you have <SpellLink id={SPELLS.WARLOCK_DEMO_T20_2P_BONUS.id} icon/>, Call Dreadstalkers is a rough estimate based on number of procs.</React.Fragment>;

class Checklist extends CoreChecklist{
  static dependencies = {
    abilities: Abilities,
    abilityTracker: AbilityTracker,
    combatants : Combatants,
    castEfficiency: CastEfficiency,
    alwaysBeCasting: AlwaysBeCasting,
    legendaryUpgradeChecker: LegendaryUpgradeChecker,
    legendaryCountChecker: LegendaryCountChecker,
    prePotion: PrePotion,
    doomguardInfernal : DoomguardInfernal,
    felstorm: Felstorm,
    callDreadstalkers: CallDreadstalkers,
    demEmpUptimePet: DemEmpUptimePet,
    demEmpUptimeDreadstalkers: DemEmpUptimeDreadstalkers,
    demEmpUptimeHog: DemEmpUptimeHoG,
    demEmpUptimeDoomguardInfernal: DemEmpUptimeDoomguardInfernal,
    enchantChecker: EnchantChecker,
    soulShardDetails: SoulShardDetails,
    soulShardTracker: SoulShardTracker,
  };

  rules = [
    new Rule({
      name: 'Rotation Spells',
      description: rotation_description,
      requirements: () => {
        return [
          new Requirement({
           name: <React.Fragment><SpellLink id={SPELLS.CALL_DREADSTALKERS.id} icon/> Efficiency</React.Fragment>,
           check: () => this.callDreadstalkers.suggestionThresholds,
         }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.DEMONIC_EMPOWERMENT.id} icon/> Main Pet Uptime</React.Fragment>,
            check: () => this.demEmpUptimePet.suggestionThresholds,
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.CALL_DREADSTALKERS.id} icon/> Empowerment Uptime</React.Fragment>,
            check: () => this.demEmpUptimeDreadstalkers.suggestionThresholds,
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.HAND_OF_GULDAN_CAST.id} icon/> Empowerment Uptime</React.Fragment>,
            check: () => this.demEmpUptimeHog.suggestionThresholds,
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.SUMMON_DOOMGUARD_UNTALENTED.id} icon/>/<SpellLink id={SPELLS.SUMMON_INFERNAL_UNTALENTED.id} icon/> Empowerment Uptime</React.Fragment>,
            check: () => this.demEmpUptimeDoomguardInfernal.suggestionThresholds,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Don\'t cap your Soul Shards',
      description: 'Avoid overcapping Soul Shards.',
      requirements: () => {
        return [
          new Requirement({
            name: 'Wasted shards per minute',
            check: () => this.soulShardDetails.suggestionThresholds,
            valueTooltip: `You wasted ${this.soulShardTracker.shardsWasted} shards and spent ${this.soulShardTracker.timeOnFullShardsSeconds} seconds on full shards`,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Use your offensive cooldowns',
      description: 'Be mindful of your cooldowns if you are specced into them and use them when it\'s appropriate. It\'s okay to hold a cooldown for a little bit when the encounter requires it (burn phases), but generally speaking you should use them as much as you can.',
      requirements: () => {
        const combatant = this.combatants.selected;
        return [
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.SUMMON_DOOMGUARD_UNTALENTED.id} icon/>/<SpellLink id={SPELLS.SUMMON_INFERNAL_UNTALENTED.id} icon/> Casts</React.Fragment>,
            check: () => this.doomguardInfernal.suggestionThresholds,
            when: !combatant.hasTalent(SPELLS.GRIMOIRE_OF_SUPREMACY_TALENT.id),
          }),
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.GRIMOIRE_FELGUARD,
            when: combatant.hasTalent(SPELLS.GRIMOIRE_OF_SERVICE_TALENT.id),
          }),
          new Requirement({
            name: <React.Fragment><SpellLink id={SPELLS.FELSTORM_BUFF.id} icon/></React.Fragment>,
            check: () => this.felstorm.suggestionThresholds,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Use your defensive and utility spells.',
      description: <React.Fragment>Use other spells in your toolkit to your advantage. For example, you can try to minimize necessary movement by using <SpellLink id={SPELLS.DEMONIC_GATEWAY_CAST.id} icon />, <SpellLink id={SPELLS.DEMONIC_CIRCLE_TALENT.id} icon />, <SpellLink id={SPELLS.BURNING_RUSH_TALENT.id} icon /> or mitigate incoming damage with <SpellLink id={SPELLS.UNENDING_RESOLVE.id} icon />/<SpellLink id={SPELLS.DARK_PACT_TALENT.id} icon />.

        While you shouldn't cast these defensives on cooldown, be aware of them and use them whenever effective. Not using them at all indicates you might not be aware of them or not using them optimally.</React.Fragment>,
      requirements: () => {
        const combatant = this.combatants.selected;
        return [
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.DEMONIC_CIRCLE_TALENT_TELEPORT,
            when: combatant.hasTalent(SPELLS.DEMONIC_CIRCLE_TALENT.id),
          }),
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.DARK_PACT_TALENT,
            when: combatant.hasTalent(SPELLS.DARK_PACT_TALENT.id),
          }),
          new GenericCastEfficiencyRequirement({
            spell: SPELLS.UNENDING_RESOLVE,
            onlyWithSuggestion: false,
          }),
        ];
      },
    }),

    new Rule({
      name: 'Always be casting',
      description: 'Avoid doing nothing at any point during the fight. Use filler spells like Shadowbolt and Demonwrath when moving.',
      requirements: () => {
        return [
          new Requirement({
            name: 'Downtime',
            check: () => this.alwaysBeCasting.suggestionThresholds,
          }),
        ];
      },
    }),

    new PreparationRule(),
  ]
}

export default Checklist;

<|endoftext|>