<commit_before>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var d3 = require('d3');
var _ = require('lodash');

var commonbolus = require('./commonbolus');
var dt = require('../../data/util/datetime');
var format = require('../../data/util/format');

module.exports = function(pool, opts) {
  opts = opts || {};

  var defaults = {
    width: 12,
    r: 14,
    suspendMarkerWidth: 5,
    markerHeight: 2,
    triangleHeight: 4,
    triangleOffset: 4,
    bolusStroke: 2,
    triangleSize: 6,
    carbPadding: 4,
    timezoneAware: false,
    tooltipHeightAddition: 3,
    tooltipPadding: 20
  };

  _.defaults(opts, defaults);

  var top = opts.yScale.range()[0];
  var bottom = top - opts.bolusStroke / 2;
  var mainGroup = pool.parent();

  var pluckBolus = function(d) {
    return d.bolus ? d.bolus : d;
  };

  var xPosition = function(d) {
    var x = opts.xScale(d.normalTime) - opts.width/2;
    return x;
  };
  var computePathHeight = function(d) {
    var base = opts.yScale(d.extended) + opts.bolusStroke / 2;
    if (d.extended === 0) {
      return base - opts.bolusStroke;
    }
    return base;
  };

  var triangleLeft = function(x) { return x + opts.width/2 - opts.triangleOffset; };
  var triangleRight = function(x) { return x + opts.width/2 + opts.triangleOffset; };
  var triangleMiddle = function(x) { return x + opts.width/2; };

  var extendedTriangle = function(x, y) {
    var top = (x + opts.triangleSize) + ' ' + (y + opts.triangleSize/2);
    var bottom = (x + opts.triangleSize) + ' ' + (y - opts.triangleSize/2);
    var point = x + ' ' + y;
    return 'M' + top + 'L' + bottom + 'L' + point + 'Z';
  };

  var underrideTriangle = function(x, y) {
    return triangleLeft(x) + ',' + (y + opts.markerHeight/2) + ' ' +
      triangleMiddle(x) + ',' + (y + opts.markerHeight/2 + opts.triangleHeight) + ' ' +
      triangleRight(x) + ',' + (y + opts.markerHeight/2);
  };

  var overrideTriangle = function(x, y) {
    return triangleLeft(x) + ',' + (y + opts.markerHeight/2) + ' ' +
      triangleMiddle(x) + ',' + (y + opts.markerHeight/2 - opts.triangleHeight) + ' ' +
      triangleRight(x) + ',' + (y + opts.markerHeight/2);
  };

  return {
    carb: function(carbs) {
      var xPos = function(d) {
        return xPosition(d) + opts.width/2;
      };

      var yPos = function(d) {
        var r = opts.yScaleCarbs ? opts.yScaleCarbs(d.carbInput) : opts.r;

        var bolusValue = d.bolus ? commonbolus.getMaxValue(d) : 0;

        return opts.yScale(bolusValue) - r - (bolusValue ? opts.carbPadding : 0);
      };

      var classNames = function (d) {
        const className = d.carbUnits === 'exchanges' ? 'd3-circle-carb-exchanges' : 'd3-circle-carbs';
        return [className, 'd3-carbs'];
      }

      carbs.append('circle')
        .attr({
          cx: xPos,
          cy: yPos,
          r: function(d) {
            return opts.yScaleCarbs ? opts.yScaleCarbs(d.carbInput) : opts.r;
          },
          'stroke-width': 0,
          'class': classNames.join(' '),
          id: function(d) {
            return 'carbs_' + d.id;
          }
        });

      carbs.append('text')
        .text(function(d) {
          return d.carbInput;
        })
        .attr({
          x: xPos,
          y: yPos,
          'class': 'd3-carbs-text'
        });
    },
    bolus: function(boluses) {
      // delivered amount of bolus
      boluses.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getDelivered(d));
          },
          width: opts.width,
          height: function(d) {
            return top - opts.yScale(commonbolus.getDelivered(d));
          },
          'class': 'd3-rect-bolus d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });
    },
    suspended: function(suspended) {
      // draw color in the suspended portion
      suspended.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getMaxValue(d));
          },
          width: opts.width,
          height: function(d) {
            d = pluckBolus(d);
            return opts.yScale(commonbolus.getDelivered(d)) - opts.yScale(commonbolus.getMaxValue(d)) - 1;
          },
          'class': 'd3-rect-suspended-bolus d3-bolus'
        });

      // draw the line
      suspended.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            if (commonbolus.getDelivered(d) === 0) {
              return opts.yScale(0) - opts.markerHeight;
            }
            return opts.yScale(commonbolus.getDelivered(d));
          },
          width: opts.width,
          height: opts.markerHeight,
          'class': 'd3-rect-suspended d3-bolus'
        });
    },
    underride: function(underride) {
      underride = underride.filter(function(d) {
        return commonbolus.getDelivered(d) > 0;
      });
      underride.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getRecommended(d));
          },
          width: opts.width,
          height: function(d) {
            return opts.yScale(commonbolus.getDelivered(d)) - opts.yScale(commonbolus.getRecommended(d));
          },
          'class': 'd3-rect-recommended d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });

      // draw the line iff the programmed and delivered are the same
      // to avoid too much confusing clutter
      // tooltip still exposes fact that suggested and programmed differed
      var uninterrupted = underride.filter(function(d) {
        return commonbolus.getProgrammed(d) === commonbolus.getDelivered(d);
      });
      uninterrupted.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getDelivered(d));
          },
          width: opts.width,
          height: opts.markerHeight,
          'class': 'd3-rect-override d3-bolus'
        });

      uninterrupted.append('polygon')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getDelivered(d));
          },
          points: function(d) {
            var bolus = pluckBolus(d);
            return underrideTriangle(xPosition(bolus), opts.yScale(commonbolus.getDelivered(d)));
          },
          'class': 'd3-polygon-override d3-bolus'
        });
    },
    override: function(override) {
      // draw the line iff the programmed and delivered are the same
      // to avoid too much confusing clutter
      // tooltip still exposes fact that suggested and programmed differed
      var uninterrupted = override.filter(function(d) {
        return commonbolus.getProgrammed(d) === commonbolus.getDelivered(d);
      });
      uninterrupted.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getRecommended(d)) - opts.markerHeight;
          },
          width: opts.width,
          height: opts.markerHeight,
          'class': 'd3-rect-override d3-bolus'
        });

      uninterrupted.append('polygon')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getRecommended(d)) - opts.markerHeight;
          },
          points: function(d) {
            var bolus = pluckBolus(d);
            return overrideTriangle(xPosition(bolus), opts.yScale(commonbolus.getRecommended(d)) - opts.markerHeight);
          },
          'class': 'd3-polygon-override d3-bolus'
        });
    },
    extended: function(extended) {
      // extended "arm" of square- and dual-wave boluses
      extended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var rightEdge = xPosition(d) + opts.width;
            var doseHeight = computePathHeight(d);
            var doseEnd = opts.xScale(d.normalTime + commonbolus.getMaxDuration(d));
            return 'M' + rightEdge + ' ' + doseHeight + 'L' + doseEnd + ' ' + doseHeight;
          },
          'stroke-width': opts.bolusStroke,
          'class': 'd3-path-extended d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });

      // triangle
      extended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var doseHeight = computePathHeight(d);
            var doseEnd = opts.xScale(d.normalTime + commonbolus.getMaxDuration(d)) - opts.triangleSize;
            return extendedTriangle(doseEnd, doseHeight);
          },
          'stroke-width': opts.bolusStroke,
          'class': function(d) {
            d = pluckBolus(d);

            if (d.expectedExtended) {
              return 'd3-path-extended-triangle-suspended d3-bolus';
            }

            return 'd3-path-extended-triangle d3-bolus';
          },
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });
    },
    extendedSuspended: function(suspended) {
      // red marker indicating where suspend happened
      suspended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var doseHeight = computePathHeight(d);
            var rightEdge = opts.xScale(d.normalTime + d.duration);
            var pathEnd = rightEdge + opts.suspendMarkerWidth;

            return 'M' + rightEdge + ' ' + doseHeight + 'L' + pathEnd + ' ' + doseHeight;
          },
          'stroke-width': opts.bolusStroke,
          'class': 'd3-path-suspended d3-bolus'
        });

      // now, light-blue path representing undelivered extended bolus
      suspended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var doseHeight = computePathHeight(d);
            var pathEnd = opts.xScale(d.normalTime + d.duration) + opts.suspendMarkerWidth;
            var doseEnd = opts.xScale(d.normalTime + d.expectedDuration);

            return 'M' + pathEnd + ' ' + doseHeight + 'L' + doseEnd + ' ' + doseHeight;
          },
          'stroke-width': opts.bolusStroke,
          'class': 'd3-path-extended-suspended d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });
    },
    tooltip: {
      add: function(d, rect) {
        if (_.get(opts, 'onBolusHover', false)) {
          opts.onBolusHover({
            data: d,
            rect: rect
          });
        }
      },
      remove: function(d) {
        if (_.get(opts, 'onBolusOut', false)){
          opts.onBolusOut({
            data: d
          });
        }
      }
    },
    annotations: function(data, selection) {
      _.each(data, function(d) {
        var annotationOpts = {
          x: opts.xScale(d.normalTime),
          y: opts.yScale(commonbolus.getMaxValue(d)),
          xMultiplier: -2,
          yMultiplier: 1,
          d: d,
          orientation: {
            up: true
          }
        };
        if (mainGroup.select('#annotation_for_' + d.id)[0][0] == null) {
          mainGroup.select('#tidelineAnnotations_bolus').call(pool.annotations(), annotationOpts);
        }
      });
    }
  };
};
<commit_msg>[WEB-717] Fix for carb css classname generation<commit_after>/*
 * == BSD2 LICENSE ==
 * Copyright (c) 2014, Tidepool Project
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the associated License, which is identical to the BSD 2-Clause
 * License as published by the Open Source Initiative at opensource.org.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the License for more details.
 *
 * You should have received a copy of the License along with this program; if
 * not, you can obtain one from Tidepool Project at tidepool.org.
 * == BSD2 LICENSE ==
 */

var d3 = require('d3');
var _ = require('lodash');

var commonbolus = require('./commonbolus');
var dt = require('../../data/util/datetime');
var format = require('../../data/util/format');

