<commit_before>/**
 * --------------------------------------------------------------------------
 * Figuration (v2.0.0): tab.js
 * Licensed under MIT (https://github.com/cast-org/figuration/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

(function($) {
    'use strict';

    var CFW_Widget_Tab = function(element, options) {
        this.$triggerElm = $(element);
        this.$navElm = null;
        this.$targetElm = null;

        this.settings = $.extend({}, CFW_Widget_Tab.DEFAULTS, this._parseDataAttr(), options);

        this._init();
    };

    CFW_Widget_Tab.DEFAULTS = {
        animate     : true,     // If tabs should be allowed fade in and out
        speed       : 150,      // Speed of animation in milliseconds
        hidden      : true      // Use aria-hidden on target containers by default
    };

    CFW_Widget_Tab.prototype = {

        _init : function() {
            var $selfRef = this;

            // Find nav and target elements
            this.$navElm = this.$triggerElm.closest('ul:not(.dropdown-menu)');
            this.$navElm.attr('role', 'tablist');

            var $selector = $(this.settings.target);
            if (!$selector.length) {
                $selector = $(this.$triggerElm.attr('href'));
            }
            this.$targetElm = $($selector);

            if (!this.$targetElm.length) {
                return false;
            }

            this.$triggerElm.attr('data-cfw', 'tab');

            // Check for presence of trigger id - set if not present
            var triggerID = this._getID(this.$triggerElm, 'cfw-tab');

            // Target should have id already - set ARIA attributes
            this.$targetElm.attr({
                'tabindex': -1,
                'role': 'tabpanel',
                'aria-labelledby': triggerID
            });
            if (this.settings.hidden) {
                this.$targetElm.attr('aria-hidden', true);
            }
            if (this.settings.animate) {
                this.fadeEnable();
            } else {
                this.fadeDisable();
            }

            // Set ARIA attributes on trigger
            this.$triggerElm.attr({
                'tabindex': -1,
                'role': 'tab',
                'aria-selected': 'false',
                'aria-expanded': 'false',
                'aria-controls': this.$targetElm.attr('id')
            });

            // Bind click handler
            this.$triggerElm.on('click', function(e) {
                $selfRef.show(e);
            });

            // Bind key handler
            this.$triggerElm.on('keydown', function(e) {
                $selfRef._actionsKeydown(e, this);
            });

            // Display panel if trigger is marked active
            if (this.$triggerElm.closest('li').hasClass('active')) {
                this.$triggerElm.attr({
                    'tabindex': 0,
                    'aria-selected': 'true',
                    'aria-expanded': 'true'
                });
                this.$targetElm.attr('tabindex', 0)
                    .addClass('active');

                if (this.settings.hidden) {
                    this.$targetElm.attr('aria-hidden', false);
                }
                if (this.settings.animate) {
                    this.$targetElm.addClass('in');
                }
            }

            // Check to see if there is an active element defined - if not set current one as active
            if (this.$navElm.find('li.active').length <= 0) {
                this.$triggerElm.closest('li').addClass('active');

                if (this.$triggerElm.parent('.dropdown-menu').length) {
                    this.$triggerElm.closest('li.dropdown').addClass('active');
                }

                this.$triggerElm.attr({
                    'tabindex': 0,
                    'aria-selected': 'true',
                    'aria-expanded': 'true'
                });
                this.$targetElm.attr('tabindex', 0)
                    .addClass('active');

                if (this.settings.hidden) {
                    this.$targetElm.attr('aria-hidden', 'false');
                }
                if (this.settings.animate) {
                    this.$targetElm.addClass('in');
                }
            }

            this._trigger(this.$triggerElm, 'init.cfw.tab');
        },

        show : function(e) {
            if (e) {
                e.preventDefault();
            }

            if (this.$triggerElm.parent('li').hasClass('active')
                || this.$triggerElm.hasClass('disabled')
                || this.$triggerElm[0].hasAttribute('disabled')) {
                return;
            }

            var $previous = this.$navElm.find('.active:last a[data-cfw="tab"]');
            if ($previous.length) {

                if (!this._trigger($previous, 'beforeHide.cfw.tab', { relatedTarget: this.$triggerElm[0] })) {
                    return;
                }
            }

            if (!this._trigger(this.$triggerElm, 'beforeShow.cfw.tab', { relatedTarget: $previous[0] })) {
                return;
            }

            if ($previous.length) {
                $previous.attr({
                    'tabindex': -1,
                    'aria-selected': 'false',
                    'aria-expanded': 'false'
                });
                this._trigger($previous, 'afterHide.cfw.tab', { relatedTarget: this.$triggerElm[0] });
                // Following line for backwards compatibility (not sure if used anywhere)
                this._trigger($previous, 'hide.cfw.tab');
            }

            this.$triggerElm.attr({
                'tabindex': 0,
                'aria-selected': 'true',
                'aria-expanded': 'true'
            });

            this._activateTab(this.$triggerElm.closest('li'), this.$navElm, false, $previous);
            this._activateTab(this.$targetElm, this.$targetElm.parent(), true, $previous);
        },

        fadeEnable : function() {
            if (!$.support.transitionEnd) { return; }
            this.$targetElm.addClass('fade');
            if (this.$targetElm.hasClass('active')) {
                this.$targetElm.addClass('in');
            }
            this.settings.animate = true;
        },

        fadeDisable : function() {
            this.$targetElm.removeClass('fade in');
            if (this.$targetElm.hasClass('active')) {
                this.$targetElm.addClass('in');
            }
            this.settings.animate = false;
        },

        hiddenDisable : function() {
            this.$targetElm.removeAttr('aria-hidden');
            this.settings.hidden = false;
        },

        _actionsKeydown : function(e, node) {
            // 37-left, 38-up, 39-right, 40-down
            var k = e.which;
            if (!/(37|38|39|40)/.test(k)) { return; }

            e.stopPropagation();
            e.preventDefault();

            var $node = $(node);
            var $ul = $node.closest('ul[role="tablist"]');
            var $items = $ul.find('[role="tab"]:visible').not('.disabled');
            var index = $items.index($items.filter('[aria-selected="true"]'));

            if ((k == 38 || k == 37) && index > 0)                 { index--; }     // up & left
            if ((k == 39 || k == 40) && index < $items.length - 1) { index++; }     // down & right
            if (!~index)                                           { index = 0; }   // force first item

            var nextTab = $items.eq(index);
            nextTab.CFW_Tab('show').trigger('focus');
        },

        _activateTab : function(node, container, isPanel, $previous) {
            var $selfRef = this;
            var $prevActive = container.find('> .active');
            var doTransition = isPanel && $.support.transitionEnd && this.settings.animate;

            function displayTab() {
                $prevActive.removeClass('active')
                    .find('> .dropdown-menu > .active')
                    .removeClass('active');

                node.addClass('active');

                if (isPanel) {
                    $prevActive.attr({
                        'tabindex': -1,
                        'aria-hidden': 'true'
                    });
                    node.attr({
                        'tabindex': 0,
                        'aria-hidden': 'false'
                    });
                }

                if (doTransition) {
                    node[0].offsetWidth; // Reflow for transition
                    node.addClass('in');
                } else {
                    if (isPanel) {
                        $selfRef.settings.animate = false;
                    }
                    node.removeClass('fade');
                }

                if (node.parent('.dropdown-menu').length) {
                    node.closest('li.dropdown').addClass('active');
                }

                if (isPanel) {
                    $selfRef._trigger($selfRef.$triggerElm, 'afterShow.cfw.tab', { relatedTarget: $previous[0] });
                }
            }

            if (doTransition) {
                node.one('cfwTransitionEnd', displayTab)
                .CFW_emulateTransitionEnd(this.settings.speed);
            } else {
                displayTab();
            }

            $prevActive.removeClass('in');
        },

        _getID : function($node, prefix) {
            var nodeID = $node.attr('id');
            if (nodeID === undefined) {
                do nodeID = prefix + '-' + ~~(Math.random() * 1000000);
                while (document.getElementById(nodeID));
                $node.attr('id', nodeID);
            }
            return nodeID;
        },

        _parseDataAttr : function() {
            var parsedData = {};
            var data = this.$triggerElm.data();

            if (typeof data.cfwTabTarget  !== 'undefined') { parsedData.target  = data.cfwTabTarget;  }
            if (typeof data.cfwTabAnimate !== 'undefined') { parsedData.animate = data.cfwTabAnimate; }
            if (typeof data.cfwTabSpeed   !== 'undefined') { parsedData.speed   = data.cfwTabSpeed;   }
            if (typeof data.cfwTabHidden  !== 'undefined') { parsedData.hidden  = data.cfwTabHidden;  }
            return parsedData;
        },

        _trigger : function($callingElm, eventName, extraData) {
            var e = $.Event(eventName);
            if ($.isPlainObject(extraData)) {
                e = $.extend({}, e, extraData);
            }
            $callingElm.trigger(e);
            if (e.isDefaultPrevented()) {
                return false;
            }
            return true;
        }
    };

    function Plugin(option) {
        var args = [].splice.call(arguments, 1);
        return this.each(function() {
            var $this = $(this);
            var data = $this.data('cfw.tab');
            var options = typeof option === 'object' && option;

            if (!data) {
                $this.data('cfw.tab', (data = new CFW_Widget_Tab(this, options)));
            }
            if (typeof option === 'string') {
                data[option].apply(data, args);
            }
        });
    }

    $.fn.CFW_Tab = Plugin;
    $.fn.CFW_Tab.Constructor = CFW_Widget_Tab;

})(jQuery);
<commit_msg>tabs: allow for <ol>, remove tabindex from pane, remove dropdown stuff<commit_after>/**
 * --------------------------------------------------------------------------
 * Figuration (v2.0.0): tab.js
 * Licensed under MIT (https://github.com/cast-org/figuration/blob/master/LICENSE)
 * --------------------------------------------------------------------------
 */

