<commit_before>Array.max = function( array ){
    return Math.max.apply( Math, array );
};

Array.min = function( array ){
    return Math.min.apply( Math, array );
};

function plotSeries(series, config) {
  var
    // series boundaries
    bounds = series.pop(),

    // extracting the date for display
    dateParts = config.fromDate.value.split('-').map(Number),
    dateString = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]).toDateString(),

    // padding for the graphics
    padding = 20,

    // bar graph width (will be added to sWidth to determine svg width)
    bWidth = 150,

    // scatterplot dimensions and scale
    sWidth = 650,
    sHeight = 400,

    sXMin = bounds['seriesMin']['x'],
    sXMax = bounds['seriesMax']['x'],

    sYMin = bounds['seriesMin']['yLeft'],
    sYMax = bounds['seriesMax']['yLeft'],

    sRMin = bounds['seriesMin']['yRight'],
    sRMax = bounds['seriesMax']['yRight'],

    sXScale = d3.scale.linear().domain([sXMin, sXMax]).range([0, sWidth]),
    sYScale = d3.scale.linear().domain([sYMin, sYMax]).range([sHeight, 0]),
    sRScale = d3.scale.linear().domain([sRMin, sRMax]).range([sRMin, sRMax]),

    sXLabels = config['xLabels']['value'].split(','),
    sXLScale = d3.scale.ordinal().domain(sXLabels).rangePoints([0, sWidth]),

    sColors = d3.scale.category10(),

    sTitle = d3.select("body")
      .append("h3")
      .text(dateString)
      .attr("align", "center"),

    svg = d3.select("body")
      .append("svg:svg")
      // may append the width of the bar graph too
      .attr("width", sWidth + bWidth + padding * 4)
      .attr("height", sHeight + padding * 2)
      .append("svg:g")
      .attr("transform", "translate(" + padding + "," + padding + ")"),

    vRules = svg.selectAll("g.vrule")
      .data(sXLabels)
      .enter().append("svg:g")
      .attr("class", "rule"),

    hRules = svg.selectAll("g.hrule")
      .data(sYScale.ticks(20))
      .enter().append("svg:g")
      .attr("class", "rule");

  vRules.append("svg:line")
    .attr("x1", sXLScale)
    .attr("x2", sXLScale)
    .attr("y1", 0)
    .attr("y2", sHeight - 1);

  vRules.append("svg:text")
    .attr("x", sXLScale)
    .attr("y", sHeight + 3)
    .attr("dy", "1.71em")
    .attr("text-anchor", "start")
    .text(function(d,i) { return d; });

  hRules.append("svg:line")
    .attr("y1", sYScale)
    .attr("y2", sYScale)
    .attr("x1", 0)
    .attr("x2", sWidth + 1);

  hRules.append("svg:text")
    .attr("y", sYScale)
    .attr("x", -3)
    .attr("dy", ".35em")
    .attr("stroke", "grey")
    .attr("text-anchor", "end")
    .text(sYScale.tickFormat(10));

  // clean up what follows
  var a = series.map(function() {return 0;});

  var t = [];

  // todo: omit data points where wait is 0 and patients waiting is 0, just noise on the graph
  series.map(function(e,i){
    e.data.map(function(o){
      a[i] = a[i] + o.yRight_2;
      o.i = i;
      o.a = a[i];
      // may not need this
      o.v = true;
      if (o.yLeft_1 > 0  && o.yRight_1 > 0) {
        t.push(o);
      }
    });
  });

  function compare(a,b) {
    if (a.x < b.x)
       return -1;
    if (a.x > b.x)
      return 1;
    return 0;
  }

  var data = t.sort(compare);

  // plot the initial set of circles
  var circle = svg.selectAll("circle")
    .data(data)
    .enter().append("svg:circle")
    .attr("class", function(d,i) { return "circle" + d.i; })
    .attr("fill", function(d,i) {return sColors(d.i);})
    //.attr("stroke", function(d,i) {return sColors(d.i);})
    .attr("opacity", .4)
    .attr("cx", function(d,i) {return sXScale(d.x);})
    .attr("cy", function(d,i) {return sYScale(d.yLeft_1);})
    .attr("r", function(d,i) {return sRScale(4 + (d.yRight_1 * 2));});

  // bolt on a bar graph
  var
    bXMax = Array.max(a),
    bXScale = d3.scale.linear().domain([0, bXMax]).range([0, bWidth]),
    bYScale = d3.scale.ordinal().domain(d3.range(series.length)).rangeBands([sHeight/8, sHeight - sHeight/8], .8);

  var barLabels = svg.selectAll("g.barLabels")
    .data(series)
    .enter().append("svg:text")
    .attr("transform", function(d, i) { return "translate(" + (sWidth + 3) + "," + (bYScale(i) - 5) + ")"; })
    .text(function(d,i) { return series[i]["seriesName"].replace(/"/g,''); })
    .on("click", function(d,i) { toggleVisible(i); });

  var bars = svg.selectAll("g.bar")
    .data(a)
    .enter().append("svg:g")
    .attr("transform", function(d, i) { return "translate(" + (sWidth + 3) + "," + bYScale(i) + ")"; });

  bars.append("svg:rect")
    .attr("class", function(d,i) {return "rect" + i;})
    .attr("stroke", function(d,i) {return sColors(i);})
    .attr("fill", function(d,i) { return sColors(i); })
    .attr("width",  function(d,i) { return bXScale(d); })
    .attr("height", bYScale.rangeBand());

  bars.append("svg:text")
    .attr("x", bXScale)
    .attr("y", bYScale.rangeBand() / 2)
    .attr("dx", -6)
    .attr("dy", ".35em")
    .attr("fill", "white")
    .attr("text-anchor", "end")
    .text(bXScale.tickFormat(10));

  function toggleVisible(di) {
    var selectedCircles = svg.selectAll(".circle" + di),
      selectedRects = svg.selectAll(".rect" + di),
      newRectFill = "";

    selectedCircles.attr("opacity", function(d,i) {
      var newOpacity;
      d.v = (d.v == true ? false : true);
      if (d.v) {
        newOpacity = .4;
        newRectFill = sColors(d.i);
      } else {
        newOpacity = 0;
        newRectFill = "none";
      }
      return newOpacity;
    });

    selectedRects.attr("fill", newRectFill);
  }

/*

  for (var o in s) {
    plotData(s[o],b,c);
  }
}

function plotSeries(series,config) {
  var b = series.pop(),
    data = [],
    w = 640,
    h = 400,
    p = 30,

    // timeframe bottom and top
    //tfb = b['seriesMin']['x'],
    //tft = b['seriesMax']['x'],

    // wait time bottom and top
    //wtb = b['seriesMin']['yLeft'],
    wtt = b['seriesMax']['yLeft'],
    //wtt = 120,

    // patients waiting bottom and top
    //pwb = b['seriesMin']['yRight'],
    pwt = b['seriesMax']['yRight'],
    //pwt = 12,

    // total patients seen bottom and top

    //xl = c['xLabels']['value'].split(','),
    c = d3.scale.category10(),

    // x axis is the accumulation of total patients seen
    x = d3.scale.linear().domain([0, 100]).range([0, w]),

    // y axis is the wait time
    y = d3.scale.linear().domain([0, wtt]).range([h, 0]),

    // r (radius) is the number of patients waiting
    r = d3.scale.linear().domain([12, (pwt*3)]).range([12, (pwt*3)]),

    // this will display the current time frame
    title = d3.select("body")
      .append("hr")
      .append("h3")
      .text("")
      .attr("align", "center"),

    svg = d3.select("body")
      .append("svg:svg")
      .attr("width", w + p * 4)
      .attr("height", h + p * 2)
      .append("svg:g")
      .attr("transform", "translate(" + p + "," + p + ")");

  var vrules = svg.selectAll("g.vrule")
    .data(x.ticks(20))
    .enter().append("svg:g")
    .attr("class", "vrule");

  vrules.append("svg:line")
    .attr("x1", x)
    .attr("x2", x)
    .attr("y1", 0)
    .attr("y2", h - 1);

  vrules.append("svg:text")
    .attr("x", x)
    .attr("y", h + 3)
    .attr("dy", "1.71em")
    .attr("text-anchor", "start")
    .text(x.tickFormat(10));

  //horizontal lines
  var hlrules = svg.selectAll("g.hlrule")
    .data(y.ticks(20))
    .enter().append("svg:g")
    .attr("class", "hlrule");

  hlrules.append("svg:line")
    .attr("y1", y)
    .attr("y2", y)
    .attr("x1", 0)
    .attr("x2", w + 1);

  hlrules.append("svg:text")
    .attr("y", y)
    .attr("x", -3)
    .attr("dy", ".35em")
    .attr("stroke", "grey")
    .attr("text-anchor", "end")
    .text(y.tickFormat(10));

    // Legend
  for (var l = 0; l < series.length; l++) {
    svg.append("svg:rect")
      .attr("y", l * 12 + 10)
      .attr("x", 12)
      .attr("width", 10)
      .attr("height", 10)
      .attr("fill", c(l))
      .attr("stroke", "none");
    svg.append("svg:text")
      .attr("x", 24)
      .attr("y", l * 12 + 10)
      .attr("dy", ".75em")
      .attr("text-anchor", "start")
      .text(series[l]['seriesName'].replace(/"/g,''));
  }

  var a = series.map(function() {return 0;});

  var t = [];

  series.map(function(e,i){
    e.data.map(function(o){
      a[i] = a[i] + o.yRight_2;
      o.i = i;
      o.a = a[i];
      t.push(o);
    });
  });

  function compare(a,b) {
    if (a.x < b.x)
       return -1;
    if (a.x > b.x)
      return 1;
    return 0;
  }

  data = t.sort(compare);

  //plot the initial set of circles
  var circle = svg.selectAll("circle")
    //.data(data.map(function() {return 0;}))
    .data(data)
    .enter().append("svg:circle")
    .attr("fill", function(d,i) {return c(d.i);})
    .attr("opacity", 0)
    .attr("cx", function(d,i) {return x(d.a);})
    .attr("cy", function(d,i) {return y(d.yLeft_1);})
    .attr("r", function(d,i) {return r(9 + (d.yRight_1 * 3));});

  var i = 0, o = 1;

  function intervalFunction(){
    var p = [i, i + ( series.length * o)];

    circle
      .attr("opacity", function(d,s) {
        var f = .05;
        if ((s >= Array.min(p)) && (s < Array.max(p))) {
          title.text(data[s].xTime);
          f = .80;
        //} else if (((o > 0) && (s < Array.min(p))) || ((o < 0) && (s >= Array.max(p))))  {
        } else if ((s > (series.length * 6)) && (s < Array.min(p))) {
          f = .10;
        } else {
          f = 0;
        }
        return f;
      });

    i = p[1];
    // get max data length here
    if (i >= data.length) { clearInterval(v); }
    if (i <= 0) { clearInterval(v); }
  }

  var v = setInterval(intervalFunction, 120);

  p = d3.select("body")
    .append("p")
    .append("button")
    .text("pause")
    .attr("align", "center");

  var g = true;

  function pauseResume() {
    g = g ? false : true;

    if (g) {
      v = setInterval(intervalFunction, 120);
      p.text("pause");
    } else {
      v = clearInterval(v);
      o = o * (-1);

      if (o == 1) {
        p.text("play");
      }
      else {
        p.text("reverse");
      }

    }

  };

  p.on("click", pauseResume);
*/

/*
  var a = data.map(function() {return 0;}),
    i = 0, o = 1;
*/

}
<commit_msg>sorting the series (hoping) to make the colors consistently set<commit_after>Array.max = function( array ){
    return Math.max.apply( Math, array );
};

Array.min = function( array ){
    return Math.min.apply( Math, array );
};

function plotSeries(series, config) {
  var
    // series boundaries
    bounds = series.pop(),

    // extracting the date for display
    dateParts = config.fromDate.value.split('-').map(Number),
    dateString = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]).toDateString(),

    // padding for the graphics
    padding = 20,

    // bar graph width (will be added to sWidth to determine svg width)
    bWidth = 150,

    // scatterplot dimensions and scale
    sWidth = 650,
    sHeight = 400,

    sXMin = bounds['seriesMin']['x'],
    sXMax = bounds['seriesMax']['x'],

    sYMin = bounds['seriesMin']['yLeft'],
    sYMax = bounds['seriesMax']['yLeft'],

    sRMin = bounds['seriesMin']['yRight'],
    sRMax = bounds['seriesMax']['yRight'],

    sXScale = d3.scale.linear().domain([sXMin, sXMax]).range([0, sWidth]),
    sYScale = d3.scale.linear().domain([sYMin, sYMax]).range([sHeight, 0]),
    sRScale = d3.scale.linear().domain([sRMin, sRMax]).range([sRMin, sRMax]),

    sXLabels = config['xLabels']['value'].split(','),
    sXLScale = d3.scale.ordinal().domain(sXLabels).rangePoints([0, sWidth]),

    sColors = d3.scale.category10(),

    sTitle = d3.select("body")
      .append("h3")
      .text(dateString)
      .attr("align", "center"),

    svg = d3.select("body")
      .append("svg:svg")
      // may append the width of the bar graph too
      .attr("width", sWidth + bWidth + padding * 4)
      .attr("height", sHeight + padding * 2)
      .append("svg:g")
      .attr("transform", "translate(" + padding + "," + padding + ")"),

    vRules = svg.selectAll("g.vrule")
      .data(sXLabels)
      .enter().append("svg:g")
      .attr("class", "rule"),

    hRules = svg.selectAll("g.hrule")
      .data(sYScale.ticks(20))
      .enter().append("svg:g")
      .attr("class", "rule");

  vRules.append("svg:line")
    .attr("x1", sXLScale)
    .attr("x2", sXLScale)
    .attr("y1", 0)
    .attr("y2", sHeight - 1);

  vRules.append("svg:text")
    .attr("x", sXLScale)
    .attr("y", sHeight + 3)
    .attr("dy", "1.71em")
    .attr("text-anchor", "start")
    .text(function(d,i) { return d; });

  hRules.append("svg:line")
    .attr("y1", sYScale)
    .attr("y2", sYScale)
    .attr("x1", 0)
    .attr("x2", sWidth + 1);

  hRules.append("svg:text")
    .attr("y", sYScale)
    .attr("x", -3)
    .attr("dy", ".35em")
    .attr("stroke", "grey")
    .attr("text-anchor", "end")
    .text(sYScale.tickFormat(10));

  // clean up what follows
  series = series.sort(function(p,n) {
    var r = 0;
    if (p.seriesKey < n.seriesKey)
      r = -1;
    if (p.seriesKey > n.seriesKey)
      r = 1;
    return r;
  });

  var a = series.map(function() {return 0;});

  var t = [];

  series.map(function(e,i){
    e.data.map(function(o){
      a[i] = a[i] + o.yRight_2;
      o.i = i;
      o.a = a[i];
      o.v = true;
      if (o.yLeft_1 > 0  && o.yRight_1 > 0) {
        t.push(o);
      }
    });
  });

  var data = t.sort(function(p,n) {
    var r = 0;
    if (p.x < n.x)
       r = -1;
    if (p.x > n.x)
      r = 1;
    return r;
  });

  // plot the initial set of circles
  var circle = svg.selectAll("circle")
    .data(data)
    .enter().append("svg:circle")
    .attr("class", function(d,i) { return "circle" + d.i; })
    .attr("fill", function(d,i) {return sColors(d.i);})
    //.attr("stroke", function(d,i) {return sColors(d.i);})
    .attr("opacity", .4)
    .attr("cx", function(d,i) {return sXScale(d.x);})
    .attr("cy", function(d,i) {return sYScale(d.yLeft_1);})
    .attr("r", function(d,i) {return sRScale(4 + (d.yRight_1 * 2));});

  // bolt on a bar graph
  var
    bXMax = Array.max(a),
    bXScale = d3.scale.linear().domain([0, bXMax]).range([0, bWidth]),
    bYScale = d3.scale.ordinal().domain(d3.range(series.length)).rangeBands([sHeight/8, sHeight - sHeight/8], .8);

  var barLabels = svg.selectAll("g.barLabels")
    .data(series)
    .enter().append("svg:text")
    .attr("transform", function(d, i) { return "translate(" + (sWidth + 3) + "," + (bYScale(i) - 5) + ")"; })
    .text(function(d,i) { return series[i]["seriesName"].replace(/"/g,''); })
    .on("click", function(d,i) { toggleVisible(i); });

  var bars = svg.selectAll("g.bar")
    .data(a)
    .enter().append("svg:g")
    .attr("transform", function(d, i) { return "translate(" + (sWidth + 3) + "," + bYScale(i) + ")"; });

  bars.append("svg:rect")
    .attr("class", function(d,i) {return "rect" + i;})
    .attr("stroke", function(d,i) {return sColors(i);})
    .attr("fill", function(d,i) { return sColors(i); })
    .attr("width",  function(d,i) { return bXScale(d); })
    .attr("height", bYScale.rangeBand());

  bars.append("svg:text")
    .attr("x", bXScale)
    .attr("y", bYScale.rangeBand() / 2)
    .attr("dx", -6)
    .attr("dy", ".35em")
    .attr("fill", "white")
    .attr("text-anchor", "end")
    .text(bXScale.tickFormat(10));

  function toggleVisible(di) {
    var selectedCircles = svg.selectAll(".circle" + di),
      selectedRects = svg.selectAll(".rect" + di),
      newRectFill = "";

    selectedCircles.attr("opacity", function(d,i) {
      var newOpacity;
      d.v = (d.v == true ? false : true);
      if (d.v) {
        newOpacity = .4;
        newRectFill = sColors(d.i);
      } else {
        newOpacity = 0;
        newRectFill = "none";
      }
      return newOpacity;
    });

    selectedRects.attr("fill", newRectFill);
  }

/*

  for (var o in s) {
    plotData(s[o],b,c);
  }
}

function plotSeries(series,config) {
  var b = series.pop(),
    data = [],
    w = 640,
    h = 400,
    p = 30,

    // timeframe bottom and top
    //tfb = b['seriesMin']['x'],
    //tft = b['seriesMax']['x'],

    // wait time bottom and top
    //wtb = b['seriesMin']['yLeft'],
    wtt = b['seriesMax']['yLeft'],
    //wtt = 120,

    // patients waiting bottom and top
    //pwb = b['seriesMin']['yRight'],
    pwt = b['seriesMax']['yRight'],
    //pwt = 12,

    // total patients seen bottom and top

    //xl = c['xLabels']['value'].split(','),
    c = d3.scale.category10(),

    // x axis is the accumulation of total patients seen
    x = d3.scale.linear().domain([0, 100]).range([0, w]),

    // y axis is the wait time
    y = d3.scale.linear().domain([0, wtt]).range([h, 0]),

    // r (radius) is the number of patients waiting
    r = d3.scale.linear().domain([12, (pwt*3)]).range([12, (pwt*3)]),

    // this will display the current time frame
    title = d3.select("body")
      .append("hr")
      .append("h3")
      .text("")
      .attr("align", "center"),

    svg = d3.select("body")
      .append("svg:svg")
      .attr("width", w + p * 4)
      .attr("height", h + p * 2)
      .append("svg:g")
      .attr("transform", "translate(" + p + "," + p + ")");

  var vrules = svg.selectAll("g.vrule")
    .data(x.ticks(20))
    .enter().append("svg:g")
    .attr("class", "vrule");

  vrules.append("svg:line")
    .attr("x1", x)
    .attr("x2", x)
    .attr("y1", 0)
    .attr("y2", h - 1);

  vrules.append("svg:text")
    .attr("x", x)
    .attr("y", h + 3)
    .attr("dy", "1.71em")
    .attr("text-anchor", "start")
    .text(x.tickFormat(10));

  //horizontal lines
  var hlrules = svg.selectAll("g.hlrule")
    .data(y.ticks(20))
    .enter().append("svg:g")
    .attr("class", "hlrule");

  hlrules.append("svg:line")
    .attr("y1", y)
    .attr("y2", y)
    .attr("x1", 0)
    .attr("x2", w + 1);

  hlrules.append("svg:text")
    .attr("y", y)
    .attr("x", -3)
    .attr("dy", ".35em")
    .attr("stroke", "grey")
    .attr("text-anchor", "end")
    .text(y.tickFormat(10));

    // Legend
  for (var l = 0; l < series.length; l++) {
    svg.append("svg:rect")
      .attr("y", l * 12 + 10)
      .attr("x", 12)
      .attr("width", 10)
      .attr("height", 10)
      .attr("fill", c(l))
      .attr("stroke", "none");
    svg.append("svg:text")
      .attr("x", 24)
      .attr("y", l * 12 + 10)
      .attr("dy", ".75em")
      .attr("text-anchor", "start")
      .text(series[l]['seriesName'].replace(/"/g,''));
  }

  var a = series.map(function() {return 0;});

  var t = [];

  series.map(function(e,i){
    e.data.map(function(o){
      a[i] = a[i] + o.yRight_2;
      o.i = i;
      o.a = a[i];
      t.push(o);
    });
  });

  function compare(a,b) {
    if (a.x < b.x)
       return -1;
    if (a.x > b.x)
      return 1;
    return 0;
  }

  data = t.sort(compare);

  //plot the initial set of circles
  var circle = svg.selectAll("circle")
    //.data(data.map(function() {return 0;}))
    .data(data)
    .enter().append("svg:circle")
    .attr("fill", function(d,i) {return c(d.i);})
    .attr("opacity", 0)
    .attr("cx", function(d,i) {return x(d.a);})
    .attr("cy", function(d,i) {return y(d.yLeft_1);})
    .attr("r", function(d,i) {return r(9 + (d.yRight_1 * 3));});

  var i = 0, o = 1;

  function intervalFunction(){
    var p = [i, i + ( series.length * o)];

    circle
      .attr("opacity", function(d,s) {
        var f = .05;
        if ((s >= Array.min(p)) && (s < Array.max(p))) {
          title.text(data[s].xTime);
          f = .80;
        //} else if (((o > 0) && (s < Array.min(p))) || ((o < 0) && (s >= Array.max(p))))  {
        } else if ((s > (series.length * 6)) && (s < Array.min(p))) {
          f = .10;
        } else {
          f = 0;
        }
        return f;
      });

    i = p[1];
    // get max data length here
    if (i >= data.length) { clearInterval(v); }
    if (i <= 0) { clearInterval(v); }
  }

  var v = setInterval(intervalFunction, 120);

  p = d3.select("body")
    .append("p")
    .append("button")
    .text("pause")
    .attr("align", "center");

  var g = true;

  function pauseResume() {
    g = g ? false : true;

    if (g) {
      v = setInterval(intervalFunction, 120);
      p.text("pause");
    } else {
      v = clearInterval(v);
      o = o * (-1);

      if (o == 1) {
        p.text("play");
      }
      else {
        p.text("reverse");
      }

    }

  };

  p.on("click", pauseResume);
*/

/*
  var a = data.map(function() {return 0;}),
    i = 0, o = 1;
*/

}
<|endoftext|>


<commit_before>/* global Blob,URL,requestAnimationFrame */
import React from 'react';
import Color from 'color';
import uuid from 'uuid';
import hterm from '../hterm';
import Component from '../component';
import getColorList from '../utils/colors';
import notify from '../utils/notify';

export default class Term extends Component {

  constructor(props) {
    super(props);
    this.handleWheel = this.handleWheel.bind(this);
    this.handleMouseDown = this.handleMouseDown.bind(this);
    this.handleMouseUp = this.handleMouseUp.bind(this);
    this.handleScrollEnter = this.handleScrollEnter.bind(this);
    this.handleScrollLeave = this.handleScrollLeave.bind(this);
    this.onHyperCaret = this.onHyperCaret.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    props.ref_(this);
  }

  componentDidMount() {
    const {props} = this;
    this.term = props.term || new hterm.Terminal(uuid.v4());
    this.term.onHyperCaret(this.hyperCaret);

    // the first term that's created has unknown size
    // subsequent new tabs have size
    if (props.cols && props.rows) {
      this.term.realizeSize_(props.cols, props.rows);
    }

    const prefs = this.term.getPrefs();

    prefs.set('font-family', props.fontFamily);
    prefs.set('font-size', props.fontSize);
    prefs.set('font-smoothing', props.fontSmoothing);
    prefs.set('cursor-color', this.validateColor(props.cursorColor, 'rgba(255,255,255,0.5)'));
    prefs.set('enable-clipboard-notice', false);
    prefs.set('foreground-color', props.foregroundColor);

    // hterm.ScrollPort.prototype.setBackgroundColor is overriden
    // to make hterm's background transparent. we still need to set
    // background-color for proper text rendering
    prefs.set('background-color', props.backgroundColor);
    prefs.set('color-palette-overrides', getColorList(props.colors));
    prefs.set('user-css', this.getStylesheet(props.customCSS));
    prefs.set('scrollbar-visible', false);
    prefs.set('receive-encoding', 'raw');
    prefs.set('send-encoding', 'raw');
    prefs.set('alt-sends-what', 'browser-key');

    if (props.bell === 'SOUND') {
      prefs.set('audible-bell-sound', this.props.bellSoundURL);
    } else {
      prefs.set('audible-bell-sound', '');
    }

    if (props.copyOnSelect) {
      prefs.set('copy-on-select', true);
    } else {
      prefs.set('copy-on-select', false);
    }

    this.term.onTerminalReady = () => {
      const io = this.term.io.push();
      io.onVTKeystroke = io.sendString = props.onData;
      io.onTerminalResize = (cols, rows) => {
        if (cols !== this.props.cols || rows !== this.props.rows) {
          props.onResize(cols, rows);
        }
      };

      this.term.modifierKeys = props.modifierKeys;
      // this.term.CursorNode_ is available at this point.
      this.term.setCursorShape(props.cursorShape);

      // emit onTitle event when hterm instance
      // wants to set the title of its tab
      this.term.setWindowTitle = props.onTitle;
      this.term.focusHyperCaret();
    };
    this.term.decorate(this.termRef);
    this.term.installKeyboard();
    if (this.props.onTerminal) {
      this.props.onTerminal(this.term);
    }

    const iframeWindow = this.getTermDocument().defaultView;
    iframeWindow.addEventListener('wheel', this.handleWheel);

    this.getScreenNode().addEventListener('mouseup', this.handleMouseUp);
    this.getScreenNode().addEventListener('mousedown', this.handleMouseDown);
  }

  handleWheel(e) {
    if (this.props.onWheel) {
      this.props.onWheel(e);
    }
    const prefs = this.term.getPrefs();
    prefs.set('scrollbar-visible', true);
    clearTimeout(this.scrollbarsHideTimer);
    if (!this.scrollMouseEnter) {
      this.scrollbarsHideTimer = setTimeout(() => {
        prefs.set('scrollbar-visible', false);
      }, 1000);
    }
  }

  handleScrollEnter() {
    clearTimeout(this.scrollbarsHideTimer);
    const prefs = this.term.getPrefs();
    prefs.set('scrollbar-visible', true);
    this.scrollMouseEnter = true;
  }

  handleScrollLeave() {
    const prefs = this.term.getPrefs();
    prefs.set('scrollbar-visible', false);
    this.scrollMouseEnter = false;
  }

  handleMouseUp() {
    this.props.onActive();
    // this makes sure that we focus the hyper caret only
    // if a click on the term does not result in a selection
    // otherwise, if we focus without such check, it'd be
    // impossible to select a piece of text
    if (this.term.document_.getSelection().type !== 'Range') {
      this.term.focusHyperCaret();
    }
  }
  handleFocus() {
    // This will in turn result in `this.focus()` being
    // called, which is unecessary.
    // Should investigate if it matters.
    this.props.onActive();
  }

  handleKeyDown(e) {
    if (e.ctrlKey && e.key === 'c') {
      this.props.onURLAbort();
    }
  }

  onHyperCaret(caret) {
    this.hyperCaret = caret;
  }

  write(data) {
    // sometimes the preference set above for
    // `receive-encoding` is not known by the vt
    // before we type to write (since the preference
    // manager is asynchronous), so we force it to
    // avoid buffering
    // this fixes a race condition where sometimes
    // opening new sessions results in broken
    // output due to the term attempting to decode
    // as `utf-8` instead of `raw`
    if (this.term.vt.characterEncoding !== 'raw') {
      this.term.vt.characterEncoding = 'raw';
    }

    this.term.io.writeUTF8(data);
  }

  focus() {
    this.term.focusHyperCaret();
  }

  clear() {
    this.term.clearPreserveCursorRow();

    // If cursor is still not at the top, a command is probably
    // running and we'd like to delete the whole screen.
    // Move cursor to top
    if (this.term.getCursorRow() !== 0) {
      this.write('\x1B[0;0H\x1B[2J');
    }
  }

  moveWordLeft() {
    this.term.onVTKeystroke('\x1bb');
  }

  moveWordRight() {
    this.term.onVTKeystroke('\x1bf');
  }

  deleteWordLeft() {
    this.term.onVTKeystroke('\x1b\x7f');
  }

  deleteWordRight() {
    this.term.onVTKeystroke('\x1bd');
  }

  deleteLine() {
    this.term.onVTKeystroke('\x1bw');
  }

  moveToStart() {
    this.term.onVTKeystroke('\x01');
  }

  moveToEnd() {
    this.term.onVTKeystroke('\x05');
  }

  selectAll() {
    this.term.selectAll();
  }

  getScreenNode() {
    return this.term.scrollPort_.getScreenNode();
  }

  getTermDocument() {
    return this.term.document_;
  }

  getStylesheet(css) {
    const hyperCaret = `
      .hyper-caret {
        outline: none;
        display: inline-block;
        color: transparent;
        text-shadow: 0 0 0 black;
        font-family: ${this.props.fontFamily};
        font-size: ${this.props.fontSize}px;
      }
    `;
    const scrollBarCss = `
      ::-webkit-scrollbar {
        width: 5px;
      }
      ::-webkit-scrollbar-thumb {
        -webkit-border-radius: 10px;
        border-radius: 10px;
        background: ${this.props.borderColor};
      }
      ::-webkit-scrollbar-thumb:window-inactive {
        background: ${this.props.borderColor};
      }
    `;
    return URL.createObjectURL(new Blob([`
      .cursor-node[focus="false"] {
         border-width: 1px !important;
      }
      x-row {
        line-height: 1.2em;
      }
      ${hyperCaret}
      ${scrollBarCss}
      ${css}
    `], {type: 'text/css'}));
  }

  validateColor(color, alternative = 'rgb(255,255,255)') {
    try {
      return Color(color).rgbString();
    } catch (err) {
      notify(`color "${color}" is invalid`);
    }
    return alternative;
  }

  handleMouseDown(ev) {
    // we prevent losing focus when clicking the boundary
    // wrappers of the main terminal element
    if (ev.target === this.termWrapperRef ||
        ev.target === this.termRef) {
      ev.preventDefault();
    }
    if (this.props.quickEdit) {
      this.term.onMouseDown_(ev);
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.url !== nextProps.url) {
      // when the url prop changes, we make sure
      // the terminal starts or stops ignoring
      // key input so that it doesn't conflict
      // with the <webview>
      if (nextProps.url) {
        this.term.io.push();
        window.addEventListener('keydown', this.handleKeyDown);
      } else {
        window.removeEventListener('keydown', this.handleKeyDown);
        this.term.io.pop();
      }
    }

    if (!this.props.cleared && nextProps.cleared) {
      this.clear();
    }

    const prefs = this.term.getPrefs();

    if (this.props.fontSize !== nextProps.fontSize) {
      prefs.set('font-size', nextProps.fontSize);
      this.hyperCaret.style.fontSize = nextProps.fontSize + 'px';
    }

    if (this.props.foregroundColor !== nextProps.foregroundColor) {
      prefs.set('foreground-color', nextProps.foregroundColor);
    }

    if (this.props.fontFamily !== nextProps.fontFamily) {
      prefs.set('font-family', nextProps.fontFamily);
      this.hyperCaret.style.fontFamily = nextProps.fontFamily;
    }

    if (this.props.fontSmoothing !== nextProps.fontSmoothing) {
      prefs.set('font-smoothing', nextProps.fontSmoothing);
    }

    if (this.props.cursorColor !== nextProps.cursorColor) {
      prefs.set('cursor-color', this.validateColor(nextProps.cursorColor, 'rgba(255,255,255,0.5)'));
    }

    if (this.props.cursorShape !== nextProps.cursorShape) {
      this.term.setCursorShape(nextProps.cursorShape);
    }

    if (this.props.colors !== nextProps.colors) {
      prefs.set('color-palette-overrides', getColorList(nextProps.colors));
    }

    if (this.props.customCSS !== nextProps.customCSS) {
      prefs.set('user-css', this.getStylesheet(nextProps.customCSS));
    }

    if (this.props.bell === 'SOUND') {
      prefs.set('audible-bell-sound', this.props.bellSoundURL);
    } else {
      prefs.set('audible-bell-sound', '');
    }

    if (this.props.copyOnSelect) {
      prefs.set('copy-on-select', true);
    } else {
      prefs.set('copy-on-select', false);
    }
  }

  componentWillUnmount() {
    clearTimeout(this.scrollbarsHideTimer);
    this.props.ref_(null);
  }

  template(css) {
    return (<div
      ref={component => {
        this.termWrapperRef = component;
      }}
      className={css('fit', this.props.isTermActive && 'active')}
      onMouseDown={this.handleMouseDown}
      style={{padding: this.props.padding}}
      >
      { this.props.customChildrenBefore }
      <div
        ref={component => {
          this.termRef = component;
        }}
        className={css('fit', 'term')}
        />
      { this.props.url ?
        <webview
          key="hyper-webview"
          src={this.props.url}
          onFocus={this.handleFocus}
          style={{
            background: '#fff',
            position: 'absolute',
            top: 0,
            left: 0,
            display: 'inline-flex',
            width: '100%',
            height: '100%'
          }}
          /> :
        <div // eslint-disable-line react/jsx-indent
          key="scrollbar"
          className={css('scrollbarShim')}
          onMouseEnter={this.handleScrollEnter}
          onMouseLeave={this.handleScrollLeave}
          />
      }
      <div key="hyper-caret" contentEditable className="hyper-caret" ref={this.onHyperCaret}/>
      { this.props.customChildren }
    </div>);
  }

  styles() {
    return {
      fit: {
        display: 'block',
        width: '100%',
        height: '100%'
      },

      term: {
        position: 'relative'
      },

      scrollbarShim: {
        position: 'fixed',
        right: 0,
        width: '50px',
        top: 0,
        bottom: 0,
        pointerEvents: 'none'
      }
    };
  }
}
<commit_msg>set select color based on caret color (#1532)<commit_after>/* global Blob,URL,requestAnimationFrame */
import React from 'react';
import Color from 'color';
import uuid from 'uuid';
import hterm from '../hterm';
import Component from '../component';
import getColorList from '../utils/colors';
import notify from '../utils/notify';

export default class Term extends Component {

  constructor(props) {
    super(props);
    this.handleWheel = this.handleWheel.bind(this);
    this.handleMouseDown = this.handleMouseDown.bind(this);
    this.handleMouseUp = this.handleMouseUp.bind(this);
    this.handleScrollEnter = this.handleScrollEnter.bind(this);
    this.handleScrollLeave = this.handleScrollLeave.bind(this);
    this.onHyperCaret = this.onHyperCaret.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    props.ref_(this);
  }

  componentDidMount() {
    const {props} = this;
    this.term = props.term || new hterm.Terminal(uuid.v4());
    this.term.onHyperCaret(this.hyperCaret);

    // the first term that's created has unknown size
    // subsequent new tabs have size
    if (props.cols && props.rows) {
      this.term.realizeSize_(props.cols, props.rows);
    }

    const prefs = this.term.getPrefs();

    prefs.set('font-family', props.fontFamily);
    prefs.set('font-size', props.fontSize);
    prefs.set('font-smoothing', props.fontSmoothing);
    prefs.set('cursor-color', this.validateColor(props.cursorColor, 'rgba(255,255,255,0.5)'));
    prefs.set('enable-clipboard-notice', false);
    prefs.set('foreground-color', props.foregroundColor);

    // hterm.ScrollPort.prototype.setBackgroundColor is overriden
    // to make hterm's background transparent. we still need to set
    // background-color for proper text rendering
    prefs.set('background-color', props.backgroundColor);
    prefs.set('color-palette-overrides', getColorList(props.colors));
    prefs.set('user-css', this.getStylesheet(props.customCSS));
    prefs.set('scrollbar-visible', false);
    prefs.set('receive-encoding', 'raw');
    prefs.set('send-encoding', 'raw');
    prefs.set('alt-sends-what', 'browser-key');

    if (props.bell === 'SOUND') {
      prefs.set('audible-bell-sound', this.props.bellSoundURL);
    } else {
      prefs.set('audible-bell-sound', '');
    }

    if (props.copyOnSelect) {
      prefs.set('copy-on-select', true);
    } else {
      prefs.set('copy-on-select', false);
    }

    this.term.onTerminalReady = () => {
      const io = this.term.io.push();
      io.onVTKeystroke = io.sendString = props.onData;
      io.onTerminalResize = (cols, rows) => {
        if (cols !== this.props.cols || rows !== this.props.rows) {
          props.onResize(cols, rows);
        }
      };

      this.term.modifierKeys = props.modifierKeys;
      // this.term.CursorNode_ is available at this point.
      this.term.setCursorShape(props.cursorShape);

      // emit onTitle event when hterm instance
      // wants to set the title of its tab
      this.term.setWindowTitle = props.onTitle;
      this.term.focusHyperCaret();
    };
    this.term.decorate(this.termRef);
    this.term.installKeyboard();
    if (this.props.onTerminal) {
      this.props.onTerminal(this.term);
    }

    const iframeWindow = this.getTermDocument().defaultView;
    iframeWindow.addEventListener('wheel', this.handleWheel);

    this.getScreenNode().addEventListener('mouseup', this.handleMouseUp);
    this.getScreenNode().addEventListener('mousedown', this.handleMouseDown);
  }

  handleWheel(e) {
    if (this.props.onWheel) {
      this.props.onWheel(e);
    }
    const prefs = this.term.getPrefs();
    prefs.set('scrollbar-visible', true);
    clearTimeout(this.scrollbarsHideTimer);
    if (!this.scrollMouseEnter) {
      this.scrollbarsHideTimer = setTimeout(() => {
        prefs.set('scrollbar-visible', false);
      }, 1000);
    }
  }

  handleScrollEnter() {
    clearTimeout(this.scrollbarsHideTimer);
    const prefs = this.term.getPrefs();
    prefs.set('scrollbar-visible', true);
    this.scrollMouseEnter = true;
  }

  handleScrollLeave() {
    const prefs = this.term.getPrefs();
    prefs.set('scrollbar-visible', false);
    this.scrollMouseEnter = false;
  }

  handleMouseUp() {
    this.props.onActive();
    // this makes sure that we focus the hyper caret only
    // if a click on the term does not result in a selection
    // otherwise, if we focus without such check, it'd be
    // impossible to select a piece of text
    if (this.term.document_.getSelection().type !== 'Range') {
      this.term.focusHyperCaret();
    }
  }
  handleFocus() {
    // This will in turn result in `this.focus()` being
    // called, which is unecessary.
    // Should investigate if it matters.
    this.props.onActive();
  }

  handleKeyDown(e) {
    if (e.ctrlKey && e.key === 'c') {
      this.props.onURLAbort();
    }
  }

  onHyperCaret(caret) {
    this.hyperCaret = caret;
  }

  write(data) {
    // sometimes the preference set above for
    // `receive-encoding` is not known by the vt
    // before we type to write (since the preference
    // manager is asynchronous), so we force it to
    // avoid buffering
    // this fixes a race condition where sometimes
    // opening new sessions results in broken
    // output due to the term attempting to decode
    // as `utf-8` instead of `raw`
    if (this.term.vt.characterEncoding !== 'raw') {
      this.term.vt.characterEncoding = 'raw';
    }

    this.term.io.writeUTF8(data);
  }

  focus() {
    this.term.focusHyperCaret();
  }

  clear() {
    this.term.clearPreserveCursorRow();

    // If cursor is still not at the top, a command is probably
    // running and we'd like to delete the whole screen.
    // Move cursor to top
    if (this.term.getCursorRow() !== 0) {
      this.write('\x1B[0;0H\x1B[2J');
    }
  }

  moveWordLeft() {
    this.term.onVTKeystroke('\x1bb');
  }

  moveWordRight() {
    this.term.onVTKeystroke('\x1bf');
  }

  deleteWordLeft() {
    this.term.onVTKeystroke('\x1b\x7f');
  }

  deleteWordRight() {
    this.term.onVTKeystroke('\x1bd');
  }

  deleteLine() {
    this.term.onVTKeystroke('\x1bw');
  }

  moveToStart() {
    this.term.onVTKeystroke('\x01');
  }

  moveToEnd() {
    this.term.onVTKeystroke('\x05');
  }

  selectAll() {
    this.term.selectAll();
  }

  getScreenNode() {
    return this.term.scrollPort_.getScreenNode();
  }

  getTermDocument() {
    return this.term.document_;
  }

  getStylesheet(css) {
    const hyperCaret = `
      .hyper-caret {
        outline: none;
        display: inline-block;
        color: transparent;
        text-shadow: 0 0 0 black;
        font-family: ${this.props.fontFamily};
        font-size: ${this.props.fontSize}px;
      }
    `;
    const scrollBarCss = `
      ::-webkit-scrollbar {
        width: 5px;
      }
      ::-webkit-scrollbar-thumb {
        -webkit-border-radius: 10px;
        border-radius: 10px;
        background: ${this.props.borderColor};
      }
      ::-webkit-scrollbar-thumb:window-inactive {
        background: ${this.props.borderColor};
      }
    `;
    const selectCss = `
      ::selection {
        background: ${Color(this.props.cursorColor).alpha(0.4).rgbString()};
      }
    `;
    return URL.createObjectURL(new Blob([`
      .cursor-node[focus="false"] {
         border-width: 1px !important;
      }
      x-row {
        line-height: 1.2em;
      }
      ${hyperCaret}
      ${scrollBarCss}
      ${selectCss}
      ${css}
    `], {type: 'text/css'}));
  }

  validateColor(color, alternative = 'rgb(255,255,255)') {
    try {
      return Color(color).rgbString();
    } catch (err) {
      notify(`color "${color}" is invalid`);
    }
    return alternative;
  }

  handleMouseDown(ev) {
    // we prevent losing focus when clicking the boundary
    // wrappers of the main terminal element
    if (ev.target === this.termWrapperRef ||
        ev.target === this.termRef) {
      ev.preventDefault();
    }
    if (this.props.quickEdit) {
      this.term.onMouseDown_(ev);
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.url !== nextProps.url) {
      // when the url prop changes, we make sure
      // the terminal starts or stops ignoring
      // key input so that it doesn't conflict
      // with the <webview>
      if (nextProps.url) {
        this.term.io.push();
        window.addEventListener('keydown', this.handleKeyDown);
      } else {
        window.removeEventListener('keydown', this.handleKeyDown);
        this.term.io.pop();
      }
    }

    if (!this.props.cleared && nextProps.cleared) {
      this.clear();
    }

    const prefs = this.term.getPrefs();

    if (this.props.fontSize !== nextProps.fontSize) {
      prefs.set('font-size', nextProps.fontSize);
      this.hyperCaret.style.fontSize = nextProps.fontSize + 'px';
    }

    if (this.props.foregroundColor !== nextProps.foregroundColor) {
      prefs.set('foreground-color', nextProps.foregroundColor);
    }

    if (this.props.fontFamily !== nextProps.fontFamily) {
      prefs.set('font-family', nextProps.fontFamily);
      this.hyperCaret.style.fontFamily = nextProps.fontFamily;
    }

    if (this.props.fontSmoothing !== nextProps.fontSmoothing) {
      prefs.set('font-smoothing', nextProps.fontSmoothing);
    }

    if (this.props.cursorColor !== nextProps.cursorColor) {
      prefs.set('cursor-color', this.validateColor(nextProps.cursorColor, 'rgba(255,255,255,0.5)'));
    }

    if (this.props.cursorShape !== nextProps.cursorShape) {
      this.term.setCursorShape(nextProps.cursorShape);
    }

    if (this.props.colors !== nextProps.colors) {
      prefs.set('color-palette-overrides', getColorList(nextProps.colors));
    }

    if (this.props.customCSS !== nextProps.customCSS) {
      prefs.set('user-css', this.getStylesheet(nextProps.customCSS));
    }

    if (this.props.bell === 'SOUND') {
      prefs.set('audible-bell-sound', this.props.bellSoundURL);
    } else {
      prefs.set('audible-bell-sound', '');
    }

    if (this.props.copyOnSelect) {
      prefs.set('copy-on-select', true);
    } else {
      prefs.set('copy-on-select', false);
    }
  }

  componentWillUnmount() {
    clearTimeout(this.scrollbarsHideTimer);
    this.props.ref_(null);
  }

  template(css) {
    return (<div
      ref={component => {
        this.termWrapperRef = component;
      }}
      className={css('fit', this.props.isTermActive && 'active')}
      onMouseDown={this.handleMouseDown}
      style={{padding: this.props.padding}}
      >
      { this.props.customChildrenBefore }
      <div
        ref={component => {
          this.termRef = component;
        }}
        className={css('fit', 'term')}
        />
      { this.props.url ?
        <webview
          key="hyper-webview"
          src={this.props.url}
          onFocus={this.handleFocus}
          style={{
            background: '#fff',
            position: 'absolute',
            top: 0,
            left: 0,
            display: 'inline-flex',
            width: '100%',
            height: '100%'
          }}
          /> :
        <div // eslint-disable-line react/jsx-indent
          key="scrollbar"
          className={css('scrollbarShim')}
          onMouseEnter={this.handleScrollEnter}
          onMouseLeave={this.handleScrollLeave}
          />
      }
      <div key="hyper-caret" contentEditable className="hyper-caret" ref={this.onHyperCaret}/>
      { this.props.customChildren }
    </div>);
  }

  styles() {
    return {
      fit: {
        display: 'block',
        width: '100%',
        height: '100%'
      },

      term: {
        position: 'relative'
      },

      scrollbarShim: {
        position: 'fixed',
        right: 0,
        width: '50px',
        top: 0,
        bottom: 0,
        pointerEvents: 'none'
      }
    };
  }
}
<|endoftext|>


<commit_before>/*global angular:true */
/*jshint bitwise:true, browser:true, camelcase:true, curly:true, devel:false, eqeqeq:false, forin:true, immed:true, indent:4, newcap:true, noarg:true, noempty:true, nonew:true, quotmark:true, regexp:false, strict:true, trailing:true, undef:true, unused:true */
(function () {
    'use strict';

    // Controller
    angular.module('hiitController', [])
        .controller('hiitEditorCtrl', function ($scope, $http, $window, localStorageService) {
        $scope.modeWorkout = false;

        $scope.showSets = function () {
            //console.log('showSets');
            $scope.modeWorkout = false;
            $scope.displayedSets = $scope.hiit.sets;
            $scope.currentSet = null;
        };

        $scope.showWorkouts = function () {
            //console.log('showWorkouts');
            $scope.modeWorkout = true;
            $scope.displayedSets = []
            $scope.currentWorkout = $scope.hiit.workouts[0];
            $scope.currentSet = null;
        };

        $scope.exportHiit = function () {
            //console.log($scope.hiit);
            $http.post('/export-db', $scope.hiit).success(function (data) {
                $window.location.href = data.location;
            });
        };

        $scope.workoutDuration = function (workout, returnSec) {
            var duration = 0;

            for (var i = 0; i < workout.sets.length; i++) {
                  duration += $scope.setDuration(workout.sets[i], true);
            }

            return returnSec ? duration : sec2minsec(duration);
        };

        $scope.setDuration = function (set, returnSec) {
            var reps = set.repetitions;
            var roundDuration = 0;
            for (var i = 0; i < set.actions.length; i++) {
                var t = set.actions[i].time;
                t = t ? parseInt(t, 10) : 0;
                roundDuration += t;
            }

            //console.log('Duration "' + set.name + '":' + roundDuration + '*' + reps + '=' + (roundDuration * reps) + 'sec.');

            return returnSec ? roundDuration * reps : sec2minsec(roundDuration * reps);
        };

        // Converts and display time from seconds to mm:ss
        var sec2minsec = function (secs) {

            if (!secs) {
                return '';
            }

            var minutes = Math.floor(secs / 60);
            var seconds = secs - (minutes * 60);

            // Zero pad
            minutes = ('00' + minutes).substr(-2, 2);
            seconds = ('00' + seconds).substr(-2, 2);

            return minutes + ':' + seconds;
        };

        $scope.addSet = function () {
            //console.log('Add new set');
            var i = $scope.displayedSets.push({
                name: '',
                repetitions: 1,
                actions: []
            });
            $scope.showSet($scope.displayedSets[i - 1], -1);
        };

        $scope.loadHiit = function () {
            //console.log('Loading data to localStorage...');
            if (localStorageService.isSupported) {
                $scope.hiit = localStorageService.get('hiit');
            }
        };

        $scope.saveHiit = function () {
            //console.log('Saving data to localStorage...');
            if (localStorageService.isSupported) {
                localStorageService.set('hiit', $scope.hiit);
            }
        };

        $scope.showWorkout = function (workout, index) {
            //console.log(workout, index);

            $scope.currentWorkout = workout;
            $scope.currentWorkout.index = index;
            $scope.displayedSets = workout.sets;

            $('#set-editor').slideDown();
        };

        $scope.deleteSet = function (index) {
            //console.log('Delete set "' + $scope.displayedSets[index] + '"');
            $scope.displayedSets.splice(index, 1);
            $scope.currentSet = $scope.displayedSets[0];
        };

        $scope.showSet = function (set, index) {
            //console.log(set, index);

            //var currentSet = {};
            //angular.copy(set, currentSet);
            //$scope.currentSet = currentSet;

            $scope.currentSet = set;
            $scope.currentSet.index = index;

            $('#set-editor').slideDown();
        };

        $scope.addAction = function () {
            //console.log('Add action to set "' + $scope.currentSet.name + '"');
            $scope.currentSet.actions.push({});
        };

        $scope.deleteAction = function (action, index) {
            //console.log('Delete action "' + action.name + '" (#' + index + ')');
            $scope.currentSet.actions.splice(index, 1);
        };

        if (localStorageService.isSupported) {
            $scope.loadHiit();
            //$scope.unbindHiit = localStorageService.bind($scope, 'hiit');
        }

        // If no data, load a default set
        if (!$scope.hiit) {
            $http.get('/hiit_data.js').success(function (data) {
                $scope.hiit = data;
            });
        }

        $scope.showSets();

    });

    // App
    angular.module('hiitTimerApp', ['hiitController', 'htmlSortable', 'colorpicker.module', 'ui.bootstrap', 'LocalStorageModule']);

    // done!
})();

<commit_msg>Fix loading error on first use<commit_after>/*global angular:true */
/*jshint bitwise:true, browser:true, camelcase:true, curly:true, devel:false, eqeqeq:false, forin:true, immed:true, indent:4, newcap:true, noarg:true, noempty:true, nonew:true, quotmark:true, regexp:false, strict:true, trailing:true, undef:true, unused:true */
(function () {
    'use strict';

    // Controller
    angular.module('hiitController', [])
        .controller('hiitEditorCtrl', function ($scope, $http, $window, localStorageService) {
        $scope.modeWorkout = false;

        $scope.showSets = function () {
            //console.log('showSets');
            $scope.modeWorkout = false;
            if ($scope.hiit) {
              $scope.displayedSets = $scope.hiit.sets;
            }
            $scope.currentSet = null;
        };

        $scope.showWorkouts = function () {
            //console.log('showWorkouts');
            $scope.modeWorkout = true;
            $scope.displayedSets = []
            if ($scope.hiit) {
              $scope.currentWorkout = $scope.hiit.workouts[0];
            }
            $scope.currentSet = null;
        };

        $scope.exportHiit = function () {
            //console.log($scope.hiit);
            $http.post('/export-db', $scope.hiit).success(function (data) {
                $window.location.href = data.location;
            });
        };

        $scope.workoutDuration = function (workout, returnSec) {
            var duration = 0;

            for (var i = 0; i < workout.sets.length; i++) {
                  duration += $scope.setDuration(workout.sets[i], true);
            }

            return returnSec ? duration : sec2minsec(duration);
        };

        $scope.setDuration = function (set, returnSec) {
            var reps = set.repetitions;
            var roundDuration = 0;
            for (var i = 0; i < set.actions.length; i++) {
                var t = set.actions[i].time;
                t = t ? parseInt(t, 10) : 0;
                roundDuration += t;
            }

            //console.log('Duration "' + set.name + '":' + roundDuration + '*' + reps + '=' + (roundDuration * reps) + 'sec.');

            return returnSec ? roundDuration * reps : sec2minsec(roundDuration * reps);
        };

        // Converts and display time from seconds to mm:ss
        var sec2minsec = function (secs) {

            if (!secs) {
                return '';
            }

            var minutes = Math.floor(secs / 60);
            var seconds = secs - (minutes * 60);

            // Zero pad
            minutes = ('00' + minutes).substr(-2, 2);
            seconds = ('00' + seconds).substr(-2, 2);

            return minutes + ':' + seconds;
        };

        $scope.addSet = function () {
            //console.log('Add new set');
            var i = $scope.displayedSets.push({
                name: '',
                repetitions: 1,
                actions: []
            });
            $scope.showSet($scope.displayedSets[i - 1], -1);
        };

        $scope.loadHiit = function () {
            //console.log('Loading data to localStorage...');
            if (localStorageService.isSupported) {
                $scope.hiit = localStorageService.get('hiit');
            }
        };

        $scope.saveHiit = function () {
            //console.log('Saving data to localStorage...');
            if (localStorageService.isSupported) {
                localStorageService.set('hiit', $scope.hiit);
            }
        };

        $scope.showWorkout = function (workout, index) {
            //console.log(workout, index);

            $scope.currentWorkout = workout;
            $scope.currentWorkout.index = index;
            $scope.displayedSets = workout.sets;

            $('#set-editor').slideDown();
        };

        $scope.deleteSet = function (index) {
            //console.log('Delete set "' + $scope.displayedSets[index] + '"');
            $scope.displayedSets.splice(index, 1);
            $scope.currentSet = $scope.displayedSets[0];
        };

        $scope.showSet = function (set, index) {
            //console.log(set, index);

            //var currentSet = {};
            //angular.copy(set, currentSet);
            //$scope.currentSet = currentSet;

            $scope.currentSet = set;
            $scope.currentSet.index = index;

            $('#set-editor').slideDown();
        };

        $scope.addAction = function () {
            //console.log('Add action to set "' + $scope.currentSet.name + '"');
            $scope.currentSet.actions.push({});
        };

        $scope.deleteAction = function (action, index) {
            //console.log('Delete action "' + action.name + '" (#' + index + ')');
            $scope.currentSet.actions.splice(index, 1);
        };

        if (localStorageService.isSupported) {
            $scope.loadHiit();
            //$scope.unbindHiit = localStorageService.bind($scope, 'hiit');
        }

        // If no data, load a default set
        if (!$scope.hiit) {
            $http.get('/hiit_data.js').success(function (data) {
                $scope.hiit = data;
            });
        }

        $scope.showSets();

    });

    // App
    angular.module('hiitTimerApp', ['hiitController', 'htmlSortable', 'colorpicker.module', 'ui.bootstrap', 'LocalStorageModule']);

    // done!
})();

<|endoftext|>


<commit_before>const
util = require('util'),
path = require('path'),
child_process = require('child_process'),
events = require('events');

// decaying factor for heurstics calculating how much work costs.
const MAX_HISTORY = 100;

function ComputeCluster(options) {
  if (!options || typeof options.module !== 'string') {
    throw "missing required 'module' argument";
  }
  // is module a file?
  if (!path.existsSync(options.module)) {
    throw "module doesn't exist: " + options.module;
  }
  if (options.max_processes &&
      (typeof options.max_processes !== 'number' || options.max_processes < 1)) {
    throw "when provided, max_processes must be an integer greater than one";
  }
  if (options.max_backlog && typeof options.max_backlog != 'number') {
    throw "when provided, max_backlog must be a number";
  }
  if (options.max_request_time && typeof options.max_request_time != 'number') {
    throw "when provided, max_request_time must be a number";
  }

  events.EventEmitter.call(this);

  // an array of child processes
  this._kids = {};
  this._MAX_KIDS = (options.max_processes || Math.ceil(require('os').cpus().length * 1.25));
  this._work_q = [];
  this._exiting = false;
  this._exit_cb;
  this._module = options.module;
  // how long shall we allow our queue to get before we stop accepting work?
  // (negative implies no limit.  careful, there.)
  this._MAX_BACKLOG = options.max_backlog || this._MAX_KIDS * 10;
  this._MAX_REQUEST_TIME = options.max_request_time || 0;
  this._work_duration = 0;
  this._jobs_run = 0;
};

util.inherits(ComputeCluster, events.EventEmitter);

ComputeCluster.prototype._onWorkerExit = function(pid) {
  var self = this;
  return function (code) {
    // inform the callback the process quit
    var worker = self._kids[pid];
    if (worker && worker.job && worker.job.cb) {
      worker.job.cb("compute process (" + pid + ") dies with code: " + code);
    }
    // if _exiting is false, we don't expect to be shutting down!
    if (!self._exiting) {
      self.emit('error',
                "compute process (" + pid + ") dies with code: " + code);
    }

    self.emit('info', "compute process (" + pid + ") exits with code " + code);

    delete self._kids[pid];
    if (self._exit_cb) {
      if (Object.keys(self._kids).length === 0) {
        self._exit_cb(null);
        _exit_cb = undefined;
      }
    }
  }
};

ComputeCluster.prototype._getEnvForWorker = function() {
  var env = {};
  for (var i in process.env) {
    env[i] = process.env[i];
  }

  delete env.NODE_WORKER_ID; //Node.js cluster worker marker for v0.6
  delete env.NODE_UNIQUE_ID; //Node.js cluster worker marker for v0.7

  return env;
};

ComputeCluster.prototype._getFreeWorker = function() {
  var self = this;

  for (var i in this._kids) {
    if (!this._kids[i].job) return this._kids[i];
  }

  // no workers!  can we spawn one?
  if (Object.keys(this._kids).length < this._MAX_KIDS) {
    var k = {
      worker: child_process.fork(
        this._module,
        [],
        { env: this._getEnvForWorker() }
      ) };
    k.worker.on('exit', this._onWorkerExit(k.worker.pid));
    this._kids[k.worker.pid] = k;

    this.emit('info', "spawned new worker process (" +  k.worker.pid + ") " +
              Object.keys(this._kids).length + "/" + this._MAX_KIDS + " processes running");

    return k;
  }
};

ComputeCluster.prototype._runWorkOnWorker = function(work, worker) {
  var self = this;
  this.emit("debug", "passing compute job to process " + worker.worker.pid);
  var startTime = new Date();
  worker.worker.once('message', function(m) {
    // clear the in-progress job
    var cb = worker.job.cb;
    delete worker.job;

    // start the next
    self._assignWork();

    // call our client's callback
    if (cb) cb(null, m);
    // emit some debug info
    var timeMS = (new Date() - startTime);
    self.emit("debug", "process " + worker.worker.pid + " completed work in " +
              (timeMS / 1000.0).toFixed(2) + "s");

    // if there is a maximum request time, perform some math to estimate how
    // long requests take, favoring history to current job in proportion:
    // MAX_HISTORY:1
    if (self._MAX_REQUEST_TIME && self._jobs_run >= (2 * self._MAX_KIDS)) {
      var history = (self._jobs_run > MAX_HISTORY) ? MAX_HISTORY : self._jobs_run;
      self._work_duration = ((self._work_duration * history) + timeMS) / (history + 1);
    }

    self._jobs_run++;
  });
  worker.worker.send(work.job);
  worker.job = work;
};

  // assign as many work units from work_q as possible to avialable
  // compute processes
ComputeCluster.prototype._assignWork = function() {
  while (this._work_q.length > 0) {
    var worker = this._getFreeWorker();
    if (!worker) break;

    this._runWorkOnWorker(this._work_q.shift(), worker);
  }
};

ComputeCluster.prototype.enqueue = function(args, cb) {
  // maximum allowed request time check
  if (this._MAX_REQUEST_TIME && this._jobs_run > (2 * this._MAX_KIDS)) {
    var numWorkers = Object.keys(this._kids).length * 1.0;
    if (numWorkers) {
      // how long would this work take?
      var expected = ((this._work_q.length / numWorkers) * this._work_duration + this._work_duration) / 1000.0;
      if (expected > this._MAX_REQUEST_TIME) {
        this.emit('info', "maximum expected work duration hit hit (work would take about " + expected +
                  "s, which is greater than "+ this._MAX_REQUEST_TIME +")!  cannot enqueue!");
        process.nextTick(function() {
          cb("cannot enqueue work: maximum expected work duration exceeded (" + expected + "s)");
        });
        return this;
      }
    }
  }

  // backlog size check
  if (this._MAX_BACKLOG > 0 && this._work_q.length >= this._MAX_BACKLOG) {
    this.emit('info', "maximum work backlog hit (" + this._MAX_BACKLOG +
              ")!  cannot enqueue additional work!");
    var mb = this._MAX_BACKLOG;
    process.nextTick(function() {
      cb("cannot enqueue work: maximum backlog exceeded (" + mb + ")");
    });
    return this;
  }

  this._work_q.push({ job: args, cb: cb });
  this._assignWork();
  return this;
};

ComputeCluster.prototype.exit = function(cb) {
  if (Object.keys(this._kids).length === 0) {
    if (cb) setTimeout(function() { cb(null); }, 0);
  } else {
    this._exiting = true;
    this._exit_cb = cb;
    this.emit('info', "exit called, shutting down " + Object.keys(this._kids).length +
              " child processes");
    for (var i in this._kids) {
      this._kids[i].worker.kill();
    }
  }
  return this;
};

module.exports = ComputeCluster;

<commit_msg>fixed existsSync warning<commit_after>const
util = require('util'),
existsSync = require('fs').existsSync || require('path').existsSync,
child_process = require('child_process'),
events = require('events');

// decaying factor for heurstics calculating how much work costs.
const MAX_HISTORY = 100;

function ComputeCluster(options) {
  if (!options || typeof options.module !== 'string') {
    throw "missing required 'module' argument";
  }
  // is module a file?
  if (!existsSync(options.module)) {
    throw "module doesn't exist: " + options.module;
  }
  if (options.max_processes &&
      (typeof options.max_processes !== 'number' || options.max_processes < 1)) {
    throw "when provided, max_processes must be an integer greater than one";
  }
  if (options.max_backlog && typeof options.max_backlog != 'number') {
    throw "when provided, max_backlog must be a number";
  }
  if (options.max_request_time && typeof options.max_request_time != 'number') {
    throw "when provided, max_request_time must be a number";
  }

  events.EventEmitter.call(this);

  // an array of child processes
  this._kids = {};
  this._MAX_KIDS = (options.max_processes || Math.ceil(require('os').cpus().length * 1.25));
  this._work_q = [];
  this._exiting = false;
  this._exit_cb;
  this._module = options.module;
  // how long shall we allow our queue to get before we stop accepting work?
  // (negative implies no limit.  careful, there.)
  this._MAX_BACKLOG = options.max_backlog || this._MAX_KIDS * 10;
  this._MAX_REQUEST_TIME = options.max_request_time || 0;
  this._work_duration = 0;
  this._jobs_run = 0;
};

util.inherits(ComputeCluster, events.EventEmitter);

ComputeCluster.prototype._onWorkerExit = function(pid) {
  var self = this;
  return function (code) {
    // inform the callback the process quit
    var worker = self._kids[pid];
    if (worker && worker.job && worker.job.cb) {
      worker.job.cb("compute process (" + pid + ") dies with code: " + code);
    }
    // if _exiting is false, we don't expect to be shutting down!
    if (!self._exiting) {
      self.emit('error',
                "compute process (" + pid + ") dies with code: " + code);
    }

    self.emit('info', "compute process (" + pid + ") exits with code " + code);

    delete self._kids[pid];
    if (self._exit_cb) {
      if (Object.keys(self._kids).length === 0) {
        self._exit_cb(null);
        _exit_cb = undefined;
      }
    }
  }
};

ComputeCluster.prototype._getEnvForWorker = function() {
  var env = {};
  for (var i in process.env) {
    env[i] = process.env[i];
  }

  delete env.NODE_WORKER_ID; //Node.js cluster worker marker for v0.6
  delete env.NODE_UNIQUE_ID; //Node.js cluster worker marker for v0.7

  return env;
};

ComputeCluster.prototype._getFreeWorker = function() {
  var self = this;

  for (var i in this._kids) {
    if (!this._kids[i].job) return this._kids[i];
  }

  // no workers!  can we spawn one?
  if (Object.keys(this._kids).length < this._MAX_KIDS) {
    var k = {
      worker: child_process.fork(
        this._module,
        [],
        { env: this._getEnvForWorker() }
      ) };
    k.worker.on('exit', this._onWorkerExit(k.worker.pid));
    this._kids[k.worker.pid] = k;

    this.emit('info', "spawned new worker process (" +  k.worker.pid + ") " +
              Object.keys(this._kids).length + "/" + this._MAX_KIDS + " processes running");

    return k;
  }
};

ComputeCluster.prototype._runWorkOnWorker = function(work, worker) {
  var self = this;
  this.emit("debug", "passing compute job to process " + worker.worker.pid);
  var startTime = new Date();
  worker.worker.once('message', function(m) {
    // clear the in-progress job
    var cb = worker.job.cb;
    delete worker.job;

    // start the next
    self._assignWork();

    // call our client's callback
    if (cb) cb(null, m);
    // emit some debug info
    var timeMS = (new Date() - startTime);
    self.emit("debug", "process " + worker.worker.pid + " completed work in " +
              (timeMS / 1000.0).toFixed(2) + "s");

    // if there is a maximum request time, perform some math to estimate how
    // long requests take, favoring history to current job in proportion:
    // MAX_HISTORY:1
    if (self._MAX_REQUEST_TIME && self._jobs_run >= (2 * self._MAX_KIDS)) {
      var history = (self._jobs_run > MAX_HISTORY) ? MAX_HISTORY : self._jobs_run;
      self._work_duration = ((self._work_duration * history) + timeMS) / (history + 1);
    }

    self._jobs_run++;
  });
  worker.worker.send(work.job);
  worker.job = work;
};

  // assign as many work units from work_q as possible to avialable
  // compute processes
ComputeCluster.prototype._assignWork = function() {
  while (this._work_q.length > 0) {
    var worker = this._getFreeWorker();
    if (!worker) break;

    this._runWorkOnWorker(this._work_q.shift(), worker);
  }
};

ComputeCluster.prototype.enqueue = function(args, cb) {
  // maximum allowed request time check
  if (this._MAX_REQUEST_TIME && this._jobs_run > (2 * this._MAX_KIDS)) {
    var numWorkers = Object.keys(this._kids).length * 1.0;
    if (numWorkers) {
      // how long would this work take?
      var expected = ((this._work_q.length / numWorkers) * this._work_duration + this._work_duration) / 1000.0;
      if (expected > this._MAX_REQUEST_TIME) {
        this.emit('info', "maximum expected work duration hit hit (work would take about " + expected +
                  "s, which is greater than "+ this._MAX_REQUEST_TIME +")!  cannot enqueue!");
        process.nextTick(function() {
          cb("cannot enqueue work: maximum expected work duration exceeded (" + expected + "s)");
        });
        return this;
      }
    }
  }

  // backlog size check
  if (this._MAX_BACKLOG > 0 && this._work_q.length >= this._MAX_BACKLOG) {
    this.emit('info', "maximum work backlog hit (" + this._MAX_BACKLOG +
              ")!  cannot enqueue additional work!");
    var mb = this._MAX_BACKLOG;
    process.nextTick(function() {
      cb("cannot enqueue work: maximum backlog exceeded (" + mb + ")");
    });
    return this;
  }

  this._work_q.push({ job: args, cb: cb });
  this._assignWork();
  return this;
};

ComputeCluster.prototype.exit = function(cb) {
  if (Object.keys(this._kids).length === 0) {
    if (cb) setTimeout(function() { cb(null); }, 0);
  } else {
    this._exiting = true;
    this._exit_cb = cb;
    this.emit('info', "exit called, shutting down " + Object.keys(this._kids).length +
              " child processes");
    for (var i in this._kids) {
      this._kids[i].worker.kill();
    }
  }
  return this;
};

module.exports = ComputeCluster;
<|endoftext|>


<commit_before>import 'jquery';
import 'jquery-ui/ui/effect-drop';
import 'jquery-ui/ui/effect-bounce';
import 'bootstrap';
import 'webshim';

/**
 * Simple, small jQuery extensions for convenience.
 */
(function ($) {
    /**
     * Disable an element.
     *
     * Sets `disabled` property to `true` and adds `disabled` class.
     */
    $.fn.disable = function () {
        return this.prop('disabled', true).addClass('disabled');
    };

    /**
     * Enable an element.
     *
     * Sets `disabled` property to `false` and removes `disabled` class
     * if present.
     */
    $.fn.enable = function () {
        return this.prop('disabled', false).removeClass('disabled');
    };

    /**
     * Check an element.
     *
     * Sets `checked` property to `true`.
     */
    $.fn.check = function () {
        return this.prop('checked', true);
    };

    /**
     * Un-check an element.
     *
     * Sets `checked` property to `false`.
     */
    $.fn.uncheck = function () {
        return this.prop('checked', false);
    };

    /**
     * Initialise Bootstrap tooltip on an element with presets. Takes title.
     */
    $.fn._tooltip = $.fn.tooltip;
    $.fn.tooltip  = function (options) {
        return this
            ._tooltip('destroy')
            ._tooltip($.extend({
                container: 'body',
                placement: 'left',
                delay: {
                    show: 1000
                }
            }, options));
    };

    /**
     * Returns true / false if any modal is active.
     */
    $.modalActive = function () {
        var active = false;
        $('.modal').each(function () {
            var modal = $(this).data('bs.modal');
            if (modal) {
                active = modal.isShown;
                return !active;
            }
        });
        return active;
    };

    /**
     * Wiggle an element.
     *
     * Used for wiggling BLAST button.
     */
    $.fn.wiggle = function () {
        this.finish().effect('bounce', {
            direction: 'left',
            distance: 24,
            times: 4,
        }, 250);
    };
}(jQuery));<commit_msg>Change placement of submit button's tooltip<commit_after>import 'jquery';
import 'jquery-ui/ui/effect-drop';
import 'jquery-ui/ui/effect-bounce';
import 'bootstrap';
import 'webshim';

/**
 * Simple, small jQuery extensions for convenience.
 */
(function ($) {
    /**
     * Disable an element.
     *
     * Sets `disabled` property to `true` and adds `disabled` class.
     */
    $.fn.disable = function () {
        return this.prop('disabled', true).addClass('disabled');
    };

    /**
     * Enable an element.
     *
     * Sets `disabled` property to `false` and removes `disabled` class
     * if present.
     */
    $.fn.enable = function () {
        return this.prop('disabled', false).removeClass('disabled');
    };

    /**
     * Check an element.
     *
     * Sets `checked` property to `true`.
     */
    $.fn.check = function () {
        return this.prop('checked', true);
    };

    /**
     * Un-check an element.
     *
     * Sets `checked` property to `false`.
     */
    $.fn.uncheck = function () {
        return this.prop('checked', false);
    };

    /**
     * Initialise Bootstrap tooltip on an element with presets. Takes title.
     */
    $.fn._tooltip = $.fn.tooltip;
    $.fn.tooltip  = function (options) {
        return this
            ._tooltip('destroy')
            ._tooltip($.extend({
                container: 'body',
                placement: 'bottom',
                delay: {
                    show: 1000
                }
            }, options));
    };

    /**
     * Returns true / false if any modal is active.
     */
    $.modalActive = function () {
        var active = false;
        $('.modal').each(function () {
            var modal = $(this).data('bs.modal');
            if (modal) {
                active = modal.isShown;
                return !active;
            }
        });
        return active;
    };

    /**
     * Wiggle an element.
     *
     * Used for wiggling BLAST button.
     */
    $.fn.wiggle = function () {
        this.finish().effect('bounce', {
            direction: 'left',
            distance: 24,
            times: 4,
        }, 250);
    };
}(jQuery));<|endoftext|>


<commit_before>const configDefinitions = require('./definitions');

module.exports = {
  getDefault,
  getConfig,
};

const defaultValues = {
  boolean: true,
  list: [],
  string: null,
  json: null,
};

function getDefault(option) {
  return option.default === undefined
    ? defaultValues[option.type]
    : option.default;
}

function getConfig() {
  const options = configDefinitions.getOptions();
  const config = {};
  options.forEach(option => {
    config[option.name] = getDefault(option);
  });
  return config;
}
<commit_msg>fix: don’t add options with parents to defaults<commit_after>const configDefinitions = require('./definitions');

module.exports = {
  getDefault,
  getConfig,
};

const defaultValues = {
  boolean: true,
  list: [],
  string: null,
  json: null,
};

function getDefault(option) {
  return option.default === undefined
    ? defaultValues[option.type]
    : option.default;
}

function getConfig() {
  const options = configDefinitions.getOptions();
  const config = {};
  options.forEach(option => {
    if (!option.parents) {
      config[option.name] = getDefault(option);
    }
  });
  return config;
}
<|endoftext|>


<commit_before>/**
 * 自定义组件基类
 * @exports factory
 * @copyright 2016 Baidu.com, Inc. All Rights Reserved
 */
define(function () {
    function customElement(element) {
        this.element = element;
        if (this.init){
            this.init();
        }
    }

    // interface
    customElement.prototype.mipCreatedCallback = function () {};
    customElement.prototype.mipAttachedCallback = function () {};
    customElement.prototype.mipDetachedCallback = function () {};
    customElement.prototype.mipAttributeChangedCallback = function () {};

    //自定义元素进入可视区域的默认处理函数，此处可以覆写，如果有特殊逻辑
    customElement.prototype.inviewCallback = function () {
        if(this.element.isInviewer()){
            this.build();
        }
    };
   //模板的元素build功能，即元素的默认初始化功能
    customElement.prototype.build = function () {};

    return function () {
        var impl = function (element) {
            customElement.call(this, element);
        };
        impl.prototype = Object.create(customElement.prototype);
        return impl;
    };
});
<commit_msg>by qijian<commit_after>/**
 * 自定义组件基类
 * @exports factory
 * @copyright 2016 Baidu.com, Inc. All Rights Reserved
 */
define(function () {
    function customElement(element) {
        this.element = element;
        if (this.init){
            this.init();
        }
    }

    // interface
    customElement.prototype.mipCreatedCallback = function () {};
    customElement.prototype.mipAttachedCallback = function () {};
    customElement.prototype.mipDetachedCallback = function () {};
    customElement.prototype.mipAttributeChangedCallback = function () {};

    //自定义元素进入可视区域的默认处理函数，此处可以覆写，如果有特殊逻辑
    customElement.prototype.inviewCallback = function () {
        if(this.element.isInviewer()){
            this.build();
        }
    };
    //模板的元素build功能，即元素的默认初始化功能
    customElement.prototype.build = function () {};

    return function () {
        var impl = function (element) {
            customElement.call(this, element);
        };
        impl.prototype = Object.create(customElement.prototype);
        return impl;
    };
});
<|endoftext|>


<commit_before>'use strict';

/**
 * A string representing the current OS platform
 * @type {string} 'windows' or 'unix'
 */
var PLATFORM = (['win32', 'win64'].indexOf(process.platform) >= 0) ?
  'windows' :
  ((process.platform === 'darwin') ? 'darwin' : 'unix');

/**
 * Indicates whether the current platform is windows
 * @returns {boolean} true for windows, else false
 */
function isWindows() {
  return (PLATFORM === 'windows');
}

/**
 * Indicates whether the current platform is darwin
 * @returns {boolean} true for darwin, else false
 */
function isMacOS() {
  return (PLATFORM === 'darwin');
}

/**
 * Indicates whether the current platform is unix
 * @returns {boolean} true for unix, else false
 */
function isUnix() {
  return (PLATFORM === 'unix');
}

/**
 * The user home directory
 * @returns {string} The path to the user home directory
 */
function userHomeDirectory() {
  return (PLATFORM === 'windows') ? process.env.USERPROFILE : process.env.HOME;
}

module.exports = {
  isWindows        : isWindows,
  isMacOS          : isMacOS,
  isUnix           : isUnix,
  userHomeDirectory: userHomeDirectory
}
<commit_msg>jshint fixes for platform.js.<commit_after>'use strict';

/**
 * A string representing the current OS platform
 * @type {string} 'windows' or 'unix'
 */
var PLATFORM = (['win32', 'win64'].indexOf(process.platform) >= 0) ?
  'windows' :
  ((process.platform === 'darwin') ? 'darwin' : 'unix');

/**
 * Indicates whether the current platform is windows
 * @returns {boolean} true for windows, else false
 */
function isWindows() {
  return (PLATFORM === 'windows');
}

/**
 * Indicates whether the current platform is darwin
 * @returns {boolean} true for darwin, else false
 */
function isMacOS() {
  return (PLATFORM === 'darwin');
}

/**
 * Indicates whether the current platform is unix
 * @returns {boolean} true for unix, else false
 */
function isUnix() {
  return (PLATFORM === 'unix');
}

/**
 * The user home directory
 * @returns {string} The path to the user home directory
 */
function userHomeDirectory() {
  return (PLATFORM === 'windows') ? process.env.USERPROFILE : process.env.HOME;
}

module.exports = {
  isWindows        : isWindows,
  isMacOS          : isMacOS,
  isUnix           : isUnix,
  userHomeDirectory: userHomeDirectory
};
<|endoftext|>


<commit_before>"use strict"

// let: limits variable to block scope

let x = 1;

if (true) {
  let x = 5;
  console.log( "value of x inside block: ", x); // 5
}

console.log( "value of x outside block: ", x); // 1

// const: creates immutable variables

const myConstant = 'can not change';
myConstant = 'can i udate?';

<commit_msg>Update veriableDeclaration.js<commit_after>"use strict"

// let: limits variable to block scope

let x = 1;

if (true) {
  let x = 5;
  console.log( "value of x inside block: ", x); // 5
}

console.log( "value of x outside block: ", x); // 1

// const: creates immutable variables
// using const guarantees references won't be overridden

const myConstant = 'can not change';
myConstant = 'can i udate?';

<|endoftext|>


<commit_before>define(['altair/facades/declare',
        'liquidfire/modules/apollo/mixins/_HasPropertyTypesMixin',
        'altair/mixins/_AssertMixin',
        'apollo/_HasSchemaMixin',
        'lodash',
        'altair/plugins/node!path'
], function (declare,
             _HasPropertyTypesMixin,
             _AssertMixin,
             _HasSchemaMixin,
             _,
             pathUtil) {

    return declare([_HasPropertyTypesMixin, _HasSchemaMixin, _AssertMixin], {

        startup: function (options) {

            //when Alfred starts, lets share our upload dir
            if (this.nexus('titan:Alfred')) {
                this.on('titan:Alfred::did-execute-server').then(this.hitch('onDidExecuteAlfredWebServer'));
            }

            return this.inherited(arguments);

        },

        /**
         * When Alfred starts, lets share our thumbnails dir
         *
         * @param e
         */
        onDidExecuteAlfredWebServer: function (e) {

            //only share publically if we have an upload uri set
            if (this.get('publicUploadUri') && this.get('uploadDir')) {
                var server = e.get('server');
                server.serveStatically(this.get('uploadDir'), this.get('publicUploadUri'));
            }

            if (!this.get('fileHost')) {

                var port        = e.get('app').options.sslPort || e.get('app').options.port,
                    protocol    = e.get('app').options.sslPort ? 'https' : 'http',
                    host        = protocol + '://' + e.get('app').options.domain;

                if (port !== 80 && port !== 443) {
                    host += ':' + port;
                }

                this.set('fileHost', host);

            }

        },

        /**
         * Helps you find the path to uploaded files (or their publicy accessible path if options { public: true } )
         *
         * @param file
         * @param options
         * @returns {*}
         */
        resolveUploadedFilePath: function (file, options) {

            this.assert(this.get('publicUploadUri'), 'You must set publicUploadDirectory on liquidfire:Files')
            this.assert(this.get('uploadDir'), 'You must set uploadDir on liquidfire:Files')
            this.assert(this.get('fileHost'), 'You must set fileHost (http://domain.com) on liquidfire:Files')

            var path,
                _options = options || {};

            if(!_.isString(file)) {
                return null;
            }

            //they want a publically accessible uri
            if(_options.public) {

                _options.absolute = false;

                //my absolute best guess on how to handle a path relative to the app that
                //is also publically available
                if (file[0] === '.') {

                    path = this.nexus('Altair').resolvePath(file);

                    //this comes back as /public/_uploads by default
                    var pub = this.get('publicUploadUri', null),
                        parts = pub.split('/'),
                        publicFolderName = parts[0] || parts[1]; //first non-empty folder name

                    //split by top level public folder (assumed public by default) and add onto it anything in the last part
                    path = '/' + publicFolderName + path.split(publicFolderName).pop(); //this should leave us with whatever is past the public facing side

                } else {

                    path = pathUtil.join(this.get('publicUploadUri', null, options), file);

                }

                path = this.get('fileHost') + path;

            } else {

                //if file starts with a . then lets look relative to the current app vs the upload dir
                if (file[0] === '.') {

                    path = (_options.absolute) ? this.nexus('Altair').resolvePath(file) : file;

                } else {

                    path = pathUtil.join(this.get('uploadDir', null, options), file);

                }

            }

            return path;
        }

    });

});<commit_msg>syntax fix<commit_after>define(['altair/facades/declare',
        'liquidfire/modules/apollo/mixins/_HasPropertyTypesMixin',
        'altair/mixins/_AssertMixin',
        'apollo/_HasSchemaMixin',
        'lodash',
        'altair/plugins/node!path'
], function (declare,
             _HasPropertyTypesMixin,
             _AssertMixin,
             _HasSchemaMixin,
             _,
             pathUtil) {

    return declare([_HasPropertyTypesMixin, _HasSchemaMixin, _AssertMixin], {

        startup: function (options) {

            //when Alfred starts, lets share our upload dir
            if (this.nexus('titan:Alfred')) {
                this.on('titan:Alfred::did-execute-server').then(this.hitch('onDidExecuteAlfredWebServer'));
            }

            return this.inherited(arguments);

        },

        /**
         * When Alfred starts, lets share our thumbnails dir
         *
         * @param e
         */
        onDidExecuteAlfredWebServer: function (e) {

            //only share publically if we have an upload uri set
            if (this.get('publicUploadUri') && this.get('uploadDir')) {
                var server = e.get('server');
                server.serveStatically(this.get('uploadDir'), this.get('publicUploadUri'));
            }

            if (!this.get('fileHost')) {

                var port        = e.get('app').options.sslPort || e.get('app').options.port,
                    protocol    = e.get('app').options.sslPort ? 'https' : 'http',
                    host        = protocol + '://' + e.get('app').options.domain;

                if (port !== 80 && port !== 443) {
                    host += ':' + port;
                }

                this.set('fileHost', host);

            }

        },

        /**
         * Helps you find the path to uploaded files (or their publicy accessible path if options { public: true } )
         *
         * @param file
         * @param options
         * @returns {*}
         */
        resolveUploadedFilePath: function (file, options) {

            this.assert(this.get('publicUploadUri'), 'You must set publicUploadDirectory on liquidfire:Files')
            this.assert(this.get('uploadDir'), 'You must set uploadDir on liquidfire:Files')
            this.assert(this.get('fileHost'), 'You must set fileHost (http://domain.com) on liquidfire:Files')

            var path,
                _options = options || {};

            if(!_.isString(file)) {
                return null;
            }

            //they want a publically accessible uri
            if(_options.public) {

                _options.absolute = false;

                //my absolute best guess on how to handle a path relative to the app that
                //is also publically available
                if (file[0] === '.') {

                    path = this.nexus('Altair').resolvePath(file);

                    //this comes back as /public/_uploads by default
                    var pub = this.get('publicUploadUri', null),
                        parts = pub.split('/'),
                        publicFolderName = parts[0] || parts[1]; //first non-empty folder name

                    //split by top level public folder (assumed public by default) and add onto it anything in the last part
                    path = '/' + publicFolderName + path.split(publicFolderName).pop(); //this should leave us with whatever is past the public facing side

                } else {

                    path = pathUtil.join(this.get('publicUploadUri', null, options), file);

                }

                path = this.get('fileHost') + path;

            } else {

                //if file starts with a . then lets look relative to the current app vs the upload dir
                if (file[0] === '.') {

                    path = (_options.absolute) ? this.nexus('Altair').resolvePath(file) : file;

                } else {

                    path = pathUtil.join(this.get('uploadDir', null, options), file);

                }

            }

            return path;
        }

    });

});<|endoftext|>