module.exports = function(pool, opts) {
  opts = opts || {};

  var defaults = {
    width: 12,
    r: 14,
    suspendMarkerWidth: 5,
    markerHeight: 2,
    triangleHeight: 4,
    triangleOffset: 4,
    bolusStroke: 2,
    triangleSize: 6,
    carbPadding: 4,
    timezoneAware: false,
    tooltipHeightAddition: 3,
    tooltipPadding: 20
  };

  _.defaults(opts, defaults);

  var top = opts.yScale.range()[0];
  var bottom = top - opts.bolusStroke / 2;
  var mainGroup = pool.parent();

  var pluckBolus = function(d) {
    return d.bolus ? d.bolus : d;
  };

  var xPosition = function(d) {
    var x = opts.xScale(d.normalTime) - opts.width/2;
    return x;
  };
  var computePathHeight = function(d) {
    var base = opts.yScale(d.extended) + opts.bolusStroke / 2;
    if (d.extended === 0) {
      return base - opts.bolusStroke;
    }
    return base;
  };

  var triangleLeft = function(x) { return x + opts.width/2 - opts.triangleOffset; };
  var triangleRight = function(x) { return x + opts.width/2 + opts.triangleOffset; };
  var triangleMiddle = function(x) { return x + opts.width/2; };

  var extendedTriangle = function(x, y) {
    var top = (x + opts.triangleSize) + ' ' + (y + opts.triangleSize/2);
    var bottom = (x + opts.triangleSize) + ' ' + (y - opts.triangleSize/2);
    var point = x + ' ' + y;
    return 'M' + top + 'L' + bottom + 'L' + point + 'Z';
  };

  var underrideTriangle = function(x, y) {
    return triangleLeft(x) + ',' + (y + opts.markerHeight/2) + ' ' +
      triangleMiddle(x) + ',' + (y + opts.markerHeight/2 + opts.triangleHeight) + ' ' +
      triangleRight(x) + ',' + (y + opts.markerHeight/2);
  };

  var overrideTriangle = function(x, y) {
    return triangleLeft(x) + ',' + (y + opts.markerHeight/2) + ' ' +
      triangleMiddle(x) + ',' + (y + opts.markerHeight/2 - opts.triangleHeight) + ' ' +
      triangleRight(x) + ',' + (y + opts.markerHeight/2);
  };

  return {
    carb: function(carbs) {
      var xPos = function(d) {
        return xPosition(d) + opts.width/2;
      };

      var yPos = function(d) {
        var r = opts.yScaleCarbs ? opts.yScaleCarbs(d.carbInput) : opts.r;

        var bolusValue = d.bolus ? commonbolus.getMaxValue(d) : 0;

        return opts.yScale(bolusValue) - r - (bolusValue ? opts.carbPadding : 0);
      };

      var classNames = function (d) {
        const className = d.carbUnits === 'exchanges' ? 'd3-circle-carb-exchanges' : 'd3-circle-carbs';
        return [className, 'd3-carbs'];
      }

      carbs.append('circle')
        .attr({
          cx: xPos,
          cy: yPos,
          r: function(d) {
            return opts.yScaleCarbs ? opts.yScaleCarbs(d.carbInput) : opts.r;
          },
          'stroke-width': 0,
          'class': d => classNames(d).join(' '),
          id: function(d) {
            return 'carbs_' + d.id;
          }
        });

      carbs.append('text')
        .text(function(d) {
          return d.carbInput;
        })
        .attr({
          x: xPos,
          y: yPos,
          'class': 'd3-carbs-text'
        });
    },
    bolus: function(boluses) {
      // delivered amount of bolus
      boluses.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getDelivered(d));
          },
          width: opts.width,
          height: function(d) {
            return top - opts.yScale(commonbolus.getDelivered(d));
          },
          'class': 'd3-rect-bolus d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });
    },
    suspended: function(suspended) {
      // draw color in the suspended portion
      suspended.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getMaxValue(d));
          },
          width: opts.width,
          height: function(d) {
            d = pluckBolus(d);
            return opts.yScale(commonbolus.getDelivered(d)) - opts.yScale(commonbolus.getMaxValue(d)) - 1;
          },
          'class': 'd3-rect-suspended-bolus d3-bolus'
        });

      // draw the line
      suspended.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            if (commonbolus.getDelivered(d) === 0) {
              return opts.yScale(0) - opts.markerHeight;
            }
            return opts.yScale(commonbolus.getDelivered(d));
          },
          width: opts.width,
          height: opts.markerHeight,
          'class': 'd3-rect-suspended d3-bolus'
        });
    },
    underride: function(underride) {
      underride = underride.filter(function(d) {
        return commonbolus.getDelivered(d) > 0;
      });
      underride.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getRecommended(d));
          },
          width: opts.width,
          height: function(d) {
            return opts.yScale(commonbolus.getDelivered(d)) - opts.yScale(commonbolus.getRecommended(d));
          },
          'class': 'd3-rect-recommended d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });

      // draw the line iff the programmed and delivered are the same
      // to avoid too much confusing clutter
      // tooltip still exposes fact that suggested and programmed differed
      var uninterrupted = underride.filter(function(d) {
        return commonbolus.getProgrammed(d) === commonbolus.getDelivered(d);
      });
      uninterrupted.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getDelivered(d));
          },
          width: opts.width,
          height: opts.markerHeight,
          'class': 'd3-rect-override d3-bolus'
        });

      uninterrupted.append('polygon')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getDelivered(d));
          },
          points: function(d) {
            var bolus = pluckBolus(d);
            return underrideTriangle(xPosition(bolus), opts.yScale(commonbolus.getDelivered(d)));
          },
          'class': 'd3-polygon-override d3-bolus'
        });
    },
    override: function(override) {
      // draw the line iff the programmed and delivered are the same
      // to avoid too much confusing clutter
      // tooltip still exposes fact that suggested and programmed differed
      var uninterrupted = override.filter(function(d) {
        return commonbolus.getProgrammed(d) === commonbolus.getDelivered(d);
      });
      uninterrupted.append('rect')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getRecommended(d)) - opts.markerHeight;
          },
          width: opts.width,
          height: opts.markerHeight,
          'class': 'd3-rect-override d3-bolus'
        });

      uninterrupted.append('polygon')
        .attr({
          x: function(d) {
            d = pluckBolus(d);
            return xPosition(d);
          },
          y: function(d) {
            return opts.yScale(commonbolus.getRecommended(d)) - opts.markerHeight;
          },
          points: function(d) {
            var bolus = pluckBolus(d);
            return overrideTriangle(xPosition(bolus), opts.yScale(commonbolus.getRecommended(d)) - opts.markerHeight);
          },
          'class': 'd3-polygon-override d3-bolus'
        });
    },
    extended: function(extended) {
      // extended "arm" of square- and dual-wave boluses
      extended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var rightEdge = xPosition(d) + opts.width;
            var doseHeight = computePathHeight(d);
            var doseEnd = opts.xScale(d.normalTime + commonbolus.getMaxDuration(d));
            return 'M' + rightEdge + ' ' + doseHeight + 'L' + doseEnd + ' ' + doseHeight;
          },
          'stroke-width': opts.bolusStroke,
          'class': 'd3-path-extended d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });

      // triangle
      extended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var doseHeight = computePathHeight(d);
            var doseEnd = opts.xScale(d.normalTime + commonbolus.getMaxDuration(d)) - opts.triangleSize;
            return extendedTriangle(doseEnd, doseHeight);
          },
          'stroke-width': opts.bolusStroke,
          'class': function(d) {
            d = pluckBolus(d);

            if (d.expectedExtended) {
              return 'd3-path-extended-triangle-suspended d3-bolus';
            }

            return 'd3-path-extended-triangle d3-bolus';
          },
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });
    },
    extendedSuspended: function(suspended) {
      // red marker indicating where suspend happened
      suspended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var doseHeight = computePathHeight(d);
            var rightEdge = opts.xScale(d.normalTime + d.duration);
            var pathEnd = rightEdge + opts.suspendMarkerWidth;

            return 'M' + rightEdge + ' ' + doseHeight + 'L' + pathEnd + ' ' + doseHeight;
          },
          'stroke-width': opts.bolusStroke,
          'class': 'd3-path-suspended d3-bolus'
        });

      // now, light-blue path representing undelivered extended bolus
      suspended.append('path')
        .attr({
          d: function(d) {
            d = pluckBolus(d);
            var doseHeight = computePathHeight(d);
            var pathEnd = opts.xScale(d.normalTime + d.duration) + opts.suspendMarkerWidth;
            var doseEnd = opts.xScale(d.normalTime + d.expectedDuration);

            return 'M' + pathEnd + ' ' + doseHeight + 'L' + doseEnd + ' ' + doseHeight;
          },
          'stroke-width': opts.bolusStroke,
          'class': 'd3-path-extended-suspended d3-bolus',
          id: function(d) {
            d = pluckBolus(d);
            return 'bolus_' + d.id;
          }
        });
    },
    tooltip: {
      add: function(d, rect) {
        if (_.get(opts, 'onBolusHover', false)) {
          opts.onBolusHover({
            data: d,
            rect: rect
          });
        }
      },
      remove: function(d) {
        if (_.get(opts, 'onBolusOut', false)){
          opts.onBolusOut({
            data: d
          });
        }
      }
    },
    annotations: function(data, selection) {
      _.each(data, function(d) {
        var annotationOpts = {
          x: opts.xScale(d.normalTime),
          y: opts.yScale(commonbolus.getMaxValue(d)),
          xMultiplier: -2,
          yMultiplier: 1,
          d: d,
          orientation: {
            up: true
          }
        };
        if (mainGroup.select('#annotation_for_' + d.id)[0][0] == null) {
          mainGroup.select('#tidelineAnnotations_bolus').call(pool.annotations(), annotationOpts);
        }
      });
    }
  };
};
<|endoftext|>