(function($) {
    'use strict';

    var CFW_Widget_Tab = function(element, options) {
        this.$triggerElm = $(element);
        this.$navElm = null;
        this.$targetElm = null;

        this.settings = $.extend({}, CFW_Widget_Tab.DEFAULTS, this._parseDataAttr(), options);

        this._init();
    };

    CFW_Widget_Tab.DEFAULTS = {
        animate     : true,     // If tabs should be allowed fade in and out
        speed       : 150,      // Speed of animation in milliseconds
        hidden      : true      // Use aria-hidden on target containers by default
    };

    CFW_Widget_Tab.prototype = {

        _init : function() {
            var $selfRef = this;

            // Find nav and target elements
            this.$navElm = this.$triggerElm.closest('ul, ol');
            this.$navElm.attr('role', 'tablist');

            var $selector = $(this.settings.target);
            if (!$selector.length) {
                $selector = $(this.$triggerElm.attr('href'));
            }
            this.$targetElm = $($selector);

            if (!this.$targetElm.length) {
                return false;
            }

            this.$triggerElm.attr('data-cfw', 'tab');

            // Check for presence of trigger id - set if not present
            var triggerID = this._getID(this.$triggerElm, 'cfw-tab');

            // Target should have id already - set ARIA attributes
            this.$targetElm.attr({
                'role': 'tabpanel',
                'aria-labelledby': triggerID
            });
            if (this.settings.hidden) {
                this.$targetElm.attr('aria-hidden', true);
            }
            if (this.settings.animate) {
                this.fadeEnable();
            } else {
                this.fadeDisable();
            }

            // Set ARIA attributes on trigger
            this.$triggerElm.attr({
                'tabindex': -1,
                'role': 'tab',
                'aria-selected': 'false',
                'aria-expanded': 'false',
                'aria-controls': this.$targetElm.attr('id')
            });

            // Bind click handler
            this.$triggerElm.on('click', function(e) {
                $selfRef.show(e);
            });

            // Bind key handler
            this.$triggerElm.on('keydown', function(e) {
                $selfRef._actionsKeydown(e, this);
            });

            // Display panel if trigger is marked active
            if (this.$triggerElm.closest('li').hasClass('active')) {
                this.$triggerElm.attr({
                    'tabindex': 0,
                    'aria-selected': 'true',
                    'aria-expanded': 'true'
                });
                this.$targetElm.addClass('active');

                if (this.settings.hidden) {
                    this.$targetElm.attr('aria-hidden', false);
                }
                if (this.settings.animate) {
                    this.$targetElm.addClass('in');
                }
            }

            // Check to see if there is an active element defined - if not set current one as active
            if (this.$navElm.find('li.active').length <= 0) {
                this.$triggerElm.closest('li').addClass('active');

                if (this.$triggerElm.parent('.dropdown-menu').length) {
                    this.$triggerElm.closest('li.dropdown').addClass('active');
                }

                this.$triggerElm.attr({
                    'tabindex': 0,
                    'aria-selected': 'true',
                    'aria-expanded': 'true'
                });
                this.$targetElm.addClass('active');

                if (this.settings.hidden) {
                    this.$targetElm.attr('aria-hidden', 'false');
                }
                if (this.settings.animate) {
                    this.$targetElm.addClass('in');
                }
            }

            this._trigger(this.$triggerElm, 'init.cfw.tab');
        },

        show : function(e) {
            if (e) {
                e.preventDefault();
            }

            if (this.$triggerElm.parent('li').hasClass('active')
                || this.$triggerElm.hasClass('disabled')
                || this.$triggerElm[0].hasAttribute('disabled')) {
                return;
            }

            var $previous = this.$navElm.find('.active:last a[data-cfw="tab"]');
            if ($previous.length) {

                if (!this._trigger($previous, 'beforeHide.cfw.tab', { relatedTarget: this.$triggerElm[0] })) {
                    return;
                }
            }

            if (!this._trigger(this.$triggerElm, 'beforeShow.cfw.tab', { relatedTarget: $previous[0] })) {
                return;
            }

            if ($previous.length) {
                $previous.attr({
                    'tabindex': -1,
                    'aria-selected': 'false',
                    'aria-expanded': 'false'
                });
                this._trigger($previous, 'afterHide.cfw.tab', { relatedTarget: this.$triggerElm[0] });
                // Following line for backwards compatibility (not sure if used anywhere)
                this._trigger($previous, 'hide.cfw.tab');
            }

            this.$triggerElm.attr({
                'tabindex': 0,
                'aria-selected': 'true',
                'aria-expanded': 'true'
            });

            this._activateTab(this.$triggerElm.closest('li'), this.$navElm, false, $previous);
            this._activateTab(this.$targetElm, this.$targetElm.parent(), true, $previous);
        },

        fadeEnable : function() {
            if (!$.support.transitionEnd) { return; }
            this.$targetElm.addClass('fade');
            if (this.$targetElm.hasClass('active')) {
                this.$targetElm.addClass('in');
            }
            this.settings.animate = true;
        },

        fadeDisable : function() {
            this.$targetElm.removeClass('fade in');
            if (this.$targetElm.hasClass('active')) {
                this.$targetElm.addClass('in');
            }
            this.settings.animate = false;
        },

        hiddenDisable : function() {
            this.$targetElm.removeAttr('aria-hidden');
            this.settings.hidden = false;
        },

        _actionsKeydown : function(e, node) {
            // 37-left, 38-up, 39-right, 40-down
            var k = e.which;
            if (!/(37|38|39|40)/.test(k)) { return; }

            e.stopPropagation();
            e.preventDefault();

            var $node = $(node);
            var $list = $node.closest('[role="tablist"]');
            var $items = $list.find('[role="tab"]:visible').not('.disabled');
            var index = $items.index($items.filter('[aria-selected="true"]'));

            if ((k == 38 || k == 37) && index > 0)                 { index--; }     // up & left
            if ((k == 39 || k == 40) && index < $items.length - 1) { index++; }     // down & right
            if (!~index)                                           { index = 0; }   // force first item

            var nextTab = $items.eq(index);
            nextTab.CFW_Tab('show').trigger('focus');
        },

        _activateTab : function(node, container, isPanel, $previous) {
            var $selfRef = this;
            var $prevActive = container.find('> .active');
            var doTransition = isPanel && $.support.transitionEnd && this.settings.animate;

            function displayTab() {
                $prevActive.removeClass('active');

                node.addClass('active');

                if (isPanel) {
                    $prevActive.attr('aria-hidden', 'true');
                    node.attr('aria-hidden', 'false');
                }

                if (doTransition) {
                    node[0].offsetWidth; // Reflow for transition
                    node.addClass('in');
                } else {
                    if (isPanel) {
                        $selfRef.settings.animate = false;
                    }
                    node.removeClass('fade');
                }

                if (isPanel) {
                    $selfRef._trigger($selfRef.$triggerElm, 'afterShow.cfw.tab', { relatedTarget: $previous[0] });
                }
            }

            if (doTransition) {
                node.one('cfwTransitionEnd', displayTab)
                .CFW_emulateTransitionEnd(this.settings.speed);
            } else {
                displayTab();
            }

            $prevActive.removeClass('in');
        },

        _getID : function($node, prefix) {
            var nodeID = $node.attr('id');
            if (nodeID === undefined) {
                do nodeID = prefix + '-' + ~~(Math.random() * 1000000);
                while (document.getElementById(nodeID));
                $node.attr('id', nodeID);
            }
            return nodeID;
        },

        _parseDataAttr : function() {
            var parsedData = {};
            var data = this.$triggerElm.data();

            if (typeof data.cfwTabTarget  !== 'undefined') { parsedData.target  = data.cfwTabTarget;  }
            if (typeof data.cfwTabAnimate !== 'undefined') { parsedData.animate = data.cfwTabAnimate; }
            if (typeof data.cfwTabSpeed   !== 'undefined') { parsedData.speed   = data.cfwTabSpeed;   }
            if (typeof data.cfwTabHidden  !== 'undefined') { parsedData.hidden  = data.cfwTabHidden;  }
            return parsedData;
        },

        _trigger : function($callingElm, eventName, extraData) {
            var e = $.Event(eventName);
            if ($.isPlainObject(extraData)) {
                e = $.extend({}, e, extraData);
            }
            $callingElm.trigger(e);
            if (e.isDefaultPrevented()) {
                return false;
            }
            return true;
        }
    };

    function Plugin(option) {
        var args = [].splice.call(arguments, 1);
        return this.each(function() {
            var $this = $(this);
            var data = $this.data('cfw.tab');
            var options = typeof option === 'object' && option;

            if (!data) {
                $this.data('cfw.tab', (data = new CFW_Widget_Tab(this, options)));
            }
            if (typeof option === 'string') {
                data[option].apply(data, args);
            }
        });
    }

    $.fn.CFW_Tab = Plugin;
    $.fn.CFW_Tab.Constructor = CFW_Widget_Tab;

})(jQuery);
<|endoftext|>