<commit_before>$(function () {
  'use strict';

  module('dropdowns plugin')

  test('should be defined on jquery object', function () {
    ok($(document.body).dropdown, 'dropdown method is defined')
  })

  module('dropdowns', {
    setup: function () {
      // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
      $.fn.bootstrapDropdown = $.fn.dropdown.noConflict()
    },
    teardown: function () {
      $.fn.dropdown = $.fn.bootstrapDropdown
      delete $.fn.bootstrapDropdown
    }
  })

  test('should provide no conflict', function () {
    ok(!$.fn.dropdown, 'dropdown was set back to undefined (org value)')
  })

  test('should return element', function () {
    var el = $('
')
    ok(el.bootstrapDropdown()[0] === el[0], 'same element returned')
  })

  test('should not open dropdown if target is disabled', function () {
    var dropdownHTML = '
' +
        '
' +
        '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '

' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok(!dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')
  })

  test('should not open dropdown if target is disabled', function () {
    var dropdownHTML = '
' +
        '
' +
        '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '

' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok(!dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')
  })

  test('should add class open to menu if clicked', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '

' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok(dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')
  })

  test('should test if element has a # before assuming it\'s a selector', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '

' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok(dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')
  })

  test('should remove open class if body clicked', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '

' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var dropdown = $(dropdownHTML)
          .appendTo('#qunit-fixture')
          .find('[data-toggle="dropdown"]')
          .bootstrapDropdown()
          .click()

    ok(dropdown.parent('.dropdown').hasClass('open'), 'open class added on click')
    $('body').click()
    ok(!dropdown.parent('.dropdown').hasClass('open'), 'open class removed')
    dropdown.remove()
  })

  test('should remove open class if body clicked, with multiple drop downs', function () {
    var dropdownHTML = '
' +
        '
Menu 1
' +
        '
' +
        '      Test menu ' +
        '
' +
        '
Submenu 1
' +
        '
' +
        '
' +
        '
' +
        '
' +
        '    <button class="btn">Actions</button>' +
        '    <button class="btn dropdown-toggle" data-toggle="dropdown"></button>' +
        '
' +
        '
Action 1
' +
        '
' +
        '
'
    var dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
    var first = dropdowns.first()
    var last = dropdowns.last()

    ok(dropdowns.length == 2, 'Should be two dropdowns')

    first.click()
    ok(first.parents('.open').length == 1, 'open class added on click')
    ok($('#qunit-fixture .open').length == 1, 'only one object is open')
    $('body').click()
    ok($('#qunit-fixture .open').length === 0, 'open class removed')

    last.click()
    ok(last.parent('.open').length == 1, 'open class added on click')
    ok($('#qunit-fixture .open').length == 1, 'only one object is open')
    $('body').click()
    ok($('#qunit-fixture .open').length === 0, 'open class removed')

    $('#qunit-fixture').html('')
  })

  test('should fire show and hide event', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '

' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var dropdown = $(dropdownHTML)
          .appendTo('#qunit-fixture')
          .find('[data-toggle="dropdown"]')
          .bootstrapDropdown()

    stop()

    dropdown
      .parent('.dropdown')
      .on('show.bs.dropdown', function () {
        ok(true, 'show was called')
      })
      .on('hide.bs.dropdown', function () {
        ok(true, 'hide was called')
        start()
      })

    dropdown.click()
    $(document.body).click()
  })

  test('should fire shown and hiden event', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '

' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var dropdown = $(dropdownHTML)
          .appendTo('#qunit-fixture')
          .find('[data-toggle="dropdown"]')
          .bootstrapDropdown()

    stop()

    dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        ok(true, 'show was called')
      })
      .on('hidden.bs.dropdown', function () {
        ok(true, 'hide was called')
        start()
      })

    dropdown.click()
    $(document.body).click()
  })

})
<commit_msg>Clean dropdown unit tests up<commit_after>$(function () {
  'use strict';

  module('dropdowns plugin')

  test('should be defined on jquery object', function () {
    ok($(document.body).dropdown, 'dropdown method is defined')
  })

  module('dropdowns', {
    setup: function () {
      // Run all tests in noConflict mode -- it's the only way to ensure that the plugin works in noConflict mode
      $.fn.bootstrapDropdown = $.fn.dropdown.noConflict()
    },
    teardown: function () {
      $.fn.dropdown = $.fn.bootstrapDropdown
      delete $.fn.bootstrapDropdown
    }
  })

  test('should provide no conflict', function () {
    strictEqual($.fn.dropdown, undefined, 'dropdown was set back to undefined (org value)')
  })

  test('should return jquery collection containing the element', function () {
    var $el = $('
')
    var $dropdown = $el.bootstrapDropdown()
    ok($dropdown instanceof $, 'returns jquery collection')
    strictEqual($dropdown[0], $el[0], 'collection contains element')
  })

  test('should not open dropdown if target is disabled via attribute', function () {
    var dropdownHTML = '
' +
        '
' +
        '<button disabled href="#" class="btn dropdown-toggle" data-toggle="dropdown">Dropdown</button>' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '
' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok(!$dropdown.parent('.dropdown').hasClass('open'), '"open" class added on click')
  })

  test('should not open dropdown if target is disabled via class', function () {
    var dropdownHTML = '
' +
        '
' +
        '<button href="#" class="btn dropdown-toggle disabled" data-toggle="dropdown">Dropdown</button>' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '
' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok(!$dropdown.parent('.dropdown').hasClass('open'), '"open" class added on click')
  })

  test('should add class open to menu if clicked', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '
' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok($dropdown.parent('.dropdown').hasClass('open'), '"open" class added on click')
  })

  test('should test if element has a # before assuming it\'s a selector', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '
' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var $dropdown = $(dropdownHTML).find('[data-toggle="dropdown"]').bootstrapDropdown().click()

    ok($dropdown.parent('.dropdown').hasClass('open'), '"open" class added on click')
  })

  test('should remove "open" class if body is clicked', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '
' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()
      .click()

    ok($dropdown.parent('.dropdown').hasClass('open'), '"open" class added on click')
    $(document.body).click()
    ok(!$dropdown.parent('.dropdown').hasClass('open'), '"open" class removed')
  })

  test('should remove "open" class if body is clicked, with multiple dropdowns', function () {
    var dropdownHTML = '
' +
        '
Menu 1
' +
        '
' +
        'Test menu ' +
        '
' +
        '
Submenu 1
' +
        '
' +
        '
' +
        '
' +
        '
' +
        '<button class="btn">Actions</button>' +
        '<button class="btn dropdown-toggle" data-toggle="dropdown"></button>' +
        '
' +
        '
Action 1
' +
        '
' +
        '
'
    var $dropdowns = $(dropdownHTML).appendTo('#qunit-fixture').find('[data-toggle="dropdown"]')
    var $first = $dropdowns.first()
    var $last = $dropdowns.last()

    strictEqual($dropdowns.length, 2, 'two dropdowns')

    $first.click()
    strictEqual($first.parents('.open').length, 1, '"open" class added on click')
    strictEqual($('#qunit-fixture .open').length, 1, 'only one dropdown is open')
    $(document.body).click()
    strictEqual($('#qunit-fixture .open').length, 0, '"open" class removed')

    $last.click()
    strictEqual($last.parent('.open').length, 1, '"open" class added on click')
    strictEqual($('#qunit-fixture .open').length, 1, 'only one dropdown is open')
    $(document.body).click()
    strictEqual($('#qunit-fixture .open').length, 0, '"open" class removed')
  })

  test('should fire show and hide event', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '
' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

    stop()

    $dropdown
      .parent('.dropdown')
      .on('show.bs.dropdown', function () {
        ok(true, 'show was fired')
      })
      .on('hide.bs.dropdown', function () {
        ok(true, 'hide was fired')
        start()
      })

    $dropdown.click()
    $(document.body).click()
  })

  test('should fire shown and hidden event', function () {
    var dropdownHTML = '
' +
        '
' +
        'Dropdown' +
        '
' +
        '
Secondary link
' +
        '
Something else here
' +
        '
' +
        '
Another link
' +
        '
' +
        '
' +
        '
'
    var $dropdown = $(dropdownHTML)
      .appendTo('#qunit-fixture')
      .find('[data-toggle="dropdown"]')
      .bootstrapDropdown()

    stop()

    $dropdown
      .parent('.dropdown')
      .on('shown.bs.dropdown', function () {
        ok(true, 'shown was fired')
      })
      .on('hidden.bs.dropdown', function () {
        ok(true, 'hidden was fired')
        start()
      })

    $dropdown.click()
    $(document.body).click()
  })

})
<|endoftext|>


<commit_before>///////////////////////////
// Map Globals           //
///////////////////////////
var tileHeight = 32,
	tileWidth = 32,
	mapWidth = 15,
	mapHeight = 15,
	mapScale = 2,
	collisionsIndex = [],
	entrances = [],
	mapArray = [];
///////////////////////////
// Globals For Character() //
///////////////////////////
var mainCharacter = new PIXI.Container(),
	mainCharacterScale = 1.1,
	npcCharacterScale = 1.1,
	xOffset = 16,
	yOffset = 7,
	startX = xOffset + 32*4,
	startY = yOffset + 32*4,
	healthbar,
	CharacterAttacking = false;
///////////////////////////////////////
// Globals for CharacterController() //
///////////////////////////////////////
var keyA = false,
	keyD = false,
	keyS = false,
	keyW = false,
	keyEnter = false,
	keySpace = false,
	moving = true, // set to false to stop character from moving
	facing;  // 1 up, 2 right, 3 down, 4 left

/////////////////////////
// Global Containers   //
/////////////////////////
var stage = new PIXI.Container(),
	gameScreenContainer = new PIXI.Container(),
	menuScreenContainer = new PIXI.Container(),
	creditsScreenContainer = new PIXI.Container(),
	instructionsScreenContainer = new PIXI.Container(),
	personalBlazerContainer = new PIXI.Container(),
	personalCurtisContainer = new PIXI.Container(),
	personalMattContainer = new PIXI.Container(),
	personalJohnContainer = new PIXI.Container(),
	mapContainer = new PIXI.Container(),
	fontContainer = new PIXI.Container(),
	forestContainer = new PIXI.Container(),
	desertContainer = new PIXI.Container(),
	plainsContainer = new PIXI.Container(),
	desertDungeonContainer = new PIXI.Container();
	forestDungeonContainer = new PIXI.Container();
	plainsDungeonContainer = new PIXI.Container();

/////////////////////////////
// Globals for LoadNPC()   //
/////////////////////////////
var npcArray = [],
	npcStartArray = [],
	npcRangeArray = [],
	npcMoving,
	npcSpeed = 4000;

/////////////////////////////
// Globals for LoadEnemy()   //
/////////////////////////////
var enemyArray = [],
	enemyStartArray = [],
	enemyRangeArray = [],
	enemyDyingArray = [],
	enemyAttackingArray = [];

/////////////////////////////
// Globals for Text   //
/////////////////////////////

var text;
var isText;
var width = 600,
	height = 600;

///////////////////////////////////////
// Globals for map transitions      //
///////////////////////////////////////
var currentMap,
	previousMap;
var forest;
var desert;
var plains;
var desertDungeon;
var forestDungeon;
var plainsDungeon;
///////////////////////////////////////
// Globals for story progression    //
///////////////////////////////////////

var hasSword = false,
	hasShield = false,
	hasPotato = false,
	dead = false;

// Sounds

var GameOverSound,
	HeroAttackSound,
	HeroDieSound,
	IntroSound,
	KillKingSound,
	LetKingLiveSound,
	MonsterAttackSound,
	MonsterDieSound,
	UncleSound,
	SlashSound
	HiBlazerSound,
	HiCurtisSound,
	HiMattSound,
	HiJohnSound;
<commit_msg>fixed one thing<commit_after>///////////////////////////
// Map Globals           //
///////////////////////////
var tileHeight = 32,
	tileWidth = 32,
	mapWidth = 15,
	mapHeight = 15,
	mapScale = 2,
	collisionsIndex = [],
	entrances = [],
	mapArray = [];
///////////////////////////
// Globals For Character() //
///////////////////////////
var mainCharacter = new PIXI.Container(),
	mainCharacterScale = 1.1,
	npcCharacterScale = 1.1,
	xOffset = 16,
	yOffset = 7,
	startX = xOffset + 32*4,
	startY = yOffset + 32*4,
	healthbar,
	CharacterAttacking = false;
///////////////////////////////////////
// Globals for CharacterController() //
///////////////////////////////////////
var keyA = false,
	keyD = false,
	keyS = false,
	keyW = false,
	keyEnter = false,
	keySpace = false,
	moving = true, // set to false to stop character from moving
	facing;  // 1 up, 2 right, 3 down, 4 left

/////////////////////////
// Global Containers   //
/////////////////////////
var stage = new PIXI.Container(),
	gameScreenContainer = new PIXI.Container(),
	menuScreenContainer = new PIXI.Container(),
	creditsScreenContainer = new PIXI.Container(),
	instructionsScreenContainer = new PIXI.Container(),
	personalBlazerContainer = new PIXI.Container(),
	personalCurtisContainer = new PIXI.Container(),
	personalMattContainer = new PIXI.Container(),
	personalJohnContainer = new PIXI.Container(),
	mapContainer = new PIXI.Container(),
	fontContainer = new PIXI.Container(),
	forestContainer = new PIXI.Container(),
	desertContainer = new PIXI.Container(),
	plainsContainer = new PIXI.Container(),
	desertDungeonContainer = new PIXI.Container();
	forestDungeonContainer = new PIXI.Container();
	plainsDungeonContainer = new PIXI.Container();

/////////////////////////////
// Globals for LoadNPC()   //
/////////////////////////////
var npcArray = [],
	npcStartArray = [],
	npcRangeArray = [],
	npcMoving,
	npcSpeed = 4000;

/////////////////////////////
// Globals for LoadEnemy()   //
/////////////////////////////
var enemyArray = [],
	enemyStartArray = [],
	enemyRangeArray = [],
	enemyDyingArray = [],
	enemyAttackingArray = [];

/////////////////////////////
// Globals for Text   //
/////////////////////////////

var text;
var isText;
var width = 600,
	height = 600;

///////////////////////////////////////
// Globals for map transitions      //
///////////////////////////////////////
var currentMap,
	previousMap;
var forest;
var desert;
var plains;
var desertDungeon;
var forestDungeon;
var plainsDungeon;
///////////////////////////////////////
// Globals for story progression    //
///////////////////////////////////////

var hasSword = false,
	hasShield = false,
	hasPotato = false,
	dead = false;

// Sounds

var GameOverSound,
	HeroAttackSound,
	HeroDieSound,
	IntroSound,
	KillKingSound,
	LetKingLiveSound,
	MonsterAttackSound,
	MonsterDieSound,
	UncleSound,
	SlashSound,
	HiBlazerSound,
	HiCurtisSound,
	HiMattSound,
	HiJohnSound;
<|endoftext|>


<commit_before>/**
 * Main module for analyze view
 * @param {type} $ jQuery module
 * @param {type} facebook Facebook Graph API module
 * @param {type} LastFMProxy LastFM API Wrapper module
 * @param {type} Aggregate Custom aggregation methods module
 * @returns {void}
 */