<commit_before>// eslint-disable-next-line no-unused-vars
const viz = {
  circleRadius: 5,

  init(nodes, links) {
    const { width, height } = this.getDimensions('visualization');
    const { canvas, context } = this.createCanvas(width, height);

    this.width = width;
    this.height = height;
    this.canvas = canvas;
    this.context = context;
    this.tooltip = document.getElementById('tooltip');

    this.addListeners();
    this.draw(nodes, links);
  },

  draw(nodes, links) {
    this.nodes = nodes;
    this.links = links;

    this.simulate();
    this.drawOnCanvas();
  },

  simulate() {
    this.simulation = this.simulateForce();
    this.simulation.tick();
  },

  simulateForce() {
    let simulation;

    if (!this.simulation) {
      simulation = d3.forceSimulation(this.nodes);
    } else {
      simulation = this.simulation;
      simulation.nodes(this.nodes);
    }

    const linkForce = d3.forceLink(this.links);
    linkForce.id((d) => d.hostname);
    linkForce.distance(100);
    simulation.force('link', linkForce);

    const centerForce = d3.forceCenter(this.width/2, this.height/2);
    centerForce.x(this.width/2);
    centerForce.y(this.height/2);
    simulation.force('center', centerForce);

    simulation.force('charge', d3.forceManyBody());
    simulation.force('collide', d3.forceCollide(50));
    simulation.alphaTarget(1);
    simulation.stop();

    return simulation;
  },

  createCanvas(width, height) {
    const base = d3.select('#visualization');
    const canvas = base.append('canvas');
    canvas.attr('width', width);
    canvas.attr('height', height);
    const context = canvas.node().getContext('2d');

    return {
      canvas,
      context
    };
  },

  getDimensions(id) {
    const element = document.getElementById(id);
    const { width, height } = element.getBoundingClientRect();

    return {
      width,
      height
    };
  },

  drawOnCanvas() {
    this.context.clearRect(0, 0, this.width, this.height);
    this.context.save();
    this.drawLinks();
    this.drawNodes();
    this.context.restore();
  },

  drawNodes() {
    for (const d of this.nodes) {
      this.context.beginPath();
      this.context.moveTo(d.x, d.y);
      this.context.arc(d.x, d.y, this.circleRadius, 0, 2 * Math.PI);
      if (d.firstParty) {
        this.context.fillStyle = 'red';
      } else {
        this.context.fillStyle = 'blue';
      }
      this.context.closePath();
      this.context.fill();
    }
  },

  showTooltip(title, x, y) {
    this.tooltip.innerText = title;
    this.tooltip.style.left = `${x + this.circleRadius}px`;
    this.tooltip.style.top = `${y + this.circleRadius}px`;
    this.tooltip.style.display = 'block';
  },

  hideTooltip() {
    this.tooltip.style.display = 'none';
  },

  drawLinks() {
    this.context.beginPath();
    for (const d of this.links) {
      this.context.moveTo(d.source.x, d.source.y);
      this.context.lineTo(d.target.x, d.target.y);
    }
    this.context.closePath();
    this.context.strokeStyle = '#ccc';
    this.context.stroke();
  },

  isPointInsideCircle(x, y, cx, cy) {
    const dx = Math.abs(x - cx);
    const dy = Math.abs(y - cy);
    const d = dx*dx + dy*dy;
    const r = this.circleRadius;

    return d <= r*r;
  },

  getNodeAtCoordinates(x, y) {
    for (const node of this.nodes) {
      if (this.isPointInsideCircle(x, y, node.x, node.y)) {
        return node;
      }
    }
    return null;
  },

  addListeners() {
    this.addMouseMove();
  },

  addMouseMove() {
    this.canvas.on('mousemove', () => {
      const [mouseX, mouseY] = d3.mouse(this.canvas.node());
      const node = this.getNodeAtCoordinates(mouseX, mouseY);
      if (node) {
        this.showTooltip(node.hostname, mouseX, mouseY);
      } else {
        this.hideTooltip();
      }
    });
  }
};
<commit_msg>dpi fix. fixes #107<commit_after>// eslint-disable-next-line no-unused-vars
const viz = {
  circleRadius: 5,

  init(nodes, links) {
    const { width, height } = this.getDimensions('visualization');
    const { canvas, context } = this.createCanvas(width, height);

    this.width = width;
    this.height = height;
    this.canvas = canvas;
    this.context = context;
    this.tooltip = document.getElementById('tooltip');

    this.addListeners();
    this.draw(nodes, links);
  },

  draw(nodes, links) {
    this.nodes = nodes;
    this.links = links;

    this.simulate();
    this.drawOnCanvas();
  },

  simulate() {
    this.simulation = this.simulateForce();
    this.simulation.tick();
  },

  simulateForce() {
    let simulation;

    if (!this.simulation) {
      simulation = d3.forceSimulation(this.nodes);
    } else {
      simulation = this.simulation;
      simulation.nodes(this.nodes);
    }

    const linkForce = d3.forceLink(this.links);
    linkForce.id((d) => d.hostname);
    linkForce.distance(100);
    simulation.force('link', linkForce);

    const centerForce = d3.forceCenter(this.width/2, this.height/2);
    centerForce.x(this.width/2);
    centerForce.y(this.height/2);
    simulation.force('center', centerForce);

    simulation.force('charge', d3.forceManyBody());
    simulation.force('collide', d3.forceCollide(50));
    simulation.alphaTarget(1);
    simulation.stop();

    return simulation;
  },

  createCanvas(width, height) {
    const base = d3.select('#visualization');
    const canvas = base.append('canvas');
    const context = canvas.node().getContext('2d');
    const scale = window.devicePixelRatio || 1;
    canvas.attr('width', width * scale);
    canvas.attr('height', height * scale);
    canvas.style('width', `${width}px`);
    canvas.style('height', `${height}px`);
    context.scale(scale, scale);

    return {
      canvas,
      context
    };
  },

  getDimensions(id) {
    const element = document.getElementById(id);
    const { width, height } = element.getBoundingClientRect();

    return {
      width,
      height
    };
  },

  drawOnCanvas() {
    this.context.clearRect(0, 0, this.width, this.height);
    this.context.save();
    this.drawLinks();
    this.drawNodes();
    this.context.restore();
  },

  drawNodes() {
    for (const d of this.nodes) {
      this.context.beginPath();
      this.context.moveTo(d.x, d.y);
      this.context.arc(d.x, d.y, this.circleRadius, 0, 2 * Math.PI);
      if (d.firstParty) {
        this.context.fillStyle = 'red';
      } else {
        this.context.fillStyle = 'blue';
      }
      this.context.closePath();
      this.context.fill();
    }
  },

  showTooltip(title, x, y) {
    this.tooltip.innerText = title;
    this.tooltip.style.left = `${x + this.circleRadius}px`;
    this.tooltip.style.top = `${y + this.circleRadius}px`;
    this.tooltip.style.display = 'block';
  },

  hideTooltip() {
    this.tooltip.style.display = 'none';
  },

  drawLinks() {
    this.context.beginPath();
    for (const d of this.links) {
      this.context.moveTo(d.source.x, d.source.y);
      this.context.lineTo(d.target.x, d.target.y);
    }
    this.context.closePath();
    this.context.strokeStyle = '#ccc';
    this.context.stroke();
  },

  isPointInsideCircle(x, y, cx, cy) {
    const dx = Math.abs(x - cx);
    const dy = Math.abs(y - cy);
    const d = dx*dx + dy*dy;
    const r = this.circleRadius;

    return d <= r*r;
  },

  getNodeAtCoordinates(x, y) {
    for (const node of this.nodes) {
      if (this.isPointInsideCircle(x, y, node.x, node.y)) {
        return node;
      }
    }
    return null;
  },

  addListeners() {
    this.addMouseMove();
  },

  addMouseMove() {
    this.canvas.on('mousemove', () => {
      const [mouseX, mouseY] = d3.mouse(this.canvas.node());
      const node = this.getNodeAtCoordinates(mouseX, mouseY);
      if (node) {
        this.showTooltip(node.hostname, mouseX, mouseY);
      } else {
        this.hideTooltip();
      }
    });
  }
};
<|endoftext|>


<commit_before>/*
 * JSFace Object Oriented Programming Library
 * https://github.com/tnhu/jsface
 *
 * Copyright (c) Tan Nhu
 * Licensed under MIT license (https://github.com/tnhu/jsface/blob/master/LICENSE.txt)
 */
(function(context, OBJECT, NUMBER, LENGTH, toString, readyFns, readyCount, undefined, oldClass, jsface) {
  /**
   * Return a map itself or null. A map is a set of { key: value }
   * @param obj object to be checked
   * @return obj itself as a map or false
   */
  function mapOrNil(obj) { return (obj && typeof obj === OBJECT && !(typeof obj.length === NUMBER && !(obj.propertyIsEnumerable(LENGTH))) && obj) || null; }

  /**
   * Return an array itself or null
   * @param obj object to be checked
   * @return obj itself as an array or null
   */
  function arrayOrNil(obj) { return (obj && typeof obj === OBJECT && typeof obj.length === NUMBER && !(obj.propertyIsEnumerable(LENGTH)) && obj) || null; }

  /**
   * Return a function itself or null
   * @param obj object to be checked
   * @return obj itself as a function or null
   */
  function functionOrNil(obj) { return (obj && typeof obj === "function" && obj) || null; }

  /**
   * Return a class itself or null
   * @param obj object to be checked
   * @return obj itself as a class or false
   */
  function classOrNil(obj) { return (functionOrNil(obj) && (obj.prototype && obj === obj.prototype.constructor) && obj) || null; }

  /**
   * Util for extend() to copy a map of { key:value } to an object
   * @param key key
   * @param value value
   * @param ignoredKeys ignored keys
   * @param object object
   * @param iClass true if object is a class
   * @param oPrototype object prototype
   */
  function copier(key, value, ignoredKeys, object, iClass, oPrototype) {
    if ( !ignoredKeys || !ignoredKeys.hasOwnProperty(key)) {
      object[key] = value;
    }
  }

  /**
   * Extend object from subject, ignore properties in ignoredKeys
   * @param object the child
   * @param subject the parent
   * @param ignoredKeys (optional) keys should not be copied to child
   */
  function extend(object, subject, ignoredKeys) {
    if (arrayOrNil(subject)) {
      for (var len = subject.length; --len >= 0;) { extend(object, subject[len], ignoredKeys); }
    } else {
      ignoredKeys = ignoredKeys || { constructor: 1, $super: 1, prototype: 1, $superp: 1 };

      var iClass     = classOrNil(object),
          isSubClass = classOrNil(subject),
          oPrototype = object.prototype, supez, key, proto;

      // copy static properties and prototype.* to object
      if (mapOrNil(subject) || iClass) {
        for (key in subject) {
          copier(key, subject[key], ignoredKeys, object, iClass, oPrototype);
        }
      }

      if (isSubClass) {
        proto = subject.prototype;
        for (key in proto) {
          copier(key, proto[key], ignoredKeys, object, iClass, oPrototype);
        }
      }

      // prototype properties
      if (iClass && isSubClass) { extend(oPrototype, subject.prototype, ignoredKeys); }
    }
  }

  /**
   * Create a class.
   * @param parent parent class(es)
   * @param api class api
   * @return class
   */
  function Class(parent, api) {
    if ( !api) {
      parent = (api = parent, 0); // !api means there's no parent
    }

    // TODO remove $statics, use $static instead
    var clazz, constructor, singleton, statics, key, bindTo, len, i = 0, p,
        ignoredKeys = { constructor: 1, $singleton: 1, $static:1, $statics: 1, prototype: 1, $super: 1, $superp: 1, main: 1, toString: 0 },
        plugins     = Class.plugins,
        rootParent, parentClass, Stub;

    api         = (typeof api === "function" ? api() : api) || {};             // execute api if it's a function
    constructor = api.hasOwnProperty("constructor") ? api.constructor : 0;     // hasOwnProperty is a must, constructor is special
    singleton   = api.$singleton;
    statics     = api.$statics || api.$static;

    // add plugins' keys into ignoredKeys
    for (key in plugins) { ignoredKeys[key] = 1; }

    // construct constructor
    clazz  = singleton ? function(){} : (constructor ? constructor : function(){});

    // make sure parent is always an array
    parent = !parent || parent instanceof Array ? parent : [ parent ];
    len = parent && parent.length;
    rootParent = parent[0];

    if ( !singleton && len) {
      parentClass = rootParent.prototype && rootParent === rootParent.prototype.constructor && rootParent;

      if ( !parentClass) {
        clazz.prototype = rootParent;
      } else {
        // Constributed by Freddy Snijder (https://github.com/tnhu/jsface/issues/26)
        Stub = function(){};

        Stub.prototype                    = parentClass.prototype;
        Stub.prototype.constructor        = Stub;
        clazz.prototype                   = new Stub();
        clazz.prototype.constructor       = clazz;       // restoring proper constructor for child class
        parentClass.prototype.constructor = parentClass; // restoring proper constructor for parent class
      }
    }

    // determine bindTo: where api should be bound
    bindTo = singleton ? clazz : clazz.prototype;

    // do inherit static properties and extentions (parents other than the first one)
    while (i < len) {
      p = parent[i++];

      // copy static properties
      for (key in p) {
        if ( !ignoredKeys[key]) {
          clazz[key] = p[key];
        }
      }
      if ( !singleton && i !== 0) {
        for (key in p.prototype) {
          if ( !ignoredKeys[key]) {
            bindTo[key] = p.prototype[key];
          }
        }
      }
    }

    // copy properties from api to bindTo
    for (key in api) {
      if ( !ignoredKeys[key]) {
        var prop = api[key];

        if (prop && (prop.get || prop.set)) {                 // check if it is a property descriptor
          Object.defineProperty(bindTo, key, prop);
        } else {
          bindTo[key] = prop;
        }
      }
    }

    // copy static properties from statics to clazz
    for (key in statics) {
      clazz[key] = statics[key];
    }

    // add $super and $superp to refer to parent class and parent.prototype (if applied)
    p = parent && rootParent || parent;
    clazz.$super  = p;
    clazz.$superp = p && p.prototype || p;

    for (key in plugins) { plugins[key](clazz, parent, api); }            // pass control to plugins
    if (typeof api.main === "function") { api.main.call(clazz, clazz); }  // execute main()

    return clazz;
  }

  /* Class plugins repository */
  Class.plugins = {
    $ready: function invoke(clazz, parent, api, loop) {
      var r       = api.$ready,
          len     = parent ? parent.length : 0,
          count   = len,
          _super  = len && parent[0].$super,
          pa, i, entry;

      // find and invoke $ready from parent(s)
      while (len--) {
        for (i = 0; i < readyCount; i++) {
          entry = readyFns[i];
          pa    = parent[len];

          if (pa === entry[0]) {
            entry[1].call(pa, clazz, parent, api);
            count--;
          }

          if ( !count) { break; }
        }
      }

      // call $ready from grandparent(s), if any
      if (_super) {
        invoke(clazz, [ _super ], api, true);
      }

      // in an environment where there are a lot of class creating/removing (rarely)
      // this implementation might cause a leak (saving pointers to clazz and $ready)
      if ( !loop && functionOrNil(r)) {
        r.call(clazz, clazz, parent, api);  // invoke ready from current class
        readyFns.push([ clazz,  r ]);
        readyCount++;
      }
    }
  };

  /* Initialization */
  jsface = {
    Class        : Class,
    extend       : extend,
    mapOrNil     : mapOrNil,
    arrayOrNil   : arrayOrNil,
    functionOrNil: functionOrNil,
    classOrNil   : classOrNil
  };

  if (typeof module !== "undefined" && module.exports) {                       // NodeJS/CommonJS
    module.exports = jsface;
  } else {
    oldClass          = context.Class;                                         // save current Class namespace
    context.Class     = Class;                                                 // bind Class and jsface to global scope
    context.jsface    = jsface;
    jsface.noConflict = function() { context.Class = oldClass; };              // no conflict
  }
})(this, "object", "number", "length", Object.prototype.toString, [], 0);
<commit_msg>Initial and untested implementation of constants<commit_after>/*
 * JSFace Object Oriented Programming Library
 * https://github.com/tnhu/jsface
 *
 * Copyright (c) Tan Nhu
 * Licensed under MIT license (https://github.com/tnhu/jsface/blob/master/LICENSE.txt)
 */
(function(context, OBJECT, NUMBER, LENGTH, toString, readyFns, readyCount, undefined, oldClass, jsface) {
  /**
   * Return a map itself or null. A map is a set of { key: value }
   * @param obj object to be checked
   * @return obj itself as a map or false
   */
  function mapOrNil(obj) { return (obj && typeof obj === OBJECT && !(typeof obj.length === NUMBER && !(obj.propertyIsEnumerable(LENGTH))) && obj) || null; }

  /**
   * Return an array itself or null
   * @param obj object to be checked
   * @return obj itself as an array or null
   */
  function arrayOrNil(obj) { return (obj && typeof obj === OBJECT && typeof obj.length === NUMBER && !(obj.propertyIsEnumerable(LENGTH)) && obj) || null; }

  /**
   * Return a function itself or null
   * @param obj object to be checked
   * @return obj itself as a function or null
   */
  function functionOrNil(obj) { return (obj && typeof obj === "function" && obj) || null; }

  /**
   * Return a class itself or null
   * @param obj object to be checked
   * @return obj itself as a class or false
   */
  function classOrNil(obj) { return (functionOrNil(obj) && (obj.prototype && obj === obj.prototype.constructor) && obj) || null; }

  /**
   * Util for extend() to copy a map of { key:value } to an object
   * @param key key
   * @param value value
   * @param ignoredKeys ignored keys
   * @param object object
   * @param iClass true if object is a class
   * @param oPrototype object prototype
   */
  function copier(key, value, ignoredKeys, object, iClass, oPrototype) {
    if ( !ignoredKeys || !ignoredKeys.hasOwnProperty(key)) {
      object[key] = value;
    }
  }

  /**
   * Extend object from subject, ignore properties in ignoredKeys
   * @param object the child
   * @param subject the parent
   * @param ignoredKeys (optional) keys should not be copied to child
   */
  function extend(object, subject, ignoredKeys) {
    if (arrayOrNil(subject)) {
      for (var len = subject.length; --len >= 0;) { extend(object, subject[len], ignoredKeys); }
    } else {
      ignoredKeys = ignoredKeys || { constructor: 1, $super: 1, prototype: 1, $superp: 1 };

      var iClass     = classOrNil(object),
          isSubClass = classOrNil(subject),
          oPrototype = object.prototype, supez, key, proto;

      // copy static properties and prototype.* to object
      if (mapOrNil(subject) || iClass) {
        for (key in subject) {
          copier(key, subject[key], ignoredKeys, object, iClass, oPrototype);
        }
      }

      if (isSubClass) {
        proto = subject.prototype;
        for (key in proto) {
          copier(key, proto[key], ignoredKeys, object, iClass, oPrototype);
        }
      }

      // prototype properties
      if (iClass && isSubClass) { extend(oPrototype, subject.prototype, ignoredKeys); }
    }
  }

  /**
   * To make object fully immutable, freeze each object inside it.
   * @param object to deep freeze
   */
  function deepFreeze(object) {
    var prop, propKey;
    Object.freeze(object); // first freeze the object
    for (propKey in object) {
      prop = object[propKey];
      if (!object.hasOwnProperty(propKey) || !(typeof prop === 'object') || Object.isFrozen(prop)) {
        // If the object is on the prototype, not an object, or is already frozen,
        // skip it. Note that this might leave an unfrozen reference somewhere in the
        // object if there is an already frozen object containing an unfrozen object.
        continue;
      }

      deepFreeze(prop); // recursively call deepFreeze
    }
  }

  /**
   * Create a class.
   * @param parent parent class(es)
   * @param api class api
   * @return class
   */
  function Class(parent, api) {
    if ( !api) {
      parent = (api = parent, 0); // !api means there's no parent
    }

    // TODO remove $statics, use $static instead
    var clazz, consts, constructor, singleton, statics, key, bindTo, len, i = 0, p,
        ignoredKeys = { constructor: 1, $const: 1, $singleton: 1, $static:1, $statics: 1, prototype: 1, $super: 1, $superp: 1, main: 1, toString: 0 },
        plugins     = Class.plugins,
        rootParent, parentClass, Stub;

    api         = (typeof api === "function" ? api() : api) || {};             // execute api if it's a function
    constructor = api.hasOwnProperty("constructor") ? api.constructor : 0;     // hasOwnProperty is a must, constructor is special
    consts      = api.$const;
    singleton   = api.$singleton;
    statics     = api.$statics || api.$static;

    // add plugins' keys into ignoredKeys
    for (key in plugins) { ignoredKeys[key] = 1; }

    // construct constructor
    clazz  = singleton ? function(){} : (constructor ? constructor : function(){});

    // make sure parent is always an array
    parent = !parent || parent instanceof Array ? parent : [ parent ];
    len = parent && parent.length;
    rootParent = parent[0];

    if ( !singleton && len) {
      parentClass = rootParent.prototype && rootParent === rootParent.prototype.constructor && rootParent;

      if ( !parentClass) {
        clazz.prototype = rootParent;
      } else {
        // Constributed by Freddy Snijder (https://github.com/tnhu/jsface/issues/26)
        Stub = function(){};

        Stub.prototype                    = parentClass.prototype;
        Stub.prototype.constructor        = Stub;
        clazz.prototype                   = new Stub();
        clazz.prototype.constructor       = clazz;       // restoring proper constructor for child class
        parentClass.prototype.constructor = parentClass; // restoring proper constructor for parent class
      }
    }

    // determine bindTo: where api should be bound
    bindTo = singleton ? clazz : clazz.prototype;

    // do inherit static properties and extentions (parents other than the first one)
    while (i < len) {
      p = parent[i++];

      // copy static properties
      for (key in p) {
        if ( !ignoredKeys[key]) {
          clazz[key] = p[key];
        }
      }
      if ( !singleton && i !== 0) {
        for (key in p.prototype) {
          if ( !ignoredKeys[key]) {
            bindTo[key] = p.prototype[key];
          }
        }
      }
    }

    // copy properties from api to bindTo
    for (key in api) {
      if ( !ignoredKeys[key]) {
        var prop = api[key];

        if (prop && (prop.get || prop.set)) {                 // check if it is a property descriptor
          Object.defineProperty(bindTo, key, prop);
        } else {
          bindTo[key] = prop;
        }
      }
    }

    // copy static properties from statics to clazz
    for (key in statics) {
      clazz[key] = statics[key];
    }

    // copy immutable properties from consts to clazz and freeze them recursively
    for (key in consts) {
      Object.defineProperty(clazz, key, { configurable: true, enumerable: true, writable: false, value: consts[key] });

      if ((typeof clazz[key] === 'object') && !Object.isFrozen(clazz[key])) {
        deepFreeze(clazz[key]); // if property is an unfrozen object, freeze it recursively
      }
    }

    // add $super and $superp to refer to parent class and parent.prototype (if applied)
    p = parent && rootParent || parent;
    clazz.$super  = p;
    clazz.$superp = p && p.prototype || p;

    for (key in plugins) { plugins[key](clazz, parent, api); }            // pass control to plugins
    if (typeof api.main === "function") { api.main.call(clazz, clazz); }  // execute main()

    return clazz;
  }

  /* Class plugins repository */
  Class.plugins = {
    $ready: function invoke(clazz, parent, api, loop) {
      var r       = api.$ready,
          len     = parent ? parent.length : 0,
          count   = len,
          _super  = len && parent[0].$super,
          pa, i, entry;

      // find and invoke $ready from parent(s)
      while (len--) {
        for (i = 0; i < readyCount; i++) {
          entry = readyFns[i];
          pa    = parent[len];

          if (pa === entry[0]) {
            entry[1].call(pa, clazz, parent, api);
            count--;
          }

          if ( !count) { break; }
        }
      }

      // call $ready from grandparent(s), if any
      if (_super) {
        invoke(clazz, [ _super ], api, true);
      }

      // in an environment where there are a lot of class creating/removing (rarely)
      // this implementation might cause a leak (saving pointers to clazz and $ready)
      if ( !loop && functionOrNil(r)) {
        r.call(clazz, clazz, parent, api);  // invoke ready from current class
        readyFns.push([ clazz,  r ]);
        readyCount++;
      }
    }
  };

  /* Initialization */
  jsface = {
    Class        : Class,
    extend       : extend,
    mapOrNil     : mapOrNil,
    arrayOrNil   : arrayOrNil,
    functionOrNil: functionOrNil,
    classOrNil   : classOrNil
  };

  if (typeof module !== "undefined" && module.exports) {                       // NodeJS/CommonJS
    module.exports = jsface;
  } else {
    oldClass          = context.Class;                                         // save current Class namespace
    context.Class     = Class;                                                 // bind Class and jsface to global scope
    context.jsface    = jsface;
    jsface.noConflict = function() { context.Class = oldClass; };              // no conflict
  }
})(this, "object", "number", "length", Object.prototype.toString, [], 0);
<|endoftext|>