define (['jquery', 'facebook', 'LastFMProxy', 'aggregate'], function ($, facebook, LastFMProxy, Aggregate) {

    // Stats object for every artist (associative array)
    var artistStats = [];

    // Number of artists liked by the user
    var artistCount = 0;

    // Number of artist already analyzed
    var analyzedArtistCount = 0;

    /**
     * Try to login and get an array of musicians
     * @param {type} callback
     * @returns {undefined}
     */
    function getArtists(callback) {
        FB.init({
            appId      : '1468034890110746',
            xfbml      : true,
            status     : true,
            cookie     : true,
            version    : 'v2.1'
        });

        // Try to login after init is complete
        FB.getLoginStatus(function(response){
            FB.login(function () {
                FB.api(
                    "/me/music?fields=likes,id,name, category",
                    function (response) {
                          var likes = response.data || [];
                          var artists = [];

                          // Filter by  category
                          likes.forEach(function (like) {
                              if(like.category === "Musician/band") {
                                  artists.push(like);
                              }
                          });

                          callback(artists);

                });
            }, {scope: 'user_likes'});
        });

    }

    /**
     * Show the modal window with a given text
     * @param {type} title Window title to show
     * @param {type} text Text to show
     * @param {function} callback
     * @returns {undefined}
     */
    function showModal (title, text, callback) {
        $('#modalTitle').text(title);
        $('#modalText').text(text);
        $('#myModal').modal('show');
        if (callback) {
            callback();
        }
    }

    /**
     * Update progress bar as analyzedArtistCound increases
     * @returns {undefined}
     */
    function updateProgress () {
        analyzedArtistCount++;
        var percent = analyzedArtistCount / artistCount;
        var progress = percent*100;
        $('#appProgress').css('width', progress + '%');
    }

    /**
     *
     * @param {type} artist
     * @returns {undefined}
     */
    function artistCallback (artist) {
        var initialStatus = $('#initial-status').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function albumCallback (artist) {
         var initialStatus = $('#initial-status-album').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function fanCallback (artist) {
        var initialStatus = $('#initial-status-fan').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function tagCallback (artist) {
        var initialStatus = $('#initial-status-tag').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function similarCallback (artist) {
        var initialStatus = $('#initial-status-similar').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    // Get stats one by one recursively and call a callback when finished
    function getStats (artists, callback) {

        // Race end: empty array
        if (artists.length === 0) {
            callback();
            return;
        }

        // Pop an artist from array
        var artist = artists.pop();

        // Get stats for the popped artist and then continue
        LastFMProxy.getStats(artist.id, artist.name, artistCallback, albumCallback, fanCallback, tagCallback, similarCallback, function (stats) {
            updateProgress();
            artistStats[artist.name] = stats;
            getStats(artists, callback);

        });
    }

    function showResults() {
        // TODO: Insert text
        var tags = [];
        artistStats.forEach(function (stats) {
            stats.tags.forEach(function (tag) {
                tags.push(tag);
            });
        });

        console.log(Aggregate.sortByFrequency(tags));

        $('#process').hide();
        $('#results').removeClass('hidden');
    }

    function selectTopRated (artists, n) {
        var selected = [];

        // Get the likes of each artist
        artists.sort(function (a, b) {
            return a.likes - b.likes;
        });

        selected = artists.splice(0,n);

        return selected;
    }

    // DOM callbacks
    $(document).ready(function () {

        // Get user artists
        getArtists(function (artists) {

            var MAX_ARTISTS = 10;
            console.log(artists);

            // If no artist likes show message
            if (artists.length === 0) {
                showModal($('#error-title').val(), $('#error-status').val(), function () {

                });

            }

            // If too much musicians
            if (artists.length > MAX_ARTISTS) {
                artists = selectTopRated(artists, MAX_ARTISTS);
            }

            artistCount = artists.length || 0;

            // Else get stats one by one
            getStats(artists, function () {
                showResults();
            });

        }); // Get user artists
    }); // End document ready
}); // End module<commit_msg>filter by likes count 6<commit_after>/**
 * Main module for analyze view
 * @param {type} $ jQuery module
 * @param {type} facebook Facebook Graph API module
 * @param {type} LastFMProxy LastFM API Wrapper module
 * @param {type} Aggregate Custom aggregation methods module
 * @returns {void}
 */
define (['jquery', 'facebook', 'LastFMProxy', 'aggregate'], function ($, facebook, LastFMProxy, Aggregate) {

    // Stats object for every artist (associative array)
    var artistStats = [];

    // Number of artists liked by the user
    var artistCount = 0;

    // Number of artist already analyzed
    var analyzedArtistCount = 0;

    /**
     * Try to login and get an array of musicians
     * @param {type} callback
     * @returns {undefined}
     */
    function getArtists(callback) {
        FB.init({
            appId      : '1468034890110746',
            xfbml      : true,
            status     : true,
            cookie     : true,
            version    : 'v2.1'
        });

        // Try to login after init is complete
        FB.getLoginStatus(function(response){
            FB.login(function () {
                FB.api(
                    "/me/music?fields=likes,id,name, category",
                    function (response) {
                          var likes = response.data || [];
                          var artists = [];

                          // Filter by  category
                          likes.forEach(function (like) {
                              if(like.category === "Musician/band") {
                                  artists.push(like);
                              }
                          });

                          callback(artists);

                });
            }, {scope: 'user_likes'});
        });

    }

    /**
     * Show the modal window with a given text
     * @param {type} title Window title to show
     * @param {type} text Text to show
     * @param {function} callback
     * @returns {undefined}
     */
    function showModal (title, text, callback) {
        $('#modalTitle').text(title);
        $('#modalText').text(text);
        $('#myModal').modal('show');
        if (callback) {
            callback();
        }
    }

    /**
     * Update progress bar as analyzedArtistCound increases
     * @returns {undefined}
     */
    function updateProgress () {
        analyzedArtistCount++;
        var percent = analyzedArtistCount / artistCount;
        var progress = percent*100;
        $('#appProgress').css('width', progress + '%');
    }

    /**
     *
     * @param {type} artist
     * @returns {undefined}
     */
    function artistCallback (artist) {
        var initialStatus = $('#initial-status').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function albumCallback (artist) {
         var initialStatus = $('#initial-status-album').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function fanCallback (artist) {
        var initialStatus = $('#initial-status-fan').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function tagCallback (artist) {
        var initialStatus = $('#initial-status-tag').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    function similarCallback (artist) {
        var initialStatus = $('#initial-status-similar').val();
        $('#status').text(initialStatus + ' ' + artist + '...');
    }

    // Get stats one by one recursively and call a callback when finished
    function getStats (artists, callback) {

        // Race end: empty array
        if (artists.length === 0) {
            callback();
            return;
        }

        // Pop an artist from array
        var artist = artists.pop();

        // Get stats for the popped artist and then continue
        LastFMProxy.getStats(artist.id, artist.name, artistCallback, albumCallback, fanCallback, tagCallback, similarCallback, function (stats) {
            updateProgress();
            artistStats[artist.name] = stats;
            getStats(artists, callback);

        });
    }

    function showResults() {
        // TODO: Insert text
        var tags = [];
        artistStats.forEach(function (stats) {
            stats.tags.forEach(function (tag) {
                tags.push(tag);
            });
        });

        console.log(Aggregate.sortByFrequency(tags));

        $('#process').hide();
        $('#results').removeClass('hidden');
    }

    function selectTopRated (artists, n) {
        var selected = [];

        // Get the likes of each artist
        artists.sort(function (a, b) {
            return a.likes - b.likes;
        });

        selected = artists.splice(0,n);

        return selected;
    }

    // DOM callbacks
    $(document).ready(function () {

        // Get user artists
        getArtists(function (artists) {

            var MAX_ARTISTS = 10;

            // If no artist likes show message
            if (artists.length === 0) {
                showModal($('#error-title').val(), $('#error-status').val(), function () {

                });

            }

            // If too much musicians
            if (artists.length > MAX_ARTISTS) {
                artists = selectTopRated(artists, MAX_ARTISTS);
            }

            console.log(artists);

            artistCount = artists.length || 0;

            // Else get stats one by one
            getStats(artists, function () {
                showResults();
            });

        }); // Get user artists
    }); // End document ready
}); // End module<|endoftext|>


<commit_before>$(document).ready(getposts);
function getposts(){

    $.getJSON('entries.json', function(data) {
		$.each(data.entries.reverse(), function(key, val) {
                var output="
";
				    output+="
" + val.date +"
";
				    output+="
" + val.title +"
";
				    output+="
" + val.text +"
";
				    output+="
";
					output+="
";

				$("#blog").append(output);
				$('#blog').paginate({itemsPerPage: 2});
      	});
    });
}
//
$('#search2').keyup(function () {
    var searchField = $('#search2').val();
    if (searchField.length)
    {
    var myExp = new RegExp(searchField, "i");
    var found = 0;

   $.getJSON('entries.json', function (data) {
   var output = '
';

   $.each(data.entries, function(key, val) {
      if (val.text.search(myExp) !== -1 || val.title.search(myExp) !== -1) {
      console.log(val);
      found = 1;
      output += '
';
      output += '
';
      output += '
' + val.date + '
';
      output += '
' + val.title + '
';
      output += '
' + val.text + '
';
      output += '
';
      $('#update').paginate({itemsPerPage: 4});
      }
   });
      output += '
';
      output += '
';
	  output += '« Newer';
	  output += '|';
	  output += 'Older »';
      output += '
';

      if (found==1) {
      $('#update').removeClass('update-hidden');
      $('#update').html(output);
      }
      else {
          $('#update').addClass('update-hidden');
      }

});
    } else {
      $('#update').addClass('update-hidden');
    }
});
<commit_msg>Last change again<commit_after>$(document).ready(getposts);
function getposts(){

    $.getJSON('entries.json', function(data) {
		$.each(data.entries.reverse(), function(key, val) {
                var output="
";
				    output+="
" + val.date +"
";
				    output+="
" + val.title +"
";
				    output+="
" + val.text +"
";
				    output+="
";
					output+="
";

				$("#blog").append(output);
				$('#blog').paginate({itemsPerPage: 2});
      	});
    });
}
//
$('#search2').keyup(function () {
    var searchField = $('#search2').val();
    if (searchField.length)
    {
    var myExp = new RegExp(searchField, "i");
    var found = 0;

   $.getJSON('entries.json', function (data) {
   var output = '
';

   $.each(data.entries, function(key, val) {
      if (val.text.search(myExp) !== -1 || val.title.search(myExp) !== -1) {
      console.log(val);
      found = 1;
      output += '
';
      output += '
';
      output += '
' + val.date + '
';
      output += '
' + val.title + '
';
      output += '
' + val.text + '
';
      output += '
';
      }
   });
      output += '
';

      output += '
';
	  output += '« Newer';
	  output += '|';
	  output += 'Older »';
      output += '
';

      if (found==1) {
      $('#update').removeClass('update-hidden');
      $('#update').html(output);
      $('#update').paginate({itemsPerPage: 4});
      }
      else {
          $('#update').addClass('update-hidden');
      }

});
    } else {
      $('#update').addClass('update-hidden');
    }
});
<|endoftext|>


<commit_before>var gallery = {
  item_template :
        '
' +
            '' +
            '' +
        '
',

  gallery : null,
  modal : null,
  modal_image: null,
  modal_caption: null,
  modal_close: null,
  load_more_requested: false,
  perload : {},
  columns : {},
  images : {},
  pointer : 0,
  enqueue_pointer : -1,
  currently_loading: 0,
  max_parallel_load: 5,
  tobe_loaded : [],
  imgidx: -1,
  interval_time: 5000,
  interval: null,

  init : function() {
    this.bind();

    var load_images = [];

    for(var ptr = 0; ptr < this.images.length; ptr++) {
      if(this.images[ptr].doload) {
        this.pointer = ptr;
        this.images[ptr].loaded = true;

        load_images.push(this.images[ptr]);
        if(ptr >= this.images.length) {
          this.allLoaded();
          break;
        }
      }
    }

    this.loadImages(load_images);
  },

  bind : function() {
    var self = this;
    $('

').appendTo('body');
    this.container = $('.gallery');
    this.modal = $('.modal');
    this.perload = this.container.data('perload');
    this.columns = this.container.data('columns');
    this.images = JSON.parse(decodeURIComponent(this.container.data('images')));

    this.prepareModal();
    this.bindImages();
    this.endlessScroll();

    $('.loadmore').on('click', function() {
      self.loadMore();
    });

    $(document).on('keyup', function(e) {
      if(e.keyCode == 27) {
        self.modal.hide();
        window.clearInterval(self.interval);
      }

      if(e.keyCode == 37) {
        self.prevImage();
      }

      if(e.keyCode == 39) {
        self.nextImage();
      }
    });

  },

  bindImages : function() {
    var self = this;
    var $imgs = $('img[data-modalimage]:not([data-loaded])');
    $imgs.on('click', function(e) {
      self.showModal($(this).parent().data('imgidx'));
    }).data('loaded', '1');

    $imgs.tilt({
      maxTilt:        40,
      perspective:    1200,   // Transform perspective, the lower the more extreme the tilt gets.

      scale:          1.02,      // 2 = 200%, 1.5 = 150%, etc..
      speed:          800,    // Speed of the enter/exit transition.
      transition:     true,   // Set a transition on enter/exit.
      axis:           null,   // What axis should be disabled. Can be X or Y.
      reset:          true,   // If the tilt effect has to be reset on exit.
      glare:          true,  // Enables glare effect
      maxGlare:       0.5       // From 0 - 1.
    });

  },

  prepareModal : function() {
    var self = this;
    var html =
    '
' +
      '

' +
      '×' +
      '
x von y
' +
      '' +
      '

' +
      '
‹
' +
      '
›
' +
      '

' +
      '＋' +
    '
';
    $(html).appendTo('body');
    this.modal = $('#the-modal');
    this.modal_image = $('#the-modal img');
    this.modal_caption = $('#the-modal caption');
    this.modal_close = $('#the-modal .close');

    this.modal_close.on('click', function() {
      self.modal.hide();
    });

    this.modal.find('.modal-control__prev').on('click', function() {
      self.prevImage();
    });

    this.modal.find('.modal-control__next').on('click', function() {
      self.nextImage();
    });

    this.modal.find('.modal-control__play').on('click', function() {
      if(self.interval) {
        window.clearInterval(self.interval);
        $(this).addClass('play').html("");
        self.interval = null;
        return;
      }

      $(this).removeClass('play').html("❚❚");
      self.interval = window.setInterval(function() {
        self.nextImage();
      }, self.interval_time);
    });

     this.modal.on('swiperight', function(e) {
      self.prevImage();
     });

     this.modal.on('swipeleft', function(e) {
      self.nextImage();
     });

  },

  showModal : function(imgidx) {
    this.modal.show();
    this.updateModalImage(imgidx);
  },

  updateModalImage : function(imgidx) {
    if(imgidx < 0 || imgidx >= this.images.length)
      return;
    this.imgidx = imgidx;

    var self = this;
    var $img = $('[data-imgidx="' + this.imgidx +'"] > img');
    var imgsrc = $img.data('modalimage');
    var bigsrc = $img.data('bigimage');
    var caption = $img.data('alt');

    this.modal.addClass("loading");
    this.modal_image.on('load', function() {
      self.modal.removeClass("loading");
      self.modal_image.loaded = null;
    });
    this.modal_image.attr('src', imgsrc);
    this.modal_caption.innerHTML = caption;

    if(this.imgidx === 0) {
      this.modal.addClass('at-start');
    } else {
      this.modal.removeClass('at-start');
    }

    if(this.images.length == this.imgidx + 1) {
      this.modal.addClass('at-end');
    } else {
      this.modal.removeClass('at-end');
    }

    this.modal.find('.modal-control__magnify').attr('href', bigsrc);
    this.modal.find('.modal-x').text(this.imgidx + 1);
    this.modal.find('.modal-y').text(this.images.length);

    var idxloaded = Math.min(this.imgidx + 4, this.images.length - 1);
    if(!$('[data-imgidx="' + idxloaded + '"]').length) {
      this.loadMore();
    }
  },

  prevImage : function() {
    this.updateModalImage(this.imgidx - 1);
  },

  nextImage : function() {
    this.updateModalImage(this.imgidx + 1);
  },

  endlessScroll : function() {
    var self = this;

    $(window).on('scroll', evt_buffer(function(e) {
      var cheight = $('body').innerHeight();
      var top = $(window).scrollTop() + window.innerHeight;
      var threshold = window.innerHeight / 2;
      if(cheight - top  < threshold) {
        self.loadMore(true);
      }
    }, 200, true));
  },

  loadMore : function(only_if_not_enqueued) {
    if(only_if_not_enqueued && this.enqueue_pointer + 1 < this.tobe_loaded.length) {
      return;
    }
    var load_images = [];
    for(var i = 0; i < this.perload; i++) {
      var ptr = this.pointer + i;
      if(ptr >= this.images.length) {
        this.allLoaded();
       break;
      }
      this.images[ptr].loaded = true;
      load_images.push(this.images[ptr]);
    }
    this.pointer = ptr;

    this.loadImages(load_images);
  },

  loadImages : function(images) {
    var self = this;
    if(images && images.length) {
      this.enqueueImages(images);
    }

    if(this.max_parallel_load <= this.currently_loading) {
      return;
    }

    this.currently_loading++;

    var img = this.getNextEnqueued();
    if(!img) {
      this.currently_loading--;
      return;
    }

    var html = '';
    var caption = $($('[data-title]')[0]).attr('data-title');

    var startcolumnidx = this.getSmallestColumn();
    var imgsrc   = img.thumbnail_url;
    var modalsrc = img.optimized_url;
    var bigsrc   = img.original_url;
    var padding  = (img['dimensions']['height'] / img['dimensions']['width']) * 100;

    html = this.item_template.replace('%imgsrc%', imgsrc);
    html = html.replace('%bigimage%', bigsrc);
    html = html.replace('%modalimage%', modalsrc);
    html = html.replace('%imgidx%', img.imgidx);
    html = html.replace('%alttext%', caption);
    html = html.replace('%padding%', padding);

    columnidx = (startcolumnidx + this.enqueue_pointer) % this.columns  + 1;

    $html = $(html);
    $html.find('img').on('load', function() {
      self.currently_loading--;
      $(this).closest('.image-holder').removeClass('loading').addClass('loaded');
      self.loadImages();
    }).on('error', function() {
      self.currently_loading--;
      self.loadImages();
    });

    $html.appendTo($(".column-" + columnidx));

    this.bindImages();

    if(this.enqueue_pointer + 1 == this.images.length) {
      this.allLoaded();
    }

    if(this.max_parallel_load > this.currently_loading) {
      this.loadImages();
    }
  },

  enqueueImages : function(images) {
    this.tobe_loaded = this.tobe_loaded.concat(images);
  },

  getNextEnqueued : function() {
    if(this.tobe_loaded.length == this.enqueue_pointer)
      return null;
    return this.tobe_loaded[++this.enqueue_pointer];
  },

  getSmallestColumn : function() {
    var c1 = $(".column-1").innerHeight();
    var c2 = $(".column-2").innerHeight();
    var c3 = $(".column-3").innerHeight();
    if(c1 < c2 && c1 < c3) {
      return 1;
    } else if(c2 < c3 && c2 < c1) {
      return 2;
    }
    return 3;
  },

  allLoaded : function() {
    if($('.alloaded').length)
      return;
    $("
Keine weitern Bilder
").appendTo('body');
    $('.loadmore').remove();
  }

};

$(document).ready(function() {
  gallery.init();
});<commit_msg>Fix laodmore<commit_after>var gallery = {
  item_template :
        '
' +
            '' +
            '' +
        '
',

  gallery : null,
  modal : null,
  modal_image: null,
  modal_caption: null,
  modal_close: null,
  load_more_requested: false,
  perload : {},
  columns : {},
  images : {},
  pointer : 0,
  enqueue_pointer : -1,
  currently_loading: 0,
  max_parallel_load: 5,
  tobe_loaded : [],
  imgidx: -1,
  interval_time: 8000,
  interval: null,

  init : function() {
    this.bind();

    var load_images = [];

    for(var ptr = 0; ptr < this.images.length; ptr++) {
      if(this.images[ptr].doload) {
        this.pointer = ptr;
        this.images[ptr].loaded = true;

        load_images.push(this.images[ptr]);
        if(ptr >= this.images.length) {
          this.allLoaded();
          break;
        }
      }
    }

    this.loadImages(load_images);
  },

  bind : function() {
    var self = this;
    $('

').appendTo('body');
    this.container = $('.gallery');
    this.modal = $('.modal');
    this.perload = this.container.data('perload');
    this.columns = this.container.data('columns');
    this.images = JSON.parse(decodeURIComponent(this.container.data('images')));

    this.prepareModal();
    this.bindImages();
    this.endlessScroll();

    $('.loadmore').on('click', function() {
      self.loadMore();
    });

    $(document).on('keyup', function(e) {
      if(e.keyCode == 27) {
        self.modal.hide();
        window.clearInterval(self.interval);
      }

      if(e.keyCode == 37) {
        self.prevImage();
      }

      if(e.keyCode == 39) {
        self.nextImage();
      }
    });

  },

  bindImages : function() {
    var self = this;
    var $imgs = $('img[data-modalimage]:not([data-loaded])');
    $imgs.on('click', function(e) {
      self.showModal($(this).parent().data('imgidx'));
    }).data('loaded', '1');

    $imgs.tilt({
      maxTilt:        40,
      perspective:    1200,   // Transform perspective, the lower the more extreme the tilt gets.

      scale:          1.02,      // 2 = 200%, 1.5 = 150%, etc..
      speed:          800,    // Speed of the enter/exit transition.
      transition:     true,   // Set a transition on enter/exit.
      axis:           null,   // What axis should be disabled. Can be X or Y.
      reset:          true,   // If the tilt effect has to be reset on exit.
      glare:          true,  // Enables glare effect
      maxGlare:       0.5       // From 0 - 1.
    });

  },

  prepareModal : function() {
    var self = this;
    var html =
    '
' +
      '

' +
      '×' +
      '
x von y
' +
      '' +
      '

' +
      '
‹
' +
      '
›
' +
      '

' +
      '＋' +
    '
';
    $(html).appendTo('body');
    this.modal = $('#the-modal');
    this.modal_image = $('#the-modal img');
    this.modal_caption = $('#the-modal caption');
    this.modal_close = $('#the-modal .close');

    this.modal_close.on('click', function() {
      self.modal.hide();
    });

    this.modal.find('.modal-control__prev').on('click', function() {
      self.prevImage();
    });

    this.modal.find('.modal-control__next').on('click', function() {
      self.nextImage();
    });

    this.modal.find('.modal-control__play').on('click', function() {
      if(self.interval) {
        window.clearInterval(self.interval);
        $(this).addClass('play').html("");
        self.interval = null;
        return;
      }

      var callaback = function() {
        if(this.modal.hasClass('loading')) {
          window.clearInterval(self.interval);
          self.interval = window.setInterval(callback);
        }
        self.nextImage();
      };

      $(this).removeClass('play').html("❚❚");
      self.interval = window.setInterval(callback, self.interval_time);
    });

     this.modal.on('swiperight', function(e) {
      self.prevImage();
     });

     this.modal.on('swipeleft', function(e) {
      self.nextImage();
     });

  },

  showModal : function(imgidx) {
    this.modal.show();
    this.updateModalImage(imgidx);
  },

  updateModalImage : function(imgidx) {
    if(imgidx < 0 || imgidx >= this.images.length)
      return;
    this.imgidx = imgidx;

    var self = this;
    var $img = $('[data-imgidx="' + this.imgidx +'"] > img');
    var imgsrc = $img.data('modalimage');
    var bigsrc = $img.data('bigimage');
    var caption = $img.data('alt');

    this.modal.addClass("loading");
    this.modal_image.on('load', function() {
      self.modal.removeClass("loading");
      self.modal_image.loaded = null;
    });
    this.modal_image.attr('src', imgsrc);
    this.modal_caption.innerHTML = caption;

    if(this.imgidx === 0) {
      this.modal.addClass('at-start');
    } else {
      this.modal.removeClass('at-start');
    }

    if(this.images.length == this.imgidx + 1) {
      this.modal.addClass('at-end');
    } else {
      this.modal.removeClass('at-end');
    }

    this.modal.find('.modal-control__magnify').attr('href', bigsrc);
    this.modal.find('.modal-x').text(this.imgidx + 1);
    this.modal.find('.modal-y').text(this.images.length);

    var idxloaded = Math.min(this.imgidx + 4, this.images.length - 1);
    if(!$('[data-imgidx="' + idxloaded + '"]').length) {
      this.loadMore();
    }
  },

  prevImage : function() {
    this.updateModalImage(this.imgidx - 1);
  },

  nextImage : function() {
    this.updateModalImage(this.imgidx + 1);
  },

  endlessScroll : function() {
    var self = this;

    $(window).on('scroll', evt_buffer(function(e) {
      var cheight = $('body').innerHeight();
      var top = $(window).scrollTop() + window.innerHeight;
      var threshold = window.innerHeight / 2;
      if(cheight - top  < threshold) {
        self.loadMore(true);
      }
    }, 200, true));
  },

  loadMore : function(only_if_not_enqueued) {
    if(only_if_not_enqueued && this.enqueue_pointer + 1 < this.tobe_loaded.length) {
      return;
    }
    var load_images = [];
    for(var i = 0; i < this.perload; i++) {
      var ptr = this.pointer + i;
      if(ptr >= this.images.length) {
        this.allLoaded();
       break;
      }
      this.images[ptr].loaded = true;
      load_images.push(this.images[ptr]);
    }
    this.pointer = ptr;

    this.loadImages(load_images);
  },

  loadImages : function(images) {
    var self = this;
    if(images && images.length) {
      this.enqueueImages(images);
    }

    if(this.max_parallel_load <= this.currently_loading) {
      return;
    }

    this.currently_loading++;

    var img = this.getNextEnqueued();
    if(!img) {
      this.currently_loading--;
      return;
    }

    var html = '';
    var caption = $($('[data-title]')[0]).attr('data-title');

    var startcolumnidx = this.getSmallestColumn();
    var imgsrc   = img.thumbnail_url;
    var modalsrc = img.optimized_url;
    var bigsrc   = img.original_url;
    var padding  = (img['dimensions']['height'] / img['dimensions']['width']) * 100;

    html = this.item_template.replace('%imgsrc%', imgsrc);
    html = html.replace('%bigimage%', bigsrc);
    html = html.replace('%modalimage%', modalsrc);
    html = html.replace('%imgidx%', img.imgidx);
    html = html.replace('%alttext%', caption);
    html = html.replace('%padding%', padding);

    columnidx = (startcolumnidx + this.enqueue_pointer) % this.columns  + 1;

    $html = $(html);
    $html.find('img').on('load', function() {
      self.currently_loading--;
      $(this).closest('.image-holder').removeClass('loading').addClass('loaded');
      self.loadImages();
    }).on('error', function() {
      self.currently_loading--;
      self.loadImages();
    });

    $html.appendTo($(".column-" + columnidx));

    this.bindImages();

    if(this.enqueue_pointer + 1 == this.images.length) {
      this.allLoaded();
    }

    if(this.max_parallel_load > this.currently_loading) {
      this.loadImages();
    }
  },

  enqueueImages : function(images) {
    this.tobe_loaded = this.tobe_loaded.concat(images);
  },

  getNextEnqueued : function() {
    if(this.tobe_loaded.length == this.enqueue_pointer)
      return null;
    return this.tobe_loaded[++this.enqueue_pointer];
  },

  getSmallestColumn : function() {
    var c1 = $(".column-1").innerHeight();
    var c2 = $(".column-2").innerHeight();
    var c3 = $(".column-3").innerHeight();
    if(c1 < c2 && c1 < c3) {
      return 1;
    } else if(c2 < c3 && c2 < c1) {
      return 2;
    }
    return 3;
  },

  allLoaded : function() {
    if($('.alloaded').length)
      return;
    $("
Keine weitern Bilder
").appendTo('body');
    $('.loadmore').remove();
  }

};

$(document).ready(function() {
  gallery.init();
});<|endoftext|>


<commit_before>"use strict";

var path = require('path'),
	moment = require('moment'),
	tz = require('../').tz;

function changeTest (zone, i) {
	var until         = moment.utc(zone.untils[i]),
		minutesOffset = zone.offsets[i],
		secondsOffset = Math.round(minutesOffset * 60),
		abbr          = zone.abbrs[i],
		dateTime      = until.format(),
		hours         = until.clone().subtract(secondsOffset, 'seconds').format('HH:mm:ss');

	if (secondsOffset % 60) {
		minutesOffset = secondsOffset + ' / 60';
	}

	return '["' + dateTime + '", "' + hours + '", "' + abbr + '", ' + minutesOffset + ']';
}

function yearTest (year, changes, name) {
	return '\t"' + year + '" : helpers.makeTestYear("' + name + '", [\n\t\t' + changes.join(',\n\t\t') + '\n\t])';
}

function tests (zone) {
	var years = {};

	zone.untils.forEach(function (until, i) {
		if (i < 2 || i >= zone.untils.length - 2) { return; }
		var year = moment.utc(until).year();
		years[year] = years[year] || [];
		years[year].push(changeTest(zone, i));
	});

	return Object.keys(years).map(function (year) {
		return yearTest(year, years[year], zone.name);
	}).join(',\n\n');
}

function intro (name) {
	var helpers = path.relative(path.dirname('zones/' + name), 'helpers/helpers');
	return '"use strict";\n\nvar helpers = require("' + helpers + '");\n\nexports["' + name + '"] = {\n';
}

function formatForMonth (name, month, format) {
	return tz([2015, month, 1], name).format(format);
}

function untilForMonth (name, month) {
	var zone = tz.zone(name),
		index = zone._index(new Date(2015, month, 1)),
		until = zone.untils[Math.min(zone.untils.length - 1, index)];
	return tz(until === Infinity ? [2015, month, 1] : until, name).format('YYYY-MM-DD HH:mm');
}

function dataToOffsetAndAbbr (zoneData) {
	var name = zoneData.name;
	return {
		name: name,
		population: zoneData.population,
		offsets: formatForMonth(name, 0, 'Z') + ' ' + formatForMonth(name, 6, 'Z'),
		untils: untilForMonth(name, 0) + ' ' + untilForMonth(name, 6),
		abbrs: formatForMonth(name, 0, 'z') + ' ' + formatForMonth(name, 6, 'z')
	};
}

function population (data, grouped) {
	var current = dataToOffsetAndAbbr(data);
	var isMostPopulatedInOffset = current.population > 0;
	var isMostPopulatedInAbbr = current.population > 0;
	grouped.forEach(function (other) {
		if (current.population > other.population || current.name === other.name) {
			return;
		}
		if (other.offsets === current.offsets) {
			isMostPopulatedInOffset = false;
			if (other.abbrs === current.abbrs) {
				isMostPopulatedInAbbr = false;
			}
		}
	});
	if (!isMostPopulatedInAbbr && !isMostPopulatedInOffset) {
		return '';
	}
	return '\t"guess" : helpers.makeTestGuess("' + data.name + '", { offset: ' + isMostPopulatedInOffset + ', abbr: ' + isMostPopulatedInAbbr + ' }),\n\n';
}

module.exports = function (grunt) {
	grunt.registerTask('data-tests', '8. Create unit tests from data-collect.', function () {
		tz.load(grunt.file.readJSON('data/packed/latest.json'));
		var zones = grunt.file.readJSON('temp/collect/latest.json'),
			grouped = zones.map(dataToOffsetAndAbbr);

		zones.forEach(function (zone) {
			var data = intro(zone.name) + population(zone, grouped) + tests(zone) + '\n};',
				dest = path.join('tests/zones', zone.name.toLowerCase() + '.js');

			grunt.file.mkdir(path.dirname(dest));
			grunt.file.write(dest, data);
			grunt.verbose.ok("Created " + zone.name + " tests.");
		});

		grunt.log.ok('Created tests');
	});
};

// Tests should look something like this.
//
// "use strict";
//
// var helpers = require("../../helpers/helpers");
//
// exports["America/Los_Angeles"] = {
// 	"guess" : helpers.makeTestGuess("America/Los_Angeles", { offset: true, abbr: true }),
//
// 	"1918" : helpers.makeTestYear("America/Los_Angeles", [
// 		["1918-03-31T09:59:59+00:00", "01:59:59", "PST", 480],
// 		["1918-03-31T10:00:00+00:00", "03:00:00", "PDT", 420],
// 		["1918-10-27T08:59:59+00:00", "01:59:59", "PDT", 420],
// 		["1918-10-27T09:00:00+00:00", "01:00:00", "PST", 480]
// 	]),
//
// 	"1919" : helpers.makeTestYear("America/Los_Angeles", [
// 		["1919-03-30T09:59:59+00:00", "01:59:59", "PST", 480],
// 		["1919-03-30T10:00:00+00:00", "03:00:00", "PDT", 420],
// 		["1919-10-26T08:59:59+00:00", "01:59:59", "PDT", 420],
// 		["1919-10-26T09:00:00+00:00", "01:00:00", "PST", 480]
// 	])
// };
<commit_msg>Use explicit format for test generation<commit_after>"use strict";

var path = require('path'),
	moment = require('moment'),
	tz = require('../').tz;

function changeTest (zone, i) {
	var until         = moment.utc(zone.untils[i]),
		minutesOffset = zone.offsets[i],
		secondsOffset = Math.round(minutesOffset * 60),
		abbr          = zone.abbrs[i],
		dateTime      = until.format('YYYY-MM-DDTHH:mm:ssZ'),
		hours         = until.clone().subtract(secondsOffset, 'seconds').format('HH:mm:ss');

	if (secondsOffset % 60) {
		minutesOffset = secondsOffset + ' / 60';
	}

	return '["' + dateTime + '", "' + hours + '", "' + abbr + '", ' + minutesOffset + ']';
}

function yearTest (year, changes, name) {
	return '\t"' + year + '" : helpers.makeTestYear("' + name + '", [\n\t\t' + changes.join(',\n\t\t') + '\n\t])';
}

function tests (zone) {
	var years = {};

	zone.untils.forEach(function (until, i) {
		if (i < 2 || i >= zone.untils.length - 2) { return; }
		var year = moment.utc(until).year();
		years[year] = years[year] || [];
		years[year].push(changeTest(zone, i));
	});

	return Object.keys(years).map(function (year) {
		return yearTest(year, years[year], zone.name);
	}).join(',\n\n');
}

function intro (name) {
	var helpers = path.relative(path.dirname('zones/' + name), 'helpers/helpers');
	return '"use strict";\n\nvar helpers = require("' + helpers + '");\n\nexports["' + name + '"] = {\n';
}

function formatForMonth (name, month, format) {
	return tz([2015, month, 1], name).format(format);
}

function untilForMonth (name, month) {
	var zone = tz.zone(name),
		index = zone._index(new Date(2015, month, 1)),
		until = zone.untils[Math.min(zone.untils.length - 1, index)];
	return tz(until === Infinity ? [2015, month, 1] : until, name).format('YYYY-MM-DD HH:mm');
}

function dataToOffsetAndAbbr (zoneData) {
	var name = zoneData.name;
	return {
		name: name,
		population: zoneData.population,
		offsets: formatForMonth(name, 0, 'Z') + ' ' + formatForMonth(name, 6, 'Z'),
		untils: untilForMonth(name, 0) + ' ' + untilForMonth(name, 6),
		abbrs: formatForMonth(name, 0, 'z') + ' ' + formatForMonth(name, 6, 'z')
	};
}

function population (data, grouped) {
	var current = dataToOffsetAndAbbr(data);
	var isMostPopulatedInOffset = current.population > 0;
	var isMostPopulatedInAbbr = current.population > 0;
	grouped.forEach(function (other) {
		if (current.population > other.population || current.name === other.name) {
			return;
		}
		if (other.offsets === current.offsets) {
			isMostPopulatedInOffset = false;
			if (other.abbrs === current.abbrs) {
				isMostPopulatedInAbbr = false;
			}
		}
	});
	if (!isMostPopulatedInAbbr && !isMostPopulatedInOffset) {
		return '';
	}
	return '\t"guess" : helpers.makeTestGuess("' + data.name + '", { offset: ' + isMostPopulatedInOffset + ', abbr: ' + isMostPopulatedInAbbr + ' }),\n\n';
}

module.exports = function (grunt) {
	grunt.registerTask('data-tests', '8. Create unit tests from data-collect.', function () {
		tz.load(grunt.file.readJSON('data/packed/latest.json'));
		var zones = grunt.file.readJSON('temp/collect/latest.json'),
			grouped = zones.map(dataToOffsetAndAbbr);

		zones.forEach(function (zone) {
			var data = intro(zone.name) + population(zone, grouped) + tests(zone) + '\n};',
				dest = path.join('tests/zones', zone.name.toLowerCase() + '.js');

			grunt.file.mkdir(path.dirname(dest));
			grunt.file.write(dest, data);
			grunt.verbose.ok("Created " + zone.name + " tests.");
		});

		grunt.log.ok('Created tests');
	});
};

// Tests should look something like this.
//
// "use strict";
//
// var helpers = require("../../helpers/helpers");
//
// exports["America/Los_Angeles"] = {
// 	"guess" : helpers.makeTestGuess("America/Los_Angeles", { offset: true, abbr: true }),
//
// 	"1918" : helpers.makeTestYear("America/Los_Angeles", [
// 		["1918-03-31T09:59:59+00:00", "01:59:59", "PST", 480],
// 		["1918-03-31T10:00:00+00:00", "03:00:00", "PDT", 420],
// 		["1918-10-27T08:59:59+00:00", "01:59:59", "PDT", 420],
// 		["1918-10-27T09:00:00+00:00", "01:00:00", "PST", 480]
// 	]),
//
// 	"1919" : helpers.makeTestYear("America/Los_Angeles", [
// 		["1919-03-30T09:59:59+00:00", "01:59:59", "PST", 480],
// 		["1919-03-30T10:00:00+00:00", "03:00:00", "PDT", 420],
// 		["1919-10-26T08:59:59+00:00", "01:59:59", "PDT", 420],
// 		["1919-10-26T09:00:00+00:00", "01:00:00", "PST", 480]
// 	])
// };
<|endoftext|>


<commit_before>var myGame = null;

function getButtonCallbacks (button) {
    return {
        light: {
            on: function () {
                $('#' + button).addClass('on');
            },
            off: function () {
                $('#' + button).removeClass('on');
            }
        },
        sound: {
            on: function () {
                return createjs.Sound.play(button);
            }
        }
    };
}

$(document).ready(function () {
    // Load our sounds
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound1.mp3", 'red');
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound2.mp3", 'green');
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound3.mp3", 'blue');
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound4.mp3", 'yellow');

    // All we should need to do is bind our DOM elements to our game object
    let gameElements = {
        red: getButtonCallbacks('red'),
        green: getButtonCallbacks('green'),
        blue: getButtonCallbacks('blue'),
        yellow: getButtonCallbacks('yellow'),
        sequenceCount: function (seqCount) {
            $('#sequence-count').html(seqCount);
        }
    };

    myGame = new SimonGame(gameElements);

    // And attach our event handlers
    let colors = ['red', 'green', 'blue', 'yellow'];
    colors.map(function (color) {
        $('#' + color).on('click', function () {
            myGame.pressButton(color);
        });
    });

    $('#onButton').click(function () {
        if ($(this).prop('checked')) {
            $('#startButton').prop('disabled', false);
            $('#strictButton').prop('disabled', false);
            myGame.on();
        } else {
            $('#startButton').prop('disabled', true);
            $('#strictButton').prop('disabled', true);
            $('#sequence-count').html("--");
            myGame.off();
        }
    });

    $('#startButton').click(function () {
        myGame.start();
    });

    $('#strictButton').click(function () {
        console.log("checked? " + $(this).prop('checked'));
        if ($(this).prop('checked')) {
            myGame.setStrict(true);
        } else {
            myGame.setStrict(false);
        }
        // myGame.strict(true);
    });
});<commit_msg>Change let to var for es5<commit_after>var myGame = null;

function getButtonCallbacks (button) {
    return {
        light: {
            on: function () {
                $('#' + button).addClass('on');
            },
            off: function () {
                $('#' + button).removeClass('on');
            }
        },
        sound: {
            on: function () {
                return createjs.Sound.play(button);
            }
        }
    };
}

$(document).ready(function () {
    // Load our sounds
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound1.mp3", 'red');
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound2.mp3", 'green');
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound3.mp3", 'blue');
    createjs.Sound.registerSound("https://dl.dropboxusercontent.com/u/13022985/simonSound4.mp3", 'yellow');

    // All we should need to do is bind our DOM elements to our game object
    var gameElements = {
        red: getButtonCallbacks('red'),
        green: getButtonCallbacks('green'),
        blue: getButtonCallbacks('blue'),
        yellow: getButtonCallbacks('yellow'),
        sequenceCount: function (seqCount) {
            $('#sequence-count').html(seqCount);
        }
    };

    myGame = new SimonGame(gameElements);

    // And attach our event handlers
    var colors = ['red', 'green', 'blue', 'yellow'];
    colors.map(function (color) {
        $('#' + color).on('click', function () {
            myGame.pressButton(color);
        });
    });

    $('#onButton').click(function () {
        if ($(this).prop('checked')) {
            $('#startButton').prop('disabled', false);
            $('#strictButton').prop('disabled', false);
            myGame.on();
        } else {
            $('#startButton').prop('disabled', true);
            $('#strictButton').prop('disabled', true);
            $('#sequence-count').html("--");
            myGame.off();
        }
    });

    $('#startButton').click(function () {
        myGame.start();
    });

    $('#strictButton').click(function () {
        if ($(this).prop('checked')) {
            myGame.setStrict(true);
        } else {
            myGame.setStrict(false);
        }
    });
});<|endoftext|>


<commit_before>"use strict";

module.exports = request;

function request(method, url, headers, body, callback) {
  if (typeof body === "function") {
    callback = body;
    body = undefined;
  }
  if (!callback) {
    return request.bind(null, method, url, headers, body);
  }
  var xhr = new XMLHttpRequest();
  xhr.open(method, url, true);
  xhr.responseType = "arraybuffer";

  Object.keys(headers).forEach(function (name) {
    xhr.setRequestHeader(name, headers[name]);
  });

  xhr.onreadystatechange = function () {
    if (xhr.readyState !== 4) return;
    var resHeaders = {};
    xhr.getAllResponseHeaders().trim().split("\r\n").forEach(function (line) {
      var index = line.indexOf(":");
      resHeaders[line.substring(0, index).toLowerCase()] = line.substring(index + 1).trim();
    });

    callback(null, {
      statusCode: xhr.status,
      headers: resHeaders,
      body: xhr.response && new Uint8Array(xhr.response)
    });
  };
  xhr.send(body);
}
<commit_msg>Save changes<commit_after>"use strict";

module.exports = request;

function request(method, url, headers, body, callback) {
  if (typeof body === "function") {
    callback = body;
    body = undefined;
  }
  if (!callback) {
    return request.bind(null, method, url, headers, body);
  }
  var xhr = new XMLHttpRequest();
  xhr.open(method, url, true);
  xhr.responseType = "arraybuffer";

  Object.keys(headers).forEach(function (name) {
    xhr.setRequestHeader(name, headers[name]);
  });

  xhr.onreadystatechange = function () {
    if (xhr.readyState !== 4) return;
    var resHeaders = {};
    xhr.getAllResponseHeaders().trim().split("\r\n").forEach(function (line) {
      var index = line.indexOf(":");
      console.log("LINE", line);
      resHeaders[line.substring(0, index).toLowerCase()] = line.substring(index + 1).trim();
    });

    callback(null, {
      statusCode: xhr.status,
      headers: resHeaders,
      body: xhr.response && new Uint8Array(xhr.response)
    });
  };
  xhr.send(body);
}
<|endoftext|>


<commit_before>$(function () {
    'use strict';
    var EXCLUDE = ['..', 'doc', 'stable', 'beta', 'experimental']
    $('.hero-unit [data-channel]').click(function () {
        $('#models').hide();
        var path = '/'+$(this).attr('data-channel')+'/factory/';
        $.get(path, function (data) {
            var routers = {},
                links = $(data).find('a[href$=".bin"]');
            links.each(function () {
                var link = path+$(this).attr('href'),//.split('/').slice(-1)[0],
                    router = link.split('-').slice(4).join('-').split('.')[0],
                    split = router.split('-'),
                    model,
                    hwversion;
                if (split.slice(-1)[0][0] === 'v') {
                    model = split.slice(0, -1).join('-');
                    hwversion = split.slice(-1)[0];
                } else if (split.slice(-2, -1)[0] === 'rev') {
                    model = split.slice(0, -2).join('-');
                    hwversion = split.slice(-1)[0];
                } else {
                    model = router;
                    hwversion = 'alle';
                }
                if (!routers[model]) {
                    routers[model] = [];
                }
                routers[model].push([hwversion, link]);
            });
            links.first().each(function () {
                var link = $(this).attr('href').split('/').slice(-1)[0],
                match = link.match(/gluon-[a-zA-Z]+-([0-9.]+~[a-zA-Z]+)-?([0-9]+)-/);
                $('#version').html(match[1].replace('%7E', '~'));
                $('#versiondate').html(renderDate(match[2]));
            });
            $('tbody').html(renderRouters(routers));
            $('#models').fadeIn(500);
            document.location.hash = 'models';
        }, 'html');
    });
    $.get('/raw/', function (data) {
      var links = $(data).find('a[href$="/"]');
      links.each(function () {
        var target = $(this).attr('href');
        target = target.substring(0, target.length - 1);
        if (EXCLUDE.indexOf(target) == -1) {
          $('#allversions').append('
'+target+'
');
        }
      });
    }, 'html');
});

var renderRouters = function (routers) {
    'use strict';
    var model, i, versions, out = '';
    for (model in routers) {
        versions = routers[model];
        out += '
' + model + '	';
        for (i in versions) {
            out += '' + versions[i][0] + '

';
        }
        out += '
';
    }
    return out;
};

var renderDate = function (date) {
    'use strict';
    return date.substr(6) + '.' + date.substr(4, 2) + '.' + date.substr(0, 4);
};
<commit_msg>location.hash now directly triggers the channel<commit_after>$(function () {
    'use strict';
    var EXCLUDE = ['..', 'doc', 'stable', 'beta', 'experimental']
    $('.hero-unit [data-channel]').click(function () {
        $('#models').hide();
        var path = '/'+$(this).attr('data-channel')+'/factory/';
        $.get(path, function (data) {
            var routers = {},
                links = $(data).find('a[href$=".bin"]');
            links.each(function () {
                var link = path+$(this).attr('href'),//.split('/').slice(-1)[0],
                    router = link.split('-').slice(4).join('-').split('.')[0],
                    split = router.split('-'),
                    model,
                    hwversion;
                if (split.slice(-1)[0][0] === 'v') {
                    model = split.slice(0, -1).join('-');
                    hwversion = split.slice(-1)[0];
                } else if (split.slice(-2, -1)[0] === 'rev') {
                    model = split.slice(0, -2).join('-');
                    hwversion = split.slice(-1)[0];
                } else {
                    model = router;
                    hwversion = 'alle';
                }
                if (!routers[model]) {
                    routers[model] = [];
                }
                routers[model].push([hwversion, link]);
            });
            links.first().each(function () {
                var link = $(this).attr('href').split('/').slice(-1)[0],
                match = link.match(/gluon-[a-zA-Z]+-([0-9.]+~[a-zA-Z]+)-?([0-9]+)-/);
                $('#version').html(match[1].replace('%7E', '~'));
                $('#versiondate').html(renderDate(match[2]));
            });
            $('tbody').html(renderRouters(routers));
            $('#models').fadeIn(500);
        }, 'html');
    });
    $.get('/raw/', function (data) {
      var links = $(data).find('a[href$="/"]');
      links.each(function () {
        var target = $(this).attr('href');
        target = target.substring(0, target.length - 1);
        if (EXCLUDE.indexOf(target) == -1) {
          $('#allversions').append('
'+target+'
');
        }
      });
    }, 'html');
    if (document.location.hash !== '') {
        var channel = document.location.hash.substr(1);
        $('[data-channel="'+channel+'"]').click();
    }
});

var renderRouters = function (routers) {
    'use strict';
    var model, i, versions, out = '';
    for (model in routers) {
        versions = routers[model];
        out += '
' + model + '	';
        for (i in versions) {
            out += '' + versions[i][0] + '

';
        }
        out += '
';
    }
    return out;
};

var renderDate = function (date) {
    'use strict';
    return date.substr(6) + '.' + date.substr(4, 2) + '.' + date.substr(0, 4);
};
<|endoftext|>