<commit_before>var e = module.exports = {};

var gm = require('gm');
var path = require('path');
var moment = require('moment');
var util = require('util');
const reload = require('require-reload');
const Jimp = reload('jimp');

e.init = () => {
    e.category = bu.CommandType.GENERAL;
};

e.requireCtx = require;

e.isCommand = true;
e.hidden = false;
e.usage = 'retarded <text> [flags]';
e.info = `Tells everyone who is retarded.`;
e.longinfo = `<p>Tells everyone who is retarded</p>`;

e.flags = [{
    flag: 'u',
    word: 'user',
    desc: 'The person who is retarded. If unset, it defaults to you!'
}]

e.execute = async function(msg, words) {
    let input = bu.parseInput(e.flags, words);
    if (input.undefined.length == 0) {
        bu.send(msg, 'Not enough input!');
        return;
    }
    let user;
    if (input.u) {
        user = await bu.getUser(msg, input.u.join(' '));
    }
    let quote = await bu.filterMentions(input.undefined.join(' '));
    let body;
    if (user)
        body = (await bu.request({
            uri: user.avatarURL,
            encoding: null
        })).body;
    bot.sendChannelTyping(msg.channel.id);
    try {

        let buf = await bu.createCaption({
            font: 'ARCENA.ttf',
            fill: 'black',
            stroke: 'white',
            strokewidth: 5,
            text: quote,
            size: '272x60'
        });

        let text = await Jimp.read(buf);
        let img = await Jimp.read(path.join(__dirname, '..', 'img', `retarded.png`));
        if (body) {
            let avatar = await Jimp.read(body);
            let smallAvatar = avatar.clone();
            smallAvatar.resize(74, 74);
            img.composite(smallAvatar, 166, 131);
            avatar.resize(171, 171);
            avatar.rotate(18)
            img.composite(avatar, 277, 32);
        }
        img.composite(text, 268, 0);
        img.getBuffer(Jimp.MIME_PNG, (err, buffer) => {
            bu.send(msg, undefined, {
                file: buffer,
                name: 'SHIT.png'
            });
        })
    } catch (err) {
        logger.error(err);
    }
};<commit_msg>whoops docs<commit_after>var e = module.exports = {};

var gm = require('gm');
var path = require('path');
var moment = require('moment');
var util = require('util');
const reload = require('require-reload');
const Jimp = reload('jimp');

e.init = () => {
    e.category = bu.CommandType.GENERAL;
};

e.requireCtx = require;

e.isCommand = true;
e.hidden = false;
e.usage = 'retarded <text> [flags]';
e.info = `Tells everyone who is retarded.`;
e.longinfo = `<p>Tells everyone who is retarded</p>`;

e.flags = [{
    flag: 'u',
    word: 'user',
    desc: 'The person who is retarded.'
}]

e.execute = async function(msg, words) {
    let input = bu.parseInput(e.flags, words);
    if (input.undefined.length == 0) {
        bu.send(msg, 'Not enough input!');
        return;
    }
    let user;
    if (input.u) {
        user = await bu.getUser(msg, input.u.join(' '));
    }
    let quote = await bu.filterMentions(input.undefined.join(' '));
    let body;
    if (user)
        body = (await bu.request({
            uri: user.avatarURL,
            encoding: null
        })).body;
    bot.sendChannelTyping(msg.channel.id);
    try {

        let buf = await bu.createCaption({
            font: 'ARCENA.ttf',
            fill: 'black',
            stroke: 'white',
            strokewidth: 5,
            text: quote,
            size: '272x60'
        });

        let text = await Jimp.read(buf);
        let img = await Jimp.read(path.join(__dirname, '..', 'img', `retarded.png`));
        if (body) {
            let avatar = await Jimp.read(body);
            let smallAvatar = avatar.clone();
            smallAvatar.resize(74, 74);
            img.composite(smallAvatar, 166, 131);
            avatar.resize(171, 171);
            avatar.rotate(18)
            img.composite(avatar, 277, 32);
        }
        img.composite(text, 268, 0);
        img.getBuffer(Jimp.MIME_PNG, (err, buffer) => {
            bu.send(msg, undefined, {
                file: buffer,
                name: 'SHIT.png'
            });
        })
    } catch (err) {
        logger.error(err);
    }
};<|endoftext|>


<commit_before>if(typeof sne == "undefined") sne = { steps: {} };
sne.steps.docchooser = {};

(function ()
{
  var docchooserCallback = null;
  var usernameMap = null;
  var docs = [];
  var $docs = $('#docs');

  sne.steps.docchooser.show = function (cb)
  {
    logNavigation('docchoser');
    $('#docChooser').addClass('active');
    reloadDocsTable();
    docchooserCallback = cb;
  };

  sne.steps.docchooser.hide = function ()
  {
    $('#docChooser').removeClass('active');
    docchooserCallback();
  };

  function reloadDocsTable ()
  {
    shownoteseditor.connectors[sne.connectorName].listDocuments(sne.connectorOptions,
      function (err, _docs)
      {
        docs = _docs;
        tabletools.clear($docs);

        $('#noDocs').css('display', (docs.length == 0) ? 'block' : 'none');

        for (var i = 0; i < docs.length; i++)
        {
          var doc = docs[i];
          addDocToTable(doc);
        }
      }
    );

    shownoteseditor.connectors[sne.connectorName].getUsernameMap(sne.connectorOptions,
      function (err, _usernameMap)
      {
        usernameMap = _usernameMap;
        console.log(usernameMap);
      }
    );
  }

  function addDocToTable (doc)
  {
    var $btns = $('#btnsTemplate').clone();
    var accessDate = moment(doc.accessDate).format("DD.MM.YYYY");
    var owner = (usernameMap[doc.owner] || {}).name || "Unnamed";
    var $td = tabletools.addRow($docs, [ doc.name, accessDate, owner, $btns ]);

    $btns = $td.find('.btns').parent().addClass('btns');
    $td.click(
      function (e)
      {
        var $target = $(e.target);

        if($target.prop('tagName').toLowerCase() == "button" ||
           $target.parent().prop('tagName').toLowerCase() == "button")
        {
          return;
        }

        openDoc(doc.id);
      }
    );
    $td.find('button.download').click(
      function ()
      {
        downloadDoc(doc.id, doc.name);
      }
    );
    $td.find('button.edit').click(
      function ()
      {
        sne.steps.docedit.show("edit", doc, usernameMap,
          function (success, doc)
          {
            $('#docChooser').addClass('active');
            reloadDocsTable();
          }
        );
      }
    );
    $td.find('button.delete').click(
      function ()
      {
        deleteDoc(doc.id,
          function (err)
          {
            reloadDocsTable();
            if(err)
              alert(err);
          }
        );
      }
    );
  }
  $('#docsSearch').keyup(
    function ()
    {
      $.uiTableFilter($docs, $('#docsSearch').val(), "Name");
    }
  );

  $('#createDoc').click(showCreateDoc);

  function showCreateDoc ()
  {
    sne.steps.docedit.show("create", null, usernameMap,
      function (success, doc)
      {
        if(success)
        {
          docs.push(doc);
          openDoc(doc.id);
        }
        else
        {
          $('#docChooser').addClass('active');
        }
      }
    );
  }

  function openDoc (id)
  {
    var doc;

    for (var i = 0; i < docs.length; i++)
    {
      if(docs[i].id == id)
        doc = docs[i];
    }

    sne.doc = doc;
    sne.files = doc.urls;
    logNavigation('doc/' + doc.name);

    sne.steps.docchooser.hide();
  }

  function downloadDoc (id, name)
  {
    shownoteseditor.connectors[sne.connectorName].getDocument(sne.connectorOptions, id,
      function (err, notes)
      {
        var osf = osftools.osfNotes(notes);

        var parts = [osf];
        var blob = new Blob(parts, { "type" : "text/octet-stream" });
        var url = window.URL.createObjectURL(blob);

        var a = document.createElement('a');
        a.href = url;
        a.download = name + ".osf.txt";
        a.style.display = 'none';
        document.body.appendChild(a);
        a.click();
        delete a;
      }
    );
  }

  function deleteDoc (id, cb)
  {
    var res = confirm("Do you really want to delete this document?");

    if(!res)
      return;

    shownoteseditor.connectors[sne.connectorName].deleteDocument(sne.connectorOptions, id, cb);
  }
})();
<commit_msg>Removed debug output<commit_after>if(typeof sne == "undefined") sne = { steps: {} };
sne.steps.docchooser = {};

(function ()
{
  var docchooserCallback = null;
  var usernameMap = null;
  var docs = [];
  var $docs = $('#docs');

  sne.steps.docchooser.show = function (cb)
  {
    logNavigation('docchoser');
    $('#docChooser').addClass('active');
    reloadDocsTable();
    docchooserCallback = cb;
  };

  sne.steps.docchooser.hide = function ()
  {
    $('#docChooser').removeClass('active');
    docchooserCallback();
  };

  function reloadDocsTable ()
  {
    shownoteseditor.connectors[sne.connectorName].listDocuments(sne.connectorOptions,
      function (err, _docs)
      {
        docs = _docs;
        tabletools.clear($docs);

        $('#noDocs').css('display', (docs.length == 0) ? 'block' : 'none');

        for (var i = 0; i < docs.length; i++)
        {
          var doc = docs[i];
          addDocToTable(doc);
        }
      }
    );

    shownoteseditor.connectors[sne.connectorName].getUsernameMap(sne.connectorOptions,
      function (err, _usernameMap)
      {
        usernameMap = _usernameMap;
      }
    );
  }

  function addDocToTable (doc)
  {
    var $btns = $('#btnsTemplate').clone();
    var accessDate = moment(doc.accessDate).format("DD.MM.YYYY");
    var owner = (usernameMap[doc.owner] || {}).name || "Unnamed";
    var $td = tabletools.addRow($docs, [ doc.name, accessDate, owner, $btns ]);

    $btns = $td.find('.btns').parent().addClass('btns');
    $td.click(
      function (e)
      {
        var $target = $(e.target);

        if($target.prop('tagName').toLowerCase() == "button" ||
           $target.parent().prop('tagName').toLowerCase() == "button")
        {
          return;
        }

        openDoc(doc.id);
      }
    );
    $td.find('button.download').click(
      function ()
      {
        downloadDoc(doc.id, doc.name);
      }
    );
    $td.find('button.edit').click(
      function ()
      {
        sne.steps.docedit.show("edit", doc, usernameMap,
          function (success, doc)
          {
            $('#docChooser').addClass('active');
            reloadDocsTable();
          }
        );
      }
    );
    $td.find('button.delete').click(
      function ()
      {
        deleteDoc(doc.id,
          function (err)
          {
            reloadDocsTable();
            if(err)
              alert(err);
          }
        );
      }
    );
  }
  $('#docsSearch').keyup(
    function ()
    {
      $.uiTableFilter($docs, $('#docsSearch').val(), "Name");
    }
  );

  $('#createDoc').click(showCreateDoc);

  function showCreateDoc ()
  {
    sne.steps.docedit.show("create", null, usernameMap,
      function (success, doc)
      {
        if(success)
        {
          docs.push(doc);
          openDoc(doc.id);
        }
        else
        {
          $('#docChooser').addClass('active');
        }
      }
    );
  }

  function openDoc (id)
  {
    var doc;

    for (var i = 0; i < docs.length; i++)
    {
      if(docs[i].id == id)
        doc = docs[i];
    }

    sne.doc = doc;
    sne.files = doc.urls;
    logNavigation('doc/' + doc.name);

    sne.steps.docchooser.hide();
  }

  function downloadDoc (id, name)
  {
    shownoteseditor.connectors[sne.connectorName].getDocument(sne.connectorOptions, id,
      function (err, notes)
      {
        var osf = osftools.osfNotes(notes);

        var parts = [osf];
        var blob = new Blob(parts, { "type" : "text/octet-stream" });
        var url = window.URL.createObjectURL(blob);

        var a = document.createElement('a');
        a.href = url;
        a.download = name + ".osf.txt";
        a.style.display = 'none';
        document.body.appendChild(a);
        a.click();
        delete a;
      }
    );
  }

  function deleteDoc (id, cb)
  {
    var res = confirm("Do you really want to delete this document?");

    if(!res)
      return;

    shownoteseditor.connectors[sne.connectorName].deleteDocument(sne.connectorOptions, id, cb);
  }
})();
<|endoftext|>


<commit_before>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function(uid_day, uid_offering, getStudentInfo, callback)	{
 	var numStud = 0;
 	var studList = [];
  //	TO DO:
  //	REPLACE THIS CALLBACK STRING WITH A JOIN QUERY
  //	EITHER USE GETSTUDENTINFO IN ANOTHER FILE OR CUT IT
  //
 	con.query('SELECT * FROM choices', function(err, row) {
    	if(!err) {
	    	for(var i=0; i<row.length; i++) {
	         	if(uid_offering == row[i].uid_offering && uid_day == row[i].uid_day) {
		           	numStud += 1;
		           	if(getStudentInfo) {
		             	studList.push(row[i].uid_student);
		           	}
	         	}
	       	}
	       	if(getStudentInfo) {
	         	var infoList = [];
	         	con.query('SELECT * FROM students', function(err, row) {
		           	if(!err) {
		            	for(var i=0; i<row.length; i++) {
		               		for(var j=0; j<studList.length; j++) {
			                 	if(row[i].uid_student == studList[j]) {
			                		infoList.push(row[i].firstname + " " + row[i].lastname);
			                 	}
		               		}
		            	}
		            	callback(numStud, infoList);
		            } else {
		            	console.log("SELECT FROM STUDENTS DONE ERRD");
	             		console.log(err);
		            }
	         	});
	       	} else {
	         callback(numStud, null);
	     	}
       	} else {
       		console.log("SELECT FROM CHOICES DONE ERRD");
       		console.log(err);
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, callback) {
   con.query('SELECT max_size FROM offerings WHERE uid_offering = ?', [uid_offering], function(err, data) {
    if(!err) {
      module.exports.numStudents(uid_day, uid_offering, false, function(num, infoList){
        if(num >= data[0].max_size) {
          callback("disabled");
        } else {
          callback("able");
        }
      });
    } else {
      console.log("The function produced an error.");
    }
  });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list ('offerList') of Offering objects, with all necessary properties (although the teacher will be a Name NOT a uid)
 getOfferings: function (uid_day, callback) {
   function Offering(uid, name, description, maxSize, recurring, teacher, location) {
    this.uid = uid;
    this.name = name;
    this.description = description;
    this.maxSize = maxSize;
    this.recur = recurring;
    this.teacher = teacher;
    this.location = location;
    this.disabled;
  }
  var offerList = [];
  var trueOffers = [];
  //	TO DO:
  //	REPLACE THIS CALLBACK STRING WITH A JOIN QUERY
  //
  //	Gets all offerings associated with that day
  con.query('SELECT * FROM calendar', function(err, dayList){
    for(var i=0; i<dayList.length; i++) {
      if(dayList[i].uid_day == uid_day) {
        trueOffers.push(dayList[i].uid_offering);
      }
    }
    //	Gets the info associated with those offerings
    con.query('SELECT * FROM offerings', function(err, rowList) {
      if(!err) {
        for(var i=0; i<rowList.length; i++) {
          for(var j=0; j<trueOffers.length; j++) {
            if(rowList[i].uid_offering == trueOffers[j]) {
              var offering = new Offering(rowList[i].uid_offering, rowList[i].name, rowList[i].description, rowList[i].max_size, rowList[i].recurring, rowList[i].uid_teacher, rowList[i].location);
              offerList.push(offering);
            }
          }
        }
        //	Gets the teacher's names rather than their uids
        con.query('SELECT * FROM teachers', function(err, row) {
          if(!err) {
            for(var j=0; j<row.length; j++) {
              for(var i=0; i<offerList.length; i++) {
                if(row[j].uid_teacher == offerList[i].teacher) {
                  offerList[i].teacher = row[j].prefix + " " + row[j].teacher_lastname;
                };
              };
            };
            callback(offerList);
          } else {
            console.log("We're sorry. getOfferings() produced an error.");
          }
        });
      } else {
        console.log("We're sorry. getOfferings() produced an error.");
      }
    });
  });
 },

// Function takes in an Oppblock day
// Returns a list of unfilled Offering Objects for that day
 getAvailableOfferings: function (uid_day, callback) {
  //	TO DO:
  //	REMOVE THIS FUNCTION AND PUT THE DISABLING LOOP IN GETOFFERINGS
  var availableList = []
  module.exports.getOfferings(uid_day, function(response) {
    var j = 0;
    for(var i = 0; i <response.length; i++) {
      module.exports.isOfferingFull(uid_day, response[i].uid, function(truth){
		  response[j].disabled = truth;
		  availableList.push(response[j]);
		  j+=1;
		  if(j==response.length) {
			callback(availableList);
		  }
      });
    }
  });
 },

// Takes in nothing
// Returns two values:
// A uid_day of the coming oppblock (null if the students can't yet choose) AND
// A boolean cutOff, signifying whether the user is now past the cutoff time for students' choices
 getSoonestOppblockDay: function(callback) {
 	//	TO DO:
 	//	FIND OUT ANYWHERE ELSE IN PROJECT WHERE THIS FUNCTION MIGHT BE NECESSARY//MAKE IT MORE GENERAL FOR THOSE PURPOSES
	con.query('SELECT * FROM opp_block_day', function(err, results){
		// Gets all Oppblock days
		if(!err){
			var uid_day = null;
			var closest = moment().add(1, 'y');
			for (var i=0; i<results.length; i++) {
				//	Loops to find soonest Oppblock
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				//	TO DO: SIMPLY THIS CODE
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and before the closest
				//	If so, replaces closest with the current
				console.log(curr);
				if (curr.isBefore(closest) && curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}
			// 	Creates Cutoff time variables relative to closest oppblock, based on admin settings
			var studentCutoff = moment(closest.add({hours:settings["hours_close_student"].value_int}));
			var teacherCutoff = moment(closest.add({hours:settings["hours_close_teacher"].value_int}));

			//	Checks to see whether the date is before or after the student and teacher cutoff times
			if (moment().isSameOrAfter(teacherCutoff)) {
				if (moment().isSameOrAfter(studentCutoff)) {
					callback(uid_day, true);
				} else {
					callback(uid_day, false);
				}
			} else {
				callback(null, null);
			}
		} else {
			console.log("Error in finding the upcoming oppblock");
		}
	});
 },
 init: function(app) {
	app.get('/student', middleware.isStudent, function(req, res){
		// Gets Student's id from middleware
		var student = req.user.local[0];
		var uid_student = student.uid_student;
		// This query gets the student's first name for the display page, thereby checking whether the url contained a valid uid
		// This function finds the upcoming oppblock, whether it is time for students to choose, and whether it is past the cutoff time
		module.exports.getSoonestOppblockDay(function(uid_day, cutOff) {
		// Checks whether it is time for students to choose yet
			if (uid_day == null) {
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
			} else {
				// Knowing there is an upcoming oppblock day with choices, the system queries to find the student's current choice
				con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, currentChoice) { // only gets the uid not the name
					if(!err) {
						// Checks if the student is in the choice table at all, thereby seeing if he/she is excluded from the oppblock day
						if(currentChoice.length != 0) {
							//	Checks to see if the student hasn't chosen yet
							if (currentChoice[0].uid_offering == null) {
								// Checks to see if it is past the cutoff time for the students to choose
								if (cutOff) {
									// Renders the page with an admin's message for the student, as they have neglected to sign up.
									res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
								} else {
									// Gets all offerings for the user to choose from
									module.exports.getAvailableOfferings(uid_day, function(offerings) {
										// At last, renders the page with the lack of choice, and the choices table
										res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
									});
								}
							} else {
								//	Knowing the student has chosen, it gets the name of their choice
								con.query('SELECT * FROM offerings WHERE uid_offering = ?', [currentChoice[0].uid_offering], function(err, choice) {
									if(!err) {
										// Checks to see if it is past the cutoff time for the students to choose
										if (cutOff) {
											// Renders the page only with the user's current choice
											res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"The time for choosing has passed. At 2:45, head to " + choice[0].location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
										} else {
											// Gets all offerings for the user to choose from
											module.exports.getAvailableOfferings(uid_day, function(offerings) {
												// At last, renders the page with the current choice, and the choices table
												res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
											});
										}
									} else {
										res.render('error.html', {err:err});
									}
								});
							}
						} else {
							// Renders the page without any choices, since the student is excluded
							res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
						}
					} else {
						console.log("An error done occured.");
						res.render('error.html', {err:err});
					}
				});
			}
		});
	});

	app.post('/student', middleware.isStudent, function(req, response) {
		// Gets Student's id from middleware
		var uid_student = req.user.local[0].uid_student;

		// checks if post request comes from an override or a choice
		if(req.body.choice != undefined) {
			// Updates Choice
			con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [req.body.choice, uid_student, req.body.uid_day], function(err, results) {
				response.redirect('/student');
				response.end();
			});
		} else {
			// Overrides excluded group by adding student into choice table
			con.query('INSERT INTO choices (uid_offering, uid_student, uid_day) values (?, ?, ?)', [null, uid_student, req.body.uid_day], function(err) {
				if(!err) {
					response.redirect('/student');
					response.end();
				} else {
					res.send(err);
					res.render('error.html', {err:err});
				}
			});
		}
	});
	return this;
 }
}
<commit_msg>Took Out Prefix<commit_after>var con = require('./database.js').connection;
var moment = require('moment');
var settings = require('./settings').system_settings;
var middleware = require('./roles.js');

// A message to students who haven't signed up after the student cutoff time has passed
// Can't be a system setting because it is text
// Will reflect an administrator decision
var message_students_notsignedup = "Meet Mr. Ware in the dining hall!";

module.exports = {
 // Gets the number of students in an offering on a day
 numStudents: function(uid_day, uid_offering, getStudentInfo, callback)	{
 	var numStud = 0;
 	var studList = [];
  //	TO DO:
  //	REPLACE THIS CALLBACK STRING WITH A JOIN QUERY
  //	EITHER USE GETSTUDENTINFO IN ANOTHER FILE OR CUT IT
  //
 	con.query('SELECT * FROM choices', function(err, row) {
    	if(!err) {
	    	for(var i=0; i<row.length; i++) {
	         	if(uid_offering == row[i].uid_offering && uid_day == row[i].uid_day) {
		           	numStud += 1;
		           	if(getStudentInfo) {
		             	studList.push(row[i].uid_student);
		           	}
	         	}
	       	}
	       	if(getStudentInfo) {
	         	var infoList = [];
	         	con.query('SELECT * FROM students', function(err, row) {
		           	if(!err) {
		            	for(var i=0; i<row.length; i++) {
		               		for(var j=0; j<studList.length; j++) {
			                 	if(row[i].uid_student == studList[j]) {
			                		infoList.push(row[i].firstname + " " + row[i].lastname);
			                 	}
		               		}
		            	}
		            	callback(numStud, infoList);
		            } else {
		            	console.log("SELECT FROM STUDENTS DONE ERRD");
	             		console.log(err);
		            }
	         	});
	       	} else {
	         callback(numStud, null);
	     	}
       	} else {
       		console.log("SELECT FROM CHOICES DONE ERRD");
       		console.log(err);
 		}
 	});
 },

 //	Pretty Self Explanatory
 isOfferingFull: function (uid_day, uid_offering, callback) {
   con.query('SELECT max_size FROM offerings WHERE uid_offering = ?', [uid_offering], function(err, data) {
    if(!err) {
      module.exports.numStudents(uid_day, uid_offering, false, function(num, infoList){
        if(num >= data[0].max_size) {
          callback("disabled");
        } else {
          callback("able");
        }
      });
    } else {
      console.log("The function produced an error.");
    }
  });
 },

 // Function gets all offerings on a certain day (uid_day)
 // Returns a list ('offerList') of Offering objects, with all necessary properties (although the teacher will be a Name NOT a uid)
 getOfferings: function (uid_day, callback) {
   function Offering(uid, name, description, maxSize, recurring, teacher, location) {
    this.uid = uid;
    this.name = name;
    this.description = description;
    this.maxSize = maxSize;
    this.recur = recurring;
    this.teacher = teacher;
    this.location = location;
    this.disabled;
  }
  var offerList = [];
  var trueOffers = [];
  //	TO DO:
  //	REPLACE THIS CALLBACK STRING WITH A JOIN QUERY
  //
  //	Gets all offerings associated with that day
  con.query('SELECT * FROM calendar', function(err, dayList){
    for(var i=0; i<dayList.length; i++) {
      if(dayList[i].uid_day == uid_day) {
        trueOffers.push(dayList[i].uid_offering);
      }
    }
    //	Gets the info associated with those offerings
    con.query('SELECT * FROM offerings', function(err, rowList) {
      if(!err) {
        for(var i=0; i<rowList.length; i++) {
          for(var j=0; j<trueOffers.length; j++) {
            if(rowList[i].uid_offering == trueOffers[j]) {
              var offering = new Offering(rowList[i].uid_offering, rowList[i].name, rowList[i].description, rowList[i].max_size, rowList[i].recurring, rowList[i].uid_teacher, rowList[i].location);
              offerList.push(offering);
            }
          }
        }
        //	Gets the teacher's names rather than their uids
        con.query('SELECT * FROM teachers', function(err, row) {
          if(!err) {
            for(var j=0; j<row.length; j++) {
              for(var i=0; i<offerList.length; i++) {
                if(row[j].uid_teacher == offerList[i].teacher) {
                  offerList[i].teacher = row[j].teacher_lastname;
                };
              };
            };
            callback(offerList);
          } else {
            console.log("We're sorry. getOfferings() produced an error.");
          }
        });
      } else {
        console.log("We're sorry. getOfferings() produced an error.");
      }
    });
  });
 },

// Function takes in an Oppblock day
// Returns a list of unfilled Offering Objects for that day
 getAvailableOfferings: function (uid_day, callback) {
  //	TO DO:
  //	REMOVE THIS FUNCTION AND PUT THE DISABLING LOOP IN GETOFFERINGS
  var availableList = []
  module.exports.getOfferings(uid_day, function(response) {
    var j = 0;
    for(var i = 0; i <response.length; i++) {
      module.exports.isOfferingFull(uid_day, response[i].uid, function(truth){
		  response[j].disabled = truth;
		  availableList.push(response[j]);
		  j+=1;
		  if(j==response.length) {
			callback(availableList);
		  }
      });
    }
  });
 },

// Takes in nothing
// Returns two values:
// A uid_day of the coming oppblock (null if the students can't yet choose) AND
// A boolean cutOff, signifying whether the user is now past the cutoff time for students' choices
 getSoonestOppblockDay: function(callback) {
 	//	TO DO:
 	//	FIND OUT ANYWHERE ELSE IN PROJECT WHERE THIS FUNCTION MIGHT BE NECESSARY//MAKE IT MORE GENERAL FOR THOSE PURPOSES
	con.query('SELECT * FROM opp_block_day', function(err, results){
		// Gets all Oppblock days
		if(!err){
			var uid_day = null;
			var closest = moment().add(1, 'y');
			for (var i=0; i<results.length; i++) {
				//	Loops to find soonest Oppblock
				var curr = moment(results[i].day, 'YYYY-MM-DD');
				// 	Specficies the oppblock to the end of oppblock on that date
				//	TO DO: SIMPLY THIS CODE
				curr.add({hours:settings["hours_close_oppblock"].value_int, minutes:settings["minutes_close_oppblock"].value_int});
				curr.add({minutes:settings["minutes_length_oppblock"].value_int});
				//	Checks if the current oppBlock day is in the future and before the closest
				//	If so, replaces closest with the current
				console.log(curr);
				if (curr.isBefore(closest) && curr.isSameOrAfter(moment())) {
					closest = moment(curr.format('YYYY-MM-DD'));
					uid_day = results[i].uid_day;
				}
			}
			// 	Creates Cutoff time variables relative to closest oppblock, based on admin settings
			var studentCutoff = moment(closest.add({hours:settings["hours_close_student"].value_int}));
			var teacherCutoff = moment(closest.add({hours:settings["hours_close_teacher"].value_int}));

			//	Checks to see whether the date is before or after the student and teacher cutoff times
			if (moment().isSameOrAfter(teacherCutoff)) {
				if (moment().isSameOrAfter(studentCutoff)) {
					callback(uid_day, true);
				} else {
					callback(uid_day, false);
				}
			} else {
				callback(null, null);
			}
		} else {
			console.log("Error in finding the upcoming oppblock");
		}
	});
 },
 init: function(app) {
	app.get('/student', middleware.isStudent, function(req, res){
		// Gets Student's id from middleware
		var student = req.user.local[0];
		var uid_student = student.uid_student;
		// This query gets the student's first name for the display page, thereby checking whether the url contained a valid uid
		// This function finds the upcoming oppblock, whether it is time for students to choose, and whether it is past the cutoff time
		module.exports.getSoonestOppblockDay(function(uid_day, cutOff) {
		// Checks whether it is time for students to choose yet
			if (uid_day == null) {
				res.render('student.html', {Student:student.firstname, Choice:"No Choice Selected", Description:"We're sorry, but the next OppBlock choices aren't ready yet. Check back soon!", oppTime:true, notExcluded:true});
			} else {
				// Knowing there is an upcoming oppblock day with choices, the system queries to find the student's current choice
				con.query('SELECT uid_offering FROM choices WHERE uid_student = ? AND uid_day = ?', [uid_student, uid_day], function(err, currentChoice) { // only gets the uid not the name
					if(!err) {
						// Checks if the student is in the choice table at all, thereby seeing if he/she is excluded from the oppblock day
						if(currentChoice.length != 0) {
							//	Checks to see if the student hasn't chosen yet
							if (currentChoice[0].uid_offering == null) {
								// Checks to see if it is past the cutoff time for the students to choose
								if (cutOff) {
									// Renders the page with an admin's message for the student, as they have neglected to sign up.
									res.render('student.html', {Student:student.firstname, Choice:"None (You Forgot to Sign Up!)", Description:message_students_notsignedup, oppTime:true, notExcluded:true});
								} else {
									// Gets all offerings for the user to choose from
									module.exports.getAvailableOfferings(uid_day, function(offerings) {
										// At last, renders the page with the lack of choice, and the choices table
										res.render('student.html', {Student:student.firstname, Choice:"None", Description:"Choose an offering from the table below!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
									});
								}
							} else {
								//	Knowing the student has chosen, it gets the name of their choice
								con.query('SELECT * FROM offerings WHERE uid_offering = ?', [currentChoice[0].uid_offering], function(err, choice) {
									if(!err) {
										// Checks to see if it is past the cutoff time for the students to choose
										if (cutOff) {
											// Renders the page only with the user's current choice
											res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"The time for choosing has passed. At 2:45, head to " + choice[0].location + "!", oppTime:true, notExcluded:true}); //Change Constant Time
										} else {
											// Gets all offerings for the user to choose from
											module.exports.getAvailableOfferings(uid_day, function(offerings) {
												// At last, renders the page with the current choice, and the choices table
												res.render('student.html', {Student:student.firstname, Choice:choice[0].name, Description:"You've already chosen, but if you'd like to change your choice, choose a different offering!", uid_day:uid_day, data:offerings, cutOffStudent:settings["hours_close_student"].value_int, notExcluded:true});
											});
										}
									} else {
										res.render('error.html', {err:err});
									}
								});
							}
						} else {
							// Renders the page without any choices, since the student is excluded
							res.render('student.html', {Student:student.firstname, Choice:"No Choice Required", Description:"Due to a sport or perhaps some other commitment, you will not participate in Oppblock today. Press Override if this doesn't apply to you.", uid_day:uid_day, oppTime:true});
						}
					} else {
						console.log("An error done occured.");
						res.render('error.html', {err:err});
					}
				});
			}
		});
	});

	app.post('/student', middleware.isStudent, function(req, response) {
		// Gets Student's id from middleware
		var uid_student = req.user.local[0].uid_student;

		// checks if post request comes from an override or a choice
		if(req.body.choice != undefined) {
			// Updates Choice
			con.query('UPDATE choices SET uid_offering = ? WHERE uid_student = ? AND uid_day = ?', [req.body.choice, uid_student, req.body.uid_day], function(err, results) {
				response.redirect('/student');
				response.end();
			});
		} else {
			// Overrides excluded group by adding student into choice table
			con.query('INSERT INTO choices (uid_offering, uid_student, uid_day) values (?, ?, ?)', [null, uid_student, req.body.uid_day], function(err) {
				if(!err) {
					response.redirect('/student');
					response.end();
				} else {
					res.send(err);
					res.render('error.html', {err:err});
				}
			});
		}
	});
	return this;
 }
}
<|endoftext|>


<commit_before>import {
    GET_CLOSE_DEPARTURES_REQUESTED,
    GET_CLOSE_DEPARTURES_FULFILLED,
    GET_CLOSE_DEPARTURES_ERROR,
} from "./actions";

/*
    Types from http://transport.opendata.ch/docs.html#api-objects
*/

const initialState = {
    data: [
        /*
            {
                from,
                to,
                category,
                number,
                departureTime
            }
        */
    ],
    pending: false,
    error: null,
};

export default (state = initialState, action) => {
    switch (action) {
        case GET_CLOSE_DEPARTURES_REQUESTED:
            return Object.assign({}, state, { pending: true });
        case GET_CLOSE_DEPARTURES_FULFILLED:
            const journeyData = action.payload;
            const data = journeyData.map(journey => ({
                from: journey.from,
                to: journey.to,
                category: journey.category,
                number: journey.category,
                departureTime: journey.stop.departure,
                checkpoints: journey.passList,
            }));

            return Object.assign({}, state, {
                data,
                pending: false,
            });
        case GET_CLOSE_DEPARTURES_ERROR:
            return Object.assign({}, state, {
                pending: false,
                error: action.error,
            });
        default:
            return state;
    }
};
<commit_msg>Bugfix - category to number<commit_after>import {
    GET_CLOSE_DEPARTURES_REQUESTED,
    GET_CLOSE_DEPARTURES_FULFILLED,
    GET_CLOSE_DEPARTURES_ERROR,
} from "./actions";

/*
    Types from http://transport.opendata.ch/docs.html#api-objects
*/

const initialState = {
    data: [
        /*
            {
                from,
                to,
                category,
                number,
                departureTime
            }
        */
    ],
    pending: false,
    error: null,
};

export default (state = initialState, action) => {
    switch (action) {
        case GET_CLOSE_DEPARTURES_REQUESTED:
            return Object.assign({}, state, { pending: true });
        case GET_CLOSE_DEPARTURES_FULFILLED:
            const journeyData = action.payload;
            const data = journeyData.map(journey => ({
                from: journey.from,
                to: journey.to,
                category: journey.category,
                number: journey.number,
                departureTime: journey.stop.departure,
                checkpoints: journey.passList,
            }));

            return Object.assign({}, state, {
                data,
                pending: false,
            });
        case GET_CLOSE_DEPARTURES_ERROR:
            return Object.assign({}, state, {
                pending: false,
                error: action.error,
            });
        default:
            return state;
    }
};
<|endoftext|>


<commit_before>'use strict'

// Checks to see if we've launched before (we touch started.txt). If not, write the file and open a browser

const helpURL = 'https://keybase.io/docs/cli_kbstage'
const filePath = 'started.txt'
import fs from 'fs'
import {shell} from 'electron'

export default () => {
  fs.stat(filePath, (err, stats) => {
    if (err) {
      fs.writeFileSync(filePath, 'hello world')
      shell.openExternal(helpURL)
    }
  })
}
<commit_msg>write splash state file into known location<commit_after>'use strict'

// Checks to see if we've launched before (we touch started.txt). If not, write the file and open a browser
import {socketRoot} from '../../react-native/react/constants/platform.native.desktop'
import path from 'path'

const helpURL = 'https://keybase.io/docs/cli_kbstage'
const filePath = path.join(socketRoot, 'started.txt')
import fs from 'fs'
import {shell} from 'electron'

export default () => {
  fs.stat(filePath, (err, stats) => {
    if (err) {
      try {
        fs.writeFileSync(filePath, 'hello world')
      }
      catch (e) {
        console.error(`Couldn't mark splash screen shown: ${e}`)
        // if we cant' write this file, let's not show the splash, maybe something weird is going on
        return
      }
      shell.openExternal(helpURL)
    }
  })
}
<|endoftext|>